=== modified file 'lisp/emacs-lisp/debug.el' --- lisp/emacs-lisp/debug.el 2012-01-19 07:21:25 +0000 +++ lisp/emacs-lisp/debug.el 2012-02-26 18:55:02 +0000 @@ -194,7 +194,8 @@ ;; Place an extra debug-on-exit for macro's. (when (eq 'lambda (car-safe (cadr (backtrace-frame 4)))) (backtrace-debug 5 t))) - (pop-to-buffer debugger-buffer) + (pop-to-buffer + debugger-buffer '((display-buffer-reuse-window display-buffer-in-previous-window) . nil)) (debugger-mode) (debugger-setup-buffer debugger-args) (when noninteractive @@ -245,7 +246,8 @@ ;; best to do that. (bury-buffer)))) (unless debugger-previous-state - (kill-buffer debugger-buffer))) + ;; (kill-buffer debugger-buffer) + )) ;; Restore the previous state of the debugger-buffer, in case we were ;; in a recursive invocation of the debugger. (when (buffer-live-p debugger-buffer) === modified file 'lisp/window.el' --- lisp/window.el 2012-02-12 05:10:30 +0000 +++ lisp/window.el 2012-02-26 19:09:54 +0000 @@ -2482,69 +2482,6 @@ ;;; Windows and buffers. -;; `prev-buffers' and `next-buffers' are two reserved window slots used -;; for (1) determining which buffer to show in the window when its -;; buffer shall be buried or killed and (2) which buffer to show for -;; `switch-to-prev-buffer' and `switch-to-next-buffer'. - -;; `prev-buffers' consists of -;; triples. The entries on this list are ordered by the time their -;; buffer has been removed from the window, the most recently removed -;; buffer's entry being first. The window-start and window-point -;; components are `window-start' and `window-point' at the time the -;; buffer was removed from the window which implies that the entry must -;; be added when `set-window-buffer' removes the buffer from the window. - -;; `next-buffers' is the list of buffers that have been replaced -;; recently by `switch-to-prev-buffer'. These buffers are the least -;; preferred candidates of `switch-to-prev-buffer' and the preferred -;; candidates of `switch-to-next-buffer' to switch to. This list is -;; reset to nil by any action changing the window's buffer with the -;; exception of `switch-to-prev-buffer' and `switch-to-next-buffer'. -;; `switch-to-prev-buffer' pushes the buffer it just replaced on it, -;; `switch-to-next-buffer' pops the last pushed buffer from it. - -;; Both `prev-buffers' and `next-buffers' may reference killed buffers -;; if such a buffer was killed while the window was hidden within a -;; window configuration. Such killed buffers get removed whenever -;; `switch-to-prev-buffer' or `switch-to-next-buffer' encounter them. - -;; The following function is called by `set-window-buffer' _before_ it -;; replaces the buffer of the argument window with the new buffer. -(defun record-window-buffer (&optional window) - "Record WINDOW's buffer. -WINDOW must be a live window and defaults to the selected one." - (let* ((window (window-normalize-window window t)) - (buffer (window-buffer window)) - (entry (assq buffer (window-prev-buffers window)))) - ;; Reset WINDOW's next buffers. If needed, they are resurrected by - ;; `switch-to-prev-buffer' and `switch-to-next-buffer'. - (set-window-next-buffers window nil) - - (when entry - ;; Remove all entries for BUFFER from WINDOW's previous buffers. - (set-window-prev-buffers - window (assq-delete-all buffer (window-prev-buffers window)))) - - ;; Don't record insignificant buffers. - (unless (eq (aref (buffer-name buffer) 0) ?\s) - ;; Add an entry for buffer to WINDOW's previous buffers. - (with-current-buffer buffer - (let ((start (window-start window)) - (point (window-point-1 window))) - (setq entry - (cons buffer - (if entry - ;; We have an entry, update marker positions. - (list (set-marker (nth 1 entry) start) - (set-marker (nth 2 entry) point)) - ;; Make new markers. - (list (copy-marker start) - (copy-marker point))))) - - (set-window-prev-buffers - window (cons entry (window-prev-buffers window)))))))) - (defun unrecord-window-buffer (&optional window buffer) "Unrecord BUFFER in WINDOW. WINDOW must be a live window and defaults to the selected one. @@ -4846,6 +4783,50 @@ (and pop-up-windows (display-buffer-pop-up-window buffer alist)))) +(defun display-buffer-in-previous-window (buffer alist) + "Display BUFFER in a window previously showing it. +If ALIST has a non-nil `inhibit-same-window' entry, the selected +window is not eligible for reuse. + +If ALIST contains a `reusable-frames' entry, its value determines +which frames to search for a reusable window: + nil -- the selected frame (actually the last non-minibuffer frame) + A frame -- just that frame + `visible' -- all visible frames + 0 -- all frames on the current terminal + t -- all frames. + +If ALIST contains no `reusable-frames' entry, search just the +selected frame if `display-buffer-reuse-frames' and +`pop-up-frames' are both nil; search all frames on the current +terminal if either of those variables is non-nil." + (let* ((alist-entry (assq 'reusable-frames alist)) + (inhibit-same-window + (cdr (assq 'inhibit-same-window alist))) + (frames (cond + (alist-entry (cdr alist-entry)) + ((if (eq pop-up-frames 'graphic-only) + (display-graphic-p) + pop-up-frames) + 0) + (display-buffer-reuse-frames 0) + (t (last-nonminibuffer-frame)))) + best-window second-best-window window) + (when inhibit-same-window (ding)) + (catch 'best + (dolist (window (window-list-1 (frame-first-window) 'nomini frames)) + (when (and (assq buffer (window-prev-buffers window)) + (not (window-dedicated-p window))) + (if (eq window (selected-window)) + (unless inhibit-same-window + (setq second-best-window window)) + (setq best-window window) + (throw 'best t))))) + + (when (setq window (or best-window second-best-window)) + (display-buffer-record-window 'reuse window buffer) + (window--display-buffer-2 buffer window display-buffer-mark-dedicated)))) + (defun display-buffer-use-some-window (buffer alist) "Display BUFFER in an existing window. Search for a usable window, set that window to the buffer, and === modified file 'src/window.c' --- src/window.c 2012-02-23 17:40:33 +0000 +++ src/window.c 2012-02-27 07:43:06 +0000 @@ -51,7 +51,7 @@ #endif Lisp_Object Qwindowp, Qwindow_live_p; -static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer; +static Lisp_Object Qwindow_configuration_p; static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer; static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window; static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically; @@ -1647,15 +1647,41 @@ DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers, Sset_window_prev_buffers, 2, 2, 0, - doc: /* Set WINDOW's previous buffers to PREV-BUFFERS. + doc: /* Set WINDOW's previous buffers to PREV-BUFFERS. WINDOW must be a live window and defaults to the selected one. PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS), where BUFFER is a buffer, WINDOW-START is the start position of the window for that buffer, and POS is a window-specific point value. */) - (Lisp_Object window, Lisp_Object prev_buffers) + (Lisp_Object window, Lisp_Object prev_buffers) { - return decode_window (window)->prev_buffers = prev_buffers; + register struct window *w = decode_window (window); + + if (NILP (prev_buffers)) + return w->prev_buffers = Qnil; + else if (!CONSP (prev_buffers)) + return w->prev_buffers; + else + { + /* Run cycle detection on prev_buffers. */ + Lisp_Object tortoise, hare; + + hare = tortoise = prev_buffers; + while (CONSP (hare)) + { + hare = XCDR (hare); + if (!CONSP (hare)) + break; + + hare = XCDR (hare); + tortoise = XCDR (tortoise); + + if (EQ (hare, tortoise)) + return w->prev_buffers; + } + + return w->prev_buffers = prev_buffers; + } } DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers, @@ -1674,7 +1700,33 @@ NEXT-BUFFERS should be a list of buffers. */) (Lisp_Object window, Lisp_Object next_buffers) { - return decode_window (window)->next_buffers = next_buffers; + register struct window *w = decode_window (window); + + if (NILP (next_buffers)) + return w->next_buffers = Qnil; + else if (!CONSP (next_buffers)) + return w->next_buffers; + else + { + /* Run cycle detection on next_buffers. */ + Lisp_Object tortoise, hare; + + hare = tortoise = next_buffers; + while (CONSP (hare)) + { + hare = XCDR (hare); + if (!CONSP (hare)) + break; + + hare = XCDR (hare); + tortoise = XCDR (tortoise); + + if (EQ (hare, tortoise)) + return w->next_buffers; + } + + return w->next_buffers = next_buffers; + } } DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters, @@ -2940,13 +2992,94 @@ DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook, Srun_window_configuration_change_hook, 1, 1, 0, doc: /* Run `window-configuration-change-hook' for FRAME. */) - (Lisp_Object frame) + (Lisp_Object frame) { CHECK_LIVE_FRAME (frame); run_window_configuration_change_hook (XFRAME (frame)); return Qnil; } +/* `prev_buffers' and `next_buffers' are two reserved window slots used +for determining + +(1) which buffer to show in the window when its buffer shall be buried + or killed, and + +(2) which buffer to show for `switch-to-prev-buffer' and + `switch-to-next-buffer'. + +`prev_buffers' is built from +triples. The entries on this list are ordered by the time their buffer +has been removed from the window, the most recently removed buffer's +entry being first. The window-start and window-point components are +`window-start' and `window-point' at the time the buffer was removed +from the window which implies that the entry must be added when +Fset_window_buffer removes the buffer from the window. + +`next_buffers' is the list of buffers that have been replaced recently +by `switch-to-prev-buffer'. These buffers are the least preferred +candidates of `switch-to-prev-buffer' and the preferred candidates of +`switch-to-next-buffer' to switch to. This list is reset to nil by any +action changing the window's buffer with the exception of +`switch-to-prev-buffer' and `switch-to-next-buffer'. +`switch-to-prev-buffer' pushes the buffer it just replaced on it, +`switch-to-next-buffer' pops the last pushed buffer from it. + +Both `prev_buffers' and `next_buffers' may reference killed buffers if +such a buffer was killed while the window was hidden within a window +configuration. Such killed buffers get removed whenever +`switch-to-prev-buffer' or `switch-to-next-buffer' encounter them. + +The following function must be called by Fset_window_buffer and +Fset_window_configuration _before_ these replace the buffer of the +argument window with the new buffer. */ + +static void +record_window_buffer (Lisp_Object window) +{ + struct window *w = XWINDOW (window); + Lisp_Object buffer = w->buffer; + struct buffer *b = XBUFFER (buffer); + Lisp_Object entry = Fassq (buffer, w->prev_buffers); + Lisp_Object start_marker, point_marker, point; + int count = SPECPDL_INDEX (); + + /* Return immediately if BUFFER is not a buffer. */ + if (!BUFFERP (buffer)) + return; + + /* Reset WINDOW's next buffers. If needed, they are resurrected by + `switch-to-prev-buffer' and `switch-to-next-buffer'. */ + w->next_buffers = Qnil; + + if (!NILP (entry)) + /* Remove all entries for BUFFER from WINDOW's previous buffers. */ + w->prev_buffers = Fdelq (entry, w->prev_buffers); + + if (NILP (BVAR (b, name)) || SREF (BVAR (b, name), 0) == ' ') + /* Don't record dead or insignificant buffers. */ + return; + + if (current_buffer != b) + { + /* Make sure Fpoint below gets the right buffer. */ + record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ()); + set_buffer_internal (b); + } + + /* Reuse existing markers if possible. */ + start_marker = !NILP (entry) ? Fnth (make_number (1), entry) : Fmake_marker (); + point_marker = !NILP (entry) ? Fnth (make_number (2), entry) : Fmake_marker (); + point = EQ (window, selected_window) ? Fpoint () : w->pointm; + set_marker_restricted (start_marker, w->start, buffer); + set_marker_restricted (point_marker, point, buffer); + w->prev_buffers = Fcons (list3 (buffer, start_marker, point_marker), + w->prev_buffers); + + unbind_to (count, Qnil); +} + + /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero means it's allowed to run hooks. See make_frame for a case where it's not allowed. KEEP_MARGINS_P non-zero means that the current @@ -3094,7 +3227,7 @@ dedication. */ w->dedicated = Qnil; - call1 (Qrecord_window_buffer, window); + record_window_buffer (window); } unshow_buffer (w); @@ -5587,6 +5720,8 @@ else if (!NILP (BVAR (XBUFFER (p->buffer), name))) /* If saved buffer is alive, install it. */ { + if (!EQ (w->buffer, p->buffer)) + record_window_buffer (window); w->buffer = p->buffer; w->start_at_line_beg = p->start_at_line_beg; set_marker_restricted (w->start, p->start, w->buffer); @@ -5620,6 +5755,7 @@ && SCHARS (auto_buffer_name) != 0 && !NILP (w->buffer = Fget_buffer_create (auto_buffer_name))) { + record_window_buffer (window); set_marker_restricted (w->start, make_number (0), w->buffer); set_marker_restricted (w->pointm, make_number (0), w->buffer); w->start_at_line_beg = Qt; @@ -5627,6 +5763,7 @@ else /* Window has no live buffer, get one. */ { + record_window_buffer (window); /* Get the buffer via other_buffer_safely in order to avoid showing an unimportant buffer and, if necessary, to recreate *scratch* in the course (part of Juanma's bs-show @@ -6509,7 +6646,6 @@ DEFSYM (Qsafe, "safe"); DEFSYM (Qdisplay_buffer, "display-buffer"); DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows"); - DEFSYM (Qrecord_window_buffer, "record-window-buffer"); DEFSYM (Qget_mru_window, "get-mru-window"); DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook"); DEFSYM (Qabove, "above");