XEmacs 21.4.5 "Civil Service".
[chise/xemacs-chise.git.1] / src / redisplay.c
index fa8e5e7..dc7048e 100644 (file)
@@ -40,7 +40,6 @@ Boston, MA 02111-1307, USA.  */
 
 #include <config.h>
 #include "lisp.h"
 
 #include <config.h>
 #include "lisp.h"
-#include <limits.h>
 
 #include "buffer.h"
 #include "commands.h"
 
 #include "buffer.h"
 #include "commands.h"
@@ -64,11 +63,10 @@ Boston, MA 02111-1307, USA.  */
 #include "file-coding.h"
 #endif
 
 #include "file-coding.h"
 #endif
 
+#include "sysfile.h"
+
 #ifdef HAVE_TTY
 #include "console-tty.h"
 #ifdef HAVE_TTY
 #include "console-tty.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> /* for isatty() */
-#endif
 #endif /* HAVE_TTY */
 
 /* Note: We have to be careful throughout this code to properly handle
 #endif /* HAVE_TTY */
 
 /* Note: We have to be careful throughout this code to properly handle
@@ -87,16 +85,10 @@ Boston, MA 02111-1307, USA.  */
 #define LEFT_GLYPHS    2
 #define RIGHT_GLYPHS   3
 
 #define LEFT_GLYPHS    2
 #define RIGHT_GLYPHS   3
 
-/* Set the vertical clip to 0 if we are currently updating the line
-   start cache.  Otherwise for buffers of line height 1 it may fail to
-   be able to work properly because regenerate_window will not layout
-   a single line.  */
 #define VERTICAL_CLIP(w, display)                                      \
 #define VERTICAL_CLIP(w, display)                                      \
-  (updating_line_start_cache                                           \
-   ? 0                                                                 \
-   : ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines))       \
+    ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines))                \
       ? INT_MAX                                                                \
       ? INT_MAX                                                                \
-      : vertical_clip))
+      : vertical_clip)
 
 /* The following structures are completely private to redisplay.c so
    we put them here instead of in a header file, for modularity. */
 
 /* The following structures are completely private to redisplay.c so
    we put them here instead of in a header file, for modularity. */
@@ -308,7 +300,7 @@ static Bytecount_dynarr *formatted_string_extent_end_dynarr;
 
 
 /* #### probably temporary */
 
 
 /* #### probably temporary */
-int cache_adjustment;
+Fixnum cache_adjustment;
 
 /* This holds a string representing the text corresponding to a single
    modeline % spec. */
 
 /* This holds a string representing the text corresponding to a single
    modeline % spec. */
@@ -323,13 +315,10 @@ int disable_preemption;   /* Used for debugging redisplay and for
 static int preemption_count;
 
 /* Minimum pixel height of clipped bottom display line. */
 static int preemption_count;
 
 /* Minimum pixel height of clipped bottom display line. */
-int vertical_clip;
+Fixnum vertical_clip;
 
 /* Minimum visible pixel width of clipped glyphs at right margin. */
 
 /* Minimum visible pixel width of clipped glyphs at right margin. */
-int horizontal_clip;
-
-/* Set if currently inside update_line_start_cache. */
-static int updating_line_start_cache;
+Fixnum horizontal_clip;
 
 /* Nonzero means reading single-character input with prompt
    so put cursor on minibuffer after the prompt.  */
 
 /* Nonzero means reading single-character input with prompt
    so put cursor on minibuffer after the prompt.  */
@@ -364,8 +353,7 @@ int frame_changed;
 int glyphs_changed;
 int glyphs_changed_set;
 
 int glyphs_changed;
 int glyphs_changed_set;
 
-/* non-zero if any displayed subwindow is in need of updating
-   somewhere. */
+/* non-zero if any subwindow has been deleted. */
 int subwindows_changed;
 int subwindows_changed_set;
 
 int subwindows_changed;
 int subwindows_changed_set;
 
@@ -419,9 +407,9 @@ int windows_structure_changed;
 Lisp_Object Vbar_cursor;
 Lisp_Object Qbar_cursor;
 
 Lisp_Object Vbar_cursor;
 Lisp_Object Qbar_cursor;
 
-int visible_bell;      /* If true and the terminal will support it
-                          then the frame will flash instead of
-                          beeping when an error occurs */
+Lisp_Object Vvisible_bell;     /* If true and the terminal will support it
+                                  then the frame will flash instead of
+                                  beeping when an error occurs */
 
 /* Nonzero means no need to redraw the entire frame on resuming
    a suspended Emacs.  This is useful on terminals with multiple pages,
 
 /* Nonzero means no need to redraw the entire frame on resuming
    a suspended Emacs.  This is useful on terminals with multiple pages,
@@ -437,10 +425,10 @@ Lisp_Object Vglobal_mode_string;
 
 /* The number of lines scroll a window by when point leaves the window; if
   it is <=0 then point is centered in the window */
 
 /* The number of lines scroll a window by when point leaves the window; if
   it is <=0 then point is centered in the window */
-int scroll_step;
+Fixnum scroll_step;
 
 /* Scroll up to this many lines, to bring point back on screen. */
 
 /* Scroll up to this many lines, to bring point back on screen. */
-int scroll_conservatively;
+Fixnum scroll_conservatively;
 
 /* Marker for where to display an arrow on top of the buffer text.  */
 Lisp_Object Voverlay_arrow_position;
 
 /* Marker for where to display an arrow on top of the buffer text.  */
 Lisp_Object Voverlay_arrow_position;
@@ -451,6 +439,9 @@ Lisp_Object Vwindow_size_change_functions;
 Lisp_Object Vwindow_scroll_functions;
 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
 
 Lisp_Object Vwindow_scroll_functions;
 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
 
+Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook;
+
+
 #define INHIBIT_REDISPLAY_HOOKS  /* #### Until we've thought about
                                    this more. */
 #ifndef INHIBIT_REDISPLAY_HOOKS
 #define INHIBIT_REDISPLAY_HOOKS  /* #### Until we've thought about
                                    this more. */
 #ifndef INHIBIT_REDISPLAY_HOOKS
@@ -460,7 +451,8 @@ Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
 #endif /* INHIBIT_REDISPLAY_HOOKS */
 
 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
 #endif /* INHIBIT_REDISPLAY_HOOKS */
 
-static int last_display_warning_tick, display_warning_tick;
+static Fixnum last_display_warning_tick;
+static Fixnum display_warning_tick;
 Lisp_Object Qdisplay_warning_buffer;
 int inhibit_warning_display;
 
 Lisp_Object Qdisplay_warning_buffer;
 int inhibit_warning_display;
 
@@ -471,8 +463,9 @@ Lisp_Object Vtext_cursor_visible_p;
 
 int column_number_start_at_one;
 
 
 int column_number_start_at_one;
 
-#define WINDOW_SCROLLED(w) \
-(w->hscroll > 0 || w->left_xoffset)
+Lisp_Object Qtop_bottom;
+
+#define WINDOW_SCROLLED(w) ((w)->hscroll > 0 || (w)->left_xoffset)
 
 \f
 /***************************************************************************/
 
 \f
 /***************************************************************************/
@@ -803,7 +796,7 @@ add_hscroll_rune (pos_data *data)
   gb.glyph = Vhscroll_glyph;
   {
     int oldpixpos = data->pixpos;
   gb.glyph = Vhscroll_glyph;
   {
     int oldpixpos = data->pixpos;
-    retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
+    retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0,
                             GLYPH_CACHEL (XWINDOW (data->window),
                                           HSCROLL_GLYPH_INDEX));
     data->hscroll_glyph_width_adjust =
                             GLYPH_CACHEL (XWINDOW (data->window),
                                           HSCROLL_GLYPH_INDEX));
     data->hscroll_glyph_width_adjust =
@@ -923,9 +916,7 @@ add_emchar_rune (pos_data *data)
   else if (data->is_modeline)
     crb->bufpos = data->modeline_charpos;
   else
   else if (data->is_modeline)
     crb->bufpos = data->modeline_charpos;
   else
-    /* fuckme if this shouldn't be an abort. */
-    /* abort (); fuckme harder, this abort gets tripped quite often,
-                in propagation and whatnot.  #### fixme */
+    /* Text but not in buffer */
     crb->bufpos = 0;
   crb->type = RUNE_CHAR;
   crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
     crb->bufpos = 0;
   crb->type = RUNE_CHAR;
   crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
