emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] trunk r115272: Refine redisplay optimizations to only redi


From: Stefan Monnier
Subject: [Emacs-diffs] trunk r115272: Refine redisplay optimizations to only redisplay *some* frames/windows
Date: Thu, 28 Nov 2013 22:43:23 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 115272
revision-id: address@hidden
parent: address@hidden
committer: Stefan Monnier <address@hidden>
branch nick: trunk
timestamp: Thu 2013-11-28 17:43:09 -0500
message:
  Refine redisplay optimizations to only redisplay *some* frames/windows
  rather than all of them.
  * src/xdisp.c (REDISPLAY_SOME): New constant.
  (redisplay_other_windows, wset_redisplay, fset_redisplay)
  (bset_redisplay, bset_update_mode_line): New functions.
  (message_dolog): Use bset_redisplay.
  (clear_garbaged_frames): Use fset_redisplay.
  (echo_area_display): Use wset_redisplay.
  (buffer_shared_and_changed): Remove.
  (prepare_menu_bars): Call Vpre_redisplay_function before updating
  frame titles.  Compute the actual set of windows redisplayed.
  Don't update frame titles and menu bars for frames that don't need to
  be redisplayed.
  (propagate_buffer_redisplay): New function.
  (AINC): New macro.
  (redisplay_internal): Use it.  Be more selective in the set of windows
  we redisplay.  Propagate windows_or_buffers_changed to
  update_mode_lines a bit later to simplify the code.
  (mark_window_display_accurate_1): Reset window and buffer's
  `redisplay' flag.
  (redisplay_window): Do nothing if neither the window nor the buffer nor
  the frame needs redisplay.
  * src/window.h (struct window): Add `redisplay' field.
  (wset_redisplay, fset_redisplay, bset_redisplay, bset_update_mode_line)
  (redisplay_other_windows, window_list): New declarations.
  * src/window.c (select_window, Fset_window_start): Use wset_redisplay.
  (window_list): Not static any more.
  (grow_mini_window, shrink_mini_window): Use fset_redisplay.
  * src/minibuf.c (read_minibuf_unwind): Don't redisplay everything.
  * src/insdel.c (prepare_to_modify_buffer_1): Use bset_redisplay.
  * src/frame.c (Fmake_frame_visible): Don't redisplay everything.
  * src/frame.h (struct frame): Add `redisplay' field.
  Move `external_menu_bar' bitfield next to other bit-fields.
  (SET_FRAME_GARBAGED): Use fset_redisplay.
  (SET_FRAME_VISIBLE): Don't garbage the frame;
  Use redisplay_other_windows.
  * src/buffer.h (struct buffer): Add `redisplay' field.
  * src/buffer.c (Fforce_mode_line_update): Pay attention to the `all' flag.
  (modify_overlay): Use bset_redisplay.
  * src/alloc.c (gc_sweep): Don't unmark strings while sweeping symbols.
  
  * lisp/doc-view.el (doc-view-goto-page): Update mode-line.
modified:
  lisp/ChangeLog                 changelog-20091113204419-o5vbwnq5f7feedwu-1432
  lisp/doc-view.el               docview.el-20091113204419-o5vbwnq5f7feedwu-6334
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/alloc.c                    alloc.c-20091113204419-o5vbwnq5f7feedwu-252
  src/buffer.c                   buffer.c-20091113204419-o5vbwnq5f7feedwu-264
  src/buffer.h                   buffer.h-20091113204419-o5vbwnq5f7feedwu-196
  src/frame.c                    frame.c-20091113204419-o5vbwnq5f7feedwu-243
  src/frame.h                    frame.h-20091113204419-o5vbwnq5f7feedwu-229
  src/insdel.c                   insdel.c-20091113204419-o5vbwnq5f7feedwu-175
  src/minibuf.c                  minibuf.c-20091113204419-o5vbwnq5f7feedwu-242
  src/window.c                   window.c-20091113204419-o5vbwnq5f7feedwu-231
  src/window.h                   window.h-20091113204419-o5vbwnq5f7feedwu-271
  src/xdisp.c                    xdisp.c-20091113204419-o5vbwnq5f7feedwu-240
  src/xterm.c                    xterm.c-20091113204419-o5vbwnq5f7feedwu-244
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2013-11-28 01:49:25 +0000
+++ b/lisp/ChangeLog    2013-11-28 22:43:09 +0000
@@ -1,5 +1,7 @@
 2013-11-28  Stefan Monnier  <address@hidden>
 
+       * doc-view.el (doc-view-goto-page): Update mode-line.
+
        * vc/vc-dispatcher.el (vc-log-edit): Setup the Summary&Author headers.
 
 2013-11-27  Glenn Morris  <address@hidden>
@@ -531,8 +533,8 @@
        * progmodes/ruby-mode.el: Improve encoding comment handling.
        (ruby-encoding-magic-comment-style): New option.
        (ruby-custom-encoding-magic-comment-template): New option.
