Subject: bug#33532: 26.1; set-window-configuration does not restore display start

From: martin rudalics <[email-masked]>
Date: Tue, 04 Dec 2018 09:33:14 +0100

> What do you think about implementing the same behavior for
 > markers like it's implemented by 'comint-move-point-for-output'?
 > I.e. the same way as 'comint-move-point-for-output' moves point
 > to the end of the output, after erasing the buffer markers could
 > move their positions towards their previous valid position until
 > there is enough reverted text that they reach the old position.
 >
 > This is straightforward to implement.  I see print.c has a question
 > in the comments:
 >
 >      case PVEC_MARKER:
 >        print_c_string ("#<marker ", printcharfun);
 >        /* Do you think this is necessary?  */
 >        if (XMARKER (obj)->insertion_type != 0)
 > 	print_c_string ("(moves after insertion) ", printcharfun);
 >
 > I think this is necessary.  And this 'insertion_type' could also
 > move after insertion until it reaches its old position in the
 > reverted buffer.

'auto-revert-tail-mode' already has

       (when buffer-file-name
         (setq eob (eobp))
         (walk-windows
          (lambda (window)
            (and (eq (window-buffer window) buffer)
                 (= (window-point window) (point-max))
                 (push window eoblist)))
          'no-mini t))

plus

       (when buffer-file-name
         (when eob (goto-char (point-max)))
         (dolist (window eoblist)
           (set-window-point window (point-max)))))

without changing the markers' point insertion types.  We can easily
extend that to handle a window's previous buffers' points.  But
changing the insertion type of markers is far too delicate with all
the implications Eli cited.  We should avoid that wherever possible.

BTW, the last patch I sent was needlessly complicated - a window's
next buffers don't have any markers.  I attach a better one.

martin
diff --git a/src/fileio.c b/src/fileio.c
index d979571..b3fdc60 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3513,23 +3513,59 @@ CONTEXT should be a list (USER ROLE TYPE RANGE), where the list
 static Lisp_Object
 get_window_points_and_markers (void)
 {
+  Lisp_Object buffer = Fcurrent_buffer ();
   Lisp_Object pt_marker = Fpoint_marker ();
-  Lisp_Object windows
-    = call3 (Qget_buffer_window_list, Fcurrent_buffer (), Qnil, Qt);
-  Lisp_Object window_markers = windows;
-  /* Window markers (and point) are handled specially: rather than move to
-     just before or just after the modified text, we try to keep the
-     markers at the same distance (bug#19161).
-     In general, this is wrong, but for window-markers, this should be harmless
-     and is convenient for the end user when most of the file is unmodified,
-     except for a few minor details near the beginning and near the end.  */
+  Lisp_Object windows = window_list ();
+  Lisp_Object window;
+  Lisp_Object window_markers = Qnil;
+  /* Window markers (and point) are handled specially: rather than
+     move to just before or just after the modified text, we try to
+     keep the markers at the same distance (bug#19161).
+
+     In general, this is wrong, but for window markers, this should be
+     harmless and is convenient for the end user when most of the file
+     is unmodified, except for a few minor details near the beginning
+     and near the end.
+
+     Window point markers now include the window point markers from
+     the lists of each live window's previous buffers.  */
   for (; CONSP (windows); windows = XCDR (windows))
-    if (WINDOWP (XCAR (windows)))
+    if (WINDOW_LIVE_P (window = XCAR (windows)))
       {
-	Lisp_Object window_marker = XWINDOW (XCAR (windows))->pointm;
-	XSETCAR (windows,
-		 Fcons (window_marker, Fmarker_position (window_marker)));
+	struct window *w = XWINDOW (window);
+	Lisp_Object prev_buffers = w->prev_buffers;
+
+	/* Look at window's buffer first.  */
+	if (EQ (WINDOW_BUFFER (w), buffer))
+	  {
+	    Lisp_Object window_marker = XWINDOW (XCAR (windows))->pointm;
+
+	    window_markers =
+	      Fcons (Fcons (window_marker, Fmarker_position (window_marker)),
+		     window_markers);
+
+	    /* Skip the list of previous buffers.  */
+	    continue;
+	  }
+
+	/* Scan window's previous buffers.  */
+	for (; CONSP (prev_buffers); prev_buffers = XCDR (prev_buffers))
+	  if (CONSP (XCAR (prev_buffers)))
+	    {
+	      Lisp_Object triple = XCAR (prev_buffers);
+
+	      if (EQ (XCAR (triple), buffer))
+		{
+		  Lisp_Object prev_marker = Fnth (make_fixnum (2), triple);
+
+		  window_markers =
+		    Fcons (Fcons (prev_marker, Fmarker_position (prev_marker)),
+			   window_markers);
+		  break;
+		}
+	    }
       }
+
   return Fcons (Fcons (pt_marker, Fpoint ()), window_markers);
 }
 
@@ -3543,6 +3579,7 @@ CONTEXT should be a list (USER ROLE TYPE RANGE), where the list
 	Lisp_Object car = XCAR (window_markers);
 	Lisp_Object marker = XCAR (car);
 	Lisp_Object oldpos = XCDR (car);
+
 	if (MARKERP (marker) && FIXNUMP (oldpos)
 	    && XFIXNUM (oldpos) > same_at_start
 	    && XFIXNUM (oldpos) < same_at_end)
@@ -3552,6 +3589,7 @@ CONTEXT should be a list (USER ROLE TYPE RANGE), where the list
 	    double growth = newsize / (double)oldsize;
 	    ptrdiff_t newpos
 	      = same_at_start + growth * (XFIXNUM (oldpos) - same_at_start);
+
 	    Fset_marker (marker, make_fixnum (newpos), Qnil);
 	  }
       }
@@ -6285,7 +6323,6 @@ current when building the annotations (i.e., at least once), with that
   DEFSYM (Qdelete_directory, "delete-directory");
 
   DEFSYM (Qsubstitute_env_in_file_name, "substitute-env-in-file-name");
-  DEFSYM (Qget_buffer_window_list, "get-buffer-window-list");
 
   DEFSYM (Qstdin, "stdin");
   DEFSYM (Qstdout, "stdout");