aboutsummaryrefslogtreecommitdiffstats
path: root/src/window.c
diff options
context:
space:
mode:
authorMartin Rudalics2011-06-09 08:35:02 +0200
committerMartin Rudalics2011-06-09 08:35:02 +0200
commit1a13852e906ca4f4f98a65106496d2cb1c517d64 (patch)
treeed4ed7a0b5ae9c961570bb41479a2bdf57763adf /src/window.c
parente8b08aeecad0dc735d8f40ddabc8c0c249dedb21 (diff)
downloademacs-1a13852e906ca4f4f98a65106496d2cb1c517d64.tar.gz
emacs-1a13852e906ca4f4f98a65106496d2cb1c517d64.zip
Final preparations for new window resize code.
* window.c (replace_window): Rename second argument REPLACEMENT to NEW. New third argument SETFLAG. Rewrite. (delete_window, make_dummy_parent): Call replace_window with third argument 1. (window_list_1): Move down in code. (run_window_configuration_change_hook): Move set_buffer part before select_frame_norecord part in order to unwind correctly. Rename count1 to count. (recombine_windows, delete_deletable_window, resize_root_window) (Fdelete_other_windows_internal) (Frun_window_configuration_change_hook, make_parent_window) (resize_window_check, resize_window_apply, Fresize_window_apply) (resize_frame_windows, Fsplit_window_internal) (Fdelete_window_internal, Fresize_mini_window_internal): New functions. (syms_of_window): New variables Vwindow_splits and Vwindow_nest.
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c1271
1 files changed, 1187 insertions, 84 deletions
diff --git a/src/window.c b/src/window.c
index 393a2478ce1..dd8cdab77a4 100644
--- a/src/window.c
+++ b/src/window.c
@@ -90,6 +90,7 @@ static int foreach_window_1 (struct window *,
90 int (* fn) (struct window *, void *), 90 int (* fn) (struct window *, void *),
91 void *); 91 void *);
92static Lisp_Object window_list_1 (Lisp_Object, Lisp_Object, Lisp_Object); 92static Lisp_Object window_list_1 (Lisp_Object, Lisp_Object, Lisp_Object);
93static void resize_window_apply (struct window *, int);
93static Lisp_Object select_window (Lisp_Object, Lisp_Object, int); 94static Lisp_Object select_window (Lisp_Object, Lisp_Object, int);
94 95
95/* This is the window in which the terminal's cursor should 96/* This is the window in which the terminal's cursor should
@@ -1853,60 +1854,146 @@ unshow_buffer (register struct window *w)
1853 BVAR (b, last_selected_window) = Qnil; 1854 BVAR (b, last_selected_window) = Qnil;
1854} 1855}
1855 1856
1856/* Put replacement into the window structure in place of old. */ 1857/* Put NEW into the window structure in place of OLD. SETFLAG zero
1858 means change window structure only. Otherwise store geometry and
1859 other settings as well. */
1857static void 1860static void
1858replace_window (Lisp_Object old, Lisp_Object replacement) 1861replace_window (Lisp_Object old, Lisp_Object new, int setflag)
1859{ 1862{
1860 register Lisp_Object tem; 1863 register Lisp_Object tem;
1861 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement); 1864 register struct window *o = XWINDOW (old), *n = XWINDOW (new);
1862
1863 /* If OLD is its frame's root_window, then replacement is the new
1864 root_window for that frame. */
1865 1865
1866 /* If OLD is its frame's root window, then NEW is the new
1867 root window for that frame. */
1866 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame)))) 1868 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1867 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement; 1869 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = new;
1868 1870
1869 p->left_col = o->left_col; 1871 if (setflag)
1870 p->top_line = o->top_line; 1872 {
1871 p->total_cols = o->total_cols; 1873 n->left_col = o->left_col;
1872 p->total_lines = o->total_lines; 1874 n->top_line = o->top_line;
1873 p->desired_matrix = p->current_matrix = 0; 1875 n->total_cols = o->total_cols;
1874 p->vscroll = 0; 1876 n->total_lines = o->total_lines;
1875 memset (&p->cursor, 0, sizeof (p->cursor)); 1877 n->normal_cols = o->normal_cols;
1876 memset (&p->last_cursor, 0, sizeof (p->last_cursor)); 1878 o->normal_cols = make_float (1.0);
1877 memset (&p->phys_cursor, 0, sizeof (p->phys_cursor)); 1879 n->normal_lines = o->normal_lines;
1878 p->phys_cursor_type = -1; 1880 o->normal_lines = make_float (1.0);
1879 p->phys_cursor_width = -1; 1881 n->desired_matrix = n->current_matrix = 0;
1880 p->must_be_updated_p = 0; 1882 n->vscroll = 0;
1881 p->pseudo_window_p = 0; 1883 memset (&n->cursor, 0, sizeof (n->cursor));
1882 XSETFASTINT (p->window_end_vpos, 0); 1884 memset (&n->last_cursor, 0, sizeof (n->last_cursor));
1883 XSETFASTINT (p->window_end_pos, 0); 1885 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
1884 p->window_end_valid = Qnil; 1886 n->phys_cursor_type = -1;
1885 p->frozen_window_start_p = 0; 1887 n->phys_cursor_width = -1;
1886 p->orig_top_line = p->orig_total_lines = Qnil; 1888 n->must_be_updated_p = 0;
1887 1889 n->pseudo_window_p = 0;
1888 p->next = tem = o->next; 1890 XSETFASTINT (n->window_end_vpos, 0);
1891 XSETFASTINT (n->window_end_pos, 0);
1892 n->window_end_valid = Qnil;
1893 n->frozen_window_start_p = 0;
1894 n->orig_top_line = n->orig_total_lines = Qnil;
1895 }
1896
1897 n->next = tem = o->next;
1889 if (!NILP (tem)) 1898 if (!NILP (tem))
1890 XWINDOW (tem)->prev = replacement; 1899 XWINDOW (tem)->prev = new;
1891 1900
1892 p->prev = tem = o->prev; 1901 n->prev = tem = o->prev;
1893 if (!NILP (tem)) 1902 if (!NILP (tem))
1894 XWINDOW (tem)->next = replacement; 1903 XWINDOW (tem)->next = new;
1895 1904
1896 p->parent = tem = o->parent; 1905 n->parent = tem = o->parent;
1897 if (!NILP (tem)) 1906 if (!NILP (tem))
1898 { 1907 {
1899 if (EQ (XWINDOW (tem)->vchild, old)) 1908 if (EQ (XWINDOW (tem)->vchild, old))
1900 XWINDOW (tem)->vchild = replacement; 1909 XWINDOW (tem)->vchild = new;
1901 if (EQ (XWINDOW (tem)->hchild, old)) 1910 if (EQ (XWINDOW (tem)->hchild, old))
1902 XWINDOW (tem)->hchild = replacement; 1911 XWINDOW (tem)->hchild = new;
1903 } 1912 }
1913}
1914
1915/* If window WINDOW and its parent window are iso-combined, merge
1916 WINDOW's children into those of its parent window and mark WINDOW as
1917 deleted. */
1918
1919static void
1920recombine_windows (Lisp_Object window)
1921{
1922 struct window *w, *p, *c;
1923 Lisp_Object parent, child;
1924 int horflag;
1925
1926 w = XWINDOW (window);
1927 parent = w->parent;
1928 if (!NILP (parent) && NILP (w->nest))
1929 {
1930 p = XWINDOW (parent);
1931 if (((!NILP (p->vchild) && !NILP (w->vchild))
1932 || (!NILP (p->hchild) && !NILP (w->hchild))))
1933 /* WINDOW and PARENT are both either a vertical or a horizontal
1934 combination. */
1935 {
1936 horflag = NILP (w->vchild);
1937 child = horflag ? w->hchild : w->vchild;
1938 c = XWINDOW (child);
1939
1940 /* Splice WINDOW's children into its parent's children and
1941 assign new normal sizes. */
1942 if (NILP (w->prev))
1943 if (horflag)
1944 p->hchild = child;
1945 else
1946 p->vchild = child;
1947 else
1948 {
1949 c->prev = w->prev;
1950 XWINDOW (w->prev)->next = child;
1951 }
1952
1953 while (c)
1954 {
1955 c->parent = parent;
1956
1957 if (horflag)
1958 c->normal_cols
1959 = make_float (XFLOATINT (c->total_cols)
1960 / XFLOATINT (p->total_cols));
1961 else
1962 c->normal_lines
1963 = make_float (XFLOATINT (c->total_lines)
1964 / XFLOATINT (p->total_lines));
1965
1966 if (NILP (c->next))
1967 {
1968 if (!NILP (w->next))
1969 {
1970 c->next = w->next;
1971 XWINDOW (c->next)->prev = child;
1972 }
1973
1974 c = 0;
1975 }
1976 else
1977 {
1978 child = c->next;
1979 c = XWINDOW (child);
1980 }
1981 }
1904 1982
1905/*** Here, if replacement is a vertical combination 1983 /* WINDOW can be deleted now. */
1906and so is its new parent, we should make replacement's 1984 w->vchild = w->hchild = Qnil;
1907children be children of that parent instead. ***/ 1985 }
1986 }
1908} 1987}
1909 1988
1989/* If WINDOW can be deleted, delete it. */
1990Lisp_Object
1991delete_deletable_window (Lisp_Object window)
1992{
1993 if (!NILP (call1 (Qwindow_deletable_p, window)))
1994 call1 (Qdelete_window, window);
1995}
1996
1910DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "", 1997DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1911 doc: /* Remove WINDOW from its frame. 1998 doc: /* Remove WINDOW from its frame.
1912WINDOW defaults to the selected window. Return nil. 1999WINDOW defaults to the selected window. Return nil.
@@ -2067,7 +2154,7 @@ delete_window (register Lisp_Object window)
2067 if (NILP (tem)) 2154 if (NILP (tem))
2068 tem = par->vchild; 2155 tem = par->vchild;
2069 if (NILP (XWINDOW (tem)->next)) { 2156 if (NILP (XWINDOW (tem)->next)) {
2070 replace_window (parent, tem); 2157 replace_window (parent, tem, 1);
2071 par = XWINDOW (tem); 2158 par = XWINDOW (tem);
2072 } 2159 }
2073 2160
@@ -2427,43 +2514,6 @@ reverse order. */)
2427} 2514}
2428 2515
2429 2516
2430DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2431 doc: /* Return a list of all live windows.
2432WINDOW specifies the first window to list and defaults to the selected
2433window.
2434
2435Optional argument MINIBUF nil or omitted means consider the minibuffer
2436window only if the minibuffer is active. MINIBUF t means consider the
2437minibuffer window even if the minibuffer is not active. Any other value
2438means do not consider the minibuffer window even if the minibuffer is
2439active.
2440
2441Optional argument ALL-FRAMES nil or omitted means consider all windows
2442on WINDOW's frame, plus the minibuffer window if specified by the
2443MINIBUF argument. If the minibuffer counts, consider all windows on all
2444frames that share that minibuffer too. The following non-nil values of
2445ALL-FRAMES have special meanings:
2446
2447- t means consider all windows on all existing frames.
2448
2449- `visible' means consider all windows on all visible frames.
2450
2451- 0 (the number zero) means consider all windows on all visible and
2452 iconified frames.
2453
2454- A frame means consider all windows on that frame only.
2455
2456Anything else means consider all windows on WINDOW's frame and no
2457others.
2458
2459If WINDOW is not on the list of windows returned, some other window will
2460be listed first but no error is signalled. */)
2461 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2462{
2463 return window_list_1 (window, minibuf, all_frames);
2464}
2465
2466
2467DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p", 2517DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
2468 doc: /* Select another window in cyclic ordering of windows. 2518 doc: /* Select another window in cyclic ordering of windows.
2469COUNT specifies the number of windows to skip, starting with the 2519COUNT specifies the number of windows to skip, starting with the
@@ -2547,6 +2597,41 @@ MINIBUF neither nil nor t means never include the minibuffer window. */)
2547} 2597}
2548 2598
2549 2599
2600DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2601 doc: /* Return a list of all live windows.
2602WINDOW specifies the first window to list and defaults to the selected
2603window.
2604
2605Optional argument MINIBUF nil or omitted means consider the minibuffer
2606window only if the minibuffer is active. MINIBUF t means consider the
2607minibuffer window even if the minibuffer is not active. Any other value
2608means do not consider the minibuffer window even if the minibuffer is
2609active.
2610
2611Optional argument ALL-FRAMES nil or omitted means consider all windows
2612on WINDOW's frame, plus the minibuffer window if specified by the
2613MINIBUF argument. If the minibuffer counts, consider all windows on all
2614frames that share that minibuffer too. The following non-nil values of
2615ALL-FRAMES have special meanings:
2616
2617- t means consider all windows on all existing frames.
2618
2619- `visible' means consider all windows on all visible frames.
2620
2621- 0 (the number zero) means consider all windows on all visible and
2622 iconified frames.
2623
2624- A frame means consider all windows on that frame only.
2625
2626Anything else means consider all windows on WINDOW's frame and no
2627others.
2628
2629If WINDOW is not on the list of windows returned, some other window will
2630be listed first but no error is signalled. */)
2631 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2632{
2633 return window_list_1 (window, minibuf, all_frames);
2634}
2550 2635
2551/* Look at all windows, performing an operation specified by TYPE 2636/* Look at all windows, performing an operation specified by TYPE
2552 with argument OBJ. 2637 with argument OBJ.
@@ -2801,6 +2886,248 @@ selected frame and no others. */)
2801 return Qnil; 2886 return Qnil;
2802} 2887}
2803 2888
2889Lisp_Object
2890resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore)
2891{
2892 return call4 (Qresize_root_window, window, delta, horizontal, ignore);
2893}
2894
2895
2896DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
2897 Sdelete_other_windows_internal, 0, 2, "",
2898 doc: /* Make WINDOW fill its frame.
2899Only the frame WINDOW is on is affected. WINDOW may be any window and
2900defaults to the selected one.
2901
2902Optional argument ROOT, if non-nil, must specify an internal window
2903containing WINDOW as a subwindow. If this is the case, replace ROOT by
2904WINDOW and leave alone any windows not contained in ROOT.
2905
2906When WINDOW is live try to reduce display jumps by keeping the text
2907previously visible in WINDOW in the same place on the frame. Doing this
2908depends on the value of (window-start WINDOW), so if calling this
2909function in a program gives strange scrolling, make sure the
2910window-start value is reasonable when this function is called. */)
2911 (Lisp_Object window, Lisp_Object root)
2912{
2913 struct window *w, *r, *s;
2914 struct frame *f;
2915 Lisp_Object sibling, pwindow, swindow, delta;
2916 EMACS_INT startpos;
2917 int top, new_top, resize_failed;
2918
2919 w = decode_any_window (window);
2920 XSETWINDOW (window, w);
2921 f = XFRAME (w->frame);
2922
2923 if (NILP (root))
2924 /* ROOT is the frame's root window. */
2925 {
2926 root = FRAME_ROOT_WINDOW (f);
2927 r = XWINDOW (root);
2928 }
2929 else
2930 /* ROOT must be an ancestor of WINDOW. */
2931 {
2932 r = decode_any_window (root);
2933 pwindow = XWINDOW (window)->parent;
2934 while (!NILP (pwindow))
2935 if (EQ (pwindow, root))
2936 break;
2937 else
2938 pwindow = XWINDOW (pwindow)->parent;
2939 if (!EQ (pwindow, root))
2940 error ("Specified root is not an ancestor of specified window");
2941 }
2942
2943 if (EQ (window, root))
2944 /* A noop. */
2945 return Qnil;
2946 /* I don't understand the "top > 0" part below. If we deal with a
2947 standalone minibuffer it would have been caught by the preceding
2948 test. */
2949 else if (MINI_WINDOW_P (w)) /* && top > 0) */
2950 error ("Can't expand minibuffer to full frame");
2951
2952 if (!NILP (w->buffer))
2953 {
2954 startpos = marker_position (w->start);
2955 top = WINDOW_TOP_EDGE_LINE (w)
2956 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2957 /* Make sure WINDOW is the frame's selected window. */
2958 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
2959 {
2960 if (EQ (selected_frame, w->frame))
2961 Fselect_window (window, Qnil);
2962 else
2963 FRAME_SELECTED_WINDOW (f) = window;
2964 }
2965 }
2966 else
2967 {
2968 /* See if the frame's selected window is a subwindow of WINDOW, by
2969 finding all the selected window's parents and comparing each
2970 one with WINDOW. If it isn't we need a new selected window for
2971 this frame. */
2972 swindow = FRAME_SELECTED_WINDOW (f);
2973 while (1)
2974 {
2975 pwindow = swindow;
2976 while (!NILP (pwindow) && !EQ (window, pwindow))
2977 pwindow = XWINDOW (pwindow)->parent;
2978
2979 if (EQ (window, pwindow))
2980 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
2981 as the new selected window. */
2982 break;
2983 else
2984 /* Else try the previous window of SWINDOW. */
2985 swindow = Fprevious_window (swindow, Qlambda, Qnil);
2986 }
2987
2988 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
2989 {
2990 if (EQ (selected_frame, w->frame))
2991 Fselect_window (swindow, Qnil);
2992 else
2993 FRAME_SELECTED_WINDOW (f) = swindow;
2994 }
2995 }
2996
2997 BLOCK_INPUT;
2998 free_window_matrices (r);
2999
3000 windows_or_buffers_changed++;
3001 Vwindow_list = Qnil;
3002 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3003
3004 if (NILP (w->buffer))
3005 {
3006 resize_failed = 0;
3007 /* Resize subwindows vertically. */
3008 XSETINT (delta, XINT (r->total_lines) - XINT (w->total_lines));
3009 w->top_line = r->top_line;
3010 resize_root_window (window, delta, Qnil, Qnil);
3011 if (resize_window_check (w, 0))
3012 resize_window_apply (w, 0);
3013 else
3014 {
3015 resize_root_window (window, delta, Qnil, Qt);
3016 if (resize_window_check (w, 0))
3017 resize_window_apply (w, 0);
3018 else
3019 resize_failed = 1;
3020 }
3021
3022 /* Resize subwindows horizontally. */
3023 if (!resize_failed)
3024 {
3025 w->left_col = r->left_col;
3026 XSETINT (delta, XINT (r->total_cols) - XINT (w->total_cols));
3027 w->left_col = r->left_col;
3028 resize_root_window (window, delta, Qt, Qnil);
3029 if (resize_window_check (w, 1))
3030 resize_window_apply (w, 1);
3031 else
3032 {
3033 resize_root_window (window, delta, Qt, Qt);
3034 if (resize_window_check (w, 1))
3035 resize_window_apply (w, 1);
3036 else
3037 resize_failed = 1;
3038 }
3039 }
3040
3041 if (resize_failed)
3042 /* Play safe, if we still can ... */
3043 {
3044 window = swindow;
3045 w = XWINDOW (window);
3046 }
3047 }
3048
3049 /* Cleanly unlink WINDOW from window-tree. */
3050 if (!NILP (w->prev))
3051 /* Get SIBLING above (on the left of) WINDOW. */
3052 {
3053 sibling = w->prev;
3054 s = XWINDOW (sibling);
3055 s->next = w->next;
3056 if (!NILP (s->next))
3057 XWINDOW (s->next)->prev = sibling;
3058 }
3059 else
3060 /* Get SIBLING below (on the right of) WINDOW. */
3061 {
3062 sibling = w->next;
3063 s = XWINDOW (sibling);
3064 s->prev = Qnil;
3065 if (!NILP (XWINDOW (w->parent)->vchild))
3066 XWINDOW (w->parent)->vchild = sibling;
3067 else
3068 XWINDOW (w->parent)->hchild = sibling;
3069 }
3070
3071 /* Delete ROOT and all subwindows of ROOT. */
3072 if (!NILP (r->vchild))
3073 {
3074 delete_all_subwindows (r->vchild);
3075 r->vchild = Qnil;
3076 }
3077 else if (!NILP (r->hchild))
3078 {
3079 delete_all_subwindows (r->hchild);
3080 r->hchild = Qnil;
3081 }
3082
3083 replace_window (root, window, 1);
3084
3085 /* Reset WINDOW's splits status. */
3086 w->splits = Qnil;
3087
3088 /* This must become SWINDOW anyway ....... */
3089 if (!NILP (w->buffer) && !resize_failed)
3090 {
3091 /* Try to minimize scrolling, by setting the window start to the
3092 point will cause the text at the old window start to be at the
3093 same place on the frame. But don't try to do this if the
3094 window start is outside the visible portion (as might happen
3095 when the display is not current, due to typeahead). */
3096 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
3097 if (new_top != top
3098 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
3099 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
3100 {
3101 struct position pos;
3102 struct buffer *obuf = current_buffer;
3103
3104 Fset_buffer (w->buffer);
3105 /* This computation used to temporarily move point, but that
3106 can have unwanted side effects due to text properties. */
3107 pos = *vmotion (startpos, -top, w);
3108
3109 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
3110 w->window_end_valid = Qnil;
3111 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
3112 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
3113 : Qnil);
3114 /* We need to do this, so that the window-scroll-functions
3115 get called. */
3116 w->optional_new_start = Qt;
3117
3118 set_buffer_internal (obuf);
3119 }
3120 }
3121
3122 adjust_glyphs (f);
3123 UNBLOCK_INPUT;
3124
3125 run_window_configuration_change_hook (f);
3126
3127 return Qnil;
3128}
3129
3130
2804DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows, 3131DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2805 0, 1, "", 3132 0, 1, "",
2806 doc: /* Make WINDOW (or the selected window) fill its frame. 3133 doc: /* Make WINDOW (or the selected window) fill its frame.
@@ -3676,12 +4003,6 @@ run_window_configuration_change_hook (struct frame *f)
3676 if (NILP (Vrun_hooks)) 4003 if (NILP (Vrun_hooks))
3677 return; 4004 return;
3678 4005
3679 if (SELECTED_FRAME () != f)
3680 {
3681 record_unwind_protect (select_frame_norecord, Fselected_frame ());
3682 Fselect_frame (frame, Qt);
3683 }
3684
3685 /* Use the right buffer. Matters when running the local hooks. */ 4006 /* Use the right buffer. Matters when running the local hooks. */
3686 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil))) 4007 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3687 { 4008 {
@@ -3689,6 +4010,12 @@ run_window_configuration_change_hook (struct frame *f)
3689 Fset_buffer (Fwindow_buffer (Qnil)); 4010 Fset_buffer (Fwindow_buffer (Qnil));
3690 } 4011 }
3691 4012
4013 if (SELECTED_FRAME () != f)
4014 {
4015 record_unwind_protect (select_frame_norecord, Fselected_frame ());
4016 select_frame_norecord (frame);
4017 }
4018
3692 /* Look for buffer-local values. */ 4019 /* Look for buffer-local values. */
3693 { 4020 {
3694 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil); 4021 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
@@ -3699,12 +4026,12 @@ run_window_configuration_change_hook (struct frame *f)
3699 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook, 4026 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3700 buffer))) 4027 buffer)))
3701 { 4028 {
3702 int count1 = SPECPDL_INDEX (); 4029 int count = SPECPDL_INDEX ();
3703 record_unwind_protect (select_window_norecord, Fselected_window ()); 4030 record_unwind_protect (select_window_norecord, Fselected_window ());
3704 select_window_norecord (window); 4031 select_window_norecord (window);
3705 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook, 4032 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3706 buffer)); 4033 buffer));
3707 unbind_to (count1, Qnil); 4034 unbind_to (count, Qnil);
3708 } 4035 }
3709 } 4036 }
3710 } 4037 }
@@ -3713,6 +4040,16 @@ run_window_configuration_change_hook (struct frame *f)
3713 unbind_to (count, Qnil); 4040 unbind_to (count, Qnil);
3714} 4041}
3715 4042
4043DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
4044 Srun_window_configuration_change_hook, 1, 1, 0,
4045 doc: /* Run `window-configuration-change-hook' for FRAME. */)
4046 (Lisp_Object frame)
4047{
4048 CHECK_LIVE_FRAME (frame);
4049 run_window_configuration_change_hook (XFRAME (frame));
4050 return Qnil;
4051}
4052
3716/* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero 4053/* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3717 means it's allowed to run hooks. See make_frame for a case where 4054 means it's allowed to run hooks. See make_frame for a case where
3718 it's not allowed. KEEP_MARGINS_P non-zero means that the current 4055 it's not allowed. KEEP_MARGINS_P non-zero means that the current
@@ -4019,7 +4356,7 @@ make_dummy_parent (Lisp_Object window)
4019 XSETFASTINT (p->clone_number, sequence_number); 4356 XSETFASTINT (p->clone_number, sequence_number);
4020 4357
4021 /* Put new into window structure in place of window */ 4358 /* Put new into window structure in place of window */
4022 replace_window (window, new); 4359 replace_window (window, new, 1);
4023 4360
4024 o->next = Qnil; 4361 o->next = Qnil;
4025 o->prev = Qnil; 4362 o->prev = Qnil;
@@ -4037,6 +4374,43 @@ make_dummy_parent (Lisp_Object window)
4037 4374
4038} 4375}
4039 4376
4377/* Make new window, have it replace WINDOW in window-tree, and make
4378 WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
4379 horizontal child). */
4380static void
4381make_parent_window (Lisp_Object window, int horflag)
4382{
4383 Lisp_Object parent;
4384 register struct window *o, *p;
4385 int i;
4386
4387 o = XWINDOW (window);
4388 p = allocate_window ();
4389 for (i = 0; i < VECSIZE (struct window); ++i)
4390 ((struct Lisp_Vector *) p)->contents[i]
4391 = ((struct Lisp_Vector *) o)->contents[i];
4392 XSETWINDOW (parent, p);
4393
4394 ++sequence_number;
4395 XSETFASTINT (p->sequence_number, sequence_number);
4396 XSETFASTINT (p->clone_number, sequence_number);
4397
4398 replace_window (window, parent, 1);
4399
4400 o->next = Qnil;
4401 o->prev = Qnil;
4402 o->parent = parent;
4403
4404 p->hchild = horflag ? window : Qnil;
4405 p->vchild = horflag ? Qnil : window;
4406 p->start = Qnil;
4407 p->pointm = Qnil;
4408 p->buffer = Qnil;
4409 p->splits = Qnil;
4410 p->nest = Qnil;
4411 p->window_parameters = Qnil;
4412}
4413
4040/* Make new window from scratch. */ 4414/* Make new window from scratch. */
4041Lisp_Object 4415Lisp_Object
4042make_window (void) 4416make_window (void)
@@ -4138,6 +4512,654 @@ Note: This function does not operate on any subwindows of WINDOW. */)
4138 return w->new_normal; 4512 return w->new_normal;
4139} 4513}
4140 4514
4515/* Return 1 if setting w->total_lines (w->total_cols if HORFLAG is
4516 non-zero) to w->new_total would result in correct heights (widths)
4517 for window W and recursively all subwindows of W.
4518
4519 Note: This function does not check any of `window-fixed-size-p',
4520 `window-min-height' or `window-min-width'. It does check that window
4521 sizes do not drop below one line (two columns). */
4522int
4523resize_window_check (struct window *w, int horflag)
4524{
4525 struct window *c;
4526
4527 if (!NILP (w->vchild))
4528 /* W is a vertical combination. */
4529 {
4530 c = XWINDOW (w->vchild);
4531 if (horflag)
4532 /* All subwindows of W must have the same width as W. */
4533 {
4534 while (c)
4535 {
4536 if ((XINT (c->new_total) != XINT (w->new_total))
4537 || !resize_window_check (c, horflag))
4538 return 0;
4539 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4540 }
4541 return 1;
4542 }
4543 else
4544 /* The sum of the heights of the subwindows of W must equal W's
4545 height. */
4546 {
4547 int sum_of_sizes = 0;
4548 while (c)
4549 {
4550 if (!resize_window_check (c, horflag))
4551 return 0;
4552 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
4553 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4554 }
4555 return (sum_of_sizes == XINT (w->new_total));
4556 }
4557 }
4558 else if (!NILP (w->hchild))
4559 /* W is a horizontal combination. */
4560 {
4561 c = XWINDOW (w->hchild);
4562 if (horflag)
4563 /* The sum of the widths of the subwindows of W must equal W's
4564 width. */
4565 {
4566 int sum_of_sizes = 0;
4567 while (c)
4568 {
4569 if (!resize_window_check (c, horflag))
4570 return 0;
4571 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
4572 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4573 }
4574 return (sum_of_sizes == XINT (w->new_total));
4575 }
4576 else
4577 /* All subwindows of W must have the same height as W. */
4578 {
4579 while (c)
4580 {
4581 if ((XINT (c->new_total) != XINT (w->new_total))
4582 || !resize_window_check (c, horflag))
4583 return 0;
4584 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4585 }
4586 return 1;
4587 }
4588 }
4589 else
4590 /* A leaf window. Make sure it's not too small. The following
4591 hardcodes the values of `window-safe-min-width' (2) and
4592 `window-safe-min-height' (1) which are defined in window.el. */
4593 return XINT (w->new_total) >= (horflag ? 2 : 1);
4594}
4595
4596/* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
4597 w->new_total for window W and recursively all subwindows of W. Also
4598 calculate and assign the new vertical (horizontal) start positions of
4599 each of these windows.
4600
4601 This function does not perform any error checks. Make sure you have
4602 run resize_window_check on W before applying this function. */
4603void
4604resize_window_apply (struct window *w, int horflag)
4605{
4606 struct window *c, *p;
4607 int pos;
4608
4609 /* Note: Assigning new_normal requires that the new total size of the
4610 parent window has been set *before*. */
4611 if (horflag)
4612 {
4613 w->total_cols = w->new_total;
4614 if (NUMBERP (w->new_normal))
4615 w->normal_cols = w->new_normal;
4616
4617 pos = XINT (w->left_col);
4618 }
4619 else
4620 {
4621 w->total_lines = w->new_total;
4622 if (NUMBERP (w->new_normal))
4623 w->normal_lines = w->new_normal;
4624
4625 pos = XINT (w->top_line);
4626 }
4627
4628 if (!NILP (w->vchild))
4629 /* W is a vertical combination. */
4630 {
4631 c = XWINDOW (w->vchild);
4632 while (c)
4633 {
4634 if (horflag)
4635 XSETFASTINT (c->left_col, pos);
4636 else
4637 XSETFASTINT (c->top_line, pos);
4638 resize_window_apply (c, horflag);
4639 if (!horflag)
4640 pos = pos + XINT (c->total_lines);
4641 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4642 }
4643 }
4644 else if (!NILP (w->hchild))
4645 /* W is a horizontal combination. */
4646 {
4647 c = XWINDOW (w->hchild);
4648 while (c)
4649 {
4650 if (horflag)
4651 XSETFASTINT (c->left_col, pos);
4652 else
4653 XSETFASTINT (c->top_line, pos);
4654 resize_window_apply (c, horflag);
4655 if (horflag)
4656 pos = pos + XINT (c->total_cols);
4657 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4658 }
4659 }
4660
4661 /* Clear out some redisplay caches. */
4662 XSETFASTINT (w->last_modified, 0);
4663 XSETFASTINT (w->last_overlay_modified, 0);
4664}
4665
4666
4667DEFUN ("resize-window-apply", Fresize_window_apply, Sresize_window_apply, 1, 2, 0,
4668 doc: /* Apply requested size values for window-tree of FRAME.
4669Optional argument HORIZONTAL omitted or nil means apply requested height
4670values. HORIZONTAL non-nil means apply requested width values.
4671
4672This function checks whether the requested values sum up to a valid
4673window layout, recursively assigns the new sizes of all subwindows and
4674calculates and assigns the new start positions of these windows.
4675
4676Note: This function does not check any of `window-fixed-size-p',
4677`window-min-height' or `window-min-width'. All these checks have to
4678be applied on the Elisp level. */)
4679 (Lisp_Object frame, Lisp_Object horizontal)
4680{
4681 struct frame *f;
4682 struct window *r;
4683 int horflag = !NILP (horizontal);
4684
4685 if (NILP (frame))
4686 frame = selected_frame;
4687 CHECK_LIVE_FRAME (frame);
4688
4689 f = XFRAME (frame);
4690 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4691
4692 if (!resize_window_check (r, horflag)
4693 || ! EQ (r->new_total, (horflag ? r->total_cols : r->total_lines)))
4694 return Qnil;
4695
4696 BLOCK_INPUT;
4697 resize_window_apply (r, horflag);
4698
4699 windows_or_buffers_changed++;
4700 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4701
4702 adjust_glyphs (f);
4703 UNBLOCK_INPUT;
4704
4705 run_window_configuration_change_hook (f);
4706
4707 return Qt;
4708}
4709
4710
4711/* Resize frame F's windows when number of lines of F is set to SIZE.
4712 HORFLAG 1 means resize windows when number of columns of F is set to
4713 SIZE.
4714
4715 This function can delete all windows but the selected one in order to
4716 satisfy the request. The result will be meaningful if and only if
4717 F's windows have meaningful sizes when you call this. */
4718void
4719resize_frame_windows (struct frame *f, int size, int horflag)
4720{
4721 Lisp_Object root = f->root_window;
4722 struct window *r = XWINDOW (root);
4723 Lisp_Object mini = f->minibuffer_window;
4724 struct window *m;
4725 /* new_size is the new size of the frame's root window. */
4726 int new_size = (horflag
4727 ? size
4728 : (size
4729 - FRAME_TOP_MARGIN (f)
4730 - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
4731 ? 1 : 0)));
4732
4733 XSETFASTINT (r->top_line, FRAME_TOP_MARGIN (f));
4734 if (NILP (r->vchild) && NILP (r->hchild))
4735 /* For a leaf root window just set the size. */
4736 if (horflag)
4737 XSETFASTINT (r->total_cols, new_size);
4738 else
4739 XSETFASTINT (r->total_lines, new_size);
4740 else
4741 {
4742 /* old_size is the old size of the frame's root window. */
4743 int old_size = XFASTINT (horflag ? r->total_cols : r->total_lines);
4744 Lisp_Object delta;
4745
4746 XSETINT (delta, new_size - old_size);
4747 /* Try a "normal" resize first. */
4748 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil);
4749 if (resize_window_check (r, horflag) && new_size == XINT (r->new_total))
4750 resize_window_apply (r, horflag);
4751 else
4752 {
4753 /* Try with "reasonable" minimum sizes next. */
4754 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt);
4755 if (resize_window_check (r, horflag)
4756 && new_size == XINT (r->new_total))
4757 resize_window_apply (r, horflag);
4758 else
4759 {
4760 /* Finally, try with "safe" minimum sizes. */
4761 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe);
4762 if (resize_window_check (r, horflag)
4763 && new_size == XINT (r->new_total))
4764 resize_window_apply (r, horflag);
4765 else
4766 {
4767 /* We lost. Delete all windows but the frame's
4768 selected one. */
4769 root = f->selected_window;
4770 Fdelete_other_windows_internal (root, Qnil);
4771 if (horflag)
4772 XSETFASTINT (XWINDOW (root)->total_cols, new_size);
4773 else
4774 XSETFASTINT (XWINDOW (root)->total_lines, new_size);
4775 }
4776 }
4777 }
4778 }
4779
4780 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
4781 {
4782 m = XWINDOW (mini);
4783 if (horflag)
4784 XSETFASTINT (m->total_cols, size);
4785 else
4786 {
4787 /* Are we sure we always want 1 line here? */
4788 XSETFASTINT (m->total_lines, 1);
4789 XSETFASTINT (m->top_line, XINT (r->top_line) + XINT (r->total_lines));
4790 }
4791 }
4792}
4793
4794
4795DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
4796 doc: /* Split window OLD.
4797Second argument TOTAL-SIZE specifies the number of lines or columns of the
4798new window. In any case TOTAL-SIZE must be a positive integer
4799
4800Third argument SIDE nil (or `below') specifies that the new window shall
4801be located below WINDOW. SIDE `above' means the new window shall be
4802located above WINDOW. In both cases TOTAL-SIZE specifies the number of
4803lines of the new window including space reserved for the mode and/or
4804header line.
4805
4806SIDE t (or `right') specifies that the new window shall be located on
4807the right side of WINDOW. SIDE `left' means the new window shall be
4808located on the left of WINDOW. In both cases TOTAL-SIZE specifies the
4809number of columns of the new window including space reserved for fringes
4810and the scrollbar or a divider column.
4811
4812Fourth argument NORMAL-SIZE specifies the normal size of the new window
4813according to the SIDE argument.
4814
4815The new total and normal sizes of all involved windows must have been
4816set correctly. See the code of `split-window' for how this is done. */)
4817 (Lisp_Object old, Lisp_Object total_size, Lisp_Object side, Lisp_Object normal_size)
4818{
4819 /* OLD (*o) is the window we have to split. (*p) is either OLD's
4820 parent window or an internal window we have to install as OLD's new
4821 parent. REFERENCE (*r) must denote a live window, or is set to OLD
4822 provided OLD is a leaf window, or to the frame's selected window.
4823 NEW (*n) is the new window created with some parameters taken from
4824 REFERENCE (*r). */
4825 register Lisp_Object new, frame, reference;
4826 register struct window *o, *p, *n, *r;
4827 struct frame *f;
4828 int horflag
4829 /* HORFLAG is 1 when we split side-by-side, 0 otherwise. */
4830 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
4831 int do_nest = 0;
4832
4833 CHECK_WINDOW (old);
4834 o = XWINDOW (old);
4835 frame = WINDOW_FRAME (o);
4836 f = XFRAME (frame);
4837
4838 CHECK_NUMBER (total_size);
4839
4840 /* Set do_nest to 1 if we have to make a new parent window. We do
4841 that if either `window-nest' is non-nil, or OLD has no parent, or
4842 OLD is ortho-combined. */
4843 do_nest =
4844 !NILP (Vwindow_nest)
4845 || NILP (o->parent)
4846 || NILP (horflag
4847 ? (XWINDOW (o->parent)->hchild)
4848 : (XWINDOW (o->parent)->vchild));
4849
4850 /* We need a live reference window to initialize some parameters. */
4851 if (WINDOW_LIVE_P (old))
4852 /* OLD is live, use it as reference window. */
4853 reference = old;
4854 else
4855 /* Use the frame's selected window as reference window. */
4856 reference = FRAME_SELECTED_WINDOW (f);
4857 r = XWINDOW (reference);
4858
4859 /* The following bugs are caught by `split-window'. */
4860 if (MINI_WINDOW_P (o))
4861 error ("Attempt to split minibuffer window");
4862 else if (XINT (total_size) < (horflag ? 2 : 1))
4863 error ("Size of new window too small (after split)");
4864 else if (!do_nest && !NILP (Vwindow_splits))
4865 /* `window-splits' non-nil means try to resize OLD's siblings
4866 proportionally. */
4867 {
4868 p = XWINDOW (o->parent);
4869 /* Temporarily pretend we split the parent window. */
4870 XSETINT (p->new_total,
4871 XINT (horflag ? p->total_cols : p->total_lines)
4872 - XINT (total_size));
4873 if (!resize_window_check (p, horflag))
4874 error ("Window sizes don't fit");
4875 else
4876 /* Undo the temporary pretension. */
4877 p->new_total = horflag ? p->total_cols : p->total_lines;
4878 }
4879 else
4880 {
4881 if (!resize_window_check (o, horflag))
4882 error ("Resizing old window failed");
4883 else if (XINT (total_size) + XINT (o->new_total)
4884 != XINT (horflag ? o->total_cols : o->total_lines))
4885 error ("Sum of sizes of old and new window don't fit");
4886 }
4887
4888 /* This is our point of no return. */
4889 if (do_nest)
4890 {
4891 /* Save the old value of o->normal_cols/lines. It gets corrupted
4892 by make_parent_window and we need it below for assigning it to
4893 p->new_normal. */
4894 Lisp_Object new_normal = horflag ? o->normal_cols : o->normal_lines;
4895
4896 make_parent_window (old, horflag);
4897 p = XWINDOW (o->parent);
4898 /* Store value of `window-nest' in new parent's nest slot. */
4899 p->nest = Vwindow_nest;
4900 /* Have PARENT inherit splits slot value from OLD. */
4901 p->splits = o->splits;
4902 /* Store value of `window-splits' in OLD's splits slot. */
4903 o->splits = Vwindow_splits;
4904 /* These get applied below. */
4905 p->new_total = horflag ? o->total_cols : o->total_lines;
4906 p->new_normal = new_normal;
4907 }
4908 else
4909 p = XWINDOW (o->parent);
4910
4911 windows_or_buffers_changed++;
4912 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4913 new = make_window ();
4914 n = XWINDOW (new);
4915 n->frame = frame;
4916 n->parent = o->parent;
4917 n->vchild = n->hchild = Qnil;
4918
4919 if (EQ (side, Qabove) || EQ (side, Qleft))
4920 {
4921 n->prev = o->prev;
4922 if (NILP (n->prev))
4923 if (horflag)
4924 p->hchild = new;
4925 else
4926 p->vchild = new;
4927 else
4928 XWINDOW (n->prev)->next = new;
4929 n->next = old;
4930 o->prev = new;
4931 }
4932 else
4933 {
4934 n->next = o->next;
4935 if (!NILP (n->next))
4936 XWINDOW (n->next)->prev = new;
4937 n->prev = old;
4938 o->next = new;
4939 }
4940
4941 n->buffer = Qt;
4942 n->window_end_valid = Qnil;
4943 memset (&n->last_cursor, 0, sizeof n->last_cursor);
4944
4945 /* Get special geometry settings from reference window. */
4946 n->left_margin_cols = r->left_margin_cols;
4947 n->right_margin_cols = r->right_margin_cols;
4948 n->left_fringe_width = r->left_fringe_width;
4949 n->right_fringe_width = r->right_fringe_width;
4950 n->fringes_outside_margins = r->fringes_outside_margins;
4951 n->scroll_bar_width = r->scroll_bar_width;
4952 n->vertical_scroll_bar_type = r->vertical_scroll_bar_type;
4953
4954 /* Store `window-splits' in NEW's splits slot. */
4955 n->splits = Vwindow_splits;
4956
4957 /* Directly assign orthogonal coordinates and sizes. */
4958 if (horflag)
4959 {
4960 n->top_line = o->top_line;
4961 n->total_lines = o->total_lines;
4962 }
4963 else
4964 {
4965 n->left_col = o->left_col;
4966 n->total_cols = o->total_cols;
4967 }
4968
4969 /* Iso-coordinates and sizes are assigned by resize_window_apply,
4970 get them ready here. */
4971 n->new_total = total_size;
4972 n->new_normal = normal_size;
4973
4974 BLOCK_INPUT;
4975 resize_window_apply (p, horflag);
4976 adjust_glyphs (f);
4977 /* Set buffer of NEW to buffer of reference window. Don't run
4978 any hooks. */
4979 set_window_buffer (new, r->buffer, 0, 1);
4980 UNBLOCK_INPUT;
4981
4982 /* Maybe we should run the scroll functions in Elisp (which already
4983 runs the configuration change hook). */
4984 if (! NILP (Vwindow_scroll_functions))
4985 run_hook_with_args_2 (Qwindow_scroll_functions, new,
4986 Fmarker_position (n->start));
4987 /* Return NEW. */
4988 return new;
4989}
4990
4991
4992DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
4993 doc: /* Remove WINDOW from its frame.
4994WINDOW defaults to the selected window. Return nil. Signal an error
4995when WINDOW is the only window on its frame. */)
4996 (register Lisp_Object window)
4997{
4998 register Lisp_Object parent, sibling, frame, root;
4999 struct window *w, *p, *s, *r;
5000 struct frame *f;
5001 int horflag;
5002 int before_sibling = 0;
5003
5004 w = decode_any_window (window);
5005 XSETWINDOW (window, w);
5006 if (NILP (w->buffer) && NILP (w->hchild) && NILP (w->vchild))
5007 /* It's a no-op to delete an already deleted window. */
5008 return Qnil;
5009
5010 parent = w->parent;
5011 if (NILP (parent))
5012 /* Never delete a minibuffer or frame root window. */
5013 error ("Attempt to delete minibuffer or sole ordinary window");
5014 else if (NILP (w->prev) && NILP (w->next))
5015 /* Rather bow out here, this case should be handled on the Elisp
5016 level. */
5017 error ("Attempt to delete sole window of parent");
5018
5019 p = XWINDOW (parent);
5020 horflag = NILP (p->vchild);
5021
5022 frame = WINDOW_FRAME (w);
5023 f = XFRAME (frame);
5024
5025 root = FRAME_ROOT_WINDOW (f);
5026 r = XWINDOW (root);
5027
5028 /* Unlink WINDOW from window tree. */
5029 if (NILP (w->prev))
5030 /* Get SIBLING below (on the right of) WINDOW. */
5031 {
5032 /* before_sibling 1 means WINDOW is the first child of its
5033 parent and thus before the sibling. */
5034 before_sibling = 1;
5035 sibling = w->next;
5036 s = XWINDOW (sibling);
5037 s->prev = Qnil;
5038 if (horflag)
5039 p->hchild = sibling;
5040 else
5041 p->vchild = sibling;
5042 }
5043 else
5044 /* Get SIBLING above (on the left of) WINDOW. */
5045 {
5046 sibling = w->prev;
5047 s = XWINDOW (sibling);
5048 s->next = w->next;
5049 if (!NILP (s->next))
5050 XWINDOW (s->next)->prev = sibling;
5051 }
5052
5053 if (resize_window_check (r, horflag)
5054 && EQ (r->new_total, (horflag ? r->total_cols : r->total_lines)))
5055 /* We can delete WINDOW now. */
5056 {
5057 /* Block input. */
5058 BLOCK_INPUT;
5059 resize_window_apply (p, horflag);
5060
5061 windows_or_buffers_changed++;
5062 Vwindow_list = Qnil;
5063 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5064
5065 w->next = Qnil; /* Don't delete w->next too. */
5066 free_window_matrices (w);
5067
5068 if (!NILP (w->vchild))
5069 {
5070 delete_all_subwindows (w->vchild);
5071 w->vchild = Qnil;
5072 }
5073 else if (!NILP (w->hchild))
5074 {
5075 delete_all_subwindows (w->hchild);
5076 w->hchild = Qnil;
5077 }
5078 else if (!NILP (w->buffer))
5079 {
5080 unshow_buffer (w);
5081 unchain_marker (XMARKER (w->pointm));
5082 unchain_marker (XMARKER (w->start));
5083 w->buffer = Qnil;
5084 }
5085
5086 if (NILP (s->prev) && NILP (s->next))
5087 /* A matrjoshka where SIBLING has become the only child of
5088 PARENT. */
5089 {
5090 /* Put SIBLING into PARENT's place. */
5091 replace_window (parent, sibling, 0);
5092 /* Have SIBLING inherit the following three slot values from
5093 PARENT (the nest slot is not inherited). */
5094 s->normal_cols = p->normal_cols;
5095 s->normal_lines = p->normal_lines;
5096 s->splits = p->splits;
5097 /* Mark PARENT as deleted. */
5098 p->vchild = p->hchild = Qnil;
5099 /* Try to merge SIBLING into its new parent. */
5100 recombine_windows (sibling);
5101 }
5102
5103 adjust_glyphs (f);
5104
5105 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
5106 /* We deleted the frame's selected window. */
5107 {
5108 /* Use the frame's first window as fallback ... */
5109 Lisp_Object new_selected_window = Fframe_first_window (frame);
5110 /* ... but preferably use its most recently used window. */
5111 Lisp_Object mru_window;
5112
5113 /* `get-mru-window' might fail for some reason so play it safe
5114 - promote the first window _without recording it_ first. */
5115 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
5116 Fselect_window (new_selected_window, Qt);
5117 else
5118 FRAME_SELECTED_WINDOW (f) = new_selected_window;
5119
5120 UNBLOCK_INPUT;
5121
5122 /* Now look whether `get-mru-window' gets us something. */
5123 mru_window = call1 (Qget_mru_window, frame);
5124 if (WINDOW_LIVE_P (mru_window)
5125 && EQ (XWINDOW (mru_window)->frame, frame))
5126 new_selected_window = mru_window;
5127
5128 /* If all ended up well, we now promote the mru window. */
5129 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
5130 Fselect_window (new_selected_window, Qnil);
5131 else
5132 FRAME_SELECTED_WINDOW (f) = new_selected_window;
5133 }
5134 else
5135 UNBLOCK_INPUT;
5136
5137 /* Must be run by the caller:
5138 run_window_configuration_change_hook (f); */
5139 }
5140 else
5141 /* We failed: Relink WINDOW into window tree. */
5142 {
5143 if (before_sibling)
5144 {
5145 s->prev = window;
5146 if (horflag)
5147 p->hchild = window;
5148 else
5149 p->vchild = window;
5150 }
5151 else
5152 {
5153 s->next = window;
5154 if (!NILP (w->next))
5155 XWINDOW (w->next)->prev = window;
5156 }
5157 error ("Deletion failed");
5158 }
5159
5160 return Qnil;
5161}
5162
4141DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "", 5163DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
4142 doc: /* Split WINDOW, putting SIZE lines in the first of the pair. 5164 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
4143WINDOW defaults to selected one and SIZE to half its size. 5165WINDOW defaults to selected one and SIZE to half its size.
@@ -4279,6 +5301,46 @@ See Info node `(elisp)Splitting Windows' for more details and examples. */)
4279 Fset_window_buffer (new, o->buffer, Qt); 5301 Fset_window_buffer (new, o->buffer, Qt);
4280 return new; 5302 return new;
4281} 5303}
5304
5305DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
5306 doc: /* Resize minibuffer window WINDOW. */)
5307 (Lisp_Object window)
5308{
5309 struct window *w = XWINDOW (window);
5310 struct window *r;
5311 struct frame *f;
5312 int height;
5313
5314 CHECK_WINDOW (window);
5315 f = XFRAME (w->frame);
5316
5317 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
5318 error ("Not a valid minibuffer window");
5319 else if (FRAME_MINIBUF_ONLY_P (f))
5320 error ("Cannot resize a minibuffer-only frame");
5321
5322 r = XWINDOW (FRAME_ROOT_WINDOW (f));
5323 height = XINT (r->total_lines) + XINT (w->total_lines);
5324 if (resize_window_check (r, 0)
5325 && XINT (w->new_total) > 0
5326 && height == XINT (r->new_total) + XINT (w->new_total))
5327 {
5328 BLOCK_INPUT;
5329 resize_window_apply (r, 0);
5330
5331 w->total_lines = w->new_total;
5332 XSETFASTINT (w->top_line, XINT (r->top_line) + XINT (r->total_lines));
5333
5334 windows_or_buffers_changed++;
5335 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5336 adjust_glyphs (f);
5337 UNBLOCK_INPUT;
5338
5339 run_window_configuration_change_hook (f);
5340 return Qt;
5341 }
5342 else error ("Failed to resize minibuffer window");
5343}
4282 5344
4283DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p", 5345DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
4284 doc: /* Make selected window SIZE lines taller. 5346 doc: /* Make selected window SIZE lines taller.
@@ -7527,6 +8589,41 @@ will redraw the entire frame; the special value `tty' causes the
7527frame to be redrawn only if it is a tty frame. */); 8589frame to be redrawn only if it is a tty frame. */);
7528 Vrecenter_redisplay = Qtty; 8590 Vrecenter_redisplay = Qtty;
7529 8591
8592 DEFVAR_LISP ("window-splits", Vwindow_splits,
8593 doc: /* Non-nil means splitting windows is handled specially.
8594If this variable is nil, splitting a window gets the entire screen space
8595for displaying the new window from the window to split. If this
8596variable is non-nil, splitting a window may resize all windows in the
8597same combination. This also allows to split a window that is otherwise
8598too small or of fixed size.
8599
8600The value of this variable is also assigned to the split status of the
8601new window and, provided the old and new window form a new combination,
8602to the window that was split as well. The split status of a window can
8603be retrieved with the function `window-splits' and altered by the
8604function `set-window-splits'.
8605
8606If the value of the variable `window-nest' is non-nil, the space for the
8607new window is exclusively taken from the window that shall be split, but
8608the split status of the window that is split as well as that of the new
8609window are still set to the value of this variable. */);
8610 Vwindow_splits = Qnil;
8611
8612 DEFVAR_LISP ("window-nest", Vwindow_nest,
8613 doc: /* Non-nil means splitting a window makes a new parent window.
8614If this variable is nil, splitting a window will create a new parent
8615window only if the window has no parent window or the window shall
8616become a combination orthogonal to the one it it is part of.
8617
8618If this variable is non-nil, splitting a window always creates a new
8619parent window. If all splits behave this way, each frame's window tree
8620is a binary tree and every window but the frame's root window has
8621exactly one sibling.
8622
8623The value of this variable is also assigned to the nest status of the
8624new parent window. The nest status of a window can be retrieved via the
8625function `window-nest' and altered by the function `set-window-nest'. */);
8626 Vwindow_nest = Qnil;
7530 8627
7531 defsubr (&Sselected_window); 8628 defsubr (&Sselected_window);
7532 defsubr (&Sminibuffer_window); 8629 defsubr (&Sminibuffer_window);
@@ -7560,6 +8657,7 @@ frame to be redrawn only if it is a tty frame. */);
7560 defsubr (&Swindow_new_normal); 8657 defsubr (&Swindow_new_normal);
7561 defsubr (&Sset_window_new_total); 8658 defsubr (&Sset_window_new_total);
7562 defsubr (&Sset_window_new_normal); 8659 defsubr (&Sset_window_new_normal);
8660 defsubr (&Sresize_window_apply);
7563 defsubr (&Swindow_body_size); 8661 defsubr (&Swindow_body_size);
7564 defsubr (&Swindow_hscroll); 8662 defsubr (&Swindow_hscroll);
7565 defsubr (&Sset_window_hscroll); 8663 defsubr (&Sset_window_hscroll);
@@ -7590,12 +8688,17 @@ frame to be redrawn only if it is a tty frame. */);
7590 defsubr (&Sdelete_windows_on); 8688 defsubr (&Sdelete_windows_on);
7591 defsubr (&Sreplace_buffer_in_windows); 8689 defsubr (&Sreplace_buffer_in_windows);
7592 defsubr (&Sdelete_window); 8690 defsubr (&Sdelete_window);
8691 defsubr (&Sdelete_other_windows_internal);
8692 defsubr (&Sdelete_window_internal);
8693 defsubr (&Sresize_mini_window_internal);
7593 defsubr (&Sset_window_buffer); 8694 defsubr (&Sset_window_buffer);
7594 defsubr (&Sset_window_clone_number); 8695 defsubr (&Sset_window_clone_number);
8696 defsubr (&Srun_window_configuration_change_hook);
7595 defsubr (&Sselect_window); 8697 defsubr (&Sselect_window);
7596 defsubr (&Sforce_window_update); 8698 defsubr (&Sforce_window_update);
7597 defsubr (&Stemp_output_buffer_show); 8699 defsubr (&Stemp_output_buffer_show);
7598 defsubr (&Ssplit_window); 8700 defsubr (&Ssplit_window);
8701 defsubr (&Ssplit_window_internal);
7599 defsubr (&Senlarge_window); 8702 defsubr (&Senlarge_window);
7600 defsubr (&Sshrink_window); 8703 defsubr (&Sshrink_window);
7601 defsubr (&Sadjust_window_trailing_edge); 8704 defsubr (&Sadjust_window_trailing_edge);