-       (ruby--insert-coding-comment, ruby--detect-encoding): New
-       functions extracted from `ruby-mode-set-encoding'.
+       (ruby--insert-coding-comment, ruby--detect-encoding):
+       New functions extracted from `ruby-mode-set-encoding'.
        (ruby-mode-set-encoding): Use `ruby-encoding-magic-comment-style'
        to control the style of the auto-inserted encoding comment.
 

=== modified file 'lisp/doc-view.el'
--- a/lisp/doc-view.el  2013-09-27 06:46:49 +0000
+++ b/lisp/doc-view.el  2013-11-28 22:43:09 +0000
@@ -499,6 +499,7 @@
                  ;; how many pages will be available.
                  (null doc-view--current-converter-processes))
        (setq page len)))
+    (force-mode-line-update)            ;To update `current-page'.
     (setf (doc-view-current-page) page
          (doc-view-current-info)
          (concat

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2013-11-28 19:40:15 +0000
+++ b/src/ChangeLog     2013-11-28 22:43:09 +0000
@@ -1,3 +1,46 @@
+2013-11-28  Stefan Monnier  <address@hidden>
+
+       Refine redisplay optimizations to only redisplay *some* frames/windows
+       rather than all of them.
+       * xdisp.c (REDISPLAY_SOME): New constant.
+       (redisplay_other_windows, wset_redisplay, fset_redisplay)
+       (bset_redisplay, bset_update_mode_line): New functions.
+       (message_dolog): Use bset_redisplay.
+       (clear_garbaged_frames): Use fset_redisplay.
+       (echo_area_display): Use wset_redisplay.
+       (buffer_shared_and_changed): Remove.
+       (prepare_menu_bars): Call Vpre_redisplay_function before updating
+       frame titles.  Compute the actual set of windows redisplayed.
+       Don't update frame titles and menu bars for frames that don't need to
+       be redisplayed.
+       (propagate_buffer_redisplay): New function.
+       (AINC): New macro.
+       (redisplay_internal): Use it.  Be more selective in the set of windows
+       we redisplay.  Propagate windows_or_buffers_changed to
+       update_mode_lines a bit later to simplify the code.
+       (mark_window_display_accurate_1): Reset window and buffer's
+       `redisplay' flag.
+       (redisplay_window): Do nothing if neither the window nor the buffer nor
+       the frame needs redisplay.
+       * window.h (struct window): Add `redisplay' field.
+       (wset_redisplay, fset_redisplay, bset_redisplay, bset_update_mode_line)
+       (redisplay_other_windows, window_list): New declarations.
+       * window.c (select_window, Fset_window_start): Use wset_redisplay.
+       (window_list): Not static any more.
+       (grow_mini_window, shrink_mini_window): Use fset_redisplay.
+       * minibuf.c (read_minibuf_unwind): Don't redisplay everything.
+       * insdel.c (prepare_to_modify_buffer_1): Use bset_redisplay.
+       * frame.c (Fmake_frame_visible): Don't redisplay everything.
+       * frame.h (struct frame): Add `redisplay' field.
+       Move `external_menu_bar' bitfield next to other bit-fields.
+       (SET_FRAME_GARBAGED): Use fset_redisplay.
+       (SET_FRAME_VISIBLE): Don't garbage the frame;
+       Use redisplay_other_windows.
+       * buffer.h (struct buffer): Add `redisplay' field.
+       * buffer.c (Fforce_mode_line_update): Pay attention to the `all' flag.
+       (modify_overlay): Use bset_redisplay.
+       * alloc.c (gc_sweep): Don't unmark strings while sweeping symbols.
+
 2013-11-28  Eli Zaretskii  <address@hidden>
 
        Support w32 file notifications in batch mode.
@@ -6,11 +49,9 @@
        handle_file_notifications to store file notification events in the
        input queue.  (Bug#15933)
 
-       * w32notify.c (send_notifications): Handle FRAME_INITIAL frames as
-       well.
+       * w32notify.c (send_notifications): Handle FRAME_INITIAL frames as well.
 
-       * w32inevt.c (handle_file_notifications): Now external, not
-       static.
+       * w32inevt.c (handle_file_notifications): Now external, not static.
 
        * w32term.h (handle_file_notifications): Provide prototype.
 
@@ -209,8 +250,8 @@
        * insdel.c (invalidate_buffer_caches): New function, consolidated
        from part of prepare_to_modify_buffer.
        (insert_from_gap, prepare_to_modify_buffer):
-       * coding.c (code_convert_region, code_convert_string): Call
-       invalidate_buffer_caches.  (Bug#15841)
+       * coding.c (code_convert_region, code_convert_string):
+       Call invalidate_buffer_caches.  (Bug#15841)
 
        * lisp.h (invalidate_buffer_caches): Add prototype.
 

=== modified file 'src/alloc.c'
--- a/src/alloc.c       2013-11-21 06:46:59 +0000
+++ b/src/alloc.c       2013-11-28 22:43:09 +0000
@@ -6291,7 +6291,7 @@
 
 
 
-/* Sweep: find all structures not marked, and free them. */
+/* Sweep: find all structures not marked, and free them.  */
 
 static void
 gc_sweep (void)
@@ -6303,7 +6303,7 @@
   sweep_strings ();
   check_string_bytes (!noninteractive);
 
-  /* Put all unmarked conses on free list */
+  /* Put all unmarked conses on free list.  */
   {
     register struct cons_block *cblk;
     struct cons_block **cprev = &cons_block;
@@ -6380,7 +6380,7 @@
     total_free_conses = num_free;
   }
 
-  /* Put all unmarked floats on free list */
+  /* Put all unmarked floats on free list.  */
   {
     register struct float_block *fblk;
     struct float_block **fprev = &float_block;
@@ -6426,7 +6426,7 @@
     total_free_floats = num_free;
   }
 
-  /* Put all unmarked intervals on free list */
+  /* Put all unmarked intervals on free list.  */
   {
     register struct interval_block *iblk;
     struct interval_block **iprev = &interval_block;
@@ -6475,7 +6475,7 @@
     total_free_intervals = num_free;
   }
 
-  /* Put all unmarked symbols on free list */
+  /* Put all unmarked symbols on free list.  */
   {
     register struct symbol_block *sblk;
     struct symbol_block **sprev = &symbol_block;
@@ -6512,7 +6512,7 @@
              {
                ++num_used;
                if (!pure_p)
-                 UNMARK_STRING (XSTRING (sym->s.name));
+                 eassert (!STRING_MARKED_P (XSTRING (sym->s.name)));
                sym->s.gcmarkbit = 0;
              }
          }

=== modified file 'src/buffer.c'
--- a/src/buffer.c      2013-11-12 01:24:04 +0000
+++ b/src/buffer.c      2013-11-28 22:43:09 +0000
@@ -1336,10 +1336,16 @@
 menu bar menus and the frame title.  */)
      (Lisp_Object all)
 {
-  if (!NILP (all) || buffer_window_count (current_buffer))
+  if (!NILP (all))
     {
       update_mode_lines = 10;
-      current_buffer->prevent_redisplay_optimizations_p = 1;
+      /* FIXME: This can't be right.  */
+      current_buffer->prevent_redisplay_optimizations_p = true;
+    }
+  else if (buffer_window_count (current_buffer))
+    {
+      bset_update_mode_line (current_buffer);
+      current_buffer->prevent_redisplay_optimizations_p = true;
     }
   return all;
 }
@@ -3895,17 +3901,7 @@
 
   BUF_COMPUTE_UNCHANGED (buf, start, end);
 
-  /* If BUF is visible, consider updating the display if ...  */
-  if (buffer_window_count (buf) > 0)
-    {
-      /* ... it's visible in other window than selected,  */
-      if (buf != XBUFFER (XWINDOW (selected_window)->contents))
-       windows_or_buffers_changed = 11;
-      /* ... or if we modify an overlay at the end of the buffer
-        and so we cannot be sure that window end is still valid.  */
-      else if (end >= ZV && start <= ZV)
-       windows_or_buffers_changed = 12;
-    }
+  bset_redisplay (buf);
 
   ++BUF_OVERLAY_MODIFF (buf);
 }

=== modified file 'src/buffer.h'
--- a/src/buffer.h      2013-11-17 07:51:24 +0000
+++ b/src/buffer.h      2013-11-28 22:43:09 +0000
@@ -475,7 +475,10 @@
     /* Usually 0.  Temporarily set to 1 in decode_coding_gap to
        prevent Fgarbage_collect from shrinking the gap and losing
        not-yet-decoded bytes.  */
-    bool inhibit_shrinking;
+    bool inhibit_shrinking : 1;
+
+    /* True if it needs to be redisplayed.  */
+    bool redisplay : 1;
   };
 
 /* Most code should use this macro to access Lisp fields in struct buffer.  */
@@ -846,10 +849,10 @@
 
   /* Non-zero means don't use redisplay optimizations for
      displaying this buffer.  */
-  unsigned prevent_redisplay_optimizations_p : 1;
+  bool prevent_redisplay_optimizations_p : 1;
 
   /* Non-zero whenever the narrowing is changed in this buffer.  */
-  unsigned clip_changed : 1;
+  bool clip_changed : 1;
 
   /* List of overlays that end at or before the current center,
      in order of end-position.  */

=== modified file 'src/frame.c'
--- a/src/frame.c       2013-11-25 02:41:02 +0000
+++ b/src/frame.c       2013-11-28 22:43:09 +0000
@@ -339,11 +339,12 @@
      non-Lisp data, so do it only for slots which should not be zero.
      To avoid subtle bugs and for the sake of readability, it's better to
      initialize enum members explicitly even if their values are zero.  */
-  f->wants_modeline = 1;
-  f->garbaged = 1;
+  f->wants_modeline = true;
+  f->redisplay = true;
+  f->garbaged = true;
   f->vertical_scroll_bar_type = vertical_scroll_bar_none;
-  f->column_width = 1;  /* !FRAME_WINDOW_P value */
-  f->line_height = 1;  /* !FRAME_WINDOW_P value */
+  f->column_width = 1;  /* !FRAME_WINDOW_P value.  */
+  f->line_height = 1;  /* !FRAME_WINDOW_P value.  */
 #ifdef HAVE_WINDOW_SYSTEM
   f->want_fullscreen = FULLSCREEN_NONE;
 #endif
@@ -785,9 +786,6 @@
   if (sf == XFRAME (frame))
     return frame;
 
-  /* This is too greedy; it causes inappropriate focus redirection
-     that's hard to get rid of.  */
-#if 0
   /* If a frame's focus has been redirected toward the currently
      selected frame, we should change the redirection to point to the
      newly selected frame.  This means that if the focus is redirected
@@ -795,6 +793,9 @@
      can use `other-window' to switch between all the frames using
      that minibuffer frame, and the focus redirection will follow us
      around.  */
+#if 0
+  /* This is too greedy; it causes inappropriate focus redirection
+     that's hard to get rid of.  */
   if (track)
     {
       Lisp_Object tail;
@@ -1681,7 +1682,7 @@
   make_frame_visible_1 (f->root_window);
 
   /* Make menu bar update for the Buffers and Frames menus.  */
-  windows_or_buffers_changed = 15;
+  /* windows_or_buffers_changed = 15; FIXME: Why?  */
 
   XSETFRAME (frame, f);
   return frame;

=== modified file 'src/frame.h'
--- a/src/frame.h       2013-10-08 17:49:20 +0000
+++ b/src/frame.h       2013-11-28 22:43:09 +0000
@@ -178,41 +178,44 @@
 
   /* 1 means that glyphs on this frame have been initialized so it can
      be used for output.  */
-  unsigned glyphs_initialized_p : 1;
+  bool glyphs_initialized_p : 1;
 
   /* Set to non-zero in change_frame_size when size of frame changed
      Clear the frame in clear_garbaged_frames if set.  */
-  unsigned resized_p : 1;
+  bool resized_p : 1;
 
   /* Set to non-zero if the default face for the frame has been
      realized.  Reset to zero whenever the default face changes.
      Used to see the difference between a font change and face change.  */
-  unsigned default_face_done_p : 1;
+  bool default_face_done_p : 1;
 
   /* Set to non-zero if this frame has already been hscrolled during
      current redisplay.  */
-  unsigned already_hscrolled_p : 1;
+  bool already_hscrolled_p : 1;
 
   /* Set to non-zero when current redisplay has updated frame.  */
-  unsigned updated_p : 1;
+  bool updated_p : 1;
 
 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
   /* Set to non-zero to minimize tool-bar height even when
      auto-resize-tool-bar is set to grow-only.  */
-  unsigned minimize_tool_bar_window_p : 1;
+  bool minimize_tool_bar_window_p : 1;
 #endif
 
 #if defined (USE_GTK) || defined (HAVE_NS)
   /* Nonzero means using a tool bar that comes from the toolkit.  */
-  unsigned external_tool_bar : 1;
+  bool external_tool_bar : 1;
 #endif
 
   /* Nonzero means that fonts have been loaded since the last glyph
      matrix adjustments.  */
-  unsigned fonts_changed : 1;
+  bool fonts_changed : 1;
 
   /* Nonzero means that cursor type has been changed.  */
-  unsigned cursor_type_changed : 1;
+  bool cursor_type_changed : 1;
+
+  /* True if it needs to be redisplayed.  */
+  bool redisplay : 1;
 
   /* Margin at the top of the frame.  Used to display the tool-bar.  */
   int tool_bar_lines;
@@ -220,17 +223,17 @@
   int n_tool_bar_rows;
   int n_tool_bar_items;
 
-  /* A buffer for decode_mode_line. */
+  /* A buffer for decode_mode_line.  */
   char *decode_mode_spec_buffer;
 
-  /* See do_line_insertion_deletion_costs for info on these arrays. */
-  /* Cost of inserting 1 line on this frame */
+  /* See do_line_insertion_deletion_costs for info on these arrays.  */
+  /* Cost of inserting 1 line on this frame.  */
   int *insert_line_cost;
-  /* Cost of deleting 1 line on this frame */
+  /* Cost of deleting 1 line on this frame.  */
   int *delete_line_cost;
-  /* Cost of inserting n lines on this frame */
+  /* Cost of inserting n lines on this frame.  */
   int *insert_n_lines_cost;
-  /* Cost of deleting n lines on this frame */
+  /* Cost of deleting n lines on this frame.  */
   int *delete_n_lines_cost;
 
   /* Size of this frame, excluding fringes, scroll bars etc.,
@@ -252,7 +255,7 @@
   int pixel_height, pixel_width;
 
   /* These many pixels are the difference between the outer window (i.e. the
-     left and top of the window manager decoration) and FRAME_X_WINDOW. */
+     left and top of the window manager decoration) and FRAME_X_WINDOW.  */
   int x_pixels_diff, y_pixels_diff;
 
   /* This is the gravity value for the specified window position.  */
@@ -281,23 +284,23 @@
   enum output_method output_method;
 
   /* The terminal device that this frame uses.  If this is NULL, then
-     the frame has been deleted. */
+     the frame has been deleted.  */
   struct terminal *terminal;
 
   /* Device-dependent, frame-local auxiliary data used for displaying
      the contents.  When the frame is deleted, this data is deleted as
-     well. */
+     well.  */
   union output_data
   {
-    struct tty_output *tty;     /* termchar.h */
-    struct x_output *x;         /* xterm.h */
-    struct w32_output *w32;     /* w32term.h */
-    struct ns_output *ns;       /* nsterm.h */
+    struct tty_output *tty;     /* From termchar.h.  */
+    struct x_output *x;         /* From xterm.h.  */
+    struct w32_output *w32;     /* From w32term.h.  */
+    struct ns_output *ns;       /* From nsterm.h.  */
     intptr_t nothing;
   }
   output_data;
 
-  /* List of font-drivers available on the frame. */
+  /* List of font-drivers available on the frame.  */
   struct font_driver_list *font_driver_list;
   /* List of data specific to font-driver and frame, but common to
      faces.  */
@@ -313,80 +316,76 @@
   /* The extra width (in pixels) currently allotted for fringes.  */
   int left_fringe_width, right_fringe_width;
 
-  /* See FULLSCREEN_ enum below */
+  /* See FULLSCREEN_ enum below.  */
   enum fullscreen_type want_fullscreen;
 
   /* Number of lines of menu bar.  */
   int menu_bar_lines;
 
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
-    || defined (HAVE_NS) || defined (USE_GTK)
-  /* Nonzero means using a menu bar that comes from the X toolkit.  */
-  unsigned int external_menu_bar : 1;
-#endif
-
 #if defined (HAVE_X_WINDOWS)
   /* Used by x_wait_for_event when watching for an X event on this frame.  */
   int wait_event_type;
 #endif
 
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
+    || defined (HAVE_NS) || defined (USE_GTK)
+  /* Nonzero means using a menu bar that comes from the X toolkit.  */
+  bool external_menu_bar : 1;
+#endif
+
   /* Next two bitfields are mutually exclusive.  They might both be
      zero if the frame has been made invisible without an icon.  */
 
   /* Nonzero if the frame is currently displayed; we check
      it to see if we should bother updating the frame's contents.
 
-     Note that, since invisible frames aren't updated, whenever a
-     frame becomes visible again, it must be marked as garbaged.
-
      On ttys and on Windows NT/9X, to avoid wasting effort updating
      visible frames that are actually completely obscured by other
      windows on the display, we bend the meaning of visible slightly:
      if equal to 2, then the frame is obscured - we still consider
      it to be "visible" as seen from lisp, but we don't bother
-     updating it.  We must take care to garbage the frame when it
-     ceases to be obscured though.  See SET_FRAME_VISIBLE below.  */
+     updating it.  */
   unsigned visible : 2;
 
   /* Nonzero if the frame is currently iconified.  Do not
      set this directly, use SET_FRAME_ICONIFIED instead.  */
-  unsigned iconified : 1;
+  bool iconified : 1;
 
   /* Nonzero if this frame should be redrawn.  */
-  unsigned garbaged : 1;
+  bool garbaged : 1;
 
   /* 0 means, if this frame has just one window,
      show no modeline for that window.  */
-  unsigned wants_modeline : 1;
+  bool wants_modeline : 1;
 
   /* Non-0 means raise this frame to the top of the heap when selected.  */
-  unsigned auto_raise : 1;
+  bool auto_raise : 1;
 
   /* Non-0 means lower this frame to the bottom of the stack when left.  */
-  unsigned auto_lower : 1;
+  bool auto_lower : 1;
 
   /* True if frame's root window can't be split.  */
-  unsigned no_split : 1;
+  bool no_split : 1;
 
   /* If this is set, then Emacs won't change the frame name to indicate
      the current buffer, etcetera.  If the user explicitly sets the frame
      name, this gets set.  If the user sets the name to Qnil, this is
      cleared.  */
-  unsigned explicit_name : 1;
+  bool explicit_name : 1;
 
   /* Nonzero if size of some window on this frame has changed.  */
-  unsigned window_sizes_changed : 1;
+  bool window_sizes_changed : 1;
 
   /* Nonzero if the mouse has moved on this display device
      since the last time we checked.  */
-  unsigned mouse_moved :1;
+  bool mouse_moved : 1;
 
-  /* Nonzero means that the pointer is invisible. */
-  unsigned pointer_invisible :1;
+  /* Nonzero means that the pointer is invisible.  */
+  bool pointer_invisible : 1;
 
   /* Nonzero means that all windows except mini-window and
      selected window on this frame have frozen window starts.  */
-  unsigned frozen_window_starts : 1;
+  bool frozen_window_starts : 1;
 
   /* Nonzero if we should actually display the scroll bars on this frame.  */
   enum vertical_scroll_bar_type vertical_scroll_bar_type;
@@ -720,7 +719,8 @@
 #define FRAME_ICONIFIED_P(f) (f)->iconified
 
 /* Mark frame F as currently garbaged.  */
-#define SET_FRAME_GARBAGED(f) (frame_garbaged = 1, f->garbaged = 1)
+#define SET_FRAME_GARBAGED(f)                          \
+  (frame_garbaged = true, fset_redisplay (f), f->garbaged = true)
 
 /* Nonzero if frame F is currently garbaged.  */
 #define FRAME_GARBAGED_P(f) (f)->garbaged
@@ -911,11 +911,14 @@
       }                                                                \
   } while (0)
 
