(Fredirect_frame_focus): Don't call Ffocus_frame.
[bpt/emacs.git] / src / xdisp.c
index 7000d8d..532d548 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>
@@ -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;
@@ -49,6 +51,8 @@ extern Lisp_Object Voverriding_local_map;
 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_functions;
 
 /* Nonzero means print newline to stdout before next minibuffer message.  */
 
@@ -156,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 ();
@@ -225,6 +230,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 ()
 {
@@ -246,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*")));
@@ -314,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.
@@ -356,11 +364,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)
@@ -375,7 +388,7 @@ message2 (m, len)
 }
 
 
-/* The non-logging part of that function.  */
+/* The non-logging counterpart of message2.  */
 
 void
 message2_nolog (m, len)
@@ -405,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)
        {
@@ -428,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)
@@ -461,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)
@@ -510,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);
@@ -528,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;
@@ -546,7 +567,7 @@ update_echo_area ()
 {
   message2 (echo_area_glyphs, echo_area_glyphs_length);
 }
-
+\f
 static void
 echo_area_display ()
 {
@@ -609,8 +630,10 @@ echo_area_display ()
 
   previous_echo_glyphs = echo_area_glyphs;
 }
+\f
+/* Update frame titles.  */
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
 static char frame_title_buf[512];
 static char *frame_title_ptr;
 
@@ -639,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?  */
@@ -704,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;
 
@@ -753,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
 }
 \f
 /* Do a frame update, taking possible shortcuts into account.
@@ -784,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;
@@ -795,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,
@@ -806,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
@@ -839,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)
@@ -979,13 +1023,14 @@ 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)
        {
          pos = *compute_motion (tlbufpos, 0,
                                 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
                                 0,
-                                PT, 2, - (1 << (SHORTBITS - 1)),
+                                PT, 2, - (1 << (BITS_PER_SHORT - 1)),
                                 window_internal_width (w) - 1,
                                 XINT (w->hscroll),
                                 pos_tab_offset (w, tlbufpos), w);
@@ -1031,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
@@ -1040,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.  */
@@ -1051,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);
     }
@@ -1064,7 +1109,6 @@ update:
     unrequest_sigio ();
   stop_polling ();
 
-#ifdef MULTI_FRAME
   if (all_windows)
     {
       Lisp_Object tail;
@@ -1080,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);
@@ -1094,7 +1138,6 @@ update:
        }
     }
   else
-#endif /* MULTI_FRAME */
     {
       if (FRAME_VISIBLE_P (selected_frame))
        pause = update_frame (selected_frame, 0, 0);
@@ -1113,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);
       }
     }
@@ -1160,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;
@@ -1205,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
@@ -1228,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);
@@ -1239,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))
@@ -1282,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
@@ -1299,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)))
@@ -1324,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);
@@ -1341,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));
@@ -1367,7 +1428,7 @@ redisplay_window (window, just_this_one)
   int opoint = PT;
   int tem;
   int update_mode_line;
-  struct Lisp_Vector *dp = window_display_table (w);
+  struct Lisp_Char_Table *dp = window_display_table (w);
 
   if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
 
@@ -1375,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))
@@ -1474,7 +1535,7 @@ redisplay_window (window, just_this_one)
      changed, so why should we worry about doing any better?  */
   if (current_buffer->width_run_cache)
     {
-      struct Lisp_Vector *disptab = buffer_display_table ();
+      struct Lisp_Char_Table *disptab = buffer_display_table ();
 
       if (! disptab_matches_widthtab (disptab,
                                       XVECTOR (current_buffer->width_table)))
@@ -1496,17 +1557,32 @@ 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.  */
-      if (!update_mode_line)
+      /* 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))
        {
+         Lisp_Object temp[3];
+
          set_buffer_temp (old);
          set_buffer_internal_1 (XBUFFER (w->buffer));
          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));
+             startp = marker_position (w->start);
+           }
        }
-      w->force_start = Qnil;
       XSETFASTINT (w->last_modified, 0);
       if (startp < BEGV) startp = BEGV;
       if (startp > ZV)   startp = ZV;
@@ -1521,7 +1597,7 @@ redisplay_window (window, just_this_one)
                                  + (hscroll ? 1 - hscroll : 0)),
                                 0,
                                 ZV, height / 2,
-                                - (1 << (SHORTBITS - 1)),
+                                - (1 << (BITS_PER_SHORT - 1)),
                                 width, hscroll, pos_tab_offset (w, startp), w);
          BUF_PT (current_buffer) = pos.bufpos;
          if (w != XWINDOW (selected_window))
@@ -1547,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;
@@ -1634,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 */
@@ -1665,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)
        {
@@ -1678,6 +1763,13 @@ redisplay_window (window, just_this_one)
 
       if (PT >= pos.bufpos)
        {
+         if (! NILP (Vwindow_scroll_functions))
+           {
+             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)
            {
@@ -1700,6 +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));
+      pos.bufpos = marker_position (w->start);
+    }
   try_window (window, pos.bufpos);
 
   startp = marker_position (w->start);
@@ -1725,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);
 