@@ -981,6 +972,8 @@ add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
 
   for (pos = c_string; pos < end;)
     {
 
   for (pos = c_string; pos < end;)
     {
+      Bufbyte *old_pos = pos;
+
       data->ch = charptr_emchar (pos);
 
       prop = add_emchar_rune (data);
       data->ch = charptr_emchar (pos);
 
       prop = add_emchar_rune (data);
@@ -1006,6 +999,9 @@ add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
        }
       INC_CHARPTR (pos);
       assert (pos <= end);
        }
       INC_CHARPTR (pos);
       assert (pos <= end);
+      /* #### Duplicate code from add_string_to_fstring_db_runes
+        should we do more?*/
+      data->bytepos += pos - old_pos;
     }
 
   return NULL;
     }
 
   return NULL;
@@ -1320,6 +1316,7 @@ add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry)
                    case '%':
                      dst += set_charptr_emchar (dst, '%');
                      break;
                    case '%':
                      dst += set_charptr_emchar (dst, '%');
                      break;
+                     /* #### unimplemented */
                    }
                }
            }
                    }
                }
            }
@@ -1528,12 +1525,21 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
      glyph sizes might have changed too */
   invalidate_glyph_geometry_maybe (gb->glyph, w);
 
      glyph sizes might have changed too */
   invalidate_glyph_geometry_maybe (gb->glyph, w);
 
+  /* This makes sure the glyph is in the cachels.
+
+     #### We do this to make sure the glyph is in the glyph cachels,
+     so that the dirty flag can be reset after redisplay has
+     finished. We should do this some other way, maybe by iterating
+     over the window cache of subwindows. */
+  get_glyph_cachel_index (w, gb->glyph);
+
   /* A nil extent indicates a special glyph (ex. truncator). */
   if (NILP (gb->extent)
       || (pos_type == BEGIN_GLYPHS &&
          extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
       || (pos_type == END_GLYPHS &&
   /* A nil extent indicates a special glyph (ex. truncator). */
   if (NILP (gb->extent)
       || (pos_type == BEGIN_GLYPHS &&
          extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
       || (pos_type == END_GLYPHS &&
-         extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT))
+         extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
+      || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS)
     {
       struct rune rb;
       int width;
     {
       struct rune rb;
       int width;
@@ -1541,6 +1547,8 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
       int ascent, descent;
       Lisp_Object baseline;
       Lisp_Object face;
       int ascent, descent;
       Lisp_Object baseline;
       Lisp_Object face;
+      Lisp_Object instance;
+      face_index findex;
 
       if (cachel)
        width = cachel->width;
 
       if (cachel)
        width = cachel->width;
@@ -1652,10 +1660,32 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
 
       face = glyph_face (gb->glyph, data->window);
       if (NILP (face))
 
       face = glyph_face (gb->glyph, data->window);
       if (NILP (face))
-       rb.findex = data->findex;
+       findex = data->findex;
       else
       else
-       rb.findex = get_builtin_face_cache_index (w, face);
+       findex = get_builtin_face_cache_index (w, face);
+
+      instance = glyph_image_instance (gb->glyph, data->window,
+                                      ERROR_ME_NOT, 1);
+      if (TEXT_IMAGE_INSTANCEP (instance))
+       {
+         Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance);
+         face_index orig_findex = data->findex;
+         Bytind orig_bufpos = data->bi_bufpos;
+         Bytind orig_start_col_enabled = data->bi_start_col_enabled;
+
+         data->findex = findex;
+         data->bi_start_col_enabled = 0;
+         if (!allow_cursor)
+           data->bi_bufpos = 0;
+         add_bufbyte_string_runes (data, XSTRING_DATA (string),
+                                   XSTRING_LENGTH (string), 0);
+         data->findex = orig_findex;
+         data->bi_bufpos = orig_bufpos;
+         data->bi_start_col_enabled = orig_start_col_enabled;
+         return NULL;
+       }
 
 
+      rb.findex = findex;
       rb.xpos = data->pixpos;
       rb.width = width;
       rb.bufpos = 0;                   /* glyphs are never "at" anywhere */
       rb.xpos = data->pixpos;
       rb.width = width;
       rb.bufpos = 0;                   /* glyphs are never "at" anywhere */
@@ -1666,13 +1696,6 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
       else
         rb.endpos = 0;
       rb.type = RUNE_DGLYPH;
       else
         rb.endpos = 0;
       rb.type = RUNE_DGLYPH;
-      /* #### Ben sez: this is way bogus if the glyph is a string.
-        You should not make the output routines have to cope with
-        this.  The string could contain Mule characters, or non-
-        printable characters, or characters to be passed through
-        the display table, or non-character objects (when this gets
-        implemented), etc.  Instead, this routine here should parse
-        the string into a series of runes. */
       rb.object.dglyph.glyph = gb->glyph;
       rb.object.dglyph.extent = gb->extent;
       rb.object.dglyph.xoffset = xoffset;
       rb.object.dglyph.glyph = gb->glyph;
       rb.object.dglyph.extent = gb->extent;
       rb.object.dglyph.xoffset = xoffset;
@@ -1875,6 +1898,7 @@ create_text_block (struct window *w, struct display_line *dl,
 
   dl->used_prop_data = 0;
   dl->num_chars = 0;
 
   dl->used_prop_data = 0;
   dl->num_chars = 0;
+  dl->line_continuation = 0;
 
   xzero (data);
   data.ef = extent_fragment_new (w->buffer, f);
 
   xzero (data);
   data.ef = extent_fragment_new (w->buffer, f);
@@ -2465,11 +2489,12 @@ done:
 
              /* data.bi_bufpos is already at the start of the next line. */
 
 
              /* data.bi_bufpos is already at the start of the next line. */
 
+             dl->line_continuation = 1;
              gb.glyph = Vcontinuation_glyph;
              cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
            }
 
              gb.glyph = Vcontinuation_glyph;
              cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
            }
 
-         add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, cachel);
+         add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
 
          if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
              && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
 
          if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
              && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
@@ -2717,8 +2742,26 @@ add_margin_runes (struct display_line *dl, struct display_block *db, int start,
                             ? dl->left_glyphs
                             : dl->right_glyphs);
   int elt, end;
                             ? dl->left_glyphs
                             : dl->right_glyphs);
   int elt, end;
-  int xpos = start;
   int reverse;
   int reverse;
+  struct window *w = XWINDOW (window);
+  struct frame *f = XFRAME (w->frame);
+  struct device *d = XDEVICE (f->device);
+  pos_data data;
+
+  xzero (data);
+  data.d = d;
+  data.window = window;
+  data.db = db;
+  data.dl = dl;
+  data.pixpos = start;
+  data.cursor_type = NO_CURSOR;
+  data.cursor_x = -1;
+  data.last_charset = Qunbound;
+  data.last_findex = DEFAULT_INDEX;
+  data.result_str = Qnil;
+  data.string = Qnil;
+  data.new_ascent = dl->ascent;
+  data.new_descent = dl->descent;
 
   if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
       || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
 
   if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
       || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
@@ -2747,79 +2790,31 @@ add_margin_runes (struct display_line *dl, struct display_block *db, int start,
           || (side == RIGHT_GLYPHS &&
               extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
        {
           || (side == RIGHT_GLYPHS &&
               extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
        {
-         struct rune rb;
-
-         rb.width = gb->width;
-         rb.findex = gb->findex;
-         rb.xpos = xpos;
-         rb.bufpos = -1;
-         rb.endpos = 0;
-         rb.type = RUNE_DGLYPH;
-         rb.object.dglyph.glyph = gb->glyph;
-         rb.object.dglyph.extent = gb->extent;
-         rb.object.dglyph.xoffset = 0;
-         rb.cursor_type = CURSOR_OFF;
-
-         Dynarr_add (db->runes, rb);
-         xpos += rb.width;
+         data.findex = gb->findex;
+         data.max_pixpos = data.pixpos + gb->width;
+         add_glyph_rune (&data, gb, side, 0, NULL);
          count--;
          gb->active = 0;
          count--;
          gb->active = 0;
-
-         if (glyph_contrib_p (gb->glyph, window))
-           {
-             unsigned short ascent, descent;
-             Lisp_Object baseline = glyph_baseline (gb->glyph, window);
-
-             ascent = glyph_ascent (gb->glyph, window);
-             descent = glyph_descent (gb->glyph, window);
-
-             /* A pixmap that has not had a baseline explicitly set.
-                 We use the existing ascent / descent ratio of the
-                 line. */
-             if (NILP (baseline))
-               {
-                 int gheight = ascent + descent;
-                 int line_height = dl->ascent + dl->descent;
-                 int pix_ascent, pix_descent;
-
-                 pix_descent = (int) (gheight * dl->descent) / line_height;
-                 pix_ascent = gheight - pix_descent;
-
-                 dl->ascent = max ((int) dl->ascent, pix_ascent);
-                 dl->descent = max ((int) dl->descent, pix_descent);
-               }
-
-             /* A string so determine contribution normally. */
-             else if (EQ (baseline, Qt))
-               {
-                 dl->ascent = max (dl->ascent, ascent);
-                 dl->descent = max (dl->descent, descent);
-               }
-
-             /* A pixmap with an explicitly set baseline.  We determine the
-                contribution here. */
-             else if (INTP (baseline))
-               {
-                 int height = ascent + descent;
-                 int pix_ascent, pix_descent;
-
-                 pix_ascent = height * XINT (baseline) / 100;
-                 pix_descent = height - pix_ascent;
-
-                 dl->ascent = max ((int) dl->ascent, pix_ascent);
-                 dl->descent = max ((int) dl->descent, pix_descent);
-               }
-
-             /* Otherwise something is screwed up. */
-             else
-               abort ();
-           }
        }
 
       (reverse ? elt-- : elt++);
     }
 
        }
 
       (reverse ? elt-- : elt++);
     }
 
-  return xpos;
+  if (data.max_pixmap_height)
+    {
+      int height = data.new_ascent + data.new_descent;
+      int pix_ascent, pix_descent;
+
+      pix_descent = data.max_pixmap_height * data.new_descent / height;
+      pix_ascent = data.max_pixmap_height - pix_descent;
+      data.new_ascent = max (data.new_ascent, pix_ascent);
+      data.new_descent = max (data.new_descent, pix_descent);
+    }
+
+  dl->ascent = data.new_ascent;
+  dl->descent = data.new_descent;
+
+  return data.pixpos;
 }
 
 /* Add a blank to a margin display block. */
 }
 
 /* Add a blank to a margin display block. */