-/* Set visibility of frame F, marking F as garbaged if needed.  */
+/* Set visibility of frame F.
+   We call redisplay_other_windows to make sure the frame gets redisplayed
+   if some changes were applied to it while it wasn't visible (and hence
+   wasn't redisplayed).  */
 
-#define SET_FRAME_VISIBLE(f, v)                                \
-  (((f)->visible == 0 || ((f)->visible == 2))          \
-   && ((v) == 1) ? SET_FRAME_GARBAGED (f) : 0,         \
+#define SET_FRAME_VISIBLE(f, v)                                        \
+  (((f)->visible == 0 || ((f)->visible == 2)) && ((v) == 1)    \
+   ? redisplay_other_windows () : 0,                           \
    (f)->visible = (eassert (0 <= (v) && (v) <= 2), (v)))
 
 /* Set iconify of frame F.  */

=== modified file 'src/insdel.c'
--- a/src/insdel.c      2013-11-18 16:29:49 +0000
+++ b/src/insdel.c      2013-11-28 22:43:09 +0000
@@ -1804,11 +1804,7 @@
   if (!NILP (BVAR (current_buffer, read_only)))
     Fbarf_if_buffer_read_only ();
 
-  /* If we're modifying the buffer other than shown in a selected window,
-     let redisplay consider other windows if this buffer is visible.  */
-  if (XBUFFER (XWINDOW (selected_window)->contents) != current_buffer
-      && buffer_window_count (current_buffer))
-    windows_or_buffers_changed = 20;
+  bset_redisplay (current_buffer);
 
   if (buffer_intervals (current_buffer))
     {

=== modified file 'src/minibuf.c'
--- a/src/minibuf.c     2013-11-15 06:52:40 +0000
+++ b/src/minibuf.c     2013-11-28 22:43:09 +0000
@@ -865,9 +865,6 @@
   if (minibuf_level == 0)
     resize_mini_window (XWINDOW (window), 0);
 
-  /* Enforce full redisplay.  FIXME: make it more selective.  */
-  windows_or_buffers_changed = 22;
-
   /* In case the previous minibuffer displayed in this miniwindow is
      dead, we may keep displaying this buffer (tho it's inactive), so reset it,
      to make sure we don't leave around bindings and stuff which only

=== modified file 'src/window.c'
--- a/src/window.c      2013-11-27 07:44:48 +0000
+++ b/src/window.c      2013-11-28 22:43:09 +0000
@@ -60,7 +60,6 @@
 static void window_scroll (Lisp_Object, EMACS_INT, bool, int);
 static void window_scroll_pixel_based (Lisp_Object, int, bool, int);
 static void window_scroll_line_based (Lisp_Object, int, bool, int);
-static Lisp_Object window_list (void);
 static int add_window_to_list (struct window *, void *);
 static Lisp_Object next_window (Lisp_Object, Lisp_Object,
                                 Lisp_Object, int);
@@ -482,6 +481,12 @@
        record_buffer before returning here.  */
     goto record_and_return;
 
+  if (NILP (norecord))
+    /* Mark the window for redisplay since the selected-window has a different
+       mode-line.  */
+    wset_redisplay (XWINDOW (selected_window));
+  else
+    redisplay_other_windows ();
   sf = SELECTED_FRAME ();
   if (XFRAME (WINDOW_FRAME (w)) != sf)
     {
@@ -500,7 +505,8 @@
 
   select_window_1 (window, inhibit_point_swap);
   bset_last_selected_window (XBUFFER (w->contents), window);
-  windows_or_buffers_changed = 24;
+  if (NILP (norecord))
+    wset_redisplay (w);
 
  record_and_return:
   /* record_buffer can run QUIT, so make sure it is run only after we have
@@ -1577,8 +1583,7 @@
   /* Bug#15957.  */
   w->window_end_valid = 0;
   if (w != XWINDOW (selected_window))
-    /* Enforce full redisplay.  FIXME: make it more selective.  */
-    windows_or_buffers_changed = 26;
+    wset_redisplay (w);
 
   return pos;
 }
@@ -2139,7 +2144,7 @@
    Vwindow_list is a list, return that list.  Otherwise, build a new
    list, cache it in Vwindow_list, and return that.  */
 
-static Lisp_Object
+Lisp_Object
 window_list (void)
 {
   if (!CONSP (Vwindow_list))
@@ -4138,8 +4143,9 @@
       /* Grow the mini-window.  */
       w->top_line = r->top_line + r->total_lines;
       w->total_lines -= XINT (value);
-      /* Enforce full redisplay.  FIXME: make it more selective.  */
-      windows_or_buffers_changed = 34;
+      /* Enforce full redisplay of the frame.  */
+      /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
+      fset_redisplay (f);
       adjust_frame_glyphs (f);
       unblock_input ();
     }
@@ -4172,8 +4178,9 @@
          /* Shrink the mini-window.  */
          w->top_line = r->top_line + r->total_lines;
          w->total_lines = 1;
-         /* Enforce full redisplay.  FIXME: make it more selective.  */
-         windows_or_buffers_changed = 35;
+         /* Enforce full redisplay of the frame.  */
+         /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
+         fset_redisplay (f);
          adjust_frame_glyphs (f);
          unblock_input ();
        }

=== modified file 'src/window.h'
--- a/src/window.h      2013-10-29 16:11:50 +0000
+++ b/src/window.h      2013-11-28 22:43:09 +0000
@@ -282,60 +282,63 @@
     int window_end_vpos;
 
     /* Non-zero if this window is a minibuffer window.  */
-    unsigned mini : 1;
+    bool mini : 1;
 
     /* Meaningful only if contents is a window, non-zero if this
        internal window is used in horizontal combination.  */
-    unsigned horizontal : 1;
+    bool horizontal : 1;
 
     /* Non-zero means must regenerate mode line of this window.  */
-    unsigned update_mode_line : 1;
+    bool update_mode_line : 1;
 
     /* Non-nil if the buffer was "modified" when the window
        was last updated.  */
-    unsigned last_had_star : 1;
+    bool last_had_star : 1;
 
     /* Non-zero means current value of `start'
        was the beginning of a line when it was chosen.  */
-    unsigned start_at_line_beg : 1;
+    bool start_at_line_beg : 1;
 
     /* Non-zero means next redisplay must use the value of start
        set up for it in advance.  Set by scrolling commands.  */
-    unsigned force_start : 1;
+    bool force_start : 1;
 
     /* Non-zero means we have explicitly changed the value of start,
        but that the next redisplay is not obliged to use the new value.
        This is used in Fdelete_other_windows to force a call to
        Vwindow_scroll_functions; also by Frecenter with argument.  */
-    unsigned optional_new_start : 1;
+    bool optional_new_start : 1;
 
     /* Non-zero means the cursor is currently displayed.  This can be
        set to zero by functions overpainting the cursor image.  */
-    unsigned phys_cursor_on_p : 1;
+    bool phys_cursor_on_p : 1;
 
     /* 0 means cursor is logically on, 1 means it's off.  Used for
        blinking cursor.  */
-    unsigned cursor_off_p : 1;
+    bool cursor_off_p : 1;
 
     /* Value of cursor_off_p as of the last redisplay.  */
-    unsigned last_cursor_off_p : 1;
+    bool last_cursor_off_p : 1;
 
     /* 1 means desired matrix has been build and window must be
        updated in update_frame.  */
-    unsigned must_be_updated_p : 1;
+    bool must_be_updated_p : 1;
 
     /* Flag indicating that this window is not a real one.
        Currently only used for menu bar windows of frames.  */
-    unsigned pseudo_window_p : 1;
+    bool pseudo_window_p : 1;
 
     /* Non-zero means fringes are drawn outside display margins.
        Otherwise draw them between margin areas and text.  */
-    unsigned fringes_outside_margins : 1;
+    bool fringes_outside_margins : 1;
 
     /* Nonzero if window_end_pos and window_end_vpos are truly valid.
        This is zero if nontrivial redisplay is preempted since in that case
        the frame image that window_end_pos did not get onto the frame.  */
-    unsigned window_end_valid : 1;
+    bool window_end_valid : 1;
+
+    /* True if it needs to be redisplayed.  */
+    bool redisplay : 1;
 
     /* Amount by which lines of this window are scrolled in
        y-direction (smooth scrolling).  */
@@ -900,15 +903,32 @@
 
 extern EMACS_INT minibuf_level;
 
-/* true if we should redraw the mode lines on the next redisplay.  */
+/* Non-zero if we should redraw the mode lines on the next redisplay.
+   Usually set to a unique small integer so we can track the main causes of
+   full redisplays in `redisplay--mode-lines-cause'.  */
 
 extern int update_mode_lines;
 
 /* Nonzero if window sizes or contents have changed since last
-   redisplay that finished.  */
+   redisplay that finished.  Usually set to a unique small integer so
+   we can track the main causes of full redisplays in
+   `redisplay--all-windows-cause'.  */
 
 extern int windows_or_buffers_changed;
 
+/* The main redisplay routine usually only redisplays the selected-window,
+   so when something's changed elsewhere, we call one of the functions below
+   to indicate which other windows might also need to be redisplayed.  */
+
+extern void wset_redisplay (struct window *w);
+extern void fset_redisplay (struct frame *f);
+extern void bset_redisplay (struct buffer *b);
+extern void bset_update_mode_line (struct buffer *b);
+/* Call this to tell redisplay to look for other windows than selected-window
+   that need to be redisplayed.  Calling one of the *set_redisplay functions
+   above already does it, so it's only needed in unusual cases.  */
+extern void redisplay_other_windows (void);
+
 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
    minimum allowable size.  */
 
@@ -942,6 +962,7 @@
 extern Lisp_Object Qwindow_live_p;
 extern Lisp_Object Vwindow_list;
 
+extern Lisp_Object window_list (void);
 extern struct window *decode_live_window (Lisp_Object);
 extern struct window *decode_any_window (Lisp_Object);
 extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool);

=== modified file 'src/xdisp.c'
--- a/src/xdisp.c       2013-11-14 17:43:49 +0000
+++ b/src/xdisp.c       2013-11-28 22:43:09 +0000
@@ -502,12 +502,20 @@
 
 static bool message_enable_multibyte;
 
-/* Nonzero if we should redraw the mode lines on the next redisplay.  */
+/* Nonzero if we should redraw the mode lines on the next redisplay.
+   If it has value REDISPLAY_SOME, then only redisplay the mode lines where
+   the `redisplay' bit has been set.  Otherwise, redisplay all mode lines
+   (the number used is then only used to track down the cause for this
+   full-redisplay).  */
 
 int update_mode_lines;
 
-/* Nonzero if window sizes or contents have changed since last
-   redisplay that finished.  */
+/* Nonzero if window sizes or contents other than selected-window have changed
+   since last redisplay that finished.
+   If it has value REDISPLAY_SOME, then only redisplay the windows where
+   the `redisplay' bit has been set.  Otherwise, redisplay all windows
+   (the number used is then only used to track down the cause for this
+   full-redisplay).  */
 
 int windows_or_buffers_changed;
 
@@ -599,6 +607,49 @@
     CACHE = NULL;                              \
   } while (0)
 
