]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
(redisplay_window): If window-scroll-functions change
[gnu-emacs] / src / xdisp.c
index ead4b78f8a06ecdea1d3bd1a7f7092dcff516aa8..7fc3425dc0d6dca41bd9c587b52bc99b01ec9bc0 100644 (file)
@@ -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 <config.h>
@@ -50,7 +51,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.  */
 
@@ -227,6 +228,8 @@ static int line_number_display_limit;
    t means infinite.  nil means don't log at all.  */
 Lisp_Object Vmessage_log_max;
 \f
+/* Output a newline in the *Messages* buffer if "needs" one.  */
+
 void
 message_log_maybe_newline ()
 {
@@ -248,6 +251,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 +320,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 +362,16 @@ message_log_check_duplicate (prev_bol, this_bol)
     }
   return 0;
 }
-
+\f
 /* 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 +386,7 @@ message2 (m, len)
 }
 
 
-/* The non-logging part of that function.  */
+/* The non-logging counterpart of message2.  */
 
 void
 message2_nolog (m, len)
@@ -430,6 +439,15 @@ message2_nolog (m, len)
        (*frame_up_to_date_hook) (f);
     }
 }
+\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)
@@ -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);
 }
-
+\f
 static void
 echo_area_display ()
 {
@@ -611,6 +630,8 @@ echo_area_display ()
 
   previous_echo_glyphs = echo_area_glyphs;
 }
+\f
+/* Update frame titles.  */
 
 #ifdef HAVE_WINDOW_SYSTEM
 static char frame_title_buf[512];
@@ -707,7 +728,7 @@ prepare_menu_bars ()
      has yet been specified."
      I think that is no longer a concern.  */
 #ifdef HAVE_WINDOW_SYSTEM
-  if (windows_or_buffers_changed)
+  if (windows_or_buffers_changed || update_mode_lines)
     {
       Lisp_Object tail, frame;
 
@@ -797,6 +818,11 @@ redisplay ()
   if (noninteractive)
     return;
 
+#ifdef USE_X_TOOLKIT
+  if (popup_activated ())
+    return;
+#endif
+
 #ifdef MULTI_FRAME
   if (FRAME_TERMCAP_P (selected_frame)
       && previous_terminal_frame != selected_frame)
@@ -1241,7 +1267,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,7 +1310,7 @@ update_menu_bar (f, save_match_data)
   if (update_mode_lines)
     w->update_mode_line = Qt;
 
-  if (FRAME_X_P (f)
+  if (FRAME_WINDOW_P (f)
       ?
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
       FRAME_EXTERNAL_MENU_BAR (f) 
@@ -1327,10 +1353,10 @@ 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));
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
-         if (FRAME_X_P (f))
+         if (FRAME_WINDOW_P (f))
            set_frame_menubar (f, 0, 0);
 #endif /* USE_X_TOOLKIT || HAVE_NTGUI */
 
@@ -1500,11 +1526,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))
        {
@@ -1515,10 +1546,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;
@@ -1559,7 +1592,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;
@@ -1677,7 +1710,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)
        {
@@ -1691,8 +1725,11 @@ 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));
+           {
+             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)
            {
@@ -1715,9 +1752,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);
@@ -1743,7 +1786,7 @@ done:
 
   /* When we reach a frame's selected window, redo the frame's menu bar.  */
   if (update_mode_line
-      && (FRAME_X_P (f)
+      && (FRAME_WINDOW_P (f)
          ?
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
          FRAME_EXTERNAL_MENU_BAR (f) 
@@ -2093,8 +2136,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.  */
@@ -2725,8 +2768,17 @@ display_text_line (w, start, vpos, hpos, taboffset)
             run the hook.  */
          if (pos >= e_t_h && e_t_h != ZV)
            {
-             Frun_hooks (1, &Qredisplay_end_trigger_hook);
+             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;
@@ -3645,6 +3697,8 @@ decode_mode_spec (w, c, spec_width, maxwidth)
     case 'F':
       /* %F displays the frame name.  */
 #ifdef MULTI_FRAME
+      if (!NILP (selected_frame->title))
+       return (char *) XSTRING (selected_frame->title)->data;
       return (char *) XSTRING (selected_frame->name)->data;
 #else
       return "Emacs";
@@ -3784,7 +3838,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)
@@ -3810,7 +3868,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)
@@ -4257,8 +4319,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);