Mercurial > emacs
comparison lisp/window.el @ 90996:f55f9811f5d7
Merge from emacs--devo--0
Patches applied:
* emacs--devo--0 (patch 824-831)
- Update from CVS
- Merge from emacs--rel--22
* emacs--rel--22 (patch 70-74)
- Update from CVS
Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-238
author | Miles Bader <miles@gnu.org> |
---|---|
date | Fri, 27 Jul 2007 10:52:18 +0000 |
parents | a66921565bcb b98604865ea0 |
children | 424b655804ca |
comparison
equal
deleted
inserted
replaced
90995:9a391d85a79f | 90996:f55f9811f5d7 |
---|---|
8 | 8 |
9 ;; This file is part of GNU Emacs. | 9 ;; This file is part of GNU Emacs. |
10 | 10 |
11 ;; GNU Emacs is free software; you can redistribute it and/or modify | 11 ;; GNU Emacs is free software; you can redistribute it and/or modify |
12 ;; it under the terms of the GNU General Public License as published by | 12 ;; it under the terms of the GNU General Public License as published by |
13 ;; the Free Software Foundation; either version 2, or (at your option) | 13 ;; the Free Software Foundation; either version 3, or (at your option) |
14 ;; any later version. | 14 ;; any later version. |
15 | 15 |
16 ;; GNU Emacs is distributed in the hope that it will be useful, | 16 ;; GNU Emacs is distributed in the hope that it will be useful, |
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
55 `(let ((save-selected-window-window (selected-window)) | 55 `(let ((save-selected-window-window (selected-window)) |
56 ;; It is necessary to save all of these, because calling | 56 ;; It is necessary to save all of these, because calling |
57 ;; select-window changes frame-selected-window for whatever | 57 ;; select-window changes frame-selected-window for whatever |
58 ;; frame that window is in. | 58 ;; frame that window is in. |
59 (save-selected-window-alist | 59 (save-selected-window-alist |
60 (mapcar (lambda (frame) (list frame (frame-selected-window frame))) | 60 (mapcar (lambda (frame) (cons frame (frame-selected-window frame))) |
61 (frame-list)))) | 61 (frame-list)))) |
62 (save-current-buffer | 62 (save-current-buffer |
63 (unwind-protect | 63 (unwind-protect |
64 (progn ,@body) | 64 (progn ,@body) |
65 (dolist (elt save-selected-window-alist) | 65 (dolist (elt save-selected-window-alist) |
66 (and (frame-live-p (car elt)) | 66 (and (frame-live-p (car elt)) |
67 (window-live-p (cadr elt)) | 67 (window-live-p (cdr elt)) |
68 (set-frame-selected-window (car elt) (cadr elt)))) | 68 (set-frame-selected-window (car elt) (cdr elt)))) |
69 (if (window-live-p save-selected-window-window) | 69 (if (window-live-p save-selected-window-window) |
70 (select-window save-selected-window-window)))))) | 70 (select-window save-selected-window-window)))))) |
71 | 71 |
72 (defun window-body-height (&optional window) | 72 (defun window-body-height (&optional window) |
73 "Return number of lines in window WINDOW for actual buffer text. | 73 "Return number of lines in window WINDOW for actual buffer text. |
394 (bw-balance-sub wt w h))))) | 394 (bw-balance-sub wt w h))))) |
395 | 395 |
396 (defun bw-adjust-window (window delta horizontal) | 396 (defun bw-adjust-window (window delta horizontal) |
397 "Wrapper around `adjust-window-trailing-edge' with error checking. | 397 "Wrapper around `adjust-window-trailing-edge' with error checking. |
398 Arguments WINDOW, DELTA and HORIZONTAL are passed on to that function." | 398 Arguments WINDOW, DELTA and HORIZONTAL are passed on to that function." |
399 (condition-case err | 399 ;; `adjust-window-trailing-edge' may fail if delta is too large. |
400 (adjust-window-trailing-edge window delta horizontal) | 400 (while (>= (abs delta) 1) |
401 (error | 401 (condition-case err |
402 ;;(message "adjust: %s" (error-message-string err)) | 402 (progn |
403 ))) | 403 (adjust-window-trailing-edge window delta horizontal) |
404 (setq delta 0)) | |
405 (error | |
406 ;;(message "adjust: %s" (error-message-string err)) | |
407 (setq delta (/ delta 2)))))) | |
404 | 408 |
405 (defun bw-balance-sub (wt w h) | 409 (defun bw-balance-sub (wt w h) |
406 (setq wt (bw-refresh-edges wt)) | 410 (setq wt (bw-refresh-edges wt)) |
407 (unless w (setq w (- (bw-r wt) (bw-l wt)))) | 411 (unless w (setq w (- (bw-r wt) (bw-l wt)))) |
408 (unless h (setq h (- (bw-b wt) (bw-t wt)))) | 412 (unless h (setq h (- (bw-b wt) (bw-t wt)))) |
420 (lastchild (car (last childs))) | 424 (lastchild (car (last childs))) |
421 (cw (when w (/ w (if (bw-eqdir 'hor wt) (length childs) 1)))) | 425 (cw (when w (/ w (if (bw-eqdir 'hor wt) (length childs) 1)))) |
422 (ch (when h (/ h (if (bw-eqdir 'ver wt) (length childs) 1))))) | 426 (ch (when h (/ h (if (bw-eqdir 'ver wt) (length childs) 1))))) |
423 (dolist (c childs) | 427 (dolist (c childs) |
424 (bw-balance-sub c cw ch))))) | 428 (bw-balance-sub c cw ch))))) |
429 | |
430 ;;; A different solution to balance-windows | |
431 | |
432 (defun window-fixed-size-p (&optional window direction) | |
433 "Non-nil if WINDOW cannot be resized in DIRECTION. | |
434 DIRECTION can be nil (i.e. any), `height' or `width'." | |
435 (with-current-buffer (window-buffer window) | |
436 (let ((fixed (and (boundp 'window-size-fixed) window-size-fixed))) | |
437 (when fixed | |
438 (not (and direction | |
439 (member (cons direction window-size-fixed) | |
440 '((height . width) (width . height))))))))) | |
441 | |
442 (defvar window-area-factor 1 | |
443 "Factor by which the window area should be over-estimated. | |
444 This is used by `balance-windows-area'. | |
445 Changing this globally has no effect.") | |
446 | |
447 (defun balance-windows-area () | |
448 "Make all visible windows the same area (approximately). | |
449 See also `window-area-factor' to change the relative size of specific buffers." | |
450 (interactive) | |
451 (let* ((unchanged 0) (carry 0) (round 0) | |
452 ;; Remove fixed-size windows. | |
453 (wins (delq nil (mapcar (lambda (win) | |
454 (if (not (window-fixed-size-p win)) win)) | |
455 (window-list nil 'nomini)))) | |
456 (changelog nil) | |
457 next) | |
458 ;; Resizing a window changes the size of surrounding windows in complex | |
459 ;; ways, so it's difficult to balance them all. The introduction of | |
460 ;; `adjust-window-trailing-edge' made it a bit easier, but it is still | |
461 ;; very difficult to do. `balance-window' above takes an off-line | |
462 ;; approach: get the whole window tree, then balance it, then try to | |
463 ;; adjust the windows so they fit the result. | |
464 ;; Here, instead, we take a "local optimization" approach, where we just | |
465 ;; go through all the windows several times until nothing needs to be | |
466 ;; changed. The main problem with this approach is that it's difficult | |
467 ;; to make sure it terminates, so we use some heuristic to try and break | |
468 ;; off infinite loops. | |
469 ;; After a round without any change, we allow a second, to give a chance | |
470 ;; to the carry to propagate a minor imbalance from the end back to | |
471 ;; the beginning. | |
472 (while (< unchanged 2) | |
473 ;; (message "New round") | |
474 (setq unchanged (1+ unchanged) round (1+ round)) | |
475 (dolist (win wins) | |
476 (setq next win) | |
477 (while (progn (setq next (next-window next)) | |
478 (window-fixed-size-p next))) | |
479 ;; (assert (eq next (or (cadr (member win wins)) (car wins)))) | |
480 (let* ((horiz | |
481 (< (car (window-edges win)) (car (window-edges next)))) | |
482 (areadiff (/ (- (* (window-height next) (window-width next) | |
483 (buffer-local-value 'window-area-factor | |
484 (window-buffer next))) | |
485 (* (window-height win) (window-width win) | |
486 (buffer-local-value 'window-area-factor | |
487 (window-buffer win)))) | |
488 (max (buffer-local-value 'window-area-factor | |
489 (window-buffer win)) | |
490 (buffer-local-value 'window-area-factor | |
491 (window-buffer next))))) | |
492 (edgesize (if horiz | |
493 (+ (window-height win) (window-height next)) | |
494 (+ (window-width win) (window-width next)))) | |
495 (diff (/ areadiff edgesize))) | |
496 (when (zerop diff) | |
497 ;; Maybe diff is actually closer to 1 than to 0. | |
498 (setq diff (/ (* 3 areadiff) (* 2 edgesize)))) | |
499 (when (and (zerop diff) (not (zerop areadiff))) | |
500 (setq diff (/ (+ areadiff carry) edgesize)) | |
501 ;; Change things smoothly. | |
502 (if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2)))) | |
503 (if (zerop diff) | |
504 ;; Make sure negligible differences don't accumulate to | |
505 ;; become significant. | |
506 (setq carry (+ carry areadiff)) | |
507 (bw-adjust-window win diff horiz) | |
508 ;; (sit-for 0.5) | |
509 (let ((change (cons win (window-edges win)))) | |
510 ;; If the same change has been seen already for this window, | |
511 ;; we're most likely in an endless loop, so don't count it as | |
512 ;; a change. | |
513 (unless (member change changelog) | |
514 (push change changelog) | |
515 (setq unchanged 0 carry 0))))))) | |
516 ;; We've now basically balanced all the windows. | |
517 ;; But there may be some minor off-by-one imbalance left over, | |
518 ;; so let's do some fine tuning. | |
519 ;; (bw-finetune wins) | |
520 ;; (message "Done in %d rounds" round) | |
521 )) | |
425 | 522 |
426 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 523 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
427 | 524 |
428 ;; I think this should be the default; I think people will prefer it--rms. | 525 ;; I think this should be the default; I think people will prefer it--rms. |
429 (defcustom split-window-keep-point t | 526 (defcustom split-window-keep-point t |