]> git.eshelyaron.com Git - emacs.git/commitdiff
Account for remapped faces in $COLUMNS and $LINES in Eshell
authorJim Porter <jporterbugs@gmail.com>
Fri, 3 Jun 2022 04:12:04 +0000 (21:12 -0700)
committerEli Zaretskii <eliz@gnu.org>
Thu, 9 Jun 2022 07:08:15 +0000 (10:08 +0300)
* src/window.h (window_body_unit): New enum...
(window_body_width): ... use it.

* src/window.c (window_body_unit_from_symbol): New function.
(window_body_height, window_body_width): Make PIXELWISE a
'window_body_unit'.
(window-body-height, window-body-width): Accept 'remap' for PIXELWISE.
(window-lines-pixel-dimensions, window_change_record_windows)
(run_window_change_functions, resize_frame_windows, grow_mini_window)
(shrink_mini_window, scroll-left, scroll-right): Update calls to
'window_body_height' and 'window_body_width'.

* src/indent.c (compute_motion): Update calls to 'window_body_width'.

* lisp/eshell/em-ls.el (eshell-ls-find-column-widths)
(eshell-ls-find-column-lengths): Use 'window-body-width'.

* lisp/eshell/esh-var.el (eshell-variable-aliases-list): Use
'window-body-width' and 'window-body-height'.

* test/lisp/eshell/esh-var-tests.el (esh-var-test/window-height)
(esh-var-test/window-width): Rename to...
(esh-var-test/lines-var, esh-var-test/columns-var): ... and update
expected value.

* doc/lispref/windows.texi (Window Sizes): Document new behavior of
PIXELWISE argument for 'window-body-width' and 'window-body-height'.

* etc/NEWS: Announce this change (bug#55696).

doc/lispref/windows.texi
etc/NEWS
lisp/eshell/em-ls.el
lisp/eshell/esh-var.el
src/indent.c
src/window.c
src/window.h
test/lisp/eshell/esh-var-tests.el

index 0d285b2ad460f6d1b925a6089fa7e3f34db6c1cb..704ed30366cb01d8a484427d0bd26eeda43d4383 100644 (file)
@@ -829,14 +829,18 @@ This function returns the height, in lines, of the body of window
 @var{window}.  If @var{window} is omitted or @code{nil}, it defaults to
 the selected window; otherwise it must be a live window.
 
-If the optional argument @var{pixelwise} is non-@code{nil}, this
-function returns the body height of @var{window} counted in pixels.
+The optional argument @var{pixelwise} defines the units to use for the
+height.  If @code{nil}, return the body height of @var{window} in
+characters, rounded down to the nearest integer, if necessary.  This
+means that if a line at the bottom of the text area is only partially
+visible, that line is not counted.  It also means that the height of a
+window's body can never exceed its total height as returned by
+@code{window-total-height}.
 
-If @var{pixelwise} is @code{nil}, the return value is rounded down to
-the nearest integer, if necessary.  This means that if a line at the
-bottom of the text area is only partially visible, that line is not
-counted.  It also means that the height of a window's body can never
-exceed its total height as returned by @code{window-total-height}.
+If @var{pixelwise} is @code{remap} and the default face is remapped
+(@pxref{Face Remapping}), use the remapped face to determine the
+character height.  For any other non-@code{nil} value, return the
+height in pixels.
 @end defun
 
 @cindex window body width
@@ -857,14 +861,18 @@ This function returns the width, in columns, of the body of window
 @var{window}.  If @var{window} is omitted or @code{nil}, it defaults to
 the selected window; otherwise it must be a live window.
 
-If the optional argument @var{pixelwise} is non-@code{nil}, this
-function returns the body width of @var{window} in units of pixels.
-
-If @var{pixelwise} is @code{nil}, the return value is rounded down to
-the nearest integer, if necessary.  This means that if a column on the
-right of the text area is only partially visible, that column is not
-counted.  It also means that the width of a window's body can never
-exceed its total width as returned by @code{window-total-width}.
+The optional argument @var{pixelwise} defines the units to use for the
+width.  If @code{nil}, return the body width of @var{window} in
+characters, rounded down to the nearest integer, if necessary.  This
+means that if a column on the right of the text area is only partially
+visible, that column is not counted.  It also means that the width of
+a window's body can never exceed its total width as returned by
+@code{window-total-width}.
+
+If @var{pixelwise} is @code{remap} and the default face is remapped
+(@pxref{Face Remapping}), use the remapped face to determine the
+character width.  For any other non-@code{nil} value, return the width
+in pixels.
 @end defun
 
 @cindex window body size
index fc9e949d8b5bac843a0bd260a6e47939d1f797e9..5710c4e50ab2ebf04b709a938eff83e75ae15147 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2433,6 +2433,12 @@ dimensions.
 Specifying a cons as the FROM argument allows to start measuring text
 from a specified amount of pixels above or below a position.
 
++++
+** 'window-body-width' and 'window-body-height' can use remapped faces.
+Specifying 'remap' as the PIXELWISE argument now checks if the default
+face was remapped, and if so, uses the remapped face to determine the
+character width/height.
+
 +++
 ** 'set-window-vscroll' now accepts a new argument PRESERVE-VSCROLL-P.
 This means the vscroll will not be reset when set on a window that is
index 874591d2501012ec532c0e44467af1835e9ec148..bebb0d81b5bcac9ba42fc3e49e7261d19c5b5a84 100644 (file)
@@ -800,7 +800,7 @@ to use, and each member of which is the width of that column
              (+ 2 (length (car file))))
           files))
         ;; must account for the added space...
