]> code.delx.au - gnu-emacs/blobdiff - src/window.c
Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-49
[gnu-emacs] / src / window.c
index e2678a3f3b89d6a2f43da46b986e266755b54e57..039e955efd033816f3b5ee3ec33a155641eeb07f 100644 (file)
@@ -1,7 +1,7 @@
 /* Window creation, deletion and examination for GNU Emacs.
    Does not include redisplay.
    Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
-                 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+                 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -50,6 +50,7 @@ Boston, MA 02110-1301, USA.  */
 
 
 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
+Lisp_Object Qscroll_up, Qscroll_down;
 Lisp_Object Qwindow_size_fixed;
 extern Lisp_Object Qleft_margin, Qright_margin;
 
@@ -214,6 +215,10 @@ Lisp_Object Vscroll_preserve_screen_position;
 
 int window_deletion_count;
 
+/* Used by the function window_scroll_pixel_based */
+
+static int window_scroll_pixel_based_preserve_y;
+
 #if 0 /* This isn't used anywhere.  */
 /* Nonzero means we can split a frame even if it is "unsplittable".  */
 static int inhibit_frame_unsplittable;
@@ -1829,7 +1834,7 @@ DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
 All windows on current frame are arranged in a cyclic order.
 This command selects the window ARG steps away in that order.
 A negative ARG moves in the opposite order.  The optional second