@@ -1878,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;
@@ -1896,12 +2000,12 @@ try_window_id (window)
     {
       if (PT < bp.bufpos)
        {
-         /* All changes are below the frame, and point is on the frame.
-            We don't need to change the frame at all.
+         /* All changes are beyond the window end, and point is on the screen.
+            We don't need to change the text at all.
             But we need to update window_end_pos to account for
             any change in buffer size.  */
          bp = *compute_motion (start, 0, lmargin, 0,
-                               Z, height, 0,
+                               ZV, height, 0,
                                width, hscroll, pos_tab_offset (w, start), w);
          XSETFASTINT (w->window_end_vpos, height);
          XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
@@ -1951,7 +2055,7 @@ try_window_id (window)
 
   /* Compute the cursor position after that newline.  */
   ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
-                       height, - (1 << (SHORTBITS - 1)),
+                       height, - (1 << (BITS_PER_SHORT - 1)),
                        width, hscroll, pos_tab_offset (w, bp.bufpos), w);
 
   /* If changes reach past the text available on the frame,
@@ -2007,13 +2111,13 @@ try_window_id (window)
          if (PT <= xp.bufpos)
            {
              pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
-                                   PT, height, - (1 << (SHORTBITS - 1)),
+                                   PT, height, - (1 << (BITS_PER_SHORT - 1)),
                                    width, hscroll, epto, w);
            }
          else
            {
              pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
-                                   PT, height, - (1 << (SHORTBITS - 1)),
+                                   PT, height, - (1 << (BITS_PER_SHORT - 1)),
                                    width, hscroll,
                                    pos_tab_offset (w, xp.bufpos), w);
            }
@@ -2072,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.  */
@@ -2123,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)
@@ -2234,7 +2344,7 @@ try_window_id (window)
   if (debug_end_pos)
     {
       val = *compute_motion (start, 0, lmargin, 0, ZV,
-                            height, - (1 << (SHORTBITS - 1)),
+                            height, - (1 << (BITS_PER_SHORT - 1)),
                             width, hscroll, pos_tab_offset (w, start), w);
       if (val.vpos != XFASTINT (w->window_end_vpos))
        abort ();
@@ -2449,14 +2559,15 @@ 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)
                   ? XINT (current_buffer->selective_display)
                   : !NILP (current_buffer->selective_display) ? -1 : 0);
   register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
-  register struct Lisp_Vector *dp = window_display_table (w);
+  register struct Lisp_Char_Table *dp = window_display_table (w);
 
   Lisp_Object default_invis_vector[3];
   /* Number of characters of ellipsis to display after an invisible line
@@ -2601,6 +2712,8 @@ display_text_line (w, start, vpos, hpos, taboffset)
     {
       if (pos >= pause)
        {
+         int e_t_h;
+
          while (pos == next_boundary)
            {
              Lisp_Object position, limit, prop, ww;
@@ -2682,16 +2795,50 @@ display_text_line (w, start, vpos, hpos, taboffset)
              break;
            }
 
+         /* Figure out where (if at all) the
+            redisplay_end_trigger-hook should run.  */
+         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;
+
+         /* If we've gone past the place to run a hook,
+            run the hook.  */
+         if (pos >= e_t_h && e_t_h != ZV)
+           {
+             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_X_P (f))
+         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.  */
+
          pause = ZV;
 
          if (pos < next_boundary && next_boundary < pause)
@@ -2699,6 +2846,9 @@ display_text_line (w, start, vpos, hpos, taboffset)
          if (pos < next_face_change && next_face_change < pause)
            pause = next_face_change;
 
+         if (e_t_h < pause)
+           pause = e_t_h;
+
          /* Wouldn't you hate to read the next line to someone over
              the phone?  */
          if (pos < PT && PT < pause)
@@ -3116,21 +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
+
+#ifdef USE_X_TOOLKIT
+  if (FRAME_X_P (f))
     return;
+#endif /* USE_X_TOOLKIT */
 
   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,
@@ -3157,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 */
 }
 \f
 /* Display the mode line for window w */
@@ -3584,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;
@@ -3724,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)
@@ -3750,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)
@@ -3952,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);
@@ -3964,12 +4128,11 @@ display_string (w, vpos, string, length, hpos, truncate,
 
   /* Use the standard display table, not the window's display table.
      We don't want the mode line in rot13.  */
-  register struct Lisp_Vector *dp = 0;
+  register struct Lisp_Char_Table *dp = 0;
   int i;
 
-  if (VECTORP (Vstandard_display_table)
-      && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE)
-    dp = XVECTOR (Vstandard_display_table);
+  if (DISP_TABLE_P (Vstandard_display_table))
+    dp = XCHAR_TABLE (Vstandard_display_table);
 
   if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
 
@@ -4005,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;
@@ -4017,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,
@@ -4070,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);
@@ -4185,6 +4357,12 @@ syms_of_xdisp ()
   staticpro (&Qoverriding_local_map);
   Qoverriding_local_map = intern ("overriding-local-map");
 
+  staticpro (&Qwindow_scroll_functions);
+  Qwindow_scroll_functions = intern ("window-scroll-functions");
+
+  staticpro (&Qredisplay_end_trigger_functions);
+  Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
+
   staticpro (&last_arrow_position);
   staticpro (&last_arrow_string);
   last_arrow_position = Qnil;
@@ -4270,6 +4448,13 @@ Just before redisplay, for each frame, if any of its windows have changed\n\
 size since the last redisplay, or have been split or deleted,\n\
 all the functions in the list are called, with the frame as argument.");
   Vwindow_size_change_functions = Qnil;
+
+  DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
+    "List of Functions to call before redisplaying a window with scrolling.\n\
+Each function is called with two arguments, the window\n\
+and its new display-start position.  Note that the value of `window-end'\n\
+is not valid when these functions are called.");
+  Vwindow_scroll_functions = Qnil;
 }
 
 /* initialize the window system */