]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Put doc strings in comments.
[gnu-emacs] / src / xdisp.c
index 85d58dbd7fe74715d5168b06ee9ce21fe15d84f1..08a378e689d44bbf2d58a8e61ba8321f962c2cfa 100644 (file)
@@ -169,6 +169,7 @@ Boston, MA 02111-1307, USA.  */
 
 #include <config.h>
 #include <stdio.h>
+#define DOC_STRINGS_IN_COMMENTS
 #include "lisp.h"
 #include "keyboard.h"
 #include "frame.h"
@@ -198,9 +199,6 @@ Boston, MA 02111-1307, USA.  */
 #include "macterm.h"
 #endif
 
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
-
 #define INFINITY 10000000
 
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
@@ -686,9 +684,6 @@ static void handle_stop P_ ((struct it *));
 static int tool_bar_lines_needed P_ ((struct frame *));
 static int single_display_prop_intangible_p P_ ((Lisp_Object));
 static void ensure_echo_area_buffers P_ ((void));
-static struct glyph_row *row_containing_pos P_ ((struct window *, int,
-                                                struct glyph_row *,
-                                                struct glyph_row *));
 static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
 static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
 static int with_echo_area_buffer P_ ((struct window *, int,
@@ -711,13 +706,11 @@ static void insert_left_trunc_glyphs P_ ((struct it *));
 static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
 static void extend_face_to_end_of_line P_ ((struct it *));
 static int append_space P_ ((struct it *, int));
-static void make_cursor_line_fully_visible P_ ((struct window *));
+static int make_cursor_line_fully_visible P_ ((struct window *));
 static int try_scrolling P_ ((Lisp_Object, int, int, int, int));
 static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
 static int trailing_whitespace_p P_ ((int));
 static int message_log_check_duplicate P_ ((int, int, int, int));
-int invisible_p P_ ((Lisp_Object, Lisp_Object));
-int invisible_ellipsis_p P_ ((Lisp_Object, Lisp_Object));
 static void push_it P_ ((struct it *));
 static void pop_it P_ ((struct it *));
 static void sync_frame_with_window_matrix_rows P_ ((struct window *));
@@ -732,7 +725,7 @@ static int display_line P_ ((struct it *));
 static int display_mode_lines P_ ((struct window *));
 static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object));
 static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object));
-static char *decode_mode_spec P_ ((struct window *, int, int, int));
+static char *decode_mode_spec P_ ((struct window *, int, int, int, int *));
 static void display_menu_bar P_ ((struct window *));
 static int display_count_lines P_ ((int, int, int, int, int *));
 static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
@@ -1435,7 +1428,7 @@ check_window_end (w)
    at character position CHARPOS.  CHARPOS < 0 means that no buffer
    position is specified which is useful when the iterator is assigned
    a position later.  BYTEPOS is the byte position corresponding to
-   CHARPOS.  BYTEPOS <= 0 means compute it from CHARPOS.
+   CHARPOS.  BYTEPOS < 0 means compute it from CHARPOS.
 
    If ROW is not null, calls to produce_glyphs with IT as parameter
    will produce glyphs in that row.
@@ -1461,7 +1454,8 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
 
   /* Some precondition checks.  */
   xassert (w != NULL && it != NULL);
-  xassert (charpos < 0 || (charpos > 0 && charpos <= ZV));
+  xassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
+                          && charpos <= ZV));
 
   /* If face attributes have been changed since the last redisplay,
      free realized faces now because they depend on face definitions
@@ -1541,7 +1535,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
 
   /* Non-zero if we should highlight the region.  */
   highlight_region_p
-    = (!NILP (Vtransient_mark_mode) 
+    = (!NILP (Vtransient_mark_mode)
        && !NILP (current_buffer->mark_active)
        && XMARKER (current_buffer->mark)->buffer != 0);
 
@@ -1678,14 +1672,14 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
 
   /* If a buffer position was specified, set the iterator there,
      getting overlays and face properties from that position.  */
-  if (charpos > 0)
+  if (charpos >= BUF_BEG (current_buffer))
     {
       it->end_charpos = ZV;
       it->face_id = -1;
       IT_CHARPOS (*it) = charpos;
       
       /* Compute byte position if not specified.  */
-      if (bytepos <= 0)
+      if (bytepos < charpos)
        IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
       else
        IT_BYTEPOS (*it) = bytepos;
@@ -1795,9 +1789,7 @@ in_ellipses_for_invisible_text_p (pos, w)
     {
       prop = Fget_char_property (make_number (charpos - 1), Qinvisible,
                                 window);
-      if (TEXT_PROP_MEANS_INVISIBLE (prop)
-         && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop))
-       ellipses_p = 1;
+      ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
     }
 
   return ellipses_p;
@@ -2209,7 +2201,6 @@ handle_fontified_prop (it)
 
       val = Vfontification_functions;
       specbind (Qfontification_functions, Qnil);
-      specbind (Qafter_change_functions, Qnil);
   
       if (!CONSP (val) || EQ (XCAR (val), Qlambda))
        safe_call1 (val, pos);
@@ -2574,7 +2565,7 @@ handle_invisible_prop (it)
     }
   else
     {
-      int visible_p, newpos, next_stop, start_charpos;
+      int invis_p, newpos, next_stop, start_charpos;
       Lisp_Object pos, prop, overlay;
 
       /* First of all, is there invisible text at this position?  */
@@ -2582,15 +2573,14 @@ handle_invisible_prop (it)
       pos = make_number (IT_CHARPOS (*it));
       prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
                                            &overlay);
-      
+      invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
+
       /* If we are on invisible text, skip over it.  */
-      if (TEXT_PROP_MEANS_INVISIBLE (prop)
-         && IT_CHARPOS (*it) < it->end_charpos)
+      if (invis_p && IT_CHARPOS (*it) < it->end_charpos)
        {
          /* Record whether we have to display an ellipsis for the
             invisible text.  */
-         int display_ellipsis_p
-           = TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (prop);
+         int display_ellipsis_p = invis_p == 2;
 
          handled = HANDLED_RECOMPUTE_PROPS;
          
@@ -2610,26 +2600,26 @@ handle_invisible_prop (it)
                 text in the first place.  If everything to the end of
                 the buffer was skipped, end the loop.  */
              if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
-               visible_p = 1;
+               invis_p = 0;
              else
                {
                  /* We skipped some characters but not necessarily
                     all there are.  Check if we ended up on visible
                     text.  Fget_char_property returns the property of
                     the char before the given position, i.e. if we
-                    get visible_p = 1, this means that the char at
+                    get invis_p = 0, this means that the char at
                     newpos is visible.  */
                  pos = make_number (newpos);
                  prop = Fget_char_property (pos, Qinvisible, it->window);
-                 visible_p = !TEXT_PROP_MEANS_INVISIBLE (prop);
+                 invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
                }
              
              /* If we ended up on invisible text, proceed to
                 skip starting with next_stop.  */
-             if (!visible_p)
+             if (invis_p)
                IT_CHARPOS (*it) = next_stop;
            }
