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