From: Keith David Bershatsky <esq@lawlist.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 22404@debbugs.gnu.org
Subject: bug#22404: 25.1.50; Forcing `window-scroll-functions` to run.
Date: Mon, 15 Feb 2016 19:39:38 -0800 [thread overview]
Message-ID: <697944A7-4633-48EA-910A-C280D1F3ACFF@lawlist.com> (raw)
In-Reply-To: <83ziv6734u.fsf@gnu.org>
[-- Attachment #1: Type: text/plain, Size: 202 bytes --]
Here is the updated draft of the `window_scroll_functions_hook.diff`. A copy of this same patch was attached to 22637 today, but I thought it should be included here also with the 22404.
Keith
[-- Attachment #2: window_start_end_hook.diff --]
[-- Type: application/octet-stream, Size: 13754 bytes --]
diff --git a/src/keyboard.c b/src/keyboard.c
index 3431cd8..3d8d54f 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1233,6 +1233,15 @@ static int read_key_sequence (Lisp_Object *, int, Lisp_Object,
bool, bool, bool, bool);
static void adjust_point_for_property (ptrdiff_t, bool);
+static void
+set_window_start_end_hook (void)
+{
+ Lisp_Object window = (selected_window);
+ struct window *w = decode_live_window (window);
+ w->window_start_end_hook_force = true;
+ w->window_start_end_hook_pending = true;
+}
+
Lisp_Object
command_loop_1 (void)
{
@@ -1258,6 +1267,8 @@ command_loop_1 (void)
if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
safe_run_hooks (Qpost_command_hook);
+ set_window_start_end_hook ();
+
/* If displaying a message, resize the echo area window to fit
that message's size exactly. */
if (!NILP (echo_area_buffer[0]))
@@ -1474,6 +1485,8 @@ command_loop_1 (void)
safe_run_hooks (Qpost_command_hook);
+ set_window_start_end_hook ();
+
/* If displaying a message, resize the echo area window to fit
that message's size exactly. */
if (!NILP (echo_area_buffer[0]))
diff --git a/src/lisp.h b/src/lisp.h
index 8aa2861..0962306 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3913,6 +3913,7 @@ extern void init_eval_once (void);
extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...);
extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object);
extern Lisp_Object safe_call2 (Lisp_Object, Lisp_Object, Lisp_Object);
+extern Lisp_Object safe_call7 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
extern void init_eval (void);
extern void syms_of_eval (void);
extern void unwind_body (Lisp_Object);
diff --git a/src/window.h b/src/window.h
index c29207d..3156927 100644
--- a/src/window.h
+++ b/src/window.h
@@ -348,6 +348,12 @@ struct window
Vwindow_scroll_functions; also by Frecenter with argument. */
bool_bf optional_new_start : 1;
+ /* True means force a call to Vwindow_start_end_hook. */
+ bool_bf window_start_end_hook_force : 1;
+
+ /* True means the hook has not yet run with point fully visible. */
+ bool_bf window_start_end_hook_pending : 1;
+
/* True means the cursor is currently displayed. This can be
set to zero by functions overpainting the cursor image. */
bool_bf phys_cursor_on_p : 1;
diff --git a/src/xdisp.c b/src/xdisp.c
index fed5879..d3e102d 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2618,6 +2618,13 @@ safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
return safe_call (3, fn, arg1, arg2);
}
+/* This is for the `window_start_end_hook'. Call function FN with seven arguments.
+ Return the result or nil if something went wrong. */
+Lisp_Object
+safe_call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7)
+{
+ return safe_call (8, fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+}
\f
/***********************************************************************
@@ -13417,6 +13424,68 @@ do { if (! polling_stopped_here) stop_polling (); \
do { if (polling_stopped_here) start_polling (); \
polling_stopped_here = false; } while (false)
+static void
+run_window_start_end_hook (struct text_pos startp, struct window *w, Lisp_Object window, struct it it, char *string)
+{
+ void *itdata = NULL;
+ bool fully_p = false;
+ EMACS_INT posint = PT;
+ int x, y, rtop, rbot, rowh, vpos, startp_integer, endp, pbol_startp, peol_endp;
+ startp_integer = CHARPOS (startp);
+ struct buffer *buf;
+ buf = XBUFFER (w->contents);
+ if (!NILP (Flocal_variable_p (Qwindow_start_end_hook, Fwindow_buffer (window)))
+ && w->window_start_end_hook_pending)
+ {
+ if ((posint >= CHARPOS (startp) && posint <= BUF_ZV (buf))
+ && CHARPOS (startp) >= BUF_BEGV (buf)
+ && CHARPOS (startp) <= BUF_ZV (buf)
+ && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos))
+ fully_p = !rtop && !rbot;
+ if (fully_p)
+ {
+ CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
+ itdata = bidi_shelve_cache ();
+ start_display (&it, w, startp);
+ move_it_vertically (&it, window_box_height (w));
+ if (it.current_y < it.last_visible_y)
+ move_it_past_eol (&it);
+ endp = (IT_CHARPOS (it));
+ bidi_unshelve_cache (itdata, false);
+ SET_PT (startp_integer);
+ pbol_startp = XINT (Fline_beginning_position (Qnil));
+ SET_PT (endp);
+ peol_endp = XINT (Fline_end_position (Qnil));
+ SET_PT (posint);
+#ifdef GLYPH_DEBUG
+ /* See the doc-string for `pos-visible-in-window-p'. */
+ debug_method_add (w, "%s -- x: %d | y: %d | startp: %d | endp: %d | pbol_startp: %d | peol_endp: %d",
+ string, x, y, startp_integer, endp, pbol_startp, peol_endp);
+#endif
+ /* Reset the flag _before_ calling Lisp, not after, so that
+ if Lisp does signal an error, the flag will be reset, and
+ won't cause the hook to be called ad nauseam. */
+ w->window_start_end_hook_pending = false;
+ /* When calling Lisp from redisplay, always use safe_call, to be
+ protected against errors signaled by that Lisp. */
+ safe_call7 (Qrun_hook_with_args, Qwindow_start_end_hook,
+ window,
+ make_number (startp_integer),
+ make_number (endp),
+ make_number (pbol_startp),
+ make_number (peol_endp),
+ fully_p ? Qt : Qnil);
+ }
+ else
+ {
+#ifdef GLYPH_DEBUG
+ /* See the doc-string for `pos-visible-in-window-p'. */
+ debug_method_add (w, "%s -- x: %d | y: %d | rtop: %d | rbot %d | rowh: %d | vpos: %d",
+ string, x, y, rtop, rbot, rowh, vpos);
+#endif
+ }
+ }
+}
/* Perhaps in the future avoid recentering windows if it
is not necessary; currently that causes some problems. */
@@ -13714,6 +13783,7 @@ redisplay_internal (void)
&& match_p
&& !w->force_start
&& !w->optional_new_start
+ && !w->window_start_end_hook_force
/* Point must be on the line that we have info recorded about. */
&& PT >= CHARPOS (tlbufpos)
&& PT <= Z - CHARPOS (tlendpos)
@@ -15418,6 +15488,8 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
/* Run window scroll functions. */
startp = run_window_scroll_functions (window, startp);
+ run_window_start_end_hook (startp, w, window, it, "try_scrolling");
+
/* Display the window. Give up if new fonts are loaded, or if point
doesn't appear. */
if (!try_window (window, startp, 0))
@@ -16082,6 +16154,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
bool last_line_misfit = false;
ptrdiff_t beg_unchanged, end_unchanged;
int frame_line_height;
+ bool window_start_end_hook_suppress_wsf = false;
SET_TEXT_POS (lpoint, PT, PT_BYTE);
opoint = lpoint;
@@ -16272,13 +16345,16 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
/* If someone specified a new starting point but did not insist,
check whether it can be used. */
- if ((w->optional_new_start || window_frozen_p (w))
+ if ((w->optional_new_start || w->window_start_end_hook_force || window_frozen_p (w))
&& CHARPOS (startp) >= BEGV
&& CHARPOS (startp) <= ZV)
{
+
+ if (w->window_start_end_hook_force && !w->optional_new_start && !window_frozen_p (w) && !w->force_start)
+ window_start_end_hook_suppress_wsf = true;
+
ptrdiff_t it_charpos;
- w->optional_new_start = false;
start_display (&it, w, startp);
move_it_to (&it, PT, 0, it.last_visible_y, -1,
MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
@@ -16299,14 +16375,28 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
w->force_start = true;
#ifdef GLYPH_DEBUG
if (w->force_start)
- {
- if (window_frozen_p (w))
- debug_method_add (w, "set force_start from frozen window start");
- else
- debug_method_add (w, "set force_start from optional_new_start");
- }
+ {
+ if (window_frozen_p (w))
+ {
+ debug_method_add (w, "set force_start from frozen window start");
+ }
+ else if (w->optional_new_start)
+ {
+ debug_method_add (w, "set force_start from optional_new_start");
+ }
+ else if (w->window_start_end_hook_force)
+ {
+ debug_method_add (w, "set force_start from window_start_end_hook_force");
+ }
+ else
+ {
+ debug_method_add (w, "This situation is not yet contemplated.");
+ }
+ }
#endif
}
+ w->optional_new_start = false;
+ w->window_start_end_hook_force = false;
}
force_start:
@@ -16334,11 +16424,18 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
than to get into an infinite loop calling the hook functions
and having them get more errors. */
if (!update_mode_line
- || ! NILP (Vwindow_scroll_functions))
+ || ! NILP (Vwindow_scroll_functions)
+ || ! NILP (Vwindow_start_end_hook))
{
update_mode_line = true;
w->update_mode_line = true;
- startp = run_window_scroll_functions (window, startp);
+
+ /* Run window scroll functions. */
+ if (!window_start_end_hook_suppress_wsf)
+ startp = run_window_scroll_functions (window, startp);
+
+ run_window_start_end_hook (startp, w, window, it, "redisplay_window (force_start)");
+
}
if (CHARPOS (startp) < BEGV)
@@ -16606,6 +16703,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
because a window scroll function can have changed the
buffer. */
|| !NILP (Vwindow_scroll_functions)
+ || !NILP (Vwindow_start_end_hook)
|| MINI_WINDOW_P (w)
|| !(used_current_matrix_p
= try_window_reusing_current_matrix (w)))
@@ -16803,6 +16901,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
/* Run scroll hooks. */
startp = run_window_scroll_functions (window, it.current.pos);
+ run_window_start_end_hook (startp, w, window, it, "redisplay_window (recenter)");
+
/* Redisplay the window. */
bool use_desired_matrix = false;
if (!current_matrix_up_to_date_p
@@ -16811,6 +16911,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
/* Don't use try_window_reusing_current_matrix in this case
because it can have changed the buffer. */
|| !NILP (Vwindow_scroll_functions)
+ || !NILP (Vwindow_start_end_hook)
|| !just_this_one_p
|| MINI_WINDOW_P (w)
|| !(used_current_matrix_p
@@ -16931,7 +17032,17 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
clear_glyph_matrix (w->desired_matrix);
if (1 == try_window (window, it.current.pos,
TRY_WINDOW_CHECK_MARGINS))
- goto done;
+ {
+ if (!NILP (Flocal_variable_p (Qwindow_start_end_hook, Fwindow_buffer (window)))
+ && w->window_start_end_hook_pending)
+ {
+ run_window_start_end_hook (it.current.pos, w, window, it, "redisplay_window (post-recenter)");
+ clear_glyph_matrix (w->desired_matrix);
+ try_window (window, it.current.pos, 0);
+ }
+ goto done;
+ }
+
}
/* If centering point failed to make the whole line visible,
@@ -23686,6 +23797,20 @@ decode_mode_spec (struct window *w, register int c, int field_width,
return "@";
}
+ case 'w':
+ {
+ ptrdiff_t window_start = marker_position (w->start);
+ pint2str (decode_mode_spec_buf, width, window_start);
+ return decode_mode_spec_buf;
+ }
+
+ case 'W':
+ {
+ ptrdiff_t window_end = BUF_Z (b) - w->window_end_pos;
+ pint2str (decode_mode_spec_buf, width, window_end);
+ return decode_mode_spec_buf;
+ }
+
case 'z':
/* coding-system (not including end-of-line format) */
case 'Z':
@@ -31151,6 +31276,7 @@ They are still logged to the *Messages* buffer. */);
DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
DEFSYM (Qoverriding_local_map, "overriding-local-map");
DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
+ DEFSYM (Qwindow_start_end_hook, "window-start-end-hook");
DEFSYM (Qwindow_text_change_functions, "window-text-change-functions");
DEFSYM (Qredisplay_end_trigger_functions, "redisplay-end-trigger-functions");
DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
@@ -31472,6 +31598,13 @@ is scrolled. It is not designed for that, and such use probably won't
work. */);
Vwindow_scroll_functions = Qnil;
+ DEFVAR_LISP ("window-start-end-hook", Vwindow_start_end_hook,
+ doc: /* A bufer-local hook used to obtain new `window-start` and `window-end`
+during redisplay. The function attached to this hook has the following arguments:
+WINDOW, WINDOW-START, WINDOW-END, PBOL-START, PEOL-END, FULLY-P. */);
+ Vwindow_start_end_hook = Qnil;
+ Fmake_variable_buffer_local (Qwindow_start_end_hook);
+
DEFVAR_LISP ("window-text-change-functions",
Vwindow_text_change_functions,
doc: /* Functions to call in redisplay when text in the window might change. */);
next prev parent reply other threads:[~2016-02-16 3:39 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-19 5:49 bug#22404: 25.1.50; Forcing `window-scroll-functions` to run Keith David Bershatsky
2016-01-19 17:50 ` Eli Zaretskii
2016-01-19 18:49 ` Keith David Bershatsky
2016-01-19 19:39 ` Eli Zaretskii
2016-01-19 18:53 ` John Wiegley
2016-01-19 19:26 ` Keith David Bershatsky
2016-01-19 20:35 ` Keith David Bershatsky
2016-01-20 13:34 ` Eli Zaretskii
2016-01-19 23:07 ` Keith David Bershatsky
2016-01-21 2:32 ` Keith David Bershatsky
2016-01-21 17:41 ` Eli Zaretskii
2016-01-21 19:54 ` Keith David Bershatsky
2016-01-21 20:28 ` Eli Zaretskii
2016-01-29 12:00 ` Michael Heerdegen
2016-01-29 14:37 ` Eli Zaretskii
2016-01-29 14:57 ` Michael Heerdegen
2016-01-29 15:33 ` Eli Zaretskii
2016-01-21 21:11 ` Keith David Bershatsky
2016-01-29 2:14 ` John Wiegley
2016-01-29 3:08 ` Keith David Bershatsky
2016-01-29 8:42 ` Eli Zaretskii
2016-01-29 15:54 ` Keith David Bershatsky
2016-02-01 3:50 ` Keith David Bershatsky
2016-02-01 19:54 ` Eli Zaretskii
2016-02-01 13:18 ` Keith David Bershatsky
2016-02-02 16:34 ` Eli Zaretskii
2016-02-02 5:58 ` Keith David Bershatsky
2016-02-02 18:16 ` Keith David Bershatsky
2016-02-02 18:43 ` Eli Zaretskii
2016-02-02 20:00 ` Keith David Bershatsky
2016-02-02 21:05 ` Keith David Bershatsky
2016-02-08 8:51 ` Keith David Bershatsky
2016-02-08 17:17 ` Eli Zaretskii
2016-02-09 16:00 ` Keith David Bershatsky
2016-02-09 17:48 ` Eli Zaretskii
2016-02-12 0:14 ` Keith David Bershatsky
2016-02-12 8:18 ` Eli Zaretskii
2016-02-16 3:39 ` Keith David Bershatsky [this message]
2016-02-22 6:05 ` Keith David Bershatsky
2016-03-11 16:21 ` Keith David Bershatsky
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=697944A7-4633-48EA-910A-C280D1F3ACFF@lawlist.com \
--to=esq@lawlist.com \
--cc=22404@debbugs.gnu.org \
--cc=eliz@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).