+/* Functions to mark elements as needing redisplay.  */
+enum { REDISPLAY_SOME = 2};    /* Arbitrary choice.  */
+
+void redisplay_other_windows (void)
+{
+  if (!windows_or_buffers_changed)
+    windows_or_buffers_changed = REDISPLAY_SOME;
+}
+
+void wset_redisplay (struct window *w)
+{
+  redisplay_other_windows ();
+  w->redisplay = true;
+}
+
+void fset_redisplay (struct frame *f)
+{
+  redisplay_other_windows ();
+  f->redisplay = true;
+}
+
+void bset_redisplay (struct buffer *b)
+{
+  int count = buffer_window_count (b);
+  if (count > 0)
+    {
+      /* ... it's visible in other window than selected,  */
+      if (count > 1 || b != XBUFFER (XWINDOW (selected_window)->contents))
+       redisplay_other_windows ();
+      /* Even if we don't set windows_or_buffers_changed, do set `redisplay'
+        so that if we later set windows_or_buffers_changed, this buffer will
+        not be omitted.  */
+      b->text->redisplay = true;
+    }
+}
+
+extern void bset_update_mode_line (struct buffer *b)
+{
+  if (!update_mode_lines)
+    update_mode_lines = REDISPLAY_SOME;
+  b->text->redisplay = true;
+}
+
 #ifdef GLYPH_DEBUG
 
 /* Non-zero means print traces of redisplay if compiled with
@@ -9468,7 +9519,6 @@
       ptrdiff_t point_at_end = 0;
       ptrdiff_t zv_at_end = 0;
       Lisp_Object old_deactivate_mark;
-      bool shown;
       struct gcpro gcpro1;
 
       old_deactivate_mark = Vdeactivate_mark;
@@ -9482,8 +9532,8 @@
 
         Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
 
-        if (newbuffer &&
-            !NILP (Ffboundp (intern ("messages-buffer-mode"))))
+        if (newbuffer
+           && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
           call0 (intern ("messages-buffer-mode"));
       }
 
@@ -9625,18 +9675,17 @@
       unchain_marker (XMARKER (oldbegv));
       unchain_marker (XMARKER (oldzv));
 
-      shown = buffer_window_count (current_buffer) > 0;
-      set_buffer_internal (oldbuf);
       /* We called insert_1_both above with its 5th argument (PREPARE)
         zero, which prevents insert_1_both from calling
         prepare_to_modify_buffer, which in turns prevents us from
         incrementing windows_or_buffers_changed even if *Messages* is
-        shown in some window.  So we must manually incrementing
+        shown in some window.  So we must manually set
         windows_or_buffers_changed here to make up for that.  */