-        (max-width (+ (window-width) 2))
+        (max-width (+ (window-body-width nil 'remap) 2))
         (best-width 0)
         col-widths)
 
@@ -845,7 +845,7 @@ to use, and each member of which is the width of that column
            (lambda (file)
              (+ 2 (length (car file))))
           files))
-        (max-width (+ (window-width) 2))
+        (max-width (+ (window-body-width nil 'remap) 2))
         col-widths
         colw)
 
index 27be6e1b1a8cc551f2be1b4ebd9be4023a64bbca..17add9b66852786addfe80acb590464614447844 100644 (file)
@@ -149,8 +149,8 @@ if they are quoted with a backslash."
 
 (defcustom eshell-variable-aliases-list
   `(;; for eshell.el
-    ("COLUMNS" ,(lambda (_indices) (window-width)) t)
-    ("LINES" ,(lambda (_indices) (window-height)) t)
+    ("COLUMNS" ,(lambda (_indices) (window-body-width nil 'remap)) t)
+    ("LINES" ,(lambda (_indices) (window-body-height nil 'remap)) t)
 
     ;; for eshell-cmd.el
     ("_" ,(lambda (indices)
index acbb9dc972344459255eafe89166ca05f3c1a1ae..51f6f414de30b31e623fcfece472443d89aa4c53 100644 (file)
@@ -1204,7 +1204,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
   /* Negative width means use all available text columns.  */
   if (width < 0)
     {
-      width = window_body_width (win, 0);
+      width = window_body_width (win, WINDOW_BODY_IN_CANONICAL_CHARS);
       /* We must make room for continuation marks if we don't have fringes.  */
 #ifdef HAVE_WINDOW_SYSTEM
       if (!FRAME_WINDOW_P (XFRAME (win->frame)))
@@ -1814,7 +1814,7 @@ visible section of the buffer, and pass LINE and COL as TOPOS.  */)
                         ? window_internal_height (w)
                         : XFIXNUM (XCDR (topos))),
                        (NILP (topos)
-                        ? (window_body_width (w, 0)
+                        ? (window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
                            - (
 #ifdef HAVE_WINDOW_SYSTEM
                               FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 :
index eba1390fed242b61ca0b5a135d96d9ee4ee8eeb6..e5666ce38e26e469923717f2fd2b34b569fe8752 100644 (file)
@@ -1014,11 +1014,20 @@ WINDOW must be a valid window and defaults to the selected one.  */)
   return make_fixnum (decode_valid_window (window)->top_line);
 }
 
+static enum window_body_unit
+window_body_unit_from_symbol (Lisp_Object unit)
+{
+  return
+    (unit == Qremap ? WINDOW_BODY_IN_REMAPPED_CHARS
+     : NILP (unit) ? WINDOW_BODY_IN_CANONICAL_CHARS
+     : WINDOW_BODY_IN_PIXELS);
+}
+
 /* Return the number of lines/pixels of W's body.  Don't count any mode
    or header line or horizontal divider of W.  Rounds down to nearest
    integer when not working pixelwise. */
 static int
-window_body_height (struct window *w, bool pixelwise)
+window_body_height (struct window *w, enum window_body_unit pixelwise)
 {
   int height = (w->pixel_height
                - WINDOW_TAB_LINE_HEIGHT (w)
@@ -1029,11 +1038,27 @@ window_body_height (struct window *w, bool pixelwise)
                - WINDOW_MODE_LINE_HEIGHT (w)
                - WINDOW_BOTTOM_DIVIDER_WIDTH (w));
 
+  int denom = 1;
+  if (pixelwise == WINDOW_BODY_IN_REMAPPED_CHARS)
+    {
+      if (!NILP (Vface_remapping_alist))
+       {
+         struct frame *f = XFRAME (WINDOW_FRAME (w));
+         int face_id = lookup_named_face (NULL, f, Qdefault, true);
+         struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
+         if (face && face->font && face->font->height)
+           denom = face->font->height;
+       }
+      /* For performance, use canonical chars if no face remapping.  */
+      else
+       pixelwise = WINDOW_BODY_IN_CANONICAL_CHARS;
+    }
+
+  if (pixelwise == WINDOW_BODY_IN_CANONICAL_CHARS)
+    denom = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
+
   /* Don't return a negative value.  */
-  return max (pixelwise
-             ? height
-             : height / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)),
-             0);
+  return max (height / denom, 0);
 }
 
 /* Return the number of columns/pixels of W's body.  Don't count columns
@@ -1042,7 +1067,7 @@ window_body_height (struct window *w, bool pixelwise)
    fringes either.  Round down to nearest integer when not working
    pixelwise.  */
 int
-window_body_width (struct window *w, bool pixelwise)
+window_body_width (struct window *w, enum window_body_unit pixelwise)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
 
@@ -1059,24 +1084,46 @@ window_body_width (struct window *w, bool pixelwise)
                   ? WINDOW_FRINGES_WIDTH (w)
                   : 0));
 
+  int denom = 1;
+  if (pixelwise == WINDOW_BODY_IN_REMAPPED_CHARS)
+    {
+      if (!NILP (Vface_remapping_alist))
+       {
+         int face_id = lookup_named_face (NULL, f, Qdefault, true);
+         struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
+         if (face && face->font)
+           {
+             if (face->font->average_width)
+               denom = face->font->average_width;
+             else if (face->font->space_width)
+               denom = face->font->space_width;
+           }
+       }
+      /* For performance, use canonical chars if no face remapping.  */
+      else
+       pixelwise = WINDOW_BODY_IN_CANONICAL_CHARS;
+    }
+
+  if (pixelwise == WINDOW_BODY_IN_CANONICAL_CHARS)
+    denom = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
+
   /* Don't return a negative value.  */
-  return max (pixelwise
-             ? width
-             : width / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)),
-             0);
+  return max (width / denom, 0);
 }
 
 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
        doc: /* Return the width of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one.  Optional
-argument PIXELWISE non-nil means return the width in pixels.  The return
-value does not include any vertical dividers, fringes or marginal areas,
-or scroll bars.
+WINDOW must be a live window and defaults to the selected one.  The
+return value does not include any vertical dividers, fringes or
+marginal areas, or scroll bars.
 
-If PIXELWISE is nil, return the largest integer smaller than WINDOW's
-pixel width divided by the character width of WINDOW's frame.  This
-means that if a column at the right of the text area is only partially
-visible, that column is not counted.
+The optional argument PIXELWISE defines the units to use for the
+width.  If nil, return the largest integer smaller than WINDOW's pixel
+width in units of the character width of WINDOW's frame.  If PIXELWISE
+is `remap' and the default face is remapped (see
+`face-remapping-alist'), use the remapped face to determine the
+character width.  For any other non-nil value, return the width in
+pixels.
 
 Note that the returned value includes the column reserved for the
 continuation glyph.
@@ -1084,25 +1131,29 @@ continuation glyph.
 Also see `window-max-chars-per-line'.  */)
   (Lisp_Object window, Lisp_Object pixelwise)
 {
-  return make_fixnum (window_body_width (decode_live_window (window),
-                                        !NILP (pixelwise)));
+  return (make_fixnum
+         (window_body_width (decode_live_window (window),
+                             window_body_unit_from_symbol (pixelwise))));
 }
 
 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
        doc: /* Return the height of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one.  Optional
-argument PIXELWISE non-nil means return the height of WINDOW's text area
-in pixels.  The return value does not include the mode line or header
-line or any horizontal divider.
-
-If PIXELWISE is nil, return the largest integer smaller than WINDOW's
-pixel height divided by the character height of WINDOW's frame.  This
-means that if a line at the bottom of the text area is only partially
-visible, that line is not counted.  */)
+WINDOW must be a live window and defaults to the selected one.  The
+return value does not include the mode line or header line or any
+horizontal divider.
+
+The optional argument PIXELWISE defines the units to use for the
+height.  If nil, return the largest integer smaller than WINDOW's
+pixel height in units of the character height of WINDOW's frame.  If
+PIXELWISE is `remap' and the default face is remapped (see
+`face-remapping-alist'), use the remapped face to determine the
+character height.  For any other non-nil value, return the height in
+pixels.  */)
   (Lisp_Object window, Lisp_Object pixelwise)
 {
-  return make_fixnum (window_body_height (decode_live_window (window),
-                                         !NILP (pixelwise)));
+  return (make_fixnum
+         (window_body_height (decode_live_window (window),
+                              window_body_unit_from_symbol (pixelwise))));
 }
 
 DEFUN ("window-old-body-pixel-width",
@@ -2124,7 +2175,8 @@ though when run from an idle timer with a delay of zero seconds.  */)
   struct glyph_row *row, *end_row;
   int max_y = NILP (body) ? WINDOW_PIXEL_HEIGHT (w) : window_text_bottom_y (w);
   Lisp_Object rows = Qnil;
-  int window_width = NILP (body) ? w->pixel_width : window_body_width (w, true);
+  int window_width = NILP (body)
+    ? w->pixel_width : window_body_width (w, WINDOW_BODY_IN_PIXELS);
   int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
   int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
   int subtract = NILP (body) ? 0 : (tab_line_height + header_line_height);
@@ -3657,8 +3709,10 @@ window_change_record_windows (Lisp_Object window, int stamp, ptrdiff_t number)
          wset_old_buffer (w, w->contents);
          w->old_pixel_width = w->pixel_width;
          w->old_pixel_height = w->pixel_height;
-         w->old_body_pixel_width = window_body_width (w, true);
-         w->old_body_pixel_height = window_body_height (w, true);
+         w->old_body_pixel_width
+           = window_body_width (w, WINDOW_BODY_IN_PIXELS);
+         w->old_body_pixel_height
+           = window_body_height (w, WINDOW_BODY_IN_PIXELS);
        }
 
       w = NILP (w->next) ? 0 : XWINDOW (w->next);
