emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master d54d8a8: Allow window-text-pixel-size to measure pixels around a


From: Po Lu
Subject: master d54d8a8: Allow window-text-pixel-size to measure pixels around a position
Date: Thu, 23 Dec 2021 05:56:06 -0500 (EST)

branch: master
commit d54d8a88e9a2f12b69e820e9bb89e304521bc8c7
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    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 or
    below a position.
    
    (Fwindow_text_pixel_size): Update doc string.
---
 doc/lispref/display.texi | 22 ++++++++----
 etc/NEWS                 |  5 +++
 lisp/pixel-scroll.el     | 34 +++++++++---------
 src/xdisp.c              | 89 ++++++++++++++++++++++++++++++++++++++----------
 4 files changed, 110 insertions(+), 40 deletions(-)

diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 98a1540..449a58a 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -2092,17 +2092,27 @@ 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.
+@var{window} to the buffer text it needs to display, and for other
+similar situations.
+
+The return value can also optionally (see below) include the buffer
+position of the first line whose dimensions were measured.
 
 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, its @code{car} specifies a buffer
+position, and its @code{cdr} specifies the vertical offset in pixels
+from that position to the first screen line whose text is to be
+measured.  (The measurement will start from the visual beginning of
+that screen line.)  In that case, the return value will instead be a
+list of the pixel-width, pixel-height, and the buffer position of the
+first line that was measured.  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 fb5ed74..39fbd8f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1011,6 +1011,11 @@ 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' understands a new meaning of 'from'.
+Specifying a cons as the from argument allows to start measuring text
+from a specified amount of pixels above or below 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 fa0185b..4aae166 100644
--- a/lisp/pixel-scroll.el
+++ b/lisp/pixel-scroll.el
@@ -516,22 +516,24 @@ the height of the current window."
                        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 1f896c2..a6c122a 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,50 @@ 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);
+
+      /* `move_it_vertically_backward' is called by move_it_vertically
+         to move by a negative value (upwards), but it is not always
+         guaranteed to leave the iterator at or above the position
+         given by the offset, which this loop ensures.  */
+      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,26 +11097,34 @@ 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.
+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.
+
+If FROM is a cons cell, the return value includes, in addition to the
+dimensions, also a third element that provides the buffer position
+from which measuring of the text dimensions was actually started.
 
 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, its car specifies a buffer
+position, and its cdr specifies the vertical offset in pixels from
+that position to the first screen line to be measured.  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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]