X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/f417bc0a9ccfd22698c74799552c959ef3692191..659114fdba7d5ea14541cdc713c7f9745eb93c46:/lisp/window.el diff --git a/lisp/window.el b/lisp/window.el index 35b2789cb0..af5d9a5b16 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -1,10 +1,11 @@ ;;; window.el --- GNU Emacs window commands aside from those written in C -;; Copyright (C) 1985, 1989, 1992, 1993, 1994, 2000, 2001, 2002, -;; 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +;; Copyright (C) 1985, 1989, 1992-1994, 2000-2011 +;; Free Software Foundation, Inc. ;; Maintainer: FSF ;; Keywords: internal +;; Package: emacs ;; This file is part of GNU Emacs. @@ -53,6 +54,7 @@ This macro saves and restores the current buffer, since otherwise its normal operation could make a different buffer current. The order of recently selected windows and the buffer list ordering are not altered by this macro (unless they are altered in BODY)." + (declare (indent 0) (debug t)) `(let ((save-selected-window-window (selected-window)) ;; It is necessary to save all of these, because calling ;; select-window changes frame-selected-window for whatever @@ -76,9 +78,9 @@ WINDOW defaults to the selected window. The return value does not include the mode line or the header line, if any. If a line at the bottom of the window is only -partially visible, that line is included in the return value. If -you do not want to include a partially visible bottom line in the -return value, use `window-text-height' instead." +partially visible, that line is included in the return value. +If you do not want to include a partially visible bottom line +in the return value, use `window-text-height' instead." (or window (setq window (selected-window))) (if (window-minibuffer-p window) (window-height window) @@ -87,6 +89,16 @@ return value, use `window-text-height' instead." (if mode-line-format 1 0) (if header-line-format 1 0)))))) +;; See discussion in bug#4543. +(defun window-full-height-p (&optional window) + "Return non-nil if WINDOW is not the result of a vertical split. +WINDOW defaults to the selected window. (This function is not +appropriate for minibuffers.)" + (unless window + (setq window (selected-window))) + (= (window-height window) + (window-height (frame-root-window (window-frame window))))) + (defun one-window-p (&optional nomini all-frames) "Return non-nil if the selected window is the only window. Optional arg NOMINI non-nil means don't count the minibuffer @@ -149,8 +161,8 @@ counts, `walk-windows' includes the windows in the frame from which you entered the minibuffer, as well as the minibuffer window. -ALL-FRAMES nil or omitted means cycle through all windows on - WINDOW's frame, plus the minibuffer window if specified by the +ALL-FRAMES nil or omitted means cycle through all windows on the + selected frame, plus the minibuffer window if specified by the MINIBUF argument, see above. If the minibuffer counts, cycle through all windows on all frames that share that minibuffer too. @@ -162,8 +174,8 @@ ALL-FRAMES 0 means cycle through all windows on all visible and iconified frames. ALL-FRAMES a frame means cycle through all windows on that frame only. -Anything else means cycle through all windows on WINDOW's frame - and no others. +Anything else means cycle through all windows on the selected + frame and no others. This function changes neither the order of recently selected windows nor the buffer list." @@ -241,15 +253,6 @@ meaning of this argument." (walk-windows (lambda (w) (setq count (+ count 1))) minibuf) count)) - -(defun window-safely-shrinkable-p (&optional window) - "Return t if WINDOW can be shrunk without shrinking other windows. -WINDOW defaults to the selected window." - (with-selected-window (or window (selected-window)) - (let ((edges (window-edges))) - (or (= (nth 2 edges) (nth 2 (window-edges (previous-window)))) - (= (nth 0 edges) (nth 0 (window-edges (next-window)))))))) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; `balance-windows' subroutines using `window-tree' @@ -557,159 +560,186 @@ Commands such as `switch-to-buffer-other-window' and (function :tag "function")) :group 'windows) -(defun special-display-p (buffer-name) - "Return non-nil if a buffer named BUFFER-NAME gets a special frame. -If the value is t, `display-buffer' or `pop-to-buffer' would -create a special frame for that buffer using the default frame -parameters. - -If the value is a list, it is a list of frame parameters that -would be used to make a frame for that buffer. The variables -`special-display-buffer-names' and `special-display-regexps' -control this." - (let (tmp) - (cond - ((not (stringp buffer-name))) - ;; Make sure to return t in the following two cases. - ((member buffer-name special-display-buffer-names) t) - ((setq tmp (assoc buffer-name special-display-buffer-names)) (cdr tmp)) - ((catch 'found - (dolist (regexp special-display-regexps) - (cond - ((stringp regexp) - (when (string-match-p regexp buffer-name) - (throw 'found t))) - ((and (consp regexp) (stringp (car regexp)) - (string-match-p (car regexp) buffer-name)) - (throw 'found (cdr regexp)))))))))) - (defcustom special-display-buffer-names nil - "List of buffer names that should have their own special frames. + "List of names of buffers that should be displayed specially. Displaying a buffer with `display-buffer' or `pop-to-buffer', if -its name is in this list, makes a special frame for it using -`special-display-function'. See also `special-display-regexps'. - -An element of the list can be a list instead of just a string. -There are two ways to use a list as an element: - (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...) -In the first case, the FRAME-PARAMETERS are pairs of the form -\(PARAMETER . VALUE); these parameter values are used to create -the frame. In the second case, FUNCTION is called with BUFFER as -the first argument, followed by the OTHER-ARGS--it can display -BUFFER in any way it likes. All this is done by the function -found in `special-display-function'. - -If the specified frame parameters include (same-buffer . t), the -buffer is displayed in the currently selected window. Otherwise, if -they include (same-frame . t), the buffer is displayed in a new window -in the currently selected frame. - -If this variable appears \"not to work\", because you add a name to it -but that buffer still appears in the selected window, look at the -values of `same-window-buffer-names' and `same-window-regexps'. -Those variables take precedence over this one." - :type '(repeat (choice :tag "Buffer" - :value "" - (string :format "%v") - (cons :tag "With attributes" - :format "%v" - :value ("" . nil) - (string :format "%v") - (repeat :tag "Attributes" - (cons :format "%v" - (symbol :tag "Parameter") - (sexp :tag "Value")))))) +its name is in this list, displays the buffer in a way specified +by `special-display-function'. `special-display-popup-frame' +\(the default for `special-display-function') usually displays +the buffer in a separate frame made with the parameters specified +by `special-display-frame-alist'. If `special-display-function' +has been set to some other function, that function is called with +the buffer as first, and nil as second argument. + +Alternatively, an element of this list can be specified as +\(BUFFER-NAME FRAME-PARAMETERS), where BUFFER-NAME is a buffer +name and FRAME-PARAMETERS an alist of \(PARAMETER . VALUE) pairs. +`special-display-popup-frame' will interpret such pairs as frame +parameters when it creates a special frame, overriding the +corresponding values from `special-display-frame-alist'. + +As a special case, if FRAME-PARAMETERS contains (same-window . t) +`special-display-popup-frame' displays that buffer in the +selected window. If FRAME-PARAMETERS contains (same-frame . t), +it displays that buffer in a window on the selected frame. + +If `special-display-function' specifies some other function than +`special-display-popup-frame', that function is called with the +buffer named BUFFER-NAME as first, and FRAME-PARAMETERS as second +argument. + +Finally, an element of this list can be also specified as +\(BUFFER-NAME FUNCTION OTHER-ARGS). In that case, +`special-display-popup-frame' will call FUNCTION with the buffer +named BUFFER-NAME as first argument, and OTHER-ARGS as the +second. If `special-display-function' specifies some other +function, that function is called with the buffer named +BUFFER-NAME as first, and the element's cdr as second argument. + +If this variable appears \"not to work\", because you added a +name to it but the corresponding buffer is displayed in the +selected window, look at the values of `same-window-buffer-names' +and `same-window-regexps'. Those variables take precedence over +this one. + +See also `special-display-regexps'." + :type '(repeat + (choice :tag "Buffer" + :value "" + (string :format "%v") + (cons :tag "With parameters" + :format "%v" + :value ("" . nil) + (string :format "%v") + (repeat :tag "Parameters" + (cons :format "%v" + (symbol :tag "Parameter") + (sexp :tag "Value")))) + (list :tag "With function" + :format "%v" + :value ("" . nil) + (string :format "%v") + (function :tag "Function") + (repeat :tag "Arguments" (sexp))))) + :group 'windows :group 'frames) +;;;###autoload +(put 'special-display-buffer-names 'risky-local-variable t) + (defcustom special-display-regexps nil - "List of regexps saying which buffers should have their own special frames. -When displaying a buffer with `display-buffer' or -`pop-to-buffer', if any regexp in this list matches the buffer -name, it makes a special frame for the buffer by calling -`special-display-function'. - -An element of the list can be a list instead of just a string. -There are two ways to use a list as an element: - (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...) -In the first case, the FRAME-PARAMETERS are pairs of the form -\(PARAMETER . VALUE); these parameter values are used to create -the frame. In the second case, FUNCTION is called with BUFFER as -the first argument, followed by the OTHER-ARGS--it can display -the buffer in any way it likes. All this is done by the function -found in `special-display-function'. - -If the specified frame parameters include (same-buffer . t), the -buffer is displayed in the currently selected window. Otherwise, -if they include (same-frame . t), the buffer is displayed in a -new window in the currently selected frame. - -If this variable appears \"not to work\", because you add a -regexp to it but the matching buffers still appear in the + "List of regexps saying which buffers should be displayed specially. +Displaying a buffer with `display-buffer' or `pop-to-buffer', if +any regexp in this list matches its name, displays it specially +using `special-display-function'. `special-display-popup-frame' +\(the default for `special-display-function') usually displays +the buffer in a separate frame made with the parameters specified +by `special-display-frame-alist'. If `special-display-function' +has been set to some other function, that function is called with +the buffer as first, and nil as second argument. + +Alternatively, an element of this list can be specified as +\(REGEXP FRAME-PARAMETERS), where REGEXP is a regexp as above and +FRAME-PARAMETERS an alist of (PARAMETER . VALUE) pairs. +`special-display-popup-frame' will then interpret these pairs as +frame parameters when creating a special frame for a buffer whose +name matches REGEXP, overriding the corresponding values from +`special-display-frame-alist'. + +As a special case, if FRAME-PARAMETERS contains (same-window . t) +`special-display-popup-frame' displays buffers matching REGEXP in +the selected window. \(same-frame . t) in FRAME-PARAMETERS means +to display such buffers in a window on the selected frame. + +If `special-display-function' specifies some other function than +`special-display-popup-frame', that function is called with the +buffer whose name matched REGEXP as first, and FRAME-PARAMETERS +as second argument. + +Finally, an element of this list can be also specified as +\(REGEXP FUNCTION OTHER-ARGS). `special-display-popup-frame' +will then call FUNCTION with the buffer whose name matched +REGEXP as first, and OTHER-ARGS as second argument. If +`special-display-function' specifies some other function, that +function is called with the buffer whose name matched REGEXP +as first, and the element's cdr as second argument. + +If this variable appears \"not to work\", because you added a +name to it but the corresponding buffer is displayed in the selected window, look at the values of `same-window-buffer-names' and `same-window-regexps'. Those variables take precedence over -this one." - :type '(repeat (choice :tag "Buffer" - :value "" - (regexp :format "%v") - (cons :tag "With attributes" - :format "%v" - :value ("" . nil) - (regexp :format "%v") - (repeat :tag "Attributes" - (cons :format "%v" - (symbol :tag "Parameter") - (sexp :tag "Value")))))) +this one. + +See also `special-display-buffer-names'." + :type '(repeat + (choice :tag "Buffer" + :value "" + (regexp :format "%v") + (cons :tag "With parameters" + :format "%v" + :value ("" . nil) + (regexp :format "%v") + (repeat :tag "Parameters" + (cons :format "%v" + (symbol :tag "Parameter") + (sexp :tag "Value")))) + (list :tag "With function" + :format "%v" + :value ("" . nil) + (regexp :format "%v") + (function :tag "Function") + (repeat :tag "Arguments" (sexp))))) + :group 'windows :group 'frames) +(defun special-display-p (buffer-name) + "Return non-nil if a buffer named BUFFER-NAME gets a special frame. +More precisely, return t if `special-display-buffer-names' or +`special-display-regexps' contain a string entry equaling or +matching BUFFER-NAME. If `special-display-buffer-names' or +`special-display-regexps' contain a list entry whose car equals +or matches BUFFER-NAME, the return value is the cdr of that +entry." + (let (tmp) + (cond + ((not (stringp buffer-name))) + ((member buffer-name special-display-buffer-names) + t) + ((setq tmp (assoc buffer-name special-display-buffer-names)) + (cdr tmp)) + ((catch 'found + (dolist (regexp special-display-regexps) + (cond + ((stringp regexp) + (when (string-match-p regexp buffer-name) + (throw 'found t))) + ((and (consp regexp) (stringp (car regexp)) + (string-match-p (car regexp) buffer-name)) + (throw 'found (cdr regexp)))))))))) + (defcustom special-display-function 'special-display-popup-frame - "Function to call to make a new frame for a special buffer. -It is called with two arguments, the buffer and optional buffer -specific data, and should return a window displaying that buffer. -The default value normally makes a separate frame for the buffer, -using `special-display-frame-alist' to specify the frame -parameters. - -But if the buffer specific data includes (same-buffer . t) then -the buffer is displayed in the current selected window. -Otherwise if it includes (same-frame . t) then the buffer is -displayed in a new window in the currently selected frame. - -A buffer is special if it is listed in + "Function to call for displaying special buffers. +This function is called with two arguments - the buffer and, +optionally, a list - and should return a window displaying that +buffer. The default value usually makes a separate frame for the +buffer using `special-display-frame-alist' to specify the frame +parameters. See the definition of `special-display-popup-frame' +for how to specify such a function. + +A buffer is special when its name is either listed in `special-display-buffer-names' or matches a regexp in `special-display-regexps'." :type 'function :group 'frames) -(defun same-window-p (buffer-name) - "Return non-nil if a buffer named BUFFER-NAME would be shown in the \"same\" window. -This function returns non-nil if `display-buffer' or -`pop-to-buffer' would show a buffer named BUFFER-NAME in the -selected rather than \(as usual\) some other window. See -`same-window-buffer-names' and `same-window-regexps'." - (cond - ((not (stringp buffer-name))) - ;; The elements of `same-window-buffer-names' can be buffer - ;; names or cons cells whose cars are buffer names. - ((member buffer-name same-window-buffer-names)) - ((assoc buffer-name same-window-buffer-names)) - ((catch 'found - (dolist (regexp same-window-regexps) - ;; The elements of `same-window-regexps' can be regexps - ;; or cons cells whose cars are regexps. - (when (or (and (stringp regexp) - (string-match regexp buffer-name)) - (and (consp regexp) (stringp (car regexp)) - (string-match-p (car regexp) buffer-name))) - (throw 'found t))))))) - (defcustom same-window-buffer-names nil "List of names of buffers that should appear in the \"same\" window. `display-buffer' and `pop-to-buffer' show a buffer whose name is on this list in the selected rather than some other window. An element of this list can be a cons cell instead of just a -string. In that case the car must be a string specifying the -buffer name. This is for compatibility with +string. In that case, the cell's car must be a string specifying +the buffer name. This is for compatibility with `special-display-buffer-names'; the cdr of the cons cell is ignored. @@ -724,18 +754,39 @@ matches a regexp on this list in the selected rather than some other window. An element of this list can be a cons cell instead of just a -string. In that case the car must be a string, which specifies +string. In that case, the cell's car must be a regexp matching the buffer name. This is for compatibility with -`special-display-buffer-names'; the cdr of the cons cell is -ignored. +`special-display-regexps'; the cdr of the cons cell is ignored. See also `same-window-buffer-names'." :type '(repeat (regexp :format "%v")) :group 'windows) +(defun same-window-p (buffer-name) + "Return non-nil if a buffer named BUFFER-NAME would be shown in the \"same\" window. +This function returns non-nil if `display-buffer' or +`pop-to-buffer' would show a buffer named BUFFER-NAME in the +selected rather than \(as usual\) some other window. See +`same-window-buffer-names' and `same-window-regexps'." + (cond + ((not (stringp buffer-name))) + ;; The elements of `same-window-buffer-names' can be buffer + ;; names or cons cells whose cars are buffer names. + ((member buffer-name same-window-buffer-names)) + ((assoc buffer-name same-window-buffer-names)) + ((catch 'found + (dolist (regexp same-window-regexps) + ;; The elements of `same-window-regexps' can be regexps + ;; or cons cells whose cars are regexps. + (when (or (and (stringp regexp) + (string-match regexp buffer-name)) + (and (consp regexp) (stringp (car regexp)) + (string-match-p (car regexp) buffer-name))) + (throw 'found t))))))) + (defcustom pop-up-frames nil "Whether `display-buffer' should make a separate frame. -If nil, never make a seperate frame. +If nil, never make a separate frame. If the value is `graphic-only', make a separate frame on graphic displays only. Any other non-nil value means always make a separate frame." @@ -758,66 +809,78 @@ that frame." :type 'boolean :group 'windows) -(defcustom split-height-threshold 80 - "Minimum height of window to be split vertically. -If the value is a number, `display-buffer' can split a window -only if it has at least as many lines. If the value is nil, -`display-buffer' cannot split a window vertically. - -If the window is the only window on its frame, `display-buffer' -can split it regardless of this value." - :type '(choice (const nil) (number :tag "lines")) +(defcustom split-window-preferred-function 'split-window-sensibly + "Function called by `display-buffer' routines to split a window. +This function is called with a window as single argument and is +supposed to split that window and return the new window. If the +window can (or shall) not be split, it is supposed to return nil. +The default is to call the function `split-window-sensibly' which +tries to split the window in a way which seems most suitable. +You can customize the options `split-height-threshold' and/or +`split-width-threshold' in order to have `split-window-sensibly' +prefer either vertical or horizontal splitting. + +If you set this to any other function, bear in mind that the +`display-buffer' routines may call this function two times. The +argument of the first call is the largest window on its frame. +If that call fails to return a live window, the function is +called again with the least recently used window as argument. If +that call fails too, `display-buffer' will use an existing window +to display its buffer. + +The window selected at the time `display-buffer' was invoked is +still selected when this function is called. Hence you can +compare the window argument with the value of `selected-window' +if you intend to split the selected window instead or if you do +not want to split the selected window." + :type 'function :version "23.1" :group 'windows) -(defcustom split-width-threshold 160 - "Minimum width of window to be split horizontally. -If the value is a number, `display-buffer' can split a window -only if it has at least as many columns. If the value is nil, -`display-buffer' cannot split a window horizontally." - :type '(choice (const nil) (number :tag "columns")) +(defcustom split-height-threshold 80 + "Minimum height for splitting windows sensibly. +If this is an integer, `split-window-sensibly' may split a window +vertically only if it has at least this many lines. If this is +nil, `split-window-sensibly' is not allowed to split a window +vertically. If, however, a window is the only window on its +frame, `split-window-sensibly' may split it vertically +disregarding the value of this variable." + :type '(choice (const nil) (integer :tag "lines")) :version "23.1" :group 'windows) -(defcustom split-window-preferred-function nil - "Function used by `display-buffer' to split windows. -If non-nil, a function called with a window as single argument -supposed to split that window and return the new window. If the -function returns nil the window is not split. - -If nil, `display-buffer' will split the window respecting the -values of `split-height-threshold' and `split-width-threshold'." - :type '(choice (const nil) (function :tag "Function")) +(defcustom split-width-threshold 160 + "Minimum width for splitting windows sensibly. +If this is an integer, `split-window-sensibly' may split a window +horizontally only if it has at least this many columns. If this +is nil, `split-window-sensibly' is not allowed to split a window +horizontally." + :type '(choice (const nil) (integer :tag "columns")) :version "23.1" :group 'windows) -(defun window--splittable-p (window &optional horizontal) - "Return non-nil if WINDOW can be split evenly. -Optional argument HORIZONTAL non-nil means check whether WINDOW -can be split horizontally. +(defun window-splittable-p (window &optional horizontal) + "Return non-nil if `split-window-sensibly' may split WINDOW. +Optional argument HORIZONTAL nil or omitted means check whether +`split-window-sensibly' may split WINDOW vertically. HORIZONTAL +non-nil means check whether WINDOW may be split horizontally. -WINDOW can be split vertically when the following conditions +WINDOW may be split vertically when the following conditions hold: - - `window-size-fixed' is either nil or equals `width' for the buffer of WINDOW. - -- `split-height-threshold' is a number and WINDOW is at least as +- `split-height-threshold' is an integer and WINDOW is at least as high as `split-height-threshold'. - - When WINDOW is split evenly, the emanating windows are at least `window-min-height' lines tall and can accommodate at least one line plus - if WINDOW has one - a mode line. -WINDOW can be split horizontally when the following conditions +WINDOW may be split horizontally when the following conditions hold: - - `window-size-fixed' is either nil or equals `height' for the buffer of WINDOW. - -- `split-width-threshold' is a number and WINDOW is at least as +- `split-width-threshold' is an integer and WINDOW is at least as wide as `split-width-threshold'. - - When WINDOW is split evenly, the emanating windows are at least `window-min-width' or two (whichever is larger) columns wide." (when (window-live-p window) @@ -846,30 +909,68 @@ hold: (* 2 (max window-min-height (if mode-line-format 2 1)))))))))) +(defun split-window-sensibly (window) + "Split WINDOW in a way suitable for `display-buffer'. +If `split-height-threshold' specifies an integer, WINDOW is at +least `split-height-threshold' lines tall and can be split +vertically, split WINDOW into two windows one above the other and +return the lower window. Otherwise, if `split-width-threshold' +specifies an integer, WINDOW is at least `split-width-threshold' +columns wide and can be split horizontally, split WINDOW into two +windows side by side and return the window on the right. If this +can't be done either and WINDOW is the only window on its frame, +try to split WINDOW vertically disregarding any value specified +by `split-height-threshold'. If that succeeds, return the lower +window. Return nil otherwise. + +By default `display-buffer' routines call this function to split +the largest or least recently used window. To change the default +customize the option `split-window-preferred-function'. + +You can enforce this function to not split WINDOW horizontally, +by setting \(or binding) the variable `split-width-threshold' to +nil. If, in addition, you set `split-height-threshold' to zero, +chances increase that this function does split WINDOW vertically. + +In order to not split WINDOW vertically, set \(or bind) the +variable `split-height-threshold' to nil. Additionally, you can +set `split-width-threshold' to zero to make a horizontal split +more likely to occur. + +Have a look at the function `window-splittable-p' if you want to +know how `split-window-sensibly' determines whether WINDOW can be +split." + (or (and (window-splittable-p window) + ;; Split window vertically. + (with-selected-window window + (split-window-vertically))) + (and (window-splittable-p window t) + ;; Split window horizontally. + (with-selected-window window + (split-window-horizontally))) + (and (eq window (frame-root-window (window-frame window))) + (not (window-minibuffer-p window)) + ;; If WINDOW is the only window on its frame and is not the + ;; minibuffer window, try to split it vertically disregarding + ;; the value of `split-height-threshold'. + (let ((split-height-threshold 0)) + (when (window-splittable-p window) + (with-selected-window window + (split-window-vertically))))))) + (defun window--try-to-split-window (window) - "Split WINDOW if it is splittable. -See `window--splittable-p' for how to determine whether a window -is splittable. If WINDOW can be split, return the value returned -by `split-window' (or `split-window-preferred-function')." - (when (and (window-live-p window) - (not (frame-parameter (window-frame window) 'unsplittable))) - (if (functionp split-window-preferred-function) - ;; `split-window-preferred-function' is specified, so use it. - (funcall split-window-preferred-function window) - (or (and (window--splittable-p window) - ;; Split window vertically. - (split-window window)) - (and (window--splittable-p window t) - ;; Split window horizontally. - (split-window window nil t)) - (and (eq window (frame-root-window (window-frame window))) - (not (window-minibuffer-p window)) - ;; If WINDOW is the only window on its frame and not the - ;; minibuffer window, attempt to split it vertically - ;; disregarding the value of `split-height-threshold'. - (let ((split-height-threshold 0)) - (and (window--splittable-p window) - (split-window window)))))))) + "Try to split WINDOW. +Return value returned by `split-window-preferred-function' if it +represents a live window, nil otherwise." + (and (window-live-p window) + (not (frame-parameter (window-frame window) 'unsplittable)) + (let ((new-window + ;; Since `split-window-preferred-function' might + ;; throw an error use `condition-case'. + (condition-case nil + (funcall split-window-preferred-function window) + (error nil)))) + (and (window-live-p new-window) new-window)))) (defun window--frame-usable-p (frame) "Return FRAME if it can be used to display a buffer." @@ -878,9 +979,15 @@ by `split-window' (or `split-window-preferred-function')." ;; `frame-root-window' may be an internal window which is considered ;; "dead" by `window-live-p'. Hence if `window' is not live we ;; implicitly know that `frame' has a visible window we can use. - (when (or (not (window-live-p window)) - (and (not (window-minibuffer-p window)) - (not (window-dedicated-p window)))) + (unless (and (window-live-p window) + (or (window-minibuffer-p window) + ;; If the window is soft-dedicated, the frame is usable. + ;; Actually, even if the window is really dedicated, + ;; the frame is still usable by splitting it. + ;; At least Emacs-22 allowed it, and it is desirable + ;; when displaying same-frame windows. + nil ; (eq t (window-dedicated-p window)) + )) frame)))) (defcustom even-window-heights t @@ -900,7 +1007,7 @@ is higher than WINDOW." (not (eq window (selected-window))) ;; Don't resize minibuffer windows. (not (window-minibuffer-p (selected-window))) - (> (window-height (selected-window)) (window-height window)) + (> (window-height (selected-window)) (window-height window)) (eq (window-frame window) (window-frame (selected-window))) (let ((sel-edges (window-edges (selected-window))) (win-edges (window-edges window))) @@ -930,13 +1037,21 @@ Do not raise the selected frame. Return WINDOW." (raise-frame frame)) window)) -(defun window--display-buffer-2 (buffer window) +(defun window--display-buffer-2 (buffer window &optional dedicated) "Display BUFFER in WINDOW and make its frame visible. +Set `window-dedicated-p' to DEDICATED if non-nil. Return WINDOW." (when (and (buffer-live-p buffer) (window-live-p window)) (set-window-buffer window buffer) + (when dedicated + (set-window-dedicated-p window dedicated)) (window--display-buffer-1 window))) +(defvar display-buffer-mark-dedicated nil + "If non-nil, `display-buffer' marks the windows it creates as dedicated. +The actual non-nil value of this variable will be copied to the +`window-dedicated-p' flag.") + (defun display-buffer (buffer-or-name &optional not-this-window frame) "Make buffer BUFFER-OR-NAME appear in some window but don't select it. BUFFER-OR-NAME must be a buffer or the name of an existing @@ -1009,10 +1124,15 @@ consider all visible or iconified frames." (not (last-nonminibuffer-frame))) 0) (last-nonminibuffer-frame)))) - (and (setq window-to-use (get-buffer-window buffer frames)) - (or can-use-selected-window - (not (eq (selected-window) window-to-use))))) - ;; If the buffer is already displayed in some window use that. + (setq window-to-use + (catch 'found + ;; Search frames for a window displaying BUFFER. Return + ;; the selected window only if we are allowed to do so. + (dolist (window (get-buffer-window-list buffer 'nomini frames)) + (when (or can-use-selected-window + (not (eq (selected-window) window))) + (throw 'found window)))))) + ;; The buffer is already displayed in some window; use that. (window--display-buffer-1 window-to-use)) ((and special-display-function ;; `special-display-p' returns either t or a list of frame @@ -1023,8 +1143,8 @@ consider all visible or iconified frames." buffer (if (listp pars) pars)))))) ((or use-pop-up-frames (not frame-to-use)) ;; We want or need a new frame. - (window--display-buffer-2 - buffer (frame-selected-window (funcall pop-up-frame-function)))) + (let ((win (frame-selected-window (funcall pop-up-frame-function)))) + (window--display-buffer-2 buffer win display-buffer-mark-dedicated))) ((and pop-up-windows ;; Make a new window. (or (not (frame-parameter frame-to-use 'unsplittable)) @@ -1039,16 +1159,34 @@ consider all visible or iconified frames." (or (window--try-to-split-window (get-largest-window frame-to-use t)) (window--try-to-split-window - (get-lru-window frame-to-use t)))) - (window--display-buffer-2 buffer window-to-use))) - ((setq window-to-use - ;; Reuse an existing window. - (or (get-lru-window frame-to-use) - (get-buffer-window buffer 'visible) - (get-largest-window 'visible nil) - (get-buffer-window buffer 0) - (get-largest-window 0 nil) - (frame-selected-window (funcall pop-up-frame-function)))) + (get-lru-window frame-to-use t))))) + (window--display-buffer-2 buffer window-to-use + display-buffer-mark-dedicated)) + ((let ((window-to-undedicate + ;; When NOT-THIS-WINDOW is non-nil, temporarily dedicate + ;; the selected window to its buffer, to avoid that some of + ;; the `get-' routines below choose it. (Bug#1415) + (and not-this-window (not (window-dedicated-p)) + (set-window-dedicated-p (selected-window) t) + (selected-window)))) + (unwind-protect + (setq window-to-use + ;; Reuse an existing window. + (or (get-lru-window frame-to-use) + (let ((window (get-buffer-window buffer 'visible))) + (unless (and not-this-window + (eq window (selected-window))) + window)) + (get-largest-window 'visible) + (let ((window (get-buffer-window buffer 0))) + (unless (and not-this-window + (eq window (selected-window))) + window)) + (get-largest-window 0) + (frame-selected-window (funcall pop-up-frame-function)))) + (when (window-live-p window-to-undedicate) + ;; Restore dedicated status of selected window. + (set-window-dedicated-p window-to-undedicate nil)))) (window--even-window-heights window-to-use) (window--display-buffer-2 buffer window-to-use))))) @@ -1083,19 +1221,16 @@ at the front of the list of recently selected ones." (let ((buf (get-buffer-create buffer-or-name))) (set-buffer-major-mode buf) buf)))) - (old-window (selected-window)) (old-frame (selected-frame)) new-window new-frame) (set-buffer buffer) (setq new-window (display-buffer buffer other-window)) - (unless (eq new-window old-window) - ;; `display-buffer' has chosen another window, select it. - (select-window new-window norecord) - (setq new-frame (window-frame new-window)) - (unless (eq new-frame old-frame) - ;; `display-buffer' has chosen another frame, make sure it gets - ;; input focus and is risen. - (select-frame-set-input-focus new-frame))) + (select-window new-window norecord) + (setq new-frame (window-frame new-window)) + (unless (eq new-frame old-frame) + ;; `display-buffer' has chosen another frame, make sure it gets + ;; input focus and is risen. + (select-frame-set-input-focus new-frame)) buffer)) ;; I think this should be the default; I think people will prefer it--rms. @@ -1143,8 +1278,7 @@ window." (setq size (+ (window-height) size))) (setq new-window (split-window nil size)) (unless split-window-keep-point - (save-excursion - (set-buffer (window-buffer)) + (with-current-buffer (window-buffer) (goto-char (window-start)) (setq moved (vertical-motion (window-height))) (set-window-start new-window (point)) @@ -1196,7 +1330,7 @@ The selected window remains selected. Return the new window." (defun set-window-text-height (window height) - "Sets the height in lines of the text display area of WINDOW to HEIGHT. + "Set the height in lines of the text display area of WINDOW to HEIGHT. HEIGHT doesn't include the mode line or header line, if any, or any partial-height lines in the text display area. @@ -1282,84 +1416,112 @@ in some window." "Adjust height of WINDOW to display its buffer's contents exactly. WINDOW defaults to the selected window. Optional argument MAX-HEIGHT specifies the maximum height of the -window and defaults to the height of WINDOW's frame. +window and defaults to the maximum permissible height of a window +on WINDOW's frame. Optional argument MIN-HEIGHT specifies the minimum height of the window and defaults to `window-min-height'. Both, MAX-HEIGHT and MIN-HEIGHT are specified in lines and include the mode line and header line, if any. -Always return nil." + +Return non-nil if height was orderly adjusted, nil otherwise. + +Caution: This function can delete WINDOW and/or other windows +when their height shrinks to less than MIN-HEIGHT." (interactive) + ;; Do all the work in WINDOW and its buffer and restore the selected + ;; window and the current buffer when we're done. + (let ((old-buffer (current-buffer)) + value) + (with-selected-window (or window (setq window (selected-window))) + (set-buffer (window-buffer)) + ;; Use `condition-case' to handle any fixed-size windows and other + ;; pitfalls nearby. + (condition-case nil + (let* (;; MIN-HEIGHT must not be less than 1 and defaults to + ;; `window-min-height'. + (min-height (max (or min-height window-min-height) 1)) + (max-window-height + ;; Maximum height of any window on this frame. + (min (window-height (frame-root-window)) (frame-height))) + ;; MAX-HEIGHT must not be larger than max-window-height and + ;; defaults to max-window-height. + (max-height + (min (or max-height max-window-height) max-window-height)) + (desired-height + ;; The height necessary to show all of WINDOW's buffer, + ;; constrained by MIN-HEIGHT and MAX-HEIGHT. + (max + (min + ;; For an empty buffer `count-screen-lines' returns zero. + ;; Even in that case we need one line for the cursor. + (+ (max (count-screen-lines) 1) + ;; For non-minibuffers count the mode line, if any. + (if (and (not (window-minibuffer-p)) mode-line-format) + 1 0) + ;; Count the header line, if any. + (if header-line-format 1 0)) + max-height) + min-height)) + (delta + ;; How much the window height has to change. + (if (= (window-height) (window-height (frame-root-window))) + ;; Don't try to resize a full-height window. + 0 + (- desired-height (window-height)))) + ;; Do something reasonable so `enlarge-window' can make + ;; windows as small as MIN-HEIGHT. + (window-min-height (min min-height window-min-height))) + ;; Don't try to redisplay with the cursor at the end on its + ;; own line--that would force a scroll and spoil things. + (when (and (eobp) (bolp) (not (bobp))) + (set-window-point window (1- (window-point)))) + ;; Adjust WINDOW's height to the nominally correct one + ;; (which may actually be slightly off because of variable + ;; height text, etc). + (unless (zerop delta) + (enlarge-window delta)) + ;; `enlarge-window' might have deleted WINDOW, so make sure + ;; WINDOW's still alive for the remainder of this. + ;; Note: Deleting WINDOW is clearly counter-intuitive in + ;; this context, but we can't do much about it given the + ;; current semantics of `enlarge-window'. + (when (window-live-p window) + ;; Check if the last line is surely fully visible. If + ;; not, enlarge the window. + (let ((end (save-excursion + (goto-char (point-max)) + (when (and (bolp) (not (bobp))) + ;; Don't include final newline. + (backward-char 1)) + (when truncate-lines + ;; If line-wrapping is turned off, test the + ;; beginning of the last line for + ;; visibility instead of the end, as the + ;; end of the line could be invisible by + ;; virtue of extending past the edge of the + ;; window. + (forward-line 0)) + (point)))) + (set-window-vscroll window 0) + (while (and (< desired-height max-height) + (= desired-height (window-height)) + (not (pos-visible-in-window-p end))) + (enlarge-window 1) + (setq desired-height (1+ desired-height)))) + ;; Return non-nil only if nothing "bad" happened. + (setq value t))) + (error nil))) + (when (buffer-live-p old-buffer) + (set-buffer old-buffer)) + value)) - (when (null window) - (setq window (selected-window))) - (when (null max-height) - (setq max-height (frame-height (window-frame window)))) - - (let* ((buf - ;; Buffer that is displayed in WINDOW - (window-buffer window)) - (window-height - ;; The current height of WINDOW - (window-height window)) - (desired-height - ;; The height necessary to show the buffer displayed by WINDOW - ;; (`count-screen-lines' always works on the current buffer). - (with-current-buffer buf - (+ (count-screen-lines) - ;; If the buffer is empty, (count-screen-lines) is - ;; zero. But, even in that case, we need one text line - ;; for cursor. - (if (= (point-min) (point-max)) - 1 0) - ;; For non-minibuffers, count the mode-line, if any - (if (and (not (window-minibuffer-p window)) - mode-line-format) - 1 0) - ;; Count the header-line, if any - (if header-line-format 1 0)))) - (delta - ;; Calculate how much the window height has to change to show - ;; desired-height lines, constrained by MIN-HEIGHT and MAX-HEIGHT. - (- (max (min desired-height max-height) - (or min-height window-min-height)) - window-height))) - - ;; Don't try to redisplay with the cursor at the end - ;; on its own line--that would force a scroll and spoil things. - (when (with-current-buffer buf - (and (eobp) (bolp) (not (bobp)))) - (set-window-point window (1- (window-point window)))) - - (save-selected-window - (select-window window 'norecord) - - ;; Adjust WINDOW to the nominally correct size (which may actually - ;; be slightly off because of variable height text, etc). - (unless (zerop delta) - (enlarge-window delta)) - - ;; Check if the last line is surely fully visible. If not, - ;; enlarge the window. - (let ((end (with-current-buffer buf - (save-excursion - (goto-char (point-max)) - (when (and (bolp) (not (bobp))) - ;; Don't include final newline - (backward-char 1)) - (when truncate-lines - ;; If line-wrapping is turned off, test the - ;; beginning of the last line for visibility - ;; instead of the end, as the end of the line - ;; could be invisible by virtue of extending past - ;; the edge of the window. - (forward-line 0)) - (point))))) - (set-window-vscroll window 0) - (while (and (< desired-height max-height) - (= desired-height (window-height window)) - (not (pos-visible-in-window-p end window))) - (enlarge-window 1) - (setq desired-height (1+ desired-height))))))) +(defun window-safely-shrinkable-p (&optional window) + "Return t if WINDOW can be shrunk without shrinking other windows. +WINDOW defaults to the selected window." + (with-selected-window (or window (selected-window)) + (let ((edges (window-edges))) + (or (= (nth 2 edges) (nth 2 (window-edges (previous-window)))) + (= (nth 0 edges) (nth 0 (window-edges (next-window)))))))) (defun shrink-window-if-larger-than-buffer (&optional window) "Shrink height of WINDOW if its buffer doesn't need so many lines. @@ -1419,72 +1581,280 @@ Return non-nil if the window was shrunk, nil otherwise." (error nil))))) (defun quit-window (&optional kill window) - "Bury or kill (with KILL non-nil) the buffer displayed in WINDOW. -With a prefix argument, kill the buffer instead. - -KILL defaults to nil, WINDOW to the selected window. If WINDOW -is dedicated or a minibuffer window, delete it and, if it's the -only window on its frame, delete its frame as well provided there -are other frames left. Otherwise, display some other buffer in -the window." + "Quit WINDOW and bury its buffer. +With a prefix argument, kill the buffer instead. WINDOW defaults +to the selected window. + +If WINDOW is non-nil, dedicated, or a minibuffer window, delete +it and, if it's alone on its frame, its frame too. Otherwise, or +if deleting WINDOW fails in any of the preceding cases, display +another buffer in WINDOW using `switch-to-buffer'. + +Optional argument KILL non-nil means kill WINDOW's buffer. +Otherwise, bury WINDOW's buffer, see `bury-buffer'." (interactive "P") - (let* ((window (or window (selected-window))) - (buffer (window-buffer window))) - (if (or (window-minibuffer-p window) (window-dedicated-p window)) - (if (eq window (frame-root-window (window-frame window))) - ;; If this is the only window on its frame, try to delete the - ;; frame (`delete-windows-on' knows how to do that). - (delete-windows-on buffer (selected-frame)) - ;; Other windows are left, delete this window. But don't - ;; throw an error if that fails for some reason. - (condition-case nil - (delete-window window) - (error nil))) - ;; The window is neither dedicated nor a minibuffer window, - ;; display another buffer in it. - (with-selected-window window - (switch-to-buffer (other-buffer)))) + (let ((buffer (window-buffer window))) + (if (or window + (window-minibuffer-p window) + (window-dedicated-p window)) + ;; WINDOW is either non-nil, a minibuffer window, or dedicated; + ;; try to delete it. + (let* ((window (or window (selected-window))) + (frame (window-frame window))) + (if (eq window (frame-root-window frame)) + ;; WINDOW is alone on its frame. `delete-windows-on' + ;; knows how to handle that case. + (delete-windows-on buffer frame) + ;; There are other windows on its frame, delete WINDOW. + (delete-window window))) + ;; Otherwise, switch to another buffer in the selected window. + (switch-to-buffer nil)) + ;; Deal with the buffer. (if kill (kill-buffer buffer) (bury-buffer buffer)))) + (defvar recenter-last-op nil "Indicates the last recenter operation performed. -Possible values: `top', `middle', `bottom'.") +Possible values: `top', `middle', `bottom', integer or float numbers.") + +(defcustom recenter-positions '(middle top bottom) + "Cycling order for `recenter-top-bottom'. +A list of elements with possible values `top', `middle', `bottom', +integer or float numbers that define the cycling order for +the command `recenter-top-bottom'. + +Top and bottom destinations are `scroll-margin' lines the from true +window top and bottom. Middle redraws the frame and centers point +vertically within the window. Integer number moves current line to +the specified absolute window-line. Float number between 0.0 and 1.0 +means the percentage of the screen space from the top. The default +cycling order is middle -> top -> bottom." + :type '(repeat (choice + (const :tag "Top" top) + (const :tag "Middle" middle) + (const :tag "Bottom" bottom) + (integer :tag "Line number") + (float :tag "Percentage"))) + :version "23.2" + :group 'windows) (defun recenter-top-bottom (&optional arg) - "Move current line to window center, top, and bottom, successively. -With no prefix argument, the first call redraws the frame and - centers point vertically within the window. Successive calls - scroll the window, placing point on the top, bottom, and middle - consecutively. The cycling order is middle -> top -> bottom. + "Move current buffer line to the specified window line. +With no prefix argument, successive calls place point according +to the cycling order defined by `recenter-positions'. A prefix argument is handled like `recenter': With numeric prefix ARG, move current line to window-line ARG. - With plain `C-u', move current line to window center. - -Top and bottom destinations are actually `scroll-margin' lines - the from true window top and bottom." + With plain `C-u', move current line to window center." (interactive "P") (cond - (arg (recenter arg)) ; Always respect ARG. - ((or (not (eq this-command last-command)) - (eq recenter-last-op 'bottom)) - (setq recenter-last-op 'middle) - (recenter)) + (arg (recenter arg)) ; Always respect ARG. (t + (setq recenter-last-op + (if (eq this-command last-command) + (car (or (cdr (member recenter-last-op recenter-positions)) + recenter-positions)) + (car recenter-positions))) (let ((this-scroll-margin (min (max 0 scroll-margin) (truncate (/ (window-body-height) 4.0))))) (cond ((eq recenter-last-op 'middle) - (setq recenter-last-op 'top) - (recenter this-scroll-margin)) + (recenter)) ((eq recenter-last-op 'top) - (setq recenter-last-op 'bottom) - (recenter (- -1 this-scroll-margin)))))))) + (recenter this-scroll-margin)) + ((eq recenter-last-op 'bottom) + (recenter (- -1 this-scroll-margin))) + ((integerp recenter-last-op) + (recenter recenter-last-op)) + ((floatp recenter-last-op) + (recenter (round (* recenter-last-op (window-height)))))))))) (define-key global-map [?\C-l] 'recenter-top-bottom) + +(defun move-to-window-line-top-bottom (&optional arg) + "Position point relative to window. + +With a prefix argument ARG, acts like `move-to-window-line'. + +With no argument, positions point at center of window. +Successive calls position point at positions defined +by `recenter-positions'." + (interactive "P") + (cond + (arg (move-to-window-line arg)) ; Always respect ARG. + (t + (setq recenter-last-op + (if (eq this-command last-command) + (car (or (cdr (member recenter-last-op recenter-positions)) + recenter-positions)) + (car recenter-positions))) + (let ((this-scroll-margin + (min (max 0 scroll-margin) + (truncate (/ (window-body-height) 4.0))))) + (cond ((eq recenter-last-op 'middle) + (call-interactively 'move-to-window-line)) + ((eq recenter-last-op 'top) + (move-to-window-line this-scroll-margin)) + ((eq recenter-last-op 'bottom) + (move-to-window-line (- -1 this-scroll-margin))) + ((integerp recenter-last-op) + (move-to-window-line recenter-last-op)) + ((floatp recenter-last-op) + (move-to-window-line (round (* recenter-last-op (window-height)))))))))) + +(define-key global-map [?\M-r] 'move-to-window-line-top-bottom) + + +;;; Scrolling commands. + +;;; Scrolling commands which does not signal errors at top/bottom +;;; of buffer at first key-press (instead moves to top/bottom +;;; of buffer). + +(defcustom scroll-error-top-bottom nil + "Move point to top/bottom of buffer before signalling a scrolling error. +A value of nil means just signal an error if no more scrolling possible. +A value of t means point moves to the beginning or the end of the buffer +\(depending on scrolling direction) when no more scrolling possible. +When point is already on that position, then signal an error." + :type 'boolean + :group 'scrolling + :version "24.1") + +(defun scroll-up-command (&optional arg) + "Scroll text of selected window upward ARG lines; or near full screen if no ARG. +If `scroll-error-top-bottom' is non-nil and `scroll-up' cannot +scroll window further, move cursor to the bottom line. +When point is already on that position, then signal an error. +A near full screen is `next-screen-context-lines' less than a full screen. +Negative ARG means scroll downward. +If ARG is the atom `-', scroll downward by nearly full screen." + (interactive "^P") + (cond + ((null scroll-error-top-bottom) + (scroll-up arg)) + ((eq arg '-) + (scroll-down-command nil)) + ((< (prefix-numeric-value arg) 0) + (scroll-down-command (- (prefix-numeric-value arg)))) + ((eobp) + (scroll-up arg)) ; signal error + (t + (condition-case nil + (scroll-up arg) + (end-of-buffer + (if arg + ;; When scrolling by ARG lines can't be done, + ;; move by ARG lines instead. + (forward-line arg) + ;; When ARG is nil for full-screen scrolling, + ;; move to the bottom of the buffer. + (goto-char (point-max)))))))) + +(put 'scroll-up-command 'scroll-command t) + +(defun scroll-down-command (&optional arg) + "Scroll text of selected window down ARG lines; or near full screen if no ARG. +If `scroll-error-top-bottom' is non-nil and `scroll-down' cannot +scroll window further, move cursor to the top line. +When point is already on that position, then signal an error. +A near full screen is `next-screen-context-lines' less than a full screen. +Negative ARG means scroll upward. +If ARG is the atom `-', scroll upward by nearly full screen." + (interactive "^P") + (cond + ((null scroll-error-top-bottom) + (scroll-down arg)) + ((eq arg '-) + (scroll-up-command nil)) + ((< (prefix-numeric-value arg) 0) + (scroll-up-command (- (prefix-numeric-value arg)))) + ((bobp) + (scroll-down arg)) ; signal error + (t + (condition-case nil + (scroll-down arg) + (beginning-of-buffer + (if arg + ;; When scrolling by ARG lines can't be done, + ;; move by ARG lines instead. + (forward-line (- arg)) + ;; When ARG is nil for full-screen scrolling, + ;; move to the top of the buffer. + (goto-char (point-min)))))))) + +(put 'scroll-down-command 'scroll-command t) + +;;; Scrolling commands which scroll a line instead of full screen. + +(defun scroll-up-line (&optional arg) + "Scroll text of selected window upward ARG lines; or one line if no ARG. +If ARG is omitted or nil, scroll upward by one line. +This is different from `scroll-up-command' that scrolls a full screen." + (interactive "p") + (scroll-up (or arg 1))) + +(put 'scroll-up-line 'scroll-command t) + +(defun scroll-down-line (&optional arg) + "Scroll text of selected window down ARG lines; or one line if no ARG. +If ARG is omitted or nil, scroll down by one line. +This is different from `scroll-down-command' that scrolls a full screen." + (interactive "p") + (scroll-down (or arg 1))) + +(put 'scroll-down-line 'scroll-command t) + + +(defun scroll-other-window-down (lines) + "Scroll the \"other window\" down. +For more details, see the documentation for `scroll-other-window'." + (interactive "P") + (scroll-other-window + ;; Just invert the argument's meaning. + ;; We can do that without knowing which window it will be. + (if (eq lines '-) nil + (if (null lines) '- + (- (prefix-numeric-value lines)))))) + +(defun beginning-of-buffer-other-window (arg) + "Move point to the beginning of the buffer in the other window. +Leave mark at previous position. +With arg N, put point N/10 of the way from the true beginning." + (interactive "P") + (let ((orig-window (selected-window)) + (window (other-window-for-scrolling))) + ;; We use unwind-protect rather than save-window-excursion + ;; because the latter would preserve the things we want to change. + (unwind-protect + (progn + (select-window window) + ;; Set point and mark in that window's buffer. + (with-no-warnings + (beginning-of-buffer arg)) + ;; Set point accordingly. + (recenter '(t))) + (select-window orig-window)))) + +(defun end-of-buffer-other-window (arg) + "Move point to the end of the buffer in the other window. +Leave mark at previous position. +With arg N, put point N/10 of the way from the true end." + (interactive "P") + ;; See beginning-of-buffer-other-window for comments. + (let ((orig-window (selected-window)) + (window (other-window-for-scrolling))) + (unwind-protect + (progn + (select-window window) + (with-no-warnings + (end-of-buffer arg)) + (recenter '(t))) + (select-window orig-window)))) + (defvar mouse-autoselect-window-timer nil "Timer used by delayed window autoselection.") @@ -1668,5 +2038,4 @@ Otherwise, consult the value of `truncate-partial-width-windows' (define-key ctl-x-map "+" 'balance-windows) (define-key ctl-x-4-map "0" 'kill-buffer-and-window) -;; arch-tag: b508dfcc-c353-4c37-89fa-e773fe10cea9 ;;; window.el ends here