master e0f3a4d4b2a 1/2: Fix :align-to when line numbers are displayed

Eli Zaretskii <[email protected]>
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: master
commit e0f3a4d4b2a47bcf56acd99ddadb9c21a5811a80
Author: Aaron Jensen <[email protected]>
Commit: Eli Zaretskii <[email protected]>

    Fix :align-to when line numbers are displayed
    
    * src/xdisp.c (calc_pixel_width_or_height): Don't account for the
    line-number display more than once.  (Bug#81253)
    
    * test/lisp/visual-wrap-tests.el
    (visual-wrap-tests/line-numbers-align-to-wrap-prefix): New test.
---
 src/xdisp.c                    | 23 ++++++++++++++++++-----
 test/lisp/visual-wrap-tests.el | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/src/xdisp.c b/src/xdisp.c
index e2321762699..6e910978bd7 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -30452,7 +30452,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
       /* ':align_to'.  First time we compute the value, window
 	 elements are interpreted as the position of the element's
 	 left edge.  */
-      if (align_to && *align_to < 0)
+      if (align_to && *align_to == -1)
 	{
 	  *res = 0;
 	  /* 'left': left edge of the text area.  */
@@ -30517,8 +30517,14 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
       int base_unit = (width_p
 		       ? FRAME_COLUMN_WIDTH (it->f)
 		       : FRAME_LINE_HEIGHT (it->f));
-      if (width_p && align_to && *align_to < 0)
-	return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
+      /* `align_to' starts at -1.  A numeric value without an explicit
+	 base is relative to the text area's left edge, so account for
+	 line numbers once and mark the default base as consumed.  */
+      if (width_p && align_to && *align_to == -1)
+	{
+	  *align_to = -2;
+	  return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
+	}
       return OK_PIXELS (XFLOATINT (prop) * base_unit);
     }
 
@@ -30579,8 +30585,15 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
       if (NUMBERP (car))
 	{
 	  double fact;
-	  int offset =
-	    width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
+	  int offset = 0;
+	  /* See the NUMBERP case above: the default text-area base
+	     should apply once to the whole pixel expression, not once
+	     for each numeric subexpression.  */
+	  if (width_p && align_to && *align_to == -1)
+	    {
+	      offset = lnum_pixel_width;
+	      *align_to = -2;
+	    }
 	  pixels = XFLOATINT (car);
 	  if (NILP (cdr))
 	    return OK_PIXELS (pixels + offset);
diff --git a/test/lisp/visual-wrap-tests.el b/test/lisp/visual-wrap-tests.el
index a1f286cf96a..6817e82bc8b 100644
--- a/test/lisp/visual-wrap-tests.el
+++ b/test/lisp/visual-wrap-tests.el
@@ -178,4 +178,37 @@ property is installed on line 1.  See bug#81039."
                       (ensure-list
                        (get-text-property (point-min) 'display))))))
 
+(ert-deftest visual-wrap-tests/line-numbers-align-to-wrap-prefix ()
+  "With line numbers, `wrap-prefix' `:align-to' aligns from text start."
+  (skip-unless (display-graphic-p))
+  (let ((buffer (generate-new-buffer " *visual-wrap-test*")))
+    (unwind-protect
+        (let ((window (display-buffer buffer)))
+          (with-selected-window window
+            (setq-local display-line-numbers t)
+            (visual-line-mode 1)
+            (let* ((columns (window-width))
+                   ;; Make the first word fit on visual line 1, but leave
+                   ;; too little room for the second word so word wrapping
+                   ;; moves it to visual line 2.
+                   (first-word-width (max 10 (- columns 20))))
+              (insert "- "
+                      (make-string first-word-width ?n)
+                      " "
+                      (make-string 20 ?n)))
+            (visual-wrap-prefix-function (point-min) (point-max))
+            (redisplay t)
+            (let* ((bol-x (car (posn-x-y (posn-at-point (point-min)))))
+                   (prefix-width (string-pixel-width "- " (current-buffer)))
+                   (second-word-pos
+                    (save-excursion
+                      (goto-char (point-min))
+                      (search-forward " " nil t 2)
+                      (point)))
+                   (second-word-x
+                    (car (posn-x-y (posn-at-point second-word-pos)))))
+              (should (= second-word-x (+ bol-x prefix-width))))))
+      (when (buffer-live-p buffer)
+        (kill-buffer buffer)))))
+
 ;; visual-wrap-tests.el ends here
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.