-         while (!visible_p);
+         while (invis_p);
 
          /* The position newpos is now either ZV or on visible text.  */
          IT_CHARPOS (*it) = newpos;
@@ -4039,6 +4029,7 @@ reseat_1 (it, pos, set_stop_p)
   IT_STRING_BYTEPOS (*it) = -1;
   it->string = Qnil;
   it->method = next_element_from_buffer;
+  it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
   it->sp = 0;
   it->face_before_selective_p = 0;
 
@@ -6239,7 +6230,7 @@ with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
 
   /* Don't get confused by reusing the buffer used for echoing
      for a different purpose.  */
-  if (!echoing && EQ (buffer, echo_message_buffer))
+  if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
     cancel_echoing ();
 
   record_unwind_protect (unwind_with_echo_area_buffer,
@@ -6262,6 +6253,7 @@ with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
   current_buffer->undo_list = Qt;
   current_buffer->read_only = Qnil;
   specbind (Qinhibit_read_only, Qt);
+  specbind (Qinhibit_modification_hooks, Qt);
 
   if (clear_buffer_p && Z > BEG)
     del_range (BEG, Z);
@@ -7800,8 +7792,8 @@ tool_bar_lines_needed (f)
 
 DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
        0, 1, 0,
-  "Return the number of lines occupied by the tool bar of FRAME.")
-  (frame)
+       /* Return the number of lines occupied by the tool bar of FRAME.  */
+       (frame))
      Lisp_Object frame;
 {
   struct frame *f;
@@ -7996,6 +7988,7 @@ hscroll_window_tree (window)
                      &text_area_width, &text_area_height);
 
          /* Scroll when cursor is inside this scroll margin.  */