@@ -3510,7 +3505,7 @@ generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
 
   /* result_str is nil when we're building a frame or icon title. Otherwise,
      we're building a modeline, so the offset starts at the modeline
 
   /* result_str is nil when we're building a frame or icon title. Otherwise,
      we're building a modeline, so the offset starts at the modeline
-     horizontal scrolling ammount */
+     horizontal scrolling amount */
   if (! NILP (result_str))
     offset = w->modeline_hscroll;
   generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
   if (! NILP (result_str))
     offset = w->modeline_hscroll;
   generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
@@ -3547,6 +3542,8 @@ generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
       Bufbyte *strdata;
       struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
 
       Bufbyte *strdata;
       struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
 
+      in_modeline_generation = 1;
+
       detach_all_extents (result_str);
       resize_string (XSTRING (result_str), -1,
                      data.bytepos - XSTRING_LENGTH (result_str));
       detach_all_extents (result_str);
       resize_string (XSTRING (result_str), -1,
                      data.bytepos - XSTRING_LENGTH (result_str));
@@ -3583,6 +3580,8 @@ generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
              Dynarr_at (formatted_string_extent_end_dynarr, elt),
              result_str);
         }
              Dynarr_at (formatted_string_extent_end_dynarr, elt),
              result_str);
         }
+
+      in_modeline_generation = 0;
     }
 }
 
     }
 }
 
@@ -3626,10 +3625,6 @@ generate_modeline (struct window *w, struct display_line *dl, int type)
       /* The modeline is at the bottom of the gutters. */
       dl->ypos = WINDOW_BOTTOM (w);
 
       /* The modeline is at the bottom of the gutters. */
       dl->ypos = WINDOW_BOTTOM (w);
 
-      /* adjust for the bottom gutter */
-      if (window_is_lowest (w))
-       dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
-
       rb.findex = MODELINE_INDEX;
       rb.xpos = dl->bounds.left_out;
       rb.width = dl->bounds.right_out - dl->bounds.left_out;
       rb.findex = MODELINE_INDEX;
       rb.xpos = dl->bounds.left_out;
       rb.width = dl->bounds.right_out - dl->bounds.left_out;
@@ -3683,18 +3678,15 @@ generate_modeline (struct window *w, struct display_line *dl, int type)
      set this until we've generated the modeline in order to account
      for any embedded faces. */
   dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
      set this until we've generated the modeline in order to account
      for any embedded faces. */
   dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
-  /* adjust for the bottom gutter */
-  if (window_is_lowest (w))
-    dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
 }
 
 static Charcount
 }
 
 static Charcount
