diff options
| author | Gerd Moellmann | 1999-08-15 22:00:53 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 1999-08-15 22:00:53 +0000 |
| commit | 233a4a2c3f36a526e564017a80ce313ea15903ea (patch) | |
| tree | ea63c40db0c29336db08daeb2168afd257b11b20 /src | |
| parent | 20c1822ee6e245f4c53e2ee501b76d104bb915d8 (diff) | |
| download | emacs-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.c | 613 |
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 | ||
| 45 | Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p; | 45 | Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p; |
| 46 | Lisp_Object Qfixed_window_size; | ||
| 47 | extern Lisp_Object Qheight, Qwidth; | ||
| 46 | 48 | ||
| 47 | static struct window *decode_window P_ ((Lisp_Object)); | 49 | static struct window *decode_window P_ ((Lisp_Object)); |
| 48 | static Lisp_Object select_window_1 P_ ((Lisp_Object, int)); | 50 | static Lisp_Object select_window_1 P_ ((Lisp_Object, int)); |
| @@ -51,7 +53,10 @@ static int get_leaf_windows P_ ((struct window *, struct window **, int)); | |||
| 51 | static void window_scroll P_ ((Lisp_Object, int, int, int)); | 53 | static void window_scroll P_ ((Lisp_Object, int, int, int)); |
| 52 | static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int)); | 54 | static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int)); |
| 53 | static void window_scroll_line_based P_ ((Lisp_Object, int, int, int)); | 55 | static void window_scroll_line_based P_ ((Lisp_Object, int, int, int)); |
| 54 | static int window_min_size P_ ((struct window *, int)); | 56 | static int window_min_size_1 P_ ((struct window *, int)); |
| 57 | static int window_min_size P_ ((struct window *, int, int *)); | ||
| 58 | static int window_fixed_size_p P_ ((struct window *, int, int)); | ||
| 59 | static 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 | ||
| 1663 | void | ||
| 1658 | check_all_windows () | 1664 | check_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 | ||
| 1891 | static INLINE int | 1900 | static int |
| 1892 | window_min_size (w, width_p) | 1901 | window_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 | |||
| 2001 | static int | ||
| 2002 | window_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 | ||
| 1918 | void | 2087 | static int |
| 1919 | set_window_height (window, height, nodelete) | 2088 | window_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 | |||
| 2113 | static void | ||
| 2114 | size_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 | ||
| 2001 | void | 2276 | void |
| 2002 | set_window_width (window, width, nodelete) | 2277 | set_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, | 2291 | void |
| 2060 | and set lastright if child was not just deleted. */ | 2292 | set_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 | ||
| 2072 | int window_select_count; | 2301 | int 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 | ||
| 2817 | void | 3050 | void |
| 2818 | change_window_height (delta, widthflag) | 3051 | change_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 () | |||
| 4514 | void | 4804 | void |
| 4515 | syms_of_window () | 4805 | syms_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"); |