+         /* Shouldn't we export this `5' for customization ?  -stef  */
          hscroll_margin = 5 * CANON_X_UNIT (XFRAME (w->frame));
          
          if ((XFASTINT (w->hscroll)
@@ -9285,9 +9278,11 @@ run_window_scroll_functions (window, startp)
 
 
 /* Modify the desired matrix of window W and W->vscroll so that the
-   line containing the cursor is fully visible.  */
+   line containing the cursor is fully visible.  If this requires
+   larger matrices than are allocated, set fonts_changed_p and return
+   0.  */
 
-static void
+static int
 make_cursor_line_fully_visible (w)
      struct window *w;
 {
@@ -9298,7 +9293,7 @@ make_cursor_line_fully_visible (w)
   /* It's not always possible to find the cursor, e.g, when a window
      is full of overlay strings.  Don't do anything in that case.  */
   if (w->cursor.vpos < 0)
-    return;
+    return 1;
   
   matrix = w->desired_matrix;
   row = MATRIX_ROW (matrix, w->cursor.vpos);
@@ -9306,13 +9301,13 @@ make_cursor_line_fully_visible (w)
   /* If the cursor row is not partially visible, there's nothing
      to do.  */
   if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
-    return;
+    return 1;
 
   /* If the row the cursor is in is taller than the window's height,
      it's not clear what to do, so do nothing.  */
   window_height = window_box_height (w);
   if (row->height >= window_height)
-    return;
+    return 1;
 
   if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
     {
@@ -9335,6 +9330,16 @@ make_cursor_line_fully_visible (w)
      the correct y-position.  */
   if (w == XWINDOW (selected_window))
     this_line_y = w->cursor.y;
+
+  /* If vscrolling requires a larger glyph matrix, arrange for a fresh
+     redisplay with larger matrices.  */
+  if (matrix->nrows < required_matrix_height (w))
+    {
+      fonts_changed_p = 1;
+      return 0;
+    }
+
+  return 1;
 }
 
 
@@ -9353,6 +9358,13 @@ make_cursor_line_fully_visible (w)
    -1  if new fonts have been loaded so that we must interrupt
    redisplay, adjust glyph matrices, and try again.  */
 
+enum
+{
+  SCROLLING_SUCCESS,
+  SCROLLING_FAILED,
+  SCROLLING_NEED_LARGER_MATRICES
+};
+
 static int
 try_scrolling (window, just_this_one_p, scroll_conservatively,
               scroll_step, temp_scroll_step)
@@ -9442,7 +9454,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
       dy = 1 + it.current_y - y0;
       
       if (dy > scroll_max)
-       return 0;
+       return SCROLLING_FAILED;
       
       /* Move the window start down.  If scrolling conservatively,
         move it just enough down to make point visible.  If
@@ -9465,7 +9477,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
        }
 
       if (amount_to_scroll <= 0)
-       return 0;
+       return SCROLLING_FAILED;
 
       move_it_vertically (&it, amount_to_scroll);
       startp = it.current.pos;
@@ -9499,7 +9511,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
                      MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
          dy = it.current_y - y0;
          if (dy > scroll_max)
-           return 0;
+           return SCROLLING_FAILED;
          
          /* Compute new window start.  */
          start_display (&it, w, startp);
@@ -9519,7 +9531,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
            }
 
          if (amount_to_scroll <= 0)
-           return 0;
+           return SCROLLING_FAILED;
          
          move_it_vertically (&it, - amount_to_scroll);
          startp = it.current.pos;
@@ -9532,11 +9544,11 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   /* Display the window.  Give up if new fonts are loaded, or if point
      doesn't appear.  */
   if (!try_window (window, startp))
-    rc = -1;
+    rc = SCROLLING_NEED_LARGER_MATRICES;
   else if (w->cursor.vpos < 0)
     {
       clear_glyph_matrix (w->desired_matrix);
-      rc = 0;
+      rc = SCROLLING_FAILED;
     }
   else
     {
@@ -9547,9 +9559,12 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
        w->base_line_number = Qnil;
       
       /* If cursor ends up on a partially visible line, shift display
-        lines up or down.  */
-      make_cursor_line_fully_visible (w);
-      rc = 1;
+        lines up or down.  If that fails because we need larger
+        matrices, give up.  */
+      if (!make_cursor_line_fully_visible (w))
+       rc = SCROLLING_NEED_LARGER_MATRICES;
+      else
+       rc = SCROLLING_SUCCESS;
     }
 
   return rc;
@@ -9631,13 +9646,25 @@ compute_window_start_on_continuation_line (w)
 /* Try cursor movement in case text has not changes in window WINDOW,
    with window start STARTP.  Value is
 
-   1   if successful
+   CURSOR_MOVEMENT_SUCCESS if successful
    
-   0   if this method cannot be used
-   
-   -1  if we know we have to scroll the display.  *SCROLL_STEP is
-   set to 1, under certain circumstances, if we want to scroll as
-   if scroll-step were set to 1.  See the code.  */
+   CURSOR_MOVEMENT_CANNOT_BE_USED if this method cannot be used
+
+   CURSOR_MOVEMENT_MUST_SCROLL if we know we have to scroll the
+   display.  *SCROLL_STEP is set to 1, under certain circumstances, if
+   we want to scroll as if scroll-step were set to 1.  See the code.
+
+   CURSOR_MOVEMENT_NEED_LARGER_MATRICES if we need larger matrices, in
+   which case we have to abort this redisplay, and adjust matrices
+   first.  */
+
+enum 
+{
+  CURSOR_MOVEMENT_SUCCESS,
+  CURSOR_MOVEMENT_CANNOT_BE_USED,
+  CURSOR_MOVEMENT_MUST_SCROLL,
+  CURSOR_MOVEMENT_NEED_LARGER_MATRICES
+};
 
 static int
 try_cursor_movement (window, startp, scroll_step)
@@ -9647,7 +9674,7 @@ try_cursor_movement (window, startp, scroll_step)
 {
   struct window *w = XWINDOW (window);
   struct frame *f = XFRAME (w->frame);
-  int rc = 0;
+  int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
   
   /* Handle case where text has not changed, only point, and it has
      not moved off the frame.  */
@@ -9705,17 +9732,17 @@ try_cursor_movement (window, startp, scroll_step)
         not paused redisplay.  Give up if that row is not valid.  */
       if (w->last_cursor.vpos < 0
          || w->last_cursor.vpos >= w->current_matrix->nrows)
-       rc = -1;
+       rc = CURSOR_MOVEMENT_MUST_SCROLL;
       else
        {
          row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
          if (row->mode_line_p)
            ++row;
          if (!row->enabled_p)
-           rc = -1;
+           rc = CURSOR_MOVEMENT_MUST_SCROLL;
        }
 
-      if (rc == 0)
+      if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
        {
          int scroll_p = 0;
          int last_y = window_text_bottom_y (w) - this_scroll_margin;
@@ -9798,14 +9825,14 @@ try_cursor_movement (window, startp, scroll_step)
              || PT > MATRIX_ROW_END_CHARPOS (row))
            {
              /* if PT is not in the glyph row, give up.  */
-             rc = -1;
+             rc = CURSOR_MOVEMENT_MUST_SCROLL;
            }
          else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
            {
              if (PT == MATRIX_ROW_END_CHARPOS (row)
                  && !row->ends_at_zv_p
                  && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
-               rc = -1;
+               rc = CURSOR_MOVEMENT_MUST_SCROLL;
              else if (row->height > window_box_height (w))
                {
                  /* If we end up in a partially visible line, let's
@@ -9813,22 +9840,24 @@ try_cursor_movement (window, startp, scroll_step)
                     than the window, in which case we can't do much
                     about it.  */
                  *scroll_step = 1;
-                 rc = -1;
+                 rc = CURSOR_MOVEMENT_MUST_SCROLL;
                }
              else
                {
                  set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
                  try_window (window, startp);
-                 make_cursor_line_fully_visible (w);
-                 rc = 1;
+                 if (!make_cursor_line_fully_visible (w))
+                   rc = CURSOR_MOVEMENT_NEED_LARGER_MATRICES;
+                 else
+                   rc = CURSOR_MOVEMENT_SUCCESS;
                }
            }
          else if (scroll_p)
-           rc = -1;
+           rc = CURSOR_MOVEMENT_MUST_SCROLL;
          else
            {
              set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
-             rc = 1;
+             rc = CURSOR_MOVEMENT_SUCCESS;
            }
        }
     }
@@ -10102,11 +10131,12 @@ redisplay_window (window, just_this_one_p)
            {
              clear_glyph_matrix (w->desired_matrix);
              if (!try_window (window, startp))
-               goto finish_scroll_bars;
+               goto need_larger_matrices;
            }
        }
 
-      make_cursor_line_fully_visible (w);
+      if (!make_cursor_line_fully_visible (w))
+       goto need_larger_matrices;
 #if GLYPH_DEBUG
       debug_method_add (w, "forced window start");
 #endif
@@ -10117,12 +10147,22 @@ redisplay_window (window, just_this_one_p)
      not moved off the frame.  */
   if (current_matrix_up_to_date_p
       && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
-         rc != 0))
+         rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
     {
-      if (rc == -1)
-       goto try_to_scroll;
-      else
-       goto done;
+      switch (rc)
+       {
+       case CURSOR_MOVEMENT_SUCCESS:
+         goto done;
+         
+       case CURSOR_MOVEMENT_NEED_LARGER_MATRICES:
+         goto need_larger_matrices;
+         
+       case CURSOR_MOVEMENT_MUST_SCROLL:
+         goto try_to_scroll;
+         
+       default:
+         abort ();
+       }
     }
   /* If current starting point was originally the beginning of a line
      but no longer is, find a new starting point.  */
@@ -10146,7 +10186,7 @@ redisplay_window (window, just_this_one_p)
 #endif
 
       if (fonts_changed_p)
-       goto finish_scroll_bars;
+       goto need_larger_matrices;
       if (tem > 0)
        goto done;
 
@@ -10181,7 +10221,7 @@ redisplay_window (window, just_this_one_p)
        }
 
       if (fonts_changed_p)
