X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/791ef5f8ea3810d934f44a4dab828767c7db4acd..71719263212fea7f8b90acef6160497d08da75c4:/lisp/window.el diff --git a/lisp/window.el b/lisp/window.el index fa7b08375c..63d75f60e1 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -1,7 +1,7 @@ ;;; window.el --- GNU Emacs window commands aside from those written in C -;; Copyright (C) 1985, 1989, 1992-1994, 2000-2012 -;; Free Software Foundation, Inc. +;; Copyright (C) 1985, 1989, 1992-1994, 2000-2013 Free Software +;; Foundation, Inc. ;; Maintainer: FSF ;; Keywords: internal @@ -142,42 +142,46 @@ to `display-buffer'." ;; Return the window. window)))) +;; Doc is very similar to with-output-to-temp-buffer. (defmacro with-temp-buffer-window (buffer-or-name action quit-function &rest body) - "Evaluate BODY and display buffer specified by BUFFER-OR-NAME. -BUFFER-OR-NAME must specify either a live buffer or the name of a -buffer. If no buffer with such a name exists, create one. - -Make sure the specified buffer is empty before evaluating BODY. -Do not make that buffer current for BODY. Instead, bind -`standard-output' to that buffer, so that output generated with -`prin1' and similar functions in BODY goes into that buffer. - -After evaluating BODY, mark the specified buffer unmodified and -read-only, and display it in a window via `display-buffer'. Pass -ACTION as action argument to `display-buffer'. Automatically -shrink the window used if `temp-buffer-resize-mode' is enabled. - -Return the value returned by BODY unless QUIT-FUNCTION specifies -a function. In that case, run the function with two arguments - + "Bind `standard-output' to BUFFER-OR-NAME, eval BODY, show the buffer. +BUFFER-OR-NAME must specify either a live buffer, or the name of a +buffer (if it does not exist, this macro creates it). + +This construct makes buffer BUFFER-OR-NAME empty before running BODY. +It does not make the buffer current for BODY. +Instead it binds `standard-output' to that buffer, so that output +generated with `prin1' and similar functions in BODY goes into +the buffer. + +At the end of BODY, this marks the specified buffer unmodified and +read-only, and displays it in a window (but does not select it, or make +the buffer current). The display happens by calling `display-buffer' +with the ACTION argument. If `temp-buffer-resize-mode' is enabled, +the relevant window shrinks automatically. + +This returns the value returned by BODY, unless QUIT-FUNCTION specifies +a function. In that case, it runs the function with two arguments - the window showing the specified buffer and the value returned by -BODY - and return the value returned by that function. +BODY - and returns the value returned by that function. If the buffer is displayed on a new frame, the window manager may decide to select that frame. In that case, it's usually a good -strategy if the function specified by QUIT-FUNCTION selects the -window showing the buffer before reading a value from the -minibuffer, for example, when asking a `yes-or-no-p' question. - -This construct is similar to `with-output-to-temp-buffer' but -does neither put the buffer in help mode nor does it call -`temp-buffer-show-function'. It also runs different hooks, -namely `temp-buffer-window-setup-hook' (with the specified buffer -current) and `temp-buffer-window-show-hook' (with the specified -buffer current and the window showing it selected). - -Since this macro calls `display-buffer', the window displaying -the buffer is usually not selected and the specified buffer -usually not made current. QUIT-FUNCTION can override that." +strategy if QUIT-FUNCTION selects the window showing the buffer +before reading any value from the minibuffer; for example, when +asking a `yes-or-no-p' question. + +This runs the hook `temp-buffer-window-setup-hook' before BODY, +with the specified buffer temporarily current. It runs the +hook `temp-buffer-window-show-hook' after displaying the buffer, +with that buffer temporarily current, and the window that was used to +display it temporarily selected. + +This construct is similar to `with-output-to-temp-buffer', but +runs different hooks. In particular, it does not run +`temp-buffer-setup-hook', which usually puts the buffer in Help mode. +Also, it does not call `temp-buffer-show-function' (the ACTION +argument replaces this)." (declare (debug t)) (let ((buffer (make-symbol "buffer")) (window (make-symbol "window")) @@ -2572,8 +2576,7 @@ move it as far as possible in the desired direction." Interactively, if no argument is given, make the selected window one line taller. If optional argument HORIZONTAL is non-nil, make selected window wider by DELTA columns. If DELTA is -negative, shrink selected window by -DELTA lines or columns. -Return nil." +negative, shrink selected window by -DELTA lines or columns." (interactive "p") (let ((minibuffer-window (minibuffer-window))) (cond @@ -2606,8 +2609,7 @@ Interactively, if no argument is given, make the selected window one line smaller. If optional argument HORIZONTAL is non-nil, make selected window narrower by DELTA columns. If DELTA is negative, enlarge selected window by -DELTA lines or columns. -Also see the `window-min-height' variable. -Return nil." +Also see the `window-min-height' variable." (interactive "p") (let ((minibuffer-window (minibuffer-window))) (cond @@ -3050,8 +3052,10 @@ WINDOW must be a live window and defaults to the selected one." (set-marker (nth 2 entry) point)) ;; Make new markers. (list (copy-marker start) - (copy-marker point))))) - + (copy-marker + ;; Preserve window-point-insertion-type + ;; (Bug#12588). + point window-point-insertion-type))))) (set-window-prev-buffers window (cons entry (window-prev-buffers window)))))))) @@ -3091,10 +3095,11 @@ before was current this also makes BUFFER the current buffer." "If non-nil, allow switching to an already visible buffer. If this variable is non-nil, `switch-to-prev-buffer' and `switch-to-next-buffer' may switch to an already visible buffer -provided the buffer was shown in the argument window before. If -this variable is nil, `switch-to-prev-buffer' and -`switch-to-next-buffer' always try to avoid switching to a buffer -that is already visible in another window on the same frame." +provided the buffer was shown before in the window specified as +argument to those functions. If this variable is nil, +`switch-to-prev-buffer' and `switch-to-next-buffer' always try to +avoid switching to a buffer that is already visible in another +window on the same frame." :type 'boolean :version "24.1" :group 'windows) @@ -3556,7 +3561,12 @@ the buffer of WINDOW. The following values are handled: quad entry) (cond ((and (not prev-buffer) - (memq (nth 1 quit-restore) '(window frame)) + (or (eq (nth 1 quit-restore) 'frame) + (and (eq (nth 1 quit-restore) 'window) + ;; If the window has been created on an existing + ;; frame and ended up as the sole window on that + ;; frame, do not delete it (Bug#12764). + (not (eq window (frame-root-window window))))) (eq (nth 3 quit-restore) buffer) ;; Delete WINDOW if possible. (window--delete window nil (eq bury-or-kill 'kill))) @@ -4550,13 +4560,17 @@ element is BUFFER." ;; If WINDOW has a quit-restore parameter, reset its car. (setcar (window-parameter window 'quit-restore) 'same)) ;; WINDOW shows another buffer. - (set-window-parameter - window 'quit-restore - (list 'other - ;; A quadruple of WINDOW's buffer, start, point and height. - (list (window-buffer window) (window-start window) - (window-point window) (window-total-size window)) - (selected-window) buffer)))) + (with-current-buffer (window-buffer window) + (set-window-parameter + window 'quit-restore + (list 'other + ;; A quadruple of WINDOW's buffer, start, point and height. + (list (current-buffer) (window-start window) + ;; Preserve window-point-insertion-type (Bug#12588). + (copy-marker + (window-point window) window-point-insertion-type) + (window-total-size window)) + (selected-window) buffer))))) ((eq type 'window) ;; WINDOW has been created on an existing frame. (set-window-parameter @@ -5165,11 +5179,12 @@ is higher than WINDOW." (error nil)))) (defun window--display-buffer (buffer window type &optional alist dedicated) - "Display BUFFER in WINDOW and make its frame visible. + "Display BUFFER in WINDOW. TYPE must be one of the symbols `reuse', `window' or `frame' and -is passed unaltered to `display-buffer-record-window'. Set -`window-dedicated-p' to DEDICATED if non-nil. Return WINDOW if -BUFFER and WINDOW are live." +is passed unaltered to `display-buffer-record-window'. ALIST is +the alist argument of `display-buffer'. Set `window-dedicated-p' +to DEDICATED if non-nil. Return WINDOW if BUFFER and WINDOW are +live." (when (and (buffer-live-p buffer) (window-live-p window)) (display-buffer-record-window type window buffer) (unless (eq buffer (window-buffer window)) @@ -5182,10 +5197,10 @@ BUFFER and WINDOW are live." (let ((parameter (window-parameter window 'quit-restore)) (height (cdr (assq 'window-height alist))) (width (cdr (assq 'window-width alist)))) - (when (or (memq type '(window frame)) + (when (or (eq type 'window) (and (eq (car parameter) 'same) - (memq (nth 1 parameter) '(window frame)))) - ;; Adjust height of new window or frame. + (eq (nth 1 parameter) 'window))) + ;; Adjust height of window if asked for. (cond ((not height)) ((numberp height) @@ -5196,19 +5211,12 @@ BUFFER and WINDOW are live." (* (window-total-size (frame-root-window window)) height)))) (delta (- new-height (window-total-size window)))) - (cond - ((and (window--resizable-p window delta nil 'safe) - (window-combined-p window)) - (window-resize window delta nil 'safe)) - ((or (eq type 'frame) - (and (eq (car parameter) 'same) - (eq (nth 1 parameter) 'frame))) - (set-frame-height - (window-frame window) - (+ (frame-height (window-frame window)) delta)))))) + (when (and (window--resizable-p window delta nil 'safe) + (window-combined-p window)) + (window-resize window delta nil 'safe)))) ((functionp height) (ignore-errors (funcall height window)))) - ;; Adjust width of a window or frame. + ;; Adjust width of window if asked for. (cond ((not width)) ((numberp width) @@ -5219,18 +5227,12 @@ BUFFER and WINDOW are live." (* (window-total-size (frame-root-window window) t) width)))) (delta (- new-width (window-total-size window t)))) - (cond - ((and (window--resizable-p window delta t 'safe) - (window-combined-p window t)) - (window-resize window delta t 'safe)) - ((or (eq type 'frame) - (and (eq (car parameter) 'same) - (eq (nth 1 parameter) 'frame))) - (set-frame-width - (window-frame window) - (+ (frame-width (window-frame window)) delta)))))) + (when (and (window--resizable-p window delta t 'safe) + (window-combined-p window t)) + (window-resize window delta t 'safe)))) ((functionp width) (ignore-errors (funcall width window)))))) + window)) (defun window--maybe-raise-frame (frame) @@ -5290,13 +5292,19 @@ See `display-buffer' for details.") "Alist of conditional actions for `display-buffer'. This is a list of elements (CONDITION . ACTION), where: - CONDITION is either a regexp matching buffer names, or a function - that takes a buffer and returns a boolean. + CONDITION is either a regexp matching buffer names, or a + function that takes two arguments - a buffer name and the + ACTION argument of `display-buffer' - and returns a boolean. ACTION is a cons cell (FUNCTION . ALIST), where FUNCTION is a function or a list of functions. Each such function should accept two arguments: a buffer to display and an alist of the - same form as ALIST. See `display-buffer' for details." + same form as ALIST. See `display-buffer' for details. + +`display-buffer' scans this alist until it either finds a +matching regular expression or the function specified by a +condition returns non-nil. In any of these cases, it adds the +associated action to the list of actions it will try." :type `(alist :key-type (choice :tag "Condition" regexp @@ -5330,15 +5338,16 @@ specified, e.g. by the user options `display-buffer-alist' or `display-buffer-base-action'. See `display-buffer'.") (put 'display-buffer-fallback-action 'risky-local-variable t) -(defun display-buffer-assq-regexp (buffer-name alist) - "Retrieve ALIST entry corresponding to BUFFER-NAME." +(defun display-buffer-assq-regexp (buffer-name alist action) + "Retrieve ALIST entry corresponding to BUFFER-NAME. +ACTION is the action argument passed to `display-buffer'." (catch 'match (dolist (entry alist) (let ((key (car entry))) (when (or (and (stringp key) (string-match-p key buffer-name)) - (and (symbolp key) (functionp key) - (funcall key buffer-name alist))) + (and (functionp key) + (funcall key buffer-name action))) (throw 'match (cdr entry))))))) (defvar display-buffer--same-window-action @@ -5414,6 +5423,22 @@ Recognized alist entries include: parameters to give a new frame, if one is created. + `window-height' -- Value specifies either an integer (the number + of lines of a new window), a floating point number (the + fraction of a new window with respect to the height of the + frame's root window) or a function to be called with one + argument - a new window. The function is supposed to adjust + the height of the window; its return value is ignored. + Suitable functions are `shrink-window-if-larger-than-buffer' + and `fit-window-to-buffer'. + + `window-width' -- Value specifies either an integer (the number + of columns of a new window), a floating point number (the + fraction of a new window with respect to the width of the + frame's root window) or a function to be called with one + argument - a new window. The function is supposed to adjust + the width of the window; its return value is ignored. + The ACTION argument to `display-buffer' can also have a non-nil and non-list value. This means to display the buffer in a window other than the selected one, even if it is already displayed in @@ -5432,8 +5457,8 @@ argument, ACTION is t." (funcall display-buffer-function buffer inhibit-same-window) ;; Otherwise, use the defined actions. (let* ((user-action - (display-buffer-assq-regexp (buffer-name buffer) - display-buffer-alist)) + (display-buffer-assq-regexp + (buffer-name buffer) display-buffer-alist action)) (special-action (display-buffer--special-action buffer)) ;; Extra actions from the arguments to this function: (extra-action @@ -5834,8 +5859,8 @@ window on any visible or iconified frame. If this is t, it unconditionally tries to display the buffer at its previous position in the selected window. -This variable is ignored if the the buffer is already displayed -in the selected window or never appeared in it before, or if +This variable is ignored if the buffer is already displayed in +the selected window or never appeared in it before, or if `switch-to-buffer' calls `pop-to-buffer' to display the buffer." :type '(choice (const :tag "Never" nil) @@ -5845,7 +5870,12 @@ in the selected window or never appeared in it before, or if :version "24.3") (defun switch-to-buffer (buffer-or-name &optional norecord force-same-window) - "Switch to buffer BUFFER-OR-NAME in the selected window. + "Display buffer BUFFER-OR-NAME in the selected window. + +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. + If the selected window cannot display the specified buffer (e.g. if it is a minibuffer window or strongly dedicated to another buffer), call `pop-to-buffer' to select the buffer in @@ -6043,26 +6073,30 @@ A frame can be resized if and only if its root window is a live window. The height of the root window is subject to the values of `fit-frame-to-buffer-max-height' and `window-min-height'." :type 'boolean - :version "24.2" + :version "24.3" :group 'help) (defcustom fit-frame-to-buffer-bottom-margin 4 - "Bottom margin for `fit-frame-to-buffer'. -This is the number of lines `fit-frame-to-buffer' leaves free at the -bottom of the display in order to not obscure the system task bar." + "Bottom margin for the command `fit-frame-to-buffer'. +This is the number of lines that function leaves free at the bottom of +the display, in order to not obscure any system task bar or panel. +If you do not have one (or if it is vertical) you might want to +reduce this. If it is thicker, you might want to increase this." + ;; If you set this too small, fit-frame-to-buffer can shift the + ;; frame up to avoid the panel. :type 'integer - :version "24.2" + :version "24.3" :group 'windows) (defun fit-frame-to-buffer (&optional frame max-height min-height) - "Adjust height of FRAME to display its buffer's contents exactly. + "Adjust height of FRAME to display its buffer contents exactly. FRAME can be any live frame and defaults to the selected one. -Optional argument MAX-HEIGHT specifies the maximum height of -FRAME and defaults to the height of the display below the current -top line of FRAME minus FIT-FRAME-TO-BUFFER-BOTTOM-MARGIN. -Optional argument MIN-HEIGHT specifies the minimum height of -FRAME." +Optional argument MAX-HEIGHT specifies the maximum height of FRAME. +It defaults to the height of the display below the current +top line of FRAME, minus `fit-frame-to-buffer-bottom-margin'. +Optional argument MIN-HEIGHT specifies the minimum height of FRAME. +The default corresponds to `window-min-height'." (interactive) (setq frame (window-normalize-frame frame)) (let* ((root (frame-root-window frame)) @@ -6139,6 +6173,10 @@ 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. +If WINDOW is a full height window, then if the option +`fit-frame-to-buffer' is non-nil, this calls the function +`fit-frame-to-buffer' to adjust the frame height. + Return the number of lines by which WINDOW was enlarged or shrunk. If an error occurs during resizing, return nil but don't signal an error.