aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2017-10-20 12:36:12 +0300
committerEli Zaretskii2017-10-20 12:36:12 +0300
commitfd3d8610b27e26107ba15070aba0d488152f8f4d (patch)
treed62498e78ac088c6f992a1f0077951ea9db6ba08
parent831eafc8ae201881e6449e2ab5d15d594573650b (diff)
downloademacs-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.texi49
-rw-r--r--lisp/emacs-lisp/tabulated-list.el25
-rw-r--r--lisp/proced.el3
-rw-r--r--lisp/ruler-mode.el16
-rw-r--r--src/indent.c23
-rw-r--r--src/xdisp.c51
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
2052This function returns the width used for displaying the line numbers 2052This function returns the width used for displaying the line numbers
2053in the selected window. Optional argument @var{pixelwise}, if 2053in the selected window. If the optional argument @var{pixelwise} is
2054non-@code{nil}, means return the value in pixels; otherwise the value 2054the symbol @code{columns}, the return value is a float number of the
2055is returned in column units of the font defined for the 2055frame's canonical columns; if @var{pixelwise} is @code{t} or any other
2056non-@code{nil} value, the value is an integer and is measured in
2057pixels. If @var{pixelwise} is omitted or @code{nil}, the value is the
2058integer 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
2057the numbers. If line numbers are not displayed in the selected 2060the numbers on display. If line numbers are not displayed in the
2058window, the value is zero. Use @code{with-selected-window} 2061selected 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
2060window. 2063Windows}) 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
4653height or width. The form @code{(@var{num})} specifies an absolute 4656height or width. The form @code{(@var{num})} specifies an absolute
4654number of pixels. If @var{num} is a symbol, @var{symbol}, its 4657number of pixels. If @var{num} is a symbol, @var{symbol}, its
4655buffer-local variable binding is used. 4658buffer-local variable binding is used; that binding can be either a
4659number or a cons cell of the forms shown above (including yet another
4660cons cell whose @code{car} is a symbol that has a buffer-local
4661binding).
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
4658pixels per inch, millimeter, and centimeter, respectively. The 4664pixels 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
4660and height of the current face. An image specification @code{image} 4666and height of the current face. An image specification of the form
4661corresponds to the width or height of the image. 4667@w{@code{(image . @var{props})}} (@pxref{Image Descriptors})
4668corresponds to the width or height of the specified image. Similarly,
4669an xwidget specification of the form @w{@code{(xwidget . @var{props})}}
4670stands 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.
4666window. 4676When the window displays line numbers (@pxref{Size of Displayed
4677Text}), the width of the @code{text} area is decreased by the screen
4678space 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
4669used with @code{:align-to} to specify a position relative to the left 4681used with @code{:align-to} to specify a position relative to the left
4670edge, center, or right edge of the text area. 4682edge, center, or right edge of the text area. When the window
4683displays line numbers, the @code{left} and the @code{center} positions
4684are offset to account for the screen space taken by the line-number
4685display.
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
4673used with @code{:align-to} to specify that the position is relative to 4688used 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
4685to the left edge of the text area. For example, @samp{:align-to 0} in a 4700to the left edge of the text area. For example, @samp{:align-to 0} in a
4686header-line aligns with the first text column in the text area. 4701header-line aligns with the first text column in the text area. When
4702the window displays line numbers, the text is considered to start where
4703the 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
4689product of the values of @var{num} and @var{expr}. For example, 4706product 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
4692image. 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
4695expressions. The form @code{(- @var{expr} ...)} negates or subtracts 4712expressions. 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.
336This sorts the `tabulated-list-entries' list if sorting is 334This 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
307N is a column number relative to selected frame. 307N is a column number relative to selected frame.
308If required, account for screen estate taken by `display-line-numbers'." 308If 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)
1991DEFUN ("line-number-display-width", Fline_number_display_width, 1991DEFUN ("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.
1994If optional argument PIXELWISE is non-nil, return the width in pixels, 1994If optional argument PIXELWISE is the symbol `columns', return the width
1995otherwise return the width in columns of the face used to display 1995in units of the frame's canonical character width. In this case, the
1996line numbers, `line-number'. Note that in the latter case, the value 1996value is a float.
1997doesn't include the 2 columns used for padding the numbers. */) 1997If optional argument PIXELWISE is t or any other non-nil value, return
1998the width as an integer number of pixels.
1999Otherwise return the value as an integer number of columns of the face
2000used to display line numbers, `line-number'. Note that in the latter
2001case, the value doesn't include the 2 columns used for padding the
2002numbers 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
25128static bool 25141static bool
25129calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, 25142calc_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