-       goto finish_scroll_bars;
+       goto need_larger_matrices;
       
       if (w->cursor.vpos >= 0)
        {
@@ -10191,7 +10231,8 @@ redisplay_window (window, just_this_one_p)
            /* Forget any recorded base line for line number display.  */
            w->base_line_number = Qnil;
          
-         make_cursor_line_fully_visible (w);
+         if (!make_cursor_line_fully_visible (w))
+           goto need_larger_matrices;
          goto done;
        }
       else
@@ -10226,10 +10267,20 @@ redisplay_window (window, just_this_one_p)
                              scroll_conservatively,
                              scroll_step,
                              temp_scroll_step);
-      if (rc > 0)
-       goto done;
-      else if (rc < 0)
-       goto finish_scroll_bars;
+      switch (rc)
+       {
+       case SCROLLING_SUCCESS:
+         goto done;
+         
+       case SCROLLING_NEED_LARGER_MATRICES:
+         goto need_larger_matrices;
+         
+       case SCROLLING_FAILED:
+         break;
+         
+       default:
+         abort ();
+       }
     }
 
   /* Finally, just choose place to start which centers point */
@@ -10290,7 +10341,7 @@ redisplay_window (window, just_this_one_p)
      have to start a new redisplay since we need to re-adjust glyph
      matrices.  */
   if (fonts_changed_p)
-    goto finish_scroll_bars;
+    goto need_larger_matrices;
 
   /* If cursor did not appear assume that the middle of the window is
      in the first line of the window.  Do it again with the next line.
@@ -10330,7 +10381,8 @@ redisplay_window (window, just_this_one_p)
       set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
     }
   
-  make_cursor_line_fully_visible (w);
+  if (!make_cursor_line_fully_visible (w))
+    goto need_larger_matrices;
 
  done:
 
@@ -10357,13 +10409,7 @@ redisplay_window (window, just_this_one_p)
        && (WINDOW_WANTS_MODELINE_P (w)
           || WINDOW_WANTS_HEADER_LINE_P (w)))
     {
-      Lisp_Object old_selected_frame;
-      
-      old_selected_frame = selected_frame;
-      
-      XSETFRAME (selected_frame, f);
       display_mode_lines (w);
-      selected_frame = old_selected_frame;
 
       /* If mode line height has changed, arrange for a thorough
         immediate redisplay using the correct mode line height.  */
@@ -10386,7 +10432,7 @@ redisplay_window (window, just_this_one_p)
        }
 
       if (fonts_changed_p)
-       goto finish_scroll_bars;
+       goto need_larger_matrices;
     }
 
   if (!line_number_displayed
@@ -10426,6 +10472,8 @@ redisplay_window (window, just_this_one_p)
 #endif
     }
 
+ need_larger_matrices:
+  ;
  finish_scroll_bars:
 
   if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
@@ -11134,7 +11182,7 @@ sync_frame_with_window_matrix_rows (w)
    all rows to the end of the display area of W.  Value is the row
    containing CHARPOS or null.  */
 
-static struct glyph_row *
+struct glyph_row *
 row_containing_pos (w, charpos, start, end)
      struct window *w;
      int charpos;
@@ -11441,7 +11489,8 @@ try_window_id (w)
         for instance.  This is easier than to set up the iterator
         exactly, and it's not a frequent case, so the additional
         effort wouldn't really pay off.  */
-      while (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
+      while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
+             || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
             && last_unchanged_at_beg_row > w->current_matrix->rows)
        --last_unchanged_at_beg_row;
 
@@ -11489,8 +11538,23 @@ try_window_id (w)
   stop_pos = 0;
   if (first_unchanged_at_end_row)
     {
+#if GLYPH_DEBUG
       xassert (last_unchanged_at_beg_row == NULL
               || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
+#else
+      /* This is for the release of 21.1 only, and should be removed
+        after the release.
+
+        This case means that unchanged information is probably bogus,
+        which leads to being unable to compute a correct
+        first_unchanged_at_end_row.  At least that was the case in
+        one debugging session.  I've fixed a bug that can lead to
+        wrong unchanged info, but didn't find a way to reproduce this
+        case.  2001-09-18 gerd.  */
+      if (last_unchanged_at_beg_row 
+         && first_unchanged_at_end_row < last_unchanged_at_beg_row)
+       GIVE_UP (20);
+#endif
       
       /* If this is a continuation line, move forward to the next one
         that isn't.  Changes in lines above affect this line.
@@ -12097,11 +12161,11 @@ dump_glyph_row (row, vpos, glyphs)
 
 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
        Sdump_glyph_matrix, 0, 1, "p",
-  "Dump the current matrix of the selected window to stderr.\n\
-Shows contents of glyph row structures.  With non-nil\n\
-parameter GLYPHS, dump glyphs as well.  If GLYPHS is 1 show\n\
-glyphs in short form, otherwise show glyphs in long form.")
-  (glyphs)
+       /* Dump the current matrix of the selected window to stderr.
+Shows contents of glyph row structures.  With non-nil
+parameter GLYPHS, dump glyphs as well.  If GLYPHS is 1 show
+glyphs in short form, otherwise show glyphs in long form.  */
+       (glyphs))
      Lisp_Object glyphs;
 {
   struct window *w = XWINDOW (selected_window);
@@ -12119,11 +12183,11 @@ glyphs in short form, otherwise show glyphs in long form.")
 
 
 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "",
-  "Dump glyph row ROW to stderr.\n\
-GLYPH 0 means don't dump glyphs.\n\
-GLYPH 1 means dump glyphs in short form.\n\
-GLYPH > 1 or omitted means dump glyphs in long form.")
-  (row, glyphs)
+       /* Dump glyph row ROW to stderr.
+GLYPH 0 means don't dump glyphs.
+GLYPH 1 means dump glyphs in short form.
+GLYPH > 1 or omitted means dump glyphs in long form.  */
+       (row, glyphs))
      Lisp_Object row, glyphs;
 {
   struct glyph_matrix *matrix;
@@ -12141,11 +12205,11 @@ GLYPH > 1 or omitted means dump glyphs in long form.")
 
 
 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "",
-  "Dump glyph row ROW of the tool-bar of the current frame to stderr.\n\
-GLYPH 0 means don't dump glyphs.\n\
-GLYPH 1 means dump glyphs in short form.\n\
-GLYPH > 1 or omitted means dump glyphs in long form.")
-  (row, glyphs)
+  /* Dump glyph row ROW of the tool-bar of the current frame to stderr.
+GLYPH 0 means don't dump glyphs.
+GLYPH 1 means dump glyphs in short form.
+GLYPH > 1 or omitted means dump glyphs in long form.  */
+       (row, glyphs))
      Lisp_Object row, glyphs;
 {
   struct frame *sf = SELECTED_FRAME ();
@@ -12162,9 +12226,9 @@ GLYPH > 1 or omitted means dump glyphs in long form.")
 
 
 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
-  "Toggle tracing of redisplay.\n\
-With ARG, turn tracing on if and only if ARG is positive.")
-  (arg)
+       /* Toggle tracing of redisplay.
+With ARG, turn tracing on if and only if ARG is positive.  */
+       (arg))
      Lisp_Object arg;
 {
   if (NILP (arg))
@@ -12180,8 +12244,8 @@ With ARG, turn tracing on if and only if ARG is positive.")
 
 
 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
-   "Like `format', but print result to stderr.")
-   (nargs, args)
+       /* Like `format', but print result to stderr.  */
+       (nargs, args))
      int nargs;
      Lisp_Object *args;
 {
@@ -12935,6 +12999,8 @@ display_line (it)
        {
          int used_before = row->used[TEXT_AREA];
 
+         row->ends_in_newline_from_string_p = STRINGP (it->object);
+
          /* Add a space at the end of the line that is used to
             display the cursor there.  */
          append_space (it, 0);
@@ -13207,7 +13273,6 @@ redisplay_mode_lines (window, force)
               || FRAME_GARBAGED_P (XFRAME (w->frame))
               || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
        {
-         Lisp_Object old_selected_frame;
          struct text_pos lpoint;
          struct buffer *old = current_buffer;
 
@@ -13230,10 +13295,6 @@ redisplay_mode_lines (window, force)
                TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
            }
 
-         /* Temporarily set up the selected frame.  */
-         old_selected_frame = selected_frame;
-         selected_frame = w->frame;
-
          /* Display mode lines.  */
          clear_glyph_matrix (w->desired_matrix);
          if (display_mode_lines (w))
@@ -13243,7 +13304,6 @@ redisplay_mode_lines (window, force)
            }
 
          /* Restore old settings.  */
-         selected_frame = old_selected_frame;
          set_buffer_internal_1 (old);
          TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
        }