-      if (shown)
-       windows_or_buffers_changed = 41;
-      else
        windows_or_buffers_changed = old_windows_or_buffers_changed;
+      bset_redisplay (current_buffer);
+
+      set_buffer_internal (oldbuf);
+
       message_log_need_newline = !nlflag;
       Vdeactivate_mark = old_deactivate_mark;
     }
@@ -10325,15 +10374,8 @@
       && WINDOWP (echo_area_window))
     {
       struct window *w = XWINDOW (echo_area_window);
-      int resized_p;
-      Lisp_Object resize_exactly;
-
-      if (minibuf_level == 0)
-       resize_exactly = Qt;
-      else
-       resize_exactly = Qnil;
-
-      resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
+      Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
+      int resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
                                         (intptr_t) w, resize_exactly);
       if (resized_p)
        {
@@ -10714,7 +10756,6 @@
   if (frame_garbaged)
     {
       Lisp_Object tail, frame;
-      int changed_count = 0;
 
       FOR_EACH_FRAME (tail, frame)
        {
@@ -10726,15 +10767,13 @@
                redraw_frame (f);
              else
                clear_current_matrices (f);
-             changed_count++;
-             f->garbaged = 0;
-             f->resized_p = 0;
+             fset_redisplay (f);
+             f->garbaged = false;
+             f->resized_p = false;
            }
        }
 
-      frame_garbaged = 0;
-      if (changed_count)
-       windows_or_buffers_changed = 43;
+      frame_garbaged = false;
     }
 }
 
