X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/8e6f69ce8902439b89669a5fbfbfc87083d3742f..1d512c6de75956e9557d95a83eab5bf49786edc6:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index f3876c9d02..532d548b2d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -15,7 +15,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ #include @@ -36,8 +37,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "intervals.h" #include "keyboard.h" -#ifdef USE_X_TOOLKIT +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) extern void set_frame_menubar (); +extern int pending_menu_activation; #endif extern int interrupt_input; @@ -50,7 +52,7 @@ extern Lisp_Object Voverriding_local_map_menu_flag; Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; -Lisp_Object Qredisplay_end_trigger_hook; +Lisp_Object Qredisplay_end_trigger_functions; /* Nonzero means print newline to stdout before next minibuffer message. */ @@ -158,6 +160,7 @@ static int debug_end_pos; /* Nonzero means display mode line highlighted */ int mode_line_inverse_video; +static void redisplay_internal (); static int message_log_check_duplicate (); static void echo_area_display (); void mark_window_display_accurate (); @@ -227,6 +230,8 @@ static int line_number_display_limit; t means infinite. nil means don't log at all. */ Lisp_Object Vmessage_log_max; +/* Output a newline in the *Messages* buffer if "needs" one. */ + void message_log_maybe_newline () { @@ -248,6 +253,7 @@ message_dolog (m, len, nlflag) { struct buffer *oldbuf; int oldpoint, oldbegv, oldzv; + int old_windows_or_buffers_changed = windows_or_buffers_changed; oldbuf = current_buffer; Fset_buffer (Fget_buffer_create (build_string ("*Messages*"))); @@ -316,11 +322,11 @@ message_dolog (m, len, nlflag) ZV = oldzv; TEMP_SET_PT (oldpoint); set_buffer_internal (oldbuf); + windows_or_buffers_changed = old_windows_or_buffers_changed; message_log_need_newline = !nlflag; } } - /* We are at the end of the buffer after just having inserted a newline. (Note: We depend on the fact we won't be crossing the gap.) Check to see if the most recent message looks a lot like the previous one. @@ -358,11 +364,16 @@ message_log_check_duplicate (prev_bol, this_bol) } return 0; } - + /* Display an echo area message M with a specified length of LEN chars. - The string may include null characters. If m is 0, clear out any + The string may include null characters. If M is 0, clear out any existing message, and let the minibuffer text show through. - Do not pass text that is stored in a Lisp string. */ + + The buffer M must continue to exist until after the echo area + gets cleared or some other message gets displayed there. + + Do not pass text that is stored in a Lisp string. + Do not pass text in a buffer that was alloca'd. */ void message2 (m, len) @@ -377,7 +388,7 @@ message2 (m, len) } -/* The non-logging part of that function. */ +/* The non-logging counterpart of message2. */ void message2_nolog (m, len) @@ -407,12 +418,10 @@ message2_nolog (m, len) mini_window = FRAME_MINIBUF_WINDOW (selected_frame); f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); -#ifdef MULTI_FRAME FRAME_SAMPLE_VISIBILITY (f); if (FRAME_VISIBLE_P (selected_frame) && ! FRAME_VISIBLE_P (f)) Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window))); -#endif if (m) { @@ -430,6 +439,15 @@ message2_nolog (m, len) (*frame_up_to_date_hook) (f); } } + +/* Display a null-terminated echo area message M. If M is 0, clear out any + existing message, and let the minibuffer text show through. + + The buffer M must continue to exist until after the echo area + gets cleared or some other message gets displayed there. + + Do not pass text that is stored in a Lisp string. + Do not pass text in a buffer that was alloca'd. */ void message1 (m) @@ -463,8 +481,9 @@ truncate_echo_area (len) zero if being used by message. */ int message_buf_print; -/* Dump an informative message to the minibuf. If m is 0, clear out +/* Dump an informative message to the minibuf. If M is 0, clear out any existing message, and let the minibuffer text show through. */ + /* VARARGS 1 */ void message (m, a1, a2, a3) @@ -512,10 +531,10 @@ message (m, a1, a2, a3) a[2] = a3; len = doprnt (FRAME_MESSAGE_BUF (f), - FRAME_WIDTH (f), m, (char *)0, 3, a); + (int) FRAME_WIDTH (f), m, (char *)0, 3, a); #else len = doprnt (FRAME_MESSAGE_BUF (f), - FRAME_WIDTH (f), m, (char *)0, 3, &a1); + (int) FRAME_WIDTH (f), m, (char *)0, 3, &a1); #endif /* NO_ARG_ARRAY */ message2 (FRAME_MESSAGE_BUF (f), len); @@ -530,7 +549,7 @@ message (m, a1, a2, a3) } } -/* The non-logging version of that function. */ +/* The non-logging version of message. */ void message_nolog (m, a1, a2, a3) char *m; @@ -548,7 +567,7 @@ update_echo_area () { message2 (echo_area_glyphs, echo_area_glyphs_length); } - + static void echo_area_display () { @@ -611,8 +630,10 @@ echo_area_display () previous_echo_glyphs = echo_area_glyphs; } + +/* Update frame titles. */ -#ifdef HAVE_X_WINDOWS +#ifdef HAVE_WINDOW_SYSTEM static char frame_title_buf[512]; static char *frame_title_ptr; @@ -641,7 +662,7 @@ x_consider_frame_title (frame) int len; FRAME_PTR f = XFRAME (frame); - if (!FRAME_X_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name) + if (!(FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name)) return; /* Do we have more than one visible frame on this X display? */ @@ -706,8 +727,8 @@ prepare_menu_bars () create its menu bar using the name `emacs' if no other name has yet been specified." I think that is no longer a concern. */ -#ifdef HAVE_X_WINDOWS - if (windows_or_buffers_changed) +#ifdef HAVE_WINDOW_SYSTEM + if (windows_or_buffers_changed || update_mode_lines) { Lisp_Object tail, frame; @@ -755,6 +776,12 @@ prepare_menu_bars () } else update_menu_bar (selected_frame, 1); + + /* Motif needs this. See comment in xmenu.c. + Turn it off when pending_menu_activation is not defined. */ +#ifdef USE_X_TOOLKIT + pending_menu_activation = 0; +#endif } /* Do a frame update, taking possible shortcuts into account. @@ -786,6 +813,19 @@ static FRAME_PTR previous_terminal_frame; void redisplay () +{ + redisplay_internal (0); +} + +/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay + is not in response to any user action; therefore, we should + preserve the echo area. (Actually, our caller does that job.) + Perhaps in the future avoid recentering windows + if it is not necessary; currently that causes some problems. */ + +static void +redisplay_internal (preserve_echo_area) + int preserve_echo_area; { register struct window *w = XWINDOW (selected_window); register int pause; @@ -797,8 +837,12 @@ redisplay () if (noninteractive) return; -#ifdef MULTI_FRAME - if (FRAME_TERMCAP_P (selected_frame) +#ifdef USE_X_TOOLKIT + if (popup_activated ()) + return; +#endif + + if (! FRAME_WINDOW_P (selected_frame) && previous_terminal_frame != selected_frame) { /* Since frames on an ASCII terminal share the same display area, @@ -808,7 +852,6 @@ redisplay () XSETFRAME (Vterminal_frame, selected_frame); } previous_terminal_frame = selected_frame; -#endif /* Set the visible flags for all frames. Do this before checking for resized or garbaged frames; they want @@ -841,9 +884,8 @@ redisplay () if (windows_or_buffers_changed) update_mode_lines++; - /* Detect case that we need to write a star in the mode line. */ - if (XFASTINT (w->last_modified) < MODIFF - && XFASTINT (w->last_modified) <= SAVE_MODIFF) + /* Detect case that we need to write or remove a star in the mode line. */ + if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star)) { w->update_mode_line = Qt; if (buffer_shared > 1) @@ -981,6 +1023,7 @@ redisplay () then we can't just move the cursor. */ else if (! (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)) + && w == XWINDOW (current_buffer->last_selected_window) && NILP (w->region_showing) && !cursor_in_echo_area) { @@ -1033,7 +1076,7 @@ redisplay () FOR_EACH_FRAME (tail, frame) { FRAME_PTR f = XFRAME (frame); - if (! FRAME_TERMCAP_P (f) || f == selected_frame) + if (FRAME_WINDOW_P (f) || f == selected_frame) { /* Mark all the scroll bars to be removed; we'll redeem the ones @@ -1042,7 +1085,7 @@ redisplay () (*condemn_scroll_bars_hook) (f); if (FRAME_VISIBLE_P (f)) - redisplay_windows (FRAME_ROOT_WINDOW (f)); + redisplay_windows (FRAME_ROOT_WINDOW (f), preserve_echo_area); /* Any scroll bars which redisplay_windows should have nuked should now go away. */ @@ -1053,7 +1096,7 @@ redisplay () } else if (FRAME_VISIBLE_P (selected_frame)) { - redisplay_window (selected_window, 1); + redisplay_window (selected_window, 1, preserve_echo_area); if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame)) preserve_other_columns (w); } @@ -1066,7 +1109,6 @@ update: unrequest_sigio (); stop_polling (); -#ifdef MULTI_FRAME if (all_windows) { Lisp_Object tail; @@ -1082,7 +1124,7 @@ update: f = XFRAME (XCONS (tail)->car); - if ((! FRAME_TERMCAP_P (f) || f == selected_frame) + if ((FRAME_WINDOW_P (f) || f == selected_frame) && FRAME_VISIBLE_P (f)) { pause |= update_frame (f, 0, 0); @@ -1096,7 +1138,6 @@ update: } } else -#endif /* MULTI_FRAME */ { if (FRAME_VISIBLE_P (selected_frame)) pause = update_frame (selected_frame, 0, 0); @@ -1115,8 +1156,7 @@ update: mini_window = FRAME_MINIBUF_WINDOW (selected_frame); mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window))); - if (mini_frame != selected_frame - && ! FRAME_TERMCAP_P (mini_frame)) + if (mini_frame != selected_frame && FRAME_WINDOW_P (mini_frame)) pause |= update_frame (mini_frame, 0, 0); } } @@ -1162,6 +1202,9 @@ update: b->clip_changed = 0; w->update_mode_line = Qnil; XSETFASTINT (w->last_modified, BUF_MODIFF (b)); + w->last_had_star + = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer)) + ? Qt : Qnil); w->window_end_valid = w->buffer; last_arrow_position = Voverlay_arrow_position; last_arrow_string = Voverlay_arrow_string; @@ -1207,11 +1250,11 @@ redisplay_preserve_echo_area () if (echo_area_glyphs == 0 && previous_echo_glyphs != 0) { echo_area_glyphs = previous_echo_glyphs; - redisplay (); + redisplay_internal (1); echo_area_glyphs = 0; } else - redisplay (); + redisplay_internal (1); } void @@ -1230,10 +1273,14 @@ mark_window_display_accurate (window, flag) { XSETFASTINT (w->last_modified, !flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer))); + w->last_had_star + = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer)) + ? Qt : Qnil); /* Record if we are showing a region, so can make sure to update it fully at next redisplay. */ w->region_showing = (!NILP (Vtransient_mark_mode) + && w == XWINDOW (current_buffer->last_selected_window) && !NILP (XBUFFER (w->buffer)->mark_active) ? Fmarker_position (XBUFFER (w->buffer)->mark) : Qnil); @@ -1241,7 +1288,7 @@ mark_window_display_accurate (window, flag) w->window_end_valid = w->buffer; w->update_mode_line = Qnil; - if (!NILP (w->buffer)) + if (!NILP (w->buffer) && flag) XBUFFER (w->buffer)->clip_changed = 0; if (!NILP (w->vchild)) @@ -1284,13 +1331,14 @@ update_menu_bar (f, save_match_data) if (update_mode_lines) w->update_mode_line = Qt; - if ( -#ifdef USE_X_TOOLKIT + if (FRAME_WINDOW_P (f) + ? +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) FRAME_EXTERNAL_MENU_BAR (f) #else FRAME_MENU_BAR_LINES (f) > 0 #endif - ) + : FRAME_MENU_BAR_LINES (f) > 0) { /* If the user has switched buffers or windows, we need to recompute to reflect the new bindings. But we'll @@ -1301,9 +1349,9 @@ update_menu_bar (f, save_match_data) windows_or_buffers_changed anyway. */ if (windows_or_buffers_changed || !NILP (w->update_mode_line) - || (XFASTINT (w->last_modified) < MODIFF - && (XFASTINT (w->last_modified) - <= BUF_SAVE_MODIFF (XBUFFER (w->buffer)))) + || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer)) + < BUF_MODIFF (XBUFFER (w->buffer))) + != !NILP (w->last_had_star)) || ((!NILP (Vtransient_mark_mode) && !NILP (XBUFFER (w->buffer)->mark_active)) != !NILP (w->region_showing))) @@ -1326,11 +1374,21 @@ update_menu_bar (f, save_match_data) really recompute the menubar from the value. */ if (! NILP (Vlucid_menu_bar_dirty_flag)) call0 (Qrecompute_lucid_menubar); - call1 (Vrun_hooks, Qmenu_bar_update_hook); + safe_run_hooks (Qmenu_bar_update_hook); FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); -#ifdef USE_X_TOOLKIT - set_frame_menubar (f, 0, 0); -#endif /* USE_X_TOOLKIT */ + /* Redisplay the menu bar in case we changed it. */ +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) + if (FRAME_WINDOW_P (f)) + set_frame_menubar (f, 0, 0); + else + /* On a terminal screen, the menu bar is an ordinary screen + line, and this makes it get updated. */ + w->update_mode_line = Qt; +#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */ + /* In the non-toolkit version, the menu bar is an ordinary screen + line, and this makes it get updated. */ + w->update_mode_line = Qt; +#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI) */ unbind_to (count, Qnil); set_buffer_internal_1 (prev); @@ -1343,19 +1401,20 @@ int do_id = 1; /* Redisplay WINDOW and its subwindows and siblings. */ static void -redisplay_windows (window) +redisplay_windows (window, preserve_echo_area) Lisp_Object window; + int preserve_echo_area; { for (; !NILP (window); window = XWINDOW (window)->next) - redisplay_window (window, 0); + redisplay_window (window, 0, preserve_echo_area); } /* Redisplay window WINDOW and its subwindows. */ static void -redisplay_window (window, just_this_one) +redisplay_window (window, just_this_one, preserve_echo_area) Lisp_Object window; - int just_this_one; + int just_this_one, preserve_echo_area; { register struct window *w = XWINDOW (window); FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); @@ -1377,12 +1436,12 @@ redisplay_window (window, just_this_one) if (!NILP (w->vchild)) { - redisplay_windows (w->vchild); + redisplay_windows (w->vchild, preserve_echo_area); return; } if (!NILP (w->hchild)) { - redisplay_windows (w->hchild); + redisplay_windows (w->hchild, preserve_echo_area); return; } if (NILP (w->buffer)) @@ -1498,11 +1557,16 @@ redisplay_window (window, just_this_one) unless the specified location is outside the accessible range. */ if (!NILP (w->force_start)) { + w->force_start = Qnil; /* Forget any recorded base line for line number display. */ w->base_line_number = Qnil; /* Redisplay the mode line. Select the buffer properly for that. Also, run the hook window-scroll-functions because we have scrolled. */ + /* Note, we do this after clearing force_start because + if there's an error, it is better to forget about force_start + than to get into an infinite loop calling the hook functions + and having them get more errors. */ if (!update_mode_line || ! NILP (Vwindow_scroll_functions)) { @@ -1513,10 +1577,12 @@ redisplay_window (window, just_this_one) update_mode_line = 1; w->update_mode_line = Qt; if (! NILP (Vwindow_scroll_functions)) - run_hook_with_args_2 (Qwindow_scroll_functions, window, - make_number (startp)); + { + run_hook_with_args_2 (Qwindow_scroll_functions, window, + make_number (startp)); + startp = marker_position (w->start); + } } - w->force_start = Qnil; XSETFASTINT (w->last_modified, 0); if (startp < BEGV) startp = BEGV; if (startp > ZV) startp = ZV; @@ -1557,7 +1623,7 @@ redisplay_window (window, just_this_one) } /* Handle case where text has not changed, only point, - and it has not moved off the frame */ + and it has not moved off the frame. */ /* This code is not used for minibuffer for the sake of the case of redisplaying to replace an echo area message; @@ -1644,8 +1710,16 @@ redisplay_window (window, just_this_one) goto done; } else if (startp >= BEGV && startp <= ZV - /* Avoid starting display at end of buffer! */ - && (startp < ZV || startp == BEGV + && (startp < ZV + /* Avoid starting at end of buffer. */ +#if 0 /* This change causes trouble for M-! finger & RET. + It will have to be considered later. */ + || ! EQ (window, selected_window) + /* Don't do the recentering if redisplay + is not for no user action. */ + || preserve_echo_area +#endif + || startp == BEGV || (XFASTINT (w->last_modified) >= MODIFF))) { /* Try to redisplay starting at same place as before */ @@ -1675,7 +1749,8 @@ redisplay_window (window, just_this_one) /* Try to scroll by specified few lines */ - if (scroll_step && !current_buffer->clip_changed) + if (scroll_step && !current_buffer->clip_changed + && startp >= BEGV && startp <= ZV) { if (PT > startp) { @@ -1689,8 +1764,12 @@ redisplay_window (window, just_this_one) if (PT >= pos.bufpos) { if (! NILP (Vwindow_scroll_functions)) - run_hook_with_args_2 (Qwindow_scroll_functions, window, - make_number (pos.bufpos)); + { + Fset_marker (w->start, make_number (pos.bufpos), Qnil); + run_hook_with_args_2 (Qwindow_scroll_functions, window, + make_number (pos.bufpos)); + pos.bufpos = marker_position (w->start); + } try_window (window, pos.bufpos); if (cursor_vpos >= 0) { @@ -1713,9 +1792,15 @@ recenter: w->base_line_number = Qnil; pos = *vmotion (PT, - (height / 2), w); + /* Set startp here explicitly in case that helps avoid an infinite loop + in case the window-scroll-functions functions get errors. */ + Fset_marker (w->start, make_number (pos.bufpos), Qnil); if (! NILP (Vwindow_scroll_functions)) - run_hook_with_args_2 (Qwindow_scroll_functions, window, - make_number (pos.bufpos)); + { + run_hook_with_args_2 (Qwindow_scroll_functions, window, + make_number (pos.bufpos)); + pos.bufpos = marker_position (w->start); + } try_window (window, pos.bufpos); startp = marker_position (w->start); @@ -1741,11 +1826,14 @@ done: /* When we reach a frame's selected window, redo the frame's menu bar. */ if (update_mode_line -#ifdef USE_X_TOOLKIT - && FRAME_EXTERNAL_MENU_BAR (f) + && (FRAME_WINDOW_P (f) + ? +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) + FRAME_EXTERNAL_MENU_BAR (f) #else - && FRAME_MENU_BAR_LINES (f) > 0 + FRAME_MENU_BAR_LINES (f) > 0 #endif + : FRAME_MENU_BAR_LINES (f) > 0) && EQ (FRAME_SELECTED_WINDOW (f), window)) display_menu_bar (w); @@ -1894,7 +1982,7 @@ try_window_id (window) struct position val, bp, ep, xp, pp; int scroll_amount = 0; int delta; - int tab_offset, epto; + int tab_offset, epto, old_tick; if (GPT - BEG < beg_unchanged) beg_unchanged = GPT - BEG; @@ -2088,8 +2176,8 @@ try_window_id (window) lines' charstarts in the case where the text of the screen line at bp.vpos has changed. (This can happen in a deletion that ends in mid-line.) - To adjust properly, we need to make things constent at - the position ep. + To adjust properly, we need to make things consistent + at the position ep. So do a second adjust to make that happen. Note that stop_vpos >= ep.vpos, so it is sufficient to update the charstarts for lines at ep.vpos and below. */ @@ -2139,9 +2227,15 @@ try_window_id (window) to account for passing the line that that character really starts in. */ if (val.hpos < lmargin) tab_offset += width; + old_tick = MODIFF; while (vpos < stop_vpos) { val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset); + /* If display_text_line ran a hook and changed some text, + redisplay all the way to bottom of buffer + So that we show the changes. */ + if (old_tick != MODIFF) + stop_vpos = height; tab_offset += width; if (val.vpos) tab_offset = 0; if (pos != val.bufpos) @@ -2465,7 +2559,8 @@ display_text_line (w, start, vpos, hpos, taboffset) /* 1 if we should highlight the region. */ int highlight_region - = !NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active); + = (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active) + && XWINDOW (current_buffer->last_selected_window) == w); int region_beg, region_end; int selective = (INTEGERP (current_buffer->selective_display) @@ -2700,22 +2795,13 @@ display_text_line (w, start, vpos, hpos, taboffset) break; } -#ifdef HAVE_FACES - /* Did we hit a face change? Figure out what face we should - use now. We also hit this the first time through the - loop, to see what face we should start with. */ - if (pos >= next_face_change && FRAME_X_P (f)) - current_face = compute_char_face (f, w, pos, - region_beg, region_end, - &next_face_change, pos + 50, 0); -#endif - /* Figure out where (if at all) the redisplay_end_trigger-hook should run. */ - if (MARKERP (current_buffer->redisplay_end_trigger)) - e_t_h = marker_position (current_buffer->redisplay_end_trigger); - else if (INTEGERP (current_buffer->redisplay_end_trigger)) - e_t_h = XINT (current_buffer->redisplay_end_trigger); + if (MARKERP (w->redisplay_end_trigger) + && XMARKER (w->redisplay_end_trigger)->buffer != 0) + e_t_h = marker_position (w->redisplay_end_trigger); + else if (INTEGERP (w->redisplay_end_trigger)) + e_t_h = XINT (w->redisplay_end_trigger); else e_t_h = ZV; @@ -2723,11 +2809,33 @@ display_text_line (w, start, vpos, hpos, taboffset) run the hook. */ if (pos >= e_t_h && e_t_h != ZV) { - call1 (Vrun_hooks, Qredisplay_end_trigger_hook); - current_buffer->redisplay_end_trigger = Qnil; + Lisp_Object args[3]; + + args[0] = Qredisplay_end_trigger_functions; + XSETWINDOW (args[1], w); + XSETINT (args[2], e_t_h); + + /* Since we are *trying* to run these functions, + don't try to run them again, even if they get an error. */ + w->redisplay_end_trigger = Qnil; + Frun_hook_with_args (3, args); + e_t_h = ZV; + /* Notice if it changed the face of this character. */ + next_face_change = pos; } +#ifdef HAVE_FACES + /* Did we hit a face change? Figure out what face we should + use now. We also hit this the first time through the + loop, to see what face we should start with. */ + if (pos >= next_face_change + && (FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f))) + current_face = compute_char_face (f, w, pos, + region_beg, region_end, + &next_face_change, pos + 50, 0); +#endif + /* Compute the next place we need to stop and do something special; set PAUSE. */ @@ -3158,34 +3266,27 @@ display_menu_bar (w) int hpos = 0; int i; -#ifndef USE_X_TOOLKIT - if (FRAME_MENU_BAR_LINES (f) <= 0) +#ifdef HAVE_NTGUI + if (!NILP (Vwindow_system)) return; +#endif - get_display_line (f, vpos, 0); +#ifdef USE_X_TOOLKIT + if (FRAME_X_P (f)) + return; +#endif /* USE_X_TOOLKIT */ -#if 0 - /* Show in the menu bar how to invoke it. */ - if (!FRAME_X_P (f)) - { - hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos, - "M-`", 3, - hpos, 0, 0, hpos, maxendcol); - /* Put 2 spaces after it. */ - hpos = display_string (w, vpos, "", 0, hpos, 0, 0, - hpos + 2, maxendcol); - } -#endif + get_display_line (f, vpos, 0); items = FRAME_MENU_BAR_ITEMS (f); - for (i = 0; i < XVECTOR (items)->size; i += 3) + for (i = 0; i < XVECTOR (items)->size; i += 4) { Lisp_Object pos, string; string = XVECTOR (items)->contents[i + 1]; if (NILP (string)) break; - XSETFASTINT (XVECTOR (items)->contents[i + 2], hpos); + XSETFASTINT (XVECTOR (items)->contents[i + 3], hpos); if (hpos < maxendcol) hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos, @@ -3212,7 +3313,6 @@ display_menu_bar (w) vpos++; while (vpos < FRAME_MENU_BAR_LINES (f)) get_display_line (f, vpos++, 0); -#endif /* not USE_X_TOOLKIT */ } /* Display the mode line for window w */ @@ -3639,11 +3739,11 @@ decode_mode_spec (w, c, spec_width, maxwidth) case 'F': /* %F displays the frame name. */ -#ifdef MULTI_FRAME - return (char *) XSTRING (selected_frame->name)->data; -#else + if (!NILP (f->title)) + return (char *) XSTRING (f->title)->data; + if (f->explicit_name || ! FRAME_WINDOW_P (f)) + return (char *) XSTRING (f->name)->data; return "Emacs"; -#endif case 'f': obj = b->filename; @@ -3779,7 +3879,11 @@ decode_mode_spec (w, c, spec_width, maxwidth) return "Top"; else { - total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total; + if (total > 1000000) + /* Do it differently for a large value, to avoid overflow. */ + total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100); + else + total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total; /* We can't normally display a 3-digit number, so get us a 2-digit number that is close. */ if (total == 100) @@ -3805,7 +3909,11 @@ decode_mode_spec (w, c, spec_width, maxwidth) } else { - total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total; + if (total > 1000000) + /* Do it differently for a large value, to avoid overflow. */ + total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100); + else + total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total; /* We can't normally display a 3-digit number, so get us a 2-digit number that is close. */ if (total == 100) @@ -4007,6 +4115,7 @@ display_string (w, vpos, string, length, hpos, truncate, int mincol, maxcol; { register int c; + int truncated; register GLYPH *p1; int hscroll = XINT (w->hscroll); int tab_width = XINT (XBUFFER (w->buffer)->tab_width); @@ -4059,7 +4168,10 @@ display_string (w, vpos, string, length, hpos, truncate, if (maxcol >= 0 && mincol > maxcol) mincol = maxcol; - while (p1 < end) + /* We set truncated to 1 if we get stopped by trying to pass END + (that is, trying to pass MAXCOL.) */ + truncated = 0; + while (1) { if (length == 0) break; @@ -4071,6 +4183,12 @@ display_string (w, vpos, string, length, hpos, truncate, else if (c == 0) break; + if (p1 >= end) + { + truncated = 1; + break; + } + if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c))) { p1 = copy_part_of_rope (f, p1, start, @@ -4124,7 +4242,7 @@ display_string (w, vpos, string, length, hpos, truncate, } } - if (c && length > 0) + if (truncated) { p1 = end; if (truncate) *p1++ = fix_glyph (f, truncate, 0); @@ -4242,8 +4360,8 @@ syms_of_xdisp () staticpro (&Qwindow_scroll_functions); Qwindow_scroll_functions = intern ("window-scroll-functions"); - staticpro (&Qredisplay_end_trigger_hook); - Qredisplay_end_trigger_hook = intern ("redisplay-end-trigger-hook"); + staticpro (&Qredisplay_end_trigger_functions); + Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions"); staticpro (&last_arrow_position); staticpro (&last_arrow_string);