]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
(message_dolog): Update PT and ZV properly when at end of
[gnu-emacs] / src / xdisp.c
index 7384985dbc658bd0fc378a7858ba44a2cd8dd3e5..cc65fff9ae996b73a627ac6520300740a7c906d1 100644 (file)
@@ -1,5 +1,6 @@
 /* Display generation from window structure and buffer text.
-   Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
+   Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 1997
+     Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -113,6 +114,11 @@ Lisp_Object Voverlay_arrow_position;
 /* String to display for the arrow.  */
 Lisp_Object Voverlay_arrow_string;
 
+/* Values of those variables at last redisplay.
+   However, if Voverlay_arrow_position is a marker,
+   last_arrow_position is its numerical position.  */
+static Lisp_Object last_arrow_position, last_arrow_string;
+
 /* Like mode-line-format, but for the titlebar on a visible frame.  */
 Lisp_Object Vframe_title_format;
 
@@ -124,9 +130,6 @@ Lisp_Object Vicon_title_format;
    have changed.  */
 static Lisp_Object Vwindow_size_change_functions;
 
-/* Values of those variables at last redisplay.  */
-static Lisp_Object last_arrow_position, last_arrow_string;
-
 Lisp_Object Qmenu_bar_update_hook;
 
 /* Nonzero if overlay arrow has been displayed once in this window.  */
@@ -152,6 +155,10 @@ static int scroll_conservatively;
    of the top or bottom of the window.  */
 int scroll_margin;
 
+/* Number of characters of overlap to show,
+   when scrolling a one-line window such as a minibuffer.  */
+static int minibuffer_scroll_overlap;
+
 /* Nonzero if try_window_id has made blank lines at window bottom
  since the last redisplay that paused */
 static int blank_end_of_window;
@@ -210,6 +217,10 @@ int echo_area_glyphs_length;
    same window currently active as a minibuffer.  */
 Lisp_Object echo_area_window;
 
+/* Nonzero means multibyte characters were enabled when the echo area
+   message was specified.  */
+int message_enable_multibyte;
+
 /* true iff we should redraw the mode lines on the next redisplay */
 int update_mode_lines;
 
@@ -246,6 +257,9 @@ static int line_number_display_limit;
 /* Number of lines to keep in the message log buffer.
    t means infinite.  nil means don't log at all.  */
 Lisp_Object Vmessage_log_max;
+
+#define COERCE_MARKER(X)       \
+  (MARKERP ((X)) ? Fmarker_position (X) : (X))
 \f
 /* Output a newline in the *Messages* buffer if "needs" one.  */
 
@@ -271,6 +285,8 @@ message_dolog (m, len, nlflag)
       struct buffer *oldbuf;
       int oldpoint, oldbegv, oldzv;
       int old_windows_or_buffers_changed = windows_or_buffers_changed;
+      int point_at_end = 0;
+      int zv_at_end = 0;
 
       oldbuf = current_buffer;
       Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
@@ -281,12 +297,48 @@ message_dolog (m, len, nlflag)
       BEGV = BEG;
       ZV = Z;
       if (oldpoint == Z)
-       oldpoint += len + nlflag;
+       point_at_end = 1;
       if (oldzv == Z)
-       oldzv += len + nlflag;
+       zv_at_end = 1;
       TEMP_SET_PT (Z);
-      if (len)
+
+      /* Insert the string--maybe converting multibyte to single byte
+        or vice versa, so that all the text fits the buffer.  */
+      if (! NILP (oldbuf->enable_multibyte_characters)
+         && NILP (current_buffer->enable_multibyte_characters))
+       {
+         int c, i = 0, nbytes;
+         /* Convert a multibyte string to single-byte
+            for the *Message* buffer.  */
+         while (i < len)
+           {
+             c = STRING_CHAR (m + i, len - i);
+             i += XFASTINT (Fchar_bytes (make_number (c)));
+             /* Truncate the character to its last byte--we can only hope
+                the user is happy with the character he gets,
+                since if it isn't right, there is no way to do it right.  */
+             c &= 0xff;
+             insert_char (c);
+           }
+       }
+      else if (NILP (oldbuf->enable_multibyte_characters)
+              && ! NILP (current_buffer->enable_multibyte_characters))
+       {
+         int c, i = 0;
+         /* Convert a single-byte string to multibyte
+            for the *Message* buffer.  */
+         while (i < len)
+           {
+             c = m[i++];
+             /* Convert non-ascii chars as if for self-insert.  */
+             if (c >= 0200 && c <= 0377)
+               c += nonascii_insert_offset;
+             insert_char (c);
+           }
+       }
+      else if (len)
        insert_1 (m, len, 1, 0);
+
       if (nlflag)
        {
          int this_bol, prev_bol, dup;
@@ -336,8 +388,14 @@ message_dolog (m, len, nlflag)
            }
        }
       BEGV = oldbegv;
-      ZV = oldzv;
-      TEMP_SET_PT (oldpoint);
+      if (zv_at_end)
+       ZV = Z;
+      else
+       ZV = oldzv;
+      if (point_at_end)
+       TEMP_SET_PT (Z);
+      else
+       TEMP_SET_PT (oldpoint);
       set_buffer_internal (oldbuf);
       windows_or_buffers_changed = old_windows_or_buffers_changed;
       message_log_need_newline = !nlflag;