@@ -3903,8 +3957,10 @@ run_window_change_functions (void)
             && (window_buffer_change
                 || w->pixel_width != w->old_pixel_width
                 || w->pixel_height != w->old_pixel_height
-                || window_body_width (w, true) != w->old_body_pixel_width
-                || window_body_height (w, true) != w->old_body_pixel_height));
+                || (window_body_width (w, WINDOW_BODY_IN_PIXELS)
+                    != w->old_body_pixel_width)
+                || (window_body_height (w, WINDOW_BODY_IN_PIXELS)
+                    != w->old_body_pixel_height)));
 
          /* The following two are needed when running the default
             values for this frame below.  */
@@ -4768,7 +4824,8 @@ resize_frame_windows (struct frame *f, int size, bool horflag)
   Lisp_Object mini = f->minibuffer_window;
   struct window *m = WINDOWP (mini) ? XWINDOW (mini) : NULL;
   int mini_height = ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
-                    ? unit + m->pixel_height - window_body_height (m, true)
+                    ? (unit + m->pixel_height
+                       - window_body_height (m, WINDOW_BODY_IN_PIXELS))
                     : 0);
 
   new_pixel_size = max (horflag ? size : size - mini_height, unit);
@@ -5255,7 +5312,7 @@ void
 grow_mini_window (struct window *w, int delta)
 {
   struct frame *f = XFRAME (w->frame);
-  int old_height = window_body_height (w, true);
+  int old_height = window_body_height (w, WINDOW_BODY_IN_PIXELS);
   int min_height = FRAME_LINE_HEIGHT (f);
 
   eassert (MINI_WINDOW_P (w));
@@ -5289,7 +5346,8 @@ void
 shrink_mini_window (struct window *w)
 {
   struct frame *f = XFRAME (w->frame);
-  int delta = window_body_height (w, true) - FRAME_LINE_HEIGHT (f);
+  int delta = (window_body_height (w, WINDOW_BODY_IN_PIXELS)
+              - FRAME_LINE_HEIGHT (f));
 
   eassert (MINI_WINDOW_P (w));
 
@@ -6356,9 +6414,10 @@ by this function.  This happens in an interactive call.  */)
   (register Lisp_Object arg, Lisp_Object set_minimum)
 {
   struct window *w = XWINDOW (selected_window);
-  EMACS_INT requested_arg = (NILP (arg)
-                            ? window_body_width (w, 0) - 2
-                            : XFIXNUM (Fprefix_numeric_value (arg)));
+  EMACS_INT requested_arg =
+    (NILP (arg)
+     ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2
+     : XFIXNUM (Fprefix_numeric_value (arg)));
   Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
 
   if (!NILP (set_minimum))
@@ -6381,9 +6440,10 @@ by this function.  This happens in an interactive call.  */)
   (register Lisp_Object arg, Lisp_Object set_minimum)
 {
   struct window *w = XWINDOW (selected_window);
-  EMACS_INT requested_arg = (NILP (arg)
-                            ? window_body_width (w, 0) - 2
-                            : XFIXNUM (Fprefix_numeric_value (arg)));
+  EMACS_INT requested_arg =
+    (NILP (arg)
+     ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2
+     : XFIXNUM (Fprefix_numeric_value (arg)));
   Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
 
   if (!NILP (set_minimum))
index 7f7de58846320c9fbef8dc9fa18a96dec3b0788f..298a80a5366da4ad6f68970535fb9b8f93d60770 100644 (file)
@@ -1186,7 +1186,13 @@ extern bool window_wants_mode_line (struct window *);
 extern bool window_wants_header_line (struct window *);
 extern bool window_wants_tab_line (struct window *);
 extern int window_internal_height (struct window *);
-extern int window_body_width (struct window *w, bool);
+enum window_body_unit
+  {
+    WINDOW_BODY_IN_CANONICAL_CHARS,
+    WINDOW_BODY_IN_PIXELS,
+    WINDOW_BODY_IN_REMAPPED_CHARS
+  };
+extern int window_body_width (struct window *w, enum window_body_unit);
 enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS };
 extern int window_scroll_margin (struct window *, enum margin_unit);
 extern void temp_output_buffer_show (Lisp_Object);
index 072cdb9b40cbf3aa0206bee096004441805d1b74..bee495eb6e1c52d9b783b6f7cd7201253b0847a3 100644 (file)
@@ -476,13 +476,15 @@ inside double-quotes"
 \f
 ;; Built-in variables
 
-(ert-deftest esh-var-test/window-height ()
-  "$LINES should equal (window-height)"
-  (should (eshell-test-command-result "= $LINES (window-height)")))
-
-(ert-deftest esh-var-test/window-width ()
-  "$COLUMNS should equal (window-width)"
-  (should (eshell-test-command-result "= $COLUMNS (window-width)")))
+(ert-deftest esh-var-test/lines-var ()
+  "$LINES should equal (window-body-height nil 'remap)"
+  (should (equal (eshell-test-command-result "echo $LINES")
+                 (window-body-height nil 'remap))))
+
+(ert-deftest esh-var-test/columns-var ()
+  "$COLUMNS should equal (window-body-width nil 'remap)"
+  (should (equal (eshell-test-command-result "echo $COLUMNS")
+                 (window-body-width nil 'remap))))
 
 (ert-deftest esh-var-test/last-result-var ()
   "Test using the \"last result\" ($$) variable"