unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Po Lu <luangruo@yahoo.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: emacs-devel@gnu.org
Subject: Re: move_it_vertically_backward question
Date: Thu, 23 Dec 2021 09:30:34 +0800	[thread overview]
Message-ID: <87h7b0m7k5.fsf@yahoo.com> (raw)
In-Reply-To: <87wnjxv4ye.fsf@yahoo.com> (Po Lu's message of "Wed, 22 Dec 2021 08:49:45 +0800")

[-- Attachment #1: Type: text/plain, Size: 407 bytes --]

Po Lu <luangruo@yahoo.com> writes:

> Also, here's a patch with some of the changes made.  I tried with the
> documentation as well, but I'm pretty bad with that stuff.

I tried updating the documentation again to better fit what's actually
done (including documenting that measurements always begin at the
beginning of the visual line).

Please take a look and see if it's OK to install this now, thanks.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Allow-window-text-pixel-size-to-measure-pixels-aroun.patch --]
[-- Type: text/x-patch, Size: 10642 bytes --]

From 2e01b17fb6ccc3bf8b6552bfb5b59811d4b04422 Mon Sep 17 00:00:00 2001
From: Po Lu <luangruo@yahoo.com>
Date: Thu, 23 Dec 2021 09:12:02 +0800
Subject: [PATCH] Allow window-text-pixel-size to measure pixels around 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              | 85 +++++++++++++++++++++++++++++++---------
 4 files changed, 99 insertions(+), 43 deletions(-)

diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 98a15404f9..7e6ee59824 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 or below the
+beginning of the visual line at 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 86f18078f6..08e19a0eb2 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1020,6 +1020,9 @@ This controls whether or not the last screen line of the text being
 measured will be counted for the purpose of calculating the text
 dimensions.
 
++++
+** '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..4aae166f2e 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 1f896c256e..d20fdc4016 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -10841,8 +10841,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
   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 doff = 0;
+  int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
 
   if (NILP (from))
     {
@@ -10868,6 +10867,13 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
 	    break;
 	}
     }
+  else if (CONSP (from))
+    {
+      start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
+      bpos = CHAR_TO_BYTE (start);
+      CHECK_FIXNUM (XCDR (from));
+      vertical_offset = XFIXNUM (XCDR (from));
+    }
   else
     {
       start = clip_to_bounds (BEGV, fix_position (from), ZV);
@@ -10914,7 +10920,9 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
 
   itdata = bidi_shelve_cache ();
   start_display (&it, w, startp);
+
   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.
      By using unidirectional movement here we at least support the use
@@ -10923,13 +10931,46 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
      same directionality.  */
   it.bidi_p = false;
 
-  /* Start at the beginning of the line containing FROM.  Otherwise
-     IT.current_x will be incorrectly set to zero at some arbitrary
-     non-zero X coordinate.  */
-  reseat_at_previous_visible_line_start (&it);
-  it.current_x = it.hpos = 0;
-  if (IT_CHARPOS (it) != start)
-    move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
+  if (vertical_offset != 0)
+    {
+      int last_y;
+      it.current_y = 0;
+
+      move_it_by_lines (&it, 0);
+
+      if (vertical_offset < 0)
+	{
+	  while (it.current_y > vertical_offset)
+	    {
+	      last_y = it.current_y;
+	      move_it_vertically_backward (&it,
+					   (abs (vertical_offset)
+					    + it.current_y));
+
+	      if (it.current_y == last_y)
+		break;
+	    }
+	}
+      else
+	{
+	  move_it_vertically (&it, vertical_offset);
+	}
+
+      it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
+		      + WINDOW_HEADER_LINE_HEIGHT (w));
+      start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
+      start_y = it.current_y;
+    }
+  else
+    {
+      /* Start at the beginning of the line containing FROM.  Otherwise
+	 IT.current_x will be incorrectly set to zero at some arbitrary
+	 non-zero X coordinate.  */
+      reseat_at_previous_visible_line_start (&it);
+      it.current_x = it.hpos = 0;
+      if (IT_CHARPOS (it) != start)
+	move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
+    }
 
   /* Now move to TO.  */
   int start_x = it.current_x;
@@ -11052,25 +11093,31 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
 
   bidi_unshelve_cache (itdata, false);
 
-  return Fcons (make_fixnum (x - start_x), make_fixnum (y));
+  return (!vertical_offset
+	  ? 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
+of the buffer.  If FROM is a cons, the cdr specifies the amount of
+pixels above or below a 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
-- 
2.33.1


  parent reply	other threads:[~2021-12-23  1:30 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <87lf0pw78r.fsf.ref@yahoo.com>
2021-12-13  2:47 ` move_it_vertically_backward question Po Lu
2021-12-13 14:50   ` Eli Zaretskii
2021-12-14  0:53     ` Po Lu
2021-12-14 12:52       ` Eli Zaretskii
2021-12-14 13:28         ` Po Lu
2021-12-14 13:45           ` Eli Zaretskii
2021-12-15  1:18             ` Po Lu
2021-12-15  3:27               ` Eli Zaretskii
2021-12-15  3:30                 ` Po Lu
2021-12-15 13:27                   ` Eli Zaretskii
2021-12-15 13:39                     ` Po Lu
2021-12-15  2:13             ` Po Lu
2021-12-15 10:28               ` Po Lu
2021-12-15 13:56                 ` Eli Zaretskii
2021-12-15 13:25               ` Eli Zaretskii
2021-12-15 13:38                 ` Po Lu
2021-12-15 14:50                   ` Eli Zaretskii
2021-12-16  0:41                     ` Po Lu
2021-12-16  8:29                       ` Eli Zaretskii
2021-12-16  9:25                         ` Po Lu
2021-12-16 10:04                           ` Eli Zaretskii
2021-12-16 10:27                             ` Po Lu
2021-12-16 12:17                               ` Po Lu
2021-12-16 13:27                                 ` Eli Zaretskii
2021-12-16 13:34                                   ` Po Lu
2021-12-16 13:59                                     ` Eli Zaretskii
2021-12-17  1:45                                       ` Po Lu
2021-12-18 10:28                                         ` Eli Zaretskii
2021-12-18 10:49                                           ` Po Lu
2021-12-18 11:03                                             ` Eli Zaretskii
2021-12-18 11:18                                               ` Po Lu
2021-12-18 11:29                                                 ` Eli Zaretskii
2021-12-18 11:31                                                   ` Po Lu
2021-12-18 11:35                                                     ` Eli Zaretskii
2021-12-18 11:39                                                       ` Po Lu
2021-12-19  0:54                                           ` Po Lu
2021-12-19  8:29                                             ` Eli Zaretskii
2021-12-19  9:16                                               ` Po Lu
2021-12-19  9:27                                                 ` Eli Zaretskii
2021-12-19 10:25                                                   ` Po Lu
2021-12-19 18:07                                                     ` Eli Zaretskii
2021-12-20  1:05                                                       ` Po Lu
2021-12-21 12:58                                                         ` Po Lu
2021-12-21 17:07                                                           ` Eli Zaretskii
2021-12-22  0:49                                                             ` Po Lu
2021-12-22 14:59                                                               ` Eli Zaretskii
2021-12-23  1:30                                                               ` Po Lu [this message]
2021-12-23  9:49                                                                 ` Eli Zaretskii
2021-12-23 10:29                                                                   ` Po Lu
2021-12-23 10:39                                                                     ` Eli Zaretskii
2021-12-23 10:42                                                                       ` Po Lu
2021-12-23 10:50                                                                         ` Eli Zaretskii
2021-12-23 10:55                                                                           ` Po Lu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87h7b0m7k5.fsf@yahoo.com \
    --to=luangruo@yahoo.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).