@@ -412,12 +470,16 @@ message2_nolog (m, len)
      char *m;
      int len;
 {
+  message_enable_multibyte
+    = ! NILP (current_buffer->enable_multibyte_characters);
+
   if (noninteractive)
     {
       if (noninteractive_need_newline)
        putc ('\n', stderr);
       noninteractive_need_newline = 0;
-      fwrite (m, len, 1, stderr);
+      if (m)
+       fwrite (m, len, 1, stderr);
       if (cursor_in_echo_area == 0)
        fprintf (stderr, "\n");
       fflush (stderr);
@@ -545,10 +607,10 @@ message (m, a1, a2, a3)
            {
              int len;
 #ifdef NO_ARG_ARRAY
-             EMACS_INT a[3];
-             a[0] = a1;
-             a[1] = a2;
-             a[2] = a3;
+             char *a[3];
+             a[0] = (char *) a1;
+             a[1] = (char *) a2;
+             a[2] = (char *) a3;
 
              len = doprnt (FRAME_MESSAGE_BUF (f),
                            FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
@@ -628,7 +690,9 @@ echo_area_display ()
                      echo_area_glyphs ? echo_area_glyphs : "",
                      echo_area_glyphs ? echo_area_glyphs_length : -1,
                      FRAME_LEFT_SCROLL_BAR_WIDTH (f),
-                     0, 0, 0, FRAME_WIDTH (f));
+                     0, 0, 0,
+                     FRAME_WIDTH (f) + FRAME_LEFT_SCROLL_BAR_WIDTH (f),
+                     message_enable_multibyte);
 
 #if 0 /* This just gets in the way.  update_frame does the job.  */
       /* If desired cursor location is on this line, put it at end of text */
@@ -646,10 +710,14 @@ echo_area_display ()
             i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++)
          {
            get_display_line (f, i, 0);
-           display_string (XWINDOW (mini_window), vpos,
+           /* We don't use FRAME_SCROLL_BAR_WIDTH (f) as the starting
+              hpos, because it is good to clear whatever is behind the
+              scroll bar.  This does not affect the scroll bar itself.  */
+           display_string (XWINDOW (mini_window), i,
                            "", 0, 
-                            FRAME_LEFT_SCROLL_BAR_WIDTH (f),
-                           0, 0, 0, FRAME_WIDTH (f));
+                            0, 0, 0,
+                            0, FRAME_WIDTH (f) + FRAME_SCROLL_BAR_WIDTH (f),
+                           0);
          }
       }
     }
@@ -864,6 +932,7 @@ redisplay_internal (preserve_echo_area)
   int all_windows;
   register int tlbufpos, tlendpos;
   struct position pos;
+  int number_of_visible_frames;
 
   if (noninteractive)
     return;
@@ -873,6 +942,8 @@ redisplay_internal (preserve_echo_area)
     return;
 #endif
 
