X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/acfa068f4a1a4652b784af1d7aaac92929399249..0877d0dc24ee792b9b14592869ea1aa0934aee58:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index f00719be37..8b0d8b6cfa 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. @@ -275,6 +276,7 @@ along with GNU Emacs. If not, see . */ #include #include "lisp.h" +#include "atimer.h" #include "keyboard.h" #include "frame.h" #include "window.h" @@ -301,7 +303,7 @@ along with GNU Emacs. If not, see . */ #ifdef HAVE_X_WINDOWS #include "xterm.h" #endif -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI #include "w32term.h" #endif #ifdef HAVE_NS @@ -332,10 +334,10 @@ static Lisp_Object Qinhibit_eval_during_redisplay; static Lisp_Object Qbuffer_position, Qposition, Qobject; static Lisp_Object Qright_to_left, Qleft_to_right; -/* Cursor shapes */ +/* Cursor shapes. */ Lisp_Object Qbar, Qhbar, Qbox, Qhollow; -/* Pointer shapes */ +/* Pointer shapes. */ static Lisp_Object Qarrow, Qhand; Lisp_Object Qtext; @@ -346,6 +348,7 @@ static Lisp_Object Qfontification_functions; static Lisp_Object Qwrap_prefix; static Lisp_Object Qline_prefix; +static Lisp_Object Qredisplay_internal; /* Non-nil means don't actually do any redisplay. */ @@ -365,22 +368,22 @@ static Lisp_Object Qmargin, Qpointer; static Lisp_Object Qline_height; /* These setters are used only in this file, so they can be private. */ -static inline void +static void wset_base_line_number (struct window *w, Lisp_Object val) { w->base_line_number = val; } -static inline void +static void wset_base_line_pos (struct window *w, Lisp_Object val) { w->base_line_pos = val; } -static inline void +static void wset_column_number_displayed (struct window *w, Lisp_Object val) { w->column_number_displayed = val; } -static inline void +static void wset_region_showing (struct window *w, Lisp_Object val) { w->region_showing = val; @@ -513,12 +516,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). keyboard.c refers to - this. */ - -int buffer_shared; - /* Vector containing glyphs for an ellipsis `...'. */ static Lisp_Object default_invis_vector[3]; @@ -873,7 +870,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); @@ -926,6 +922,7 @@ static enum move_it_result move_it_in_display_line_to (struct it *, ptrdiff_t, int, enum move_operation_enum); void move_it_vertically_backward (struct it *, int); +static void get_visually_first_element (struct it *); static void init_to_row_start (struct it *, struct window *, struct glyph_row *); static int init_to_row_end (struct it *, struct window *, @@ -1189,7 +1186,7 @@ window_box (struct window *w, int area, int *box_x, int *box_y, *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the box. */ -static inline void +static void window_box_edges (struct window *w, int area, int *top_left_x, int *top_left_y, int *bottom_right_x, int *bottom_right_y) { @@ -1276,7 +1273,7 @@ string_from_display_spec (Lisp_Object spec) /* Limit insanely large values of W->hscroll on frame F to the largest value that will still prevent first_visible_x and last_visible_x of 'struct it' from overflowing an int. */ -static inline int +static int window_hscroll_limited (struct window *w, struct frame *f) { ptrdiff_t window_hscroll = w->hscroll; @@ -1333,7 +1330,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 @@ -1341,7 +1338,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))) { @@ -1623,7 +1620,7 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, returns an invalid character. If we find one, we return a `?', but with the length of the invalid character. */ -static inline int +static int string_char_and_length (const unsigned char *str, int *len) { int c; @@ -1671,7 +1668,7 @@ string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t ncha /* Value is the text position, i.e. character and byte position, for character position CHARPOS in STRING. */ -static inline struct text_pos +static struct text_pos string_pos (ptrdiff_t charpos, Lisp_Object string) { struct text_pos pos; @@ -2562,8 +2559,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 ***********************************************************************/ @@ -2592,7 +2605,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. */ @@ -2695,16 +2708,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 @@ -2716,7 +2724,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); } @@ -3111,6 +3118,40 @@ init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos) eassert (STRINGP (it->string)); it->current.string_pos = pos->string_pos; it->method = GET_FROM_STRING; + it->end_charpos = SCHARS (it->string); + /* Set up the bidi iterator for this overlay string. */ + if (it->bidi_p) + { + it->bidi_it.string.lstring = it->string; + it->bidi_it.string.s = NULL; + it->bidi_it.string.schars = SCHARS (it->string); + it->bidi_it.string.bufpos = it->overlay_strings_charpos; + it->bidi_it.string.from_disp_str = it->string_from_display_prop_p; + it->bidi_it.string.unibyte = !it->multibyte_p; + bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it), + FRAME_WINDOW_P (it->f), &it->bidi_it); + + /* Synchronize the state of the bidi iterator with + pos->string_pos. For any string position other than + zero, this will be done automagically when we resume + iteration over the string and get_visually_first_element + is called. But if string_pos is zero, and the string is + to be reordered for display, we need to resync manually, + since it could be that the iteration state recorded in + pos ended at string_pos of 0 moving backwards in string. */ + if (CHARPOS (pos->string_pos) == 0) + { + get_visually_first_element (it); + if (IT_STRING_CHARPOS (*it) != 0) + do { + /* Paranoia. */ + eassert (it->bidi_it.charpos < it->bidi_it.string.schars); + bidi_move_to_visually_next (&it->bidi_it); + } while (it->bidi_it.charpos != 0); + } + eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos + && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos); + } } if (CHARPOS (pos->string_pos) >= 0) @@ -3120,6 +3161,9 @@ init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos) IT should already be filled with that string. */ it->current.string_pos = pos->string_pos; eassert (STRINGP (it->string)); + if (it->bidi_p) + bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it), + FRAME_WINDOW_P (it->f), &it->bidi_it); } /* Restore position in display vector translations, control @@ -3721,18 +3765,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; } } @@ -5346,6 +5398,7 @@ next_overlay_string (struct it *it) SET_TEXT_POS (it->current.string_pos, 0, 0); it->method = GET_FROM_STRING; it->stop_charpos = 0; + it->end_charpos = SCHARS (it->string); if (it->cmp_it.stop_pos >= 0) it->cmp_it.stop_pos = 0; it->prev_stop = 0; @@ -6299,6 +6352,8 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p) it->stop_charpos = CHARPOS (pos); it->base_level_stop = CHARPOS (pos); } + /* This make the information stored in it->cmp_it invalidate. */ + it->cmp_it.id = -1; } @@ -9343,7 +9398,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; @@ -9458,7 +9514,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) @@ -9468,7 +9524,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); } @@ -9477,17 +9533,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; @@ -9600,7 +9656,7 @@ message2_nolog (const char *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); } } @@ -9697,7 +9753,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); } } @@ -10050,8 +10106,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 { @@ -10348,8 +10404,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) @@ -10726,7 +10781,7 @@ clear_garbaged_frames (void) { if (f->resized_p) { - Fredraw_frame (frame); + redraw_frame (f); f->force_flush_display_p = 1; } clear_current_matrices (f); @@ -10773,8 +10828,7 @@ echo_area_display (int update_frame_p) #endif /* HAVE_WINDOW_SYSTEM */ /* Redraw garbaged frames. */ - if (frame_garbaged) - clear_garbaged_frames (); + clear_garbaged_frames (); if (!NILP (echo_area_buffer[0]) || minibuf_level == 0) { @@ -10847,8 +10901,52 @@ echo_area_display (int update_frame_p) return window_height_changed_p; } +/* 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_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. FIXME: this may be called when + XBUFFER (w->buffer) != current_buffer, which looks suspicious. */ + +static int +window_outdated (struct window *w) +{ + 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))) + != !NILP (w->region_showing))); +} + +/* 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 (!NILP (w->column_number_displayed) + && !(PT == w->last_point && !window_outdated (w)) + && (XFASTINT (w->column_number_displayed) != current_column ())); +} - /*********************************************************************** Mode Lines and Frame Titles ***********************************************************************/ @@ -11053,17 +11151,15 @@ x_consider_frame_title (Lisp_Object frame) || f->explicit_name) { /* Do we have more than one visible frame on this X display? */ - Lisp_Object tail; - Lisp_Object fmt; + Lisp_Object tail, other_frame, fmt; ptrdiff_t title_start; char *title; ptrdiff_t len; struct it it; ptrdiff_t count = SPECPDL_INDEX (); - for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail)) + FOR_EACH_FRAME (tail, other_frame) { - Lisp_Object other_frame = XCAR (tail); struct frame *tf = XFRAME (other_frame); if (tf != f @@ -11156,7 +11252,7 @@ prepare_menu_bars (void) /* Update the menu bar item lists, if appropriate. This has to be done before any actual redisplay or generation of display lines. */ all_windows = (update_mode_lines - || buffer_shared > 1 + || buffer_shared_and_changed () || windows_or_buffers_changed); if (all_windows) { @@ -11270,12 +11366,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 (); @@ -11401,11 +11492,11 @@ x_cursor_to (int vpos, int hpos, int y, int x) This will also set the cursor position of W. */ if (updated_window == NULL) { - BLOCK_INPUT; + block_input (); display_and_set_cursor (w, 1, hpos, vpos, x, y); if (FRAME_RIF (SELECTED_FRAME ())->flush_display_optional) FRAME_RIF (SELECTED_FRAME ())->flush_display_optional (SELECTED_FRAME ()); - UNBLOCK_INPUT; + unblock_input (); } } @@ -11427,11 +11518,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; } @@ -11468,12 +11566,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 (); @@ -11503,9 +11596,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 @@ -11519,11 +11616,11 @@ update_tool_bar (struct frame *f, int save_match_data) /* Redisplay that happens asynchronously due to an expose event may access f->tool_bar_items. Make sure we update both variables within BLOCK_INPUT so no such event interrupts. */ - BLOCK_INPUT; + block_input (); fset_tool_bar_items (f, new_tool_bar); f->n_tool_bar_items = new_n_tool_bar; w->update_mode_line = 1; - UNBLOCK_INPUT; + unblock_input (); } UNGCPRO; @@ -11873,19 +11970,14 @@ tool_bar_lines_needed (struct frame *f, int *n_rows) DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed, 0, 1, 0, - doc: /* Return the number of lines occupied by the tool bar of FRAME. */) + doc: /* Return the number of lines occupied by the tool bar of FRAME. +If FRAME is nil or omitted, use the selected frame. */) (Lisp_Object frame) { - struct frame *f; + struct frame *f = decode_any_frame (frame); struct window *w; int nlines = 0; - if (NILP (frame)) - frame = selected_frame; - else - CHECK_FRAME (frame); - f = XFRAME (frame); - if (WINDOWP (f->tool_bar_window) && (w = XWINDOW (f->tool_bar_window), WINDOW_TOTAL_LINES (w) > 0)) @@ -12185,7 +12277,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 @@ -12196,7 +12287,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); @@ -12265,7 +12355,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. */ @@ -12294,7 +12383,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: @@ -12418,11 +12506,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. */ @@ -12574,15 +12658,14 @@ debug_method_add (struct window *w, char const *fmt, ...) buffer position, END is given as a distance from Z. Used in redisplay_internal for display optimization. */ -static inline int +static int text_outside_line_unchanged_p (struct window *w, ptrdiff_t start, ptrdiff_t end) { int unchanged_p = 1; /* If text or overlays have changed, see where. */ - if (w->last_modified < MODIFF - || w->last_overlay_modified < OVERLAY_MODIFF) + if (window_outdated (w)) { /* Gap in the line? */ if (GPT < start || Z - GPT < end) @@ -12835,7 +12918,7 @@ check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt, /* Reconsider the setting of B->clip_changed which is displayed in window W. */ -static inline void +static void reconsider_clip_changes (struct window *w, struct buffer *b) { if (b->clip_changed @@ -12870,37 +12953,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) @@ -12926,13 +12978,14 @@ 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 frames. Zero means, only selected_window is considered. */ int consider_all_windows_p; - /* Non-zero means redisplay has to redisplay the miniwindow */ + /* Non-zero means redisplay has to redisplay the miniwindow. */ int update_miniwindow_p = 0; TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p)); @@ -12969,28 +13022,21 @@ redisplay_internal (void) redisplaying_p = 1; specbind (Qinhibit_free_realized_faces, Qnil); - { - Lisp_Object tail, frame; + /* Record this function, so it appears on the profiler's backtraces. */ + backtrace.next = backtrace_list; + backtrace.function = Qredisplay_internal; + backtrace.args = &Qnil; + backtrace.nargs = 0; + backtrace.debug_on_exit = 0; + backtrace_list = &backtrace; - 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; @@ -13027,25 +13073,20 @@ 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); - } - } + FRAME_SAMPLE_VISIBILITY (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); @@ -13059,8 +13100,7 @@ redisplay_internal (void) } /* Clear frames marked as garbaged. */ - if (frame_garbaged) - clear_garbaged_frames (); + clear_garbaged_frames (); /* Build menubar and tool-bar items. */ if (NILP (Vmemory_full)) @@ -13073,7 +13113,7 @@ redisplay_internal (void) if ((SAVE_MODIFF < MODIFF) != w->last_had_star) { w->update_mode_line = 1; - if (buffer_shared > 1) + if (buffer_shared_and_changed ()) update_mode_lines++; } @@ -13081,24 +13121,15 @@ 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 - && w->last_modified >= MODIFF - && w->last_overlay_modified >= OVERLAY_MODIFF) - && (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 > 1 + consider_all_windows_p = (update_mode_lines + || buffer_shared_and_changed () || cursor_type_changed); /* If specs for an arrow have changed, do thorough redisplay @@ -13144,23 +13175,20 @@ redisplay_internal (void) /* If window configuration was changed, frames may have been marked garbaged. Clear them or we will experience surprises wrt scrolling. */ - if (frame_garbaged) - clear_garbaged_frames (); + clear_garbaged_frames (); } } else if (EQ (selected_window, minibuf_window) - && (current_buffer->clip_changed - || w->last_modified < MODIFF - || w->last_overlay_modified < OVERLAY_MODIFF) + && (current_buffer->clip_changed || window_outdated (w)) && resize_mini_window (w, 0)) { /* Resized active mini-window to fit the size of what it is showing if its contents might have changed. */ must_finish = 1; -/* FIXME: this causes all frames to be updated, which seems unnecessary - since only the current frame needs to be considered. This function needs - to be rewritten with two variables, consider_all_windows and - consider_all_frames. */ + /* FIXME: this causes all frames to be updated, which seems unnecessary + since only the current frame needs to be considered. This function + needs to be rewritten with two variables, consider_all_windows and + consider_all_frames. */ consider_all_windows_p = 1; ++windows_or_buffers_changed; ++update_mode_lines; @@ -13168,8 +13196,7 @@ redisplay_internal (void) /* If window configuration was changed, frames may have been marked garbaged. Clear them or we will experience surprises wrt scrolling. */ - if (frame_garbaged) - clear_garbaged_frames (); + clear_garbaged_frames (); } @@ -13216,9 +13243,7 @@ redisplay_internal (void) || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n')) /* Former continuation line has disappeared by becoming empty. */ goto cancel; - else if (w->last_modified < MODIFF - || w->last_overlay_modified < OVERLAY_MODIFF - || MINI_WINDOW_P (w)) + else if (window_outdated (w) || MINI_WINDOW_P (w)) { /* We have to handle the case of continuation around a wide-column character (see the comment in indent.c around @@ -13392,7 +13417,7 @@ redisplay_internal (void) } CHARPOS (this_line_start_pos) = 0; - consider_all_windows_p |= buffer_shared > 1; + consider_all_windows_p |= buffer_shared_and_changed (); ++clear_face_cache_count; #ifdef HAVE_WINDOW_SYSTEM ++clear_image_cache_count; @@ -13404,15 +13429,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); @@ -13425,11 +13444,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) @@ -13479,14 +13493,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) { @@ -13615,7 +13622,6 @@ redisplay_internal (void) frames here explicitly. */ if (!pending) { - Lisp_Object tail, frame; int new_count = 0; FOR_EACH_FRAME (tail, frame) @@ -13666,6 +13672,7 @@ redisplay_internal (void) #endif /* HAVE_WINDOW_SYSTEM */ end_of_redisplay: + backtrace_list = backtrace.next; unbind_to (count, Qnil); RESUME_POLLING; } @@ -13705,17 +13712,12 @@ 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; } @@ -13732,8 +13734,8 @@ mark_window_display_accurate_1 (struct window *w, int accurate_p) { 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_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); @@ -13757,7 +13759,7 @@ mark_window_display_accurate_1 (struct window *w, int accurate_p) if (w == XWINDOW (selected_window)) w->last_point = BUF_PT (b); else - w->last_point = XMARKER (w->pointm)->charpos; + w->last_point = marker_position (w->pointm); } } @@ -14179,7 +14181,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. @@ -14188,7 +14190,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) { @@ -14525,7 +14532,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, We assume that the window's buffer is really current. */ -static inline struct text_pos +static struct text_pos run_window_scroll_functions (Lisp_Object window, struct text_pos startp) { struct window *w = XWINDOW (window); @@ -14738,13 +14745,18 @@ try_scrolling (Lisp_Object window, int just_this_one_p, if (NUMBERP (aggressive)) { double float_amount = XFLOATINT (aggressive) * height; - amount_to_scroll = float_amount; - if (amount_to_scroll == 0 && float_amount > 0) - amount_to_scroll = 1; + int aggressive_scroll = float_amount; + if (aggressive_scroll == 0 && float_amount > 0) + aggressive_scroll = 1; /* Don't let point enter the scroll margin near top of - the window. */ - if (amount_to_scroll > height - 2*this_scroll_margin + dy) - amount_to_scroll = height - 2*this_scroll_margin + dy; + the window. This could happen if the value of + scroll_up_aggressively is too large and there are + non-zero margins, because scroll_up_aggressively + means put point that fraction of window height + _from_the_bottom_margin_. */ + if (aggressive_scroll + 2*this_scroll_margin > height) + aggressive_scroll = height - 2*this_scroll_margin; + amount_to_scroll = dy + aggressive_scroll; } } @@ -14804,7 +14816,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p, /* Compute the vertical distance from PT to the scroll margin position. Move as far as scroll_max allows, or one screenful, or 10 screen lines, whichever is largest. - Give up if distance is greater than scroll_max. */ + Give up if distance is greater than scroll_max or if we + didn't reach the scroll margin position. */ SET_TEXT_POS (pos, PT, PT_BYTE); start_display (&it, w, pos); y0 = it.current_y; @@ -14814,7 +14827,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p, y_to_move, -1, MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); dy = it.current_y - y0; - if (dy > scroll_max) + if (dy > scroll_max + || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos)) return SCROLLING_FAILED; /* Compute new window start. */ @@ -14832,15 +14846,16 @@ try_scrolling (Lisp_Object window, int just_this_one_p, if (NUMBERP (aggressive)) { double float_amount = XFLOATINT (aggressive) * height; - amount_to_scroll = float_amount; - if (amount_to_scroll == 0 && float_amount > 0) - amount_to_scroll = 1; - amount_to_scroll -= - this_scroll_margin - dy - FRAME_LINE_HEIGHT (f); + int aggressive_scroll = float_amount; + if (aggressive_scroll == 0 && float_amount > 0) + aggressive_scroll = 1; /* Don't let point enter the scroll margin near - bottom of the window. */ - if (amount_to_scroll > height - 2*this_scroll_margin + dy) - amount_to_scroll = height - 2*this_scroll_margin + dy; + bottom of the window, if the value of + scroll_down_aggressively happens to be too + large. */ + if (aggressive_scroll + 2*this_scroll_margin > height) + aggressive_scroll = height - 2*this_scroll_margin; + amount_to_scroll = dy + aggressive_scroll; } } @@ -15018,8 +15033,7 @@ 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))) + && markpos_of_region () < 0 && NILP (w->region_showing) && NILP (Vshow_trailing_whitespace) /* This code is not used for mini-buffer for the sake of the case @@ -15460,8 +15474,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) = (!NILP (w->window_end_valid) && !current_buffer->clip_changed && !current_buffer->prevent_redisplay_optimizations_p - && w->last_modified >= MODIFF - && w->last_overlay_modified >= OVERLAY_MODIFF); + && !window_outdated (w)); /* Run the window-bottom-change-functions if it is possible that the text on the screen has changed @@ -15483,8 +15496,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) buffer_unchanged_p = (!NILP (w->window_end_valid) && !current_buffer->clip_changed - && w->last_modified >= MODIFF - && w->last_overlay_modified >= OVERLAY_MODIFF); + && !window_outdated (w)); /* When windows_or_buffers_changed is non-zero, we can't rely on the window end being valid, so set it to nil there. */ @@ -15505,36 +15517,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 - && w->last_modified >= MODIFF - && w->last_overlay_modified >= OVERLAY_MODIFF) - && (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) { @@ -15660,6 +15650,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. */ @@ -15683,8 +15701,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)) @@ -15753,8 +15770,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) && (CHARPOS (startp) < ZV /* Avoid starting at end of buffer. */ || CHARPOS (startp) == BEGV - || (w->last_modified >= MODIFF - && w->last_overlay_modified >= OVERLAY_MODIFF))) + || !window_outdated (w))) { int d1, d2, d3, d4, d5, d6; @@ -16204,10 +16220,10 @@ redisplay_window (Lisp_Object window, int just_this_one_p) || w->pseudo_window_p))) { update_begin (f); - BLOCK_INPUT; + block_input (); if (draw_window_fringes (w, 1)) x_draw_vertical_border (w); - UNBLOCK_INPUT; + unblock_input (); update_end (f); } #endif /* HAVE_WINDOW_SYSTEM */ @@ -16390,8 +16406,7 @@ 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))) + if (0 <= markpos_of_region () || !NILP (w->region_showing) || !NILP (Vshow_trailing_whitespace)) return 0; @@ -17223,8 +17238,7 @@ try_window_id (struct window *w) /* 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. */ @@ -18557,6 +18571,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; @@ -18578,6 +18593,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); @@ -18591,6 +18616,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; } } @@ -18680,7 +18706,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; @@ -18695,6 +18721,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. */ @@ -18702,11 +18729,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 */ @@ -20160,10 +20189,6 @@ display_menu_bar (struct window *w) this. */ it.paragraph_embedding = L2R; - if (! mode_line_inverse_video) - /* Force the menu-bar to be displayed in the default face. */ - it.base_face_id = it.face_id = DEFAULT_FACE_ID; - /* Clear all rows of the menu bar. */ for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i) { @@ -20277,13 +20302,17 @@ 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; @@ -20306,6 +20335,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; @@ -20333,10 +20363,6 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format) it.glyph_row->mode_line_p = 1; - if (! mode_line_inverse_video) - /* Force the mode-line to be displayed in the default face. */ - it.base_face_id = it.face_id = DEFAULT_FACE_ID; - /* FIXME: This should be controlled by a user option. But supporting such an option is not trivial, since the mode line is made up of many separate strings. */ @@ -21011,10 +21037,8 @@ are the selected window and the WINDOW's buffer). */) Lisp_Object str; int string_start = 0; - if (NILP (window)) - window = selected_window; - CHECK_WINDOW (window); - w = XWINDOW (window); + w = decode_any_window (window); + XSETWINDOW (window, w); if (NILP (buffer)) buffer = w->buffer; @@ -21043,7 +21067,7 @@ are the selected window and the WINDOW's buffer). */) and set that to nil so that we don't alter the outer value. */ record_unwind_protect (unwind_format_mode_line, format_mode_line_unwind_data - (XFRAME (WINDOW_FRAME (XWINDOW (window))), + (XFRAME (WINDOW_FRAME (w)), old_buffer, selected_window, 1)); mode_line_proptrans_alist = Qnil; @@ -21327,6 +21351,12 @@ decode_mode_spec (struct window *w, register int c, int field_width, Lisp_Object obj; struct frame *f = XFRAME (WINDOW_FRAME (w)); char *decode_mode_spec_buf = f->decode_mode_spec_buffer; + /* We are going to use f->decode_mode_spec_buffer as the buffer to + produce strings from numerical values, so limit preposterously + large values of FIELD_WIDTH to avoid overrunning the buffer's + end. The size of the buffer is enough for FRAME_MESSAGE_BUF_SIZE + bytes plus the terminating null. */ + int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f)); struct buffer *b = current_buffer; obj = Qnil; @@ -21391,8 +21421,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)) @@ -21422,7 +21452,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, { ptrdiff_t col = current_column (); wset_column_number_displayed (w, make_number (col)); - pint2str (decode_mode_spec_buf, field_width, col); + pint2str (decode_mode_spec_buf, width, col); return decode_mode_spec_buf; } @@ -21453,14 +21483,14 @@ decode_mode_spec (struct window *w, register int c, int field_width, case 'i': { ptrdiff_t size = ZV - BEGV; - pint2str (decode_mode_spec_buf, field_width, size); + pint2str (decode_mode_spec_buf, width, size); return decode_mode_spec_buf; } case 'I': { ptrdiff_t size = ZV - BEGV; - pint2hrstr (decode_mode_spec_buf, field_width, size); + pint2hrstr (decode_mode_spec_buf, width, size); return decode_mode_spec_buf; } @@ -21474,7 +21504,7 @@ 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); @@ -21567,12 +21597,12 @@ decode_mode_spec (struct window *w, register int c, int field_width, line_number_displayed = 1; /* Make the string to show. */ - pint2str (decode_mode_spec_buf, field_width, topline + nlines); + pint2str (decode_mode_spec_buf, width, topline + nlines); return decode_mode_spec_buf; no_value: { char* p = decode_mode_spec_buf; - int pad = field_width - 2; + int pad = width - 2; while (pad-- > 0) *p++ = ' '; *p++ = '?'; @@ -22486,7 +22516,7 @@ init_glyph_string (struct glyph_string *s, /* Append the list of glyph strings with head H and tail T to the list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */ -static inline void +static void append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail, struct glyph_string *h, struct glyph_string *t) { @@ -22506,7 +22536,7 @@ append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tai list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */ -static inline void +static void prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail, struct glyph_string *h, struct glyph_string *t) { @@ -22525,7 +22555,7 @@ prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **ta /* Append glyph string S to the list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the resulting list. */ -static inline void +static void append_glyph_string (struct glyph_string **head, struct glyph_string **tail, struct glyph_string *s) { @@ -22540,7 +22570,7 @@ append_glyph_string (struct glyph_string **head, struct glyph_string **tail, Value is a pointer to a realized face that is ready for display if DISPLAY_P is non-zero. */ -static inline struct face * +static struct face * get_char_face_and_encoding (struct frame *f, int c, int face_id, XChar2b *char2b, int display_p) { @@ -22573,7 +22603,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id, The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is a pointer to a realized face that is ready for display. */ -static inline struct face * +static struct face * get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph, XChar2b *char2b, int *two_byte_p) { @@ -22610,7 +22640,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph, /* Get glyph code of character C in FONT in the two-byte form CHAR2B. Return 1 if FONT has a glyph for C, otherwise return 0. */ -static inline int +static int get_char_glyph_code (int c, struct font *font, XChar2b *char2b) { unsigned code; @@ -23084,7 +23114,7 @@ right_overwriting (struct glyph_string *s) first glyph following S. LAST_X is the right-most x-position + 1 in the drawing area. */ -static inline void +static void set_glyph_string_background_width (struct glyph_string *s, int start, int last_x) { /* If the face of this glyph string has to be drawn to the end of @@ -23410,8 +23440,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. */ @@ -23453,7 +23482,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; @@ -23645,7 +23676,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, /* Store one glyph for IT->char_to_display in IT->glyph_row. Called from x_produce_glyphs when IT->glyph_row is non-null. */ -static inline void +static void append_glyph (struct it *it) { struct glyph *glyph; @@ -23688,8 +23719,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; @@ -23719,7 +23760,7 @@ append_glyph (struct it *it) IT->glyph_row. Called from x_produce_glyphs when IT->glyph_row is non-null. */ -static inline void +static void append_composite_glyph (struct it *it) { struct glyph *glyph; @@ -23763,8 +23804,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; @@ -23788,7 +23839,7 @@ append_composite_glyph (struct it *it) /* Change IT->ascent and IT->height according to the setting of IT->voffset. */ -static inline void +static void take_vertical_position_into_account (struct it *it) { if (it->voffset) @@ -23941,8 +23992,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; @@ -24001,8 +24062,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; @@ -24069,17 +24140,16 @@ produce_stretch_glyph (struct it *it) Lisp_Object prop, plist; int width = 0, height = 0, align_to = -1; int zero_width_ok_p = 0; - int ascent = 0; double tem; - struct face *face = NULL; struct font *font = NULL; #ifdef HAVE_WINDOW_SYSTEM + int ascent = 0; int zero_height_ok_p = 0; if (FRAME_WINDOW_P (it->f)) { - face = FACE_FROM_ID (it->f, it->face_id); + struct face *face = FACE_FROM_ID (it->f, it->face_id); font = face->font ? face->font : FRAME_FONT (it->f); PREPARE_FACE_FOR_DISPLAY (it->f, face); } @@ -24455,8 +24525,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; @@ -25326,7 +25406,7 @@ x_write_glyphs (struct glyph *start, int len) if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA]) chpos = updated_row->used[TEXT_AREA] - 1; - BLOCK_INPUT; + block_input (); /* Write glyphs. */ @@ -25344,7 +25424,7 @@ x_write_glyphs (struct glyph *start, int len) && chpos < hpos + len) updated_window->phys_cursor_on_p = 0; - UNBLOCK_INPUT; + unblock_input (); /* Advance the output cursor. */ output_cursor.hpos += len; @@ -25367,7 +25447,7 @@ x_insert_glyphs (struct glyph *start, int len) ptrdiff_t hpos; eassert (updated_window && updated_row); - BLOCK_INPUT; + block_input (); w = updated_window; f = XFRAME (WINDOW_FRAME (w)); @@ -25401,7 +25481,7 @@ x_insert_glyphs (struct glyph *start, int len) /* Advance the output cursor. */ output_cursor.hpos += len; output_cursor.x += shift_by_width; - UNBLOCK_INPUT; + unblock_input (); } @@ -25470,10 +25550,10 @@ x_clear_end_of_line (int to_x) /* Prevent inadvertently clearing to end of the X window. */ if (to_x > from_x && to_y > from_y) { - BLOCK_INPUT; + block_input (); FRAME_RIF (f)->clear_frame_area (f, from_x, from_y, to_x - from_x, to_y - from_y); - UNBLOCK_INPUT; + unblock_input (); } } @@ -25800,7 +25880,7 @@ x_fix_overlapping_area (struct window *w, struct glyph_row *row, { int i, x; - BLOCK_INPUT; + block_input (); x = 0; for (i = 0; i < row->used[area];) @@ -25828,7 +25908,7 @@ x_fix_overlapping_area (struct window *w, struct glyph_row *row, } } - UNBLOCK_INPUT; + unblock_input (); } @@ -26046,7 +26126,7 @@ display_and_set_cursor (struct window *w, int on, || (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])) glyph = glyph_row->glyphs[TEXT_AREA] + hpos; - eassert (interrupt_input_blocked); + eassert (input_blocked_p ()); /* Set new_cursor_type to the cursor we want to be displayed. */ new_cursor_type = get_window_cursor_type (w, glyph, @@ -26116,10 +26196,10 @@ update_window_cursor (struct window *w, int on) if (row->reversed_p && hpos >= row->used[TEXT_AREA]) hpos = row->used[TEXT_AREA] - 1; - BLOCK_INPUT; + block_input (); display_and_set_cursor (w, on, hpos, vpos, w->phys_cursor.x, w->phys_cursor.y); - UNBLOCK_INPUT; + unblock_input (); } } @@ -26297,10 +26377,10 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) if (row->reversed_p && hpos >= row->used[TEXT_AREA]) hpos = row->used[TEXT_AREA] - 1; - BLOCK_INPUT; + block_input (); display_and_set_cursor (w, 1, hpos, w->phys_cursor.vpos, w->phys_cursor.x, w->phys_cursor.y); - UNBLOCK_INPUT; + unblock_input (); } #endif /* HAVE_WINDOW_SYSTEM */ } @@ -27633,12 +27713,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); @@ -28115,11 +28189,11 @@ x_clear_window_mouse_face (struct window *w) Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); Lisp_Object window; - BLOCK_INPUT; + block_input (); XSETWINDOW (window, w); if (EQ (window, hlinfo->mouse_face_window)) clear_mouse_face (hlinfo); - UNBLOCK_INPUT; + unblock_input (); } @@ -28689,6 +28763,7 @@ syms_of_xdisp (void) staticpro (&Vmessage_stack); DEFSYM (Qinhibit_redisplay, "inhibit-redisplay"); + DEFSYM (Qredisplay_internal, "redisplay_internal (C function)"); message_dolog_marker1 = Fmake_marker (); staticpro (&message_dolog_marker1); @@ -28928,12 +29003,6 @@ A value of nil means to respect the value of `truncate-lines'. If `word-wrap' is enabled, you might want to reduce this. */); Vtruncate_partial_width_windows = make_number (50); - DEFVAR_BOOL ("mode-line-inverse-video", mode_line_inverse_video, - doc: /* When nil, display the mode-line/header-line/menu-bar in the default face. -Any other value means to use the appropriate face, `mode-line', -`header-line', or `menu' respectively. */); - mode_line_inverse_video = 1; - DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit, doc: /* Maximum buffer size for which line number should be displayed. If the buffer is bigger than this, the line number does not appear @@ -28986,7 +29055,7 @@ and is used only on frames for which no explicit name has been set doc: /* Maximum number of lines to keep in the message log buffer. If nil, disable message logging. If t, log messages but don't truncate the buffer when it becomes large. */); - Vmessage_log_max = make_number (100); + Vmessage_log_max = make_number (1000); DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions, doc: /* Functions called before redisplay, if window sizes have changed. @@ -29357,11 +29426,7 @@ init_xdisp (void) help_echo_showing_p = 0; } -/* Since w32 does not support atimers, it defines its own implementation of - the following three functions in w32fns.c. */ -#ifndef WINDOWSNT - -/* Platform-independent portion of hourglass implementation. */ +/* Platform-independent portion of hourglass implementation. */ /* Cancel a currently active hourglass timer, and start a new one. */ void @@ -29383,6 +29448,13 @@ start_hourglass (void) else delay = make_emacs_time (DEFAULT_HOURGLASS_DELAY, 0); +#ifdef HAVE_NTGUI + { + extern void w32_note_current_window (void); + w32_note_current_window (); + } +#endif /* HAVE_NTGUI */ + hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay, show_hourglass, NULL); #endif @@ -29405,4 +29477,3 @@ cancel_hourglass (void) hide_hourglass (); #endif } -#endif /* ! WINDOWSNT */