@@ -13262,7 +13322,13 @@ static int
 display_mode_lines (w)
      struct window *w;
 {
+  Lisp_Object old_selected_window, old_selected_frame;
   int n = 0;
+
+  old_selected_frame = selected_frame;
+  selected_frame = w->frame;
+  old_selected_window = selected_window;
+  XSETWINDOW (selected_window, w);
   
   /* These will be set while the mode line specs are processed.  */
   line_number_displayed = 0;
@@ -13282,6 +13348,8 @@ display_mode_lines (w)
       ++n;
     }
 
+  selected_frame = old_selected_frame;
+  selected_window = old_selected_window;
   return n;
 }
 
@@ -13407,7 +13475,8 @@ display_mode_element (it, depth, field_width, precision, elt)
                    int bytepos = last - lisp_string;
                    int charpos = string_byte_to_char (elt, bytepos);
                    n += display_string (NULL, elt, Qnil, 0, charpos,
-                                        it, 0, prec, 0, -1);
+                                        it, 0, prec, 0,
+                                        STRING_MULTIBYTE (elt));
                  }
              }
            else /* c == '%' */
@@ -13432,22 +13501,25 @@ display_mode_element (it, depth, field_width, precision, elt)
                                             Vglobal_mode_string);
                else if (c != 0)
                  {
+                   int multibyte;
                    unsigned char *spec
-                     = decode_mode_spec (it->w, c, field, prec);
-                   
+                     = decode_mode_spec (it->w, c, field, prec, &multibyte);
+
                    if (frame_title_ptr)
                      n += store_frame_title (spec, field, prec);
                    else
                      {
-                       int nglyphs_before
-                         = it->glyph_row->used[TEXT_AREA];
-                       int bytepos
-                         = percent_position - XSTRING (elt)->data;
-                       int charpos
-                         = string_byte_to_char (elt, bytepos);
-                       int nwritten
-                         = display_string (spec, Qnil, elt, charpos, 0, it,
-                                           field, prec, 0, -1);
+                       int nglyphs_before, bytepos, charpos, nwritten;
+                       
+                       nglyphs_before = it->glyph_row->used[TEXT_AREA];
+                       bytepos = percent_position - XSTRING (elt)->data;
+                       charpos = (multibyte
+                                  ? string_byte_to_char (elt, bytepos)
+                                  : bytepos);
+                       nwritten = display_string (spec, Qnil, elt,
+                                                  charpos, 0, it,
+                                                  field, prec, 0,
+                                                  multibyte);
 
                        /* Assign to the glyphs written above the
                           string where the `%x' came from, position
@@ -13494,7 +13566,7 @@ display_mode_element (it, depth, field_width, precision, elt)
                  n += store_frame_title (XSTRING (tem)->data, -1, prec);
                else
                  n += display_string (NULL, tem, Qnil, 0, 0, it,
-                                      0, prec, 0, -1);
+                                      0, prec, 0, STRING_MULTIBYTE (tem));
              }
            else if (!EQ (tem, elt))
              {
@@ -13743,15 +13815,17 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
 /* Return a string for the output of a mode line %-spec for window W,
    generated by character C.  PRECISION >= 0 means don't return a
    string longer than that value.  FIELD_WIDTH > 0 means pad the
-   string returned with spaces to that value.  */
+   string returned with spaces to that value.  Return 1 in *MULTIBYTE
+   if the result is multibyte text.  */
 
 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
 
 static char *
-decode_mode_spec (w, c, field_width, precision)
+decode_mode_spec (w, c, field_width, precision, multibyte)
      struct window *w;
      register int c;
      int field_width, precision;
+     int *multibyte;
 {
   Lisp_Object obj;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
@@ -13759,6 +13833,7 @@ decode_mode_spec (w, c, field_width, precision)
   struct buffer *b = XBUFFER (w->buffer);
 
   obj = Qnil;
+  *multibyte = 0;
 
   switch (c)
     {
@@ -14092,7 +14167,10 @@ decode_mode_spec (w, c, field_width, precision)
     }
 
   if (STRINGP (obj))
-    return (char *) XSTRING (obj)->data;
+    {
+      *multibyte = STRING_MULTIBYTE (obj);
+      return (char *) XSTRING (obj)->data;
+    }
   else
     return "";
 }
@@ -14421,11 +14499,13 @@ display_string (string, lisp_string, face_string, face_string_pos,
 
 
 \f
-/* This is like a combination of memq and assq.  Return 1 if PROPVAL
+/* This is like a combination of memq and assq.  Return 1/2 if PROPVAL
    appears as an element of LIST or as the car of an element of LIST.
    If PROPVAL is a list, compare each element against LIST in that
-   way, and return 1 if any element of PROPVAL is found in LIST.
-   Otherwise return 0.  This function cannot quit.  */
+   way, and return 1/2 if any element of PROPVAL is found in LIST.
+   Otherwise return 0.  This function cannot quit.
+   The return value is 2 if the text is invisible but with an ellipsis
+   and 1 if it's invisible and without an ellipsis.  */
 
 int
 invisible_p (propval, list)
@@ -14441,7 +14521,7 @@ invisible_p (propval, list)
       if (EQ (propval, tem))
        return 1;
       if (CONSP (tem) && EQ (propval, XCAR (tem)))
-       return 1;
+       return NILP (XCDR (tem)) ? 1 : 2;
     }
   
   if (CONSP (propval))
@@ -14457,7 +14537,7 @@ invisible_p (propval, list)
              if (EQ (propelt, tem))
                return 1;
              if (CONSP (tem) && EQ (propelt, XCAR (tem)))
-               return 1;
+               return NILP (XCDR (tem)) ? 1 : 2;
            }
        }
     }