+ retry:
+
   if (! FRAME_WINDOW_P (selected_frame)
       && previous_terminal_frame != selected_frame)
     {
@@ -891,10 +962,15 @@ redisplay_internal (preserve_echo_area)
   {
     Lisp_Object tail, frame;
 
+    number_of_visible_frames = 0;
+
     FOR_EACH_FRAME (tail, frame)
       {
        FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
 
+       if (FRAME_VISIBLE_P (XFRAME (frame)))
+         number_of_visible_frames++;
+
        /* Clear out all the display lines in which we will generate the
           glyphs to display.  */
        init_desired_glyphs (XFRAME (frame));
@@ -939,7 +1015,7 @@ redisplay_internal (preserve_echo_area)
 
   /* If specs for an arrow have changed, do thorough redisplay
      to ensure we remove any arrow that should no longer exist.  */
-  if (! EQ (Voverlay_arrow_position, last_arrow_position)
+  if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
       || ! EQ (Voverlay_arrow_string, last_arrow_string))
     all_windows = 1;
 
@@ -967,6 +1043,7 @@ redisplay_internal (preserve_echo_area)
   if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
       && !current_buffer->clip_changed
       && FRAME_VISIBLE_P (XFRAME (w->frame))
+      && !FRAME_OBSCURED_P (XFRAME (w->frame))
       /* Make sure recorded data applies to current buffer, etc */
       && this_line_buffer == current_buffer
       && current_buffer == XBUFFER (w->buffer)
@@ -1086,7 +1163,8 @@ redisplay_internal (preserve_echo_area)
         then we can't just move the cursor.  */
       else if (! (!NILP (Vtransient_mark_mode)
                  && !NILP (current_buffer->mark_active))
-              && w == XWINDOW (current_buffer->last_selected_window)
+              && (w == XWINDOW (current_buffer->last_selected_window)
+                  || highlight_nonselected_windows)
               && NILP (w->region_showing)
               && !cursor_in_echo_area)
        {
@@ -1147,7 +1225,7 @@ redisplay_internal (preserve_echo_area)
              if (condemn_scroll_bars_hook)
                (*condemn_scroll_bars_hook) (f);
 
-             if (FRAME_VISIBLE_P (f))
+             if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
                redisplay_windows (FRAME_ROOT_WINDOW (f), preserve_echo_area);
 
              /* Any scroll bars which redisplay_windows should have nuked
@@ -1157,7 +1235,7 @@ redisplay_internal (preserve_echo_area)
            }
        }
     }
-  else if (FRAME_VISIBLE_P (selected_frame))
+  else if (FRAME_VISIBLE_P (selected_frame) && !FRAME_OBSCURED_P (selected_frame))
     {
       redisplay_window (selected_window, 1, preserve_echo_area);
       if (!WINDOW_FULL_WIDTH_P (w))
@@ -1188,7 +1266,7 @@ update:
          f = XFRAME (XCONS (tail)->car);
 
          if ((FRAME_WINDOW_P (f) || f == selected_frame)
-             && FRAME_VISIBLE_P (f))
+             && FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
            {
              pause |= update_frame (f, 0, 0);
              if (!pause)
@@ -1202,7 +1280,7 @@ update:
     }
   else
     {
-      if (FRAME_VISIBLE_P (selected_frame))
+      if (FRAME_VISIBLE_P (selected_frame) && !FRAME_OBSCURED_P (selected_frame))
        pause = update_frame (selected_frame, 0, 0);
       else
        pause = 0;
@@ -1270,8 +1348,18 @@ update:
          w->last_had_star
            = (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
               ? Qt : Qnil);
+
+         /* Record if we are showing a region, so can make sure to
+            update it fully at next redisplay.  */
+         w->region_showing = (!NILP (Vtransient_mark_mode)
+                              && (w == XWINDOW (current_buffer->last_selected_window)
+                                  || highlight_nonselected_windows)
+                              && !NILP (XBUFFER (w->buffer)->mark_active)
+                              ? Fmarker_position (XBUFFER (w->buffer)->mark)
+                              : Qnil);
+
          w->window_end_valid = w->buffer;
-         last_arrow_position = Voverlay_arrow_position;
+         last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
          last_arrow_string = Voverlay_arrow_string;
          if (do_verify_charstarts)
            verify_charstarts (w);
@@ -1293,13 +1381,38 @@ update:
     request_sigio ();
   start_polling ();
 
+  /* If something has become visible now which was not before,
+     redisplay again, so that we get them.  */
+  if (!pause)
+    {
+      Lisp_Object tail, frame;
+      int new_count = 0;
+
+      FOR_EACH_FRAME (tail, frame)
+       {
+         int this_is_visible = 0;
+
+         if (XFRAME (frame)->visible)
+           this_is_visible = 1;
+         FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
+         if (XFRAME (frame)->visible)
+           this_is_visible = 1;
+
+         if (this_is_visible)
+           new_count++;
+       }
+
+      if (new_count != number_of_visible_frames)
+       windows_or_buffers_changed++;
+    }
+
   /* Change frame size now if a change is pending.  */
   do_pending_window_change ();
 
-  /* If we just did a pending size change, redisplay again
-     for the new size.  */
+  /* If we just did a pending size change, or have additional
+     visible frames, redisplay again.  */
   if (windows_or_buffers_changed && !pause)
-    redisplay ();
+    goto retry;
 }
 
 /* Redisplay, but leave alone any recent echo area message
@@ -1310,6 +1423,7 @@ update:
    area to be cleared.  See tracking_off and
    wait_reading_process_input for examples of these situations.  */
 
+void
 redisplay_preserve_echo_area ()
 {
   if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
@@ -1347,7 +1461,8 @@ mark_window_display_accurate (window, flag)
          /* Record if we are showing a region, so can make sure to
             update it fully at next redisplay.  */
          w->region_showing = (!NILP (Vtransient_mark_mode)
-                              && w == XWINDOW (current_buffer->last_selected_window)
+                              && (w == XWINDOW (current_buffer->last_selected_window)
+                                  || highlight_nonselected_windows)
                               && !NILP (XBUFFER (w->buffer)->mark_active)
                               ? Fmarker_position (XBUFFER (w->buffer)->mark)
                               : Qnil);
@@ -1366,7 +1481,7 @@ mark_window_display_accurate (window, flag)
 
   if (flag)
     {
-      last_arrow_position = Voverlay_arrow_position;
+      last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
       last_arrow_string = Voverlay_arrow_string;
     }
   else
@@ -1476,6 +1591,43 @@ redisplay_windows (window, preserve_echo_area)
     redisplay_window (window, 0, preserve_echo_area);
 }
 
+/* Return value in display table DP (Lisp_Char_Table *) for character
+   C.  Since a display table doesn't have any parent, we don't have to
+   follow parent.  Do not call this function directly but use the
+   macro DISP_CHAR_VECTOR.  */
+Lisp_Object
+disp_char_vector (dp, c)
+     struct Lisp_Char_Table *dp;
+     int c;
+{
+  int code[4], i;
+  Lisp_Object val;
+
+  if (SINGLE_BYTE_CHAR_P (c)) return (dp->contents[c]);
+  
+  SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]);
+  if (code[0] != CHARSET_COMPOSITION)
+    {
+      if (code[1] < 32) code[1] = -1;
+      else if (code[2] < 32) code[2] = -1;
+    }
+  /* Here, the possible range of CODE[0] (== charset ID) is
+     128..MAX_CHARSET.  Since the top level char table contains data
+     for multibyte characters after 256th element, we must increment
+     CODE[0] by 128 to get a correct index.  */
+  code[0] += 128;
+  code[3] = -1;                /* anchor */
+
+  for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
+    {
+      val = dp->contents[code[i]];
+      if (!SUB_CHAR_TABLE_P (val))
+       return (NILP (val) ? dp->defalt : val);
+    }
+  /* Here, VAL is a sub char table.  We return the default value of it.  */
+  return (dp->defalt);
+}
+
 /* Redisplay window WINDOW and its subwindows.  */
 
 static void
@@ -1536,7 +1688,7 @@ redisplay_window (window, just_this_one, preserve_echo_area)
              get_display_line (f, vpos + i, 0);
              display_string (w, vpos + i, "", 0, 
                              FRAME_LEFT_SCROLL_BAR_WIDTH (f),
-                             0, 1, 0, width);
+                             0, 1, 0, width, 0);
            }
          
          goto finish_scroll_bars;
