mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-25 10:47:00 +00:00
Move/add window-buffer-related functions to window.el.
* buffer.c: New Lisp objects Qbuffer_list_update_hook and Qclone_number. Remove external declaration of Qdelete_window. (Fbuffer_list): Rewrite doc-string. Minor restructuring of code. (Fget_buffer_create, Fmake_indirect_buffer, Frename_buffer): Run Qbuffer_list_update_hook if allowed. (Fother_buffer): Rewrite doc-string. Major rewrite for new buffer list implementation. (other_buffer_safely): New function. (Fkill_buffer): Replace call to replace_buffer_in_all_windows by calls to replace_buffer_in_windows and replace_buffer_in_windows_safely. Run Qbuffer_list_update_hook if allowed. (record_buffer): Inhibit quitting and rewrite using quittable functions. Run Qbuffer_list_update_hook if allowed. (Frecord_buffer, Funrecord_buffer): New functions. (switch_to_buffer_1, Fswitch_to_buffer): Remove. Move switch-to-buffer to window.el. (bury-buffer): Move to window.el. (Vbuffer_list_update_hook): New variable. * lisp.h (other_buffer_safely): Add prototype in buffer.c section. * window.h (resize_frame_windows): Move up in code. (Fwindow_frame): Remove EXFUN. (replace_buffer_in_all_windows): Remove prototype. (replace_buffer_in_windows_safely): Add prototype. * window.c: Declare Qdelete_window static again. Move down declaration of select_count. (Fnext_window, Fprevious_window): Rewrite doc-strings. (Fother_window): Move to window.el. (window_loop): Remove DELETE_BUFFER_WINDOWS and UNSHOW_BUFFER cases. Add REPLACE_BUFFER_IN_WINDOWS_SAFELY case. (Fdelete_windows_on, Freplace_buffer_in_windows): Move to window.el. (replace_buffer_in_windows): Implement by calling Qreplace_buffer_in_windows. (replace_buffer_in_all_windows): Remove with some functionality moved into replace_buffer_in_windows_safely. (replace_buffer_in_windows_safely): New function. (select_window_norecord, select_frame_norecord): Move in front of run_window_configuration_change_hook. Remove now obsolete declarations. (Fset_window_buffer): Rewrite doc-string. Call Qrecord_window_buffer. (keys_of_window): Move binding for other-window to window.el. * loadup.el (top-level): Load window before files for the sake of replace-buffer-in-windows. * files.el (read-buffer-to-switch) (switch-to-buffer-other-window) (switch-to-buffer-other-frame, display-buffer-other-frame): Move to window.el. * simple.el (get-next-valid-buffer, last-buffer, next-buffer) (previous-buffer): Move to window.el. * bindings.el (unbury-buffer): Move to window.el. * window.el (delete-other-windows-vertically): Move after definition of delete-other-windows. (other-window, delete-windows-on, replace-buffer-in-windows): Move here from window.c. (record-window-buffer, unrecord-window-buffer) (set-window-buffer-start-and-point, switch-to-prev-buffer) (switch-to-next-buffer): New functions. (get-next-valid-buffer, last-buffer, next-buffer): Move here from simple.el. Call switch-to-next-buffer. (previous-buffer): Move here from simple.el. Call switch-to-prev-buffer. (bury-buffer): Move here from buffer.c. Switch to previous buffer when window cannot be deleted. (unbury-buffer): Move here from bindings.el. (ctl-x-map): Move binding for other-window from window.c to here. (read-buffer-to-switch, switch-to-buffer-other-window) (switch-to-buffer-other-frame): Move here from files.el. (normalize-buffer-to-switch-to): New functions. (switch-to-buffer): Move here from buffer.c. Use read-buffer-to-switch and normalize-buffer-to-switch-to.
This commit is contained in:
parent
b50691aaaf
commit
9397e56f74
@ -1,3 +1,40 @@
|
||||
2011-06-10 Martin Rudalics <rudalics@gmx.at>
|
||||
|
||||
* loadup.el (top-level): Load window before files for the sake
|
||||
of replace-buffer-in-windows.
|
||||
|
||||
* files.el (read-buffer-to-switch)
|
||||
(switch-to-buffer-other-window)
|
||||
(switch-to-buffer-other-frame, display-buffer-other-frame): Move
|
||||
to window.el.
|
||||
|
||||
* simple.el (get-next-valid-buffer, last-buffer, next-buffer)
|
||||
(previous-buffer): Move to window.el.
|
||||
|
||||
* bindings.el (unbury-buffer): Move to window.el.
|
||||
|
||||
* window.el (delete-other-windows-vertically): Move after
|
||||
definition of delete-other-windows.
|
||||
(other-window, delete-windows-on, replace-buffer-in-windows):
|
||||
Move here from window.c.
|
||||
(record-window-buffer, unrecord-window-buffer)
|
||||
(set-window-buffer-start-and-point, switch-to-prev-buffer)
|
||||
(switch-to-next-buffer): New functions.
|
||||
(get-next-valid-buffer, last-buffer, next-buffer): Move here
|
||||
from simple.el. Call switch-to-next-buffer.
|
||||
(previous-buffer): Move here from simple.el. Call
|
||||
switch-to-prev-buffer.
|
||||
(bury-buffer): Move here from buffer.c. Switch to previous
|
||||
buffer when window cannot be deleted.
|
||||
(unbury-buffer): Move here from bindings.el.
|
||||
(ctl-x-map): Move binding for other-window from window.c to
|
||||
here.
|
||||
(read-buffer-to-switch, switch-to-buffer-other-window)
|
||||
(switch-to-buffer-other-frame): Move here from files.el.
|
||||
(normalize-buffer-to-switch-to): New functions.
|
||||
(switch-to-buffer): Move here from buffer.c. Use
|
||||
read-buffer-to-switch and normalize-buffer-to-switch-to.
|
||||
|
||||
2011-06-10 Martin Rudalics <rudalics@gmx.at>
|
||||
|
||||
* window.el (window-min-height, window-min-width): Move here
|
||||
|
@ -454,11 +454,6 @@ Major modes that edit things other than ordinary files may change this
|
||||
(put 'mode-line-buffer-identification 'risky-local-variable t)
|
||||
(make-variable-buffer-local 'mode-line-buffer-identification)
|
||||
|
||||
(defun unbury-buffer () "\
|
||||
Switch to the last buffer in the buffer list."
|
||||
(interactive)
|
||||
(switch-to-buffer (last-buffer)))
|
||||
|
||||
(defun mode-line-unbury-buffer (event) "\
|
||||
Call `unbury-buffer' in this window."
|
||||
(interactive "e")
|
||||
|
@ -1288,100 +1288,6 @@ return value, which may be passed as the REQUIRE-MATCH arg to
|
||||
'confirm)
|
||||
(t nil)))
|
||||
|
||||
(defun read-buffer-to-switch (prompt)
|
||||
"Read the name of a buffer to switch to and return as a string.
|
||||
It is intended for `switch-to-buffer' family of commands since they
|
||||
need to omit the name of current buffer from the list of completions
|
||||
and default values."
|
||||
(let ((rbts-completion-table (internal-complete-buffer-except)))
|
||||
(minibuffer-with-setup-hook
|
||||
(lambda ()
|
||||
(setq minibuffer-completion-table rbts-completion-table)
|
||||
;; Since rbts-completion-table is built dynamically, we
|
||||
;; can't just add it to the default value of
|
||||
;; icomplete-with-completion-tables, so we add it
|
||||
;; here manually.
|
||||
(if (and (boundp 'icomplete-with-completion-tables)
|
||||
(listp icomplete-with-completion-tables))
|
||||
(set (make-local-variable 'icomplete-with-completion-tables)
|
||||
(cons rbts-completion-table
|
||||
icomplete-with-completion-tables))))
|
||||
(read-buffer prompt (other-buffer (current-buffer))
|
||||
(confirm-nonexistent-file-or-buffer)))))
|
||||
|
||||
(defun switch-to-buffer-other-window (buffer-or-name &optional norecord)
|
||||
"Select the buffer specified by BUFFER-OR-NAME in another window.
|
||||
BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
|
||||
nil. Return the buffer switched to.
|
||||
|
||||
If called interactively, prompt for the buffer name using the
|
||||
minibuffer. The variable `confirm-nonexistent-file-or-buffer'
|
||||
determines whether to request confirmation before creating a new
|
||||
buffer.
|
||||
|
||||
If BUFFER-OR-NAME is a string and does not identify an existing
|
||||
buffer, create a new buffer with that name. If BUFFER-OR-NAME is
|
||||
nil, switch to the buffer returned by `other-buffer'.
|
||||
|
||||
Optional second argument NORECORD non-nil means do not put this
|
||||
buffer at the front of the list of recently selected ones.
|
||||
|
||||
This uses the function `display-buffer' as a subroutine; see its
|
||||
documentation for additional customization information."
|
||||
(interactive
|
||||
(list (read-buffer-to-switch "Switch to buffer in other window: ")))
|
||||
(let ((pop-up-windows t)
|
||||
same-window-buffer-names same-window-regexps)
|
||||
(pop-to-buffer buffer-or-name t norecord)))
|
||||
|
||||
(defun switch-to-buffer-other-frame (buffer-or-name &optional norecord)
|
||||
"Switch to buffer BUFFER-OR-NAME in another frame.
|
||||
BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
|
||||
nil. Return the buffer switched to.
|
||||
|
||||
If called interactively, prompt for the buffer name using the
|
||||
minibuffer. The variable `confirm-nonexistent-file-or-buffer'
|
||||
determines whether to request confirmation before creating a new
|
||||
buffer.
|
||||
|
||||
If BUFFER-OR-NAME is a string and does not identify an existing
|
||||
buffer, create a new buffer with that name. If BUFFER-OR-NAME is
|
||||
nil, switch to the buffer returned by `other-buffer'.
|
||||
|
||||
Optional second arg NORECORD non-nil means do not put this
|
||||
buffer at the front of the list of recently selected ones.
|
||||
|
||||
This uses the function `display-buffer' as a subroutine; see its
|
||||
documentation for additional customization information."
|
||||
(interactive
|
||||
(list (read-buffer-to-switch "Switch to buffer in other frame: ")))
|
||||
(let ((pop-up-frames t)
|
||||
same-window-buffer-names same-window-regexps)
|
||||
(pop-to-buffer buffer-or-name t norecord)))
|
||||
|
||||
(defun display-buffer-other-frame (buffer)
|
||||
"Display buffer BUFFER in another frame.
|
||||
This uses the function `display-buffer' as a subroutine; see
|
||||
its documentation for additional customization information."
|
||||
(interactive "BDisplay buffer in other frame: ")
|
||||
(let ((pop-up-frames t)
|
||||
same-window-buffer-names same-window-regexps
|
||||
;;(old-window (selected-window))
|
||||
new-window)
|
||||
(setq new-window (display-buffer buffer t))
|
||||
;; This may have been here in order to prevent the new frame from hiding
|
||||
;; the old frame. But it does more harm than good.
|
||||
;; Maybe we should call `raise-window' on the old-frame instead? --Stef
|
||||
;;(lower-frame (window-frame new-window))
|
||||
|
||||
;; This may have been here in order to make sure the old-frame gets the
|
||||
;; focus. But not only can it cause an annoying flicker, with some
|
||||
;; window-managers it just makes the window invisible, with no easy
|
||||
;; way to recover it. --Stef
|
||||
;;(make-frame-invisible (window-frame old-window))
|
||||
;;(make-frame-visible (window-frame old-window))
|
||||
))
|
||||
|
||||
(defmacro minibuffer-with-setup-hook (fun &rest body)
|
||||
"Temporarily add FUN to `minibuffer-setup-hook' while executing BODY.
|
||||
BODY should use the minibuffer at most once.
|
||||
|
@ -95,6 +95,7 @@
|
||||
(load "env")
|
||||
(load "format")
|
||||
(load "bindings")
|
||||
(load "window") ; Needed here for `replace-buffer-in-windows'.
|
||||
(setq load-source-file-function 'load-with-code-conversion)
|
||||
(load "files")
|
||||
|
||||
@ -156,7 +157,6 @@
|
||||
(load "language/cham")
|
||||
|
||||
(load "indent")
|
||||
(load "window")
|
||||
(load "frame")
|
||||
(load "term/tty-colors")
|
||||
(load "font-core")
|
||||
|
@ -52,60 +52,6 @@ wait this many seconds after Emacs becomes idle before doing an update."
|
||||
(defgroup paren-matching nil
|
||||
"Highlight (un)matching of parens and expressions."
|
||||
:group 'matching)
|
||||
|
||||
(defun get-next-valid-buffer (list &optional buffer visible-ok frame)
|
||||
"Search LIST for a valid buffer to display in FRAME.
|
||||
Return nil when all buffers in LIST are undesirable for display,
|
||||
otherwise return the first suitable buffer in LIST.
|
||||
|
||||
Buffers not visible in windows are preferred to visible buffers,
|
||||
unless VISIBLE-OK is non-nil.
|
||||
If the optional argument FRAME is nil, it defaults to the selected frame.
|
||||
If BUFFER is non-nil, ignore occurrences of that buffer in LIST."
|
||||
;; This logic is more or less copied from other-buffer.
|
||||
(setq frame (or frame (selected-frame)))
|
||||
(let ((pred (frame-parameter frame 'buffer-predicate))
|
||||
found buf)
|
||||
(while (and (not found) list)
|
||||
(setq buf (car list))
|
||||
(if (and (not (eq buffer buf))
|
||||
(buffer-live-p buf)
|
||||
(or (null pred) (funcall pred buf))
|
||||
(not (eq (aref (buffer-name buf) 0) ?\s))
|
||||
(or visible-ok (null (get-buffer-window buf 'visible))))
|
||||
(setq found buf)
|
||||
(setq list (cdr list))))
|
||||
(car list)))
|
||||
|
||||
(defun last-buffer (&optional buffer visible-ok frame)
|
||||
"Return the last buffer in FRAME's buffer list.
|
||||
If BUFFER is the last buffer, return the preceding buffer instead.
|
||||
Buffers not visible in windows are preferred to visible buffers,
|
||||
unless optional argument VISIBLE-OK is non-nil.
|
||||
Optional third argument FRAME nil or omitted means use the
|
||||
selected frame's buffer list.
|
||||
If no such buffer exists, return the buffer `*scratch*', creating
|
||||
it if necessary."
|
||||
(setq frame (or frame (selected-frame)))
|
||||
(or (get-next-valid-buffer (nreverse (buffer-list frame))
|
||||
buffer visible-ok frame)
|
||||
(get-buffer "*scratch*")
|
||||
(let ((scratch (get-buffer-create "*scratch*")))
|
||||
(set-buffer-major-mode scratch)
|
||||
scratch)))
|
||||
|
||||
(defun next-buffer ()
|
||||
"Switch to the next buffer in cyclic order."
|
||||
(interactive)
|
||||
(let ((buffer (current-buffer)))
|
||||
(switch-to-buffer (other-buffer buffer t))
|
||||
(bury-buffer buffer)))
|
||||
|
||||
(defun previous-buffer ()
|
||||
"Switch to the previous buffer in cyclic order."
|
||||
(interactive)
|
||||
(switch-to-buffer (last-buffer (current-buffer) t)))
|
||||
|
||||
|
||||
;;; next-error support framework
|
||||
|
||||
|
768
lisp/window.el
768
lisp/window.el
@ -2078,6 +2078,74 @@ WINDOW can be any window and defaults to the selected window."
|
||||
"Return non-nil if WINDOW is the root window of its frame."
|
||||
(eq window (frame-root-window window)))
|
||||
|
||||
(defun other-window (count &optional all-frames)
|
||||
"Select another window in cyclic ordering of windows.
|
||||
COUNT specifies the number of windows to skip, starting with the
|
||||
selected window, before making the selection. If COUNT is
|
||||
positive, skip COUNT windows forwards. If COUNT is negative,
|
||||
skip -COUNT windows backwards. COUNT zero means do not skip any
|
||||
window, so select the selected window. In an interactive call,
|
||||
COUNT is the numeric prefix argument. Return nil.
|
||||
|
||||
If the `other-window' parameter of WINDOW is a function and
|
||||
`ignore-window-parameters' is nil, call that function with the
|
||||
arguments COUNT and ALL-FRAMES.
|
||||
|
||||
This function does not select a window whose `no-other-window'
|
||||
window parameter is non-nil.
|
||||
|
||||
This function uses `next-window' for finding the window to
|
||||
select. The argument ALL-FRAMES has the same meaning as in
|
||||
`next-window', but the MINIBUF argument of `next-window' is
|
||||
always effectively nil."
|
||||
(interactive "p")
|
||||
(let* ((window (selected-window))
|
||||
(function (and (not ignore-window-parameters)
|
||||
(window-parameter window 'other-window)))
|
||||
old-window old-count)
|
||||
(if (functionp function)
|
||||
(funcall function count all-frames)
|
||||
;; `next-window' and `previous-window' may return a window we are
|
||||
;; not allowed to select. Hence we need an exit strategy in case
|
||||
;; all windows are non-selectable.
|
||||
(catch 'exit
|
||||
(while (> count 0)
|
||||
(setq window (next-window window nil all-frames))
|
||||
(cond
|
||||
((eq window old-window)
|
||||
(when (= count old-count)
|
||||
;; Keep out of infinite loops. When COUNT has not changed
|
||||
;; since we last looked at `window' we're probably in one.
|
||||
(throw 'exit nil)))
|
||||
((window-parameter window 'no-other-window)
|
||||
(unless old-window
|
||||
;; The first non-selectable window `next-window' got us:
|
||||
;; Remember it and the current value of COUNT.
|
||||
(setq old-window window)
|
||||
(setq old-count count)))
|
||||
(t
|
||||
(setq count (1- count)))))
|
||||
(while (< count 0)
|
||||
(setq window (previous-window window nil all-frames))
|
||||
(cond
|
||||
((eq window old-window)
|
||||
(when (= count old-count)
|
||||
;; Keep out of infinite loops. When COUNT has not changed
|
||||
;; since we last looked at `window' we're probably in one.
|
||||
(throw 'exit nil)))
|
||||
((window-parameter window 'no-other-window)
|
||||
(unless old-window
|
||||
;; The first non-selectable window `previous-window' got
|
||||
;; us: Remember it and the current value of COUNT.
|
||||
(setq old-window window)
|
||||
(setq old-count count)))
|
||||
(t
|
||||
(setq count (1+ count)))))
|
||||
|
||||
(select-window window)
|
||||
;; Always return nil.
|
||||
nil))))
|
||||
|
||||
;; This should probably return non-nil when the selected window is part
|
||||
;; of an atomic window whose root is the frame's root window.
|
||||
(defun one-window-p (&optional nomini all-frames)
|
||||
@ -2285,6 +2353,518 @@ window signal an error."
|
||||
(window-check frame))
|
||||
;; Always return nil.
|
||||
nil)))
|
||||
|
||||
(defun delete-other-windows-vertically (&optional window)
|
||||
"Delete the windows in the same column with WINDOW, but not WINDOW itself.
|
||||
This may be a useful alternative binding for \\[delete-other-windows]
|
||||
if you often split windows horizontally."
|
||||
(interactive)
|
||||
(let* ((window (or window (selected-window)))
|
||||
(edges (window-edges window))
|
||||
(w window) delenda)
|
||||
(while (not (eq (setq w (next-window w 1)) window))
|
||||
(let ((e (window-edges w)))
|
||||
(when (and (= (car e) (car edges))
|
||||
(= (caddr e) (caddr edges)))
|
||||
(push w delenda))))
|
||||
(mapc 'delete-window delenda)))
|
||||
|
||||
;;; 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 <buffer, window-start, window-point>
|
||||
;; 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 (normalize-live-window window))
|
||||
(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 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.
|
||||
BUFFER must be a live buffer and defaults to the buffer of
|
||||
WINDOW."
|
||||
(let* ((window (normalize-live-window window))
|
||||
(buffer (or buffer (window-buffer window))))
|
||||
(set-window-prev-buffers
|
||||
window (assq-delete-all buffer (window-prev-buffers window)))
|
||||
(set-window-next-buffers
|
||||
window (delq buffer (window-next-buffers window)))))
|
||||
|
||||
(defun set-window-buffer-start-and-point (window buffer &optional start point)
|
||||
"Set WINDOW's buffer to BUFFER.
|
||||
Optional argument START non-nil means set WINDOW's start position
|
||||
to START. Optional argument POINT non-nil means set WINDOW's
|
||||
point to POINT. If WINDOW is selected this also sets BUFFER's
|
||||
`point' to POINT. If WINDOW is selected and the buffer it showed
|
||||
before was current this also makes BUFFER the current buffer."
|
||||
(let ((selected (eq window (selected-window)))
|
||||
(current (eq (window-buffer window) (current-buffer))))
|
||||
(set-window-buffer window buffer)
|
||||
(when (and selected current)
|
||||
(set-buffer buffer))
|
||||
(when start
|
||||
(set-window-start window start))
|
||||
(when point
|
||||
(if selected
|
||||
(with-current-buffer buffer
|
||||
(goto-char point))
|
||||
(set-window-point window point)))))
|
||||
|
||||
(defun switch-to-prev-buffer (&optional window bury-or-kill)
|
||||
"In WINDOW switch to previous buffer.
|
||||
WINDOW must be a live window and defaults to the selected one.
|
||||
|
||||
Optional argument BURY-OR-KILL non-nil means the buffer currently
|
||||
shown in WINDOW is about to be buried or killed and consequently
|
||||
shall not be switched to in future invocations of this command."
|
||||
(interactive)
|
||||
(let* ((window (normalize-live-window window))
|
||||
(old-buffer (window-buffer window))
|
||||
;; Save this since it's destroyed by `set-window-buffer'.
|
||||
(next-buffers (window-next-buffers window))
|
||||
entry new-buffer killed-buffers deletable visible)
|
||||
(cond
|
||||
;; When BURY-OR-KILL is non-nil, there's no previous buffer for
|
||||
;; this window, and we can delete the window (or the frame) do
|
||||
;; that.
|
||||
((and bury-or-kill
|
||||
(or (not (window-prev-buffers window))
|
||||
(and (eq (caar (window-prev-buffers window)) old-buffer)
|
||||
(not (cdr (car (window-prev-buffers window))))))
|
||||
(setq deletable (window-deletable-p window)))
|
||||
(if (eq deletable 'frame)
|
||||
(delete-frame (window-frame window))
|
||||
(delete-window window)))
|
||||
((window-dedicated-p window)
|
||||
(error "Window %s is dedicated to buffer %s" window old-buffer)))
|
||||
|
||||
(unless deletable
|
||||
(catch 'found
|
||||
;; Scan WINDOW's previous buffers first, skipping entries of next
|
||||
;; buffers.
|
||||
(dolist (entry (window-prev-buffers window))
|
||||
(when (and (setq new-buffer (car entry))
|
||||
(or (buffer-live-p new-buffer)
|
||||
(not (setq killed-buffers
|
||||
(cons new-buffer killed-buffers))))
|
||||
(not (eq new-buffer old-buffer))
|
||||
(or bury-or-kill
|
||||
(not (memq new-buffer next-buffers))))
|
||||
(set-window-buffer-start-and-point
|
||||
window new-buffer (nth 1 entry) (nth 2 entry))
|
||||
(throw 'found t)))
|
||||
;; Scan reverted buffer list of WINDOW's frame next, skipping
|
||||
;; entries of next buffers. Note that when we bury or kill a
|
||||
;; buffer we don't reverse the global buffer list to avoid showing
|
||||
;; a buried buffer instead. Otherwise, we must reverse the global
|
||||
;; buffer list in order to make sure that switching to the
|
||||
;; previous/next buffer traverse it in opposite directions.
|
||||
(dolist (buffer (if bury-or-kill
|
||||
(buffer-list (window-frame window))
|
||||
(nreverse (buffer-list (window-frame window)))))
|
||||
(when (and (buffer-live-p buffer)
|
||||
(not (eq buffer old-buffer))
|
||||
(not (eq (aref (buffer-name buffer) 0) ?\s))
|
||||
(or bury-or-kill (not (memq buffer next-buffers))))
|
||||
(if (get-buffer-window buffer)
|
||||
;; Try to avoid showing a buffer visible in some other window.
|
||||
(setq visible buffer)
|
||||
(setq new-buffer buffer)
|
||||
(set-window-buffer-start-and-point window new-buffer)
|
||||
(throw 'found t))))
|
||||
(unless bury-or-kill
|
||||
;; Scan reverted next buffers last (must not use nreverse
|
||||
;; here!).
|
||||
(dolist (buffer (reverse next-buffers))
|
||||
;; Actually, buffer _must_ be live here since otherwise it
|
||||
;; would have been caught in the scan of previous buffers.
|
||||
(when (and (or (buffer-live-p buffer)
|
||||
(not (setq killed-buffers
|
||||
(cons buffer killed-buffers))))
|
||||
(not (eq buffer old-buffer))
|
||||
(setq entry (assq buffer (window-prev-buffers window))))
|
||||
(setq new-buffer buffer)
|
||||
(set-window-buffer-start-and-point
|
||||
window new-buffer (nth 1 entry) (nth 2 entry))
|
||||
(throw 'found t))))
|
||||
|
||||
;; Show a buffer visible in another window.
|
||||
(when visible
|
||||
(setq new-buffer visible)
|
||||
(set-window-buffer-start-and-point window new-buffer)))
|
||||
|
||||
(if bury-or-kill
|
||||
;; Remove `old-buffer' from WINDOW's previous and (restored list
|
||||
;; of) next buffers.
|
||||
(progn
|
||||
(set-window-prev-buffers
|
||||
window (assq-delete-all old-buffer (window-prev-buffers window)))
|
||||
(set-window-next-buffers window (delq old-buffer next-buffers)))
|
||||
;; Move `old-buffer' to head of WINDOW's restored list of next
|
||||
;; buffers.
|
||||
(set-window-next-buffers
|
||||
window (cons old-buffer (delq old-buffer next-buffers)))))
|
||||
|
||||
;; Remove killed buffers from WINDOW's previous and next buffers.
|
||||
(when killed-buffers
|
||||
(dolist (buffer killed-buffers)
|
||||
(set-window-prev-buffers
|
||||
window (assq-delete-all buffer (window-prev-buffers window)))
|
||||
(set-window-next-buffers
|
||||
window (delq buffer (window-next-buffers window)))))
|
||||
|
||||
;; Return new-buffer.
|
||||
new-buffer))
|
||||
|
||||
(defun switch-to-next-buffer (&optional window)
|
||||
"In WINDOW switch to next buffer.
|
||||
WINDOW must be a live window and defaults to the selected one."
|
||||
(interactive)
|
||||
(let* ((window (normalize-live-window window))
|
||||
(old-buffer (window-buffer window))
|
||||
(next-buffers (window-next-buffers window))
|
||||
new-buffer entry killed-buffers visible)
|
||||
(when (window-dedicated-p window)
|
||||
(error "Window %s is dedicated to buffer %s" window old-buffer))
|
||||
|
||||
(catch 'found
|
||||
;; Scan WINDOW's next buffers first.
|
||||
(dolist (buffer next-buffers)
|
||||
(when (and (or (buffer-live-p buffer)
|
||||
(not (setq killed-buffers
|
||||
(cons buffer killed-buffers))))
|
||||
(not (eq buffer old-buffer))
|
||||
(setq entry (assq buffer (window-prev-buffers window))))
|
||||
(setq new-buffer buffer)
|
||||
(set-window-buffer-start-and-point
|
||||
window new-buffer (nth 1 entry) (nth 2 entry))
|
||||
(throw 'found t)))
|
||||
;; Scan the buffer list of WINDOW's frame next, skipping previous
|
||||
;; buffers entries.
|
||||
(dolist (buffer (buffer-list (window-frame window)))
|
||||
(when (and (buffer-live-p buffer) (not (eq buffer old-buffer))
|
||||
(not (eq (aref (buffer-name buffer) 0) ?\s))
|
||||
(not (assq buffer (window-prev-buffers window))))
|
||||
(if (get-buffer-window buffer)
|
||||
;; Try to avoid showing a buffer visible in some other window.
|
||||
(setq visible buffer)
|
||||
(setq new-buffer buffer)
|
||||
(set-window-buffer-start-and-point window new-buffer)
|
||||
(throw 'found t))))
|
||||
;; Scan WINDOW's reverted previous buffers last (must not use
|
||||
;; nreverse here!)
|
||||
(dolist (entry (reverse (window-prev-buffers window)))
|
||||
(when (and (setq new-buffer (car entry))
|
||||
(or (buffer-live-p new-buffer)
|
||||
(not (setq killed-buffers
|
||||
(cons new-buffer killed-buffers))))
|
||||
(not (eq new-buffer old-buffer)))
|
||||
(set-window-buffer-start-and-point
|
||||
window new-buffer (nth 1 entry) (nth 2 entry))
|
||||
(throw 'found t)))
|
||||
|
||||
;; Show a buffer visible in another window.
|
||||
(when visible
|
||||
(setq new-buffer visible)
|
||||
(set-window-buffer-start-and-point window new-buffer)))
|
||||
|
||||
;; Remove `new-buffer' from and restore WINDOW's next buffers.
|
||||
(set-window-next-buffers window (delq new-buffer next-buffers))
|
||||
|
||||
;; Remove killed buffers from WINDOW's previous and next buffers.
|
||||
(when killed-buffers
|
||||
(dolist (buffer killed-buffers)
|
||||
(set-window-prev-buffers
|
||||
window (assq-delete-all buffer (window-prev-buffers window)))
|
||||
(set-window-next-buffers
|
||||
window (delq buffer (window-next-buffers window)))))
|
||||
|
||||
;; Return new-buffer.
|
||||
new-buffer))
|
||||
|
||||
(defun get-next-valid-buffer (list &optional buffer visible-ok frame)
|
||||
"Search LIST for a valid buffer to display in FRAME.
|
||||
Return nil when all buffers in LIST are undesirable for display,
|
||||
otherwise return the first suitable buffer in LIST.
|
||||
|
||||
Buffers not visible in windows are preferred to visible buffers,
|
||||
unless VISIBLE-OK is non-nil.
|
||||
If the optional argument FRAME is nil, it defaults to the selected frame.
|
||||
If BUFFER is non-nil, ignore occurrences of that buffer in LIST."
|
||||
;; This logic is more or less copied from other-buffer.
|
||||
(setq frame (or frame (selected-frame)))
|
||||
(let ((pred (frame-parameter frame 'buffer-predicate))
|
||||
found buf)
|
||||
(while (and (not found) list)
|
||||
(setq buf (car list))
|
||||
(if (and (not (eq buffer buf))
|
||||
(buffer-live-p buf)
|
||||
(or (null pred) (funcall pred buf))
|
||||
(not (eq (aref (buffer-name buf) 0) ?\s))
|
||||
(or visible-ok (null (get-buffer-window buf 'visible))))
|
||||
(setq found buf)
|
||||
(setq list (cdr list))))
|
||||
(car list)))
|
||||
|
||||
(defun last-buffer (&optional buffer visible-ok frame)
|
||||
"Return the last buffer in FRAME's buffer list.
|
||||
If BUFFER is the last buffer, return the preceding buffer
|
||||
instead. Buffers not visible in windows are preferred to visible
|
||||
buffers, unless optional argument VISIBLE-OK is non-nil.
|
||||
Optional third argument FRAME nil or omitted means use the
|
||||
selected frame's buffer list. If no such buffer exists, return
|
||||
the buffer `*scratch*', creating it if necessary."
|
||||
(setq frame (or frame (selected-frame)))
|
||||
(or (get-next-valid-buffer (nreverse (buffer-list frame))
|
||||
buffer visible-ok frame)
|
||||
(get-buffer "*scratch*")
|
||||
(let ((scratch (get-buffer-create "*scratch*")))
|
||||
(set-buffer-major-mode scratch)
|
||||
scratch)))
|
||||
|
||||
(defun bury-buffer (&optional buffer-or-name)
|
||||
"Put BUFFER-OR-NAME at the end of the list of all buffers.
|
||||
There it is the least likely candidate for `other-buffer' to
|
||||
return; thus, the least likely buffer for \\[switch-to-buffer] to
|
||||
select by default.
|
||||
|
||||
You can specify a buffer name as BUFFER-OR-NAME, or an actual
|
||||
buffer object. If BUFFER-OR-NAME is nil or omitted, bury the
|
||||
current buffer. Also, if BUFFER-OR-NAME is nil or omitted,
|
||||
remove the current buffer from the selected window if it is
|
||||
displayed there."
|
||||
(interactive)
|
||||
(let* ((buffer (normalize-live-buffer buffer-or-name)))
|
||||
;; If `buffer-or-name' is not on the selected frame we unrecord it
|
||||
;; although it's not "here" (call it a feature).
|
||||
(unrecord-buffer buffer)
|
||||
;; Handle case where `buffer-or-name' is nil and the current buffer
|
||||
;; is shown in the selected window.
|
||||
(cond
|
||||
((or buffer-or-name (not (eq buffer (window-buffer)))))
|
||||
((not (window-dedicated-p))
|
||||
(switch-to-prev-buffer nil 'bury))
|
||||
((frame-root-window-p (selected-window))
|
||||
(iconify-frame (window-frame (selected-window))))
|
||||
((window-deletable-p)
|
||||
(delete-window)))
|
||||
;; Always return nil.
|
||||
nil))
|
||||
|
||||
(defun unbury-buffer ()
|
||||
"Switch to the last buffer in the buffer list."
|
||||
(interactive)
|
||||
(switch-to-buffer (last-buffer)))
|
||||
|
||||
(defun next-buffer ()
|
||||
"In selected window switch to next buffer."
|
||||
(interactive)
|
||||
(switch-to-next-buffer))
|
||||
|
||||
(defun previous-buffer ()
|
||||
"In selected window switch to previous buffer."
|
||||
(interactive)
|
||||
(switch-to-prev-buffer))
|
||||
|
||||
(defun delete-windows-on (&optional buffer-or-name frame)
|
||||
"Delete all windows showing BUFFER-OR-NAME.
|
||||
BUFFER-OR-NAME may be a buffer or the name of an existing buffer
|
||||
and defaults to the current buffer.
|
||||
|
||||
The following non-nil values of the optional argument FRAME
|
||||
have special meanings:
|
||||
|
||||
- t means consider all windows on the selected frame only.
|
||||
|
||||
- `visible' means consider all windows on all visible frames on
|
||||
the current terminal.
|
||||
|
||||
- 0 (the number zero) means consider all windows on all visible
|
||||
and iconified frames on the current terminal.
|
||||
|
||||
- A frame means consider all windows on that frame only.
|
||||
|
||||
Any other value of FRAME means consider all windows on all
|
||||
frames.
|
||||
|
||||
When a window showing BUFFER-OR-NAME is dedicated and the only
|
||||
window of its frame, that frame is deleted when there are other
|
||||
frames left."
|
||||
(interactive "BDelete windows on (buffer):\nP")
|
||||
(let ((buffer (normalize-live-buffer buffer-or-name))
|
||||
;; Handle the "inverted" meaning of the FRAME argument wrt other
|
||||
;; `window-list-1' based function.
|
||||
(all-frames (cond ((not frame) t) ((eq frame t) nil) (t frame))))
|
||||
(dolist (window (window-list-1 nil nil all-frames))
|
||||
(if (eq (window-buffer window) buffer)
|
||||
(let ((deletable (window-deletable-p window)))
|
||||
(cond
|
||||
((eq deletable 'frame)
|
||||
;; Delete frame.
|
||||
(delete-frame (window-frame window)))
|
||||
(deletable
|
||||
;; Delete window only.
|
||||
(delete-window window))
|
||||
(t
|
||||
;; In window switch to previous buffer.
|
||||
(set-window-dedicated-p window nil)
|
||||
(switch-to-prev-buffer window 'bury))))
|
||||
;; If a window doesn't show BUFFER, unrecord BUFFER in it.
|
||||
(unrecord-window-buffer window buffer)))))
|
||||
|
||||
(defun replace-buffer-in-windows (&optional buffer-or-name)
|
||||
"Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
|
||||
BUFFER-OR-NAME may be a buffer or the name of an existing buffer
|
||||
and defaults to the current buffer.
|
||||
|
||||
When a window showing BUFFER-OR-NAME is either dedicated, or the
|
||||
window has no previous buffer, that window is deleted. If that
|
||||
window is the only window on its frame, the frame is deleted too
|
||||
when there are other frames left. If there are no other frames
|
||||
left, some other buffer is displayed in that window.
|
||||
|
||||
This function removes the buffer denoted by BUFFER-OR-NAME from
|
||||
all window-local buffer lists."
|
||||
(let ((buffer (normalize-live-buffer buffer-or-name)))
|
||||
(dolist (window (window-list-1 nil nil t))
|
||||
(if (eq (window-buffer window) buffer)
|
||||
(let ((deletable (window-deletable-p window)))
|
||||
(cond
|
||||
((eq deletable 'frame)
|
||||
;; Delete frame.
|
||||
(delete-frame (window-frame window)))
|
||||
((and (window-dedicated-p window) deletable)
|
||||
;; Delete window.
|
||||
(delete-window window))
|
||||
(t
|
||||
;; Switch to another buffer in window.
|
||||
(set-window-dedicated-p window nil)
|
||||
(switch-to-prev-buffer window 'kill))))
|
||||
;; Unrecord BUFFER in WINDOW.
|
||||
(unrecord-window-buffer window buffer)))))
|
||||
|
||||
(defun quit-restore-window (&optional window kill)
|
||||
"Quit WINDOW in some way.
|
||||
WINDOW must be a live window and defaults to the selected window.
|
||||
Return nil.
|
||||
|
||||
According to information stored in WINDOW's `quit-restore' window
|
||||
parameter either \(1) delete WINDOW and its frame, \(2) delete
|
||||
WINDOW, \(3) restore the buffer previously displayed in WINDOW,
|
||||
or \(4) make WINDOW display some other buffer than the present
|
||||
one. If non-nil, reset `quit-restore' parameter to nil.
|
||||
|
||||
Optional argument KILL non-nil means in addition kill WINDOW's
|
||||
buffer. If KILL is nil, put WINDOW's buffer at the end of the
|
||||
buffer list. Interactively, KILL is the prefix argument."
|
||||
(interactive "i\nP")
|
||||
(setq window (normalize-live-window window))
|
||||
(let ((buffer (window-buffer window))
|
||||
(quit-restore (window-parameter window 'quit-restore))
|
||||
deletable resize)
|
||||
(cond
|
||||
((and (or (and (memq (car-safe quit-restore) '(new-window new-frame))
|
||||
;; Check that WINDOW's buffer is still the same.
|
||||
(eq (window-buffer window) (nth 1 quit-restore)))
|
||||
(window-dedicated-p window))
|
||||
(setq deletable (window-deletable-p window)))
|
||||
;; WINDOW can be deleted.
|
||||
(unrecord-buffer buffer)
|
||||
(if (eq deletable 'frame)
|
||||
;; WINDOW's frame can be deleted.
|
||||
(delete-frame (window-frame window))
|
||||
;; Just delete WINDOW.
|
||||
(delete-window window))
|
||||
;; If the previously selected window is still alive, select it.
|
||||
(when (window-live-p (nth 2 quit-restore))
|
||||
(select-window (nth 2 quit-restore))))
|
||||
((and (buffer-live-p (nth 0 quit-restore))
|
||||
;; The buffer currently shown in WINDOW must still be the
|
||||
;; buffer shown when its `quit-restore' parameter was created
|
||||
;; in the first place.
|
||||
(eq (window-buffer window) (nth 3 quit-restore)))
|
||||
(setq resize (with-current-buffer buffer temp-buffer-resize-mode))
|
||||
;; Unrecord buffer.
|
||||
(unrecord-buffer buffer)
|
||||
(unrecord-window-buffer window buffer)
|
||||
;; Display buffer stored in the quit-restore parameter.
|
||||
(set-window-dedicated-p window nil)
|
||||
(set-window-buffer window (nth 0 quit-restore))
|
||||
(set-window-start window (nth 1 quit-restore))
|
||||
(set-window-point window (nth 2 quit-restore))
|
||||
(when (and resize (/= (nth 4 quit-restore) (window-total-size window)))
|
||||
(resize-window
|
||||
window (- (nth 4 quit-restore) (window-total-size window))))
|
||||
;; Reset the quit-restore parameter.
|
||||
(set-window-parameter window 'quit-restore nil)
|
||||
(when (window-live-p (nth 5 quit-restore))
|
||||
(select-window (nth 5 quit-restore))))
|
||||
(t
|
||||
;; Otherwise, show another buffer in WINDOW and reset the
|
||||
;; quit-restore parameter.
|
||||
(set-window-parameter window 'quit-restore nil)
|
||||
(unrecord-buffer buffer)
|
||||
(switch-to-prev-buffer window 'bury-or-kill)))
|
||||
|
||||
;; Kill WINDOW's old-buffer if requested
|
||||
(when kill (kill-buffer buffer))
|
||||
nil))
|
||||
|
||||
;;; Splitting windows.
|
||||
(defsubst window-split-min-size (&optional horizontal)
|
||||
@ -2569,22 +3149,14 @@ window."
|
||||
(<= (window-start new-window) old-point)
|
||||
(set-window-point new-window old-point)
|
||||
(select-window new-window)))
|
||||
(split-window-save-restore-data new-window old-window)))
|
||||
;; Always copy quit-restore parameter in interactive use.
|
||||
(let ((quit-restore (window-parameter old-window 'quit-restore)))
|
||||
(when quit-restore
|
||||
(set-window-parameter new-window 'quit-restore quit-restore)))
|
||||
new-window))
|
||||
|
||||
(defalias 'split-window-vertically 'split-window-above-each-other)
|
||||
|
||||
;; This is to avoid compiler warnings.
|
||||
(defvar view-return-to-alist)
|
||||
|
||||
(defun split-window-save-restore-data (new-window old-window)
|
||||
(with-current-buffer (window-buffer)
|
||||
(when view-mode
|
||||
(let ((old-info (assq old-window view-return-to-alist)))
|
||||
(when old-info
|
||||
(push (cons new-window (cons (car (cdr old-info)) t))
|
||||
view-return-to-alist))))
|
||||
new-window))
|
||||
|
||||
(defun split-window-side-by-side (&optional size)
|
||||
"Split selected window into two windows side by side.
|
||||
The selected window becomes the left one and gets SIZE columns.
|
||||
@ -2603,7 +3175,12 @@ The selected window remains selected. Return the new window."
|
||||
(when (and size (< size 0) (< (- size) window-min-width))
|
||||
;; `split-window' would not signal an error here.
|
||||
(error "Size of new window too small"))
|
||||
(split-window-save-restore-data (split-window nil size t) old-window)))
|
||||
(setq new-window (split-window nil size t))
|
||||
;; Always copy quit-restore parameter in interactive use.
|
||||
(let ((quit-restore (window-parameter old-window 'quit-restore)))
|
||||
(when quit-restore
|
||||
(set-window-parameter new-window 'quit-restore quit-restore)))
|
||||
new-window))
|
||||
|
||||
(defalias 'split-window-horizontally 'split-window-side-by-side)
|
||||
|
||||
@ -3545,6 +4122,29 @@ consider all visible or iconified frames on the current terminal."
|
||||
(window--even-window-heights window-to-use)
|
||||
(window--display-buffer-2 buffer window-to-use)))))
|
||||
|
||||
(defun display-buffer-other-frame (buffer)
|
||||
"Display buffer BUFFER in another frame.
|
||||
This uses the function `display-buffer' as a subroutine; see
|
||||
its documentation for additional customization information."
|
||||
(interactive "BDisplay buffer in other frame: ")
|
||||
(let ((pop-up-frames t)
|
||||
same-window-buffer-names same-window-regexps
|
||||
;;(old-window (selected-window))
|
||||
new-window)
|
||||
(setq new-window (display-buffer buffer t))
|
||||
;; This may have been here in order to prevent the new frame from hiding
|
||||
;; the old frame. But it does more harm than good.
|
||||
;; Maybe we should call `raise-window' on the old-frame instead? --Stef
|
||||
;;(lower-frame (window-frame new-window))
|
||||
|
||||
;; This may have been here in order to make sure the old-frame gets the
|
||||
;; focus. But not only can it cause an annoying flicker, with some
|
||||
;; window-managers it just makes the window invisible, with no easy
|
||||
;; way to recover it. --Stef
|
||||
;;(make-frame-invisible (window-frame old-window))
|
||||
;;(make-frame-visible (window-frame old-window))
|
||||
))
|
||||
|
||||
(defun pop-to-buffer (buffer-or-name &optional other-window norecord)
|
||||
"Select buffer BUFFER-OR-NAME in some window, preferably a different one.
|
||||
BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
|
||||
@ -3587,6 +4187,130 @@ at the front of the list of recently selected ones."
|
||||
;; input focus and is risen.
|
||||
(select-frame-set-input-focus new-frame))
|
||||
buffer))
|
||||
|
||||
(defun read-buffer-to-switch (prompt)
|
||||
"Read the name of a buffer to switch to, prompting with PROMPT.
|
||||
Return the neame of the buffer as a string.
|
||||
|
||||
This function is intended for the `switch-to-buffer' family of
|
||||
commands since these need to omit the name of the current buffer
|
||||
from the list of completions and default values."
|
||||
(let ((rbts-completion-table (internal-complete-buffer-except)))
|
||||
(minibuffer-with-setup-hook
|
||||
(lambda ()
|
||||
(setq minibuffer-completion-table rbts-completion-table)
|
||||
;; Since rbts-completion-table is built dynamically, we
|
||||
;; can't just add it to the default value of
|
||||
;; icomplete-with-completion-tables, so we add it
|
||||
;; here manually.
|
||||
(if (and (boundp 'icomplete-with-completion-tables)
|
||||
(listp icomplete-with-completion-tables))
|
||||
(set (make-local-variable 'icomplete-with-completion-tables)
|
||||
(cons rbts-completion-table
|
||||
icomplete-with-completion-tables))))
|
||||
(read-buffer prompt (other-buffer (current-buffer))
|
||||
(confirm-nonexistent-file-or-buffer)))))
|
||||
|
||||
(defun normalize-buffer-to-switch-to (buffer-or-name)
|
||||
"Normalize BUFFER-OR-NAME argument of buffer switching functions.
|
||||
If BUFFER-OR-NAME is nil, return the buffer returned by
|
||||
`other-buffer'. Else, if a buffer specified by BUFFER-OR-NAME
|
||||
exists, return that buffer. If no such buffer exists, create a
|
||||
buffer with the name BUFFER-OR-NAME and return that buffer."
|
||||
(if buffer-or-name
|
||||
(or (get-buffer buffer-or-name)
|
||||
(let ((buffer (get-buffer-create buffer-or-name)))
|
||||
(set-buffer-major-mode buffer)
|
||||
buffer))
|
||||
(other-buffer)))
|
||||
|
||||
(defun switch-to-buffer (buffer-or-name &optional norecord)
|
||||
"Switch to buffer BUFFER-OR-NAME in the selected window.
|
||||
If called interactively, prompt for the buffer name using the
|
||||
minibuffer. The variable `confirm-nonexistent-file-or-buffer'
|
||||
determines whether to request confirmation before creating a new
|
||||
buffer.
|
||||
|
||||
BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
|
||||
nil. If BUFFER-OR-NAME is a string that does not identify an
|
||||
existing buffer, create a buffer with that name. If
|
||||
BUFFER-OR-NAME is nil, switch to the buffer returned by
|
||||
`other-buffer'.
|
||||
|
||||
Optional argument NORECORD non-nil means do not put the buffer
|
||||
specified by BUFFER-OR-NAME at the front of the buffer list and
|
||||
do not make the window displaying it the most recently selected
|
||||
one. Return the buffer switched to.
|
||||
|
||||
This function is intended for interactive use only. Lisp
|
||||
functions should call `pop-to-buffer-same-window' instead."
|
||||
(interactive
|
||||
(list (read-buffer-to-switch "Switch to buffer: ")))
|
||||
(let ((buffer (normalize-buffer-to-switch-to buffer-or-name)))
|
||||
(if (and (or (window-minibuffer-p) (eq (window-dedicated-p) t))
|
||||
(not (eq buffer (window-buffer))))
|
||||
;; Cannot switch to another buffer in a minibuffer or strongly
|
||||
;; dedicated window that does not show the buffer already. Call
|
||||
;; `pop-to-buffer' instead.
|
||||
(pop-to-buffer buffer nil norecord)
|
||||
(unless (eq buffer (window-buffer))
|
||||
;; I'm not sure why we should NOT call `set-window-buffer' here,
|
||||
;; but let's keep things as they are (otherwise we could always
|
||||
;; call `pop-to-buffer-same-window' here).
|
||||
(set-window-buffer nil buffer))
|
||||
(unless norecord
|
||||
(select-window (selected-window)))
|
||||
(set-buffer buffer))))
|
||||
|
||||
(defun switch-to-buffer-other-window (buffer-or-name &optional norecord)
|
||||
"Select the buffer specified by BUFFER-OR-NAME in another window.
|
||||
BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
|
||||
nil. Return the buffer switched to.
|
||||
|
||||
If called interactively, prompt for the buffer name using the
|
||||
minibuffer. The variable `confirm-nonexistent-file-or-buffer'
|
||||
determines whether to request confirmation before creating a new
|
||||
buffer.
|
||||
|
||||
If BUFFER-OR-NAME is a string and does not identify an existing
|
||||
buffer, create a new buffer with that name. If BUFFER-OR-NAME is
|
||||
nil, switch to the buffer returned by `other-buffer'.
|
||||
|
||||
Optional second argument NORECORD non-nil means do not put this
|
||||
buffer at the front of the list of recently selected ones.
|
||||
|
||||
This uses the function `display-buffer' as a subroutine; see its
|
||||
documentation for additional customization information."
|
||||
(interactive
|
||||
(list (read-buffer-to-switch "Switch to buffer in other window: ")))
|
||||
(let ((pop-up-windows t)
|
||||
same-window-buffer-names same-window-regexps)
|
||||
(pop-to-buffer buffer-or-name t norecord)))
|
||||
|
||||
(defun switch-to-buffer-other-frame (buffer-or-name &optional norecord)
|
||||
"Switch to buffer BUFFER-OR-NAME in another frame.
|
||||
BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
|
||||
nil. Return the buffer switched to.
|
||||
|
||||
If called interactively, prompt for the buffer name using the
|
||||
minibuffer. The variable `confirm-nonexistent-file-or-buffer'
|
||||
determines whether to request confirmation before creating a new
|
||||
buffer.
|
||||
|
||||
If BUFFER-OR-NAME is a string and does not identify an existing
|
||||
buffer, create a new buffer with that name. If BUFFER-OR-NAME is
|
||||
nil, switch to the buffer returned by `other-buffer'.
|
||||
|
||||
Optional second arg NORECORD non-nil means do not put this
|
||||
buffer at the front of the list of recently selected ones.
|
||||
|
||||
This uses the function `display-buffer' as a subroutine; see its
|
||||
documentation for additional customization information."
|
||||
(interactive
|
||||
(list (read-buffer-to-switch "Switch to buffer in other frame: ")))
|
||||
(let ((pop-up-frames t)
|
||||
same-window-buffer-names same-window-regexps)
|
||||
(pop-to-buffer buffer-or-name t norecord)))
|
||||
|
||||
(defun set-window-text-height (window height)
|
||||
"Set the height in lines of the text display area of WINDOW to HEIGHT.
|
||||
@ -4258,21 +4982,6 @@ active. This function is run by `mouse-autoselect-window-timer'."
|
||||
(run-hooks 'mouse-leave-buffer-hook))
|
||||
(select-window window))))
|
||||
|
||||
(defun delete-other-windows-vertically (&optional window)
|
||||
"Delete the windows in the same column with WINDOW, but not WINDOW itself.
|
||||
This may be a useful alternative binding for \\[delete-other-windows]
|
||||
if you often split windows horizontally."
|
||||
(interactive)
|
||||
(let* ((window (or window (selected-window)))
|
||||
(edges (window-edges window))
|
||||
(w window) delenda)
|
||||
(while (not (eq (setq w (next-window w 1)) window))
|
||||
(let ((e (window-edges w)))
|
||||
(when (and (= (car e) (car edges))
|
||||
(= (caddr e) (caddr edges)))
|
||||
(push w delenda))))
|
||||
(mapc 'delete-window delenda)))
|
||||
|
||||
(defun truncated-partial-width-window-p (&optional window)
|
||||
"Return non-nil if lines in WINDOW are specifically truncated due to its width.
|
||||
WINDOW defaults to the selected window.
|
||||
@ -4293,6 +5002,7 @@ Otherwise, consult the value of `truncate-partial-width-windows'
|
||||
(define-key ctl-x-map "1" 'delete-other-windows)
|
||||
(define-key ctl-x-map "2" 'split-window-above-each-other)
|
||||
(define-key ctl-x-map "3" 'split-window-side-by-side)
|
||||
(define-key ctl-x-map "o" 'other-window)
|
||||
(define-key ctl-x-map "^" 'enlarge-window)
|
||||
(define-key ctl-x-map "}" 'enlarge-window-horizontally)
|
||||
(define-key ctl-x-map "{" 'shrink-window-horizontally)
|
||||
|
@ -1,3 +1,54 @@
|
||||
2011-06-11 Martin Rudalics <rudalics@gmx.at>
|
||||
|
||||
* buffer.c: New Lisp objects Qbuffer_list_update_hook and
|
||||
Qclone_number. Remove external declaration of Qdelete_window.
|
||||
(Fbuffer_list): Rewrite doc-string. Minor restructuring of
|
||||
code.
|
||||
(Fget_buffer_create, Fmake_indirect_buffer, Frename_buffer): Run
|
||||
Qbuffer_list_update_hook if allowed.
|
||||
(Fother_buffer): Rewrite doc-string. Major rewrite for new
|
||||
buffer list implementation.
|
||||
(other_buffer_safely): New function.
|
||||
(Fkill_buffer): Replace call to replace_buffer_in_all_windows by
|
||||
calls to replace_buffer_in_windows and
|
||||
replace_buffer_in_windows_safely. Run Qbuffer_list_update_hook
|
||||
if allowed.
|
||||
(record_buffer): Inhibit quitting and rewrite using quittable
|
||||
functions. Run Qbuffer_list_update_hook if allowed.
|
||||
(Frecord_buffer, Funrecord_buffer): New functions.
|
||||
(switch_to_buffer_1, Fswitch_to_buffer): Remove. Move
|
||||
switch-to-buffer to window.el.
|
||||
(bury-buffer): Move to window.el.
|
||||
(Vbuffer_list_update_hook): New variable.
|
||||
|
||||
* lisp.h (other_buffer_safely): Add prototype in buffer.c
|
||||
section.
|
||||
|
||||
* window.h (resize_frame_windows): Move up in code.
|
||||
(Fwindow_frame): Remove EXFUN.
|
||||
(replace_buffer_in_all_windows): Remove prototype.
|
||||
(replace_buffer_in_windows_safely): Add prototype.
|
||||
|
||||
* window.c: Declare Qdelete_window static again. Move down
|
||||
declaration of select_count.
|
||||
(Fnext_window, Fprevious_window): Rewrite doc-strings.
|
||||
(Fother_window): Move to window.el.
|
||||
(window_loop): Remove DELETE_BUFFER_WINDOWS and UNSHOW_BUFFER
|
||||
cases. Add REPLACE_BUFFER_IN_WINDOWS_SAFELY case.
|
||||
(Fdelete_windows_on, Freplace_buffer_in_windows): Move to
|
||||
window.el.
|
||||
(replace_buffer_in_windows): Implement by calling
|
||||
Qreplace_buffer_in_windows.
|
||||
(replace_buffer_in_all_windows): Remove with some functionality
|
||||
moved into replace_buffer_in_windows_safely.
|
||||
(replace_buffer_in_windows_safely): New function.
|
||||
(select_window_norecord, select_frame_norecord): Move in front
|
||||
of run_window_configuration_change_hook. Remove now obsolete
|
||||
declarations.
|
||||
(Fset_window_buffer): Rewrite doc-string. Call
|
||||
Qrecord_window_buffer.
|
||||
(keys_of_window): Move binding for other-window to window.el.
|
||||
|
||||
2011-06-11 Chong Yidong <cyd@stupidchicken.com>
|
||||
|
||||
* dispextern.h (struct image): Replace data member, whose int_val
|
||||
|
453
src/buffer.c
453
src/buffer.c
@ -131,13 +131,15 @@ static Lisp_Object Qprotected_field;
|
||||
static Lisp_Object QSFundamental; /* A string "Fundamental" */
|
||||
|
||||
static Lisp_Object Qkill_buffer_hook;
|
||||
static Lisp_Object Qbuffer_list_update_hook;
|
||||
|
||||
static Lisp_Object Qget_file_buffer;
|
||||
|
||||
static Lisp_Object Qoverlayp;
|
||||
|
||||
Lisp_Object Qpriority, Qbefore_string, Qafter_string;
|
||||
static Lisp_Object Qevaporate;
|
||||
|
||||
static Lisp_Object Qclone_number, Qevaporate;
|
||||
|
||||
Lisp_Object Qmodification_hooks;
|
||||
Lisp_Object Qinsert_in_front_hooks;
|
||||
@ -171,9 +173,9 @@ Value is nil if OBJECT is not a buffer or if it has been killed. */)
|
||||
|
||||
DEFUN ("buffer-list", Fbuffer_list, Sbuffer_list, 0, 1, 0,
|
||||
doc: /* Return a list of all existing live buffers.
|
||||
If the optional arg FRAME is a frame, we return the buffer list
|
||||
in the proper order for that frame: the buffers in FRAME's `buffer-list'
|
||||
frame parameter come first, followed by the rest of the buffers. */)
|
||||
If the optional arg FRAME is a frame, we return the buffer list in the
|
||||
proper order for that frame: the buffers show in FRAME come first,
|
||||
followed by the rest of the buffers. */)
|
||||
(Lisp_Object frame)
|
||||
{
|
||||
Lisp_Object general;
|
||||
@ -185,9 +187,9 @@ frame parameter come first, followed by the rest of the buffers. */)
|
||||
Lisp_Object args[3];
|
||||
|
||||
CHECK_FRAME (frame);
|
||||
|
||||
framelist = Fcopy_sequence (XFRAME (frame)->buffer_list);
|
||||
prevlist = Fnreverse (Fcopy_sequence (XFRAME (frame)->buried_buffer_list));
|
||||
prevlist = Fnreverse (Fcopy_sequence
|
||||
(XFRAME (frame)->buried_buffer_list));
|
||||
|
||||
/* Remove from GENERAL any buffer that duplicates one in
|
||||
FRAMELIST or PREVLIST. */
|
||||
@ -209,7 +211,7 @@ frame parameter come first, followed by the rest of the buffers. */)
|
||||
args[2] = prevlist;
|
||||
return Fnconc (3, args);
|
||||
}
|
||||
|
||||
else
|
||||
return general;
|
||||
}
|
||||
|
||||
@ -384,6 +386,9 @@ even if it is dead. The return value is never nil. */)
|
||||
/* Put this in the alist of all live buffers. */
|
||||
XSETBUFFER (buffer, b);
|
||||
Vbuffer_alist = nconc2 (Vbuffer_alist, Fcons (Fcons (name, buffer), Qnil));
|
||||
/* And run buffer-list-update-hook. */
|
||||
if (!NILP (Vrun_hooks))
|
||||
call1 (Vrun_hooks, Qbuffer_list_update_hook);
|
||||
|
||||
/* An error in calling the function here (should someone redefine it)
|
||||
can lead to infinite regress until you run out of stack. rms
|
||||
@ -659,6 +664,10 @@ CLONE nil means the indirect buffer's state is reset to default values. */)
|
||||
set_buffer_internal_1 (old_b);
|
||||
}
|
||||
|
||||
/* Run buffer-list-update-hook. */
|
||||
if (!NILP (Vrun_hooks))
|
||||
call1 (Vrun_hooks, Qbuffer_list_update_hook);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -1262,75 +1271,82 @@ This does not change the name of the visited file (if any). */)
|
||||
if (NILP (BVAR (current_buffer, filename))
|
||||
&& !NILP (BVAR (current_buffer, auto_save_file_name)))
|
||||
call0 (intern ("rename-auto-save-file"));
|
||||
|
||||
/* Run buffer-list-update-hook. */
|
||||
if (!NILP (Vrun_hooks))
|
||||
call1 (Vrun_hooks, Qbuffer_list_update_hook);
|
||||
|
||||
/* Refetch since that last call may have done GC. */
|
||||
return BVAR (current_buffer, name);
|
||||
}
|
||||
|
||||
DEFUN ("other-buffer", Fother_buffer, Sother_buffer, 0, 3, 0,
|
||||
doc: /* Return most recently selected buffer other than BUFFER.
|
||||
Buffers not visible in windows are preferred to visible buffers,
|
||||
unless optional second argument VISIBLE-OK is non-nil.
|
||||
If the optional third argument FRAME is non-nil, use that frame's
|
||||
buffer list instead of the selected frame's buffer list.
|
||||
If no other buffer exists, the buffer `*scratch*' is returned.
|
||||
If BUFFER is omitted or nil, some interesting buffer is returned. */)
|
||||
Buffers not visible in windows are preferred to visible buffers, unless
|
||||
optional second argument VISIBLE-OK is non-nil. Ignore the argument
|
||||
BUFFER unless it denotes a live buffer. If the optional third argument
|
||||
FRAME is non-nil, use that frame's buffer list instead of the selected
|
||||
frame's buffer list.
|
||||
|
||||
The buffer is found by scanning the selected or specified frame's buffer
|
||||
list first, followed by the list of all buffers. If no other buffer
|
||||
exists, return the buffer `*scratch*' (creating it if necessary). */)
|
||||
(register Lisp_Object buffer, Lisp_Object visible_ok, Lisp_Object frame)
|
||||
{
|
||||
register Lisp_Object tail, buf, notsogood, tem, pred, add_ons;
|
||||
notsogood = Qnil;
|
||||
Lisp_Object Fset_buffer_major_mode (Lisp_Object buffer);
|
||||
Lisp_Object tail, buf, pred;
|
||||
Lisp_Object notsogood = Qnil;
|
||||
|
||||
if (NILP (frame))
|
||||
frame = selected_frame;
|
||||
|
||||
CHECK_FRAME (frame);
|
||||
|
||||
tail = Vbuffer_alist;
|
||||
pred = frame_buffer_predicate (frame);
|
||||
|
||||
/* Consider buffers that have been seen in the selected frame
|
||||
before other buffers. */
|
||||
|
||||
tem = frame_buffer_list (frame);
|
||||
add_ons = Qnil;
|
||||
while (CONSP (tem))
|
||||
/* Consider buffers that have been seen in the frame first. */
|
||||
tail = XFRAME (frame)->buffer_list;
|
||||
for (; CONSP (tail); tail = XCDR (tail))
|
||||
{
|
||||
if (BUFFERP (XCAR (tem)))
|
||||
add_ons = Fcons (Fcons (Qnil, XCAR (tem)), add_ons);
|
||||
tem = XCDR (tem);
|
||||
buf = XCAR (tail);
|
||||
if (BUFFERP (buf) && !EQ (buf, buffer)
|
||||
&& !NILP (BVAR (XBUFFER (buf), name))
|
||||
&& (SREF (BVAR (XBUFFER (buf), name), 0) != ' ')
|
||||
/* If the frame has a buffer_predicate, disregard buffers that
|
||||
don't fit the predicate. */
|
||||
&& (NILP (pred) || !NILP (call1 (pred, buf))))
|
||||
{
|
||||
if (!NILP (visible_ok)
|
||||
|| NILP (Fget_buffer_window (buf, Qvisible)))
|
||||
return buf;
|
||||
else if (NILP (notsogood))
|
||||
notsogood = buf;
|
||||
}
|
||||
}
|
||||
tail = nconc2 (Fnreverse (add_ons), tail);
|
||||
|
||||
/* Consider alist of all buffers next. */
|
||||
tail = Vbuffer_alist;
|
||||
for (; CONSP (tail); tail = XCDR (tail))
|
||||
{
|
||||
buf = Fcdr (XCAR (tail));
|
||||
if (EQ (buf, buffer))
|
||||
continue;
|
||||
if (NILP (buf))
|
||||
continue;
|
||||
if (NILP (BVAR (XBUFFER (buf), name)))
|
||||
continue;
|
||||
if (SREF (BVAR (XBUFFER (buf), name), 0) == ' ')
|
||||
continue;
|
||||
/* If the selected frame has a buffer_predicate,
|
||||
disregard buffers that don't fit the predicate. */
|
||||
if (!NILP (pred))
|
||||
if (BUFFERP (buf) && !EQ (buf, buffer)
|
||||
&& !NILP (BVAR (XBUFFER (buf), name))
|
||||
&& (SREF (BVAR (XBUFFER (buf), name), 0) != ' ')
|
||||
/* If the frame has a buffer_predicate, disregard buffers that
|
||||
don't fit the predicate. */
|
||||
&& (NILP (pred) || !NILP (call1 (pred, buf))))
|
||||
{
|
||||
tem = call1 (pred, buf);
|
||||
if (NILP (tem))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NILP (visible_ok))
|
||||
tem = Fget_buffer_window (buf, Qvisible);
|
||||
else
|
||||
tem = Qnil;
|
||||
if (NILP (tem))
|
||||
if (!NILP (visible_ok)
|
||||
|| NILP (Fget_buffer_window (buf, Qvisible)))
|
||||
return buf;
|
||||
if (NILP (notsogood))
|
||||
else if (NILP (notsogood))
|
||||
notsogood = buf;
|
||||
}
|
||||
}
|
||||
|
||||
if (!NILP (notsogood))
|
||||
return notsogood;
|
||||
else
|
||||
{
|
||||
buf = Fget_buffer (build_string ("*scratch*"));
|
||||
if (NILP (buf))
|
||||
{
|
||||
@ -1339,6 +1355,37 @@ If BUFFER is omitted or nil, some interesting buffer is returned. */)
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
/* The following function is a safe variant of Fother_buffer: It doesn't
|
||||
pay attention to any frame-local buffer lists, doesn't care about
|
||||
visibility of buffers, and doesn't evaluate any frame predicates. */
|
||||
|
||||
Lisp_Object
|
||||
other_buffer_safely (Lisp_Object buffer)
|
||||
{
|
||||
Lisp_Object Fset_buffer_major_mode (Lisp_Object buffer);
|
||||
Lisp_Object tail, buf;
|
||||
|
||||
tail = Vbuffer_alist;
|
||||
for (; CONSP (tail); tail = XCDR (tail))
|
||||
{
|
||||
buf = Fcdr (XCAR (tail));
|
||||
if (BUFFERP (buf) && !EQ (buf, buffer)
|
||||
&& !NILP (BVAR (XBUFFER (buf), name))
|
||||
&& (SREF (BVAR (XBUFFER (buf), name), 0) != ' '))
|
||||
return buf;
|
||||
}
|
||||
|
||||
buf = Fget_buffer (build_string ("*scratch*"));
|
||||
if (NILP (buf))
|
||||
{
|
||||
buf = Fget_buffer_create (build_string ("*scratch*"));
|
||||
Fset_buffer_major_mode (buf);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
DEFUN ("buffer-enable-undo", Fbuffer_enable_undo, Sbuffer_enable_undo,
|
||||
0, 1, "",
|
||||
@ -1509,13 +1556,20 @@ with SIGHUP. */)
|
||||
if (NILP (BVAR (b, name)))
|
||||
return Qnil;
|
||||
|
||||
/* These may run Lisp code and into infinite loops (if someone
|
||||
insisted on circular lists) so allow quitting here. */
|
||||
replace_buffer_in_windows (buffer);
|
||||
frames_discard_buffer (buffer);
|
||||
|
||||
clear_charpos_cache (b);
|
||||
|
||||
tem = Vinhibit_quit;
|
||||
Vinhibit_quit = Qt;
|
||||
replace_buffer_in_all_windows (buffer);
|
||||
/* Remove the buffer from the list of all buffers. */
|
||||
Vbuffer_alist = Fdelq (Frassq (buffer, Vbuffer_alist), Vbuffer_alist);
|
||||
frames_discard_buffer (buffer);
|
||||
/* If replace_buffer_in_windows didn't do its job correctly fix that
|
||||
now. */
|
||||
replace_buffer_in_windows_safely (buffer);
|
||||
Vinhibit_quit = tem;
|
||||
|
||||
/* Delete any auto-save file, if we saved it in this session.
|
||||
@ -1589,83 +1643,103 @@ with SIGHUP. */)
|
||||
UNBLOCK_INPUT;
|
||||
BVAR (b, undo_list) = Qnil;
|
||||
|
||||
/* Run buffer-list-update-hook. */
|
||||
if (!NILP (Vrun_hooks))
|
||||
call1 (Vrun_hooks, Qbuffer_list_update_hook);
|
||||
|
||||
return Qt;
|
||||
}
|
||||
|
||||
/* Move the assoc for buffer BUF to the front of buffer-alist. Since
|
||||
we do this each time BUF is selected visibly, the more recently
|
||||
selected buffers are always closer to the front of the list. This
|
||||
means that other_buffer is more likely to choose a relevant buffer. */
|
||||
/* Move association for BUFFER to the front of buffer (a)lists. Since
|
||||
we do this each time BUFFER is selected visibly, the more recently
|
||||
selected buffers are always closer to the front of those lists. This
|
||||
means that other_buffer is more likely to choose a relevant buffer.
|
||||
|
||||
Note that this moves BUFFER to the front of the buffer lists of the
|
||||
selected frame even if BUFFER is not shown there. If BUFFER is not
|
||||
shown in the selected frame, consider the present behavior a feature.
|
||||
`select-window' gets this right since it shows BUFFER in the selected
|
||||
window when calling us. */
|
||||
|
||||
void
|
||||
record_buffer (Lisp_Object buf)
|
||||
record_buffer (Lisp_Object buffer)
|
||||
{
|
||||
register Lisp_Object list, prev;
|
||||
Lisp_Object frame;
|
||||
frame = selected_frame;
|
||||
Lisp_Object aelt, link, tem;
|
||||
register struct frame *f = XFRAME (selected_frame);
|
||||
register struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
|
||||
|
||||
prev = Qnil;
|
||||
for (list = Vbuffer_alist; CONSP (list); list = XCDR (list))
|
||||
{
|
||||
if (EQ (XCDR (XCAR (list)), buf))
|
||||
break;
|
||||
prev = list;
|
||||
CHECK_BUFFER (buffer);
|
||||
|
||||
/* Update Vbuffer_alist (we know that it has an entry for BUFFER).
|
||||
Don't allow quitting since this might leave the buffer list in an
|
||||
inconsistent state. */
|
||||
tem = Vinhibit_quit;
|
||||
Vinhibit_quit = Qt;
|
||||
aelt = Frassq (buffer, Vbuffer_alist);
|
||||
link = Fmemq (aelt, Vbuffer_alist);
|
||||
Vbuffer_alist = Fdelq (aelt, Vbuffer_alist);
|
||||
XSETCDR (link, Vbuffer_alist);
|
||||
Vbuffer_alist = link;
|
||||
Vinhibit_quit = tem;
|
||||
|
||||
/* Update buffer list of selected frame. */
|
||||
f->buffer_list = Fcons (buffer, Fdelq (buffer, f->buffer_list));
|
||||
f->buried_buffer_list = Fdelq (buffer, f->buried_buffer_list);
|
||||
|
||||
/* Run buffer-list-update-hook. */
|
||||
if (!NILP (Vrun_hooks))
|
||||
call1 (Vrun_hooks, Qbuffer_list_update_hook);
|
||||
}
|
||||
|
||||
/* Effectively do Vbuffer_alist = Fdelq (list, Vbuffer_alist);
|
||||
we cannot use Fdelq itself here because it allows quitting. */
|
||||
|
||||
if (NILP (prev))
|
||||
Vbuffer_alist = XCDR (Vbuffer_alist);
|
||||
else
|
||||
XSETCDR (prev, XCDR (XCDR (prev)));
|
||||
|
||||
XSETCDR (list, Vbuffer_alist);
|
||||
Vbuffer_alist = list;
|
||||
|
||||
/* Effectively do a delq on buried_buffer_list. */
|
||||
|
||||
prev = Qnil;
|
||||
for (list = XFRAME (frame)->buried_buffer_list; CONSP (list);
|
||||
list = XCDR (list))
|
||||
DEFUN ("record-buffer", Frecord_buffer, Srecord_buffer, 1, 1, 0,
|
||||
doc: /* Move BUFFER to the front of the buffer list.
|
||||
Return BUFFER. */)
|
||||
(Lisp_Object buffer)
|
||||
{
|
||||
if (EQ (XCAR (list), buf))
|
||||
{
|
||||
if (NILP (prev))
|
||||
XFRAME (frame)->buried_buffer_list = XCDR (list);
|
||||
else
|
||||
XSETCDR (prev, XCDR (XCDR (prev)));
|
||||
break;
|
||||
}
|
||||
prev = list;
|
||||
CHECK_BUFFER (buffer);
|
||||
|
||||
record_buffer (buffer);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Now move this buffer to the front of frame_buffer_list also. */
|
||||
/* Move BUFFER to the end of the buffer (a)lists. Do nothing if the
|
||||
buffer is killed. For the selected frame's buffer list this moves
|
||||
BUFFER to its end even if it was never shown in that frame. If
|
||||
this happens we have a feature, hence `unrecord-buffer' should be
|
||||
called only when BUFFER was shown in the selected frame. */
|
||||
|
||||
prev = Qnil;
|
||||
for (list = frame_buffer_list (frame); CONSP (list);
|
||||
list = XCDR (list))
|
||||
DEFUN ("unrecord-buffer", Funrecord_buffer, Sunrecord_buffer, 1, 1, 0,
|
||||
doc: /* Move BUFFER to the end of the buffer list.
|
||||
Return BUFFER. */)
|
||||
(Lisp_Object buffer)
|
||||
{
|
||||
if (EQ (XCAR (list), buf))
|
||||
break;
|
||||
prev = list;
|
||||
}
|
||||
Lisp_Object aelt, link, tem;
|
||||
register struct frame *f = XFRAME (selected_frame);
|
||||
|
||||
/* Effectively do delq. */
|
||||
CHECK_BUFFER (buffer);
|
||||
|
||||
if (CONSP (list))
|
||||
{
|
||||
if (NILP (prev))
|
||||
set_frame_buffer_list (frame,
|
||||
XCDR (frame_buffer_list (frame)));
|
||||
else
|
||||
XSETCDR (prev, XCDR (XCDR (prev)));
|
||||
/* Update Vbuffer_alist (we know that it has an entry for BUFFER).
|
||||
Don't allow quitting since this might leave the buffer list in an
|
||||
inconsistent state. */
|
||||
tem = Vinhibit_quit;
|
||||
Vinhibit_quit = Qt;
|
||||
aelt = Frassq (buffer, Vbuffer_alist);
|
||||
link = Fmemq (aelt, Vbuffer_alist);
|
||||
Vbuffer_alist = Fdelq (aelt, Vbuffer_alist);
|
||||
XSETCDR (link, Qnil);
|
||||
Vbuffer_alist = nconc2 (Vbuffer_alist, link);
|
||||
Vinhibit_quit = tem;
|
||||
|
||||
XSETCDR (list, frame_buffer_list (frame));
|
||||
set_frame_buffer_list (frame, list);
|
||||
}
|
||||
else
|
||||
set_frame_buffer_list (frame, Fcons (buf, frame_buffer_list (frame)));
|
||||
/* Update buffer lists of selected frame. */
|
||||
f->buffer_list = Fdelq (buffer, f->buffer_list);
|
||||
f->buried_buffer_list = Fcons (buffer, Fdelq (buffer, f->buried_buffer_list));
|
||||
|
||||
/* Run buffer-list-update-hook. */
|
||||
if (!NILP (Vrun_hooks))
|
||||
call1 (Vrun_hooks, Qbuffer_list_update_hook);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
DEFUN ("set-buffer-major-mode", Fset_buffer_major_mode, Sset_buffer_major_mode, 1, 1, 0,
|
||||
@ -1708,86 +1782,6 @@ the current buffer's major mode. */)
|
||||
return unbind_to (count, Qnil);
|
||||
}
|
||||
|
||||
/* Switch to buffer BUFFER in the selected window.
|
||||
If NORECORD is non-nil, don't call record_buffer. */
|
||||
|
||||
static Lisp_Object
|
||||
switch_to_buffer_1 (Lisp_Object buffer_or_name, Lisp_Object norecord)
|
||||
{
|
||||
register Lisp_Object buffer;
|
||||
|
||||
if (NILP (buffer_or_name))
|
||||
buffer = Fother_buffer (Fcurrent_buffer (), Qnil, Qnil);
|
||||
else
|
||||
{
|
||||
buffer = Fget_buffer (buffer_or_name);
|
||||
if (NILP (buffer))
|
||||
{
|
||||
buffer = Fget_buffer_create (buffer_or_name);
|
||||
Fset_buffer_major_mode (buffer);
|
||||
}
|
||||
}
|
||||
Fset_buffer (buffer);
|
||||
if (NILP (norecord))
|
||||
record_buffer (buffer);
|
||||
|
||||
Fset_window_buffer (EQ (selected_window, minibuf_window)
|
||||
? Fnext_window (minibuf_window, Qnil, Qnil)
|
||||
: selected_window,
|
||||
buffer, Qnil);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
DEFUN ("switch-to-buffer", Fswitch_to_buffer, Sswitch_to_buffer, 1, 2,
|
||||
"(list (read-buffer-to-switch \"Switch to buffer: \"))",
|
||||
doc: /* Make BUFFER-OR-NAME current and display it in selected window.
|
||||
BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or
|
||||
nil. Return the buffer switched to.
|
||||
|
||||
If BUFFER-OR-NAME is a string and does not identify an existing
|
||||
buffer, create a new buffer with that name. Interactively, if
|
||||
`confirm-nonexistent-file-or-buffer' is non-nil, request
|
||||
confirmation before creating a new buffer. If BUFFER-OR-NAME is
|
||||
nil, switch to buffer returned by `other-buffer'.
|
||||
|
||||
Optional second arg NORECORD non-nil means do not put this buffer
|
||||
at the front of the list of recently selected ones. This
|
||||
function returns the buffer it switched to as a Lisp object.
|
||||
|
||||
If the selected window is the minibuffer window or dedicated to
|
||||
its buffer, use `pop-to-buffer' for displaying the buffer.
|
||||
|
||||
WARNING: This is NOT the way to work on another buffer temporarily
|
||||
within a Lisp program! Use `set-buffer' instead. That avoids
|
||||
messing with the window-buffer correspondences. */)
|
||||
(Lisp_Object buffer_or_name, Lisp_Object norecord)
|
||||
{
|
||||
if (EQ (buffer_or_name, Fwindow_buffer (selected_window)))
|
||||
{
|
||||
/* Basically a NOP. Avoid signalling an error in the case where
|
||||
the selected window is dedicated, or a minibuffer. */
|
||||
|
||||
/* But do put this buffer at the front of the buffer list, unless
|
||||
that has been inhibited. Note that even if BUFFER-OR-NAME is
|
||||
at the front of the main buffer-list already, we still want to
|
||||
move it to the front of the frame's buffer list. */
|
||||
if (NILP (norecord))
|
||||
record_buffer (buffer_or_name);
|
||||
return Fset_buffer (buffer_or_name);
|
||||
}
|
||||
else if (EQ (minibuf_window, selected_window)
|
||||
/* If `dedicated' is neither nil nor t, it means it's
|
||||
dedicatedness can be overridden by an explicit request
|
||||
such as a call to switch-to-buffer. */
|
||||
|| EQ (Fwindow_dedicated_p (selected_window), Qt))
|
||||
/* We can't use the selected window so let `pop-to-buffer' try some
|
||||
other window. */
|
||||
return call3 (intern ("pop-to-buffer"), buffer_or_name, Qnil, norecord);
|
||||
else
|
||||
return switch_to_buffer_1 (buffer_or_name, norecord);
|
||||
}
|
||||
|
||||
DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0,
|
||||
doc: /* Return the current buffer as a Lisp object. */)
|
||||
(void)
|
||||
@ -1937,70 +1931,6 @@ DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only,
|
||||
xsignal1 (Qbuffer_read_only, Fcurrent_buffer ());
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
extern Lisp_Object Qdelete_window;
|
||||
|
||||
DEFUN ("bury-buffer", Fbury_buffer, Sbury_buffer, 0, 1, "",
|
||||
doc: /* Put BUFFER-OR-NAME at the end of the list of all buffers.
|
||||
There it is the least likely candidate for `other-buffer' to return;
|
||||
thus, the least likely buffer for \\[switch-to-buffer] to select by
|
||||
default.
|
||||
|
||||
The argument may be a buffer name or an actual buffer object. If
|
||||
BUFFER-OR-NAME is nil or omitted, bury the current buffer and remove it
|
||||
from the selected window if it is displayed there. If the selected
|
||||
window is dedicated to its buffer, delete that window if there are other
|
||||
windows on the same frame. If the selected window is the only window on
|
||||
its frame, iconify that frame. */)
|
||||
(register Lisp_Object buffer_or_name)
|
||||
{
|
||||
Lisp_Object buffer;
|
||||
|
||||
/* Figure out what buffer we're going to bury. */
|
||||
if (NILP (buffer_or_name))
|
||||
{
|
||||
Lisp_Object tem;
|
||||
XSETBUFFER (buffer, current_buffer);
|
||||
|
||||
tem = Fwindow_buffer (selected_window);
|
||||
/* If we're burying the current buffer, unshow it. */
|
||||
if (EQ (buffer, tem))
|
||||
{
|
||||
if (NILP (Fwindow_dedicated_p (selected_window)))
|
||||
Fswitch_to_buffer (Fother_buffer (buffer, Qnil, Qnil), Qnil);
|
||||
else if (NILP (XWINDOW (selected_window)->parent))
|
||||
Ficonify_frame (Fwindow_frame (selected_window));
|
||||
else
|
||||
call1 (Qdelete_window, selected_window);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = Fget_buffer (buffer_or_name);
|
||||
if (NILP (buffer))
|
||||
nsberror (buffer_or_name);
|
||||
}
|
||||
|
||||
/* Move buffer to the end of the buffer list. Do nothing if the
|
||||
buffer is killed. */
|
||||
if (!NILP (BVAR (XBUFFER (buffer), name)))
|
||||
{
|
||||
Lisp_Object aelt, list;
|
||||
|
||||
aelt = Frassq (buffer, Vbuffer_alist);
|
||||
list = Fmemq (aelt, Vbuffer_alist);
|
||||
Vbuffer_alist = Fdelq (aelt, Vbuffer_alist);
|
||||
XSETCDR (list, Qnil);
|
||||
Vbuffer_alist = nconc2 (Vbuffer_alist, list);
|
||||
|
||||
XFRAME (selected_frame)->buffer_list
|
||||
= Fdelq (buffer, XFRAME (selected_frame)->buffer_list);
|
||||
XFRAME (selected_frame)->buried_buffer_list
|
||||
= Fcons (buffer, Fdelq (buffer, XFRAME (selected_frame)->buried_buffer_list));
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
DEFUN ("erase-buffer", Ferase_buffer, Serase_buffer, 0, 0, "*",
|
||||
doc: /* Delete the entire contents of the current buffer.
|
||||
@ -6101,6 +6031,15 @@ The function `kill-all-local-variables' runs this before doing anything else. *
|
||||
Qchange_major_mode_hook = intern_c_string ("change-major-mode-hook");
|
||||
staticpro (&Qchange_major_mode_hook);
|
||||
|
||||
DEFVAR_LISP ("buffer-list-update-hook", Vbuffer_list_update_hook,
|
||||
doc: /* Hook run when the buffer list changes.
|
||||
Functions running this hook are `get-buffer-create',
|
||||
`make-indirect-buffer', `rename-buffer', `kill-buffer',
|
||||
`record-buffer' and `unrecord-buffer'. */);
|
||||
Vbuffer_list_update_hook = Qnil;
|
||||
Qbuffer_list_update_hook = intern_c_string ("buffer-list-update-hook");
|
||||
staticpro (&Qbuffer_list_update_hook);
|
||||
|
||||
defsubr (&Sbuffer_live_p);
|
||||
defsubr (&Sbuffer_list);
|
||||
defsubr (&Sget_buffer);
|
||||
@ -6122,12 +6061,12 @@ The function `kill-all-local-variables' runs this before doing anything else. *
|
||||
defsubr (&Sother_buffer);
|
||||
defsubr (&Sbuffer_enable_undo);
|
||||
defsubr (&Skill_buffer);
|
||||
defsubr (&Srecord_buffer);
|
||||
defsubr (&Sunrecord_buffer);
|
||||
defsubr (&Sset_buffer_major_mode);
|
||||
defsubr (&Sswitch_to_buffer);
|
||||
defsubr (&Scurrent_buffer);
|
||||
defsubr (&Sset_buffer);
|
||||
defsubr (&Sbarf_if_buffer_read_only);
|
||||
defsubr (&Sbury_buffer);
|
||||
defsubr (&Serase_buffer);
|
||||
defsubr (&Sbuffer_swap_text);
|
||||
defsubr (&Sset_buffer_multibyte);
|
||||
|
@ -3011,6 +3011,7 @@ extern Lisp_Object set_buffer_if_live (Lisp_Object);
|
||||
EXFUN (Fbarf_if_buffer_read_only, 0);
|
||||
EXFUN (Fcurrent_buffer, 0);
|
||||
EXFUN (Fother_buffer, 3);
|
||||
extern Lisp_Object other_buffer_safely (Lisp_Object);
|
||||
EXFUN (Foverlay_get, 2);
|
||||
EXFUN (Fbuffer_modified_p, 1);
|
||||
EXFUN (Fset_buffer_modified_p, 1);
|
||||
|
380
src/window.c
380
src/window.c
@ -50,9 +50,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
||||
#include "nsterm.h"
|
||||
#endif
|
||||
|
||||
Lisp_Object Qwindowp, Qwindow_live_p, Qdelete_window;
|
||||
Lisp_Object Qwindowp, Qwindow_live_p;
|
||||
static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer;
|
||||
static Lisp_Object Qwindow_deletable_p, Qdisplay_buffer;
|
||||
static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
|
||||
static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
|
||||
static Lisp_Object Qresize_root_window, Qresize_root_window_vertically;
|
||||
static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
|
||||
@ -310,6 +310,8 @@ selected windows appears and to which many commands apply. */)
|
||||
return selected_window;
|
||||
}
|
||||
|
||||
int window_select_count;
|
||||
|
||||
/* If select_window is called with inhibit_point_swap non-zero it will
|
||||
not store point of the old selected window's buffer back into that
|
||||
window's pointm slot. This is needed by Fset_window_configuration to
|
||||
@ -2210,33 +2212,30 @@ next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, in
|
||||
|
||||
DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
|
||||
doc: /* Return window following WINDOW in cyclic ordering of windows.
|
||||
WINDOW defaults to the selected window. The optional arguments
|
||||
MINIBUF and ALL-FRAMES specify the set of windows to consider.
|
||||
WINDOW must be a live window and defaults to the selected one. The
|
||||
optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
|
||||
consider.
|
||||
|
||||
MINIBUF t means consider the minibuffer window even if the
|
||||
minibuffer is not active. MINIBUF nil or omitted means consider
|
||||
the minibuffer window only if the minibuffer is active. Any
|
||||
other value means do not consider the minibuffer window even if
|
||||
the minibuffer is active.
|
||||
MINIBUF nil or omitted means consider the minibuffer window only if the
|
||||
minibuffer is active. MINIBUF t means consider the minibuffer window
|
||||
even if the minibuffer is not active. Any other value means do not
|
||||
consider the minibuffer window even if the minibuffer is active.
|
||||
|
||||
Several frames may share a single minibuffer; if the minibuffer
|
||||
is active, all windows on all frames that share that minibuffer
|
||||
are considered too. Therefore, if you are using a separate
|
||||
minibuffer frame and the minibuffer is active and MINIBUF says it
|
||||
counts, `next-window' considers the windows in the frame from
|
||||
which you entered the minibuffer, as well as the minibuffer
|
||||
window.
|
||||
ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
|
||||
plus the minibuffer window if specified by the MINIBUF argument. If the
|
||||
minibuffer counts, consider all windows on all frames that share that
|
||||
minibuffer too. The following non-nil values of ALL-FRAMES have special
|
||||
meanings:
|
||||
|
||||
- t means consider all windows on all existing frames.
|
||||
|
||||
- `visible' means consider all windows on all visible frames.
|
||||
|
||||
- 0 (the number zero) means consider all windows on all visible and
|
||||
iconified frames.
|
||||
|
||||
- A frame means consider all windows on that frame only.
|
||||
|
||||
ALL-FRAMES nil or omitted means consider all windows on WINDOW's
|
||||
frame, plus the minibuffer window if specified by the MINIBUF
|
||||
argument, see above. If the minibuffer counts, consider all
|
||||
windows on all frames that share that minibuffer too.
|
||||
ALL-FRAMES t means consider all windows on all existing frames.
|
||||
ALL-FRAMES `visible' means consider all windows on all visible
|
||||
frames on the current terminal.
|
||||
ALL-FRAMES 0 means consider all windows on all visible and
|
||||
iconified frames on the current terminal.
|
||||
ALL-FRAMES a frame means consider all windows on that frame only.
|
||||
Anything else means consider all windows on WINDOW's frame and no
|
||||
others.
|
||||
|
||||
@ -2252,9 +2251,32 @@ windows, eventually ending up back at the window you started with.
|
||||
|
||||
DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
|
||||
doc: /* Return window preceding WINDOW in cyclic ordering of windows.
|
||||
WINDOW defaults to the selected window. The optional arguments
|
||||
MINIBUF and ALL-FRAMES specify the set of windows to consider.
|
||||
For the precise meaning of these arguments see `next-window'.
|
||||
WINDOW must be a live window and defaults to the selected one. The
|
||||
optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
|
||||
consider.
|
||||
|
||||
MINIBUF nil or omitted means consider the minibuffer window only if the
|
||||
minibuffer is active. MINIBUF t means consider the minibuffer window
|
||||
even if the minibuffer is not active. Any other value means do not
|
||||
consider the minibuffer window even if the minibuffer is active.
|
||||
|
||||
ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
|
||||
plus the minibuffer window if specified by the MINIBUF argument. If the
|
||||
minibuffer counts, consider all windows on all frames that share that
|
||||
minibuffer too. The following non-nil values of ALL-FRAMES have special
|
||||
meanings:
|
||||
|
||||
- t means consider all windows on all existing frames.
|
||||
|
||||
- `visible' means consider all windows on all visible frames.
|
||||
|
||||
- 0 (the number zero) means consider all windows on all visible and
|
||||
iconified frames.
|
||||
|
||||
- A frame means consider all windows on that frame only.
|
||||
|
||||
Anything else means consider all windows on WINDOW's frame and no
|
||||
others.
|
||||
|
||||
If you use consistent values for MINIBUF and ALL-FRAMES, you can
|
||||
use `previous-window' to iterate through the entire cycle of
|
||||
@ -2267,37 +2289,6 @@ reverse order. */)
|
||||
}
|
||||
|
||||
|
||||
DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
|
||||
doc: /* Select another window in cyclic ordering of windows.
|
||||
COUNT specifies the number of windows to skip, starting with the
|
||||
selected window, before making the selection. If COUNT is
|
||||
positive, skip COUNT windows forwards. If COUNT is negative,
|
||||
skip -COUNT windows backwards. COUNT zero means do not skip any
|
||||
window, so select the selected window. In an interactive call,
|
||||
COUNT is the numeric prefix argument. Return nil.
|
||||
|
||||
This function uses `next-window' for finding the window to select.
|
||||
The argument ALL-FRAMES has the same meaning as in `next-window',
|
||||
but the MINIBUF argument of `next-window' is always effectively
|
||||
nil. */)
|
||||
(Lisp_Object count, Lisp_Object all_frames)
|
||||
{
|
||||
Lisp_Object window;
|
||||
int i;
|
||||
|
||||
CHECK_NUMBER (count);
|
||||
window = selected_window;
|
||||
|
||||
for (i = XINT (count); i > 0; --i)
|
||||
window = Fnext_window (window, Qnil, all_frames);
|
||||
for (; i < 0; ++i)
|
||||
window = Fprevious_window (window, Qnil, all_frames);
|
||||
|
||||
Fselect_window (window, Qnil);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
/* Return a list of windows in cyclic ordering. Arguments are like
|
||||
for `next-window'. */
|
||||
|
||||
@ -2398,8 +2389,7 @@ enum window_loop
|
||||
{
|
||||
WINDOW_LOOP_UNUSED,
|
||||
GET_BUFFER_WINDOW, /* Arg is buffer */
|
||||
DELETE_BUFFER_WINDOWS, /* Arg is buffer */
|
||||
UNSHOW_BUFFER, /* Arg is buffer */
|
||||
REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
|
||||
REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
|
||||
CHECK_ALL_WINDOWS
|
||||
};
|
||||
@ -2408,6 +2398,7 @@ static Lisp_Object
|
||||
window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
|
||||
{
|
||||
Lisp_Object window, windows, best_window, frame_arg;
|
||||
int frame_best_window_flag = 0;
|
||||
struct frame *f;
|
||||
struct gcpro gcpro1;
|
||||
|
||||
@ -2457,111 +2448,52 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame
|
||||
is visible, since Fwindow_list skips non-visible frames if
|
||||
that is desired, under the control of frame_arg. */
|
||||
if (!MINI_WINDOW_P (w)
|
||||
/* For UNSHOW_BUFFER, we must always consider all windows. */
|
||||
|| type == UNSHOW_BUFFER
|
||||
/* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
|
||||
consider all windows. */
|
||||
|| type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
|
||||
|| (mini && minibuf_level > 0))
|
||||
switch (type)
|
||||
{
|
||||
case GET_BUFFER_WINDOW:
|
||||
if (EQ (w->buffer, obj)
|
||||
/* Don't find any minibuffer window
|
||||
except the one that is currently in use. */
|
||||
&& (MINI_WINDOW_P (w)
|
||||
? EQ (window, minibuf_window)
|
||||
: 1))
|
||||
/* Don't find any minibuffer window except the one that
|
||||
is currently in use. */
|
||||
&& (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
|
||||
{
|
||||
if (NILP (best_window))
|
||||
best_window = window;
|
||||
else if (EQ (window, selected_window))
|
||||
/* Prefer to return selected-window. */
|
||||
if (EQ (window, selected_window))
|
||||
/* Preferably return the selected window. */
|
||||
RETURN_UNGCPRO (window);
|
||||
else if (EQ (Fwindow_frame (window), selected_frame))
|
||||
/* Prefer windows on the current frame. */
|
||||
else if (EQ (XWINDOW (window)->frame, selected_frame)
|
||||
&& !frame_best_window_flag)
|
||||
/* Prefer windows on the current frame (but don't
|
||||
choose another one if we have one already). */
|
||||
{
|
||||
best_window = window;
|
||||
frame_best_window_flag = 1;
|
||||
}
|
||||
else if (NILP (best_window))
|
||||
best_window = window;
|
||||
}
|
||||
break;
|
||||
|
||||
case DELETE_BUFFER_WINDOWS:
|
||||
case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
|
||||
/* We could simply check whether the buffer shown by window
|
||||
is live, and show another buffer in case it isn't. */
|
||||
if (EQ (w->buffer, obj))
|
||||
{
|
||||
struct frame *fr = XFRAME (WINDOW_FRAME (w));
|
||||
|
||||
/* If this window is dedicated, and in a frame of its own,
|
||||
kill the frame. */
|
||||
if (EQ (window, FRAME_ROOT_WINDOW (fr))
|
||||
&& !NILP (w->dedicated)
|
||||
&& other_visible_frames (fr))
|
||||
{
|
||||
/* Skip the other windows on this frame.
|
||||
There might be one, the minibuffer! */
|
||||
while (CONSP (XCDR (windows))
|
||||
&& EQ (XWINDOW (XCAR (windows))->frame,
|
||||
XWINDOW (XCAR (XCDR (windows)))->frame))
|
||||
windows = XCDR (windows);
|
||||
|
||||
/* Now we can safely delete the frame. */
|
||||
delete_frame (w->frame, Qnil);
|
||||
}
|
||||
else if (NILP (w->parent))
|
||||
{
|
||||
/* If we're deleting the buffer displayed in the
|
||||
only window on the frame, find a new buffer to
|
||||
display there. */
|
||||
Lisp_Object buffer;
|
||||
buffer = Fother_buffer (obj, Qnil, w->frame);
|
||||
/* Reset dedicated state of window. */
|
||||
/* Undedicate WINDOW. */
|
||||
w->dedicated = Qnil;
|
||||
Fset_window_buffer (window, buffer, Qnil);
|
||||
if (EQ (window, selected_window))
|
||||
/* Make WINDOW show the buffer returned by
|
||||
other_buffer_safely, don't run any hooks. */
|
||||
set_window_buffer
|
||||
(window, other_buffer_safely (w->buffer), 0, 0);
|
||||
/* If WINDOW is the selected window, make its buffer
|
||||
current. But do so only if the window shows the
|
||||
current buffer (Bug#6454). */
|
||||
if (EQ (window, selected_window)
|
||||
&& XBUFFER (w->buffer) == current_buffer)
|
||||
Fset_buffer (w->buffer);
|
||||
}
|
||||
else
|
||||
call1 (Qdelete_window, window);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNSHOW_BUFFER:
|
||||
if (EQ (w->buffer, obj))
|
||||
{
|
||||
Lisp_Object buffer;
|
||||
struct frame *fr = XFRAME (w->frame);
|
||||
|
||||
/* Find another buffer to show in this window. */
|
||||
buffer = Fother_buffer (obj, Qnil, w->frame);
|
||||
|
||||
/* If this window is dedicated, and in a frame of its own,
|
||||
kill the frame. */
|
||||
if (EQ (window, FRAME_ROOT_WINDOW (fr))
|
||||
&& !NILP (w->dedicated)
|
||||
&& other_visible_frames (fr))
|
||||
{
|
||||
/* Skip the other windows on this frame.
|
||||
There might be one, the minibuffer! */
|
||||
while (CONSP (XCDR (windows))
|
||||
&& EQ (XWINDOW (XCAR (windows))->frame,
|
||||
XWINDOW (XCAR (XCDR (windows)))->frame))
|
||||
windows = XCDR (windows);
|
||||
|
||||
/* Now we can safely delete the frame. */
|
||||
delete_frame (w->frame, Qnil);
|
||||
}
|
||||
else if (!NILP (w->dedicated) && !NILP (w->parent))
|
||||
{
|
||||
Lisp_Object window_to_delete;
|
||||
XSETWINDOW (window_to_delete, w);
|
||||
/* If this window is dedicated and not the only window
|
||||
in its frame, then kill it. */
|
||||
call1 (Qdelete_window, window_to_delete);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise show a different buffer in the window. */
|
||||
w->dedicated = Qnil;
|
||||
Fset_window_buffer (window, buffer, Qnil);
|
||||
if (EQ (window, selected_window))
|
||||
Fset_buffer (w->buffer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REDISPLAY_BUFFER_WINDOWS:
|
||||
@ -2875,85 +2807,26 @@ window-start value is reasonable when this function is called. */)
|
||||
}
|
||||
|
||||
|
||||
DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
|
||||
0, 2, "bDelete windows on (buffer): ",
|
||||
doc: /* Delete all windows showing BUFFER-OR-NAME.
|
||||
BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
|
||||
defaults to the current buffer.
|
||||
|
||||
Optional second argument FRAME controls which frames are affected.
|
||||
If optional argument FRAME is `visible', search all visible frames.
|
||||
If FRAME is 0, search all visible and iconified frames.
|
||||
If FRAME is nil, search all frames.
|
||||
If FRAME is t, search only the selected frame.
|
||||
If FRAME is a frame, search only that frame.
|
||||
When a window showing BUFFER-OR-NAME is dedicated and the only window of
|
||||
its frame, that frame is deleted when there are other frames left. */)
|
||||
(Lisp_Object buffer_or_name, Lisp_Object frame)
|
||||
void
|
||||
replace_buffer_in_windows (Lisp_Object buffer)
|
||||
{
|
||||
Lisp_Object buffer;
|
||||
|
||||
/* FRAME uses t and nil to mean the opposite of what window_loop
|
||||
expects. */
|
||||
if (NILP (frame))
|
||||
frame = Qt;
|
||||
else if (EQ (frame, Qt))
|
||||
frame = Qnil;
|
||||
|
||||
if (NILP (buffer_or_name))
|
||||
buffer = Fcurrent_buffer ();
|
||||
else
|
||||
{
|
||||
buffer = Fget_buffer (buffer_or_name);
|
||||
CHECK_BUFFER (buffer);
|
||||
call1 (Qreplace_buffer_in_windows, buffer);
|
||||
}
|
||||
|
||||
window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
|
||||
Sreplace_buffer_in_windows,
|
||||
0, 1, "bReplace buffer in windows: ",
|
||||
doc: /* Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
|
||||
BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
|
||||
defaults to the current buffer.
|
||||
|
||||
When a window showing BUFFER-OR-NAME is dedicated that window is
|
||||
deleted. If that window is the only window on its frame, that frame is
|
||||
deleted too when there are other frames left. If there are no other
|
||||
frames left, some other buffer is displayed in that window. */)
|
||||
(Lisp_Object buffer_or_name)
|
||||
{
|
||||
Lisp_Object buffer;
|
||||
|
||||
if (NILP (buffer_or_name))
|
||||
buffer = Fcurrent_buffer ();
|
||||
else
|
||||
{
|
||||
buffer = Fget_buffer (buffer_or_name);
|
||||
CHECK_BUFFER (buffer);
|
||||
}
|
||||
|
||||
window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
/* Replace BUFFER with some other buffer in all windows
|
||||
of all frames, even those on other keyboards. */
|
||||
/* Safely replace BUFFER with some other buffer in all windows of all
|
||||
frames, even those on other keyboards. */
|
||||
|
||||
void
|
||||
replace_buffer_in_all_windows (Lisp_Object buffer)
|
||||
replace_buffer_in_windows_safely (Lisp_Object buffer)
|
||||
{
|
||||
Lisp_Object tail, frame;
|
||||
|
||||
/* A single call to window_loop won't do the job
|
||||
because it only considers frames on the current keyboard.
|
||||
So loop manually over frames, and handle each one. */
|
||||
/* A single call to window_loop won't do the job because it only
|
||||
considers frames on the current keyboard. So loop manually over
|
||||
frames, and handle each one. */
|
||||
FOR_EACH_FRAME (tail, frame)
|
||||
window_loop (UNSHOW_BUFFER, buffer, 1, frame);
|
||||
window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
|
||||
}
|
||||
|
||||
/* If *ROWS or *COLS are too small a size for FRAME, set them to the
|
||||
@ -3014,8 +2887,6 @@ adjust_window_margins (struct window *w)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int window_select_count;
|
||||
|
||||
static Lisp_Object Fset_window_margins (Lisp_Object, Lisp_Object, Lisp_Object);
|
||||
static Lisp_Object Fset_window_fringes (Lisp_Object, Lisp_Object, Lisp_Object,
|
||||
Lisp_Object);
|
||||
@ -3023,6 +2894,8 @@ static Lisp_Object Fset_window_scroll_bars (Lisp_Object, Lisp_Object,
|
||||
Lisp_Object, Lisp_Object);
|
||||
static Lisp_Object Fset_window_vscroll (Lisp_Object, Lisp_Object, Lisp_Object);
|
||||
|
||||
/* The following three routines are needed for running a window's
|
||||
configuration change hook. */
|
||||
static void
|
||||
run_funs (Lisp_Object funs)
|
||||
{
|
||||
@ -3031,8 +2904,19 @@ run_funs (Lisp_Object funs)
|
||||
call0 (XCAR (funs));
|
||||
}
|
||||
|
||||
static Lisp_Object select_window_norecord (Lisp_Object window);
|
||||
static Lisp_Object select_frame_norecord (Lisp_Object frame);
|
||||
static Lisp_Object
|
||||
select_window_norecord (Lisp_Object window)
|
||||
{
|
||||
return WINDOW_LIVE_P (window)
|
||||
? Fselect_window (window, Qt) : selected_window;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
select_frame_norecord (Lisp_Object frame)
|
||||
{
|
||||
return FRAME_LIVE_P (XFRAME (frame))
|
||||
? Fselect_frame (frame, Qt) : selected_frame;
|
||||
}
|
||||
|
||||
void
|
||||
run_window_configuration_change_hook (struct frame *f)
|
||||
@ -3209,11 +3093,13 @@ WINDOW can be any window and defaults to the selected one. */)
|
||||
|
||||
DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
|
||||
doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
|
||||
WINDOW defaults to the selected window. BUFFER-OR-NAME must be a buffer
|
||||
or the name of an existing buffer. Optional third argument KEEP-MARGINS
|
||||
non-nil means that WINDOW's current display margins, fringe widths, and
|
||||
scroll bar settings are preserved; the default is to reset these from
|
||||
the local settings for BUFFER-OR-NAME or the frame defaults. Return nil.
|
||||
WINDOW has to be a live window and defaults to the selected one.
|
||||
BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
|
||||
|
||||
Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
|
||||
display margins, fringe widths, and scroll bar settings are preserved;
|
||||
the default is to reset these from the local settings for BUFFER-OR-NAME
|
||||
or the frame defaults. Return nil.
|
||||
|
||||
This function throws an error when WINDOW is strongly dedicated to its
|
||||
buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
|
||||
@ -3238,33 +3124,27 @@ This function runs `window-scroll-functions' before running
|
||||
else if (!EQ (tem, Qt))
|
||||
/* w->buffer is t when the window is first being set up. */
|
||||
{
|
||||
if (EQ (tem, buffer))
|
||||
return Qnil;
|
||||
else if (EQ (w->dedicated, Qt))
|
||||
if (!EQ (tem, buffer))
|
||||
{
|
||||
if (EQ (w->dedicated, Qt))
|
||||
/* WINDOW is strongly dedicated to its buffer, signal an
|
||||
error. */
|
||||
error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
|
||||
else
|
||||
/* WINDOW is weakly dedicated to its buffer, reset
|
||||
dedicatedness. */
|
||||
w->dedicated = Qnil;
|
||||
|
||||
call1 (Qrecord_window_buffer, window);
|
||||
}
|
||||
|
||||
unshow_buffer (w);
|
||||
}
|
||||
|
||||
set_window_buffer (window, buffer, 1, !NILP (keep_margins));
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
select_window_norecord (Lisp_Object window)
|
||||
{
|
||||
return WINDOW_LIVE_P (window)
|
||||
? Fselect_window (window, Qt) : selected_window;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
select_frame_norecord (Lisp_Object frame)
|
||||
{
|
||||
return FRAME_LIVE_P (XFRAME (frame))
|
||||
? Fselect_frame (frame, Qt) : selected_frame;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
|
||||
@ -3799,7 +3679,7 @@ resize_frame_windows (struct frame *f, int size, int horflag)
|
||||
DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
|
||||
doc: /* Split window OLD.
|
||||
Second argument TOTAL-SIZE specifies the number of lines or columns of the
|
||||
new window. In any case TOTAL-SIZE must be a positive integer
|
||||
new window. In any case TOTAL-SIZE must be a positive integer.
|
||||
|
||||
Third argument SIDE nil (or `below') specifies that the new window shall
|
||||
be located below WINDOW. SIDE `above' means the new window shall be
|
||||
@ -4280,7 +4160,6 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini
|
||||
else error ("Failed to resize minibuffer window");
|
||||
}
|
||||
|
||||
|
||||
/* Mark window cursors off for all windows in the window tree rooted
|
||||
at W by setting their phys_cursor_on_p flag to zero. Called from
|
||||
xterm.c, e.g. when a frame is cleared and thereby all cursors on
|
||||
@ -5337,7 +5216,6 @@ and redisplay normally--don't erase and redraw the frame. */)
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
|
||||
0, 1, 0,
|
||||
doc: /* Return the height in lines of the text display area of WINDOW.
|
||||
@ -6865,10 +6743,7 @@ function `window-nest' and altered by the function `set-window-nest'. */);
|
||||
defsubr (&Sset_window_display_table);
|
||||
defsubr (&Snext_window);
|
||||
defsubr (&Sprevious_window);
|
||||
defsubr (&Sother_window);
|
||||
defsubr (&Sget_buffer_window);
|
||||
defsubr (&Sdelete_windows_on);
|
||||
defsubr (&Sreplace_buffer_in_windows);
|
||||
defsubr (&Sdelete_other_windows_internal);
|
||||
defsubr (&Sdelete_window_internal);
|
||||
defsubr (&Sresize_mini_window_internal);
|
||||
@ -6917,7 +6792,6 @@ function `window-nest' and altered by the function `set-window-nest'. */);
|
||||
void
|
||||
keys_of_window (void)
|
||||
{
|
||||
initial_define_key (control_x_map, 'o', "other-window");
|
||||
initial_define_key (control_x_map, '<', "scroll-left");
|
||||
initial_define_key (control_x_map, '>', "scroll-right");
|
||||
|
||||
|
@ -827,6 +827,7 @@ extern Lisp_Object make_window (void);
|
||||
extern Lisp_Object window_from_coordinates (struct frame *, int, int,
|
||||
enum window_part *, int);
|
||||
EXFUN (Fwindow_dedicated_p, 1);
|
||||
extern void resize_frame_windows (struct frame *, int, int);
|
||||
extern void delete_all_subwindows (Lisp_Object);
|
||||
extern void freeze_window_starts (struct frame *, int);
|
||||
extern void grow_mini_window (struct window *, int);
|
||||
@ -902,7 +903,6 @@ extern Lisp_Object Qwindowp, Qwindow_live_p;
|
||||
extern Lisp_Object Vwindow_list;
|
||||
|
||||
EXFUN (Fwindow_buffer, 1);
|
||||
EXFUN (Fwindow_frame, 1);
|
||||
EXFUN (Fget_buffer_window, 2);
|
||||
EXFUN (Fwindow_minibuffer_p, 1);
|
||||
EXFUN (Fselected_window, 0);
|
||||
@ -918,12 +918,10 @@ extern int window_internal_height (struct window *);
|
||||
extern int window_body_cols (struct window *w);
|
||||
EXFUN (Frecenter, 1);
|
||||
extern void temp_output_buffer_show (Lisp_Object);
|
||||
extern void replace_buffer_in_all_windows (Lisp_Object);
|
||||
extern void replace_buffer_in_windows_safely (Lisp_Object);
|
||||
extern void init_window_once (void);
|
||||
extern void init_window (void);
|
||||
extern void syms_of_window (void);
|
||||
extern void keys_of_window (void);
|
||||
extern void resize_frame_windows (struct frame *, int, int);
|
||||
|
||||
|
||||
#endif /* not WINDOW_H_INCLUDED */
|
||||
|
Loading…
Reference in New Issue
Block a user