-add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str,
+add_string_to_fstring_db_runes (pos_data *data, const Bufbyte *str,
                                 Charcount pos, Charcount min_pos, Charcount max_pos)
 {
   /* This function has been Mule-ized. */
   Charcount end;
                                 Charcount pos, Charcount min_pos, Charcount max_pos)
 {
   /* This function has been Mule-ized. */
   Charcount end;
-  CONST Bufbyte *cur_pos = str;
+  const Bufbyte *cur_pos = str;
   struct display_block *db = data->db;
 
   data->blank_width = space_width (XWINDOW (data->window));
   struct display_block *db = data->db;
 
   data->blank_width = space_width (XWINDOW (data->window));
@@ -3702,13 +3694,13 @@ add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str,
     add_blank_rune (data, NULL, 0);
 
   end = (Dynarr_length (db->runes) +
     add_blank_rune (data, NULL, 0);
 
   end = (Dynarr_length (db->runes) +
-         bytecount_to_charcount (str, strlen ((CONST char *) str)));
+         bytecount_to_charcount (str, strlen ((const char *) str)));
   if (max_pos != -1)
     end = min (max_pos, end);
 
   while (pos < end && *cur_pos)
     {
   if (max_pos != -1)
     end = min (max_pos, end);
 
   while (pos < end && *cur_pos)
     {
-      CONST Bufbyte *old_cur_pos = cur_pos;
+      const Bufbyte *old_cur_pos = cur_pos;
       int succeeded;
 
       data->ch = charptr_emchar (cur_pos);
       int succeeded;
 
       data->ch = charptr_emchar (cur_pos);
@@ -3820,7 +3812,7 @@ tail_recurse:
                {
                  Charcount tmp_max = (max_pos == -1 ? pos + size - *offset :
                                       min (pos + size - *offset, max_pos));
                {
                  Charcount tmp_max = (max_pos == -1 ? pos + size - *offset :
                                       min (pos + size - *offset, max_pos));
-                 CONST Bufbyte *tmp_last = charptr_n_addr (last, *offset);
+                 const Bufbyte *tmp_last = charptr_n_addr (last, *offset);
 
                  pos = add_string_to_fstring_db_runes (data, tmp_last,
                                                        pos, pos, tmp_max);
 
                  pos = add_string_to_fstring_db_runes (data, tmp_last,
                                                        pos, pos, tmp_max);
@@ -3877,7 +3869,7 @@ tail_recurse:
 
                   while (num_to_add--)
                     pos = add_string_to_fstring_db_runes
 
                   while (num_to_add--)
                     pos = add_string_to_fstring_db_runes
-                      (data, (CONST Bufbyte *) "-", pos, pos, max_pos);
+                      (data, (const Bufbyte *) "-", pos, pos, max_pos);
                 }
               else if (*this != 0)
                 {
                 }
               else if (*this != 0)
                 {
@@ -3896,7 +3888,7 @@ tail_recurse:
                    *offset -= size;
                  else
                    {
                    *offset -= size;
                  else
                    {
-                     CONST Bufbyte *tmp_str = charptr_n_addr (str, *offset);
+                     const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
 
                      /* #### NOTE: I don't understand why a tmp_max is not
                         computed and used here as in the plain string case
 
                      /* #### NOTE: I don't understand why a tmp_max is not
                         computed and used here as in the plain string case
@@ -3942,7 +3934,7 @@ tail_recurse:
                *offset -= size;
              else
                {
                *offset -= size;
              else
                {
-                 CONST Bufbyte *tmp_str = charptr_n_addr (str, *offset);
+                 const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
 
                  /* #### NOTE: I don't understand why a tmp_max is not
                     computed and used here as in the plain string case
 
                  /* #### NOTE: I don't understand why a tmp_max is not
                     computed and used here as in the plain string case
@@ -3983,8 +3975,8 @@ tail_recurse:
        * - If first element is another symbol, process the cadr or caddr
        *   recursively according to whether the symbol's value is non-nil or
        *   nil.
        * - If first element is another symbol, process the cadr or caddr
        *   recursively according to whether the symbol's value is non-nil or
        *   nil.
-       * - If first element is a face, process the cdr recursively
-       *   without altering the depth.
+       * - If first element is an extent, process the cdr recursively
+       *   and handle the extent's face.
        */
 
       Lisp_Object car, tem;
        */
 
       Lisp_Object car, tem;
@@ -4136,8 +4128,8 @@ tail_recurse:
          *offset -= size;
        else
          {
          *offset -= size;
        else
          {
-           CONST Bufbyte *tmp_str =
-             charptr_n_addr ((CONST Bufbyte *) str, *offset);
+           const Bufbyte *tmp_str =
+             charptr_n_addr ((const Bufbyte *) str, *offset);
 
            /* #### NOTE: I don't understand why a tmp_max is not computed and
               used here as in the plain string case above. -- dv */
 
            /* #### NOTE: I don't understand why a tmp_max is not computed and
               used here as in the plain string case above. -- dv */
@@ -4150,7 +4142,7 @@ tail_recurse:
 
   if (min_pos > pos)
     {
 
   if (min_pos > pos)
     {
-      add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos,
+      add_string_to_fstring_db_runes (data, (const Bufbyte *) "", pos,
                                      min_pos, -1);
     }
 
                                      min_pos, -1);
     }
 
@@ -4297,9 +4289,9 @@ create_string_text_block (struct window *w, Lisp_Object disp_string,
   int truncate_win = b ? window_truncation_on (w) : 0;
   int end_glyph_width = 0;
 
   int truncate_win = b ? window_truncation_on (w) : 0;
   int end_glyph_width = 0;
 
-  /* we're going to ditch selective display for static text, its an
-     FSF thing and invisble extents are the way to go
-     here. Implementing it also relies on a number of buffer-specific
+  /* We're going to ditch selective display for static text, it's an
+     FSF thing and invisible extents are the way to go here.
+     Implementing it also relies on a number of buffer-specific
      functions that we don't have the luxury of being able to use
      here. */
 
      functions that we don't have the luxury of being able to use
      here. */
 
@@ -4365,6 +4357,7 @@ create_string_text_block (struct window *w, Lisp_Object disp_string,
 
   dl->used_prop_data = 0;
   dl->num_chars = 0;
 
   dl->used_prop_data = 0;
   dl->num_chars = 0;
+  dl->line_continuation = 0;
 
   /* set up faces to use for clearing areas, used by
      output_display_line */
 
   /* set up faces to use for clearing areas, used by
      output_display_line */
@@ -4522,7 +4515,7 @@ create_string_text_block (struct window *w, Lisp_Object disp_string,
                goto done;
            }
 
                goto done;
            }
 
-         /* #### What if we we're dealing with a display table? */
+         /* #### What if we're dealing with a display table? */
          if (data.start_col)
            data.start_col--;
 
          if (data.start_col)
            data.start_col--;
 
@@ -4757,6 +4750,7 @@ done:
 
              /* data.bi_bufpos is already at the start of the next line. */
 
 
              /* data.bi_bufpos is already at the start of the next line. */
 
+             dl->line_continuation = 1;
              gb.glyph = Vcontinuation_glyph;
              cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
            }
              gb.glyph = Vcontinuation_glyph;
              cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
            }
@@ -4766,7 +4760,7 @@ done:
 
          if (truncate_win && data.bi_bufpos == bi_string_zv)
            {
 
          if (truncate_win && data.bi_bufpos == bi_string_zv)
            {
-             CONST Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv);
+             const Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv);
              DEC_CHARPTR (endb);
              if (charptr_emchar (endb) != '\n')
                {
              DEC_CHARPTR (endb);
              if (charptr_emchar (endb) != '\n')
                {
@@ -5098,6 +5092,7 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
   int ypos = WINDOW_TEXT_TOP (w);
   int yend;    /* set farther down */
   int yclip = WINDOW_TEXT_TOP_CLIP (w);
   int ypos = WINDOW_TEXT_TOP (w);
   int yend;    /* set farther down */
   int yclip = WINDOW_TEXT_TOP_CLIP (w);
+  int force;
 
   prop_block_dynarr *prop;
   layout_bounds bounds;
 
   prop_block_dynarr *prop;
   layout_bounds bounds;
@@ -5151,7 +5146,14 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
   else
     prop = 0;
 
   else
     prop = 0;
 
-  while (ypos < yend)
+  /* When we are computing things for scrolling purposes, make
+     sure at least one line is always generated */
+  force = (type == CMOTION_DISP);
+
+  /* Make sure this is set always */
+  /* Note the conversion at end */
+  w->window_end_pos[type] = start_pos;
+  while (ypos < yend || force)
     {
       struct display_line dl;
       struct display_line *dlp;
     {
       struct display_line dl;
       struct display_line *dlp;
@@ -5204,7 +5206,7 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
             the top clip and the bottom clip. */
          visible_height -= (dlp->clip + dlp->top_clip);
 
             the top clip and the bottom clip. */
          visible_height -= (dlp->clip + dlp->top_clip);
 
-         if (visible_height < VERTICAL_CLIP (w, 1))
+         if (visible_height < VERTICAL_CLIP (w, 1) && !force)
            {
              if (local)
                free_display_line (dlp);
            {
              if (local)
                free_display_line (dlp);
@@ -5248,16 +5250,22 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
         generate_display_line call. */
       if (start_pos > BUF_ZV (b))
        break;
         generate_display_line call. */
       if (start_pos > BUF_ZV (b))
        break;
+
+      force = 0;
     }
 
   if (prop)
     Dynarr_free (prop);
 
   /* #### More not quite right, but close enough. */
     }
 
   if (prop)
     Dynarr_free (prop);
 
   /* #### More not quite right, but close enough. */
-  /* #### Ben sez: apparently window_end_pos[] is measured
+  /* Ben sez: apparently window_end_pos[] is measured
      as the number of characters between the window end and the
      end of the buffer?  This seems rather weirdo.  What's
      as the number of characters between the window end and the
      end of the buffer?  This seems rather weirdo.  What's
-     the justification for this? */
+     the justification for this?
+
+     JV sez: Because BUF_Z (b) would be a good initial value, however
+     that can change. This representation allows initalizing with 0.
+  */
   w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
 
   if (need_modeline)
   w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
 
   if (need_modeline)
@@ -5588,20 +5596,9 @@ regenerate_window_incrementally (struct window *w, Bufpos startp,
       assert (cdl->end_bufpos == ddl->end_bufpos);
       assert (cdl->offset == ddl->offset);
 
       assert (cdl->end_bufpos == ddl->end_bufpos);
       assert (cdl->offset == ddl->offset);
 
-      /* If the last rune is already a continuation glyph, fail.
-         #### We should be able to handle this better. */
-      {
-       struct display_block *db = get_display_block_from_line (ddl, TEXT);
-       if (Dynarr_length (db->runes))
-         {
-           struct rune *rb =
-             Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
-
-           if (rb->type == RUNE_DGLYPH
-               && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
-             return 0;
-         }
-      }
+      /* If the line continues to next display line, fail. */
+      if (ddl->line_continuation)
+       return 0;
 
       /* If the line was generated using propagation data, fail. */
       if (ddl->used_prop_data)
 
       /* If the line was generated using propagation data, fail. */
       if (ddl->used_prop_data)
@@ -5619,19 +5616,9 @@ regenerate_window_incrementally (struct window *w, Bufpos startp,
          return 0;
        }
 
          return 0;
        }
 
-      /* If the last rune is now a continuation glyph, fail. */
-      {
-       struct display_block *db = get_display_block_from_line (ddl, TEXT);
-       if (Dynarr_length (db->runes))
-         {
-           struct rune *rb =
-             Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
-
-           if (rb->type == RUNE_DGLYPH
-               && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
-             return 0;
-         }
-      }
+      /* If the line continues to next display line, fail. */
+      if (ddl->line_continuation)
+       return 0;
 
       /* If any line position parameters have changed or a
          cursor has disappeared or disappeared, fail. */
 
       /* If any line position parameters have changed or a
          cursor has disappeared or disappeared, fail. */
@@ -6007,7 +5994,7 @@ redisplay_window (Lisp_Object window, int skip_selected)
       && !(MINI_WINDOW_P (w) && f->buffers_changed)
       && !f->frame_changed
       && !truncation_changed
       && !(MINI_WINDOW_P (w) && f->buffers_changed)
       && !f->frame_changed
       && !truncation_changed
-      /* check whether start is really at the begining of a line  GE */
+      /* check whether start is really at the beginning of a line  GE */
       && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
       )
     {
       && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
       )
     {
@@ -6021,7 +6008,7 @@ redisplay_window (Lisp_Object window, int skip_selected)
          && !f->faces_changed
          && !f->glyphs_changed
          && !f->subwindows_changed
          && !f->faces_changed
          && !f->glyphs_changed
          && !f->subwindows_changed
-         && !f->subwindows_state_changed
+         /*      && !f->subwindows_state_changed*/
          && !f->point_changed
          && !f->windows_structure_changed)
        {
          && !f->point_changed
          && !f->windows_structure_changed)
        {
@@ -6043,7 +6030,7 @@ redisplay_window (Lisp_Object window, int skip_selected)
              && !f->faces_changed
              && !f->glyphs_changed
              && !f->subwindows_changed
              && !f->faces_changed
              && !f->glyphs_changed
              && !f->subwindows_changed
-             && !f->subwindows_state_changed
+             /*              && !f->subwindows_state_changed*/
              && !f->windows_structure_changed)
            {
              if (point_visible (w, pointm, CURRENT_DISP)
              && !f->windows_structure_changed)
            {
              if (point_visible (w, pointm, CURRENT_DISP)
@@ -6102,7 +6089,7 @@ redisplay_window (Lisp_Object window, int skip_selected)
           && !f->faces_changed
           && !f->glyphs_changed
           && !f->subwindows_changed
           && !f->faces_changed
           && !f->glyphs_changed
           && !f->subwindows_changed
-          && !f->subwindows_state_changed
+          /*      && !f->subwindows_state_changed*/
           && !f->windows_structure_changed
           && !f->frame_changed
           && !truncation_changed
           && !f->windows_structure_changed
           && !f->frame_changed
           && !truncation_changed
@@ -6284,12 +6271,13 @@ call_redisplay_end_triggers (struct window *w, void *closure)
 
 /* Ensure that all windows on the given frame are correctly displayed. */
 
 
 /* Ensure that all windows on the given frame are correctly displayed. */
 
-static int
+int
 redisplay_frame (struct frame *f, int preemption_check)
 {
   struct device *d = XDEVICE (f->device);
 
 redisplay_frame (struct frame *f, int preemption_check)
 {
   struct device *d = XDEVICE (f->device);
 
-  if (preemption_check)
+  if (preemption_check
+      && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY))
     {
       /* The preemption check itself takes a lot of time,
         so normally don't do it here.  We do it if called
     {
       /* The preemption check itself takes a lot of time,
         so normally don't do it here.  We do it if called
@@ -6301,6 +6289,16 @@ redisplay_frame (struct frame *f, int preemption_check)
        return 1;
     }
 
        return 1;
     }
 
+  if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0))
+    {
+      Lisp_Object frame;
+
+      f->old_buffer_alist = Freplace_list (f->old_buffer_alist,
+                                          f->buffer_alist);
+      XSETFRAME (frame, f);
+      va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame);
+    }
+
   /* Before we put a hold on frame size changes, attempt to process
      any which are already pending. */
   if (f->size_change_pending)
   /* Before we put a hold on frame size changes, attempt to process
      any which are already pending. */
   if (f->size_change_pending)
@@ -6326,40 +6324,33 @@ redisplay_frame (struct frame *f, int preemption_check)
      being handled. */
   update_frame_menubars (f);
 #endif /* HAVE_MENUBARS */
      being handled. */
   update_frame_menubars (f);
 #endif /* HAVE_MENUBARS */
-  /* widgets are similar to menus in that they can call lisp to
-     determine activation etc. Therefore update them before we get
-     into redisplay. This is primarily for connected widgets such as
-     radio buttons. */
-  update_frame_subwindows (f);
 #ifdef HAVE_TOOLBARS
   /* Update the toolbars. */
   update_frame_toolbars (f);
 #endif /* HAVE_TOOLBARS */
 #ifdef HAVE_TOOLBARS
   /* Update the toolbars. */
   update_frame_toolbars (f);
 #endif /* HAVE_TOOLBARS */
+  /* Gutter update proper has to be done inside display when no frame
+     size changes can occur, thus we separately update the gutter
+     geometry here if it needs it. */
+  update_frame_gutter_geometry (f);
 
   /* If we clear the frame we have to force its contents to be redrawn. */
   if (f->clear)
     f->frame_changed = 1;
 
 
   /* If we clear the frame we have to force its contents to be redrawn. */
   if (f->clear)
     f->frame_changed = 1;
 
-  /* invalidate the subwindow cache. We use subwindows_changed here to
-     cause subwindows to get instantiated. This is because
+  /* Invalidate the subwindow caches. We use subwindows_changed here
+     to cause subwindows to get instantiated. This is because
      subwindows_state_changed is less strict - dealing with things
      like the clicked state of button. We have to do this before
      redisplaying the gutters as subwindows get unmapped in the
      process.*/
      subwindows_state_changed is less strict - dealing with things
      like the clicked state of button. We have to do this before
      redisplaying the gutters as subwindows get unmapped in the
      process.*/
-  if (!Dynarr_length (f->subwindow_cachels)
-      || f->subwindows_changed
-      || f->faces_changed
-      || f->frame_changed)
+  if (f->frame_changed)
+    reset_frame_subwindow_instance_cache (f);
+
+  if (f->frame_changed || f->subwindows_changed)
     {
     {
-      reset_subwindow_cachels (f);
       /* we have to do this so the gutter gets regenerated. */
       reset_gutter_display_lines (f);
     }
       /* we have to do this so the gutter gets regenerated. */
       reset_gutter_display_lines (f);
     }
-  else
-    mark_subwindow_cachels_as_not_updated (f);
-  /* We can now update the gutters, safe in the knowledge that our
-     efforts won't get undone. */
-  update_frame_gutters (f);
 
   hold_frame_size_changes ();
 
 
   hold_frame_size_changes ();
 
@@ -6387,10 +6378,22 @@ redisplay_frame (struct frame *f, int preemption_check)
      #### If a frame-size change does occur we should probably
      actually be preempting redisplay. */
 
      #### If a frame-size change does occur we should probably
      actually be preempting redisplay. */
 
+  MAYBE_DEVMETH (d, frame_output_begin, (f));
+
+  /* We can now update the gutters, safe in the knowledge that our
+     efforts won't get undone. */
+
+  /* This can call lisp, but redisplay is protected by binding
+     inhibit_quit.  More importantly the code involving display lines
+     *assumes* that GC will not happen and so does not GCPRO
+     anything. Since we use this code the whole time with the gutters
+     we cannot allow GC to happen when manipulating the gutters. */
+  update_frame_gutters (f);
+
   /* Erase the frame before outputting its contents. */
   if (f->clear)
     {
   /* Erase the frame before outputting its contents. */
   if (f->clear)
     {
-      DEVMETH (d, clear_frame, (f));
+      MAYBE_DEVMETH (d, clear_frame, (f));
     }
 
   /* Do the selected window first. */
     }
 
   /* Do the selected window first. */
@@ -6399,11 +6402,7 @@ redisplay_frame (struct frame *f, int preemption_check)
   /* Then do the rest. */
   redisplay_windows (f->root_window, 1);
 
   /* Then do the rest. */
   redisplay_windows (f->root_window, 1);
 
-  /* We now call the output_end routine for tty frames.  We delay
-     doing so in order to avoid cursor flicker.  So much for 100%
-     encapsulation. */
-  if (FRAME_TTY_P (f))
-    DEVMETH (d, output_end, (d));
+  MAYBE_DEVMETH (d, frame_output_end, (f));
 
   update_frame_title (f);
 
 
   update_frame_title (f);
 
@@ -6438,27 +6437,29 @@ static int
 redisplay_device (struct device *d, int automatic)
 {
   Lisp_Object frame, frmcons;
 redisplay_device (struct device *d, int automatic)
 {
   Lisp_Object frame, frmcons;
-  int preempted = 0;
   int size_change_failed = 0;
   struct frame *f;
 
   int size_change_failed = 0;
   struct frame *f;
 
-  if (automatic
-      && (MAYBE_INT_DEVMETH (d, device_implementation_flags, ())
-         & XDEVIMPF_NO_AUTO_REDISPLAY))
+  if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY))
     return 0;
 
   if (DEVICE_STREAM_P (d)) /* nothing to do */
     return 0;
 
   /* It is possible that redisplay has been called before the
     return 0;
 
   if (DEVICE_STREAM_P (d)) /* nothing to do */
     return 0;
 
   /* It is possible that redisplay has been called before the
-     device is fully initialized.  If so then continue with the
-     next device. */
+     device is fully initialized, or that the console implementation
+     allows frameless devices.  If so then continue with the next
+     device. */
   if (NILP (DEVICE_SELECTED_FRAME (d)))
     return 0;
 
   if (NILP (DEVICE_SELECTED_FRAME (d)))
     return 0;
 
-  REDISPLAY_PREEMPTION_CHECK;
-  if (preempted)
-    return 1;
+  if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY))
+    {
+      int preempted;
+      REDISPLAY_PREEMPTION_CHECK;
+      if (preempted)
+       return 1;
+    }
 
   /* Always do the selected frame first. */
   frame = DEVICE_SELECTED_FRAME (d);
 
   /* Always do the selected frame first. */
   frame = DEVICE_SELECTED_FRAME (d);
@@ -6472,12 +6473,11 @@ redisplay_device (struct device *d, int automatic)
     {
       if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f))
        {
     {
       if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f))
        {
-         preempted = redisplay_frame (f, 0);
+         int preempted = redisplay_frame (f, 0);
+         if (preempted)
+           return 1;
        }
 
        }
 
-      if (preempted)
-       return 1;
-
       /* If the frame redisplay did not get preempted, then this flag
          should have gotten set to 0.  It might be possible for that
          not to happen if a size change event were to occur at an odd
       /* If the frame redisplay did not get preempted, then this flag
          should have gotten set to 0.  It might be possible for that
          not to happen if a size change event were to occur at an odd
@@ -6502,12 +6502,11 @@ redisplay_device (struct device *d, int automatic)
        {
          if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f))
            {
        {
          if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f))
            {
-             preempted = redisplay_frame (f, 0);
+             int preempted = redisplay_frame (f, 0);
+             if (preempted)
+               return 1;
            }
 
            }
 
-         if (preempted)
-           return 1;
-
          if (f->size_change_pending)
            size_change_failed = 1;
        }
          if (f->size_change_pending)
            size_change_failed = 1;
        }
@@ -6675,7 +6674,7 @@ static void
 decode_mode_spec (struct window *w, Emchar spec, int type)
 {
   Lisp_Object obj = Qnil;
 decode_mode_spec (struct window *w, Emchar spec, int type)
 {
   Lisp_Object obj = Qnil;
-  CONST char *str = NULL;
+  const char *str = NULL;
   struct buffer *b = XBUFFER (w->buffer);
 
   Dynarr_reset (mode_spec_bufbyte_string);
   struct buffer *b = XBUFFER (w->buffer);
 
   Dynarr_reset (mode_spec_bufbyte_string);
@@ -6704,7 +6703,7 @@ decode_mode_spec (struct window *w, Emchar spec, int type)
        long_to_string (buf, col);
 
        Dynarr_add_many (mode_spec_bufbyte_string,
        long_to_string (buf, col);
 
        Dynarr_add_many (mode_spec_bufbyte_string,
-                        (CONST Bufbyte *) buf, strlen (buf));
+                        (const Bufbyte *) buf, strlen (buf));
 
        goto decode_mode_spec_done;
       }
 
        goto decode_mode_spec_done;
       }
@@ -7041,7 +7040,9 @@ mark_glyph_block_dynarr (glyph_block_dynarr *gba)
     }
 }
 
     }
 }
 
-static void
+/* See the comment in image_instantiate_cache_result as to why marking
+   the glyph will also mark the image_instance. */
+void
 mark_redisplay_structs (display_line_dynarr *dla)
 {
   display_line *dl = Dynarr_atp (dla, 0);
 mark_redisplay_structs (display_line_dynarr *dla)
 {
   display_line *dl = Dynarr_atp (dla, 0);
@@ -7099,8 +7100,13 @@ mark_redisplay (void)
   FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
     {
       struct frame *f = XFRAME (XCAR (frmcons));
   FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
     {
       struct frame *f = XFRAME (XCAR (frmcons));
+      /* #### urk!  this does tons o' crap, such as creating lots of
+        structs, doing window system actions, etc.  we DO NOT want to
+        be doing this -- marking should never change any state.
+        i think we can just delete this. --ben */
       update_frame_window_mirror (f);
       mark_window_mirror (f->root_mirror);
       update_frame_window_mirror (f);
       mark_window_mirror (f->root_mirror);
+      mark_gutters (f);
     }
 }
 \f
     }
 }
 \f
@@ -7537,11 +7543,18 @@ point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
    displayed.  The end of the last line is also know as the window end
    position.
 
    displayed.  The end of the last line is also know as the window end
    position.
 
+   WARNING: It is possible that redisplay failed to layout any lines for the
+   windows. Under normal circumstances this is rare. However it seems that it
+   does occur in the following situation: A mouse event has come in and we
+   need to compute its location in a window. That code (in
+   pixel_to_glyph_translation) already can handle 0 as an error return value.
+
    #### With a little work this could probably be reworked as just a
    call to start_with_line_at_pixpos. */
 
 static Bufpos
    #### With a little work this could probably be reworked as just a
    call to start_with_line_at_pixpos. */
 
 static Bufpos
-start_end_of_last_line (struct window *w, Bufpos startp, int end)
+start_end_of_last_line (struct window *w, Bufpos startp, int end,
+                        int may_error)
 {
   struct buffer *b = XBUFFER (w->buffer);
   line_start_cache_dynarr *cache = w->line_start_cache;
 {
   struct buffer *b = XBUFFER (w->buffer);
   line_start_cache_dynarr *cache = w->line_start_cache;
@@ -7561,7 +7574,7 @@ start_end_of_last_line (struct window *w, Bufpos startp, int end)
 
   start_elt = point_in_line_start_cache (w, cur_start, 0);
   if (start_elt == -1)
 
   start_elt = point_in_line_start_cache (w, cur_start, 0);
   if (start_elt == -1)
-    abort ();  /* this had better never happen */
+      return may_error ? 0 : startp;
 
   while (1)
     {
 
   while (1)
     {
@@ -7625,7 +7638,7 @@ start_end_of_last_line (struct window *w, Bufpos startp, int end)
 Bufpos
 start_of_last_line (struct window *w, Bufpos startp)
 {
 Bufpos
 start_of_last_line (struct window *w, Bufpos startp)
 {
-  return start_end_of_last_line (w, startp, 0);
+  return start_end_of_last_line (w, startp, 0 , 0);
 }
 
 /* For the given window W, if display starts at STARTP, what will be
 }
 
 /* For the given window W, if display starts at STARTP, what will be
@@ -7635,9 +7648,16 @@ start_of_last_line (struct window *w, Bufpos startp)
 Bufpos
 end_of_last_line (struct window *w, Bufpos startp)
 {
 Bufpos
 end_of_last_line (struct window *w, Bufpos startp)
 {
-  return start_end_of_last_line (w, startp, 1);
+  return start_end_of_last_line (w, startp, 1, 0);
 }
 
 }
 
+static Bufpos
+end_of_last_line_may_error (struct window *w, Bufpos startp)
+{
+  return start_end_of_last_line (w, startp, 1, 1);
+}
+
+
 /* For window W, what does the starting position have to be so that
    the line containing POINT will cover pixel position PIXPOS. */
 
 /* For window W, what does the starting position have to be so that
    the line containing POINT will cover pixel position PIXPOS. */
 
@@ -7821,7 +7841,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
 
   validate_line_start_cache (w);
   w->line_cache_validation_override++;
 
   validate_line_start_cache (w);
   w->line_cache_validation_override++;
-  updating_line_start_cache = 1;
 
   if (from < BUF_BEGV (b))
     from = BUF_BEGV (b);
 
   if (from < BUF_BEGV (b))
     from = BUF_BEGV (b);
@@ -7830,7 +7849,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
 
   if (from > to)
     {
 
   if (from > to)
     {
-      updating_line_start_cache = 0;
       w->line_cache_validation_override--;
       return;
     }
       w->line_cache_validation_override--;
       return;
     }
@@ -7843,7 +7861,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
       /* Check to see if the desired range is already in the cache. */
       if (from >= low_bound && to <= high_bound)
        {
       /* Check to see if the desired range is already in the cache. */
       if (from >= low_bound && to <= high_bound)
        {
-         updating_line_start_cache = 0;
          w->line_cache_validation_override--;
          return;
        }
          w->line_cache_validation_override--;
          return;
        }
@@ -7872,7 +7889,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
       update_internal_cache_list (w, DESIRED_DISP);
       if (!Dynarr_length (internal_cache))
        {
       update_internal_cache_list (w, DESIRED_DISP);
       if (!Dynarr_length (internal_cache))
        {
-         updating_line_start_cache = 0;
          w->line_cache_validation_override--;
          return;
        }
          w->line_cache_validation_override--;
          return;
        }
@@ -7900,7 +7916,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
        {
          Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
                           Dynarr_length (internal_cache));
        {
          Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
                           Dynarr_length (internal_cache));
-         updating_line_start_cache = 0;
          w->line_cache_validation_override--;
          return;
        }
          w->line_cache_validation_override--;
          return;
        }
@@ -7909,7 +7924,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
          the bounds of the DESIRED structs in the first place. */
       if (start >= low_bound && end <= high_bound)
        {
          the bounds of the DESIRED structs in the first place. */
       if (start >= low_bound && end <= high_bound)
        {
-         updating_line_start_cache = 0;
          w->line_cache_validation_override--;
          return;
        }
          w->line_cache_validation_override--;
          return;
        }
@@ -7932,7 +7946,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
              Dynarr_reset (cache);
              Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
                               Dynarr_length (internal_cache));
              Dynarr_reset (cache);
              Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
                               Dynarr_length (internal_cache));
-             updating_line_start_cache = 0;
              w->line_cache_validation_override--;
              return;
            }
              w->line_cache_validation_override--;
              return;
            }
@@ -7958,7 +7971,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
              Dynarr_reset (cache);
              Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
                               Dynarr_length (internal_cache));
              Dynarr_reset (cache);
              Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
                               Dynarr_length (internal_cache));
-             updating_line_start_cache = 0;
              w->line_cache_validation_override--;
              return;
            }
              w->line_cache_validation_override--;
              return;
            }
@@ -7967,7 +7979,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
                           Dynarr_length (internal_cache) - ic_elt);
        }
 
                           Dynarr_length (internal_cache) - ic_elt);
        }
 
-      updating_line_start_cache = 0;
       w->line_cache_validation_override--;
       return;
     }
       w->line_cache_validation_override--;
       return;
     }
@@ -7987,23 +7998,9 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
          update_internal_cache_list (w, CMOTION_DISP);
 
          /* If this assert is triggered then regenerate_window failed
          update_internal_cache_list (w, CMOTION_DISP);
 
          /* If this assert is triggered then regenerate_window failed
-             to layout a single line.  That is not supposed to be
-             possible because we impose a minimum height on the buffer
-             and override vertical clip when we are in here. */
-         /* #### Ah, but it is because the window may temporarily
-             exist but not have any lines at all if the minibuffer is
-             real big.  Look into that situation better. */
-         if (!Dynarr_length (internal_cache))
-           {
-             if (old_lb == -1 && low_bound == -1)
-               {
-                 updating_line_start_cache = 0;
-                 w->line_cache_validation_override--;
-                 return;
-               }
-
-             assert (Dynarr_length (internal_cache));
-           }
+             to layout a single line. This is not possible since we
+            force at least a single line to be layout for CMOTION_DISP */
+         assert (Dynarr_length (internal_cache));
          assert (startp == Dynarr_atp (internal_cache, 0)->start);
 
          ic_elt = Dynarr_length (internal_cache) - 1;
          assert (startp == Dynarr_atp (internal_cache, 0)->start);
 
          ic_elt = Dynarr_length (internal_cache) - 1;
@@ -8049,7 +8046,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
          startp = new_startp;
          if (startp > BUF_ZV (b))
            {
          startp = new_startp;
          if (startp > BUF_ZV (b))
            {
-             updating_line_start_cache = 0;
              w->line_cache_validation_override--;
              return;
            }
              w->line_cache_validation_override--;
              return;
            }
@@ -8083,7 +8079,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
       while (to > high_bound);
     }
 
       while (to > high_bound);
     }
 