@@ -1741,17 +1893,51 @@ redisplay_window (window, just_this_one, preserve_echo_area)
       /* If end pos is out of date, scroll bar and percentage will be wrong */
       && INTEGERP (w->window_end_vpos)
       && XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
-      && !EQ (window, minibuf_window))
+      && !EQ (window, minibuf_window)
+      && (!MARKERP (Voverlay_arrow_position)
+         || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
     {
+      /* All positions in this clause are relative to the window edge.  */
+
       int this_scroll_margin = scroll_margin;
+      int last_point_y = XFASTINT (w->last_point_y) - XINT (w->top);
+      int last_point_x = (XFASTINT (w->last_point_x) - WINDOW_LEFT_MARGIN (w));
 
-      pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
-                            PT, height,
-                            /* BUG FIX: See the comment of
-                                Fpos_visible_in_window_p (window.c).  */
-                            - (1 << (BITS_PER_SHORT - 1)),
-                            width, hscroll,
-                            pos_tab_offset (w, startp), w);
+      /* Find where PT is located now on the frame.  */
+      /* Check just_this_one as a way of verifying that the 
+        window edges have not changed.  */
+      if (PT == XFASTINT (w->last_point) && just_this_one)
+       {
+         pos.hpos = last_point_x;
+         pos.vpos = last_point_y;
+         pos.bufpos = PT;
+       }
+      else if (PT > XFASTINT (w->last_point)
+              && XFASTINT (w->last_point) > startp && just_this_one
+              /* We can't use this if point is in the left margin of a
+                 hscrolled window, because w->last_point_x has been
+                 clipped to the window edges.  */
+              && !(last_point_x <= 0 && hscroll))
+       {
+         pos = *compute_motion (XFASTINT (w->last_point),
+                                last_point_y, last_point_x, 0,
+                                PT, height,
+                                /* BUG FIX: See the comment of
+                                   Fpos_visible_in_window_p (window.c).  */
+                                - (1 << (BITS_PER_SHORT - 1)),
+                                width, hscroll,
+                                pos_tab_offset (w, startp), w);
+       }
+      else
+       {
+         pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
+                                PT, height,
+                                /* BUG FIX: See the comment of
+                                   Fpos_visible_in_window_p (window.c).  */
+                                - (1 << (BITS_PER_SHORT - 1)),
+                                width, hscroll,
+                                pos_tab_offset (w, startp), w);
+       }
 
       /* Don't use a scroll margin that is negative or too large.  */
       if (this_scroll_margin < 0)
@@ -1780,6 +1966,11 @@ redisplay_window (window, just_this_one, preserve_echo_area)
             if (WINDOW_FULL_WIDTH_P (w))
             preserve_my_columns (w);
             */
+         if (current_buffer->clip_changed
+             && ! NILP (Vwindow_scroll_functions))
+           run_hook_with_args_2 (Qwindow_scroll_functions, window,
+                                 make_number (marker_position (w->start)));
+
          goto done;
        }
       /* Don't bother trying redisplay with same start;
@@ -1809,7 +2000,7 @@ redisplay_window (window, just_this_one, preserve_echo_area)
              doesn't display as the end of a line.  */
           && !(dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, '\n')))
           && NILP (w->region_showing)
-          && EQ (last_arrow_position, Voverlay_arrow_position)
+          && EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
           && EQ (last_arrow_string, Voverlay_arrow_string)
           && (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
           && tem != -2)
@@ -1844,6 +2035,12 @@ redisplay_window (window, just_this_one, preserve_echo_area)
              || beg_unchanged < startp)
            /* Forget any recorded base line for line number display.  */
            w->base_line_number = Qnil;
+
+         if (current_buffer->clip_changed
+             && ! NILP (Vwindow_scroll_functions))
+           run_hook_with_args_2 (Qwindow_scroll_functions, window,
+                                 make_number (marker_position (w->start)));
+
          goto done;
        }
       else