@@ -14465,46 +14545,6 @@ invisible_p (propval, list)
   return 0;
 }
 
-
-/* Return 1 if PROPVAL appears as the car of an element of LIST and
-   the cdr of that element is non-nil.  If PROPVAL is a list, check
-   each element of PROPVAL in that way, and the first time some
-   element is found, return 1 if the cdr of that element is non-nil.
-   Otherwise return 0.  This function cannot quit.  */
-
-int
-invisible_ellipsis_p (propval, list)
-     register Lisp_Object propval;
-     Lisp_Object list;
-{
-  register Lisp_Object tail, proptail;
-  
-  for (tail = list; CONSP (tail); tail = XCDR (tail))
-    {
-      register Lisp_Object tem;
-      tem = XCAR (tail);
-      if (CONSP (tem) && EQ (propval, XCAR (tem)))
-       return ! NILP (XCDR (tem));
-    }
-  
-  if (CONSP (propval))
-    for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
-      {
-       Lisp_Object propelt;
-       propelt = XCAR (proptail);
-       for (tail = list; CONSP (tail); tail = XCDR (tail))
-         {
-           register Lisp_Object tem;
-           tem = XCAR (tail);
-           if (CONSP (tem) && EQ (propelt, XCAR (tem)))
-             return ! NILP (XCDR (tem));
-         }
-      }
-  
-  return 0;
-}
-
-
 \f
 /***********************************************************************
                            Initialization
@@ -14622,220 +14662,219 @@ syms_of_xdisp ()
   Vmessages_buffer_name = build_string ("*Messages*");
   staticpro (&Vmessages_buffer_name);
   
-  DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
-    "Non-nil means highlight trailing whitespace.\n\
-The face used for trailing whitespace is `trailing-whitespace'.");
+  DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace
+    /* Non-nil means highlight trailing whitespace.
+The face used for trailing whitespace is `trailing-whitespace'.  */);
   Vshow_trailing_whitespace = Qnil;
 
-  DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
-    "Non-nil means don't actually do any redisplay.\n\
-This is used for internal purposes.");
+  DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay
+    /* Non-nil means don't actually do any redisplay.
+This is used for internal purposes.  */);
   Vinhibit_redisplay = Qnil;
 
-  DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
-    "String (or mode line construct) included (normally) in `mode-line-format'.");
+  DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string
+    /* String (or mode line construct) included (normally) in `mode-line-format'.  */);
   Vglobal_mode_string = Qnil;
 
-  DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
-    "Marker for where to display an arrow on top of the buffer text.\n\
-This must be the beginning of a line in order to work.\n\
-See also `overlay-arrow-string'.");
+  DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position
+    /* Marker for where to display an arrow on top of the buffer text.
+This must be the beginning of a line in order to work.
+See also `overlay-arrow-string'.  */);
   Voverlay_arrow_position = Qnil;
 
-  DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
-    "String to display as an arrow.  See also `overlay-arrow-position'.");
+  DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string
+    /* String to display as an arrow.  See also `overlay-arrow-position'.  */);
   Voverlay_arrow_string = Qnil;
 
-  DEFVAR_INT ("scroll-step", &scroll_step,
-    "*The number of lines to try scrolling a window by when point moves out.\n\
-If that fails to bring point back on frame, point is centered instead.\n\
-If this is zero, point is always centered after it moves off frame.\n\
-If you want scrolling to always be a line at a time, you should set\n\
-  `scroll-conservatively' to a large value rather than set this to 1.");
-
-  DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
-    "*Scroll up to this many lines, to bring point back on screen.\n\
-A value of zero means to scroll the text to center point vertically\n\
-in the window.");
+  DEFVAR_INT ("scroll-step", &scroll_step
+    /* *The number of lines to try scrolling a window by when point moves out.
+If that fails to bring point back on frame, point is centered instead.
+If this is zero, point is always centered after it moves off frame.
+If you want scrolling to always be a line at a time, you should set
+`scroll-conservatively' to a large value rather than set this to 1.  */);
+
+  DEFVAR_INT ("scroll-conservatively", &scroll_conservatively
+    /* *Scroll up to this many lines, to bring point back on screen.
+A value of zero means to scroll the text to center point vertically
+in the window.  */);
   scroll_conservatively = 0;
 
-  DEFVAR_INT ("scroll-margin", &scroll_margin,
-    "*Number of lines of margin at the top and bottom of a window.\n\
-Recenter the window whenever point gets within this many lines\n\
-of the top or bottom of the window.");
+  DEFVAR_INT ("scroll-margin", &scroll_margin
+    /* *Number of lines of margin at the top and bottom of a window.
+Recenter the window whenever point gets within this many lines
+of the top or bottom of the window.  */);
   scroll_margin = 0;
 
 #if GLYPH_DEBUG
