diff options
| author | Alan Mackenzie | 2015-11-11 12:02:48 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2015-11-11 12:02:48 +0000 |
| commit | 2c56fc2a3f106a1286ad793eed9bfaafd09a7411 (patch) | |
| tree | 6082e9df4733fb39a9d1423568a703c93f7ead62 /src | |
| parent | 25775a12c5168b0494dff15639ac25d8e1017530 (diff) | |
| download | emacs-2c56fc2a3f106a1286ad793eed9bfaafd09a7411.tar.gz emacs-2c56fc2a3f106a1286ad793eed9bfaafd09a7411.zip | |
First commit to scratch/follow. Make Isearch work with Follow Mode, etc.
doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of
Windows" and new @defun selected-window-group.
(Window Start and End): Describe new &optional parameter GROUP and
...-group-function for window-start, window-end, set-window-start, and
pos-visible-in-window-p.
(Textual Scrolling) Describe the same for recenter.
doc/lispref/positions.texi (Screen Lines): Describe the same for
move-to-window-line.
src/window.c (Fwindow_start, Fwindow_end, Fset_window_start)
(Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar
new optional parameter "group". At the beginning of each, check whether the
corresponding ...-group-function is set to a function, and if so execute this
function in place of the normal processing.
(syms_of_window): Define symbols for the six new variables below.
(window-start-group-function, window-end-group-function)
(set-window-start-group-function, recenter-group-function)
(pos-visible-in-window-p-group-function, move-to-window-line-group-function):
New permanent local buffer local variables.
src/keyboard.c (Fposn_at_point): Add extra parameter in call to
Fpos_visible_in_window_p.
lisp/window.el (selected-window-group-function): New permanent local buffer
local variable.
(selected-window-group): New function.
lisp/follow.el (follow-mode): Set the ...-group-function variables at mode
enable, kill them at mode disable. Add/remove follow-after-change to/from
after-change-functions.
(follow-start-end-invalid): New variable.
(follow-redisplay): Manipulate follow-start-end-invalid.
(follow-after-change, follow-window-start, follow-window-end)
(follow-set-window-start, follow-pos-visible-in-window-p)
(follow-move-to-window-line, follow-sit-for): New functions.
lisp/isearch.el (isearch-call-message): New macro.
(isearch-update, with-isearch-suspended, isearch-del-char)
(isearch-search-and-update, isearch-ring-adjust): Invoke above new macro.
(with-isearch-suspended): Rearrange code such that isearch-call-message is
invoked before point is moved.
(isearch-message): Add comment about where point must be at function call.
(isearch-search): Remove call to isearch-message.
(isearch-lazy-highlight-window-group): New variable.
(isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move
the battery of tests to ...
(isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer.
Note: (sit-for 0) is still called.
(isearch-lazy-highlight-update): Check membership of
isearch-lazy-highlight-window-group. Don't set the `window' overlay
property.
(isearch-update, isearch-done, isearch-string-out-of-window)
(isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop)
(isearch-lazy-highlight-search, isearch-lazy-highlight-update)
(isearch-lazy-highlight-update): Call the six amended primitives (see
src/window.c above) with the new `group' argument set to t, to cooperate
with Follow Mode.
Diffstat (limited to 'src')
| -rw-r--r-- | src/keyboard.c | 2 | ||||
| -rw-r--r-- | src/window.c | 772 |
2 files changed, 462 insertions, 312 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index 851207874db..c7733568e7f 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -10663,7 +10663,7 @@ The `posn-' functions access elements of such lists. */) | |||
| 10663 | if (NILP (window)) | 10663 | if (NILP (window)) |
| 10664 | window = selected_window; | 10664 | window = selected_window; |
| 10665 | 10665 | ||
| 10666 | tem = Fpos_visible_in_window_p (pos, window, Qt); | 10666 | tem = Fpos_visible_in_window_p (pos, window, Qt, Qnil); |
| 10667 | if (!NILP (tem)) | 10667 | if (!NILP (tem)) |
| 10668 | { | 10668 | { |
| 10669 | Lisp_Object x = XCAR (tem); | 10669 | Lisp_Object x = XCAR (tem); |
diff --git a/src/window.c b/src/window.c index 0ac76d41861..efb4c9b4f8c 100644 --- a/src/window.c +++ b/src/window.c | |||
| @@ -1540,13 +1540,23 @@ WINDOW must be a live window and defaults to the selected one. */) | |||
| 1540 | return Fmarker_position (decode_live_window (window)->old_pointm); | 1540 | return Fmarker_position (decode_live_window (window)->old_pointm); |
| 1541 | } | 1541 | } |
| 1542 | 1542 | ||
| 1543 | DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0, | 1543 | DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 2, 0, |
| 1544 | doc: /* Return position at which display currently starts in WINDOW. | 1544 | doc: /* Return position at which display currently starts in WINDOW. |
| 1545 | WINDOW must be a live window and defaults to the selected one. | 1545 | WINDOW must be a live window and defaults to the selected one. |
| 1546 | This is updated by redisplay or by calling `set-window-start'. */) | 1546 | This is updated by redisplay or by calling `set-window-start'. |
| 1547 | (Lisp_Object window) | 1547 | |
| 1548 | If GROUP is non-nil, and WINDOW is part of a group of windows collectively | ||
| 1549 | displaying a buffer (such as with Follow Mode), return the start position of | ||
| 1550 | the group rather than of the individual WINDOW. This condition holds when | ||
| 1551 | `window-start-group-function' is set to a function, in which case | ||
| 1552 | `window-start' calls the function with the argument WINDOW, then returns its | ||
| 1553 | result, instead of doing its normal processing. */) | ||
| 1554 | (Lisp_Object window, Lisp_Object group) | ||
| 1548 | { | 1555 | { |
| 1549 | return Fmarker_position (decode_live_window (window)->start); | 1556 | return (!NILP (group) |
| 1557 | && FUNCTIONP (Vwindow_start_group_function)) | ||
| 1558 | ? call1 (Vwindow_start_group_function, window) | ||
| 1559 | : Fmarker_position (decode_live_window (window)->start); | ||
| 1550 | } | 1560 | } |
| 1551 | 1561 | ||
| 1552 | /* This is text temporarily removed from the doc string below. | 1562 | /* This is text temporarily removed from the doc string below. |
| @@ -1560,7 +1570,7 @@ have been if redisplay had finished, do this: | |||
| 1560 | (vertical-motion (1- (window-height window)) window) | 1570 | (vertical-motion (1- (window-height window)) window) |
| 1561 | (point))") */ | 1571 | (point))") */ |
| 1562 | 1572 | ||
| 1563 | DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0, | 1573 | DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 3, 0, |
| 1564 | doc: /* Return position at which display currently ends in WINDOW. | 1574 | doc: /* Return position at which display currently ends in WINDOW. |
| 1565 | WINDOW must be a live window and defaults to the selected one. | 1575 | WINDOW must be a live window and defaults to the selected one. |
| 1566 | This is updated by redisplay, when it runs to completion. | 1576 | This is updated by redisplay, when it runs to completion. |
| @@ -1569,65 +1579,77 @@ does not update this value. | |||
| 1569 | Return nil if there is no recorded value. (This can happen if the | 1579 | Return nil if there is no recorded value. (This can happen if the |
| 1570 | last redisplay of WINDOW was preempted, and did not finish.) | 1580 | last redisplay of WINDOW was preempted, and did not finish.) |
| 1571 | If UPDATE is non-nil, compute the up-to-date position | 1581 | If UPDATE is non-nil, compute the up-to-date position |
| 1572 | if it isn't already recorded. */) | 1582 | if it isn't already recorded. |
| 1573 | (Lisp_Object window, Lisp_Object update) | 1583 | |
| 1574 | { | 1584 | If GROUP is non-nil, and WINDOW is part of a group of windows collectively |
| 1575 | Lisp_Object value; | 1585 | displaying a buffer (such as with Follow Mode), return the end position of |
| 1576 | struct window *w = decode_live_window (window); | 1586 | the group rather than of the individual WINDOW. This condition holds when |
| 1577 | Lisp_Object buf; | 1587 | `window-end-group-function' is set to a function, in which case `window-end' |
| 1578 | struct buffer *b; | 1588 | calls the function with the two arguments WINDOW and UPDATE, then returns its |
| 1579 | 1589 | result, instead of doing its normal processing. */) | |
| 1580 | buf = w->contents; | 1590 | (Lisp_Object window, Lisp_Object update, Lisp_Object group) |
| 1581 | CHECK_BUFFER (buf); | 1591 | { |
| 1582 | b = XBUFFER (buf); | 1592 | if (!NILP (group) |
| 1583 | 1593 | && FUNCTIONP (Vwindow_end_group_function)) | |
| 1584 | if (! NILP (update) | 1594 | return call2 (Vwindow_end_group_function, window, update); |
| 1585 | && (windows_or_buffers_changed | 1595 | { |
| 1586 | || !w->window_end_valid | 1596 | Lisp_Object value; |
| 1587 | || b->clip_changed | 1597 | struct window *w = decode_live_window (window); |
| 1588 | || b->prevent_redisplay_optimizations_p | 1598 | Lisp_Object buf; |
| 1589 | || window_outdated (w)) | 1599 | struct buffer *b; |
| 1590 | /* Don't call display routines if we didn't yet create any real | 1600 | |
| 1591 | frames, because the glyph matrices are not yet allocated in | 1601 | buf = w->contents; |
| 1592 | that case. This could happen in some code that runs in the | 1602 | CHECK_BUFFER (buf); |
| 1593 | daemon during initialization (e.g., see bug#20565). */ | 1603 | b = XBUFFER (buf); |
| 1594 | && !(noninteractive || FRAME_INITIAL_P (WINDOW_XFRAME (w)))) | 1604 | |
| 1595 | { | 1605 | if (! NILP (update) |
| 1596 | struct text_pos startp; | 1606 | && (windows_or_buffers_changed |
| 1597 | struct it it; | 1607 | || !w->window_end_valid |
| 1598 | struct buffer *old_buffer = NULL; | 1608 | || b->clip_changed |
| 1599 | void *itdata = NULL; | 1609 | || b->prevent_redisplay_optimizations_p |
| 1600 | 1610 | || window_outdated (w)) | |
| 1601 | /* Cannot use Fvertical_motion because that function doesn't | 1611 | /* Don't call display routines if we didn't yet create any real |
| 1602 | cope with variable-height lines. */ | 1612 | frames, because the glyph matrices are not yet allocated in |
| 1603 | if (b != current_buffer) | 1613 | that case. This could happen in some code that runs in the |
| 1604 | { | 1614 | daemon during initialization (e.g., see bug#20565). */ |
| 1605 | old_buffer = current_buffer; | 1615 | && !(noninteractive || FRAME_INITIAL_P (WINDOW_XFRAME (w)))) |
| 1606 | set_buffer_internal (b); | 1616 | { |
| 1607 | } | 1617 | struct text_pos startp; |
| 1608 | 1618 | struct it it; | |
| 1609 | /* In case W->start is out of the range, use something | 1619 | struct buffer *old_buffer = NULL; |
| 1610 | reasonable. This situation occurred when loading a file with | 1620 | void *itdata = NULL; |
| 1611 | `-l' containing a call to `rmail' with subsequent other | 1621 | |
| 1612 | commands. At the end, W->start happened to be BEG, while | 1622 | /* Cannot use Fvertical_motion because that function doesn't |
| 1613 | rmail had already narrowed the buffer. */ | 1623 | cope with variable-height lines. */ |
| 1614 | CLIP_TEXT_POS_FROM_MARKER (startp, w->start); | 1624 | if (b != current_buffer) |
| 1615 | 1625 | { | |
| 1616 | itdata = bidi_shelve_cache (); | 1626 | old_buffer = current_buffer; |
| 1617 | start_display (&it, w, startp); | 1627 | set_buffer_internal (b); |
| 1618 | move_it_vertically (&it, window_box_height (w)); | 1628 | } |
| 1619 | if (it.current_y < it.last_visible_y) | 1629 | |
| 1620 | move_it_past_eol (&it); | 1630 | /* In case W->start is out of the range, use something |
| 1621 | value = make_number (IT_CHARPOS (it)); | 1631 | reasonable. This situation occurred when loading a file with |
| 1622 | bidi_unshelve_cache (itdata, false); | 1632 | `-l' containing a call to `rmail' with subsequent other |
| 1623 | 1633 | commands. At the end, W->start happened to be BEG, while | |
| 1624 | if (old_buffer) | 1634 | rmail had already narrowed the buffer. */ |
| 1625 | set_buffer_internal (old_buffer); | 1635 | CLIP_TEXT_POS_FROM_MARKER (startp, w->start); |
| 1626 | } | 1636 | |
| 1627 | else | 1637 | itdata = bidi_shelve_cache (); |
| 1628 | XSETINT (value, BUF_Z (b) - w->window_end_pos); | 1638 | start_display (&it, w, startp); |
| 1639 | move_it_vertically (&it, window_box_height (w)); | ||
| 1640 | if (it.current_y < it.last_visible_y) | ||
| 1641 | move_it_past_eol (&it); | ||
| 1642 | value = make_number (IT_CHARPOS (it)); | ||
| 1643 | bidi_unshelve_cache (itdata, false); | ||
| 1644 | |||
| 1645 | if (old_buffer) | ||
| 1646 | set_buffer_internal (old_buffer); | ||
| 1647 | } | ||
| 1648 | else | ||
| 1649 | XSETINT (value, BUF_Z (b) - w->window_end_pos); | ||
| 1629 | 1650 | ||
| 1630 | return value; | 1651 | return value; |
| 1652 | } | ||
| 1631 | } | 1653 | } |
| 1632 | 1654 | ||
| 1633 | DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0, | 1655 | DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0, |
| @@ -1666,30 +1688,43 @@ Return POS. */) | |||
| 1666 | return pos; | 1688 | return pos; |
| 1667 | } | 1689 | } |
| 1668 | 1690 | ||
| 1669 | DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0, | 1691 | DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 4, 0, |
| 1670 | doc: /* Make display in WINDOW start at position POS in WINDOW's buffer. | 1692 | doc: /* Make display in WINDOW start at position POS in WINDOW's buffer. |
| 1671 | WINDOW must be a live window and defaults to the selected one. Return | 1693 | WINDOW must be a live window and defaults to the selected one. Return |
| 1672 | POS. Optional third arg NOFORCE non-nil inhibits next redisplay from | 1694 | POS. Optional third arg NOFORCE non-nil inhibits next redisplay from |
| 1673 | overriding motion of point in order to display at this exact start. */) | 1695 | overriding motion of point in order to display at this exact start. |
| 1674 | (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce) | 1696 | |
| 1675 | { | 1697 | If GROUP is non-nil, and WINDOW is part of a group of windows collectively |
| 1676 | register struct window *w = decode_live_window (window); | 1698 | displaying a buffer (such as with Follow Mode), set the start position of |
| 1699 | the group rather than of the individual WINDOW. This condition holds when | ||
| 1700 | `set-window-start-group-function' is set to a function, in which case | ||
| 1701 | `set-window-start' calls the function with the three arguments WINDOW, POS, | ||
| 1702 | and NOFORCE, then returns its result, instead of doing its normal | ||
| 1703 | processing. */) | ||
| 1704 | (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce, Lisp_Object group) | ||
| 1705 | { | ||
| 1706 | if (!NILP (group) | ||
| 1707 | && FUNCTIONP (Vset_window_start_group_function)) | ||
| 1708 | return call3 (Vset_window_start_group_function, window, pos, noforce); | ||
| 1709 | { | ||
| 1710 | register struct window *w = decode_live_window (window); | ||
| 1677 | 1711 | ||
| 1678 | set_marker_restricted (w->start, pos, w->contents); | 1712 | set_marker_restricted (w->start, pos, w->contents); |
| 1679 | /* This is not right, but much easier than doing what is right. */ | 1713 | /* This is not right, but much easier than doing what is right. */ |
| 1680 | w->start_at_line_beg = false; | 1714 | w->start_at_line_beg = false; |
| 1681 | if (NILP (noforce)) | 1715 | if (NILP (noforce)) |
| 1682 | w->force_start = true; | 1716 | w->force_start = true; |
| 1683 | wset_update_mode_line (w); | 1717 | wset_update_mode_line (w); |
| 1684 | /* Bug#15957. */ | 1718 | /* Bug#15957. */ |
| 1685 | w->window_end_valid = false; | 1719 | w->window_end_valid = false; |
| 1686 | wset_redisplay (w); | 1720 | wset_redisplay (w); |
| 1687 | 1721 | ||
| 1688 | return pos; | 1722 | return pos; |
| 1723 | } | ||
| 1689 | } | 1724 | } |
| 1690 | 1725 | ||
| 1691 | DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, | 1726 | DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, |
| 1692 | Spos_visible_in_window_p, 0, 3, 0, | 1727 | Spos_visible_in_window_p, 0, 4, 0, |
| 1693 | doc: /* Return non-nil if position POS is currently on the frame in WINDOW. | 1728 | doc: /* Return non-nil if position POS is currently on the frame in WINDOW. |
| 1694 | WINDOW must be a live window and defaults to the selected one. | 1729 | WINDOW must be a live window and defaults to the selected one. |
| 1695 | 1730 | ||
| @@ -1709,9 +1744,21 @@ of the window. The remaining elements are omitted if the character after | |||
| 1709 | POS is fully visible; otherwise, RTOP and RBOT are the number of pixels | 1744 | POS is fully visible; otherwise, RTOP and RBOT are the number of pixels |
| 1710 | off-window at the top and bottom of the screen line ("row") containing | 1745 | off-window at the top and bottom of the screen line ("row") containing |
| 1711 | POS, ROWH is the visible height of that row, and VPOS is the row number | 1746 | POS, ROWH is the visible height of that row, and VPOS is the row number |
| 1712 | (zero-based). */) | 1747 | (zero-based). |
| 1713 | (Lisp_Object pos, Lisp_Object window, Lisp_Object partially) | 1748 | |
| 1714 | { | 1749 | If GROUP is non-nil, and WINDOW is part of a group of windows collectively |
| 1750 | displaying a buffer (such as with Follow Mode), test whether POS is visible | ||
| 1751 | in the group of windows rather than in the individual WINDOW. This | ||
| 1752 | condition holds when `pos-visible-in-window-p-function' is set to a | ||
| 1753 | function, in which case `pos-visible-in-window-p' calls the function with | ||
| 1754 | the three arguments POS, WINDOW, and PARTIALLY, then returns its result, | ||
| 1755 | instead of doing its normal processing. */) | ||
| 1756 | (Lisp_Object pos, Lisp_Object window, Lisp_Object partially, Lisp_Object group) | ||
| 1757 | { | ||
| 1758 | if (!NILP (group) | ||
| 1759 | && FUNCTIONP (Vpos_visible_in_window_p_group_function)) | ||
| 1760 | return call3 (Vpos_visible_in_window_p_group_function, pos, window, partially); | ||
| 1761 | { | ||
| 1715 | struct window *w; | 1762 | struct window *w; |
| 1716 | EMACS_INT posint; | 1763 | EMACS_INT posint; |
| 1717 | struct buffer *buf; | 1764 | struct buffer *buf; |
| @@ -1760,6 +1807,7 @@ POS, ROWH is the visible height of that row, and VPOS is the row number | |||
| 1760 | } | 1807 | } |
| 1761 | 1808 | ||
| 1762 | return in_window; | 1809 | return in_window; |
| 1810 | } | ||
| 1763 | } | 1811 | } |
| 1764 | 1812 | ||
| 1765 | DEFUN ("window-line-height", Fwindow_line_height, | 1813 | DEFUN ("window-line-height", Fwindow_line_height, |
| @@ -5185,7 +5233,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5185 | } | 5233 | } |
| 5186 | 5234 | ||
| 5187 | XSETFASTINT (tem, PT); | 5235 | XSETFASTINT (tem, PT); |
| 5188 | tem = Fpos_visible_in_window_p (tem, window, Qnil); | 5236 | tem = Fpos_visible_in_window_p (tem, window, Qnil, Qnil); |
| 5189 | 5237 | ||
| 5190 | if (NILP (tem)) | 5238 | if (NILP (tem)) |
| 5191 | { | 5239 | { |
| @@ -5574,7 +5622,7 @@ displayed_window_lines (struct window *w) | |||
| 5574 | } | 5622 | } |
| 5575 | 5623 | ||
| 5576 | 5624 | ||
| 5577 | DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P", | 5625 | DEFUN ("recenter", Frecenter, Srecenter, 0, 2, "P\ni", |
| 5578 | doc: /* Center point in selected window and maybe redisplay frame. | 5626 | doc: /* Center point in selected window and maybe redisplay frame. |
| 5579 | With a numeric prefix argument ARG, recenter putting point on screen line ARG | 5627 | With a numeric prefix argument ARG, recenter putting point on screen line ARG |
| 5580 | relative to the selected window. If ARG is negative, it counts up from the | 5628 | relative to the selected window. If ARG is negative, it counts up from the |
| @@ -5588,208 +5636,221 @@ height needed); if `recenter-redisplay' has the special value `tty', | |||
| 5588 | then only tty frames are redrawn. | 5636 | then only tty frames are redrawn. |
| 5589 | 5637 | ||
| 5590 | Just C-u as prefix means put point in the center of the window | 5638 | Just C-u as prefix means put point in the center of the window |
| 5591 | and redisplay normally--don't erase and redraw the frame. */) | 5639 | and redisplay normally--don't erase and redraw the frame. |
| 5592 | (register Lisp_Object arg) | 5640 | |
| 5593 | { | 5641 | When `recenter' is called from a program, GROUP is non-nil, and WINDOW is |
| 5594 | struct window *w = XWINDOW (selected_window); | 5642 | part of a group of windows collectively displaying a buffer (such as with |
| 5595 | struct buffer *buf = XBUFFER (w->contents); | 5643 | Follow Mode), perform `recenter''s actions on the group rather than on the |
| 5596 | bool center_p = false; | 5644 | individual WINDOW. This condition holds when `recenter-group-function' is |
| 5597 | ptrdiff_t charpos, bytepos; | 5645 | set to a function, in which case `recenter' calls the function with the |
| 5598 | EMACS_INT iarg IF_LINT (= 0); | 5646 | argument ARG, then returns its value, instead of doing its normal |
| 5599 | int this_scroll_margin; | 5647 | processing. */) |
| 5600 | 5648 | (register Lisp_Object arg, Lisp_Object group) | |
| 5601 | if (buf != current_buffer) | 5649 | { |
| 5602 | error ("`recenter'ing a window that does not display current-buffer."); | 5650 | if (!NILP (group) |
| 5651 | && FUNCTIONP (Vrecenter_group_function)) | ||
| 5652 | return call1 (Vrecenter_group_function, arg); | ||
| 5653 | { | ||
| 5654 | struct window *w = XWINDOW (selected_window); | ||
| 5655 | struct buffer *buf = XBUFFER (w->contents); | ||
| 5656 | bool center_p = false; | ||
| 5657 | ptrdiff_t charpos, bytepos; | ||
| 5658 | EMACS_INT iarg IF_LINT (= 0); | ||
| 5659 | int this_scroll_margin; | ||
| 5603 | 5660 | ||
| 5604 | /* If redisplay is suppressed due to an error, try again. */ | 5661 | if (buf != current_buffer) |
| 5605 | buf->display_error_modiff = 0; | 5662 | error ("`recenter'ing a window that does not display current-buffer."); |
| 5606 | 5663 | ||
| 5607 | if (NILP (arg)) | 5664 | /* If redisplay is suppressed due to an error, try again. */ |
| 5608 | { | 5665 | buf->display_error_modiff = 0; |
| 5609 | if (!NILP (Vrecenter_redisplay) | ||
| 5610 | && (!EQ (Vrecenter_redisplay, Qtty) | ||
| 5611 | || !NILP (Ftty_type (selected_frame)))) | ||
| 5612 | { | ||
| 5613 | ptrdiff_t i; | ||
| 5614 | 5666 | ||
| 5615 | /* Invalidate pixel data calculated for all compositions. */ | 5667 | if (NILP (arg)) |
| 5616 | for (i = 0; i < n_compositions; i++) | 5668 | { |
| 5617 | composition_table[i]->font = NULL; | 5669 | if (!NILP (Vrecenter_redisplay) |
| 5670 | && (!EQ (Vrecenter_redisplay, Qtty) | ||
| 5671 | || !NILP (Ftty_type (selected_frame)))) | ||
| 5672 | { | ||
| 5673 | ptrdiff_t i; | ||
| 5674 | |||
| 5675 | /* Invalidate pixel data calculated for all compositions. */ | ||
| 5676 | for (i = 0; i < n_compositions; i++) | ||
| 5677 | composition_table[i]->font = NULL; | ||
| 5618 | #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS) | 5678 | #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS) |
| 5619 | WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1; | 5679 | WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1; |
| 5620 | #endif | 5680 | #endif |
| 5621 | Fredraw_frame (WINDOW_FRAME (w)); | 5681 | Fredraw_frame (WINDOW_FRAME (w)); |
| 5622 | SET_FRAME_GARBAGED (WINDOW_XFRAME (w)); | 5682 | SET_FRAME_GARBAGED (WINDOW_XFRAME (w)); |
| 5623 | } | 5683 | } |
| 5624 | 5684 | ||
| 5685 | center_p = true; | ||
| 5686 | } | ||
| 5687 | else if (CONSP (arg)) /* Just C-u. */ | ||
| 5625 | center_p = true; | 5688 | center_p = true; |
| 5626 | } | 5689 | else |
| 5627 | else if (CONSP (arg)) /* Just C-u. */ | 5690 | { |
| 5628 | center_p = true; | 5691 | arg = Fprefix_numeric_value (arg); |
| 5629 | else | 5692 | CHECK_NUMBER (arg); |
| 5630 | { | 5693 | iarg = XINT (arg); |
| 5631 | arg = Fprefix_numeric_value (arg); | 5694 | } |
| 5632 | CHECK_NUMBER (arg); | ||
| 5633 | iarg = XINT (arg); | ||
| 5634 | } | ||
| 5635 | |||
| 5636 | /* Do this after making BUF current | ||
| 5637 | in case scroll_margin is buffer-local. */ | ||
| 5638 | this_scroll_margin | ||
| 5639 | = max (0, min (scroll_margin, w->total_lines / 4)); | ||
| 5640 | |||
| 5641 | /* Don't use redisplay code for initial frames, as the necessary | ||
| 5642 | data structures might not be set up yet then. */ | ||
| 5643 | if (!FRAME_INITIAL_P (XFRAME (w->frame))) | ||
| 5644 | { | ||
| 5645 | if (center_p) | ||
| 5646 | { | ||
| 5647 | struct it it; | ||
| 5648 | struct text_pos pt; | ||
| 5649 | void *itdata = bidi_shelve_cache (); | ||
| 5650 | |||
| 5651 | SET_TEXT_POS (pt, PT, PT_BYTE); | ||
| 5652 | start_display (&it, w, pt); | ||
| 5653 | move_it_vertically_backward (&it, window_box_height (w) / 2); | ||
| 5654 | charpos = IT_CHARPOS (it); | ||
| 5655 | bytepos = IT_BYTEPOS (it); | ||
| 5656 | bidi_unshelve_cache (itdata, false); | ||
| 5657 | } | ||
| 5658 | else if (iarg < 0) | ||
| 5659 | { | ||
| 5660 | struct it it; | ||
| 5661 | struct text_pos pt; | ||
| 5662 | ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg); | ||
| 5663 | int extra_line_spacing; | ||
| 5664 | int h = window_box_height (w); | ||
| 5665 | int ht = window_internal_height (w); | ||
| 5666 | void *itdata = bidi_shelve_cache (); | ||
| 5667 | |||
| 5668 | nlines = clip_to_bounds (this_scroll_margin + 1, nlines, | ||
| 5669 | ht - this_scroll_margin); | ||
| 5670 | |||
| 5671 | SET_TEXT_POS (pt, PT, PT_BYTE); | ||
| 5672 | start_display (&it, w, pt); | ||
| 5673 | |||
| 5674 | /* Be sure we have the exact height of the full line containing PT. */ | ||
| 5675 | move_it_by_lines (&it, 0); | ||
| 5676 | |||
| 5677 | /* The amount of pixels we have to move back is the window | ||
| 5678 | height minus what's displayed in the line containing PT, | ||
| 5679 | and the lines below. */ | ||
| 5680 | it.current_y = 0; | ||
| 5681 | it.vpos = 0; | ||
| 5682 | move_it_by_lines (&it, nlines); | ||
| 5683 | |||
| 5684 | if (it.vpos == nlines) | ||
| 5685 | h -= it.current_y; | ||
| 5686 | else | ||
| 5687 | { | ||
| 5688 | /* Last line has no newline. */ | ||
| 5689 | h -= line_bottom_y (&it); | ||
| 5690 | it.vpos++; | ||
| 5691 | } | ||
| 5692 | |||
| 5693 | /* Don't reserve space for extra line spacing of last line. */ | ||
| 5694 | extra_line_spacing = it.max_extra_line_spacing; | ||
| 5695 | |||
| 5696 | /* If we can't move down NLINES lines because we hit | ||
| 5697 | the end of the buffer, count in some empty lines. */ | ||
| 5698 | if (it.vpos < nlines) | ||
| 5699 | { | ||
| 5700 | nlines -= it.vpos; | ||
| 5701 | extra_line_spacing = it.extra_line_spacing; | ||
| 5702 | h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing); | ||
| 5703 | } | ||
| 5704 | if (h <= 0) | ||
| 5705 | { | ||
| 5706 | bidi_unshelve_cache (itdata, false); | ||
| 5707 | return Qnil; | ||
| 5708 | } | ||
| 5709 | |||
| 5710 | /* Now find the new top line (starting position) of the window. */ | ||
| 5711 | start_display (&it, w, pt); | ||
| 5712 | it.current_y = 0; | ||
| 5713 | move_it_vertically_backward (&it, h); | ||
| 5714 | |||
| 5715 | /* If extra line spacing is present, we may move too far | ||
| 5716 | back. This causes the last line to be only partially | ||
| 5717 | visible (which triggers redisplay to recenter that line | ||
| 5718 | in the middle), so move forward. | ||
| 5719 | But ignore extra line spacing on last line, as it is not | ||
| 5720 | considered to be part of the visible height of the line. | ||
| 5721 | */ | ||
| 5722 | h += extra_line_spacing; | ||
| 5723 | while (-it.current_y > h) | ||
| 5724 | move_it_by_lines (&it, 1); | ||
| 5725 | |||
| 5726 | charpos = IT_CHARPOS (it); | ||
| 5727 | bytepos = IT_BYTEPOS (it); | ||
| 5728 | |||
| 5729 | bidi_unshelve_cache (itdata, false); | ||
| 5730 | } | ||
| 5731 | else | ||
| 5732 | { | ||
| 5733 | struct it it; | ||
| 5734 | struct text_pos pt; | ||
| 5735 | ptrdiff_t nlines = min (PTRDIFF_MAX, iarg); | ||
| 5736 | int ht = window_internal_height (w); | ||
| 5737 | void *itdata = bidi_shelve_cache (); | ||
| 5738 | |||
| 5739 | nlines = clip_to_bounds (this_scroll_margin, nlines, | ||
| 5740 | ht - this_scroll_margin - 1); | ||
| 5741 | |||
| 5742 | SET_TEXT_POS (pt, PT, PT_BYTE); | ||
| 5743 | start_display (&it, w, pt); | ||
| 5744 | |||
| 5745 | /* Move to the beginning of screen line containing PT. */ | ||
| 5746 | move_it_by_lines (&it, 0); | ||
| 5747 | |||
| 5748 | /* Move back to find the point which is ARG screen lines above PT. */ | ||
| 5749 | if (nlines > 0) | ||
| 5750 | { | ||
| 5751 | it.current_y = 0; | ||
| 5752 | it.vpos = 0; | ||
| 5753 | move_it_by_lines (&it, -nlines); | ||
| 5754 | } | ||
| 5755 | 5695 | ||
| 5756 | charpos = IT_CHARPOS (it); | 5696 | /* Do this after making BUF current |
| 5757 | bytepos = IT_BYTEPOS (it); | 5697 | in case scroll_margin is buffer-local. */ |
| 5698 | this_scroll_margin | ||
| 5699 | = max (0, min (scroll_margin, w->total_lines / 4)); | ||
| 5758 | 5700 | ||
| 5759 | bidi_unshelve_cache (itdata, false); | 5701 | /* Don't use redisplay code for initial frames, as the necessary |
| 5760 | } | 5702 | data structures might not be set up yet then. */ |
| 5761 | } | 5703 | if (!FRAME_INITIAL_P (XFRAME (w->frame))) |
| 5762 | else | 5704 | { |
| 5763 | { | 5705 | if (center_p) |
| 5764 | struct position pos; | 5706 | { |
| 5765 | int ht = window_internal_height (w); | 5707 | struct it it; |
| 5708 | struct text_pos pt; | ||
| 5709 | void *itdata = bidi_shelve_cache (); | ||
| 5710 | |||
| 5711 | SET_TEXT_POS (pt, PT, PT_BYTE); | ||
| 5712 | start_display (&it, w, pt); | ||
| 5713 | move_it_vertically_backward (&it, window_box_height (w) / 2); | ||
| 5714 | charpos = IT_CHARPOS (it); | ||
| 5715 | bytepos = IT_BYTEPOS (it); | ||
| 5716 | bidi_unshelve_cache (itdata, false); | ||
| 5717 | } | ||
| 5718 | else if (iarg < 0) | ||
| 5719 | { | ||
| 5720 | struct it it; | ||
| 5721 | struct text_pos pt; | ||
| 5722 | ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg); | ||
| 5723 | int extra_line_spacing; | ||
| 5724 | int h = window_box_height (w); | ||
| 5725 | int ht = window_internal_height (w); | ||
| 5726 | void *itdata = bidi_shelve_cache (); | ||
| 5727 | |||
| 5728 | nlines = clip_to_bounds (this_scroll_margin + 1, nlines, | ||
| 5729 | ht - this_scroll_margin); | ||
| 5730 | |||
| 5731 | SET_TEXT_POS (pt, PT, PT_BYTE); | ||
| 5732 | start_display (&it, w, pt); | ||
| 5733 | |||
| 5734 | /* Be sure we have the exact height of the full line containing PT. */ | ||
| 5735 | move_it_by_lines (&it, 0); | ||
| 5736 | |||
| 5737 | /* The amount of pixels we have to move back is the window | ||
| 5738 | height minus what's displayed in the line containing PT, | ||
| 5739 | and the lines below. */ | ||
| 5740 | it.current_y = 0; | ||
| 5741 | it.vpos = 0; | ||
| 5742 | move_it_by_lines (&it, nlines); | ||
| 5743 | |||
| 5744 | if (it.vpos == nlines) | ||
| 5745 | h -= it.current_y; | ||
| 5746 | else | ||
| 5747 | { | ||
| 5748 | /* Last line has no newline. */ | ||
| 5749 | h -= line_bottom_y (&it); | ||
| 5750 | it.vpos++; | ||
| 5751 | } | ||
| 5752 | |||
| 5753 | /* Don't reserve space for extra line spacing of last line. */ | ||
| 5754 | extra_line_spacing = it.max_extra_line_spacing; | ||
| 5755 | |||
| 5756 | /* If we can't move down NLINES lines because we hit | ||
| 5757 | the end of the buffer, count in some empty lines. */ | ||
| 5758 | if (it.vpos < nlines) | ||
| 5759 | { | ||
| 5760 | nlines -= it.vpos; | ||
| 5761 | extra_line_spacing = it.extra_line_spacing; | ||
| 5762 | h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing); | ||
| 5763 | } | ||
| 5764 | if (h <= 0) | ||
| 5765 | { | ||
| 5766 | bidi_unshelve_cache (itdata, false); | ||
| 5767 | return Qnil; | ||
| 5768 | } | ||
| 5769 | |||
| 5770 | /* Now find the new top line (starting position) of the window. */ | ||
| 5771 | start_display (&it, w, pt); | ||
| 5772 | it.current_y = 0; | ||
| 5773 | move_it_vertically_backward (&it, h); | ||
| 5774 | |||
| 5775 | /* If extra line spacing is present, we may move too far | ||
| 5776 | back. This causes the last line to be only partially | ||
| 5777 | visible (which triggers redisplay to recenter that line | ||
| 5778 | in the middle), so move forward. | ||
| 5779 | But ignore extra line spacing on last line, as it is not | ||
| 5780 | considered to be part of the visible height of the line. | ||
| 5781 | */ | ||
| 5782 | h += extra_line_spacing; | ||
| 5783 | while (-it.current_y > h) | ||
| 5784 | move_it_by_lines (&it, 1); | ||
| 5785 | |||
| 5786 | charpos = IT_CHARPOS (it); | ||
| 5787 | bytepos = IT_BYTEPOS (it); | ||
| 5788 | |||
| 5789 | bidi_unshelve_cache (itdata, false); | ||
| 5790 | } | ||
| 5791 | else | ||
| 5792 | { | ||
| 5793 | struct it it; | ||
| 5794 | struct text_pos pt; | ||
| 5795 | ptrdiff_t nlines = min (PTRDIFF_MAX, iarg); | ||
| 5796 | int ht = window_internal_height (w); | ||
| 5797 | void *itdata = bidi_shelve_cache (); | ||
| 5798 | |||
| 5799 | nlines = clip_to_bounds (this_scroll_margin, nlines, | ||
| 5800 | ht - this_scroll_margin - 1); | ||
| 5801 | |||
| 5802 | SET_TEXT_POS (pt, PT, PT_BYTE); | ||
| 5803 | start_display (&it, w, pt); | ||
| 5804 | |||
| 5805 | /* Move to the beginning of screen line containing PT. */ | ||
| 5806 | move_it_by_lines (&it, 0); | ||
| 5807 | |||
| 5808 | /* Move back to find the point which is ARG screen lines above PT. */ | ||
| 5809 | if (nlines > 0) | ||
| 5810 | { | ||
| 5811 | it.current_y = 0; | ||
| 5812 | it.vpos = 0; | ||
| 5813 | move_it_by_lines (&it, -nlines); | ||
| 5814 | } | ||
| 5815 | |||
| 5816 | charpos = IT_CHARPOS (it); | ||
| 5817 | bytepos = IT_BYTEPOS (it); | ||
| 5818 | |||
| 5819 | bidi_unshelve_cache (itdata, false); | ||
| 5820 | } | ||
| 5821 | } | ||
| 5822 | else | ||
| 5823 | { | ||
| 5824 | struct position pos; | ||
| 5825 | int ht = window_internal_height (w); | ||
| 5766 | 5826 | ||
| 5767 | if (center_p) | 5827 | if (center_p) |
| 5768 | iarg = ht / 2; | 5828 | iarg = ht / 2; |
| 5769 | else if (iarg < 0) | 5829 | else if (iarg < 0) |
| 5770 | iarg += ht; | 5830 | iarg += ht; |
| 5771 | 5831 | ||
| 5772 | /* Don't let it get into the margin at either top or bottom. */ | 5832 | /* Don't let it get into the margin at either top or bottom. */ |
| 5773 | iarg = clip_to_bounds (this_scroll_margin, iarg, | 5833 | iarg = clip_to_bounds (this_scroll_margin, iarg, |
| 5774 | ht - this_scroll_margin - 1); | 5834 | ht - this_scroll_margin - 1); |
| 5775 | 5835 | ||
| 5776 | pos = *vmotion (PT, PT_BYTE, - iarg, w); | 5836 | pos = *vmotion (PT, PT_BYTE, - iarg, w); |
| 5777 | charpos = pos.bufpos; | 5837 | charpos = pos.bufpos; |
| 5778 | bytepos = pos.bytepos; | 5838 | bytepos = pos.bytepos; |
| 5779 | } | 5839 | } |
| 5780 | 5840 | ||
| 5781 | /* Set the new window start. */ | 5841 | /* Set the new window start. */ |
| 5782 | set_marker_both (w->start, w->contents, charpos, bytepos); | 5842 | set_marker_both (w->start, w->contents, charpos, bytepos); |
| 5783 | w->window_end_valid = false; | 5843 | w->window_end_valid = false; |
| 5784 | 5844 | ||
| 5785 | w->optional_new_start = true; | 5845 | w->optional_new_start = true; |
| 5786 | 5846 | ||
| 5787 | w->start_at_line_beg = (bytepos == BEGV_BYTE | 5847 | w->start_at_line_beg = (bytepos == BEGV_BYTE |
| 5788 | || FETCH_BYTE (bytepos - 1) == '\n'); | 5848 | || FETCH_BYTE (bytepos - 1) == '\n'); |
| 5789 | 5849 | ||
| 5790 | wset_redisplay (w); | 5850 | wset_redisplay (w); |
| 5791 | 5851 | ||
| 5792 | return Qnil; | 5852 | return Qnil; |
| 5853 | } | ||
| 5793 | } | 5854 | } |
| 5794 | 5855 | ||
| 5795 | DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width, | 5856 | DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width, |
| @@ -5836,52 +5897,68 @@ pixels. */) | |||
| 5836 | } | 5897 | } |
| 5837 | 5898 | ||
| 5838 | DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line, | 5899 | DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line, |
| 5839 | 1, 1, "P", | 5900 | 1, 2, "P\ni", |
| 5840 | doc: /* Position point relative to window. | 5901 | doc: /* Position point relative to window. |
| 5841 | ARG nil means position point at center of window. | 5902 | ARG nil means position point at center of window. |
| 5842 | Else, ARG specifies vertical position within the window; | 5903 | Else, ARG specifies vertical position within the window; |
| 5843 | zero means top of window, negative means relative to bottom of window. */) | 5904 | zero means top of window, negative means relative to bottom of window. |
| 5844 | (Lisp_Object arg) | 5905 | |
| 5845 | { | 5906 | When GROUP is non-nil, and `move-to-window-line-group-function' is set to a |
| 5846 | struct window *w = XWINDOW (selected_window); | 5907 | function, then instead of the above, that function is called with the |
| 5847 | int lines, start; | 5908 | single argument ARG, and its result returned. |
| 5848 | Lisp_Object window; | 5909 | |
| 5910 | If GROUP is non-nil, and WINDOW is part of a group of windows collectively | ||
| 5911 | displaying a buffer (such as with Follow Mode), position point relative to | ||
| 5912 | the group of windows as a whole rather than the individual WINDOW. This | ||
| 5913 | condition holds when `move-to-window-line-group-function' is set to a | ||
| 5914 | function, in which case `move-to-window-line' calls the function with the | ||
| 5915 | argument ARG, then returns its result, instead of doing its normal | ||
| 5916 | processing. */) | ||
| 5917 | (Lisp_Object arg, Lisp_Object group) | ||
| 5918 | { | ||
| 5919 | if (!NILP (group) | ||
| 5920 | && FUNCTIONP (Vmove_to_window_line_group_function)) | ||
| 5921 | return call1 (Vmove_to_window_line_group_function, arg); | ||
| 5922 | { | ||
| 5923 | struct window *w = XWINDOW (selected_window); | ||
| 5924 | int lines, start; | ||
| 5925 | Lisp_Object window; | ||
| 5849 | #if false | 5926 | #if false |
| 5850 | int this_scroll_margin; | 5927 | int this_scroll_margin; |
| 5851 | #endif | 5928 | #endif |
| 5852 | 5929 | ||
| 5853 | if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer)) | 5930 | if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer)) |
| 5854 | /* This test is needed to make sure PT/PT_BYTE make sense in w->contents | 5931 | /* This test is needed to make sure PT/PT_BYTE make sense in w->contents |
| 5855 | when passed below to set_marker_both. */ | 5932 | when passed below to set_marker_both. */ |
| 5856 | error ("move-to-window-line called from unrelated buffer"); | 5933 | error ("move-to-window-line called from unrelated buffer"); |
| 5857 | 5934 | ||
| 5858 | window = selected_window; | 5935 | window = selected_window; |
| 5859 | start = marker_position (w->start); | 5936 | start = marker_position (w->start); |
| 5860 | if (start < BEGV || start > ZV) | 5937 | if (start < BEGV || start > ZV) |
| 5861 | { | 5938 | { |
| 5862 | int height = window_internal_height (w); | 5939 | int height = window_internal_height (w); |
| 5863 | Fvertical_motion (make_number (- (height / 2)), window, Qnil); | 5940 | Fvertical_motion (make_number (- (height / 2)), window, Qnil); |
| 5864 | set_marker_both (w->start, w->contents, PT, PT_BYTE); | 5941 | set_marker_both (w->start, w->contents, PT, PT_BYTE); |
| 5865 | w->start_at_line_beg = !NILP (Fbolp ()); | 5942 | w->start_at_line_beg = !NILP (Fbolp ()); |
| 5866 | w->force_start = true; | 5943 | w->force_start = true; |
| 5867 | } | 5944 | } |
| 5868 | else | 5945 | else |
| 5869 | Fgoto_char (w->start); | 5946 | Fgoto_char (w->start); |
| 5870 | 5947 | ||
| 5871 | lines = displayed_window_lines (w); | 5948 | lines = displayed_window_lines (w); |
| 5872 | 5949 | ||
| 5873 | #if false | 5950 | #if false |
| 5874 | this_scroll_margin = max (0, min (scroll_margin, lines / 4)); | 5951 | this_scroll_margin = max (0, min (scroll_margin, lines / 4)); |
| 5875 | #endif | 5952 | #endif |
| 5876 | 5953 | ||
| 5877 | if (NILP (arg)) | 5954 | if (NILP (arg)) |
| 5878 | XSETFASTINT (arg, lines / 2); | 5955 | XSETFASTINT (arg, lines / 2); |
| 5879 | else | 5956 | else |
| 5880 | { | 5957 | { |
| 5881 | EMACS_INT iarg = XINT (Fprefix_numeric_value (arg)); | 5958 | EMACS_INT iarg = XINT (Fprefix_numeric_value (arg)); |
| 5882 | 5959 | ||
| 5883 | if (iarg < 0) | 5960 | if (iarg < 0) |
| 5884 | iarg = iarg + lines; | 5961 | iarg = iarg + lines; |
| 5885 | 5962 | ||
| 5886 | #if false /* This code would prevent move-to-window-line from moving point | 5963 | #if false /* This code would prevent move-to-window-line from moving point |
| 5887 | to a place inside the scroll margins (which would cause the | 5964 | to a place inside the scroll margins (which would cause the |
| @@ -5889,19 +5966,20 @@ zero means top of window, negative means relative to bottom of window. */) | |||
| 5889 | it is probably better not to install it. However, it is here | 5966 | it is probably better not to install it. However, it is here |
| 5890 | inside #if false so as not to lose it. -- rms. */ | 5967 | inside #if false so as not to lose it. -- rms. */ |
| 5891 | 5968 | ||
| 5892 | /* Don't let it get into the margin at either top or bottom. */ | 5969 | /* Don't let it get into the margin at either top or bottom. */ |
| 5893 | iarg = max (iarg, this_scroll_margin); | 5970 | iarg = max (iarg, this_scroll_margin); |
| 5894 | iarg = min (iarg, lines - this_scroll_margin - 1); | 5971 | iarg = min (iarg, lines - this_scroll_margin - 1); |
| 5895 | #endif | 5972 | #endif |
| 5896 | 5973 | ||
| 5897 | arg = make_number (iarg); | 5974 | arg = make_number (iarg); |
| 5898 | } | 5975 | } |
| 5899 | 5976 | ||
| 5900 | /* Skip past a partially visible first line. */ | 5977 | /* Skip past a partially visible first line. */ |
| 5901 | if (w->vscroll) | 5978 | if (w->vscroll) |
| 5902 | XSETINT (arg, XINT (arg) + 1); | 5979 | XSETINT (arg, XINT (arg) + 1); |
| 5903 | 5980 | ||
| 5904 | return Fvertical_motion (arg, window, Qnil); | 5981 | return Fvertical_motion (arg, window, Qnil); |
| 5982 | } | ||
| 5905 | } | 5983 | } |
| 5906 | 5984 | ||
| 5907 | 5985 | ||
| @@ -7175,6 +7253,12 @@ syms_of_window (void) | |||
| 7175 | DEFSYM (Qclone_of, "clone-of"); | 7253 | DEFSYM (Qclone_of, "clone-of"); |
| 7176 | DEFSYM (Qfloor, "floor"); | 7254 | DEFSYM (Qfloor, "floor"); |
| 7177 | DEFSYM (Qceiling, "ceiling"); | 7255 | DEFSYM (Qceiling, "ceiling"); |
| 7256 | DEFSYM (Qwindow_start_group_function, "window-start-group-function"); | ||
| 7257 | DEFSYM (Qwindow_end_group_function, "window-end-group-function"); | ||
| 7258 | DEFSYM (Qset_window_start_group_function, "set-window-start-group-function"); | ||
| 7259 | DEFSYM (Qrecenter_group_function, "recenter-group-function"); | ||
| 7260 | DEFSYM (Qpos_visible_in_window_p_group_function, "pos-visible-in-window-p-group-function"); | ||
| 7261 | DEFSYM (Qmove_to_window_line_group_function, "move-to-window-line-group-function"); | ||
| 7178 | 7262 | ||
| 7179 | staticpro (&Vwindow_list); | 7263 | staticpro (&Vwindow_list); |
| 7180 | 7264 | ||
| @@ -7346,6 +7430,72 @@ Note that this optimization can cause the portion of the buffer | |||
| 7346 | displayed after a scrolling operation to be somewhat inaccurate. */); | 7430 | displayed after a scrolling operation to be somewhat inaccurate. */); |
| 7347 | Vfast_but_imprecise_scrolling = false; | 7431 | Vfast_but_imprecise_scrolling = false; |
| 7348 | 7432 | ||
| 7433 | DEFVAR_LISP ("window-start-group-function", Vwindow_start_group_function, | ||
| 7434 | doc: /* Function to call for `window-start' when its GROUP parameter is non-nil. | ||
| 7435 | When this variable contains a function, and `window-start' is called with a | ||
| 7436 | non-nil GROUP parameter, the function is called instead of `window-start''s | ||
| 7437 | normal action. `window-start' passes the function its argument WINDOW, which | ||
| 7438 | might be nil. The function may recursively call `window-start'. */); | ||
| 7439 | Vwindow_start_group_function = Qnil; | ||
| 7440 | Fmake_variable_buffer_local (Qwindow_start_group_function); | ||
| 7441 | Fput (Qwindow_start_group_function, Qpermanent_local, Qt); | ||
| 7442 | |||
| 7443 | DEFVAR_LISP ("window-end-group-function", Vwindow_end_group_function, | ||
| 7444 | doc: /* Function to call for `window-end' if its GROUP parameter is non-nil. | ||
| 7445 | When this variable contains a function, and `window-end' is called with a | ||
| 7446 | non-nil GROUP parameter, the function is called instead of `window-end''s | ||
| 7447 | normal action. `window-end' passes the function its two parameters WINDOW, | ||
| 7448 | and UPDATE. The function may call `window-end' recursively. */); | ||
| 7449 | Vwindow_end_group_function = Qnil; | ||
| 7450 | Fmake_variable_buffer_local (Qwindow_end_group_function); | ||
| 7451 | Fput (Qwindow_end_group_function, Qpermanent_local, Qt); | ||
| 7452 | |||
| 7453 | DEFVAR_LISP ("set-window-start-group-function", | ||
| 7454 | Vset_window_start_group_function, | ||
| 7455 | doc: /* The function to call for `set-window-start' when its GROUP parameter is non-nil. | ||
| 7456 | When this variable contains a function, and `set-window-start' is called | ||
| 7457 | with a non-nil GROUP parameter, the function is called instead of | ||
| 7458 | `set-window-start''s normal action. `set-window-start' passes the function | ||
| 7459 | its three parameters WINDOW, POS, and NOFORCE. The function may call | ||
| 7460 | `set-window-start' recursively. */); | ||
| 7461 | Vset_window_start_group_function = Qnil; | ||
| 7462 | Fmake_variable_buffer_local (Qset_window_start_group_function); | ||
| 7463 | Fput (Qset_window_start_group_function, Qpermanent_local, Qt); | ||
| 7464 | |||
| 7465 | DEFVAR_LISP ("recenter-group-function", Vrecenter_group_function, | ||
| 7466 | doc: /* Function to call for `recenter' when its GROUP parameter is non-nil. | ||
| 7467 | When this variable contains a function, and `recenter' is called with a | ||
| 7468 | non-nil GROUP parameter, the function is called instead of `recenter''s | ||
| 7469 | normal action. `recenter' passes the function its parameter ARG. The | ||
| 7470 | function may call `recenter' recursively. */); | ||
| 7471 | Vrecenter_group_function = Qnil; | ||
| 7472 | Fmake_variable_buffer_local (Qrecenter_group_function); | ||
| 7473 | Fput (Qrecenter_group_function, Qpermanent_local, Qt); | ||
| 7474 | |||
| 7475 | DEFVAR_LISP ("pos-visible-in-window-p-group-function", | ||
| 7476 | Vpos_visible_in_window_p_group_function, | ||
| 7477 | doc: /* Function for `pos-visible-in-window-p' when its GROUP parameter is non-nil. | ||
| 7478 | When this variable contains a function, and `pos-visible-in-window-p' is | ||
| 7479 | called with a non-nil GROUP parameter, the function is called instead of | ||
| 7480 | `pos-visible-in-window-p''s normal action. `pos-visible-in-window-p' | ||
| 7481 | passes the function its three parameters POS, WINDOW, and PARTIALLY. The | ||
| 7482 | function may call `pos-visible-in-window-p' recursively. */); | ||
| 7483 | Vpos_visible_in_window_p_group_function = Qnil; | ||
| 7484 | Fmake_variable_buffer_local (Qpos_visible_in_window_p_group_function); | ||
| 7485 | Fput (Qpos_visible_in_window_p_group_function, Qpermanent_local, Qt); | ||
| 7486 | |||
| 7487 | DEFVAR_LISP ("move-to-window-line-group-function", | ||
| 7488 | Vmove_to_window_line_group_function, | ||
| 7489 | doc: /* Function for `move-to-window-line' when its GROUP parameter is non-nil. | ||
| 7490 | When this variable contains a function, and `move-to-window-line' is | ||
| 7491 | called with a non-nil GROUP parameter, the function is called instead of | ||
| 7492 | `move-to-window-line''s normal action. `move-to-window-line' passes the | ||
| 7493 | function its parameter ARG. The function may call `move-to-window-line' | ||
| 7494 | recursively. */); | ||
| 7495 | Vmove_to_window_line_group_function = Qnil; | ||
| 7496 | Fmake_variable_buffer_local (Qmove_to_window_line_group_function); | ||
| 7497 | Fput (Qmove_to_window_line_group_function, Qpermanent_local, Qt); | ||
| 7498 | |||
| 7349 | defsubr (&Sselected_window); | 7499 | defsubr (&Sselected_window); |
| 7350 | defsubr (&Sminibuffer_window); | 7500 | defsubr (&Sminibuffer_window); |
| 7351 | defsubr (&Swindow_minibuffer_p); | 7501 | defsubr (&Swindow_minibuffer_p); |