From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Po Lu Newsgroups: gmane.emacs.devel Subject: Re: move_it_vertically_backward question Date: Fri, 17 Dec 2021 09:45:53 +0800 Message-ID: <87r1achulq.fsf@yahoo.com> References: <87lf0pw78r.fsf.ref@yahoo.com> <87lf0pw78r.fsf@yahoo.com> <837dc8mue3.fsf@gnu.org> <874k7cuhv4.fsf@yahoo.com> <83lf0nl56t.fsf@gnu.org> <875yrrtiwj.fsf@yahoo.com> <837dc7l2pa.fsf@gnu.org> <87ilvqty24.fsf@yahoo.com> <8335muj8zk.fsf@gnu.org> <87h7bang3d.fsf@yahoo.com> <83mtl1j527.fsf@gnu.org> <87zgp1mldh.fsf@yahoo.com> <83tuf9gdg5.fsf@gnu.org> <87pmpwkikp.fsf@yahoo.com> <83mtl0hnm5.fsf@gnu.org> <87czlwkfpk.fsf@yahoo.com> <8735mskal2.fsf@yahoo.com> <83ee6che8h.fsf@gnu.org> <87y24kisgf.fsf@yahoo.com> <838rwkhcqb.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="8293"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.60 (gnu/linux) Cc: emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Fri Dec 17 02:48:12 2021 Return-path: Envelope-to: ged-emacs-devel@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 1my2Lz-0001xB-JL for ged-emacs-devel@m.gmane-mx.org; Fri, 17 Dec 2021 02:48:12 +0100 Original-Received: from localhost ([::1]:48516 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1my2Lx-0000da-Qz for ged-emacs-devel@m.gmane-mx.org; Thu, 16 Dec 2021 20:48:09 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:50348) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1my2K3-0008NQ-Gx for emacs-devel@gnu.org; Thu, 16 Dec 2021 20:46:11 -0500 Original-Received: from sonic314-21.consmr.mail.ne1.yahoo.com ([66.163.189.147]:33778) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1my2K0-0000w1-Io for emacs-devel@gnu.org; Thu, 16 Dec 2021 20:46:11 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1639705566; bh=CwWIoxWl1fCfWxWFssHYk6engrARL1G45ArZ3dbG9Vs=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From:Subject:Reply-To; b=sLkwoVKQ4OplUTy93BLkKZp5gt7fBCw572cFiahah7MQaVgT79Brjy654FBoka+LjJnr3UttxJWWlsF2h84pePY5D/hzRDXaA9qw/KT9mEczfIZSUbkxmXl0XSCAaO6qaQyeRtiUCloEueN/KLHYu7ftZPFSP+geon0Flg3YU1roI6OsQEc8+XZkqHb7SpLreH0l0MoKK0i+i/qtO3Dyigz0jkEH6gABDHyemVsdZVPYUkYKiRBTLF6MmtuCC6yv/Q9D7VbojQdrBL3J0TufKik/fvhz+v/zkY5mLpsSM412zUePHeWt54gvMjSBP7mQnYl5+14x/PFVvl/OviaXJA== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1639705566; bh=sX+oIhbmlF7XApWgEkfhj0u18xs6O8OSaPLYJBhFIGI=; h=X-Sonic-MF:From:To:Subject:Date:From:Subject; b=Tbi+ervIODZMKNvLp2GhlRQoGW4WlDvr+Gy/cyPInN5dGL+A/gL9HOihfgrRF93Q3cNoTq+AC2saS9V5Vs3uWDZNRAYLT1dDoez8DFcYHSGv/grSuhIrRtpimrXXtaPoKMpjpwtK2UwARvsemiSzpzo+UXLbuhMU+2y+ANrd8Y45pFjwzhGKX/xXsEXsDVQHqcImN4pqKWCPzwaTI2VdRtETr4oP5sD/skLX9lXGRedZCz0GCYvrMkjdm01jZqmAfc6upAATwWxvBNf8+rIeN4UmwWBAxsFENbXwgZsf+NXwBQDi7AIU/jP2VbhR5SqD2efsYUgePZOqIM3vzMAtWw== X-YMail-OSG: VIoGrccVM1lyeCWzO4Lhcb4SxKQrn.LuSL9m_6N8Dvr89w9ETPROlWxbtgcvHt6 KUyWla3YZ_8h2c0oKi2y2kuJU_vkUV5HURQTZSlmsE30i37ivqZwpnWifGtB__.9dxOWn2FpeKUi WIWBHztZv7gSQX21ghjdEWTNEM9w4z5pAo3W6pr1y85NNBVi7JQx5pVs53bNqaV84FD3Uwlk2GX8 jAFeo2yHxjcrPgUnSYJRhObuUUszxiApa7clpFrGv3J_PJ8aUfpFHrXOwAfwkQ7ajd50pEs0glT0 27UVCsVqN9_2.WVgNVzf2mDq4N3A3OW310EcdFzir6u_MNH.YkQZCXD5pxLB6AsgScF6_9WXUAXZ Wh2knc2.6tE1xQyIqJ6SMHH.HDYadPaP6sHW4SpQhbsQ7VYrToNpJvMKLF4ltUxRy165kotHsafA Rhv_2BdB1jeCluz8bG3OGxzxlr5y0Me2r3H21pH4BCdvGW51ngjsb1gC_vS2SAZ.UF2yCIG5DrKi Y45V6fxmdlLPsIpORJigafJyRGq2AoB48UzWcyxGLtcVQ.oO3z7WKZPYcZ2Kyumo1.mQY9njUFMs TDmwqUHoh9mAVnLbI1bdYLVuoIgEsMCis2a6OBsrHfYX3zDZ8m6UkTgx1C1dyLxqA8m_7yTMkcST BP2pOJ8wSUc04q8LBqYJ0XeDlu5wjMeLvB0Tiq3.UmLDcsLll36ferbWdrS94zRnxBBzeZYTw4Vz 0QizwSVM4lj9ybczIN4YUhw73eOwENtaoNUNUR2yuvkrBjX98cR45rtN96EMLKizHk4Xp1KqfxL2 NnQOyLo_ZkvaKSaBuoCjCUBpD3u4M.vx0p0nmfajT4 X-Sonic-MF: Original-Received: from sonic.gate.mail.ne1.yahoo.com by sonic314.consmr.mail.ne1.yahoo.com with HTTP; Fri, 17 Dec 2021 01:46:06 +0000 Original-Received: by kubenode501.mail-prod1.omega.sg3.yahoo.com (VZM Hermes SMTP Server) with ESMTPA ID a2d78ea50576c36cc7f6428af0cafc1b; Fri, 17 Dec 2021 01:45:58 +0000 (UTC) In-Reply-To: <838rwkhcqb.fsf@gnu.org> (Eli Zaretskii's message of "Thu, 16 Dec 2021 15:59:40 +0200") X-Mailer: WebService/1.1.19415 mail.backend.jedi.jws.acl:role.jedi.acl.token.atz.jws.hermes.yahoo Received-SPF: pass client-ip=66.163.189.147; envelope-from=luangruo@yahoo.com; helo=sonic314-21.consmr.mail.ne1.yahoo.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:282171 Archived-At: --=-=-= Content-Type: text/plain Eli Zaretskii writes: > The difference is that window-text-pixel-size already exists, we just > extend it for another use case. > Well, then this is equivalent to telling window-text-pixel-size to > stop at the visual left edge of a screen line, right? That is, > interpret TO not as a literal buffer position, but as the visual > beginning of the line which shows position TO. Yes, I think the two meanings are equivalent. I documented it as the former, but it wouldn't hurt to document it like this instead. Anyway, here are two patches that implement the extensions to `window-text-pixel-size', along with the code in pixel-scroll-precision-mode that makes use of them. I tried to update the documentation, but to be frank I'm not good at writing documentation and couldn't word it very well, so someone else should take a look at it. Thanks a lot! --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Add-new-argument-no-descents-ascents-to-window-text-.patch >From 0ebd752969a2ace5e8f897bb140b8daeb21d978e Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 16 Dec 2021 20:24:16 +0800 Subject: [PATCH 1/2] Add new argument `no-descents-ascents' to `window-text-pixel-size' * doc/lispref/display.texi (Size of Displayed Text): Update documentation. * etc/NEWS: Announce new argument. * src/xdisp.c (window_text_pixel_size): Allow controlling if the iterator's ascent and descent will be appended to the pixel height returned. All callers changed. (Fwindow_text_pixel_size): New argument `no-ascents-descents'. All callers changed. --- doc/lispref/display.texi | 6 +++++- etc/NEWS | 5 +++++ src/haikufns.c | 3 ++- src/w32fns.c | 3 ++- src/xdisp.c | 42 ++++++++++++++++++++++++++++++---------- src/xfns.c | 3 ++- 6 files changed, 48 insertions(+), 14 deletions(-) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index b82473f9c2..bf0d1c05e1 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -2086,7 +2086,7 @@ Size of Displayed Text (@pxref{Resizing Windows}) to make a window exactly as large as the text it contains. -@defun window-text-pixel-size &optional window from to x-limit y-limit mode-lines +@defun window-text-pixel-size &optional window from to x-limit y-limit mode-lines no-ascents-descents This function returns the size of the text of @var{window}'s buffer in pixels. @var{window} must be a live window and defaults to the selected one. The return value is a cons of the maximum pixel-width @@ -2136,6 +2136,10 @@ Size of Displayed Text height of all of these lines, if present, in the return value. @end defun +The optional argument @var{no-ascents-descents} controls whether or +not to count the height of text in @var{to}'s screen line as part of +the returned pixel-height. + @code{window-text-pixel-size} treats the text displayed in a window as a whole and does not care about the size of individual lines. The following function does. diff --git a/etc/NEWS b/etc/NEWS index 8d9c645694..b3e335f00a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -984,6 +984,11 @@ when they have changed. This can be used to check whether a specific font has a glyph for a character. ++++ +** 'window-text-pixel-size' now accepts a new argument `no-ascents-descents'. +This controls whether or not the screen line at the end of the +measured area will be counted during the height calculation. + ** XDG support *** New function 'xdg-state-home' returns 'XDG_STATE_HOME' environment variable. diff --git a/src/haikufns.c b/src/haikufns.c index 868fc71f97..737b033899 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -1970,7 +1970,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); /* Calculate size of tooltip window. */ size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil, - make_fixnum (w->pixel_height), Qnil); + make_fixnum (w->pixel_height), Qnil, + Qnil); /* Add the frame's internal border to calculated size. */ width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); diff --git a/src/w32fns.c b/src/w32fns.c index 65463b5261..02a6d78b51 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -7525,7 +7525,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); /* Calculate size of tooltip window. */ size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil, - make_fixnum (w->pixel_height), Qnil); + make_fixnum (w->pixel_height), Qnil, + Qnil); /* Add the frame's internal border to calculated size. */ width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); diff --git a/src/xdisp.c b/src/xdisp.c index 5e549c9c63..0772238f2d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -10833,7 +10833,7 @@ in_display_vector_p (struct it *it) 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) + Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object no_ascents_descents) { struct window *w = decode_live_window (window); struct it it; @@ -10969,8 +10969,19 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li if (IT_CHARPOS (it) == end) { x += it.pixel_width; - it.max_ascent = max (it.max_ascent, it.ascent); - it.max_descent = max (it.max_descent, it.descent); + + /* DTRT if no_ascents_descents is t. */ + if (no_ascents_descents) + { + saw_display_prop_at_end_p = true; + doff = (max (it.max_ascent, it.ascent) + + max (it.max_descent, it.descent)); + } + else + { + it.max_ascent = max (it.max_ascent, it.ascent); + it.max_descent = max (it.max_descent, it.descent); + } } } else @@ -10991,8 +11002,14 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li /* Subtract height of header-line and tab-line which was counted automatically by start_display. */ - y = it.current_y + it.max_ascent + it.max_descent - - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w); + y = (it.current_y + (NILP (no_ascents_descents) + ? it.max_ascent + it.max_descent + : 0) + - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w)); + + if (saw_display_prop_at_end_p) + y += doff; + /* Don't return more than Y-LIMIT. */ if (y > max_y) y = max_y; @@ -11039,7 +11056,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li return Fcons (make_fixnum (x - start_x), make_fixnum (y)); } -DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 6, 0, +DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 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 @@ -11086,9 +11103,12 @@ DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_siz 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. */) +include the height of any of these, if present, in the return value. + +NO-ASCENTS-DESCENTS means to not add the height of the screen line at +TO to the returned height. */) (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, - Lisp_Object y_limit, Lisp_Object mode_lines) + Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object no_ascents_descents) { struct window *w = decode_live_window (window); struct buffer *b = XBUFFER (w->contents); @@ -11101,7 +11121,8 @@ DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_siz set_buffer_internal_1 (b); } - value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines); + value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines, + no_ascents_descents); if (old_b) set_buffer_internal_1 (old_b); @@ -11151,7 +11172,8 @@ DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_siz set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE); } - value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil); + value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil, + Qnil); unbind_to (count, Qnil); diff --git a/src/xfns.c b/src/xfns.c index dc25d7bfca..30ed358fb2 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -7169,7 +7169,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); /* Calculate size of tooltip window. */ size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil, - make_fixnum (w->pixel_height), Qnil); + make_fixnum (w->pixel_height), Qnil, + Qnil); /* Add the frame's internal border to calculated size. */ width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); -- 2.33.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-Allow-window-text-pixel-size-to-measure-from-pixels-.patch >From 0910fb8e2dfb71c2dff44c6b99633ab61baa7f0e Mon Sep 17 00:00:00 2001 From: Po Lu Date: Fri, 17 Dec 2021 09:40:41 +0800 Subject: [PATCH 2/2] Allow window-text-pixel-size to measure from pixels above a position * doc/lispref/display.texi (Size of Displayed Text): Announce new meaning of `from'. * etc/NEWS: Announce changes. * lisp/pixel-scroll.el (pixel-scroll-precision-scroll-up-page): Use new feature. * src/xdisp.c (window_text_pixel_size): Understand a special format of `from' that specifies the amount of pixels above a position. (Fwindow_text_pixel_size): Update doc string. --- doc/lispref/display.texi | 20 ++++++++----- etc/NEWS | 3 ++ lisp/pixel-scroll.el | 34 +++++++++++---------- src/xdisp.c | 64 ++++++++++++++++++++++++++++++++-------- 4 files changed, 84 insertions(+), 37 deletions(-) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index bf0d1c05e1..766b2c5d64 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -2090,19 +2090,23 @@ Size of Displayed Text This function returns the size of the text of @var{window}'s buffer in pixels. @var{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 maximum pixel-height of all text lines. This -function exists to allow Lisp programs to adjust the dimensions of -@var{window} to the buffer text it needs to display. +of any text line and the maximum pixel-height of all text lines, or if +@var{from} is a cons, a list of the pixel-width, pixel-height, and the +buffer position of the first line that was measured. This function +exists to allow Lisp programs to adjust the dimensions of @var{window} +to the buffer text it needs to display. The optional argument @var{from}, if non-@code{nil}, specifies the first text position to consider, and defaults to the minimum accessible position of the buffer. If @var{from} is @code{t}, it stands for the minimum accessible position that is not a newline -character. The optional argument @var{to}, if non-@code{nil}, -specifies the last text position to consider, and defaults to the -maximum accessible position of the buffer. If @var{to} is @code{t}, -it stands for the maximum accessible position that is not a newline -character. +character. If @var{from} is a cons, the cdr specifies a position, and +the car specifies the minimum amount of pixels above that position to +start measuring from. The optional argument @var{to}, if +non-@code{nil}, specifies the last text position to consider, and +defaults to the maximum accessible position of the buffer. If +@var{to} is @code{t}, it stands for the maximum accessible position +that is not a newline character. The optional argument @var{x-limit}, if non-@code{nil}, specifies the maximum X coordinate beyond which text should be ignored; it is diff --git a/etc/NEWS b/etc/NEWS index b3e335f00a..47145adbc0 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -989,6 +989,9 @@ character. This controls whether or not the screen line at the end of the measured area will be counted during the height calculation. ++++ +** 'window-text-pixel-size' can now measure from a set amount of pixels above a position. + ** XDG support *** New function 'xdg-state-home' returns 'XDG_STATE_HOME' environment variable. diff --git a/lisp/pixel-scroll.el b/lisp/pixel-scroll.el index fa0185b16e..efcabae108 100644 --- a/lisp/pixel-scroll.el +++ b/lisp/pixel-scroll.el @@ -516,22 +516,24 @@ pixel-scroll-precision-scroll-up-page usable-height)))) (goto-char up-point))) (let ((current-vscroll (window-vscroll nil t))) - (if (<= delta current-vscroll) - (set-window-vscroll nil (- current-vscroll delta) t) - (setq delta (- delta current-vscroll)) - (set-window-vscroll nil 0 t) - (while (> delta 0) - (let ((position (pixel-point-and-height-at-unseen-line))) - (unless (cdr position) - (signal 'beginning-of-buffer nil)) - (set-window-start nil (car position) t) - ;; If the line above is taller than the window height (i.e. there's - ;; a very tall image), keep point on it. - (when (> (cdr position) usable-height) - (goto-char (car position))) - (setq delta (- delta (cdr position))))) - (when (< delta 0) - (set-window-vscroll nil (- delta) t)))))) + (setq delta (- delta current-vscroll)) + (set-window-vscroll nil 0 t) + (when (> delta 0) + (let* ((start (window-start)) + (dims (window-text-pixel-size nil (cons start delta) + start nil nil nil t)) + (height (nth 1 dims)) + (position (nth 2 dims))) + (set-window-start nil position t) + ;; If the line above is taller than the window height (i.e. there's + ;; a very tall image), keep point on it. + (when (> height usable-height) + (goto-char position)) + (when (or (not position) (eq position start)) + (signal 'beginning-of-buffer nil)) + (setq delta (- delta height)))) + (when (< delta 0) + (set-window-vscroll nil (- delta) t))))) (defun pixel-scroll-precision-interpolate (delta) "Interpolate a scroll of DELTA pixels. diff --git a/src/xdisp.c b/src/xdisp.c index 0772238f2d..e84f99499b 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -10840,7 +10840,8 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li ptrdiff_t start, end, bpos; struct text_pos startp; void *itdata = NULL; - int c, max_x = 0, max_y = 0, x = 0, y = 0; + int c, max_x = 0, max_y = 0, x = 0, y = 0, movement = 0, doff; + bool saw_display_prop_at_end_p = false; if (NILP (from)) { @@ -10866,6 +10867,13 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li break; } } + else if (CONSP (from)) + { + start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV); + bpos = CHAR_TO_BYTE (start); + CHECK_FIXNAT (XCDR (from)); + movement = XFIXNAT (XCDR (from)); + } else { start = clip_to_bounds (BEGV, fix_position (from), ZV); @@ -10912,6 +10920,27 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li itdata = bidi_shelve_cache (); start_display (&it, w, startp); + + if (movement > 0) + { + int last_y; + it.current_y = 0; + + move_it_by_lines (&it, 0); + + while (-it.current_y < movement) + { + last_y = it.current_y; + move_it_vertically_backward (&it, movement + it.current_y); + + if (it.current_y == last_y) + break; + } + + it.current_y = 0; + start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV); + } + int start_y = it.current_y; /* It makes no sense to measure dimensions of region of text that crosses the point where bidi reordering changes scan direction. @@ -11005,7 +11034,10 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li y = (it.current_y + (NILP (no_ascents_descents) ? it.max_ascent + it.max_descent : 0) - - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w)); + - (movement < 0 + ? (WINDOW_TAB_LINE_HEIGHT (w) + - WINDOW_HEADER_LINE_HEIGHT (w)) + : 0)); if (saw_display_prop_at_end_p) y += doff; @@ -11053,26 +11085,32 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li bidi_unshelve_cache (itdata, false); - return Fcons (make_fixnum (x - start_x), make_fixnum (y)); + return (!movement + ? Fcons (make_fixnum (x - start_x), make_fixnum (y)) + : list3i (x - start_x, y, start)); } DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 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. + 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 or a list of the maximum pixel-width, +pixel-height, and the buffer position of the line at FROM. 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. +of the buffer. If FROM is a cons, the cdr specifies the amount of +pixels above the buffer position to begin measuring text, and the car +specifies the buffer position. In that case, a list is returned. 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 -- 2.33.1 --=-=-=--