]> 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 b7c0c274c1fa17c7105d56ee8b82a31745a18724..cc65fff9ae996b73a627ac6520300740a7c906d1 100644 (file)
@@ -155,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;
@@ -281,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*")));
@@ -291,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;
@@ -346,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;
@@ -559,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);
@@ -1375,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)
@@ -1917,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;
@@ -1981,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
@@ -2134,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);
@@ -2884,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)
@@ -2948,10 +3021,12 @@ display_text_line (w, start, vpos, hpos, taboffset, ovstr_done)
   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)
@@ -5132,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 */