From b76852a07f9f2a6ef4b98fd90807e357a9ebb81c Mon Sep 17 00:00:00 2001 From: Sebastien Chapuis Date: Thu, 7 Nov 2019 06:36:04 +0800 Subject: [PATCH] Add function window-line-width * src/window.c: Define the function. * etc/NEWS: Mention `window-line-width'. --- etc/NEWS | 4 ++ src/window.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/etc/NEWS b/etc/NEWS index bfcb7cf325..2f15185efe 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -221,6 +221,10 @@ To get the old, less-secure behavior, you can set the *** When run by root, emacsclient no longer connects to non-root sockets. (Instead you can use Tramp methods to run root commands in a non-root Emacs.) +--- +** New function 'window-line-width'. +Return width in pixels of a text line. + ** New function 'network-lookup-address-info'. This does IPv4 and/or IPv6 address lookups on hostnames. diff --git a/src/window.c b/src/window.c index 0fa0bdf7b9..4bfdfc05de 100644 --- a/src/window.c +++ b/src/window.c @@ -1929,6 +1929,115 @@ DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, return in_window; } +DEFUN ("window-line-width", Fwindow_line_width, + Swindow_line_width, 0, 3, 0, + doc: /* Return width in pixels of a text line LINE in WINDOW, in AREA. + +Return width of current line if LINE is omitted or nil. +LINE can also be `tab-line', `header-line' and `mode-line'. +Otherwise, LINE is a row number (zero-based). + +WINDOW must be a live window and defaults to the selected one. + +AREA can take one of those values: +- `left-margin': Width of the left margin area +- `right-margin': Width of the right margin area +- `text-area': Width of the text area, until the new line (excluded) +- `text-area-full': Similar to `text-area' but include glyphs after the + new line, if any. +If omitted, AREA defaults to `text-area'. + +Return nil if the window display is not up-to-date. */) + (Lisp_Object line, Lisp_Object window, Lisp_Object area) +{ + struct window *w = decode_live_window (window); + struct buffer *buffer UNINIT; + int vpos UNINIT; + + if (noninteractive || w->pseudo_window_p) + return Qnil; + + CHECK_BUFFER (w->contents); + buffer = XBUFFER (w->contents); + + /* Fail if current matrix is not up-to-date. */ + if (!w->window_end_valid + || windows_or_buffers_changed + || buffer->clip_changed + || buffer->prevent_redisplay_optimizations_p + || window_outdated (w)) + return Qnil; + + struct glyph_matrix *matrix = w->current_matrix; + + if (NILP (line)) + vpos = w->cursor.vpos; + else if (EQ (line, Qtab_line)) + { + if (!window_wants_tab_line (w) || !matrix->tab_line_p) + return Qnil; + vpos = 0; + } + else if (EQ (line, Qheader_line)) + { + if (!window_wants_header_line (w) || !matrix->header_line_p) + return Qnil; + vpos = matrix->tab_line_p ? 1 : 0; + } + else if (EQ (line, Qmode_line)) + { + if (!window_wants_mode_line (w)) + return Qnil; + vpos = matrix->nrows - 1; + } + else + { + CHECK_FIXNUM (line); + vpos = XFIXNUM (line) + + window_wants_tab_line (w) + + window_wants_header_line (w); + } + + if (vpos < 0 || vpos >= matrix->nrows) + error ("Invalid line"); + + enum glyph_row_area actual_area UNINIT; + bool full_text = false; + + if (EQ (area, Qleft_margin)) + actual_area = LEFT_MARGIN_AREA; + else if (EQ (area, Qright_margin)) + actual_area = RIGHT_MARGIN_AREA; + else + { + if (EQ (area, Qtext_area_full)) + full_text = true; + actual_area = TEXT_AREA; + } + + struct glyph_row *row = MATRIX_ROW (matrix, vpos); + + struct glyph *glyph = row->glyphs[actual_area]; + int used = row->used[actual_area]; + int width = 0; + + for (int i = 0; i < used; ++i) + { + if (actual_area == TEXT_AREA && full_text == false + && NILP (glyph[i].object) && glyph[i].charpos >= 0) + /* + We reached the end of the line in TEXT_AREA. + display-line-numbers-mode inserts glyphs with NILP(glyph.object) + and glyph.charpos == -1, so we can't check only for + NILP (glyph.object) + */ + break; + width += glyph[i].pixel_width; + } + + return make_fixnum (width); +} + DEFUN ("window-line-height", Fwindow_line_height, Swindow_line_height, 0, 2, 0, doc: /* Return height in pixels of text line LINE in window WINDOW. @@ -8179,6 +8288,8 @@ syms_of_window (void) DEFSYM (Qmode_line_format, "mode-line-format"); DEFSYM (Qheader_line_format, "header-line-format"); DEFSYM (Qtab_line_format, "tab-line-format"); + DEFSYM (Qtext_area, "text-area"); + DEFSYM (Qtext_area_full, "text-area-full"); DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function, doc: /* Non-nil means call as function to display a help buffer. @@ -8443,6 +8554,7 @@ syms_of_window (void) defsubr (&Sset_frame_selected_window); defsubr (&Spos_visible_in_window_p); defsubr (&Swindow_line_height); + defsubr (&Swindow_line_width); defsubr (&Swindow_buffer); defsubr (&Swindow_old_buffer); defsubr (&Swindow_parent); -- 2.21.0