-argument ALL_FRAMES has the same meaning as in `next-window', which see.  */)
+argument ALL-FRAMES has the same meaning as in `next-window', which see.  */)
      (arg, all_frames)
      Lisp_Object arg, all_frames;
 {
@@ -1861,7 +1866,8 @@ MINIBUF neither nil nor t means never include the minibuffer window.  */)
      Lisp_Object frame, minibuf, window;
 {
   if (NILP (window))
-    window = selected_window;
+    window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
+  CHECK_WINDOW (window);
   if (NILP (frame))
     frame = selected_frame;
 
@@ -2568,7 +2574,10 @@ window_min_size_1 (w, width_p)
   else
     {
       if (width_p)
-       size = window_min_width;
+       size = max (window_min_width,
+                   (MIN_SAFE_WINDOW_WIDTH
+                    + WINDOW_FRINGE_COLS (w)
+                    + WINDOW_SCROLL_BAR_COLS (w)));
       else
        {
          if (MINI_WINDOW_P (w)
@@ -4284,6 +4293,14 @@ adjust_window_trailing_edge (window, delta, horiz_flag)
        {
          if (!NILP (XWINDOW (window)->next))
            {
+              /* This may happen for the minibuffer.  In that case
+                 the window_deletion_count check below does not work.  */
+              if (XINT (CURSIZE (p->next)) - delta <= 0)
+                {
+                  Fset_window_configuration (old_config);
+                  error ("Cannot adjust window size as specified");
+                }
+
              XSETINT (CURBEG (p->next),
                       XINT (CURBEG (p->next)) + delta);
              size_window (p->next, XINT (CURSIZE (p->next)) - delta,
@@ -4709,7 +4726,6 @@ window_scroll_pixel_based (window, n, whole, noerror)
   struct text_pos start;
   Lisp_Object tem;
   int this_scroll_margin;
-  int preserve_y;
   /* True if we fiddled the window vscroll field without really scrolling.   */
   int vscrolled = 0;
 
@@ -4775,12 +4791,21 @@ window_scroll_pixel_based (window, n, whole, noerror)
      point in the same window line as it is now, so get that line.  */
   if (!NILP (Vscroll_preserve_screen_position))
     {
-      start_display (&it, w, start);
-      move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
-      preserve_y = it.current_y;
+      /* We preserve the goal pixel coordinate across consecutive
+        calls to scroll-up or scroll-down.  This avoids the
+        possibility of point becoming "stuck" on a tall line when
+        scrolling by one line.  */
+      if (window_scroll_pixel_based_preserve_y < 0
+         || (!EQ (current_kboard->Vlast_command, Qscroll_up)
+             && !EQ (current_kboard->Vlast_command, Qscroll_down)))
+       {
+         start_display (&it, w, start);
+         move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+         window_scroll_pixel_based_preserve_y = it.current_y;
+       }
     }
   else
-    preserve_y = -1;
+    window_scroll_pixel_based_preserve_y = -1;
 
   /* Move iterator it from start the specified distance forward or
      backward.  The result is the new window start.  */
@@ -4910,14 +4935,14 @@ window_scroll_pixel_based (window, n, whole, noerror)
              || EQ (Vscroll_preserve_screen_position, Qt)))
        /* We found PT at a legitimate height.  Leave it alone.  */
        ;
-      else if (preserve_y >= 0)
+      else if (window_scroll_pixel_based_preserve_y >= 0)
        {
          /* If we have a header line, take account of it.
             This is necessary because we set it.current_y to 0, above.  */
-         if (WINDOW_WANTS_HEADER_LINE_P (w))
-           preserve_y -= CURRENT_HEADER_LINE_HEIGHT (w);
-
-         move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
+         move_it_to (&it, -1, -1,
+                     window_scroll_pixel_based_preserve_y
+                     - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
+                     -1, MOVE_TO_Y);
          SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
        }
       else
@@ -4937,7 +4962,8 @@ window_scroll_pixel_based (window, n, whole, noerror)
       int charpos, bytepos;
       int partial_p;
 
-      /* Save our position, for the preserve_y case.  */
+      /* Save our position, for the
+        window_scroll_pixel_based_preserve_y case.  */
       charpos = IT_CHARPOS (it);
       bytepos = IT_BYTEPOS (it);
 
@@ -4967,20 +4993,15 @@ window_scroll_pixel_based (window, n, whole, noerror)
              || EQ (Vscroll_preserve_screen_position, Qt)))
        /* We found PT before we found the display margin, so PT is ok.  */
        ;
-      else if (preserve_y >= 0)
+      else if (window_scroll_pixel_based_preserve_y >= 0)
        {
          SET_TEXT_POS_FROM_MARKER (start, w->start);
          start_display (&it, w, start);
-#if 0  /* It's wrong to subtract this here
-         because we called start_display again
-         and did not alter it.current_y this time.  */
-
-         /* If we have a header line, take account of it.  */
-         if (WINDOW_WANTS_HEADER_LINE_P (w))
-           preserve_y -= CURRENT_HEADER_LINE_HEIGHT (w);
-#endif
-
-         move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
+         /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
+            here because we called start_display again and did not
+            alter it.current_y this time.  */
+         move_it_to (&it, -1, -1, window_scroll_pixel_based_preserve_y, -1,
+                     MOVE_TO_Y);
          SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
        }
       else
@@ -6592,7 +6613,8 @@ this is automatically adjusted to a multiple of the frame column width.
 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
 bar: left, right, or nil.
 If WIDTH is nil, use the frame's scroll-bar width.
-If TYPE is t, use the frame's scroll-bar type.  */)
+If VERTICAL-TYPE is t, use the frame's scroll-bar type.
+Fourth parameter HORIZONTAL-TYPE is currently unused.  */)
      (window, width, vertical_type, horizontal_type)
      Lisp_Object window, width, vertical_type, horizontal_type;
 {
@@ -6660,7 +6682,7 @@ DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
        doc: /* Return the amount by which WINDOW is scrolled vertically.
 Use the selected window if WINDOW is nil or omitted.
 Normally, value is a multiple of the canonical character height of WINDOW;
-optional second arg PIXELS_P means value is measured in pixels.  */)
+optional second arg PIXELS-P means value is measured in pixels.  */)
   (window, pixels_p)
      Lisp_Object window, pixels_p;
 {
@@ -6690,7 +6712,7 @@ DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
        doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
 WINDOW nil means use the selected window.  Normally, VSCROLL is a
 non-negative multiple of the canonical character height of WINDOW;
-optional third arg PIXELS_P non-nil means that VSCROLL is in pixels.
+optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
 corresponds to an integral number of pixels.  The return value is the
 result of this rounding.
@@ -6975,6 +6997,12 @@ init_window ()
 void
 syms_of_window ()
 {
+  Qscroll_up = intern ("scroll-up");
+  staticpro (&Qscroll_up);
+
+  Qscroll_down = intern ("scroll-down");
+  staticpro (&Qscroll_down);
+
   Qwindow_size_fixed = intern ("window-size-fixed");
   staticpro (&Qwindow_size_fixed);
   Fset (Qwindow_size_fixed, Qnil);
@@ -7000,6 +7028,8 @@ syms_of_window ()
   minibuf_selected_window = Qnil;
   staticpro (&minibuf_selected_window);
 
+  window_scroll_pixel_based_preserve_y = -1;
+
   DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
               doc: /* Non-nil means call as function to display a help buffer.
 The function is called with one argument, the buffer to be displayed.