From 562dd5e9532d75d18843a37a1e42a1f4398d4823 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Fri, 10 Jun 2011 08:55:18 +0200 Subject: [PATCH] Move window resize code from window.c to window.el. * window.c: Remove declarations of Qwindow_size_fixed, window_min_size_1, window_min_size_2, window_min_size, size_window, window_fixed_size_p, enlarge_window, delete_window. Remove static from declaration of Qdelete_window, it's temporarily needed by Fbury_buffer. (replace_window): Don't assign orig_top_line and orig_total_lines. (Fdelete_window, delete_window): Remove. Window deletion is handled by window.el. (window_loop): Remove DELETE_OTHER_WINDOWS case. Replace Fdelete_window calls with calls to Qdelete_window. (Fdelete_other_windows): Remove. Deleting other windows is handled by window.el. (window_fixed_size_p): Remove. Fixed-sizeness of windows is handled in window.el. (window_min_size_2, window_min_size_1, window_min_size): Remove. Window minimum sizes are handled in window.el. (shrink_windows, size_window, set_window_height) (set_window_width, change_window_heights, window_height) (window_width, CURBEG, CURSIZE, enlarge_window) (adjust_window_trailing_edge, Fadjust_window_trailing_edge) (Fenlarge_window, Fshrink_window): Remove. Window resizing is handled in window.el. (make_dummy_parent): Rename to make_parent_window and give it a second argument horflag. (make_window): Don't set resize_proportionally any more. (Fsplit_window): Remove. Windows are split in window.el. (save_restore_action, save_restore_orig_size) (shrink_window_lowest_first, save_restore_orig_size): Remove. Resize mini windows in window.el. (grow_mini_window, shrink_mini_window): Implement by calling Qresize_root_window_vertically, resize_window_check and resize_window_apply. (saved_window, Fset_window_configuration, save_window_save): Do not handle orig_top_line, orig_total_lines, and resize_proportionally. (window_min_height, window_min_width): Move to window.el. (keys_of_window): Move bindings for delete-other-windows, split-window, delete-window and enlarge-window to window.el. * buffer.c: Temporarily extern Qdelete_window. (Fbury_buffer): Temporarily call Qdelete_window instead of Fdelete_window (Fbury_buffer will move to window.el soon). * frame.c (set_menu_bar_lines_1): Remove code handling orig_top_line and orig_total_lines. * dispnew.c (adjust_frame_glyphs_initially): Don't use set_window_height but set heights directly. (change_frame_size_1): Use resize_frame_windows. * xdisp.c (init_xdisp): Don't use set_window_height but set heights directly. * xfns.c (x_set_menu_bar_lines, x_set_tool_bar_lines): Use resize_frame_windows instead of change_window_heights and run run_window_configuration_change_hook. * w32fns.c (x_set_tool_bar_lines): Use resize_frame_windows instead of change_window_heights and run run_window_configuration_change_hook. * window.el (window-min-height, window-min-width): Move here from window.c. Add defcustoms and rewrite doc-strings. (resize-mini-window, resize-window): New functions. (adjust-window-trailing-edge, enlarge-window, shrink-window): Move here from window.c. (maximize-window, minimize-window): New functions. (delete-window, delete-other-windows, split-window): Move here from window.c. (window-split-min-size): New function. (split-window-keep-point): Mention split-window-above-each-other instead of split-window-vertically. (split-window-above-each-other, split-window-vertically): Rename split-window-vertically to split-window-above-each-other and provide defalias for old definition. (split-window-side-by-side, split-window-horizontally): Rename split-window-horizontally to split-window-side-by-side and provide defalias for the old definition. (ctl-x-map): Move bindings for delete-window, delete-other-windows and enlarge-window here from window.c. Replace bindings for split-window-vertically and split-window-horizontally by bindings for split-window-above-each-other and split-window-side-by-side. * cus-start.el (all): Remove entries for window-min-height and window-min-width. Add entries for window-splits and window-nest. --- lisp/ChangeLog | 29 + lisp/cus-start.el | 15 +- lisp/window.el | 826 +++++++++++++++-- src/ChangeLog | 64 ++ src/buffer.c | 4 +- src/dispnew.c | 27 +- src/frame.c | 5 - src/w32fns.c | 7 +- src/window.c | 2221 +++++---------------------------------------- src/xdisp.c | 28 +- src/xfns.c | 8 +- 11 files changed, 1058 insertions(+), 2176 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index ae1da48b477..1ac216dfbe2 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,32 @@ +2011-06-10 Martin Rudalics + + * window.el (window-min-height, window-min-width): Move here + from window.c. Add defcustoms and rewrite doc-strings. + (resize-mini-window, resize-window): New functions. + (adjust-window-trailing-edge, enlarge-window, shrink-window): + Move here from window.c. + (maximize-window, minimize-window): New functions. + (delete-window, delete-other-windows, split-window): Move here + from window.c. + (window-split-min-size): New function. + (split-window-keep-point): Mention split-window-above-each-other + instead of split-window-vertically. + (split-window-above-each-other, split-window-vertically): Rename + split-window-vertically to split-window-above-each-other and + provide defalias for old definition. + (split-window-side-by-side, split-window-horizontally): Rename + split-window-horizontally to split-window-side-by-side and provide + defalias for the old definition. + (ctl-x-map): Move bindings for delete-window, + delete-other-windows and enlarge-window here from window.c. + Replace bindings for split-window-vertically and + split-window-horizontally by bindings for + split-window-above-each-other and split-window-side-by-side. + + * cus-start.el (all): Remove entries for window-min-height and + window-min-width. Add entries for window-splits and + window-nest. + 2011-06-09 Glenn Morris * calendar/appt.el (appt-mode-line): New function. diff --git a/lisp/cus-start.el b/lisp/cus-start.el index 6113a4321c5..389716b35b9 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -388,19 +388,18 @@ since it could result in memory overflow and make Emacs crash." ;; window.c (temp-buffer-show-function windows (choice (const nil) function)) (next-screen-context-lines windows integer) - (window-min-height windows integer) - (window-min-width windows integer) (scroll-preserve-screen-position windows (choice (const :tag "Off (nil)" :value nil) (const :tag "Full screen (t)" :value t) (other :tag "Always" 1)) "22.1") - (recenter-redisplay windows - (choice - (const :tag "Never (nil)" :value nil) - (const :tag "Only on ttys" :value tty) - (other :tag "Always" t)) - "23.1") + (recenter-redisplay + windows (choice + (const :tag "Never (nil)" :value nil) + (const :tag "Only on ttys" :value tty) + (other :tag "Always" t)) "23.1") + (window-splits windows boolean "24.1") + (window-nest windows boolean "24.1") ;; xdisp.c (show-trailing-whitespace whitespace-faces boolean nil :safe booleanp) diff --git a/lisp/window.el b/lisp/window.el index 566577ca72f..a88e56be83c 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -161,10 +161,41 @@ these functions to inhibit processing of window parameters.") "The absolut minimum number of lines of a window. Anything less might crash Emacs.") +(defcustom window-min-height 4 + "The minimum number of lines of any window. +The value has to accomodate a mode- or header-line if present. A +value less than `window-safe-min-height' is ignored. The value +of this variable is honored when windows are resized or split. + +Applications should never rebind this variable. To resize a +window to a height less than the one specified here, an +application should instead call `resize-window' with a non-nil +IGNORE argument. In order to have `split-window' make a window +shorter, explictly specify the SIZE argument of that function." + :type 'integer + :version "24.1" + :group 'windows) + (defconst window-safe-min-width 2 "The absolut minimum number of columns of a window. Anything less might crash Emacs.") +(defcustom window-min-width 10 + "The minimum number of columns of any window. +The value has to accomodate margins, fringes, or scrollbars if +present. A value less than `window-safe-min-width' is ignored. +The value of this variable is honored when windows are resized or +split. + +Applications should never rebind this variable. To resize a +window to a width less than the one specified here, an +application should instead call `resize-window' with a non-nil +IGNORE argument. In order to have `split-window' make a window +narrower, explictly specify the SIZE argument of that function." + :type 'integer + :version "24.1" + :group 'windows) + (defun window-iso-combination-p (&optional window horizontal) "If WINDOW is a vertical combination return WINDOW's first child. WINDOW can be any window and defaults to the selected one. @@ -1336,6 +1367,97 @@ windows." (when (window-right window) (resize-window-reset-1 (window-right window) horizontal))) +;; The following routine is used to manually resize the minibuffer +;; window and is currently used, for example, by ispell.el. +(defun resize-mini-window (window delta) + "Resize minibuffer window WINDOW by DELTA lines. +If WINDOW cannot be resized by DELTA lines make it as large \(or +as small) as possible but don't signal an error." + (when (window-minibuffer-p window) + (let* ((frame (window-frame window)) + (root (frame-root-window frame)) + (height (window-total-size window)) + (min-delta + (- (window-total-size root) + (window-min-size root)))) + ;; Sanitize DELTA. + (cond + ((<= (+ height delta) 0) + (setq delta (- (- height 1)))) + ((> delta min-delta) + (setq delta min-delta))) + + ;; Resize now. + (resize-window-reset frame) + ;; Ideally we should be able to resize just the last subwindow of + ;; root here. See the comment in `resize-root-window-vertically' + ;; for why we do not do that. + (resize-this-window root (- delta) nil nil t) + (set-window-new-total window (+ height delta)) + ;; The following routine catches the case where we want to resize + ;; a minibuffer-only frame. + (resize-mini-window-internal window)))) + +(defun resize-window (window delta &optional horizontal ignore) + "Resize WINDOW vertically by DELTA lines. +WINDOW can be an arbitrary window and defaults to the selected +one. An attempt to resize the root window of a frame will raise +an error though. + +DELTA a positive number means WINDOW shall be enlarged by DELTA +lines. DELTA negative means WINDOW shall be shrunk by -DELTA +lines. + +Optional argument HORIZONTAL non-nil means resize WINDOW +horizontally by DELTA columns. In this case a positive DELTA +means enlarge WINDOW by DELTA columns. DELTA negative means +WINDOW shall be shrunk by -DELTA columns. + +Optional argument IGNORE non-nil means ignore any restrictions +imposed by fixed size windows, `window-min-height' or +`window-min-width' settings. IGNORE any window means ignore +restrictions for that window only. IGNORE equal `safe' means +live windows may get as small as `window-safe-min-height' lines +and `window-safe-min-width' columns. + +This function resizes other windows proportionally and never +deletes any windows. If you want to move only the low (right) +edge of WINDOW consider using `adjust-window-trailing-edge' +instead." + (setq window (normalize-any-window window)) + (let* ((frame (window-frame window)) + sibling) + (cond + ((eq window (frame-root-window frame)) + (error "Cannot resize the root window of a frame")) + ((window-minibuffer-p window) + (resize-mini-window window delta)) + ((window-resizable-p window delta horizontal ignore) + (resize-window-reset frame horizontal) + (resize-this-window window delta horizontal ignore t) + (if (and (not (window-splits window)) + (window-iso-combined-p window horizontal) + (setq sibling (or (window-right window) (window-left window))) + (window-sizable-p sibling (- delta) horizontal ignore)) + ;; If window-splits returns nil for WINDOW, WINDOW is part of + ;; an iso-combination, and WINDOW's neighboring right or left + ;; sibling can be resized as requested, resize that sibling. + (let ((normal-delta + (/ (float delta) + (window-total-size (window-parent window) horizontal)))) + (resize-this-window sibling (- delta) horizontal nil t) + (set-window-new-normal + window (+ (window-normal-size window horizontal) + normal-delta)) + (set-window-new-normal + sibling (- (window-normal-size sibling horizontal) + normal-delta))) + ;; Otherwise, resize all other windows in the same combination. + (resize-other-windows window delta horizontal ignore)) + (resize-window-apply frame horizontal)) + (t + (error "Cannot resize window %s" window))))) + (defsubst resize-subwindows-skip-p (window) "Return non-nil if WINDOW shall be skipped by resizing routines." (memq (window-new-normal window) '(ignore stuck skip))) @@ -1805,6 +1927,153 @@ any windows." (resize-this-window window delta nil ignore t) delta))) +(defun adjust-window-trailing-edge (window delta &optional horizontal) + "Move WINDOW's bottom edge by DELTA lines. +Optional argument HORIZONTAL non-nil means move WINDOW's right +edge by DELTA columns. WINDOW defaults to the selected window. + +If DELTA is greater zero, then move the edge downwards or to the +right. If DELTA is less than zero, move the edge upwards or to +the left. If the edge can't be moved by DELTA lines or columns, +move it as far as possible in the desired direction." + (setq window (normalize-any-window window)) + (let ((frame (window-frame window)) + (right window) + left this-delta min-delta max-delta failed) + ;; Find the edge we want to move. + (while (and (or (not (window-iso-combined-p right horizontal)) + (not (window-right right))) + (setq right (window-parent right)))) + (cond + ((and (not right) (not horizontal) (not resize-mini-windows) + (eq (window-frame (minibuffer-window frame)) frame)) + (resize-mini-window (minibuffer-window frame) (- delta))) + ((or (not (setq left right)) (not (setq right (window-right right)))) + (if horizontal + (error "No window on the right of this one") + (error "No window below this one"))) + (t + ;; Set LEFT to the first resizable window on the left. This step is + ;; needed to handle fixed-size windows. + (while (and left (window-size-fixed-p left horizontal)) + (setq left + (or (window-left left) + (progn + (while (and (setq left (window-parent left)) + (not (window-iso-combined-p left horizontal)))) + (window-left left))))) + (unless left + (if horizontal + (error "No resizable window on the left of this one") + (error "No resizable window above this one"))) + + ;; Set RIGHT to the first resizable window on the right. This step + ;; is needed to handle fixed-size windows. + (while (and right (window-size-fixed-p right horizontal)) + (setq right + (or (window-right right) + (progn + (while (and (setq right (window-parent right)) + (not (window-iso-combined-p right horizontal)))) + (window-right right))))) + (unless right + (if horizontal + (error "No resizable window on the right of this one") + (error "No resizable window below this one"))) + + ;; LEFT and RIGHT (which might be both internal windows) are now the + ;; two windows we want to resize. + (cond + ((> delta 0) + (setq max-delta (window-max-delta-1 left 0 horizontal nil 'after)) + (setq min-delta (window-min-delta-1 right (- delta) horizontal nil 'before)) + (when (or (< max-delta delta) (> min-delta (- delta))) + ;; We can't get the whole DELTA - move as far as possible. + (setq delta (min max-delta (- min-delta)))) + (unless (zerop delta) + ;; Start resizing. + (resize-window-reset frame horizontal) + ;; Try to enlarge LEFT first. + (setq this-delta (window-resizable left delta horizontal)) + (unless (zerop this-delta) + (resize-this-window + left this-delta horizontal nil t 'before + (if horizontal + (+ (window-left-column left) (window-total-size left t)) + (+ (window-top-line left) (window-total-size left))))) + ;; Shrink windows on right of LEFT. + (resize-other-windows + left delta horizontal nil 'after + (if horizontal + (window-left-column right) + (window-top-line right))))) + ((< delta 0) + (setq max-delta (window-max-delta-1 right 0 horizontal nil 'before)) + (setq min-delta (window-min-delta-1 left delta horizontal nil 'after)) + (when (or (< max-delta (- delta)) (> min-delta delta)) + ;; We can't get the whole DELTA - move as far as possible. + (setq delta (max (- max-delta) min-delta))) + (unless (zerop delta) + ;; Start resizing. + (resize-window-reset frame horizontal) + ;; Try to enlarge RIGHT. + (setq this-delta (window-resizable right (- delta) horizontal)) + (unless (zerop this-delta) + (resize-this-window + right this-delta horizontal nil t 'after + (if horizontal + (window-left-column right) + (window-top-line right)))) + ;; Shrink windows on left of RIGHT. + (resize-other-windows + right (- delta) horizontal nil 'before + (if horizontal + (+ (window-left-column left) (window-total-size left t)) + (+ (window-top-line left) (window-total-size left))))))) + (unless (zerop delta) + ;; Don't report an error in the standard case. + (unless (resize-window-apply frame horizontal) + ;; But do report an error if applying the changes fails. + (error "Failed adjusting window %s" window))))))) + +(defun enlarge-window (delta &optional horizontal) + "Make selected window DELTA lines taller. +Interactively, if no argument is given, make the selected window +one line taller. If optional argument HORIZONTAL is non-nil, +make selected window wider by DELTA columns. If DELTA is +negative, shrink selected window by -DELTA lines or columns. +Return nil." + (interactive "p") + (resize-window (selected-window) delta horizontal)) + +(defun shrink-window (delta &optional horizontal) + "Make selected window DELTA lines smaller. +Interactively, if no argument is given, make the selected window +one line smaller. If optional argument HORIZONTAL is non-nil, +make selected window narrower by DELTA columns. If DELTA is +negative, enlarge selected window by -DELTA lines or columns. +Return nil." + (interactive "p") + (resize-window (selected-window) (- delta) horizontal)) + +(defun maximize-window (&optional window) + "Maximize WINDOW. +Make WINDOW as large as possible without deleting any windows. +WINDOW can be any window and defaults to the selected window." + (interactive) + (setq window (normalize-any-window window)) + (resize-window window (window-max-delta window)) + (resize-window window (window-max-delta window t) t)) + +(defun minimize-window (&optional window) + "Minimize WINDOW. +Make WINDOW as small as possible without deleting any windows. +WINDOW can be any window and defaults to the selected window." + (interactive) + (setq window (normalize-any-window window)) + (resize-window window (- (window-min-delta window))) + (resize-window window (- (window-min-delta window t)) t)) + (defsubst frame-root-window-p (window) "Return non-nil if WINDOW is the root window of its frame." (eq window (frame-root-window window))) @@ -1886,6 +2155,458 @@ instead." (throw 'done t) (setq parent (window-parent parent)))))))) +(defun delete-window (&optional window) + "Delete WINDOW. +WINDOW can be an arbitrary window and defaults to the selected +one. Return nil. + +If the variable `ignore-window-parameters' is non-nil or the +`delete-window' parameter of WINDOW equals t, do not process any +parameters of WINDOW. Otherwise, if the `delete-window' +parameter of WINDOW specifies a function, call that function with +WINDOW as its sole argument and return the value returned by that +function. + +Otherwise, if WINDOW is part of an atomic window, call +`delete-window' with the root of the atomic window as its +argument. If WINDOW is the only window on its frame or the last +non-side window, signal an error." + (interactive) + (setq window (normalize-any-window window)) + (let* ((frame (window-frame window)) + (function (window-parameter window 'delete-window)) + (parent (window-parent window)) + atom-root) + (window-check frame) + (catch 'done + ;; Handle window parameters. + (cond + ;; Ignore window parameters if `ignore-window-parameters' tells + ;; us so or `delete-window' equals t. + ((or ignore-window-parameters (eq function t))) + ((functionp function) + ;; The `delete-window' parameter specifies the function to call. + ;; If that function is `ignore' nothing is done. It's up to the + ;; function called here to avoid infinite recursion. + (throw 'done (funcall function window))) + ((and (window-parameter window 'window-atom) + (setq atom-root (window-atom-root window)) + (not (eq atom-root window))) + (throw 'done (delete-window atom-root))) + ((and (eq (window-parameter window 'window-side) 'none) + (or (not parent) + (not (eq (window-parameter parent 'window-side) 'none)))) + (error "Attempt to delete last non-side window")) + ((not parent) + (error "Attempt to delete minibuffer or sole ordinary window"))) + + (let* ((horizontal (window-hchild parent)) + (size (window-total-size window horizontal)) + (frame-selected + (window-or-subwindow-p (frame-selected-window frame) window)) + ;; Emacs 23 preferably gives WINDOW's space to its left + ;; sibling. + (sibling (or (window-left window) (window-right window)))) + (resize-window-reset frame horizontal) + (cond + ((and (not (window-splits window)) + sibling (window-sizable-p sibling size)) + ;; Resize WINDOW's sibling. + (resize-this-window sibling size horizontal nil t) + (set-window-new-normal + sibling (+ (window-normal-size sibling horizontal) + (window-normal-size window horizontal)))) + ((window-resizable-p window (- size) horizontal nil nil nil t) + ;; Can do without resizing fixed-size windows. + (resize-other-windows window (- size) horizontal)) + (t + ;; Can't do without resizing fixed-size windows. + (resize-other-windows window (- size) horizontal t))) + ;; Actually delete WINDOW. + (delete-window-internal window) + (when (and frame-selected + (window-parameter + (frame-selected-window frame) 'no-other-window)) + ;; `delete-window-internal' has selected a window that should + ;; not be selected, fix this here. + (other-window -1 frame)) + (run-window-configuration-change-hook frame) + (window-check frame) + ;; Always return nil. + nil)))) + +(defun delete-other-windows (&optional window) + "Make WINDOW fill its frame. +WINDOW may be any window and defaults to the selected one. +Return nil. + +If the variable `ignore-window-parameters' is non-nil or the +`delete-other-windows' parameter of WINDOW equals t, do not +process any parameters of WINDOW. Otherwise, if the +`delete-other-windows' parameter of WINDOW specifies a function, +call that function with WINDOW as its sole argument and return +the value returned by that function. + +Otherwise, if WINDOW is part of an atomic window, call this +function with the root of the atomic window as its argument. If +WINDOW is a non-side window, make WINDOW the only non-side window +on the frame. Side windows are not deleted. If WINDOW is a side +window signal an error." + (interactive) + (setq window (normalize-any-window window)) + (let* ((frame (window-frame window)) + (function (window-parameter window 'delete-other-windows)) + (window-side (window-parameter window 'window-side)) + atom-root side-main) + (window-check frame) + (catch 'done + (cond + ;; Ignore window parameters if `ignore-window-parameters' is t or + ;; `delete-other-windows' is t. + ((or ignore-window-parameters (eq function t))) + ((functionp function) + ;; The `delete-other-windows' parameter specifies the function + ;; to call. If the function is `ignore' no windows are deleted. + ;; It's up to the function called to avoid infinite recursion. + (throw 'done (funcall function window))) + ((and (window-parameter window 'window-atom) + (setq atom-root (window-atom-root window)) + (not (eq atom-root window))) + (throw 'done (delete-other-windows atom-root))) + ((eq window-side 'none) + ;; Set side-main to the major non-side window. + (setq side-main (window-with-parameter 'window-side 'none nil t))) + ((memq window-side window-sides) + (error "Cannot make side window the only window"))) + ;; If WINDOW is the main non-side window, do nothing. + (unless (eq window side-main) + (delete-other-windows-internal window side-main) + (run-window-configuration-change-hook frame) + (window-check frame)) + ;; Always return nil. + nil))) + +;;; Splitting windows. +(defsubst window-split-min-size (&optional horizontal) + "Return minimum height of any window when splitting windows. +Optional argument HORIZONTAL non-nil means return minimum width." + (if horizontal + (max window-min-width window-safe-min-width) + (max window-min-height window-safe-min-height))) + +(defun split-window (&optional window size side) + "Make a new window adjacent to WINDOW. +WINDOW can be any window and defaults to the selected one. +Return the new window which is always a live window. + +Optional argument SIZE a positive number means make WINDOW SIZE +lines or columns tall. If SIZE is negative, make the new window +-SIZE lines or columns tall. If and only if SIZE is non-nil, its +absolute value can be less than `window-min-height' or +`window-min-width'; so this command can make a new window as +small as one line or two columns. SIZE defaults to half of +WINDOW's size. Interactively, SIZE is the prefix argument. + +Optional third argument SIDE nil (or `below') specifies that the +new window shall be located below WINDOW. SIDE `above' means the +new window shall be located above WINDOW. In both cases SIZE +specifies the new number of lines for WINDOW \(or the new window +if SIZE is negative) including space reserved for the mode and/or +header line. + +SIDE t (or `right') specifies that the new window shall be +located on the right side of WINDOW. SIDE `left' means the new +window shall be located on the left of WINDOW. In both cases +SIZE specifies the new number of columns for WINDOW \(or the new +window provided SIZE is negative) including space reserved for +fringes and the scrollbar or a divider column. Any other non-nil +value for SIDE is currently handled like t (or `right'). + +If the variable `ignore-window-parameters' is non-nil or the +`split-window' parameter of WINDOW equals t, do not process any +parameters of WINDOW. Otherwise, if the `split-window' parameter +of WINDOW specifies a function, call that function with all three +arguments and return the value returned by that function. + +Otherwise, if WINDOW is part of an atomic window, \"split\" the +root of that atomic window. The new window does not become a +member of that atomic window. + +If WINDOW is live, properties of the new window like margins and +scrollbars are inherited from WINDOW. If WINDOW is an internal +window, these properties as well as the buffer displayed in the +new window are inherited from the window selected on WINDOW's +frame. The selected window is not changed by this function." + (interactive "i") + (setq window (normalize-any-window window)) + (let* ((horizontal (not (memq side '(nil below above)))) + (frame (window-frame window)) + (parent (window-parent window)) + (function (window-parameter window 'split-window)) + (window-side (window-parameter window 'window-side)) + ;; Rebind `window-nest' since in some cases we may have to + ;; override its value. + (window-nest window-nest) + atom-root) + + (window-check frame) + (catch 'done + (cond + ;; Ignore window parameters if either `ignore-window-parameters' + ;; is t or the `split-window' parameter equals t. + ((or ignore-window-parameters (eq function t))) + ((functionp function) + ;; The `split-window' parameter specifies the function to call. + ;; If that function is `ignore', do nothing. + (throw 'done (funcall function window size side))) + ;; If WINDOW is a subwindow of an atomic window, split the root + ;; window of that atomic window instead. + ((and (window-parameter window 'window-atom) + (setq atom-root (window-atom-root window)) + (not (eq atom-root window))) + (throw 'done (split-window atom-root size side)))) + + (when (and window-side + (or (not parent) + (not (window-parameter parent 'window-side)))) + ;; WINDOW is a side root window. To make sure that a new parent + ;; window gets created set `window-nest' to t. + (setq window-nest t)) + + (when (and window-splits size (> size 0)) + ;; If `window-splits' is non-nil and SIZE is a non-negative + ;; integer, we cannot reasonably resize other windows. Rather + ;; bind `window-nest' to t to make sure that subsequent window + ;; deletions are handled correctly. + (setq window-nest t)) + + (let* ((parent-size + ;; `parent-size' is the size of WINDOW's parent, provided + ;; it has one. + (when parent (window-total-size parent horizontal))) + ;; `resize' non-nil means we are supposed to resize other + ;; windows in WINDOW's combination. + (resize + (and window-splits (not window-nest) + ;; Resize makes sense in iso-combinations only. + (window-iso-combined-p window horizontal))) + ;; `old-size' is the current size of WINDOW. + (old-size (window-total-size window horizontal)) + ;; `new-size' is the specified or calculated size of the + ;; new window. + (new-size + (cond + ((not size) + (max (window-split-min-size horizontal) + (if resize + ;; When resizing try to give the new window the + ;; average size of a window in its combination. + (min (- parent-size + (window-min-size parent horizontal)) + (/ parent-size + (1+ (window-iso-combinations + parent horizontal)))) + ;; Else try to give the new window half the size + ;; of WINDOW (plus an eventual odd line). + (+ (/ old-size 2) (% old-size 2))))) + ((>= size 0) + ;; SIZE non-negative specifies the new size of WINDOW. + + ;; Note: Specifying a non-negative SIZE is practically + ;; always done as workaround for making the new window + ;; appear above or on the left of the new window (the + ;; ispell window is a typical example of that). In all + ;; these cases the SIDE argument should be set to 'above + ;; or 'left in order to support the 'resize option. + ;; Here we have to nest the windows instead, see above. + (- old-size size)) + (t + ;; SIZE negative specifies the size of the new window. + (- size)))) + new-parent new-normal) + + ;; Check SIZE. + (cond + ((not size) + (cond + (resize + ;; SIZE unspecified, resizing. + (when (and (not (window-sizable-p parent (- new-size) horizontal)) + ;; Try again with minimum split size. + (setq new-size + (max new-size (window-split-min-size horizontal))) + (not (window-sizable-p parent (- new-size) horizontal))) + (error "Window %s too small for splitting" parent))) + ((> (+ new-size (window-min-size window horizontal)) old-size) + ;; SIZE unspecified, no resizing. + (error "Window %s too small for splitting" window)))) + ((and (>= size 0) + (or (>= size old-size) + (< new-size (if horizontal + window-safe-min-width + window-safe-min-width)))) + ;; SIZE specified as new size of old window. If the new size + ;; is larger than the old size or the size of the new window + ;; would be less than the safe minimum, signal an error. + (error "Window %s too small for splitting" window)) + (resize + ;; SIZE specified, resizing. + (unless (window-sizable-p parent (- new-size) horizontal) + ;; If we cannot resize the parent give up. + (error "Window %s too small for splitting" parent))) + ((or (< new-size + (if horizontal window-safe-min-width window-safe-min-height)) + (< (- old-size new-size) + (if horizontal window-safe-min-width window-safe-min-height))) + ;; SIZE specification violates minimum size restrictions. + (error "Window %s too small for splitting" window))) + + (resize-window-reset frame horizontal) + + (setq new-parent + ;; Make new-parent non-nil if we need a new parent window; + ;; either because we want to nest or because WINDOW is not + ;; iso-combined. + (or window-nest (not (window-iso-combined-p window horizontal)))) + (setq new-normal + ;; Make new-normal the normal size of the new window. + (cond + (size (/ (float new-size) (if new-parent old-size parent-size))) + (new-parent 0.5) + (resize (/ 1.0 (1+ (window-iso-combinations parent horizontal)))) + (t (/ (window-normal-size window horizontal) 2.0)))) + + (if resize + ;; Try to get space from OLD's siblings. We could go "up" and + ;; try getting additional space from surrounding windows but + ;; we won't be able to return space to those windows when we + ;; delete the one we create here. Hence we do not go up. + (progn + (resize-subwindows parent (- new-size) horizontal) + (let* ((normal (- 1.0 new-normal)) + (sub (window-child parent))) + (while sub + (set-window-new-normal + sub (* (window-normal-size sub horizontal) normal)) + (setq sub (window-right sub))))) + ;; Get entire space from WINDOW. + (set-window-new-total window (- old-size new-size)) + (resize-this-window window (- new-size) horizontal) + (set-window-new-normal + window (- (if new-parent 1.0 (window-normal-size window horizontal)) + new-normal))) + + (let* ((new (split-window-internal window new-size side new-normal))) + ;; Inherit window-side parameters, if any. + (when (and window-side new-parent) + (set-window-parameter (window-parent new) 'window-side window-side) + (set-window-parameter new 'window-side window-side)) + + (run-window-configuration-change-hook frame) + (window-check frame) + ;; Always return the new window. + new))))) + +;; I think this should be the default; I think people will prefer it--rms. +(defcustom split-window-keep-point t + "If non-nil, \\[split-window-above-each-other] keeps the original point \ +in both children. +This is often more convenient for editing. +If nil, adjust point in each of the two windows to minimize redisplay. +This is convenient on slow terminals, but point can move strangely. + +This option applies only to `split-window-above-each-other' and +functions that call it. `split-window' always keeps the original +point in both children." + :type 'boolean + :group 'windows) + +(defun split-window-above-each-other (&optional size) + "Split selected window into two windows, one above the other. +The upper window gets SIZE lines and the lower one gets the rest. +SIZE negative means the lower window gets -SIZE lines and the +upper one the rest. With no argument, split windows equally or +close to it. Both windows display the same buffer, now current. + +If the variable `split-window-keep-point' is non-nil, both new +windows will get the same value of point as the selected window. +This is often more convenient for editing. The upper window is +the selected window. + +Otherwise, we choose window starts so as to minimize the amount of +redisplay; this is convenient on slow terminals. The new selected +window is the one that the current value of point appears in. The +value of point can change if the text around point is hidden by the +new mode line. + +Regardless of the value of `split-window-keep-point', the upper +window is the original one and the return value is the new, lower +window." + (interactive "P") + (let ((old-window (selected-window)) + (old-point (point)) + (size (and size (prefix-numeric-value size))) + moved-by-window-height moved new-window bottom) + (when (and size (< size 0) (< (- size) window-min-height)) + ;; `split-window' would not signal an error here. + (error "Size of new window too small")) + (setq new-window (split-window nil size)) + (unless split-window-keep-point + (with-current-buffer (window-buffer) + (goto-char (window-start)) + (setq moved (vertical-motion (window-height))) + (set-window-start new-window (point)) + (when (> (point) (window-point new-window)) + (set-window-point new-window (point))) + (when (= moved (window-height)) + (setq moved-by-window-height t) + (vertical-motion -1)) + (setq bottom (point))) + (and moved-by-window-height + (<= bottom (point)) + (set-window-point old-window (1- bottom))) + (and moved-by-window-height + (<= (window-start new-window) old-point) + (set-window-point new-window old-point) + (select-window new-window))) + (split-window-save-restore-data new-window old-window))) + +(defalias 'split-window-vertically 'split-window-above-each-other) + +;; This is to avoid compiler warnings. +(defvar view-return-to-alist) + +(defun split-window-save-restore-data (new-window old-window) + (with-current-buffer (window-buffer) + (when view-mode + (let ((old-info (assq old-window view-return-to-alist))) + (when old-info + (push (cons new-window (cons (car (cdr old-info)) t)) + view-return-to-alist)))) + new-window)) + +(defun split-window-side-by-side (&optional size) + "Split selected window into two windows side by side. +The selected window becomes the left one and gets SIZE columns. +SIZE negative means the right window gets -SIZE lines. + +SIZE includes the width of the window's scroll bar; if there are +no scroll bars, it includes the width of the divider column to +the window's right, if any. SIZE omitted or nil means split +window equally. + +The selected window remains selected. Return the new window." + (interactive "P") + (let ((old-window (selected-window)) + (size (and size (prefix-numeric-value size))) + new-window) + (when (and size (< size 0) (< (- size) window-min-width)) + ;; `split-window' would not signal an error here. + (error "Size of new window too small")) + (split-window-save-restore-data (split-window nil size t) old-window))) + +(defalias 'split-window-horizontally 'split-window-side-by-side) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; `balance-windows' subroutines using `window-tree' @@ -2866,102 +3587,6 @@ at the front of the list of recently selected ones." ;; input focus and is risen. (select-frame-set-input-focus new-frame)) buffer)) - -;; I think this should be the default; I think people will prefer it--rms. -(defcustom split-window-keep-point t - "If non-nil, \\[split-window-vertically] keeps the original point \ -in both children. -This is often more convenient for editing. -If nil, adjust point in each of the two windows to minimize redisplay. -This is convenient on slow terminals, but point can move strangely. - -This option applies only to `split-window-vertically' and -functions that call it. `split-window' always keeps the original -point in both children." - :type 'boolean - :group 'windows) - -(defun split-window-vertically (&optional size) - "Split selected window into two windows, one above the other. -The upper window gets SIZE lines and the lower one gets the rest. -SIZE negative means the lower window gets -SIZE lines and the -upper one the rest. With no argument, split windows equally or -close to it. Both windows display the same buffer, now current. - -If the variable `split-window-keep-point' is non-nil, both new -windows will get the same value of point as the selected window. -This is often more convenient for editing. The upper window is -the selected window. - -Otherwise, we choose window starts so as to minimize the amount of -redisplay; this is convenient on slow terminals. The new selected -window is the one that the current value of point appears in. The -value of point can change if the text around point is hidden by the -new mode line. - -Regardless of the value of `split-window-keep-point', the upper -window is the original one and the return value is the new, lower -window." - (interactive "P") - (let ((old-window (selected-window)) - (old-point (point)) - (size (and size (prefix-numeric-value size))) - moved-by-window-height moved new-window bottom) - (and size (< size 0) - ;; Handle negative SIZE value. - (setq size (+ (window-height) size))) - (setq new-window (split-window nil size)) - (unless split-window-keep-point - (with-current-buffer (window-buffer) - (goto-char (window-start)) - (setq moved (vertical-motion (window-height))) - (set-window-start new-window (point)) - (when (> (point) (window-point new-window)) - (set-window-point new-window (point))) - (when (= moved (window-height)) - (setq moved-by-window-height t) - (vertical-motion -1)) - (setq bottom (point))) - (and moved-by-window-height - (<= bottom (point)) - (set-window-point old-window (1- bottom))) - (and moved-by-window-height - (<= (window-start new-window) old-point) - (set-window-point new-window old-point) - (select-window new-window))) - (split-window-save-restore-data new-window old-window))) - -;; This is to avoid compiler warnings. -(defvar view-return-to-alist) - -(defun split-window-save-restore-data (new-window old-window) - (with-current-buffer (window-buffer) - (when view-mode - (let ((old-info (assq old-window view-return-to-alist))) - (when old-info - (push (cons new-window (cons (car (cdr old-info)) t)) - view-return-to-alist)))) - new-window)) - -(defun split-window-horizontally (&optional size) - "Split selected window into two windows side by side. -The selected window becomes the left one and gets SIZE columns. -SIZE negative means the right window gets -SIZE lines. - -SIZE includes the width of the window's scroll bar; if there are -no scroll bars, it includes the width of the divider column to -the window's right, if any. SIZE omitted or nil means split -window equally. - -The selected window remains selected. Return the new window." - (interactive "P") - (let ((old-window (selected-window)) - (size (and size (prefix-numeric-value size)))) - (and size (< size 0) - ;; Handle negative SIZE value. - (setq size (+ (window-width) size))) - (split-window-save-restore-data (split-window nil size t) old-window))) - (defun set-window-text-height (window height) "Set the height in lines of the text display area of WINDOW to HEIGHT. @@ -3663,9 +4288,12 @@ Otherwise, consult the value of `truncate-partial-width-windows' (if (integerp t-p-w-w) (< (window-width window) t-p-w-w) t-p-w-w)))) - -(define-key ctl-x-map "2" 'split-window-vertically) -(define-key ctl-x-map "3" 'split-window-horizontally) + +(define-key ctl-x-map "0" 'delete-window) +(define-key ctl-x-map "1" 'delete-other-windows) +(define-key ctl-x-map "2" 'split-window-above-each-other) +(define-key ctl-x-map "3" 'split-window-side-by-side) +(define-key ctl-x-map "^" 'enlarge-window) (define-key ctl-x-map "}" 'enlarge-window-horizontally) (define-key ctl-x-map "{" 'shrink-window-horizontally) (define-key ctl-x-map "-" 'shrink-window-if-larger-than-buffer) diff --git a/src/ChangeLog b/src/ChangeLog index 01c102c3bc0..1643be47a1a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,67 @@ +2011-06-10 Martin Rudalics + + * window.c: Remove declarations of Qwindow_size_fixed, + window_min_size_1, window_min_size_2, window_min_size, + size_window, window_fixed_size_p, enlarge_window, delete_window. + Remove static from declaration of Qdelete_window, it's + temporarily needed by Fbury_buffer. + (replace_window): Don't assign orig_top_line and + orig_total_lines. + (Fdelete_window, delete_window): Remove. Window deletion is + handled by window.el. + (window_loop): Remove DELETE_OTHER_WINDOWS case. Replace + Fdelete_window calls with calls to Qdelete_window. + (Fdelete_other_windows): Remove. Deleting other windows is + handled by window.el. + (window_fixed_size_p): Remove. Fixed-sizeness of windows is + handled in window.el. + (window_min_size_2, window_min_size_1, window_min_size): Remove. + Window minimum sizes are handled in window.el. + (shrink_windows, size_window, set_window_height) + (set_window_width, change_window_heights, window_height) + (window_width, CURBEG, CURSIZE, enlarge_window) + (adjust_window_trailing_edge, Fadjust_window_trailing_edge) + (Fenlarge_window, Fshrink_window): Remove. Window resizing is + handled in window.el. + (make_dummy_parent): Rename to make_parent_window and give it a + second argument horflag. + (make_window): Don't set resize_proportionally any more. + (Fsplit_window): Remove. Windows are split in window.el. + (save_restore_action, save_restore_orig_size) + (shrink_window_lowest_first, save_restore_orig_size): Remove. + Resize mini windows in window.el. + (grow_mini_window, shrink_mini_window): Implement by calling + Qresize_root_window_vertically, resize_window_check and + resize_window_apply. + (saved_window, Fset_window_configuration, save_window_save): Do + not handle orig_top_line, orig_total_lines, and + resize_proportionally. + (window_min_height, window_min_width): Move to window.el. + (keys_of_window): Move bindings for delete-other-windows, + split-window, delete-window and enlarge-window to window.el. + + * buffer.c: Temporarily extern Qdelete_window. + (Fbury_buffer): Temporarily call Qdelete_window instead of + Fdelete_window (Fbury_buffer will move to window.el soon). + + * frame.c (set_menu_bar_lines_1): Remove code handling + orig_top_line and orig_total_lines. + + * dispnew.c (adjust_frame_glyphs_initially): Don't use + set_window_height but set heights directly. + (change_frame_size_1): Use resize_frame_windows. + + * xdisp.c (init_xdisp): Don't use set_window_height but set + heights directly. + + * xfns.c (x_set_menu_bar_lines, x_set_tool_bar_lines): Use + resize_frame_windows instead of change_window_heights and run + run_window_configuration_change_hook. + + * w32fns.c (x_set_tool_bar_lines): Use resize_frame_windows + instead of change_window_heights and run + run_window_configuration_change_hook. + 2011-06-09 Martin Rudalics * window.c (replace_window): Rename second argument REPLACEMENT to diff --git a/src/buffer.c b/src/buffer.c index e9ff8f492ba..0862de9baf7 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1938,6 +1938,8 @@ DEFUN ("barf-if-buffer-read-only", Fbarf_if_buffer_read_only, return Qnil; } +extern Lisp_Object Qdelete_window; + DEFUN ("bury-buffer", Fbury_buffer, Sbury_buffer, 0, 1, "", doc: /* Put BUFFER-OR-NAME at the end of the list of all buffers. There it is the least likely candidate for `other-buffer' to return; @@ -1969,7 +1971,7 @@ its frame, iconify that frame. */) else if (NILP (XWINDOW (selected_window)->parent)) Ficonify_frame (Fwindow_frame (selected_window)); else - Fdelete_window (selected_window); + call1 (Qdelete_window, selected_window); } } else diff --git a/src/dispnew.c b/src/dispnew.c index 501dc4ffd80..2dffc0dce25 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -1933,13 +1933,13 @@ adjust_frame_glyphs_initially (void) /* Do it for the root window. */ XSETFASTINT (root->top_line, top_margin); + XSETFASTINT (root->total_lines, frame_lines - 1 - top_margin); XSETFASTINT (root->total_cols, frame_cols); - set_window_height (sf->root_window, frame_lines - 1 - top_margin, 0); /* Do it for the mini-buffer window. */ XSETFASTINT (mini->top_line, frame_lines - 1); + XSETFASTINT (mini->total_lines, 1); XSETFASTINT (mini->total_cols, frame_cols); - set_window_height (root->next, 1, 0); adjust_frame_glyphs (sf); glyphs_initialized_initially_p = 1; @@ -5715,24 +5715,7 @@ change_frame_size_1 (register struct frame *f, int newheight, int newwidth, int if (newheight != FRAME_LINES (f)) { - if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f)) - { - /* Frame has both root and mini-buffer. */ - XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (f))->top_line, - FRAME_TOP_MARGIN (f)); - set_window_height (FRAME_ROOT_WINDOW (f), - (newheight - - 1 - - FRAME_TOP_MARGIN (f)), - 2); - XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top_line, - newheight - 1); - set_window_height (FRAME_MINIBUF_WINDOW (f), 1, 0); - } - else - /* Frame has just one top-level window. */ - set_window_height (FRAME_ROOT_WINDOW (f), - newheight - FRAME_TOP_MARGIN (f), 2); + resize_frame_windows (f, newheight, 0); /* MSDOS frames cannot PRETEND, as they change frame size by manipulating video hardware. */ @@ -5742,9 +5725,7 @@ change_frame_size_1 (register struct frame *f, int newheight, int newwidth, int if (new_frame_total_cols != FRAME_TOTAL_COLS (f)) { - set_window_width (FRAME_ROOT_WINDOW (f), new_frame_total_cols, 2); - if (FRAME_HAS_MINIBUF_P (f)) - set_window_width (FRAME_MINIBUF_WINDOW (f), new_frame_total_cols, 0); + resize_frame_windows (f, new_frame_total_cols, 1); /* MSDOS frames cannot PRETEND, as they change frame size by manipulating video hardware. */ diff --git a/src/frame.c b/src/frame.c index 71881265b44..6baf2d0e671 100644 --- a/src/frame.c +++ b/src/frame.c @@ -135,11 +135,6 @@ set_menu_bar_lines_1 (Lisp_Object window, int n) XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n); XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n); - if (INTEGERP (w->orig_top_line)) - XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n); - if (INTEGERP (w->orig_total_lines)) - XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n); - /* Handle just the top child in a vertical split. */ if (!NILP (w->vchild)) set_menu_bar_lines_1 (w->vchild, n); diff --git a/src/w32fns.c b/src/w32fns.c index bdf9dce9411..823dbe3567e 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -1596,7 +1596,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) } FRAME_TOOL_BAR_LINES (f) = nlines; - change_window_heights (root_window, delta); + resize_frame_windows (f, FRAME_LINES (f), 0); adjust_glyphs (f); /* We also have to make sure that the internal border at the top of @@ -1631,6 +1631,9 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) if (WINDOWP (f->tool_bar_window)) clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix); } + + run_window_configuration_change_hook (f); + } @@ -5822,8 +5825,6 @@ Value is t if tooltip was open, nil otherwise. */) UNGCPRO; return unbind_to (count, deleted); } - - /*********************************************************************** File selection dialog diff --git a/src/window.c b/src/window.c index dd8cdab77a4..3ee220e1d27 100644 --- a/src/window.c +++ b/src/window.c @@ -50,17 +50,15 @@ along with GNU Emacs. If not, see . */ #include "nsterm.h" #endif -Lisp_Object Qwindowp, Qwindow_live_p; +Lisp_Object Qwindowp, Qwindow_live_p, Qdelete_window; static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer; -static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer; +static Lisp_Object Qwindow_deletable_p, Qdisplay_buffer; static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window; static Lisp_Object Qresize_root_window, Qresize_root_window_vertically; static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command; static Lisp_Object Qsafe, Qabove, Qbelow; static Lisp_Object Qauto_buffer_name; -static Lisp_Object Qwindow_size_fixed; - static int displayed_window_lines (struct window *); static struct window *decode_window (Lisp_Object); static int count_windows (struct window *); @@ -68,13 +66,7 @@ static int get_leaf_windows (struct window *, struct window **, int); static void window_scroll (Lisp_Object, int, int, int); static void window_scroll_pixel_based (Lisp_Object, int, int, int); static void window_scroll_line_based (Lisp_Object, int, int, int); -static int window_min_size_1 (struct window *, int, int); -static int window_min_size_2 (struct window *, int, int); -static int window_min_size (struct window *, int, int, int, int *); -static void size_window (Lisp_Object, int, int, int, int, int); static int freeze_window_start (struct window *, void *); -static int window_fixed_size_p (struct window *, int, int); -static void enlarge_window (Lisp_Object, int, int); static Lisp_Object window_list (void); static int add_window_to_list (struct window *, void *); static int candidate_window_p (Lisp_Object, Lisp_Object, Lisp_Object, @@ -1803,9 +1795,7 @@ DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_displa return table; } -static void delete_window (Lisp_Object); - -/* Record info on buffer window w is displaying +/* Record info on buffer window W is displaying when it is about to cease to display that buffer. */ static void unshow_buffer (register struct window *w) @@ -1891,7 +1881,6 @@ replace_window (Lisp_Object old, Lisp_Object new, int setflag) XSETFASTINT (n->window_end_pos, 0); n->window_end_valid = Qnil; n->frozen_window_start_p = 0; - n->orig_top_line = n->orig_total_lines = Qnil; } n->next = tem = o->next; @@ -1993,232 +1982,6 @@ delete_deletable_window (Lisp_Object window) if (!NILP (call1 (Qwindow_deletable_p, window))) call1 (Qdelete_window, window); } - -DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "", - doc: /* Remove WINDOW from its frame. -WINDOW defaults to the selected window. Return nil. -Signal an error when WINDOW is the only window on its frame. */) - (register Lisp_Object window) -{ - struct frame *f; - if (NILP (window)) - window = selected_window; - else - CHECK_LIVE_WINDOW (window); - - f = XFRAME (WINDOW_FRAME (XWINDOW (window))); - delete_window (window); - - run_window_configuration_change_hook (f); - - return Qnil; -} - -static void -delete_window (register Lisp_Object window) -{ - register Lisp_Object tem, parent, sib; - register struct window *p; - register struct window *par; - struct frame *f; - - /* Because this function is called by other C code on non-leaf - windows, the CHECK_LIVE_WINDOW macro would choke inappropriately, - so we can't decode_window here. */ - CHECK_WINDOW (window); - p = XWINDOW (window); - - /* It's a no-op to delete an already-deleted window. */ - if (NILP (p->buffer) - && NILP (p->hchild) - && NILP (p->vchild)) - return; - - parent = p->parent; - if (NILP (parent)) - error ("Attempt to delete minibuffer or sole ordinary window"); - par = XWINDOW (parent); - - windows_or_buffers_changed++; - Vwindow_list = Qnil; - f = XFRAME (WINDOW_FRAME (p)); - FRAME_WINDOW_SIZES_CHANGED (f) = 1; - - /* Are we trying to delete any frame's selected window? */ - { - Lisp_Object swindow, pwindow; - - /* See if the frame's selected window is either WINDOW - or any subwindow of it, by finding all that window's parents - and comparing each one with WINDOW. */ - swindow = FRAME_SELECTED_WINDOW (f); - - while (1) - { - pwindow = swindow; - while (!NILP (pwindow)) - { - if (EQ (window, pwindow)) - break; - pwindow = XWINDOW (pwindow)->parent; - } - - /* If the window being deleted is not a parent of SWINDOW, - then SWINDOW is ok as the new selected window. */ - if (!EQ (window, pwindow)) - break; - /* Otherwise, try another window for SWINDOW. */ - swindow = Fnext_window (swindow, Qlambda, Qnil); - - /* If we get back to the frame's selected window, - it means there was no acceptable alternative, - so we cannot delete. */ - if (EQ (swindow, FRAME_SELECTED_WINDOW (f))) - error ("Cannot delete window"); - } - - /* If we need to change SWINDOW, do it. */ - if (! EQ (swindow, FRAME_SELECTED_WINDOW (f))) - { - /* If we're about to delete the selected window on the - selected frame, then we should use Fselect_window to select - the new window. On the other hand, if we're about to - delete the selected window on any other frame, we shouldn't do - anything but set the frame's selected_window slot. */ - if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) - Fselect_window (swindow, Qnil); - else - FRAME_SELECTED_WINDOW (f) = swindow; - } - } - - /* Now we know we can delete this one. */ - window_deletion_count++; - - tem = p->buffer; - /* tem is null for dummy parent windows - (which have inferiors but not any contents themselves) */ - if (!NILP (tem)) - { - unshow_buffer (p); - unchain_marker (XMARKER (p->pointm)); - unchain_marker (XMARKER (p->start)); - } - - /* Free window glyph matrices. It is sure that they are allocated - again when ADJUST_GLYPHS is called. Block input so that expose - events and other events that access glyph matrices are not - processed while we are changing them. */ - BLOCK_INPUT; - free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f))); - - tem = p->next; - if (!NILP (tem)) - XWINDOW (tem)->prev = p->prev; - - tem = p->prev; - if (!NILP (tem)) - XWINDOW (tem)->next = p->next; - - if (EQ (window, par->hchild)) - par->hchild = p->next; - if (EQ (window, par->vchild)) - par->vchild = p->next; - - /* Find one of our siblings to give our space to. */ - sib = p->prev; - if (NILP (sib)) - { - /* If p gives its space to its next sibling, that sibling needs - to have its top/left side pulled back to where p's is. - set_window_{height,width} will re-position the sibling's - children. */ - sib = p->next; - XWINDOW (sib)->top_line = p->top_line; - XWINDOW (sib)->left_col = p->left_col; - } - - /* Stretch that sibling. */ - if (!NILP (par->vchild)) - set_window_height (sib, - XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines), - 1); - if (!NILP (par->hchild)) - set_window_width (sib, - XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols), - 1); - - /* If parent now has only one child, - put the child into the parent's place. */ - tem = par->hchild; - if (NILP (tem)) - tem = par->vchild; - if (NILP (XWINDOW (tem)->next)) { - replace_window (parent, tem, 1); - par = XWINDOW (tem); - } - - /* Since we may be deleting combination windows, we must make sure that - not only p but all its children have been marked as deleted. */ - if (! NILP (p->hchild)) - delete_all_subwindows (p->hchild); - else if (! NILP (p->vchild)) - delete_all_subwindows (p->vchild); - - /* Mark this window as deleted. */ - p->buffer = p->hchild = p->vchild = Qnil; - - if (! NILP (par->parent)) - par = XWINDOW (par->parent); - - /* Check if we have a v/hchild with a v/hchild. In that case remove - one of them. */ - - if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild)) - { - p = XWINDOW (par->vchild); - par->vchild = p->vchild; - tem = p->vchild; - } - else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild)) - { - p = XWINDOW (par->hchild); - par->hchild = p->hchild; - tem = p->hchild; - } - else - p = 0; - - if (p) - { - while (! NILP (tem)) { - XWINDOW (tem)->parent = p->parent; - if (NILP (XWINDOW (tem)->next)) - break; - tem = XWINDOW (tem)->next; - } - if (! NILP (tem)) { - /* The next of the v/hchild we are removing is now the next of the - last child for the v/hchild: - Before v/hchild -> v/hchild -> next1 -> next2 - | - -> next3 - After: v/hchild -> next1 -> next2 -> next3 - */ - XWINDOW (tem)->next = p->next; - if (! NILP (p->next)) - XWINDOW (p->next)->prev = tem; - } - p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil; - } - - - /* Adjust glyph matrices. */ - adjust_glyphs (f); - UNBLOCK_INPUT; -} - - /*********************************************************************** Window List @@ -2645,7 +2408,6 @@ enum window_loop { WINDOW_LOOP_UNUSED, GET_BUFFER_WINDOW, /* Arg is buffer */ - DELETE_OTHER_WINDOWS, /* Arg is window not to delete */ DELETE_BUFFER_WINDOWS, /* Arg is buffer */ UNSHOW_BUFFER, /* Arg is buffer */ REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */ @@ -2729,11 +2491,6 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame } break; - case DELETE_OTHER_WINDOWS: - if (!EQ (window, obj)) - Fdelete_window (window); - break; - case DELETE_BUFFER_WINDOWS: if (EQ (w->buffer, obj)) { @@ -2769,7 +2526,7 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame Fset_buffer (w->buffer); } else - Fdelete_window (window); + call1 (Qdelete_window, window); } break; @@ -2804,7 +2561,7 @@ window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frame XSETWINDOW (window_to_delete, w); /* If this window is dedicated and not the only window in its frame, then kill it. */ - Fdelete_window (window_to_delete); + call1 (Qdelete_window, window_to_delete); } else { @@ -3128,68 +2885,6 @@ window-start value is reasonable when this function is called. */) } -DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows, - 0, 1, "", - doc: /* Make WINDOW (or the selected window) fill its frame. -Only the frame WINDOW is on is affected. -This function tries to reduce display jumps by keeping the text -previously visible in WINDOW in the same place on the frame. Doing this -depends on the value of (window-start WINDOW), so if calling this -function in a program gives strange scrolling, make sure the -window-start value is reasonable when this function is called. */) - (Lisp_Object window) -{ - struct window *w; - EMACS_INT startpos; - int top, new_top; - - if (NILP (window)) - window = selected_window; - else - CHECK_LIVE_WINDOW (window); - w = XWINDOW (window); - - startpos = marker_position (w->start); - top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))); - - if (MINI_WINDOW_P (w) && top > 0) - error ("Can't expand minibuffer to full frame"); - - window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w)); - - /* Try to minimize scrolling, by setting the window start to the point - will cause the text at the old window start to be at the same place - on the frame. But don't try to do this if the window start is - outside the visible portion (as might happen when the display is - not current, due to typeahead). */ - new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))); - if (new_top != top - && startpos >= BUF_BEGV (XBUFFER (w->buffer)) - && startpos <= BUF_ZV (XBUFFER (w->buffer))) - { - struct position pos; - struct buffer *obuf = current_buffer; - - Fset_buffer (w->buffer); - /* This computation used to temporarily move point, but that can - have unwanted side effects due to text properties. */ - pos = *vmotion (startpos, -top, w); - - set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos); - w->window_end_valid = Qnil; - w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE - || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt - : Qnil); - /* We need to do this, so that the window-scroll-functions - get called. */ - w->optional_new_start = Qt; - - set_buffer_internal (obuf); - } - - return Qnil; -} - DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on, 0, 2, "bDelete windows on (buffer): ", doc: /* Delete all windows showing BUFFER-OR-NAME. @@ -3271,8 +2966,6 @@ replace_buffer_in_all_windows (Lisp_Object buffer) window_loop (UNSHOW_BUFFER, buffer, 1, frame); } -/* Set the height of WINDOW and all its inferiors. */ - /* If *ROWS or *COLS are too small a size for FRAME, set them to the minimum allowable size. */ @@ -3296,243 +2989,6 @@ check_frame_size (FRAME_PTR frame, int *rows, int *cols) *cols = MIN_SAFE_WINDOW_WIDTH; } -/* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means - check if W's width can be changed, otherwise check W's height. - CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's - siblings, too. If none of the siblings is resizable, WINDOW isn't - either. */ - -static int -window_fixed_size_p (struct window *w, int width_p, int check_siblings_p) -{ - int fixed_p; - struct window *c; - - if (!NILP (w->hchild)) - { - c = XWINDOW (w->hchild); - - if (width_p) - { - /* A horizontal combination is fixed-width if all of if its - children are. */ - while (c && window_fixed_size_p (c, width_p, 0)) - c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; - fixed_p = c == NULL; - } - else - { - /* A horizontal combination is fixed-height if one of if its - children is. */ - while (c && !window_fixed_size_p (c, width_p, 0)) - c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; - fixed_p = c != NULL; - } - } - else if (!NILP (w->vchild)) - { - c = XWINDOW (w->vchild); - - if (width_p) - { - /* A vertical combination is fixed-width if one of if its - children is. */ - while (c && !window_fixed_size_p (c, width_p, 0)) - c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; - fixed_p = c != NULL; - } - else - { - /* A vertical combination is fixed-height if all of if its - children are. */ - while (c && window_fixed_size_p (c, width_p, 0)) - c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; - fixed_p = c == NULL; - } - } - else if (BUFFERP (w->buffer)) - { - struct buffer *old = current_buffer; - Lisp_Object val; - - current_buffer = XBUFFER (w->buffer); - val = find_symbol_value (Qwindow_size_fixed); - current_buffer = old; - - fixed_p = 0; - if (!EQ (val, Qunbound)) - { - fixed_p = !NILP (val); - - if (fixed_p - && ((EQ (val, Qheight) && width_p) - || (EQ (val, Qwidth) && !width_p))) - fixed_p = 0; - } - - /* Can't tell if this one is resizable without looking at - siblings. If all siblings are fixed-size this one is too. */ - if (!fixed_p && check_siblings_p && WINDOWP (w->parent)) - { - Lisp_Object child; - - for (child = w->prev; WINDOWP (child); child = XWINDOW (child)->prev) - if (!window_fixed_size_p (XWINDOW (child), width_p, 0)) - break; - - if (NILP (child)) - for (child = w->next; WINDOWP (child); child = XWINDOW (child)->next) - if (!window_fixed_size_p (XWINDOW (child), width_p, 0)) - break; - - if (NILP (child)) - fixed_p = 1; - } - } - else - fixed_p = 1; - - return fixed_p; -} - -/* Return minimum size of leaf window W. WIDTH_P non-zero means return - the minimum width of W, WIDTH_P zero means return the minimum height - of W. SAFE_P non-zero means ignore window-min-height|width but just - return values that won't crash Emacs and don't hide components like - fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the - minibuffer window, always return 1. */ - -static int -window_min_size_2 (struct window *w, int width_p, int safe_p) -{ - /* We should consider buffer-local values of window_min_height and - window_min_width here. */ - if (width_p) - { - int safe_size = (MIN_SAFE_WINDOW_WIDTH - + WINDOW_FRINGE_COLS (w) - + WINDOW_SCROLL_BAR_COLS (w)); - - return safe_p ? safe_size : max (window_min_width, safe_size); - } - else if (MINI_WINDOW_P (w)) - return 1; - else - { - int safe_size = (MIN_SAFE_WINDOW_HEIGHT - + ((BUFFERP (w->buffer) - && !NILP (BVAR (XBUFFER (w->buffer), mode_line_format))) - ? 1 : 0)); - - return safe_p ? safe_size : max (window_min_height, safe_size); - } -} - -/* Return minimum size of window W, not taking fixed-width windows into - account. WIDTH_P non-zero means return the minimum width, otherwise - return the minimum height. SAFE_P non-zero means ignore - window-min-height|width but just return values that won't crash Emacs - and don't hide components like fringes, scrollbars, or modelines. If - W is a combination window, compute the minimum size from the minimum - sizes of W's children. */ - -static int -window_min_size_1 (struct window *w, int width_p, int safe_p) -{ - struct window *c; - int size; - - if (!NILP (w->hchild)) - { - /* W is a horizontal combination. */ - c = XWINDOW (w->hchild); - size = 0; - - if (width_p) - { - /* The minimum width of a horizontal combination is the sum of - the minimum widths of its children. */ - while (c) - { - size += window_min_size_1 (c, 1, safe_p); - c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; - } - } - else - { - /* The minimum height of a horizontal combination is the - maximum of the minimum heights of its children. */ - while (c) - { - size = max (window_min_size_1 (c, 0, safe_p), size); - c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; - } - } - } - else if (!NILP (w->vchild)) - { - /* W is a vertical combination. */ - c = XWINDOW (w->vchild); - size = 0; - - if (width_p) - { - /* The minimum width of a vertical combination is the maximum - of the minimum widths of its children. */ - while (c) - { - size = max (window_min_size_1 (c, 1, safe_p), size); - c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; - } - } - else - { - /* The minimum height of a vertical combination is the sum of - the minimum height of its children. */ - while (c) - { - size += window_min_size_1 (c, 0, safe_p); - c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL; - } - } - } - else - /* W is a leaf window. */ - size = window_min_size_2 (w, width_p, safe_p); - - return size; -} - -/* Return the minimum size of window W, taking fixed-size windows into - account. WIDTH_P non-zero means return the minimum width, otherwise - return the minimum height. SAFE_P non-zero means ignore - window-min-height|width but just return values that won't crash Emacs - and don't hide components like fringes, scrollbars, or modelines. - IGNORE_FIXED_P non-zero means ignore if W is fixed-size. Set *FIXED - to 1 if W is fixed-size unless FIXED is null. */ - -static int -window_min_size (struct window *w, int width_p, int safe_p, int ignore_fixed_p, int *fixed) -{ - int size, fixed_p; - - if (ignore_fixed_p) - fixed_p = 0; - else - fixed_p = window_fixed_size_p (w, width_p, 1); - - if (fixed) - *fixed = fixed_p; - - if (fixed_p) - size = WINDOW_TOTAL_SIZE (w, width_p); - else - size = window_min_size_1 (w, width_p, safe_p); - - return size; -} - - /* Adjust the margins of window W if text area is too small. Return 1 if window width is ok after adjustment; 0 if window is still too narrow. */ @@ -3567,448 +3023,44 @@ adjust_window_margins (struct window *w) w->left_margin_cols = make_number (margin_cols); return 1; } + +int window_select_count; -/* Calculate new sizes for windows in the list FORWARD when their - compound size goes from TOTAL to SIZE. TOTAL must be greater than - SIZE. The number of windows in FORWARD is NCHILDREN, and the number - that can shrink is SHRINKABLE. Fixed-size windows may be shrunk if - and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means - shrink columns, otherwise shrink lines. - - SAFE_P zero means windows may be sized down to window-min-height - lines (window-min-window columns for WIDTH_P non-zero). SAFE_P - non-zero means windows may be sized down to their minimum safe sizes - taking into account the space needed to display modelines, fringes, - and scrollbars. - - This function returns an allocated array of new sizes that the caller - must free. A size -1 means the window is fixed and RESIZE_FIXED_P is - zero. A size zero means the window shall be deleted. Array index 0 - refers to the first window in FORWARD, 1 to the second, and so on. - - This function resizes windows proportionally to their size. It also - tries to preserve smaller windows by resizing larger windows before - resizing any window to zero. If resize_proportionally is non-nil for - a specific window, it will attempt to strictly resize that window - proportionally, even at the expense of deleting smaller windows. */ -static int * -shrink_windows (int total, int size, int nchildren, int shrinkable, - int resize_fixed_p, Lisp_Object forward, int width_p, int safe_p) -{ - int available_resize = 0; - int *new_sizes, *min_sizes; - struct window *c; - Lisp_Object child; - int smallest = total; - int total_removed = 0; - int total_shrink = total - size; - int i; +static Lisp_Object Fset_window_margins (Lisp_Object, Lisp_Object, Lisp_Object); +static Lisp_Object Fset_window_fringes (Lisp_Object, Lisp_Object, Lisp_Object, + Lisp_Object); +static Lisp_Object Fset_window_scroll_bars (Lisp_Object, Lisp_Object, + Lisp_Object, Lisp_Object); +static Lisp_Object Fset_window_vscroll (Lisp_Object, Lisp_Object, Lisp_Object); - new_sizes = xmalloc (sizeof (*new_sizes) * nchildren); - min_sizes = xmalloc (sizeof (*min_sizes) * nchildren); +static void +run_funs (Lisp_Object funs) +{ + for (; CONSP (funs); funs = XCDR (funs)) + if (!EQ (XCAR (funs), Qt)) + call0 (XCAR (funs)); +} - for (i = 0, child = forward; !NILP (child); child = c->next, ++i) - { - int child_size; +static Lisp_Object select_window_norecord (Lisp_Object window); +static Lisp_Object select_frame_norecord (Lisp_Object frame); - c = XWINDOW (child); - child_size = WINDOW_TOTAL_SIZE (c, width_p); +void +run_window_configuration_change_hook (struct frame *f) +{ + int count = SPECPDL_INDEX (); + Lisp_Object frame, global_wcch + = Fdefault_value (Qwindow_configuration_change_hook); + XSETFRAME (frame, f); - if (!resize_fixed_p && window_fixed_size_p (c, width_p, 0)) - new_sizes[i] = -1; - else - { - new_sizes[i] = child_size; - min_sizes[i] = window_min_size_1 (c, width_p, safe_p); - if (child_size > min_sizes[i] - && NILP (c->resize_proportionally)) - available_resize += child_size - min_sizes[i]; - } - } - /* We might need to shrink some windows to zero. Find the smallest - windows and set them to 0 until we can fulfil the new size. */ + if (NILP (Vrun_hooks)) + return; - while (shrinkable > 1 && size + available_resize < total) + /* Use the right buffer. Matters when running the local hooks. */ + if (current_buffer != XBUFFER (Fwindow_buffer (Qnil))) { - for (i = 0; i < nchildren; ++i) - if (new_sizes[i] > 0 && smallest > new_sizes[i]) - smallest = new_sizes[i]; - - for (i = 0; i < nchildren; ++i) - if (new_sizes[i] == smallest) - { - /* Resize this window down to zero. */ - new_sizes[i] = 0; - if (smallest > min_sizes[i]) - available_resize -= smallest - min_sizes[i]; - available_resize += smallest; - --shrinkable; - total_removed += smallest; - - /* We don't know what the smallest is now. */ - smallest = total; - - /* Out of for, just remove one window at the time and - check again if we have enough space. */ - break; - } - } - - /* Now, calculate the new sizes. Try to shrink each window - proportional to its size. */ - for (i = 0; i < nchildren; ++i) - { - if (new_sizes[i] > min_sizes[i]) - { - int to_shrink = total_shrink * new_sizes[i] / total; - - if (new_sizes[i] - to_shrink < min_sizes[i]) - to_shrink = new_sizes[i] - min_sizes[i]; - new_sizes[i] -= to_shrink; - total_removed += to_shrink; - } - } - - /* Any reminder due to rounding, we just subtract from windows - that are left and still can be shrunk. */ - while (total_shrink > total_removed) - { - int nonzero_sizes = 0; - - for (i = 0; i < nchildren; ++i) - if (new_sizes[i] > 0) - ++nonzero_sizes; - - for (i = 0; i < nchildren; ++i) - if (new_sizes[i] > min_sizes[i]) - { - --new_sizes[i]; - ++total_removed; - - /* Out of for, just shrink one window at the time and - check again if we have enough space. */ - break; - } - - /* Special case, only one window left. */ - if (nonzero_sizes == 1) - break; - } - - /* Any surplus due to rounding, we add to windows that are left. */ - while (total_shrink < total_removed) - { - for (i = 0; i < nchildren; ++i) - { - if (new_sizes[i] != 0 && total_shrink < total_removed) - { - ++new_sizes[i]; - --total_removed; - break; - } - } - } - - xfree (min_sizes); - - return new_sizes; -} - -/* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set - WINDOW's width. Resize WINDOW's children, if any, so that they keep - their proportionate size relative to WINDOW. - - If FIRST_ONLY is 1, change only the first of WINDOW's children when - they are in series. If LAST_ONLY is 1, change only the last of - WINDOW's children when they are in series. - - Propagate WINDOW's top or left edge position to children. Delete - windows that become too small unless NODELETE_P is 1. When - NODELETE_P equals 2 do not honor settings for window-min-height and - window-min-width when resizing windows but use safe defaults instead. - This should give better behavior when resizing frames. */ - -static void -size_window (Lisp_Object window, int size, int width_p, int nodelete_p, int first_only, int last_only) -{ - struct window *w = XWINDOW (window); - struct window *c; - Lisp_Object child, *forward, *sideward; - int old_size = WINDOW_TOTAL_SIZE (w, width_p); - - size = max (0, size); - - /* Delete WINDOW if it's too small. */ - if (nodelete_p != 1 && !NILP (w->parent) - && size < window_min_size_1 (w, width_p, nodelete_p == 2)) - { - delete_window (window); - return; - } - - /* Set redisplay hints. */ - w->last_modified = make_number (0); - w->last_overlay_modified = make_number (0); - windows_or_buffers_changed++; - FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1; - - if (width_p) - { - sideward = &w->vchild; - forward = &w->hchild; - w->total_cols = make_number (size); - adjust_window_margins (w); - } - else - { - sideward = &w->hchild; - forward = &w->vchild; - w->total_lines = make_number (size); - w->orig_total_lines = Qnil; - } - - if (!NILP (*sideward)) - { - /* We have a chain of parallel siblings whose size should all change. */ - for (child = *sideward; !NILP (child); child = c->next) - { - c = XWINDOW (child); - if (width_p) - c->left_col = w->left_col; - else - c->top_line = w->top_line; - size_window (child, size, width_p, nodelete_p, - first_only, last_only); - } - } - else if (!NILP (*forward) && last_only) - { - /* Change the last in a series of siblings. */ - Lisp_Object last_child; - int child_size; - - child = *forward; - do - { - c = XWINDOW (child); - last_child = child; - child = c->next; - } - while (!NILP (child)); - - child_size = WINDOW_TOTAL_SIZE (c, width_p); - size_window (last_child, size - old_size + child_size, - width_p, nodelete_p, first_only, last_only); - } - else if (!NILP (*forward) && first_only) - { - /* Change the first in a series of siblings. */ - int child_size; - - child = *forward; - c = XWINDOW (child); - - if (width_p) - c->left_col = w->left_col; - else - c->top_line = w->top_line; - - child_size = WINDOW_TOTAL_SIZE (c, width_p); - size_window (child, size - old_size + child_size, - width_p, nodelete_p, first_only, last_only); - } - else if (!NILP (*forward)) - { - int fixed_size, each IF_LINT (= 0), extra IF_LINT (= 0), n; - int resize_fixed_p, nfixed; - int last_pos, first_pos, nchildren, total; - int *new_sizes = NULL; - - /* Determine the fixed-size portion of this window, and the - number of child windows. */ - fixed_size = nchildren = nfixed = total = 0; - for (child = *forward; !NILP (child); child = c->next, ++nchildren) - { - int child_size; - - c = XWINDOW (child); - child_size = WINDOW_TOTAL_SIZE (c, width_p); - total += child_size; - - if (window_fixed_size_p (c, width_p, 0)) - { - fixed_size += child_size; - ++nfixed; - } - } - - /* If the new size is smaller than fixed_size, or if there - aren't any resizable windows, allow resizing fixed-size - windows. */ - resize_fixed_p = nfixed == nchildren || size < fixed_size; - - /* Compute how many lines/columns to add/remove to each child. The - value of extra takes care of rounding errors. */ - n = resize_fixed_p ? nchildren : nchildren - nfixed; - if (size < total && n > 1) - new_sizes = shrink_windows (total, size, nchildren, n, - resize_fixed_p, *forward, width_p, - nodelete_p == 2); - else - { - each = (size - total) / n; - extra = (size - total) - n * each; - } - - /* Compute new children heights and edge positions. */ - first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line); - last_pos = first_pos; - for (n = 0, child = *forward; !NILP (child); child = c->next, ++n) - { - int new_child_size, old_child_size; - - c = XWINDOW (child); - old_child_size = WINDOW_TOTAL_SIZE (c, width_p); - new_child_size = old_child_size; - - /* The top or left edge position of this child equals the - bottom or right edge of its predecessor. */ - if (width_p) - c->left_col = make_number (last_pos); - else - c->top_line = make_number (last_pos); - - /* If this child can be resized, do it. */ - if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0)) - { - new_child_size = - new_sizes ? new_sizes[n] : old_child_size + each + extra; - extra = 0; - } - - /* Set new size. Note that size_window also propagates - edge positions to children, so it's not a no-op if we - didn't change the child's size. */ - size_window (child, new_child_size, width_p, 1, - first_only, last_only); - - /* Remember the bottom/right edge position of this child; it - will be used to set the top/left edge of the next child. */ - last_pos += new_child_size; - } - - xfree (new_sizes); - - /* We should have covered the parent exactly with child windows. */ - xassert (size == last_pos - first_pos); - - /* Now delete any children that became too small. */ - if (nodelete_p != 1) - for (child = *forward; !NILP (child); child = c->next) - { - int child_size; - - c = XWINDOW (child); - child_size = WINDOW_TOTAL_SIZE (c, width_p); - size_window (child, child_size, width_p, nodelete_p, - first_only, last_only); - } - } -} - -/* Set WINDOW's height to HEIGHT, and recursively change the height of - WINDOW's children. NODELETE zero means windows that have become - smaller than window-min-height in the process may be deleted. - NODELETE 1 means never delete windows that become too small in the - process. (The caller should check later and do so if appropriate.) - NODELETE 2 means delete only windows that have become too small to be - displayed correctly. */ - -void -set_window_height (Lisp_Object window, int height, int nodelete) -{ - size_window (window, height, 0, nodelete, 0, 0); -} - -/* Set WINDOW's width to WIDTH, and recursively change the width of - WINDOW's children. NODELETE zero means windows that have become - smaller than window-min-width in the process may be deleted. - NODELETE 1 means never delete windows that become too small in the - process. (The caller should check later and do so if appropriate.) - NODELETE 2 means delete only windows that have become too small to be - displayed correctly. */ - -void -set_window_width (Lisp_Object window, int width, int nodelete) -{ - size_window (window, width, 1, nodelete, 0, 0); -} - -/* Change window heights in windows rooted in WINDOW by N lines. */ - -void -change_window_heights (Lisp_Object window, int n) -{ - struct window *w = XWINDOW (window); - - XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n); - XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n); - - if (INTEGERP (w->orig_top_line)) - XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n); - if (INTEGERP (w->orig_total_lines)) - XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n); - - /* Handle just the top child in a vertical split. */ - if (!NILP (w->vchild)) - change_window_heights (w->vchild, n); - - /* Adjust all children in a horizontal split. */ - for (window = w->hchild; !NILP (window); window = w->next) - { - w = XWINDOW (window); - change_window_heights (window, n); - } -} - - -int window_select_count; - -static Lisp_Object Fset_window_margins (Lisp_Object, Lisp_Object, Lisp_Object); -static Lisp_Object Fset_window_fringes (Lisp_Object, Lisp_Object, Lisp_Object, - Lisp_Object); -static Lisp_Object Fset_window_scroll_bars (Lisp_Object, Lisp_Object, - Lisp_Object, Lisp_Object); -static Lisp_Object Fset_window_vscroll (Lisp_Object, Lisp_Object, Lisp_Object); - -static void -run_funs (Lisp_Object funs) -{ - for (; CONSP (funs); funs = XCDR (funs)) - if (!EQ (XCAR (funs), Qt)) - call0 (XCAR (funs)); -} - -static Lisp_Object select_window_norecord (Lisp_Object window); -static Lisp_Object select_frame_norecord (Lisp_Object frame); - -void -run_window_configuration_change_hook (struct frame *f) -{ - int count = SPECPDL_INDEX (); - Lisp_Object frame, global_wcch - = Fdefault_value (Qwindow_configuration_change_hook); - XSETFRAME (frame, f); - - if (NILP (Vrun_hooks)) - return; - - /* Use the right buffer. Matters when running the local hooks. */ - if (current_buffer != XBUFFER (Fwindow_buffer (Qnil))) - { - record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); - Fset_buffer (Fwindow_buffer (Qnil)); - } + record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); + Fset_buffer (Fwindow_buffer (Qnil)); + } if (SELECTED_FRAME () != f) { @@ -4337,43 +3389,6 @@ DEFUN ("internal-temp-output-buffer-show", return Qnil; } -static void -make_dummy_parent (Lisp_Object window) -{ - Lisp_Object new; - register struct window *o, *p; - int i; - - o = XWINDOW (window); - p = allocate_window (); - for (i = 0; i < VECSIZE (struct window); ++i) - ((struct Lisp_Vector *) p)->contents[i] - = ((struct Lisp_Vector *)o)->contents[i]; - XSETWINDOW (new, p); - - ++sequence_number; - XSETFASTINT (p->sequence_number, sequence_number); - XSETFASTINT (p->clone_number, sequence_number); - - /* Put new into window structure in place of window */ - replace_window (window, new, 1); - - o->next = Qnil; - o->prev = Qnil; - o->vchild = Qnil; - o->hchild = Qnil; - o->parent = new; - - p->start = Qnil; - p->pointm = Qnil; - p->buffer = Qnil; - - p->splits = Qnil; - p->nest = Qnil; - p->window_parameters = Qnil; - -} - /* Make new window, have it replace WINDOW in window-tree, and make WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only horizontal child). */ @@ -4470,7 +3485,6 @@ make_window (void) w->pseudo_window_p = 0; w->frozen_window_start_p = 0; w->vscroll = 0; - w->resize_proportionally = Qnil; /* Reset window_list. */ Vwindow_list = Qnil; /* Return window. */ @@ -5046,1026 +4060,236 @@ when WINDOW is the only window on its frame. */) sibling = w->prev; s = XWINDOW (sibling); s->next = w->next; - if (!NILP (s->next)) - XWINDOW (s->next)->prev = sibling; - } - - if (resize_window_check (r, horflag) - && EQ (r->new_total, (horflag ? r->total_cols : r->total_lines))) - /* We can delete WINDOW now. */ - { - /* Block input. */ - BLOCK_INPUT; - resize_window_apply (p, horflag); - - windows_or_buffers_changed++; - Vwindow_list = Qnil; - FRAME_WINDOW_SIZES_CHANGED (f) = 1; - - w->next = Qnil; /* Don't delete w->next too. */ - free_window_matrices (w); - - if (!NILP (w->vchild)) - { - delete_all_subwindows (w->vchild); - w->vchild = Qnil; - } - else if (!NILP (w->hchild)) - { - delete_all_subwindows (w->hchild); - w->hchild = Qnil; - } - else if (!NILP (w->buffer)) - { - unshow_buffer (w); - unchain_marker (XMARKER (w->pointm)); - unchain_marker (XMARKER (w->start)); - w->buffer = Qnil; - } - - if (NILP (s->prev) && NILP (s->next)) - /* A matrjoshka where SIBLING has become the only child of - PARENT. */ - { - /* Put SIBLING into PARENT's place. */ - replace_window (parent, sibling, 0); - /* Have SIBLING inherit the following three slot values from - PARENT (the nest slot is not inherited). */ - s->normal_cols = p->normal_cols; - s->normal_lines = p->normal_lines; - s->splits = p->splits; - /* Mark PARENT as deleted. */ - p->vchild = p->hchild = Qnil; - /* Try to merge SIBLING into its new parent. */ - recombine_windows (sibling); - } - - adjust_glyphs (f); - - if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f))) - /* We deleted the frame's selected window. */ - { - /* Use the frame's first window as fallback ... */ - Lisp_Object new_selected_window = Fframe_first_window (frame); - /* ... but preferably use its most recently used window. */ - Lisp_Object mru_window; - - /* `get-mru-window' might fail for some reason so play it safe - - promote the first window _without recording it_ first. */ - if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) - Fselect_window (new_selected_window, Qt); - else - FRAME_SELECTED_WINDOW (f) = new_selected_window; - - UNBLOCK_INPUT; - - /* Now look whether `get-mru-window' gets us something. */ - mru_window = call1 (Qget_mru_window, frame); - if (WINDOW_LIVE_P (mru_window) - && EQ (XWINDOW (mru_window)->frame, frame)) - new_selected_window = mru_window; - - /* If all ended up well, we now promote the mru window. */ - if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) - Fselect_window (new_selected_window, Qnil); - else - FRAME_SELECTED_WINDOW (f) = new_selected_window; - } - else - UNBLOCK_INPUT; - - /* Must be run by the caller: - run_window_configuration_change_hook (f); */ - } - else - /* We failed: Relink WINDOW into window tree. */ - { - if (before_sibling) - { - s->prev = window; - if (horflag) - p->hchild = window; - else - p->vchild = window; - } - else - { - s->next = window; - if (!NILP (w->next)) - XWINDOW (w->next)->prev = window; - } - error ("Deletion failed"); - } - - return Qnil; -} - -DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "", - doc: /* Split WINDOW, putting SIZE lines in the first of the pair. -WINDOW defaults to selected one and SIZE to half its size. -If optional third arg HORIZONTAL is non-nil, split side by side and put -SIZE columns in the first of the pair. In that case, SIZE includes that -window's scroll bar, or the divider column to its right. -Interactively, all arguments are nil. -Returns the newly created window (which is the lower or rightmost one). -The upper or leftmost window is the original one, and remains selected -if it was selected before. - -See Info node `(elisp)Splitting Windows' for more details and examples. */) - (Lisp_Object window, Lisp_Object size, Lisp_Object horizontal) -{ - register Lisp_Object new; - register struct window *o, *p; - FRAME_PTR fo; - register int size_int; - - if (NILP (window)) - window = selected_window; - else - CHECK_LIVE_WINDOW (window); - - o = XWINDOW (window); - fo = XFRAME (WINDOW_FRAME (o)); - - if (NILP (size)) - { - if (!NILP (horizontal)) - /* Calculate the size of the left-hand window, by dividing - the usable space in columns by two. - We round up, since the left-hand window may include - a dividing line, while the right-hand may not. */ - size_int = (XFASTINT (o->total_cols) + 1) >> 1; - else - size_int = XFASTINT (o->total_lines) >> 1; - } - else - { - CHECK_NUMBER (size); - size_int = XINT (size); - } - - if (MINI_WINDOW_P (o)) - error ("Attempt to split minibuffer window"); - else if (window_fixed_size_p (o, !NILP (horizontal), 0)) - error ("Attempt to split fixed-size window"); - - if (NILP (horizontal)) - { - int window_safe_height = window_min_size_2 (o, 0, 0); - - if (size_int < window_safe_height) - error ("Window height %d too small (after splitting)", size_int); - if (size_int + window_safe_height > XFASTINT (o->total_lines)) - error ("Window height %d too small (after splitting)", - (int) (XFASTINT (o->total_lines) - size_int)); - if (NILP (o->parent) - || NILP (XWINDOW (o->parent)->vchild)) - { - make_dummy_parent (window); - new = o->parent; - XWINDOW (new)->vchild = window; - } - } - else - { - int window_safe_width = window_min_size_2 (o, 1, 0); - - if (size_int < window_safe_width) - error ("Window width %d too small (after splitting)", size_int); - if (size_int + window_safe_width > XFASTINT (o->total_cols)) - error ("Window width %d too small (after splitting)", - (int) (XFASTINT (o->total_cols) - size_int)); - if (NILP (o->parent) - || NILP (XWINDOW (o->parent)->hchild)) - { - make_dummy_parent (window); - new = o->parent; - XWINDOW (new)->hchild = window; - } - } - - /* Now we know that window's parent is a vertical combination - if we are dividing vertically, or a horizontal combination - if we are making side-by-side windows */ - - windows_or_buffers_changed++; - FRAME_WINDOW_SIZES_CHANGED (fo) = 1; - new = make_window (); - p = XWINDOW (new); - - p->frame = o->frame; - p->next = o->next; - if (!NILP (p->next)) - XWINDOW (p->next)->prev = new; - p->prev = window; - o->next = new; - p->parent = o->parent; - p->buffer = Qt; - p->window_end_valid = Qnil; - memset (&p->last_cursor, 0, sizeof p->last_cursor); - - /* Duplicate special geometry settings. */ - - p->left_margin_cols = o->left_margin_cols; - p->right_margin_cols = o->right_margin_cols; - p->left_fringe_width = o->left_fringe_width; - p->right_fringe_width = o->right_fringe_width; - p->fringes_outside_margins = o->fringes_outside_margins; - p->scroll_bar_width = o->scroll_bar_width; - p->vertical_scroll_bar_type = o->vertical_scroll_bar_type; - - /* Apportion the available frame space among the two new windows */ - - if (!NILP (horizontal)) - { - p->total_lines = o->total_lines; - p->top_line = o->top_line; - XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int); - XSETFASTINT (o->total_cols, size_int); - XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int); - adjust_window_margins (p); - adjust_window_margins (o); - } - else - { - p->left_col = o->left_col; - p->total_cols = o->total_cols; - XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int); - XSETFASTINT (o->total_lines, size_int); - XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int); - } - - /* Adjust glyph matrices. */ - adjust_glyphs (fo); - - Fset_window_buffer (new, o->buffer, Qt); - return new; -} - -DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0, - doc: /* Resize minibuffer window WINDOW. */) - (Lisp_Object window) -{ - struct window *w = XWINDOW (window); - struct window *r; - struct frame *f; - int height; - - CHECK_WINDOW (window); - f = XFRAME (w->frame); - - if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window)) - error ("Not a valid minibuffer window"); - else if (FRAME_MINIBUF_ONLY_P (f)) - error ("Cannot resize a minibuffer-only frame"); - - r = XWINDOW (FRAME_ROOT_WINDOW (f)); - height = XINT (r->total_lines) + XINT (w->total_lines); - if (resize_window_check (r, 0) - && XINT (w->new_total) > 0 - && height == XINT (r->new_total) + XINT (w->new_total)) - { - BLOCK_INPUT; - resize_window_apply (r, 0); - - w->total_lines = w->new_total; - XSETFASTINT (w->top_line, XINT (r->top_line) + XINT (r->total_lines)); - - windows_or_buffers_changed++; - FRAME_WINDOW_SIZES_CHANGED (f) = 1; - adjust_glyphs (f); - UNBLOCK_INPUT; - - run_window_configuration_change_hook (f); - return Qt; - } - else error ("Failed to resize minibuffer window"); -} - -DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p", - doc: /* Make selected window SIZE lines taller. -Interactively, if no argument is given, make the selected window one -line taller. If optional argument HORIZONTAL is non-nil, make selected -window wider by SIZE columns. If SIZE is negative, shrink the window by --SIZE lines or columns. Return nil. - -This function can delete windows if they get too small. The size of -fixed size windows is not altered by this function. */) - (Lisp_Object size, Lisp_Object horizontal) -{ - CHECK_NUMBER (size); - enlarge_window (selected_window, XINT (size), !NILP (horizontal)); - - run_window_configuration_change_hook (SELECTED_FRAME ()); - - return Qnil; -} - -DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p", - doc: /* Make selected window SIZE lines smaller. -Interactively, if no argument is given, make the selected window one -line smaller. If optional argument HORIZONTAL is non-nil, make the -window narrower by SIZE columns. If SIZE is negative, enlarge selected -window by -SIZE lines or columns. Return nil. - -This function can delete windows if they get too small. The size of -fixed size windows is not altered by this function. */) - (Lisp_Object size, Lisp_Object horizontal) -{ - CHECK_NUMBER (size); - enlarge_window (selected_window, -XINT (size), !NILP (horizontal)); - - run_window_configuration_change_hook (SELECTED_FRAME ()); - - return Qnil; -} - -static int -window_height (Lisp_Object window) -{ - register struct window *p = XWINDOW (window); - return WINDOW_TOTAL_LINES (p); -} - -static int -window_width (Lisp_Object window) -{ - register struct window *p = XWINDOW (window); - return WINDOW_TOTAL_COLS (p); -} - - -#define CURBEG(w) \ - *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line)) - -#define CURSIZE(w) \ - *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines)) - - -/* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it - horizontally; zero means do it vertically. - - Siblings of the selected window are resized to fulfill the size - request. If they become too small in the process, they may be - deleted. */ - -static void -enlarge_window (Lisp_Object window, int delta, int horiz_flag) -{ - Lisp_Object parent, next, prev; - struct window *p; - Lisp_Object *sizep; - int maximum; - int (*sizefun) (Lisp_Object) - = horiz_flag ? window_width : window_height; - void (*setsizefun) (Lisp_Object, int, int) - = (horiz_flag ? set_window_width : set_window_height); - - /* Give up if this window cannot be resized. */ - if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1)) - error ("Window is not resizable"); - - /* Find the parent of the selected window. */ - while (1) - { - p = XWINDOW (window); - parent = p->parent; - - if (NILP (parent)) - { - if (horiz_flag) - error ("No other window to side of this one"); - break; - } - - if (horiz_flag - ? !NILP (XWINDOW (parent)->hchild) - : !NILP (XWINDOW (parent)->vchild)) - break; - - window = parent; - } - - sizep = &CURSIZE (window); - - { - register int maxdelta; - - /* Compute the maximum size increment this window can have. */ - - maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep) - /* This is a main window followed by a minibuffer. */ - : !NILP (p->next) ? ((*sizefun) (p->next) - - window_min_size (XWINDOW (p->next), - horiz_flag, 0, 0, 0)) - /* This is a minibuffer following a main window. */ - : !NILP (p->prev) ? ((*sizefun) (p->prev) - - window_min_size (XWINDOW (p->prev), - horiz_flag, 0, 0, 0)) - /* This is a frame with only one window, a minibuffer-only - or a minibufferless frame. */ - : (delta = 0)); - - if (delta > maxdelta) - /* This case traps trying to make the minibuffer - the full frame, or make the only window aside from the - minibuffer the full frame. */ - delta = maxdelta; - } - - if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), - horiz_flag, 0, 0, 0)) - { - delete_window (window); - return; - } - - if (delta == 0) - return; - - /* Find the total we can get from other siblings without deleting them. */ - maximum = 0; - for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next) - maximum += (*sizefun) (next) - window_min_size (XWINDOW (next), - horiz_flag, 0, 0, 0); - for (prev = p->prev; WINDOWP (prev); prev = XWINDOW (prev)->prev) - maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev), - horiz_flag, 0, 0, 0); - - /* If we can get it all from them without deleting them, do so. */ - if (delta <= maximum) - { - Lisp_Object first_unaffected; - Lisp_Object first_affected; - int fixed_p; - - next = p->next; - prev = p->prev; - first_affected = window; - /* Look at one sibling at a time, - moving away from this window in both directions alternately, - and take as much as we can get without deleting that sibling. */ - while (delta != 0 - && (!NILP (next) || !NILP (prev))) - { - if (! NILP (next)) - { - int this_one = ((*sizefun) (next) - - window_min_size (XWINDOW (next), horiz_flag, - 0, 0, &fixed_p)); - if (!fixed_p) - { - if (this_one > delta) - this_one = delta; - - (*setsizefun) (next, (*sizefun) (next) - this_one, 0); - (*setsizefun) (window, XINT (*sizep) + this_one, 0); - - delta -= this_one; - } - - next = XWINDOW (next)->next; - } - - if (delta == 0) - break; - - if (! NILP (prev)) - { - int this_one = ((*sizefun) (prev) - - window_min_size (XWINDOW (prev), horiz_flag, - 0, 0, &fixed_p)); - if (!fixed_p) - { - if (this_one > delta) - this_one = delta; - - first_affected = prev; - - (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0); - (*setsizefun) (window, XINT (*sizep) + this_one, 0); - - delta -= this_one; - } - - prev = XWINDOW (prev)->prev; - } - } - - xassert (delta == 0); - - /* Now recalculate the edge positions of all the windows affected, - based on the new sizes. */ - first_unaffected = next; - prev = first_affected; - for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected); - prev = next, next = XWINDOW (next)->next) - { - XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev)); - /* This does not change size of NEXT, - but it propagates the new top edge to its children */ - (*setsizefun) (next, (*sizefun) (next), 0); - } - } - else - { - register int delta1; - register int opht = (*sizefun) (parent); - - if (opht <= XINT (*sizep) + delta) - { - /* If trying to grow this window to or beyond size of the parent, - just delete all the sibling windows. */ - Lisp_Object start, tem; - - start = XWINDOW (parent)->vchild; - if (NILP (start)) - start = XWINDOW (parent)->hchild; - - /* Delete any siblings that come after WINDOW. */ - tem = XWINDOW (window)->next; - while (! NILP (tem)) - { - Lisp_Object next1 = XWINDOW (tem)->next; - delete_window (tem); - tem = next1; - } - - /* Delete any siblings that come after WINDOW. - Note that if START is not WINDOW, then WINDOW still - has siblings, so WINDOW has not yet replaced its parent. */ - tem = start; - while (! EQ (tem, window)) - { - Lisp_Object next1 = XWINDOW (tem)->next; - delete_window (tem); - tem = next1; - } - } - else - { - /* Otherwise, make delta1 just right so that if we add - delta1 lines to this window and to the parent, and then - shrink the parent back to its original size, the new - proportional size of this window will increase by delta. - - The function size_window will compute the new height h' - of the window from delta1 as: - - e = delta1/n - x = delta1 - delta1/n * n for the 1st resizable child - h' = h + e + x - - where n is the number of children that can be resized. - We can ignore x by choosing a delta1 that is a multiple of - n. We want the height of this window to come out as - - h' = h + delta - - So, delta1 must be - - h + e = h + delta - delta1/n = delta - delta1 = n * delta. - - The number of children n equals the number of resizable - children of this window + 1 because we know window itself - is resizable (otherwise we would have signaled an error). - - This reasoning is not correct when other windows become too - small and shrink_windows refuses to delete them. Below we - use resize_proportionally to work around this problem. */ - - struct window *w = XWINDOW (window); - Lisp_Object s; - int n = 1; - - for (s = w->next; WINDOWP (s); s = XWINDOW (s)->next) - if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0)) - ++n; - for (s = w->prev; WINDOWP (s); s = XWINDOW (s)->prev) - if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0)) - ++n; - - delta1 = n * delta; - - /* Add delta1 lines or columns to this window, and to the parent, - keeping things consistent while not affecting siblings. */ - XSETINT (CURSIZE (parent), opht + delta1); - (*setsizefun) (window, XINT (*sizep) + delta1, 0); - - /* Squeeze out delta1 lines or columns from our parent, - shrinking this window and siblings proportionately. This - brings parent back to correct size. Delta1 was calculated - so this makes this window the desired size, taking it all - out of the siblings. - - Temporarily set resize_proportionally to Qt to assure that, - if necessary, shrink_windows deletes smaller windows rather - than shrink this window. */ - w->resize_proportionally = Qt; - (*setsizefun) (parent, opht, 0); - w->resize_proportionally = Qnil; - } + if (!NILP (s->next)) + XWINDOW (s->next)->prev = sibling; } - XSETFASTINT (p->last_modified, 0); - XSETFASTINT (p->last_overlay_modified, 0); - - /* Adjust glyph matrices. */ - adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window)))); -} - - -/* Adjust the size of WINDOW by DELTA, moving only its trailing edge. - HORIZ_FLAG nonzero means adjust the width, moving the right edge. - zero means adjust the height, moving the bottom edge. - - Following siblings of the selected window are resized to fulfill - the size request. If they become too small in the process, they - are not deleted; instead, we signal an error. */ - -static void -adjust_window_trailing_edge (Lisp_Object window, int delta, int horiz_flag) -{ - Lisp_Object parent, child; - struct window *p; - Lisp_Object old_config = Fcurrent_window_configuration (Qnil); - int delcount = window_deletion_count; - - CHECK_WINDOW (window); + if (resize_window_check (r, horflag) + && EQ (r->new_total, (horflag ? r->total_cols : r->total_lines))) + /* We can delete WINDOW now. */ + { + /* Block input. */ + BLOCK_INPUT; + resize_window_apply (p, horflag); - /* Give up if this window cannot be resized. */ - if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1)) - error ("Window is not resizable"); + windows_or_buffers_changed++; + Vwindow_list = Qnil; + FRAME_WINDOW_SIZES_CHANGED (f) = 1; - while (1) - { - Lisp_Object first_parallel = Qnil; + w->next = Qnil; /* Don't delete w->next too. */ + free_window_matrices (w); - if (NILP (window)) + if (!NILP (w->vchild)) { - /* This happens if WINDOW on the previous iteration was - at top level of the window tree. */ - Fset_window_configuration (old_config); - error ("Specified window edge is fixed"); + delete_all_subwindows (w->vchild); + w->vchild = Qnil; } - - p = XWINDOW (window); - parent = p->parent; - - /* See if this level has windows in parallel in the specified - direction. If so, set FIRST_PARALLEL to the first one. */ - if (horiz_flag) + else if (!NILP (w->hchild)) { - if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild)) - first_parallel = XWINDOW (parent)->vchild; - else if (NILP (parent) && !NILP (p->next)) - { - /* Handle the vertical chain of main window and minibuffer - which has no parent. */ - first_parallel = window; - while (! NILP (XWINDOW (first_parallel)->prev)) - first_parallel = XWINDOW (first_parallel)->prev; - } + delete_all_subwindows (w->hchild); + w->hchild = Qnil; } - else + else if (!NILP (w->buffer)) { - if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild)) - first_parallel = XWINDOW (parent)->hchild; + unshow_buffer (w); + unchain_marker (XMARKER (w->pointm)); + unchain_marker (XMARKER (w->start)); + w->buffer = Qnil; } - /* If this level's succession is in the desired dimension, - and this window is the last one, and there is no higher level, - its trailing edge is fixed. */ - if (NILP (XWINDOW (window)->next) && NILP (first_parallel) - && NILP (parent)) + if (NILP (s->prev) && NILP (s->next)) + /* A matrjoshka where SIBLING has become the only child of + PARENT. */ { - Fset_window_configuration (old_config); - error ("Specified window edge is fixed"); + /* Put SIBLING into PARENT's place. */ + replace_window (parent, sibling, 0); + /* Have SIBLING inherit the following three slot values from + PARENT (the nest slot is not inherited). */ + s->normal_cols = p->normal_cols; + s->normal_lines = p->normal_lines; + s->splits = p->splits; + /* Mark PARENT as deleted. */ + p->vchild = p->hchild = Qnil; + /* Try to merge SIBLING into its new parent. */ + recombine_windows (sibling); } - /* Don't make this window too small. */ - if (XINT (CURSIZE (window)) + delta - < window_min_size_2 (XWINDOW (window), horiz_flag, 0)) + adjust_glyphs (f); + + if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f))) + /* We deleted the frame's selected window. */ { - Fset_window_configuration (old_config); - error ("Cannot adjust window size as specified"); - } + /* Use the frame's first window as fallback ... */ + Lisp_Object new_selected_window = Fframe_first_window (frame); + /* ... but preferably use its most recently used window. */ + Lisp_Object mru_window; - /* Clear out some redisplay caches. */ - XSETFASTINT (p->last_modified, 0); - XSETFASTINT (p->last_overlay_modified, 0); + /* `get-mru-window' might fail for some reason so play it safe + - promote the first window _without recording it_ first. */ + if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) + Fselect_window (new_selected_window, Qt); + else + FRAME_SELECTED_WINDOW (f) = new_selected_window; - /* Adjust this window's edge. */ - XSETINT (CURSIZE (window), - XINT (CURSIZE (window)) + delta); + UNBLOCK_INPUT; - /* If this window has following siblings in the desired dimension, - make them smaller, and exit the loop. + /* Now look whether `get-mru-window' gets us something. */ + mru_window = call1 (Qget_mru_window, frame); + if (WINDOW_LIVE_P (mru_window) + && EQ (XWINDOW (mru_window)->frame, frame)) + new_selected_window = mru_window; - (If we reach the top of the tree and can never do this, - we will fail and report an error, above.) */ - if (NILP (first_parallel)) - { - if (!NILP (p->next)) - { - /* This may happen for the minibuffer. In that case - the window_deletion_count check below does not work. */ - if (XINT (CURSIZE (p->next)) - delta <= 0) - { - Fset_window_configuration (old_config); - error ("Cannot adjust window size as specified"); - } - - XSETINT (CURBEG (p->next), - XINT (CURBEG (p->next)) + delta); - size_window (p->next, XINT (CURSIZE (p->next)) - delta, - horiz_flag, 0, 1, 0); - break; - } + /* If all ended up well, we now promote the mru window. */ + if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) + Fselect_window (new_selected_window, Qnil); + else + FRAME_SELECTED_WINDOW (f) = new_selected_window; } else - /* Here we have a chain of parallel siblings, in the other dimension. - Change the size of the other siblings. */ - for (child = first_parallel; - ! NILP (child); - child = XWINDOW (child)->next) - if (! EQ (child, window)) - size_window (child, XINT (CURSIZE (child)) + delta, - horiz_flag, 0, 0, 1); + UNBLOCK_INPUT; - window = parent; + /* Must be run by the caller: + run_window_configuration_change_hook (f); */ } - - /* If we made a window so small it got deleted, - we failed. Report failure. */ - if (delcount != window_deletion_count) + else + /* We failed: Relink WINDOW into window tree. */ { - Fset_window_configuration (old_config); - error ("Cannot adjust window size as specified"); + if (before_sibling) + { + s->prev = window; + if (horflag) + p->hchild = window; + else + p->vchild = window; + } + else + { + s->next = window; + if (!NILP (w->next)) + XWINDOW (w->next)->prev = window; + } + error ("Deletion failed"); } - /* Adjust glyph matrices. */ - adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window)))); -} - -#undef CURBEG -#undef CURSIZE - -DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge, - Sadjust_window_trailing_edge, 3, 3, 0, - doc: /* Adjust the bottom or right edge of WINDOW by DELTA. -If HORIZONTAL is non-nil, that means adjust the width, moving the right edge. -Otherwise, adjust the height, moving the bottom edge. - -Following siblings of the selected window are resized to fulfill -the size request. If they become too small in the process, they -are not deleted; instead, we signal an error. */) - (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal) -{ - CHECK_NUMBER (delta); - if (NILP (window)) - window = selected_window; - adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal)); - - run_window_configuration_change_hook - (XFRAME (WINDOW_FRAME (XWINDOW (window)))); - return Qnil; } - - /*********************************************************************** Resizing Mini-Windows ***********************************************************************/ -static void shrink_window_lowest_first (struct window *, int); - -enum save_restore_action -{ - CHECK_ORIG_SIZES, - SAVE_ORIG_SIZES, - RESTORE_ORIG_SIZES -}; - -static int save_restore_orig_size (struct window *, - enum save_restore_action); - -/* Shrink windows rooted in window W to HEIGHT. Take the space needed - from lowest windows first. */ - -static void -shrink_window_lowest_first (struct window *w, int height) +/* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we + can. */ +void +grow_mini_window (struct window *w, int delta) { - struct window *c; - Lisp_Object child; - int old_height; - - xassert (!MINI_WINDOW_P (w)); - - /* Set redisplay hints. */ - XSETFASTINT (w->last_modified, 0); - XSETFASTINT (w->last_overlay_modified, 0); - windows_or_buffers_changed++; - FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1; + struct frame *f = XFRAME (w->frame); + struct window *r; + Lisp_Object root, value; - old_height = XFASTINT (w->total_lines); - XSETFASTINT (w->total_lines, height); + xassert (MINI_WINDOW_P (w)); + xassert (delta >= 0); - if (!NILP (w->hchild)) - { - for (child = w->hchild; !NILP (child); child = c->next) - { - c = XWINDOW (child); - c->top_line = w->top_line; - shrink_window_lowest_first (c, height); - } - } - else if (!NILP (w->vchild)) + root = FRAME_ROOT_WINDOW (f); + r = XWINDOW (root); + value = call2 (Qresize_root_window_vertically, root, make_number (- delta)); + if (INTEGERP (value) && resize_window_check (r, 0)) { - Lisp_Object last_child; - int delta = old_height - height; - int last_top; - - last_child = Qnil; - - /* Find the last child. We are taking space from lowest windows - first, so we iterate over children from the last child - backwards. */ - for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next) - last_child = child; - - /* Size children down to their safe heights. */ - for (child = last_child; delta && !NILP (child); child = c->prev) - { - int this_one; - - c = XWINDOW (child); - this_one = XFASTINT (c->total_lines) - window_min_size_1 (c, 0, 1); - - if (this_one > delta) - this_one = delta; + BLOCK_INPUT; + resize_window_apply (r, 0); - shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one); - delta -= this_one; - } + /* Grow the mini-window. */ + XSETFASTINT (w->top_line, XFASTINT (r->top_line) + XFASTINT (r->total_lines)); + XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - XINT (value)); + XSETFASTINT (w->last_modified, 0); + XSETFASTINT (w->last_overlay_modified, 0); - /* Compute new positions. */ - last_top = XINT (w->top_line); - for (child = w->vchild; !NILP (child); child = c->next) - { - c = XWINDOW (child); - c->top_line = make_number (last_top); - shrink_window_lowest_first (c, XFASTINT (c->total_lines)); - last_top += XFASTINT (c->total_lines); - } + adjust_glyphs (f); + UNBLOCK_INPUT; } } -/* Save, restore, or check positions and sizes in the window tree - rooted at W. ACTION says what to do. - - If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and - orig_total_lines members are valid for all windows in the window - tree. Value is non-zero if they are valid. - - If ACTION is SAVE_ORIG_SIZES, save members top and height in - orig_top_line and orig_total_lines for all windows in the tree. - - If ACTION is RESTORE_ORIG_SIZES, restore top and height from values - stored in orig_top_line and orig_total_lines for all windows. */ - -static int -save_restore_orig_size (struct window *w, enum save_restore_action action) +/* Shrink mini-window W. */ +void +shrink_mini_window (struct window *w) { - int success_p = 1; + struct frame *f = XFRAME (w->frame); + struct window *r; + Lisp_Object root, value; + EMACS_INT size; - while (w) - { - if (!NILP (w->hchild)) - { - if (!save_restore_orig_size (XWINDOW (w->hchild), action)) - success_p = 0; - } - else if (!NILP (w->vchild)) - { - if (!save_restore_orig_size (XWINDOW (w->vchild), action)) - success_p = 0; - } + xassert (MINI_WINDOW_P (w)); - switch (action) + size = XINT (w->total_lines); + if (size > 1) + { + root = FRAME_ROOT_WINDOW (f); + r = XWINDOW (root); + value = call2 (Qresize_root_window_vertically, + root, make_number (size - 1)); + if (INTEGERP (value) && resize_window_check (r, 0)) { - case CHECK_ORIG_SIZES: - if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines)) - return 0; - break; + BLOCK_INPUT; + resize_window_apply (r, 0); - case SAVE_ORIG_SIZES: - w->orig_top_line = w->top_line; - w->orig_total_lines = w->total_lines; - XSETFASTINT (w->last_modified, 0); - XSETFASTINT (w->last_overlay_modified, 0); - break; + /* Shrink the mini-window. */ + XSETFASTINT (w->top_line, XFASTINT (r->top_line) + XFASTINT (r->total_lines)); + XSETFASTINT (w->total_lines, 1); - case RESTORE_ORIG_SIZES: - xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines)); - w->top_line = w->orig_top_line; - w->total_lines = w->orig_total_lines; - w->orig_total_lines = w->orig_top_line = Qnil; - XSETFASTINT (w->last_modified, 0); - XSETFASTINT (w->last_overlay_modified, 0); - break; + XSETFASTINT (w->last_modified, 0); + XSETFASTINT (w->last_overlay_modified, 0); - default: - abort (); + adjust_glyphs (f); + UNBLOCK_INPUT; } - - w = NILP (w->next) ? NULL : XWINDOW (w->next); + /* If the above failed for whatever strange reason we must make a + one window frame here. The same routine will be needed when + shrinking the frame (and probably when making the initial + *scratch* window). For the moment leave things as they are. */ } - - return success_p; } - -/* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can - without deleting other windows. */ - -void -grow_mini_window (struct window *w, int delta) +DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0, + doc: /* Resize minibuffer window WINDOW. */) + (Lisp_Object window) { - struct frame *f = XFRAME (w->frame); - struct window *root; + struct window *w = XWINDOW (window); + struct window *r; + struct frame *f; + int height; - xassert (MINI_WINDOW_P (w)); - /* Commenting out the following assertion goes against the stated interface - of the function, but it currently does not seem to do anything useful. - See discussion of this issue in the thread for bug#4534. - xassert (delta >= 0); */ + CHECK_WINDOW (window); + f = XFRAME (w->frame); - /* Compute how much we can enlarge the mini-window without deleting - other windows. */ - root = XWINDOW (FRAME_ROOT_WINDOW (f)); - if (delta > 0) - { - int min_height = window_min_size (root, 0, 0, 0, 0); - if (XFASTINT (root->total_lines) - delta < min_height) - /* Note that the root window may already be smaller than - min_height. */ - delta = max (0, XFASTINT (root->total_lines) - min_height); - } + if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window)) + error ("Not a valid minibuffer window"); + else if (FRAME_MINIBUF_ONLY_P (f)) + error ("Cannot resize a minibuffer-only frame"); - if (delta) + r = XWINDOW (FRAME_ROOT_WINDOW (f)); + height = XINT (r->total_lines) + XINT (w->total_lines); + if (resize_window_check (r, 0) + && XINT (w->new_total) > 0 + && height == XINT (r->new_total) + XINT (w->new_total)) { - /* Save original window sizes and positions, if not already done. */ - if (!save_restore_orig_size (root, CHECK_ORIG_SIZES)) - save_restore_orig_size (root, SAVE_ORIG_SIZES); - - /* Shrink other windows. */ - shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta); + BLOCK_INPUT; + resize_window_apply (r, 0); - /* Grow the mini-window. */ - w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines)); - w->total_lines = make_number (XFASTINT (w->total_lines) + delta); - XSETFASTINT (w->last_modified, 0); - XSETFASTINT (w->last_overlay_modified, 0); + w->total_lines = w->new_total; + XSETFASTINT (w->top_line, XINT (r->top_line) + XINT (r->total_lines)); + windows_or_buffers_changed++; + FRAME_WINDOW_SIZES_CHANGED (f) = 1; adjust_glyphs (f); - } -} - - -/* Shrink mini-window W. If there is recorded info about window sizes - before a call to grow_mini_window, restore recorded window sizes. - Otherwise, if the mini-window is higher than 1 line, resize it to 1 - line. */ - -void -shrink_mini_window (struct window *w) -{ - struct frame *f = XFRAME (w->frame); - struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f)); + UNBLOCK_INPUT; - if (save_restore_orig_size (root, CHECK_ORIG_SIZES)) - { - save_restore_orig_size (root, RESTORE_ORIG_SIZES); - adjust_glyphs (f); - FRAME_WINDOW_SIZES_CHANGED (f) = 1; - windows_or_buffers_changed = 1; - } - else if (XFASTINT (w->total_lines) > 1) - { - /* Distribute the additional lines of the mini-window - among the other windows. */ - Lisp_Object window; - XSETWINDOW (window, w); - enlarge_window (window, 1 - XFASTINT (w->total_lines), 0); + run_window_configuration_change_hook (f); + return Qt; } + else error ("Failed to resize minibuffer window"); } - - + /* Mark window cursors off for all windows in the window tree rooted at W by setting their phys_cursor_on_p flag to zero. Called from @@ -7252,11 +5476,9 @@ struct saved_window Lisp_Object parent, prev; Lisp_Object start_at_line_beg; Lisp_Object display_table; - Lisp_Object orig_top_line, orig_total_lines; Lisp_Object left_margin_cols, right_margin_cols; Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins; - Lisp_Object scroll_bar_width, vertical_scroll_bar_type; - Lisp_Object dedicated, resize_proportionally; + Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated; Lisp_Object splits, nest, window_parameters; }; @@ -7476,8 +5698,6 @@ the return value is nil. Otherwise the value is t. */) w->hscroll = p->hscroll; w->min_hscroll = p->min_hscroll; w->display_table = p->display_table; - w->orig_top_line = p->orig_top_line; - w->orig_total_lines = p->orig_total_lines; w->left_margin_cols = p->left_margin_cols; w->right_margin_cols = p->right_margin_cols; w->left_fringe_width = p->left_fringe_width; @@ -7489,7 +5709,6 @@ the return value is nil. Otherwise the value is t. */) w->splits = p->splits; w->nest = p->nest; w->window_parameters = p->window_parameters; - w->resize_proportionally = p->resize_proportionally; XSETFASTINT (w->last_modified, 0); XSETFASTINT (w->last_overlay_modified, 0); @@ -7618,6 +5837,7 @@ the return value is nil. Otherwise the value is t. */) return (FRAME_LIVE_P (f) ? Qt : Qnil); } + /* Delete all subwindows reachable via the next, vchild, and hchild slots of WINDOW. */ void @@ -7670,7 +5890,6 @@ count_windows (register struct window *window) /* Fill vector FLAT with leaf windows under W, starting at index I. Value is last index + 1. */ - static int get_leaf_windows (struct window *w, struct window **flat, int i) { @@ -7693,7 +5912,6 @@ get_leaf_windows (struct window *w, struct window **flat, int i) /* Return a pointer to the glyph W's physical cursor is on. Value is null if W's current matrix is invalid, so that no meaningfull glyph can be returned. */ - struct glyph * get_phys_cursor_glyph (struct window *w) { @@ -7738,8 +5956,6 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) p->hscroll = w->hscroll; p->min_hscroll = w->min_hscroll; p->display_table = w->display_table; - p->orig_top_line = w->orig_top_line; - p->orig_total_lines = w->orig_total_lines; p->left_margin_cols = w->left_margin_cols; p->right_margin_cols = w->right_margin_cols; p->left_fringe_width = w->left_fringe_width; @@ -7750,7 +5966,6 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i) p->dedicated = w->dedicated; p->splits = w->splits; p->nest = w->nest; - p->resize_proportionally = w->resize_proportionally; p->window_parameters = w->window_parameters; if (!NILP (w->buffer)) { @@ -8444,10 +6659,6 @@ syms_of_window (void) Fput (Qscroll_up, Qscroll_command, Qt); Fput (Qscroll_down, Qscroll_command, Qt); - Qwindow_size_fixed = intern_c_string ("window-size-fixed"); - staticpro (&Qwindow_size_fixed); - Fset (Qwindow_size_fixed, Qnil); - staticpro (&Qwindow_configuration_change_hook); Qwindow_configuration_change_hook = intern_c_string ("window-configuration-change-hook"); @@ -8540,24 +6751,6 @@ is displayed in the `mode-line' face. */); doc: /* *Number of lines of continuity when scrolling by screenfuls. */); next_screen_context_lines = 2; - DEFVAR_INT ("window-min-height", window_min_height, - doc: /* Allow deleting windows less than this tall. -The value is measured in line units. If a window wants a modeline it -is counted as one line. - -Emacs honors settings of this variable when enlarging or shrinking -windows vertically. A value less than 1 is invalid. */); - window_min_height = 4; - - DEFVAR_INT ("window-min-width", window_min_width, - doc: /* Allow deleting windows less than this wide. -The value is measured in characters and includes any fringes or -the scrollbar. - -Emacs honors settings of this variable when enlarging or shrinking -windows horizontally. A value less than 2 is invalid. */); - window_min_width = 10; - DEFVAR_LISP ("scroll-preserve-screen-position", Vscroll_preserve_screen_position, doc: /* *Controls if scroll commands move point to keep its screen position unchanged. @@ -8684,10 +6877,8 @@ function `window-nest' and altered by the function `set-window-nest'. */); defsubr (&Sprevious_window); defsubr (&Sother_window); defsubr (&Sget_buffer_window); - defsubr (&Sdelete_other_windows); defsubr (&Sdelete_windows_on); defsubr (&Sreplace_buffer_in_windows); - defsubr (&Sdelete_window); defsubr (&Sdelete_other_windows_internal); defsubr (&Sdelete_window_internal); defsubr (&Sresize_mini_window_internal); @@ -8697,11 +6888,7 @@ function `window-nest' and altered by the function `set-window-nest'. */); defsubr (&Sselect_window); defsubr (&Sforce_window_update); defsubr (&Stemp_output_buffer_show); - defsubr (&Ssplit_window); defsubr (&Ssplit_window_internal); - defsubr (&Senlarge_window); - defsubr (&Sshrink_window); - defsubr (&Sadjust_window_trailing_edge); defsubr (&Sscroll_up); defsubr (&Sscroll_down); defsubr (&Sscroll_left); @@ -8740,11 +6927,7 @@ function `window-nest' and altered by the function `set-window-nest'. */); void keys_of_window (void) { - initial_define_key (control_x_map, '1', "delete-other-windows"); - initial_define_key (control_x_map, '2', "split-window"); - initial_define_key (control_x_map, '0', "delete-window"); initial_define_key (control_x_map, 'o', "other-window"); - initial_define_key (control_x_map, '^', "enlarge-window"); initial_define_key (control_x_map, '<', "scroll-left"); initial_define_key (control_x_map, '>', "scroll-right"); diff --git a/src/xdisp.c b/src/xdisp.c index 02467c7bedd..65f6ddd3889 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -27115,31 +27115,27 @@ Its value should be an ASCII acronym string, `hex-code', `empty-box', or void init_xdisp (void) { - Lisp_Object root_window; - struct window *mini_w; - current_header_line_height = current_mode_line_height = -1; CHARPOS (this_line_start_pos) = 0; - mini_w = XWINDOW (minibuf_window); - root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w))); - echo_area_window = minibuf_window; - if (!noninteractive) { - struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window))); + struct window *m = XWINDOW (minibuf_window); + Lisp_Object frame = m->frame; + struct frame *f = XFRAME (frame); + Lisp_Object root = FRAME_ROOT_WINDOW (f); + struct window *r = XWINDOW (root); int i; - XWINDOW (root_window)->top_line = make_number (FRAME_TOP_MARGIN (f)); - set_window_height (root_window, - FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f), - 0); - mini_w->top_line = make_number (FRAME_LINES (f) - 1); - set_window_height (minibuf_window, 1, 0); + echo_area_window = minibuf_window; - XWINDOW (root_window)->total_cols = make_number (FRAME_COLS (f)); - mini_w->total_cols = make_number (FRAME_COLS (f)); + XSETFASTINT (r->top_line, FRAME_TOP_MARGIN (f)); + XSETFASTINT (r->total_lines, FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f)); + XSETFASTINT (r->total_cols, FRAME_COLS (f)); + XSETFASTINT (m->top_line, FRAME_LINES (f) - 1); + XSETFASTINT (m->total_lines, 1); + XSETFASTINT (m->total_cols, FRAME_COLS (f)); scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs; scratch_glyph_row.glyphs[TEXT_AREA + 1] diff --git a/src/xfns.c b/src/xfns.c index c307cc345e3..3d74ead330a 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1227,7 +1227,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) } #else /* not USE_X_TOOLKIT && not USE_GTK */ FRAME_MENU_BAR_LINES (f) = nlines; - change_window_heights (f->root_window, nlines - olines); + resize_frame_windows (f, FRAME_LINES (f), 0); /* If the menu bar height gets changed, the internal border below the top margin has to be cleared. Also, if the menu bar gets @@ -1266,6 +1266,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) } #endif /* not USE_X_TOOLKIT && not USE_GTK */ adjust_glyphs (f); + run_window_configuration_change_hook (f); } @@ -1326,7 +1327,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) } FRAME_TOOL_BAR_LINES (f) = nlines; - change_window_heights (root_window, delta); + resize_frame_windows (f, FRAME_LINES (f), 0); adjust_glyphs (f); /* We also have to make sure that the internal border at the top of @@ -1362,6 +1363,9 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) if (WINDOWP (f->tool_bar_window)) clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix); } + + run_window_configuration_change_hook (f); + } -- 2.39.2