]> code.delx.au - gnu-emacs/blobdiff - lisp/window.el
(write-contents-hooks): Call make-variable-buffer-local.
[gnu-emacs] / lisp / window.el
index eafded0572be68f2fdf4d3061b1f125e852879c9..27c42efc5baab58c43474983d33a74a44698c64e 100644 (file)
 
 ;;; 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
@@ -35,7 +98,10 @@ even if it is active."
 (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
@@ -53,7 +119,7 @@ even if it is active."
          (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)
@@ -65,14 +131,15 @@ even if it is active."
                                       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.
@@ -100,7 +167,8 @@ new mode line."
   (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
@@ -108,18 +176,23 @@ new mode line."
          (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)
@@ -132,7 +205,7 @@ No arg means split equally."
     (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")