unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
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.  */);

  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).