-  updating_line_start_cache = 0;
   w->line_cache_validation_override--;
   assert (to <= high_bound);
 }
   w->line_cache_validation_override--;
   assert (to <= high_bound);
 }
@@ -8791,7 +8786,7 @@ pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
   if (!MARKERP ((*w)->start[CURRENT_DISP]))
     *closest = 0;
   else
   if (!MARKERP ((*w)->start[CURRENT_DISP]))
     *closest = 0;
   else
-    *closest = end_of_last_line (*w,
+    *closest = end_of_last_line_may_error (*w,
                                 marker_position ((*w)->start[CURRENT_DISP]));
   *col = 0;
   UPDATE_CACHE_RETURN;
                                 marker_position ((*w)->start[CURRENT_DISP]));
   *col = 0;
   UPDATE_CACHE_RETURN;
@@ -8824,6 +8819,9 @@ Ensure that all minibuffers are correctly showing the echo area.
          if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
            {
              Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
          if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
            {
              Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
+
+             MAYBE_DEVMETH (d, frame_output_begin, (f));
+
              /*
               * If the frame size has changed, there may be random
               * chud on the screen left from previous messages
              /*
               * If the frame size has changed, there may be random
               * chud on the screen left from previous messages
@@ -8832,19 +8830,15 @@ Ensure that all minibuffers are correctly showing the echo area.
               */
              if (f->echo_area_garbaged)
                {
               */
              if (f->echo_area_garbaged)
                {
-                 DEVMETH (d, clear_frame, (f));
+                 MAYBE_DEVMETH (d, clear_frame, (f));
                  f->echo_area_garbaged = 0;
                }
              redisplay_window (window, 0);
                  f->echo_area_garbaged = 0;
                }
              redisplay_window (window, 0);
+             MAYBE_DEVMETH (d, frame_output_end, (f));
+
              call_redisplay_end_triggers (XWINDOW (window), 0);
            }
        }
              call_redisplay_end_triggers (XWINDOW (window), 0);
            }
        }