-  DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
+  DEFVAR_INT ("debug-end-pos", &debug_end_pos /* Don't ask.  */);
 #endif
 
   DEFVAR_BOOL ("truncate-partial-width-windows",
-              &truncate_partial_width_windows,
-    "*Non-nil means truncate lines in all windows less than full frame wide.");
+              &truncate_partial_width_windows
+    /* *Non-nil means truncate lines in all windows less than full frame wide.  */);
   truncate_partial_width_windows = 1;
 
-  DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
-    "nil means display the mode-line/header-line/menu-bar in the default face.\n\
-Any other value means to use the appropriate face, `mode-line',\n\
-`header-line', or `menu' respectively.\n\
-\n\
-This variable is deprecated; please change the above faces instead.");
+  DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video
+    /* nil means display the mode-line/header-line/menu-bar in the default face.
+Any other value means to use the appropriate face, `mode-line',
+`header-line', or `menu' respectively.
+
+This variable is deprecated; please change the above faces instead.  */);
   mode_line_inverse_video = 1;
 
-  DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
-    "*Maximum buffer size for which line number should be displayed.\n\
-If the buffer is bigger than this, the line number does not appear\n\
-in the mode line.  A value of nil means no limit.");
+  DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit
+    /* *Maximum buffer size for which line number should be displayed.
+If the buffer is bigger than this, the line number does not appear
+in the mode line.  A value of nil means no limit.  */);
   Vline_number_display_limit = Qnil;
 
   DEFVAR_INT ("line-number-display-limit-width",
-             &line_number_display_limit_width,
-    "*Maximum line width (in characters) for line number display.\n\
-If the average length of the lines near point is bigger than this, then the\n\
-line number may be omitted from the mode line.");
+             &line_number_display_limit_width
+    /* *Maximum line width (in characters) for line number display.
+If the average length of the lines near point is bigger than this, then the
+line number may be omitted from the mode line.  */);
   line_number_display_limit_width = 200;
 
-  DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
-    "*Non-nil means highlight region even in nonselected windows.");
+  DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows
+    /* *Non-nil means highlight region even in nonselected windows.  */);
   highlight_nonselected_windows = 0;
 
-  DEFVAR_BOOL ("multiple-frames", &multiple_frames,
-    "Non-nil if more than one frame is visible on this display.\n\
-Minibuffer-only frames don't count, but iconified frames do.\n\
-This variable is not guaranteed to be accurate except while processing\n\
-`frame-title-format' and `icon-title-format'.");
-
-  DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
-    "Template for displaying the title bar of visible frames.\n\
-\(Assuming the window manager supports this feature.)\n\
-This variable has the same structure as `mode-line-format' (which see),\n\
-and is used only on frames for which no explicit name has been set\n\
-\(see `modify-frame-parameters').");
-  DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
-    "Template for displaying the title bar of an iconified frame.\n\
-\(Assuming the window manager supports this feature.)\n\
-This variable has the same structure as `mode-line-format' (which see),\n\
-and is used only on frames for which no explicit name has been set\n\
-\(see `modify-frame-parameters').");
+  DEFVAR_BOOL ("multiple-frames", &multiple_frames
+    /* Non-nil if more than one frame is visible on this display.
+Minibuffer-only frames don't count, but iconified frames do.
+This variable is not guaranteed to be accurate except while processing
+`frame-title-format' and `icon-title-format'.  */);
+
+  DEFVAR_LISP ("frame-title-format", &Vframe_title_format
+    /* Template for displaying the title bar of visible frames.
+\(Assuming the window manager supports this feature.)
+This variable has the same structure as `mode-line-format' (which see),
+and is used only on frames for which no explicit name has been set
+\(see `modify-frame-parameters').  */);
+  DEFVAR_LISP ("icon-title-format", &Vicon_title_format
+    /* Template for displaying the title bar of an iconified frame.
+\(Assuming the window manager supports this feature.)
+This variable has the same structure as `mode-line-format' (which see),
+and is used only on frames for which no explicit name has been set
+\(see `modify-frame-parameters').  */);
   Vicon_title_format
     = Vframe_title_format
     = Fcons (intern ("multiple-frames"),
             Fcons (build_string ("%b"),
-                   Fcons (Fcons (build_string (""),
+                   Fcons (Fcons (empty_string,
                                  Fcons (intern ("invocation-name"),
                                         Fcons (build_string ("@"),
                                                Fcons (intern ("system-name"),
                                                               Qnil)))),
                           Qnil)));
 
-  DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
-    "Maximum number of lines to keep in the message log buffer.\n\
-If nil, disable message logging.  If t, log messages but don't truncate\n\
-the buffer when it becomes large.");
+  DEFVAR_LISP ("message-log-max", &Vmessage_log_max
+    /* Maximum number of lines to keep in the message log buffer.
+If nil, disable message logging.  If t, log messages but don't truncate
+the buffer when it becomes large.  */);
   Vmessage_log_max = make_number (50);
 
-  DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
-    "Functions called before redisplay, if window sizes have changed.\n\
-The value should be a list of functions that take one argument.\n\
-Just before redisplay, for each frame, if any of its windows have changed\n\
-size since the last redisplay, or have been split or deleted,\n\
-all the functions in the list are called, with the frame as argument.");
+  DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions
+    /* Functions called before redisplay, if window sizes have changed.
+The value should be a list of functions that take one argument.
+Just before redisplay, for each frame, if any of its windows have changed
+size since the last redisplay, or have been split or deleted,
+all the functions in the list are called, with the frame as argument.  */);
   Vwindow_size_change_functions = Qnil;
 
-  DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
-    "List of Functions to call before redisplaying a window with scrolling.\n\
-Each function is called with two arguments, the window\n\
-and its new display-start position.  Note that the value of `window-end'\n\
-is not valid when these functions are called.");
+  DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions
+    /* List of Functions to call before redisplaying a window with scrolling.
+Each function is called with two arguments, the window
+and its new display-start position.  Note that the value of `window-end'
+is not valid when these functions are called.  */);
   Vwindow_scroll_functions = Qnil;
   
-  DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
-    "*Non-nil means automatically resize tool-bars.\n\
-This increases a tool-bar's height if not all tool-bar items are visible.\n\
-It decreases a tool-bar's height when it would display blank lines\n\
-otherwise.");
+  DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p
+    /* *Non-nil means automatically resize tool-bars.
+This increases a tool-bar's height if not all tool-bar items are visible.
+It decreases a tool-bar's height when it would display blank lines
+otherwise.  */);
   auto_resize_tool_bars_p = 1;
   
