(mac_init_fringe) [MAC_OS]: Add prototype.
[bpt/emacs.git] / src / window.c
index e7040e3..c8067f9 100644 (file)
@@ -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;
@@ -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;
 
@@ -4720,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;
 
@@ -4786,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
+         || (current_kboard->Vlast_command != Qscroll_up
+             && 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.  */
@@ -4921,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
@@ -4948,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);
 
@@ -4978,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
@@ -6987,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);
@@ -7012,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.