From: Martin Rudalics Date: Tue, 22 Feb 2011 13:55:12 +0000 (+0100) Subject: Provide functions for saving window states and for converting Emacs 23 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=9dcacdefada6d65cfd2bd4949509a50e238a4e06;p=emacs.git Provide functions for saving window states and for converting Emacs 23 options to display-buffer-alist settings. Fix some minor errors. * window.h (w): New slot clone_number. Rename "inhibit_recombine" slot to "nested". * window.c (Fwindow_clone_number, Fwindow_nested) (Fset_window_nested, Fset_window_clone_number): New functions. (recombine_windows): Write "nested" isntead of "inhibit_recombine". (make_parent_window): Set clone_number. (make_window): Set clone_number. Write "nested" instead of "inhibit_recombine". (Fsplit_window_internal): Write "nested" instead of "inhibit_recombine". (Fresize_window_apply, Fdelete_window_internal): Add parens in EQ test. (saved_window): Add clone_number and write "nested" instead of "inhibit_recombine". (Fset_window_configuration, save_window_save): Set clone_number and write "nested" instead of "inhibit_recombine". (syms_of_window): Add Swindow_clone_number, Swindow_nested, Sset_window_nested and Sset_window_clone_number. * buffer.c (sort_overlays, overlay_strings): When an overlay has the same clone-number property as the associated window don't skip it even if the window properties are different. (syms_of_buffer): Intern new Lisp_object Qclone_number. * window.c (run_window_configuration_change_hook): Call select_frame_norecord instead of Fselect_frame. * progmodes/compile.el (compilation-goto-locus): Call display-buffer-same-frame-other-window. * window.el (window-atom-check-1): Fix handling of case where only one atomic window was left. (window-sizable-p): Fix doc-string. (window-size-fixed-p): Move after window-size-firxed-1. (split-window): Make sure that the new window gets any odd line since this was the Emacs 23 behavior. (window-list-no-nils, window-state-get-1, window-state-get) (window-state-put-1, window-state-put-2, window-state-put): New functions. (window-state-ignored-parameters, window-state-put-list): New variables. (display-buffer-alist): Fix doc-string. (display-buffer-even-sizes): Rename to display-buffer-even-window-sizes. (display-buffer-reuse-window): Call display-buffer-even-window-sizes. (display-buffer-pop-up-window): Don't pass specifiers to side window function. (display-buffer-same-window, display-buffer-same-frame) (display-buffer-other-window) (display-buffer-same-frame-other-window) (pop-to-buffer-same-frame) (pop-to-buffer-same-frame-other-window): Make these interactive. (display-buffer-alist-add, display-buffer-alist-set): New functions. * window.el (display-buffer-pop-up-frame): Fix typo. Pass pop-up-frame-alist to pop-up-frame-function only if the latter is a symbol. * frame.el (pop-up-frame-alist, pop-up-frame-function) (special-display-frame-alist, special-display-popup-frame): Move to window.el. * window.el (display-buffer-alist): Remove some specifiers from default value. Fix some typos. (pop-up-frame-alist, pop-up-frame-function) (special-display-frame-alist, special-display-popup-frame): Move here from frame.el. Disable byte compiler obsolete warnings. (special-display-p, same-window-p): Restore Emacs 23 definitions with obsolete warnings for byte compiler disabled. * window.el (delete-other-windows): Mention return value in doc-string. (display-buffer-method-specifiers): Remove variable. (display-buffer-alist): Add fun-with-args specifier. (display-buffer-even-sizes): Simplify code. (display-buffer): Handle fun-with-args specifier. (mouse-autoselect-window-select): Replace condition-case by ignore-errors. * window.el (display-buffer-even-sizes): Fix typo. --- diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 8d8beb2808a..566057723e7 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,69 @@ +2011-02-22 Martin Rudalics + + * progmodes/compile.el (compilation-goto-locus): Call + display-buffer-same-frame-other-window. + + * window.el (window-atom-check-1): Fix handling of case where + only one atomic window was left. + (window-sizable-p): Fix doc-string. + (window-size-fixed-p): Move after window-size-firxed-1. + (split-window): Make sure that the new window gets any odd line + since this was the Emacs 23 behavior. + (window-list-no-nils, window-state-get-1, window-state-get) + (window-state-put-1, window-state-put-2, window-state-put): New + functions. + (window-state-ignored-parameters, window-state-put-list): New + variables. + (display-buffer-alist): Fix doc-string. + (display-buffer-even-sizes): Rename to + display-buffer-even-window-sizes. + (display-buffer-reuse-window): Call + display-buffer-even-window-sizes. + (display-buffer-pop-up-window): Don't pass specifiers to side + window function. + (display-buffer-same-window, display-buffer-same-frame) + (display-buffer-other-window) + (display-buffer-same-frame-other-window) + (pop-to-buffer-same-frame) + (pop-to-buffer-same-frame-other-window): Make these interactive. + (display-buffer-alist-add, display-buffer-alist-set): New + functions. + +2011-01-22 Martin Rudalics + + * window.el (display-buffer-pop-up-frame): Fix typo. Pass + pop-up-frame-alist to pop-up-frame-function only if the latter + is a symbol. + +2011-01-21 Martin Rudalics + + * frame.el (pop-up-frame-alist, pop-up-frame-function) + (special-display-frame-alist, special-display-popup-frame): Move + to window.el. + + * window.el (display-buffer-alist): Remove some specifiers from + default value. Fix some typos. + (pop-up-frame-alist, pop-up-frame-function) + (special-display-frame-alist, special-display-popup-frame): Move + here from frame.el. Disable byte compiler obsolete warnings. + (special-display-p, same-window-p): Restore Emacs 23 definitions + with obsolete warnings for byte compiler disabled. + +2011-01-19 Martin Rudalics + + * window.el (delete-other-windows): Mention return value in + doc-string. + (display-buffer-method-specifiers): Remove variable. + (display-buffer-alist): Add fun-with-args specifier. + (display-buffer-even-sizes): Simplify code. + (display-buffer): Handle fun-with-args specifier. + (mouse-autoselect-window-select): Replace condition-case by + ignore-errors. + +2011-01-17 Martin Rudalics + + * window.el (display-buffer-even-sizes): Fix typo. + 2011-01-14 Martin Rudalics * simple.el (compose-mail-other-frame): Fix typo introduced in diff --git a/lisp/frame.el b/lisp/frame.el index 9901077736a..fec831dc636 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -95,108 +95,6 @@ appended when the minibuffer frame is created." (sexp :tag "Value"))) :group 'frames) -(defcustom pop-up-frame-alist nil - "Alist of parameters for automatically generated new frames. -You can set this in your init file; for example, - - (setq pop-up-frame-alist '((width . 80) (height . 20))) - -If non-nil, the value you specify here is used by the default -`pop-up-frame-function' for the creation of new frames. - -Since `pop-up-frame-function' is used by `display-buffer' for -making new frames, any value specified here by default affects -the automatic generation of new frames via `display-buffer' and -all functions based on it. The behavior of `make-frame' is not -affected by this variable." - :type '(repeat (cons :format "%v" - (symbol :tag "Parameter") - (sexp :tag "Value"))) - :group 'frames) -(make-obsolete-variable - 'pop-up-frame-alist - "use `display-buffer-alist' or 2nd arg of `display-buffer' instead." - "24.1") - -(defcustom pop-up-frame-function - (lambda () (make-frame pop-up-frame-alist)) - "Function used by `display-buffer' for creating a new frame. -This function is called with no arguments and should return a new -frame. The default value calls `make-frame' with the argument -`pop-up-frame-alist'." - :type 'function - :group 'frames) -(make-obsolete-variable - 'pop-up-frame-function - "use `display-buffer-alist' or 2nd arg of `display-buffer' instead." - "24.1") - -(defcustom special-display-frame-alist - '((height . 14) (width . 80) (unsplittable . t)) - "Alist of parameters for special frames. -Special frames are used for buffers whose names are listed in -`special-display-buffer-names' and for buffers whose names match -one of the regular expressions in `special-display-regexps'. - -This variable can be set in your init file, like this: - - (setq special-display-frame-alist '((width . 80) (height . 20))) - -These supersede the values given in `default-frame-alist'." - :type '(repeat (cons :format "%v" - (symbol :tag "Parameter") - (sexp :tag "Value"))) - :group 'frames) -(make-obsolete-variable - 'special-display-frame-alist - "use `display-buffer-alist' or 2nd arg of `display-buffer' instead." - "24.1") - -(defun special-display-popup-frame (buffer &optional args) - "Display BUFFER and return the window chosen. -If BUFFER is already displayed in a visible or iconified frame, -raise that frame. Otherwise, display BUFFER in a new frame. - -Optional argument ARGS is a list specifying additional -information. - -If ARGS is an alist, use it as a list of frame parameters. If -these parameters contain \(same-window . t), display BUFFER in -the selected window. If they contain \(same-frame . t), display -BUFFER in a window of the selected frame. - -If ARGS is a list whose car is a symbol, use (car ARGS) as a -function to do the work. Pass it BUFFER as first argument, -and (cdr ARGS) as second." - (if (and args (symbolp (car args))) - (apply (car args) buffer (cdr args)) - (let ((window (get-buffer-window buffer 0))) - (or - ;; If we have a window already, make it visible. - (when window - (let ((frame (window-frame window))) - (make-frame-visible frame) - (raise-frame frame) - window)) - ;; Reuse the current window if the user requested it. - (when (cdr (assq 'same-window args)) - (condition-case nil - (progn (switch-to-buffer buffer) (selected-window)) - (error nil))) - ;; Stay on the same frame if requested. - (when (or (cdr (assq 'same-frame args)) (cdr (assq 'same-window args))) - (let* ((pop-up-windows t) - pop-up-frames - special-display-buffer-names special-display-regexps) - (display-buffer buffer))) - ;; If no window yet, make one in a new frame. - (let ((frame - (with-current-buffer buffer - (make-frame (append args special-display-frame-alist))))) - (set-window-buffer (frame-selected-window frame) buffer) - (set-window-dedicated-p (frame-selected-window frame) t) - (frame-selected-window frame)))))) - (defun handle-delete-frame (event) "Handle delete-frame events from the X server." (interactive "e") diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index 97465417228..0a868294f83 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -2117,7 +2117,7 @@ and overlay is highlighted between MK and END-MK." ;; Temporarily select msg-buffer-window to make sure it's not ;; reused by `display-buffer'. (with-selected-window msg-buffer-window - (display-buffer mk-buffer 'same-frame-other-window)))) + (display-buffer-same-frame-other-window mk-buffer)))) ;; Now select mk-buffer-window. (select-window mk-buffer-window) (unless (eq (goto-char mk) (point)) @@ -2225,7 +2225,7 @@ attempts to find a file whose name is produced by (format FMT FILENAME)." (compilation-set-window ;; Apparently the window should be made on the same frame. If ;; it should be made in another window but the selected one - ;; call display-buffer-same-frame-other-window. + ;; replace same-frame by t. (display-buffer-same-frame (marker-buffer marker)) marker) (let* ((name (read-file-name (format "Find this %s in (default %s): " diff --git a/lisp/window.el b/lisp/window.el index df4e298a506..b85de714f24 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -359,7 +359,6 @@ WINDOW must be an internal window. Return WINDOW." window t) window)) - (defun window-atom-check-1 (window) "Subroutine of `window-atom-check'." (when window @@ -372,7 +371,9 @@ WINDOW must be an internal window. Return WINDOW." (setq count (1+ count)) (throw 'reset t))) window t)) - (zerop count)) + ;; count >= 1 must hold here. If there's no other + ;; window around dissovle this atomic window. + (= count 1)) ;; Dissolve atomic window. (walk-window-subtree (lambda (window) @@ -381,9 +382,9 @@ WINDOW must be an internal window. Return WINDOW." ;; Check children. (unless (window-buffer window) (window-atom-check-1 (window-hchild window)) - (window-atom-check-1 (window-vchild window))) - ;; Check right sibling - (window-atom-check-1 (window-right window))))) + (window-atom-check-1 (window-vchild window)))) + ;; Check right sibling + (window-atom-check-1 (window-right window)))) (defun window-atom-check (&optional frame) "Check atomicity of all windows on FRAME. @@ -803,7 +804,7 @@ restrictions for that window only." (t 0))) (defsubst window-sizable-p (window delta &optional horizontal ignore) - "Return t if WINDOW can have DELTA lines. + "Return t if WINDOW can be resized by DELTA lines. For the meaning of the arguments of this function see the doc-string of `window-sizable'." (setq window (normalize-any-window window)) @@ -811,18 +812,6 @@ doc-string of `window-sizable'." (>= (window-sizable window delta horizontal ignore) delta) (<= (window-sizable window delta horizontal ignore) delta))) -(defun window-size-fixed-p (&optional window horizontal) - "Return non-nil if WINDOW's height is fixed. -WINDOW can be an arbitrary window and defaults to the selected -window. Optional argument HORIZONTAL non-nil means return -non-nil if WINDOW's width is fixed. - -If this function returns nil, this does not necessarily mean that -WINDOW can be resized in the desired direction. The functions -`window-resizable' and `window-resizable-p' will tell that." - (window-size-fixed-1 - (normalize-any-window window) horizontal)) - (defun window-size-fixed-1 (window horizontal) "Internal function for `window-size-fixed-p'." (let ((sub (window-child window))) @@ -856,6 +845,18 @@ WINDOW can be resized in the desired direction. The functions (memq window-size-fixed '(width t)) (memq window-size-fixed '(height t)))))))) +(defun window-size-fixed-p (&optional window horizontal) + "Return non-nil if WINDOW's height is fixed. +WINDOW can be an arbitrary window and defaults to the selected +window. Optional argument HORIZONTAL non-nil means return +non-nil if WINDOW's width is fixed. + +If this function returns nil, this does not necessarily mean that +WINDOW can be resized in the desired direction. The functions +`window-resizable' and `window-resizable-p' will tell that." + (window-size-fixed-1 + (normalize-any-window window) horizontal)) + (defun window-min-delta (&optional window horizontal ignore side noup nodown) "Return number of lines by which WINDOW can be shrunk. WINDOW can be an arbitrary window and defaults to the selected @@ -1767,7 +1768,7 @@ DELTA is greater zero. Any other value of SIDE is ignored." ;; present round. `delta' is de-/increased by the sum of ;; `sub-amount' for all subwindows we we're not able to resize ;; completely in the present round. So `amount' and `delta' - ;; grow/shrink towards each other and we are done when the have + ;; grow/shrink towards each other and we are done when they have ;; the same value. `sub-rest' is the remainder when calculating ;; `sub-delta' and is used when calculating the new normal ;; sizes. @@ -2482,6 +2483,7 @@ non-side window, signal an error." (defun delete-other-windows (&optional window) "Make WINDOW fill its frame. WINDOW may be any window and defaults to the selected one. +Return nil. If the variable `ignore-window-parameters' is non-nil do not process any parameters of WINDOW. Otherwise, if the @@ -3124,20 +3126,21 @@ selected on WINDOW's frame." (max (window-split-min-size horflag) (if resize ;; For a "resize" split try to give the new - ;; window a fitting size (which must be at least - ;; as large as what we can get at all). + ;; window a fitting size (which must be at + ;; least as large as what we can get in the + ;; first place). (min (- parent-size (window-min-size parent horflag)) (/ parent-size (1+ (window-iso-combinations parent horflag)))) - ;; Else try to give the new window half the size of - ;; WINDOW. - (/ old-size 2)))) + ;; Else try to give the new window half the size + ;; of WINDOW (plus an eventual odd line). + (+ (/ old-size 2) (% old-size 2))))) ((>= size 0) ;; SIZE non-negative specifies the new size of WINDOW. ;; Note: Specifying a non-negative SIZE is practically - ;; always doen to have a workaround for making the new + ;; always done to have a workaround for making the new ;; window appear above or on the left of the new window ;; (the ispell window is a typical example of that). In ;; all these cases the HORIZONTAL argument should be set @@ -3553,6 +3556,306 @@ specific buffers." ;; (message "Done in %d rounds" round) )) +;;; Window states, how to get them and how to put them in a window. +(defsubst window-list-no-nils (&rest args) + "Like LIST but do not add nil elements of ARGS." + (delq nil (apply 'list args))) + +(defvar window-state-ignored-parameters '(quit-restore) + "List of window parameters ignored by `window-state-get'.") + +(defun window-state-get-1 (window &optional markers) + "Helper function for `window-state-get'." + (let* ((type + (cond + ((window-vchild window) 'vc) + ((window-hchild window) 'hc) + (t 'leaf))) + (buffer (window-buffer window)) + (selected (eq window (selected-window))) + (head + (window-list-no-nils + type + (unless (window-next window) (cons 'last t)) + (cons 'clone-number (window-clone-number window)) + (cons 'total-height (window-total-size window)) + (cons 'total-width (window-total-size window t)) + (cons 'normal-height (window-normal-size window)) + (cons 'normal-width (window-normal-size window t)) + (when (and (not buffer) (window-nested window)) + (cons 'nested t)) + (let (list) + (dolist (parameter (window-parameters window)) + (unless (memq (car parameter) + window-state-ignored-parameters) + (setq list (cons parameter list)))) + (when list + (cons 'parameters list))) + (when buffer + ;; All buffer related things go in here - make the buffer + ;; current when retrieving `point' and `mark'. + (with-current-buffer (window-buffer window) + (let ((point (if selected (point) (window-point window))) + (start (window-start window)) + (mark (mark))) + (window-list-no-nils + 'buffer (buffer-name buffer) + (cons 'selected selected) + (when window-size-fixed (cons 'size-fixed window-size-fixed)) + (cons 'hscroll (window-hscroll window)) + (cons 'fringes (window-fringes window)) + (cons 'margins (window-margins window)) + (cons 'scroll-bars (window-scroll-bars window)) + (cons 'vscroll (window-vscroll window)) + (cons 'dedicated (window-dedicated-p window)) + (cons 'point (if markers (copy-marker point) point)) + (cons 'start (if markers (copy-marker start) start)) + (when mark + (cons 'mark (if markers (copy-marker mark) mark))))))))) + (tail + (when (memq type '(vc hc)) + (let (list) + (setq window (window-child window)) + (while window + (setq list (cons (window-state-get-1 window markers) list)) + (setq window (window-right window))) + (nreverse list))))) + (append head tail))) + +(defun window-state-get (&optional window markers) + "Return state of WINDOW as a Lisp object. +WINDOW can be any window and defaults to the root window of the +selected frame. + +Optional argument MARKERS non-nil means use markers for sampling +positions like `window-point' or `window-start'. MARKERS should +be non-nil only if the value is used for putting the state back +in the same session (note that markers slow down processing). + +The return value can be used as argument for `window-state-put' +to put the state recorded here into an arbitrary window. The +value can be also stored on disk and read back in a new session." + (setq window + (if window + (if (window-any-p window) + window + (error "%s is not a live or internal window" window)) + (frame-root-window))) + ;; The return value is a cons whose car specifies some constraints on + ;; the size of WINDOW. The cdr lists the states of the subwindows of + ;; WINDOW. + (cons + ;; Frame related things would go into a function, say `frame-state', + ;; calling `window-state-get' to insert the frame's root window. + (window-list-no-nils + (cons 'min-height (window-min-size window)) + (cons 'min-width (window-min-size window t)) + (cons 'min-height-ignore (window-min-size window nil t)) + (cons 'min-width-ignore (window-min-size window t t)) + (cons 'min-height-safe (window-min-size window nil 'safe)) + (cons 'min-width-safe (window-min-size window t 'safe)) + ;; These are probably not needed. + (when (window-size-fixed-p window) (cons 'fixed-height t)) + (when (window-size-fixed-p window t) (cons 'fixed-width t))) + (window-state-get-1 window markers))) + +(defvar window-state-put-list nil + "Helper variable for `window-state-put'.") + +(defun window-state-put-1 (state &optional window ignore totals) + "Helper function for `window-state-put'." + (let ((type (car state))) + (setq state (cdr state)) + (cond + ((eq type 'leaf) + ;; For a leaf window just add unprocessed entries to + ;; `window-state-put-list'. + (setq window-state-put-list + (cons (cons window state) window-state-put-list))) + ((memq type '(vc hc)) + (let* ((horflag (eq type 'hc)) + (total (window-total-size window horflag)) + (first t) + size new) + (dolist (item state) + ;; Find the next child window. WINDOW always points to the + ;; real window that we want to fill with what we find here. + (when (memq (car item) '(leaf vc hc)) + (if (assq 'last item) + ;; The last child window. Below `window-state-put-1' + ;; will put into it whatever ITEM has in store. + (setq new nil) + ;; Not the last child window, prepare for splitting + ;; WINDOW. SIZE is the new (and final) size of the old + ;; window. + (setq size + (if totals + ;; Use total size. + (cdr (assq (if horflag 'total-width 'total-height) item)) + ;; Use normalized size and round. + (round (* total + (cdr (assq + (if horflag 'normal-width 'normal-height) + item)))))) + + ;; Use safe sizes, we try to resize later. + (setq size (max size (if horflag + window-safe-min-height + window-safe-min-width))) + + (if (window-sizable-p window (- size) horflag 'safe) + (let* ((window-splits (when (assq 'nested item) 'nest))) + ;; We must inherit the nesting, otherwise we might mess + ;; up handling of atomic and side window. + (setq new (split-window window size horflag))) + ;; Give up if we can't resize window down to safe sizes. + (error "Cannot resize window %s" window)) + + (when first + (setq first nil) + ;; When creating the first child window add for parent + ;; unprocessed entries to `window-state-put-list'. + (setq window-state-put-list + (cons (cons (window-parent window) state) + window-state-put-list)))) + + ;; Now process the current window (either the one we've just + ;; split or the last child of its parent). + (window-state-put-1 item window ignore totals) + ;; Continue with the last window split off. + (setq window new)))))))) + +(defun window-state-put-2 (ignore) + "Helper function for `window-state-put'." + (dolist (item window-state-put-list) + (let ((window (car item)) + (clone-number (cdr (assq 'clone-number item))) + (parameters (cdr (assq 'parameters item))) + (state (cdr (assq 'buffer item)))) + ;; Put in clone-number. + (when clone-number (set-window-clone-number window clone-number)) + ;; Process parameters. + (when parameters + (dolist (parameter parameters) + (set-window-parameter window (car parameter) (cdr parameter)))) + ;; Process buffer related state. + (when state + ;; We don't want to raise an error here so we create a buffer if + ;; there's none. + (set-window-buffer window (get-buffer-create (car state))) + (with-current-buffer (window-buffer window) + (set-window-hscroll window (cdr (assq 'hscroll state))) + (apply 'set-window-fringes + (cons window (cdr (assq 'fringes state)))) + (let ((margins (cdr (assq 'margins state)))) + (set-window-margins window (car margins) (cdr margins))) + (let ((scroll-bars (cdr (assq 'scroll-bars state)))) + (set-window-scroll-bars + window (car scroll-bars) (nth 2 scroll-bars) (nth 3 scroll-bars))) + (set-window-vscroll window (cdr (assq 'vscroll state))) + ;; Adjust vertically. + (if (memq window-size-fixed '(t height)) + ;; A fixed height window, try to restore the original size. + (let ((delta (- (cdr (assq 'total-height item)) + (window-total-height window))) + window-size-fixed) + (when (window-resizable-p window delta) + (resize-window window delta))) + ;; Else check whether the window is not high enough. + (let* ((min-size (window-min-size window nil ignore)) + (delta (- min-size (window-total-size window)))) + (when (and (> delta 0) + (window-resizable-p window delta nil ignore)) + (resize-window window delta nil ignore)))) + ;; Adjust horizontally. + (if (memq window-size-fixed '(t width)) + ;; A fixed width window, try to restore the original size. + (let ((delta (- (cdr (assq 'total-width item)) + (window-total-width window))) + window-size-fixed) + (when (window-resizable-p window delta) + (resize-window window delta))) + ;; Else check whether the window is not wide enough. + (let* ((min-size (window-min-size window t ignore)) + (delta (- min-size (window-total-size window t)))) + (when (and (> delta 0) + (window-resizable-p window delta t ignore)) + (resize-window window delta t ignore)))) + ;; Set dedicated status. + (set-window-dedicated-p window (cdr (assq 'dedicated state))) + ;; Install positions (maybe we should do this after all windows + ;; have been created and sized). + (ignore-errors + (set-window-start window (cdr (assq 'start state))) + (set-window-point window (cdr (assq 'point state))) + ;; I'm not sure whether we should set the mark here, but maybe + ;; it can be used. + (let ((mark (cdr (assq 'mark state)))) + (when mark (set-mark mark)))) + ;; Select window if it's the selected one. + (when (cdr (assq 'selected state)) + (select-window window))))))) + +(defun window-state-put (state &optional window ignore) + "Put window state STATE into WINDOW. +STATE should be the state of a window returned by an earlier +invocation of `window-state-get'. Optional argument WINDOW must +specify a live window and defaults to the selected one. + +Optional argument IGNORE non-nil means ignore minimum window +sizes and fixed size restrictions. IGNORE equal `safe' means +subwindows can get as small as `window-safe-min-height' and +`window-safe-min-width'." + (setq window (normalize-live-window window)) + (let* ((frame (window-frame window)) + (head (car state)) + ;; We check here (1) whether the total sizes of root window of + ;; STATE and that of WINDOW are equal so we can avoid + ;; calculating new sizes, and (2) if we do have to resize + ;; whether we can do so without violating size restrictions. + (totals + (and (= (window-total-size window) + (cdr (assq 'total-height state))) + (= (window-total-size window t) + (cdr (assq 'total-width state))))) + (min-height (cdr (assq 'min-height head))) + (min-width (cdr (assq 'min-width head))) + window-splits selected) + (if (and (not totals) + (or (> min-height (window-total-size window)) + (> min-width (window-total-size window t))) + (or (not ignore) + (and (setq min-height + (cdr (assq 'min-height-ignore head))) + (setq min-width + (cdr (assq 'min-width-ignore head))) + (or (> min-height (window-total-size window)) + (> min-width (window-total-size window t))) + (or (not (eq ignore 'safe)) + (and (setq min-height + (cdr (assq 'min-height-safe head))) + (setq min-width + (cdr (assq 'min-width-safe head))) + (or (> min-height + (window-total-size window)) + (> min-width + (window-total-size window t)))))))) + ;; The check above might not catch all errors due to rounding + ;; issues - so IGNORE equal 'safe might not always produce the + ;; minimum possible state. But such configurations hardly make + ;; sense anyway. + (error "Window %s too small to accomodate state" window) + (setq state (cdr state)) + (setq window-state-put-list nil) + ;; Work on the windows of a temporary buffer to make sure that + ;; splitting proceeds regardless of any buffer local values of + ;; `window-size-fixed'. Release that buffer after the buffers of + ;; all live windows have been set by `window-state-put-2'. + (with-temp-buffer + (set-window-buffer window (current-buffer)) + (window-state-put-1 state window nil totals) + (window-state-put-2 ignore)) + (window-check frame)))) ;;; Displaying buffers. (defgroup display-buffer nil @@ -3560,9 +3863,6 @@ specific buffers." :version "24.1" :group 'windows) -(defconst display-buffer-method-specifiers '(reuse-window pop-up-window pop-up-frame) - "Buffer display method specifiers.") - (defconst display-buffer-default-specifiers '((reuse-window nil same visible) (pop-up-window (largest . nil) (lru . nil)) @@ -3612,12 +3912,8 @@ buffer display specifiers.") reuse-window (reuse-window nil same visible) pop-up-window (pop-up-window (largest . nil) (lru . nil)) - (pop-up-window-min-height . 24) - (pop-up-window-min-width . 60) pop-up-frame (pop-up-frame) - (pop-up-frame-alist - (height . 24) (width . 80) (unsplittable . t)) reuse-window (reuse-window nil other visible) (reuse-window-even-sizes . t))) "List associating buffer identifiers with display specifiers. @@ -3640,9 +3936,9 @@ match occurs in one of the following three cases: the third \(LABEL) argument of `display-buffer'. Display specifiers are either symbols, cons cells, or lists. -Three specifiers indicate the basic method for displaying the -buffer: `reuse-window', `pop-up-window', `pop-up-frame' and -`use-side-window'. +Five specifiers have been reserved to indicate the basic method +for displaying the buffer: `reuse-window', `pop-up-window', +`pop-up-frame', `use-side-window', and `fun-with-args'. A list whose car is the symbol `reuse-window' indicates that an existing window shall be reused for displaying the buffer. The @@ -3726,9 +4022,9 @@ split the new window shall appear and can be one of `below', `right', `above', or `left' with the obvious meanings. If the cdr is nil, the window is split in a fashion suitable for its current dimensions. If the cdr specifies a function, that -function is called with two arguments - the window to split and a -list of display specifiers. The function is supposed to split -that window and return the new window. +function is called with one argument - the window to split. The +function is supposed to split that window and return the new +window. `display-buffer' scans these tuples until it can either produce a suitable window or fails. The default value for @@ -3769,7 +4065,7 @@ The following specifiers are useful if the method specifier is - If the cdr specifies a function, that function is called with one argument - the new window. The function is supposed to - adjust the height of the window, its return value is ignored. + 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'. @@ -3806,15 +4102,15 @@ displays only. The following specifiers are useful if the method specifier is `pop-up-frame'. -- A list whose car is the symbol `popup-frame-function' together +- A list whose car is the symbol `pop-up-frame-function' together with a valid function as cdr specifies the function for creating a new frame. If the cdr is nil, the default function `make-frame' is called. The function is called with the parameters and values provided by the specifier described next. -- A list whose car is the symbol `popup-frame-alist' followed by +- A list whose car is the symbol `pop-up-frame-alist' followed by an arbitrary number of frame parameter/value tuples, each given - as a cons cell, specifies the parameters passed to the popup + as a cons cell, specifies the parameters passed to the pop-up frame function. A list of three elements whose car is the symbol @@ -3830,6 +4126,21 @@ The following specifiers are useful in connection with the `pop-up-window-min-height', `pop-up-window-min-width', `pop-up-window-set-height' and `pop-up-window-set-width'. +A list whose car is the symbol `fun-with-args' specifies that the +function specified in the second element of the list is +responsible for displaying the buffer. `display-buffer' calls +this function with the buffer as first argument and the remaining +elements of the list as second argument. + +The function should choose or create a window, display the buffer +in it, and return the window. It is also responsible for giving +the variable `display-buffer-window' and the `quit-restore' +parameter of the window used a meaningful value. + +Within the body of this function avoid calling `display-buffer' +with the same buffer as argument since this may lead to endless +recursion. + Instead of supplying basic method specifiers, it's sometimes more convenient to use macro specifiers. They provide some commonly used display methods but do not support the fine control provided @@ -4232,6 +4543,31 @@ using the location specifiers `same-window' or `other-frame'." (float :tag "Fraction of frame width" :value .25 :size 5) (function :tag "Function" :size 25))))) + ;; Function with argument specifiers. + (list + :tag "Function with arguments" + :value (fun-with-args (fun-with-args 'ignore)) + :format "%t\n%v" + :inline t + ;; For customization purposes only. + (const :format "" fun-with-args) + (set + :format "%v" + :inline t + (list + :format "%v" + :value (fun-with-args 'ignore) + (const :format "" fun-with-args) + (function :tag "Function" :format "%t: %v\n" :size 25) + (list + :format "%v" + (repeat + :tag "Arguments" + :inline t + (sexp + :format "%v\n" + :size 16)))))) + ;; Macro specifiers. (list :tag "Same frame only" @@ -4336,7 +4672,7 @@ meaningful value to this variable. See the functions `display-buffer-reuse-window', `display-buffer-pop-up-window' and `display-buffer-pop-up-frame' for how this can be done.") -(defun display-buffer-even-sizes (window specifiers) +(defun display-buffer-even-window-sizes (window specifiers) "Even sizes of WINDOW and selected window according to SPECIFIERS. SPECIFIERS must be a list of buffer display specifiers, see the documentation of `display-buffer-alist' for a description. @@ -4344,35 +4680,34 @@ documentation of `display-buffer-alist' for a description. Sizes are evened out if and only if WINDOW and the selected window appear next to each other and the selected window is larger than WINDOW." - (let ((even-window-sizes (cdr (assq 'even-window-sizes specifiers)))) - (cond - ((or (not even-window-sizes) - ;; Don't resize minibuffer windows. - (window-minibuffer-p) - ;; WINDOW must be adjacent to the selected one. - (not (or (eq window (window-prev)) - (eq window (window-next)))))) - ((and (window-iso-combined-p window) - ;; Resize iff the selected window is higher than WINDOW. - (> (window-total-height) (window-total-height window))) - ;; Don't throw an error if we can't even window heights for - ;; whatever reason. In any case, enlarging the selected window - ;; might fail anyway if there are other windows above or below - ;; WINDOW and the selected one. But for a simple two windows - ;; configuration the present behavior is good enough so why care? - (ignore-errors - (resize-window - window (/ (- (window-total-height) (window-total-height window)) - 2)))) - ((and (window-iso-combined-p window t) - ;; Resize iff the selected window is wider than WINDOW. - (> (window-total-width) (window-total-width window))) - ;; Don't throw an error if we can't even window widths, see - ;; comment above. - (ignore-errors - (resize-window - window (/ (- (window-total-width) (window-total-width window)) - 2) t)))))) + (cond + ((or (not (cdr (assq 'reuse-window-even-sizes specifiers))) + ;; Don't resize minibuffer windows. + (window-minibuffer-p) + ;; WINDOW must be adjacent to the selected one. + (not (or (eq window (window-prev)) + (eq window (window-next)))))) + ((and (window-iso-combined-p window) + ;; Resize iff the selected window is higher than WINDOW. + (> (window-total-height) (window-total-height window))) + ;; Don't throw an error if we can't even window heights for + ;; whatever reason. In any case, enlarging the selected window + ;; might fail anyway if there are other windows above or below + ;; WINDOW and the selected one. But for a simple two windows + ;; configuration the present behavior is good enough so why care? + (ignore-errors + (resize-window + window (/ (- (window-total-height) (window-total-height window)) + 2)))) + ((and (window-iso-combined-p window t) + ;; Resize iff the selected window is wider than WINDOW. + (> (window-total-width) (window-total-width window))) + ;; Don't throw an error if we can't even window widths, see + ;; comment above. + (ignore-errors + (resize-window + window (/ (- (window-total-width) (window-total-width window)) + 2) t))))) (defun display-buffer-set-height (window specifiers) "Adjust height of WINDOW according to SPECIFIERS. @@ -4537,7 +4872,7 @@ none was found." (car windows)))) (when best-window - (display-buffer-even-sizes best-window specifiers) + (display-buffer-even-window-sizes best-window specifiers) ;; Never change the quit-restore parameter of a window here. (if (eq (window-buffer best-window) buffer) (setq display-buffer-window @@ -4755,7 +5090,8 @@ description." (display-buffer-split-window window side specifiers))) ((functionp side) (ignore-errors - (funcall side window specifiers))))) + ;; Don't pass any specifiers to this function. + (funcall side window))))) (throw 'done window)))) (when window @@ -4777,10 +5113,15 @@ SPECIFIERS must be a list of buffer display specifiers, see the documentation of `display-buffer-alist' for a description." (unless (and graphic-only (not (display-graphic-p))) (let* ((selected-window (selected-window)) - (function (or (cdr (assq 'popup-frame-function specifiers)) + (function (or (cdr (assq 'pop-up-frame-function specifiers)) 'make-frame)) - (parameters (cdr (assq 'popup-frame-alist specifiers))) - (frame (funcall function parameters))) + (parameters + (when (symbolp function) + (cdr (assq 'pop-up-frame-alist specifiers)))) + (frame + (if (symbolp function) + (funcall function parameters) + (funcall function)))) (when frame (let ((window (frame-selected-window frame))) (set-window-parameter @@ -5153,7 +5494,9 @@ this list as arguments." buffer (cdr specifier) specifiers)) ((eq method 'use-side-window) (display-buffer-in-side-window - buffer (nth 1 specifier) (nth 2 specifier) specifiers))))) + buffer (nth 1 specifier) (nth 2 specifier) specifiers)) + ((eq method 'fun-with-args) + (apply (cadr specifier) buffer (cddr specifier)))))) ;; If we don't have a window yet, try a fallback method. All ;; specifiers have been used up by now. @@ -5179,6 +5522,7 @@ Another window will be used only if the buffer can't be shown in the selected window, usually because it is dedicated to another buffer. Optional argument BUFFER-OR-NAME and LABEL are as for `display-buffer'." + (interactive "BDisplay buffer in same window:\nP") (display-buffer buffer-or-name 'same-window label)) (defsubst display-buffer-same-frame (&optional buffer-or-name label) @@ -5186,6 +5530,7 @@ buffer. Optional argument BUFFER-OR-NAME and LABEL are as for Another frame will be used only if there is no other choice. Optional argument BUFFER-OR-NAME and LABEL are as for `display-buffer'." + (interactive "BDisplay buffer on same frame:\nP") (display-buffer buffer-or-name 'same-frame label)) (defsubst display-buffer-other-window (&optional buffer-or-name label) @@ -5194,6 +5539,7 @@ The selected window will be used only if there is no other choice. Windows on the selected frame are preferred to windows on other frames. Optional argument BUFFER-OR-NAME and LABEL are as for `display-buffer'." + (interactive "BDisplay buffer in another window:\nP") (display-buffer buffer-or-name 'other-window label)) (defun display-buffer-same-frame-other-window (&optional buffer-or-name label) @@ -5201,6 +5547,7 @@ for `display-buffer'." The selected window or another frame will be used only if there is no other choice. Optional argument BUFFER-OR-NAME and LABEL are as for `display-buffer'." + (interactive "BDisplay buffer in another window on same frame:\nP") (display-buffer buffer-or-name 'same-frame-other-window label)) (defun pop-to-buffer (&optional buffer-or-name specifiers norecord label) @@ -5257,7 +5604,7 @@ as for `pop-to-buffer'." Another frame will be used only if there is no other choice. Optional arguments BUFFER-OR-NAME, NORECORD and LABEL are as for `pop-to-buffer'." - (interactive "BPop to buffer in another window:\nP") + (interactive "BPop to buffer on same frame:\nP") (pop-to-buffer buffer-or-name 'same-frame norecord label)) (defsubst pop-to-buffer-other-window (&optional buffer-or-name norecord label) @@ -5274,7 +5621,7 @@ LABEL are as for `pop-to-buffer'." The selected window or another frame will be used only if there is no other choice. Optional arguments BUFFER-OR-NAME, NORECORD and LABEL are as for `pop-to-buffer'." - (interactive "BPop to buffer in another window:\nP") + (interactive "BPop to buffer in another window on same frame:\nP") (pop-to-buffer buffer-or-name 'same-frame-other-window norecord label)) (defsubst pop-to-buffer-other-frame (&optional buffer-or-name norecord label) @@ -5414,6 +5761,112 @@ functions should call `pop-to-buffer-other-frame' instead." (pop-to-buffer buffer 'other-frame norecord))) ;;; Obsolete definitions of `display-buffer' below. +(defcustom pop-up-frame-alist nil + "Alist of parameters for automatically generated new frames. +You can set this in your init file; for example, + + (setq pop-up-frame-alist '((width . 80) (height . 20))) + +If non-nil, the value you specify here is used by the default +`pop-up-frame-function' for the creation of new frames. + +Since `pop-up-frame-function' is used by `display-buffer' for +making new frames, any value specified here by default affects +the automatic generation of new frames via `display-buffer' and +all functions based on it. The behavior of `make-frame' is not +affected by this variable." + :type '(repeat (cons :format "%v" + (symbol :tag "Parameter") + (sexp :tag "Value"))) + :group 'frames) +(make-obsolete-variable + 'pop-up-frame-alist + "use `display-buffer-alist' or 2nd arg of `display-buffer' instead." + "24.1") + +(defcustom pop-up-frame-function + (lambda () (make-frame pop-up-frame-alist)) + "Function used by `display-buffer' for creating a new frame. +This function is called with no arguments and should return a new +frame. The default value calls `make-frame' with the argument +`pop-up-frame-alist'." + :type 'function + :group 'frames) +(make-obsolete-variable + 'pop-up-frame-function + "use `display-buffer-alist' or 2nd arg of `display-buffer' instead." + "24.1") + +(defcustom special-display-frame-alist + '((height . 14) (width . 80) (unsplittable . t)) + "Alist of parameters for special frames. +Special frames are used for buffers whose names are listed in +`special-display-buffer-names' and for buffers whose names match +one of the regular expressions in `special-display-regexps'. + +This variable can be set in your init file, like this: + + (setq special-display-frame-alist '((width . 80) (height . 20))) + +These supersede the values given in `default-frame-alist'." + :type '(repeat (cons :format "%v" + (symbol :tag "Parameter") + (sexp :tag "Value"))) + :group 'frames) +(make-obsolete-variable + 'special-display-frame-alist + "use `display-buffer-alist' or 2nd arg of `display-buffer' instead." + "24.1") + +(defun special-display-popup-frame (buffer &optional args) + "Display BUFFER in a special frame and return the window chosen. +If BUFFER is already displayed in a visible or iconified frame, +raise that frame. Otherwise, display BUFFER in a way as +specified by optional argument ARGS. + +If ARGS is an alist, use it as a list of frame parameters. If +these parameters contain \(same-window . t), display BUFFER in +the selected window. If they contain \(same-frame . t), display +BUFFER in a window on the selected frame. + +If ARGS is a list whose car is a symbol, use (car ARGS) as a +function to do the work. Pass it BUFFER as first argument, +and (cdr ARGS) as second." + (if (and args (symbolp (car args))) + (apply (car args) buffer (cdr args)) + (let ((window (get-buffer-window buffer 0))) + (or + ;; If we have a window already, make it visible. + (when window + (let ((frame (window-frame window))) + (make-frame-visible frame) + (raise-frame frame) + window)) + ;; Reuse the current window if the user requested it. + (when (cdr (assq 'same-window args)) + (display-buffer-reuse-window + buffer '(same nil nil) '((reuse-dedicated . 'weak)))) + ;; Stay on the same frame if requested. + (when (or (cdr (assq 'same-frame args)) + (cdr (assq 'same-window args))) + (or (display-buffer-pop-up-window + buffer '((largest . nil) (lru . nil))) + (display-buffer-reuse-window + buffer '(nil nil nil)))) + ;; If no window yet, make one in a new frame. + (let ((frame + (with-current-buffer buffer + (make-frame + (append args (with-no-warnings + special-display-frame-alist)))))) + (set-window-buffer (frame-selected-window frame) buffer) + (set-window-dedicated-p (frame-selected-window frame) t) + (frame-selected-window frame)))))) +(make-obsolete + 'special-display-popup-frame + "use `display-buffer-alist' or 2nd arg of `display-buffer' instead." + "24.1") + (defcustom special-display-buffer-names nil "List of names of buffers that should be displayed specially. Displaying a buffer with `display-buffer' or `pop-to-buffer', if @@ -5558,22 +6011,32 @@ See also `special-display-buffer-names'." (defun special-display-p (buffer-name) "Return non-nil if a buffer named BUFFER-NAME gets a special frame. -More precisely, return t if `display-buffer-alist' would ask for -displayin BUFFER-NAME in a special way." - (catch 'found - (dolist (entry display-buffer-alist) - (when (and (listp entry) - (catch 'match - (dolist (id (car entry)) - (when (consp id) - (let ((type (car id)) - (value (cdr id))) - (when (or (and (eq type 'name) (stringp value) - (equal value buffer-name)) - (and (eq type 'regexp) (stringp value) - (string-match-p value buffer-name))) - (throw 'match t))))))) - (throw 'found (cdr entry)))))) +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 ((buffer-names (with-no-warnings + special-display-buffer-names)) + (regexps (with-no-warnings + special-display-regexps)) + tmp) + (cond + ((not (stringp buffer-name))) + ((member buffer-name buffer-names) + t) + ((setq tmp (assoc buffer-name buffer-names)) + (cdr tmp)) + ((catch 'found + (dolist (regexp 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)))))))))) (make-obsolete 'special-display-p "pass argument to buffer display function instead." "24.1") (defcustom special-display-function 'special-display-popup-frame @@ -5635,24 +6098,29 @@ See also `same-window-buffer-names'." (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-alist' contains -an entry stating that a buffer named BUFFER-NAME should be -displayed in the selected rather than some other window." - (catch 'found - (dolist (entry display-buffer-alist) - (when (and (listp entry) - (catch 'match - (dolist (id (car entry)) - (when (consp id) - (let ((type (car id)) - (value (cdr id))) - (when (or (and (eq type 'name) (stringp value) - (equal value buffer-name)) - (and (eq type 'regexp) (stringp value) - (string-match-p value buffer-name))) - (throw 'match t))))))) - (when (eq (cadr entry) 'same-window) - (throw 'found t)))))) +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'." + (let ((buffer-names (with-no-warnings + (same-window-buffer-names))) + (regexps (with-no-warnings + (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 buffer-names)) + ((assoc buffer-name buffer-names)) + ((catch 'found + (dolist (regexp 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)))))))) (make-obsolete 'same-window-p "pass argument to buffer display function instead." "24.1") (defcustom pop-up-frames nil @@ -5792,6 +6260,217 @@ The actual non-nil value of this variable will be copied to the 'display-buffer-mark-dedicated "use `display-buffer-alist' or 2nd arg of `display-buffer' instead." "24.1") + +;; Functions for converting Emacs 23 buffer display options to buffer +;; display specifiers. +(defun display-buffer-alist-add (identifiers specifiers &optional no-custom) + "Helper function for `display-buffer-alist-set'." + (unless identifiers + (setq identifiers '((regexp . ".*")))) + (unless (atom specifiers) + (setq specifiers (delq nil specifiers))) + + (if no-custom + (setq display-buffer-alist + (cons (cons identifiers specifiers) display-buffer-alist)) + (customize-set-variable + 'display-buffer-alist + (cons (cons identifiers specifiers) display-buffer-alist)))) + +(defun display-buffer-alist-set (&optional no-custom add) + "Set `display-buffer-alist' from Emacs 23 buffer display options. +Optional argument NO-CUSTOM nil means use `customize-set-variable' +to set the value of `display-buffer-alist'. NO-CUSTOM non-nil +means to use `setq' instead. + +Optional argument ADD nil means to replace the actual value of +`display-buffer-alist' with the value calculated here. ADD +non-nil means prepend the value calculated here to the current +value of `display-buffer-alist'." + (unless add + (if no-custom + (setq display-buffer-alist nil) + (customize-set-variable 'display-buffer-alist nil))) + + ;; Disable warnings, there are too many obsolete options here. + (with-no-warnings + ;; `pop-up-windows' + (display-buffer-alist-add + nil + (let ((fun (unless (eq split-window-preferred-function + 'split-window-sensibly) + ;; `split-window-sensibly' has been merged into the + ;; `display-buffer-split-window' code as `nil'. + split-window-preferred-function)) + (min-height + (if (numberp split-height-threshold) + (/ split-height-threshold 2) + ;; Undocumented hack. + 1.0)) + (min-width + (if (numberp split-width-threshold) + (/ split-width-threshold 2) + ;; Undocumented hack. + 1.0))) + (list + 'pop-up-window + (when pop-up-windows + (list + 'pop-up-window + (cons 'largest fun) + (cons 'lru fun))) + (cons 'pop-up-window-min-height min-height) + (cons 'pop-up-window-min-width min-width))) + no-custom) + + ;; `pop-up-frames' + (display-buffer-alist-add + nil + (list + 'pop-up-frame + (when pop-up-frames (list 'pop-up-frame pop-up-frames)) + (when pop-up-frame-function + (cons 'pop-up-frame-function pop-up-frame-function)) + (when pop-up-frame-alist + (cons 'pop-up-frame-alist pop-up-frame-alist))) + no-custom) + + ;; `special-display-buffer-names' + (dolist (entry special-display-buffer-names) + (cond + ((stringp entry) + ;; Plain string. + (display-buffer-alist-add + `((name . ,entry)) + (list + 'fun-with-args + (list 'fun-with-args special-display-function + special-display-frame-alist)) + no-custom)) + ((consp entry) + (let ((name (car entry)) + (rest (cdr entry))) + (cond + ((functionp (car rest)) + ;; A function. + (display-buffer-alist-add + `((name . ,name)) + (list + 'fun-with-args + ;; Weary. + (list 'fun-with-args (car rest) (cadr rest))) + no-custom)) + ((listp rest) + ;; A list of parameters. + (cond + ((assq 'same-window rest) + (display-buffer-alist-add + `((name . ,name)) + (list 'reuse-window + (list 'reuse-window 'same) + (list 'reuse-window-dedicated 'weak)) + no-custom)) + ((assq 'same-frame rest) + (display-buffer-alist-add + `((name . ,name)) (list 'same-frame) no-custom)) + (t + (display-buffer-alist-add + `((name . ,name)) + (list + 'fun-with-args + (list 'fun-with-args special-display-function + special-display-frame-alist)) + no-custom))))))))) + + ;; `special-display-regexps' + (dolist (entry special-display-regexps) + (cond + ((stringp entry) + ;; Plain string. + (display-buffer-alist-add + `((regexp . ,entry)) + (list + 'fun-with-args + (list 'fun-with-args special-display-function + special-display-frame-alist)) + no-custom)) + ((consp entry) + (let ((name (car entry)) + (rest (cdr entry))) + (cond + ((functionp (car rest)) + ;; A function. + (display-buffer-alist-add + `((name . ,name)) + (list + 'fun-with-args + ;; Weary. + (list 'fun-with-args (car rest) (cadr rest))) + no-custom)) + ((listp rest) + ;; A list of parameters. + (cond + ((assq 'same-window rest) + (display-buffer-alist-add + `((name . ,name)) + (list 'reuse-window + (list 'reuse-window 'same) + (list 'reuse-window-dedicated 'weak)) + no-custom)) + ((assq 'same-frame rest) + (display-buffer-alist-add + `((name . ,name)) (list 'same-frame) no-custom)) + (t + (display-buffer-alist-add + `((name . ,name)) + (list + 'fun-with-args + (list 'fun-with-args special-display-function + special-display-frame-alist)) + no-custom))))))))) + + ;; `same-window-regexps' + (dolist (entry same-window-regexps) + (cond + ((stringp entry) + (display-buffer-alist-add + `((regexp . ,entry)) + (list 'reuse-window (list 'reuse-window 'same)) + no-custom)) + ((consp entry) + (display-buffer-alist-add + `((regexp . ,(car entry))) + (list 'reuse-window (list 'reuse-window 'same)) + no-custom)))) + + ;; `same-window-buffer-names' + (dolist (entry same-window-buffer-names) + (cond + ((stringp entry) + (display-buffer-alist-add + `((name . ,entry)) + (list 'reuse-window (list 'reuse-window 'same)) + no-custom)) + ((consp entry) + (display-buffer-alist-add + `((name . ,(car entry))) + (list 'reuse-window (list 'reuse-window 'same)) + no-custom)))) + + ;; `reuse-window' + (display-buffer-alist-add + nil + (list + 'reuse-window + (list 'reuse-window nil 'same + ;; "0" (all visible and iconified frames) is hardcoded in + ;; Emacs 23. + (if (or display-buffer-reuse-frames pop-up-frames) 0 nil)) + (when even-window-heights + (cons 'reuse-window-even-sizes t))) + no-custom)) + + display-buffer-alist) (defun set-window-text-height (window height) "Set the height in lines of the text display area of WINDOW to HEIGHT. @@ -6349,62 +7028,60 @@ means suspend autoselection." If the mouse position has stabilized in a non-selected window, select that window. The minibuffer window is selected only if the minibuffer is active. This function is run by `mouse-autoselect-window-timer'." - (condition-case nil - (let* ((mouse-position (mouse-position)) - (window - (condition-case nil - (window-at (cadr mouse-position) (cddr mouse-position) - (car mouse-position)) - (error nil)))) - (cond - ((or (menu-or-popup-active-p) - (and window - (not (coordinates-in-window-p (cdr mouse-position) window)))) - ;; A menu / popup dialog is active or the mouse is on the scroll-bar - ;; of WINDOW, temporarily suspend delayed autoselection. - (mouse-autoselect-window-start mouse-position nil t)) - ((eq mouse-autoselect-window-state 'suspend) - ;; Delayed autoselection was temporarily suspended, reenable it. - (mouse-autoselect-window-start mouse-position)) - ((and window (not (eq window (selected-window))) - (or (not (numberp mouse-autoselect-window)) - (and (> mouse-autoselect-window 0) - ;; If `mouse-autoselect-window' is positive, select - ;; window if the window is the same as before. - (eq window mouse-autoselect-window-window)) - ;; Otherwise select window if the mouse is at the same - ;; position as before. Observe that the first test after - ;; starting autoselection usually fails since the value of - ;; `mouse-autoselect-window-position' recorded there is the - ;; position where the mouse has entered the new window and - ;; not necessarily where the mouse has stopped moving. - (equal mouse-position mouse-autoselect-window-position)) - ;; The minibuffer is a candidate window if it's active. - (or (not (window-minibuffer-p window)) - (eq window (active-minibuffer-window)))) - ;; Mouse position has stabilized in non-selected window: Cancel - ;; delayed autoselection and try to select that window. - (mouse-autoselect-window-cancel t) - ;; Select window where mouse appears unless the selected window is the - ;; minibuffer. Use `unread-command-events' in order to execute pre- - ;; and post-command hooks and trigger idle timers. To avoid delaying - ;; autoselection again, set `mouse-autoselect-window-state'." - (unless (window-minibuffer-p (selected-window)) - (setq mouse-autoselect-window-state 'select) - (setq unread-command-events - (cons (list 'select-window (list window)) - unread-command-events)))) - ((or (and window (eq window (selected-window))) - (not (numberp mouse-autoselect-window)) - (equal mouse-position mouse-autoselect-window-position)) - ;; Mouse position has either stabilized in the selected window or at - ;; `mouse-autoselect-window-position': Cancel delayed autoselection. - (mouse-autoselect-window-cancel t)) - (t - ;; Mouse position has not stabilized yet, resume delayed - ;; autoselection. - (mouse-autoselect-window-start mouse-position window)))) - (error nil))) + (ignore-errors + (let* ((mouse-position (mouse-position)) + (window + (ignore-errors + (window-at (cadr mouse-position) (cddr mouse-position) + (car mouse-position))))) + (cond + ((or (menu-or-popup-active-p) + (and window + (not (coordinates-in-window-p (cdr mouse-position) window)))) + ;; A menu / popup dialog is active or the mouse is on the scroll-bar + ;; of WINDOW, temporarily suspend delayed autoselection. + (mouse-autoselect-window-start mouse-position nil t)) + ((eq mouse-autoselect-window-state 'suspend) + ;; Delayed autoselection was temporarily suspended, reenable it. + (mouse-autoselect-window-start mouse-position)) + ((and window (not (eq window (selected-window))) + (or (not (numberp mouse-autoselect-window)) + (and (> mouse-autoselect-window 0) + ;; If `mouse-autoselect-window' is positive, select + ;; window if the window is the same as before. + (eq window mouse-autoselect-window-window)) + ;; Otherwise select window if the mouse is at the same + ;; position as before. Observe that the first test after + ;; starting autoselection usually fails since the value of + ;; `mouse-autoselect-window-position' recorded there is the + ;; position where the mouse has entered the new window and + ;; not necessarily where the mouse has stopped moving. + (equal mouse-position mouse-autoselect-window-position)) + ;; The minibuffer is a candidate window if it's active. + (or (not (window-minibuffer-p window)) + (eq window (active-minibuffer-window)))) + ;; Mouse position has stabilized in non-selected window: Cancel + ;; delayed autoselection and try to select that window. + (mouse-autoselect-window-cancel t) + ;; Select window where mouse appears unless the selected window is the + ;; minibuffer. Use `unread-command-events' in order to execute pre- + ;; and post-command hooks and trigger idle timers. To avoid delaying + ;; autoselection again, set `mouse-autoselect-window-state'." + (unless (window-minibuffer-p (selected-window)) + (setq mouse-autoselect-window-state 'select) + (setq unread-command-events + (cons (list 'select-window (list window)) + unread-command-events)))) + ((or (and window (eq window (selected-window))) + (not (numberp mouse-autoselect-window)) + (equal mouse-position mouse-autoselect-window-position)) + ;; Mouse position has either stabilized in the selected window or at + ;; `mouse-autoselect-window-position': Cancel delayed autoselection. + (mouse-autoselect-window-cancel t)) + (t + ;; Mouse position has not stabilized yet, resume delayed + ;; autoselection. + (mouse-autoselect-window-start mouse-position window)))))) (defun handle-select-window (event) "Handle select-window events." diff --git a/src/ChangeLog b/src/ChangeLog index 9f2f82f6c1a..3e75d997999 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,36 @@ +2011-02-22 Martin Rudalics + + * window.h (w): New slot clone_number. Rename + "inhibit_recombine" slot to "nested". + + * window.c (Fwindow_clone_number, Fwindow_nested) + (Fset_window_nested, Fset_window_clone_number): New functions. + (recombine_windows): Write "nested" isntead of + "inhibit_recombine". + (make_parent_window): Set clone_number. + (make_window): Set clone_number. Write "nested" instead of + "inhibit_recombine". + (Fsplit_window_internal): Write "nested" instead of + "inhibit_recombine". + (Fresize_window_apply, Fdelete_window_internal): Add parens in + EQ test. + (saved_window): Add clone_number and write "nested" instead of + "inhibit_recombine". + (Fset_window_configuration, save_window_save): Set clone_number + and write "nested" instead of "inhibit_recombine". + (syms_of_window): Add Swindow_clone_number, Swindow_nested, + Sset_window_nested and Sset_window_clone_number. + + * buffer.c (sort_overlays, overlay_strings): When an overlay has + the same clone-number property as the associated window don't + skip it even if the window properties are different. + (syms_of_buffer): Intern new Lisp_object Qclone_number. + +2011-01-16 Martin Rudalics + + * window.c (run_window_configuration_change_hook): Call + select_frame_norecord instead of Fselect_frame. + 2011-01-11 Tassilo Horn * image.c (imagemagick_load_image, Finit_image_library): Free diff --git a/src/buffer.c b/src/buffer.c index 28cad54f7ff..2b1a9441fc9 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -159,7 +159,7 @@ Lisp_Object Qget_file_buffer; Lisp_Object Qoverlayp; -Lisp_Object Qpriority, Qevaporate, Qbefore_string, Qafter_string; +Lisp_Object Qpriority, Qclone_number, Qevaporate, Qbefore_string, Qafter_string; Lisp_Object Qmodification_hooks; Lisp_Object Qinsert_in_front_hooks; @@ -2873,10 +2873,13 @@ sort_overlays (Lisp_Object *overlay_vec, int noverlays, struct window *w) overlays that are limited to some other window. */ if (w) { - Lisp_Object window; + Lisp_Object window, clone_number; window = Foverlay_get (overlay, Qwindow); - if (WINDOWP (window) && XWINDOW (window) != w) + clone_number = Foverlay_get (overlay, Qclone_number); + if (WINDOWP (window) && XWINDOW (window) != w + && (! NUMBERP (clone_number) + || XFASTINT (clone_number) != XFASTINT (w->clone_number))) continue; } @@ -3001,7 +3004,7 @@ record_overlay_string (struct sortstrlist *ssl, Lisp_Object str, Lisp_Object str EMACS_INT overlay_strings (EMACS_INT pos, struct window *w, unsigned char **pstr) { - Lisp_Object overlay, window, str; + Lisp_Object overlay, window, clone_number, str; struct Lisp_Overlay *ov; EMACS_INT startpos, endpos; int multibyte = ! NILP (current_buffer->enable_multibyte_characters); @@ -3020,8 +3023,12 @@ overlay_strings (EMACS_INT pos, struct window *w, unsigned char **pstr) if (endpos != pos && startpos != pos) continue; window = Foverlay_get (overlay, Qwindow); - if (WINDOWP (window) && XWINDOW (window) != w) + clone_number = Foverlay_get (overlay, Qclone_number); + if (WINDOWP (window) && XWINDOW (window) != w + && (! NUMBERP (clone_number) + || XFASTINT (clone_number) != XFASTINT (w->clone_number))) continue; + if (startpos == pos && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))) record_overlay_string (&overlay_heads, str, @@ -3048,8 +3055,12 @@ overlay_strings (EMACS_INT pos, struct window *w, unsigned char **pstr) if (endpos != pos && startpos != pos) continue; window = Foverlay_get (overlay, Qwindow); - if (WINDOWP (window) && XWINDOW (window) != w) + clone_number = Foverlay_get (overlay, Qclone_number); + if (WINDOWP (window) && XWINDOW (window) != w + && (! NUMBERP (clone_number) + || XFASTINT (clone_number) != XFASTINT (w->clone_number))) continue; + if (startpos == pos && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))) record_overlay_string (&overlay_heads, str, @@ -5206,6 +5217,8 @@ syms_of_buffer (void) staticpro (&Qget_file_buffer); Qpriority = intern_c_string ("priority"); staticpro (&Qpriority); + Qclone_number = intern_c_string ("clone-number"); + staticpro (&Qclone_number); Qbefore_string = intern_c_string ("before-string"); staticpro (&Qbefore_string); Qafter_string = intern_c_string ("after-string"); diff --git a/src/window.c b/src/window.c index 36fd4196e13..60e0b93157a 100644 --- a/src/window.c +++ b/src/window.c @@ -351,25 +351,18 @@ selected windows appears and to which many commands apply. */) int window_select_count; -/* Note that selected_window can be nil when this is called from - Fset_window_configuration. */ -DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0, - doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer. -Also make WINDOW's buffer current and make WINDOW the frame's selected -window. Return WINDOW. - -Optional second arg NORECORD non-nil means do not put this buffer at the -front of the buffer list and do not make this window the most recently -selected one. - -Note that the main editor command loop sets the current buffer to the -buffer of the selected window before each command. */) - (register Lisp_Object window, Lisp_Object norecord) +/* 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 + avoid that the display routine is called with selected_window set to + Qnil causing a subsequent crash. */ +static Lisp_Object +select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap) { register struct window *w; register struct window *ow; struct frame *sf; - int not_selected_before = !EQ (window, selected_window); + int not_selected_before = !EQ (window, selected_window) || inhibit_point_swap; CHECK_LIVE_WINDOW (window); @@ -394,11 +387,11 @@ buffer of the selected window before each command. */) else sf->selected_window = window; - /* Store the current buffer's actual point into the - old selected window. It belongs to that window, - and when the window is not selected, must be in the window. */ - if (!NILP (selected_window)) + if (!inhibit_point_swap) { + /* Store the current buffer's actual point into the old + selected window. It belongs to that window, and when the + window is not selected, must be in the window. */ ow = XWINDOW (selected_window); if (! NILP (ow->buffer)) set_marker_both (ow->pointm, ow->buffer, @@ -440,7 +433,34 @@ buffer of the selected window before each command. */) return window; } + + +/* Note that selected_window can be nil when this is called from + Fset_window_configuration. */ +DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0, + doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer. +Also make WINDOW's buffer current and make WINDOW the frame's selected +window. Return WINDOW. + +Optional second arg NORECORD non-nil means do not put this buffer at the +front of the buffer list and do not make this window the most recently +selected one. + +Note that the main editor command loop sets the current buffer to the +buffer of the selected window before each command. */) + (register Lisp_Object window, Lisp_Object norecord) +{ + return select_window (window, norecord, 0); +} +DEFUN ("window-clone-number", Fwindow_clone_number, Swindow_clone_number, 0, 1, 0, + doc: /* Return WINDOW's clone number. +WINDOW can be any window and defaults to the selected one. */) + (Lisp_Object window) +{ + return decode_any_window (window)->clone_number; +} + DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0, doc: /* Return the buffer that WINDOW is displaying. WINDOW can be any window and defaults to the selected one. @@ -495,6 +515,33 @@ Return nil if WINDOW has no left sibling. */) return decode_any_window (window)->prev; } +DEFUN ("window-nested", Fwindow_nested, Swindow_nested, 0, 1, 0, + doc: /* Return non-nil when WINDOW is nested. +WINDOW can be any window and defaults to the selected one. + +Subwindows of a nested are never \(re-)combined with the window's +siblings. */) + (Lisp_Object window) +{ + return decode_any_window (window)->nested; +} + +DEFUN ("set-window-nested", Fset_window_nested, Sset_window_nested, 2, 2, 0, + doc: /* Set nesting of WINDOW to STATUS. +WINDOW must be an internal window. Return STATUS. + +When a window is nested its subwindows are never recombined with the +window's siblings. */) + (Lisp_Object window, Lisp_Object status) +{ + register struct window *w = decode_any_window (window); + + if (! NILP (w->buffer)) + w->nested = status; + + return w->nested; +} + DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0, doc: /* Return WINDOW's use time. WINDOW defaults to the selected window. The window with the highest use @@ -1874,7 +1921,7 @@ recombine_windows (Lisp_Object window) w = XWINDOW (window); parent = w->parent; - if (NILP (w->inhibit_recombine) && !NILP (parent)) + if (NILP (w->nested) && !NILP (parent)) { p = XWINDOW (parent); if (((!NILP (p->vchild) && !NILP (w->vchild)) @@ -1935,7 +1982,6 @@ recombine_windows (Lisp_Object window) } } - /* If WINDOW can be deleted, delete it. */ Lisp_Object delete_deletable_window (Lisp_Object window) @@ -2361,9 +2407,9 @@ be listed first but no error is signalled. */) enum window_loop { WINDOW_LOOP_UNUSED, - GET_BUFFER_WINDOW, /* Arg is buffer */ + GET_BUFFER_WINDOW, /* Arg is buffer */ REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */ - REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */ + REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */ CHECK_ALL_WINDOWS }; @@ -2897,7 +2943,7 @@ run_window_configuration_change_hook (struct frame *f) if (SELECTED_FRAME () != f) { record_unwind_protect (select_frame_norecord, Fselected_frame ()); - Fselect_frame (frame, Qt); + select_frame_norecord (frame); } /* Use the right buffer. Matters when running the local hooks. */ @@ -3044,6 +3090,18 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int unbind_to (count, Qnil); } +DEFUN ("set-window-clone-number", Fset_window_clone_number, Sset_window_clone_number, 2, 2, 0, + doc: /* Set WINDOW's clone number to CLONE-NUMBER. +WINDOW can be any window and defaults to the selected one. */) + (Lisp_Object window, Lisp_Object clone_number) +{ + register struct window *w = decode_any_window (window); + + CHECK_NUMBER (clone_number); + w->clone_number = clone_number; + return w->clone_number; +} + DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0, doc: /* Make WINDOW display BUFFER-OR-NAME as its contents. WINDOW has to be a live window and defaults to the selected one. @@ -3231,6 +3289,7 @@ make_parent_window (Lisp_Object window, int horflag) ++sequence_number; XSETFASTINT (p->sequence_number, sequence_number); + XSETFASTINT (p->clone_number, sequence_number); replace_window (window, parent, 1); @@ -3274,6 +3333,7 @@ make_window (void) XSETFASTINT (w->use_time, 0); ++sequence_number; XSETFASTINT (w->sequence_number, sequence_number); + XSETFASTINT (w->clone_number, sequence_number); w->temslot = w->last_modified = w->last_overlay_modified = Qnil; XSETFASTINT (w->last_point, 0); w->last_had_star = w->vertical_scroll_bar = Qnil; @@ -3289,7 +3349,7 @@ make_window (void) w->start_at_line_beg = w->display_table = w->dedicated = Qnil; w->base_line_number = w->base_line_pos = w->region_showing = Qnil; w->column_number_displayed = w->redisplay_end_trigger = Qnil; - w->inhibit_recombine = w->window_parameters = Qnil; + w->nested = w->window_parameters = Qnil; w->prev_buffers = w->next_buffers = Qnil; /* Initialize non-Lisp data. */ w->desired_matrix = w->current_matrix = 0; @@ -3541,7 +3601,7 @@ be applied on the Elisp level. */) r = XWINDOW (FRAME_ROOT_WINDOW (f)); if (!resize_window_check (r, horflag) - || ! EQ (r->new_total, horflag ? r->total_cols : r->total_lines)) + || ! EQ (r->new_total, (horflag ? r->total_cols : r->total_lines))) return Qnil; BLOCK_INPUT; @@ -3752,7 +3812,7 @@ divder column. */) p = XWINDOW (o->parent); if (EQ (Vwindow_splits, Qnest)) /* Make sure that parent is not recombined. */ - p->inhibit_recombine = Qt; + p->nested = Qt; /* These get applied below. */ p->new_total = horflag ? o->total_cols : o->total_lines; p->new_normal = new_normal; @@ -3911,7 +3971,7 @@ when WINDOW is the only window on its frame. */) } if (resize_window_check (r, horflag) - && EQ (r->new_total, horflag ? r->total_cols : r->total_lines)) + && EQ (r->new_total, (horflag ? r->total_cols : r->total_lines))) /* We can delete WINDOW now. */ { /* Block input. */ @@ -5184,7 +5244,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. @@ -5308,7 +5367,7 @@ struct saved_window EMACS_UINT size; struct Lisp_Vector *next_from_Lisp_Vector_struct; - Lisp_Object window; + Lisp_Object window, clone_number; Lisp_Object buffer, start, pointm, mark; Lisp_Object left_col, top_line, total_cols, total_lines; Lisp_Object normal_cols, normal_lines; @@ -5319,7 +5378,7 @@ struct saved_window Lisp_Object left_margin_cols, right_margin_cols; Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins; Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated; - Lisp_Object inhibit_recombine; + Lisp_Object nested; Lisp_Object window_parameters; }; @@ -5528,6 +5587,7 @@ the return value is nil. Otherwise the value is t. */) } } + w->clone_number = p->clone_number; /* If we squirreled away the buffer in the window's height, restore it now. */ if (BUFFERP (w->total_lines)) @@ -5549,7 +5609,7 @@ the return value is nil. Otherwise the value is t. */) w->scroll_bar_width = p->scroll_bar_width; w->vertical_scroll_bar_type = p->vertical_scroll_bar_type; w->dedicated = p->dedicated; - w->inhibit_recombine = p->inhibit_recombine; + w->nested = p->nested; w->window_parameters = p->window_parameters; XSETFASTINT (w->last_modified, 0); XSETFASTINT (w->last_overlay_modified, 0); @@ -5585,7 +5645,7 @@ the return value is nil. Otherwise the value is t. */) set_marker_restricted (w->pointm, make_number (0), w->buffer); w->start_at_line_beg = Qt; if (!NILP (w->dedicated)) - /* Record this window as window as dead. */ + /* Record this window as dead. */ dead_windows = Fcons (window, dead_windows); /* Make sure window is no more dedicated. */ w->dedicated = Qnil; @@ -5607,11 +5667,6 @@ the return value is nil. Otherwise the value is t. */) } FRAME_ROOT_WINDOW (f) = data->root_window; - /* Prevent "swapping out point" in the old selected window - using the buffer that has been restored into it. - We already swapped out point that from that window's old buffer. */ - selected_window = Qnil; - /* Arrange *not* to restore point in the buffer that was current when the window configuration was saved. */ if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)) @@ -5619,7 +5674,11 @@ the return value is nil. Otherwise the value is t. */) make_number (old_point), XWINDOW (data->current_window)->buffer); - Fselect_window (data->current_window, Qnil); + /* In the following call to `select-window, prevent "swapping out + point" in the old selected window using the buffer that has + been restored into it. We already swapped out that point from + that window's old buffer. */ + select_window (data->current_window, Qnil, 1); XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window = selected_window; @@ -5803,6 +5862,7 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) XSETFASTINT (w->temslot, i); i++; p->window = window; + p->clone_number = w->clone_number; p->buffer = w->buffer; p->left_col = w->left_col; p->top_line = w->top_line; @@ -5821,7 +5881,7 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) p->scroll_bar_width = w->scroll_bar_width; p->vertical_scroll_bar_type = w->vertical_scroll_bar_type; p->dedicated = w->dedicated; - p->inhibit_recombine = w->inhibit_recombine; + p->nested = w->nested; p->window_parameters = w->window_parameters; if (!NILP (w->buffer)) { @@ -6305,8 +6365,7 @@ freeze_window_starts (struct frame *f, int freeze_p) and the like. This ignores a couple of things like the dedicatedness status of - window, inhibit_recombine and the like. This might have to be - fixed. */ + window, nested and the like. This might have to be fixed. */ int compare_window_configurations (Lisp_Object configuration1, Lisp_Object configuration2, int ignore_positions) @@ -6601,12 +6660,15 @@ small or of fixed size. */); defsubr (&Sset_frame_selected_window); defsubr (&Spos_visible_in_window_p); defsubr (&Swindow_line_height); + defsubr (&Swindow_clone_number); defsubr (&Swindow_buffer); defsubr (&Swindow_parent); defsubr (&Swindow_vchild); defsubr (&Swindow_hchild); defsubr (&Swindow_next); defsubr (&Swindow_prev); + defsubr (&Swindow_nested); + defsubr (&Sset_window_nested); defsubr (&Swindow_use_time); defsubr (&Swindow_top_line); defsubr (&Swindow_left_column); @@ -6646,6 +6708,7 @@ small or of fixed size. */); defsubr (&Sdelete_window_internal); defsubr (&Sresize_mini_window_internal); defsubr (&Sset_window_buffer); + defsubr (&Sset_window_clone_number); defsubr (&Srun_window_configuration_change_hook); defsubr (&Sselect_window); defsubr (&Sforce_window_update); diff --git a/src/window.h b/src/window.h index 1172d856b01..814dfe8c7d0 100644 --- a/src/window.h +++ b/src/window.h @@ -110,7 +110,7 @@ struct window unless the window is dead. */ Lisp_Object hchild, vchild; - /* The window this one is a child of. */ + /* The window this one is a child of. */ Lisp_Object parent; /* The upper left corner coordinates of this window, as integers @@ -162,20 +162,26 @@ struct window the user has set, by set-window-hscroll for example. */ Lisp_Object min_hscroll; - /* Number saying how recently window was selected */ + /* Number saying how recently window was selected. */ Lisp_Object use_time; - /* Unique number of window assigned when it was created */ + /* Unique number of window assigned when it was created. */ Lisp_Object sequence_number; - /* No permanent meaning; used by save-window-excursion's bookkeeping */ + /* Sequence number of window this window was cloned from. Identic + to sequence number if window was not cloned. */ + Lisp_Object clone_number; + + /* No permanent meaning; used by save-window-excursion's + bookkeeping. */ Lisp_Object temslot; - /* text.modified of displayed buffer as of last time display completed */ + /* text.modified of displayed buffer as of last time display + completed. */ Lisp_Object last_modified; /* BUF_OVERLAY_MODIFIED of displayed buffer as of last complete update. */ Lisp_Object last_overlay_modified; - /* Value of point at that time */ + /* Value of point at that time. */ Lisp_Object last_point; /* Non-nil if the buffer was "modified" when the window was last updated. */ @@ -259,8 +265,8 @@ struct window must run the redisplay-end-trigger-hook. */ Lisp_Object redisplay_end_trigger; - /* Non-nil means window must not be recombined. */ - Lisp_Object inhibit_recombine; + /* Non-nil means this window's subwindows are never recombined. */ + Lisp_Object nested; /* Alist of triples listing buffers previously shown in this window. */