Subject: bug#1488: 23.0.60; dired-pop-to-buffer: use fit-window-to-buffer

From: martin rudalics <[email-masked]>
Date: Sat, 06 Dec 2008 20:25:00 +0100

Stephen,

`fit-window-to-buffer' had more bugs than I thought.  I rewrote it
completely but you would have to use it for a couple of days to know
whether it DTRT.  Patch attached.

martin
*** window.el.~1.169.~	2008-11-27 11:14:14.671875000 +0100
--- window.el	2008-12-06 20:20:34.390625000 +0100
***************
*** 1296,1379 ****
    "Adjust height of WINDOW to display its buffer's contents exactly.
  WINDOW defaults to the selected window.
  Optional argument MAX-HEIGHT specifies the maximum height of the
! window and defaults to the height of WINDOW's frame.
  Optional argument MIN-HEIGHT specifies the minimum height of the
  window and defaults to `window-min-height'.
  Both, MAX-HEIGHT and MIN-HEIGHT are specified in lines and
  include the mode line and header line, if any.
  Always return nil."
    (interactive)
! 
!   (when (null window)
!     (setq window (selected-window)))
!   (when (null max-height)
!     (setq max-height (frame-height (window-frame window))))
! 
!   (let* ((buf
! 	  ;; Buffer that is displayed in WINDOW
! 	  (window-buffer window))
! 	 (window-height
! 	  ;; The current height of WINDOW
! 	  (window-height window))
! 	 (desired-height
! 	  ;; The height necessary to show the buffer displayed by WINDOW
! 	  ;; (`count-screen-lines' always works on the current buffer).
! 	  (with-current-buffer buf
! 	    (+ (count-screen-lines)
! 	       ;; If the buffer is empty, (count-screen-lines) is
! 	       ;; zero.  But, even in that case, we need one text line
! 	       ;; for cursor.
! 	       (if (= (point-min) (point-max))
! 		   1 0)
! 	       ;; For non-minibuffers, count the mode-line, if any
! 	       (if (and (not (window-minibuffer-p window))
! 			mode-line-format)
! 		   1 0)
! 	       ;; Count the header-line, if any
! 	       (if header-line-format 1 0))))
! 	 (delta
! 	  ;; Calculate how much the window height has to change to show
! 	  ;; desired-height lines, constrained by MIN-HEIGHT and MAX-HEIGHT.
! 	  (- (max (min desired-height max-height)
! 		  (or min-height window-min-height))
! 	     window-height)))
! 
!     ;; Don't try to redisplay with the cursor at the end
!     ;; on its own line--that would force a scroll and spoil things.
!     (when (with-current-buffer buf
! 	    (and (eobp) (bolp) (not (bobp))))
!       (set-window-point window (1- (window-point window))))
! 
!     (save-selected-window
!       (select-window window 'norecord)
! 
!       ;; Adjust WINDOW to the nominally correct size (which may actually
!       ;; be slightly off because of variable height text, etc).
!       (unless (zerop delta)
! 	(enlarge-window delta))
! 
!       ;; Check if the last line is surely fully visible.  If not,
!       ;; enlarge the window.
!       (let ((end (with-current-buffer buf
! 		   (save-excursion
! 		     (goto-char (point-max))
! 		     (when (and (bolp) (not (bobp)))
! 		       ;; Don't include final newline
! 		       (backward-char 1))
! 		     (when truncate-lines
! 		       ;; If line-wrapping is turned off, test the
! 		       ;; beginning of the last line for visibility
! 		       ;; instead of the end, as the end of the line
! 		       ;; could be invisible by virtue of extending past
! 		       ;; the edge of the window.
! 		       (forward-line 0))
! 		     (point)))))
! 	(set-window-vscroll window 0)
! 	(while (and (< desired-height max-height)
! 		    (= desired-height (window-height window))
! 		    (not (pos-visible-in-window-p end window)))
! 	  (enlarge-window 1)
! 	  (setq desired-height (1+ desired-height)))))))
  
  (defun window-safely-shrinkable-p (&optional window)
    "Return t if WINDOW can be shrunk without shrinking other windows.
--- 1296,1383 ----
    "Adjust height of WINDOW to display its buffer's contents exactly.
  WINDOW defaults to the selected window.
  Optional argument MAX-HEIGHT specifies the maximum height of the
! window and defaults to the maximum permissible height of a window
! on WINDOW's frame.
  Optional argument MIN-HEIGHT specifies the minimum height of the
  window and defaults to `window-min-height'.
  Both, MAX-HEIGHT and MIN-HEIGHT are specified in lines and
  include the mode line and header line, if any.
  Always return nil."
    (interactive)
!   ;; Do all the work in WINDOW and its buffer and restore the selected
!   ;; window and the current buffer when we're done.
!   (save-excursion
!     (with-selected-window (or window (selected-window))
!       (set-buffer (window-buffer))
!       (let* ((desired-height
! 	      ;; The height necessary to show all of WINDOW's buffer.
! 	      ;; For an empty buffer (count-screen-lines) returns zero.
! 	      ;; Even in that case we need one line for the cursor.
! 	      (+ (max (count-screen-lines) 1)
! 		 ;; For non-minibuffers count the mode-line, if any.
! 		 (if (and (not (window-minibuffer-p)) mode-line-format) 1 0)
! 		 ;; Count the header-line, if any.
! 		 (if header-line-format 1 0)))
! 	     ;; MIN-HEIGHT must not be less than 1 and defaults to
! 	     ;; `window-min-height'.
! 	     (min-height (max (or min-height window-min-height) 1))
! 	     (max-window-height
! 	      ;; Maximum height of any window on this frame.
! 	      (min (window-height (frame-root-window)) (frame-height)))
! 	     ;; MAX-HEIGHT must not be larger than max-window-height and
! 	     ;; also defaults to that value.
! 	     (max-height
! 	      (min (or max-height max-window-height) max-window-height))
! 	     (delta
! 	      ;; How much the window height has to change to show
! 	      ;; desired-height lines, constrained by MIN-HEIGHT and
! 	      ;; MAX-HEIGHT.
! 	      (- (min max-height (max desired-height min-height))
! 		 (window-height)))
! 	     ;; Avoid deleting this window if it becomes too small.  As
! 	     ;; a side-effect, this may keep some other windows as well.
! 
! 	     ;; Note: The following was removed by Jan on 2007-07-09 but
! 	     ;; it seems needed to (1) avoid deleting the window we want
! 	     ;; to shrink, and (2) as a consequence of (1) have
! 	     ;; (window-height WINDOW) return the buffer displayed by
! 	     ;; WINDOW which seems like a bug in delete_all_subwindows
! 	     ;; which uses decode_any_window (so it doesn't care wether
! 	     ;; WINDOW is live).
! 	     (window-min-height 1))
! 	;; Don't try to redisplay with the cursor at the end on its own
! 	;; line--that would force a scroll and spoil things.
! 	(when (and (eobp) (bolp) (not (bobp)))
! 	  (set-window-point window (1- (window-point))))
! 	;; Use condition-case to handle any fixed-size windows and other
! 	;; pitfalls nearby.
! 	(condition-case nil
! 	    ;; Adjust WINDOW's height to the nominally correct one
! 	    ;; (which may actually be slightly off because of variable
! 	    ;; height text, etc).
! 	    (unless (zerop delta)
! 	      (enlarge-window delta)
! 	      ;; Check if the last line is surely fully visible.  If
! 	      ;; not, enlarge the window.
! 	      (let ((end (save-excursion
! 			   (goto-char (point-max))
! 			   (when (and (bolp) (not (bobp)))
! 			     ;; Don't include final newline
! 			     (backward-char 1))
! 			   (when truncate-lines
! 			     ;; If line-wrapping is turned off, test the
! 			     ;; beginning of the last line for
! 			     ;; visibility instead of the end, as the
! 			     ;; end of the line could be invisible by
! 			     ;; virtue of extending past the edge of the
! 			     ;; window.
! 			     (forward-line 0))
! 			   (point))))
! 		(set-window-vscroll window 0)
! 		(while (and (< (window-height) max-height)
! 			    (not (pos-visible-in-window-p end)))
! 		  (enlarge-window 1))))
! 	  (error nil))))))
  
  (defun window-safely-shrinkable-p (&optional window)
    "Return t if WINDOW can be shrunk without shrinking other windows.