diff options
| author | Po Lu | 2021-12-23 09:12:02 +0800 |
|---|---|---|
| committer | Po Lu | 2021-12-23 18:55:54 +0800 |
| commit | d54d8a88e9a2f12b69e820e9bb89e304521bc8c7 (patch) | |
| tree | 6f94010f49db10a3a213f356f9463cfb934ad1e5 | |
| parent | 2001ae5898a1e48cae5b138828190ac2cba39b40 (diff) | |
| download | emacs-d54d8a88e9a2f12b69e820e9bb89e304521bc8c7.tar.gz emacs-d54d8a88e9a2f12b69e820e9bb89e304521bc8c7.zip | |
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.
| -rw-r--r-- | doc/lispref/display.texi | 22 | ||||
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/pixel-scroll.el | 34 | ||||
| -rw-r--r-- | src/xdisp.c | 89 |
4 files changed, 110 insertions, 40 deletions
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 98a15404f91..449a58a3bb9 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 | |||
| 2092 | selected one. The return value is a cons of the maximum pixel-width | 2092 | selected one. The return value is a cons of the maximum pixel-width |
| 2093 | of any text line and the maximum pixel-height of all text lines. This | 2093 | of any text line and the maximum pixel-height of all text lines. This |
| 2094 | function exists to allow Lisp programs to adjust the dimensions of | 2094 | function exists to allow Lisp programs to adjust the dimensions of |
| 2095 | @var{window} to the buffer text it needs to display. | 2095 | @var{window} to the buffer text it needs to display, and for other |
| 2096 | similar situations. | ||
| 2097 | |||
| 2098 | The return value can also optionally (see below) include the buffer | ||
| 2099 | position of the first line whose dimensions were measured. | ||
| 2096 | 2100 | ||
| 2097 | The optional argument @var{from}, if non-@code{nil}, specifies the | 2101 | The optional argument @var{from}, if non-@code{nil}, specifies the |
| 2098 | first text position to consider, and defaults to the minimum | 2102 | first text position to consider, and defaults to the minimum |
| 2099 | accessible position of the buffer. If @var{from} is @code{t}, it | 2103 | accessible position of the buffer. If @var{from} is @code{t}, it |
| 2100 | stands for the minimum accessible position that is not a newline | 2104 | stands for the minimum accessible position that is not a newline |
| 2101 | character. The optional argument @var{to}, if non-@code{nil}, | 2105 | character. If @var{from} is a cons, its @code{car} specifies a buffer |
| 2102 | specifies the last text position to consider, and defaults to the | 2106 | position, and its @code{cdr} specifies the vertical offset in pixels |
| 2103 | maximum accessible position of the buffer. If @var{to} is @code{t}, | 2107 | from that position to the first screen line whose text is to be |
| 2104 | it stands for the maximum accessible position that is not a newline | 2108 | measured. (The measurement will start from the visual beginning of |
| 2105 | character. | 2109 | that screen line.) In that case, the return value will instead be a |
| 2110 | list of the pixel-width, pixel-height, and the buffer position of the | ||
| 2111 | first line that was measured. The optional argument @var{to}, if | ||
| 2112 | non-@code{nil}, specifies the last text position to consider, and | ||
| 2113 | defaults to the maximum accessible position of the buffer. If | ||
| 2114 | @var{to} is @code{t}, it stands for the maximum accessible position | ||
| 2115 | that is not a newline character. | ||
| 2106 | 2116 | ||
| 2107 | The optional argument @var{x-limit}, if non-@code{nil}, specifies the | 2117 | The optional argument @var{x-limit}, if non-@code{nil}, specifies the |
| 2108 | maximum X coordinate beyond which text should be ignored; it is | 2118 | maximum X coordinate beyond which text should be ignored; it is |
| @@ -1011,6 +1011,11 @@ This controls whether or not the last screen line of the text being | |||
| 1011 | measured will be counted for the purpose of calculating the text | 1011 | measured will be counted for the purpose of calculating the text |
| 1012 | dimensions. | 1012 | dimensions. |
| 1013 | 1013 | ||
| 1014 | +++ | ||
| 1015 | ** 'window-text-pixel-size' understands a new meaning of 'from'. | ||
| 1016 | Specifying a cons as the from argument allows to start measuring text | ||
| 1017 | from a specified amount of pixels above or below a position. | ||
| 1018 | |||
| 1014 | ** XDG support | 1019 | ** XDG support |
| 1015 | 1020 | ||
| 1016 | *** New function 'xdg-state-home' returns 'XDG_STATE_HOME' environment variable. | 1021 | *** New function 'xdg-state-home' returns 'XDG_STATE_HOME' environment variable. |
diff --git a/lisp/pixel-scroll.el b/lisp/pixel-scroll.el index fa0185b16e9..4aae166f2e0 100644 --- a/lisp/pixel-scroll.el +++ b/lisp/pixel-scroll.el | |||
| @@ -516,22 +516,24 @@ the height of the current window." | |||
| 516 | usable-height)))) | 516 | usable-height)))) |
| 517 | (goto-char up-point))) | 517 | (goto-char up-point))) |
| 518 | (let ((current-vscroll (window-vscroll nil t))) | 518 | (let ((current-vscroll (window-vscroll nil t))) |
| 519 | (if (<= delta current-vscroll) | 519 | (setq delta (- delta current-vscroll)) |
| 520 | (set-window-vscroll nil (- current-vscroll delta) t) | 520 | (set-window-vscroll nil 0 t) |
| 521 | (setq delta (- delta current-vscroll)) | 521 | (when (> delta 0) |
| 522 | (set-window-vscroll nil 0 t) | 522 | (let* ((start (window-start)) |
| 523 | (while (> delta 0) | 523 | (dims (window-text-pixel-size nil (cons start (- delta)) |
| 524 | (let ((position (pixel-point-and-height-at-unseen-line))) | 524 | start nil nil nil t)) |
| 525 | (unless (cdr position) | 525 | (height (nth 1 dims)) |
| 526 | (signal 'beginning-of-buffer nil)) | 526 | (position (nth 2 dims))) |
| 527 | (set-window-start nil (car position) t) | 527 | (set-window-start nil position t) |
| 528 | ;; If the line above is taller than the window height (i.e. there's | 528 | ;; If the line above is taller than the window height (i.e. there's |
| 529 | ;; a very tall image), keep point on it. | 529 | ;; a very tall image), keep point on it. |
| 530 | (when (> (cdr position) usable-height) | 530 | (when (> height usable-height) |
| 531 | (goto-char (car position))) | 531 | (goto-char position)) |
| 532 | (setq delta (- delta (cdr position))))) | 532 | (when (or (not position) (eq position start)) |
| 533 | (when (< delta 0) | 533 | (signal 'beginning-of-buffer nil)) |
| 534 | (set-window-vscroll nil (- delta) t)))))) | 534 | (setq delta (- delta height)))) |
| 535 | (when (< delta 0) | ||
| 536 | (set-window-vscroll nil (- delta) t))))) | ||
| 535 | 537 | ||
| 536 | (defun pixel-scroll-precision-interpolate (delta) | 538 | (defun pixel-scroll-precision-interpolate (delta) |
| 537 | "Interpolate a scroll of DELTA pixels. | 539 | "Interpolate a scroll of DELTA pixels. |
diff --git a/src/xdisp.c b/src/xdisp.c index 1f896c256ee..a6c122aee8b 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, | |||
| 10841 | ptrdiff_t start, end, bpos; | 10841 | ptrdiff_t start, end, bpos; |
| 10842 | struct text_pos startp; | 10842 | struct text_pos startp; |
| 10843 | void *itdata = NULL; | 10843 | void *itdata = NULL; |
| 10844 | int c, max_x = 0, max_y = 0, x = 0, y = 0; | 10844 | int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0; |
| 10845 | int doff = 0; | ||
| 10846 | 10845 | ||
| 10847 | if (NILP (from)) | 10846 | if (NILP (from)) |
| 10848 | { | 10847 | { |
| @@ -10868,6 +10867,13 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, | |||
| 10868 | break; | 10867 | break; |
| 10869 | } | 10868 | } |
| 10870 | } | 10869 | } |
| 10870 | else if (CONSP (from)) | ||
| 10871 | { | ||
| 10872 | start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV); | ||
| 10873 | bpos = CHAR_TO_BYTE (start); | ||
| 10874 | CHECK_FIXNUM (XCDR (from)); | ||
| 10875 | vertical_offset = XFIXNUM (XCDR (from)); | ||
| 10876 | } | ||
| 10871 | else | 10877 | else |
| 10872 | { | 10878 | { |
| 10873 | start = clip_to_bounds (BEGV, fix_position (from), ZV); | 10879 | 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, | |||
| 10914 | 10920 | ||
| 10915 | itdata = bidi_shelve_cache (); | 10921 | itdata = bidi_shelve_cache (); |
| 10916 | start_display (&it, w, startp); | 10922 | start_display (&it, w, startp); |
| 10923 | |||
| 10917 | int start_y = it.current_y; | 10924 | int start_y = it.current_y; |
| 10925 | |||
| 10918 | /* It makes no sense to measure dimensions of region of text that | 10926 | /* It makes no sense to measure dimensions of region of text that |
| 10919 | crosses the point where bidi reordering changes scan direction. | 10927 | crosses the point where bidi reordering changes scan direction. |
| 10920 | By using unidirectional movement here we at least support the use | 10928 | 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, | |||
| 10923 | same directionality. */ | 10931 | same directionality. */ |
| 10924 | it.bidi_p = false; | 10932 | it.bidi_p = false; |
| 10925 | 10933 | ||
| 10926 | /* Start at the beginning of the line containing FROM. Otherwise | 10934 | if (vertical_offset != 0) |
| 10927 | IT.current_x will be incorrectly set to zero at some arbitrary | 10935 | { |
| 10928 | non-zero X coordinate. */ | 10936 | int last_y; |
| 10929 | reseat_at_previous_visible_line_start (&it); | 10937 | it.current_y = 0; |
| 10930 | it.current_x = it.hpos = 0; | 10938 | |
| 10931 | if (IT_CHARPOS (it) != start) | 10939 | move_it_by_lines (&it, 0); |
| 10932 | move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS); | 10940 | |
| 10941 | /* `move_it_vertically_backward' is called by move_it_vertically | ||
| 10942 | to move by a negative value (upwards), but it is not always | ||
| 10943 | guaranteed to leave the iterator at or above the position | ||
| 10944 | given by the offset, which this loop ensures. */ | ||
| 10945 | if (vertical_offset < 0) | ||
| 10946 | { | ||
| 10947 | while (it.current_y > vertical_offset) | ||
| 10948 | { | ||
| 10949 | last_y = it.current_y; | ||
| 10950 | move_it_vertically_backward (&it, | ||
| 10951 | (abs (vertical_offset) | ||
| 10952 | + it.current_y)); | ||
| 10953 | |||
| 10954 | if (it.current_y == last_y) | ||
| 10955 | break; | ||
| 10956 | } | ||
| 10957 | } | ||
| 10958 | else | ||
| 10959 | { | ||
| 10960 | move_it_vertically (&it, vertical_offset); | ||
| 10961 | } | ||
| 10962 | |||
| 10963 | it.current_y = (WINDOW_TAB_LINE_HEIGHT (w) | ||
| 10964 | + WINDOW_HEADER_LINE_HEIGHT (w)); | ||
| 10965 | start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV); | ||
| 10966 | start_y = it.current_y; | ||
| 10967 | } | ||
| 10968 | else | ||
| 10969 | { | ||
| 10970 | /* Start at the beginning of the line containing FROM. Otherwise | ||
| 10971 | IT.current_x will be incorrectly set to zero at some arbitrary | ||
| 10972 | non-zero X coordinate. */ | ||
| 10973 | reseat_at_previous_visible_line_start (&it); | ||
| 10974 | it.current_x = it.hpos = 0; | ||
| 10975 | if (IT_CHARPOS (it) != start) | ||
| 10976 | move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS); | ||
| 10977 | } | ||
| 10933 | 10978 | ||
| 10934 | /* Now move to TO. */ | 10979 | /* Now move to TO. */ |
| 10935 | int start_x = it.current_x; | 10980 | int start_x = it.current_x; |
| @@ -11052,26 +11097,34 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, | |||
| 11052 | 11097 | ||
| 11053 | bidi_unshelve_cache (itdata, false); | 11098 | bidi_unshelve_cache (itdata, false); |
| 11054 | 11099 | ||
| 11055 | return Fcons (make_fixnum (x - start_x), make_fixnum (y)); | 11100 | return (!vertical_offset |
| 11101 | ? Fcons (make_fixnum (x - start_x), make_fixnum (y)) | ||
| 11102 | : list3i (x - start_x, y, start)); | ||
| 11056 | } | 11103 | } |
| 11057 | 11104 | ||
| 11058 | DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0, | 11105 | DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0, |
| 11059 | doc: /* Return the size of the text of WINDOW's buffer in pixels. | 11106 | doc: /* Return the size of the text of WINDOW's buffer in pixels. |
| 11060 | WINDOW must be a live window and defaults to the selected one. The | 11107 | WINDOW must be a live window and defaults to the selected one. The |
| 11061 | return value is a cons of the maximum pixel-width of any text line | 11108 | return value is a cons of the maximum pixel-width of any text line and |
| 11062 | and the pixel-height of all the text lines in the accessible portion | 11109 | the pixel-height of all the text lines in the accessible portion of |
| 11063 | of buffer text. | 11110 | buffer text. |
| 11111 | |||
| 11112 | If FROM is a cons cell, the return value includes, in addition to the | ||
| 11113 | dimensions, also a third element that provides the buffer position | ||
| 11114 | from which measuring of the text dimensions was actually started. | ||
| 11064 | 11115 | ||
| 11065 | This function exists to allow Lisp programs to adjust the dimensions | 11116 | This function exists to allow Lisp programs to adjust the dimensions |
| 11066 | of WINDOW to the buffer text it needs to display. | 11117 | of WINDOW to the buffer text it needs to display. |
| 11067 | 11118 | ||
| 11068 | The optional argument FROM, if non-nil, specifies the first text | 11119 | The optional argument FROM, if non-nil, specifies the first text |
| 11069 | position to consider, and defaults to the minimum accessible position | 11120 | position to consider, and defaults to the minimum accessible position |
| 11070 | of the buffer. If FROM is t, it stands for the minimum accessible | 11121 | of the buffer. If FROM is a cons, its car specifies a buffer |
| 11071 | position that starts a non-empty line. TO, if non-nil, specifies the | 11122 | position, and its cdr specifies the vertical offset in pixels from |
| 11072 | last text position and defaults to the maximum accessible position of | 11123 | that position to the first screen line to be measured. If FROM is t, |
| 11073 | the buffer. If TO is t, it stands for the maximum accessible position | 11124 | it stands for the minimum accessible position that starts a non-empty |
| 11074 | that ends a non-empty line. | 11125 | line. TO, if non-nil, specifies the last text position and defaults |
| 11126 | to the maximum accessible position of the buffer. If TO is t, it | ||
| 11127 | stands for the maximum accessible position that ends a non-empty line. | ||
| 11075 | 11128 | ||
| 11076 | The optional argument X-LIMIT, if non-nil, specifies the maximum X | 11129 | The optional argument X-LIMIT, if non-nil, specifies the maximum X |
| 11077 | coordinate beyond which the text should be ignored. It is therefore | 11130 | coordinate beyond which the text should be ignored. It is therefore |