-  DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
-    "*Non-nil means raise tool-bar buttons when the mouse moves over them.");
+  DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p
+    /* *Non-nil means raise tool-bar buttons when the mouse moves over them.  */);
   auto_raise_tool_bar_buttons_p = 1;
 
-  DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
-    "*Margin around tool-bar buttons in pixels.\n\
-If an integer, use that for both horizontal and vertical margins.\n\
-Otherwise, value should be a pair of integers `(HORZ : VERT)' with\n\
-HORZ specifying the horizontal margin, and VERT specifying the\n\
-vertical margin.");
+  DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin
+    /* *Margin around tool-bar buttons in pixels.
+If an integer, use that for both horizontal and vertical margins.
+Otherwise, value should be a pair of integers `(HORZ : VERT)' with
+HORZ specifying the horizontal margin, and VERT specifying the
+vertical margin.  */);
   Vtool_bar_button_margin = make_number (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
 
-  DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
-    "Relief thickness of tool-bar buttons.");
+  DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief
+    /* Relief thickness of tool-bar buttons.  */);
   tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
 
-  DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
-    "List of functions to call to fontify regions of text.\n\
-Each function is called with one argument POS.  Functions must\n\
-fontify a region starting at POS in the current buffer, and give\n\
-fontified regions the property `fontified'.\n\
-This variable automatically becomes buffer-local when set.");
+  DEFVAR_LISP ("fontification-functions", &Vfontification_functions
+    /* List of functions to call to fontify regions of text.
+Each function is called with one argument POS.  Functions must
+fontify a region starting at POS in the current buffer, and give
+fontified regions the property `fontified'.  */);
   Vfontification_functions = Qnil;
   Fmake_variable_buffer_local (Qfontification_functions);
 
   DEFVAR_BOOL ("unibyte-display-via-language-environment",
-               &unibyte_display_via_language_environment,
-    "*Non-nil means display unibyte text according to language environment.\n\
-Specifically this means that unibyte non-ASCII characters\n\
-are displayed by converting them to the equivalent multibyte characters\n\
-according to the current language environment.  As a result, they are\n\
-displayed according to the current fontset.");
+               &unibyte_display_via_language_environment
+    /* *Non-nil means display unibyte text according to language environment.
+Specifically this means that unibyte non-ASCII characters
+are displayed by converting them to the equivalent multibyte characters
+according to the current language environment.  As a result, they are
+displayed according to the current fontset.  */);
   unibyte_display_via_language_environment = 0;
 
-  DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
-    "*Maximum height for resizing mini-windows.\n\
-If a float, it specifies a fraction of the mini-window frame's height.\n\
-If an integer, it specifies a number of lines.");
+  DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height
+    /* *Maximum height for resizing mini-windows.
+If a float, it specifies a fraction of the mini-window frame's height.
+If an integer, it specifies a number of lines.  */);
   Vmax_mini_window_height = make_float (0.25);
 
-  DEFVAR_LISP ("resize-mini-windows", &Vresize_mini_windows,
-    "*How to resize mini-windows.\n\
-A value of nil means don't automatically resize mini-windows.\n\
-A value of t means resize them to fit the text displayed in them.\n\
-A value of `grow-only', the default, means let mini-windows grow\n\
-only, until their display becomes empty, at which point the windows\n\
-go back to their normal size.");
+  DEFVAR_LISP ("resize-mini-windows", &Vresize_mini_windows
+    /* *How to resize mini-windows.
+A value of nil means don't automatically resize mini-windows.
+A value of t means resize them to fit the text displayed in them.
+A value of `grow-only', the default, means let mini-windows grow
+only, until their display becomes empty, at which point the windows
+go back to their normal size.  */);
   Vresize_mini_windows = Qgrow_only;
 
   DEFVAR_BOOL ("cursor-in-non-selected-windows",
-              &cursor_in_non_selected_windows,
-    "*Non-nil means display a hollow cursor in non-selected windows.\n\
-Nil means don't display a cursor there.");
+              &cursor_in_non_selected_windows
+    /* *Non-nil means display a hollow cursor in non-selected windows.
+Nil means don't display a cursor there.  */);
   cursor_in_non_selected_windows = 1;
   
-  DEFVAR_BOOL ("automatic-hscrolling", &automatic_hscrolling_p,
-    "*Non-nil means scroll the display automatically to make point visible.");
+  DEFVAR_BOOL ("automatic-hscrolling", &automatic_hscrolling_p
+    /* *Non-nil means scroll the display automatically to make point visible.  */);
   automatic_hscrolling_p = 1;
   
-  DEFVAR_LISP ("image-types", &Vimage_types,
-    "List of supported image types.\n\
-Each element of the list is a symbol for a supported image type.");
+  DEFVAR_LISP ("image-types", &Vimage_types
+    /* List of supported image types.
+Each element of the list is a symbol for a supported image type.  */);
   Vimage_types = Qnil;
   
-  DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
-    "If non-nil, messages are truncated instead of resizing the echo area.\n\
-Bind this around calls to `message' to let it take effect.");
+  DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines
+    /* If non-nil, messages are truncated instead of resizing the echo area.
+Bind this around calls to `message' to let it take effect.  */);
   message_truncate_lines = 0;
 
-  DEFVAR_LISP ("menu-bar-update-hook",  &Vmenu_bar_update_hook,
-    "Normal hook run for clicks on menu bar, before displaying a submenu.\n\
-Can be used to update submenus whose contents should vary.");
+  DEFVAR_LISP ("menu-bar-update-hook",  &Vmenu_bar_update_hook
+    /* Normal hook run for clicks on menu bar, before displaying a submenu.
+Can be used to update submenus whose contents should vary.  */);
   Vmenu_bar_update_hook = Qnil;
   
-  DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,
-    "Non-nil means don't update menu bars.  Internal use only.");
+  DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update
+    /* Non-nil means don't update menu bars.  Internal use only.  */);
   inhibit_menubar_update = 0;
 
-  DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
-    "Non-nil means don't eval Lisp during redisplay.");
+  DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay
+    /* Non-nil means don't eval Lisp during redisplay.  */);
   inhibit_eval_during_redisplay = 0;
 }