;;; 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
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."
(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.
(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."