aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Moellmann1999-08-15 22:00:53 +0000
committerGerd Moellmann1999-08-15 22:00:53 +0000
commit233a4a2c3f36a526e564017a80ce313ea15903ea (patch)
treeea63c40db0c29336db08daeb2168afd257b11b20 /src
parent20c1822ee6e245f4c53e2ee501b76d104bb915d8 (diff)
downloademacs-233a4a2c3f36a526e564017a80ce313ea15903ea.tar.gz
emacs-233a4a2c3f36a526e564017a80ce313ea15903ea.zip
(Qfixed_window_size): New.
(syms_of_window): Initialiaze it. (check_all_windows): Add return type void. (window_fixed_size_p): New. Return non-zero if window is fixed-size. (window_min_size_1): New. (window_min_size): Handle fixed-size windows. (size_window): New. Rewritten combination of set_window_height and set_window_width that handles fixed-size windows. (set_window_height): Call it. (set_window_width): Call it. (Fsplit_window): Give an error on attempt to split a fixed-size window. (change_window_height): Partly rewritten to handle fixed-size windows.
Diffstat (limited to 'src')
-rw-r--r--src/window.c613
1 files changed, 453 insertions, 160 deletions
diff --git a/src/window.c b/src/window.c
index 5153ea191e2..5c0abd6e93d 100644
--- a/src/window.c
+++ b/src/window.c
@@ -43,6 +43,8 @@ Boston, MA 02111-1307, USA. */
43 43
44 44
45Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p; 45Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
46Lisp_Object Qfixed_window_size;
47extern Lisp_Object Qheight, Qwidth;
46 48
47static struct window *decode_window P_ ((Lisp_Object)); 49static struct window *decode_window P_ ((Lisp_Object));
48static Lisp_Object select_window_1 P_ ((Lisp_Object, int)); 50static Lisp_Object select_window_1 P_ ((Lisp_Object, int));
@@ -51,7 +53,10 @@ static int get_leaf_windows P_ ((struct window *, struct window **, int));
51static void window_scroll P_ ((Lisp_Object, int, int, int)); 53static void window_scroll P_ ((Lisp_Object, int, int, int));
52static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int)); 54static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
53static void window_scroll_line_based P_ ((Lisp_Object, int, int, int)); 55static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
54static int window_min_size P_ ((struct window *, int)); 56static int window_min_size_1 P_ ((struct window *, int));
57static int window_min_size P_ ((struct window *, int, int *));
58static int window_fixed_size_p P_ ((struct window *, int, int));
59static void size_window P_ ((Lisp_Object, int, int, int));
55 60
56 61
57/* This is the window in which the terminal's cursor should 62/* This is the window in which the terminal's cursor should
@@ -1655,6 +1660,7 @@ window_loop (type, obj, mini, frames)
1655 1660
1656/* Used for debugging. Abort if any window has a dead buffer. */ 1661/* Used for debugging. Abort if any window has a dead buffer. */
1657 1662
1663void
1658check_all_windows () 1664check_all_windows ()
1659{ 1665{
1660 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt); 1666 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
@@ -1885,189 +1891,412 @@ check_frame_size (frame, rows, cols)
1885} 1891}
1886 1892
1887 1893
1888/* Return the minimum size of window W. WIDTH_P non-zero means 1894/* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
1889 return the minimum width, otherwise return the minimum height. */ 1895 check if W's width can be changed, otherwise check W's height.
1896 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
1897 siblings, too. If none of the siblings is resizable, WINDOW isn't
1898 either. */
1890 1899
1891static INLINE int 1900static int
1892window_min_size (w, width_p) 1901window_fixed_size_p (w, width_p, check_siblings_p)
1902 struct window *w;
1903 int width_p, check_siblings_p;
1904{
1905 int fixed_p;
1906 struct window *c;
1907
1908 if (!NILP (w->hchild))
1909 {
1910 c = XWINDOW (w->hchild);
1911
1912 if (width_p)
1913 {
1914 /* A horiz. combination is fixed-width if all of if its
1915 children are. */
1916 while (c && window_fixed_size_p (c, width_p, 0))
1917 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1918 fixed_p = c == NULL;
1919 }
1920 else
1921 {
1922 /* A horiz. combination is fixed-height if one of if its
1923 children is. */
1924 while (c && !window_fixed_size_p (c, width_p, 0))
1925 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1926 fixed_p = c != NULL;
1927 }
1928 }
1929 else if (!NILP (w->vchild))
1930 {
1931 c = XWINDOW (w->vchild);
1932
1933 if (width_p)
1934 {
1935 /* A vert. combination is fixed-width if one of if its
1936 children is. */
1937 while (c && !window_fixed_size_p (c, width_p, 0))
1938 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1939 fixed_p = c != NULL;
1940 }
1941 else
1942 {
1943 /* A vert. combination is fixed-height if all of if its
1944 children are. */
1945 while (c && window_fixed_size_p (c, width_p, 0))
1946 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1947 fixed_p = c == NULL;
1948 }
1949 }
1950 else if (BUFFERP (w->buffer))
1951 {
1952 Lisp_Object val;
1953 struct buffer *old = current_buffer;
1954
1955 current_buffer = XBUFFER (w->buffer);
1956 val = find_symbol_value (Qfixed_window_size);
1957 current_buffer = old;
1958
1959 fixed_p = 0;
1960 if (!EQ (val, Qunbound))
1961 {
1962 fixed_p = !NILP (val);
1963
1964 if (fixed_p
1965 && ((EQ (val, Qheight) && width_p)
1966 || (EQ (val, Qwidth) && !width_p)))
1967 fixed_p = 0;
1968 }
1969
1970 /* Can't tell if this one is resizable without looking at
1971 siblings. If all siblings are fixed-size this one is too. */
1972 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
1973 {
1974 Lisp_Object child;
1975
1976 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
1977 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
1978 break;
1979
1980 if (NILP (child))
1981 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
1982 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
1983 break;
1984
1985 if (NILP (child))
1986 fixed_p = 1;
1987 }
1988 }
1989 else
1990 fixed_p = 1;
1991
1992 return fixed_p;
1993}
1994
1995
1996/* Return the minimum size of window W, not taking fixed-width windows
1997 into account. WIDTH_P non-zero means return the minimum width,
1998 otherwise return the minimum height. If W is a combination window,
1999 compute the minimum size from the minimum sizes of W's children. */
2000
2001static int
2002window_min_size_1 (w, width_p)
1893 struct window *w; 2003 struct window *w;
1894 int width_p; 2004 int width_p;
1895{ 2005{
2006 struct window *c;
1896 int size; 2007 int size;
1897 2008
1898 if (width_p) 2009 if (!NILP (w->hchild))
1899 size = window_min_width; 2010 {
2011 c = XWINDOW (w->hchild);
2012 size = 0;
2013
2014 if (width_p)
2015 {
2016 /* The min width of a horizontal combination is
2017 the sum of the min widths of its children. */
2018 while (c)
2019 {
2020 size += window_min_size_1 (c, width_p);
2021 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2022 }
2023 }
2024 else
2025 {
2026 /* The min height a horizontal combination equals
2027 the maximum of all min height of its children. */
2028 while (c)
2029 {
2030 int min_size = window_min_size_1 (c, width_p);
2031 size = max (min_size, size);
2032 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2033 }
2034 }
2035 }
2036 else if (!NILP (w->vchild))
2037 {
2038 c = XWINDOW (w->vchild);
2039 size = 0;
2040
2041 if (width_p)
2042 {
2043 /* The min width of a vertical combination is
2044 the maximum of the min widths of its children. */
2045 while (c)
2046 {
2047 int min_size = window_min_size_1 (c, width_p);
2048 size = max (min_size, size);
2049 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2050 }
2051 }
2052 else
2053 {
2054 /* The min height of a vertical combination equals
2055 the sum of the min height of its children. */
2056 while (c)
2057 {
2058 size += window_min_size_1 (c, width_p);
2059 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2060 }
2061 }
2062 }
1900 else 2063 else
1901 { 2064 {
1902 if (MINI_WINDOW_P (w) 2065 if (width_p)
1903 || (!WINDOW_WANTS_MODELINE_P (w) 2066 size = window_min_width;
1904 && !WINDOW_WANTS_TOP_LINE_P (w)))
1905 size = 1;
1906 else 2067 else
1907 size = window_min_height; 2068 {
2069 if (MINI_WINDOW_P (w)
2070 || (!WINDOW_WANTS_MODELINE_P (w)
2071 && !WINDOW_WANTS_TOP_LINE_P (w)))
2072 size = 1;
2073 else
2074 size = window_min_height;
2075 }
1908 } 2076 }
1909 2077
1910 return size; 2078 return size;
1911} 2079}
1912 2080
1913 2081
1914/* Normally the window is deleted if it gets too small. nodelete 2082/* Return the minimum size of window W, taking fixed-size windows into
1915 nonzero means do not do this. (The caller should check later and 2083 account. WIDTH_P non-zero means return the minimum width,
1916 do so if appropriate) */ 2084 otherwise return the minimum height. Set *FIXED to 1 if W is
2085 fixed-size unless FIXED is null. */
1917 2086
1918void 2087static int
1919set_window_height (window, height, nodelete) 2088window_min_size (w, width_p, fixed)
2089 struct window *w;
2090 int width_p, *fixed;
2091{
2092 int size, fixed_p;
2093
2094 fixed_p = window_fixed_size_p (w, width_p, 1);
2095 if (fixed)
2096 *fixed = fixed_p;
2097
2098 if (fixed_p)
2099 size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
2100 else
2101 size = window_min_size_1 (w, width_p);
2102
2103 return size;
2104}
2105
2106
2107/* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2108 WINDOW's width. Resize WINDOW's children, if any, so that they
2109 keep their proportionate size relative to WINDOW. Propagate
2110 WINDOW's top or left edge position to children. Delete windows
2111 that become too small unless NODELETE_P is non-zero. */
2112
2113static void
2114size_window (window, size, width_p, nodelete_p)
1920 Lisp_Object window; 2115 Lisp_Object window;
1921 int height; 2116 int size, width_p, nodelete_p;
1922 int nodelete;
1923{ 2117{
1924 register struct window *w = XWINDOW (window); 2118 struct window *w = XWINDOW (window);
1925 register struct window *c; 2119 struct window *c;
1926 int oheight = XFASTINT (w->height); 2120 Lisp_Object child, *forward, *sideward;
1927 int top, pos, lastbot, opos, lastobot; 2121 int old_size, min_size;
1928 Lisp_Object child;
1929 2122
1930 check_min_window_sizes (); 2123 check_min_window_sizes ();
1931 2124
1932 /* If the window has been "too small" at one point, 2125 /* If the window has been "too small" at one point,
1933 don't delete it for being "too small" in the future. 2126 don't delete it for being "too small" in the future.
1934 Preserve it as long as that is at all possible. */ 2127 Preserve it as long as that is at all possible. */
1935 if (oheight < window_min_height) 2128 if (width_p)
2129 {
2130 old_size = XFASTINT (w->width);
2131 min_size = window_min_width;
2132 }
2133 else
2134 {
2135 old_size = XFASTINT (w->height);
2136 min_size = window_min_height;
2137 }
2138
2139 if (old_size < window_min_width)
1936 w->too_small_ok = Qt; 2140 w->too_small_ok = Qt;
1937 2141
1938 if (!nodelete && !NILP (w->parent)) 2142 /* Maybe delete WINDOW if it's too small. */
2143 if (!nodelete_p && !NILP (w->parent))
1939 { 2144 {
1940 int min_height; 2145 int min_size;
1941 2146
1942 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok)) 2147 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
1943 min_height = MIN_SAFE_WINDOW_HEIGHT; 2148 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
1944 else 2149 else
1945 min_height = window_min_size (w, 0); 2150 min_size = width_p ? window_min_width : window_min_height;
1946 2151
1947 if (height < min_height) 2152 if (size < min_size)
1948 { 2153 {
1949 delete_window (window); 2154 delete_window (window);
1950 return; 2155 return;
1951 } 2156 }
1952 } 2157 }
1953 2158
2159 /* Set redisplay hints. */
1954 XSETFASTINT (w->last_modified, 0); 2160 XSETFASTINT (w->last_modified, 0);
1955 XSETFASTINT (w->last_overlay_modified, 0); 2161 XSETFASTINT (w->last_overlay_modified, 0);
1956 windows_or_buffers_changed++; 2162 windows_or_buffers_changed++;
1957 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1; 2163 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
1958 2164
1959 XSETFASTINT (w->height, height); 2165 if (width_p)
1960 if (!NILP (w->hchild)) 2166 {
2167 sideward = &w->vchild;
2168 forward = &w->hchild;
2169 XSETFASTINT (w->width, size);
2170 }
2171 else
2172 {
2173 sideward = &w->hchild;
2174 forward = &w->vchild;
2175 XSETFASTINT (w->height, size);
2176 }
2177
2178 if (!NILP (*sideward))
1961 { 2179 {
1962 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next) 2180 for (child = *sideward; !NILP (child); child = c->next)
1963 { 2181 {
1964 XWINDOW (child)->top = w->top; 2182 c = XWINDOW (child);
1965 set_window_height (child, height, nodelete); 2183 if (width_p)
2184 c->left = w->left;
2185 else
2186 c->top = w->top;
2187 size_window (child, size, width_p, nodelete_p);
1966 } 2188 }
1967 } 2189 }
1968 else if (!NILP (w->vchild)) 2190 else if (!NILP (*forward))
1969 { 2191 {
1970 lastbot = top = XFASTINT (w->top); 2192 int fixed_size, each, extra, n;
1971 lastobot = 0; 2193 int resize_fixed_p, nfixed;
1972 for (child = w->vchild; !NILP (child); child = c->next) 2194 int last_pos, first_pos, nchildren;
2195
2196 /* Determine the fixed-size portion of the this window, and the
2197 number of child windows. */
2198 fixed_size = nchildren = nfixed = 0;
2199 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
1973 { 2200 {
1974 c = XWINDOW (child); 2201 c = XWINDOW (child);
2202 if (window_fixed_size_p (c, width_p, 0))
2203 {
2204 fixed_size += (width_p
2205 ? XFASTINT (c->width) : XFASTINT (c->height));
2206 ++nfixed;
2207 }
2208 }
1975 2209
1976 opos = lastobot + XFASTINT (c->height); 2210 /* If the new size is smaller than fixed_size, or if there
1977 2211 aren't any resizable windows, allow resizing fixed-size
1978 XSETFASTINT (c->top, lastbot); 2212 windows. */
1979 2213 resize_fixed_p = nfixed == nchildren || size < fixed_size;
1980 pos = (((opos * height) << 1) + oheight) / (oheight << 1); 2214
2215 /* Compute how many lines/columns to add to each child. The
2216 value of extra takes care of rounding errors. */
2217 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2218 each = (size - old_size) / n;
2219 extra = (size - old_size) - n * each;
2220
2221 /* Compute new children heights and edge positions. */
2222 first_pos = width_p ? XFASTINT (w->left) : XFASTINT (w->top);
2223 last_pos = first_pos;
2224 for (child = *forward; !NILP (child); child = c->next)
2225 {
2226 int new_size, old_size;
2227
2228 c = XWINDOW (child);
2229 old_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2230 new_size = old_size;
1981 2231
1982 /* Avoid confusion: inhibit deletion of child if becomes too small */ 2232 /* The top or left edge position of this child equals the
1983 set_window_height (child, pos + top - lastbot, 1); 2233 bottom or right edge of its predecessor. */
2234 if (width_p)
2235 c->left = make_number (last_pos);
2236 else
2237 c->top = make_number (last_pos);
1984 2238
1985 /* Now advance child to next window, 2239 /* If this child can be resized, do it. */
1986 and set lastbot if child was not just deleted. */ 2240 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
1987 lastbot = pos + top; 2241 {
1988 lastobot = opos; 2242 new_size = old_size + each + extra;
2243 extra = 0;
2244 }
2245
2246 /* Set new height. Note that size_window also propagates
2247 edge positions to children, so it's not a no-op if we
2248 didn't change the child's size. */
2249 size_window (child, new_size, width_p, 1);
2250
2251 /* Remember the bottom/right edge position of this child; it
2252 will be used to set the top/left edge of the next child. */
2253 last_pos += new_size;
1989 } 2254 }
2255
2256 /* We should have covered the parent exactly with child windows. */
2257 xassert (size == last_pos - first_pos);
2258
1990 /* Now delete any children that became too small. */ 2259 /* Now delete any children that became too small. */
1991 if (!nodelete) 2260 if (!nodelete_p)
1992 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next) 2261 for (child = *forward; !NILP (child); child = c->next)
1993 { 2262 {
1994 set_window_height (child, XINT (XWINDOW (child)->height), 0); 2263 int child_size;
2264 c = XWINDOW (child);
2265 child_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2266 size_window (child, child_size, width_p, 0);
1995 } 2267 }
1996 } 2268 }
1997} 2269}
1998 2270
1999/* Recursively set width of WINDOW and its inferiors. */ 2271/* Set WINDOW's height to HEIGHT, and recursively change the height of
2272 WINDOW's children. NODELETE non-zero means don't delete windows
2273 that become too small in the process. (The caller should check
2274 later and do so if appropriate.) */
2000 2275
2001void 2276void
2002set_window_width (window, width, nodelete) 2277set_window_height (window, height, nodelete)
2003 Lisp_Object window; 2278 Lisp_Object window;
2004 int width; 2279 int height;
2005 int nodelete; 2280 int nodelete;
2006{ 2281{
2007 register struct window *w = XWINDOW (window); 2282 size_window (window, height, 0, nodelete);
2008 register struct window *c; 2283}
2009 int owidth = XFASTINT (w->width);
2010 int left, pos, lastright, opos, lastoright;
2011 Lisp_Object child;
2012
2013 /* If the window has been "too small" at one point,
2014 don't delete it for being "too small" in the future.
2015 Preserve it as long as that is at all possible. */
2016 if (owidth < window_min_width)
2017 w->too_small_ok = Qt;
2018
2019 if (!nodelete && !NILP (w->parent)
2020 && (! NILP (w->too_small_ok)
2021 ? width < MIN_SAFE_WINDOW_WIDTH
2022 : width < window_min_width))
2023 {
2024 delete_window (window);
2025 return;
2026 }
2027
2028 XSETFASTINT (w->last_modified, 0);
2029 XSETFASTINT (w->last_overlay_modified, 0);
2030 windows_or_buffers_changed++;
2031 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
2032
2033 XSETFASTINT (w->width, width);
2034 if (!NILP (w->vchild))
2035 {
2036 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
2037 {
2038 XWINDOW (child)->left = w->left;
2039 set_window_width (child, width, nodelete);
2040 }
2041 }
2042 else if (!NILP (w->hchild))
2043 {
2044 lastright = left = XFASTINT (w->left);
2045 lastoright = 0;
2046 for (child = w->hchild; !NILP (child); child = c->next)
2047 {
2048 c = XWINDOW (child);
2049
2050 opos = lastoright + XFASTINT (c->width);
2051
2052 XSETFASTINT (c->left, lastright);
2053 2284
2054 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
2055 2285
2056 /* Inhibit deletion for becoming too small */ 2286/* Set WINDOW's width to WIDTH, and recursively change the width of
2057 set_window_width (child, pos + left - lastright, 1); 2287 WINDOW's children. NODELETE non-zero means don't delete windows
2288 that become too small in the process. (The caller should check
2289 later and do so if appropriate.) */
2058 2290
2059 /* Now advance child to next window, 2291void
2060 and set lastright if child was not just deleted. */ 2292set_window_width (window, width, nodelete)
2061 lastright = pos + left, lastoright = opos; 2293 Lisp_Object window;
2062 } 2294 int width;
2063 /* Delete children that became too small */ 2295 int nodelete;
2064 if (!nodelete) 2296{
2065 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next) 2297 size_window (window, width, 1, nodelete);
2066 {
2067 set_window_width (child, XINT (XWINDOW (child)->width), 0);
2068 }
2069 }
2070} 2298}
2299
2071 2300
2072int window_select_count; 2301int window_select_count;
2073 2302
@@ -2677,6 +2906,8 @@ SIZE includes that window's scroll bar, or the divider column to its right.")
2677 2906
2678 if (MINI_WINDOW_P (o)) 2907 if (MINI_WINDOW_P (o))
2679 error ("Attempt to split minibuffer window"); 2908 error ("Attempt to split minibuffer window");
2909 else if (window_fixed_size_p (o, !NILP (horflag), 0))
2910 error ("Attempt to split fixed-size window");
2680 2911
2681 check_min_window_sizes (); 2912 check_min_window_sizes ();
2682 2913
@@ -2810,42 +3041,51 @@ window_width (window)
2810#define CURSIZE(w) \ 3041#define CURSIZE(w) \
2811 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height)) 3042 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
2812 3043
2813/* Unlike set_window_height, this function 3044
2814 also changes the heights of the siblings so as to 3045/* Enlarge selected_window by DELTA. WIDTHFLAG non-zero means
2815 keep everything consistent. */ 3046 increase its width. Siblings of the selected window are resized to
3047 fullfil the size request. If they become too small in the process,
3048 they will be deleted. */
2816 3049
2817void 3050void
2818change_window_height (delta, widthflag) 3051change_window_height (delta, widthflag)
2819 register int delta; 3052 int delta, widthflag;
2820 int widthflag;
2821{ 3053{
2822 register Lisp_Object parent; 3054 Lisp_Object parent, window, next, prev;
2823 Lisp_Object window; 3055 struct window *p;
2824 register struct window *p; 3056 int *sizep, maximum;
2825 int *sizep;
2826 int (*sizefun) P_ ((Lisp_Object)) 3057 int (*sizefun) P_ ((Lisp_Object))
2827 = widthflag ? window_width : window_height; 3058 = widthflag ? window_width : window_height;
2828 register void (*setsizefun) P_ ((Lisp_Object, int, int)) 3059 void (*setsizefun) P_ ((Lisp_Object, int, int))
2829 = (widthflag ? set_window_width : set_window_height); 3060 = (widthflag ? set_window_width : set_window_height);
2830 int maximum;
2831 Lisp_Object next, prev;
2832 3061
3062 /* Check values of window_min_width and window_min_height for
3063 validity. */
2833 check_min_window_sizes (); 3064 check_min_window_sizes ();
2834 3065
3066 /* Give up if this window cannot be resized. */
2835 window = selected_window; 3067 window = selected_window;
3068 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3069 error ("Window is not resizable");
3070
3071 /* Find the parent of the selected window. */
2836 while (1) 3072 while (1)
2837 { 3073 {
2838 p = XWINDOW (window); 3074 p = XWINDOW (window);
2839 parent = p->parent; 3075 parent = p->parent;
3076
2840 if (NILP (parent)) 3077 if (NILP (parent))
2841 { 3078 {
2842 if (widthflag) 3079 if (widthflag)
2843 error ("No other window to side of this one"); 3080 error ("No other window to side of this one");
2844 break; 3081 break;
2845 } 3082 }
2846 if (widthflag ? !NILP (XWINDOW (parent)->hchild) 3083
3084 if (widthflag
3085 ? !NILP (XWINDOW (parent)->hchild)
2847 : !NILP (XWINDOW (parent)->vchild)) 3086 : !NILP (XWINDOW (parent)->vchild))
2848 break; 3087 break;
3088
2849 window = parent; 3089 window = parent;
2850 } 3090 }
2851 3091
@@ -2857,10 +3097,10 @@ change_window_height (delta, widthflag)
2857 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep 3097 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
2858 : !NILP (p->next) ? ((*sizefun) (p->next) 3098 : !NILP (p->next) ? ((*sizefun) (p->next)
2859 - window_min_size (XWINDOW (p->next), 3099 - window_min_size (XWINDOW (p->next),
2860 widthflag)) 3100 widthflag, 0))
2861 : !NILP (p->prev) ? ((*sizefun) (p->prev) 3101 : !NILP (p->prev) ? ((*sizefun) (p->prev)
2862 - window_min_size (XWINDOW (p->prev), 3102 - window_min_size (XWINDOW (p->prev),
2863 widthflag)) 3103 widthflag, 0))
2864 /* This is a frame with only one window, a minibuffer-only 3104 /* This is a frame with only one window, a minibuffer-only
2865 or a minibufferless frame. */ 3105 or a minibufferless frame. */
2866 : (delta = 0)); 3106 : (delta = 0));
@@ -2872,7 +3112,7 @@ change_window_height (delta, widthflag)
2872 delta = maxdelta; 3112 delta = maxdelta;
2873 } 3113 }
2874 3114
2875 if (*sizep + delta < window_min_size (XWINDOW (window), widthflag)) 3115 if (*sizep + delta < window_min_size (XWINDOW (window), widthflag, 0))
2876 { 3116 {
2877 delete_window (window); 3117 delete_window (window);
2878 return; 3118 return;
@@ -2885,16 +3125,17 @@ change_window_height (delta, widthflag)
2885 maximum = 0; 3125 maximum = 0;
2886 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next) 3126 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
2887 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next), 3127 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
2888 widthflag); 3128 widthflag, 0);
2889 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev) 3129 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
2890 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev), 3130 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
2891 widthflag); 3131 widthflag, 0);
2892 3132
2893 /* If we can get it all from them, do so. */ 3133 /* If we can get it all from them, do so. */
2894 if (delta <= maximum) 3134 if (delta <= maximum)
2895 { 3135 {
2896 Lisp_Object first_unaffected; 3136 Lisp_Object first_unaffected;
2897 Lisp_Object first_affected; 3137 Lisp_Object first_affected;
3138 int fixed_p;
2898 3139
2899 next = p->next; 3140 next = p->next;
2900 prev = p->prev; 3141 prev = p->prev;
@@ -2902,42 +3143,54 @@ change_window_height (delta, widthflag)
2902 /* Look at one sibling at a time, 3143 /* Look at one sibling at a time,
2903 moving away from this window in both directions alternately, 3144 moving away from this window in both directions alternately,
2904 and take as much as we can get without deleting that sibling. */ 3145 and take as much as we can get without deleting that sibling. */
2905 while (delta != 0) 3146 while (delta != 0 && (!NILP (next) || !NILP (prev)))
2906 { 3147 {
2907 if (delta == 0)
2908 break;
2909 if (! NILP (next)) 3148 if (! NILP (next))
2910 { 3149 {
2911 int this_one = ((*sizefun) (next) 3150 int this_one = ((*sizefun) (next)
2912 - window_min_size (XWINDOW (next), widthflag)); 3151 - window_min_size (XWINDOW (next),
2913 if (this_one > delta) 3152 widthflag, &fixed_p));
2914 this_one = delta; 3153 if (!fixed_p)
2915 3154 {
2916 (*setsizefun) (next, (*sizefun) (next) - this_one, 0); 3155 if (this_one > delta)
2917 (*setsizefun) (window, *sizep + this_one, 0); 3156 this_one = delta;
3157
3158 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3159 (*setsizefun) (window, *sizep + this_one, 0);
2918 3160
2919 delta -= this_one; 3161 delta -= this_one;
3162 }
3163
2920 next = XWINDOW (next)->next; 3164 next = XWINDOW (next)->next;
2921 } 3165 }
3166
2922 if (delta == 0) 3167 if (delta == 0)
2923 break; 3168 break;
3169
2924 if (! NILP (prev)) 3170 if (! NILP (prev))
2925 { 3171 {
2926 int this_one = ((*sizefun) (prev) 3172 int this_one = ((*sizefun) (prev)
2927 - window_min_size (XWINDOW (prev), widthflag)); 3173 - window_min_size (XWINDOW (prev),
2928 if (this_one > delta) 3174 widthflag, &fixed_p));
2929 this_one = delta; 3175 if (!fixed_p)
2930 3176 {
2931 first_affected = prev; 3177 if (this_one > delta)
2932 3178 this_one = delta;
2933 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0); 3179
2934 (*setsizefun) (window, *sizep + this_one, 0); 3180 first_affected = prev;
2935 3181
2936 delta -= this_one; 3182 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3183 (*setsizefun) (window, *sizep + this_one, 0);
3184
3185 delta -= this_one;
3186 }
3187
2937 prev = XWINDOW (prev)->prev; 3188 prev = XWINDOW (prev)->prev;
2938 } 3189 }
2939 } 3190 }
2940 3191
3192 xassert (delta == 0);
3193
2941 /* Now recalculate the edge positions of all the windows affected, 3194 /* Now recalculate the edge positions of all the windows affected,
2942 based on the new sizes. */ 3195 based on the new sizes. */
2943 first_unaffected = next; 3196 first_unaffected = next;
@@ -2961,12 +3214,49 @@ change_window_height (delta, widthflag)
2961 all the siblings end up with less than one line and are deleted. */ 3214 all the siblings end up with less than one line and are deleted. */
2962 if (opht <= *sizep + delta) 3215 if (opht <= *sizep + delta)
2963 delta1 = opht * opht * 2; 3216 delta1 = opht * opht * 2;
2964 /* Otherwise, make delta1 just right so that if we add delta1
2965 lines to this window and to the parent, and then shrink
2966 the parent back to its original size, the new proportional
2967 size of this window will increase by delta. */
2968 else 3217 else
2969 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100); 3218 {
3219 /* Otherwise, make delta1 just right so that if we add
3220 delta1 lines to this window and to the parent, and then
3221 shrink the parent back to its original size, the new
3222 proportional size of this window will increase by delta.
3223
3224 The function size_window will compute the new height h'
3225 of the window from delta1 as:
3226
3227 e = delta1/n
3228 x = delta1 - delta1/n * n for the 1st resizable child
3229 h' = h + e + x
3230
3231 where n is the number of children that can be resized.
3232 We can ignore x by choosing a delta1 that is a multiple of
3233 n. We want the height of this window to come out as
3234
3235 h' = h + delta
3236
3237 So, delta1 must be
3238
3239 h + e = h + delta
3240 delta1/n = delta
3241 delta1 = n * delta.
3242
3243 The number of children n rquals the number of resizable
3244 children of this window + 1 because we know window itself
3245 is resizable (otherwise we would have signalled an error. */
3246
3247 struct window *w = XWINDOW (window);
3248 Lisp_Object s;
3249 int n = 1;
3250
3251 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3252 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3253 ++n;
3254 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3255 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3256 ++n;
3257
3258 delta1 = n * delta;
3259 }
2970 3260
2971 /* Add delta1 lines or columns to this window, and to the parent, 3261 /* Add delta1 lines or columns to this window, and to the parent,
2972 keeping things consistent while not affecting siblings. */ 3262 keeping things consistent while not affecting siblings. */
@@ -4514,6 +4804,9 @@ init_window_once ()
4514void 4804void
4515syms_of_window () 4805syms_of_window ()
4516{ 4806{
4807 Qfixed_window_size = intern ("fixed-window-size");
4808 staticpro (&Qfixed_window_size);
4809
4517 staticpro (&Qwindow_configuration_change_hook); 4810 staticpro (&Qwindow_configuration_change_hook);
4518 Qwindow_configuration_change_hook 4811 Qwindow_configuration_change_hook
4519 = intern ("window-configuration-change-hook"); 4812 = intern ("window-configuration-change-hook");