@@ -1867,25 +2064,32 @@ redisplay_window (window, just_this_one, preserve_echo_area)
       && startp >= BEGV && startp <= ZV)
     {
       int this_scroll_margin = scroll_margin;
+      int scroll_margin_pos;
 
       /* Don't use a scroll margin that is negative or too large.  */
       if (this_scroll_margin < 0)
        this_scroll_margin = 0;
 
-      if (XINT (w->height) < 4 * scroll_margin)
+      if (XINT (w->height) < 4 * this_scroll_margin)
        this_scroll_margin = XINT (w->height) / 4;
 
-      if (PT >= Z - XFASTINT (w->window_end_pos))
+      scroll_margin_pos = Z - XFASTINT (w->window_end_pos);
+      if (this_scroll_margin)
+       {
+         pos = *vmotion (scroll_margin_pos, -this_scroll_margin, w);
+         scroll_margin_pos = pos.bufpos;
+       }
+      if (PT >= scroll_margin_pos)
        {
          struct position pos;
-         pos = *compute_motion (Z - XFASTINT (w->window_end_pos), 0, 0, 0,
+         pos = *compute_motion (scroll_margin_pos, 0, 0, 0,
                                 PT, XFASTINT (w->height), 0,
                                 XFASTINT (w->width), XFASTINT (w->hscroll),
                                 pos_tab_offset (w, startp), w);
          if (pos.vpos > scroll_conservatively)
            goto scroll_fail_1;
 
-         pos = *vmotion (startp, pos.vpos + 1 + this_scroll_margin, w);
+         pos = *vmotion (startp, pos.vpos + 1, w);
 
          if (! NILP (Vwindow_scroll_functions))
            {
@@ -1906,17 +2110,24 @@ redisplay_window (window, just_this_one, preserve_echo_area)
          else
            cancel_my_columns (w);
        }
-      if (PT < startp)
+
+      scroll_margin_pos = startp;
+      if (this_scroll_margin)
+       {
+         pos = *vmotion (scroll_margin_pos, this_scroll_margin, w);
+         scroll_margin_pos = pos.bufpos;
+       }
+      if (PT < scroll_margin_pos)
        {
          struct position pos;
          pos = *compute_motion (PT, 0, 0, 0,
-                                startp, XFASTINT (w->height), 0,
+                                scroll_margin_pos, XFASTINT (w->height), 0,
                                 XFASTINT (w->width), XFASTINT (w->hscroll),
                                 pos_tab_offset (w, startp), w);
-         if (pos.vpos >= scroll_conservatively)
+         if (pos.vpos > scroll_conservatively)
            goto scroll_fail_1;
 
-         pos = *vmotion (startp, - pos.vpos - this_scroll_margin, w);
+         pos = *vmotion (startp, -pos.vpos, w);
 
          if (! NILP (Vwindow_scroll_functions))
            {
@@ -1983,6 +2194,20 @@ recenter:
   w->base_line_number = Qnil;
 
   pos = *vmotion (PT, - (height / 2), w);
+
+  /* The minibuffer is often just one line.  Ordinary scrolling
+     gives little overlap and looks bad.  So show 20 chars before point.  */
+  if (height == 1
+      && (pos.bufpos >= PT - minibuffer_scroll_overlap
+         /* If we scrolled less than 1/2 line forward, we will
+            get too much overlap, so change to the usual amount.  */
+         || pos.bufpos < startp + width / 2)
+      && PT > BEGV + minibuffer_scroll_overlap
+      /* If we scrolled to an actual line boundary,
+        that's different; don't ignore line boundaries.  */
+      && FETCH_CHAR (pos.bufpos - 1) != '\n')
+    pos.bufpos = PT - minibuffer_scroll_overlap;
+    
   /* Set startp here explicitly in case that helps avoid an infinite loop
      in case the window-scroll-functions functions get errors.  */
   Fset_marker (w->start, make_number (pos.bufpos), Qnil);
@@ -2617,8 +2842,13 @@ copy_part_of_rope (f, to, s, from, len, face)
   if (! FRAME_TERMCAP_P (f))
     while (n--)
       {
-       int glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
+       GLYPH glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
        int facecode;
+       unsigned int c = FAST_GLYPH_CHAR (glyph);
+
+       if (c > MAX_CHAR)
+         /* For an invalid character code, use space.  */
+         c = ' ';
 
        if (FAST_GLYPH_FACE (glyph) == 0)
          /* If GLYPH has no face code, use FACE.  */
@@ -2634,7 +2864,7 @@ copy_part_of_rope (f, to, s, from, len, face)
          }
 
        if (to >= s)
-         *to = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), facecode);
+         *to = FAST_MAKE_GLYPH (c, facecode);
        ++to;
        ++fp;
       }
@@ -2728,10 +2958,10 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
                      && !WINDOW_FULL_WIDTH_P (w))
                  || !NILP (current_buffer->truncate_lines));
 
-  /* 1 if we should highlight the region.  */
+  /* 1 if this buffer has a region to highlight.  */
   int highlight_region
     = (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)
-       && XWINDOW (current_buffer->last_selected_window) == w);
+       && XMARKER (current_buffer->mark)->buffer != 0);
   int region_beg, region_end;
 
   int selective = (INTEGERP (current_buffer->selective_display)
@@ -2757,8 +2987,10 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
        : default_invis_vector);
 
   GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
+                    || !GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (dp)))
                     ? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
   GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
+                    || !GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (dp)))
                     ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
 
   /* If 1, we must handle multibyte characters.  */
@@ -2785,15 +3017,16 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
   XSETFASTINT (default_invis_vector[2], '.');
   default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
 
-  hpos += WINDOW_LEFT_MARGIN (w);
   get_display_line (f, vpos, WINDOW_LEFT_MARGIN (w));
   if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
 
   /* Show where to highlight the region.  */
-  if (highlight_region && XMARKER (current_buffer->mark)->buffer != 0
+  if (highlight_region
       /* Maybe highlight only in selected window.  */
       && (highlight_nonselected_windows
-         || w == XWINDOW (selected_window)))
+         || w == XWINDOW (selected_window)
+         || (MINI_WINDOW_P (XWINDOW (selected_window))
+             && w == XWINDOW (Vminibuf_scroll_window))))
     {
       region_beg = marker_position (current_buffer->mark);
       if (PT < region_beg)
@@ -2806,7 +3039,10 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
       w->region_showing = Qt;
     }
   else
-    region_beg = region_end = -1;
+    {
+      region_beg = region_end = -1;
+      w->region_showing = Qnil;
+    }
 
   if (MINI_WINDOW_P (w)
       && start == BEG
@@ -2814,19 +3050,24 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
     {
       if (! NILP (minibuf_prompt))
        {
+         int old_width = minibuf_prompt_width;
+
          minibuf_prompt_width
            = (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
-                              XSTRING (minibuf_prompt)->size, hpos,
+                              XSTRING (minibuf_prompt)->size,
+                              hpos + WINDOW_LEFT_MARGIN (w),
                               /* Display a space if we truncate.  */
                               ' ',
                               1, -1,
                               /* Truncate the prompt a little before the
                                  margin, so user input can at least start
                                  on the first line.  */
-                              w->width > 10 ? w->width - 4 : -1)
-              - hpos);
+                              (XFASTINT (w->width) > 10
+                               ? XFASTINT (w->width) - 4 : -1),
+                              -1)
+              - hpos - WINDOW_LEFT_MARGIN (w));
          hpos += minibuf_prompt_width;