-
-      /* We now call the output_end routine for tty frames.  We delay
-        doing so in order to avoid cursor flicker.  So much for 100%
-        encapsulation. */
-      if (DEVICE_TTY_P (d))
-       DEVMETH (d, output_end, (d));
     }
 
   return Qnil;
     }
 
   return Qnil;
@@ -8879,6 +8873,9 @@ input and is guaranteed to proceed to completion.
   f->clear = 1;
   redisplay_frame (f, 1);
 
   f->clear = 1;
   redisplay_frame (f, 1);
 
+  /* See the comment in Fredisplay_frame. */
+  RESET_CHANGED_SET_FLAGS;
+
   return unbind_to (count, Qnil);
 }
 
   return unbind_to (count, Qnil);
 }
 
@@ -8906,6 +8903,15 @@ input and is guaranteed to proceed to completion.
 
   redisplay_frame (f, 1);
 
 
   redisplay_frame (f, 1);
 
+  /* If we don't reset the global redisplay flags here, subsequent
+     changes to the display will not get registered by redisplay
+     because it thinks it already has registered changes. If you
+     really knew what you were doing you could confuse redisplay by
+     calling Fredisplay_frame while updating another frame. We assume
+     that if you know what you are doing you will not be that
+     stupid. */
+  RESET_CHANGED_SET_FLAGS;
+
   return unbind_to (count, Qnil);
 }
 
   return unbind_to (count, Qnil);
 }
 
