diff options
| author | Eli Zaretskii | 2017-10-20 12:36:12 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2017-10-20 12:36:12 +0300 |
| commit | fd3d8610b27e26107ba15070aba0d488152f8f4d (patch) | |
| tree | d62498e78ac088c6f992a1f0077951ea9db6ba08 | |
| parent | 831eafc8ae201881e6449e2ab5d15d594573650b (diff) | |
| download | emacs-fd3d8610b27e26107ba15070aba0d488152f8f4d.tar.gz emacs-fd3d8610b27e26107ba15070aba0d488152f8f4d.zip | |
Make :align-to account for display-line-numbers
These changes also update the various bundled packages to use
new feature, and better support customizations of the line-number
face.
* src/xdisp.c (calc_pixel_width_or_height): Improve commentary.
Make :align-to count from the end of the line-number display when
the offset or the width form reference that of the text area.
(Bug#28855)
* src/indent.c (Fline_number_display_width): Implement support for
the PIXELWISE argument being 'columns'. Update the doc string.
(syms_of_indent): New symbol 'columns'.
* lisp/ruler-mode.el (ruler-mode-window-col, ruler-mode-ruler):
Call line-number-display-width with last argument 'columns'.
* lisp/proced.el (proced-header-line): Call
line-number-display-width with 2nd arg 'columns', which also fixes
a problem when display-line-numbers is nil.
* lisp/emacs-lisp/tabulated-list.el
(tabulated-list-line-number-width): Call line-number-display-width
with 2nd arg 'columns.
(tabulated-list-entry-lnum-width): Remove unneeded defvar.
(tabulated-list-print, tabulated-list-print-entry): No need to
account for the value of tabulated-list-entry-lnum-width.
(tabulated-list--current-lnum-width): New defvar.
(tabulated-list-watch-line-number-width): New function.
(tabulated-list-mode): Bind tabulated-list--current-lnum-width
locally, and set up tabulated-list-watch-line-number-width as
pre-redisplay-functions hook.
* doc/lispref/display.texi (Size of Displayed Text): Document the
'columns' value of the PIXELWISE argument.
(Pixel Specification): Update and improve the documentation of the
supported forms.
| -rw-r--r-- | doc/lispref/display.texi | 49 | ||||
| -rw-r--r-- | lisp/emacs-lisp/tabulated-list.el | 25 | ||||
| -rw-r--r-- | lisp/proced.el | 3 | ||||
| -rw-r--r-- | lisp/ruler-mode.el | 16 | ||||
| -rw-r--r-- | src/indent.c | 23 | ||||
| -rw-r--r-- | src/xdisp.c | 51 |
6 files changed, 129 insertions, 38 deletions
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index fbdd810247d..17126ce72b9 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi | |||
| @@ -2050,14 +2050,17 @@ calculations. | |||
| 2050 | 2050 | ||
| 2051 | @defun line-number-display-width &optional pixelwise | 2051 | @defun line-number-display-width &optional pixelwise |
| 2052 | This function returns the width used for displaying the line numbers | 2052 | This function returns the width used for displaying the line numbers |
| 2053 | in the selected window. Optional argument @var{pixelwise}, if | 2053 | in the selected window. If the optional argument @var{pixelwise} is |
| 2054 | non-@code{nil}, means return the value in pixels; otherwise the value | 2054 | the symbol @code{columns}, the return value is a float number of the |
| 2055 | is returned in column units of the font defined for the | 2055 | frame's canonical columns; if @var{pixelwise} is @code{t} or any other |
| 2056 | non-@code{nil} value, the value is an integer and is measured in | ||
| 2057 | pixels. If @var{pixelwise} is omitted or @code{nil}, the value is the | ||
| 2058 | integer number of columns of the font defined for the | ||
| 2056 | @code{line-number} face, and doesn't include the 2 columns used to pad | 2059 | @code{line-number} face, and doesn't include the 2 columns used to pad |
| 2057 | the numbers. If line numbers are not displayed in the selected | 2060 | the numbers on display. If line numbers are not displayed in the |
| 2058 | window, the value is zero. Use @code{with-selected-window} | 2061 | selected window, the value is zero regardless of the value of |
| 2059 | (@pxref{Selecting Windows}) if you need this information about another | 2062 | @var{pixelwise}. Use @code{with-selected-window} (@pxref{Selecting |
| 2060 | window. | 2063 | Windows}) if you need this information about another window. |
| 2061 | @end defun | 2064 | @end defun |
| 2062 | 2065 | ||
| 2063 | 2066 | ||
| @@ -4636,7 +4639,7 @@ as an absolute number of pixels. | |||
| 4636 | 4639 | ||
| 4637 | @smallexample | 4640 | @smallexample |
| 4638 | @group | 4641 | @group |
| 4639 | @var{expr} ::= @var{num} | (@var{num}) | @var{unit} | @var{elem} | @var{pos} | @var{image} | @var{form} | 4642 | @var{expr} ::= @var{num} | (@var{num}) | @var{unit} | @var{elem} | @var{pos} | @var{image} | @var{xwidget} | @var{form} |
| 4640 | @var{num} ::= @var{integer} | @var{float} | @var{symbol} | 4643 | @var{num} ::= @var{integer} | @var{float} | @var{symbol} |
| 4641 | @var{unit} ::= in | mm | cm | width | height | 4644 | @var{unit} ::= in | mm | cm | width | height |
| 4642 | @end group | 4645 | @end group |
| @@ -4652,22 +4655,34 @@ as an absolute number of pixels. | |||
| 4652 | The form @var{num} specifies a fraction of the default frame font | 4655 | The form @var{num} specifies a fraction of the default frame font |
| 4653 | height or width. The form @code{(@var{num})} specifies an absolute | 4656 | height or width. The form @code{(@var{num})} specifies an absolute |
| 4654 | number of pixels. If @var{num} is a symbol, @var{symbol}, its | 4657 | number of pixels. If @var{num} is a symbol, @var{symbol}, its |
| 4655 | buffer-local variable binding is used. | 4658 | buffer-local variable binding is used; that binding can be either a |
| 4659 | number or a cons cell of the forms shown above (including yet another | ||
| 4660 | cons cell whose @code{car} is a symbol that has a buffer-local | ||
| 4661 | binding). | ||
| 4656 | 4662 | ||
| 4657 | The @code{in}, @code{mm}, and @code{cm} units specify the number of | 4663 | The @code{in}, @code{mm}, and @code{cm} units specify the number of |
| 4658 | pixels per inch, millimeter, and centimeter, respectively. The | 4664 | pixels per inch, millimeter, and centimeter, respectively. The |
| 4659 | @code{width} and @code{height} units correspond to the default width | 4665 | @code{width} and @code{height} units correspond to the default width |
| 4660 | and height of the current face. An image specification @code{image} | 4666 | and height of the current face. An image specification of the form |
| 4661 | corresponds to the width or height of the image. | 4667 | @w{@code{(image . @var{props})}} (@pxref{Image Descriptors}) |
| 4668 | corresponds to the width or height of the specified image. Similarly, | ||
| 4669 | an xwidget specification of the form @w{@code{(xwidget . @var{props})}} | ||
| 4670 | stands for the width or height of the specified xwidget. | ||
| 4671 | @xref{Xwidgets}. | ||
| 4662 | 4672 | ||
| 4663 | The elements @code{left-fringe}, @code{right-fringe}, | 4673 | The elements @code{left-fringe}, @code{right-fringe}, |
| 4664 | @code{left-margin}, @code{right-margin}, @code{scroll-bar}, and | 4674 | @code{left-margin}, @code{right-margin}, @code{scroll-bar}, and |
| 4665 | @code{text} specify to the width of the corresponding area of the | 4675 | @code{text} specify the width of the corresponding area of the window. |
| 4666 | window. | 4676 | When the window displays line numbers (@pxref{Size of Displayed |
| 4677 | Text}), the width of the @code{text} area is decreased by the screen | ||
| 4678 | space taken by the line-number display. | ||
| 4667 | 4679 | ||
| 4668 | The @code{left}, @code{center}, and @code{right} positions can be | 4680 | The @code{left}, @code{center}, and @code{right} positions can be |
| 4669 | used with @code{:align-to} to specify a position relative to the left | 4681 | used with @code{:align-to} to specify a position relative to the left |
| 4670 | edge, center, or right edge of the text area. | 4682 | edge, center, or right edge of the text area. When the window |
| 4683 | displays line numbers, the @code{left} and the @code{center} positions | ||
| 4684 | are offset to account for the screen space taken by the line-number | ||
| 4685 | display. | ||
| 4671 | 4686 | ||
| 4672 | Any of the above window elements (except @code{text}) can also be | 4687 | Any of the above window elements (except @code{text}) can also be |
| 4673 | used with @code{:align-to} to specify that the position is relative to | 4688 | used with @code{:align-to} to specify that the position is relative to |
| @@ -4683,13 +4698,15 @@ the left-margin, use | |||
| 4683 | 4698 | ||
| 4684 | If no specific base offset is set for alignment, it is always relative | 4699 | If no specific base offset is set for alignment, it is always relative |
| 4685 | to the left edge of the text area. For example, @samp{:align-to 0} in a | 4700 | to the left edge of the text area. For example, @samp{:align-to 0} in a |
| 4686 | header-line aligns with the first text column in the text area. | 4701 | header-line aligns with the first text column in the text area. When |
| 4702 | the window displays line numbers, the text is considered to start where | ||
| 4703 | the space used for line-number display ends. | ||
| 4687 | 4704 | ||
| 4688 | A value of the form @code{(@var{num} . @var{expr})} stands for the | 4705 | A value of the form @code{(@var{num} . @var{expr})} stands for the |
| 4689 | product of the values of @var{num} and @var{expr}. For example, | 4706 | product of the values of @var{num} and @var{expr}. For example, |
| 4690 | @code{(2 . in)} specifies a width of 2 inches, while @code{(0.5 . | 4707 | @code{(2 . in)} specifies a width of 2 inches, while @code{(0.5 . |
| 4691 | @var{image})} specifies half the width (or height) of the specified | 4708 | @var{image})} specifies half the width (or height) of the specified |
| 4692 | image. | 4709 | @var{image} (which should be given by its image spec). |
| 4693 | 4710 | ||
| 4694 | The form @code{(+ @var{expr} ...)} adds up the value of the | 4711 | The form @code{(+ @var{expr} ...)} adds up the value of the |
| 4695 | expressions. The form @code{(- @var{expr} ...)} negates or subtracts | 4712 | expressions. The form @code{(- @var{expr} ...)} negates or subtracts |
diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el index d1d7c0a8042..73ddadfb805 100644 --- a/lisp/emacs-lisp/tabulated-list.el +++ b/lisp/emacs-lisp/tabulated-list.el | |||
| @@ -193,10 +193,10 @@ Populated by `tabulated-list-init-header'.") | |||
| 193 | ;; is displayed. | 193 | ;; is displayed. |
| 194 | (if (not display-line-numbers) | 194 | (if (not display-line-numbers) |
| 195 | 0 | 195 | 0 |
| 196 | (let ((cbuf-window (get-buffer-window (current-buffer)))) | 196 | (let ((cbuf-window (get-buffer-window (current-buffer) t))) |
| 197 | (if (window-live-p cbuf-window) | 197 | (if (window-live-p cbuf-window) |
| 198 | (with-selected-window cbuf-window | 198 | (with-selected-window cbuf-window |
| 199 | (+ (line-number-display-width) 2)) | 199 | (line-number-display-width 'columns)) |
| 200 | 4)))) | 200 | 4)))) |
| 201 | 201 | ||
| 202 | (defun tabulated-list-init-header () | 202 | (defun tabulated-list-init-header () |
| @@ -329,8 +329,6 @@ Check the current row, the previous one and the next row." | |||
| 329 | (string-width (if (stringp nt) nt (car nt))))) | 329 | (string-width (if (stringp nt) nt (car nt))))) |
| 330 | tabulated-list--near-rows))) | 330 | tabulated-list--near-rows))) |
| 331 | 331 | ||
| 332 | (defvar tabulated-list-entry-lnum-width nil) | ||
| 333 | |||
| 334 | (defun tabulated-list-print (&optional remember-pos update) | 332 | (defun tabulated-list-print (&optional remember-pos update) |
| 335 | "Populate the current Tabulated List mode buffer. | 333 | "Populate the current Tabulated List mode buffer. |
| 336 | This sorts the `tabulated-list-entries' list if sorting is | 334 | This sorts the `tabulated-list-entries' list if sorting is |
| @@ -373,7 +371,6 @@ changing `tabulated-list-sort-key'." | |||
| 373 | (unless tabulated-list-use-header-line | 371 | (unless tabulated-list-use-header-line |
| 374 | (tabulated-list-print-fake-header))) | 372 | (tabulated-list-print-fake-header))) |
| 375 | ;; Finally, print the resulting list. | 373 | ;; Finally, print the resulting list. |
| 376 | (setq tabulated-list-entry-lnum-width (tabulated-list-line-number-width)) | ||
| 377 | (while entries | 374 | (while entries |
| 378 | (let* ((elt (car entries)) | 375 | (let* ((elt (car entries)) |
| 379 | (tabulated-list--near-rows | 376 | (tabulated-list--near-rows |
| @@ -428,9 +425,8 @@ of column descriptors." | |||
| 428 | (x (max tabulated-list-padding 0)) | 425 | (x (max tabulated-list-padding 0)) |
| 429 | (ncols (length tabulated-list-format)) | 426 | (ncols (length tabulated-list-format)) |
| 430 | (inhibit-read-only t)) | 427 | (inhibit-read-only t)) |
| 431 | (setq x (+ x tabulated-list-entry-lnum-width)) | ||
| 432 | (if (> tabulated-list-padding 0) | 428 | (if (> tabulated-list-padding 0) |
| 433 | (insert (make-string (- x tabulated-list-entry-lnum-width) ?\s))) | 429 | (insert (make-string x ?\s))) |
| 434 | (let ((tabulated-list--near-rows ; Bind it if not bound yet (Bug#25506). | 430 | (let ((tabulated-list--near-rows ; Bind it if not bound yet (Bug#25506). |
| 435 | (or (bound-and-true-p tabulated-list--near-rows) | 431 | (or (bound-and-true-p tabulated-list--near-rows) |
| 436 | (list (or (tabulated-list-get-entry (point-at-bol 0)) | 432 | (list (or (tabulated-list-get-entry (point-at-bol 0)) |
| @@ -601,6 +597,14 @@ With a numeric prefix argument N, sort the Nth column." | |||
| 601 | (tabulated-list-init-header) | 597 | (tabulated-list-init-header) |
| 602 | (tabulated-list-print t))) | 598 | (tabulated-list-print t))) |
| 603 | 599 | ||
| 600 | (defvar tabulated-list--current-lnum-width nil) | ||
| 601 | (defun tabulated-list-watch-line-number-width (_window) | ||
| 602 | (if display-line-numbers | ||
| 603 | (let ((lnum-width (tabulated-list-line-number-width))) | ||
| 604 | (when (not (= tabulated-list--current-lnum-width lnum-width)) | ||
| 605 | (setq-local tabulated-list--current-lnum-width lnum-width) | ||
| 606 | (tabulated-list-revert))))) | ||
| 607 | |||
| 604 | ;;; The mode definition: | 608 | ;;; The mode definition: |
| 605 | 609 | ||
| 606 | (define-derived-mode tabulated-list-mode special-mode "Tabulated" | 610 | (define-derived-mode tabulated-list-mode special-mode "Tabulated" |
| @@ -645,7 +649,12 @@ as the ewoc pretty-printer." | |||
| 645 | ;; column of the first entry happens to begin with a R2L letter. | 649 | ;; column of the first entry happens to begin with a R2L letter. |
| 646 | (setq bidi-paragraph-direction 'left-to-right) | 650 | (setq bidi-paragraph-direction 'left-to-right) |
| 647 | ;; This is for if/when they turn on display-line-numbers | 651 | ;; This is for if/when they turn on display-line-numbers |
| 648 | (add-hook 'display-line-numbers-mode-hook #'tabulated-list-revert nil t)) | 652 | (add-hook 'display-line-numbers-mode-hook #'tabulated-list-revert nil t) |
| 653 | ;; This is for if/when they customize the line-number face or when | ||
| 654 | ;; the line-number width needs to change due to scrolling. | ||
| 655 | (setq-local tabulated-list--current-lnum-width 0) | ||
| 656 | (add-hook 'pre-redisplay-functions | ||
| 657 | #'tabulated-list-watch-line-number-width nil t)) | ||
| 649 | 658 | ||
| 650 | (put 'tabulated-list-mode 'mode-class 'special) | 659 | (put 'tabulated-list-mode 'mode-class 'special) |
| 651 | 660 | ||
diff --git a/lisp/proced.el b/lisp/proced.el index c9e851b7e05..aec54b59211 100644 --- a/lisp/proced.el +++ b/lisp/proced.el | |||
| @@ -604,7 +604,8 @@ Important: the match ends just after the marker.") | |||
| 604 | "Return header line for Proced buffer." | 604 | "Return header line for Proced buffer." |
| 605 | (list (propertize " " | 605 | (list (propertize " " |
| 606 | 'display | 606 | 'display |
| 607 | (list 'space :align-to (+ 2 (line-number-display-width)))) | 607 | (list 'space :align-to |
| 608 | (line-number-display-width 'columns))) | ||
| 608 | (if (<= (window-hscroll) (length proced-header-line)) | 609 | (if (<= (window-hscroll) (length proced-header-line)) |
| 609 | (replace-regexp-in-string ;; preserve text properties | 610 | (replace-regexp-in-string ;; preserve text properties |
| 610 | "\\(%\\)" "\\1\\1" | 611 | "\\(%\\)" "\\1\\1" |
diff --git a/lisp/ruler-mode.el b/lisp/ruler-mode.el index 7a23f4d03c0..3d27858d0fe 100644 --- a/lisp/ruler-mode.el +++ b/lisp/ruler-mode.el | |||
| @@ -307,7 +307,12 @@ or remove a tab stop. \\[ruler-mode-toggle-show-tab-stops] or | |||
| 307 | N is a column number relative to selected frame. | 307 | N is a column number relative to selected frame. |
| 308 | If required, account for screen estate taken by `display-line-numbers'." | 308 | If required, account for screen estate taken by `display-line-numbers'." |
| 309 | (if display-line-numbers | 309 | (if display-line-numbers |
| 310 | (setq n (- n (line-number-display-width) 2))) | 310 | ;; FIXME: ruler-mode relies on N being an integer, so if the |
| 311 | ;; 'line-number' face is customized to use a font that is larger | ||
| 312 | ;; or smaller than that of the default face, the alignment might | ||
| 313 | ;; be off by up to half a column, unless the font width is an | ||
| 314 | ;; integral multiple or divisor of the default face's font. | ||
| 315 | (setq n (- n (round (line-number-display-width 'columns))))) | ||
| 311 | (- n | 316 | (- n |
| 312 | (or (car (window-margins)) 0) | 317 | (or (car (window-margins)) 0) |
| 313 | (fringe-columns 'left) | 318 | (fringe-columns 'left) |
| @@ -668,7 +673,12 @@ Optional argument PROPS specifies other text properties to apply." | |||
| 668 | (let* ((w (ruler-mode-text-scaled-window-width)) | 673 | (let* ((w (ruler-mode-text-scaled-window-width)) |
| 669 | (m (window-margins)) | 674 | (m (window-margins)) |
| 670 | (f (window-fringes)) | 675 | (f (window-fringes)) |
| 671 | (i (if display-line-numbers (+ (line-number-display-width) 2) 0)) | 676 | (i (if display-line-numbers |
| 677 | ;; FIXME: ruler-mode relies on I being an integer, so | ||
| 678 | ;; the column numbers might be slightly off if the | ||
| 679 | ;; line-number face is customized. | ||
| 680 | (round (line-number-display-width 'columns)) | ||
| 681 | 0)) | ||
| 672 | (j (ruler-mode-text-scaled-window-hscroll)) | 682 | (j (ruler-mode-text-scaled-window-hscroll)) |
| 673 | ;; Setup the scrollbar, fringes, and margins areas. | 683 | ;; Setup the scrollbar, fringes, and margins areas. |
| 674 | (lf (ruler-mode-space | 684 | (lf (ruler-mode-space |
| @@ -708,7 +718,7 @@ Optional argument PROPS specifies other text properties to apply." | |||
| 708 | ;; line-number display be blank, not filled with | 718 | ;; line-number display be blank, not filled with |
| 709 | ;; ruler-mode-basic-graduation-char. | 719 | ;; ruler-mode-basic-graduation-char. |
| 710 | (if display-line-numbers | 720 | (if display-line-numbers |
| 711 | (let* ((lndw (+ (line-number-display-width) 2)) | 721 | (let* ((lndw (round (line-number-display-width 'columns))) |
| 712 | (s (make-string lndw ?\s))) | 722 | (s (make-string lndw ?\s))) |
| 713 | (concat s (make-string (- w lndw) | 723 | (concat s (make-string (- w lndw) |
| 714 | ruler-mode-basic-graduation-char))) | 724 | ruler-mode-basic-graduation-char))) |
diff --git a/src/indent.c b/src/indent.c index a3e9b5b0b9a..192eec72efe 100644 --- a/src/indent.c +++ b/src/indent.c | |||
| @@ -1991,15 +1991,26 @@ line_number_display_width (struct window *w, int *width, int *pixel_width) | |||
| 1991 | DEFUN ("line-number-display-width", Fline_number_display_width, | 1991 | DEFUN ("line-number-display-width", Fline_number_display_width, |
| 1992 | Sline_number_display_width, 0, 1, 0, | 1992 | Sline_number_display_width, 0, 1, 0, |
| 1993 | doc: /* Return the width used for displaying line numbers in the selected window. | 1993 | doc: /* Return the width used for displaying line numbers in the selected window. |
| 1994 | If optional argument PIXELWISE is non-nil, return the width in pixels, | 1994 | If optional argument PIXELWISE is the symbol `columns', return the width |
| 1995 | otherwise return the width in columns of the face used to display | 1995 | in units of the frame's canonical character width. In this case, the |
| 1996 | line numbers, `line-number'. Note that in the latter case, the value | 1996 | value is a float. |
| 1997 | doesn't include the 2 columns used for padding the numbers. */) | 1997 | If optional argument PIXELWISE is t or any other non-nil value, return |
| 1998 | the width as an integer number of pixels. | ||
| 1999 | Otherwise return the value as an integer number of columns of the face | ||
| 2000 | used to display line numbers, `line-number'. Note that in the latter | ||
| 2001 | case, the value doesn't include the 2 columns used for padding the | ||
| 2002 | numbers on display. */) | ||
| 1998 | (Lisp_Object pixelwise) | 2003 | (Lisp_Object pixelwise) |
| 1999 | { | 2004 | { |
| 2000 | int width, pixel_width; | 2005 | int width, pixel_width; |
| 2006 | struct window *w = XWINDOW (selected_window); | ||
| 2001 | line_number_display_width (XWINDOW (selected_window), &width, &pixel_width); | 2007 | line_number_display_width (XWINDOW (selected_window), &width, &pixel_width); |
| 2002 | if (!NILP (pixelwise)) | 2008 | if (EQ (pixelwise, Qcolumns)) |
| 2009 | { | ||
| 2010 | struct frame *f = XFRAME (w->frame); | ||
| 2011 | return make_float ((double) pixel_width / FRAME_COLUMN_WIDTH (f)); | ||
| 2012 | } | ||
| 2013 | else if (!NILP (pixelwise)) | ||
| 2003 | return make_number (pixel_width); | 2014 | return make_number (pixel_width); |
| 2004 | return make_number (width); | 2015 | return make_number (width); |
| 2005 | } | 2016 | } |
| @@ -2361,6 +2372,8 @@ syms_of_indent (void) | |||
| 2361 | doc: /* Indentation can insert tabs if this is non-nil. */); | 2372 | doc: /* Indentation can insert tabs if this is non-nil. */); |
| 2362 | indent_tabs_mode = 1; | 2373 | indent_tabs_mode = 1; |
| 2363 | 2374 | ||
| 2375 | DEFSYM (Qcolumns, "columns"); | ||
| 2376 | |||
| 2364 | defsubr (&Scurrent_indentation); | 2377 | defsubr (&Scurrent_indentation); |
| 2365 | defsubr (&Sindent_to); | 2378 | defsubr (&Sindent_to); |
| 2366 | defsubr (&Scurrent_column); | 2379 | defsubr (&Scurrent_column); |
diff --git a/src/xdisp.c b/src/xdisp.c index 6d9acecb424..dc23959aadb 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -25123,7 +25123,20 @@ else if the text is replaced by an ellipsis. */) | |||
| 25123 | '(space :width (+ left-fringe left-margin (- (1)))) | 25123 | '(space :width (+ left-fringe left-margin (- (1)))) |
| 25124 | '(space :width (+ left-fringe left-margin (-1))) | 25124 | '(space :width (+ left-fringe left-margin (-1))) |
| 25125 | 25125 | ||
| 25126 | */ | 25126 | If ALIGN_TO is NULL, returns the result in *RES. If ALIGN_TO is |
| 25127 | non-NULL, the value of *ALIGN_TO is a window-relative pixel | ||
| 25128 | coordinate, and *RES is the additional pixel width from that point | ||
| 25129 | till the end of the stretch glyph. | ||
| 25130 | |||
| 25131 | WIDTH_P non-zero means take the width dimension or X coordinate of | ||
| 25132 | the object specified by PROP, WIDTH_P zero means take the height | ||
| 25133 | dimension or the Y coordinate. (Therefore, if ALIGN_TO is | ||
| 25134 | non-NULL, WIDTH_P should be non-zero.) | ||
| 25135 | |||
| 25136 | FONT is the font of the face of the surrounding text. | ||
| 25137 | |||
| 25138 | The return value is non-zero if width or height were successfully | ||
| 25139 | calculated, i.e. if PROP is a valid spec. */ | ||
| 25127 | 25140 | ||
| 25128 | static bool | 25141 | static bool |
| 25129 | calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, | 25142 | calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, |
| @@ -25145,6 +25158,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, | |||
| 25145 | { | 25158 | { |
| 25146 | char *unit = SSDATA (SYMBOL_NAME (prop)); | 25159 | char *unit = SSDATA (SYMBOL_NAME (prop)); |
| 25147 | 25160 | ||
| 25161 | /* The UNIT expression, e.g. as part of (NUM . UNIT). */ | ||
| 25148 | if (unit[0] == 'i' && unit[1] == 'n') | 25162 | if (unit[0] == 'i' && unit[1] == 'n') |
| 25149 | pixels = 1.0; | 25163 | pixels = 1.0; |
| 25150 | else if (unit[0] == 'm' && unit[1] == 'm') | 25164 | else if (unit[0] == 'm' && unit[1] == 'm') |
| @@ -25165,10 +25179,12 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, | |||
| 25165 | } | 25179 | } |
| 25166 | 25180 | ||
| 25167 | #ifdef HAVE_WINDOW_SYSTEM | 25181 | #ifdef HAVE_WINDOW_SYSTEM |
| 25182 | /* 'height': the height of FONT. */ | ||
| 25168 | if (EQ (prop, Qheight)) | 25183 | if (EQ (prop, Qheight)) |
| 25169 | return OK_PIXELS (font | 25184 | return OK_PIXELS (font |
| 25170 | ? normal_char_height (font, -1) | 25185 | ? normal_char_height (font, -1) |
| 25171 | : FRAME_LINE_HEIGHT (it->f)); | 25186 | : FRAME_LINE_HEIGHT (it->f)); |
| 25187 | /* 'width': the width of FONT. */ | ||
| 25172 | if (EQ (prop, Qwidth)) | 25188 | if (EQ (prop, Qwidth)) |
| 25173 | return OK_PIXELS (font | 25189 | return OK_PIXELS (font |
| 25174 | ? FONT_WIDTH (font) | 25190 | ? FONT_WIDTH (font) |
| @@ -25178,33 +25194,48 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, | |||
| 25178 | return OK_PIXELS (1); | 25194 | return OK_PIXELS (1); |
| 25179 | #endif | 25195 | #endif |
| 25180 | 25196 | ||
| 25197 | /* 'text': the width or height of the text area. */ | ||
| 25181 | if (EQ (prop, Qtext)) | 25198 | if (EQ (prop, Qtext)) |
| 25182 | return OK_PIXELS (width_p | 25199 | return OK_PIXELS (width_p |
| 25183 | ? window_box_width (it->w, TEXT_AREA) | 25200 | ? (window_box_width (it->w, TEXT_AREA) |
| 25201 | - it->lnum_pixel_width) | ||
| 25184 | : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w)); | 25202 | : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w)); |
| 25185 | 25203 | ||
| 25204 | /* ':align_to'. First time we compute the value, window | ||
| 25205 | elements are interpreted as the position of the element's | ||
| 25206 | left edge. */ | ||
| 25186 | if (align_to && *align_to < 0) | 25207 | if (align_to && *align_to < 0) |
| 25187 | { | 25208 | { |
| 25188 | *res = 0; | 25209 | *res = 0; |
| 25210 | /* 'left': left edge of the text area. */ | ||
| 25189 | if (EQ (prop, Qleft)) | 25211 | if (EQ (prop, Qleft)) |
| 25190 | return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)); | 25212 | return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA) |
| 25213 | + it->lnum_pixel_width); | ||
| 25214 | /* 'right': right edge of the text area. */ | ||
| 25191 | if (EQ (prop, Qright)) | 25215 | if (EQ (prop, Qright)) |
| 25192 | return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA)); | 25216 | return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA)); |
| 25217 | /* 'center': the center of the text area. */ | ||
| 25193 | if (EQ (prop, Qcenter)) | 25218 | if (EQ (prop, Qcenter)) |
| 25194 | return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA) | 25219 | return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA) |
| 25220 | + it->lnum_pixel_width | ||
| 25195 | + window_box_width (it->w, TEXT_AREA) / 2); | 25221 | + window_box_width (it->w, TEXT_AREA) / 2); |
| 25222 | /* 'left-fringe': left edge of the left fringe. */ | ||
| 25196 | if (EQ (prop, Qleft_fringe)) | 25223 | if (EQ (prop, Qleft_fringe)) |
| 25197 | return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w) | 25224 | return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w) |
| 25198 | ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w) | 25225 | ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w) |
| 25199 | : window_box_right_offset (it->w, LEFT_MARGIN_AREA)); | 25226 | : window_box_right_offset (it->w, LEFT_MARGIN_AREA)); |
| 25227 | /* 'right-fringe': left edge of the right fringe. */ | ||
| 25200 | if (EQ (prop, Qright_fringe)) | 25228 | if (EQ (prop, Qright_fringe)) |
| 25201 | return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w) | 25229 | return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w) |
| 25202 | ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA) | 25230 | ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA) |
| 25203 | : window_box_right_offset (it->w, TEXT_AREA)); | 25231 | : window_box_right_offset (it->w, TEXT_AREA)); |
| 25232 | /* 'left-margin': left edge of the left display margin. */ | ||
| 25204 | if (EQ (prop, Qleft_margin)) | 25233 | if (EQ (prop, Qleft_margin)) |
| 25205 | return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA)); | 25234 | return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA)); |
| 25235 | /* 'right-margin': left edge of the right display margin. */ | ||
| 25206 | if (EQ (prop, Qright_margin)) | 25236 | if (EQ (prop, Qright_margin)) |
| 25207 | return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA)); | 25237 | return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA)); |
| 25238 | /* 'scroll-bar': left edge of the vertical scroll bar. */ | ||
| 25208 | if (EQ (prop, Qscroll_bar)) | 25239 | if (EQ (prop, Qscroll_bar)) |
| 25209 | return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w) | 25240 | return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w) |
| 25210 | ? 0 | 25241 | ? 0 |
| @@ -25215,6 +25246,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, | |||
| 25215 | } | 25246 | } |
| 25216 | else | 25247 | else |
| 25217 | { | 25248 | { |
| 25249 | /* Otherwise, the elements stand for their width. */ | ||
| 25218 | if (EQ (prop, Qleft_fringe)) | 25250 | if (EQ (prop, Qleft_fringe)) |
| 25219 | return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w)); | 25251 | return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w)); |
| 25220 | if (EQ (prop, Qright_fringe)) | 25252 | if (EQ (prop, Qright_fringe)) |
| @@ -25237,6 +25269,8 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, | |||
| 25237 | int base_unit = (width_p | 25269 | int base_unit = (width_p |
| 25238 | ? FRAME_COLUMN_WIDTH (it->f) | 25270 | ? FRAME_COLUMN_WIDTH (it->f) |
| 25239 | : FRAME_LINE_HEIGHT (it->f)); | 25271 | : FRAME_LINE_HEIGHT (it->f)); |
| 25272 | if (width_p && align_to && *align_to < 0) | ||
| 25273 | return OK_PIXELS (XFLOATINT (prop) * base_unit + it->lnum_pixel_width); | ||
| 25240 | return OK_PIXELS (XFLOATINT (prop) * base_unit); | 25274 | return OK_PIXELS (XFLOATINT (prop) * base_unit); |
| 25241 | } | 25275 | } |
| 25242 | 25276 | ||
| @@ -25248,6 +25282,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, | |||
| 25248 | if (SYMBOLP (car)) | 25282 | if (SYMBOLP (car)) |
| 25249 | { | 25283 | { |
| 25250 | #ifdef HAVE_WINDOW_SYSTEM | 25284 | #ifdef HAVE_WINDOW_SYSTEM |
| 25285 | /* '(image PROPS...)': width or height of the specified image. */ | ||
| 25251 | if (FRAME_WINDOW_P (it->f) | 25286 | if (FRAME_WINDOW_P (it->f) |
| 25252 | && valid_image_p (prop)) | 25287 | && valid_image_p (prop)) |
| 25253 | { | 25288 | { |
| @@ -25256,12 +25291,15 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, | |||
| 25256 | 25291 | ||
| 25257 | return OK_PIXELS (width_p ? img->width : img->height); | 25292 | return OK_PIXELS (width_p ? img->width : img->height); |
| 25258 | } | 25293 | } |
| 25294 | /* '(xwidget PROPS...)': dimensions of the specified xwidget. */ | ||
| 25259 | if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop)) | 25295 | if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop)) |
| 25260 | { | 25296 | { |
| 25261 | /* TODO: Don't return dummy size. */ | 25297 | /* TODO: Don't return dummy size. */ |
| 25262 | return OK_PIXELS (100); | 25298 | return OK_PIXELS (100); |
| 25263 | } | 25299 | } |
| 25264 | #endif | 25300 | #endif |
| 25301 | /* '(+ EXPR...)' or '(- EXPR...)' add or subtract | ||
| 25302 | recursively calculated values. */ | ||
| 25265 | if (EQ (car, Qplus) || EQ (car, Qminus)) | 25303 | if (EQ (car, Qplus) || EQ (car, Qminus)) |
| 25266 | { | 25304 | { |
| 25267 | bool first = true; | 25305 | bool first = true; |
| @@ -25289,15 +25327,18 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, | |||
| 25289 | car = Qnil; | 25327 | car = Qnil; |
| 25290 | } | 25328 | } |
| 25291 | 25329 | ||
| 25330 | /* '(NUM)': absolute number of pixels. */ | ||
| 25292 | if (NUMBERP (car)) | 25331 | if (NUMBERP (car)) |
| 25293 | { | 25332 | { |
| 25294 | double fact; | 25333 | double fact; |
| 25334 | int offset = | ||
| 25335 | width_p && align_to && *align_to < 0 ? it->lnum_pixel_width : 0; | ||
| 25295 | pixels = XFLOATINT (car); | 25336 | pixels = XFLOATINT (car); |
| 25296 | if (NILP (cdr)) | 25337 | if (NILP (cdr)) |
| 25297 | return OK_PIXELS (pixels); | 25338 | return OK_PIXELS (pixels + offset); |
| 25298 | if (calc_pixel_width_or_height (&fact, it, cdr, | 25339 | if (calc_pixel_width_or_height (&fact, it, cdr, |
| 25299 | font, width_p, align_to)) | 25340 | font, width_p, align_to)) |
| 25300 | return OK_PIXELS (pixels * fact); | 25341 | return OK_PIXELS (pixels * fact + offset); |
| 25301 | return false; | 25342 | return false; |
| 25302 | } | 25343 | } |
| 25303 | 25344 | ||