Mercurial > emacs
diff src/window.c @ 90261:7beb78bc1f8e
Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-97
Merge from emacs--cvs-trunk--0
Patches applied:
* emacs--cvs-trunk--0 (patch 616-696)
- Add lisp/mh-e/.arch-inventory
- Update from CVS
- Merge from gnus--rel--5.10
- Update from CVS: lisp/smerge-mode.el: Add 'tools' to file keywords.
- lisp/gnus/ChangeLog: Remove duplicate entry
* gnus--rel--5.10 (patch 147-181)
- Update from CVS
- Merge from emacs--cvs-trunk--0
- Update from CVS: lisp/mml.el (mml-preview): Doc fix.
- Update from CVS: texi/message.texi: Fix default values.
- Update from CVS: texi/gnus.texi (RSS): Addition.
author | Miles Bader <miles@gnu.org> |
---|---|
date | Mon, 16 Jan 2006 08:37:27 +0000 |
parents | 0ca0d9181b5e 97a5b7b69235 |
children | 7432ca837c8d |
line wrap: on
line diff
--- a/src/window.c Mon Jan 16 06:59:21 2006 +0000 +++ b/src/window.c Mon Jan 16 08:37:27 2006 +0000 @@ -65,7 +65,7 @@ static void size_window P_ ((Lisp_Object, int, int, int)); static int freeze_window_start P_ ((struct window *, void *)); static int window_fixed_size_p P_ ((struct window *, int, int)); -static void enlarge_window P_ ((Lisp_Object, int, int, int)); +static void enlarge_window P_ ((Lisp_Object, int, int)); static Lisp_Object window_list P_ ((void)); static int add_window_to_list P_ ((struct window *, void *)); static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object, @@ -210,6 +210,10 @@ Lisp_Object Vscroll_preserve_screen_position; +/* Incremented by 1 whenever a window is deleted. */ + +int window_deletion_count; + #if 0 /* This isn't used anywhere. */ /* Nonzero means we can split a frame even if it is "unsplittable". */ static int inhibit_frame_unsplittable; @@ -1333,7 +1337,7 @@ CHECK_WINDOW (window); p = XWINDOW (window); - /* It's okay to delete an already-deleted window. */ + /* It's a no-op to delete an already-deleted window. */ if (NILP (p->buffer) && NILP (p->hchild) && NILP (p->vchild)) @@ -1397,6 +1401,9 @@ } } + /* 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) */ @@ -1962,7 +1969,7 @@ GCPRO1 (windows); best_window = Qnil; - for (; CONSP (windows); windows = CDR (windows)) + for (; CONSP (windows); windows = XCDR (windows)) { struct window *w; @@ -1996,11 +2003,13 @@ break; case GET_LRU_WINDOW: - /* t as arg means consider only full-width windows */ - if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w)) - break; - /* Ignore dedicated windows and minibuffers. */ - if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt)) + /* `obj' is an integer encoding a bitvector. + `obj & 1' means consider only full-width windows. + `obj & 2' means consider also dedicated windows. */ + if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w)) + || (!(XINT (obj) & 2) && EQ (w->dedicated, Qt)) + /* Minibuffer windows are always ignored. */ + || MINI_WINDOW_P (w)) break; if (NILP (best_window) || (XFASTINT (XWINDOW (best_window)->use_time) @@ -2051,9 +2060,9 @@ break; case GET_LARGEST_WINDOW: - { + { /* nil `obj' means to ignore dedicated windows. */ /* Ignore dedicated windows and minibuffers. */ - if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt)) + if (MINI_WINDOW_P (w) || (NILP (obj) && EQ (w->dedicated, Qt))) break; if (NILP (best_window)) @@ -2147,43 +2156,47 @@ window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt); } -DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0, +DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0, doc: /* Return the window least recently selected or used for display. Return a full-width window if possible. A minibuffer window is never a candidate. -A dedicated window is never a candidate, so if all windows are dedicated, -the value is nil. +A dedicated window is never a candidate, unless DEDICATED is non-nil, + so if all windows are dedicated, the value is nil. If optional argument FRAME is `visible', search all visible frames. If FRAME is 0, search all visible and iconified frames. If FRAME is t, search all frames. If FRAME is nil, search only the selected frame. If FRAME is a frame, search only that frame. */) - (frame) - Lisp_Object frame; + (frame, dedicated) + Lisp_Object frame, dedicated; { register Lisp_Object w; /* First try for a window that is full-width */ - w = window_loop (GET_LRU_WINDOW, Qt, 0, frame); + w = window_loop (GET_LRU_WINDOW, + NILP (dedicated) ? make_number (1) : make_number (3), + 0, frame); if (!NILP (w) && !EQ (w, selected_window)) return w; /* If none of them, try the rest */ - return window_loop (GET_LRU_WINDOW, Qnil, 0, frame); -} - -DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0, + return window_loop (GET_LRU_WINDOW, + NILP (dedicated) ? make_number (0) : make_number (2), + 0, frame); +} + +DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0, doc: /* Return the largest window in area. A minibuffer window is never a candidate. -A dedicated window is never a candidate, so if all windows are dedicated, -the value is nil. +A dedicated window is never a candidate unless DEDICATED is non-nil, + so if all windows are dedicated, the value is nil. If optional argument FRAME is `visible', search all visible frames. If FRAME is 0, search all visible and iconified frames. If FRAME is t, search all frames. If FRAME is nil, search only the selected frame. If FRAME is a frame, search only that frame. */) - (frame) - Lisp_Object frame; -{ - return window_loop (GET_LARGEST_WINDOW, Qnil, 0, + (frame, dedicated) + Lisp_Object frame, dedicated; +{ + return window_loop (GET_LARGEST_WINDOW, dedicated, 0, frame); } @@ -3503,15 +3516,17 @@ if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame)) { /* Try visible frames first. */ - window = Fget_largest_window (Qvisible); + window = Fget_largest_window (Qvisible, Qt); /* If that didn't work, try iconified frames. */ if (NILP (window)) - window = Fget_largest_window (make_number (0)); + window = Fget_largest_window (make_number (0), Qt); +#if 0 /* Don't try windows on other displays. */ if (NILP (window)) - window = Fget_largest_window (Qt); + window = Fget_largest_window (Qt, Qt); +#endif } else - window = Fget_largest_window (frames); + window = Fget_largest_window (frames, Qt); /* If we got a tall enough full-width window that can be split, split it. */ @@ -3524,7 +3539,7 @@ { Lisp_Object upper, other; - window = Fget_lru_window (frames); + window = Fget_lru_window (frames, Qt); /* If the LRU window is selected, and big enough, and can be split, split it. */ if (!NILP (window) @@ -3533,23 +3548,27 @@ || EQ (XWINDOW (window)->parent, Qnil)) && window_height (window) >= window_min_height << 1) window = Fsplit_window (window, Qnil, Qnil); + else + window = Fget_lru_window (frames, Qnil); /* If Fget_lru_window returned nil, try other approaches. */ /* Try visible frames first. */ if (NILP (window)) window = Fget_buffer_window (buffer, Qvisible); if (NILP (window)) - window = Fget_largest_window (Qvisible); + window = Fget_largest_window (Qvisible, Qnil); /* If that didn't work, try iconified frames. */ if (NILP (window)) window = Fget_buffer_window (buffer, make_number (0)); if (NILP (window)) - window = Fget_largest_window (make_number (0)); - /* Try invisible frames. */ + window = Fget_largest_window (make_number (0), Qnil); + +#if 0 /* Don't try frames on other displays. */ if (NILP (window)) window = Fget_buffer_window (buffer, Qt); if (NILP (window)) - window = Fget_largest_window (Qt); + window = Fget_largest_window (Qt, Qnil); +#endif /* As a last resort, make a new frame. */ if (NILP (window)) window = Fframe_selected_window (call0 (Vpop_up_frame_function)); @@ -3571,12 +3590,12 @@ + XFASTINT (XWINDOW (window)->total_lines)); enlarge_window (upper, total / 2 - XFASTINT (XWINDOW (upper)->total_lines), - 0, 0); + 0); } } } else - window = Fget_lru_window (Qnil); + window = Fget_lru_window (Qnil, Qnil); Fset_window_buffer (window, buffer, Qnil); return display_buffer_1 (window); @@ -3648,7 +3667,7 @@ #endif set_buffer_internal (old); - if (!EQ (Vtemp_buffer_show_function, Qnil)) + if (!NILP (Vtemp_buffer_show_function)) call1 (Vtemp_buffer_show_function, buf); else { @@ -3862,20 +3881,18 @@ return new; } -DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 3, "p", +DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p", doc: /* Make current window ARG lines bigger. From program, optional second arg non-nil means grow sideways ARG columns. Interactively, if an argument is not given, make the window one line bigger. - -Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size -of the siblings above or to the left of the selected window. Only -siblings to the right or below are changed. */) - (arg, side, preserve_before) - register Lisp_Object arg, side, preserve_before; +If HORIZONTAL is non-nil, enlarge horizontally instead of vertically. +This function can delete windows, even the second window, if they get +too small. */) + (arg, horizontal) + Lisp_Object arg, horizontal; { CHECK_NUMBER (arg); - enlarge_window (selected_window, XINT (arg), !NILP (side), - !NILP (preserve_before)); + enlarge_window (selected_window, XINT (arg), !NILP (horizontal)); if (! NILP (Vwindow_configuration_change_hook)) call1 (Vrun_hooks, Qwindow_configuration_change_hook); @@ -3883,20 +3900,16 @@ return Qnil; } -DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 3, "p", +DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p", doc: /* Make current window ARG lines smaller. From program, optional second arg non-nil means shrink sideways arg columns. -Interactively, if an argument is not given, make the window one line smaller. - -Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size -of the siblings above or to the left of the selected window. Only +Interactively, if an argument is not given, make the window one line smaller. Only siblings to the right or below are changed. */) - (arg, side, preserve_before) - register Lisp_Object arg, side, preserve_before; + (arg, side) + Lisp_Object arg, side; { CHECK_NUMBER (arg); - enlarge_window (selected_window, -XINT (arg), !NILP (side), - !NILP (preserve_before)); + enlarge_window (selected_window, -XINT (arg), !NILP (side)); if (! NILP (Vwindow_configuration_change_hook)) call1 (Vrun_hooks, Qwindow_configuration_change_hook); @@ -3922,40 +3935,40 @@ #define CURBEG(w) \ - *(widthflag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line)) + *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line)) #define CURSIZE(w) \ - *(widthflag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines)) - - -/* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means - increase its width. Siblings of the selected window are resized to - fulfill the size request. If they become too small in the process, - they will be deleted. - - If PRESERVE_BEFORE is nonzero, that means don't alter - the siblings to the left or above WINDOW. */ + *(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 will be + deleted. */ static void -enlarge_window (window, delta, widthflag, preserve_before) +enlarge_window (window, delta, horiz_flag) Lisp_Object window; - int delta, widthflag, preserve_before; + int delta, horiz_flag; { Lisp_Object parent, next, prev; struct window *p; Lisp_Object *sizep; int maximum; int (*sizefun) P_ ((Lisp_Object)) - = widthflag ? window_width : window_height; + = horiz_flag ? window_width : window_height; void (*setsizefun) P_ ((Lisp_Object, int, int)) - = (widthflag ? set_window_width : set_window_height); + = (horiz_flag ? set_window_width : set_window_height); /* Check values of window_min_width and window_min_height for validity. */ check_min_window_sizes (); /* Give up if this window cannot be resized. */ - if (window_fixed_size_p (XWINDOW (window), widthflag, 1)) + if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1)) error ("Window is not resizable"); /* Find the parent of the selected window. */ @@ -3966,12 +3979,12 @@ if (NILP (parent)) { - if (widthflag) + if (horiz_flag) error ("No other window to side of this one"); break; } - if (widthflag + if (horiz_flag ? !NILP (XWINDOW (parent)->hchild) : !NILP (XWINDOW (parent)->vchild)) break; @@ -3986,33 +3999,18 @@ /* Compute the maximum size increment this window can have. */ - if (preserve_before) - { - if (!NILP (parent)) - { - maxdelta = (*sizefun) (parent) - XINT (*sizep); - /* Subtract size of siblings before, since we can't take that. */ - maxdelta -= XINT (CURBEG (window)) - XINT (CURBEG (parent)); - } - else - maxdelta = (!NILP (p->next) ? ((*sizefun) (p->next) - - window_min_size (XWINDOW (p->next), - widthflag, 0, 0)) - : (delta = 0)); - } - else - 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), - widthflag, 0, 0)) - /* This is a minibuffer following a main window. */ - : !NILP (p->prev) ? ((*sizefun) (p->prev) - - window_min_size (XWINDOW (p->prev), - widthflag, 0, 0)) - /* This is a frame with only one window, a minibuffer-only - or a minibufferless frame. */ - : (delta = 0)); + 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)) + /* This is a minibuffer following a main window. */ + : !NILP (p->prev) ? ((*sizefun) (p->prev) + - window_min_size (XWINDOW (p->prev), + horiz_flag, 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 @@ -4021,7 +4019,7 @@ delta = maxdelta; } - if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0)) + if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), horiz_flag, 0, 0)) { delete_window (window); return; @@ -4034,11 +4032,10 @@ maximum = 0; for (next = p->next; ! NILP (next); next = XWINDOW (next)->next) maximum += (*sizefun) (next) - window_min_size (XWINDOW (next), - widthflag, 0, 0); - if (! preserve_before) - for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev) - maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev), - widthflag, 0, 0); + horiz_flag, 0, 0); + for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev) + maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev), + horiz_flag, 0, 0); /* If we can get it all from them without deleting them, do so. */ if (delta <= maximum) @@ -4054,13 +4051,13 @@ 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) || (!preserve_before && !NILP (prev)))) + && (!NILP (next) || !NILP (prev))) { if (! NILP (next)) { int this_one = ((*sizefun) (next) - window_min_size (XWINDOW (next), - widthflag, 0, &fixed_p)); + horiz_flag, 0, &fixed_p)); if (!fixed_p) { if (this_one > delta) @@ -4078,11 +4075,11 @@ if (delta == 0) break; - if (!preserve_before && ! NILP (prev)) + if (! NILP (prev)) { int this_one = ((*sizefun) (prev) - window_min_size (XWINDOW (prev), - widthflag, 0, &fixed_p)); + horiz_flag, 0, &fixed_p)); if (!fixed_p) { if (this_one > delta) @@ -4185,10 +4182,10 @@ int n = 1; for (s = w->next; !NILP (s); s = XWINDOW (s)->next) - if (!window_fixed_size_p (XWINDOW (s), widthflag, 0)) + if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0)) ++n; for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev) - if (!window_fixed_size_p (XWINDOW (s), widthflag, 0)) + if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0)) ++n; delta1 = n * delta; @@ -4215,9 +4212,136 @@ 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 (window, delta, horiz_flag) + Lisp_Object window; + int delta, horiz_flag; +{ + Lisp_Object parent, child; + struct window *p; + Lisp_Object old_config = Fcurrent_window_configuration (Qnil); + int delcount = window_deletion_count; + + /* Check values of window_min_width and window_min_height for + validity. */ + check_min_window_sizes (); + + if (NILP (window)) + window = Fselected_window (); + + CHECK_WINDOW (window); + + /* Give up if this window cannot be resized. */ + if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1)) + error ("Window is not resizable"); + + while (1) + { + p = XWINDOW (window); + parent = p->parent; + + /* Make sure there is a following window. */ + if (NILP (parent) + && (horiz_flag ? 1 + : NILP (XWINDOW (window)->next))) + { + Fset_window_configuration (old_config); + error ("No other window following this one"); + } + + /* Don't make this window too small. */ + if (XINT (CURSIZE (window)) + delta + < (horiz_flag ? window_min_width : window_min_height)) + { + Fset_window_configuration (old_config); + error ("Cannot adjust window size as specified"); + } + + /* Clear out some redisplay caches. */ + XSETFASTINT (p->last_modified, 0); + XSETFASTINT (p->last_overlay_modified, 0); + + /* Adjust this window's edge. */ + XSETINT (CURSIZE (window), + XINT (CURSIZE (window)) + delta); + + /* If this window has following siblings in the desired dimension, + make them smaller. + (If we reach the top of the tree and can never do this, + we will fail and report an error, above.) */ + if (horiz_flag + ? !NILP (XWINDOW (parent)->hchild) + : !NILP (XWINDOW (parent)->vchild)) + { + if (!NILP (XWINDOW (window)->next)) + { + XSETINT (CURBEG (p->next), + XINT (CURBEG (p->next)) + delta); + size_window (p->next, XINT (CURSIZE (p->next)) - delta, + horiz_flag, 0); + break; + } + } + else + /* Here we have a chain of parallel siblings, in the other dimension. + Change the size of the other siblings. */ + for (child = (horiz_flag + ? XWINDOW (parent)->vchild + : XWINDOW (parent)->hchild); + ! NILP (child); + child = XWINDOW (child)->next) + if (! EQ (child, window)) + size_window (child, XINT (CURSIZE (child)) + delta, + horiz_flag, 0); + + window = parent; + } + + /* If we made a window so small it got deleted, + we failed. Report failure. */ + if (delcount != window_deletion_count) + { + Fset_window_configuration (old_config); + error ("Cannot adjust window size as specified"); + } + + /* 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. */) + (window, delta, horizontal) + Lisp_Object window, delta, horizontal; +{ + CHECK_NUMBER (delta); + adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal)); + + if (! NILP (Vwindow_configuration_change_hook)) + call1 (Vrun_hooks, Qwindow_configuration_change_hook); + + return Qnil; +} + /*********************************************************************** @@ -4452,7 +4576,7 @@ among the other windows. */ Lisp_Object window; XSETWINDOW (window, w); - enlarge_window (window, 1 - XFASTINT (w->total_lines), 0, 0); + enlarge_window (window, 1 - XFASTINT (w->total_lines), 0); } } @@ -5681,7 +5805,23 @@ else { if (XBUFFER (new_current_buffer) == current_buffer) - old_point = PT; + /* The code further down "preserves point" by saving here PT in + old_point and then setting it later back into PT. When the + current-selected-window and the final-selected-window both show + the current buffer, this suffers from the problem that the + current PT is the window-point of the current-selected-window, + while the final PT is the point of the final-selected-window, so + this copy from one PT to the other would end up moving the + window-point of the final-selected-window to the window-point of + the current-selected-window. So we have to be careful which + point of the current-buffer we copy into old_point. */ + if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer) + && WINDOWP (selected_window) + && EQ (XWINDOW (selected_window)->buffer, new_current_buffer) + && !EQ (selected_window, data->current_window)) + old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos; + else + old_point = PT; else /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of point in new_current_buffer as of the last time this buffer was @@ -7098,6 +7238,7 @@ defsubr (&Ssplit_window); defsubr (&Senlarge_window); defsubr (&Sshrink_window); + defsubr (&Sadjust_window_trailing_edge); defsubr (&Sscroll_up); defsubr (&Sscroll_down); defsubr (&Sscroll_left);