@@ -8935,6 +8941,9 @@ input and is guaranteed to proceed to completion.
     }
   redisplay_device (d, 0);
 
     }
   redisplay_device (d, 0);
 
+  /* See the comment in Fredisplay_frame. */
+  RESET_CHANGED_SET_FLAGS;
+
   return unbind_to (count, Qnil);
 }
 
   return unbind_to (count, Qnil);
 }
 
@@ -8962,6 +8971,9 @@ input and is guaranteed to proceed to completion.
 
   redisplay_device (d, 0);
 
 
   redisplay_device (d, 0);
 
+  /* See the comment in Fredisplay_frame. */
+  RESET_CHANGED_SET_FLAGS;
+
   return unbind_to (count, Qnil);
 }
 
   return unbind_to (count, Qnil);
 }
 
@@ -9176,6 +9188,15 @@ init_redisplay (void)
     }
 #endif /* HAVE_X_WINDOWS */
 
     }
 #endif /* HAVE_X_WINDOWS */
 
+#ifdef HAVE_GTK
+  if (!strcmp (display_use, "gtk"))
+    {
+      Vwindow_system = Qgtk;
+      Vinitial_window_system = Qgtk;
+      return;
+    }
+#endif
+
 #ifdef HAVE_MS_WINDOWS
   if (!strcmp (display_use, "mswindows"))
     {
 #ifdef HAVE_MS_WINDOWS
   if (!strcmp (display_use, "mswindows"))
     {
@@ -9224,6 +9245,8 @@ syms_of_redisplay (void)
   defsymbol (&Qbar_cursor, "bar-cursor");
   defsymbol (&Qredisplay_end_trigger_functions,
             "redisplay-end-trigger-functions");
   defsymbol (&Qbar_cursor, "bar-cursor");
   defsymbol (&Qredisplay_end_trigger_functions,
             "redisplay-end-trigger-functions");
+  defsymbol (&Qtop_bottom, "top-bottom");
+  defsymbol (&Qbuffer_list_changed_hook, "buffer-list-changed-hook");
 
   DEFSUBR (Fredisplay_echo_area);
   DEFSUBR (Fredraw_frame);
 
   DEFSUBR (Fredisplay_echo_area);
   DEFSUBR (Fredraw_frame);
@@ -9235,15 +9258,8 @@ syms_of_redisplay (void)
 }
 
 void
 }
 
 void