-         taboffset -= minibuf_prompt_width;
+         taboffset -= minibuf_prompt_width - old_width;
        }
       else
        minibuf_prompt_width = 0;
@@ -2866,6 +3107,8 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
         }
     }
 
+  hpos += WINDOW_LEFT_MARGIN (w);
+
   desired_glyphs->bufp[vpos] = start;
   p1 = desired_glyphs->glyphs[vpos] + hpos;
   p1start = p1;
@@ -2891,7 +3134,17 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
   next_boundary = pos;
   p1prev = p1;
   prevpos = pos;
-  while (1)
+
+  /* If the window is hscrolled and point is in the invisible part of the
+     current line beyond the left margin we can record the cursor location
+     right away.  */
+  if (hscroll && start <= PT && PT < pos && cursor_vpos < 0)
+    {
+      cursor_vpos = vpos;
+      cursor_hpos = p1 - leftmargin;
+    }
+
+  while (p1 < endp)
     {
       if (pos >= pause)
        {
@@ -3113,6 +3366,12 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
        }
       else if (c == '\n')
        {
+#if 0
+         /* Same as p1prev, but after the invis_vector_contents text
+            (if we have that on this line).  */
+         GLYPH *p1prev_modified;
+#endif
+
          invis = 0;
          if (last_invis_skip == pos
              && TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
@@ -3128,23 +3387,30 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
            }
          if (invis && selective_rlen > 0 && p1 >= leftmargin)
            {
+#if 0
+             GLYPH *cs, *csend;
+
+             cs = charstart + (p1 - p1start);
+#endif
+
              p1 += selective_rlen;
              if (p1 - leftmargin > width)
                p1 = endp;
+
+#if 0 /* This needs more work; charstarts needs to record
+        both whether a position ho;ds an ellipsis character
+        and what buffer position it corresponds to.  */
+             csend = charstart + (p1 - p1start);
+             while (cs != csend)
+               *cs++ = -2;
+             /* The idea is to use p1prev_modified instead of p1prev
+                in the loop below over p2x.  */
+             p1prev_modified = p1;
+#endif
+
              copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
                                 (p1 - p1prev), current_face, rev_dir_bit);
            }
-#ifdef HAVE_FACES
-         /* Draw the face of the newline character as extending all the 
-            way to the end of the frame line.  */
-         if (current_face)
-           {
-             if (p1 < leftmargin)
-               p1 = leftmargin;
-             while (p1 < endp)
-               *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
-           }
-#endif
 
          /* Update charstarts for the newline that ended this line.  */
          /* Do nothing here for a char that's entirely off the left edge
@@ -3163,6 +3429,17 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
              while (p2x < p2)
                *p2x++ = -1;
            }
+#ifdef HAVE_FACES
+         /* Draw the face of the newline character as extending all the 
+            way to the end of the frame line.  */
+         if (current_face)
+           {
+             if (p1 < leftmargin)
+               p1 = leftmargin;
+             while (p1 < endp)
+               *p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
+           }
+#endif
 
          break;
        }
@@ -3224,9 +3501,11 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
       else if (c < 0200 && ctl_arrow)
        {
          if (p1 >= leftmargin)
-           *p1 = (fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
-                                 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
-                             current_face)
+           *p1 = (fix_glyph
+                  (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
+                       && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp)))
+                       ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
+                   current_face)
                   | rev_dir_bit);
          p1++;
          if (p1 >= leftmargin && p1 < endp)
@@ -3237,9 +3516,11 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
        {
          /* C is not a multibyte character.  */
          if (p1 >= leftmargin)
-           *p1 = (fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
-                                 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
-                             current_face)
+           *p1 = (fix_glyph
+                  (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
+                       && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp)))
+                       ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
+                   current_face)
                   | rev_dir_bit);
          p1++;
          if (p1 >= leftmargin && p1 < endp)
@@ -3443,7 +3724,7 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
                  this_line_bufpos = start;
                  this_line_buffer = current_buffer;
                  this_line_vpos = cursor_vpos;
-                 this_line_start_hpos = hpos;
+                 this_line_start_hpos = hpos - WINDOW_LEFT_MARGIN (w);
                  this_line_endpos = Z - lastpos;
                }
              else
@@ -3485,7 +3766,7 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
        }
       else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
        *p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
-                ? DISP_BORDER_GLYPH (dp)
+                ? XINT (DISP_BORDER_GLYPH (dp))
                 : '|');
     }
   desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
@@ -3554,7 +3835,7 @@ display_menu_bar (w)
   Lisp_Object items, tail;
   register int vpos = 0;
   register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
-  int maxendcol = FRAME_WIDTH (f);
+  int maxendcol = FRAME_WIDTH (f) + WINDOW_LEFT_MARGIN (w);
   int hpos = 0;
   int i;
 
@@ -3581,16 +3862,16 @@ display_menu_bar (w)
       XSETFASTINT (XVECTOR (items)->contents[i + 3], hpos);
 
       if (hpos < maxendcol)
