From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: martin rudalics Newsgroups: gmane.emacs.bugs Subject: bug#51995: 29.0.50; `string-pixel-width' depends on the current window width Date: Sun, 21 Nov 2021 10:12:40 +0100 Message-ID: <1e235f66-126f-96b6-2193-ce4642badb80@gmx.at> References: <84h7c67bdi.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------D4640899B678C361160E0F37" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="27513"; mail-complaints-to="usenet@ciao.gmane.io" Cc: 51995@debbugs.gnu.org To: Brahimi Saifullah Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sun Nov 21 10:13:12 2021 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1moiuN-0006xh-M8 for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 21 Nov 2021 10:13:11 +0100 Original-Received: from localhost ([::1]:33462 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1moiuM-0002qf-I4 for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 21 Nov 2021 04:13:10 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:45866) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1moiuE-0002qP-L1 for bug-gnu-emacs@gnu.org; Sun, 21 Nov 2021 04:13:02 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:60937) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1moiuE-0001pC-Cy for bug-gnu-emacs@gnu.org; Sun, 21 Nov 2021 04:13:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1moiuE-0000kS-3U for bug-gnu-emacs@gnu.org; Sun, 21 Nov 2021 04:13:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: martin rudalics Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 21 Nov 2021 09:13:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 51995 X-GNU-PR-Package: emacs Original-Received: via spool by 51995-submit@debbugs.gnu.org id=B51995.16374859732860 (code B ref 51995); Sun, 21 Nov 2021 09:13:02 +0000 Original-Received: (at 51995) by debbugs.gnu.org; 21 Nov 2021 09:12:53 +0000 Original-Received: from localhost ([127.0.0.1]:44250 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1moiu4-0000k3-Fs for submit@debbugs.gnu.org; Sun, 21 Nov 2021 04:12:53 -0500 Original-Received: from mout.gmx.net ([212.227.17.20]:53803) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1moiu0-0000jZ-1M for 51995@debbugs.gnu.org; Sun, 21 Nov 2021 04:12:48 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1637485962; bh=++p7UR97rUd+2cK/DP5yI+dbOYBLIEX8GnT0g88PmIs=; h=X-UI-Sender-Class:Subject:To:Cc:References:From:Date:In-Reply-To; b=Lp8H/1jwGW+6RcUp2USKYZnKT+r7hGIgKvs33jmDsEPjEdSfgymCpdG3dfUac2MQm bSZg4056UJbAyiFcZYSn23PSv4TmYrexcs1o52QiMIR0SHiiKwIimOkXR0Aghvrajj CrBQiIEpnXSc2JkR+o6gMipkxDjl190KxRu3ub28= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Original-Received: from [192.168.1.101] ([213.142.96.19]) by mail.gmx.net (mrgmx105 [212.227.17.168]) with ESMTPSA (Nemesis) id 1N8XPt-1mc3Vw30Ov-014T3Q; Sun, 21 Nov 2021 10:12:41 +0100 In-Reply-To: <84h7c67bdi.fsf@gmail.com> Content-Language: en-US X-Provags-ID: V03:K1:5Z+GPAgg/72H/aszm9ztEyXptFDvMQ9EFaBcVijFcT9yTAMhbGy 50hzN8O7eYyM4BNnFSJ7cz/bnNS24gl5Krpv2EdXnIhUWUjzuI7lU9IVllDDHb67hFyDtbl 6AbSPymR01Yphk4S9KYjma/tzS/JP/116Ax8Lu3yVl3u4Wl6t3jYTYFb/O5np7enG9meuni GaIM+Vj1d1DxCyLWsd15A== X-UI-Out-Filterresults: notjunk:1;V03:K0:onNvHfAFEPw=:tT9VneR1v0otvItkzdUhtM TemHtQ8hWzGjNGnaV+2TfEIzXwUsClwLAXSqi5JArhEuKtZVlSE9VQDydS4HcgFrmhkXAa6s2 hm5UCLL3BVOP8CtjdpZ0F0OQjTp1ZKGTtgwfLlV7F6xFloK4QjQZJJT3KQ35s8jxQ1qupW8Ir ry9MnxNoDrcRoEp30aZbQdTtjCKXNOKKyPuo9n3HY1tiU4KiuHrOUcj4CAMbcwSZPh3UBe09f 4o3vJ0s2YNQ4jtG6MqtWahd9vMye+1wPDjVwqvZYguT6TD/a7CMBytzhebjXkxlThIWZnE1/x QY2sq5uNYZgc/VuPr0CaVCJ0oZQl7RTqmUEjDiHwFLkPQy6gFUGpA9piEjLzQAEImfBGE76FI piazyVrd/a5T8dbImKCA9JgLUBxVv336svWj3h6LYV90fes0LsH5knvUEB8X94hK0lEOJWhl4 0s74Hg6f5kZtlr3eOSr4c7Wm+fZrSVfvifuDuvuzymU5QJIyU0rOEBqfmmVVWK2Swa3qnufrA LnEX/6roO2rA0vD7HiqaWGF6cJb/cIDSjCghS6TW+8Cp5DjJ06z8oXw40dhdSt2do3qLoiheh 0ndheI69apeJnO8QfFvStjVfgGpy6yZNR0p+5CtENH/wXbk3hyAlJd099A3Qd3RpyKP/EHqcn Ko0Ubo/d+SGgMMEIgCaG57mCTuzdh0fQUs6fZ6qBjhx7kGaH5NfkvfutTQ1k0glCMyHwEi1KI J0x5sBMudJ4Jbpy4BPNIXv99g9H+8ZiIBjL0ZOBclpr0c39e2Wa4W5ZENPnzDWymshI0wcfc X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:220547 Archived-At: This is a multi-part message in MIME format. --------------D4640899B678C361160E0F37 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit > I saw the warnings, but I'm unsure of their validity. > Here are some benchmarks that I did. Each form was run on a fresh emacs -Q. > Apologies in advance if there is something wrong about them: [...] > (benchmark-run 100000 > (with-temp-buffer > (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore") > (car (window-text-pixel-size > (current-buffer) (point-min) (point) 1000000)))) > ;; (8.006855 167 2.318854) > > It's a lot more efficient to use a buffer, but the difference > between the limits themselves continue to be insignificant. These examples are harmless. Please try to test (1) with a large buffer that has no newline characters and (2) with 'truncate-lines' non-nil. 'window-text-pixel-size' must be able to handle these cases gracefully even if it's not geared to them. Any clients of 'window-text-pixel-size' like 'string-pixel-width' can easily set X-LIMIT to some sufficiently large value without affecting the basic functionality of 'window-text-pixel-size'. >> I hopefully fixed most of the issues here but cannot send you a patch at >> the moment to test because my local copy is completely out of synch with >> master. So please bear with me. Please try the attached patch (if it doesn't apply, I'll send you the affected functions separately so you can apply the changes manually). Thanks, martin --------------D4640899B678C361160E0F37 Content-Type: text/x-patch; name="buffer-text-pixel-size.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="buffer-text-pixel-size.diff" diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 00668d4743..a9d0d1b11f 100644 =2D-- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -446,8 +446,7 @@ string-pixel-width "Return the width of STRING in pixels." (with-temp-buffer (insert string) - (car (window-text-pixel-size - (current-buffer) (point-min) (point))))) + (car (buffer-text-pixel-size nil nil (buffer-size))))) (provide 'subr-x) diff --git a/src/xdisp.c b/src/xdisp.c index aa01db210b..0f3b407a30 100644 =2D-- a/src/xdisp.c +++ b/src/xdisp.c @@ -10626,77 +10626,21 @@ in_display_vector_p (struct it *it) && it->dpvec + it->current.dpvec_index !=3D it->dpend); } -DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pi= xel_size, 0, 6, 0, - doc: /* Return the size of the text of WINDOW's buffer in pixels. -WINDOW can be any live window and defaults to the selected one. The -return value is a cons of the maximum pixel-width of any text line -and the pixel-height of all the text lines in the accessible portion -of buffer text. -WINDOW can also be a buffer, in which case the selected window is used, -and the function behaves as if that window was displaying this buffer. - -This function exists to allow Lisp programs to adjust the dimensions -of WINDOW to the buffer text it needs to display. - -The optional argument FROM, if non-nil, specifies the first text -position to consider, and defaults to the minimum accessible position -of the buffer. If FROM is t, it stands for the minimum accessible -position that starts a non-empty line. TO, if non-nil, specifies the -last text position and defaults to the maximum accessible position of -the buffer. If TO is t, it stands for the maximum accessible position -that ends a non-empty line. - -The optional argument X-LIMIT, if non-nil, specifies the maximum X -coordinate beyond which the text should be ignored. It is therefore -also the maximum width that the function can return. X-LIMIT nil or -omitted means to use the pixel-width of WINDOW's body. This default -means text of truncated lines wider than the window will be ignored; -specify a large value for X-LIMIT if lines are truncated and you need -to account for the truncated text. Use nil for X-LIMIT if you want to -know how high WINDOW should become in order to fit all of its buffer's -text with the width of WINDOW unaltered. Use the maximum width WINDOW -may assume if you intend to change WINDOW's width. Since calculating -the width of long lines can take some time, it's always a good idea to -make this argument as small as possible; in particular, if the buffer -contains long lines that shall be truncated anyway. - -The optional argument Y-LIMIT, if non-nil, specifies the maximum Y -coordinate beyond which the text is to be ignored; it is therefore -also the maximum height that the function can return (excluding the -height of the mode- or header-line, if any). Y-LIMIT nil or omitted -means consider all of the accessible portion of buffer text up to the -position specified by TO. Since calculating the text height of a -large buffer can take some time, it makes sense to specify this -argument if the size of the buffer is large or unknown. - -Optional argument MODE-LINES nil or omitted means do not include the -height of the mode-, tab- or header-line of WINDOW in the return value. -If it is the symbol `mode-line', 'tab-line' or `header-line', include -only the height of that line, if present, in the return value. If t, -include the height of any of these, if present, in the return value. */) - (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_li= mit, - Lisp_Object y_limit, Lisp_Object mode_lines) +/* This is like Fwindow_text_pixel_size but assumes that WINDOW's buffer + is the current buffer. Fbuffer_text_pixel_size calls it after it has + set WINDOW's buffer to the buffer specified by its BUFFER_OR_NAME + argument. */ +static Lisp_Object +window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object= to, Lisp_Object x_limit, + Lisp_Object y_limit, Lisp_Object mode_lines) { - struct window *w =3D BUFFERP (window) ? XWINDOW (selected_window) - : decode_live_window (window); - Lisp_Object buffer =3D BUFFERP (window) ? window : w->contents; - struct buffer *b; + struct window *w =3D decode_live_window (window); struct it it; - struct buffer *old_b =3D NULL; ptrdiff_t start, end, bpos; struct text_pos startp; void *itdata =3D NULL; int c, max_x =3D 0, max_y =3D 0, x =3D 0, y =3D 0; - CHECK_BUFFER (buffer); - b =3D XBUFFER (buffer); - - if (b !=3D current_buffer) - { - old_b =3D current_buffer; - set_buffer_internal (b); - } - if (NILP (from)) { start =3D BEGV; @@ -10889,12 +10833,126 @@ DEFUN ("window-text-pixel-size", Fwindow_text_p= ixel_size, Swindow_text_pixel_siz bidi_unshelve_cache (itdata, false); + return Fcons (make_fixnum (x - start_x), make_fixnum (y)); +} + +DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pi= xel_size, 0, 6, 0, + doc: /* Return the size of the text of WINDOW's buffer in pixels. +WINDOW must be a live window and defaults to the selected one. The +return value is a cons of the maximum pixel-width of any text line +and the pixel-height of all the text lines in the accessible portion +of buffer text. + +This function exists to allow Lisp programs to adjust the dimensions +of WINDOW to the buffer text it needs to display. + +The optional argument FROM, if non-nil, specifies the first text +position to consider, and defaults to the minimum accessible position +of the buffer. If FROM is t, it stands for the minimum accessible +position that starts a non-empty line. TO, if non-nil, specifies the +last text position and defaults to the maximum accessible position of +the buffer. If TO is t, it stands for the maximum accessible position +that ends a non-empty line. + +The optional argument X-LIMIT, if non-nil, specifies the maximum X +coordinate beyond which the text should be ignored. It is therefore +also the maximum width that the function can return. X-LIMIT nil or +omitted means to use the pixel-width of WINDOW's body. This default +means text of truncated lines wider than the window will be ignored; +specify a large value for X-LIMIT if lines are truncated and you need +to account for the truncated text. Use nil for X-LIMIT if you want to +know how high WINDOW should become in order to fit all of its buffer's +text with the width of WINDOW unaltered. Use the maximum width WINDOW +may assume if you intend to change WINDOW's width. Since calculating +the width of long lines can take some time, it's always a good idea to +make this argument as small as possible; in particular, if the buffer +contains long lines that shall be truncated anyway. + +The optional argument Y-LIMIT, if non-nil, specifies the maximum Y +coordinate beyond which the text is to be ignored; it is therefore +also the maximum height that the function can return (excluding the +height of the mode- or header-line, if any). Y-LIMIT nil or omitted +means consider all of the accessible portion of buffer text up to the +position specified by TO. Since calculating the text height of a +large buffer can take some time, it makes sense to specify this +argument if the size of the buffer is large or unknown. + +Optional argument MODE-LINES nil or omitted means do not include the +height of the mode-, tab- or header-line of WINDOW in the return value. +If it is the symbol `mode-line', 'tab-line' or `header-line', include +only the height of that line, if present, in the return value. If t, +include the height of any of these, if present, in the return value. */) + (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_li= mit, + Lisp_Object y_limit, Lisp_Object mode_lines) +{ + struct window *w =3D decode_live_window (window); + struct buffer *b =3D XBUFFER (w->contents); + struct buffer *old_b =3D NULL; + Lisp_Object value; + + if (b !=3D current_buffer) + { + old_b =3D current_buffer; + set_buffer_internal_1 (b); + } + + value =3D window_text_pixel_size (window, from, to, x_limit, y_limit, m= ode_lines); + if (old_b) - set_buffer_internal (old_b); + set_buffer_internal_1 (old_b); + + return value; +} + +DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pi= xel_size, 0, 4, 0, + doc: /* Return size of whole text of BUFFER_OR_NAME in WINDOW. +BUFFER-OR-NAME must specify a live buffer or the name of a live buffer +and defaults to the current buffer. WINDOW must be a live window and +defaults to the selected one. The return value is a cons of the maximum +pixel-width of any text line and the pixel-height of all the text lines +of the buffer specified by BUFFER-OR-NAME. + +The optional arguments X-LIMIT and Y-LIMIT have the same meaning as with +`window-text-pixel-size'. + +Do not use this function if the buffer specified by BUFFER_OR_NAME is +already displayed in WINDOW. `window-text-pixel-size' is cheaper in +that case because it does not have to temporarily show that buffer in +WINDOW. */) + (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit, + Lisp_Object y_limit) +{ + struct window *w =3D decode_live_window (window); + struct buffer *b =3D (NILP (buffer_or_name) + ? current_buffer + : XBUFFER (Fget_buffer (buffer_or_name))); + Lisp_Object buffer, value; + ptrdiff_t count =3D SPECPDL_INDEX (); - return Fcons (make_fixnum (x - start_x), make_fixnum (y)); + XSETBUFFER (buffer, b); + + /* The unwind form of with_echo_area_buffer is what we need here to + make WINDOW temporarily show our buffer. */ + record_unwind_protect (unwind_with_echo_area_buffer, + with_echo_area_buffer_unwind_data (w)); + + set_buffer_internal_1 (b); + + if (!EQ (buffer, w->contents)) + { + wset_buffer (w, buffer); + set_marker_both (w->pointm, buffer, BEG, BEG_BYTE); + set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE); + } + + value =3D window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit,= Qnil); + + unbind_to (count, Qnil); + + return value; } + DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p, Sdisplay__line_is_continued_p, 0, 0, 0, doc: /* Return non-nil if the current screen line is continued on = display. */) @@ -35023,6 +35081,7 @@ syms_of_xdisp (void) defsubr (&Sinvisible_p); defsubr (&Scurrent_bidi_paragraph_direction); defsubr (&Swindow_text_pixel_size); + defsubr (&Sbuffer_text_pixel_size); defsubr (&Smove_point_visually); defsubr (&Sbidi_find_overridden_directionality); defsubr (&Sdisplay__line_is_continued_p); --------------D4640899B678C361160E0F37--