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 /src | |
| 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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/indent.c | 23 | ||||
| -rw-r--r-- | src/xdisp.c | 51 |
2 files changed, 64 insertions, 10 deletions
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 | ||