X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/5e6d03b2abd37151ae1329c4b98edfa8242d2f0f..9ce28d805f8777b3f7ca6a1039ed845319a5d4f5:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 0d3f473b6f..ab492d098d 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-2013 Free Software Foundation, Inc. +Copyright (C) 1985-1988, 1993-1995, 1997-2014 Free Software Foundation, +Inc. This file is part of GNU Emacs. @@ -570,7 +571,7 @@ static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS]; /* Ascent and height of the last line processed by move_it_to. */ -static int last_max_ascent, last_height; +static int last_height; /* Non-zero if there's a help-echo in the echo area. */ @@ -1018,23 +1019,25 @@ window_text_bottom_y (struct window *w) int window_box_width (struct window *w, enum glyph_row_area area) { - int pixels = w->pixel_width; + int width = w->pixel_width; if (!w->pseudo_window_p) { - pixels -= WINDOW_SCROLL_BAR_AREA_WIDTH (w); - pixels -= WINDOW_RIGHT_DIVIDER_WIDTH (w); + width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w); + width -= WINDOW_RIGHT_DIVIDER_WIDTH (w); if (area == TEXT_AREA) - pixels -= (WINDOW_MARGINS_WIDTH (w) + width -= (WINDOW_MARGINS_WIDTH (w) + WINDOW_FRINGES_WIDTH (w)); else if (area == LEFT_MARGIN_AREA) - pixels = WINDOW_LEFT_MARGIN_WIDTH (w); + width = WINDOW_LEFT_MARGIN_WIDTH (w); else if (area == RIGHT_MARGIN_AREA) - pixels = WINDOW_RIGHT_MARGIN_WIDTH (w); + width = WINDOW_RIGHT_MARGIN_WIDTH (w); } - return pixels; + /* With wide margins, fringes, etc. we might end up with a negative + width, correct that here. */ + return max (0, width); } @@ -1114,7 +1117,8 @@ window_box_left_offset (struct window *w, enum glyph_row_area area) && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)) x += WINDOW_LEFT_FRINGE_WIDTH (w); - return x; + /* Don't return more than the window's pixel width. */ + return min (x, w->pixel_width); } @@ -1125,7 +1129,9 @@ window_box_left_offset (struct window *w, enum glyph_row_area area) int window_box_right_offset (struct window *w, enum glyph_row_area area) { - return window_box_left_offset (w, area) + window_box_width (w, area); + /* Don't return more than the window's pixel width. */ + return min (window_box_left_offset (w, area) + window_box_width (w, area), + w->pixel_width); } /* Return the frame-relative coordinate of the left edge of display @@ -1256,12 +1262,23 @@ Value is the height in pixels of the line at point. */) struct it it; struct text_pos pt; struct window *w = XWINDOW (selected_window); + struct buffer *old_buffer = NULL; + Lisp_Object result; + if (XBUFFER (w->contents) != current_buffer) + { + old_buffer = current_buffer; + set_buffer_internal_1 (XBUFFER (w->contents)); + } SET_TEXT_POS (pt, PT, PT_BYTE); start_display (&it, w, pt); it.vpos = it.current_y = 0; last_height = 0; - return make_number (line_bottom_y (&it)); + result = make_number (line_bottom_y (&it)); + if (old_buffer) + set_buffer_internal_1 (old_buffer); + + return result; } /* Return the default pixel height of text lines in window W. The @@ -2413,7 +2430,13 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) } if (part != ON_MODE_LINE && part != ON_HEADER_LINE) - gx += window_box_left_offset (w, area); + { + gx += window_box_left_offset (w, area); + /* Don't expand over the modeline to make sure the vertical + drag cursor is shown early enough. */ + height = min (height, + max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy)); + } } else { @@ -2421,6 +2444,10 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) gx = (x / width) * width; y -= gy; gy += (y / height) * height; + if (part != ON_MODE_LINE && part != ON_HEADER_LINE) + /* See comment above. */ + height = min (height, + max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy)); } break; @@ -2435,7 +2462,22 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? window_box_right_offset (w, RIGHT_MARGIN_AREA) : window_box_right_offset (w, TEXT_AREA)); - width = WINDOW_RIGHT_FRINGE_WIDTH (w); + if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0 + && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w) + && !WINDOW_RIGHTMOST_P (w)) + if (gx < WINDOW_PIXEL_WIDTH (w) - width) + /* Make sure the vertical border can get her own glyph to the + right of the one we build here. */ + width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width; + else + width = WINDOW_PIXEL_WIDTH (w) - gx; + else + width = WINDOW_RIGHT_FRINGE_WIDTH (w); + + goto row_glyph; + + case ON_VERTICAL_BORDER: + gx = WINDOW_PIXEL_WIDTH (w) - width; goto row_glyph; case ON_SCROLL_BAR: @@ -2466,6 +2508,21 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) } break; + case ON_RIGHT_DIVIDER: + gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w); + width = WINDOW_RIGHT_DIVIDER_WIDTH (w); + gy = 0; + /* The bottom divider prevails. */ + height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w); + goto add_edge;; + + case ON_BOTTOM_DIVIDER: + gx = 0; + width = WINDOW_PIXEL_WIDTH (w); + gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w); + height = WINDOW_BOTTOM_DIVIDER_WIDTH (w); + goto add_edge; + default: ; virtual_glyph: @@ -2486,6 +2543,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) goto store_rect; } + add_edge: gx += WINDOW_LEFT_EDGE_X (w); gy += WINDOW_TOP_EDGE_Y (w); @@ -2803,8 +2861,9 @@ init_iterator (struct it *it, struct window *w, it->redisplay_end_trigger_charpos = marker_position (w->redisplay_end_trigger); else if (INTEGERP (w->redisplay_end_trigger)) - it->redisplay_end_trigger_charpos = - clip_to_bounds (PTRDIFF_MIN, XINT (w->redisplay_end_trigger), PTRDIFF_MAX); + it->redisplay_end_trigger_charpos + = clip_to_bounds (PTRDIFF_MIN, XINT (w->redisplay_end_trigger), + PTRDIFF_MAX); it->tab_width = SANE_TAB_WIDTH (current_buffer); @@ -2921,7 +2980,7 @@ init_iterator (struct it *it, struct window *w, /* If we have a boxed mode line, make the first character appear with a left box line. */ face = FACE_FROM_ID (it->f, remapped_base_face_id); - if (face->box != FACE_NO_BOX) + if (face && face->box != FACE_NO_BOX) it->start_of_box_run_p = true; } @@ -3906,6 +3965,15 @@ handle_face_prop (struct it *it) For strings from wrap-prefix and line-prefix properties, use the default face, possibly remapped via Vface_remapping_alist. */ + /* Note that the fact that we use the face at _buffer_ + position means that a 'display' property on an overlay + string will not inherit the face of that overlay string, + but will instead revert to the face of buffer text + covered by the overlay. This is visible, e.g., when the + overlay specifies a box face, but neither the buffer nor + the display string do. This sounds like a design bug, + but Emacs always did that since v21.1, so changing that + might be a big deal. */ base_face_id = it->string_from_prefix_prop_p ? (!NILP (Vface_remapping_alist) ? lookup_basic_face (it->f, DEFAULT_FACE_ID) @@ -5939,7 +6007,16 @@ pop_it (struct it *it) it->object = it->w->contents; break; case GET_FROM_STRING: - it->object = it->string; + { + struct face *face = FACE_FROM_ID (it->f, it->face_id); + + /* Restore the face_box_p flag, since it could have been + overwritten by the face of the object that we just finished + displaying. */ + if (face) + it->face_box_p = face->box != FACE_NO_BOX; + it->object = it->string; + } break; case GET_FROM_DISPLAY_VECTOR: if (it->s) @@ -6408,6 +6485,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p) it->bidi_it.string.s = NULL; it->bidi_it.string.lstring = Qnil; it->bidi_it.string.bufpos = 0; + it->bidi_it.string.from_disp_str = 0; it->bidi_it.string.unibyte = 0; it->bidi_it.w = it->w; } @@ -7025,21 +7103,44 @@ get_next_display_element (struct it *it) If this is the last string character displayed, check the next buffer location. */ else if ((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1) - && (it->current.overlay_string_index - == it->n_overlay_strings - 1)) + /* n_overlay_strings is unreliable unless + overlay_string_index is non-negative. */ + && ((it->current.overlay_string_index >= 0 + && (it->current.overlay_string_index + == it->n_overlay_strings - 1)) + /* A string from display property. */ + || it->from_disp_prop_p)) { ptrdiff_t ignore; int next_face_id; struct text_pos pos = it->current.pos; - INC_TEXT_POS (pos, it->multibyte_p); - next_face_id = face_at_buffer_position - (it->w, CHARPOS (pos), &ignore, - (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT), 0, - -1); - it->end_of_box_run_p - = (FACE_FROM_ID (it->f, next_face_id)->box - == FACE_NO_BOX); + /* For a string from a display property, the next + buffer position is stored in the 'position' + member of the iteration stack slot below the + current one, see handle_single_display_spec. By + contrast, it->current.pos was is not yet updated + to point to that buffer position; that will + happen in pop_it, after we finish displaying the + current string. Note that we already checked + above that it->sp is positive, so subtracting one + from it is safe. */ + if (it->from_disp_prop_p) + pos = (it->stack + it->sp - 1)->position; + else + INC_TEXT_POS (pos, it->multibyte_p); + + if (CHARPOS (pos) >= ZV) + it->end_of_box_run_p = true; + else + { + next_face_id = face_at_buffer_position + (it->w, CHARPOS (pos), &ignore, + CHARPOS (pos) + TEXT_PROP_DISTANCE_LIMIT, 0, -1); + it->end_of_box_run_p + = (FACE_FROM_ID (it->f, next_face_id)->box + == FACE_NO_BOX); + } } } } @@ -8305,7 +8406,7 @@ move_it_in_display_line_to (struct it *it, void *ppos_data = NULL; int may_wrap = 0; enum it_method prev_method = it->method; - ptrdiff_t prev_pos = IT_CHARPOS (*it); + ptrdiff_t closest_pos IF_LINT (= 0), prev_pos = IT_CHARPOS (*it); int saw_smaller_pos = prev_pos < to_charpos; /* Don't produce glyphs in produce_glyphs. */ @@ -8322,16 +8423,21 @@ move_it_in_display_line_to (struct it *it, atx_it.sp = -1; /* Use ppos_it under bidi reordering to save a copy of IT for the - position > CHARPOS that is the closest to CHARPOS. We restore - that position in IT when we have scanned the entire display line - without finding a match for CHARPOS and all the character - positions are greater than CHARPOS. */ + initial position. We restore that position in IT when we have + scanned the entire display line without finding a match for + TO_CHARPOS and all the character positions are greater than + TO_CHARPOS. We then restart the scan from the initial position, + and stop at CLOSEST_POS, which is a position > TO_CHARPOS that is + the closest to TO_CHARPOS. */ if (it->bidi_p) { - SAVE_IT (ppos_it, *it, ppos_data); - SET_TEXT_POS (ppos_it.current.pos, ZV, ZV_BYTE); if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos) - SAVE_IT (ppos_it, *it, ppos_data); + { + SAVE_IT (ppos_it, *it, ppos_data); + closest_pos = IT_CHARPOS (*it); + } + else + closest_pos = ZV; } #define BUFFER_POS_REACHED_P() \ @@ -8475,8 +8581,8 @@ move_it_in_display_line_to (struct it *it, if (it->bidi_p && (op & MOVE_TO_POS) && IT_CHARPOS (*it) > to_charpos - && IT_CHARPOS (*it) < IT_CHARPOS (ppos_it)) - SAVE_IT (ppos_it, *it, ppos_data); + && IT_CHARPOS (*it) < closest_pos) + closest_pos = IT_CHARPOS (*it); continue; } @@ -8556,7 +8662,12 @@ move_it_in_display_line_to (struct it *it, doesn't fit on the line, e.g. a wide image. */ it->hpos == 0 || (new_x == it->last_visible_x - && FRAME_WINDOW_P (it->f))) + && FRAME_WINDOW_P (it->f) + /* When word-wrap is ON and we have a valid + wrap point, we don't allow the last glyph + to "just barely fit" on the line. */ + && (it->line_wrap != WORD_WRAP + || wrap_it.sp < 0))) { ++it->hpos; it->current_x = new_x; @@ -8698,9 +8809,11 @@ move_it_in_display_line_to (struct it *it, { if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos) { - if (IT_CHARPOS (ppos_it) < ZV) + if (closest_pos < ZV) { RESTORE_IT (it, &ppos_it, ppos_data); + move_it_in_display_line_to (it, closest_pos, -1, + MOVE_TO_POS); result = MOVE_POS_MATCH_OR_ZV; } else @@ -8730,8 +8843,8 @@ move_it_in_display_line_to (struct it *it, if (it->bidi_p && (op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos - && IT_CHARPOS (*it) < IT_CHARPOS (ppos_it)) - SAVE_IT (ppos_it, *it, ppos_data); + && IT_CHARPOS (*it) < closest_pos) + closest_pos = IT_CHARPOS (*it); /* Stop if lines are truncated and IT's current x-position is past the right edge of the window now. */ @@ -8757,8 +8870,13 @@ move_it_in_display_line_to (struct it *it, && IT_CHARPOS (*it) > to_charpos)) { if (it->bidi_p - && !at_eob_p && IT_CHARPOS (ppos_it) < ZV) - RESTORE_IT (it, &ppos_it, ppos_data); + && !BUFFER_POS_REACHED_P () + && !at_eob_p && closest_pos < ZV) + { + RESTORE_IT (it, &ppos_it, ppos_data); + move_it_in_display_line_to (it, closest_pos, -1, + MOVE_TO_POS); + } result = MOVE_POS_MATCH_OR_ZV; break; } @@ -8772,8 +8890,11 @@ move_it_in_display_line_to (struct it *it, && !saw_smaller_pos && IT_CHARPOS (*it) > to_charpos) { - if (IT_CHARPOS (ppos_it) < ZV) - RESTORE_IT (it, &ppos_it, ppos_data); + if (closest_pos < ZV) + { + RESTORE_IT (it, &ppos_it, ppos_data); + move_it_in_display_line_to (it, closest_pos, -1, MOVE_TO_POS); + } result = MOVE_POS_MATCH_OR_ZV; break; } @@ -9096,7 +9217,6 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos it->current_y += it->max_ascent + it->max_descent; ++it->vpos; last_height = it->max_ascent + it->max_descent; - last_max_ascent = it->max_ascent; it->max_ascent = it->max_descent = 0; } @@ -9123,7 +9243,6 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos it->current_y += it->max_ascent + it->max_descent; ++it->vpos; last_height = it->max_ascent + it->max_descent; - last_max_ascent = it->max_ascent; } if (backup_data) @@ -9403,6 +9522,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) ptrdiff_t start_charpos, i; int nchars_per_row = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f); + bool hit_pos_limit = false; ptrdiff_t pos_limit; /* Start at the beginning of the screen line containing IT's @@ -9419,8 +9539,11 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) 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); + if (i > 0 && IT_CHARPOS (*it) <= pos_limit) + hit_pos_limit = true; reseat (it, it->current.pos, 1); /* Move further back if we end up in a string or an image. */ @@ -9464,6 +9587,25 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) else bidi_unshelve_cache (it2data, 1); } + else if (hit_pos_limit && pos_limit > BEGV + && dvpos < 0 && it2.vpos < -dvpos) + { + /* If we hit the limit, but still didn't make it far enough + back, that means there's a display string with a newline + covering a large chunk of text, and that caused + back_to_previous_visible_line_start try to go too far. + Punish those who commit such atrocities by going back + until we've reached DVPOS, after lifting the limit, which + could make it slow for very long lines. "If it hurts, + don't do that!" */ + dvpos += it2.vpos; + RESTORE_IT (it, it, it2data); + for (i = -dvpos; i > 0; --i) + { + back_to_previous_visible_line_start (it); + it->vpos--; + } + } else RESTORE_IT (it, it, it2data); } @@ -9492,23 +9634,27 @@ character. TO, if non-nil, specifies the last text position and defaults to the maximum accessible position of the buffer. If TO is t, use the maximum accessible position that is not a newline character. -The optional argument X_LIMIT, if non-nil, specifies the maximum text -width that can be returned. X_LIMIT nil or omitted, means to use the +The optional argument X-LIMIT, if non-nil, specifies the maximum text +width that can be returned. X-LIMIT nil or omitted, means to use the pixel-width of WINDOW's body; use this if you do not intend to change the width of WINDOW. Use the maximum width WINDOW may assume if you -intend to change WINDOW's width. +intend to change WINDOW's width. In any case, text whose x-coordinate +is beyond X-LIMIT is ignored. Since calculating the width of long lines +can take some time, it's always a good idea to make this argument as +small as possible; in particular, if the buffer contains long lines that +shall be truncated anyway. -The optional argument Y_LIMIT, if non-nil, specifies the maximum text +The optional argument Y-LIMIT, if non-nil, specifies the maximum text height that can be returned. Text lines whose y-coordinate is beyond -Y_LIMIT are ignored. Since calculating the text height of a large +Y-LIMIT are ignored. Since calculating the text height of a large buffer can take some time, it makes sense to specify this argument if the size of the buffer is unknown. -Optional argument MODE_AND_HEADER_LINE nil or omitted means do not +Optional argument MODE-AND-HEADER-LINE nil or omitted means do not include the height of the mode- or header-line of WINDOW in the return value. If it is either the symbol `mode-line' or `header-line', include only the height of that line, if present, in the return value. If t, -include the height of any of these lines in the return value. */) +include the height of both, if present, in the return value. */) (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, Lisp_Object y_limit, Lisp_Object mode_and_header_line) { @@ -9576,7 +9722,6 @@ include the height of any of these lines in the return value. */) SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start)); start_display (&it, w, startp); - /** move_it_vertically_backward (&it, 0); **/ if (NILP (x_limit)) x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y); else @@ -9590,14 +9735,7 @@ include the height of any of these lines in the return value. */) MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); } - if (start == end) - y = it.current_y; - else - { - /* Count last line. */ - last_height = 0; - y = line_bottom_y (&it); /* - y; */ - } + y = it.current_y + it.max_ascent + it.max_descent; if (!EQ (mode_and_header_line, Qheader_line) && !EQ (mode_and_header_line, Qt)) @@ -9853,7 +9991,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte) incrementing windows_or_buffers_changed even if *Messages* is shown in some window. So we must manually set windows_or_buffers_changed here to make up for that. */ - windows_or_buffers_changed = old_windows_or_buffers_changed; + windows_or_buffers_changed = old_windows_or_buffers_changed; bset_redisplay (current_buffer); set_buffer_internal (oldbuf); @@ -10657,9 +10795,9 @@ resize_mini_window (struct window *w, int exact_p) /* Compute a suitable window start. */ if (height > max_height) { - height = max_height; + height = (max_height / unit) * unit; init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID); - move_it_vertically_backward (&it, height); + move_it_vertically_backward (&it, height - unit); start = it.current.pos; } else @@ -12057,8 +12195,8 @@ display_tool_bar_line (struct it *it, int height) #define MAX_FRAME_TOOL_BAR_HEIGHT(f) \ ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f))) -/* Value is the number of screen lines needed to make all tool-bar - items of frame F visible. The number of actual rows needed is +/* Value is the number of pixels needed to make all tool-bar items of + frame F visible. The actual number of glyph rows needed is returned in *N_ROWS if non-NULL. */ static int @@ -12075,8 +12213,7 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise) F->desired_tool_bar_string in the tool-bar window of frame F. */ init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID); it.first_visible_x = 0; - /* PXW: Use FRAME_PIXEL_WIDTH (f) here? */ - it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f); + it.last_visible_x = WINDOW_PIXEL_WIDTH (w); reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1); it.paragraph_embedding = L2R; @@ -12109,7 +12246,7 @@ DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height, 0, 2, 0, doc: /* Return the number of lines occupied by the tool bar of FRAME. If FRAME is nil or omitted, use the selected frame. Optional argument -PIXELWISE non-nil means return the height of the tool bar inpixels. */) +PIXELWISE non-nil means return the height of the tool bar in pixels. */) (Lisp_Object frame, Lisp_Object pixelwise) { int height = 0; @@ -12254,6 +12391,10 @@ redisplay_tool_bar (struct frame *f) && it.current_y < max_tool_bar_height) change_height_p = 1; + /* We subtract 1 because display_tool_bar_line advances the + glyph_row pointer before returning to its caller. We want to + examine the last glyph row produced by + display_tool_bar_line. */ row = it.glyph_row - 1; /* If there are blank lines at the end, except for a partially @@ -12286,18 +12427,35 @@ redisplay_tool_bar (struct frame *f) if (change_height_p) { + /* Current size of the tool-bar window in canonical line + units. */ + int old_lines = WINDOW_TOTAL_LINES (w); + /* Required size of the tool-bar window in canonical + line units. */ int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f)); - - XSETFRAME (frame, f); - Fmodify_frame_parameters (frame, - list1 (Fcons (Qtool_bar_lines, - make_number (new_lines)))); - /* Always do that now. */ - clear_glyph_matrix (w->desired_matrix); - f->n_tool_bar_rows = nrows; - f->fonts_changed = 1; - return 1; + /* Maximum size of the tool-bar window in canonical line + units that this frame can allow. */ + int max_lines = + WINDOW_TOTAL_LINES (XWINDOW (FRAME_ROOT_WINDOW (f))) - 1; + + /* Don't try to change the tool-bar window size and set + the fonts_changed flag unless really necessary. That + flag causes redisplay to give up and retry + redisplaying the frame from scratch, so setting it + unnecessarily can lead to nasty redisplay loops. */ + if (new_lines <= max_lines + && eabs (new_lines - old_lines) >= 1) + { + XSETFRAME (frame, f); + Fmodify_frame_parameters (frame, + list1 (Fcons (Qtool_bar_lines, + make_number (new_lines)))); + clear_glyph_matrix (w->desired_matrix); + f->n_tool_bar_rows = nrows; + f->fonts_changed = 1; + return 1; + } } } } @@ -12607,15 +12765,25 @@ hscroll_window_tree (Lisp_Object window) { int h_margin; int text_area_width; - struct glyph_row *current_cursor_row - = MATRIX_ROW (w->current_matrix, w->cursor.vpos); - struct glyph_row *desired_cursor_row - = MATRIX_ROW (w->desired_matrix, w->cursor.vpos); - struct glyph_row *cursor_row - = (desired_cursor_row->enabled_p - ? desired_cursor_row - : current_cursor_row); - int row_r2l_p = cursor_row->reversed_p; + struct glyph_row *cursor_row; + struct glyph_row *bottom_row; + int row_r2l_p; + + bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w); + if (w->cursor.vpos < bottom_row - w->desired_matrix->rows) + cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos); + else + cursor_row = bottom_row - 1; + + if (!cursor_row->enabled_p) + { + bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w); + if (w->cursor.vpos < bottom_row - w->current_matrix->rows) + cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos); + else + cursor_row = bottom_row - 1; + } + row_r2l_p = cursor_row->reversed_p; text_area_width = window_box_width (w, TEXT_AREA); @@ -15442,29 +15610,32 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste /* As soon as we've found the exact match for point, or the first suitable row whose ends_at_zv_p flag is set, we are done. */ - at_zv_p = - MATRIX_ROW (w->current_matrix, w->cursor.vpos)->ends_at_zv_p; - if (rv && !at_zv_p - && w->cursor.hpos >= 0 - && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix, - w->cursor.vpos)) + if (rv) { - struct glyph_row *candidate = - MATRIX_ROW (w->current_matrix, w->cursor.vpos); - struct glyph *g = - candidate->glyphs[TEXT_AREA] + w->cursor.hpos; - ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate); - - exact_match_p = - (BUFFERP (g->object) && g->charpos == PT) - || (INTEGERP (g->object) - && (g->charpos == PT - || (g->charpos == 0 && endpos - 1 == PT))); - } - if (rv && (at_zv_p || exact_match_p)) - { - rc = CURSOR_MOVEMENT_SUCCESS; - break; + at_zv_p = MATRIX_ROW (w->current_matrix, + w->cursor.vpos)->ends_at_zv_p; + if (!at_zv_p + && w->cursor.hpos >= 0 + && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix, + w->cursor.vpos)) + { + struct glyph_row *candidate = + MATRIX_ROW (w->current_matrix, w->cursor.vpos); + struct glyph *g = + candidate->glyphs[TEXT_AREA] + w->cursor.hpos; + ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate); + + exact_match_p = + (BUFFERP (g->object) && g->charpos == PT) + || (INTEGERP (g->object) + && (g->charpos == PT + || (g->charpos == 0 && endpos - 1 == PT))); + } + if (at_zv_p || exact_match_p) + { + rc = CURSOR_MOVEMENT_SUCCESS; + break; + } } if (MATRIX_ROW_BOTTOM_Y (row) == last_y) break; @@ -15590,7 +15761,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) && REDISPLAY_SOME_P () && !w->redisplay && !f->redisplay - && !buffer->text->redisplay) + && !buffer->text->redisplay + && BUF_PT (buffer) == w->last_point) return; /* Make sure that both W's markers are valid. */ @@ -15736,16 +15908,20 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) this may be a bit late to catch such changes, but the rest of redisplay goes (non-fatally) haywire when the display table is changed, so why should we worry about doing any better? */ - if (current_buffer->width_run_cache) + if (current_buffer->width_run_cache + || (current_buffer->base_buffer + && current_buffer->base_buffer->width_run_cache)) { struct Lisp_Char_Table *disptab = buffer_display_table (); if (! disptab_matches_widthtab (disptab, XVECTOR (BVAR (current_buffer, width_table)))) { - invalidate_region_cache (current_buffer, - current_buffer->width_run_cache, - BEG, Z); + struct buffer *buf = current_buffer; + + if (buf->base_buffer) + buf = buf->base_buffer; + invalidate_region_cache (buf, buf->width_run_cache, BEG, Z); recompute_width_table (current_buffer, disptab); } } @@ -16258,12 +16434,50 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) /* Consider the following case: Window starts at BEGV, there is invisible, intangible text at BEGV, so that display starts at some point START > BEGV. It can happen that we are called with - PT somewhere between BEGV and START. Try to handle that case. */ + PT somewhere between BEGV and START. Try to handle that case, + and similar ones. */ if (w->cursor.vpos < 0) { - struct glyph_row *row = w->current_matrix->rows; - if (row->mode_line_p) - ++row; + /* First, try locating the proper glyph row for PT. */ + struct glyph_row *row = + row_containing_pos (w, PT, w->current_matrix->rows, NULL, 0); + + /* Sometimes point is at the beginning of invisible text that is + before the 1st character displayed in the row. In that case, + row_containing_pos fails to find the row, because no glyphs + with appropriate buffer positions are present in the row. + Therefore, we next try to find the row which shows the 1st + position after the invisible text. */ + if (!row) + { + Lisp_Object val = + get_char_property_and_overlay (make_number (PT), Qinvisible, + Qnil, NULL); + + if (TEXT_PROP_MEANS_INVISIBLE (val)) + { + ptrdiff_t alt_pos; + Lisp_Object invis_end = + Fnext_single_char_property_change (make_number (PT), Qinvisible, + Qnil, Qnil); + + if (NATNUMP (invis_end)) + alt_pos = XFASTINT (invis_end); + else + alt_pos = ZV; + row = row_containing_pos (w, alt_pos, w->current_matrix->rows, + NULL, 0); + } + } + /* Finally, fall back on the first row of the window after the + header line (if any). This is slightly better than not + displaying the cursor at all. */ + if (!row) + { + row = w->current_matrix->rows; + if (row->mode_line_p) + ++row; + } set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0); } @@ -17297,9 +17511,16 @@ row_containing_pos (struct window *w, ptrdiff_t charpos, Value is - 1 if display has been updated - 0 if otherwise unsuccessful + >= 1 if successful, i.e. display has been updated + specifically: + 1 means the changes were in front of a newline that precedes + the window start, and the whole current matrix was reused + 2 means the changes were after the last position displayed + in the window, and the whole current matrix was reused + 3 means portions of the current matrix were reused, while + some of the screen lines were redrawn -1 if redisplay with same window start is known not to succeed + 0 if otherwise unsuccessful The following steps are performed: @@ -17374,6 +17595,12 @@ try_window_id (struct window *w) if (windows_or_buffers_changed || f->cursor_type_changed) GIVE_UP (2); + /* This function's optimizations cannot be used if overlays have + changed in the buffer displayed by the window, so give up if they + have. */ + if (w->last_overlay_modified != OVERLAY_MODIFF) + GIVE_UP (21); + /* Verify that narrowing has not changed. Also verify that we were not told to prevent redisplay optimizations. It would be nice to further @@ -18461,6 +18688,7 @@ insert_left_trunc_glyphs (struct it *it) truncate_it.current_x = 0; truncate_it.face_id = DEFAULT_FACE_ID; truncate_it.glyph_row = &scratch_glyph_row; + truncate_it.area = TEXT_AREA; truncate_it.glyph_row->used[TEXT_AREA] = 0; CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1; truncate_it.object = make_number (0); @@ -18876,14 +19104,16 @@ extend_face_to_end_of_line (struct it *it) && it->glyph_row->used[LEFT_MARGIN_AREA] == 0) { it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph; - it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id = face->id; + it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id = + default_face->id; it->glyph_row->used[LEFT_MARGIN_AREA] = 1; } if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0) { it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph; - it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id = face->id; + it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id = + default_face->id; it->glyph_row->used[RIGHT_MARGIN_AREA] = 1; } } @@ -18952,20 +19182,12 @@ extend_face_to_end_of_line (struct it *it) it->object = make_number (0); it->c = it->char_to_display = ' '; it->len = 1; - /* The last row's blank glyphs should get the default face, to - avoid painting the rest of the window with the region face, - if the region ends at ZV. */ - if (it->glyph_row->ends_at_zv_p) - it->face_id = default_face->id; - else - it->face_id = face->id; - face = FACE_FROM_ID (f, it->face_id); if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0 && (it->glyph_row->used[LEFT_MARGIN_AREA] < WINDOW_LEFT_MARGIN_WIDTH (it->w)) && !it->glyph_row->mode_line_p - && face && face->background != FRAME_BACKGROUND_PIXEL (f)) + && default_face->background != FRAME_BACKGROUND_PIXEL (f)) { struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA]; struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA]; @@ -18974,6 +19196,7 @@ extend_face_to_end_of_line (struct it *it) it->current_x += g->pixel_width; it->area = LEFT_MARGIN_AREA; + it->face_id = default_face->id; while (it->glyph_row->used[LEFT_MARGIN_AREA] < WINDOW_LEFT_MARGIN_WIDTH (it->w)) { @@ -18987,6 +19210,13 @@ extend_face_to_end_of_line (struct it *it) it->area = TEXT_AREA; } + /* The last row's blank glyphs should get the default face, to + avoid painting the rest of the window with the region face, + if the region ends at ZV. */ + if (it->glyph_row->ends_at_zv_p) + it->face_id = default_face->id; + else + it->face_id = face->id; PRODUCE_GLYPHS (it); while (it->current_x <= it->last_visible_x) @@ -18996,7 +19226,7 @@ extend_face_to_end_of_line (struct it *it) && (it->glyph_row->used[RIGHT_MARGIN_AREA] < WINDOW_RIGHT_MARGIN_WIDTH (it->w)) && !it->glyph_row->mode_line_p - && face && face->background != FRAME_BACKGROUND_PIXEL (f)) + && default_face->background != FRAME_BACKGROUND_PIXEL (f)) { struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA]; struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA]; @@ -19005,6 +19235,7 @@ extend_face_to_end_of_line (struct it *it) it->current_x += g->pixel_width; it->area = RIGHT_MARGIN_AREA; + it->face_id = default_face->id; while (it->glyph_row->used[RIGHT_MARGIN_AREA] < WINDOW_RIGHT_MARGIN_WIDTH (it->w)) { @@ -20070,7 +20301,12 @@ display_line (struct it *it) /* If we truncate lines, we are done when the last displayed glyphs reach past the right margin of the window. */ if (it->line_wrap == TRUNCATE - && (FRAME_WINDOW_P (it->f) && WINDOW_RIGHT_FRINGE_WIDTH (it->w) + && ((FRAME_WINDOW_P (it->f) + /* Images are preprocessed in produce_image_glyph such + that they are cropped at the right edge of the + window, so an image glyph will always end exactly at + last_visible_x, even if there's no right fringe. */ + && (WINDOW_RIGHT_FRINGE_WIDTH (it->w) || it->what == IT_IMAGE)) ? (it->current_x >= it->last_visible_x) : (it->current_x > it->last_visible_x))) { @@ -20103,19 +20339,26 @@ display_line (struct it *it) i = row->used[TEXT_AREA] - (i + 1); } - it->current_x = x_before; - if (!FRAME_WINDOW_P (it->f)) + /* produce_special_glyphs overwrites the last glyph, so + we don't want that if we want to keep that last + glyph, which means it's an image. */ + if (it->current_x > it->last_visible_x) { - for (n = row->used[TEXT_AREA]; i < n; ++i) + it->current_x = x_before; + if (!FRAME_WINDOW_P (it->f)) + { + for (n = row->used[TEXT_AREA]; i < n; ++i) + { + row->used[TEXT_AREA] = i; + produce_special_glyphs (it, IT_TRUNCATION); + } + } + else { row->used[TEXT_AREA] = i; produce_special_glyphs (it, IT_TRUNCATION); } - } - else - { - row->used[TEXT_AREA] = i; - produce_special_glyphs (it, IT_TRUNCATION); + it->hpos = hpos_before; } } else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)) @@ -20134,13 +20377,13 @@ display_line (struct it *it) goto at_end_of_line; } it->current_x = x_before; + it->hpos = hpos_before; } row->truncated_on_right_p = 1; it->continuation_lines_width = 0; reseat_at_next_visible_line_start (it, 0); row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n'; - it->hpos = hpos_before; break; } } @@ -20154,9 +20397,12 @@ display_line (struct it *it) && IT_CHARPOS (*it) != CHARPOS (row->start.pos)) { if (!FRAME_WINDOW_P (it->f) - || (row->reversed_p - ? WINDOW_RIGHT_FRINGE_WIDTH (it->w) - : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0) + || (((row->reversed_p + ? WINDOW_RIGHT_FRINGE_WIDTH (it->w) + : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0) + /* Don't let insert_left_trunc_glyphs overwrite the + first glyph of the row if it is an image. */ + && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH)) insert_left_trunc_glyphs (it); row->truncated_on_left_p = 1; } @@ -20359,6 +20605,7 @@ See also `bidi-paragraph-direction'. */) itb.string.s = NULL; itb.string.lstring = Qnil; itb.string.bufpos = 0; + itb.string.from_disp_str = 0; itb.string.unibyte = 0; /* We have no window to use here for ignoring window-specific overlays. Using NULL for window pointer will cause @@ -20692,6 +20939,30 @@ Value is the new character position of point. */) move_it_by_lines (&it, -1); target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f); target_is_eol_p = true; + /* Under word-wrap, we don't know the x coordinate of + the last character displayed on the previous line, + which immediately precedes the wrap point. To find + out its x coordinate, we try moving to the right + margin of the window, which will stop at the wrap + point, and then reset target_x to point at the + character that precedes the wrap point. This is not + needed on GUI frames, because (see below) there we + move from the left margin one grapheme cluster at a + time, and stop when we hit the wrap point. */ + if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP) + { + void *it_data = NULL; + struct it it2; + + SAVE_IT (it2, it, it_data); + move_it_in_display_line_to (&it, ZV, target_x, + MOVE_TO_POS | MOVE_TO_X); + /* If we arrived at target_x, that _is_ the last + character on the previous line. */ + if (it.current_x != target_x) + target_x = it.current_x - 1; + RESTORE_IT (&it, &it2, it_data); + } } } else @@ -20730,7 +21001,12 @@ Value is the new character position of point. */) new_pos = it.current.pos; while (it.current_x + it.pixel_width <= target_x - && rc == MOVE_X_REACHED) + && (rc == MOVE_X_REACHED + /* Under word-wrap, move_it_in_display_line_to + stops at correct coordinates, but sometimes + returns MOVE_POS_MATCH_OR_ZV. */ + || (it.line_wrap == WORD_WRAP + && rc == MOVE_POS_MATCH_OR_ZV))) { int new_x = it.current_x + it.pixel_width; @@ -20849,8 +21125,7 @@ display_menu_bar (struct window *w) eassert (!FRAME_WINDOW_P (f)); init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID); it.first_visible_x = 0; - /* PXW: Use FRAME_PIXEL_WIDTH (f) here? */ - it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f); + it.last_visible_x = FRAME_PIXEL_WIDTH (f); #elif defined (HAVE_X_WINDOWS) /* X without toolkit. */ if (FRAME_WINDOW_P (f)) { @@ -20861,8 +21136,7 @@ display_menu_bar (struct window *w) init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows, MENU_FACE_ID); it.first_visible_x = 0; - /* PXW: Use FRAME_PIXEL_WIDTH (f) here? */ - it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f); + it.last_visible_x = FRAME_PIXEL_WIDTH (f); } else #endif /* not USE_X_TOOLKIT and not USE_GTK */ @@ -22400,7 +22674,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, return decode_mode_spec_buf; no_value: { - char* p = decode_mode_spec_buf; + char *p = decode_mode_spec_buf; int pad = width - 2; while (pad-- > 0) *p++ = ' '; @@ -23148,7 +23422,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w)); } - prop = buffer_local_value_1 (prop, it->w->contents); + prop = buffer_local_value (prop, it->w->contents); if (EQ (prop, Qunbound)) prop = Qnil; } @@ -23200,7 +23474,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (pixels); } - car = buffer_local_value_1 (car, it->w->contents); + car = buffer_local_value (car, it->w->contents); if (EQ (car, Qunbound)) car = Qnil; } @@ -24315,13 +24589,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; + if (hl != overlap_hl) + clip_head = head; j = i; BUILD_GLYPH_STRINGS (j, start, h, t, overlap_hl, dummy_x, last_x); start = i; compute_overhangs_and_x (t, head->x, 1); prepend_glyph_string_lists (&head, &tail, h, t); - clip_head = head; + if (clip_head == NULL) + clip_head = head; } /* Prepend glyph strings for glyphs in front of the first glyph @@ -24342,7 +24619,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; - clip_head = head; + if (hl == overlap_hl || clip_head == NULL) + clip_head = head; BUILD_GLYPH_STRINGS (i, start, h, t, overlap_hl, dummy_x, last_x); for (s = h; s; s = s->next) @@ -24366,13 +24644,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; + if (hl != overlap_hl) + clip_tail = tail; BUILD_GLYPH_STRINGS (end, i, h, t, overlap_hl, x, last_x); /* Because BUILD_GLYPH_STRINGS updates the first argument, we don't have `end = i;' here. */ compute_overhangs_and_x (h, tail->x + tail->width, 0); append_glyph_string_lists (&head, &tail, h, t); - clip_tail = tail; + if (clip_tail == NULL) + clip_tail = tail; } /* Append glyph strings for glyphs following the last glyph @@ -24390,7 +24671,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, else overlap_hl = DRAW_NORMAL_TEXT; - clip_tail = tail; + if (hl == overlap_hl || clip_tail == NULL) + clip_tail = tail; i++; /* We must include the Ith glyph. */ BUILD_GLYPH_STRINGS (end, i, h, t, overlap_hl, x, last_x); @@ -27052,7 +27334,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) if (/* If window is in the process of being destroyed, don't bother to do anything. */ w->current_matrix != NULL - /* Don't update mouse highlight if hidden */ + /* Don't update mouse highlight if hidden. */ && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden) /* Recognize when we are called to operate on rows that don't exist anymore. This can happen when a window is split. */ @@ -28269,8 +28551,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, else if (area == ON_MODE_LINE) { Lisp_Object default_help - = buffer_local_value_1 (Qmode_line_default_help_echo, - w->contents); + = buffer_local_value (Qmode_line_default_help_echo, + w->contents); if (STRINGP (default_help)) { @@ -28286,6 +28568,10 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, /* Change the mouse pointer according to what is under it. */ if (FRAME_WINDOW_P (f)) { + bool draggable = (! WINDOW_BOTTOMMOST_P (w) + || minibuf_level + || NILP (Vresize_mini_windows)); + dpyinfo = FRAME_DISPLAY_INFO (f); if (STRINGP (string)) { @@ -28302,11 +28588,11 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, map = Fget_text_property (pos, Qlocal_map, string); if (!KEYMAPP (map)) map = Fget_text_property (pos, Qkeymap, string); - if (!KEYMAPP (map)) + if (!KEYMAPP (map) && draggable) cursor = dpyinfo->vertical_scroll_bar_cursor; } } - else + else if (draggable) /* Default mode-line pointer. */ cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor; } @@ -28525,7 +28811,17 @@ note_mouse_highlight (struct frame *f, int x, int y) || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN) { note_mode_line_or_margin_highlight (window, x, y, part); - return; + +#ifdef HAVE_WINDOW_SYSTEM + if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN) + { + cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + /* Show non-text cursor (Bug#16647). */ + goto set_cursor; + } + else +#endif + return; } #ifdef HAVE_WINDOW_SYSTEM @@ -28540,10 +28836,15 @@ note_mouse_highlight (struct frame *f, int x, int y) help_echo_string = build_string ("drag-mouse-1: resize"); } else if (part == ON_BOTTOM_DIVIDER) - { - cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor; - help_echo_string = build_string ("drag-mouse-1: resize"); - } + if (! WINDOW_BOTTOMMOST_P (w) + || minibuf_level + || NILP (Vresize_mini_windows)) + { + cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor; + help_echo_string = build_string ("drag-mouse-1: resize"); + } + else + cursor = FRAME_X_OUTPUT (f)->nontext_cursor; else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE || part == ON_SCROLL_BAR) cursor = FRAME_X_OUTPUT (f)->nontext_cursor; @@ -29234,7 +29535,8 @@ x_draw_right_divider (struct window *w) int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w); int x1 = WINDOW_RIGHT_EDGE_X (w); int y0 = WINDOW_TOP_EDGE_Y (w); - int y1 = WINDOW_BOTTOM_EDGE_Y (w); + /* The bottom divider prevails. */ + int y1 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w); FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1); } @@ -30079,8 +30381,8 @@ Bind this around calls to `message' to let it take effect. */); DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook, doc: /* Normal hook run to update the menu bar definitions. Redisplay runs this hook before it redisplays the menu bar. -This is used to update submenus such as Buffers, -whose contents depend on various data. */); +This is used to update menus such as Buffers, whose contents depend on +various data. */); Vmenu_bar_update_hook = Qnil; DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,