]> code.delx.au - gnu-emacs/blobdiff - lisp/window.el
(menu-bar-tools-menu): Call read-mail-command
[gnu-emacs] / lisp / window.el
index c18dcc41accd7352c2d2664a708ada785366f9cc..6f7e730bad4d20011ad13f6d6e51b44512b9a3e8 100644 (file)
@@ -1,6 +1,7 @@
 ;;; window.el --- GNU Emacs window commands aside from those written in C.
 
-;; Copyright (C) 1985, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1989, 1992, 1993, 1994, 2000
+;;  Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 
@@ -62,17 +63,21 @@ 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.
+If ALL-FRAMES is a frame, it means include windows on that frame.
 Anything else means restrict to the selected 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))))))
+  (save-selected-window
+    (if (framep all-frames)
+       (select-window (frame-first-window all-frames)))
+    (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."
@@ -237,6 +242,59 @@ to the window's right, if any.  No arg means split equally."
   (interactive "p")
   (shrink-window arg t))
 
+(defun window-buffer-height (window)
+  "Return the height (in screen lines) of the buffer that WINDOW is displaying."
+  (save-excursion
+    (set-buffer (window-buffer window))
+    (goto-char (point-min))
+    (let ((ignore-final-newline
+           ;; If buffer ends with a newline, ignore it when counting height
+           ;; unless point is after it.
+           (and (not (eobp)) (eq ?\n (char-after (1- (point-max)))))))
+      (+ 1 (nth 2 (compute-motion (point-min)
+                                  '(0 . 0)
+                                  (- (point-max) (if ignore-final-newline 1 0))
+                                  (cons 0 100000000)
+                                  (window-width window)
+                                  nil
+                                  window))))))
+
+(defun count-screen-lines (&optional beg end count-final-newline window)
+  "Return the number of screen lines in the region.
+The number of screen lines may be different from the number of actual lines,
+due to line breaking, display table, etc.
+
+Optional arguments BEG and END default to `point-min' and `point-max'
+respectively.
+
+If region ends with a newline, ignore it unless optinal third argument
+COUNT-FINAL-NEWLINE is non-nil.
+
+The optional fourth argument WINDOW specifies the window used for obtaining
+parameters such as width, horizontal scrolling, and so on. The default is
+to use the selected window's parameters.
+
+Like `vertical-motion', `count-screen-lines' always uses the current buffer,
+regardless of which buffer is displayed in WINDOW. This makes possible to use
+`count-screen-lines' in any buffer, whether or not it is currently displayed
+in some window."
+  (unless beg
+    (setq beg (point-min)))
+  (unless end
+    (setq end (point-max)))
+  (if (= beg end)
+      0
+    (save-excursion
+      (save-restriction
+        (widen)
+        (narrow-to-region (min beg end)
+                          (if (and (not count-final-newline)
+                                   (= ?\n (char-before (max beg end))))
+                              (1- (max beg end))
+                            (max beg end)))
+        (goto-char (point-min))
+        (1+ (vertical-motion (buffer-size) window))))))
+
 (defun shrink-window-if-larger-than-buffer (&optional window)
   "Shrink the WINDOW to be as small as possible to display its contents.
 Do not shrink to less than `window-min-height' lines.
@@ -249,41 +307,28 @@ or if the window is the only window of its frame."
     (if window
        (select-window window)
       (setq window (selected-window)))
-    (save-excursion
-      (set-buffer (window-buffer window))
-      (goto-char (point-min))
-      (let* ((ignore-final-newline
-             ;; If buffer ends with a newline, ignore it when counting height
-             ;; unless point is after it.
-             (and (not (eobp))
-                  (eq ?\n (char-after (1- (point-max))))))
-            (params (frame-parameters))
-            (mini (cdr (assq 'minibuffer params)))
-            (edges (window-edges))
-            text-height)
-       (if (and (< 1 (count-windows))
-                (= (window-width) (frame-width))
-                (pos-visible-in-window-p (point-min) window)
-                (not (eq mini 'only))
-                (or (not mini)
-                    (< (nth 3 edges)
-                       (nth 1 (window-edges mini)))
-                    (> (nth 1 edges)
-                       (cdr (assq 'menu-bar-lines params)))))
-           (let (result height)
-             (setq result
-                   (compute-motion (point-min) '(0 . 0)
-                                   (- (point-max)
-                                      (if ignore-final-newline 1 0))
-                                   (cons 0 (window-height))
-                                   (window-width) nil
-                                   window))
-             ;; Get number of screen lines that the text needs.
-             (setq text-height (+ 1 (nth 2 result)))
-             ;; Shrink down to that, or as far as we can go.
-             (if (> (window-height) (1+ text-height))
-                 (shrink-window (- (window-height)
-                                   (max (1+ text-height) window-min-height))))))))))
+    (let* ((params (frame-parameters))
+           (mini (cdr (assq 'minibuffer params)))
+           (edges (window-edges)))
+      (if (and (< 1 (count-windows))
+               (= (window-width) (frame-width))
+               (pos-visible-in-window-p (point-min) window)
+               (not (eq mini 'only))
+               (or (not mini)
+                   (< (nth 3 edges) (nth 1 (window-edges mini)))
+                   (> (nth 1 edges) (cdr (assq 'menu-bar-lines params)))))
+          ;; `count-screen-lines' always works on the current buffer, so
+          ;; make sure it is the buffer displayed by WINDOW.
+          (let ((text-height (with-current-buffer (window-buffer window)
+                               (count-screen-lines)))
+                (window-height (window-height)))
+           ;; Don't try to redisplay with the cursor at the end
+           ;; on its own line--that would force a scroll and spoil things.
+           (when (and (eobp) (bolp) (not (bobp)))
+             (forward-char -1))
+            (when (> window-height (1+ text-height))
+              (shrink-window
+               (- window-height (max (1+ text-height) window-min-height)))))))))
 
 (defun kill-buffer-and-window ()
   "Kill the current buffer and delete the selected window."