@@ -10822,11 +10861,11 @@
             redisplay displays the minibuffer, so that the cursor will
             be replaced with what the minibuffer wants.  */
          if (cursor_in_echo_area)
-           windows_or_buffers_changed = 45;
+           wset_redisplay (XWINDOW (mini_window));
        }
     }
   else if (!EQ (mini_window, selected_window))
-    windows_or_buffers_changed = 46;
+    wset_redisplay (XWINDOW (mini_window));
 
   /* Last displayed message is now the current message.  */
   echo_area_buffer[1] = echo_area_buffer[0];
@@ -10842,16 +10881,6 @@
   return window_height_changed_p;
 }
 
-/* Nonzero if the current window's buffer is shown in more than one
-   window and was modified since last redisplay.  */
-
-static int
-buffer_shared_and_changed (void)
-{
-  return (buffer_window_count (current_buffer) > 1
-         && UNCHANGED_MODIFIED < MODIFF);
-}
-
 /* Nonzero if W's buffer was changed but not saved.  */
 
 static int
@@ -11171,9 +11200,13 @@
 static void
 prepare_menu_bars (void)
 {
-  int all_windows;
+  bool all_windows = windows_or_buffers_changed || update_mode_lines;
+  bool some_windows
+    = (windows_or_buffers_changed == 0
+       || windows_or_buffers_changed == REDISPLAY_SOME)
+    && (update_mode_lines == 0
+       || update_mode_lines == REDISPLAY_SOME);
   struct gcpro gcpro1, gcpro2;
-  struct frame *f;
   Lisp_Object tooltip_frame;
 
 #ifdef HAVE_WINDOW_SYSTEM
@@ -11182,17 +11215,45 @@
   tooltip_frame = Qnil;
 #endif
 
+  if (FUNCTIONP (Vpre_redisplay_function))
+    {
+      Lisp_Object windows = all_windows ? Qt : Qnil;
+      if (all_windows && some_windows)
+       {
+         Lisp_Object ws = window_list ();
+         for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
+           {
+             Lisp_Object this = XCAR (ws);
+             struct window *w = XWINDOW (this);
+             if (w->redisplay
+                 || XFRAME (w->frame)->redisplay
+                 || XBUFFER (w->contents)->text->redisplay)
+               {
+                 windows = Fcons (this, windows);
+               }
+           }
+       }
+      safe_call1 (Vpre_redisplay_function, windows);
+    }
+
   /* Update all frame titles based on their buffer names, etc.  We do
      this before the menu bars so that the buffer-menu will show the
      up-to-date frame titles.  */
 #ifdef HAVE_WINDOW_SYSTEM
-  if (windows_or_buffers_changed || update_mode_lines)
+  if (all_windows)
     {
       Lisp_Object tail, frame;
 
       FOR_EACH_FRAME (tail, frame)
        {
-         f = XFRAME (frame);
+         struct frame *f = XFRAME (frame);
+         struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+         if (some_windows
+             && !f->redisplay
+             && !w->redisplay
+             && !XBUFFER (w->contents)->text->redisplay)
+           continue;
+
          if (!EQ (frame, tooltip_frame)
              && (FRAME_ICONIFIED_P (f)
                  || FRAME_VISIBLE_P (f) == 1
@@ -11213,12 +11274,6 @@
 
   /* Update the menu bar item lists, if appropriate.  This has to be
      done before any actual redisplay or generation of display lines.  */
-  all_windows = (update_mode_lines
-                || buffer_shared_and_changed ()
-                || windows_or_buffers_changed);
-
-  if (FUNCTIONP (Vpre_redisplay_function))
-    safe_call1 (Vpre_redisplay_function, all_windows ? Qt : Qnil);
 
   if (all_windows)
     {
@@ -11232,12 +11287,19 @@
 
       FOR_EACH_FRAME (tail, frame)
        {
-         f = XFRAME (frame);
+         struct frame *f = XFRAME (frame);
+         struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
 
          /* Ignore tooltip frame.  */
          if (EQ (frame, tooltip_frame))
            continue;
 
+         if (some_windows
+             && !f->redisplay
+             && !w->redisplay
+             && !XBUFFER (w->contents)->text->redisplay)
+           continue;
+
          /* If a window on this frame changed size, report that to
             the user and clear the size-change flag.  */
          if (FRAME_WINDOW_SIZES_CHANGED (f))
@@ -12860,6 +12922,27 @@
     }
 }
 
+void propagate_buffer_redisplay (void)
+{ /* Resetting b->text->redisplay is problematic!
+     We can't just reset it in the case that some window that displays
+     it has not been redisplayed; and such a window can stay
+     unredisplayed for a long time if it's currently invisible.
+     But we do want to reset it at the end of redisplay otherwise
+     its displayed windows will keep being redisplayed over and over
+     again.
+     So we copy all b->text->redisplay flags up to their windows here,
+     such that mark_window_display_accurate can safely reset
+     b->text->redisplay.  */
+  Lisp_Object ws = window_list ();
+  for (; CONSP (ws); ws = XCDR (ws))
+    {
+      struct window *thisw = XWINDOW (XCAR (ws));
+      struct buffer *thisb = XBUFFER (thisw->contents);
+      if (thisb->text->redisplay)
+       thisw->redisplay = true;
+    }
+}
+
 #define STOP_POLLING                                   \
 do { if (! polling_stopped_here) stop_polling ();      \
        polling_stopped_here = 1; } while (0)
@@ -12956,7 +13039,6 @@
       /* Since frames on a single ASCII terminal share the same
         display area, displaying a different frame means redisplay
         the whole thing.  */
-      windows_or_buffers_changed = 48;
       SET_FRAME_GARBAGED (sf);
 #ifndef DOS_NT
       set_tty_color_mode (FRAME_TTY (sf), sf);
@@ -13005,9 +13087,6 @@
   if (NILP (Vmemory_full))
     prepare_menu_bars ();
 
-  if (windows_or_buffers_changed && !update_mode_lines)
-    update_mode_lines = 32;
-
   reconsider_clip_changes (w);
 
   /* In most cases selected window displays current buffer.  */
@@ -13016,27 +13095,12 @@
     {
       /* Detect case that we need to write or remove a star in the mode line.  
*/
       if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
-       {
          w->update_mode_line = 1;
-         if (buffer_shared_and_changed ())
-           update_mode_lines = 33;
-       }
 
       if (mode_line_update_needed (w))
        w->update_mode_line = 1;
     }
 
-  consider_all_windows_p = (update_mode_lines
-                           || buffer_shared_and_changed ());
-
-  /* If specs for an arrow have changed, do thorough redisplay
-     to ensure we remove any arrow that should no longer exist.  */
-  if (overlay_arrows_changed_p ())
-    {
-      consider_all_windows_p = true;
-      windows_or_buffers_changed = 49;
-    }
-
   /* Normally the message* functions will have already displayed and
      updated the echo area, but the frame may have been trashed, or
      the update may have been preempted, so display the echo area
@@ -13066,8 +13130,6 @@
 
       if (window_height_changed_p)
        {
-         consider_all_windows_p = true;
-         update_mode_lines = 34;
          windows_or_buffers_changed = 50;
 
          /* If window configuration was changed, frames may have been
@@ -13083,13 +13145,6 @@
       /* Resized active mini-window to fit the size of what it is
          showing if its contents might have changed.  */
       must_finish = 1;
-      /* FIXME: this causes all frames to be updated, which seems unnecessary
-        since only the current frame needs to be considered.  This function
-        needs to be rewritten with two variables, consider_all_windows and
-        consider_all_frames.  */
-      consider_all_windows_p = true;
-      windows_or_buffers_changed = 51;
-      update_mode_lines = 35;
 
       /* If window configuration was changed, frames may have been
         marked garbaged.  Clear them or we will experience
@@ -13097,23 +13152,29 @@
       clear_garbaged_frames ();
     }
 
-  if (VECTORP (Vredisplay__all_windows_cause)
-      && windows_or_buffers_changed >= 0
-      && windows_or_buffers_changed < ASIZE (Vredisplay__all_windows_cause)
-      && INTEGERP (AREF (Vredisplay__all_windows_cause,
-                        windows_or_buffers_changed)))
-    ASET (Vredisplay__all_windows_cause, windows_or_buffers_changed,
-         make_number (1 + XINT (AREF (Vredisplay__all_windows_cause,
-                                      windows_or_buffers_changed))));
-
-  if (VECTORP (Vredisplay__mode_lines_cause)
-      && update_mode_lines >= 0
-      && update_mode_lines < ASIZE (Vredisplay__mode_lines_cause)
-      && INTEGERP (AREF (Vredisplay__mode_lines_cause,
-                        update_mode_lines)))
-    ASET (Vredisplay__mode_lines_cause, update_mode_lines,
-         make_number (1 + XINT (AREF (Vredisplay__mode_lines_cause,
-                                      update_mode_lines))));
+  if (windows_or_buffers_changed && !update_mode_lines)
+    /* Code that sets windows_or_buffers_changed doesn't distinguish whether
+       only the windows's contents needs to be refreshed, or whether the
+       mode-lines also need a refresh.  */
+    update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
+                        ? REDISPLAY_SOME : 32);
+
+  /* If specs for an arrow have changed, do thorough redisplay
+     to ensure we remove any arrow that should no longer exist.  */
+  if (overlay_arrows_changed_p ())
+    /* Apparently, this is the only case where we update other windows,
+       without updating other mode-lines.  */
+    windows_or_buffers_changed = 49;
+
+  consider_all_windows_p = (update_mode_lines
+                           || windows_or_buffers_changed);
+
+#define AINC(a,i) \
+  if (VECTORP (a) && i >= 0 && i < ASIZE (a) && INTEGERP (AREF (a, i))) \
+    ASET (a, i, make_number (1 + XINT (AREF (a, i))))
+
+  AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
+  AINC (Vredisplay__mode_lines_cause, update_mode_lines);
 
   /* Optimize the case that only the line containing the cursor in the
      selected window has changed.  Variables starting with this_ are
@@ -13330,6 +13391,8 @@
       FOR_EACH_FRAME (tail, frame)
        XFRAME (frame)->updated_p = 0;
 
+      propagate_buffer_redisplay ();
+
       FOR_EACH_FRAME (tail, frame)
        {
          struct frame *f = XFRAME (frame);
@@ -13344,9 +13407,12 @@
 
          if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
            {
+             bool gcscrollbars
+               /* Only GC scollbars when we redisplay the whole frame.  */
+               = f->redisplay || windows_or_buffers_changed != REDISPLAY_SOME;
              /* Mark all the scroll bars to be removed; we'll redeem
                 the ones we want when we redisplay their windows.  */
-             if (FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
+             if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
                FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
 
              if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
@@ -13358,7 +13424,7 @@
 
              /* Any scroll bars which redisplay_windows should have
                 nuked should now go away.  */
-             if (FRAME_TERMINAL (f)->judge_scroll_bars_hook)
+             if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
                FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
 
              if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
@@ -13413,6 +13479,7 @@
              struct frame *f = XFRAME (frame);
               if (f->updated_p)
                 {
+                 f->redisplay = false;
                   mark_window_display_accurate (f->root_window, 1);
                   if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
                     FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
@@ -13502,6 +13569,11 @@
        {
          /* This has already been done above if
             consider_all_windows_p is set.  */
+         if (XBUFFER (w->contents)->text->redisplay
+             && buffer_window_count (XBUFFER (w->contents)) > 1)
+           /* This can happen if b->text->redisplay was set during
+              jit-lock.  */
+           propagate_buffer_redisplay ();
          mark_window_display_accurate_1 (w, 1);
 
          /* Say overlay arrows are up to date.  */
@@ -13535,12 +13607,7 @@
 
       FOR_EACH_FRAME (tail, frame)
        {
-         int this_is_visible = 0;
-
          if (XFRAME (frame)->visible)
-           this_is_visible = 1;
-
-         if (this_is_visible)
            new_count++;
        }
 
@@ -13639,8 +13706,13 @@
 
   if (accurate_p)
     {
-      b->clip_changed = 0;
-      b->prevent_redisplay_optimizations_p = 0;
+      b->clip_changed = false;
+      b->prevent_redisplay_optimizations_p = false;
+      eassert (buffer_window_count (b) > 0);
+      /* Resetting b->text->redisplay is problematic!
+        In order to make it safer to do it here, redisplay_internal must
+        have copied all b->text->redisplay to their respective windows.  */
+      b->text->redisplay = false;
 
       BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
       BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
@@ -13659,9 +13731,11 @@
       else
        w->last_point = marker_position (w->pointm);
 
-      w->window_end_valid = 1;
-      w->update_mode_line = 0;
+      w->window_end_valid = true;
+      w->update_mode_line = false;
     }
+
+  w->redisplay = !accurate_p;
 }
 
 
@@ -14314,9 +14388,9 @@
      occlude point.  Only set w->cursor if we found a better
      approximation to the cursor position than we have from previously
      examined candidate rows belonging to the same continued line.  */
-  if (/* we already have a candidate row */
+  if (/* We already have a candidate row.  */
       w->cursor.vpos >= 0
-      /* that candidate is not the row we are processing */
+      /* That candidate is not the row we are processing.  */
       && MATRIX_ROW (matrix, w->cursor.vpos) != row
       /* Make sure cursor.vpos specifies a row whose start and end
         charpos occlude point, and it is valid candidate for being a
@@ -14327,30 +14401,30 @@
       && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
       && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
     {
-      struct glyph *g1 =
-       MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
+      struct glyph *g1
+       = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
 
       /* Don't consider glyphs that are outside TEXT_AREA.  */
       if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
        return 0;
       /* Keep the candidate whose buffer position is the closest to
         point or has the `cursor' property.  */
-      if (/* previous candidate is a glyph in TEXT_AREA of that row */
+      if (/* Previous candidate is a glyph in TEXT_AREA of that row.  */
          w->cursor.hpos >= 0
          && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
          && ((BUFFERP (g1->object)
-              && (g1->charpos == pt_old /* an exact match always wins */
+              && (g1->charpos == pt_old /* An exact match always wins.  */
                   || (BUFFERP (glyph->object)
                       && eabs (g1->charpos - pt_old)
                       < eabs (glyph->charpos - pt_old))))
-             /* previous candidate is a glyph from a string that has
-                a non-nil `cursor' property */
+             /* Previous candidate is a glyph from a string that has
+                a non-nil `cursor' property.  */
              || (STRINGP (g1->object)
                  && (!NILP (Fget_char_property (make_number (g1->charpos),
                                                Qcursor, g1->object))
-                     /* previous candidate is from the same display
+                     /* Previous candidate is from the same display
                         string as this one, and the display string
-                        came from a text property */
+                        came from a text property.  */
                      || (EQ (g1->object, glyph->object)
                          && string_from_text_prop)
                      /* this candidate is from newline and its
@@ -15329,6 +15403,16 @@
   *w->desired_matrix->method = 0;
 #endif
 
+  if (!just_this_one_p
+      && (update_mode_lines == REDISPLAY_SOME
+         || update_mode_lines == 0)
+      && (windows_or_buffers_changed == REDISPLAY_SOME
+         || windows_or_buffers_changed == 0)
+      && !w->redisplay
+      && !f->redisplay
+      && !buffer->text->redisplay)
+    return;
+
   /* Make sure that both W's markers are valid.  */
   eassert (XMARKER (w->start)->buffer == buffer);
   eassert (XMARKER (w->pointm)->buffer == buffer);

=== modified file 'src/xterm.c'
--- a/src/xterm.c       2013-11-24 18:28:33 +0000
+++ b/src/xterm.c       2013-11-28 22:43:09 +0000
@@ -6202,7 +6202,7 @@
             SET_FRAME_GARBAGED (f);
 
           /* Check if fullscreen was specified before we where mapped the
-             first time, i.e. from the command line. */
+             first time, i.e. from the command line.  */
           if (!f->output_data.x->has_been_visible)
             x_check_fullscreen (f);
 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]