aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Rudalics2011-06-07 15:50:31 +0200
committerMartin Rudalics2011-06-07 15:50:31 +0200
commita1511cafb5484ff26663bb6258df47f8bdba734b (patch)
treef048dec08e34ed07d71322387ef2b1570457b4fb
parent190b47e683f61b30533bcc548f8be9d3b861029e (diff)
downloademacs-a1511cafb5484ff26663bb6258df47f8bdba734b.tar.gz
emacs-a1511cafb5484ff26663bb6258df47f8bdba734b.zip
Add and rewrite window size functions in window.el.
* window.el (window-safe-min-height, window-safe-min-width): New constants. (window-size-ignore, window-min-size, window-min-size-1) (window-sizable, window-sizable-p, window-size-fixed-1) (window-size-fixed-p, window-min-delta-1, window-min-delta) (window-max-delta-1, window-max-delta, window-resizable) (window-resizable-p, window-total-height, window-total-width) (window-body-width): New functions. (window-full-height-p, window-full-width-p): Rewrite using window-total-size. (window-body-height): Rewrite using window-body-size.
-rw-r--r--lisp/ChangeLog10
-rw-r--r--lisp/window.el481
2 files changed, 467 insertions, 24 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 910591d1887..ab80b59e0be 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -5,6 +5,16 @@
5 doc-strings. 5 doc-strings.
6 (get-buffer-window-list): Rewrite using window-list-1. Rephrase 6 (get-buffer-window-list): Rewrite using window-list-1. Rephrase
7 doc-string. 7 doc-string.
8 (window-safe-min-height, window-safe-min-width): New constants.
9 (window-size-ignore, window-min-size, window-min-size-1)
10 (window-sizable, window-sizable-p, window-size-fixed-1)
11 (window-size-fixed-p, window-min-delta-1, window-min-delta)
12 (window-max-delta-1, window-max-delta, window-resizable)
13 (window-resizable-p, window-total-height, window-total-width)
14 (window-body-width): New functions.
15 (window-full-height-p, window-full-width-p): Rewrite using
16 window-total-size.
17 (window-body-height): Rewrite using window-body-size.
8 18
92011-06-06 Martin Rudalics <rudalics@gmx.at> 192011-06-06 Martin Rudalics <rudalics@gmx.at>
10 20
diff --git a/lisp/window.el b/lisp/window.el
index 5905443de67..856ec66a005 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -157,6 +157,14 @@ The functions currently affected by this are `split-window',
157An application may bind this to a non-nil value around calls to 157An application may bind this to a non-nil value around calls to
158these functions to inhibit processing of window parameters.") 158these functions to inhibit processing of window parameters.")
159 159
160(defconst window-safe-min-height 1
161 "The absolut minimum number of lines of a window.
162Anything less might crash Emacs.")
163
164(defconst window-safe-min-width 2
165 "The absolut minimum number of columns of a window.
166Anything less might crash Emacs.")
167
160(defun window-iso-combination-p (&optional window horizontal) 168(defun window-iso-combination-p (&optional window horizontal)
161 "If WINDOW is a vertical combination return WINDOW's first child. 169 "If WINDOW is a vertical combination return WINDOW's first child.
162WINDOW can be any window and defaults to the selected one. 170WINDOW can be any window and defaults to the selected one.
@@ -491,32 +499,457 @@ unless it has no other choice \(like when deleting a neighboring
491window).") 499window).")
492(make-variable-buffer-local 'window-size-fixed) 500(make-variable-buffer-local 'window-size-fixed)
493 501
494(defun window-body-height (&optional window) 502(defsubst window-size-ignore (window ignore)
495 "Return number of lines in WINDOW available for actual buffer text. 503 "Return non-nil if IGNORE says to ignore size restrictions for WINDOW."
496WINDOW defaults to the selected window. 504 (if (window-any-p ignore) (eq window ignore) ignore))
497 505
498The return value does not include the mode line or the header 506(defun window-min-size (&optional window horizontal ignore)
499line, if any. If a line at the bottom of the window is only 507 "Return the minimum number of lines of WINDOW.
500partially visible, that line is included in the return value. 508WINDOW can be an arbitrary window and defaults to the selected
501If you do not want to include a partially visible bottom line 509one. Optional argument HORIZONTAL non-nil means return the
502in the return value, use `window-text-height' instead." 510minimum number of columns of WINDOW.
503 (or window (setq window (selected-window))) 511
504 (if (window-minibuffer-p window) 512Optional argument IGNORE non-nil means ignore any restrictions
505 (window-height window) 513imposed by fixed size windows, `window-min-height' or
506 (with-current-buffer (window-buffer window) 514`window-min-width' settings. IGNORE equal `safe' means live
507 (max 1 (- (window-height window) 515windows may get as small as `window-safe-min-height' lines and
508 (if mode-line-format 1 0) 516`window-safe-min-width' columns. IGNORE a window means ignore
509 (if header-line-format 1 0)))))) 517restrictions for that window only."
518 (window-min-size-1
519 (normalize-any-window window) horizontal ignore))
520
521(defun window-min-size-1 (window horizontal ignore)
522 "Internal function of `window-min-size'."
523 (let ((sub (window-child window)))
524 (if sub
525 (let ((value 0))
526 ;; WINDOW is an internal window.
527 (if (window-iso-combined-p sub horizontal)
528 ;; The minimum size of an iso-combination is the sum of
529 ;; the minimum sizes of its subwindows.
530 (while sub
531 (setq value (+ value
532 (window-min-size-1 sub horizontal ignore)))
533 (setq sub (window-right sub)))
534 ;; The minimum size of an ortho-combination is the maximum of
535 ;; the minimum sizes of its subwindows.
536 (while sub
537 (setq value (max value
538 (window-min-size-1 sub horizontal ignore)))
539 (setq sub (window-right sub))))
540 value)
541 (with-current-buffer (window-buffer window)
542 (cond
543 ((and (not (window-size-ignore window ignore))
544 (window-size-fixed-p window horizontal))
545 ;; The minimum size of a fixed size window is its size.
546 (window-total-size window horizontal))
547 ((or (eq ignore 'safe) (eq ignore window))
548 ;; If IGNORE equals `safe' or WINDOW return the safe values.
549 (if horizontal window-safe-min-width window-safe-min-height))
550 (horizontal
551 ;; For the minimum width of a window take fringes and
552 ;; scroll-bars into account. This is questionable and should
553 ;; be removed as soon as we are able to split (and resize)
554 ;; windows such that the new (or resized) windows can get a
555 ;; size less than the user-specified `window-min-height' and
556 ;; `window-min-width'.
557 (let ((frame (window-frame window))
558 (fringes (window-fringes window))
559 (scroll-bars (window-scroll-bars window)))
560 (max
561 (+ window-safe-min-width
562 (ceiling (car fringes) (frame-char-width frame))
563 (ceiling (cadr fringes) (frame-char-width frame))
564 (cond
565 ((memq (nth 2 scroll-bars) '(left right))
566 (nth 1 scroll-bars))
567 ((memq (frame-parameter frame 'vertical-scroll-bars)
568 '(left right))
569 (ceiling (or (frame-parameter frame 'scroll-bar-width) 14)
570 (frame-char-width)))
571 (t 0)))
572 (if (and (not (window-size-ignore window ignore))
573 (numberp window-min-width))
574 window-min-width
575 0))))
576 (t
577 ;; For the minimum height of a window take any mode- or
578 ;; header-line into account.
579 (max (+ window-safe-min-height
580 (if header-line-format 1 0)
581 (if mode-line-format 1 0))
582 (if (and (not (window-size-ignore window ignore))
583 (numberp window-min-height))
584 window-min-height
585 0))))))))
586
587(defun window-sizable (window delta &optional horizontal ignore)
588 "Return DELTA if DELTA lines can be added to WINDOW.
589Optional argument HORIZONTAL non-nil means return DELTA if DELTA
590columns can be added to WINDOW. A return value of zero means
591that no lines (or columns) can be added to WINDOW.
592
593This function looks only at WINDOW and its subwindows. The
594function `window-resizable' looks at other windows as well.
595
596DELTA positive means WINDOW shall be enlarged by DELTA lines or
597columns. If WINDOW cannot be enlarged by DELTA lines or columns
598return the maximum value in the range 0..DELTA by which WINDOW
599can be enlarged.
600
601DELTA negative means WINDOW shall be shrunk by -DELTA lines or
602columns. If WINDOW cannot be shrunk by -DELTA lines or columns,
603return the minimum value in the range DELTA..0 by which WINDOW
604can be shrunk.
605
606Optional argument IGNORE non-nil means ignore any restrictions
607imposed by fixed size windows, `window-min-height' or
608`window-min-width' settings. IGNORE equal `safe' means live
609windows may get as small as `window-safe-min-height' lines and
610`window-safe-min-width' columns. IGNORE any window means ignore
611restrictions for that window only."
612 (setq window (normalize-any-window window))
613 (cond
614 ((< delta 0)
615 (max (- (window-min-size window horizontal ignore)
616 (window-total-size window horizontal))
617 delta))
618 ((window-size-ignore window ignore)
619 delta)
620 ((> delta 0)
621 (if (window-size-fixed-p window horizontal)
622 0
623 delta))
624 (t 0)))
625
626(defsubst window-sizable-p (window delta &optional horizontal ignore)
627 "Return t if WINDOW can be resized by DELTA lines.
628For the meaning of the arguments of this function see the
629doc-string of `window-sizable'."
630 (setq window (normalize-any-window window))
631 (if (> delta 0)
632 (>= (window-sizable window delta horizontal ignore) delta)
633 (<= (window-sizable window delta horizontal ignore) delta)))
634
635(defun window-size-fixed-1 (window horizontal)
636 "Internal function for `window-size-fixed-p'."
637 (let ((sub (window-child window)))
638 (catch 'fixed
639 (if sub
640 ;; WINDOW is an internal window.
641 (if (window-iso-combined-p sub horizontal)
642 ;; An iso-combination is fixed size if all its subwindows
643 ;; are fixed-size.
644 (progn
645 (while sub
646 (unless (window-size-fixed-1 sub horizontal)
647 ;; We found a non-fixed-size subwindow, so WINDOW's
648 ;; size is not fixed.
649 (throw 'fixed nil))
650 (setq sub (window-right sub)))
651 ;; All subwindows are fixed-size, so WINDOW's size is
652 ;; fixed.
653 (throw 'fixed t))
654 ;; An ortho-combination is fixed-size if at least one of its
655 ;; subwindows is fixed-size.
656 (while sub
657 (when (window-size-fixed-1 sub horizontal)
658 ;; We found a fixed-size subwindow, so WINDOW's size is
659 ;; fixed.
660 (throw 'fixed t))
661 (setq sub (window-right sub))))
662 ;; WINDOW is a live window.
663 (with-current-buffer (window-buffer window)
664 (if horizontal
665 (memq window-size-fixed '(width t))
666 (memq window-size-fixed '(height t))))))))
667
668(defun window-size-fixed-p (&optional window horizontal)
669 "Return non-nil if WINDOW's height is fixed.
670WINDOW can be an arbitrary window and defaults to the selected
671window. Optional argument HORIZONTAL non-nil means return
672non-nil if WINDOW's width is fixed.
673
674If this function returns nil, this does not necessarily mean that
675WINDOW can be resized in the desired direction. The functions
676`window-resizable' and `window-resizable-p' will tell that."
677 (window-size-fixed-1
678 (normalize-any-window window) horizontal))
679
680(defun window-min-delta-1 (window delta &optional horizontal ignore trail noup)
681 "Internal function for `window-min-delta'."
682 (if (not (window-parent window))
683 ;; If we can't go up, return zero.
684 0
685 ;; Else try to find a non-fixed-size sibling of WINDOW.
686 (let* ((parent (window-parent window))
687 (sub (window-child parent)))
688 (catch 'done
689 (if (window-iso-combined-p sub horizontal)
690 ;; In an iso-combination throw DELTA if we find at least one
691 ;; subwindow and that subwindow is either not of fixed-size
692 ;; or we can ignore fixed-sizeness.
693 (let ((skip (eq trail 'after)))
694 (while sub
695 (cond
696 ((eq sub window)
697 (setq skip (eq trail 'before)))
698 (skip)
699 ((and (not (window-size-ignore window ignore))
700 (window-size-fixed-p sub horizontal)))
701 (t
702 ;; We found a non-fixed-size subwindow.
703 (throw 'done delta)))
704 (setq sub (window-right sub))))
705 ;; In an ortho-combination set DELTA to the minimum value by
706 ;; which other subwindows can shrink.
707 (while sub
708 (unless (eq sub window)
709 (setq delta
710 (min delta
711 (- (window-total-size sub horizontal)
712 (window-min-size sub horizontal ignore)))))
713 (setq sub (window-right sub))))
714 (if noup
715 delta
716 (window-min-delta-1 parent delta horizontal ignore trail))))))
717
718(defun window-min-delta (&optional window horizontal ignore trail noup nodown)
719 "Return number of lines by which WINDOW can be shrunk.
720WINDOW can be an arbitrary window and defaults to the selected
721window. Return zero if WINDOW cannot be shrunk.
722
723Optional argument HORIZONTAL non-nil means return number of
724columns by which WINDOW can be shrunk.
725
726Optional argument IGNORE non-nil means ignore any restrictions
727imposed by fixed size windows, `window-min-height' or
728`window-min-width' settings. IGNORE a window means ignore
729restrictions for that window only. IGNORE equal `safe' means
730live windows may get as small as `window-safe-min-height' lines
731and `window-safe-min-width' columns.
732
733Optional argument TRAIL `before' means only windows to the left
734of or above WINDOW can be enlarged. Optional argument TRAIL
735`after' means only windows to the right of or below WINDOW can be
736enlarged.
737
738Optional argument NOUP non-nil means don't go up in the window
739tree but try to enlarge windows within WINDOW's combination only.
740
741Optional argument NODOWN non-nil means don't check whether WINDOW
742itself \(and its subwindows) can be shrunk; check only whether at
743least one other windows can be enlarged appropriately."
744 (setq window (normalize-any-window window))
745 (let ((size (window-total-size window horizontal))
746 (minimum (window-min-size window horizontal ignore)))
747 (cond
748 (nodown
749 ;; If NODOWN is t, try to recover the entire size of WINDOW.
750 (window-min-delta-1 window size horizontal ignore trail noup))
751 ((= size minimum)
752 ;; If NODOWN is nil and WINDOW's size is already at its minimum,
753 ;; there's nothing to recover.
754 0)
755 (t
756 ;; Otherwise, try to recover whatever WINDOW is larger than its
757 ;; minimum size.
758 (window-min-delta-1
759 window (- size minimum) horizontal ignore trail noup)))))
760
761(defun window-max-delta-1 (window delta &optional horizontal ignore trail noup)
762 "Internal function of `window-max-delta'."
763 (if (not (window-parent window))
764 ;; Can't go up. Return DELTA.
765 delta
766 (let* ((parent (window-parent window))
767 (sub (window-child parent)))
768 (catch 'fixed
769 (if (window-iso-combined-p sub horizontal)
770 ;; For an iso-combination calculate how much we can get from
771 ;; other subwindows.
772 (let ((skip (eq trail 'after)))
773 (while sub
774 (cond
775 ((eq sub window)
776 (setq skip (eq trail 'before)))
777 (skip)
778 (t
779 (setq delta
780 (+ delta
781 (- (window-total-size sub horizontal)
782 (window-min-size sub horizontal ignore))))))
783 (setq sub (window-right sub))))
784 ;; For an ortho-combination throw DELTA when at least one
785 ;; subwindow is fixed-size.
786 (while sub
787 (when (and (not (eq sub window))
788 (not (window-size-ignore sub ignore))
789 (window-size-fixed-p sub horizontal))
790 (throw 'fixed delta))
791 (setq sub (window-right sub))))
792 (if noup
793 ;; When NOUP is nil, DELTA is all we can get.
794 delta
795 ;; Else try with parent of WINDOW, passing the DELTA we
796 ;; recovered so far.
797 (window-max-delta-1 parent delta horizontal ignore trail))))))
798
799(defun window-max-delta (&optional window horizontal ignore trail noup nodown)
800 "Return maximum number of lines WINDOW by which WINDOW can be enlarged.
801WINDOW can be an arbitrary window and defaults to the selected
802window. The return value is zero if WINDOW cannot be enlarged.
803
804Optional argument HORIZONTAL non-nil means return maximum number
805of columns by which WINDOW can be enlarged.
806
807Optional argument IGNORE non-nil means ignore any restrictions
808imposed by fixed size windows, `window-min-height' or
809`window-min-width' settings. IGNORE a window means ignore
810restrictions for that window only. IGNORE equal `safe' means
811live windows may get as small as `window-safe-min-height' lines
812and `window-safe-min-width' columns.
813
814Optional argument TRAIL `before' means only windows to the left
815of or below WINDOW can be shrunk. Optional argument TRAIL
816`after' means only windows to the right of or above WINDOW can be
817shrunk.
818
819Optional argument NOUP non-nil means don't go up in the window
820tree but try to obtain the entire space from windows within
821WINDOW's combination.
822
823Optional argument NODOWN non-nil means do not check whether
824WINDOW itself \(and its subwindows) can be enlarged; check only
825whether other windows can be shrunk appropriately."
826 (setq window (normalize-any-window window))
827 (if (and (not (window-size-ignore window ignore))
828 (not nodown) (window-size-fixed-p window horizontal))
829 ;; With IGNORE and NOWDON nil return zero if WINDOW has fixed
830 ;; size.
831 0
832 ;; WINDOW has no fixed size.
833 (window-max-delta-1 window 0 horizontal ignore trail noup)))
834
835;; Make NOUP also inhibit the min-size check.
836(defun window-resizable (window delta &optional horizontal ignore trail noup nodown)
837 "Return DELTA if WINDOW can be resized vertically by DELTA lines.
838Optional argument HORIZONTAL non-nil means return DELTA if WINDOW
839can be resized horizontally by DELTA columns. A return value of
840zero means that WINDOW is not resizable.
841
842DELTA positive means WINDOW shall be enlarged by DELTA lines or
843columns. If WINDOW cannot be enlarged by DELTA lines or columns
844return the maximum value in the range 0..DELTA by which WINDOW
845can be enlarged.
846
847DELTA negative means WINDOW shall be shrunk by -DELTA lines or
848columns. If WINDOW cannot be shrunk by -DELTA lines or columns,
849return the minimum value in the range DELTA..0 that can be used
850for shrinking WINDOW.
851
852Optional argument IGNORE non-nil means ignore any restrictions
853imposed by fixed size windows, `window-min-height' or
854`window-min-width' settings. IGNORE a window means ignore
855restrictions for that window only. IGNORE equal `safe' means
856live windows may get as small as `window-safe-min-height' lines
857and `window-safe-min-width' columns.
858
859Optional argument TRAIL `before' means only windows to the left
860of or below WINDOW can be shrunk. Optional argument TRAIL
861`after' means only windows to the right of or above WINDOW can be
862shrunk.
863
864Optional argument NOUP non-nil means don't go up in the window
865tree but try to distribute the space among the other windows
866within WINDOW's combination.
867
868Optional argument NODOWN non-nil means don't check whether WINDOW
869and its subwindows can be resized."
870 (setq window (normalize-any-window window))
871 (cond
872 ((< delta 0)
873 (max (- (window-min-delta window horizontal ignore trail noup nodown))
874 delta))
875 ((> delta 0)
876 (min (window-max-delta window horizontal ignore trail noup nodown)
877 delta))
878 (t 0)))
879
880(defun window-resizable-p (window delta &optional horizontal ignore trail noup nodown)
881 "Return t if WINDOW can be resized vertically by DELTA lines.
882For the meaning of the arguments of this function see the
883doc-string of `window-resizable'."
884 (setq window (normalize-any-window window))
885 (if (> delta 0)
886 (>= (window-resizable window delta horizontal ignore trail noup nodown)
887 delta)
888 (<= (window-resizable window delta horizontal ignore trail noup nodown)
889 delta)))
890
891(defsubst window-total-height (&optional window)
892 "Return the total number of lines of WINDOW.
893WINDOW can be any window and defaults to the selected one. The
894return value includes WINDOW's mode line and header line, if any.
895If WINDOW is internal the return value is the sum of the total
896number of lines of WINDOW's child windows if these are vertically
897combined and the height of WINDOW's first child otherwise.
898
899Note: This function does not take into account the value of
900`line-spacing' when calculating the number of lines in WINDOW."
901 (window-total-size window))
510 902
511;; See discussion in bug#4543. 903;; See discussion in bug#4543.
512(defun window-full-height-p (&optional window) 904(defsubst window-full-height-p (&optional window)
513 "Return non-nil if WINDOW is not the result of a vertical split. 905 "Return t if WINDOW is as high as the containing frame.
514WINDOW defaults to the selected window. (This function is not 906More precisely, return t if and only if the total height of
515appropriate for minibuffers.)" 907WINDOW equals the total height of the root window of WINDOW's
516 (unless window 908frame. WINDOW can be any window and defaults to the selected
517 (setq window (selected-window))) 909one."
518 (= (window-height window) 910 (setq window (normalize-any-window window))
519 (window-height (frame-root-window (window-frame window))))) 911 (= (window-total-size window)
912 (window-total-size (frame-root-window window))))
913
914(defsubst window-total-width (&optional window)
915 "Return the total number of columns of WINDOW.
916WINDOW can be any window and defaults to the selected one. The
917return value includes any vertical dividers or scrollbars of
918WINDOW. If WINDOW is internal, the return value is the sum of
919the total number of columns of WINDOW's child windows if these
920are horizontally combined and the width of WINDOW's first child
921otherwise."
922 (window-total-size window t))
923
924(defsubst window-full-width-p (&optional window)
925 "Return t if WINDOW is as wide as the containing frame.
926More precisely, return t if and only if the total width of WINDOW
927equals the total width of the root window of WINDOW's frame.
928WINDOW can be any window and defaults to the selected one."
929 (setq window (normalize-any-window window))
930 (= (window-total-size window t)
931 (window-total-size (frame-root-window window) t)))
932
933(defsubst window-body-height (&optional window)
934 "Return the number of lines of WINDOW's body.
935WINDOW must be a live window and defaults to the selected one.
936
937The return value does not include WINDOW's mode line and header
938line, if any. If a line at the bottom of the window is only
939partially visible, that line is included in the return value. If
940you do not want to include a partially visible bottom line in the
941return value, use `window-text-height' instead."
942 (window-body-size window))
943
944(defsubst window-body-width (&optional window)
945 "Return the number of columns of WINDOW's body.
946WINDOW must be a live window and defaults to the selected one.
947
948The return value does not include any vertical dividers or scroll
949bars owned by WINDOW. On a window-system the return value does
950not include the number of columns used for WINDOW's fringes or
951display margins either."
952 (window-body-size window t))
520 953
521(defun one-window-p (&optional nomini all-frames) 954(defun one-window-p (&optional nomini all-frames)
522 "Return non-nil if the selected window is the only window. 955 "Return non-nil if the selected window is the only window.