aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Mackenzie2015-12-14 16:38:07 +0000
committerAlan Mackenzie2015-12-14 16:38:07 +0000
commite8937de5547a687b6d03199368645f168cb8ad37 (patch)
tree7b974d1ed2470576d1f7649a25b0a0af76eaf4c8 /src
parent3194f1ccd99cfd13ddaf621d6e7f1e1aa1645165 (diff)
downloademacs-e8937de5547a687b6d03199368645f168cb8ad37.tar.gz
emacs-e8937de5547a687b6d03199368645f168cb8ad37.zip
Replace GROUP argument in six window primitives by new functions.
* doc/lispref/windows.texi (Window Start and End, Textual Scrolling) * doc/lispref/positions.texi (Screen Lines): Remove optional GROUP argument from description of six window functions. Add in description of new functions window-group-start, window-group-end, set-window-group-start, pos-visible-in-window-group-p, recenter-group and move-to-window-group-line, together with the six variables indirecting to the pertinent group functions. * src/window.c * src/keyboard.c: Revert the commit from 2015-11-11 12:02:48, in so far as it applies to these two files, which added the GROUP argument to six window primitives. * lisp/follow.el (follow-mode): Use updated variable names for the indirected functions. * lisp/isearch.el (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update): Replace calls to window primitives (e.g. window-start) with a GROUP argument by calls to new functions (e.g. window-group-start). * lisp/ispell.el (ispell-command-loop): Replace call to pos-visible-in-window-p with pos-visible-in-window-group-p. * lisp/window.el (window-group-start, window-group-end) (set-window-group-start, recenter-group, pos-visible-in-window-group-p) (selected-window-group, move-to-window-group-line): New functions. (window-group-start-function, window-group-end-function) (set-window-group-start-function, recenter-group-function) (pos-visible-in-window-group-p-function, selected-window-group-function) (move-to-window-group-line-function): New variables.
Diffstat (limited to 'src')
-rw-r--r--src/keyboard.c2
-rw-r--r--src/window.c772
2 files changed, 312 insertions, 462 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index 725c324eb77..02bc7d2a0b7 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -10658,7 +10658,7 @@ The `posn-' functions access elements of such lists. */)
10658 if (NILP (window)) 10658 if (NILP (window))
10659 window = selected_window; 10659 window = selected_window;
10660 10660
10661 tem = Fpos_visible_in_window_p (pos, window, Qt, Qnil); 10661 tem = Fpos_visible_in_window_p (pos, window, Qt);
10662 if (!NILP (tem)) 10662 if (!NILP (tem))
10663 { 10663 {
10664 Lisp_Object x = XCAR (tem); 10664 Lisp_Object x = XCAR (tem);
diff --git a/src/window.c b/src/window.c
index 1a0163c02e9..9f6b489e74a 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1540,23 +1540,13 @@ 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
1543DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 2, 0, 1543DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1544 doc: /* Return position at which display currently starts in WINDOW. 1544 doc: /* Return position at which display currently starts in WINDOW.
1545WINDOW must be a live window and defaults to the selected one. 1545WINDOW must be a live window and defaults to the selected one.
1546This is updated by redisplay or by calling `set-window-start'. 1546This is updated by redisplay or by calling `set-window-start'. */)
1547 1547 (Lisp_Object window)
1548If GROUP is non-nil, and WINDOW is part of a group of windows collectively
1549displaying a buffer (such as with Follow Mode), return the start position of
1550the 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
1553result, instead of doing its normal processing. */)
1554 (Lisp_Object window, Lisp_Object group)
1555{ 1548{
1556 return (!NILP (group) 1549 return Fmarker_position (decode_live_window (window)->start);
1557 && FUNCTIONP (Vwindow_start_group_function))
1558 ? call1 (Vwindow_start_group_function, window)
1559 : Fmarker_position (decode_live_window (window)->start);
1560} 1550}
1561 1551
1562/* This is text temporarily removed from the doc string below. 1552/* This is text temporarily removed from the doc string below.
@@ -1570,7 +1560,7 @@ have been if redisplay had finished, do this:
1570 (vertical-motion (1- (window-height window)) window) 1560 (vertical-motion (1- (window-height window)) window)
1571 (point))") */ 1561 (point))") */
1572 1562
1573DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 3, 0, 1563DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1574 doc: /* Return position at which display currently ends in WINDOW. 1564 doc: /* Return position at which display currently ends in WINDOW.
1575WINDOW must be a live window and defaults to the selected one. 1565WINDOW must be a live window and defaults to the selected one.
1576This is updated by redisplay, when it runs to completion. 1566This is updated by redisplay, when it runs to completion.
@@ -1579,77 +1569,65 @@ does not update this value.
1579Return nil if there is no recorded value. (This can happen if the 1569Return nil if there is no recorded value. (This can happen if the
1580last redisplay of WINDOW was preempted, and did not finish.) 1570last redisplay of WINDOW was preempted, and did not finish.)
1581If UPDATE is non-nil, compute the up-to-date position 1571If UPDATE is non-nil, compute the up-to-date position
1582if it isn't already recorded. 1572if it isn't already recorded. */)
1583 1573 (Lisp_Object window, Lisp_Object update)
1584If GROUP is non-nil, and WINDOW is part of a group of windows collectively 1574{
1585displaying a buffer (such as with Follow Mode), return the end position of 1575 Lisp_Object value;
1586the group rather than of the individual WINDOW. This condition holds when 1576 struct window *w = decode_live_window (window);
1587`window-end-group-function' is set to a function, in which case `window-end' 1577 Lisp_Object buf;
1588calls the function with the two arguments WINDOW and UPDATE, then returns its 1578 struct buffer *b;
1589result, instead of doing its normal processing. */) 1579
1590 (Lisp_Object window, Lisp_Object update, Lisp_Object group) 1580 buf = w->contents;
1591{ 1581 CHECK_BUFFER (buf);
1592 if (!NILP (group) 1582 b = XBUFFER (buf);
1593 && FUNCTIONP (Vwindow_end_group_function)) 1583
1594 return call2 (Vwindow_end_group_function, window, update); 1584 if (! NILP (update)
1595 { 1585 && (windows_or_buffers_changed
1596 Lisp_Object value; 1586 || !w->window_end_valid
1597 struct window *w = decode_live_window (window); 1587 || b->clip_changed
1598 Lisp_Object buf; 1588 || b->prevent_redisplay_optimizations_p
1599 struct buffer *b; 1589 || window_outdated (w))
1600 1590 /* Don't call display routines if we didn't yet create any real
1601 buf = w->contents; 1591 frames, because the glyph matrices are not yet allocated in
1602 CHECK_BUFFER (buf); 1592 that case. This could happen in some code that runs in the
1603 b = XBUFFER (buf); 1593 daemon during initialization (e.g., see bug#20565). */
1604 1594 && !(noninteractive || FRAME_INITIAL_P (WINDOW_XFRAME (w))))
1605 if (! NILP (update) 1595 {
1606 && (windows_or_buffers_changed 1596 struct text_pos startp;
1607 || !w->window_end_valid 1597 struct it it;
1608 || b->clip_changed 1598 struct buffer *old_buffer = NULL;
1609 || b->prevent_redisplay_optimizations_p 1599 void *itdata = NULL;
1610 || window_outdated (w)) 1600
1611 /* Don't call display routines if we didn't yet create any real 1601 /* Cannot use Fvertical_motion because that function doesn't
1612 frames, because the glyph matrices are not yet allocated in 1602 cope with variable-height lines. */
1613 that case. This could happen in some code that runs in the 1603 if (b != current_buffer)
1614 daemon during initialization (e.g., see bug#20565). */ 1604 {
1615 && !(noninteractive || FRAME_INITIAL_P (WINDOW_XFRAME (w)))) 1605 old_buffer = current_buffer;
1616 { 1606 set_buffer_internal (b);
1617 struct text_pos startp; 1607 }
1618 struct it it;
1619 struct buffer *old_buffer = NULL;
1620 void *itdata = NULL;
1621
1622 /* Cannot use Fvertical_motion because that function doesn't
1623 cope with variable-height lines. */
1624 if (b != current_buffer)
1625 {
1626 old_buffer = current_buffer;
1627 set_buffer_internal (b);
1628 }
1629
1630 /* In case W->start is out of the range, use something
1631 reasonable. This situation occurred when loading a file with
1632 `-l' containing a call to `rmail' with subsequent other
1633 commands. At the end, W->start happened to be BEG, while
1634 rmail had already narrowed the buffer. */
1635 CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
1636
1637 itdata = bidi_shelve_cache ();
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);
1650 1608
1651 return value; 1609 /* In case W->start is out of the range, use something
1652 } 1610 reasonable. This situation occurred when loading a file with
1611 `-l' containing a call to `rmail' with subsequent other
1612 commands. At the end, W->start happened to be BEG, while
1613 rmail had already narrowed the buffer. */
1614 CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
1615
1616 itdata = bidi_shelve_cache ();
1617 start_display (&it, w, startp);
1618 move_it_vertically (&it, window_box_height (w));
1619 if (it.current_y < it.last_visible_y)
1620 move_it_past_eol (&it);
1621 value = make_number (IT_CHARPOS (it));
1622 bidi_unshelve_cache (itdata, false);
1623
1624 if (old_buffer)
1625 set_buffer_internal (old_buffer);
1626 }
1627 else
1628 XSETINT (value, BUF_Z (b) - w->window_end_pos);
1629
1630 return value;
1653} 1631}
1654 1632
1655DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0, 1633DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
@@ -1688,43 +1666,30 @@ Return POS. */)
1688 return pos; 1666 return pos;
1689} 1667}
1690 1668
1691DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 4, 0, 1669DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1692 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer. 1670 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1693WINDOW must be a live window and defaults to the selected one. Return 1671WINDOW must be a live window and defaults to the selected one. Return
1694POS. Optional third arg NOFORCE non-nil inhibits next redisplay from 1672POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
1695overriding motion of point in order to display at this exact start. 1673overriding motion of point in order to display at this exact start. */)
1696 1674 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1697If GROUP is non-nil, and WINDOW is part of a group of windows collectively 1675{
1698displaying a buffer (such as with Follow Mode), set the start position of 1676 register struct window *w = decode_live_window (window);
1699the 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,
1702and NOFORCE, then returns its result, instead of doing its normal
1703processing. */)
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);
1711 1677
1712 set_marker_restricted (w->start, pos, w->contents); 1678 set_marker_restricted (w->start, pos, w->contents);
1713 /* This is not right, but much easier than doing what is right. */ 1679 /* This is not right, but much easier than doing what is right. */
1714 w->start_at_line_beg = false; 1680 w->start_at_line_beg = false;
1715 if (NILP (noforce)) 1681 if (NILP (noforce))
1716 w->force_start = true; 1682 w->force_start = true;
1717 wset_update_mode_line (w); 1683 wset_update_mode_line (w);
1718 /* Bug#15957. */ 1684 /* Bug#15957. */
1719 w->window_end_valid = false; 1685 w->window_end_valid = false;
1720 wset_redisplay (w); 1686 wset_redisplay (w);
1721 1687
1722 return pos; 1688 return pos;
1723 }
1724} 1689}
1725 1690
1726DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 1691DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1727 Spos_visible_in_window_p, 0, 4, 0, 1692 Spos_visible_in_window_p, 0, 3, 0,
1728 doc: /* Return non-nil if position POS is currently on the frame in WINDOW. 1693 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1729WINDOW must be a live window and defaults to the selected one. 1694WINDOW must be a live window and defaults to the selected one.
1730 1695
@@ -1744,21 +1709,9 @@ of the window. The remaining elements are omitted if the character after
1744POS is fully visible; otherwise, RTOP and RBOT are the number of pixels 1709POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1745off-window at the top and bottom of the screen line ("row") containing 1710off-window at the top and bottom of the screen line ("row") containing
1746POS, ROWH is the visible height of that row, and VPOS is the row number 1711POS, ROWH is the visible height of that row, and VPOS is the row number
1747(zero-based). 1712(zero-based). */)
1748 1713 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1749If GROUP is non-nil, and WINDOW is part of a group of windows collectively 1714{
1750displaying a buffer (such as with Follow Mode), test whether POS is visible
1751in the group of windows rather than in the individual WINDOW. This
1752condition holds when `pos-visible-in-window-p-function' is set to a
1753function, in which case `pos-visible-in-window-p' calls the function with
1754the three arguments POS, WINDOW, and PARTIALLY, then returns its result,
1755instead 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 {
1762 struct window *w; 1715 struct window *w;
1763 EMACS_INT posint; 1716 EMACS_INT posint;
1764 struct buffer *buf; 1717 struct buffer *buf;
@@ -1807,7 +1760,6 @@ instead of doing its normal processing. */)
1807 } 1760 }
1808 1761
1809 return in_window; 1762 return in_window;
1810 }
1811} 1763}
1812 1764
1813DEFUN ("window-line-height", Fwindow_line_height, 1765DEFUN ("window-line-height", Fwindow_line_height,
@@ -5205,7 +5157,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
5205 } 5157 }
5206 5158
5207 XSETFASTINT (tem, PT); 5159 XSETFASTINT (tem, PT);
5208 tem = Fpos_visible_in_window_p (tem, window, Qnil, Qnil); 5160 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5209 5161
5210 if (NILP (tem)) 5162 if (NILP (tem))
5211 { 5163 {
@@ -5594,7 +5546,7 @@ displayed_window_lines (struct window *w)
5594} 5546}
5595 5547
5596 5548
5597DEFUN ("recenter", Frecenter, Srecenter, 0, 2, "P\ni", 5549DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5598 doc: /* Center point in selected window and maybe redisplay frame. 5550 doc: /* Center point in selected window and maybe redisplay frame.
5599With a numeric prefix argument ARG, recenter putting point on screen line ARG 5551With a numeric prefix argument ARG, recenter putting point on screen line ARG
5600relative to the selected window. If ARG is negative, it counts up from the 5552relative to the selected window. If ARG is negative, it counts up from the
@@ -5608,221 +5560,208 @@ height needed); if `recenter-redisplay' has the special value `tty',
5608then only tty frames are redrawn. 5560then only tty frames are redrawn.
5609 5561
5610Just C-u as prefix means put point in the center of the window 5562Just C-u as prefix means put point in the center of the window
5611and redisplay normally--don't erase and redraw the frame. 5563and redisplay normally--don't erase and redraw the frame. */)
5612 5564 (register Lisp_Object arg)
5613When `recenter' is called from a program, GROUP is non-nil, and WINDOW is 5565{
5614part of a group of windows collectively displaying a buffer (such as with 5566 struct window *w = XWINDOW (selected_window);
5615Follow Mode), perform `recenter''s actions on the group rather than on the 5567 struct buffer *buf = XBUFFER (w->contents);
5616individual WINDOW. This condition holds when `recenter-group-function' is 5568 bool center_p = false;
5617set to a function, in which case `recenter' calls the function with the 5569 ptrdiff_t charpos, bytepos;
5618argument ARG, then returns its value, instead of doing its normal 5570 EMACS_INT iarg IF_LINT (= 0);
5619processing. */) 5571 int this_scroll_margin;
5620 (register Lisp_Object arg, Lisp_Object group)
5621{
5622 if (!NILP (group)
5623 && FUNCTIONP (Vrecenter_group_function))
5624 return call1 (Vrecenter_group_function, arg);
5625 {
5626 struct window *w = XWINDOW (selected_window);
5627 struct buffer *buf = XBUFFER (w->contents);
5628 bool center_p = false;
5629 ptrdiff_t charpos, bytepos;
5630 EMACS_INT iarg IF_LINT (= 0);
5631 int this_scroll_margin;
5632 5572
5633 if (buf != current_buffer) 5573 if (buf != current_buffer)
5634 error ("`recenter'ing a window that does not display current-buffer."); 5574 error ("`recenter'ing a window that does not display current-buffer.");
5635 5575
5636 /* If redisplay is suppressed due to an error, try again. */ 5576 /* If redisplay is suppressed due to an error, try again. */
5637 buf->display_error_modiff = 0; 5577 buf->display_error_modiff = 0;
5638 5578
5639 if (NILP (arg)) 5579 if (NILP (arg))
5640 { 5580 {
5641 if (!NILP (Vrecenter_redisplay) 5581 if (!NILP (Vrecenter_redisplay)
5642 && (!EQ (Vrecenter_redisplay, Qtty) 5582 && (!EQ (Vrecenter_redisplay, Qtty)
5643 || !NILP (Ftty_type (selected_frame)))) 5583 || !NILP (Ftty_type (selected_frame))))
5644 { 5584 {
5645 ptrdiff_t i; 5585 ptrdiff_t i;
5646 5586
5647 /* Invalidate pixel data calculated for all compositions. */ 5587 /* Invalidate pixel data calculated for all compositions. */
5648 for (i = 0; i < n_compositions; i++) 5588 for (i = 0; i < n_compositions; i++)
5649 composition_table[i]->font = NULL; 5589 composition_table[i]->font = NULL;
5650#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS) 5590#if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
5651 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1; 5591 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5652#endif 5592#endif
5653 Fredraw_frame (WINDOW_FRAME (w)); 5593 Fredraw_frame (WINDOW_FRAME (w));
5654 SET_FRAME_GARBAGED (WINDOW_XFRAME (w)); 5594 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5655 } 5595 }
5656 5596
5657 center_p = true;
5658 }
5659 else if (CONSP (arg)) /* Just C-u. */
5660 center_p = true; 5597 center_p = true;
5661 else 5598 }
5662 { 5599 else if (CONSP (arg)) /* Just C-u. */
5663 arg = Fprefix_numeric_value (arg); 5600 center_p = true;
5664 CHECK_NUMBER (arg); 5601 else
5665 iarg = XINT (arg); 5602 {
5666 } 5603 arg = Fprefix_numeric_value (arg);
5604 CHECK_NUMBER (arg);
5605 iarg = XINT (arg);
5606 }
5667 5607
5668 /* Do this after making BUF current 5608 /* Do this after making BUF current
5669 in case scroll_margin is buffer-local. */ 5609 in case scroll_margin is buffer-local. */
5670 this_scroll_margin 5610 this_scroll_margin
5671 = max (0, min (scroll_margin, w->total_lines / 4)); 5611 = max (0, min (scroll_margin, w->total_lines / 4));
5672 5612
5673 /* Don't use redisplay code for initial frames, as the necessary 5613 /* Don't use redisplay code for initial frames, as the necessary
5674 data structures might not be set up yet then. */ 5614 data structures might not be set up yet then. */
5675 if (!FRAME_INITIAL_P (XFRAME (w->frame))) 5615 if (!FRAME_INITIAL_P (XFRAME (w->frame)))
5676 { 5616 {
5677 if (center_p) 5617 if (center_p)
5678 { 5618 {
5679 struct it it; 5619 struct it it;
5680 struct text_pos pt; 5620 struct text_pos pt;
5681 void *itdata = bidi_shelve_cache (); 5621 void *itdata = bidi_shelve_cache ();
5682 5622
5683 SET_TEXT_POS (pt, PT, PT_BYTE); 5623 SET_TEXT_POS (pt, PT, PT_BYTE);
5684 start_display (&it, w, pt); 5624 start_display (&it, w, pt);
5685 move_it_vertically_backward (&it, window_box_height (w) / 2); 5625 move_it_vertically_backward (&it, window_box_height (w) / 2);
5686 charpos = IT_CHARPOS (it); 5626 charpos = IT_CHARPOS (it);
5687 bytepos = IT_BYTEPOS (it); 5627 bytepos = IT_BYTEPOS (it);
5688 bidi_unshelve_cache (itdata, false); 5628 bidi_unshelve_cache (itdata, false);
5689 } 5629 }
5690 else if (iarg < 0) 5630 else if (iarg < 0)
5691 { 5631 {
5692 struct it it; 5632 struct it it;
5693 struct text_pos pt; 5633 struct text_pos pt;
5694 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg); 5634 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
5695 int extra_line_spacing; 5635 int extra_line_spacing;
5696 int h = window_box_height (w); 5636 int h = window_box_height (w);
5697 int ht = window_internal_height (w); 5637 int ht = window_internal_height (w);
5698 void *itdata = bidi_shelve_cache (); 5638 void *itdata = bidi_shelve_cache ();
5699 5639
5700 nlines = clip_to_bounds (this_scroll_margin + 1, nlines, 5640 nlines = clip_to_bounds (this_scroll_margin + 1, nlines,
5701 ht - this_scroll_margin); 5641 ht - this_scroll_margin);
5702 5642
5703 SET_TEXT_POS (pt, PT, PT_BYTE); 5643 SET_TEXT_POS (pt, PT, PT_BYTE);
5704 start_display (&it, w, pt); 5644 start_display (&it, w, pt);
5705 5645
5706 /* Be sure we have the exact height of the full line containing PT. */ 5646 /* Be sure we have the exact height of the full line containing PT. */
5707 move_it_by_lines (&it, 0); 5647 move_it_by_lines (&it, 0);
5708 5648
5709 /* The amount of pixels we have to move back is the window 5649 /* The amount of pixels we have to move back is the window
5710 height minus what's displayed in the line containing PT, 5650 height minus what's displayed in the line containing PT,
5711 and the lines below. */ 5651 and the lines below. */
5712 it.current_y = 0; 5652 it.current_y = 0;
5713 it.vpos = 0; 5653 it.vpos = 0;
5714 move_it_by_lines (&it, nlines); 5654 move_it_by_lines (&it, nlines);
5715
5716 if (it.vpos == nlines)
5717 h -= it.current_y;
5718 else
5719 {
5720 /* Last line has no newline. */
5721 h -= line_bottom_y (&it);
5722 it.vpos++;
5723 }
5724
5725 /* Don't reserve space for extra line spacing of last line. */
5726 extra_line_spacing = it.max_extra_line_spacing;
5727
5728 /* If we can't move down NLINES lines because we hit
5729 the end of the buffer, count in some empty lines. */
5730 if (it.vpos < nlines)
5731 {
5732 nlines -= it.vpos;
5733 extra_line_spacing = it.extra_line_spacing;
5734 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5735 }
5736 if (h <= 0)
5737 {
5738 bidi_unshelve_cache (itdata, false);
5739 return Qnil;
5740 }
5741
5742 /* Now find the new top line (starting position) of the window. */
5743 start_display (&it, w, pt);
5744 it.current_y = 0;
5745 move_it_vertically_backward (&it, h);
5746
5747 /* If extra line spacing is present, we may move too far
5748 back. This causes the last line to be only partially
5749 visible (which triggers redisplay to recenter that line
5750 in the middle), so move forward.
5751 But ignore extra line spacing on last line, as it is not
5752 considered to be part of the visible height of the line.
5753 */
5754 h += extra_line_spacing;
5755 while (-it.current_y > h)
5756 move_it_by_lines (&it, 1);
5757
5758 charpos = IT_CHARPOS (it);
5759 bytepos = IT_BYTEPOS (it);
5760
5761 bidi_unshelve_cache (itdata, false);
5762 }
5763 else
5764 {
5765 struct it it;
5766 struct text_pos pt;
5767 ptrdiff_t nlines = min (PTRDIFF_MAX, iarg);
5768 int ht = window_internal_height (w);
5769 void *itdata = bidi_shelve_cache ();
5770
5771 nlines = clip_to_bounds (this_scroll_margin, nlines,
5772 ht - this_scroll_margin - 1);
5773
5774 SET_TEXT_POS (pt, PT, PT_BYTE);
5775 start_display (&it, w, pt);
5776
5777 /* Move to the beginning of screen line containing PT. */
5778 move_it_by_lines (&it, 0);
5779
5780 /* Move back to find the point which is ARG screen lines above PT. */
5781 if (nlines > 0)
5782 {
5783 it.current_y = 0;
5784 it.vpos = 0;
5785 move_it_by_lines (&it, -nlines);
5786 }
5787
5788 charpos = IT_CHARPOS (it);
5789 bytepos = IT_BYTEPOS (it);
5790
5791 bidi_unshelve_cache (itdata, false);
5792 }
5793 }
5794 else
5795 {
5796 struct position pos;
5797 int ht = window_internal_height (w);
5798 5655
5799 if (center_p) 5656 if (it.vpos == nlines)
5800 iarg = ht / 2; 5657 h -= it.current_y;
5801 else if (iarg < 0) 5658 else
5802 iarg += ht; 5659 {
5660 /* Last line has no newline. */
5661 h -= line_bottom_y (&it);
5662 it.vpos++;
5663 }
5803 5664
5804 /* Don't let it get into the margin at either top or bottom. */ 5665 /* Don't reserve space for extra line spacing of last line. */
5805 iarg = clip_to_bounds (this_scroll_margin, iarg, 5666 extra_line_spacing = it.max_extra_line_spacing;
5806 ht - this_scroll_margin - 1);
5807 5667
5808 pos = *vmotion (PT, PT_BYTE, - iarg, w); 5668 /* If we can't move down NLINES lines because we hit
5809 charpos = pos.bufpos; 5669 the end of the buffer, count in some empty lines. */
5810 bytepos = pos.bytepos; 5670 if (it.vpos < nlines)
5811 } 5671 {
5672 nlines -= it.vpos;
5673 extra_line_spacing = it.extra_line_spacing;
5674 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5675 }
5676 if (h <= 0)
5677 {
5678 bidi_unshelve_cache (itdata, false);
5679 return Qnil;
5680 }
5812 5681
5813 /* Set the new window start. */ 5682 /* Now find the new top line (starting position) of the window. */
5814 set_marker_both (w->start, w->contents, charpos, bytepos); 5683 start_display (&it, w, pt);
5815 w->window_end_valid = false; 5684 it.current_y = 0;
5685 move_it_vertically_backward (&it, h);
5686
5687 /* If extra line spacing is present, we may move too far
5688 back. This causes the last line to be only partially
5689 visible (which triggers redisplay to recenter that line
5690 in the middle), so move forward.
5691 But ignore extra line spacing on last line, as it is not
5692 considered to be part of the visible height of the line.
5693 */
5694 h += extra_line_spacing;
5695 while (-it.current_y > h)
5696 move_it_by_lines (&it, 1);
5816 5697
5817 w->optional_new_start = true; 5698 charpos = IT_CHARPOS (it);
5699 bytepos = IT_BYTEPOS (it);
5818 5700
5819 w->start_at_line_beg = (bytepos == BEGV_BYTE 5701 bidi_unshelve_cache (itdata, false);
5820 || FETCH_BYTE (bytepos - 1) == '\n'); 5702 }
5703 else
5704 {
5705 struct it it;
5706 struct text_pos pt;
5707 ptrdiff_t nlines = min (PTRDIFF_MAX, iarg);
5708 int ht = window_internal_height (w);
5709 void *itdata = bidi_shelve_cache ();
5821 5710
5822 wset_redisplay (w); 5711 nlines = clip_to_bounds (this_scroll_margin, nlines,
5712 ht - this_scroll_margin - 1);
5823 5713
5824 return Qnil; 5714 SET_TEXT_POS (pt, PT, PT_BYTE);
5825 } 5715 start_display (&it, w, pt);
5716
5717 /* Move to the beginning of screen line containing PT. */
5718 move_it_by_lines (&it, 0);
5719
5720 /* Move back to find the point which is ARG screen lines above PT. */
5721 if (nlines > 0)
5722 {
5723 it.current_y = 0;
5724 it.vpos = 0;
5725 move_it_by_lines (&it, -nlines);
5726 }
5727
5728 charpos = IT_CHARPOS (it);
5729 bytepos = IT_BYTEPOS (it);
5730
5731 bidi_unshelve_cache (itdata, false);
5732 }
5733 }
5734 else
5735 {
5736 struct position pos;
5737 int ht = window_internal_height (w);
5738
5739 if (center_p)
5740 iarg = ht / 2;
5741 else if (iarg < 0)
5742 iarg += ht;
5743
5744 /* Don't let it get into the margin at either top or bottom. */
5745 iarg = clip_to_bounds (this_scroll_margin, iarg,
5746 ht - this_scroll_margin - 1);
5747
5748 pos = *vmotion (PT, PT_BYTE, - iarg, w);
5749 charpos = pos.bufpos;
5750 bytepos = pos.bytepos;
5751 }
5752
5753 /* Set the new window start. */
5754 set_marker_both (w->start, w->contents, charpos, bytepos);
5755 w->window_end_valid = false;
5756
5757 w->optional_new_start = true;
5758
5759 w->start_at_line_beg = (bytepos == BEGV_BYTE
5760 || FETCH_BYTE (bytepos - 1) == '\n');
5761
5762 wset_redisplay (w);
5763
5764 return Qnil;
5826} 5765}
5827 5766
5828DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width, 5767DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
@@ -5869,68 +5808,52 @@ pixels. */)
5869} 5808}
5870 5809
5871DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line, 5810DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5872 1, 2, "P\ni", 5811 1, 1, "P",
5873 doc: /* Position point relative to window. 5812 doc: /* Position point relative to window.
5874ARG nil means position point at center of window. 5813ARG nil means position point at center of window.
5875Else, ARG specifies vertical position within the window; 5814Else, ARG specifies vertical position within the window;
5876zero means top of window, negative means relative to bottom of window. 5815zero means top of window, negative means relative to bottom of window. */)
5877 5816 (Lisp_Object arg)
5878When GROUP is non-nil, and `move-to-window-line-group-function' is set to a 5817{
5879function, then instead of the above, that function is called with the 5818 struct window *w = XWINDOW (selected_window);
5880single argument ARG, and its result returned. 5819 int lines, start;
5881 5820 Lisp_Object window;
5882If GROUP is non-nil, and WINDOW is part of a group of windows collectively
5883displaying a buffer (such as with Follow Mode), position point relative to
5884the group of windows as a whole rather than the individual WINDOW. This
5885condition holds when `move-to-window-line-group-function' is set to a
5886function, in which case `move-to-window-line' calls the function with the
5887argument ARG, then returns its result, instead of doing its normal
5888processing. */)
5889 (Lisp_Object arg, Lisp_Object group)
5890{
5891 if (!NILP (group)
5892 && FUNCTIONP (Vmove_to_window_line_group_function))
5893 return call1 (Vmove_to_window_line_group_function, arg);
5894 {
5895 struct window *w = XWINDOW (selected_window);
5896 int lines, start;
5897 Lisp_Object window;
5898#if false 5821#if false
5899 int this_scroll_margin; 5822 int this_scroll_margin;
5900#endif 5823#endif
5901 5824
5902 if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer)) 5825 if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer))
5903 /* This test is needed to make sure PT/PT_BYTE make sense in w->contents 5826 /* This test is needed to make sure PT/PT_BYTE make sense in w->contents
5904 when passed below to set_marker_both. */ 5827 when passed below to set_marker_both. */
5905 error ("move-to-window-line called from unrelated buffer"); 5828 error ("move-to-window-line called from unrelated buffer");
5906 5829
5907 window = selected_window; 5830 window = selected_window;
5908 start = marker_position (w->start); 5831 start = marker_position (w->start);
5909 if (start < BEGV || start > ZV) 5832 if (start < BEGV || start > ZV)
5910 { 5833 {
5911 int height = window_internal_height (w); 5834 int height = window_internal_height (w);
5912 Fvertical_motion (make_number (- (height / 2)), window, Qnil); 5835 Fvertical_motion (make_number (- (height / 2)), window, Qnil);
5913 set_marker_both (w->start, w->contents, PT, PT_BYTE); 5836 set_marker_both (w->start, w->contents, PT, PT_BYTE);
5914 w->start_at_line_beg = !NILP (Fbolp ()); 5837 w->start_at_line_beg = !NILP (Fbolp ());
5915 w->force_start = true; 5838 w->force_start = true;
5916 } 5839 }
5917 else 5840 else
5918 Fgoto_char (w->start); 5841 Fgoto_char (w->start);
5919 5842
5920 lines = displayed_window_lines (w); 5843 lines = displayed_window_lines (w);
5921 5844
5922#if false 5845#if false
5923 this_scroll_margin = max (0, min (scroll_margin, lines / 4)); 5846 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
5924#endif 5847#endif
5925 5848
5926 if (NILP (arg)) 5849 if (NILP (arg))
5927 XSETFASTINT (arg, lines / 2); 5850 XSETFASTINT (arg, lines / 2);
5928 else 5851 else
5929 { 5852 {
5930 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg)); 5853 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
5931 5854
5932 if (iarg < 0) 5855 if (iarg < 0)
5933 iarg = iarg + lines; 5856 iarg = iarg + lines;
5934 5857
5935#if false /* This code would prevent move-to-window-line from moving point 5858#if false /* This code would prevent move-to-window-line from moving point
5936 to a place inside the scroll margins (which would cause the 5859 to a place inside the scroll margins (which would cause the
@@ -5938,20 +5861,19 @@ processing. */)
5938 it is probably better not to install it. However, it is here 5861 it is probably better not to install it. However, it is here
5939 inside #if false so as not to lose it. -- rms. */ 5862 inside #if false so as not to lose it. -- rms. */
5940 5863
5941 /* Don't let it get into the margin at either top or bottom. */ 5864 /* Don't let it get into the margin at either top or bottom. */
5942 iarg = max (iarg, this_scroll_margin); 5865 iarg = max (iarg, this_scroll_margin);
5943 iarg = min (iarg, lines - this_scroll_margin - 1); 5866 iarg = min (iarg, lines - this_scroll_margin - 1);
5944#endif 5867#endif
5945 5868
5946 arg = make_number (iarg); 5869 arg = make_number (iarg);
5947 } 5870 }
5948 5871
5949 /* Skip past a partially visible first line. */ 5872 /* Skip past a partially visible first line. */
5950 if (w->vscroll) 5873 if (w->vscroll)
5951 XSETINT (arg, XINT (arg) + 1); 5874 XSETINT (arg, XINT (arg) + 1);
5952 5875
5953 return Fvertical_motion (arg, window, Qnil); 5876 return Fvertical_motion (arg, window, Qnil);
5954 }
5955} 5877}
5956 5878
5957 5879
@@ -7225,12 +7147,6 @@ syms_of_window (void)
7225 DEFSYM (Qclone_of, "clone-of"); 7147 DEFSYM (Qclone_of, "clone-of");
7226 DEFSYM (Qfloor, "floor"); 7148 DEFSYM (Qfloor, "floor");
7227 DEFSYM (Qceiling, "ceiling"); 7149 DEFSYM (Qceiling, "ceiling");
7228 DEFSYM (Qwindow_start_group_function, "window-start-group-function");
7229 DEFSYM (Qwindow_end_group_function, "window-end-group-function");
7230 DEFSYM (Qset_window_start_group_function, "set-window-start-group-function");
7231 DEFSYM (Qrecenter_group_function, "recenter-group-function");
7232 DEFSYM (Qpos_visible_in_window_p_group_function, "pos-visible-in-window-p-group-function");
7233 DEFSYM (Qmove_to_window_line_group_function, "move-to-window-line-group-function");
7234 7150
7235 staticpro (&Vwindow_list); 7151 staticpro (&Vwindow_list);
7236 7152
@@ -7402,72 +7318,6 @@ Note that this optimization can cause the portion of the buffer
7402displayed after a scrolling operation to be somewhat inaccurate. */); 7318displayed after a scrolling operation to be somewhat inaccurate. */);
7403 Vfast_but_imprecise_scrolling = false; 7319 Vfast_but_imprecise_scrolling = false;
7404 7320
7405 DEFVAR_LISP ("window-start-group-function", Vwindow_start_group_function,
7406 doc: /* Function to call for `window-start' when its GROUP parameter is non-nil.
7407When this variable contains a function, and `window-start' is called with a
7408non-nil GROUP parameter, the function is called instead of `window-start''s
7409normal action. `window-start' passes the function its argument WINDOW, which
7410might be nil. The function may recursively call `window-start'. */);
7411 Vwindow_start_group_function = Qnil;
7412 Fmake_variable_buffer_local (Qwindow_start_group_function);
7413 Fput (Qwindow_start_group_function, Qpermanent_local, Qt);
7414
7415 DEFVAR_LISP ("window-end-group-function", Vwindow_end_group_function,
7416 doc: /* Function to call for `window-end' if its GROUP parameter is non-nil.
7417When this variable contains a function, and `window-end' is called with a
7418non-nil GROUP parameter, the function is called instead of `window-end''s
7419normal action. `window-end' passes the function its two parameters WINDOW,
7420and UPDATE. The function may call `window-end' recursively. */);
7421 Vwindow_end_group_function = Qnil;
7422 Fmake_variable_buffer_local (Qwindow_end_group_function);
7423 Fput (Qwindow_end_group_function, Qpermanent_local, Qt);
7424
7425 DEFVAR_LISP ("set-window-start-group-function",
7426 Vset_window_start_group_function,
7427 doc: /* The function to call for `set-window-start' when its GROUP parameter is non-nil.
7428When this variable contains a function, and `set-window-start' is called
7429with a non-nil GROUP parameter, the function is called instead of
7430`set-window-start''s normal action. `set-window-start' passes the function
7431its three parameters WINDOW, POS, and NOFORCE. The function may call
7432`set-window-start' recursively. */);
7433 Vset_window_start_group_function = Qnil;
7434 Fmake_variable_buffer_local (Qset_window_start_group_function);
7435 Fput (Qset_window_start_group_function, Qpermanent_local, Qt);
7436
7437 DEFVAR_LISP ("recenter-group-function", Vrecenter_group_function,
7438 doc: /* Function to call for `recenter' when its GROUP parameter is non-nil.
7439When this variable contains a function, and `recenter' is called with a
7440non-nil GROUP parameter, the function is called instead of `recenter''s
7441normal action. `recenter' passes the function its parameter ARG. The
7442function may call `recenter' recursively. */);
7443 Vrecenter_group_function = Qnil;
7444 Fmake_variable_buffer_local (Qrecenter_group_function);
7445 Fput (Qrecenter_group_function, Qpermanent_local, Qt);
7446
7447 DEFVAR_LISP ("pos-visible-in-window-p-group-function",
7448 Vpos_visible_in_window_p_group_function,
7449 doc: /* Function for `pos-visible-in-window-p' when its GROUP parameter is non-nil.
7450When this variable contains a function, and `pos-visible-in-window-p' is
7451called with a non-nil GROUP parameter, the function is called instead of
7452`pos-visible-in-window-p''s normal action. `pos-visible-in-window-p'
7453passes the function its three parameters POS, WINDOW, and PARTIALLY. The
7454function may call `pos-visible-in-window-p' recursively. */);
7455 Vpos_visible_in_window_p_group_function = Qnil;
7456 Fmake_variable_buffer_local (Qpos_visible_in_window_p_group_function);
7457 Fput (Qpos_visible_in_window_p_group_function, Qpermanent_local, Qt);
7458
7459 DEFVAR_LISP ("move-to-window-line-group-function",
7460 Vmove_to_window_line_group_function,
7461 doc: /* Function for `move-to-window-line' when its GROUP parameter is non-nil.
7462When this variable contains a function, and `move-to-window-line' is
7463called with a non-nil GROUP parameter, the function is called instead of
7464`move-to-window-line''s normal action. `move-to-window-line' passes the
7465function its parameter ARG. The function may call `move-to-window-line'
7466recursively. */);
7467 Vmove_to_window_line_group_function = Qnil;
7468 Fmake_variable_buffer_local (Qmove_to_window_line_group_function);
7469 Fput (Qmove_to_window_line_group_function, Qpermanent_local, Qt);
7470
7471 defsubr (&Sselected_window); 7321 defsubr (&Sselected_window);
7472 defsubr (&Sminibuffer_window); 7322 defsubr (&Sminibuffer_window);
7473 defsubr (&Swindow_minibuffer_p); 7323 defsubr (&Swindow_minibuffer_p);