From xemacs-m  Wed Aug 20 22:18:06 1997
Received: from GS213.SP.CS.CMU.EDU (GS213.SP.CS.CMU.EDU [128.2.209.183])
	by xemacs.org (8.8.5/8.8.5) with SMTP id WAA23498
	for <xemacs-beta@xemacs.org>; Wed, 20 Aug 1997 22:18:05 -0500 (CDT)
Received: by GS213.SP.CS.CMU.EDU (AIX 3.2/UCB 5.64/4.03)
          id AA09462; Wed, 20 Aug 1997 23:18:04 -0400
Date: Wed, 20 Aug 1997 23:18:04 -0400
Message-Id: <9708210318.AA09462@GS213.SP.CS.CMU.EDU>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
From: Darrell Kindred <dkindred@cmu.edu>
To: xemacs-beta@xemacs.org
Subject: [PATCH] 19.15p7 redisplay annoyance
Organization: Carnegie Mellon University School of Computer Science
X-Mailer: VM 6.22 under 19.15 XEmacs Lucid

The following bug exists in 19.15p7 and 20.3-b18:

  Load the elisp below.  Press f1, then press the up arrow
  until you're at the top of the window, then press once
  more so the window scrolls by one line.  Then press f2
  (this should just add a line at the end of the buffer).
  Note that the window gets recentered for no reason.

The problem is that redisplay_window() sets the
w->last_start[DESIRED_DISP] marker using startp,
but it doesn't update startp in those situations
where the window start position has been changed.  
The patch below fixes this in the 19.15p7 redisplay.c.
It fits 20.3-b18 as well.  I welcome comments from
any redisplay whizzes.

It would be nice if this patch could be applied for 
19.16.

- Darrell

--- bug test code:

(defun test-1 ()
  (interactive)
  (switch-to-buffer (get-buffer-create "*testbug*"))
  (erase-buffer)
  (make-variable-buffer-local 'scroll-step)
  (setq scroll-step 1)
  (let ((l 1))
    (while (< l 100)
      (insert (format "line %d\n" l))
      (setq l (1+ l)))))

(defun test-2 ()
  (interactive)
  (save-excursion
    (goto-char (point-max))
    (insert (format "line 100\n"))))

(global-set-key 'f1 'test-1)
(global-set-key 'f2 'test-2)

--- and the patch:

*** src/redisplay.c.orig	Sat Jul  5 12:29:15 1997
--- src/redisplay.c	Wed Aug 20 19:45:12 1997
***************
*** 277,284 ****
  				      struct display_line *dl);
  static void regenerate_window (struct window *w, Bufpos start_pos,
  			       Bufpos point, int type);
! static void regenerate_window_point_center (struct window *w, Bufpos point,
! 					    int type);
  int window_half_pixpos (struct window *w);
  int line_at_center (struct window *w, int type, Bufpos start, Bufpos point);
  Bufpos point_at_center (struct window *w, int type, Bufpos start,
--- 277,284 ----
  				      struct display_line *dl);
  static void regenerate_window (struct window *w, Bufpos start_pos,
  			       Bufpos point, int type);
! static Bufpos regenerate_window_point_center (struct window *w, Bufpos point,
! 					      int type);
  int window_half_pixpos (struct window *w);
  int line_at_center (struct window *w, int type, Bufpos start, Bufpos point);
  Bufpos point_at_center (struct window *w, int type, Bufpos start,
***************
*** 4784,4792 ****
  }
  
  /* Given a window and a point, update the given display lines such
!    that point is displayed in the middle of the window. */
  
! static void
  regenerate_window_point_center (struct window *w, Bufpos point, int type)
  {
    Bufpos startp;
--- 4784,4793 ----
  }
  
  /* Given a window and a point, update the given display lines such
!    that point is displayed in the middle of the window. 
!    Return the window's new start position. */
  
! static Bufpos
  regenerate_window_point_center (struct window *w, Bufpos point, int type)
  {
    Bufpos startp;
***************
*** 4799,4805 ****
    regenerate_window (w, startp, point, type);
    Fset_marker (w->start[type], make_int (startp), w->buffer);
  
!   return;
  }
  
  /* Given a window and a set of display lines, return a boolean
--- 4800,4806 ----
    regenerate_window (w, startp, point, type);
    Fset_marker (w->start[type], make_int (startp), w->buffer);
  
!   return startp;
  }
  
  /* Given a window and a set of display lines, return a boolean
***************
*** 5006,5012 ****
    if (!MINI_WINDOW_P (w)
        && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer))
      {
!       regenerate_window_point_center (w, pointm, DESIRED_DISP);
  
        goto regeneration_done;
      }
--- 5007,5013 ----
    if (!MINI_WINDOW_P (w)
        && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer))
      {
!       startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
  
        goto regeneration_done;
      }
***************
*** 5140,5146 ****
  	       startp < marker_position (w->last_start[CURRENT_DISP]))
  	   || (startp == BUF_ZV (b)))
      {
!       regenerate_window_point_center (w, pointm, DESIRED_DISP);
  
        goto regeneration_done;
      }
--- 5141,5147 ----
  	       startp < marker_position (w->last_start[CURRENT_DISP]))
  	   || (startp == BUF_ZV (b)))
      {
!       startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
  
        goto regeneration_done;
      }
***************
*** 5178,5188 ****
       back onto the screen. */
    if (scroll_step)
      {
!       Bufpos bufpos;
! 
!       bufpos = vmotion (w, startp,
  			(pointm < startp) ? -scroll_step : scroll_step, 0);
!       regenerate_window (w, bufpos, pointm, DESIRED_DISP);
  
        if (point_visible (w, pointm, DESIRED_DISP))
  	goto regeneration_done;
--- 5179,5187 ----
       back onto the screen. */
    if (scroll_step)
      {
!       startp = vmotion (w, startp,
  			(pointm < startp) ? -scroll_step : scroll_step, 0);
!       regenerate_window (w, startp, pointm, DESIRED_DISP);
  
        if (point_visible (w, pointm, DESIRED_DISP))
  	goto regeneration_done;
***************
*** 5190,5196 ****
  
    /* We still haven't managed to get the screen drawn with point on
       the screen, so just center it and be done with it. */
!   regenerate_window_point_center (w, pointm, DESIRED_DISP);
  
  
  regeneration_done:
--- 5189,5195 ----
  
    /* We still haven't managed to get the screen drawn with point on
       the screen, so just center it and be done with it. */
!   startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
  
  
  regeneration_done:

