Doc fixes.
[bpt/emacs.git] / lisp / window.el
CommitLineData
12169754 1;;; window.el --- GNU Emacs window commands aside from those written in C.
d46bac56 2
5ed8d62f 3;;; Copyright (C) 1985, 1989, 1992, 1993 Free Software Foundation, Inc.
a2535589 4
58142744
ER
5;; Maintainer: FSF
6
a2535589
JA
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
492878e4 11;; the Free Software Foundation; either version 2, or (at your option)
a2535589
JA
12;; any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs; see the file COPYING. If not, write to
21;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22
d46bac56 23;;; Code:
a2535589
JA
24
25(defun count-windows (&optional minibuf)
26 "Returns the number of visible windows.
27Optional arg NO-MINI non-nil means don't count the minibuffer
28even if it is active."
29 (let ((count 0))
12169754 30 (walk-windows (function (lambda (w)
a2535589
JA
31 (setq count (+ count 1))))
32 minibuf)
33 count))
34
35(defun balance-windows ()
7162c5c4 36 "Makes all visible windows the same height (approximately)."
a2535589 37 (interactive)
7162c5c4
RS
38 (let ((count -1) levels newsizes size)
39 ;; Find all the different vpos's at which windows start,
40 ;; then count them. But ignore levels that differ by only 1.
41 (save-window-excursion
42 (let (tops (prev-top -2))
43 (walk-windows (function (lambda (w)
44 (setq tops (cons (nth 1 (window-edges w))
45 tops))))
46 'nomini)
47 (setq tops (sort tops '<))
48 (while tops
49 (if (> (car tops) (1+ prev-top))
50 (setq prev-top (car tops)
51 count (1+ count)))
52 (setq levels (cons (cons (car tops) count) levels))
53 (setq tops (cdr tops)))
54 (setq count (1+ count))))
55 ;; Subdivide the frame into that many vertical levels.
56 (setq size (/ (frame-height) count))
57 (walk-windows (function
58 (lambda (w)
59 (select-window w)
60 (let ((newtop (cdr (assq (nth 1 (window-edges))
61 levels)))
62 (newbot (or (cdr (assq (+ (window-height)
63 (nth 1 (window-edges)))
64 levels))
65 count)))
66 (setq newsizes
67 (cons (cons w (* size (- newbot newtop)))
68 newsizes))))))
a2535589 69 (walk-windows (function (lambda (w)
7162c5c4
RS
70 (select-window w)
71 (let ((newsize (cdr (assq w newsizes))))
72 (enlarge-window (- newsize
73 (window-height))))))
74 'nomini)))
a2535589 75
69037c38 76;;; I think this should be the default; I think people will prefer it--rms.
69037c38 77(defvar split-window-keep-point t
7162c5c4
RS
78 "*If non-nil, split windows keeps the original point in both children.
79This is often more convenient for editing.
80If nil, adjust point in each of the two windows to minimize redisplay.
81This is convenient on slow terminals, but point can move strangely.")
8e4b71d8 82
a2535589
JA
83(defun split-window-vertically (&optional arg)
84 "Split current window into two windows, one above the other.
c65c1681 85The uppermost window gets ARG lines and the other gets the rest.
ab94bf9f 86Negative arg means select the size of the lowermost window instead.
c65c1681
RS
87With no argument, split equally or close to it.
88Both windows display the same buffer now current.
c65c1681 89
8e4b71d8
JB
90If the variable split-window-keep-point is non-nil, both new windows
91will get the same value of point as the current window. This is often
92more convenient for editing.
93
94Otherwise, we chose window starts so as to minimize the amount of
95redisplay; this is convenient on slow terminals. The new selected
96window is the one that the current value of point appears in. The
97value of point can change if the text around point is hidden by the
98new mode line."
a2535589
JA
99 (interactive "P")
100 (let ((old-w (selected-window))
c65c1681 101 (old-point (point))
ab94bf9f 102 (size (and arg (prefix-numeric-value arg)))
c65c1681 103 new-w bottom switch)
ab94bf9f
KH
104 (and size (< size 0) (setq size (+ (window-height) size)))
105 (setq new-w (split-window nil size))
7d7f1f33 106 (or split-window-keep-point
c65c1681 107 (progn
8e4b71d8
JB
108 (save-excursion
109 (set-buffer (window-buffer))
110 (goto-char (window-start))
111 (vertical-motion (window-height))
112 (set-window-start new-w (point))
113 (if (> (point) (window-point new-w))
114 (set-window-point new-w (point)))
115 (vertical-motion -1)
116 (setq bottom (point)))
117 (if (<= bottom (point))
118 (set-window-point old-w (1- bottom)))
119 (if (< (window-start new-w) old-point)
120 (progn
121 (set-window-point new-w old-point)
2ed3f64c
RS
122 (select-window new-w)))))
123 new-w))
a2535589
JA
124
125(defun split-window-horizontally (&optional arg)
126 "Split current window into two windows side by side.
127This window becomes the leftmost of the two, and gets
128ARG columns. No arg means split equally."
129 (interactive "P")
130 (split-window nil (and arg (prefix-numeric-value arg)) t))
131
132(defun enlarge-window-horizontally (arg)
133 "Make current window ARG columns wider."
134 (interactive "p")
135 (enlarge-window arg t))
136
137(defun shrink-window-horizontally (arg)
138 "Make current window ARG columns narrower."
139 (interactive "p")
140 (shrink-window arg t))
141
a0900d9f 142(defun shrink-window-if-larger-than-buffer (&optional window)
d0bee390
RS
143 "Shrink the WINDOW to be as small as possible to display its contents.
144Do nothing if the buffer contains more lines than the present window height,
3eb217a0
RS
145or if some of the window's contents are scrolled out of view,
146or if the window is the only window of its frame."
d0bee390 147 (interactive)
a0900d9f
ER
148 (save-excursion
149 (set-buffer (window-buffer window))
150 (let ((w (selected-window)) ;save-window-excursion can't win
151 (buffer-file-name buffer-file-name)
152 (p (point))
153 (n 0)
3eb217a0
RS
154 (ignore-final-newline
155 ;; If buffer ends with a newline, ignore it when counting height
156 ;; unless point is after it.
157 (and (not (eobp))
158 (eq ?\n (char-after (1- (point-max))))))
a0900d9f
ER
159 (window-min-height 0)
160 (buffer-read-only nil)
161 (modified (buffer-modified-p))
5e2ec73e
KH
162 (buffer (current-buffer))
163 (mini (cdr (assq 'minibuffer (frame-parameters))))
164 (edges (window-edges (selected-window))))
3eb217a0 165 (if (and (< 1 (count-windows))
5e2ec73e
KH
166 (pos-visible-in-window-p (point-min) window)
167 (or (not mini)
168 (< (nth 3 edges)
169 (nth 1 (window-edges mini)))
170 (> (nth 1 edges)
171 (cdr (assq 'menu-bar-lines (frame-parameters))))))
d0bee390
RS
172 (unwind-protect
173 (progn
174 (select-window (or window w))
175 (goto-char (point-min))
3eb217a0
RS
176 (while (pos-visible-in-window-p
177 (- (point-max)
178 (if ignore-final-newline 1 0)))
d0bee390
RS
179 ;; defeat file locking... don't try this at home, kids!
180 (setq buffer-file-name nil)
181 (insert ?\n) (setq n (1+ n)))
182 (if (> n 0) (shrink-window (1- n))))
183 (delete-region (point-min) (point))
184 (set-buffer-modified-p modified)
185 (goto-char p)
186 (select-window w)
187 ;; Make sure we unbind buffer-read-only
188 ;; with the proper current buffer.
189 (set-buffer buffer))))))
a0900d9f 190
a2535589 191(define-key ctl-x-map "2" 'split-window-vertically)
492878e4 192(define-key ctl-x-map "3" 'split-window-horizontally)
a2535589
JA
193(define-key ctl-x-map "}" 'enlarge-window-horizontally)
194(define-key ctl-x-map "{" 'shrink-window-horizontally)
a0900d9f
ER
195(define-key ctl-x-map "-" 'shrink-window-if-larger-than-buffer)
196(define-key ctl-x-map "+" 'balance-windows)
76d7458e
ER
197
198;;; windows.el ends here