Subject: Re: bug#37563: 27.0.50; fit-frame-to-buffer does not account for line-spacing

From: martin rudalics <[email-masked]>
Date: Tue, 1 Oct 2019 09:32:08 +0200

> 1) When max-height is provided, the actual frame height is calculated in
 > ll 8736ff of window.el (as of commit
 > 5746202c182a9c69c732beb29b8507a6e6364799), and that just multiplies by
 > the char-height, which excludes the line-spacing.  This is the buggy
 > case.

I attached a fix.  Please try it.

Many thanks for the report, martin
diff --git a/lisp/window.el b/lisp/window.el
index cf733153b8..3df463533c 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -8494,6 +8494,40 @@ window-buffer-height
 			     (eobp)
 			     window))))
 
+(defun window-char-height (&optional window)
+  "Return number of pixels of the height of a character in WINDOW.
+WINDOW must be a live window and defaults to the selected one.
+The return value accounts for any remapping of the default face
+of WINDOW's frame."
+  ;; Code mostly stolen from simple.el's `default-font-height'.
+  (let* ((window (window-normalize-window window t))
+	 (frame (window-frame window))
+	 (default-font (face-font 'default frame)))
+    (cond
+     ((and (display-multi-font-p (frame-parameter frame 'display))
+	   (not (string-equal (frame-parameter frame 'font) default-font)))
+      (aref (font-info default-font frame) 3))
+     (t (frame-char-height frame)))))
+
+(defun window-line-height (&optional window)
+  "Return number of pixels of a text line in WINDOW.
+WINDOW must be a live window and defaults to the selected one.
+The return value includes any line spacing defined for WINDOW's
+buffer or frame."
+  ;; Code mostly stolen from simple.el's `default-line-height'.
+  (let* ((window (window-normalize-window window t))
+	 (char-height (window-char-height window))
+	 (buffer (window-buffer window))
+	 (frame (window-frame window))
+	 (space-height
+	  (or (and (display-graphic-p)
+		   (or (buffer-local-value 'line-spacing buffer)
+		       (frame-parameter frame 'line-spacing)))
+	      0)))
+    (when (floatp space-height)
+      (setq space-height (truncate (* char-height space-height))))
+    (+ char-height space-height)))
+
 ;;; Resizing windows and frames to fit their contents exactly.
 (defcustom fit-window-to-buffer-horizontally nil
   "Non-nil means `fit-window-to-buffer' can resize windows horizontally.
@@ -8636,6 +8670,7 @@ fit-frame-to-buffer
            (char-height (frame-char-height frame))
            ;; WINDOW is FRAME's root window.
            (window (frame-root-window frame))
+           (line-height (window-line-height window))
            (parent (frame-parent frame))
            (monitor-attributes
             (unless parent
@@ -8732,16 +8767,16 @@ fit-frame-to-buffer
            (max-height
             (min
              (cond
-              ((numberp max-height) (* max-height char-height))
-              ((numberp (nth 0 sizes)) (* (nth 0 sizes) char-height))
+              ((numberp max-height) (* max-height line-height))
+              ((numberp (nth 0 sizes)) (* (nth 0 sizes) line-height))
               (t parent-or-display-height))
              ;; The following is the maximum height that fits into the
              ;; top and bottom margins.
              (max (- bottom-margin top-margin outer-minus-body-height))))
            (min-height
             (cond
-             ((numberp min-height) (* min-height char-height))
-             ((numberp (nth 1 sizes)) (* (nth 1 sizes) char-height))
+             ((numberp min-height) (* min-height line-height))
+             ((numberp (nth 1 sizes)) (* (nth 1 sizes) line-height))
              (t (window-min-size window nil nil t))))
            (max-width
             (min