-reinit_vars_of_redisplay (void)
-{
-  updating_line_start_cache = 0;
-}
-
-void
 vars_of_redisplay (void)
 {
 vars_of_redisplay (void)
 {
-  reinit_vars_of_redisplay ();
 
 #if 0
   staticpro (&last_arrow_position);
 
 #if 0
   staticpro (&last_arrow_position);
@@ -9288,7 +9304,9 @@ See also `overlay-arrow-string'.
   Voverlay_arrow_position = Qnil;
 
   DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
   Voverlay_arrow_position = Qnil;
 
   DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
-String to display as an arrow.  See also `overlay-arrow-position'.
+String or glyph to display as an arrow.  See also `overlay-arrow-position'.
+\(Note that despite the name of this variable, it can be set to a glyph as
+well as a string.)
 */ ,
                     redisplay_variable_changed);
   Voverlay_arrow_string = Qnil;
 */ ,
                     redisplay_variable_changed);
   Voverlay_arrow_string = Qnil;
@@ -9312,10 +9330,19 @@ If this is zero, point is always centered after it moves off screen.
                     redisplay_variable_changed);
   truncate_partial_width_windows = 1;
 
                     redisplay_variable_changed);
   truncate_partial_width_windows = 1;
 
-  DEFVAR_BOOL ("visible-bell", &visible_bell /*
-*Non-nil means try to flash the frame to represent a bell.
+  DEFVAR_LISP ("visible-bell", &Vvisible_bell /*
+*Non-nil substitutes a visual signal for the audible bell.
+
+Default behavior is to flash the whole screen.  On some platforms,
+special effects are available using the following values:
+
+'display       Flash the whole screen (ie, the default behavior).
+'top-bottom    Flash only the top and bottom lines of the selected frame.
+
+When effects are unavailable on a platform, the visual bell is the
+default, whole screen.  (Currently only X supports any special effects.)
 */ );
 */ );
-  visible_bell = 0;
+  Vvisible_bell = Qnil;
 
   DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
 *Non-nil means no need to redraw entire frame after suspending.
 
   DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
 *Non-nil means no need to redraw entire frame after suspending.
@@ -9359,24 +9386,29 @@ Non-nil means put cursor in minibuffer, at end of any message there.
      maybe a caret cursor, etc. */
 
   DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
      maybe a caret cursor, etc. */
 
   DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
-Use vertical bar cursor if non-nil.  If t width is 1 pixel, otherwise 2.
+*Use vertical bar cursor if non-nil.  If t width is 1 pixel, otherwise 2.
 */ );
   Vbar_cursor = Qnil;
 
 #ifndef INHIBIT_REDISPLAY_HOOKS
   xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
 Function or functions to run before every redisplay.
 */ );
   Vbar_cursor = Qnil;
 
 #ifndef INHIBIT_REDISPLAY_HOOKS
   xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
 Function or functions to run before every redisplay.
-Functions on this hook must be careful to avoid signalling errors!
 */ );
   Vpre_redisplay_hook = Qnil;
 
   xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
 Function or functions to run after every redisplay.
 */ );
   Vpre_redisplay_hook = Qnil;
 
   xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
 Function or functions to run after every redisplay.
-Functions on this hook must be careful to avoid signalling errors!
 */ );
   Vpost_redisplay_hook = Qnil;
 #endif /* INHIBIT_REDISPLAY_HOOKS */
 
 */ );
   Vpost_redisplay_hook = Qnil;
 #endif /* INHIBIT_REDISPLAY_HOOKS */
 
+  DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /*
+Function or functions to call when a frame's buffer list has changed.
+This is called during redisplay, before redisplaying each frame.
+Functions on this hook are called with one argument, the frame.
+*/ );
+  Vbuffer_list_changed_hook = Qnil;
+
   DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
 Bump this to tell the C code to call `display-warning-buffer'
 at next redisplay.  You should not normally change this; the function
   DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
 Bump this to tell the C code to call `display-warning-buffer'
 at next redisplay.  You should not normally change this; the function
@@ -9438,7 +9470,7 @@ This is a specifier; use `set-specifier' to change it.
                         offsetof (struct window, left_margin_width),
                         some_window_value_changed,
                         offsetof (struct frame, left_margin_width),
                         offsetof (struct window, left_margin_width),
                         some_window_value_changed,
                         offsetof (struct frame, left_margin_width),
-                        margin_width_changed_in_frame);
+                        margin_width_changed_in_frame, 0);
 
   DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
 *Width of right margin.
 
   DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
 *Width of right margin.
@@ -9450,7 +9482,7 @@ This is a specifier; use `set-specifier' to change it.
                         offsetof (struct window, right_margin_width),
                         some_window_value_changed,
                         offsetof (struct frame, right_margin_width),
                         offsetof (struct window, right_margin_width),
                         some_window_value_changed,
                         offsetof (struct frame, right_margin_width),
-                        margin_width_changed_in_frame);
+                        margin_width_changed_in_frame, 0);
 
   DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
 *Minimum ascent height of lines.
 
   DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
 *Minimum ascent height of lines.
@@ -9461,7 +9493,7 @@ This is a specifier; use `set-specifier' to change it.
   set_specifier_caching (Vminimum_line_ascent,
                         offsetof (struct window, minimum_line_ascent),
                         some_window_value_changed,
   set_specifier_caching (Vminimum_line_ascent,
                         offsetof (struct window, minimum_line_ascent),
                         some_window_value_changed,
-                        0, 0);
+                        0, 0, 0);
 
   DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
 *Minimum descent height of lines.
 
   DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
 *Minimum descent height of lines.
@@ -9472,7 +9504,7 @@ This is a specifier; use `set-specifier' to change it.
   set_specifier_caching (Vminimum_line_descent,
                         offsetof (struct window, minimum_line_descent),
                         some_window_value_changed,
   set_specifier_caching (Vminimum_line_descent,
                         offsetof (struct window, minimum_line_descent),
                         some_window_value_changed,
-                        0, 0);
+                        0, 0, 0);
 
   DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
 *Non-nil means use the left outside margin as extra whitespace when
 
   DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
 *Non-nil means use the left outside margin as extra whitespace when
@@ -9484,7 +9516,7 @@ This is a specifier; use `set-specifier' to change it.
   set_specifier_caching (Vuse_left_overflow,
                         offsetof (struct window, use_left_overflow),
                         some_window_value_changed,
   set_specifier_caching (Vuse_left_overflow,
                         offsetof (struct window, use_left_overflow),
                         some_window_value_changed,
-                        0, 0);
+                        0, 0, 0);
 
   DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
 *Non-nil means use the right outside margin as extra whitespace when
 
   DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
 *Non-nil means use the right outside margin as extra whitespace when
@@ -9496,7 +9528,7 @@ This is a specifier; use `set-specifier' to change it.
   set_specifier_caching (Vuse_right_overflow,
                         offsetof (struct window, use_right_overflow),
                         some_window_value_changed,
   set_specifier_caching (Vuse_right_overflow,
                         offsetof (struct window, use_right_overflow),
                         some_window_value_changed,
-                        0, 0);
+                        0, 0, 0);
 
   DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
 *Non-nil means the text cursor is visible (this is usually the case).
 
   DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
 *Non-nil means the text cursor is visible (this is usually the case).
@@ -9507,6 +9539,6 @@ This is a specifier; use `set-specifier' to change it.
   set_specifier_caching (Vtext_cursor_visible_p,
                         offsetof (struct window, text_cursor_visible_p),
                         text_cursor_visible_p_changed,
   set_specifier_caching (Vtext_cursor_visible_p,
                         offsetof (struct window, text_cursor_visible_p),
                         text_cursor_visible_p_changed,
-                        0, 0);
+                        0, 0, 0);
 
 }
 
 }