;;; Code:
+;;;; Window tree functions.
+
+(defun one-window-p (&optional nomini all-frames)
+ "Returns non-nil if the selected window is the only window (in its frame).
+Optional arg NOMINI non-nil means don't count the minibuffer
+even if it is active.
+
+The optional arg ALL-FRAMES t means count windows on all frames.
+If it is `visible', count windows on all visible frames.
+ALL-FRAMES nil or omitted means count only the selected frame,
+plus the minibuffer it uses (which may be on another frame).
+If ALL-FRAMES is neither nil nor t, count only the selected frame."
+ (let ((base-window (selected-window)))
+ (if (and nomini (eq base-window (minibuffer-window)))
+ (setq base-window (next-window base-window)))
+ (eq base-window
+ (next-window base-window (if nomini 'arg) all-frames))))
+
+(defun walk-windows (proc &optional minibuf all-frames)
+ "Cycle through all visible windows, calling PROC for each one.
+PROC is called with a window as argument.
+
+Optional second arg MINIBUF t means count the minibuffer window even
+if not active. MINIBUF nil or omitted means count the minibuffer iff
+it is active. MINIBUF neither t nor nil means not to count the
+minibuffer even if it is active.
+
+Several frames may share a single minibuffer; if the minibuffer
+counts, all windows on all frames that share that minibuffer count
+too. Therefore, when a separate minibuffer frame is active,
+`walk-windows' includes the windows in the frame from which you
+entered the minibuffer, as well as the minibuffer window. But if the
+minibuffer does not count, only windows from WINDOW's frame count.
+
+ALL-FRAMES is the optional third argument.
+ALL-FRAMES nil or omitted means cycle within the frames as specified above.
+ALL-FRAMES = `visible' means include windows on all visible frames.
+ALL-FRAMES = 0 means include windows on all visible and iconified frames.
+ALL-FRAMES = t means include windows on all frames including invisible frames.
+Anything else means restrict to WINDOW's frame."
+ ;; If we start from the minibuffer window, don't fail to come back to it.
+ (if (window-minibuffer-p (selected-window))
+ (setq minibuf t))
+ (let* ((walk-windows-start (selected-window))
+ (walk-windows-current walk-windows-start))
+ (while (progn
+ (setq walk-windows-current
+ (next-window walk-windows-current minibuf all-frames))
+ (funcall proc walk-windows-current)
+ (not (eq walk-windows-current walk-windows-start))))))
+
+(defun minibuffer-window-active-p (window)
+ "Return t if WINDOW (a minibuffer window) is now active."
+ (eq window (active-minibuffer-window)))
+
+(defmacro save-selected-window (&rest body)
+ "Execute BODY, then select the window that was selected before BODY."
+ (list 'let
+ '((save-selected-window-window (selected-window)))
+ (list 'unwind-protect
+ (cons 'progn body)
+ (list 'select-window 'save-selected-window-window))))
+\f
(defun count-windows (&optional minibuf)
"Returns the number of visible windows.
Optional arg NO-MINI non-nil means don't count the minibuffer
(defun balance-windows ()
"Makes all visible windows the same height (approximately)."
(interactive)
- (let ((count -1) levels newsizes size)
+ (let ((count -1) levels newsizes size
+ ;; Don't count the lines that are above the uppermost windows.
+ ;; (These are the menu bar lines, if any.)
+ (mbl (nth 1 (window-edges (frame-first-window (selected-frame))))))
;; Find all the different vpos's at which windows start,
;; then count them. But ignore levels that differ by only 1.
(save-window-excursion
(setq tops (cdr tops)))
(setq count (1+ count))))
;; Subdivide the frame into that many vertical levels.
- (setq size (/ (frame-height) count))
+ (setq size (/ (- (frame-height) mbl) count))
(walk-windows (function
(lambda (w)
(select-window w)
count)))
(setq newsizes
(cons (cons w (* size (- newbot newtop)))
- newsizes))))))
+ newsizes)))))
+ 'nomini)
(walk-windows (function (lambda (w)
(select-window w)
(let ((newsize (cdr (assq w newsizes))))
(enlarge-window (- newsize
(window-height))))))
'nomini)))
-
+\f
;;; I think this should be the default; I think people will prefer it--rms.
(defvar split-window-keep-point t
"*If non-nil, split windows keeps the original point in both children.
(let ((old-w (selected-window))
(old-point (point))
(size (and arg (prefix-numeric-value arg)))
- new-w bottom switch)
+ (window-full-p nil)
+ new-w bottom switch moved)
(and size (< size 0) (setq size (+ (window-height) size)))
(setq new-w (split-window nil size))
(or split-window-keep-point
(save-excursion
(set-buffer (window-buffer))
(goto-char (window-start))
- (vertical-motion (window-height))
+ (setq moved (vertical-motion (window-height)))
(set-window-start new-w (point))
(if (> (point) (window-point new-w))
(set-window-point new-w (point)))
- (vertical-motion -1)
- (setq bottom (point)))
- (if (<= bottom (point))
- (set-window-point old-w (1- bottom)))
- (if (< (window-start new-w) old-point)
- (progn
- (set-window-point new-w old-point)
- (select-window new-w)))))
+ (and (= moved (window-height))
+ (progn
+ (setq window-full-p t)
+ (vertical-motion -1)))
+ (setq bottom (point)))
+ (and window-full-p
+ (<= bottom (point))
+ (set-window-point old-w (1- bottom)))
+ (and window-full-p
+ (<= (window-start new-w) old-point)
+ (progn
+ (set-window-point new-w old-point)
+ (select-window new-w)))))
new-w))
(defun split-window-horizontally (&optional arg)
(and size (< size 0)
(setq size (+ (window-width) size)))
(split-window nil size t)))
-
+\f
(defun enlarge-window-horizontally (arg)
"Make current window ARG columns wider."
(interactive "p")