changeset 93068:3ca0c43ea37d

(run_funs): New fun. (run_window_configuration_change_hook): Use it to run the buffer-local and the global part of the hook.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Wed, 19 Mar 2008 15:18:30 +0000
parents b14afcccfab6
children 36945fea0cff
files src/ChangeLog src/window.c
diffstat 2 files changed, 52 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Wed Mar 19 15:02:00 2008 +0000
+++ b/src/ChangeLog	Wed Mar 19 15:18:30 2008 +0000
@@ -1,5 +1,9 @@
 2008-03-19  Stefan Monnier  <monnier@iro.umontreal.ca>
 
+	* window.c (run_funs): New fun.
+	(run_window_configuration_change_hook): Use it to run the buffer-local
+	and the global part of the hook.
+
 	* xdisp.c (format_mode_line_unwind_data): Add window argument.
 	(unwind_format_mode_line): Restore selected window.
 	(x_consider_frame_title, Fformat_mode_line): Set selected window.
--- a/src/window.c	Wed Mar 19 15:02:00 2008 +0000
+++ b/src/window.c	Wed Mar 19 15:18:30 2008 +0000
@@ -3306,25 +3306,62 @@
 EXFUN (Fset_window_fringes, 4);
 EXFUN (Fset_window_scroll_bars, 4);
 
+static void
+run_funs (Lisp_Object funs)
+{
+  for (; CONSP (funs); funs = XCDR (funs))
+    if (!EQ (XCAR (funs), Qt))
+      call0 (XCAR (funs));
+}
+
+static Lisp_Object select_window_norecord (Lisp_Object window);
+
 void
 run_window_configuration_change_hook (struct frame *f)
 {
-  /* FIXME: buffer-local values of Vwindow_configuration_change_hook
-     aren't handled properly.  */
-  if (! NILP (Vwindow_configuration_change_hook)
-      && ! NILP (Vrun_hooks))
-    {
       int count = SPECPDL_INDEX ();
+  Lisp_Object frame, global_wcch
+    = Fdefault_value (Qwindow_configuration_change_hook);
+  XSETFRAME (frame, f);
+
+  if (NILP (Vrun_hooks))
+    return;
+
       if (SELECTED_FRAME () != f)
 	{
-	  Lisp_Object frame;
-	  XSETFRAME (frame, f);
 	  record_unwind_protect (Fselect_frame, Fselected_frame ());
 	  Fselect_frame (frame);
 	}
-      call1 (Vrun_hooks, Qwindow_configuration_change_hook);
+
+  /* Use the right buffer.  Matters when running the local hooks.  */
+  if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
+    {
+      record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+      Fset_buffer (Fwindow_buffer (Qnil));
+    }
+
+  /* Look for buffer-local values.  */
+  {
+    Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
+    for (; CONSP (windows); windows = XCDR (windows))
+      {
+	Lisp_Object window = XCAR (windows);
+	Lisp_Object buffer = Fwindow_buffer (window);
+	if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
+				      buffer)))
+	  {
+	    int count = SPECPDL_INDEX ();
+	    record_unwind_protect (select_window_norecord, Fselected_window ());
+	    select_window_norecord (window);
+	    run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
+					   buffer));
       unbind_to (count, Qnil);
     }
+      }
+  }
+  
+  run_funs (global_wcch);
+  unbind_to (count, Qnil);
 }
 
 /* Make WINDOW display BUFFER as its contents.  RUN_HOOKS_P non-zero
@@ -7586,7 +7623,9 @@
   DEFVAR_LISP ("window-configuration-change-hook",
 	       &Vwindow_configuration_change_hook,
 	       doc: /* Functions to call when window configuration changes.
-The selected frame is the one whose configuration has changed.  */);
+The buffer-local part is run once per window, with the relevant window
+selected; while the global part is run only once for the modified frame,
+with the relevant frame selected.  */);
   Vwindow_configuration_change_hook = Qnil;
 
   defsubr (&Sselected_window);