X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/37b9099068c10383e959ee366a52a22516846163..20038f8ab75dd1551412a43cd58520c483c22921:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 7dc99e1c28..b8dcdcec41 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1321,6 +1321,11 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y, if (CHARPOS (top) > ZV) SET_TEXT_POS (top, BEGV, BEGV_BYTE); + /* If the top of the window is after CHARPOS, the latter is surely + not visible. */ + if (charpos >= 0 && CHARPOS (top) > charpos) + return visible_p; + /* Compute exact mode line heights. */ if (WINDOW_WANTS_MODELINE_P (w)) w->mode_line_height @@ -1813,7 +1818,7 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id) cache and mode line face are not yet initialized. */ if (FRAME_FACE_CACHE (f)) { - struct face *face = FACE_FROM_ID (f, face_id); + struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); if (face) { if (face->font) @@ -2836,11 +2841,7 @@ init_iterator (struct it *it, struct window *w, frames when the fringes are turned off. But leave the dimensions zero for tooltip frames, as these glyphs look ugly there and also sabotage calculations of tooltip dimensions in x-show-tip. */ -#ifdef HAVE_WINDOW_SYSTEM - if (!(FRAME_WINDOW_P (it->f) - && FRAMEP (tip_frame) - && it->f == XFRAME (tip_frame))) -#endif + if (!FRAME_TOOLTIP_P (it->f)) { if (it->line_wrap == TRUNCATE) { @@ -2918,7 +2919,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); + face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id); if (face && face->box != FACE_NO_BOX) it->start_of_box_run_p = true; } @@ -3877,9 +3878,9 @@ handle_face_prop (struct it *it) { 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); + the definition of FACE_FROM_ID_OR_NULL. This will happen + if this is the initial call that gets the face. */ + struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id); /* 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 @@ -3888,7 +3889,7 @@ handle_face_prop (struct it *it) { int prev_face_id = face_before_it_pos (it); - old_face = FACE_FROM_ID (it->f, prev_face_id); + old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id); } /* If the new face has a box, but the old face does not, @@ -3988,7 +3989,7 @@ 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); - struct face *old_face = FACE_FROM_ID (it->f, it->face_id); + struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id); /* If new face has a box but old face hasn't, this is the start of a run of characters with box, i.e. it has a @@ -4847,7 +4848,6 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, it->font_height = XCAR (XCDR (spec)); if (!NILP (it->font_height)) { - struct face *face = FACE_FROM_ID (it->f, it->face_id); int new_height = -1; if (CONSP (it->font_height) @@ -4866,6 +4866,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, { /* Call function with current height as argument. Value is the new height. */ + struct face *face = FACE_FROM_ID (it->f, it->face_id); Lisp_Object height; height = safe_call1 (it->font_height, face->lface[LFACE_HEIGHT_INDEX]); @@ -4887,6 +4888,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, /* Evaluate IT->font_height with `height' bound to the current specified height to get the new height. */ ptrdiff_t count = SPECPDL_INDEX (); + struct face *face = FACE_FROM_ID (it->f, it->face_id); specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]); value = safe_eval (it->font_height); @@ -5016,8 +5018,6 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, || EQ (XCAR (spec), Qright_fringe)) && CONSP (XCDR (spec))) { - int fringe_bitmap; - if (it) { if (!FRAME_WINDOW_P (it->f)) @@ -5042,8 +5042,8 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, #ifdef HAVE_WINDOW_SYSTEM value = XCAR (XCDR (spec)); - if (!SYMBOLP (value) - || !(fringe_bitmap = lookup_fringe_bitmap (value))) + int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0; + if (! fringe_bitmap) /* If we return here, POSITION has been advanced across the text with this property. */ { @@ -6096,7 +6096,7 @@ pop_it (struct it *it) break; case GET_FROM_STRING: { - struct face *face = FACE_FROM_ID (it->f, it->face_id); + struct face *face = FACE_FROM_ID_OR_NULL (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 @@ -6777,7 +6777,8 @@ static next_element_function const get_next_element[NUM_IT_METHODS] = || ((IT)->cmp_it.stop_pos == (CHARPOS) \ && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \ END_CHARPOS, (IT)->w, \ - FACE_FROM_ID ((IT)->f, (IT)->face_id), \ + FACE_FROM_ID_OR_NULL ((IT)->f, \ + (IT)->face_id), \ (IT)->string))) @@ -7080,6 +7081,19 @@ get_next_display_element (struct it *it) goto display_control; } + /* Handle non-ascii hyphens in the mode where it only + gets highlighting. */ + + if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt)) + { + /* Merge `nobreak-space' into the current face. */ + face_id = merge_faces (it->f, Qnobreak_hyphen, 0, + it->face_id); + XSETINT (it->ctl_chars[0], '-'); + ctl_len = 1; + goto display_control; + } + /* Handle sequences that start with the "escape glyph". */ /* the default escape glyph is \. */ @@ -7096,15 +7110,6 @@ get_next_display_element (struct it *it) ? merge_faces (it->f, Qt, lface_id, it->face_id) : merge_escape_glyph_face (it)); - /* Draw non-ASCII hyphen with just highlighting: */ - - if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt)) - { - XSETINT (it->ctl_chars[0], '-'); - ctl_len = 1; - goto display_control; - } - /* Draw non-ASCII space/hyphen with escape glyph: */ if (nonascii_space_p || nonascii_hyphen_p) @@ -7202,7 +7207,7 @@ get_next_display_element (struct it *it) if (it->method == GET_FROM_STRING && it->sp) { int face_id = underlying_face_id (it); - struct face *face = FACE_FROM_ID (it->f, face_id); + struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id); if (face) { @@ -7229,18 +7234,21 @@ get_next_display_element (struct it *it) { ptrdiff_t ignore; int next_face_id; + bool text_from_string = false; + /* Normally, the next buffer location is stored in + IT->current.pos... */ struct text_pos pos = it->current.pos; - /* For a string from a display property, the next - buffer position is stored in the 'position' + /* ...but 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 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. */ + contrast, it->current.pos was 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) { int stackp = it->sp - 1; @@ -7249,19 +7257,49 @@ get_next_display_element (struct it *it) while (stackp >= 0 && STRINGP ((it->stack + stackp)->string)) stackp--; - eassert (stackp >= 0); - pos = (it->stack + stackp)->position; + if (stackp < 0) + { + /* If no stack slot was found for iterating + a buffer, we are displaying text from a + string, most probably the mode line or + the header line, and that string has a + display string on some of its + characters. */ + text_from_string = true; + pos = it->stack[it->sp - 1].position; + } + else + pos = (it->stack + stackp)->position; } else INC_TEXT_POS (pos, it->multibyte_p); - if (CHARPOS (pos) >= ZV) + if (text_from_string) + { + Lisp_Object base_string = it->stack[it->sp - 1].string; + + if (CHARPOS (pos) >= SCHARS (base_string) - 1) + it->end_of_box_run_p = true; + else + { + next_face_id + = face_at_string_position (it->w, base_string, + CHARPOS (pos), 0, + &ignore, face_id, false); + it->end_of_box_run_p + = (FACE_FROM_ID (it->f, next_face_id)->box + == FACE_NO_BOX); + } + } + else 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, false, -1); + next_face_id = + face_at_buffer_position (it->w, CHARPOS (pos), &ignore, + CHARPOS (pos) + + TEXT_PROP_DISTANCE_LIMIT, + false, -1); it->end_of_box_run_p = (FACE_FROM_ID (it->f, next_face_id)->box == FACE_NO_BOX); @@ -7702,8 +7740,8 @@ next_element_from_display_vector (struct it *it) /* Glyphs in the display vector could have the box face, so we need to set the related flags in the iterator, as appropriate. */ - this_face = FACE_FROM_ID (it->f, it->face_id); - prev_face = FACE_FROM_ID (it->f, prev_face_id); + this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id); + prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id); /* Is this character the first character of a box-face run? */ it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX @@ -7728,7 +7766,7 @@ next_element_from_display_vector (struct it *it) it->saved_face_id); } } - next_face = FACE_FROM_ID (it->f, next_face_id); + next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id); it->end_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX && (!next_face || next_face->box == FACE_NO_BOX)); @@ -8520,7 +8558,8 @@ move_it_in_display_line_to (struct it *it, void *ppos_data = NULL; bool may_wrap = false; enum it_method prev_method = it->method; - ptrdiff_t closest_pos IF_LINT (= 0), prev_pos = IT_CHARPOS (*it); + ptrdiff_t closest_pos UNINIT; + ptrdiff_t prev_pos = IT_CHARPOS (*it); bool saw_smaller_pos = prev_pos < to_charpos; /* Don't produce glyphs in produce_glyphs. */ @@ -8571,8 +8610,7 @@ move_it_in_display_line_to (struct it *it, && it->dpvec + it->current.dpvec_index + 1 >= it->dpend))) /* If there's a line-/wrap-prefix, handle it. */ - if (it->hpos == 0 && it->method == GET_FROM_BUFFER - && it->current_y < it->last_visible_y) + if (it->hpos == 0 && it->method == GET_FROM_BUFFER) handle_line_prefix (it); if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) @@ -8772,6 +8810,8 @@ move_it_in_display_line_to (struct it *it, ? WINDOW_LEFT_FRINGE_WIDTH (it->w) : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))) { + bool moved_forward = false; + if (/* IT->hpos == 0 means the very first glyph doesn't fit on the line, e.g. a wide image. */ it->hpos == 0 @@ -8790,16 +8830,37 @@ move_it_in_display_line_to (struct it *it, now that we know it fits in this row. */ if (BUFFER_POS_REACHED_P ()) { + bool can_wrap = true; + + /* If we are at a whitespace character + that barely fits on this screen line, + but the next character is also + whitespace, we cannot wrap here. */ + if (it->line_wrap == WORD_WRAP + && wrap_it.sp >= 0 + && may_wrap + && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)) + { + struct it tem_it; + void *tem_data = NULL; + + SAVE_IT (tem_it, *it, tem_data); + set_iterator_to_next (it, true); + if (get_next_display_element (it) + && IT_DISPLAYING_WHITESPACE (it)) + can_wrap = false; + RESTORE_IT (it, &tem_it, tem_data); + } if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0 - /* If we've just found whitespace to - wrap, effectively ignore the - previous wrap point -- it is no - longer relevant, but we won't - have an opportunity to update it, - since we've reached the edge of - this screen line. */ - || (may_wrap + /* If we've just found whitespace + where we can wrap, effectively + ignore the previous wrap point -- + it is no longer relevant, but we + won't have an opportunity to + update it, since we've reached + the edge of this screen line. */ + || (may_wrap && can_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))) { it->hpos = hpos_before_this_char; @@ -8842,6 +8903,7 @@ move_it_in_display_line_to (struct it *it, result = MOVE_POS_MATCH_OR_ZV; break; } + moved_forward = true; if (BUFFER_POS_REACHED_P ()) { if (ITERATOR_AT_END_OF_LINE_P (it)) @@ -8869,7 +8931,14 @@ move_it_in_display_line_to (struct it *it, longer relevant, but we won't have an opportunity to update it, since we are done with this screen line. */ - if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)) + if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it) + /* If the character after the one which set the + may_wrap flag is also whitespace, we can't + wrap here, since the screen line cannot be + wrapped in the middle of whitespace. + Therefore, wrap_it _is_ relevant in that + case. */ + && !(moved_forward && IT_DISPLAYING_WHITESPACE (it))) { /* If we've found TO_X, go back there, as we now know the last word fits on this screen line. */ @@ -8968,6 +9037,11 @@ move_it_in_display_line_to (struct it *it, } else result = MOVE_NEWLINE_OR_CR; + /* If we've processed the newline, make sure this flag is + reset, as it must only be set when the newline itself is + processed. */ + if (result == MOVE_NEWLINE_OR_CR) + it->constrain_row_ascent_descent_p = false; break; } @@ -9050,9 +9124,18 @@ move_it_in_display_line_to (struct it *it, #undef BUFFER_POS_REACHED_P - /* If we scanned beyond to_pos and didn't find a point to wrap at, - restore the saved iterator. */ - if (atpos_it.sp >= 0) + /* If we scanned beyond TO_POS, restore the saved iterator either to + the wrap point (if found), or to atpos/atx location. We decide which + data to use to restore the saved iterator state by their X coordinates, + since buffer positions might increase non-monotonically with screen + coordinates due to bidi reordering. */ + if (result == MOVE_LINE_CONTINUED + && it->line_wrap == WORD_WRAP + && wrap_it.sp >= 0 + && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x) + || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x))) + RESTORE_IT (it, &wrap_it, wrap_data); + else if (atpos_it.sp >= 0) RESTORE_IT (it, &atpos_it, atpos_data); else if (atx_it.sp >= 0) RESTORE_IT (it, &atx_it, atx_data); @@ -9811,7 +9894,7 @@ 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 -height (exluding the height of the mode- or header-line, if any) that +height (excluding the height of the mode- or header-line, if any) that can be returned. Text lines whose y-coordinate is beyond 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 @@ -9897,18 +9980,21 @@ include the height of both, if present, in the return value. */) it.last_visible_x = max_x; /* Actually, we never want move_it_to stop at to_x. But to make sure that move_it_in_display_line_to always moves far enough, - we set it to INT_MAX and specify MOVE_TO_X. Also bound width - value by X-LIMIT. */ - x = min (move_it_to (&it, end, INT_MAX, max_y, -1, - MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y), - max_x); + we set it to INT_MAX and specify MOVE_TO_X. */ + x = move_it_to (&it, end, INT_MAX, max_y, -1, + MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); + /* Don't return more than X-LIMIT. */ + if (x > max_x) + x = max_x; } /* Subtract height of header-line which was counted automatically by start_display. */ - y = min (it.current_y + it.max_ascent + it.max_descent - - WINDOW_HEADER_LINE_HEIGHT (w), - max_y); + y = it.current_y + it.max_ascent + it.max_descent + - WINDOW_HEADER_LINE_HEIGHT (w); + /* Don't return more than Y-LIMIT. */ + if (y > max_y) + y = max_y; if (EQ (mode_and_header_line, Qheader_line) || EQ (mode_and_header_line, Qt)) @@ -10495,25 +10581,21 @@ update_echo_area (void) static void ensure_echo_area_buffers (void) { - int i; - - for (i = 0; i < 2; ++i) + for (int i = 0; i < 2; i++) if (!BUFFERP (echo_buffer[i]) || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i]))) { - char name[30]; - Lisp_Object old_buffer; - int j; - - old_buffer = echo_buffer[i]; - echo_buffer[i] = Fget_buffer_create - (make_formatted_string (name, " *Echo Area %d*", i)); + Lisp_Object old_buffer = echo_buffer[i]; + static char const name_fmt[] = " *Echo Area %d*"; + char name[sizeof name_fmt + INT_STRLEN_BOUND (int)]; + AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i)); + echo_buffer[i] = Fget_buffer_create (lname); bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil); /* to force word wrap in echo area - it was decided to postpone this*/ /* XBUFFER (echo_buffer[i])->word_wrap = Qt; */ - for (j = 0; j < 2; ++j) + for (int j = 0; j < 2; j++) if (EQ (old_buffer, echo_area_buffer[j])) echo_area_buffer[j] = echo_buffer[i]; } @@ -11627,7 +11709,7 @@ x_consider_frame_title (Lisp_Object frame) if ((FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name) - && NILP (Fframe_parameter (frame, Qtooltip))) + && !FRAME_TOOLTIP_P (f)) { /* Do we have more than one visible frame on this X display? */ Lisp_Object tail, other_frame, fmt; @@ -11644,7 +11726,7 @@ x_consider_frame_title (Lisp_Object frame) if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f) && !FRAME_MINIBUF_ONLY_P (tf) - && !EQ (other_frame, tip_frame) + && !FRAME_TOOLTIP_P (tf) && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf))) break; } @@ -11707,13 +11789,6 @@ prepare_menu_bars (void) { bool all_windows = windows_or_buffers_changed || update_mode_lines; bool some_windows = REDISPLAY_SOME_P (); - Lisp_Object tooltip_frame; - -#ifdef HAVE_WINDOW_SYSTEM - tooltip_frame = tip_frame; -#else - tooltip_frame = Qnil; -#endif if (FUNCTIONP (Vpre_redisplay_function)) { @@ -11754,7 +11829,7 @@ prepare_menu_bars (void) && !XBUFFER (w->contents)->text->redisplay) continue; - if (!EQ (frame, tooltip_frame) + if (!FRAME_TOOLTIP_P (f) && (FRAME_ICONIFIED_P (f) || FRAME_VISIBLE_P (f) == 1 /* Exclude TTY frames that are obscured because they @@ -11791,7 +11866,7 @@ prepare_menu_bars (void) struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); /* Ignore tooltip frame. */ - if (EQ (frame, tooltip_frame)) + if (FRAME_TOOLTIP_P (f)) continue; if (some_windows @@ -13475,7 +13550,7 @@ redisplay_internal (void) specbind (Qinhibit_free_realized_faces, Qnil); /* Record this function, so it appears on the profiler's backtraces. */ - record_in_backtrace (Qredisplay_internal, 0, 0); + record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0); FOR_EACH_FRAME (tail, frame) XFRAME (frame)->already_hscrolled_p = false; @@ -15431,12 +15506,14 @@ try_scrolling (Lisp_Object window, bool just_this_one_p, The new window start will be computed, based on W's width, starting from the start of the continued line. It is the start of the - screen line with the minimum distance from the old start W->start. */ + screen line with the minimum distance from the old start W->start, + which is still before point (otherwise point will definitely not + be visible in the window). */ static bool compute_window_start_on_continuation_line (struct window *w) { - struct text_pos pos, start_pos; + struct text_pos pos, start_pos, pos_before_pt; bool window_start_changed_p = false; SET_TEXT_POS_FROM_MARKER (start_pos, w->start); @@ -15464,10 +15541,14 @@ compute_window_start_on_continuation_line (struct window *w) reseat_at_previous_visible_line_start (&it); /* If the line start is "too far" away from the window start, - say it takes too much time to compute a new window start. */ - if (CHARPOS (start_pos) - IT_CHARPOS (it) - /* PXW: Do we need upper bounds here? */ - < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)) + say it takes too much time to compute a new window start. + Also, give up if the line start is after point, as in that + case point will not be visible with any window start we + compute. */ + if (IT_CHARPOS (it) <= PT + || (CHARPOS (start_pos) - IT_CHARPOS (it) + /* PXW: Do we need upper bounds here? */ + < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w))) { int min_distance, distance; @@ -15477,12 +15558,14 @@ compute_window_start_on_continuation_line (struct window *w) decreased, the new window start will be < the old start. So, we're looking for the display line start with the minimum distance from the old window start. */ - pos = it.current.pos; + pos_before_pt = pos = it.current.pos; min_distance = INFINITY; while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))), distance < min_distance) { min_distance = distance; + if (CHARPOS (pos) <= PT) + pos_before_pt = pos; pos = it.current.pos; if (it.line_wrap == WORD_WRAP) { @@ -15505,6 +15588,13 @@ compute_window_start_on_continuation_line (struct window *w) move_it_by_lines (&it, 1); } + /* It makes very little sense to make the new window start + after point, as point won't be visible. If that's what + the loop above finds, fall back on the candidate before + or at point that is closest to the old window start. */ + if (CHARPOS (pos) > PT) + pos = pos_before_pt; + /* Set the window start there. */ SET_MARKER_FROM_TEXT_POS (w->start, pos); window_start_changed_p = true; @@ -17013,7 +17103,16 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) ignore_mouse_drag_p = true; #endif } + ptrdiff_t count1 = SPECPDL_INDEX (); + /* x_consider_frame_title calls select-frame, which calls + resize_mini_window, which could resize the mini-window and by + that undo the effect of this redisplay cycle wrt minibuffer + and echo-area display. Binding inhibit-redisplay to t makes + the call to resize_mini_window a no-op, thus avoiding the + adverse side effects. */ + specbind (Qinhibit_redisplay, Qt); x_consider_frame_title (w->frame); + unbind_to (count1, Qnil); #endif } @@ -18620,7 +18719,7 @@ try_window_id (struct window *w) eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)); row = find_last_row_displaying_text (w->current_matrix, &it, first_unchanged_at_end_row); - eassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row)); + eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row)); adjust_window_ends (w, row, true); eassert (w->window_end_bytepos >= 0); IF_DEBUG (debug_method_add (w, "A")); @@ -18650,10 +18749,9 @@ try_window_id (struct window *w) struct glyph_row *current_row = current_matrix->rows + vpos; struct glyph_row *desired_row = desired_matrix->rows + vpos; - for (row = NULL; - row == NULL && vpos >= first_vpos; - --vpos, --current_row, --desired_row) + for (row = NULL; !row; --vpos, --current_row, --desired_row) { + eassert (first_vpos <= vpos); if (desired_row->enabled_p) { if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row)) @@ -18663,7 +18761,6 @@ try_window_id (struct window *w) row = current_row; } - eassert (row != NULL); w->window_end_vpos = vpos + 1; w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row); w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row); @@ -19427,7 +19524,6 @@ append_space_for_newline (struct it *it, bool default_face_p) struct text_pos saved_pos; Lisp_Object saved_object; struct face *face; - struct glyph *g; saved_object = it->object; saved_pos = it->position; @@ -19463,7 +19559,7 @@ append_space_for_newline (struct it *it, bool default_face_p) /* Make sure this space glyph has the right ascent and descent values, or else cursor at end of line will look funny, and height of empty lines will be incorrect. */ - g = it->glyph_row->glyphs[TEXT_AREA] + n; + struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n; struct font *font = face->font ? face->font : FRAME_FONT (it->f); if (n == 0) { @@ -19588,15 +19684,15 @@ extend_face_to_end_of_line (struct it *it) return; /* The default face, possibly remapped. */ - default_face = FACE_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID)); + default_face = FACE_FROM_ID_OR_NULL (f, + lookup_basic_face (f, DEFAULT_FACE_ID)); /* Face extension extends the background and box of IT->face_id to the end of the line. If the background equals the background of the frame, we don't have to do anything. */ - if (it->face_before_selective_p) - face = FACE_FROM_ID (f, it->saved_face_id); - else - face = FACE_FROM_ID (f, it->face_id); + face = FACE_FROM_ID (f, (it->face_before_selective_p + ? it->saved_face_id + : it->face_id)); if (FRAME_WINDOW_P (f) && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row) @@ -20336,16 +20432,16 @@ display_line (struct it *it) struct it wrap_it; void *wrap_data = NULL; bool may_wrap = false; - int wrap_x IF_LINT (= 0); + int wrap_x UNINIT; int wrap_row_used = -1; - int wrap_row_ascent IF_LINT (= 0), wrap_row_height IF_LINT (= 0); - int wrap_row_phys_ascent IF_LINT (= 0), wrap_row_phys_height IF_LINT (= 0); - int wrap_row_extra_line_spacing IF_LINT (= 0); - ptrdiff_t wrap_row_min_pos IF_LINT (= 0), wrap_row_min_bpos IF_LINT (= 0); - ptrdiff_t wrap_row_max_pos IF_LINT (= 0), wrap_row_max_bpos IF_LINT (= 0); + int wrap_row_ascent UNINIT, wrap_row_height UNINIT; + int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT; + int wrap_row_extra_line_spacing UNINIT; + ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT; + ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT; int cvpos; ptrdiff_t min_pos = ZV + 1, max_pos = 0; - ptrdiff_t min_bpos IF_LINT (= 0), max_bpos IF_LINT (= 0); + ptrdiff_t min_bpos UNINIT, max_bpos UNINIT; bool pending_handle_line_prefix = false; /* We always start displaying at hpos zero even if hscrolled. */ @@ -21762,7 +21858,6 @@ Value is the new character position of point. */) } /* Move to the target X coordinate. */ -#ifdef HAVE_WINDOW_SYSTEM /* On GUI frames, as we don't know the X coordinate of the character to the left of point, moving point to the left requires walking, one grapheme cluster at a time, until we @@ -21819,9 +21914,7 @@ Value is the new character position of point. */) new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos); it.current.pos = new_pos; } - else -#endif - if (it.current_x != target_x) + else if (it.current_x != target_x) move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X); /* If we ended up in a display string that covers point, move to @@ -24570,7 +24663,6 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph, face = FACE_FROM_ID (f, glyph->face_id); /* Make sure X resources of the face are allocated. */ - eassert (face != NULL); prepare_face_for_display (f, face); if (face->font) @@ -25295,7 +25387,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p) #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ do { \ int face_id = (row)->glyphs[area][START].face_id; \ - struct face *base_face = FACE_FROM_ID (f, face_id); \ + struct face *base_face = FACE_FROM_ID (f, face_id); \ ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \ struct composition *cmp = composition_table[cmp_id]; \ XChar2b *char2b; \ @@ -25516,7 +25608,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, { struct glyph_string *h, *t; Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); - int mouse_beg_col IF_LINT (= 0), mouse_end_col IF_LINT (= 0); + int mouse_beg_col UNINIT, mouse_end_col UNINIT; bool check_mouse_face = false; int dummy_x = 0; @@ -25750,6 +25842,7 @@ append_glyph (struct it *it) glyph->object = it->object; if (it->pixel_width > 0) { + eassert (it->pixel_width <= SHRT_MAX); glyph->pixel_width = it->pixel_width; glyph->padding_p = false; } @@ -25830,6 +25923,7 @@ append_composite_glyph (struct it *it) } glyph->charpos = it->cmp_it.charpos; glyph->object = it->object; + eassert (it->pixel_width <= SHRT_MAX); glyph->pixel_width = it->pixel_width; glyph->ascent = it->ascent; glyph->descent = it->descent; @@ -25916,7 +26010,6 @@ produce_image_glyph (struct it *it) eassert (it->what == IT_IMAGE); face = FACE_FROM_ID (it->f, it->face_id); - eassert (face); /* Make sure X resources of the face is loaded. */ prepare_face_for_display (it->f, face); @@ -25931,7 +26024,6 @@ produce_image_glyph (struct it *it) } img = IMAGE_FROM_ID (it->f, it->image_id); - eassert (img); /* Make sure X resources of the image is loaded. */ prepare_image_for_display (it->f, img); @@ -26039,7 +26131,7 @@ produce_image_glyph (struct it *it) { glyph->charpos = CHARPOS (it->position); glyph->object = it->object; - glyph->pixel_width = it->pixel_width; + glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX); glyph->ascent = glyph_ascent; glyph->descent = it->descent; glyph->voffset = it->voffset; @@ -26087,7 +26179,6 @@ produce_xwidget_glyph (struct it *it) eassert (it->what == IT_XWIDGET); struct face *face = FACE_FROM_ID (it->f, it->face_id); - eassert (face); /* Make sure X resources of the face is loaded. */ prepare_face_for_display (it->f, face); @@ -26143,7 +26234,7 @@ produce_xwidget_glyph (struct it *it) { glyph->charpos = CHARPOS (it->position); glyph->object = it->object; - glyph->pixel_width = it->pixel_width; + glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX); glyph->ascent = glyph_ascent; glyph->descent = it->descent; glyph->voffset = it->voffset; @@ -26229,7 +26320,9 @@ append_stretch_glyph (struct it *it, Lisp_Object object, } glyph->charpos = CHARPOS (it->position); glyph->object = object; - glyph->pixel_width = width; + /* FIXME: It would be better to use TYPE_MAX here, but + __typeof__ is not portable enough... */ + glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX); glyph->ascent = ascent; glyph->descent = height - ascent; glyph->voffset = it->voffset; @@ -26611,12 +26704,8 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font, struct face *face; face_id = lookup_named_face (it->f, face_name, false); - if (face_id < 0) - return make_number (-1); - - face = FACE_FROM_ID (it->f, face_id); - font = face->font; - if (font == NULL) + face = FACE_FROM_ID_OR_NULL (it->f, face_id); + if (face == NULL || ((font = face->font) == NULL)) return make_number (-1); boff = font->baseline_offset; if (font->vertical_centering) @@ -26680,6 +26769,7 @@ append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len, } glyph->charpos = CHARPOS (it->position); glyph->object = it->object; + eassert (it->pixel_width <= SHRT_MAX); glyph->pixel_width = it->pixel_width; glyph->ascent = it->ascent; glyph->descent = it->descent; @@ -27261,18 +27351,21 @@ x_produce_glyphs (struct it *it) int leftmost, rightmost, lowest, highest; int lbearing, rbearing; int i, width, ascent, descent; - int c IF_LINT (= 0); /* cmp->glyph_len can't be zero; see Bug#8512 */ + int c; XChar2b char2b; struct font_metrics *pcm; ptrdiff_t pos; - for (glyph_len = cmp->glyph_len; glyph_len > 0; glyph_len--) - if ((c = COMPOSITION_GLYPH (cmp, glyph_len - 1)) != '\t') - break; + eassume (0 < glyph_len); /* See Bug#8512. */ + do + c = COMPOSITION_GLYPH (cmp, glyph_len - 1); + while (c == '\t' && 0 < --glyph_len); + bool right_padded = glyph_len < cmp->glyph_len; for (i = 0; i < glyph_len; i++) { - if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t') + c = COMPOSITION_GLYPH (cmp, i); + if (c != '\t') break; cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0; } @@ -27971,7 +28064,7 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width, /* Using a block cursor on large images can be very annoying. So use a hollow cursor for "large" images. If image is not transparent (no mask), also use hollow cursor. */ - struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id); + struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id); if (img != NULL && IMAGEP (img->spec)) { /* Arbitrarily, interpret "Large" as >32x32 and >NxN @@ -28596,12 +28689,12 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) } } -#ifdef HAVE_WINDOW_SYSTEM /* When we've written over the cursor, arrange for it to be displayed again. */ if (FRAME_WINDOW_P (f) && phys_cursor_on_p && !w->phys_cursor_on_p) { +#ifdef HAVE_WINDOW_SYSTEM int hpos = w->phys_cursor.hpos; /* When the window is hscrolled, cursor hpos can legitimately be @@ -28616,8 +28709,8 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos, w->phys_cursor.x, w->phys_cursor.y); unblock_input (); - } #endif /* HAVE_WINDOW_SYSTEM */ + } } #ifdef HAVE_WINDOW_SYSTEM @@ -29557,12 +29650,17 @@ Returns the alist element for the first matching AREA in MAP. */) clip_to_bounds (INT_MIN, XINT (x), INT_MAX), clip_to_bounds (INT_MIN, XINT (y), INT_MAX)); } +#endif /* HAVE_WINDOW_SYSTEM */ /* Display frame CURSOR, optionally using shape defined by POINTER. */ static void define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer) { +#ifdef HAVE_WINDOW_SYSTEM + if (!FRAME_WINDOW_P (f)) + return; + /* Do not change cursor shape while dragging mouse. */ if (EQ (do_mouse_tracking, Qdragging)) return; @@ -29579,10 +29677,10 @@ define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer) cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; else if (EQ (pointer, intern ("nhdrag"))) cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor; -#ifdef HAVE_X_WINDOWS +# ifdef HAVE_X_WINDOWS else if (EQ (pointer, intern ("vdrag"))) cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor; -#endif +# endif else if (EQ (pointer, intern ("hourglass"))) cursor = FRAME_X_OUTPUT (f)->hourglass_cursor; else if (EQ (pointer, Qmodeline)) @@ -29593,10 +29691,9 @@ define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer) if (cursor != No_Cursor) FRAME_RIF (f)->define_frame_cursor (f, cursor); +#endif } -#endif /* HAVE_WINDOW_SYSTEM */ - /* Take proper action when mouse has moved to the mode or header line or marginal area AREA of window W, x-position X and y-position Y. X is relative to the start of the text display area of W, so the @@ -29618,12 +29715,11 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, int dx, dy, width, height; ptrdiff_t charpos; Lisp_Object string, object = Qnil; - Lisp_Object pos IF_LINT (= Qnil), help; - + Lisp_Object pos UNINIT; Lisp_Object mouse_face; int original_x_pixel = x; struct glyph * glyph = NULL, * row_start_glyph = NULL; - struct glyph_row *row IF_LINT (= 0); + struct glyph_row *row UNINIT; if (area == ON_MODE_LINE || area == ON_HEADER_LINE) { @@ -29663,7 +29759,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, &object, &dx, &dy, &width, &height); } - help = Qnil; + Lisp_Object help = Qnil; #ifdef HAVE_WINDOW_SYSTEM if (IMAGEP (object)) @@ -29911,10 +30007,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, if ((area == ON_MODE_LINE || area == ON_HEADER_LINE) && !mouse_face_shown) clear_mouse_face (hlinfo); -#ifdef HAVE_WINDOW_SYSTEM - if (FRAME_WINDOW_P (f)) - define_frame_cursor1 (f, cursor, pointer); -#endif + define_frame_cursor1 (f, cursor, pointer); } @@ -30058,7 +30151,7 @@ note_mouse_highlight (struct frame *f, int x, int y) /* Look for :pointer property on image. */ if (glyph != NULL && glyph->type == IMAGE_GLYPH) { - struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id); + struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id); if (img != NULL && IMAGEP (img->spec)) { Lisp_Object image_map, hotspot; @@ -30119,15 +30212,15 @@ note_mouse_highlight (struct frame *f, int x, int y) { if (clear_mouse_face (hlinfo)) cursor = No_Cursor; -#ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (f) && NILP (pointer)) { +#ifdef HAVE_WINDOW_SYSTEM if (area != TEXT_AREA) cursor = FRAME_X_OUTPUT (f)->nontext_cursor; else pointer = Vvoid_text_area_pointer; - } #endif + } goto set_cursor; } @@ -30238,8 +30331,8 @@ note_mouse_highlight (struct frame *f, int x, int y) { /* The mouse-highlighting, if any, comes from an overlay or text property in the buffer. */ - Lisp_Object buffer IF_LINT (= Qnil); - Lisp_Object disp_string IF_LINT (= Qnil); + Lisp_Object buffer UNINIT; + Lisp_Object disp_string UNINIT; if (STRINGP (object)) { @@ -30439,15 +30532,7 @@ note_mouse_highlight (struct frame *f, int x, int y) } set_cursor: - -#ifdef HAVE_WINDOW_SYSTEM - if (FRAME_WINDOW_P (f)) - define_frame_cursor1 (f, cursor, pointer); -#else - /* This is here to prevent a compiler error, about "label at end of - compound statement". */ - return; -#endif + define_frame_cursor1 (f, cursor, pointer); } @@ -31084,7 +31169,7 @@ syms_of_xdisp (void) /* Non-nil means don't actually do any redisplay. */ DEFSYM (Qinhibit_redisplay, "inhibit-redisplay"); - DEFSYM (Qredisplay_internal, "redisplay_internal (C function)"); + DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)"); DEFVAR_BOOL("inhibit-message", inhibit_message, doc: /* Non-nil means calls to `message' are not displayed. @@ -31155,8 +31240,10 @@ They are still logged to the *Messages* buffer. */); /* Name and number of the face used to highlight escape glyphs. */ DEFSYM (Qescape_glyph, "escape-glyph"); - /* Name and number of the face used to highlight non-breaking spaces. */ + /* Name and number of the face used to highlight non-breaking + spaces/hyphens. */ DEFSYM (Qnobreak_space, "nobreak-space"); + DEFSYM (Qnobreak_hyphen, "nobreak-hyphen"); /* The symbol 'image' which is the car of the lists used to represent images in Lisp. Also a tool bar style. */ @@ -31268,7 +31355,7 @@ The face used for trailing whitespace is `trailing-whitespace'. */); doc: /* Control highlighting of non-ASCII space and hyphen chars. If the value is t, Emacs highlights non-ASCII chars which have the same appearance as an ASCII space or hyphen, using the `nobreak-space' -or `escape-glyph' face respectively. +or `nobreak-hyphen' face respectively. U+00A0 (no-break space), U+00AD (soft hyphen), U+2010 (hyphen), and U+2011 (non-breaking hyphen) are affected. @@ -31353,8 +31440,11 @@ Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI). */); Vtruncate_partial_width_windows, doc: /* Non-nil means truncate lines in windows narrower than the frame. For an integer value, truncate lines in each window narrower than the -full frame width, provided the window width is less than that integer; -otherwise, respect the value of `truncate-lines'. +full frame width, provided the total window width in column units is less +than that integer; otherwise, respect the value of `truncate-lines'. +The total width of the window is as returned by `window-total-width', it +includes the fringes, the continuation and truncation glyphs, the +display margins (if any), and the scroll bar For any other non-nil value, truncate lines in all windows that do not span the full frame width.