-       hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
+       hpos = display_string (w, vpos,
                               XSTRING (string)->data,
                               XSTRING (string)->size,
-                              hpos, 0, 0, hpos, maxendcol);
+                              hpos, 0, 0, hpos, maxendcol, -1);
       /* Put a space between items.  */
       if (hpos < maxendcol)
        {
          int hpos1 = hpos + 1;
          hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
-                                min (hpos1, maxendcol), maxendcol);
+                                min (hpos1, maxendcol), maxendcol, 0);
        }
     }
 
@@ -3599,7 +3880,7 @@ display_menu_bar (w)
 
   /* Fill out the line with spaces.  */
   if (maxendcol > hpos)
-    hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol);
+    hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol, 0);
 
   /* Clear the rest of the lines allocated to the menu bar.  */
   vpos++;
@@ -3724,7 +4005,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
                  hpos = store_frame_title (last, hpos, min (lim, maxendcol));
                else
                  hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
-                                        hpos, min (lim, maxendcol));
+                                        hpos, min (lim, maxendcol), -1);
              }
            else /* c == '%' */
              {
@@ -3761,7 +4042,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
                    else
                      hpos = display_string (w, vpos, spec, -1,
                                             hpos, 0, 1,
-                                            minendcol, maxendcol);
+                                            minendcol, maxendcol, -1);
                  }
              }
          }
@@ -3789,7 +4070,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
                else
                  hpos = display_string (w, vpos, XSTRING (tem)->data,
                                         XSTRING (tem)->size,
-                                        hpos, 0, 1, minendcol, maxendcol);
+                                        hpos, 0, 1, minendcol, maxendcol, -1);
              }
            /* Give up right away for nil or t.  */
            else if (!EQ (tem, elt))
@@ -3883,7 +4164,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
        hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
       else
        hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
-                              minendcol, maxendcol);
+                              minendcol, maxendcol, 0);
       return hpos;
     }
 
@@ -3891,7 +4172,8 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
     if (frame_title_ptr)
       hpos = store_frame_title ("", minendcol, maxendcol);
     else
-      hpos = display_string (w, vpos, "", 0, hpos, 0, 1, minendcol, maxendcol);
+      hpos = display_string (w, vpos, "", 0, hpos,
+                            0, 1, minendcol, maxendcol, 0);
   return hpos;
 }
 \f
@@ -3934,31 +4216,53 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
      register char *buf;
      int eol_flag;
 {
-  register Lisp_Object val = coding_system;
+  Lisp_Object val;
+  int multibyte = !NILP (current_buffer->enable_multibyte_characters);
+
+  val = coding_system;
 
   if (NILP (val))              /* Not yet decided.  */
     {
-      *buf++ = '-';
-      if (eol_flag) *buf++ = eol_mnemonic_undecided;
+      if (multibyte)
+       *buf++ = '-';
+      if (eol_flag)
+       *buf++ = eol_mnemonic_undecided;
+      /* Don't mention EOL conversion if it isn't decided.  */
     }
   else
     {
+      Lisp_Object eolvalue;
+
+      eolvalue = Fget (coding_system, Qeol_type);
+
       while (!NILP (val) && SYMBOLP (val))
-       val = Fget (val, Qcoding_system);
-      *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
+       {
+         val = Fget (val, Qcoding_system);
+         if (NILP (eolvalue))
+           eolvalue = Fget (val, Qeol_type);
+       }
+
+      if (multibyte)
+       *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
+
       if (eol_flag)
        {
-         val = Fget (coding_system, Qeol_type);
-
-         if (NILP (val))       /* Not yet decided.  */
-           *buf++ = eol_mnemonic_undecided;
-         else if (VECTORP (val)) /* Not yet decided.  */
-           *buf++ = eol_mnemonic_undecided;
-         else                  /* INTEGERP (val) -- 1:LF, 2:CRLF, 3:CR */
-           *buf++ = (XFASTINT (val) == 1
-                     ? eol_mnemonic_unix
-                     : (XFASTINT (val) == 2
-                        ? eol_mnemonic_dos : eol_mnemonic_mac));
+         /* The EOL conversion we are using.  */
+         int eoltype;
+         /* The EOL conversion that is normal on this system.  */
+
+         if (NILP (eolvalue))  /* Not yet decided.  */
+           eoltype = eol_mnemonic_undecided;
+         else if (VECTORP (eolvalue)) /* Not yet decided.  */
+           eoltype = eol_mnemonic_undecided;
+         else                  /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
+           eoltype = (XFASTINT (eolvalue) == 0
+                      ? eol_mnemonic_unix
+                      : (XFASTINT (eolvalue) == 1
+                         ? eol_mnemonic_dos : eol_mnemonic_mac));
+
+         /* Mention the EOL conversion if it is not the usual one.  */
+         *buf++ = eoltype;
        }
     }
   return buf;
@@ -4080,7 +4384,10 @@ decode_mode_spec (w, c, spec_width, maxwidth)
 
     case 'F':
       /* %F displays the frame name.  */
-      if (!NILP (f->title))
+      /* Systems that can only display a single frame at a time should
+        NOT replace the frame name with the (constant) frame title,
+        since then they won't be able to tell which frame is that.  */
+      if (FRAME_WINDOW_P (f) && !NILP (f->title))
        return (char *) XSTRING (f->title)->data;
       if (f->explicit_name || ! FRAME_WINDOW_P (f))
        return (char *) XSTRING (f->name)->data;
@@ -4293,16 +4600,19 @@ decode_mode_spec (w, c, spec_width, maxwidth)
       /* coding-system (including end-of-line type) */
       {
        int eol_flag = (c == 'Z');
-       char *p;
+       char *p = decode_mode_spec_buf;
 
-       p = decode_mode_spec_coding
-         (find_symbol_value (Qbuffer_file_coding_system),
-          decode_mode_spec_buf, eol_flag);
-       if (FRAME_TERMCAP_P (f))
+       if (! FRAME_WINDOW_P (f))
          {
-           p = decode_mode_spec_coding (keyboard_coding.symbol, p, eol_flag);
-           p = decode_mode_spec_coding (terminal_coding.symbol, p, eol_flag);
+           /* No need to mention EOL here--the terminal never needs
+              to do EOL conversion.  */
+           p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
+           p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
          }
+       p = decode_mode_spec_coding (b->buffer_file_coding_system,
+                                    p, eol_flag);
+
+#if 0 /* This proves to be annoying; I think we can do without.  -- rms.  */
 #ifdef subprocesses
        obj = Fget_buffer_process (Fcurrent_buffer ());
        if (PROCESSP (obj))
@@ -4313,6 +4623,7 @@ decode_mode_spec (w, c, spec_width, maxwidth)
                                         p, eol_flag);
          }
 #endif /* subprocesses */
