]> 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 9d88cff44b851892bd33ba888e37626fabd9bc65..cc65fff9ae996b73a627ac6520300740a7c906d1 100644 (file)
@@ -114,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;
 
@@ -125,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.  */
@@ -153,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;
@@ -211,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;
 
@@ -247,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.  */
 
@@ -272,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*")));
@@ -282,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;
@@ -337,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;
@@ -413,6 +470,9 @@ message2_nolog (m, len)
      char *m;
      int len;
 {
+  message_enable_multibyte
+    = ! NILP (current_buffer->enable_multibyte_characters);
+
   if (noninteractive)
     {
       if (noninteractive_need_newline)
@@ -547,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);
@@ -631,7 +691,8 @@ echo_area_display ()
                      echo_area_glyphs ? echo_area_glyphs_length : -1,
                      FRAME_LEFT_SCROLL_BAR_WIDTH (f),
                      0, 0, 0,
-                     FRAME_WIDTH (f) + FRAME_LEFT_SCROLL_BAR_WIDTH (f));
+                     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 */
@@ -655,7 +716,8 @@ echo_area_display ()
            display_string (XWINDOW (mini_window), i,
                            "", 0, 
                             0, 0, 0,
-                            0, FRAME_WIDTH (f) + FRAME_SCROLL_BAR_WIDTH (f));
+                            0, FRAME_WIDTH (f) + FRAME_SCROLL_BAR_WIDTH (f),
+                           0);
          }
       }
     }
@@ -870,7 +932,7 @@ redisplay_internal (preserve_echo_area)
   int all_windows;
   register int tlbufpos, tlendpos;
   struct position pos;
-  int number_of_frames_redisplayed;
+  int number_of_visible_frames;
 
   if (noninteractive)
     return;
@@ -900,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));
@@ -948,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;
 
@@ -971,14 +1038,12 @@ redisplay_internal (preserve_echo_area)
                  Fmarker_position (XBUFFER (w->buffer)->mark))))
     this_line_bufpos = -1;
 
-  /* This is in case we goto update, below.  */
-  number_of_frames_redisplayed = 1;
-
   tlbufpos = this_line_bufpos;
   tlendpos = this_line_endpos;
   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)
@@ -1148,7 +1213,6 @@ redisplay_internal (preserve_echo_area)
       /* Recompute # windows showing selected buffer.
         This will be incremented each time such a window is displayed.  */
       buffer_shared = 0;
-      number_of_frames_redisplayed = 0;
 
       FOR_EACH_FRAME (tail, frame)
        {
@@ -1161,11 +1225,8 @@ redisplay_internal (preserve_echo_area)
              if (condemn_scroll_bars_hook)
                (*condemn_scroll_bars_hook) (f);
 
-             if (FRAME_VISIBLE_P (f))
-               {
-                 redisplay_windows (FRAME_ROOT_WINDOW (f), preserve_echo_area);
-                 number_of_frames_redisplayed++;
-               }
+             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
                 should now go away.  */
@@ -1174,12 +1235,11 @@ 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))
        preserve_other_columns (w);
-      number_of_frames_redisplayed = 1;
     }
 
 update: 
@@ -1206,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)
@@ -1220,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;
@@ -1299,7 +1359,7 @@ update:
                               : 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);
@@ -1331,21 +1391,18 @@ update:
       FOR_EACH_FRAME (tail, frame)
        {
          int this_is_visible = 0;
-         if (FRAME_WINDOW_P (XFRAME (frame))
-             || XFRAME (frame) == selected_frame)
-           {
-             if (XFRAME (frame)->visible)
-               this_is_visible = 1;
-             FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
-             if (XFRAME (frame)->visible)
-               this_is_visible = 1;
-           }
+
+         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_frames_redisplayed)
+      if (new_count != number_of_visible_frames)
        windows_or_buffers_changed++;
     }
 
@@ -1366,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)
@@ -1423,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
@@ -1630,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;
@@ -1835,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)
@@ -1874,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;
@@ -1903,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)
@@ -1938,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
@@ -1961,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))
            {
@@ -2000,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))
            {
@@ -2077,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);
@@ -2827,11 +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
-          || highlight_nonselected_windows));
+       && XMARKER (current_buffer->mark)->buffer != 0);
   int region_beg, region_end;
 
   int selective = (INTEGERP (current_buffer->selective_display)
@@ -2887,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)
@@ -2923,7 +3054,8 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
 
          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,
@@ -2931,8 +3063,9 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
                                  margin, so user input can at least start
                                  on the first line.  */
                               (XFASTINT (w->width) > 10
-                               ? XFASTINT (w->width) - 4 : -1))
-              - hpos);
+                               ? XFASTINT (w->width) - 4 : -1),
+                              -1)
+              - hpos - WINDOW_LEFT_MARGIN (w));
          hpos += minibuf_prompt_width;
          taboffset -= minibuf_prompt_width - old_width;
        }
@@ -2974,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;
@@ -3589,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
@@ -3700,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;
 
@@ -3730,13 +3865,13 @@ display_menu_bar (w)
        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);
        }
     }
 
@@ -3745,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++;
@@ -3870,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 == '%' */
              {
@@ -3907,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);
                  }
              }
          }
@@ -3935,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))
@@ -4029,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;
     }
 
@@ -4037,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
@@ -4081,12 +4217,14 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
      int eol_flag;
 {
   Lisp_Object val;
+  int multibyte = !NILP (current_buffer->enable_multibyte_characters);
 
   val = coding_system;
 
   if (NILP (val))              /* Not yet decided.  */
     {
-      *buf++ = '-';
+      if (multibyte)
+       *buf++ = '-';
       if (eol_flag)
        *buf++ = eol_mnemonic_undecided;
       /* Don't mention EOL conversion if it isn't decided.  */
@@ -4104,7 +4242,9 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
            eolvalue = Fget (val, Qeol_type);
        }
 
-      *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
+      if (multibyte)
+       *buf++ = XFASTINT (XVECTOR (val)->contents[1]);
+
       if (eol_flag)
        {
          /* The EOL conversion we are using.  */
@@ -4244,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;
@@ -4459,7 +4602,7 @@ decode_mode_spec (w, c, spec_width, maxwidth)
        int eol_flag = (c == 'Z');
        char *p = decode_mode_spec_buf;
 
-       if (FRAME_TERMCAP_P (f))
+       if (! FRAME_WINDOW_P (f))
          {
            /* No need to mention EOL here--the terminal never needs
               to do EOL conversion.  */
@@ -4643,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;
@@ -4655,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;
@@ -4667,14 +4815,16 @@ 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);
 
@@ -5057,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 */