162 |
(defun balance-windows () |
(defun balance-windows () |
163 |
"Make all visible windows the same height (approximately)." |
"Make all visible windows the same height (approximately)." |
164 |
(interactive) |
(interactive) |
165 |
(let ((count -1) levels newsizes size |
(let ((count -1) levels newsizes level-size |
166 |
;; Don't count the lines that are above the uppermost windows. |
;; Don't count the lines that are above the uppermost windows. |
167 |
;; (These are the menu bar lines, if any.) |
;; (These are the menu bar lines, if any.) |
168 |
(mbl (nth 1 (window-edges (frame-first-window (selected-frame)))))) |
(mbl (nth 1 (window-edges (frame-first-window (selected-frame))))) |
169 |
|
(last-window (previous-window (frame-first-window (selected-frame)))) |
170 |
|
;; Don't count the lines that are past the lowest main window. |
171 |
|
total) |
172 |
|
;; Bottom edge of last window determines what size we have to work with. |
173 |
|
(setq total |
174 |
|
(+ (window-height last-window) |
175 |
|
(nth 1 (window-edges last-window)))) |
176 |
|
|
177 |
;; Find all the different vpos's at which windows start, |
;; Find all the different vpos's at which windows start, |
178 |
;; then count them. But ignore levels that differ by only 1. |
;; then count them. But ignore levels that differ by only 1. |
179 |
(save-window-excursion |
(let (tops (prev-top -2)) |
180 |
(let (tops (prev-top -2)) |
(walk-windows (function (lambda (w) |
181 |
(walk-windows (function (lambda (w) |
(setq tops (cons (nth 1 (window-edges w)) |
182 |
(setq tops (cons (nth 1 (window-edges w)) |
tops)))) |
183 |
tops)))) |
'nomini) |
184 |
'nomini) |
(setq tops (sort tops '<)) |
185 |
(setq tops (sort tops '<)) |
(while tops |
186 |
(while tops |
(if (> (car tops) (1+ prev-top)) |
187 |
(if (> (car tops) (1+ prev-top)) |
(setq prev-top (car tops) |
188 |
(setq prev-top (car tops) |
count (1+ count))) |
189 |
count (1+ count))) |
(setq levels (cons (cons (car tops) count) levels)) |
190 |
(setq levels (cons (cons (car tops) count) levels)) |
(setq tops (cdr tops))) |
191 |
(setq tops (cdr tops))) |
(setq count (1+ count))) |
192 |
(setq count (1+ count)))) |
;; Subdivide the frame into desired number of vertical levels. |
193 |
;; Subdivide the frame into that many vertical levels. |
(setq level-size (/ (- total mbl) count)) |
194 |
(setq size (/ (- (frame-height) mbl) count)) |
(save-selected-window |
195 |
(walk-windows (function |
;; Set up NEWSIZES to map windows to their desired sizes. |
196 |
(lambda (w) |
;; If a window ends at the bottom level, don't include |
197 |
(select-window w) |
;; it in NEWSIZES. Those windows get the right sizes |
198 |
(let ((newtop (cdr (assq (nth 1 (window-edges)) |
;; by adjusting the ones above them. |
199 |
levels))) |
(walk-windows (function |
200 |
(newbot (or (cdr (assq (+ (window-height) |
(lambda (w) |
201 |
(nth 1 (window-edges))) |
(let ((newtop (cdr (assq (nth 1 (window-edges w)) |
202 |
levels)) |
levels))) |
203 |
count))) |
(newbot (cdr (assq (+ (window-height w) |
204 |
(setq newsizes |
(nth 1 (window-edges w))) |
205 |
(cons (cons w (* size (- newbot newtop))) |
levels)))) |
206 |
newsizes))))) |
(if newbot |
207 |
'nomini) |
(setq newsizes |
208 |
(walk-windows (function (lambda (w) |
(cons (cons w (* level-size (- newbot newtop))) |
209 |
(select-window w) |
newsizes))))))) |
210 |
(let ((newsize (cdr (assq w newsizes)))) |
'nomini) |
211 |
(enlarge-window (- newsize |
;; Make walk-windows start with the topmost window. |
212 |
(window-height)))))) |
(select-window (previous-window (frame-first-window (selected-frame)))) |
213 |
'nomini))) |
(let (done (count 0)) |
214 |
|
;; Give each window its precomputed size, or at least try. |
215 |
|
;; Keep trying until they all get the intended sizes, |
216 |
|
;; but not more than 3 times (to prevent infinite loop). |
217 |
|
(while (and (not done) (< count 3)) |
218 |
|
(setq done t) |
219 |
|
(setq count (1+ count)) |
220 |
|
(walk-windows (function (lambda (w) |
221 |
|
(select-window w) |
222 |
|
(let ((newsize (cdr (assq w newsizes)))) |
223 |
|
(when newsize |
224 |
|
(enlarge-window (- newsize |
225 |
|
(window-height)) |
226 |
|
nil t) |
227 |
|
(unless (= (window-height) newsize) |
228 |
|
(setq done nil)))))) |
229 |
|
'nomini))))) |
230 |
|
|
231 |
;;; I think this should be the default; I think people will prefer it--rms. |
;;; I think this should be the default; I think people will prefer it--rms. |
232 |
(defcustom split-window-keep-point t |
(defcustom split-window-keep-point t |