X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/09b911adf4e22bbcac8c588bc14ade801276732e..fa8678ebb05c28c54f114727a0bec7453903dbf0:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 6728a0275e..774903b6bc 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -98,7 +98,9 @@ along with GNU Emacs. If not, see . */ This function attempts to redisplay a window by reusing parts of its existing display. It finds and reuses the part that was not - changed, and redraws the rest. + changed, and redraws the rest. (The "id" part in the function's + name stands for "insert/delete", not for "identification" or + somesuch.) . try_window @@ -113,6 +115,19 @@ along with GNU Emacs. If not, see . */ optimizations were successful, redisplay calls redisplay_windows, which performs a full redisplay of all windows. + Note that there's one more important optimization up Emacs's + sleeve, but it is related to actually redrawing the potentially + changed portions of the window/frame, not to reproducing the + desired matrices of those potentially changed portions. Namely, + the function update_frame and its subroutines, which you will find + in dispnew.c, compare the desired matrices with the current + matrices, and only redraw the portions that changed. So it could + happen that the functions in this file for some reason decide that + the entire desired matrix needs to be regenerated from scratch, and + still only parts of the Emacs display, or even nothing at all, will + be actually delivered to the glass, because update_frame has found + that the new and the old screen contents are similar or identical. + Desired matrices. Desired matrices are always built per Emacs window. The function @@ -622,7 +637,7 @@ void wset_redisplay (struct window *w) { /* Beware: selected_window can be nil during early stages. */ - if (!EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window)) + if (!EQ (w->header.self, selected_window)) redisplay_other_windows (); w->redisplay = true; } @@ -2591,8 +2606,8 @@ safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args) following. Return the result, or nil if something went wrong. Prevent redisplay during the evaluation. */ -Lisp_Object -safe_call (ptrdiff_t nargs, Lisp_Object func, ...) +static Lisp_Object +safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap) { Lisp_Object val; @@ -2600,32 +2615,42 @@ safe_call (ptrdiff_t nargs, Lisp_Object func, ...) val = Qnil; else { - va_list ap; ptrdiff_t i; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); struct gcpro gcpro1; Lisp_Object *args = alloca (nargs * word_size); args[0] = func; - va_start (ap, func); for (i = 1; i < nargs; i++) args[i] = va_arg (ap, Lisp_Object); - va_end (ap); GCPRO1 (args[0]); gcpro1.nvars = nargs; specbind (Qinhibit_redisplay, Qt); + if (inhibit_quit) + specbind (Qinhibit_quit, Qt); /* Use Qt to ensure debugger does not run, so there is no possibility of wanting to redisplay. */ val = internal_condition_case_n (Ffuncall, nargs, args, Qt, safe_eval_handler); UNGCPRO; - val = unbind_to (count, val); + dynwind_end (); } return val; } +Lisp_Object +safe_call (ptrdiff_t nargs, Lisp_Object func, ...) +{ + Lisp_Object retval; + va_list ap; + + va_start (ap, func); + retval = safe__call (false, nargs, func, ap); + va_end (ap); + return retval; +} /* Call function FN with one argument ARG. Return the result, or nil if something went wrong. */ @@ -2636,12 +2661,30 @@ safe_call1 (Lisp_Object fn, Lisp_Object arg) return safe_call (2, fn, arg); } +static Lisp_Object +safe__call1 (bool inhibit_quit, Lisp_Object fn, ...) +{ + Lisp_Object retval; + va_list ap; + + va_start (ap, fn); + retval = safe__call (inhibit_quit, 2, fn, ap); + va_end (ap); + return retval; +} + static Lisp_Object Qeval; Lisp_Object safe_eval (Lisp_Object sexpr) { - return safe_call1 (Qeval, sexpr); + return safe__call1 (false, Qeval, sexpr); +} + +static Lisp_Object +safe__eval (bool inhibit_quit, Lisp_Object sexpr) +{ + return safe__call1 (inhibit_quit, Qeval, sexpr); } /* Call function FN with two arguments ARG1 and ARG2. @@ -3768,7 +3811,7 @@ handle_fontified_prop (struct it *it) no amount of fontifying will be able to change it. */ NILP (prop) && IT_CHARPOS (*it) < Z)) { - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); Lisp_Object val; struct buffer *obuf = current_buffer; ptrdiff_t begv = BEGV, zv = ZV; @@ -3816,7 +3859,7 @@ handle_fontified_prop (struct it *it) UNGCPRO; } - unbind_to (count, Qnil); + dynwind_end (); /* Fontification functions routinely call `save-restriction'. Normally, this tags clip_changed, which can confuse redisplay @@ -4780,7 +4823,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, if (!NILP (form) && !EQ (form, Qt)) { - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); struct gcpro gcpro1; /* Bind `object' to the object having the `display' property, a @@ -4796,7 +4839,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, GCPRO1 (form); form = safe_eval (form); UNGCPRO; - unbind_to (count, Qnil); + dynwind_end (); } if (NILP (form)) @@ -4854,11 +4897,11 @@ 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 (); + dynwind_begin (); specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]); value = safe_eval (it->font_height); - unbind_to (count, Qnil); + dynwind_end (); if (NUMBERP (value)) new_height = XFLOATINT (value); @@ -8226,7 +8269,7 @@ next_element_from_buffer (struct it *it) /* Get the next character, maybe multibyte. */ p = BYTE_POS_ADDR (IT_BYTEPOS (*it)); - if (it->multibyte_p && !ASCII_BYTE_P (*p)) + if (it->multibyte_p && !ASCII_CHAR_P (*p)) it->c = STRING_CHAR_AND_LENGTH (p, it->len); else it->c = *p, it->len = 1; @@ -8528,7 +8571,7 @@ move_it_in_display_line_to (struct it *it, } else { - if (it->line_wrap == WORD_WRAP) + if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA) { if (IT_DISPLAYING_WHITESPACE (it)) may_wrap = 1; @@ -8812,8 +8855,11 @@ move_it_in_display_line_to (struct it *it, if (closest_pos < ZV) { RESTORE_IT (it, &ppos_it, ppos_data); - move_it_in_display_line_to (it, closest_pos, -1, - MOVE_TO_POS); + /* Don't recurse if closest_pos is equal to + to_charpos, since we have just tried that. */ + if (closest_pos != to_charpos) + move_it_in_display_line_to (it, closest_pos, -1, + MOVE_TO_POS); result = MOVE_POS_MATCH_OR_ZV; } else @@ -8874,8 +8920,9 @@ move_it_in_display_line_to (struct it *it, && !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); + if (closest_pos != to_charpos) + move_it_in_display_line_to (it, closest_pos, -1, + MOVE_TO_POS); } result = MOVE_POS_MATCH_OR_ZV; break; @@ -8893,7 +8940,9 @@ move_it_in_display_line_to (struct it *it, if (closest_pos < ZV) { RESTORE_IT (it, &ppos_it, ppos_data); - move_it_in_display_line_to (it, closest_pos, -1, MOVE_TO_POS); + if (closest_pos != to_charpos) + move_it_in_display_line_to (it, closest_pos, -1, + MOVE_TO_POS); } result = MOVE_POS_MATCH_OR_ZV; break; @@ -9883,9 +9932,7 @@ message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte) for (i = 0; i < nbytes; i += char_bytes) { c = string_char_and_length (msg + i, &char_bytes); - work[0] = (ASCII_CHAR_P (c) - ? c - : multibyte_char_to_unibyte (c)); + work[0] = CHAR_TO_BYTE8 (c); insert_1_both (work, 1, 1, 1, 0, 0); } } @@ -10167,19 +10214,17 @@ message_with_string (const char *m, Lisp_Object string, int log) { if (m) { - /* ENCODE_SYSTEM below can GC and/or relocate the Lisp - String whose data pointer might be passed to us in M. So - we use a local copy. */ - char *fmt = xstrdup (m); + /* ENCODE_SYSTEM below can GC and/or relocate the + Lisp data, so make sure we don't use it here. */ + eassert (relocatable_string_data_p (m) != 1); if (noninteractive_need_newline) putc ('\n', stderr); noninteractive_need_newline = 0; - fprintf (stderr, fmt, SDATA (ENCODE_SYSTEM (string))); + fprintf (stderr, m, SDATA (ENCODE_SYSTEM (string))); if (!cursor_in_echo_area) fprintf (stderr, "\n"); fflush (stderr); - xfree (fmt); } } else if (INTERACTIVE) @@ -10380,7 +10425,7 @@ with_echo_area_buffer (struct window *w, int which, { Lisp_Object buffer; int this_one, the_other, clear_buffer_p, rc; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); /* If buffers aren't live, make new ones. */ ensure_echo_area_buffers (); @@ -10454,7 +10499,7 @@ with_echo_area_buffer (struct window *w, int which, eassert (BEGV >= BEG); eassert (ZV <= Z && ZV >= BEGV); - unbind_to (count, Qnil); + dynwind_end (); return rc; } @@ -10559,11 +10604,11 @@ setup_echo_area_for_printing (int multibyte_p) if (Z > BEG) { - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); specbind (Qinhibit_read_only, Qt); /* Note that undo recording is always disabled. */ del_range (BEG, Z); - unbind_to (count, Qnil); + dynwind_end (); } TEMP_SET_PT_BOTH (BEG, BEG_BYTE); @@ -10614,13 +10659,6 @@ display_echo_area (struct window *w) { int i, no_message_p, window_height_changed_p; - /* Temporarily disable garbage collections while displaying the echo - area. This is done because a GC can print a message itself. - That message would modify the echo area buffer's contents while a - redisplay of the buffer is going on, and seriously confuse - redisplay. */ - ptrdiff_t count = inhibit_garbage_collection (); - /* If there is no message, we must call display_echo_area_1 nevertheless because it resizes the window. But we will have to reset the echo_area_buffer in question to nil at the end because @@ -10636,7 +10674,6 @@ display_echo_area (struct window *w) if (no_message_p) echo_area_buffer[i] = Qnil; - unbind_to (count, Qnil); return window_height_changed_p; } @@ -11148,11 +11185,11 @@ echo_area_display (int update_frame_p) /* Must update other windows. Likewise as in other cases, don't let this update be interrupted by pending input. */ - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); specbind (Qredisplay_dont_pause, Qt); windows_or_buffers_changed = 44; redisplay_internal (); - unbind_to (count, Qnil); + dynwind_end (); } else if (FRAME_WINDOW_P (f) && n == 0) { @@ -11444,7 +11481,7 @@ x_consider_frame_title (Lisp_Object frame) char *title; ptrdiff_t len; struct it it; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); FOR_EACH_FRAME (tail, other_frame) { @@ -11480,7 +11517,7 @@ x_consider_frame_title (Lisp_Object frame) display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0); len = MODE_LINE_NOPROP_LEN (title_start); title = mode_line_noprop_buf + title_start; - unbind_to (count, Qnil); + dynwind_end (); /* Set the title only if it's changed. This avoids consing in the common case where it hasn't. (If it turns out that we've @@ -11543,7 +11580,7 @@ prepare_menu_bars (void) } } } - safe_call1 (Vpre_redisplay_function, windows); + safe__call1 (true, Vpre_redisplay_function, windows); } /* Update all frame titles based on their buffer names, etc. We do @@ -11588,7 +11625,7 @@ prepare_menu_bars (void) if (all_windows) { Lisp_Object tail, frame; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); /* 1 means that update_menu_bar has run its hooks so any further calls to update_menu_bar shouldn't do so again. */ int menu_bar_hooks_run = 0; @@ -11644,7 +11681,7 @@ prepare_menu_bars (void) UNGCPRO; } - unbind_to (count, Qnil); + dynwind_end (); } else { @@ -11707,7 +11744,7 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run) || window_buffer_changed (w)) { struct buffer *prev = current_buffer; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); specbind (Qinhibit_menubar_update, Qt); @@ -11760,7 +11797,7 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run) w->update_mode_line = 1; #endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */ - unbind_to (count, Qnil); + dynwind_end (); set_buffer_internal_1 (prev); } } @@ -11774,11 +11811,6 @@ update_menu_bar (struct frame *f, int save_match_data, int hooks_run) #ifdef HAVE_WINDOW_SYSTEM -/* Tool-bar item index of the item on which a mouse button was pressed - or -1. */ - -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 @@ -11829,7 +11861,7 @@ update_tool_bar (struct frame *f, int save_match_data) || window_buffer_changed (w)) { struct buffer *prev = current_buffer; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); Lisp_Object frame, new_tool_bar; int new_n_tool_bar; struct gcpro gcpro1; @@ -11885,7 +11917,7 @@ update_tool_bar (struct frame *f, int save_match_data) UNGCPRO; - unbind_to (count, Qnil); + dynwind_end (); set_buffer_internal_1 (prev); } } @@ -12237,11 +12269,6 @@ tool_bar_height (struct frame *f, int *n_rows, bool pixelwise) #endif /* !USE_GTK && !HAVE_NS */ -#if defined USE_GTK || defined HAVE_NS -EXFUN (Ftool_bar_height, 2) ATTRIBUTE_CONST; -EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST; -#endif - 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. @@ -12580,7 +12607,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, where the button was pressed, disregarding where it was released. */ if (NILP (Vmouse_highlight) && !down_p) - prop_idx = last_tool_bar_item; + prop_idx = f->last_tool_bar_item; /* If item is disabled, do nothing. */ enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P); @@ -12592,7 +12619,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, /* Show item in pressed state. */ if (!NILP (Vmouse_highlight)) show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN); - last_tool_bar_item = prop_idx; + f->last_tool_bar_item = prop_idx; } else { @@ -12617,7 +12644,7 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, event.arg = key; event.modifiers = modifiers; kbd_buffer_store_event (&event); - last_tool_bar_item = -1; + f->last_tool_bar_item = -1; } } @@ -12667,8 +12694,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y) mouse_down_p = (x_mouse_grabbed (dpyinfo) && f == dpyinfo->last_mouse_frame); - if (mouse_down_p - && last_tool_bar_item != prop_idx) + if (mouse_down_p && f->last_tool_bar_item != prop_idx) return; draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; @@ -13292,15 +13318,6 @@ propagate_buffer_redisplay (void) } } -#define STOP_POLLING \ -do { if (! polling_stopped_here) stop_polling (); \ - polling_stopped_here = 1; } while (0) - -#define RESUME_POLLING \ -do { if (polling_stopped_here) start_polling (); \ - polling_stopped_here = 0; } while (0) - - /* Perhaps in the future avoid recentering windows if it is not necessary; currently that causes some problems. */ @@ -13355,13 +13372,13 @@ redisplay_internal (void) /* Record a function that clears redisplaying_p when we leave this function. */ - count = SPECPDL_INDEX (); + dynwind_begin (); record_unwind_protect_void (unwind_redisplay); redisplaying_p = 1; specbind (Qinhibit_free_realized_faces, Qnil); /* Record this function, so it appears on the profiler's backtraces. */ - record_in_backtrace (Qredisplay_internal, &Qnil, 0); + /*record_in_backtrace (Qredisplay_internal, &Qnil, 0);*/ FOR_EACH_FRAME (tail, frame) XFRAME (frame)->already_hscrolled_p = 0; @@ -13800,13 +13817,6 @@ redisplay_internal (void) goto retry_frame; } - /* Prevent various kinds of signals during display - update. stdio is not robust about handling - signals, which can cause an apparent I/O error. */ - if (interrupt_input) - unrequest_sigio (); - STOP_POLLING; - pending |= update_frame (f, 0, 0); f->cursor_type_changed = 0; f->updated_p = 1; @@ -13857,13 +13867,6 @@ redisplay_internal (void) if (sf->fonts_changed) goto retry; - /* Prevent various kinds of signals during display update. - stdio is not robust about handling signals, - which can cause an apparent I/O error. */ - if (interrupt_input) - unrequest_sigio (); - STOP_POLLING; - if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf)) { if (hscroll_windows (selected_window)) @@ -13934,14 +13937,6 @@ redisplay_internal (void) windows_or_buffers_changed = 0; } - /* Start SIGIO interrupts coming again. Having them off during the - code above makes it less likely one will discard output, but not - impossible, since there might be stuff in the system buffer here. - But it is much hairier to try to do anything about that. */ - if (interrupt_input) - request_sigio (); - RESUME_POLLING; - /* If a frame has become visible which was not before, redisplay again, so that we display it. Expose events for such a frame (which it gets when becoming visible) don't call the parts of @@ -13992,11 +13987,7 @@ redisplay_internal (void) #endif /* HAVE_WINDOW_SYSTEM */ end_of_redisplay: - if (interrupt_input && interrupts_deferred) - request_sigio (); - - unbind_to (count, Qnil); - RESUME_POLLING; + dynwind_end (); } @@ -14387,7 +14378,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, pos_after, 0); if (prop_pos >= pos_before) - bpos_max = prop_pos - 1; + bpos_max = prop_pos; } if (INTEGERP (chprop)) { @@ -14461,7 +14452,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, pos_after, 0); if (prop_pos >= pos_before) - bpos_max = prop_pos - 1; + bpos_max = prop_pos; } if (INTEGERP (chprop)) { @@ -14491,7 +14482,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_max < pt_old && pt_old <= bpos_covered)) + && !(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. @@ -15678,9 +15669,6 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste return rc; } -#if !defined USE_TOOLKIT_SCROLL_BARS || defined USE_GTK -static -#endif void set_vertical_scroll_bar (struct window *w) { @@ -15723,7 +15711,51 @@ set_vertical_scroll_bar (struct window *w) selected_window is redisplayed. We can return without actually redisplaying the window if fonts has been - changed on window's frame. In that case, redisplay_internal will retry. */ + changed on window's frame. In that case, redisplay_internal will retry. + + As one of the important parts of redisplaying a window, we need to + decide whether the previous window-start position (stored in the + window's w->start marker position) is still valid, and if it isn't, + recompute it. Some details about that: + + . The previous window-start could be in a continuation line, in + which case we need to recompute it when the window width + changes. See compute_window_start_on_continuation_line and its + call below. + + . The text that changed since last redisplay could include the + previous window-start position. In that case, we try to salvage + what we can from the current glyph matrix by calling + try_scrolling, which see. + + . Some Emacs command could force us to use a specific window-start + position by setting the window's force_start flag, or gently + propose doing that by setting the window's optional_new_start + flag. In these cases, we try using the specified start point if + that succeeds (i.e. the window desired matrix is successfully + recomputed, and point location is within the window). In case + of optional_new_start, we first check if the specified start + position is feasible, i.e. if it will allow point to be + displayed in the window. If using the specified start point + fails, e.g., if new fonts are needed to be loaded, we abort the + redisplay cycle and leave it up to the next cycle to figure out + things. + + . Note that the window's force_start flag is sometimes set by + redisplay itself, when it decides that the previous window start + point is fine and should be kept. Search for "goto force_start" + below to see the details. Like the values of window-start + specified outside of redisplay, these internally-deduced values + are tested for feasibility, and ignored if found to be + unfeasible. + + . Note that the function try_window, used to completely redisplay + a window, accepts the window's start point as its argument. + This is used several times in the redisplay code to control + where the window start will be, according to user options such + as scroll-conservatively, and also to ensure the screen line + showing point will be fully (as opposed to partially) visible on + display. */ static void redisplay_window (Lisp_Object window, bool just_this_one_p) @@ -15743,7 +15775,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) It indicates that the buffer contents and narrowing are unchanged. */ bool buffer_unchanged_p = false; int temp_scroll_step = 0; - ptrdiff_t count = SPECPDL_INDEX (); int rc; int centering_position = -1; int last_line_misfit = 0; @@ -15769,6 +15800,10 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) eassert (XMARKER (w->start)->buffer == buffer); eassert (XMARKER (w->pointm)->buffer == buffer); + dynwind_begin (); + + /* We come here again if we need to run window-text-change-functions + below. */ restart: reconsider_clip_changes (w); frame_line_height = default_line_pixel_height (w); @@ -15833,7 +15868,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) && !current_buffer->prevent_redisplay_optimizations_p && !window_outdated (w)); - /* Run the window-bottom-change-functions + /* Run the window-text-change-functions if it is possible that the text on the screen has changed (either due to modification of the text, or any other reason). */ if (!current_matrix_up_to_date_p @@ -16680,7 +16715,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) if (CHARPOS (lpoint) <= ZV) TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint)); - unbind_to (count, Qnil); + dynwind_end (); } @@ -20667,6 +20702,10 @@ Value is the new character position of point. */) && !b->clip_changed && !b->prevent_redisplay_optimizations_p && !window_outdated (w) + /* We rely below on the cursor coordinates to be up to date, but + we cannot trust them if some command moved point since the + last complete redisplay. */ + && w->last_point == BUF_PT (b) && w->cursor.vpos >= 0 && w->cursor.vpos < w->current_matrix->nrows && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p) @@ -21430,7 +21469,7 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format) { struct it it; struct face *face; - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); init_iterator (&it, w, -1, -1, NULL, face_id); /* Don't extend on a previously drawn mode-line. @@ -21458,7 +21497,7 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format) display_mode_element (&it, 0, 0, 0, format, Qnil, 0); pop_kboard (); - unbind_to (count, Qnil); + dynwind_end (); /* Fill up with spaces. */ display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0); @@ -21857,7 +21896,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision, if (CONSP (XCDR (elt))) { Lisp_Object spec; - spec = safe_eval (XCAR (XCDR (elt))); + spec = safe__eval (true, XCAR (XCDR (elt))); n += display_mode_element (it, depth, field_width - n, precision - n, spec, props, risky); @@ -22110,7 +22149,7 @@ are the selected window and the WINDOW's buffer). */) struct buffer *old_buffer = NULL; int face_id; int no_props = INTEGERP (face); - ptrdiff_t count = SPECPDL_INDEX (); + dynwind_begin (); Lisp_Object str; int string_start = 0; @@ -22123,8 +22162,10 @@ are the selected window and the WINDOW's buffer). */) /* Make formatting the modeline a non-op when noninteractive, otherwise there will be problems later caused by a partially initialized frame. */ - if (NILP (format) || noninteractive) + if (NILP (format) || noninteractive) { + dynwind_end (); return empty_unibyte_string; + } if (no_props) face = Qnil; @@ -22185,7 +22226,7 @@ are the selected window and the WINDOW's buffer). */) empty_unibyte_string); } - unbind_to (count, Qnil); + dynwind_end (); return str; } @@ -22770,10 +22811,8 @@ decode_mode_spec (struct window *w, register int c, int field_width, case '@': { - ptrdiff_t count = inhibit_garbage_collection (); Lisp_Object val = call1 (intern ("file-remote-p"), BVAR (current_buffer, directory)); - unbind_to (count, Qnil); if (NILP (val)) return "-"; @@ -23651,7 +23690,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id, #endif { eassert (face != NULL); - PREPARE_FACE_FOR_DISPLAY (f, face); + prepare_face_for_display (f, face); } return face; @@ -23674,7 +23713,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph, /* Make sure X resources of the face are allocated. */ eassert (face != NULL); - PREPARE_FACE_FOR_DISPLAY (f, face); + prepare_face_for_display (f, face); if (two_byte_p) *two_byte_p = 0; @@ -23991,7 +24030,7 @@ fill_stretch_glyph_string (struct glyph_string *s, int start, int end) s->ybase += voffset; /* The case that face->gc == 0 is handled when drawing the glyph - string by calling PREPARE_FACE_FOR_DISPLAY. */ + string by calling prepare_face_for_display. */ eassert (s->face); return glyph - s->row->glyphs[s->area]; } @@ -24589,13 +24628,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 @@ -24616,7 +24658,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) @@ -24640,13 +24683,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 @@ -24664,7 +24710,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); @@ -24932,7 +24979,7 @@ produce_image_glyph (struct it *it) 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); + prepare_face_for_display (it->f, face); if (it->image_id < 0) { @@ -25210,7 +25257,7 @@ produce_stretch_glyph (struct it *it) { 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); + prepare_face_for_display (it->f, face); } #endif @@ -25674,7 +25721,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) face = FACE_FROM_ID (it->f, face_id); font = face->font ? face->font : FRAME_FONT (it->f); - PREPARE_FACE_FOR_DISPLAY (it->f, face); + prepare_face_for_display (it->f, face); if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM) { @@ -25690,7 +25737,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c); str = buf; } - for (len = 0; str[len] && ASCII_BYTE_P (str[len]) && len < 6; len++) + for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++) code[len] = font->driver->encode_char (font, str[len]); upper_len = (len + 1) / 2; font->driver->text_extents (font, code, upper_len, @@ -27015,9 +27062,6 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row, /* Erase the image of a cursor of window W from the screen. */ -#ifndef HAVE_NTGUI -static -#endif void erase_phys_cursor (struct window *w) { @@ -29879,6 +29923,8 @@ x_intersect_rectangles (XRectangle *r1, XRectangle *r2, XRectangle *result) void syms_of_xdisp (void) { +#include "xdisp.x" + Vwith_echo_area_save_vector = Qnil; staticpro (&Vwith_echo_area_save_vector); @@ -29895,25 +29941,6 @@ syms_of_xdisp (void) message_dolog_marker3 = Fmake_marker (); staticpro (&message_dolog_marker3); -#ifdef GLYPH_DEBUG - defsubr (&Sdump_frame_glyph_matrix); - defsubr (&Sdump_glyph_matrix); - defsubr (&Sdump_glyph_row); - defsubr (&Sdump_tool_bar_row); - defsubr (&Strace_redisplay); - defsubr (&Strace_to_stderr); -#endif -#ifdef HAVE_WINDOW_SYSTEM - defsubr (&Stool_bar_height); - defsubr (&Slookup_image_map); -#endif - defsubr (&Sline_pixel_height); - defsubr (&Sformat_mode_line); - defsubr (&Sinvisible_p); - defsubr (&Scurrent_bidi_paragraph_direction); - defsubr (&Swindow_text_pixel_size); - defsubr (&Smove_point_visually); - DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook"); DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map"); DEFSYM (Qoverriding_local_map, "overriding-local-map"); @@ -30565,7 +30592,7 @@ init_xdisp (void) /* Allocate the buffer for frame titles. Also used for `format-mode-line'. */ int size = 100; - mode_line_noprop_buf = xmalloc (size); + mode_line_noprop_buf = xmalloc_atomic (size); mode_line_noprop_buf_end = mode_line_noprop_buf + size; mode_line_noprop_ptr = mode_line_noprop_buf; mode_line_target = MODE_LINE_DISPLAY;