+#endif /* 0 */
        *p = 0;
        return decode_mode_spec_buf;
       }
@@ -4475,11 +4786,15 @@ display_count_lines (from, limit, n, pos_ptr)
   and not display anything beyond there.  Otherwise, only MAXCOL
   controls where to stop output.
 
+  MULTIBYTE can be 0 meaning do not display multibyte chars,
+  1 meaning do display them, or -1 meaning obey the current buffer's
+  value of enable_multibyte_characters.
+
   Returns ending hpos.  */
 
 static int
 display_string (w, vpos, string, length, hpos, truncate,
-               obey_window_width, mincol, maxcol)
+               obey_window_width, mincol, maxcol, multibyte)
      struct window *w;
      unsigned char *string;
      int length;
@@ -4487,6 +4802,7 @@ display_string (w, vpos, string, length, hpos, truncate,
      GLYPH truncate;
      int obey_window_width;
      int mincol, maxcol;
+     int multibyte;
 {
   register int c;
   int truncated;
@@ -4499,24 +4815,27 @@ display_string (w, vpos, string, length, hpos, truncate,
   struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
   GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
   int window_width = XFASTINT (w->width);
-  /* If 1, we must display multibyte characters.  */
-  int multibyte = !NILP (XBUFFER (w->buffer)->enable_multibyte_characters);
 
   /* Use the standard display table, not the window's display table.
      We don't want the mode line in rot13.  */
   register struct Lisp_Char_Table *dp = 0;
   int i;
 
+  if (multibyte == -1)
+    multibyte = !NILP (current_buffer->enable_multibyte_characters);
+  /* Now multibyte is 1 if we should display multibyte characters.  */
+
   if (DISP_TABLE_P (Vstandard_display_table))
     dp = XCHAR_TABLE (Vstandard_display_table);
 
   if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
 
   p1 = p1start;
-  start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left);
+  start = desired_glyphs->glyphs[vpos];
 
   if (obey_window_width)
     {
+      start += XFASTINT (w->left);
       end = start + window_width - (truncate != 0);
 
       if (!WINDOW_RIGHTMOST_P (w))
@@ -4596,9 +4915,11 @@ display_string (w, vpos, string, length, hpos, truncate,
       else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
        {
          if (p1 >= start)
-           *p1 = fix_glyph (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
-                                ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
-                            0);
+           *p1 = (fix_glyph
+                  (f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
+                       && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp)))
+                       ? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
+                   0));
          p1++;
          if (p1 >= start && p1 < end)
            *p1 = c ^ 0100;
@@ -4608,9 +4929,11 @@ display_string (w, vpos, string, length, hpos, truncate,
        {
          /* C is a control character or a binary byte data.  */
          if (p1 >= start)
-           *p1 = fix_glyph (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
-                                ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
-                            0);
+           *p1 = (fix_glyph
+                  (f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
+                       && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp)))
+                       ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
+                   0));
          p1++;
          if (p1 >= start && p1 < end)
            *p1 = (c >> 6) + '0';
@@ -4838,7 +5161,7 @@ of the top or bottom of the window.");
 
   DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
     "*Non-nil means highlight region even in nonselected windows.");
-  highlight_nonselected_windows = 1;
+  highlight_nonselected_windows = 0;
 
   DEFVAR_BOOL ("multiple-frames", &multiple_frames,
     "Non-nil if more than one frame is visible on this display.\n\
@@ -4884,11 +5207,16 @@ 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\
+    "List of functions to call before redisplaying a window with scrolling.\n\
 Each function is called with two arguments, the window\n\
 and its new display-start position.  Note that the value of `window-end'\n\
 is not valid when these functions are called.");
   Vwindow_scroll_functions = Qnil;
+
+  DEFVAR_INT ("minibuffer-scroll-overlap", &minibuffer_scroll_overlap,
+    "*Number of characters of overlap when scrolling a one-line window.\n\
+This commonly affects the minibuffer window, hence the name of the variable.");
+  minibuffer_scroll_overlap = 20;
 }
 
 /* initialize the window system */
@@ -4911,8 +5239,10 @@ init_xdisp ()
   if (!noninteractive)
     {
       FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
-      XSETFASTINT (XWINDOW (root_window)->top, 0);
-      set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0);
+      XSETFASTINT (XWINDOW (root_window)->top, FRAME_MENU_BAR_LINES (f));
+      set_window_height (root_window,
+                        FRAME_HEIGHT (f) - 1 - FRAME_MENU_BAR_LINES (f),
+                        0);
       XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
       set_window_height (minibuf_window, 1, 0);