Remove entry for comments-only change that was later mostly reverted.
[bpt/emacs.git] / src / window.c
CommitLineData
7ab12479
JB
1/* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
e68def1e 3 Copyright (C) 1985,86,87,93,94,95,96,97,1998,2000, 2001, 2002, 2003
6529ed87 4 Free Software Foundation, Inc.
7ab12479
JB
5
6This file is part of GNU Emacs.
7
8GNU Emacs is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
1113d9db 10the Free Software Foundation; either version 2, or (at your option)
7ab12479
JB
11any later version.
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
20the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21Boston, MA 02111-1307, USA. */
7ab12479 22
18160b98 23#include <config.h>
7ab12479
JB
24#include "lisp.h"
25#include "buffer.h"
3e4731a3 26#include "keyboard.h"
e35f6ff7 27#include "keymap.h"
44fa5b1e 28#include "frame.h"
7ab12479
JB
29#include "window.h"
30#include "commands.h"
31#include "indent.h"
32#include "termchar.h"
33#include "disptab.h"
dfcf069d 34#include "dispextern.h"
5500c422
GM
35#include "blockinput.h"
36#include "intervals.h"
37
6d55d620 38#ifdef HAVE_X_WINDOWS
dfcf069d 39#include "xterm.h"
5500c422 40#endif /* HAVE_X_WINDOWS */
8f23f280
AI
41#ifdef WINDOWSNT
42#include "w32term.h"
43#endif
1e3c8885
EZ
44#ifdef MSDOS
45#include "msdos.h"
46#endif
e0f712ba 47#ifdef MAC_OS
1a578e9b
AC
48#include "macterm.h"
49#endif
5500c422 50
5500c422 51
3f8ab7bd 52Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
90647b07 53Lisp_Object Qwindow_size_fixed;
49b996e7 54extern Lisp_Object Qleft_margin, Qright_margin;
7ab12479 55
521b203e 56static int displayed_window_lines P_ ((struct window *));
5e14b1fc 57static struct window *decode_window P_ ((Lisp_Object));
5500c422
GM
58static int count_windows P_ ((struct window *));
59static int get_leaf_windows P_ ((struct window *, struct window **, int));
60static void window_scroll P_ ((Lisp_Object, int, int, int));
61static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
62static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
233a4a2c 63static int window_min_size_1 P_ ((struct window *, int));
f984d4fc 64static int window_min_size P_ ((struct window *, int, int, int *));
233a4a2c 65static void size_window P_ ((Lisp_Object, int, int, int));
f95464e4 66static int freeze_window_start P_ ((struct window *, void *));
f984d4fc 67static int window_fixed_size_p P_ ((struct window *, int, int));
f95284d2 68static void enlarge_window P_ ((Lisp_Object, int, int, int));
67492200 69static Lisp_Object window_list P_ ((void));
f95464e4 70static int add_window_to_list P_ ((struct window *, void *));
118ea242
GM
71static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
72 Lisp_Object));
67492200
GM
73static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
74 Lisp_Object, int));
75static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
76 Lisp_Object *));
f95464e4
GM
77static int foreach_window_1 P_ ((struct window *,
78 int (* fn) (struct window *, void *),
79 void *));
cd2904bd 80static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
b7354ddf 81
b0b7ed0e
GM
82/* The value of `window-size-fixed'. */
83
84int window_size_fixed;
85
7ab12479
JB
86/* This is the window in which the terminal's cursor should
87 be left when nothing is being done with it. This must
88 always be a leaf window, and its buffer is selected by
89 the top level editing loop at the end of each command.
90
91 This value is always the same as
44fa5b1e 92 FRAME_SELECTED_WINDOW (selected_frame). */
7ab12479
JB
93
94Lisp_Object selected_window;
95
67492200
GM
96/* A list of all windows for use by next_window and Fwindow_list.
97 Functions creating or deleting windows should invalidate this cache
98 by setting it to nil. */
99
100Lisp_Object Vwindow_list;
101
5500c422
GM
102/* The mini-buffer window of the selected frame.
103 Note that you cannot test for mini-bufferness of an arbitrary window
104 by comparing against this; but you can test for mini-bufferness of
7ab12479 105 the selected window. */
5500c422 106
7ab12479
JB
107Lisp_Object minibuf_window;
108
3f49fddc
KS
109/* Non-nil means it is the window whose mode line should be
110 shown as the selected window when the minibuffer is selected. */
111
3dbab091 112Lisp_Object minibuf_selected_window;
3f49fddc 113
7ab12479 114/* Non-nil means it is the window for C-M-v to scroll
5500c422
GM
115 when the mini-buffer is selected. */
116
7ab12479
JB
117Lisp_Object Vminibuf_scroll_window;
118
119/* Non-nil means this is the buffer whose window C-M-v should scroll. */
5500c422 120
7ab12479
JB
121Lisp_Object Vother_window_scroll_buffer;
122
7ab12479 123/* Non-nil means it's function to call to display temp buffers. */
5500c422 124
7ab12479
JB
125Lisp_Object Vtemp_buffer_show_function;
126
cc91894c
KS
127/* Non-zero means to use mode-line-inactive face in all windows but the
128 selected-window and the minibuffer-scroll-window when the
129 minibuffer is active. */
130int mode_line_in_non_selected_windows;
26124d5e 131
7ab12479 132/* If a window gets smaller than either of these, it is removed. */
5500c422 133
31ade731
SM
134EMACS_INT window_min_height;
135EMACS_INT window_min_width;
7ab12479
JB
136
137/* Nonzero implies Fdisplay_buffer should create windows. */
5500c422 138
7ab12479
JB
139int pop_up_windows;
140
44fa5b1e 141/* Nonzero implies make new frames for Fdisplay_buffer. */
5500c422 142
44fa5b1e 143int pop_up_frames;
7ab12479 144
9c3da604
GM
145/* Nonzero means reuse existing frames for displaying buffers. */
146
147int display_buffer_reuse_frames;
148
7ab12479 149/* Non-nil means use this function instead of default */
5500c422 150
44fa5b1e 151Lisp_Object Vpop_up_frame_function;
7ab12479
JB
152
153/* Function to call to handle Fdisplay_buffer. */
5500c422 154
7ab12479
JB
155Lisp_Object Vdisplay_buffer_function;
156
6529ed87
GM
157/* Non-nil means that Fdisplay_buffer should even the heights of windows. */
158
159Lisp_Object Veven_window_heights;
160
a90712c2 161/* List of buffer *names* for buffers that should have their own frames. */
5500c422 162
a90712c2
RS
163Lisp_Object Vspecial_display_buffer_names;
164
165/* List of regexps for buffer names that should have their own frames. */
5500c422 166
a90712c2
RS
167Lisp_Object Vspecial_display_regexps;
168
169/* Function to pop up a special frame. */
5500c422 170
a90712c2
RS
171Lisp_Object Vspecial_display_function;
172
855d8627 173/* List of buffer *names* for buffers to appear in selected window. */
5500c422 174
855d8627
RS
175Lisp_Object Vsame_window_buffer_names;
176
177/* List of regexps for buffer names to appear in selected window. */
5500c422 178
855d8627
RS
179Lisp_Object Vsame_window_regexps;
180
a58ec57d 181/* Hook run at end of temp_output_buffer_show. */
5500c422 182
a58ec57d
RS
183Lisp_Object Qtemp_buffer_show_hook;
184
37962e60 185/* Fdisplay_buffer always splits the largest window
7ab12479 186 if that window is more than this high. */
5500c422 187
31ade731 188EMACS_INT split_height_threshold;
7ab12479
JB
189
190/* Number of lines of continuity in scrolling by screenfuls. */
5500c422 191
31ade731 192EMACS_INT next_screen_context_lines;
7ab12479
JB
193
194/* Incremented for each window created. */
5500c422 195
7ab12479
JB
196static int sequence_number;
197
5b03d3c0 198/* Nonzero after init_window_once has finished. */
5500c422 199
5b03d3c0
RS
200static int window_initialized;
201
543f5fb1 202/* Hook to run when window config changes. */
5500c422 203
543f5fb1
RS
204Lisp_Object Qwindow_configuration_change_hook;
205Lisp_Object Vwindow_configuration_change_hook;
206
9317a85d
RS
207/* Nonzero means scroll commands try to put point
208 at the same screen height as previously. */
9317a85d 209
5500c422
GM
210Lisp_Object Vscroll_preserve_screen_position;
211
212#if 0 /* This isn't used anywhere. */
91a78190 213/* Nonzero means we can split a frame even if it is "unsplittable". */
eddd51c2 214static int inhibit_frame_unsplittable;
5500c422 215#endif /* 0 */
7d601aaa 216
31ade731 217extern EMACS_INT scroll_margin;
9317a85d 218
dba06815 219extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
7ab12479
JB
220\f
221DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
fdb82f93
PJ
222 doc: /* Returns t if OBJECT is a window. */)
223 (object)
413430c5 224 Lisp_Object object;
7ab12479 225{
413430c5 226 return WINDOWP (object) ? Qt : Qnil;
7ab12479
JB
227}
228
806b4d9b 229DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
fdb82f93 230 doc: /* Returns t if OBJECT is a window which is currently visible. */)
413430c5
EN
231 (object)
232 Lisp_Object object;
605be8af 233{
9e571f49 234 return WINDOW_LIVE_P (object) ? Qt : Qnil;
605be8af
JB
235}
236
7ab12479
JB
237Lisp_Object
238make_window ()
239{
cffec418 240 Lisp_Object val;
7ab12479 241 register struct window *p;
cffec418 242
26605be9 243 p = allocate_window ();
d834a2e9 244 XSETFASTINT (p->sequence_number, ++sequence_number);
949cf20f
KS
245 XSETFASTINT (p->left_col, 0);
246 XSETFASTINT (p->top_line, 0);
247 XSETFASTINT (p->total_lines, 0);
248 XSETFASTINT (p->total_cols, 0);
d834a2e9 249 XSETFASTINT (p->hscroll, 0);
ea68264b 250 XSETFASTINT (p->min_hscroll, 0);
949cf20f 251 p->orig_top_line = p->orig_total_lines = Qnil;
7ab12479
JB
252 p->start = Fmake_marker ();
253 p->pointm = Fmake_marker ();
d834a2e9 254 XSETFASTINT (p->use_time, 0);
44fa5b1e 255 p->frame = Qnil;
7ab12479
JB
256 p->display_table = Qnil;
257 p->dedicated = Qnil;
5500c422
GM
258 p->pseudo_window_p = 0;
259 bzero (&p->cursor, sizeof (p->cursor));
260 bzero (&p->last_cursor, sizeof (p->last_cursor));
261 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
262 p->desired_matrix = p->current_matrix = 0;
263 p->phys_cursor_type = -1;
4b26579e 264 p->phys_cursor_width = -1;
5500c422
GM
265 p->must_be_updated_p = 0;
266 XSETFASTINT (p->window_end_vpos, 0);
267 XSETFASTINT (p->window_end_pos, 0);
268 p->window_end_valid = Qnil;
269 p->vscroll = 0;
cffec418 270 XSETWINDOW (val, p);
5500c422 271 XSETFASTINT (p->last_point, 0);
7bbb5782 272 p->frozen_window_start_p = 0;
6b448755
RS
273 p->height_fixed_p = 0;
274 p->last_cursor_off_p = p->cursor_off_p = 0;
949cf20f
KS
275 p->left_margin_cols = Qnil;
276 p->right_margin_cols = Qnil;
277 p->left_fringe_width = Qnil;
278 p->right_fringe_width = Qnil;
279 p->fringes_outside_margins = Qnil;
280 p->scroll_bar_width = Qnil;
281 p->vertical_scroll_bar_type = Qt;
67492200
GM
282
283 Vwindow_list = Qnil;
7ab12479
JB
284 return val;
285}
286
287DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
fdb82f93
PJ
288 doc: /* Return the window that the cursor now appears in and commands apply to. */)
289 ()
7ab12479
JB
290{
291 return selected_window;
292}
293
83762ba4 294DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
fdb82f93
PJ
295 doc: /* Return the window used now for minibuffers.
296If the optional argument FRAME is specified, return the minibuffer window
297used by that frame. */)
298 (frame)
83762ba4 299 Lisp_Object frame;
7ab12479 300{
83762ba4 301 if (NILP (frame))
1ae1a37d 302 frame = selected_frame;
b7826503 303 CHECK_LIVE_FRAME (frame);
83762ba4 304 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
7ab12479
JB
305}
306
605be8af 307DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
fdb82f93
PJ
308 doc: /* Returns non-nil if WINDOW is a minibuffer window. */)
309 (window)
7ab12479
JB
310 Lisp_Object window;
311{
312 struct window *w = decode_window (window);
53bb6b99 313 return MINI_WINDOW_P (w) ? Qt : Qnil;
81e4d465
MB
314}
315
316
7ab12479 317DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
fdb82f93
PJ
318 Spos_visible_in_window_p, 0, 3, 0,
319 doc: /* Return t if position POS is currently on the frame in WINDOW.
320Return nil if that position is scrolled vertically out of view.
321If a character is only partially visible, nil is returned, unless the
322optional argument PARTIALLY is non-nil.
323POS defaults to point in WINDOW; WINDOW defaults to the selected window. */)
324 (pos, window, partially)
5cdb3cf3 325 Lisp_Object pos, window, partially;
7ab12479
JB
326{
327 register struct window *w;
7ab12479
JB
328 register int posint;
329 register struct buffer *buf;
9a132b1f
GM
330 struct text_pos top;
331 Lisp_Object in_window;
53bb6b99 332 int fully_p;
7ab12479 333
f28b75a9
MB
334 w = decode_window (window);
335 buf = XBUFFER (w->buffer);
336 SET_TEXT_POS_FROM_MARKER (top, w->start);
337
338 if (!NILP (pos))
7ab12479 339 {
b7826503 340 CHECK_NUMBER_COERCE_MARKER (pos);
7ab12479
JB
341 posint = XINT (pos);
342 }
f28b75a9
MB
343 else if (w == XWINDOW (selected_window))
344 posint = PT;
345 else
346 posint = XMARKER (w->pointm)->charpos;
7ab12479 347
53bb6b99 348 /* If position is above window start, it's not visible. */
5500c422 349 if (posint < CHARPOS (top))
9a132b1f
GM
350 in_window = Qnil;
351 else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
81e4d465
MB
352 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
353 && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
81e4d465 354 {
53bb6b99
GM
355 /* If frame is up-to-date, and POSINT is < window end pos, use
356 that info. This doesn't work for POSINT == end pos, because
357 the window end pos is actually the position _after_ the last
358 char in the window. */
5cdb3cf3 359 if (NILP (partially))
53bb6b99 360 {
5cdb3cf3 361 pos_visible_p (w, posint, &fully_p, NILP (partially));
53bb6b99
GM
362 in_window = fully_p ? Qt : Qnil;
363 }
81e4d465 364 else
53bb6b99 365 in_window = Qt;
81e4d465 366 }
9a132b1f
GM
367 else if (posint > BUF_ZV (buf))
368 in_window = Qnil;
369 else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
370 /* If window start is out of range, do something reasonable. */
371 in_window = Qnil;
7ab12479
JB
372 else
373 {
5cdb3cf3
MB
374 if (pos_visible_p (w, posint, &fully_p, NILP (partially)))
375 in_window = !NILP (partially) || fully_p ? Qt : Qnil;
81e4d465
MB
376 else
377 in_window = Qnil;
7ab12479 378 }
9a132b1f
GM
379
380 return in_window;
7ab12479 381}
53bb6b99 382
7ab12479
JB
383\f
384static struct window *
385decode_window (window)
386 register Lisp_Object window;
387{
265a9e55 388 if (NILP (window))
7ab12479
JB
389 return XWINDOW (selected_window);
390
b7826503 391 CHECK_LIVE_WINDOW (window);
7ab12479
JB
392 return XWINDOW (window);
393}
394
395DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
fdb82f93
PJ
396 doc: /* Return the buffer that WINDOW is displaying. */)
397 (window)
7ab12479
JB
398 Lisp_Object window;
399{
400 return decode_window (window)->buffer;
401}
402
403DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
fdb82f93
PJ
404 doc: /* Return the number of lines in WINDOW (including its mode line). */)
405 (window)
7ab12479
JB
406 Lisp_Object window;
407{
949cf20f 408 return decode_window (window)->total_lines;
7ab12479
JB
409}
410
411DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
fdb82f93
PJ
412 doc: /* Return the number of display columns in WINDOW.
413This is the width that is usable columns available for text in WINDOW.
414If you want to find out how many columns WINDOW takes up,
415use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
416 (window)
7ab12479
JB
417 Lisp_Object window;
418{
949cf20f 419 return make_number (window_box_text_cols (decode_window (window)));
7ab12479
JB
420}
421
422DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
fdb82f93
PJ
423 doc: /* Return the number of columns by which WINDOW is scrolled from left margin. */)
424 (window)
7ab12479
JB
425 Lisp_Object window;
426{
427 return decode_window (window)->hscroll;
428}
429
430DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
fdb82f93 431 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
ebadb1e4
EZ
432NCOL should be zero or positive.
433
434Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
435window so that the location of point becomes invisible. */)
fdb82f93 436 (window, ncol)
ea68264b 437 Lisp_Object window, ncol;
7ab12479 438{
ea68264b
GM
439 struct window *w = decode_window (window);
440 int hscroll;
7ab12479 441
b7826503 442 CHECK_NUMBER (ncol);
ea68264b 443 hscroll = max (0, XINT (ncol));
177c0ea7 444
ea68264b
GM
445 /* Prevent redisplay shortcuts when changing the hscroll. */
446 if (XINT (w->hscroll) != hscroll)
b1599b4c 447 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
177c0ea7 448
c67fa410 449 w->hscroll = make_number (hscroll);
7ab12479
JB
450 return ncol;
451}
452
190eb263
RS
453DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
454 Swindow_redisplay_end_trigger, 0, 1, 0,
fdb82f93
PJ
455 doc: /* Return WINDOW's redisplay end trigger value.
456See `set-window-redisplay-end-trigger' for more information. */)
457 (window)
190eb263
RS
458 Lisp_Object window;
459{
460 return decode_window (window)->redisplay_end_trigger;
461}
462
463DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
464 Sset_window_redisplay_end_trigger, 2, 2, 0,
fdb82f93
PJ
465 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
466VALUE should be a buffer position (typically a marker) or nil.
467If it is a buffer position, then if redisplay in WINDOW reaches a position
468beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
469with two arguments: WINDOW, and the end trigger value.
470Afterwards the end-trigger value is reset to nil. */)
471 (window, value)
190eb263
RS
472 register Lisp_Object window, value;
473{
474 register struct window *w;
475
476 w = decode_window (window);
477 w->redisplay_end_trigger = value;
478 return value;
479}
480
7ab12479 481DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
fdb82f93
PJ
482 doc: /* Return a list of the edge coordinates of WINDOW.
483\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
c99a9eb3
RS
484RIGHT is one more than the rightmost column occupied by WINDOW,
485and BOTTOM is one more than the bottommost row occupied by WINDOW.
486The edges include the space used by the window's scroll bar,
487display margins, fringes, header line, and mode line, if it has them.
488To get the edges of the actual text area, use `window-inside-edges'. */)
fdb82f93 489 (window)
7ab12479
JB
490 Lisp_Object window;
491{
492 register struct window *w = decode_window (window);
493
949cf20f
KS
494 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
495 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
496 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
497 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
498 Qnil))));
7ab12479
JB
499}
500
c99a9eb3
RS
501DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
502 doc: /* Return a list of the edge pixel coordinates of WINDOW.
503\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
504RIGHT is one more than the rightmost x position occupied by WINDOW,
505and BOTTOM is one more than the bottommost y position occupied by WINDOW.
506The pixel edges include the space used by the window's scroll bar,
507display margins, fringes, header line, and mode line, if it has them.
508To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
509 (window)
510 Lisp_Object window;
511{
512 register struct window *w = decode_window (window);
513
514 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
515 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
516 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
517 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
518 Qnil))));
519}
520
521DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
522 doc: /* Return a list of the edge coordinates of WINDOW.
523\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
524RIGHT is one more than the rightmost column used by text in WINDOW,
525and BOTTOM is one more than the bottommost row used by text in WINDOW.
526The inside edges do not include the space used by the window's scroll bar,
527display margins, fringes, header line, and/or mode line. */)
528 (window)
529 Lisp_Object window;
530{
531 register struct window *w = decode_window (window);
532
533 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
534 + WINDOW_LEFT_MARGIN_COLS (w)
535 + WINDOW_LEFT_FRINGE_COLS (w)),
536 make_number (WINDOW_TOP_EDGE_LINE (w)
537 + WINDOW_HEADER_LINE_LINES (w)),
538 make_number (WINDOW_RIGHT_EDGE_COL (w)
539 - WINDOW_RIGHT_MARGIN_COLS (w)
540 - WINDOW_RIGHT_FRINGE_COLS (w)),
541 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
542 - WINDOW_MODE_LINE_LINES (w)));
543}
544
545DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
546 doc: /* Return a list of the edge coordinates of WINDOW.
547\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
548RIGHT is one more than the rightmost x position used by text in WINDOW,
549and BOTTOM is one more than the bottommost y position used by text in WINDOW.
550The inside edges do not include the space used by the window's scroll bar,
551display margins, fringes, header line, and/or mode line. */)
552 (window)
553 Lisp_Object window;
554{
555 register struct window *w = decode_window (window);
556
557 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
558 + WINDOW_LEFT_MARGIN_WIDTH (w)
559 + WINDOW_LEFT_FRINGE_WIDTH (w)),
560 make_number (WINDOW_TOP_EDGE_Y (w)
561 + WINDOW_HEADER_LINE_HEIGHT (w)),
562 make_number (WINDOW_RIGHT_EDGE_X (w)
563 - WINDOW_RIGHT_MARGIN_WIDTH (w)
564 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
565 make_number (WINDOW_BOTTOM_EDGE_Y (w)
566 - WINDOW_MODE_LINE_HEIGHT (w)));
567}
568
fbad6f9a 569/* Test if the character at column *X, row *Y is within window W.
341f3858 570 If it is not, return ON_NOTHING;
d5783c40
JB
571 if it is in the window's text area,
572 set *x and *y to its location relative to the upper left corner
573 of the window, and
341f3858
KS
574 return ON_TEXT;
575 if it is on the window's modeline, return ON_MODE_LINE;
d5783c40 576 if it is on the border between the window and its right sibling,
341f3858
KS
577 return ON_VERTICAL_BORDER.
578 if it is on the window's top line, return ON_HEADER_LINE;
81d189fd 579 if it is in left or right fringe of the window,
341f3858
KS
580 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
581 to window-relative coordinates;
49b996e7 582 if it is in the marginal area to the left/right of the window,
341f3858
KS
583 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
584 to window-relative coordinates.
5500c422
GM
585
586 X and Y are frame relative pixel coordinates. */
587
7442878f 588static enum window_part
d5783c40
JB
589coordinates_in_window (w, x, y)
590 register struct window *w;
591 register int *x, *y;
592{
b0228ace
GM
593 struct frame *f = XFRAME (WINDOW_FRAME (w));
594 int left_x, right_x, top_y, bottom_y;
7442878f 595 enum window_part part;
949cf20f
KS
596 int ux = FRAME_COLUMN_WIDTH (f);
597 int x0 = WINDOW_LEFT_EDGE_X (w);
598 int x1 = WINDOW_RIGHT_EDGE_X (w);
dad75588
GM
599 /* The width of the area where the vertical line can be dragged.
600 (Between mode lines for instance. */
601 int grabbable_width = ux;
949cf20f 602 int lmargin_width, rmargin_width, text_left, text_right;
b0228ace
GM
603
604 if (*x < x0 || *x >= x1)
605 return ON_NOTHING;
177c0ea7 606
466539bc
EZ
607 /* In what's below, we subtract 1 when computing right_x because we
608 want the rightmost pixel, which is given by left_pixel+width-1. */
5500c422
GM
609 if (w->pseudo_window_p)
610 {
611 left_x = 0;
949cf20f
KS
612 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
613 top_y = WINDOW_TOP_EDGE_Y (w);
614 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
5500c422
GM
615 }
616 else
617 {
949cf20f
KS
618 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
619 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
620 top_y = WINDOW_TOP_EDGE_Y (w);
621 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
5500c422 622 }
37962e60 623
949cf20f
KS
624 /* Outside any interesting row? */
625 if (*y < top_y || *y >= bottom_y)
626 return ON_NOTHING;
627
1cb794ba
GM
628 /* On the mode line or header line? If it's near the start of
629 the mode or header line of window that's has a horizontal
630 sibling, say it's on the vertical line. That's to be able
631 to resize windows horizontally in case we're using toolkit
632 scroll bars. */
b0228ace 633
1cb794ba 634 if (WINDOW_WANTS_MODELINE_P (w)
b0228ace
GM
635 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
636 && *y < bottom_y)
1cb794ba 637 {
949cf20f
KS
638 part = ON_MODE_LINE;
639
640 header_vertical_border_check:
b0228ace
GM
641 /* We're somewhere on the mode line. We consider the place
642 between mode lines of horizontally adjacent mode lines
643 as the vertical border. If scroll bars on the left,
644 return the right window. */
949cf20f
KS
645 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
646 || WINDOW_RIGHTMOST_P (w))
b0228ace 647 {
949cf20f
KS
648 if (!WINDOW_LEFTMOST_P (w) && abs (*x - x0) < grabbable_width)
649 return ON_VERTICAL_BORDER;
b0228ace 650 }
79fd290e 651 else
b0228ace 652 {
949cf20f
KS
653 if (abs (*x - x1) < grabbable_width)
654 return ON_VERTICAL_BORDER;
b0228ace 655 }
949cf20f 656
a5303820
KS
657 /* Convert X and Y to window relative coordinates.
658 Mode line starts at left edge of window. */
659 *x -= x0;
660 *y -= top_y;
949cf20f 661 return part;
b0228ace 662 }
949cf20f
KS
663
664 if (WINDOW_WANTS_HEADER_LINE_P (w)
665 && *y >= top_y
666 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
1cb794ba 667 {
949cf20f
KS
668 part = ON_HEADER_LINE;
669 goto header_vertical_border_check;
1cb794ba 670 }
949cf20f
KS
671
672 /* Outside any interesting column? */
673 if (*x < left_x || *x > right_x)
674 return ON_NOTHING;
675
676 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
677 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
79fd290e 678
949cf20f
KS
679 text_left = window_box_left (w, TEXT_AREA);
680 text_right = text_left + window_box_width (w, TEXT_AREA);
681
682 if (FRAME_WINDOW_P (f))
fbad6f9a 683 {
447e9da0 684 if (!w->pseudo_window_p
949cf20f 685 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
447e9da0 686 && !WINDOW_RIGHTMOST_P (w)
949cf20f
KS
687 && (abs (*x - right_x) < grabbable_width))
688 return ON_VERTICAL_BORDER;
fbad6f9a 689 }
447e9da0
GM
690 else
691 {
692 /* Need to say "*x > right_x" rather than >=, since on character
693 terminals, the vertical line's x coordinate is right_x. */
949cf20f
KS
694 if (!w->pseudo_window_p
695 && !WINDOW_RIGHTMOST_P (w)
696 && *x > right_x - ux)
b0228ace
GM
697 {
698 /* On the border on the right side of the window? Assume that
699 this area begins at RIGHT_X minus a canonical char width. */
949cf20f 700 return ON_VERTICAL_BORDER;
b0228ace 701 }
447e9da0 702 }
b0228ace 703
949cf20f
KS
704 if (*x < text_left)
705 {
706 if (lmargin_width > 0
707 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
708 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
709 : (*x < left_x + lmargin_width)))
a5303820
KS
710 {
711 *x -= x0;
712 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
713 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
714 *y -= top_y;
715 return ON_LEFT_MARGIN;
716 }
949cf20f
KS
717
718 /* Convert X and Y to window-relative pixel coordinates. */
719 *x -= left_x;
720 *y -= top_y;
721 return ON_LEFT_FRINGE;
722 }
723
724 if (*x >= text_right)
725 {
726 if (rmargin_width > 0
727 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
728 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
729 : (*x >= right_x - rmargin_width)))
a5303820
KS
730 {
731 *x -= right_x;
732 if (!WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
733 *x -= WINDOW_RIGHT_FRINGE_WIDTH (w);
734 *y -= top_y;
735 return ON_RIGHT_MARGIN;
736 }
949cf20f
KS
737
738 /* Convert X and Y to window-relative pixel coordinates. */
739 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
740 *y -= top_y;
741 return ON_RIGHT_FRINGE;
742 }
743
744 /* Everything special ruled out - must be on text area */
745 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
746 *y -= top_y;
747 return ON_TEXT;
d5783c40
JB
748}
749
b0228ace 750
d5783c40 751DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
fdb82f93
PJ
752 Scoordinates_in_window_p, 2, 2, 0,
753 doc: /* Return non-nil if COORDINATES are in WINDOW.
754COORDINATES is a cons of the form (X . Y), X and Y being distances
755measured in characters from the upper-left corner of the frame.
756\(0 . 0) denotes the character in the upper left corner of the
757frame.
758If COORDINATES are in the text portion of WINDOW,
759 the coordinates relative to the window are returned.
760If they are in the mode line of WINDOW, `mode-line' is returned.
761If they are in the top mode line of WINDOW, `header-line' is returned.
81d189fd
KS
762If they are in the left fringe of WINDOW, `left-fringe' is returned.
763If they are in the right fringe of WINDOW, `right-fringe' is returned.
fdb82f93 764If they are on the border between WINDOW and its right sibling,
49b996e7
GM
765 `vertical-line' is returned.
766If they are in the windows's left or right marginal areas, `left-margin'\n\
767 or `right-margin' is returned. */)
fdb82f93 768 (coordinates, window)
d5783c40
JB
769 register Lisp_Object coordinates, window;
770{
5500c422
GM
771 struct window *w;
772 struct frame *f;
d5783c40 773 int x, y;
5500c422 774 Lisp_Object lx, ly;
d5783c40 775
b7826503 776 CHECK_LIVE_WINDOW (window);
5500c422
GM
777 w = XWINDOW (window);
778 f = XFRAME (w->frame);
b7826503 779 CHECK_CONS (coordinates);
5500c422
GM
780 lx = Fcar (coordinates);
781 ly = Fcdr (coordinates);
b7826503
PJ
782 CHECK_NUMBER_OR_FLOAT (lx);
783 CHECK_NUMBER_OR_FLOAT (ly);
949cf20f
KS
784 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx);
785 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly);
5500c422
GM
786
787 switch (coordinates_in_window (w, &x, &y))
d5783c40 788 {
7442878f 789 case ON_NOTHING:
d5783c40
JB
790 return Qnil;
791
7442878f
GM
792 case ON_TEXT:
793 /* X and Y are now window relative pixel coordinates. Convert
794 them to canonical char units before returning them. */
949cf20f
KS
795 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
796 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
d5783c40 797
7442878f 798 case ON_MODE_LINE:
d5783c40 799 return Qmode_line;
37962e60 800
7442878f 801 case ON_VERTICAL_BORDER:
e5d77022 802 return Qvertical_line;
d5783c40 803
7442878f 804 case ON_HEADER_LINE:
045dee35 805 return Qheader_line;
5500c422 806
7442878f
GM
807 case ON_LEFT_FRINGE:
808 return Qleft_fringe;
177c0ea7 809
7442878f
GM
810 case ON_RIGHT_FRINGE:
811 return Qright_fringe;
fbad6f9a 812
49b996e7
GM
813 case ON_LEFT_MARGIN:
814 return Qleft_margin;
177c0ea7 815
49b996e7
GM
816 case ON_RIGHT_MARGIN:
817 return Qright_margin;
818
d5783c40
JB
819 default:
820 abort ();
821 }
822}
823
67492200
GM
824
825/* Callback for foreach_window, used in window_from_coordinates.
f95464e4
GM
826 Check if window W contains coordinates specified by USER_DATA which
827 is actually a pointer to a struct check_window_data CW.
828
829 Check if window W contains coordinates *CW->x and *CW->y. If it
830 does, return W in *CW->window, as Lisp_Object, and return in
5372262f 831 *CW->part the part of the window under coordinates *X,*Y. Return
f95464e4
GM
832 zero from this function to stop iterating over windows. */
833
834struct check_window_data
835{
836 Lisp_Object *window;
341f3858
KS
837 int *x, *y;
838 enum window_part *part;
f95464e4 839};
67492200
GM
840
841static int
f95464e4 842check_window_containing (w, user_data)
67492200 843 struct window *w;
f95464e4 844 void *user_data;
67492200 845{
f95464e4 846 struct check_window_data *cw = (struct check_window_data *) user_data;
7442878f
GM
847 enum window_part found;
848 int continue_p = 1;
67492200 849
f95464e4 850 found = coordinates_in_window (w, cw->x, cw->y);
7442878f 851 if (found != ON_NOTHING)
67492200 852 {
341f3858 853 *cw->part = found;
f95464e4 854 XSETWINDOW (*cw->window, w);
7442878f 855 continue_p = 0;
67492200 856 }
177c0ea7 857
7442878f 858 return continue_p;
67492200
GM
859}
860
861
5500c422 862/* Find the window containing frame-relative pixel position X/Y and
949cf20f
KS
863 return it as a Lisp_Object.
864
865 If X, Y is on one of the window's special `window_part' elements,
866 set *PART to the id of that element, and return X and Y converted
867 to window relative coordinates in WX and WY.
868
341f3858 869 If there is no window under X, Y return nil and leave *PART
67492200
GM
870 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
871
872 This function was previously implemented with a loop cycling over
873 windows with Fnext_window, and starting with the frame's selected
874 window. It turned out that this doesn't work with an
875 implementation of next_window using Vwindow_list, because
876 FRAME_SELECTED_WINDOW (F) is not always contained in the window
877 tree of F when this function is called asynchronously from
878 note_mouse_highlight. The original loop didn't terminate in this
879 case. */
5500c422 880
7ab12479 881Lisp_Object
949cf20f 882window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
67492200 883 struct frame *f;
7ab12479 884 int x, y;
341f3858 885 enum window_part *part;
949cf20f 886 int *wx, *wy;
9ea173e8 887 int tool_bar_p;
7ab12479 888{
67492200 889 Lisp_Object window;
f95464e4 890 struct check_window_data cw;
341f3858
KS
891 enum window_part dummy;
892
893 if (part == 0)
894 part = &dummy;
5500c422 895
67492200 896 window = Qnil;
f95464e4
GM
897 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
898 foreach_window (f, check_window_containing, &cw);
177c0ea7 899
67492200
GM
900 /* If not found above, see if it's in the tool bar window, if a tool
901 bar exists. */
902 if (NILP (window)
903 && tool_bar_p
904 && WINDOWP (f->tool_bar_window)
949cf20f 905 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
7442878f
GM
906 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
907 != ON_NOTHING))
5500c422 908 {
341f3858 909 *part = ON_TEXT;
67492200 910 window = f->tool_bar_window;
5500c422 911 }
37962e60 912
949cf20f
KS
913 if (wx) *wx = x;
914 if (wy) *wy = y;
915
67492200 916 return window;
7ab12479
JB
917}
918
ab17c3f2 919DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
fdb82f93
PJ
920 doc: /* Return window containing coordinates X and Y on FRAME.
921If omitted, FRAME defaults to the currently selected frame.
922The top left corner of the frame is considered to be row 0,
923column 0. */)
924 (x, y, frame)
925 Lisp_Object x, y, frame;
7ab12479 926{
5500c422 927 struct frame *f;
7ab12479 928
44fa5b1e 929 if (NILP (frame))
1ae1a37d 930 frame = selected_frame;
b7826503 931 CHECK_LIVE_FRAME (frame);
5500c422 932 f = XFRAME (frame);
7ab12479 933
5500c422 934 /* Check that arguments are integers or floats. */
b7826503
PJ
935 CHECK_NUMBER_OR_FLOAT (x);
936 CHECK_NUMBER_OR_FLOAT (y);
5500c422 937
177c0ea7 938 return window_from_coordinates (f,
949cf20f
KS
939 FRAME_PIXEL_X_FROM_CANON_X (f, x),
940 FRAME_PIXEL_Y_FROM_CANON_Y (f, y),
941 0, 0, 0, 0);
7ab12479
JB
942}
943
944DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
fdb82f93
PJ
945 doc: /* Return current value of point in WINDOW.
946For a nonselected window, this is the value point would have
947if that window were selected.
948
949Note that, when WINDOW is the selected window and its buffer
950is also currently selected, the value returned is the same as (point).
951It would be more strictly correct to return the `top-level' value
952of point, outside of any save-excursion forms.
953But that is hard to define. */)
954 (window)
7ab12479
JB
955 Lisp_Object window;
956{
957 register struct window *w = decode_window (window);
958
959 if (w == XWINDOW (selected_window)
960 && current_buffer == XBUFFER (w->buffer))
961 return Fpoint ();
962 return Fmarker_position (w->pointm);
963}
964
965DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
fdb82f93
PJ
966 doc: /* Return position at which display currently starts in WINDOW.
967This is updated by redisplay or by calling `set-window-start'. */)
968 (window)
7ab12479
JB
969 Lisp_Object window;
970{
971 return Fmarker_position (decode_window (window)->start);
972}
973
8646118f
RS
974/* This is text temporarily removed from the doc string below.
975
fdb82f93
PJ
976This function returns nil if the position is not currently known.
977That happens when redisplay is preempted and doesn't finish.
978If in that case you want to compute where the end of the window would
979have been if redisplay had finished, do this:
980 (save-excursion
981 (goto-char (window-start window))
982 (vertical-motion (1- (window-height window)) window)
8646118f
RS
983 (point))") */
984
478292ed 985DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
fdb82f93
PJ
986 doc: /* Return position at which display currently ends in WINDOW.
987This is updated by redisplay, when it runs to completion.
988Simply changing the buffer text or setting `window-start'
989does not update this value.
990If UPDATE is non-nil, compute the up-to-date position
991if it isn't already recorded. */)
992 (window, update)
478292ed 993 Lisp_Object window, update;
7ab12479
JB
994{
995 Lisp_Object value;
996 struct window *w = decode_window (window);
5a41ab94
RS
997 Lisp_Object buf;
998
999 buf = w->buffer;
b7826503 1000 CHECK_BUFFER (buf);
5a41ab94 1001
8646118f 1002#if 0 /* This change broke some things. We should make it later. */
7250968e
RS
1003 /* If we don't know the end position, return nil.
1004 The user can compute it with vertical-motion if he wants to.
1005 It would be nicer to do it automatically,
1006 but that's so slow that it would probably bother people. */
1007 if (NILP (w->window_end_valid))
1008 return Qnil;
8646118f 1009#endif
7250968e 1010
478292ed
RS
1011 if (! NILP (update)
1012 && ! (! NILP (w->window_end_valid)
1013 && XFASTINT (w->last_modified) >= MODIFF))
1014 {
cbc099e5
GM
1015 struct text_pos startp;
1016 struct it it;
99593a9d 1017 struct buffer *old_buffer = NULL, *b = XBUFFER (buf);
2d6d9df0
GM
1018
1019 /* In case W->start is out of the range, use something
cb795ec4 1020 reasonable. This situation occurred when loading a file with
2d6d9df0
GM
1021 `-l' containing a call to `rmail' with subsequent other
1022 commands. At the end, W->start happened to be BEG, while
cbc099e5 1023 rmail had already narrowed the buffer. */
2d6d9df0 1024 if (XMARKER (w->start)->charpos < BEGV)
cbc099e5 1025 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
2d6d9df0 1026 else if (XMARKER (w->start)->charpos > ZV)
cbc099e5 1027 SET_TEXT_POS (startp, ZV, ZV_BYTE);
2d6d9df0 1028 else
cbc099e5
GM
1029 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1030
1031 /* Cannot use Fvertical_motion because that function doesn't
1032 cope with variable-height lines. */
99593a9d
GM
1033 if (b != current_buffer)
1034 {
1035 old_buffer = current_buffer;
1036 set_buffer_internal (b);
1037 }
177c0ea7 1038
cbc099e5
GM
1039 start_display (&it, w, startp);
1040 move_it_vertically (&it, window_box_height (w));
c3c45f65
GM
1041 if (it.current_y < it.last_visible_y)
1042 move_it_past_eol (&it);
cbc099e5 1043 value = make_number (IT_CHARPOS (it));
177c0ea7 1044
99593a9d
GM
1045 if (old_buffer)
1046 set_buffer_internal (old_buffer);
478292ed
RS
1047 }
1048 else
cbc099e5 1049 XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
7ab12479
JB
1050
1051 return value;
1052}
1053
1054DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
fdb82f93
PJ
1055 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer. */)
1056 (window, pos)
7ab12479
JB
1057 Lisp_Object window, pos;
1058{
1059 register struct window *w = decode_window (window);
1060
b7826503 1061 CHECK_NUMBER_COERCE_MARKER (pos);
e90c4fe6
RS
1062 if (w == XWINDOW (selected_window)
1063 && XBUFFER (w->buffer) == current_buffer)
7ab12479
JB
1064 Fgoto_char (pos);
1065 else
1066 set_marker_restricted (w->pointm, pos, w->buffer);
799417bd 1067
0685cb3c
GM
1068 /* We have to make sure that redisplay updates the window to show
1069 the new value of point. */
1070 if (!EQ (window, selected_window))
799417bd 1071 ++windows_or_buffers_changed;
177c0ea7 1072
7ab12479
JB
1073 return pos;
1074}
1075
1076DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
fdb82f93
PJ
1077 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1078Optional third arg NOFORCE non-nil inhibits next redisplay
1079from overriding motion of point in order to display at this exact start. */)
1080 (window, pos, noforce)
7ab12479
JB
1081 Lisp_Object window, pos, noforce;
1082{
1083 register struct window *w = decode_window (window);
1084
b7826503 1085 CHECK_NUMBER_COERCE_MARKER (pos);
7ab12479
JB
1086 set_marker_restricted (w->start, pos, w->buffer);
1087 /* this is not right, but much easier than doing what is right. */
1088 w->start_at_line_beg = Qnil;
265a9e55 1089 if (NILP (noforce))
7ab12479
JB
1090 w->force_start = Qt;
1091 w->update_mode_line = Qt;
d834a2e9 1092 XSETFASTINT (w->last_modified, 0);
3cd21523 1093 XSETFASTINT (w->last_overlay_modified, 0);
62c07cc7
JB
1094 if (!EQ (window, selected_window))
1095 windows_or_buffers_changed++;
ce7fae7d 1096
7ab12479
JB
1097 return pos;
1098}
1099
1100DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1101 1, 1, 0,
fdb82f93
PJ
1102 doc: /* Return WINDOW's dedicated object, usually t or nil.
1103See also `set-window-dedicated-p'. */)
1104 (window)
7ab12479
JB
1105 Lisp_Object window;
1106{
1107 return decode_window (window)->dedicated;
1108}
1109
d207b766
RS
1110DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1111 Sset_window_dedicated_p, 2, 2, 0,
fdb82f93
PJ
1112 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1113If it is dedicated, Emacs will not automatically change
1114which buffer appears in it.
1115The second argument is the new value for the dedication flag;
1116non-nil means yes. */)
1117 (window, arg)
1118 Lisp_Object window, arg;
7ab12479
JB
1119{
1120 register struct window *w = decode_window (window);
1121
2d0834cc 1122 w->dedicated = arg;
7ab12479
JB
1123
1124 return w->dedicated;
1125}
1126
1127DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1128 0, 1, 0,
fdb82f93
PJ
1129 doc: /* Return the display-table that WINDOW is using. */)
1130 (window)
7ab12479
JB
1131 Lisp_Object window;
1132{
1133 return decode_window (window)->display_table;
1134}
1135
5500c422
GM
1136/* Get the display table for use on window W. This is either W's
1137 display table or W's buffer's display table. Ignore the specified
1138 tables if they are not valid; if no valid table is specified,
1139 return 0. */
7ab12479 1140
319315f1 1141struct Lisp_Char_Table *
7ab12479
JB
1142window_display_table (w)
1143 struct window *w;
1144{
c756cdbe
GM
1145 struct Lisp_Char_Table *dp = NULL;
1146
1147 if (DISP_TABLE_P (w->display_table))
1148 dp = XCHAR_TABLE (w->display_table);
1149 else if (BUFFERP (w->buffer))
1150 {
1151 struct buffer *b = XBUFFER (w->buffer);
177c0ea7 1152
c756cdbe
GM
1153 if (DISP_TABLE_P (b->display_table))
1154 dp = XCHAR_TABLE (b->display_table);
1155 else if (DISP_TABLE_P (Vstandard_display_table))
1156 dp = XCHAR_TABLE (Vstandard_display_table);
1157 }
171d003c 1158
c756cdbe 1159 return dp;
7ab12479
JB
1160}
1161
3a2712f9 1162DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
fdb82f93
PJ
1163 doc: /* Set WINDOW's display-table to TABLE. */)
1164 (window, table)
7ab12479
JB
1165 register Lisp_Object window, table;
1166{
1167 register struct window *w;
7ab12479
JB
1168
1169 w = decode_window (window);
1170 w->display_table = table;
1171 return table;
1172}
1173\f
1174/* Record info on buffer window w is displaying
1175 when it is about to cease to display that buffer. */
dfcf069d 1176static void
7ab12479
JB
1177unshow_buffer (w)
1178 register struct window *w;
1179{
12cae7c0 1180 Lisp_Object buf;
b73ea88e 1181 struct buffer *b;
7ab12479 1182
12cae7c0 1183 buf = w->buffer;
b73ea88e
RS
1184 b = XBUFFER (buf);
1185 if (b != XMARKER (w->pointm)->buffer)
7ab12479
JB
1186 abort ();
1187
573f41ab 1188#if 0
7ab12479
JB
1189 if (w == XWINDOW (selected_window)
1190 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1191 /* Do this except when the selected window's buffer
1192 is being removed from some other window. */
573f41ab
RS
1193#endif
1194 /* last_window_start records the start position that this buffer
1195 had in the last window to be disconnected from it.
1196 Now that this statement is unconditional,
1197 it is possible for the buffer to be displayed in the
1198 selected window, while last_window_start reflects another
1199 window which was recently showing the same buffer.
1200 Some people might say that might be a good thing. Let's see. */
b73ea88e 1201 b->last_window_start = marker_position (w->start);
7ab12479
JB
1202
1203 /* Point in the selected window's buffer
1204 is actually stored in that buffer, and the window's pointm isn't used.
1205 So don't clobber point in that buffer. */
719eaeb1
GM
1206 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1207 /* This line helps to fix Horsley's testbug.el bug. */
8801a864
KR
1208 && !(WINDOWP (b->last_selected_window)
1209 && w != XWINDOW (b->last_selected_window)
719eaeb1 1210 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
b73ea88e
RS
1211 temp_set_point_both (b,
1212 clip_to_bounds (BUF_BEGV (b),
1213 XMARKER (w->pointm)->charpos,
1214 BUF_ZV (b)),
1215 clip_to_bounds (BUF_BEGV_BYTE (b),
1216 marker_byte_position (w->pointm),
1217 BUF_ZV_BYTE (b)));
177c0ea7 1218
8801a864
KR
1219 if (WINDOWP (b->last_selected_window)
1220 && w == XWINDOW (b->last_selected_window))
719eaeb1 1221 b->last_selected_window = Qnil;
7ab12479
JB
1222}
1223
1224/* Put replacement into the window structure in place of old. */
dfcf069d 1225static void
7ab12479
JB
1226replace_window (old, replacement)
1227 Lisp_Object old, replacement;
1228{
1229 register Lisp_Object tem;
1230 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1231
44fa5b1e
JB
1232 /* If OLD is its frame's root_window, then replacement is the new
1233 root_window for that frame. */
7ab12479 1234
7f4161e0 1235 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
44fa5b1e 1236 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
7ab12479 1237
949cf20f
KS
1238 p->left_col = o->left_col;
1239 p->top_line = o->top_line;
1240 p->total_cols = o->total_cols;
1241 p->total_lines = o->total_lines;
5500c422
GM
1242 p->desired_matrix = p->current_matrix = 0;
1243 p->vscroll = 0;
1244 bzero (&p->cursor, sizeof (p->cursor));
1245 bzero (&p->last_cursor, sizeof (p->last_cursor));
1246 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1247 p->phys_cursor_type = -1;
4b26579e 1248 p->phys_cursor_width = -1;
5500c422
GM
1249 p->must_be_updated_p = 0;
1250 p->pseudo_window_p = 0;
1251 XSETFASTINT (p->window_end_vpos, 0);
1252 XSETFASTINT (p->window_end_pos, 0);
1253 p->window_end_valid = Qnil;
7bbb5782 1254 p->frozen_window_start_p = 0;
949cf20f 1255 p->orig_top_line = p->orig_total_lines = Qnil;
7ab12479
JB
1256
1257 p->next = tem = o->next;
265a9e55 1258 if (!NILP (tem))
7ab12479
JB
1259 XWINDOW (tem)->prev = replacement;
1260
1261 p->prev = tem = o->prev;
265a9e55 1262 if (!NILP (tem))
7ab12479
JB
1263 XWINDOW (tem)->next = replacement;
1264
1265 p->parent = tem = o->parent;
265a9e55 1266 if (!NILP (tem))
7ab12479
JB
1267 {
1268 if (EQ (XWINDOW (tem)->vchild, old))
1269 XWINDOW (tem)->vchild = replacement;
1270 if (EQ (XWINDOW (tem)->hchild, old))
1271 XWINDOW (tem)->hchild = replacement;
1272 }
1273
1274/*** Here, if replacement is a vertical combination
1275and so is its new parent, we should make replacement's
1276children be children of that parent instead. ***/
1277}
1278
1279DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
fdb82f93
PJ
1280 doc: /* Remove WINDOW from the display. Default is selected window. */)
1281 (window)
7ab12479 1282 register Lisp_Object window;
543f5fb1
RS
1283{
1284 delete_window (window);
1285
1286 if (! NILP (Vwindow_configuration_change_hook)
1287 && ! NILP (Vrun_hooks))
1288 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1289
1290 return Qnil;
1291}
1292
5e14b1fc 1293void
543f5fb1
RS
1294delete_window (window)
1295 register Lisp_Object window;
7ab12479
JB
1296{
1297 register Lisp_Object tem, parent, sib;
1298 register struct window *p;
1299 register struct window *par;
951f9df5 1300 struct frame *f;
7ab12479 1301
605be8af
JB
1302 /* Because this function is called by other C code on non-leaf
1303 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1304 so we can't decode_window here. */
265a9e55 1305 if (NILP (window))
7ab12479
JB
1306 window = selected_window;
1307 else
b7826503 1308 CHECK_WINDOW (window);
7ab12479 1309 p = XWINDOW (window);
605be8af
JB
1310
1311 /* It's okay to delete an already-deleted window. */
1312 if (NILP (p->buffer)
1313 && NILP (p->hchild)
1314 && NILP (p->vchild))
296b535c 1315 return;
605be8af 1316
7ab12479 1317 parent = p->parent;
265a9e55 1318 if (NILP (parent))
7ab12479
JB
1319 error ("Attempt to delete minibuffer or sole ordinary window");
1320 par = XWINDOW (parent);
1321
1322 windows_or_buffers_changed++;
67492200 1323 Vwindow_list = Qnil;
951f9df5
GM
1324 f = XFRAME (WINDOW_FRAME (p));
1325 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
7ab12479 1326
605be8af
JB
1327 /* Are we trying to delete any frame's selected window? */
1328 {
192c3131 1329 Lisp_Object swindow, pwindow;
605be8af 1330
0def0403
RS
1331 /* See if the frame's selected window is either WINDOW
1332 or any subwindow of it, by finding all that window's parents
1333 and comparing each one with WINDOW. */
192c3131 1334 swindow = FRAME_SELECTED_WINDOW (f);
0def0403 1335
192c3131 1336 while (1)
0def0403 1337 {
192c3131
RS
1338 pwindow = swindow;
1339 while (!NILP (pwindow))
1340 {
1341 if (EQ (window, pwindow))
1342 break;
1343 pwindow = XWINDOW (pwindow)->parent;
1344 }
1345
1346 /* If the window being deleted is not a parent of SWINDOW,
1347 then SWINDOW is ok as the new selected window. */
1348 if (!EQ (window, pwindow))
0def0403 1349 break;
192c3131
RS
1350 /* Otherwise, try another window for SWINDOW. */
1351 swindow = Fnext_window (swindow, Qlambda, Qnil);;
1352
1353 /* If we get back to the frame's selected window,
1354 it means there was no acceptable alternative,
1355 so we cannot delete. */
1356 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1357 error ("Cannot delete window");
0def0403
RS
1358 }
1359
192c3131
RS
1360 /* If we need to change SWINDOW, do it. */
1361 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
605be8af 1362 {
605be8af
JB
1363 /* If we're about to delete the selected window on the
1364 selected frame, then we should use Fselect_window to select
1365 the new window. On the other hand, if we're about to
1366 delete the selected window on any other frame, we shouldn't do
1367 anything but set the frame's selected_window slot. */
192c3131 1368 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
14d87dc9 1369 Fselect_window (swindow, Qnil);
605be8af 1370 else
192c3131 1371 FRAME_SELECTED_WINDOW (f) = swindow;
605be8af
JB
1372 }
1373 }
7ab12479
JB
1374
1375 tem = p->buffer;
1376 /* tem is null for dummy parent windows
1377 (which have inferiors but not any contents themselves) */
265a9e55 1378 if (!NILP (tem))
7ab12479
JB
1379 {
1380 unshow_buffer (p);
2d0834cc
SM
1381 unchain_marker (XMARKER (p->pointm));
1382 unchain_marker (XMARKER (p->start));
7ab12479
JB
1383 }
1384
05e71564
GM
1385 /* Free window glyph matrices. It is sure that they are allocated
1386 again when ADJUST_GLYPHS is called. Block input so that expose
1387 events and other events that access glyph matrices are not
1388 processed while we are changing them. */
1389 BLOCK_INPUT;
951f9df5 1390 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
5500c422 1391
7ab12479 1392 tem = p->next;
265a9e55 1393 if (!NILP (tem))
7ab12479
JB
1394 XWINDOW (tem)->prev = p->prev;
1395
1396 tem = p->prev;
265a9e55 1397 if (!NILP (tem))
7ab12479
JB
1398 XWINDOW (tem)->next = p->next;
1399
1400 if (EQ (window, par->hchild))
1401 par->hchild = p->next;
1402 if (EQ (window, par->vchild))
1403 par->vchild = p->next;
1404
1405 /* Find one of our siblings to give our space to. */
1406 sib = p->prev;
265a9e55 1407 if (NILP (sib))
7ab12479
JB
1408 {
1409 /* If p gives its space to its next sibling, that sibling needs
1410 to have its top/left side pulled back to where p's is.
1411 set_window_{height,width} will re-position the sibling's
1412 children. */
1413 sib = p->next;
949cf20f
KS
1414 XWINDOW (sib)->top_line = p->top_line;
1415 XWINDOW (sib)->left_col = p->left_col;
7ab12479
JB
1416 }
1417
1418 /* Stretch that sibling. */
265a9e55 1419 if (!NILP (par->vchild))
7ab12479 1420 set_window_height (sib,
949cf20f 1421 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
7ab12479 1422 1);
265a9e55 1423 if (!NILP (par->hchild))
7ab12479 1424 set_window_width (sib,
949cf20f 1425 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
7ab12479
JB
1426 1);
1427
1428 /* If parent now has only one child,
1429 put the child into the parent's place. */
7ab12479 1430 tem = par->hchild;
265a9e55 1431 if (NILP (tem))
7ab12479 1432 tem = par->vchild;
265a9e55 1433 if (NILP (XWINDOW (tem)->next))
7ab12479 1434 replace_window (parent, tem);
605be8af
JB
1435
1436 /* Since we may be deleting combination windows, we must make sure that
1437 not only p but all its children have been marked as deleted. */
1438 if (! NILP (p->hchild))
1439 delete_all_subwindows (XWINDOW (p->hchild));
1440 else if (! NILP (p->vchild))
1441 delete_all_subwindows (XWINDOW (p->vchild));
1442
1443 /* Mark this window as deleted. */
1444 p->buffer = p->hchild = p->vchild = Qnil;
5500c422
GM
1445
1446 /* Adjust glyph matrices. */
951f9df5 1447 adjust_glyphs (f);
05e71564 1448 UNBLOCK_INPUT;
7ab12479 1449}
67492200
GM
1450
1451
7ab12479 1452\f
67492200
GM
1453/***********************************************************************
1454 Window List
1455 ***********************************************************************/
1456
f95464e4
GM
1457/* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1458 pointer. This is a callback function for foreach_window, used in
1459 function window_list. */
67492200
GM
1460
1461static int
f95464e4 1462add_window_to_list (w, user_data)
67492200 1463 struct window *w;
f95464e4 1464 void *user_data;
67492200 1465{
f95464e4 1466 Lisp_Object *list = (Lisp_Object *) user_data;
67492200
GM
1467 Lisp_Object window;
1468 XSETWINDOW (window, w);
212116d6 1469 *list = Fcons (window, *list);
67492200
GM
1470 return 1;
1471}
1472
1473
1474/* Return a list of all windows, for use by next_window. If
1475 Vwindow_list is a list, return that list. Otherwise, build a new
1476 list, cache it in Vwindow_list, and return that. */
1477
1478static Lisp_Object
1479window_list ()
1480{
1481 if (!CONSP (Vwindow_list))
1482 {
1483 Lisp_Object tail;
212116d6 1484
67492200
GM
1485 Vwindow_list = Qnil;
1486 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
212116d6
GM
1487 {
1488 Lisp_Object args[2];
1489
1490 /* We are visiting windows in canonical order, and add
1491 new windows at the front of args[1], which means we
1492 have to reverse this list at the end. */
1493 args[1] = Qnil;
1494 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1495 args[0] = Vwindow_list;
1496 args[1] = Fnreverse (args[1]);
1497 Vwindow_list = Fnconc (2, args);
1498 }
67492200 1499 }
177c0ea7 1500
67492200
GM
1501 return Vwindow_list;
1502}
1503
1504
118ea242
GM
1505/* Value is non-zero if WINDOW satisfies the constraints given by
1506 OWINDOW, MINIBUF and ALL_FRAMES.
67492200 1507
118ea242
GM
1508 MINIBUF t means WINDOW may be minibuffer windows.
1509 `lambda' means WINDOW may not be a minibuffer window.
1510 a window means a specific minibuffer window
67492200 1511
118ea242
GM
1512 ALL_FRAMES t means search all frames,
1513 nil means search just current frame,
1514 `visible' means search just visible frames,
1515 0 means search visible and iconified frames,
1516 a window means search the frame that window belongs to,
1517 a frame means consider windows on that frame, only. */
67492200
GM
1518
1519static int
118ea242
GM
1520candidate_window_p (window, owindow, minibuf, all_frames)
1521 Lisp_Object window, owindow, minibuf, all_frames;
67492200
GM
1522{
1523 struct window *w = XWINDOW (window);
1524 struct frame *f = XFRAME (w->frame);
1525 int candidate_p = 1;
1526
1527 if (!BUFFERP (w->buffer))
1528 candidate_p = 0;
1529 else if (MINI_WINDOW_P (w)
1530 && (EQ (minibuf, Qlambda)
1531 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1532 {
1533 /* If MINIBUF is `lambda' don't consider any mini-windows.
1534 If it is a window, consider only that one. */
1535 candidate_p = 0;
1536 }
118ea242
GM
1537 else if (EQ (all_frames, Qt))
1538 candidate_p = 1;
67492200 1539 else if (NILP (all_frames))
118ea242
GM
1540 {
1541 xassert (WINDOWP (owindow));
1542 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1543 }
67492200
GM
1544 else if (EQ (all_frames, Qvisible))
1545 {
1546 FRAME_SAMPLE_VISIBILITY (f);
1547 candidate_p = FRAME_VISIBLE_P (f);
1548 }
1549 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1550 {
1551 FRAME_SAMPLE_VISIBILITY (f);
1552 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1553 }
67492200
GM
1554 else if (WINDOWP (all_frames))
1555 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1556 || EQ (XWINDOW (all_frames)->frame, w->frame)
1557 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
118ea242
GM
1558 else if (FRAMEP (all_frames))
1559 candidate_p = EQ (all_frames, w->frame);
67492200
GM
1560
1561 return candidate_p;
1562}
1563
1564
1565/* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1566 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1567 ALL_FRAMES. */
1568
1569static void
1570decode_next_window_args (window, minibuf, all_frames)
1571 Lisp_Object *window, *minibuf, *all_frames;
1572{
1573 if (NILP (*window))
1574 *window = selected_window;
1575 else
b7826503 1576 CHECK_LIVE_WINDOW (*window);
177c0ea7 1577
67492200
GM
1578 /* MINIBUF nil may or may not include minibuffers. Decide if it
1579 does. */
1580 if (NILP (*minibuf))
1581 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1582 else if (!EQ (*minibuf, Qt))
1583 *minibuf = Qlambda;
177c0ea7 1584
67492200
GM
1585 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1586 => count none of them, or a specific minibuffer window (the
1587 active one) to count. */
1588
1589 /* ALL_FRAMES nil doesn't specify which frames to include. */
1590 if (NILP (*all_frames))
1591 *all_frames = (!EQ (*minibuf, Qlambda)
1592 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1593 : Qnil);
1594 else if (EQ (*all_frames, Qvisible))
1595 ;
1596 else if (XFASTINT (*all_frames) == 0)
1597 ;
1598 else if (FRAMEP (*all_frames))
1599 ;
1600 else if (!EQ (*all_frames, Qt))
1601 *all_frames = Qnil;
177c0ea7 1602
67492200
GM
1603 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1604 search just current frame, `visible' meaning search just visible
1605 frames, 0 meaning search visible and iconified frames, or a
1606 window, meaning search the frame that window belongs to, or a
1607 frame, meaning consider windows on that frame, only. */
1608}
1609
1610
1611/* Return the next or previous window of WINDOW in canonical ordering
1612 of windows. NEXT_P non-zero means return the next window. See the
1613 documentation string of next-window for the meaning of MINIBUF and
1614 ALL_FRAMES. */
1615
1616static Lisp_Object
1617next_window (window, minibuf, all_frames, next_p)
1618 Lisp_Object window, minibuf, all_frames;
1619 int next_p;
1620{
1621 decode_next_window_args (&window, &minibuf, &all_frames);
177c0ea7 1622
67492200
GM
1623 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1624 return the first window on the frame. */
1625 if (FRAMEP (all_frames)
1626 && !EQ (all_frames, XWINDOW (window)->frame))
1627 return Fframe_first_window (all_frames);
177c0ea7 1628
212116d6 1629 if (next_p)
67492200
GM
1630 {
1631 Lisp_Object list;
177c0ea7 1632
67492200
GM
1633 /* Find WINDOW in the list of all windows. */
1634 list = Fmemq (window, window_list ());
1635
1636 /* Scan forward from WINDOW to the end of the window list. */
1637 if (CONSP (list))
1638 for (list = XCDR (list); CONSP (list); list = XCDR (list))
118ea242 1639 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
67492200
GM
1640 break;
1641
1642 /* Scan from the start of the window list up to WINDOW. */
1643 if (!CONSP (list))
1644 for (list = Vwindow_list;
1645 CONSP (list) && !EQ (XCAR (list), window);
1646 list = XCDR (list))
118ea242 1647 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
67492200
GM
1648 break;
1649
1650 if (CONSP (list))
1651 window = XCAR (list);
1652 }
1653 else
1654 {
1655 Lisp_Object candidate, list;
177c0ea7 1656
67492200
GM
1657 /* Scan through the list of windows for candidates. If there are
1658 candidate windows in front of WINDOW, the last one of these
1659 is the one we want. If there are candidates following WINDOW
1660 in the list, again the last one of these is the one we want. */
1661 candidate = Qnil;
1662 for (list = window_list (); CONSP (list); list = XCDR (list))
1663 {
1664 if (EQ (XCAR (list), window))
1665 {
1666 if (WINDOWP (candidate))
1667 break;
1668 }
118ea242
GM
1669 else if (candidate_window_p (XCAR (list), window, minibuf,
1670 all_frames))
67492200
GM
1671 candidate = XCAR (list);
1672 }
1673
1674 if (WINDOWP (candidate))
1675 window = candidate;
1676 }
1677
1678 return window;
1679}
7ab12479 1680
7ab12479 1681
26f6279d 1682DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
fdb82f93
PJ
1683 doc: /* Return next window after WINDOW in canonical ordering of windows.
1684If omitted, WINDOW defaults to the selected window.
1685
1686Optional second arg MINIBUF t means count the minibuffer window even
1687if not active. MINIBUF nil or omitted means count the minibuffer iff
1688it is active. MINIBUF neither t nor nil means not to count the
1689minibuffer even if it is active.
1690
1691Several frames may share a single minibuffer; if the minibuffer
1692counts, all windows on all frames that share that minibuffer count
1693too. Therefore, `next-window' can be used to iterate through the
1694set of windows even when the minibuffer is on another frame. If the
1695minibuffer does not count, only windows from WINDOW's frame count.
1696
1697Optional third arg ALL-FRAMES t means include windows on all frames.
1698ALL-FRAMES nil or omitted means cycle within the frames as specified
1699above. ALL-FRAMES = `visible' means include windows on all visible frames.
1700ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1701If ALL-FRAMES is a frame, restrict search to windows on that frame.
1702Anything else means restrict to WINDOW's frame.
1703
1704If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1705`next-window' to iterate through the entire cycle of acceptable
1706windows, eventually ending up back at the window you started with.
1707`previous-window' traverses the same cycle, in the reverse order. */)
1708 (window, minibuf, all_frames)
67492200 1709 Lisp_Object window, minibuf, all_frames;
7ab12479 1710{
67492200 1711 return next_window (window, minibuf, all_frames, 1);
7ab12479
JB
1712}
1713
67492200 1714
26f6279d 1715DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
fdb82f93
PJ
1716 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1717If omitted, WINDOW defaults to the selected window.
1718
1719Optional second arg MINIBUF t means count the minibuffer window even
1720if not active. MINIBUF nil or omitted means count the minibuffer iff
1721it is active. MINIBUF neither t nor nil means not to count the
1722minibuffer even if it is active.
1723
1724Several frames may share a single minibuffer; if the minibuffer
1725counts, all windows on all frames that share that minibuffer count
1726too. Therefore, `previous-window' can be used to iterate through
1727the set of windows even when the minibuffer is on another frame. If
1728the minibuffer does not count, only windows from WINDOW's frame count
1729
1730Optional third arg ALL-FRAMES t means include windows on all frames.
1731ALL-FRAMES nil or omitted means cycle within the frames as specified
1732above. ALL-FRAMES = `visible' means include windows on all visible frames.
1733ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1734If ALL-FRAMES is a frame, restrict search to windows on that frame.
1735Anything else means restrict to WINDOW's frame.
1736
1737If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1738`previous-window' to iterate through the entire cycle of acceptable
1739windows, eventually ending up back at the window you started with.
1740`next-window' traverses the same cycle, in the reverse order. */)
1741 (window, minibuf, all_frames)
67492200 1742 Lisp_Object window, minibuf, all_frames;
7ab12479 1743{
67492200 1744 return next_window (window, minibuf, all_frames, 0);
7ab12479
JB
1745}
1746
67492200 1747
62c07cc7 1748DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
fdb82f93
PJ
1749 doc: /* Select the ARG'th different window on this frame.
1750All windows on current frame are arranged in a cyclic order.
1751This command selects the window ARG steps away in that order.
1752A negative ARG moves in the opposite order. If the optional second
1753argument ALL_FRAMES is non-nil, cycle through all frames. */)
1754 (arg, all_frames)
67492200 1755 Lisp_Object arg, all_frames;
7ab12479 1756{
67492200
GM
1757 Lisp_Object window;
1758 int i;
7ab12479 1759
b7826503 1760 CHECK_NUMBER (arg);
67492200 1761 window = selected_window;
177c0ea7 1762
67492200
GM
1763 for (i = XINT (arg); i > 0; --i)
1764 window = Fnext_window (window, Qnil, all_frames);
1765 for (; i < 0; ++i)
1766 window = Fprevious_window (window, Qnil, all_frames);
50e88778 1767
14d87dc9 1768 Fselect_window (window, Qnil);
7ab12479
JB
1769 return Qnil;
1770}
67492200
GM
1771
1772
1773DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
fdb82f93
PJ
1774 doc: /* Return a list of windows on FRAME, starting with WINDOW.
1775FRAME nil or omitted means use the selected frame.
1776WINDOW nil or omitted means use the selected window.
1777MINIBUF t means include the minibuffer window, even if it isn't active.
1778MINIBUF nil or omitted means include the minibuffer window only
1779if it's active.
1780MINIBUF neither nil nor t means never include the minibuffer window. */)
1781 (frame, minibuf, window)
cd2904bd
GM
1782 Lisp_Object frame, minibuf, window;
1783{
cd2904bd
GM
1784 if (NILP (window))
1785 window = selected_window;
1786 if (NILP (frame))
1787 frame = selected_frame;
1788
1789 if (!EQ (frame, XWINDOW (window)->frame))
1790 error ("Window is on a different frame");
1791
1792 return window_list_1 (window, minibuf, frame);
1793}
1794
1795
1796/* Return a list of windows in canonical ordering. Arguments are like
1797 for `next-window'. */
1798
1799static Lisp_Object
1800window_list_1 (window, minibuf, all_frames)
069f5950 1801 Lisp_Object window, minibuf, all_frames;
67492200
GM
1802{
1803 Lisp_Object tail, list;
1804
1805 decode_next_window_args (&window, &minibuf, &all_frames);
1806 list = Qnil;
177c0ea7 1807
67492200 1808 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
118ea242 1809 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
67492200 1810 list = Fcons (XCAR (tail), list);
177c0ea7 1811
118ea242 1812 return Fnreverse (list);
67492200
GM
1813}
1814
1815
7ab12479
JB
1816\f
1817/* Look at all windows, performing an operation specified by TYPE
1818 with argument OBJ.
75d8f668 1819 If FRAMES is Qt, look at all frames;
75d8f668 1820 Qnil, look at just the selected frame;
89bca612 1821 Qvisible, look at visible frames;
75d8f668 1822 a frame, just look at windows on that frame.
85fe3b5e 1823 If MINI is non-zero, perform the operation on minibuffer windows too. */
7ab12479
JB
1824
1825enum window_loop
1826{
1827 WINDOW_LOOP_UNUSED,
1828 GET_BUFFER_WINDOW, /* Arg is buffer */
1829 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1830 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1831 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1832 GET_LARGEST_WINDOW,
3f8ab7bd
RS
1833 UNSHOW_BUFFER, /* Arg is buffer */
1834 CHECK_ALL_WINDOWS
7ab12479
JB
1835};
1836
1837static Lisp_Object
44fa5b1e 1838window_loop (type, obj, mini, frames)
7ab12479 1839 enum window_loop type;
118ea242 1840 Lisp_Object obj, frames;
7ab12479
JB
1841 int mini;
1842{
118ea242
GM
1843 Lisp_Object window, windows, best_window, frame_arg;
1844 struct frame *f;
ffdc852d 1845 struct gcpro gcpro1;
177c0ea7 1846
44fa5b1e
JB
1847 /* If we're only looping through windows on a particular frame,
1848 frame points to that frame. If we're looping through windows
1849 on all frames, frame is 0. */
1850 if (FRAMEP (frames))
118ea242 1851 f = XFRAME (frames);
44fa5b1e 1852 else if (NILP (frames))
118ea242 1853 f = SELECTED_FRAME ();
7ab12479 1854 else
118ea242 1855 f = NULL;
177c0ea7 1856
118ea242 1857 if (f)
89bca612 1858 frame_arg = Qlambda;
f812f9c6
RS
1859 else if (XFASTINT (frames) == 0)
1860 frame_arg = frames;
89bca612
RS
1861 else if (EQ (frames, Qvisible))
1862 frame_arg = frames;
118ea242
GM
1863 else
1864 frame_arg = Qt;
7ab12479 1865
89bca612
RS
1866 /* frame_arg is Qlambda to stick to one frame,
1867 Qvisible to consider all visible frames,
1868 or Qt otherwise. */
1869
7ab12479 1870 /* Pick a window to start with. */
017b2bad 1871 if (WINDOWP (obj))
118ea242
GM
1872 window = obj;
1873 else if (f)
1874 window = FRAME_SELECTED_WINDOW (f);
7ab12479 1875 else
118ea242 1876 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
4b206065 1877
cd2904bd 1878 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
118ea242 1879 GCPRO1 (windows);
7ab12479 1880 best_window = Qnil;
118ea242
GM
1881
1882 for (; CONSP (windows); windows = CDR (windows))
7ab12479 1883 {
118ea242 1884 struct window *w;
177c0ea7 1885
118ea242
GM
1886 window = XCAR (windows);
1887 w = XWINDOW (window);
177c0ea7 1888
118ea242
GM
1889 /* Note that we do not pay attention here to whether the frame
1890 is visible, since Fwindow_list skips non-visible frames if
1891 that is desired, under the control of frame_arg. */
1892 if (!MINI_WINDOW_P (w)
65a04b96
RS
1893 /* For UNSHOW_BUFFER, we must always consider all windows. */
1894 || type == UNSHOW_BUFFER
7ab12479
JB
1895 || (mini && minibuf_level > 0))
1896 switch (type)
1897 {
1898 case GET_BUFFER_WINDOW:
118ea242 1899 if (EQ (w->buffer, obj)
5c204627
RS
1900 /* Don't find any minibuffer window
1901 except the one that is currently in use. */
118ea242
GM
1902 && (MINI_WINDOW_P (w)
1903 ? EQ (window, minibuf_window)
1904 : 1))
1905 {
5ddc1b75
GM
1906 if (NILP (best_window))
1907 best_window = window;
1908 else if (EQ (window, selected_window))
1909 /* For compatibility with 20.x, prefer to return
1910 selected-window. */
1911 best_window = window;
118ea242 1912 }
7ab12479
JB
1913 break;
1914
1915 case GET_LRU_WINDOW:
1916 /* t as arg means consider only full-width windows */
118ea242 1917 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w))
7ab12479 1918 break;
7ab12479 1919 /* Ignore dedicated windows and minibuffers. */
a5731348 1920 if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
7ab12479 1921 break;
265a9e55 1922 if (NILP (best_window)
7ab12479 1923 || (XFASTINT (XWINDOW (best_window)->use_time)
118ea242
GM
1924 > XFASTINT (w->use_time)))
1925 best_window = window;
7ab12479
JB
1926 break;
1927
1928 case DELETE_OTHER_WINDOWS:
118ea242
GM
1929 if (!EQ (window, obj))
1930 Fdelete_window (window);
7ab12479
JB
1931 break;
1932
1933 case DELETE_BUFFER_WINDOWS:
118ea242 1934 if (EQ (w->buffer, obj))
7ab12479 1935 {
118ea242 1936 struct frame *f = XFRAME (WINDOW_FRAME (w));
3548e138
RS
1937
1938 /* If this window is dedicated, and in a frame of its own,
1939 kill the frame. */
118ea242
GM
1940 if (EQ (window, FRAME_ROOT_WINDOW (f))
1941 && !NILP (w->dedicated)
3548e138 1942 && other_visible_frames (f))
7ab12479 1943 {
3548e138
RS
1944 /* Skip the other windows on this frame.
1945 There might be one, the minibuffer! */
118ea242
GM
1946 while (CONSP (XCDR (windows))
1947 && EQ (XWINDOW (XCAR (windows))->frame,
1948 XWINDOW (XCAR (XCDR (windows)))->frame))
1949 windows = XCDR (windows);
177c0ea7 1950
3548e138 1951 /* Now we can safely delete the frame. */
118ea242
GM
1952 Fdelete_frame (w->frame, Qnil);
1953 }
1954 else if (NILP (w->parent))
1955 {
1956 /* If we're deleting the buffer displayed in the
1957 only window on the frame, find a new buffer to
1958 display there. */
1959 Lisp_Object buffer;
1960 buffer = Fother_buffer (obj, Qnil, w->frame);
949cf20f 1961 Fset_window_buffer (window, buffer, Qnil);
118ea242
GM
1962 if (EQ (window, selected_window))
1963 Fset_buffer (w->buffer);
7ab12479
JB
1964 }
1965 else
118ea242 1966 Fdelete_window (window);
7ab12479
JB
1967 }
1968 break;
1969
1970 case GET_LARGEST_WINDOW:
7ab12479 1971 {
118ea242 1972 /* Ignore dedicated windows and minibuffers. */
a5731348 1973 if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
118ea242 1974 break;
177c0ea7 1975
c930dfab 1976 if (NILP (best_window))
118ea242 1977 best_window = window;
c930dfab
GM
1978 else
1979 {
1980 struct window *b = XWINDOW (best_window);
949cf20f
KS
1981 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
1982 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
c930dfab
GM
1983 best_window = window;
1984 }
7ab12479
JB
1985 }
1986 break;
1987
1988 case UNSHOW_BUFFER:
118ea242 1989 if (EQ (w->buffer, obj))
7ab12479 1990 {
118ea242
GM
1991 Lisp_Object buffer;
1992 struct frame *f = XFRAME (w->frame);
177c0ea7 1993
7ab12479 1994 /* Find another buffer to show in this window. */
118ea242 1995 buffer = Fother_buffer (obj, Qnil, w->frame);
177c0ea7 1996
38ab08d1
RS
1997 /* If this window is dedicated, and in a frame of its own,
1998 kill the frame. */
118ea242
GM
1999 if (EQ (window, FRAME_ROOT_WINDOW (f))
2000 && !NILP (w->dedicated)
38ab08d1 2001 && other_visible_frames (f))
45945a7b
RS
2002 {
2003 /* Skip the other windows on this frame.
2004 There might be one, the minibuffer! */
118ea242
GM
2005 while (CONSP (XCDR (windows))
2006 && EQ (XWINDOW (XCAR (windows))->frame,
2007 XWINDOW (XCAR (XCDR (windows)))->frame))
2008 windows = XCDR (windows);
177c0ea7 2009
45945a7b 2010 /* Now we can safely delete the frame. */
118ea242 2011 Fdelete_frame (w->frame, Qnil);
45945a7b 2012 }
a5731348
SM
2013 else if (!NILP (w->dedicated) && !NILP (w->parent))
2014 {
2015 Lisp_Object window;
2016 XSETWINDOW (window, w);
2017 /* If this window is dedicated and not the only window
2018 in its frame, then kill it. */
2019 Fdelete_window (window);
2020 }
38ab08d1 2021 else
38ab08d1
RS
2022 {
2023 /* Otherwise show a different buffer in the window. */
118ea242 2024 w->dedicated = Qnil;
949cf20f 2025 Fset_window_buffer (window, buffer, Qnil);
118ea242
GM
2026 if (EQ (window, selected_window))
2027 Fset_buffer (w->buffer);
38ab08d1 2028 }
7ab12479
JB
2029 }
2030 break;
3f8ab7bd
RS
2031
2032 /* Check for a window that has a killed buffer. */
2033 case CHECK_ALL_WINDOWS:
118ea242
GM
2034 if (! NILP (w->buffer)
2035 && NILP (XBUFFER (w->buffer)->name))
3f8ab7bd 2036 abort ();
118ea242 2037 break;
6bbd7a29
GM
2038
2039 case WINDOW_LOOP_UNUSED:
2040 break;
7ab12479 2041 }
7ab12479 2042 }
7ab12479 2043
118ea242 2044 UNGCPRO;
7ab12479 2045 return best_window;
37962e60 2046}
605be8af 2047
3f8ab7bd
RS
2048/* Used for debugging. Abort if any window has a dead buffer. */
2049
233a4a2c 2050void
3f8ab7bd
RS
2051check_all_windows ()
2052{
2053 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2054}
2055
7ab12479 2056DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
fdb82f93
PJ
2057 doc: /* Return the window least recently selected or used for display.
2058If optional argument FRAME is `visible', search all visible frames.
2059If FRAME is 0, search all visible and iconified frames.
2060If FRAME is t, search all frames.
2061If FRAME is nil, search only the selected frame.
2062If FRAME is a frame, search only that frame. */)
2063 (frame)
2064 Lisp_Object frame;
7ab12479
JB
2065{
2066 register Lisp_Object w;
2067 /* First try for a window that is full-width */
89bca612 2068 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
265a9e55 2069 if (!NILP (w) && !EQ (w, selected_window))
7ab12479
JB
2070 return w;
2071 /* If none of them, try the rest */
89bca612 2072 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
7ab12479
JB
2073}
2074
2075DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
fdb82f93
PJ
2076 doc: /* Return the largest window in area.
2077If optional argument FRAME is `visible', search all visible frames.
2078If FRAME is 0, search all visible and iconified frames.
2079If FRAME is t, search all frames.
2080If FRAME is nil, search only the selected frame.
2081If FRAME is a frame, search only that frame. */)
2082 (frame)
2083 Lisp_Object frame;
7ab12479
JB
2084{
2085 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
44fa5b1e 2086 frame);
7ab12479
JB
2087}
2088
2089DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
fdb82f93
PJ
2090 doc: /* Return a window currently displaying BUFFER, or nil if none.
2091If optional argument FRAME is `visible', search all visible frames.
2092If optional argument FRAME is 0, search all visible and iconified frames.
2093If FRAME is t, search all frames.
2094If FRAME is nil, search only the selected frame.
2095If FRAME is a frame, search only that frame. */)
2096 (buffer, frame)
2097 Lisp_Object buffer, frame;
7ab12479
JB
2098{
2099 buffer = Fget_buffer (buffer);
017b2bad 2100 if (BUFFERP (buffer))
44fa5b1e 2101 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
7ab12479
JB
2102 else
2103 return Qnil;
2104}
2105
2106DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
fdb82f93
PJ
2107 0, 1, "",
2108 doc: /* Make WINDOW (or the selected window) fill its frame.
2109Only the frame WINDOW is on is affected.
2110This function tries to reduce display jumps
2111by keeping the text previously visible in WINDOW
2112in the same place on the frame. Doing this depends on
2113the value of (window-start WINDOW), so if calling this function
2114in a program gives strange scrolling, make sure the window-start
2115value is reasonable when this function is called. */)
2116 (window)
7ab12479
JB
2117 Lisp_Object window;
2118{
2119 struct window *w;
00d3d838 2120 int startpos;
85fe3b5e 2121 int top, new_top;
7ab12479 2122
265a9e55 2123 if (NILP (window))
7ab12479
JB
2124 window = selected_window;
2125 else
b7826503 2126 CHECK_LIVE_WINDOW (window);
7ab12479 2127 w = XWINDOW (window);
a2b38b3c 2128
00d3d838 2129 startpos = marker_position (w->start);
949cf20f 2130 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
7ab12479 2131
a2b38b3c
RS
2132 if (MINI_WINDOW_P (w) && top > 0)
2133 error ("Can't expand minibuffer to full frame");
2134
70728a80 2135 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
7ab12479 2136
00d3d838
KH
2137 /* Try to minimize scrolling, by setting the window start to the point
2138 will cause the text at the old window start to be at the same place
2139 on the frame. But don't try to do this if the window start is
2140 outside the visible portion (as might happen when the display is
2141 not current, due to typeahead). */
949cf20f 2142 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
85fe3b5e
GM
2143 if (new_top != top
2144 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
00d3d838
KH
2145 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2146 {
2147 struct position pos;
2148 struct buffer *obuf = current_buffer;
2149
2150 Fset_buffer (w->buffer);
2151 /* This computation used to temporarily move point, but that can
2152 have unwanted side effects due to text properties. */
0383eb57 2153 pos = *vmotion (startpos, -top, w);
4d047f50 2154
b73ea88e 2155 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
85fe3b5e 2156 w->window_end_valid = Qnil;
b73ea88e
RS
2157 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2158 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
00d3d838 2159 : Qnil);
80622eec
RS
2160 /* We need to do this, so that the window-scroll-functions
2161 get called. */
4d047f50 2162 w->optional_new_start = Qt;
00d3d838
KH
2163
2164 set_buffer_internal (obuf);
2165 }
5500c422 2166
7ab12479
JB
2167 return Qnil;
2168}
2169
2170DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
fdb82f93
PJ
2171 1, 2, "bDelete windows on (buffer): ",
2172 doc: /* Delete all windows showing BUFFER.
2173Optional second argument FRAME controls which frames are affected.
2174If optional argument FRAME is `visible', search all visible frames.
2175If FRAME is 0, search all visible and iconified frames.
2176If FRAME is nil, search all frames.
2177If FRAME is t, search only the selected frame.
2178If FRAME is a frame, search only that frame. */)
2179 (buffer, frame)
26f6279d 2180 Lisp_Object buffer, frame;
7ab12479 2181{
26f6279d
JB
2182 /* FRAME uses t and nil to mean the opposite of what window_loop
2183 expects. */
c520265e
RS
2184 if (NILP (frame))
2185 frame = Qt;
2186 else if (EQ (frame, Qt))
2187 frame = Qnil;
26f6279d 2188
265a9e55 2189 if (!NILP (buffer))
7ab12479
JB
2190 {
2191 buffer = Fget_buffer (buffer);
b7826503 2192 CHECK_BUFFER (buffer);
26f6279d 2193 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
7ab12479 2194 }
177c0ea7 2195
7ab12479
JB
2196 return Qnil;
2197}
2198
2199DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
fdb82f93
PJ
2200 Sreplace_buffer_in_windows,
2201 1, 1, "bReplace buffer in windows: ",
2202 doc: /* Replace BUFFER with some other buffer in all windows showing it. */)
2203 (buffer)
7ab12479
JB
2204 Lisp_Object buffer;
2205{
265a9e55 2206 if (!NILP (buffer))
7ab12479
JB
2207 {
2208 buffer = Fget_buffer (buffer);
b7826503 2209 CHECK_BUFFER (buffer);
7ab12479
JB
2210 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2211 }
2212 return Qnil;
2213}
ff58478b
RS
2214
2215/* Replace BUFFER with some other buffer in all windows
2216 of all frames, even those on other keyboards. */
2217
2218void
2219replace_buffer_in_all_windows (buffer)
2220 Lisp_Object buffer;
2221{
27abb84f 2222#ifdef MULTI_KBOARD
ff58478b
RS
2223 Lisp_Object tail, frame;
2224
ff58478b
RS
2225 /* A single call to window_loop won't do the job
2226 because it only considers frames on the current keyboard.
2227 So loop manually over frames, and handle each one. */
2228 FOR_EACH_FRAME (tail, frame)
db7f721d 2229 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
ff58478b 2230#else
db7f721d 2231 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
ff58478b
RS
2232#endif
2233}
7ab12479
JB
2234\f
2235/* Set the height of WINDOW and all its inferiors. */
a481b3ea
JB
2236
2237/* The smallest acceptable dimensions for a window. Anything smaller
2238 might crash Emacs. */
5500c422 2239
a481b3ea 2240#define MIN_SAFE_WINDOW_WIDTH (2)
dc1ab1ee 2241#define MIN_SAFE_WINDOW_HEIGHT (1)
a481b3ea
JB
2242
2243/* Make sure that window_min_height and window_min_width are
2244 not too small; if they are, set them to safe minima. */
2245
2246static void
2247check_min_window_sizes ()
2248{
2249 /* Smaller values might permit a crash. */
2250 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2251 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2252 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2253 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2254}
2255
2256/* If *ROWS or *COLS are too small a size for FRAME, set them to the
2257 minimum allowable size. */
5500c422 2258
605be8af 2259void
a481b3ea 2260check_frame_size (frame, rows, cols)
605be8af
JB
2261 FRAME_PTR frame;
2262 int *rows, *cols;
a481b3ea 2263{
628df3bf 2264 /* For height, we have to see:
54b8bcb5
RS
2265 how many windows the frame has at minimum (one or two),
2266 and whether it has a menu bar or other special stuff at the top. */
2267 int min_height
2268 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2269 ? MIN_SAFE_WINDOW_HEIGHT
2270 : 2 * MIN_SAFE_WINDOW_HEIGHT);
177c0ea7 2271
5500c422
GM
2272 if (FRAME_TOP_MARGIN (frame) > 0)
2273 min_height += FRAME_TOP_MARGIN (frame);
a481b3ea
JB
2274
2275 if (*rows < min_height)
2276 *rows = min_height;
2277 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2278 *cols = MIN_SAFE_WINDOW_WIDTH;
2279}
2280
c1636aa6 2281
233a4a2c
GM
2282/* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2283 check if W's width can be changed, otherwise check W's height.
2284 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2285 siblings, too. If none of the siblings is resizable, WINDOW isn't
2286 either. */
c1636aa6 2287
233a4a2c
GM
2288static int
2289window_fixed_size_p (w, width_p, check_siblings_p)
2290 struct window *w;
2291 int width_p, check_siblings_p;
2292{
2293 int fixed_p;
2294 struct window *c;
177c0ea7 2295
233a4a2c
GM
2296 if (!NILP (w->hchild))
2297 {
2298 c = XWINDOW (w->hchild);
177c0ea7 2299
233a4a2c
GM
2300 if (width_p)
2301 {
2302 /* A horiz. combination is fixed-width if all of if its
2303 children are. */
2304 while (c && window_fixed_size_p (c, width_p, 0))
2305 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2306 fixed_p = c == NULL;
2307 }
2308 else
2309 {
2310 /* A horiz. combination is fixed-height if one of if its
2311 children is. */
2312 while (c && !window_fixed_size_p (c, width_p, 0))
2313 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2314 fixed_p = c != NULL;
2315 }
2316 }
2317 else if (!NILP (w->vchild))
2318 {
2319 c = XWINDOW (w->vchild);
177c0ea7 2320
233a4a2c
GM
2321 if (width_p)
2322 {
2323 /* A vert. combination is fixed-width if one of if its
2324 children is. */
2325 while (c && !window_fixed_size_p (c, width_p, 0))
2326 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2327 fixed_p = c != NULL;
2328 }
2329 else
2330 {
2331 /* A vert. combination is fixed-height if all of if its
2332 children are. */
2333 while (c && window_fixed_size_p (c, width_p, 0))
2334 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2335 fixed_p = c == NULL;
2336 }
2337 }
2338 else if (BUFFERP (w->buffer))
2339 {
a34dfd12
GM
2340 if (w->height_fixed_p && !width_p)
2341 fixed_p = 1;
2342 else
233a4a2c 2343 {
a34dfd12
GM
2344 struct buffer *old = current_buffer;
2345 Lisp_Object val;
177c0ea7 2346
a34dfd12
GM
2347 current_buffer = XBUFFER (w->buffer);
2348 val = find_symbol_value (Qwindow_size_fixed);
2349 current_buffer = old;
2350
2351 fixed_p = 0;
2352 if (!EQ (val, Qunbound))
2353 {
2354 fixed_p = !NILP (val);
177c0ea7 2355
a34dfd12
GM
2356 if (fixed_p
2357 && ((EQ (val, Qheight) && width_p)
2358 || (EQ (val, Qwidth) && !width_p)))
2359 fixed_p = 0;
2360 }
233a4a2c
GM
2361 }
2362
2363 /* Can't tell if this one is resizable without looking at
2364 siblings. If all siblings are fixed-size this one is too. */
2365 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2366 {
2367 Lisp_Object child;
177c0ea7 2368
233a4a2c
GM
2369 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2370 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2371 break;
2372
2373 if (NILP (child))
2374 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2375 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2376 break;
2377
2378 if (NILP (child))
2379 fixed_p = 1;
2380 }
2381 }
2382 else
2383 fixed_p = 1;
2384
2385 return fixed_p;
2386}
177c0ea7 2387
233a4a2c
GM
2388
2389/* Return the minimum size of window W, not taking fixed-width windows
2390 into account. WIDTH_P non-zero means return the minimum width,
2391 otherwise return the minimum height. If W is a combination window,
2392 compute the minimum size from the minimum sizes of W's children. */
2393
2394static int
2395window_min_size_1 (w, width_p)
c1636aa6
GM
2396 struct window *w;
2397 int width_p;
2398{
233a4a2c 2399 struct window *c;
c1636aa6 2400 int size;
177c0ea7 2401
233a4a2c
GM
2402 if (!NILP (w->hchild))
2403 {
2404 c = XWINDOW (w->hchild);
2405 size = 0;
177c0ea7 2406
233a4a2c
GM
2407 if (width_p)
2408 {
2409 /* The min width of a horizontal combination is
2410 the sum of the min widths of its children. */
2411 while (c)
2412 {
2413 size += window_min_size_1 (c, width_p);
2414 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2415 }
2416 }
2417 else
2418 {
2419 /* The min height a horizontal combination equals
2420 the maximum of all min height of its children. */
2421 while (c)
2422 {
2423 int min_size = window_min_size_1 (c, width_p);
2424 size = max (min_size, size);
2425 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2426 }
2427 }
2428 }
2429 else if (!NILP (w->vchild))
2430 {
2431 c = XWINDOW (w->vchild);
2432 size = 0;
177c0ea7 2433
233a4a2c
GM
2434 if (width_p)
2435 {
2436 /* The min width of a vertical combination is
2437 the maximum of the min widths of its children. */
2438 while (c)
2439 {
2440 int min_size = window_min_size_1 (c, width_p);
2441 size = max (min_size, size);
2442 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2443 }
2444 }
2445 else
2446 {
2447 /* The min height of a vertical combination equals
2448 the sum of the min height of its children. */
2449 while (c)
2450 {
2451 size += window_min_size_1 (c, width_p);
2452 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2453 }
2454 }
2455 }
c1636aa6
GM
2456 else
2457 {
233a4a2c
GM
2458 if (width_p)
2459 size = window_min_width;
c1636aa6 2460 else
233a4a2c
GM
2461 {
2462 if (MINI_WINDOW_P (w)
2463 || (!WINDOW_WANTS_MODELINE_P (w)
045dee35 2464 && !WINDOW_WANTS_HEADER_LINE_P (w)))
233a4a2c
GM
2465 size = 1;
2466 else
2467 size = window_min_height;
2468 }
c1636aa6
GM
2469 }
2470
2471 return size;
2472}
2473
2474
233a4a2c
GM
2475/* Return the minimum size of window W, taking fixed-size windows into
2476 account. WIDTH_P non-zero means return the minimum width,
f984d4fc
GM
2477 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2478 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2479 unless FIXED is null. */
7ab12479 2480
233a4a2c 2481static int
f984d4fc 2482window_min_size (w, width_p, ignore_fixed_p, fixed)
233a4a2c 2483 struct window *w;
f984d4fc 2484 int width_p, ignore_fixed_p, *fixed;
233a4a2c
GM
2485{
2486 int size, fixed_p;
2487
f984d4fc
GM
2488 if (ignore_fixed_p)
2489 fixed_p = 0;
2490 else
2491 fixed_p = window_fixed_size_p (w, width_p, 1);
177c0ea7 2492
233a4a2c
GM
2493 if (fixed)
2494 *fixed = fixed_p;
177c0ea7 2495
233a4a2c 2496 if (fixed_p)
949cf20f 2497 size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines);
233a4a2c
GM
2498 else
2499 size = window_min_size_1 (w, width_p);
177c0ea7 2500
233a4a2c
GM
2501 return size;
2502}
2503
2504
79fd290e 2505/* Adjust the margins of window W if text area is too small.
949cf20f
KS
2506 Return 1 if window width is ok after adjustment; 0 if window
2507 is still too narrow. */
2508
2509static int
2510adjust_window_margins (w)
2511 struct window *w;
2512{
2513 int box_cols = (WINDOW_TOTAL_COLS (w)
2514 - WINDOW_FRINGE_COLS (w)
2515 - WINDOW_SCROLL_BAR_COLS (w));
2516 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2517 + WINDOW_RIGHT_MARGIN_COLS (w));
2518
2519 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2520 return 1;
2521
2522 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2523 return 0;
2524
2525 /* Window's text area is too narrow, but reducing the window
2526 margins will fix that. */
2527 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2528 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2529 {
2530 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2531 w->left_margin_cols = w->right_margin_cols
2532 = make_number (margin_cols/2);
2533 else
2534 w->right_margin_cols = make_number (margin_cols);
2535 }
2536 else
2537 w->left_margin_cols = make_number (margin_cols);
2538 return 1;
2539}
2540
0aa513ed
JD
2541/* Calculate new sizes for windows in the list FORWARD when the window size
2542 goes from TOTAL to SIZE. TOTAL must be greater than SIZE.
2543 The number of windows in FORWARD is NCHILDREN, and the number that
2544 can shrink is SHRINKABLE.
2545 The minimum size a window can have is MIN_SIZE.
2546 If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
2547 If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
2548 shrinking rows.
2549
2550 This function returns an allocated array of new sizes that the caller
2551 must free. The size -1 means the window is fixed and RESIZE_FIXED_P
2552 is zero. Array index 0 refers to the first window in FORWARD, 1 to
2553 the second, and so on.
2554
2555 This function tries to keep windows at least at the minimum size
2556 and resize other windows before it resizes any window to zero (i.e.
2557 delete that window).
2558
2559 Windows are resized proportional to their size, so bigger windows
2560 shrink more than smaller windows. */
2561static int *
2562shrink_windows (total, size, nchildren, shrinkable,
2563 min_size, resize_fixed_p, forward, width_p)
2564 int total, size, nchildren, shrinkable, min_size;
2565 int resize_fixed_p, width_p;
2566 Lisp_Object forward;
2567{
2568 int available_resize = 0;
2569 int *new_sizes;
2570 struct window *c;
2571 Lisp_Object child;
2572 int smallest = total;
2573 int total_removed = 0;
2574 int total_shrink = total - size;
2575 int i;
2576
2577 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2578
2579 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2580 {
2581 int child_size;
2582
2583 c = XWINDOW (child);
2584 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2585
2586 if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2587 new_sizes[i] = -1;
2588 else
2589 {
2590 new_sizes[i] = child_size;
2591 if (child_size > min_size)
2592 available_resize += child_size - min_size;
2593 }
2594 }
2595 /* We might need to shrink some windows to zero. Find the smallest
2596 windows and set them to 0 until we can fulfil the new size. */
2597
2598 while (shrinkable > 1 && size + available_resize < total)
2599 {
2600 for (i = 0; i < nchildren; ++i)
2601 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2602 smallest = new_sizes[i];
2603
2604 for (i = 0; i < nchildren; ++i)
2605 if (new_sizes[i] == smallest)
2606 {
2607 /* Resize this window down to zero. */
2608 new_sizes[i] = 0;
2609 if (smallest > min_size)
2610 available_resize -= smallest - min_size;
2611 available_resize += smallest;
2612 --shrinkable;
2613 total_removed += smallest;
2614
2615 /* Out of for, just remove one window at the time and
2616 check again if we have enough space. */
2617 break;
2618 }
2619 }
2620
2621 /* Now, calculate the new sizes. Try to shrink each window
2622 proportional to its size. */
2623 for (i = 0; i < nchildren; ++i)
2624 {
2625 if (new_sizes[i] > min_size)
2626 {
2627 int to_shrink = total_shrink*new_sizes[i]/total;
2628 if (new_sizes[i] - to_shrink < min_size)
2629 to_shrink = new_sizes[i] - min_size;
2630 new_sizes[i] -= to_shrink;
2631 total_removed += to_shrink;
2632 }
2633 }
2634
2635 /* Any reminder due to rounding, we just subtract from windows
2636 that are left and still can be shrunk. */
2637 while (total_shrink > total_removed)
2638 {
2639 for (i = 0; i < nchildren; ++i)
2640 if (new_sizes[i] > min_size)
2641 {
2642 --new_sizes[i];
2643 ++total_removed;
2644
2645 /* Out of for, just shrink one window at the time and
2646 check again if we have enough space. */
2647 break;
2648 }
2649 }
2650
2651 return new_sizes;
2652}
949cf20f 2653
233a4a2c
GM
2654/* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2655 WINDOW's width. Resize WINDOW's children, if any, so that they
2656 keep their proportionate size relative to WINDOW. Propagate
2657 WINDOW's top or left edge position to children. Delete windows
192c3131
RS
2658 that become too small unless NODELETE_P is non-zero.
2659
2660 If NODELETE_P is 2, that means we do delete windows that are
2661 too small, even if they were too small before! */
233a4a2c
GM
2662
2663static void
2664size_window (window, size, width_p, nodelete_p)
7ab12479 2665 Lisp_Object window;
233a4a2c 2666 int size, width_p, nodelete_p;
7ab12479 2667{
233a4a2c
GM
2668 struct window *w = XWINDOW (window);
2669 struct window *c;
2670 Lisp_Object child, *forward, *sideward;
949cf20f 2671 int old_size, min_size, safe_min_size;
7ab12479 2672
949cf20f
KS
2673 /* We test nodelete_p != 2 and nodelete_p != 1 below, so it
2674 seems like it's too soon to do this here. ++KFS. */
192c3131
RS
2675 if (nodelete_p == 2)
2676 nodelete_p = 0;
2677
a481b3ea 2678 check_min_window_sizes ();
7ae2f10f 2679 size = max (0, size);
177c0ea7 2680
b5f05b50
GM
2681 /* If the window has been "too small" at one point,
2682 don't delete it for being "too small" in the future.
2683 Preserve it as long as that is at all possible. */
233a4a2c
GM
2684 if (width_p)
2685 {
949cf20f 2686 old_size = WINDOW_TOTAL_COLS (w);
233a4a2c 2687 min_size = window_min_width;
949cf20f
KS
2688 /* Ensure that there is room for the scroll bar and fringes!
2689 We may reduce display margins though. */
2690 safe_min_size = (MIN_SAFE_WINDOW_WIDTH
2691 + WINDOW_FRINGE_COLS (w)
2692 + WINDOW_SCROLL_BAR_COLS (w));
233a4a2c
GM
2693 }
2694 else
2695 {
949cf20f 2696 old_size = XINT (w->total_lines);
233a4a2c 2697 min_size = window_min_height;
949cf20f 2698 safe_min_size = MIN_SAFE_WINDOW_HEIGHT;
233a4a2c 2699 }
192c3131
RS
2700
2701 if (old_size < min_size && nodelete_p != 2)
b5f05b50
GM
2702 w->too_small_ok = Qt;
2703
233a4a2c 2704 /* Maybe delete WINDOW if it's too small. */
192c3131 2705 if (nodelete_p != 1 && !NILP (w->parent))
7ab12479 2706 {
b5f05b50 2707 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
233a4a2c 2708 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
949cf20f
KS
2709 if (min_size < safe_min_size)
2710 min_size = safe_min_size;
233a4a2c 2711 if (size < min_size)
c1636aa6
GM
2712 {
2713 delete_window (window);
2714 return;
2715 }
7ab12479
JB
2716 }
2717
233a4a2c 2718 /* Set redisplay hints. */
7ae2f10f
GM
2719 w->last_modified = make_number (0);
2720 w->last_overlay_modified = make_number (0);
7ab12479 2721 windows_or_buffers_changed++;
7ae2f10f 2722 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
29aeee73 2723
233a4a2c
GM
2724 if (width_p)
2725 {
2726 sideward = &w->vchild;
2727 forward = &w->hchild;
949cf20f
KS
2728 w->total_cols = make_number (size);
2729 adjust_window_margins (w);
233a4a2c
GM
2730 }
2731 else
2732 {
2733 sideward = &w->hchild;
2734 forward = &w->vchild;
949cf20f
KS
2735 w->total_lines = make_number (size);
2736 w->orig_total_lines = Qnil;
233a4a2c
GM
2737 }
2738
2739 if (!NILP (*sideward))
7ab12479 2740 {
233a4a2c 2741 for (child = *sideward; !NILP (child); child = c->next)
7ab12479 2742 {
233a4a2c
GM
2743 c = XWINDOW (child);
2744 if (width_p)
949cf20f 2745 c->left_col = w->left_col;
233a4a2c 2746 else
949cf20f 2747 c->top_line = w->top_line;
233a4a2c 2748 size_window (child, size, width_p, nodelete_p);
7ab12479
JB
2749 }
2750 }
233a4a2c 2751 else if (!NILP (*forward))
7ab12479 2752 {
233a4a2c
GM
2753 int fixed_size, each, extra, n;
2754 int resize_fixed_p, nfixed;
8b6d9dc9 2755 int last_pos, first_pos, nchildren, total;
0aa513ed 2756 int *new_sizes = NULL;
233a4a2c
GM
2757
2758 /* Determine the fixed-size portion of the this window, and the
2759 number of child windows. */
8b6d9dc9 2760 fixed_size = nchildren = nfixed = total = 0;
233a4a2c 2761 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
7ab12479 2762 {
8b6d9dc9 2763 int child_size;
177c0ea7 2764
7ab12479 2765 c = XWINDOW (child);
949cf20f 2766 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
8b6d9dc9 2767 total += child_size;
177c0ea7 2768
233a4a2c
GM
2769 if (window_fixed_size_p (c, width_p, 0))
2770 {
8b6d9dc9 2771 fixed_size += child_size;
233a4a2c
GM
2772 ++nfixed;
2773 }
2774 }
7ab12479 2775
233a4a2c
GM
2776 /* If the new size is smaller than fixed_size, or if there
2777 aren't any resizable windows, allow resizing fixed-size
2778 windows. */
2779 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2780
0aa513ed 2781 /* Compute how many lines/columns to add/remove to each child. The
233a4a2c
GM
2782 value of extra takes care of rounding errors. */
2783 n = resize_fixed_p ? nchildren : nchildren - nfixed;
0aa513ed
JD
2784 if (size < total && n > 1)
2785 new_sizes = shrink_windows (total, size, nchildren, n, min_size,
2786 resize_fixed_p, *forward, width_p);
2787 else
2788 {
2789 each = (size - total) / n;
2790 extra = (size - total) - n * each;
2791 }
233a4a2c
GM
2792
2793 /* Compute new children heights and edge positions. */
949cf20f 2794 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
233a4a2c 2795 last_pos = first_pos;
0aa513ed 2796 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
233a4a2c
GM
2797 {
2798 int new_size, old_size;
177c0ea7 2799
233a4a2c 2800 c = XWINDOW (child);
949cf20f 2801 old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines);
233a4a2c 2802 new_size = old_size;
7ab12479 2803
233a4a2c
GM
2804 /* The top or left edge position of this child equals the
2805 bottom or right edge of its predecessor. */
2806 if (width_p)
949cf20f 2807 c->left_col = make_number (last_pos);
233a4a2c 2808 else
949cf20f 2809 c->top_line = make_number (last_pos);
7ab12479 2810
233a4a2c
GM
2811 /* If this child can be resized, do it. */
2812 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2813 {
0aa513ed 2814 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
233a4a2c
GM
2815 extra = 0;
2816 }
177c0ea7 2817
233a4a2c
GM
2818 /* Set new height. Note that size_window also propagates
2819 edge positions to children, so it's not a no-op if we
2820 didn't change the child's size. */
2821 size_window (child, new_size, width_p, 1);
2822
2823 /* Remember the bottom/right edge position of this child; it
2824 will be used to set the top/left edge of the next child. */
0aa513ed 2825 last_pos += new_size;
7ab12479 2826 }
233a4a2c 2827
0aa513ed
JD
2828 if (new_sizes) xfree (new_sizes);
2829
233a4a2c
GM
2830 /* We should have covered the parent exactly with child windows. */
2831 xassert (size == last_pos - first_pos);
177c0ea7 2832
7ab12479 2833 /* Now delete any children that became too small. */
233a4a2c
GM
2834 if (!nodelete_p)
2835 for (child = *forward; !NILP (child); child = c->next)
7ab12479 2836 {
233a4a2c
GM
2837 int child_size;
2838 c = XWINDOW (child);
949cf20f 2839 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
192c3131 2840 size_window (child, child_size, width_p, 2);
7ab12479
JB
2841 }
2842 }
2843}
2844
233a4a2c
GM
2845/* Set WINDOW's height to HEIGHT, and recursively change the height of
2846 WINDOW's children. NODELETE non-zero means don't delete windows
2847 that become too small in the process. (The caller should check
2848 later and do so if appropriate.) */
7ab12479 2849
5e14b1fc 2850void
233a4a2c 2851set_window_height (window, height, nodelete)
7ab12479 2852 Lisp_Object window;
233a4a2c 2853 int height;
7ab12479
JB
2854 int nodelete;
2855{
233a4a2c
GM
2856 size_window (window, height, 0, nodelete);
2857}
7ab12479 2858
7ab12479 2859
233a4a2c
GM
2860/* Set WINDOW's width to WIDTH, and recursively change the width of
2861 WINDOW's children. NODELETE non-zero means don't delete windows
2862 that become too small in the process. (The caller should check
2863 later and do so if appropriate.) */
7ab12479 2864
233a4a2c
GM
2865void
2866set_window_width (window, width, nodelete)
2867 Lisp_Object window;
2868 int width;
2869 int nodelete;
2870{
2871 size_window (window, width, 1, nodelete);
7ab12479 2872}
233a4a2c 2873
cdbc7fec
KS
2874/* Change window heights in windows rooted in WINDOW by N lines. */
2875
2876void
2877change_window_heights (window, n)
2878 Lisp_Object window;
2879 int n;
2880{
2881 struct window *w = XWINDOW (window);
2882
949cf20f
KS
2883 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
2884 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
cdbc7fec 2885
949cf20f
KS
2886 if (INTEGERP (w->orig_top_line))
2887 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
2888 if (INTEGERP (w->orig_total_lines))
2889 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
cdbc7fec
KS
2890
2891 /* Handle just the top child in a vertical split. */
2892 if (!NILP (w->vchild))
2893 change_window_heights (w->vchild, n);
2894
2895 /* Adjust all children in a horizontal split. */
2896 for (window = w->hchild; !NILP (window); window = w->next)
2897 {
2898 w = XWINDOW (window);
2899 change_window_heights (window, n);
2900 }
2901}
2902
7ab12479 2903\f
1d8d96fa 2904int window_select_count;
7ab12479 2905
5b03d3c0
RS
2906Lisp_Object
2907Fset_window_buffer_unwind (obuf)
2908 Lisp_Object obuf;
2909{
2910 Fset_buffer (obuf);
2911 return Qnil;
2912}
2913
56613f06
SM
2914EXFUN (Fset_window_fringes, 4);
2915EXFUN (Fset_window_scroll_bars, 4);
7ab12479 2916
5500c422
GM
2917/* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2918 means it's allowed to run hooks. See make_frame for a case where
949cf20f
KS
2919 it's not allowed. KEEP_MARGINS_P non-zero means that the current
2920 margins, fringes, and scroll-bar settings of the window are not
2921 reset from the buffer's local settings. */
7ab12479 2922
5500c422 2923void
949cf20f 2924set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
5500c422 2925 Lisp_Object window, buffer;
949cf20f 2926 int run_hooks_p, keep_margins_p;
5500c422
GM
2927{
2928 struct window *w = XWINDOW (window);
2929 struct buffer *b = XBUFFER (buffer);
aed13378 2930 int count = SPECPDL_INDEX ();
7ab12479
JB
2931
2932 w->buffer = buffer;
86e48436
RS
2933
2934 if (EQ (window, selected_window))
5500c422 2935 b->last_selected_window = window;
beb4e312
RS
2936
2937 /* Update time stamps of buffer display. */
5500c422
GM
2938 if (INTEGERP (b->display_count))
2939 XSETINT (b->display_count, XINT (b->display_count) + 1);
2940 b->display_time = Fcurrent_time ();
86e48436 2941
d834a2e9 2942 XSETFASTINT (w->window_end_pos, 0);
5500c422
GM
2943 XSETFASTINT (w->window_end_vpos, 0);
2944 bzero (&w->last_cursor, sizeof w->last_cursor);
5a41ab94 2945 w->window_end_valid = Qnil;
1c686c99 2946 w->hscroll = w->min_hscroll = make_number (0);
224227d1 2947 w->vscroll = 0;
5500c422 2948 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
7ab12479 2949 set_marker_restricted (w->start,
5500c422 2950 make_number (b->last_window_start),
7ab12479
JB
2951 buffer);
2952 w->start_at_line_beg = Qnil;
e36ab06b 2953 w->force_start = Qnil;
d834a2e9 2954 XSETFASTINT (w->last_modified, 0);
3cd21523 2955 XSETFASTINT (w->last_overlay_modified, 0);
7ab12479 2956 windows_or_buffers_changed++;
5b03d3c0
RS
2957
2958 /* We must select BUFFER for running the window-scroll-functions.
2959 If WINDOW is selected, switch permanently.
2960 Otherwise, switch but go back to the ambient buffer afterward. */
7ab12479
JB
2961 if (EQ (window, selected_window))
2962 Fset_buffer (buffer);
5b03d3c0
RS
2963 /* We can't check ! NILP (Vwindow_scroll_functions) here
2964 because that might itself be a local variable. */
2965 else if (window_initialized)
2966 {
2967 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2968 Fset_buffer (buffer);
2969 }
2970
949cf20f
KS
2971 if (!keep_margins_p)
2972 {
2973 /* Set left and right marginal area width etc. from buffer. */
2974
79fd290e 2975 /* This may call adjust_window_margins three times, so
949cf20f 2976 temporarily disable window margins. */
3834380d
KS
2977 Lisp_Object save_left = w->left_margin_cols;
2978 Lisp_Object save_right = w->right_margin_cols;
2979
949cf20f
KS
2980 w->left_margin_cols = w->right_margin_cols = Qnil;
2981
2982 Fset_window_fringes (window,
2983 b->left_fringe_width, b->right_fringe_width,
2984 b->fringes_outside_margins);
2985
2986 Fset_window_scroll_bars (window,
2987 b->scroll_bar_width,
2988 b->vertical_scroll_bar_type, Qnil);
2989
3834380d
KS
2990 w->left_margin_cols = save_left;
2991 w->right_margin_cols = save_right;
2992
949cf20f
KS
2993 Fset_window_margins (window,
2994 b->left_margin_cols, b->right_margin_cols);
2995 }
7ab12479 2996
5500c422
GM
2997 if (run_hooks_p)
2998 {
2999 if (! NILP (Vwindow_scroll_functions))
3000 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3001 Fmarker_position (w->start));
3002
3003 if (! NILP (Vwindow_configuration_change_hook)
3004 && ! NILP (Vrun_hooks))
3005 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3006 }
543f5fb1 3007
5b03d3c0 3008 unbind_to (count, Qnil);
5500c422 3009}
5b03d3c0 3010
5500c422 3011
949cf20f 3012DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
fdb82f93 3013 doc: /* Make WINDOW display BUFFER as its contents.
79fd290e 3014BUFFER can be a buffer or buffer name.
949cf20f
KS
3015Optional third arg KEEP_MARGINS non-nil means that WINDOW's current
3016display margins, fringe widths, and scroll bar settings are maintained;
3017the default is to reset these from BUFFER's local settings or the frame
3018defaults. */)
3019 (window, buffer, keep_margins)
56613f06 3020 register Lisp_Object window, buffer, keep_margins;
5500c422
GM
3021{
3022 register Lisp_Object tem;
3023 register struct window *w = decode_window (window);
5500c422 3024
bed0c171 3025 XSETWINDOW (window, w);
5500c422 3026 buffer = Fget_buffer (buffer);
b7826503 3027 CHECK_BUFFER (buffer);
5500c422
GM
3028
3029 if (NILP (XBUFFER (buffer)->name))
3030 error ("Attempt to display deleted buffer");
3031
3032 tem = w->buffer;
3033 if (NILP (tem))
3034 error ("Window is deleted");
3035 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3036 is first being set up. */
3037 {
3038 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3039 error ("Window is dedicated to `%s'",
d5db4077 3040 SDATA (XBUFFER (tem)->name));
5500c422
GM
3041
3042 unshow_buffer (w);
3043 }
3044
949cf20f 3045 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
7ab12479
JB
3046 return Qnil;
3047}
3048
2d0834cc
SM
3049/* Note that selected_window can be nil
3050 when this is called from Fset_window_configuration. */
3051
14d87dc9 3052DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
fdb82f93
PJ
3053 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3054If WINDOW is not already selected, also make WINDOW's buffer current.
d1755117 3055Also make WINDOW the frame's selected window.
14d87dc9
SM
3056Optional second arg NORECORD non-nil means
3057do not put this buffer at the front of the list of recently selected ones.
282f7831 3058
fdb82f93
PJ
3059Note that the main editor command loop
3060selects the buffer of the selected window before each command. */)
14d87dc9
SM
3061 (window, norecord)
3062 register Lisp_Object window, norecord;
7ab12479
JB
3063{
3064 register struct window *w;
719eaeb1 3065 register struct window *ow;
1ae1a37d 3066 struct frame *sf;
7ab12479 3067
b7826503 3068 CHECK_LIVE_WINDOW (window);
7ab12479
JB
3069
3070 w = XWINDOW (window);
50e88778 3071 w->frozen_window_start_p = 0;
7ab12479 3072
d834a2e9 3073 XSETFASTINT (w->use_time, ++window_select_count);
7ab12479
JB
3074 if (EQ (window, selected_window))
3075 return window;
3076
719eaeb1
GM
3077 if (!NILP (selected_window))
3078 {
3079 ow = XWINDOW (selected_window);
3080 if (! NILP (ow->buffer))
3081 set_marker_both (ow->pointm, ow->buffer,
3082 BUF_PT (XBUFFER (ow->buffer)),
3083 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3084 }
7ab12479
JB
3085
3086 selected_window = window;
1ae1a37d 3087 sf = SELECTED_FRAME ();
d1755117
RS
3088 if (XFRAME (WINDOW_FRAME (w)) != sf)
3089 {
3090 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3091 /* Use this rather than Fhandle_switch_frame
3092 so that FRAME_FOCUS_FRAME is moved appropriately as we
3093 move around in the state where a minibuffer in a separate
3094 frame is active. */
3095 Fselect_frame (WINDOW_FRAME (w), Qnil);
3096 }
3097 else
1ae1a37d 3098 sf->selected_window = window;
7ab12479 3099
14d87dc9 3100 if (NILP (norecord))
b7354ddf 3101 record_buffer (w->buffer);
7ab12479
JB
3102 Fset_buffer (w->buffer);
3103
86e48436
RS
3104 XBUFFER (w->buffer)->last_selected_window = window;
3105
7ab12479
JB
3106 /* Go to the point recorded in the window.
3107 This is important when the buffer is in more
3108 than one window. It also matters when
3109 redisplay_window has altered point after scrolling,
3110 because it makes the change only in the window. */
3111 {
3112 register int new_point = marker_position (w->pointm);
3113 if (new_point < BEGV)
3114 SET_PT (BEGV);
a9c95e08 3115 else if (new_point > ZV)
7ab12479
JB
3116 SET_PT (ZV);
3117 else
3118 SET_PT (new_point);
3119 }
3120
3121 windows_or_buffers_changed++;
3122 return window;
3123}
14d87dc9
SM
3124
3125static Lisp_Object
3126select_window_norecord (window)
3127 Lisp_Object window;
3128{
3129 return Fselect_window (window, Qt);
3130}
b7354ddf 3131\f
441a127e
RS
3132/* Deiconify the frame containing the window WINDOW,
3133 unless it is the selected frame;
3134 then return WINDOW.
3135
3136 The reason for the exception for the selected frame
3137 is that it seems better not to change the selected frames visibility
3138 merely because of displaying a different buffer in it.
3139 The deiconification is useful when a buffer gets shown in
3140 another frame that you were not using lately. */
d07f802a
RS
3141
3142static Lisp_Object
3143display_buffer_1 (window)
3144 Lisp_Object window;
3145{
1ae1a37d
GM
3146 Lisp_Object frame = XWINDOW (window)->frame;
3147 FRAME_PTR f = XFRAME (frame);
177c0ea7 3148
d07f802a 3149 FRAME_SAMPLE_VISIBILITY (f);
177c0ea7 3150
2d0834cc
SM
3151 if (EQ (frame, selected_frame))
3152 ; /* Assume the selected frame is already visible enough. */
3153 else if (minibuf_level > 0
3154 && MINI_WINDOW_P (XWINDOW (selected_window))
3155 && WINDOW_LIVE_P (minibuf_selected_window)
3156 && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
3157 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3158 else
60117126
RS
3159 {
3160 if (FRAME_ICONIFIED_P (f))
1ae1a37d 3161 Fmake_frame_visible (frame);
37962e60 3162 else if (FRAME_VISIBLE_P (f))
1ae1a37d 3163 Fraise_frame (frame);
60117126 3164 }
177c0ea7 3165
d07f802a
RS
3166 return window;
3167}
3168
4628f7a4 3169DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
fdb82f93
PJ
3170 doc: /* Returns non-nil if a buffer named BUFFER-NAME would be created specially.
3171The value is actually t if the frame should be called with default frame
3172parameters, and a list of frame parameters if they were specified.
3173See `special-display-buffer-names', and `special-display-regexps'. */)
3174 (buffer_name)
4628f7a4
EN
3175 Lisp_Object buffer_name;
3176{
3177 Lisp_Object tem;
3178
b7826503 3179 CHECK_STRING (buffer_name);
4628f7a4
EN
3180
3181 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
3182 if (!NILP (tem))
3183 return Qt;
3184
3185 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
3186 if (!NILP (tem))
3187 return XCDR (tem);
3188
3189 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
3190 {
3191 Lisp_Object car = XCAR (tem);
3192 if (STRINGP (car)
3193 && fast_string_match (car, buffer_name) >= 0)
3194 return Qt;
3195 else if (CONSP (car)
3196 && STRINGP (XCAR (car))
3197 && fast_string_match (XCAR (car), buffer_name) >= 0)
0057b00a 3198 return XCDR (car);
4628f7a4
EN
3199 }
3200 return Qnil;
177c0ea7 3201}
4628f7a4
EN
3202
3203DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
fdb82f93
PJ
3204 doc: /* Returns non-nil if a new buffer named BUFFER-NAME would use the same window.
3205See `same-window-buffer-names' and `same-window-regexps'. */)
3206 (buffer_name)
4628f7a4
EN
3207 Lisp_Object buffer_name;
3208{
3209 Lisp_Object tem;
3210
b7826503 3211 CHECK_STRING (buffer_name);
4628f7a4
EN
3212
3213 tem = Fmember (buffer_name, Vsame_window_buffer_names);
3214 if (!NILP (tem))
3215 return Qt;
3216
3217 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
3218 if (!NILP (tem))
3219 return Qt;
3220
3221 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3222 {
3223 Lisp_Object car = XCAR (tem);
3224 if (STRINGP (car)
3225 && fast_string_match (car, buffer_name) >= 0)
3226 return Qt;
3227 else if (CONSP (car)
3228 && STRINGP (XCAR (car))
3229 && fast_string_match (XCAR (car), buffer_name) >= 0)
3230 return Qt;
3231 }
3232 return Qnil;
3233}
3234
fdb82f93 3235/* Use B so the default is (other-buffer). */
53f76081 3236DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
fdb82f93
PJ
3237 "BDisplay buffer: \nP",
3238 doc: /* Make BUFFER appear in some window but don't select it.
3239BUFFER can be a buffer or a buffer name.
3240If BUFFER is shown already in some window, just use that one,
3241unless the window is the selected window and the optional second
3242argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3243If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3244Returns the window displaying BUFFER.
079d288f 3245If `display-buffer-reuse-frames' is non-nil, and another frame is currently
fdb82f93
PJ
3246displaying BUFFER, then simply raise that frame.
3247
3248The variables `special-display-buffer-names', `special-display-regexps',
3249`same-window-buffer-names', and `same-window-regexps' customize how certain
3250buffer names are handled.
3251
3252If optional argument FRAME is `visible', search all visible frames.
3253If FRAME is 0, search all visible and iconified frames.
3254If FRAME is t, search all frames.
3255If FRAME is a frame, search only that frame.
3256If FRAME is nil, search only the selected frame
3257 (actually the last nonminibuffer frame),
3258 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3259 which means search visible and iconified frames.
3260
3261If `even-window-heights' is non-nil, window heights will be evened out
3262if displaying the buffer causes two vertically adjacent windows to be
3263displayed. */)
3264 (buffer, not_this_window, frame)
53f76081 3265 register Lisp_Object buffer, not_this_window, frame;
7ab12479 3266{
aee631c2 3267 register Lisp_Object window, tem, swp;
1ae1a37d 3268 struct frame *f;
7ab12479 3269
aee631c2 3270 swp = Qnil;
7ab12479 3271 buffer = Fget_buffer (buffer);
b7826503 3272 CHECK_BUFFER (buffer);
7ab12479 3273
265a9e55 3274 if (!NILP (Vdisplay_buffer_function))
7ab12479
JB
3275 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3276
265a9e55 3277 if (NILP (not_this_window)
7ab12479 3278 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
d07f802a 3279 return display_buffer_1 (selected_window);
7ab12479 3280
855d8627
RS
3281 /* See if the user has specified this buffer should appear
3282 in the selected window. */
3283 if (NILP (not_this_window))
3284 {
aee631c2
RS
3285 swp = Fsame_window_p (XBUFFER (buffer)->name);
3286 if (!NILP (swp) && !no_switch_window (selected_window))
c63dc4a2
RS
3287 {
3288 Fswitch_to_buffer (buffer, Qnil);
d07f802a 3289 return display_buffer_1 (selected_window);
c63dc4a2 3290 }
855d8627
RS
3291 }
3292
079d288f 3293 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
73dc5198
KH
3294 look for a window showing BUFFER on any visible or iconified frame.
3295 Otherwise search only the current frame. */
53f76081
RS
3296 if (! NILP (frame))
3297 tem = frame;
9c3da604
GM
3298 else if (pop_up_frames
3299 || display_buffer_reuse_frames
3300 || last_nonminibuf_frame == 0)
73dc5198
KH
3301 XSETFASTINT (tem, 0);
3302 else
73dc5198 3303 XSETFRAME (tem, last_nonminibuf_frame);
177c0ea7 3304
73dc5198 3305 window = Fget_buffer_window (buffer, tem);
265a9e55
JB
3306 if (!NILP (window)
3307 && (NILP (not_this_window) || !EQ (window, selected_window)))
9c3da604 3308 return display_buffer_1 (window);
7ab12479 3309
a90712c2 3310 /* Certain buffer names get special handling. */
aee631c2 3311 if (!NILP (Vspecial_display_function) && NILP (swp))
a90712c2 3312 {
4628f7a4
EN
3313 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3314 if (EQ (tem, Qt))
a90712c2 3315 return call1 (Vspecial_display_function, buffer);
4628f7a4
EN
3316 if (CONSP (tem))
3317 return call2 (Vspecial_display_function, buffer, tem);
a90712c2
RS
3318 }
3319
44fa5b1e
JB
3320 /* If there are no frames open that have more than a minibuffer,
3321 we need to create a new frame. */
3322 if (pop_up_frames || last_nonminibuf_frame == 0)
7ab12479 3323 {
a90712c2 3324 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
949cf20f 3325 Fset_window_buffer (window, buffer, Qnil);
d07f802a 3326 return display_buffer_1 (window);
7ab12479 3327 }
7ab12479 3328
1ae1a37d 3329 f = SELECTED_FRAME ();
43bad991 3330 if (pop_up_windows
1ae1a37d 3331 || FRAME_MINIBUF_ONLY_P (f)
cee67da9
RS
3332 /* If the current frame is a special display frame,
3333 don't try to reuse its windows. */
1ae1a37d 3334 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
7ab12479 3335 {
12cae7c0
KH
3336 Lisp_Object frames;
3337
37962e60 3338 frames = Qnil;
1ae1a37d 3339 if (FRAME_MINIBUF_ONLY_P (f))
74112613 3340 XSETFRAME (frames, last_nonminibuf_frame);
a5731348 3341 /* Don't try to create a window if we would get an error. */
7ab12479
JB
3342 if (split_height_threshold < window_min_height << 1)
3343 split_height_threshold = window_min_height << 1;
3344
cee67da9
RS
3345 /* Note that both Fget_largest_window and Fget_lru_window
3346 ignore minibuffers and dedicated windows.
3347 This means they can return nil. */
7ab12479 3348
cee67da9
RS
3349 /* If the frame we would try to split cannot be split,
3350 try other frames. */
1ae1a37d 3351 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
cee67da9
RS
3352 {
3353 /* Try visible frames first. */
3354 window = Fget_largest_window (Qvisible);
3355 /* If that didn't work, try iconified frames. */
3356 if (NILP (window))
3357 window = Fget_largest_window (make_number (0));
3358 if (NILP (window))
3359 window = Fget_largest_window (Qt);
3360 }
3361 else
3362 window = Fget_largest_window (frames);
3363
92cca945
RS
3364 /* If we got a tall enough full-width window that can be split,
3365 split it. */
265a9e55 3366 if (!NILP (window)
92cca945 3367 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
7ab12479 3368 && window_height (window) >= split_height_threshold
111e5992 3369 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
7ab12479
JB
3370 window = Fsplit_window (window, Qnil, Qnil);
3371 else
3372 {
1942f68f
RS
3373 Lisp_Object upper, lower, other;
3374
44fa5b1e 3375 window = Fget_lru_window (frames);
92cca945
RS
3376 /* If the LRU window is selected, and big enough,
3377 and can be split, split it. */
cee67da9 3378 if (!NILP (window)
92cca945 3379 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
cee67da9
RS
3380 && (EQ (window, selected_window)
3381 || EQ (XWINDOW (window)->parent, Qnil))
7ab12479
JB
3382 && window_height (window) >= window_min_height << 1)
3383 window = Fsplit_window (window, Qnil, Qnil);
cee67da9 3384 /* If Fget_lru_window returned nil, try other approaches. */
48d9379d 3385
cee67da9 3386 /* Try visible frames first. */
48d9379d
RS
3387 if (NILP (window))
3388 window = Fget_buffer_window (buffer, Qvisible);
cee67da9
RS
3389 if (NILP (window))
3390 window = Fget_largest_window (Qvisible);
3391 /* If that didn't work, try iconified frames. */
48d9379d
RS
3392 if (NILP (window))
3393 window = Fget_buffer_window (buffer, make_number (0));
cee67da9
RS
3394 if (NILP (window))
3395 window = Fget_largest_window (make_number (0));
3396 /* Try invisible frames. */
48d9379d
RS
3397 if (NILP (window))
3398 window = Fget_buffer_window (buffer, Qt);
cee67da9
RS
3399 if (NILP (window))
3400 window = Fget_largest_window (Qt);
3401 /* As a last resort, make a new frame. */
3402 if (NILP (window))
3403 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
1942f68f
RS
3404 /* If window appears above or below another,
3405 even out their heights. */
cac66e4f 3406 other = upper = lower = Qnil;
1942f68f
RS
3407 if (!NILP (XWINDOW (window)->prev))
3408 other = upper = XWINDOW (window)->prev, lower = window;
3409 if (!NILP (XWINDOW (window)->next))
3410 other = lower = XWINDOW (window)->next, upper = window;
3411 if (!NILP (other)
6529ed87 3412 && !NILP (Veven_window_heights)
1942f68f 3413 /* Check that OTHER and WINDOW are vertically arrayed. */
949cf20f
KS
3414 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3415 && (XFASTINT (XWINDOW (other)->total_lines)
3416 > XFASTINT (XWINDOW (window)->total_lines)))
1942f68f 3417 {
949cf20f
KS
3418 int total = (XFASTINT (XWINDOW (other)->total_lines)
3419 + XFASTINT (XWINDOW (window)->total_lines));
86c8e823 3420 enlarge_window (upper,
949cf20f 3421 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
f95284d2 3422 0, 0);
1942f68f 3423 }
7ab12479
JB
3424 }
3425 }
3426 else
3427 window = Fget_lru_window (Qnil);
3428
949cf20f 3429 Fset_window_buffer (window, buffer, Qnil);
d07f802a 3430 return display_buffer_1 (window);
7ab12479
JB
3431}
3432
3433void
3434temp_output_buffer_show (buf)
3435 register Lisp_Object buf;
3436{
3437 register struct buffer *old = current_buffer;
3438 register Lisp_Object window;
3439 register struct window *w;
3440
bccd3dd1
RS
3441 XBUFFER (buf)->directory = current_buffer->directory;
3442
7ab12479 3443 Fset_buffer (buf);
c6367666 3444 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
7ab12479
JB
3445 BEGV = BEG;
3446 ZV = Z;
3447 SET_PT (BEG);
06be4f85 3448#if 0 /* rms: there should be no reason for this. */
b1599b4c 3449 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
06be4f85 3450#endif
7ab12479
JB
3451 set_buffer_internal (old);
3452
3453 if (!EQ (Vtemp_buffer_show_function, Qnil))
3454 call1 (Vtemp_buffer_show_function, buf);
3455 else
3456 {
53f76081 3457 window = Fdisplay_buffer (buf, Qnil, Qnil);
7ab12479 3458
1ae1a37d 3459 if (!EQ (XWINDOW (window)->frame, selected_frame))
44fa5b1e 3460 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
7ab12479
JB
3461 Vminibuf_scroll_window = window;
3462 w = XWINDOW (window);
d834a2e9 3463 XSETFASTINT (w->hscroll, 0);
ea68264b 3464 XSETFASTINT (w->min_hscroll, 0);
2d0834cc
SM
3465 set_marker_restricted_both (w->start, buf, BEG, BEG);
3466 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
a58ec57d 3467
beb4e312 3468 /* Run temp-buffer-show-hook, with the chosen window selected
a5731348 3469 and its buffer current. */
2d0834cc
SM
3470
3471 if (!NILP (Vrun_hooks)
3472 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3473 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
2cccc823 3474 {
2d0834cc
SM
3475 int count = SPECPDL_INDEX ();
3476 Lisp_Object prev_window, prev_buffer;
3477 prev_window = selected_window;
3478 XSETBUFFER (prev_buffer, old);
3479
3480 /* Select the window that was chosen, for running the hook.
3481 Note: Both Fselect_window and select_window_norecord may
3482 set-buffer to the buffer displayed in the window,
3483 so we need to save the current buffer. --stef */
3484 record_unwind_protect (Fset_buffer, prev_buffer);
3485 record_unwind_protect (select_window_norecord, prev_window);
3486 Fselect_window (window, Qt);
3487 Fset_buffer (w->buffer);
3488 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3489 unbind_to (count, Qnil);
2cccc823
RS
3490 }
3491 }
7ab12479
JB
3492}
3493\f
dfcf069d 3494static void
7ab12479
JB
3495make_dummy_parent (window)
3496 Lisp_Object window;
3497{
cffec418 3498 Lisp_Object new;
7ab12479 3499 register struct window *o, *p;
cffec418 3500 int i;
7ab12479 3501
cffec418 3502 o = XWINDOW (window);
26605be9 3503 p = allocate_window ();
cffec418 3504 for (i = 0; i < VECSIZE (struct window); ++i)
26605be9
GM
3505 ((struct Lisp_Vector *) p)->contents[i]
3506 = ((struct Lisp_Vector *)o)->contents[i];
cffec418 3507 XSETWINDOW (new, p);
7ab12479 3508
d834a2e9 3509 XSETFASTINT (p->sequence_number, ++sequence_number);
7ab12479
JB
3510
3511 /* Put new into window structure in place of window */
3512 replace_window (window, new);
3513
3514 o->next = Qnil;
3515 o->prev = Qnil;
3516 o->vchild = Qnil;
3517 o->hchild = Qnil;
3518 o->parent = new;
3519
3520 p->start = Qnil;
3521 p->pointm = Qnil;
3522 p->buffer = Qnil;
3523}
3524
3525DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
fdb82f93
PJ
3526 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3527WINDOW defaults to selected one and SIZE to half its size.
3528If optional third arg HORFLAG is non-nil, split side by side
3529and put SIZE columns in the first of the pair. In that case,
3530SIZE includes that window's scroll bar, or the divider column to its right. */)
3531 (window, size, horflag)
77ae0fe3 3532 Lisp_Object window, size, horflag;
7ab12479
JB
3533{
3534 register Lisp_Object new;
3535 register struct window *o, *p;
c0807608 3536 FRAME_PTR fo;
77ae0fe3 3537 register int size_int;
7ab12479 3538
265a9e55 3539 if (NILP (window))
7ab12479
JB
3540 window = selected_window;
3541 else
b7826503 3542 CHECK_LIVE_WINDOW (window);
7ab12479
JB
3543
3544 o = XWINDOW (window);
c0807608 3545 fo = XFRAME (WINDOW_FRAME (o));
7ab12479 3546
77ae0fe3 3547 if (NILP (size))
7ab12479 3548 {
265a9e55 3549 if (!NILP (horflag))
c0807608 3550 /* Calculate the size of the left-hand window, by dividing
25b33244
KH
3551 the usable space in columns by two.
3552 We round up, since the left-hand window may include
3553 a dividing line, while the right-hand may not. */
949cf20f 3554 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
7ab12479 3555 else
949cf20f 3556 size_int = XFASTINT (o->total_lines) >> 1;
7ab12479
JB
3557 }
3558 else
3559 {
b7826503 3560 CHECK_NUMBER (size);
77ae0fe3 3561 size_int = XINT (size);
7ab12479
JB
3562 }
3563
3564 if (MINI_WINDOW_P (o))
3565 error ("Attempt to split minibuffer window");
233a4a2c
GM
3566 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3567 error ("Attempt to split fixed-size window");
7ab12479 3568
a481b3ea 3569 check_min_window_sizes ();
7ab12479 3570
265a9e55 3571 if (NILP (horflag))
7ab12479 3572 {
77ae0fe3
KH
3573 if (size_int < window_min_height)
3574 error ("Window height %d too small (after splitting)", size_int);
949cf20f 3575 if (size_int + window_min_height > XFASTINT (o->total_lines))
37962e60 3576 error ("Window height %d too small (after splitting)",
949cf20f 3577 XFASTINT (o->total_lines) - size_int);
265a9e55
JB
3578 if (NILP (o->parent)
3579 || NILP (XWINDOW (o->parent)->vchild))
7ab12479
JB
3580 {
3581 make_dummy_parent (window);
3582 new = o->parent;
3583 XWINDOW (new)->vchild = window;
3584 }
3585 }
3586 else
3587 {
77ae0fe3
KH
3588 if (size_int < window_min_width)
3589 error ("Window width %d too small (after splitting)", size_int);
a59fed7e 3590
949cf20f 3591 if (size_int + window_min_width > XFASTINT (o->total_cols))
37962e60 3592 error ("Window width %d too small (after splitting)",
949cf20f 3593 XFASTINT (o->total_cols) - size_int);
265a9e55
JB
3594 if (NILP (o->parent)
3595 || NILP (XWINDOW (o->parent)->hchild))
7ab12479
JB
3596 {
3597 make_dummy_parent (window);
3598 new = o->parent;
3599 XWINDOW (new)->hchild = window;
3600 }
3601 }
3602
3603 /* Now we know that window's parent is a vertical combination
3604 if we are dividing vertically, or a horizontal combination
3605 if we are making side-by-side windows */
3606
3607 windows_or_buffers_changed++;
c0807608 3608 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
7ab12479
JB
3609 new = make_window ();
3610 p = XWINDOW (new);
3611
44fa5b1e 3612 p->frame = o->frame;
7ab12479 3613 p->next = o->next;
265a9e55 3614 if (!NILP (p->next))
7ab12479
JB
3615 XWINDOW (p->next)->prev = new;
3616 p->prev = window;
3617 o->next = new;
3618 p->parent = o->parent;
3619 p->buffer = Qt;
5500c422
GM
3620 p->window_end_valid = Qnil;
3621 bzero (&p->last_cursor, sizeof p->last_cursor);
7ab12479 3622
949cf20f
KS
3623 /* Duplicate special geometry settings. */
3624
3625 p->left_margin_cols = o->left_margin_cols;
3626 p->right_margin_cols = o->right_margin_cols;
3627 p->left_fringe_width = o->left_fringe_width;
3628 p->right_fringe_width = o->right_fringe_width;
3629 p->fringes_outside_margins = o->fringes_outside_margins;
3630 p->scroll_bar_width = o->scroll_bar_width;
3631 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
3632
44fa5b1e 3633 /* Apportion the available frame space among the two new windows */
7ab12479 3634
265a9e55 3635 if (!NILP (horflag))
7ab12479 3636 {
949cf20f
KS
3637 p->total_lines = o->total_lines;
3638 p->top_line = o->top_line;
3639 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
3640 XSETFASTINT (o->total_cols, size_int);
3641 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
3642 adjust_window_margins (p);
3643 adjust_window_margins (o);
7ab12479
JB
3644 }
3645 else
3646 {
949cf20f
KS
3647 p->left_col = o->left_col;
3648 p->total_cols = o->total_cols;
3649 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
3650 XSETFASTINT (o->total_lines, size_int);
3651 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
7ab12479
JB
3652 }
3653
5500c422
GM
3654 /* Adjust glyph matrices. */
3655 adjust_glyphs (fo);
949cf20f
KS
3656
3657 Fset_window_buffer (new, o->buffer, Qt);
7ab12479
JB
3658 return new;
3659}
3660\f
f95284d2 3661DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 3, "p",
fdb82f93
PJ
3662 doc: /* Make current window ARG lines bigger.
3663From program, optional second arg non-nil means grow sideways ARG columns.
f95284d2
RS
3664Interactively, if an argument is not given, make the window one line bigger.
3665
3666Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3667of the siblings above or to the left of the selected window. Only
3668siblings to the right or below are changed. */)
3669 (arg, side, preserve_before)
3670 register Lisp_Object arg, side, preserve_before;
7ab12479 3671{
b7826503 3672 CHECK_NUMBER (arg);
f95284d2
RS
3673 enlarge_window (selected_window, XINT (arg), !NILP (side),
3674 !NILP (preserve_before));
543f5fb1
RS
3675
3676 if (! NILP (Vwindow_configuration_change_hook))
3677 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3678
7ab12479
JB
3679 return Qnil;
3680}
3681
a5731348 3682DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 3, "p",
fdb82f93
PJ
3683 doc: /* Make current window ARG lines smaller.
3684From program, optional second arg non-nil means shrink sideways arg columns.
a5731348
SM
3685Interactively, if an argument is not given, make the window one line smaller.
3686
3687Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3688of the siblings above or to the left of the selected window. Only
3689siblings to the right or below are changed. */)
3690 (arg, side, preserve_before)
3691 register Lisp_Object arg, side, preserve_before;
7ab12479 3692{
b7826503 3693 CHECK_NUMBER (arg);
a5731348
SM
3694 enlarge_window (selected_window, -XINT (arg), !NILP (side),
3695 !NILP (preserve_before));
543f5fb1
RS
3696
3697 if (! NILP (Vwindow_configuration_change_hook))
3698 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3699
7ab12479
JB
3700 return Qnil;
3701}
3702
3703int
3704window_height (window)
3705 Lisp_Object window;
3706{
3707 register struct window *p = XWINDOW (window);
949cf20f 3708 return WINDOW_TOTAL_LINES (p);
7ab12479
JB
3709}
3710
3711int
3712window_width (window)
3713 Lisp_Object window;
3714{
3715 register struct window *p = XWINDOW (window);
949cf20f 3716 return WINDOW_TOTAL_COLS (p);
7ab12479
JB
3717}
3718
177c0ea7 3719
7ab12479 3720#define CURBEG(w) \
949cf20f 3721 *(widthflag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
7ab12479
JB
3722
3723#define CURSIZE(w) \
949cf20f 3724 *(widthflag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
7ab12479 3725
233a4a2c 3726
f95284d2 3727/* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means
233a4a2c 3728 increase its width. Siblings of the selected window are resized to
f95284d2
RS
3729 fulfill the size request. If they become too small in the process,
3730 they will be deleted.
3731
3732 If PRESERVE_BEFORE is nonzero, that means don't alter
3733 the siblings to the left or above WINDOW. */
7ab12479 3734
f984d4fc 3735static void
f95284d2 3736enlarge_window (window, delta, widthflag, preserve_before)
86c8e823 3737 Lisp_Object window;
f95284d2 3738 int delta, widthflag, preserve_before;
7ab12479 3739{
86c8e823 3740 Lisp_Object parent, next, prev;
233a4a2c 3741 struct window *p;
3578db3c
KR
3742 Lisp_Object *sizep;
3743 int maximum;
5e14b1fc
AS
3744 int (*sizefun) P_ ((Lisp_Object))
3745 = widthflag ? window_width : window_height;
233a4a2c 3746 void (*setsizefun) P_ ((Lisp_Object, int, int))
5e14b1fc 3747 = (widthflag ? set_window_width : set_window_height);
7ab12479 3748
233a4a2c
GM
3749 /* Check values of window_min_width and window_min_height for
3750 validity. */
a481b3ea 3751 check_min_window_sizes ();
7ab12479 3752
233a4a2c 3753 /* Give up if this window cannot be resized. */
233a4a2c
GM
3754 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3755 error ("Window is not resizable");
3756
3757 /* Find the parent of the selected window. */
7ab12479
JB
3758 while (1)
3759 {
3760 p = XWINDOW (window);
3761 parent = p->parent;
177c0ea7 3762
265a9e55 3763 if (NILP (parent))
7ab12479
JB
3764 {
3765 if (widthflag)
3766 error ("No other window to side of this one");
3767 break;
3768 }
177c0ea7 3769
233a4a2c
GM
3770 if (widthflag
3771 ? !NILP (XWINDOW (parent)->hchild)
265a9e55 3772 : !NILP (XWINDOW (parent)->vchild))
7ab12479 3773 break;
177c0ea7 3774
7ab12479
JB
3775 window = parent;
3776 }
3777
05c2896a 3778 sizep = &CURSIZE (window);
7ab12479 3779
7ab12479
JB
3780 {
3781 register int maxdelta;
7ab12479 3782
f95284d2
RS
3783 /* Compute the maximum size increment this window can have. */
3784
3785 if (preserve_before)
3786 {
3787 if (!NILP (parent))
3788 {
3789 maxdelta = (*sizefun) (parent) - XINT (*sizep);
3790 /* Subtract size of siblings before, since we can't take that. */
1ab964d7 3791 maxdelta -= XINT (CURBEG (window)) - XINT (CURBEG (parent));
f95284d2
RS
3792 }
3793 else
3794 maxdelta = (!NILP (p->next) ? ((*sizefun) (p->next)
3795 - window_min_size (XWINDOW (p->next),
3796 widthflag, 0, 0))
3797 : (delta = 0));
3798 }
3799 else
3800 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
3801 /* This is a main window followed by a minibuffer. */
3802 : !NILP (p->next) ? ((*sizefun) (p->next)
3803 - window_min_size (XWINDOW (p->next),
3804 widthflag, 0, 0))
3805 /* This is a minibuffer following a main window. */
3806 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3807 - window_min_size (XWINDOW (p->prev),
3808 widthflag, 0, 0))
3809 /* This is a frame with only one window, a minibuffer-only
3810 or a minibufferless frame. */
3811 : (delta = 0));
7ab12479
JB
3812
3813 if (delta > maxdelta)
3814 /* This case traps trying to make the minibuffer
44fa5b1e
JB
3815 the full frame, or make the only window aside from the
3816 minibuffer the full frame. */
7ab12479 3817 delta = maxdelta;
6b54027b 3818 }
d5783c40 3819
3578db3c 3820 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
6b54027b 3821 {
543f5fb1 3822 delete_window (window);
d5783c40 3823 return;
6b54027b
RS
3824 }
3825
3826 if (delta == 0)
3827 return;
7ab12479 3828
f95284d2 3829 /* Find the total we can get from other siblings without deleting them. */
db98a733
RS
3830 maximum = 0;
3831 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
c1636aa6 3832 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
f984d4fc 3833 widthflag, 0, 0);
f95284d2
RS
3834 if (! preserve_before)
3835 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3836 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3837 widthflag, 0, 0);
db98a733 3838
f95284d2 3839 /* If we can get it all from them without deleting them, do so. */
c6b530ed 3840 if (delta <= maximum)
7ab12479 3841 {
db98a733
RS
3842 Lisp_Object first_unaffected;
3843 Lisp_Object first_affected;
233a4a2c 3844 int fixed_p;
db98a733
RS
3845
3846 next = p->next;
3847 prev = p->prev;
3848 first_affected = window;
3849 /* Look at one sibling at a time,
3850 moving away from this window in both directions alternately,
3851 and take as much as we can get without deleting that sibling. */
f95284d2
RS
3852 while (delta != 0
3853 && (!NILP (next) || (!preserve_before && !NILP (prev))))
db98a733 3854 {
db98a733
RS
3855 if (! NILP (next))
3856 {
c1636aa6 3857 int this_one = ((*sizefun) (next)
233a4a2c 3858 - window_min_size (XWINDOW (next),
f984d4fc 3859 widthflag, 0, &fixed_p));
233a4a2c
GM
3860 if (!fixed_p)
3861 {
3862 if (this_one > delta)
3863 this_one = delta;
177c0ea7 3864
233a4a2c 3865 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3578db3c 3866 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
db98a733 3867
233a4a2c
GM
3868 delta -= this_one;
3869 }
177c0ea7 3870
db98a733
RS
3871 next = XWINDOW (next)->next;
3872 }
177c0ea7 3873
db98a733
RS
3874 if (delta == 0)
3875 break;
177c0ea7 3876
f95284d2 3877 if (!preserve_before && ! NILP (prev))
db98a733 3878 {
c1636aa6 3879 int this_one = ((*sizefun) (prev)
233a4a2c 3880 - window_min_size (XWINDOW (prev),
f984d4fc 3881 widthflag, 0, &fixed_p));
233a4a2c
GM
3882 if (!fixed_p)
3883 {
3884 if (this_one > delta)
3885 this_one = delta;
177c0ea7 3886
233a4a2c 3887 first_affected = prev;
177c0ea7 3888
233a4a2c 3889 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3578db3c 3890 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
233a4a2c
GM
3891
3892 delta -= this_one;
3893 }
177c0ea7 3894
db98a733
RS
3895 prev = XWINDOW (prev)->prev;
3896 }
3897 }
3898
233a4a2c
GM
3899 xassert (delta == 0);
3900
db98a733
RS
3901 /* Now recalculate the edge positions of all the windows affected,
3902 based on the new sizes. */
3903 first_unaffected = next;
3904 prev = first_affected;
3905 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3906 prev = next, next = XWINDOW (next)->next)
3907 {
3578db3c 3908 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
db98a733
RS
3909 /* This does not change size of NEXT,
3910 but it propagates the new top edge to its children */
3911 (*setsizefun) (next, (*sizefun) (next), 0);
3912 }
7ab12479
JB
3913 }
3914 else
3915 {
3916 register int delta1;
3917 register int opht = (*sizefun) (parent);
3918
3578db3c 3919 if (opht <= XINT (*sizep) + delta)
daf516d3
RS
3920 {
3921 /* If trying to grow this window to or beyond size of the parent,
3922 just delete all the sibling windows. */
dc1ab1ee 3923 Lisp_Object start, tem, next;
daf516d3 3924
dc1ab1ee
RS
3925 start = XWINDOW (parent)->vchild;
3926 if (NILP (start))
3927 start = XWINDOW (parent)->hchild;
daf516d3 3928
dc1ab1ee
RS
3929 /* Delete any siblings that come after WINDOW. */
3930 tem = XWINDOW (window)->next;
daf516d3
RS
3931 while (! NILP (tem))
3932 {
3933 next = XWINDOW (tem)->next;
dc1ab1ee
RS
3934 delete_window (tem);
3935 tem = next;
3936 }
3937
3938 /* Delete any siblings that come after WINDOW.
3939 Note that if START is not WINDOW, then WINDOW still
3940 Fhas siblings, so WINDOW has not yet replaced its parent. */
3941 tem = start;
3942 while (! EQ (tem, window))
3943 {
3944 next = XWINDOW (tem)->next;
3945 delete_window (tem);
daf516d3
RS
3946 tem = next;
3947 }
3948 }
7ab12479 3949 else
233a4a2c
GM
3950 {
3951 /* Otherwise, make delta1 just right so that if we add
3952 delta1 lines to this window and to the parent, and then
3953 shrink the parent back to its original size, the new
3954 proportional size of this window will increase by delta.
3955
3956 The function size_window will compute the new height h'
3957 of the window from delta1 as:
177c0ea7 3958
233a4a2c
GM
3959 e = delta1/n
3960 x = delta1 - delta1/n * n for the 1st resizable child
3961 h' = h + e + x
3962
3963 where n is the number of children that can be resized.
3964 We can ignore x by choosing a delta1 that is a multiple of
3965 n. We want the height of this window to come out as
177c0ea7 3966
233a4a2c
GM
3967 h' = h + delta
3968
3969 So, delta1 must be
177c0ea7 3970
233a4a2c
GM
3971 h + e = h + delta
3972 delta1/n = delta
3973 delta1 = n * delta.
3974
a5731348 3975 The number of children n equals the number of resizable
233a4a2c
GM
3976 children of this window + 1 because we know window itself
3977 is resizable (otherwise we would have signalled an error. */
3978
3979 struct window *w = XWINDOW (window);
3980 Lisp_Object s;
3981 int n = 1;
3982
3983 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3984 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3985 ++n;
3986 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3987 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3988 ++n;
3989
3990 delta1 = n * delta;
7ab12479 3991
daf516d3
RS
3992 /* Add delta1 lines or columns to this window, and to the parent,
3993 keeping things consistent while not affecting siblings. */
3994 XSETINT (CURSIZE (parent), opht + delta1);
3995 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
3996
3997 /* Squeeze out delta1 lines or columns from our parent,
3998 shriking this window and siblings proportionately.
3999 This brings parent back to correct size.
4000 Delta1 was calculated so this makes this window the desired size,
4001 taking it all out of the siblings. */
4002 (*setsizefun) (parent, opht, 0);
4003
4004 }
7ab12479
JB
4005 }
4006
d834a2e9 4007 XSETFASTINT (p->last_modified, 0);
3cd21523 4008 XSETFASTINT (p->last_overlay_modified, 0);
5500c422
GM
4009
4010 /* Adjust glyph matrices. */
4011 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
7ab12479 4012}
c1636aa6 4013
7ab12479
JB
4014#undef CURBEG
4015#undef CURSIZE
4016
5500c422 4017
f984d4fc
GM
4018\f
4019/***********************************************************************
4020 Resizing Mini-Windows
4021 ***********************************************************************/
4022
4023static void shrink_window_lowest_first P_ ((struct window *, int));
f984d4fc 4024
43b4a21f
GM
4025enum save_restore_action
4026{
4027 CHECK_ORIG_SIZES,
4028 SAVE_ORIG_SIZES,
4029 RESTORE_ORIG_SIZES
4030};
4031
177c0ea7 4032static int save_restore_orig_size P_ ((struct window *,
43b4a21f 4033 enum save_restore_action));
f984d4fc
GM
4034
4035/* Shrink windows rooted in window W to HEIGHT. Take the space needed
4036 from lowest windows first. */
4037
4038static void
4039shrink_window_lowest_first (w, height)
4040 struct window *w;
4041 int height;
4042{
4043 struct window *c;
4044 Lisp_Object child;
4045 int old_height;
4046
4047 xassert (!MINI_WINDOW_P (w));
4048
4049 /* Set redisplay hints. */
4050 XSETFASTINT (w->last_modified, 0);
4051 XSETFASTINT (w->last_overlay_modified, 0);
4052 windows_or_buffers_changed++;
4053 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4054
949cf20f
KS
4055 old_height = XFASTINT (w->total_lines);
4056 XSETFASTINT (w->total_lines, height);
f984d4fc
GM
4057
4058 if (!NILP (w->hchild))
4059 {
4060 for (child = w->hchild; !NILP (child); child = c->next)
4061 {
4062 c = XWINDOW (child);
949cf20f 4063 c->top_line = w->top_line;
f984d4fc
GM
4064 shrink_window_lowest_first (c, height);
4065 }
4066 }
4067 else if (!NILP (w->vchild))
4068 {
4069 Lisp_Object last_child;
4070 int delta = old_height - height;
4071 int last_top;
6bbd7a29
GM
4072
4073 last_child = Qnil;
177c0ea7 4074
f984d4fc
GM
4075 /* Find the last child. We are taking space from lowest windows
4076 first, so we iterate over children from the last child
4077 backwards. */
4078 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
4079 last_child = child;
4080
4081 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
4082 for (child = last_child; delta && !NILP (child); child = c->prev)
4083 {
4084 int this_one;
177c0ea7 4085
f984d4fc 4086 c = XWINDOW (child);
949cf20f 4087 this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
f984d4fc
GM
4088
4089 if (this_one > delta)
4090 this_one = delta;
4091
949cf20f 4092 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
f984d4fc
GM
4093 delta -= this_one;
4094 }
4095
4096 /* Compute new positions. */
949cf20f 4097 last_top = XINT (w->top_line);
f984d4fc
GM
4098 for (child = w->vchild; !NILP (child); child = c->next)
4099 {
4100 c = XWINDOW (child);
949cf20f
KS
4101 c->top_line = make_number (last_top);
4102 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4103 last_top += XFASTINT (c->total_lines);
f984d4fc
GM
4104 }
4105 }
4106}
4107
4108
43b4a21f
GM
4109/* Save, restore, or check positions and sizes in the window tree
4110 rooted at W. ACTION says what to do.
f984d4fc 4111
949cf20f
KS
4112 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4113 orig_total_lines members are valid for all windows in the window
4114 tree. Value is non-zero if they are valid.
177c0ea7 4115
43b4a21f 4116 If ACTION is SAVE_ORIG_SIZES, save members top and height in
949cf20f 4117 orig_top_line and orig_total_lines for all windows in the tree.
43b4a21f 4118
949cf20f
KS
4119 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4120 stored in orig_top_line and orig_total_lines for all windows. */
43b4a21f
GM
4121
4122static int
4123save_restore_orig_size (w, action)
f984d4fc 4124 struct window *w;
43b4a21f 4125 enum save_restore_action action;
f984d4fc 4126{
43b4a21f
GM
4127 int success_p = 1;
4128
f984d4fc
GM
4129 while (w)
4130 {
4131 if (!NILP (w->hchild))
43b4a21f
GM
4132 {
4133 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4134 success_p = 0;
4135 }
f984d4fc 4136 else if (!NILP (w->vchild))
43b4a21f
GM
4137 {
4138 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4139 success_p = 0;
4140 }
177c0ea7 4141
43b4a21f 4142 switch (action)
f984d4fc 4143 {
43b4a21f 4144 case CHECK_ORIG_SIZES:
949cf20f 4145 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
43b4a21f
GM
4146 return 0;
4147 break;
4148
4149 case SAVE_ORIG_SIZES:
949cf20f
KS
4150 w->orig_top_line = w->top_line;
4151 w->orig_total_lines = w->total_lines;
43b4a21f
GM
4152 XSETFASTINT (w->last_modified, 0);
4153 XSETFASTINT (w->last_overlay_modified, 0);
4154 break;
4155
4156 case RESTORE_ORIG_SIZES:
949cf20f
KS
4157 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4158 w->top_line = w->orig_top_line;
4159 w->total_lines = w->orig_total_lines;
4160 w->orig_total_lines = w->orig_top_line = Qnil;
43b4a21f
GM
4161 XSETFASTINT (w->last_modified, 0);
4162 XSETFASTINT (w->last_overlay_modified, 0);
4163 break;
4164
4165 default:
4166 abort ();
f984d4fc 4167 }
43b4a21f 4168
f984d4fc
GM
4169 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4170 }
43b4a21f
GM
4171
4172 return success_p;
f984d4fc
GM
4173}
4174
4175
4176/* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4177 without deleting other windows. */
4178
4179void
4180grow_mini_window (w, delta)
4181 struct window *w;
4182 int delta;
4183{
4184 struct frame *f = XFRAME (w->frame);
4185 struct window *root;
177c0ea7 4186
f984d4fc
GM
4187 xassert (MINI_WINDOW_P (w));
4188 xassert (delta >= 0);
177c0ea7 4189
f984d4fc
GM
4190 /* Check values of window_min_width and window_min_height for
4191 validity. */
4192 check_min_window_sizes ();
4193
4194 /* Compute how much we can enlarge the mini-window without deleting
4195 other windows. */
4196 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4197 if (delta)
4198 {
4199 int min_height = window_min_size (root, 0, 0, 0);
949cf20f 4200 if (XFASTINT (root->total_lines) - delta < min_height)
8b8bd9c6 4201 /* Note that the root window may already be smaller than
eafa3196 4202 min_height. */
949cf20f 4203 delta = max (0, XFASTINT (root->total_lines) - min_height);
f984d4fc 4204 }
177c0ea7 4205
f984d4fc
GM
4206 if (delta)
4207 {
4208 /* Save original window sizes and positions, if not already done. */
43b4a21f
GM
4209 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4210 save_restore_orig_size (root, SAVE_ORIG_SIZES);
f984d4fc
GM
4211
4212 /* Shrink other windows. */
949cf20f 4213 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
f984d4fc
GM
4214
4215 /* Grow the mini-window. */
949cf20f
KS
4216 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4217 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
f984d4fc
GM
4218 XSETFASTINT (w->last_modified, 0);
4219 XSETFASTINT (w->last_overlay_modified, 0);
177c0ea7 4220
f984d4fc
GM
4221 adjust_glyphs (f);
4222 }
4223}
4224
4225
86c8e823
GM
4226/* Shrink mini-window W. If there is recorded info about window sizes
4227 before a call to grow_mini_window, restore recorded window sizes.
4228 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4229 line. */
f984d4fc
GM
4230
4231void
4232shrink_mini_window (w)
4233 struct window *w;
4234{
4235 struct frame *f = XFRAME (w->frame);
4236 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4237
43b4a21f 4238 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
f984d4fc 4239 {
43b4a21f 4240 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
f984d4fc
GM
4241 adjust_glyphs (f);
4242 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4243 windows_or_buffers_changed = 1;
4244 }
949cf20f 4245 else if (XFASTINT (w->total_lines) > 1)
86c8e823 4246 {
0130fe1a
GM
4247 /* Distribute the additional lines of the mini-window
4248 among the other windows. */
86c8e823
GM
4249 Lisp_Object window;
4250 XSETWINDOW (window, w);
949cf20f 4251 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0, 0);
86c8e823 4252 }
f984d4fc
GM
4253}
4254
4255
4256\f
5500c422
GM
4257/* Mark window cursors off for all windows in the window tree rooted
4258 at W by setting their phys_cursor_on_p flag to zero. Called from
4259 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4260 the frame are cleared. */
4261
4262void
4263mark_window_cursors_off (w)
4264 struct window *w;
4265{
4266 while (w)
4267 {
4268 if (!NILP (w->hchild))
4269 mark_window_cursors_off (XWINDOW (w->hchild));
4270 else if (!NILP (w->vchild))
4271 mark_window_cursors_off (XWINDOW (w->vchild));
4272 else
4273 w->phys_cursor_on_p = 0;
4274
4275 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4276 }
4277}
4278
4279
e9c195b1 4280/* Return number of lines of text (not counting mode lines) in W. */
7ab12479
JB
4281
4282int
4283window_internal_height (w)
4284 struct window *w;
4285{
949cf20f 4286 int ht = XFASTINT (w->total_lines);
7ab12479 4287
e9c195b1
GM
4288 if (!MINI_WINDOW_P (w))
4289 {
4290 if (!NILP (w->parent)
4291 || !NILP (w->vchild)
4292 || !NILP (w->hchild)
4293 || !NILP (w->next)
4294 || !NILP (w->prev)
4295 || WINDOW_WANTS_MODELINE_P (w))
4296 --ht;
7ab12479 4297
e9c195b1
GM
4298 if (WINDOW_WANTS_HEADER_LINE_P (w))
4299 --ht;
4300 }
7ab12479
JB
4301
4302 return ht;
4303}
4304
535e0b8e
JB
4305
4306/* Return the number of columns in W.
a3c87d4e 4307 Don't count columns occupied by scroll bars or the vertical bar
535e0b8e 4308 separating W from the sibling to its right. */
5500c422 4309
535e0b8e 4310int
949cf20f 4311window_box_text_cols (w)
535e0b8e
JB
4312 struct window *w;
4313{
5500c422 4314 struct frame *f = XFRAME (WINDOW_FRAME (w));
949cf20f 4315 int width = XINT (w->total_cols);
535e0b8e 4316
949cf20f 4317 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
5500c422 4318 /* Scroll bars occupy a few columns. */
949cf20f
KS
4319 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4320 else if (!FRAME_WINDOW_P (f)
4321 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
5500c422
GM
4322 /* The column of `|' characters separating side-by-side windows
4323 occupies one column only. */
4324 width -= 1;
4325
5500c422 4326 if (FRAME_WINDOW_P (f))
949cf20f
KS
4327 /* On window-systems, fringes and display margins cannot be
4328 used for normal text. */
4329 width -= (WINDOW_FRINGE_COLS (w)
4330 + WINDOW_LEFT_MARGIN_COLS (w)
4331 + WINDOW_RIGHT_MARGIN_COLS (w));
111e5992
RS
4332
4333 return width;
535e0b8e
JB
4334}
4335
5500c422
GM
4336\f
4337/************************************************************************
4338 Window Scrolling
4339 ***********************************************************************/
535e0b8e 4340
5500c422 4341/* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
d4e7cf01 4342 N screen-fulls, which is defined as the height of the window minus
5500c422
GM
4343 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4344 instead. Negative values of N mean scroll down. NOERROR non-zero
4345 means don't signal an error if we try to move over BEGV or ZV,
4346 respectively. */
7ab12479 4347
101d1605
RS
4348static void
4349window_scroll (window, n, whole, noerror)
7ab12479
JB
4350 Lisp_Object window;
4351 int n;
101d1605 4352 int whole;
f8026fd8 4353 int noerror;
5500c422 4354{
cba59f77
RS
4355 immediate_quit = 1;
4356
5500c422
GM
4357 /* If we must, use the pixel-based version which is much slower than
4358 the line-based one but can handle varying line heights. */
4359 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4360 window_scroll_pixel_based (window, n, whole, noerror);
4361 else
4362 window_scroll_line_based (window, n, whole, noerror);
cba59f77
RS
4363
4364 immediate_quit = 0;
5500c422
GM
4365}
4366
4367
4368/* Implementation of window_scroll that works based on pixel line
4369 heights. See the comment of window_scroll for parameter
4370 descriptions. */
4371
4372static void
4373window_scroll_pixel_based (window, n, whole, noerror)
4374 Lisp_Object window;
4375 int n;
4376 int whole;
4377 int noerror;
4378{
4379 struct it it;
4380 struct window *w = XWINDOW (window);
4381 struct text_pos start;
4382 Lisp_Object tem;
4383 int this_scroll_margin;
4384 int preserve_y;
5cdb3cf3
MB
4385 /* True if we fiddled the window vscroll field without really scrolling. */
4386 int vscrolled = 0;
5500c422
GM
4387
4388 SET_TEXT_POS_FROM_MARKER (start, w->start);
177c0ea7 4389
5500c422 4390 /* If PT is not visible in WINDOW, move back one half of
288d4e06
GM
4391 the screen. Allow PT to be partially visible, otherwise
4392 something like (scroll-down 1) with PT in the line before
4393 the partially visible one would recenter. */
4394 tem = Fpos_visible_in_window_p (make_number (PT), window, Qt);
5500c422
GM
4395 if (NILP (tem))
4396 {
4397 /* Move backward half the height of the window. Performance note:
4398 vmotion used here is about 10% faster, but would give wrong
4399 results for variable height lines. */
4400 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4401 it.current_y = it.last_visible_y;
202379cf 4402 move_it_vertically (&it, - window_box_height (w) / 2);
177c0ea7 4403
5500c422
GM
4404 /* The function move_iterator_vertically may move over more than
4405 the specified y-distance. If it->w is small, e.g. a
4406 mini-buffer window, we may end up in front of the window's
4407 display area. This is the case when Start displaying at the
4408 start of the line containing PT in this case. */
4409 if (it.current_y <= 0)
4410 {
4411 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4412 move_it_vertically (&it, 0);
4413 it.current_y = 0;
4414 }
4415
4416 start = it.current.pos;
4417 }
4418
4419 /* If scroll_preserve_screen_position is non-zero, we try to set
4420 point in the same window line as it is now, so get that line. */
4421 if (!NILP (Vscroll_preserve_screen_position))
4422 {
4423 start_display (&it, w, start);
4424 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4425 preserve_y = it.current_y;
4426 }
4427 else
4428 preserve_y = -1;
4429
4430 /* Move iterator it from start the specified distance forward or
4431 backward. The result is the new window start. */
4432 start_display (&it, w, start);
4433 if (whole)
4434 {
202379cf 4435 int screen_full = (window_box_height (w)
949cf20f 4436 - next_screen_context_lines * FRAME_LINE_HEIGHT (it.f));
d4e7cf01 4437 int dy = n * screen_full;
d72340d4
GM
4438
4439 /* Note that move_it_vertically always moves the iterator to the
4440 start of a line. So, if the last line doesn't have a newline,
4441 we would end up at the start of the line ending at ZV. */
4442 if (dy <= 0)
4443 move_it_vertically_backward (&it, -dy);
4444 else if (dy > 0)
4445 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4446 MOVE_TO_POS | MOVE_TO_Y);
5500c422
GM
4447 }
4448 else
4449 move_it_by_lines (&it, n, 1);
4450
96ae58c8
RS
4451 /* We failed if we find ZV is already on the screen (scrolling up,
4452 means there's nothing past the end), or if we can't start any
4453 earlier (scrolling down, means there's nothing past the top). */
5500c422 4454 if ((n > 0 && IT_CHARPOS (it) == ZV)
96ae58c8 4455 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
5500c422 4456 {
5cdb3cf3
MB
4457 if (IT_CHARPOS (it) == ZV)
4458 {
07ce8b53
RS
4459 if (it.current_y < it.last_visible_y
4460 && (it.current_y + it.max_ascent + it.max_descent
4461 >= it.last_visible_y))
a74eca50
GM
4462 {
4463 /* The last line was only partially visible, make it fully
4464 visible. */
4465 w->vscroll = (it.last_visible_y
4466 - it.current_y + it.max_ascent + it.max_descent);
4467 adjust_glyphs (it.f);
4468 }
5cdb3cf3
MB
4469 else if (noerror)
4470 return;
4471 else
4472 Fsignal (Qend_of_buffer, Qnil);
4473 }
5500c422 4474 else
5cdb3cf3
MB
4475 {
4476 if (w->vscroll != 0)
4477 /* The first line was only partially visible, make it fully
4478 visible. */
4479 w->vscroll = 0;
4480 else if (noerror)
4481 return;
4482 else
4483 Fsignal (Qbeginning_of_buffer, Qnil);
4484 }
4485
4486 /* If control gets here, then we vscrolled. */
4487
4488 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4489
4490 /* Don't try to change the window start below. */
4491 vscrolled = 1;
5500c422
GM
4492 }
4493
5cdb3cf3
MB
4494 if (! vscrolled)
4495 {
dad67609
RS
4496 int pos = IT_CHARPOS (it);
4497 int bytepos;
e68def1e
AS
4498
4499 /* If in the middle of a multi-glyph character move forward to
4500 the next character. */
4501 if (in_display_vector_p (&it))
4502 {
4503 ++pos;
4504 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4505 }
4506
5cdb3cf3 4507 /* Set the window start, and set up the window for redisplay. */
dad67609 4508 set_marker_restricted (w->start, make_number (pos),
5cdb3cf3 4509 w->buffer);
dad67609
RS
4510 bytepos = XMARKER (w->start)->bytepos;
4511 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
4512 ? Qt : Qnil);
5cdb3cf3
MB
4513 w->update_mode_line = Qt;
4514 XSETFASTINT (w->last_modified, 0);
4515 XSETFASTINT (w->last_overlay_modified, 0);
4516 /* Set force_start so that redisplay_window will run the
4517 window-scroll-functions. */
4518 w->force_start = Qt;
4519 }
177c0ea7 4520
5500c422 4521 it.current_y = it.vpos = 0;
177c0ea7 4522
5500c422
GM
4523 /* Preserve the screen position if we must. */
4524 if (preserve_y >= 0)
4525 {
4526 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
4527 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4528 }
4529 else
4530 {
4531 /* Move PT out of scroll margins. */
4532 this_scroll_margin = max (0, scroll_margin);
949cf20f
KS
4533 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4534 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5500c422
GM
4535
4536 if (n > 0)
4537 {
4538 /* We moved the window start towards ZV, so PT may be now
4539 in the scroll margin at the top. */
4540 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4541 while (it.current_y < this_scroll_margin)
e9b2c961
RS
4542 {
4543 int prev = it.current_y;
4544 move_it_by_lines (&it, 1, 1);
4545 if (prev == it.current_y)
4546 break;
4547 }
5500c422
GM
4548 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4549 }
4550 else if (n < 0)
4551 {
5cdb3cf3
MB
4552 int charpos, bytepos;
4553
5500c422
GM
4554 /* We moved the window start towards BEGV, so PT may be now
4555 in the scroll margin at the bottom. */
4556 move_it_to (&it, PT, -1,
4557 it.last_visible_y - this_scroll_margin - 1, -1,
4558 MOVE_TO_POS | MOVE_TO_Y);
5cdb3cf3
MB
4559
4560 /* Save our position, in case it's correct. */
4561 charpos = IT_CHARPOS (it);
4562 bytepos = IT_BYTEPOS (it);
177c0ea7 4563
5cdb3cf3
MB
4564 /* See if point is on a partially visible line at the end. */
4565 move_it_by_lines (&it, 1, 1);
4566 if (it.current_y > it.last_visible_y)
4567 /* The last line was only partially visible, so back up two
4568 lines to make sure we're on a fully visible line. */
4569 {
4570 move_it_by_lines (&it, -2, 0);
4571 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4572 }
4573 else
4574 /* No, the position we saved is OK, so use it. */
4575 SET_PT_BOTH (charpos, bytepos);
5500c422
GM
4576 }
4577 }
4578}
4579
4580
4581/* Implementation of window_scroll that works based on screen lines.
4582 See the comment of window_scroll for parameter descriptions. */
4583
4584static void
4585window_scroll_line_based (window, n, whole, noerror)
4586 Lisp_Object window;
4587 int n;
4588 int whole;
4589 int noerror;
7ab12479
JB
4590{
4591 register struct window *w = XWINDOW (window);
5500c422 4592 register int opoint = PT, opoint_byte = PT_BYTE;
b73ea88e 4593 register int pos, pos_byte;
7ab12479
JB
4594 register int ht = window_internal_height (w);
4595 register Lisp_Object tem;
4596 int lose;
5500c422 4597 Lisp_Object bolp;
345d45b2 4598 int startpos;
101d1605
RS
4599 struct position posit;
4600 int original_vpos;
4601
d4e7cf01
GM
4602 /* If scrolling screen-fulls, compute the number of lines to
4603 scroll from the window's height. */
4604 if (whole)
4605 n *= max (1, ht - next_screen_context_lines);
4606
101d1605
RS
4607 startpos = marker_position (w->start);
4608
4609 posit = *compute_motion (startpos, 0, 0, 0,
4610 PT, ht, 0,
949cf20f 4611 window_box_text_cols (w), XINT (w->hscroll),
101d1605
RS
4612 0, w);
4613 original_vpos = posit.vpos;
0a1f771a 4614
d834a2e9 4615 XSETFASTINT (tem, PT);
6ffdb539 4616 tem = Fpos_visible_in_window_p (tem, window, Qnil);
7ab12479 4617
265a9e55 4618 if (NILP (tem))
7ab12479 4619 {
cd2be1dd 4620 Fvertical_motion (make_number (- (ht / 2)), window);
345d45b2 4621 startpos = PT;
7ab12479
JB
4622 }
4623
345d45b2 4624 SET_PT (startpos);
5ce7b543 4625 lose = n < 0 && PT == BEGV;
540b6aa0 4626 Fvertical_motion (make_number (n), window);
5ce7b543 4627 pos = PT;
b73ea88e 4628 pos_byte = PT_BYTE;
7ab12479 4629 bolp = Fbolp ();
b73ea88e 4630 SET_PT_BOTH (opoint, opoint_byte);
7ab12479
JB
4631
4632 if (lose)
f8026fd8
JB
4633 {
4634 if (noerror)
4635 return;
4636 else
4637 Fsignal (Qbeginning_of_buffer, Qnil);
4638 }
7ab12479
JB
4639
4640 if (pos < ZV)
7ab12479 4641 {
0c7da84e
RS
4642 int this_scroll_margin = scroll_margin;
4643
4644 /* Don't use a scroll margin that is negative or too large. */
4645 if (this_scroll_margin < 0)
4646 this_scroll_margin = 0;
4647
949cf20f
KS
4648 if (XINT (w->total_lines) < 4 * scroll_margin)
4649 this_scroll_margin = XINT (w->total_lines) / 4;
0c7da84e 4650
b73ea88e 4651 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
7ab12479
JB
4652 w->start_at_line_beg = bolp;
4653 w->update_mode_line = Qt;
d834a2e9 4654 XSETFASTINT (w->last_modified, 0);
3cd21523 4655 XSETFASTINT (w->last_overlay_modified, 0);
345d45b2
RS
4656 /* Set force_start so that redisplay_window will run
4657 the window-scroll-functions. */
4658 w->force_start = Qt;
0c7da84e 4659
5500c422 4660 if (whole && !NILP (Vscroll_preserve_screen_position))
0c7da84e 4661 {
b73ea88e 4662 SET_PT_BOTH (pos, pos_byte);
101d1605 4663 Fvertical_motion (make_number (original_vpos), window);
0c7da84e 4664 }
101d1605
RS
4665 /* If we scrolled forward, put point enough lines down
4666 that it is outside the scroll margin. */
4667 else if (n > 0)
0c7da84e 4668 {
101d1605
RS
4669 int top_margin;
4670
4671 if (this_scroll_margin > 0)
4672 {
b73ea88e 4673 SET_PT_BOTH (pos, pos_byte);
101d1605
RS
4674 Fvertical_motion (make_number (this_scroll_margin), window);
4675 top_margin = PT;
4676 }
4677 else
4678 top_margin = pos;
4679
4680 if (top_margin <= opoint)
b73ea88e 4681 SET_PT_BOTH (opoint, opoint_byte);
5500c422 4682 else if (!NILP (Vscroll_preserve_screen_position))
101d1605 4683 {
b73ea88e 4684 SET_PT_BOTH (pos, pos_byte);
101d1605
RS
4685 Fvertical_motion (make_number (original_vpos), window);
4686 }
9317a85d 4687 else
335406fc 4688 SET_PT (top_margin);
0c7da84e 4689 }
101d1605 4690 else if (n < 0)
7ab12479 4691 {
101d1605
RS
4692 int bottom_margin;
4693
0c7da84e
RS
4694 /* If we scrolled backward, put point near the end of the window
4695 but not within the scroll margin. */
b73ea88e 4696 SET_PT_BOTH (pos, pos_byte);
0c7da84e 4697 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
101d1605
RS
4698 if (XFASTINT (tem) == ht - this_scroll_margin)
4699 bottom_margin = PT;
4700 else
4701 bottom_margin = PT + 1;
4702
4703 if (bottom_margin > opoint)
b73ea88e 4704 SET_PT_BOTH (opoint, opoint_byte);
7ab12479 4705 else
101d1605 4706 {
5500c422 4707 if (!NILP (Vscroll_preserve_screen_position))
9317a85d 4708 {
b73ea88e 4709 SET_PT_BOTH (pos, pos_byte);
9317a85d
RS
4710 Fvertical_motion (make_number (original_vpos), window);
4711 }
4712 else
4713 Fvertical_motion (make_number (-1), window);
101d1605 4714 }
7ab12479
JB
4715 }
4716 }
4717 else
f8026fd8
JB
4718 {
4719 if (noerror)
4720 return;
4721 else
4722 Fsignal (Qend_of_buffer, Qnil);
4723 }
7ab12479 4724}
5500c422
GM
4725
4726
4727/* Scroll selected_window up or down. If N is nil, scroll a
4728 screen-full which is defined as the height of the window minus
4729 next_screen_context_lines. If N is the symbol `-', scroll.
4730 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4731 up. This is the guts of Fscroll_up and Fscroll_down. */
7ab12479
JB
4732
4733static void
4734scroll_command (n, direction)
5500c422 4735 Lisp_Object n;
7ab12479
JB
4736 int direction;
4737{
331379bf 4738 int count = SPECPDL_INDEX ();
7ab12479 4739
5500c422
GM
4740 xassert (abs (direction) == 1);
4741
4742 /* If selected window's buffer isn't current, make it current for
4743 the moment. But don't screw up if window_scroll gets an error. */
7ab12479 4744 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
95605e15
JB
4745 {
4746 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4747 Fset_buffer (XWINDOW (selected_window)->buffer);
5500c422
GM
4748
4749 /* Make redisplay consider other windows than just selected_window. */
4750 ++windows_or_buffers_changed;
95605e15 4751 }
7ab12479 4752
265a9e55 4753 if (NILP (n))
d4e7cf01 4754 window_scroll (selected_window, direction, 1, 0);
7ab12479 4755 else if (EQ (n, Qminus))
d4e7cf01 4756 window_scroll (selected_window, -direction, 1, 0);
7ab12479
JB
4757 else
4758 {
4759 n = Fprefix_numeric_value (n);
101d1605 4760 window_scroll (selected_window, XINT (n) * direction, 0, 0);
7ab12479 4761 }
95605e15
JB
4762
4763 unbind_to (count, Qnil);
7ab12479
JB
4764}
4765
4766DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
fdb82f93
PJ
4767 doc: /* Scroll text of current window upward ARG lines; or near full screen if no ARG.
4768A near full screen is `next-screen-context-lines' less than a full screen.
4769Negative ARG means scroll downward.
4770If ARG is the atom `-', scroll downward by nearly full screen.
4771When calling from a program, supply as argument a number, nil, or `-'. */)
4772 (arg)
413430c5 4773 Lisp_Object arg;
7ab12479 4774{
413430c5 4775 scroll_command (arg, 1);
7ab12479
JB
4776 return Qnil;
4777}
4778
4779DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
fdb82f93
PJ
4780 doc: /* Scroll text of current window down ARG lines; or near full screen if no ARG.
4781A near full screen is `next-screen-context-lines' less than a full screen.
4782Negative ARG means scroll upward.
4783If ARG is the atom `-', scroll upward by nearly full screen.
4784When calling from a program, supply as argument a number, nil, or `-'. */)
4785 (arg)
413430c5 4786 Lisp_Object arg;
7ab12479 4787{
413430c5 4788 scroll_command (arg, -1);
7ab12479
JB
4789 return Qnil;
4790}
ccd0664b
RS
4791\f
4792DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
fdb82f93
PJ
4793 doc: /* Return the other window for \"other window scroll\" commands.
4794If in the minibuffer, `minibuffer-scroll-window' if non-nil
4795specifies the window.
4796If `other-window-scroll-buffer' is non-nil, a window
4797showing that buffer is used. */)
4798 ()
7ab12479 4799{
ccd0664b 4800 Lisp_Object window;
7ab12479
JB
4801
4802 if (MINI_WINDOW_P (XWINDOW (selected_window))
265a9e55 4803 && !NILP (Vminibuf_scroll_window))
7ab12479
JB
4804 window = Vminibuf_scroll_window;
4805 /* If buffer is specified, scroll that buffer. */
265a9e55 4806 else if (!NILP (Vother_window_scroll_buffer))
7ab12479
JB
4807 {
4808 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
265a9e55 4809 if (NILP (window))
53f76081 4810 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
7ab12479
JB
4811 }
4812 else
dbc4e1c1
JB
4813 {
4814 /* Nothing specified; look for a neighboring window on the same
4815 frame. */
4816 window = Fnext_window (selected_window, Qnil, Qnil);
4817
4818 if (EQ (window, selected_window))
4819 /* That didn't get us anywhere; look for a window on another
4820 visible frame. */
4821 do
4822 window = Fnext_window (window, Qnil, Qt);
4823 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4824 && ! EQ (window, selected_window));
4825 }
4826
b7826503 4827 CHECK_LIVE_WINDOW (window);
7ab12479
JB
4828
4829 if (EQ (window, selected_window))
4830 error ("There is no other window");
4831
ccd0664b
RS
4832 return window;
4833}
4834
4835DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
fdb82f93
PJ
4836 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4837A near full screen is `next-screen-context-lines' less than a full screen.
4838The next window is the one below the current one; or the one at the top
4839if the current one is at the bottom. Negative ARG means scroll downward.
4840If ARG is the atom `-', scroll downward by nearly full screen.
4841When calling from a program, supply as argument a number, nil, or `-'.
4842
4843If in the minibuffer, `minibuffer-scroll-window' if non-nil
4844specifies the window to scroll.
4845If `other-window-scroll-buffer' is non-nil, scroll the window
4846showing that buffer, popping the buffer up if necessary. */)
4847 (arg)
d4e7cf01 4848 Lisp_Object arg;
ccd0664b 4849{
d4e7cf01
GM
4850 Lisp_Object window;
4851 struct window *w;
331379bf 4852 int count = SPECPDL_INDEX ();
ccd0664b
RS
4853
4854 window = Fother_window_for_scrolling ();
7ab12479 4855 w = XWINDOW (window);
7ab12479
JB
4856
4857 /* Don't screw up if window_scroll gets an error. */
4858 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5500c422 4859 ++windows_or_buffers_changed;
7ab12479
JB
4860
4861 Fset_buffer (w->buffer);
4862 SET_PT (marker_position (w->pointm));
4863
413430c5 4864 if (NILP (arg))
d4e7cf01 4865 window_scroll (window, 1, 1, 1);
413430c5 4866 else if (EQ (arg, Qminus))
d4e7cf01 4867 window_scroll (window, -1, 1, 1);
7ab12479
JB
4868 else
4869 {
413430c5
EN
4870 if (CONSP (arg))
4871 arg = Fcar (arg);
b7826503 4872 CHECK_NUMBER (arg);
101d1605 4873 window_scroll (window, XINT (arg), 0, 1);
7ab12479
JB
4874 }
4875
b73ea88e 4876 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
f4e7b2c2 4877 unbind_to (count, Qnil);
7ab12479
JB
4878
4879 return Qnil;
4880}
4881\f
644b477c 4882DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
fdb82f93 4883 doc: /* Scroll selected window display ARG columns left.
2fe41216
EZ
4884Default for ARG is window width minus 2.
4885Value is the total amount of leftward horizontal scrolling in
4886effect after the change.
4887If `automatic-hscrolling' is non-nil, the argument ARG modifies
4888a lower bound for automatic scrolling, i.e. automatic scrolling
4889will not scroll a window to a column less than the value returned
4890by this function. */)
fdb82f93 4891 (arg)
7ab12479
JB
4892 register Lisp_Object arg;
4893{
c67fa410
GM
4894 Lisp_Object result;
4895 int hscroll;
4896 struct window *w = XWINDOW (selected_window);
177c0ea7 4897
265a9e55 4898 if (NILP (arg))
949cf20f 4899 XSETFASTINT (arg, window_box_text_cols (w) - 2);
7ab12479
JB
4900 else
4901 arg = Fprefix_numeric_value (arg);
4902
c67fa410
GM
4903 hscroll = XINT (w->hscroll) + XINT (arg);
4904 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4905
f5686fbd 4906 if (interactive_p (0))
c67fa410
GM
4907 w->min_hscroll = w->hscroll;
4908
4909 return result;
7ab12479
JB
4910}
4911
644b477c 4912DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
fdb82f93 4913 doc: /* Scroll selected window display ARG columns right.
2fe41216
EZ
4914Default for ARG is window width minus 2.
4915Value is the total amount of leftward horizontal scrolling in
4916effect after the change.
4917If `automatic-hscrolling' is non-nil, the argument ARG modifies
4918a lower bound for automatic scrolling, i.e. automatic scrolling
4919will not scroll a window to a column less than the value returned
4920by this function. */)
fdb82f93 4921 (arg)
7ab12479
JB
4922 register Lisp_Object arg;
4923{
c67fa410
GM
4924 Lisp_Object result;
4925 int hscroll;
4926 struct window *w = XWINDOW (selected_window);
177c0ea7 4927
265a9e55 4928 if (NILP (arg))
949cf20f 4929 XSETFASTINT (arg, window_box_text_cols (w) - 2);
7ab12479
JB
4930 else
4931 arg = Fprefix_numeric_value (arg);
4932
c67fa410
GM
4933 hscroll = XINT (w->hscroll) - XINT (arg);
4934 result = Fset_window_hscroll (selected_window, make_number (hscroll));
177c0ea7 4935
f5686fbd 4936 if (interactive_p (0))
c67fa410
GM
4937 w->min_hscroll = w->hscroll;
4938
4939 return result;
7ab12479
JB
4940}
4941
fa832261
KS
4942DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
4943 doc: /* Return the window which was selected when entering the minibuffer.
4944Returns nil, if current window is not a minibuffer window. */)
4945 ()
4946{
4947 if (minibuf_level > 0
4948 && MINI_WINDOW_P (XWINDOW (selected_window))
fa832261
KS
4949 && WINDOW_LIVE_P (minibuf_selected_window))
4950 return minibuf_selected_window;
4951
4952 return Qnil;
4953}
4954
12c8b416
GM
4955/* Value is the number of lines actually displayed in window W,
4956 as opposed to its height. */
4957
4958static int
4959displayed_window_lines (w)
4960 struct window *w;
4961{
4962 struct it it;
4963 struct text_pos start;
4964 int height = window_box_height (w);
4965 struct buffer *old_buffer;
4966 int bottom_y;
4967
4968 if (XBUFFER (w->buffer) != current_buffer)
4969 {
4970 old_buffer = current_buffer;
4971 set_buffer_internal (XBUFFER (w->buffer));
4972 }
4973 else
4974 old_buffer = NULL;
4975
521b203e
GM
4976 /* In case W->start is out of the accessible range, do something
4977 reasonable. This happens in Info mode when Info-scroll-down
4978 calls (recenter -1) while W->start is 1. */
4979 if (XMARKER (w->start)->charpos < BEGV)
4980 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4981 else if (XMARKER (w->start)->charpos > ZV)
4982 SET_TEXT_POS (start, ZV, ZV_BYTE);
4983 else
4984 SET_TEXT_POS_FROM_MARKER (start, w->start);
4985
12c8b416
GM
4986 start_display (&it, w, start);
4987 move_it_vertically (&it, height);
c8bc6f65 4988 bottom_y = line_bottom_y (&it);
12c8b416 4989
1de65f51
RS
4990 /* rms: On a non-window display,
4991 the value of it.vpos at the bottom of the screen
4992 seems to be 1 larger than window_box_height (w).
4993 This kludge fixes a bug whereby (move-to-window-line -1)
4994 when ZV is on the last screen line
4995 moves to the previous screen line instead of the last one. */
4996 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
4997 height++;
4998
12c8b416
GM
4999 /* Add in empty lines at the bottom of the window. */
5000 if (bottom_y < height)
5001 {
949cf20f 5002 int uy = FRAME_LINE_HEIGHT (it.f);
c8bc6f65 5003 it.vpos += (height - bottom_y + uy - 1) / uy;
12c8b416
GM
5004 }
5005
c8bc6f65
GM
5006 if (old_buffer)
5007 set_buffer_internal (old_buffer);
5008
12c8b416
GM
5009 return it.vpos;
5010}
5011
5012
7ab12479 5013DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
fdb82f93
PJ
5014 doc: /* Center point in window and redisplay frame.
5015With prefix argument ARG, recenter putting point on screen line ARG
5016relative to the current window. If ARG is negative, it counts up from the
5017bottom of the window. (ARG should be less than the height of the window.)
5018
5019If ARG is omitted or nil, erase the entire frame and then
5020redraw with point in the center of the current window.
5021Just C-u as prefix means put point in the center of the window
5022and redisplay normally--don't erase and redraw the frame. */)
5023 (arg)
413430c5 5024 register Lisp_Object arg;
7ab12479 5025{
6df47b59 5026 struct window *w = XWINDOW (selected_window);
478292ed
RS
5027 struct buffer *buf = XBUFFER (w->buffer);
5028 struct buffer *obuf = current_buffer;
6df47b59
GM
5029 int center_p = 0;
5030 int charpos, bytepos;
7ab12479 5031
0fa5d25b
RS
5032 /* If redisplay is suppressed due to an error, try again. */
5033 obuf->display_error_modiff = 0;
5034
413430c5 5035 if (NILP (arg))
7ab12479 5036 {
f02d6d5c
KH
5037 int i;
5038
5039 /* Invalidate pixel data calculated for all compositions. */
5040 for (i = 0; i < n_compositions; i++)
5041 composition_table[i]->font = NULL;
7ab12479 5042
527b6458 5043 Fredraw_frame (w->frame);
44fa5b1e 5044 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
6df47b59 5045 center_p = 1;
7ab12479 5046 }
413430c5 5047 else if (CONSP (arg)) /* Just C-u. */
6df47b59 5048 center_p = 1;
7ab12479
JB
5049 else
5050 {
413430c5 5051 arg = Fprefix_numeric_value (arg);
b7826503 5052 CHECK_NUMBER (arg);
7ab12479
JB
5053 }
5054
478292ed 5055 set_buffer_internal (buf);
7ab12479 5056
521b203e 5057 /* Handle centering on a graphical frame specially. Such frames can
6df47b59
GM
5058 have variable-height lines and centering point on the basis of
5059 line counts would lead to strange effects. */
521b203e 5060 if (FRAME_WINDOW_P (XFRAME (w->frame)))
6df47b59 5061 {
6df47b59
GM
5062 if (center_p)
5063 {
521b203e
GM
5064 struct it it;
5065 struct text_pos pt;
177c0ea7 5066
521b203e
GM
5067 SET_TEXT_POS (pt, PT, PT_BYTE);
5068 start_display (&it, w, pt);
202379cf 5069 move_it_vertically (&it, - window_box_height (w) / 2);
521b203e
GM
5070 charpos = IT_CHARPOS (it);
5071 bytepos = IT_BYTEPOS (it);
6df47b59
GM
5072 }
5073 else if (XINT (arg) < 0)
5074 {
521b203e
GM
5075 struct it it;
5076 struct text_pos pt;
d466fa4d 5077 int y0, y1, h, nlines;
177c0ea7 5078
521b203e
GM
5079 SET_TEXT_POS (pt, PT, PT_BYTE);
5080 start_display (&it, w, pt);
5081 y0 = it.current_y;
5082
d466fa4d 5083 /* The amount of pixels we have to move back is the window
521b203e
GM
5084 height minus what's displayed in the line containing PT,
5085 and the lines below. */
d466fa4d
GM
5086 nlines = - XINT (arg) - 1;
5087 move_it_by_lines (&it, nlines, 1);
5088
201c831a 5089 y1 = line_bottom_y (&it);
d466fa4d
GM
5090
5091 /* If we can't move down NLINES lines because we hit
5092 the end of the buffer, count in some empty lines. */
5093 if (it.vpos < nlines)
949cf20f 5094 y1 += (nlines - it.vpos) * FRAME_LINE_HEIGHT (it.f);
177c0ea7 5095
201c831a
GM
5096 h = window_box_height (w) - (y1 - y0);
5097
521b203e 5098 start_display (&it, w, pt);
201c831a 5099 move_it_vertically (&it, - h);
521b203e
GM
5100 charpos = IT_CHARPOS (it);
5101 bytepos = IT_BYTEPOS (it);
6df47b59 5102 }
521b203e
GM
5103 else
5104 {
5105 struct position pos;
5106 pos = *vmotion (PT, - XINT (arg), w);
5107 charpos = pos.bufpos;
5108 bytepos = pos.bytepos;
5109 }
5110 }
5111 else
5112 {
5113 struct position pos;
5114 int ht = window_internal_height (w);
5115
5116 if (center_p)
5117 arg = make_number (ht / 2);
5118 else if (XINT (arg) < 0)
5119 arg = make_number (XINT (arg) + ht);
177c0ea7 5120
6df47b59
GM
5121 pos = *vmotion (PT, - XINT (arg), w);
5122 charpos = pos.bufpos;
5123 bytepos = pos.bytepos;
5124 }
5125
5126 /* Set the new window start. */
5127 set_marker_both (w->start, w->buffer, charpos, bytepos);
2f3cad6c 5128 w->window_end_valid = Qnil;
177c0ea7 5129
95605b1b
RS
5130 w->optional_new_start = Qt;
5131
6df47b59
GM
5132 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5133 w->start_at_line_beg = Qt;
5134 else
5135 w->start_at_line_beg = Qnil;
177c0ea7 5136
478292ed 5137 set_buffer_internal (obuf);
7ab12479
JB
5138 return Qnil;
5139}
b7617575
GM
5140
5141
81fe0836 5142DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
fdb82f93
PJ
5143 0, 1, 0,
5144 doc: /* Return the height in lines of the text display area of WINDOW.
5145This doesn't include the mode-line (or header-line if any) or any
5146partial-height lines in the text display area. */)
5147 (window)
81fe0836
MB
5148 Lisp_Object window;
5149{
5150 struct window *w = decode_window (window);
5151 int pixel_height = window_box_height (w);
949cf20f 5152 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
81fe0836
MB
5153 return make_number (line_height);
5154}
5155
5156
7ab12479
JB
5157\f
5158DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
fdb82f93
PJ
5159 1, 1, "P",
5160 doc: /* Position point relative to window.
5161With no argument, position point at center of window.
5162An argument specifies vertical position within the window;
5163zero means top of window, negative means relative to bottom of window. */)
5164 (arg)
b7617575 5165 Lisp_Object arg;
7ab12479 5166{
b7617575
GM
5167 struct window *w = XWINDOW (selected_window);
5168 int lines, start;
540b6aa0 5169 Lisp_Object window;
7ab12479 5170
b7617575 5171 window = selected_window;
7ab12479
JB
5172 start = marker_position (w->start);
5173 if (start < BEGV || start > ZV)
5174 {
b7617575 5175 int height = window_internal_height (w);
cd2be1dd 5176 Fvertical_motion (make_number (- (height / 2)), window);
b73ea88e 5177 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
7ab12479
JB
5178 w->start_at_line_beg = Fbolp ();
5179 w->force_start = Qt;
5180 }
5181 else
b73ea88e 5182 Fgoto_char (w->start);
7ab12479 5183
b7617575
GM
5184 lines = displayed_window_lines (w);
5185 if (NILP (arg))
5186 XSETFASTINT (arg, lines / 2);
5187 else
5188 {
5189 arg = Fprefix_numeric_value (arg);
5190 if (XINT (arg) < 0)
5191 XSETINT (arg, XINT (arg) + lines);
5192 }
5193
c8bc6f65 5194 /* Skip past a partially visible first line. */
163784df 5195 if (w->vscroll)
163784df
MB
5196 XSETINT (arg, XINT (arg) + 1);
5197
540b6aa0 5198 return Fvertical_motion (arg, window);
7ab12479 5199}
5500c422
GM
5200
5201
7ab12479 5202\f
5500c422
GM
5203/***********************************************************************
5204 Window Configuration
5205 ***********************************************************************/
5206
7ab12479
JB
5207struct save_window_data
5208 {
f5ccc0cc 5209 EMACS_INT size_from_Lisp_Vector_struct;
7ab12479 5210 struct Lisp_Vector *next_from_Lisp_Vector_struct;
949cf20f 5211 Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
9ea173e8 5212 Lisp_Object frame_tool_bar_lines;
bdc727bf 5213 Lisp_Object selected_frame;
7ab12479
JB
5214 Lisp_Object current_window;
5215 Lisp_Object current_buffer;
5216 Lisp_Object minibuf_scroll_window;
3f49fddc 5217 Lisp_Object minibuf_selected_window;
7ab12479 5218 Lisp_Object root_window;
bdc727bf 5219 Lisp_Object focus_frame;
756b6edc
RS
5220 /* Record the values of window-min-width and window-min-height
5221 so that window sizes remain consistent with them. */
5222 Lisp_Object min_width, min_height;
cbff28e8
RS
5223 /* A vector, each of whose elements is a struct saved_window
5224 for one window. */
7ab12479
JB
5225 Lisp_Object saved_windows;
5226 };
ff06df24 5227
cbff28e8 5228/* This is saved as a Lisp_Vector */
7ab12479 5229struct saved_window
ea68264b
GM
5230{
5231 /* these first two must agree with struct Lisp_Vector in lisp.h */
5232 EMACS_INT size_from_Lisp_Vector_struct;
5233 struct Lisp_Vector *next_from_Lisp_Vector_struct;
7ab12479 5234
ea68264b
GM
5235 Lisp_Object window;
5236 Lisp_Object buffer, start, pointm, mark;
949cf20f
KS
5237 Lisp_Object left_col, top_line, total_cols, total_lines;
5238 Lisp_Object hscroll, min_hscroll;
ea68264b
GM
5239 Lisp_Object parent, prev;
5240 Lisp_Object start_at_line_beg;
5241 Lisp_Object display_table;
949cf20f
KS
5242 Lisp_Object orig_top_line, orig_total_lines;
5243 Lisp_Object left_margin_cols, right_margin_cols;
5244 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5245 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
ea68264b
GM
5246};
5247
949cf20f 5248#define SAVED_WINDOW_VECTOR_SIZE 24 /* Arg to Fmake_vector */
7ab12479
JB
5249
5250#define SAVED_WINDOW_N(swv,n) \
5251 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5252
5253DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
fdb82f93
PJ
5254 doc: /* Return t if OBJECT is a window-configuration object. */)
5255 (object)
413430c5 5256 Lisp_Object object;
7ab12479 5257{
413430c5 5258 if (WINDOW_CONFIGURATIONP (object))
7ab12479
JB
5259 return Qt;
5260 return Qnil;
5261}
5262
3f8ab7bd 5263DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
fdb82f93
PJ
5264 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5265 (config)
3f8ab7bd
RS
5266 Lisp_Object config;
5267{
5268 register struct save_window_data *data;
5269 struct Lisp_Vector *saved_windows;
5270
5271 if (! WINDOW_CONFIGURATIONP (config))
5272 wrong_type_argument (Qwindow_configuration_p, config);
5273
5274 data = (struct save_window_data *) XVECTOR (config);
5275 saved_windows = XVECTOR (data->saved_windows);
5276 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5277}
5278
d5b2799e 5279DEFUN ("set-window-configuration", Fset_window_configuration,
fdb82f93
PJ
5280 Sset_window_configuration, 1, 1, 0,
5281 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5282CONFIGURATION must be a value previously returned
5283by `current-window-configuration' (which see).
5284If CONFIGURATION was made from a frame that is now deleted,
5285only frame-independent values can be restored. In this case,
5286the return value is nil. Otherwise the value is t. */)
5287 (configuration)
2f83aebe 5288 Lisp_Object configuration;
7ab12479 5289{
7ab12479
JB
5290 register struct save_window_data *data;
5291 struct Lisp_Vector *saved_windows;
7ab12479 5292 Lisp_Object new_current_buffer;
fd482be5 5293 Lisp_Object frame;
44fa5b1e 5294 FRAME_PTR f;
72695e47 5295 int old_point = -1;
7ab12479 5296
017b2bad 5297 while (!WINDOW_CONFIGURATIONP (configuration))
3f8ab7bd 5298 wrong_type_argument (Qwindow_configuration_p, configuration);
7ab12479 5299
2f83aebe 5300 data = (struct save_window_data *) XVECTOR (configuration);
7ab12479
JB
5301 saved_windows = XVECTOR (data->saved_windows);
5302
7ab12479 5303 new_current_buffer = data->current_buffer;
265a9e55 5304 if (NILP (XBUFFER (new_current_buffer)->name))
7ab12479 5305 new_current_buffer = Qnil;
72695e47 5306 else
73cadfc1
DK
5307 {
5308 if (XBUFFER (new_current_buffer) == current_buffer)
5309 old_point = PT;
5310 else
5311 old_point = BUF_PT (XBUFFER (new_current_buffer));
5312 }
7ab12479 5313
fd482be5
JB
5314 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5315 f = XFRAME (frame);
177c0ea7 5316
fd482be5
JB
5317 /* If f is a dead frame, don't bother rebuilding its window tree.
5318 However, there is other stuff we should still try to do below. */
5319 if (FRAME_LIVE_P (f))
7ab12479 5320 {
fd482be5
JB
5321 register struct window *w;
5322 register struct saved_window *p;
5500c422
GM
5323 struct window *root_window;
5324 struct window **leaf_windows;
5325 int n_leaf_windows;
c4280705 5326 int k, i, n;
fd482be5
JB
5327
5328 /* If the frame has been resized since this window configuration was
5329 made, we change the frame to the size specified in the
5330 configuration, restore the configuration, and then resize it
5331 back. We keep track of the prevailing height in these variables. */
949cf20f
KS
5332 int previous_frame_lines = FRAME_LINES (f);
5333 int previous_frame_cols = FRAME_COLS (f);
8f6ea2e9 5334 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
9ea173e8 5335 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
fd482be5 5336
d2b35234
RS
5337 /* The mouse highlighting code could get screwed up
5338 if it runs during this. */
5339 BLOCK_INPUT;
5340
949cf20f
KS
5341 if (XFASTINT (data->frame_lines) != previous_frame_lines
5342 || XFASTINT (data->frame_cols) != previous_frame_cols)
5343 change_frame_size (f, XFASTINT (data->frame_lines),
5344 XFASTINT (data->frame_cols), 0, 0, 0);
e3678b64 5345#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
8f6ea2e9
KH
5346 if (XFASTINT (data->frame_menu_bar_lines)
5347 != previous_frame_menu_bar_lines)
f8ad443a 5348 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
4314246f 5349#ifdef HAVE_WINDOW_SYSTEM
9ea173e8
GM
5350 if (XFASTINT (data->frame_tool_bar_lines)
5351 != previous_frame_tool_bar_lines)
5352 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
4314246f 5353#endif
217f2871 5354#endif
fd482be5 5355
719eaeb1
GM
5356 /* "Swap out" point from the selected window
5357 into its buffer. We do this now, before
5358 restoring the window contents, and prevent it from
5359 being done later on when we select a new window. */
596ae0cf
RS
5360 if (! NILP (XWINDOW (selected_window)->buffer))
5361 {
5362 w = XWINDOW (selected_window);
5363 set_marker_both (w->pointm,
5364 w->buffer,
5365 BUF_PT (XBUFFER (w->buffer)),
5366 BUF_PT_BYTE (XBUFFER (w->buffer)));
5367 }
5368
fd482be5 5369 windows_or_buffers_changed++;
29aeee73 5370 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
fd482be5 5371
5500c422 5372 /* Problem: Freeing all matrices and later allocating them again
177c0ea7 5373 is a serious redisplay flickering problem. What we would
5500c422
GM
5374 really like to do is to free only those matrices not reused
5375 below. */
5376 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5377 leaf_windows
5378 = (struct window **) alloca (count_windows (root_window)
5379 * sizeof (struct window *));
5380 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5381
756b6edc
RS
5382 /* Temporarily avoid any problems with windows that are smaller
5383 than they are supposed to be. */
5384 window_min_height = 1;
5385 window_min_width = 1;
5386
fd482be5
JB
5387 /* Kludge Alert!
5388 Mark all windows now on frame as "deleted".
5389 Restoring the new configuration "undeletes" any that are in it.
37962e60 5390
fd482be5
JB
5391 Save their current buffers in their height fields, since we may
5392 need it later, if a buffer saved in the configuration is now
5393 dead. */
5394 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5395
5396 for (k = 0; k < saved_windows->size; k++)
5397 {
5398 p = SAVED_WINDOW_N (saved_windows, k);
5399 w = XWINDOW (p->window);
5400 w->next = Qnil;
7ab12479 5401
fd482be5
JB
5402 if (!NILP (p->parent))
5403 w->parent = SAVED_WINDOW_N (saved_windows,
5404 XFASTINT (p->parent))->window;
5405 else
5406 w->parent = Qnil;
7ab12479 5407
fd482be5 5408 if (!NILP (p->prev))
7ab12479 5409 {
fd482be5
JB
5410 w->prev = SAVED_WINDOW_N (saved_windows,
5411 XFASTINT (p->prev))->window;
5412 XWINDOW (w->prev)->next = p->window;
5413 }
5414 else
5415 {
5416 w->prev = Qnil;
5417 if (!NILP (w->parent))
5418 {
949cf20f 5419 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
fd482be5
JB
5420 {
5421 XWINDOW (w->parent)->vchild = p->window;
5422 XWINDOW (w->parent)->hchild = Qnil;
5423 }
5424 else
5425 {
5426 XWINDOW (w->parent)->hchild = p->window;
5427 XWINDOW (w->parent)->vchild = Qnil;
5428 }
5429 }
5430 }
5431
5432 /* If we squirreled away the buffer in the window's height,
5433 restore it now. */
949cf20f
KS
5434 if (BUFFERP (w->total_lines))
5435 w->buffer = w->total_lines;
5436 w->left_col = p->left_col;
5437 w->top_line = p->top_line;
5438 w->total_cols = p->total_cols;
5439 w->total_lines = p->total_lines;
fd482be5 5440 w->hscroll = p->hscroll;
ea68264b 5441 w->min_hscroll = p->min_hscroll;
fd482be5 5442 w->display_table = p->display_table;
949cf20f
KS
5443 w->orig_top_line = p->orig_top_line;
5444 w->orig_total_lines = p->orig_total_lines;
5445 w->left_margin_cols = p->left_margin_cols;
5446 w->right_margin_cols = p->right_margin_cols;
5447 w->left_fringe_width = p->left_fringe_width;
5448 w->right_fringe_width = p->right_fringe_width;
5449 w->fringes_outside_margins = p->fringes_outside_margins;
5450 w->scroll_bar_width = p->scroll_bar_width;
5451 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
d834a2e9 5452 XSETFASTINT (w->last_modified, 0);
3cd21523 5453 XSETFASTINT (w->last_overlay_modified, 0);
fd482be5
JB
5454
5455 /* Reinstall the saved buffer and pointers into it. */
5456 if (NILP (p->buffer))
5457 w->buffer = p->buffer;
5458 else
5459 {
5460 if (!NILP (XBUFFER (p->buffer)->name))
5461 /* If saved buffer is alive, install it. */
5462 {
5463 w->buffer = p->buffer;
5464 w->start_at_line_beg = p->start_at_line_beg;
b73ea88e
RS
5465 set_marker_restricted (w->start, p->start, w->buffer);
5466 set_marker_restricted (w->pointm, p->pointm, w->buffer);
fd482be5 5467 Fset_marker (XBUFFER (w->buffer)->mark,
b73ea88e 5468 p->mark, w->buffer);
fd482be5
JB
5469
5470 /* As documented in Fcurrent_window_configuration, don't
243a5ce6
RS
5471 restore the location of point in the buffer which was
5472 current when the window configuration was recorded. */
6b54027b
RS
5473 if (!EQ (p->buffer, new_current_buffer)
5474 && XBUFFER (p->buffer) == current_buffer)
fd482be5
JB
5475 Fgoto_char (w->pointm);
5476 }
52a68e98
RS
5477 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
5478 /* Else unless window has a live buffer, get one. */
7ab12479 5479 {
fd482be5
JB
5480 w->buffer = Fcdr (Fcar (Vbuffer_alist));
5481 /* This will set the markers to beginning of visible
5482 range. */
5483 set_marker_restricted (w->start, make_number (0), w->buffer);
5484 set_marker_restricted (w->pointm, make_number (0),w->buffer);
5485 w->start_at_line_beg = Qt;
7ab12479
JB
5486 }
5487 else
fd482be5 5488 /* Keeping window's old buffer; make sure the markers
52a68e98 5489 are real. */
7ab12479 5490 {
fd482be5
JB
5491 /* Set window markers at start of visible range. */
5492 if (XMARKER (w->start)->buffer == 0)
5493 set_marker_restricted (w->start, make_number (0),
5494 w->buffer);
5495 if (XMARKER (w->pointm)->buffer == 0)
b73ea88e
RS
5496 set_marker_restricted_both (w->pointm, w->buffer,
5497 BUF_PT (XBUFFER (w->buffer)),
5498 BUF_PT_BYTE (XBUFFER (w->buffer)));
fd482be5 5499 w->start_at_line_beg = Qt;
7ab12479
JB
5500 }
5501 }
5502 }
9ace597f 5503
fd482be5 5504 FRAME_ROOT_WINDOW (f) = data->root_window;
719eaeb1
GM
5505 /* Prevent "swapping out point" in the old selected window
5506 using the buffer that has been restored into it.
72695e47
RS
5507 Use the point value from the beginning of this function
5508 since unshow_buffer (called from delete_all_subwindows)
5509 could have altered it. */
719eaeb1 5510 selected_window = Qnil;
243a5ce6
RS
5511 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5512 set_marker_restricted (XWINDOW (data->current_window)->pointm,
18787f5e 5513 make_number (old_point),
243a5ce6 5514 XWINDOW (data->current_window)->buffer);
177c0ea7 5515
14d87dc9 5516 Fselect_window (data->current_window, Qnil);
396a830c
RS
5517 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
5518 = selected_window;
7ab12479 5519
db269683 5520 if (NILP (data->focus_frame)
017b2bad 5521 || (FRAMEP (data->focus_frame)
db269683
JB
5522 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5523 Fredirect_frame_focus (frame, data->focus_frame);
7ab12479 5524
fd482be5
JB
5525#if 0 /* I don't understand why this is needed, and it causes problems
5526 when the frame's old selected window has been deleted. */
e4e59717 5527 if (f != selected_frame && FRAME_WINDOW_P (f))
9a7c6fc3 5528 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
d12f6f83 5529 0, 0);
fd482be5
JB
5530#endif
5531
5532 /* Set the screen height to the value it had before this function. */
949cf20f
KS
5533 if (previous_frame_lines != FRAME_LINES (f)
5534 || previous_frame_cols != FRAME_COLS (f))
5535 change_frame_size (f, previous_frame_lines, previous_frame_cols,
2b653806 5536 0, 0, 0);
e3678b64 5537#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
8f6ea2e9 5538 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
f8ad443a
AS
5539 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5540 make_number (0));
4314246f 5541#ifdef HAVE_WINDOW_SYSTEM
9ea173e8
GM
5542 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5543 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5544 make_number (0));
4314246f 5545#endif
217f2871 5546#endif
d2b35234 5547
5500c422 5548 /* Now, free glyph matrices in windows that were not reused. */
c4280705
GM
5549 for (i = n = 0; i < n_leaf_windows; ++i)
5550 {
5551 if (NILP (leaf_windows[i]->buffer))
5552 {
5553 /* Assert it's not reused as a combination. */
177c0ea7 5554 xassert (NILP (leaf_windows[i]->hchild)
c4280705
GM
5555 && NILP (leaf_windows[i]->vchild));
5556 free_window_matrices (leaf_windows[i]);
c4280705
GM
5557 }
5558 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5559 ++n;
5560 }
177c0ea7 5561
5500c422
GM
5562 adjust_glyphs (f);
5563
d2b35234 5564 UNBLOCK_INPUT;
756b6edc 5565
478292ed
RS
5566 /* Fselect_window will have made f the selected frame, so we
5567 reselect the proper frame here. Fhandle_switch_frame will change the
5568 selected window too, but that doesn't make the call to
5569 Fselect_window above totally superfluous; it still sets f's
5570 selected window. */
5571 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
d12f6f83 5572 do_switch_frame (data->selected_frame, 0, 0);
478292ed
RS
5573
5574 if (! NILP (Vwindow_configuration_change_hook)
5575 && ! NILP (Vrun_hooks))
5576 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
5577 }
bdc727bf
JB
5578
5579 if (!NILP (new_current_buffer))
243a5ce6 5580 Fset_buffer (new_current_buffer);
bdc727bf 5581
478292ed
RS
5582 /* Restore the minimum heights recorded in the configuration. */
5583 window_min_height = XINT (data->min_height);
5584 window_min_width = XINT (data->min_width);
543f5fb1 5585
478292ed 5586 Vminibuf_scroll_window = data->minibuf_scroll_window;
3dbab091 5587 minibuf_selected_window = data->minibuf_selected_window;
543f5fb1 5588
3f8ab7bd 5589 return (FRAME_LIVE_P (f) ? Qt : Qnil);
7ab12479
JB
5590}
5591
44fa5b1e 5592/* Mark all windows now on frame as deleted
7ab12479
JB
5593 by setting their buffers to nil. */
5594
fd482be5 5595void
7ab12479
JB
5596delete_all_subwindows (w)
5597 register struct window *w;
5598{
265a9e55 5599 if (!NILP (w->next))
7ab12479 5600 delete_all_subwindows (XWINDOW (w->next));
265a9e55 5601 if (!NILP (w->vchild))
7ab12479 5602 delete_all_subwindows (XWINDOW (w->vchild));
265a9e55 5603 if (!NILP (w->hchild))
7ab12479 5604 delete_all_subwindows (XWINDOW (w->hchild));
605be8af 5605
949cf20f 5606 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
605be8af 5607
86e48436
RS
5608 if (!NILP (w->buffer))
5609 unshow_buffer (w);
5610
605be8af
JB
5611 /* We set all three of these fields to nil, to make sure that we can
5612 distinguish this dead window from any live window. Live leaf
5613 windows will have buffer set, and combination windows will have
5614 vchild or hchild set. */
5615 w->buffer = Qnil;
5616 w->vchild = Qnil;
5617 w->hchild = Qnil;
acf70840
GM
5618
5619 Vwindow_list = Qnil;
7ab12479
JB
5620}
5621\f
5622static int
5623count_windows (window)
5624 register struct window *window;
5625{
5626 register int count = 1;
265a9e55 5627 if (!NILP (window->next))
7ab12479 5628 count += count_windows (XWINDOW (window->next));
265a9e55 5629 if (!NILP (window->vchild))
7ab12479 5630 count += count_windows (XWINDOW (window->vchild));
265a9e55 5631 if (!NILP (window->hchild))
7ab12479
JB
5632 count += count_windows (XWINDOW (window->hchild));
5633 return count;
5634}
5635
5500c422 5636
177c0ea7 5637/* Fill vector FLAT with leaf windows under W, starting at index I.
5500c422
GM
5638 Value is last index + 1. */
5639
5640static int
5641get_leaf_windows (w, flat, i)
5642 struct window *w;
5643 struct window **flat;
5644 int i;
5645{
5646 while (w)
5647 {
5648 if (!NILP (w->hchild))
5649 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5650 else if (!NILP (w->vchild))
5651 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
177c0ea7 5652 else
5500c422
GM
5653 flat[i++] = w;
5654
5655 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5656 }
5657
5658 return i;
5659}
5660
5661
5662/* Return a pointer to the glyph W's physical cursor is on. Value is
5663 null if W's current matrix is invalid, so that no meaningfull glyph
5664 can be returned. */
5665
5666struct glyph *
5667get_phys_cursor_glyph (w)
5668 struct window *w;
5669{
5670 struct glyph_row *row;
5671 struct glyph *glyph;
5672
5673 if (w->phys_cursor.vpos >= 0
5674 && w->phys_cursor.vpos < w->current_matrix->nrows
5675 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
5676 row->enabled_p)
5677 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
5678 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
5679 else
5680 glyph = NULL;
5681
5682 return glyph;
5683}
5684
5685
7ab12479
JB
5686static int
5687save_window_save (window, vector, i)
5688 Lisp_Object window;
5689 struct Lisp_Vector *vector;
5690 int i;
5691{
5692 register struct saved_window *p;
5693 register struct window *w;
5694 register Lisp_Object tem;
5695
265a9e55 5696 for (;!NILP (window); window = w->next)
7ab12479
JB
5697 {
5698 p = SAVED_WINDOW_N (vector, i);
5699 w = XWINDOW (window);
5700
d834a2e9 5701 XSETFASTINT (w->temslot, i++);
7ab12479
JB
5702 p->window = window;
5703 p->buffer = w->buffer;
949cf20f
KS
5704 p->left_col = w->left_col;
5705 p->top_line = w->top_line;
5706 p->total_cols = w->total_cols;
5707 p->total_lines = w->total_lines;
7ab12479 5708 p->hscroll = w->hscroll;
ea68264b 5709 p->min_hscroll = w->min_hscroll;
7ab12479 5710 p->display_table = w->display_table;
949cf20f
KS
5711 p->orig_top_line = w->orig_top_line;
5712 p->orig_total_lines = w->orig_total_lines;
5713 p->left_margin_cols = w->left_margin_cols;
5714 p->right_margin_cols = w->right_margin_cols;
5715 p->left_fringe_width = w->left_fringe_width;
5716 p->right_fringe_width = w->right_fringe_width;
5717 p->fringes_outside_margins = w->fringes_outside_margins;
5718 p->scroll_bar_width = w->scroll_bar_width;
5719 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
265a9e55 5720 if (!NILP (w->buffer))
7ab12479
JB
5721 {
5722 /* Save w's value of point in the window configuration.
5723 If w is the selected window, then get the value of point
5724 from the buffer; pointm is garbage in the selected window. */
5725 if (EQ (window, selected_window))
5726 {
5727 p->pointm = Fmake_marker ();
b73ea88e
RS
5728 set_marker_both (p->pointm, w->buffer,
5729 BUF_PT (XBUFFER (w->buffer)),
5730 BUF_PT_BYTE (XBUFFER (w->buffer)));
7ab12479
JB
5731 }
5732 else
eeb82665 5733 p->pointm = Fcopy_marker (w->pointm, Qnil);
7ab12479 5734
eeb82665 5735 p->start = Fcopy_marker (w->start, Qnil);
7ab12479
JB
5736 p->start_at_line_beg = w->start_at_line_beg;
5737
5738 tem = XBUFFER (w->buffer)->mark;
eeb82665 5739 p->mark = Fcopy_marker (tem, Qnil);
7ab12479
JB
5740 }
5741 else
5742 {
5743 p->pointm = Qnil;
5744 p->start = Qnil;
5745 p->mark = Qnil;
5746 p->start_at_line_beg = Qnil;
5747 }
5748
265a9e55 5749 if (NILP (w->parent))
7ab12479
JB
5750 p->parent = Qnil;
5751 else
5752 p->parent = XWINDOW (w->parent)->temslot;
5753
265a9e55 5754 if (NILP (w->prev))
7ab12479
JB
5755 p->prev = Qnil;
5756 else
5757 p->prev = XWINDOW (w->prev)->temslot;
5758
265a9e55 5759 if (!NILP (w->vchild))
7ab12479 5760 i = save_window_save (w->vchild, vector, i);
265a9e55 5761 if (!NILP (w->hchild))
7ab12479
JB
5762 i = save_window_save (w->hchild, vector, i);
5763 }
5764
5765 return i;
5766}
5767
a0d76c27 5768DEFUN ("current-window-configuration", Fcurrent_window_configuration,
fdb82f93
PJ
5769 Scurrent_window_configuration, 0, 1, 0,
5770 doc: /* Return an object representing the current window configuration of FRAME.
5771If FRAME is nil or omitted, use the selected frame.
5772This describes the number of windows, their sizes and current buffers,
5773and for each displayed buffer, where display starts, and the positions of
5774point and mark. An exception is made for point in the current buffer:
5775its value is -not- saved.
5776This also records the currently selected frame, and FRAME's focus
5777redirection (see `redirect-frame-focus'). */)
5778 (frame)
44fa5b1e 5779 Lisp_Object frame;
7ab12479
JB
5780{
5781 register Lisp_Object tem;
5782 register int n_windows;
5783 register struct save_window_data *data;
da2792e0 5784 register struct Lisp_Vector *vec;
7ab12479 5785 register int i;
44fa5b1e 5786 FRAME_PTR f;
43bad991 5787
44fa5b1e 5788 if (NILP (frame))
1ae1a37d 5789 frame = selected_frame;
b7826503 5790 CHECK_LIVE_FRAME (frame);
1ae1a37d 5791 f = XFRAME (frame);
7ab12479 5792
44fa5b1e 5793 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
26605be9 5794 vec = allocate_other_vector (VECSIZE (struct save_window_data));
da2792e0
KH
5795 data = (struct save_window_data *)vec;
5796
949cf20f
KS
5797 XSETFASTINT (data->frame_cols, FRAME_COLS (f));
5798 XSETFASTINT (data->frame_lines, FRAME_LINES (f));
d834a2e9 5799 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
9ea173e8 5800 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
1ae1a37d 5801 data->selected_frame = selected_frame;
44fa5b1e 5802 data->current_window = FRAME_SELECTED_WINDOW (f);
74112613 5803 XSETBUFFER (data->current_buffer, current_buffer);
3f49fddc 5804 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
3dbab091 5805 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
44fa5b1e 5806 data->root_window = FRAME_ROOT_WINDOW (f);
bdc727bf 5807 data->focus_frame = FRAME_FOCUS_FRAME (f);
74112613
KH
5808 XSETINT (data->min_height, window_min_height);
5809 XSETINT (data->min_width, window_min_width);
7ab12479
JB
5810 tem = Fmake_vector (make_number (n_windows), Qnil);
5811 data->saved_windows = tem;
5812 for (i = 0; i < n_windows; i++)
5813 XVECTOR (tem)->contents[i]
5814 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
a1d58e5b 5815 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
74112613 5816 XSETWINDOW_CONFIGURATION (tem, data);
7ab12479
JB
5817 return (tem);
5818}
5819
5820DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
fdb82f93
PJ
5821 0, UNEVALLED, 0,
5822 doc: /* Execute body, preserving window sizes and contents.
5823Restore which buffer appears in which window, where display starts,
5824and the value of point and mark for each window.
5825Also restore the choice of selected window.
5826Also restore which buffer is current.
6924dda6
MB
5827Does not restore the value of point in current buffer.
5828usage: (save-window-excursion BODY ...) */)
fdb82f93 5829 (args)
7ab12479
JB
5830 Lisp_Object args;
5831{
5832 register Lisp_Object val;
aed13378 5833 register int count = SPECPDL_INDEX ();
7ab12479
JB
5834
5835 record_unwind_protect (Fset_window_configuration,
43bad991 5836 Fcurrent_window_configuration (Qnil));
7ab12479
JB
5837 val = Fprogn (args);
5838 return unbind_to (count, val);
5839}
5500c422
GM
5840
5841\f
5842/***********************************************************************
5843 Marginal Areas
5844 ***********************************************************************/
5845
5846DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
a7bdfc08 5847 2, 3, 0,
fdb82f93
PJ
5848 doc: /* Set width of marginal areas of window WINDOW.
5849If window is nil, set margins of the currently selected window.
5850First parameter LEFT-WIDTH specifies the number of character
5851cells to reserve for the left marginal area. Second parameter
5852RIGHT-WIDTH does the same for the right marginal area.
5853A nil width parameter means no margin. */)
5854 (window, left, right)
5500c422
GM
5855 Lisp_Object window, left, right;
5856{
5857 struct window *w = decode_window (window);
5500c422 5858
949cf20f
KS
5859 /* TODO: It doesn't make sense to use FLOATs here, since
5860 the rest of the code assumes they are integers.
5861 So don't allow floats! ++KFS */
5862
5500c422 5863 if (!NILP (left))
b7826503 5864 CHECK_NUMBER_OR_FLOAT (left);
5500c422 5865 if (!NILP (right))
b7826503 5866 CHECK_NUMBER_OR_FLOAT (right);
5500c422
GM
5867
5868 /* Check widths < 0 and translate a zero width to nil.
5869 Margins that are too wide have to be checked elsewhere. */
5870 if ((INTEGERP (left) && XINT (left) < 0)
7539e11f 5871 || (FLOATP (left) && XFLOAT_DATA (left) <= 0))
5500c422
GM
5872 XSETFASTINT (left, 0);
5873 if (INTEGERP (left) && XFASTINT (left) == 0)
5874 left = Qnil;
177c0ea7 5875
5500c422 5876 if ((INTEGERP (right) && XINT (right) < 0)
7539e11f 5877 || (FLOATP (right) && XFLOAT_DATA (right) <= 0))
5500c422
GM
5878 XSETFASTINT (right, 0);
5879 if (INTEGERP (right) && XFASTINT (right) == 0)
5880 right = Qnil;
5881
949cf20f
KS
5882 if (!EQ (w->left_margin_cols, left)
5883 || !EQ (w->right_margin_cols, right))
5884 {
5885 w->left_margin_cols = left;
5886 w->right_margin_cols = right;
5887
5888 adjust_window_margins (w);
5889
5890 ++windows_or_buffers_changed;
5891 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5892 }
5500c422 5893
5500c422
GM
5894 return Qnil;
5895}
5896
5897
5898DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
5899 0, 1, 0,
fdb82f93
PJ
5900 doc: /* Get width of marginal areas of window WINDOW.
5901If WINDOW is omitted or nil, use the currently selected window.
5902Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
5903If a marginal area does not exist, its width will be returned
5904as nil. */)
5905 (window)
5500c422
GM
5906 Lisp_Object window;
5907{
5908 struct window *w = decode_window (window);
949cf20f
KS
5909 return Fcons (w->left_margin_cols, w->right_margin_cols);
5910}
5911
5912
5913\f
5914/***********************************************************************
5915 Fringes
5916 ***********************************************************************/
5917
5918DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
5919 2, 4, 0,
5920 doc: /* Set width of fringes of window WINDOW.
5921
5922If window is nil, set fringes of the currently selected window.
5923Second parameter LEFT-WIDTH specifies the number of pixels to reserve
5924for the left fringe. Third parameter RIGHT-WIDTH does the same for
79fd290e 5925the right fringe. Fourth parameter OUTSIDE-MARGINS non-nil specifies
949cf20f
KS
5926that fringes are drawn outside of the display margins; by default, fringes
5927are drawn between display marginal areas and the text area.
154b6114
LK
5928A nil width parameter means to use the frame's default fringe width;
5929default fringe widths can be set with the command `set-fringe-style'. */)
949cf20f
KS
5930 (window, left, right, outside_margins)
5931 Lisp_Object window, left, right, outside_margins;
5932{
5933 struct window *w = decode_window (window);
5934
5935 if (!NILP (left))
5936 CHECK_NUMBER (left);
5937 if (!NILP (right))
5938 CHECK_NUMBER (right);
5939
5940 if (!EQ (w->left_fringe_width, left)
5941 || !EQ (w->right_fringe_width, right)
5942 || !EQ (w->fringes_outside_margins, outside_margins))
5943 {
5944 w->left_fringe_width = left;
5945 w->right_fringe_width = right;
5946 w->fringes_outside_margins = outside_margins;
5947
5948 adjust_window_margins (w);
5949
5950 clear_glyph_matrix (w->current_matrix);
5951 w->window_end_valid = Qnil;
5952
5953 ++windows_or_buffers_changed;
5954 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5955 }
5956
5957 return Qnil;
5958}
5959
5960
5961DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
5962 0, 1, 0,
5963 doc: /* Get width of fringes of window WINDOW.
5964If WINDOW is omitted or nil, use the currently selected window.
5965Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS).
5966If a window specific fringe width is not set, its width will be returned
5967as nil. */)
5968 (window)
5969 Lisp_Object window;
5970{
5971 struct window *w = decode_window (window);
5972 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
5973 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
5974 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ?
5975 Qt : Qnil), Qnil)));
5976}
5977
5978
5979\f
5980/***********************************************************************
5981 Scroll bars
5982 ***********************************************************************/
5983
5984DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
5985 2, 4, 0,
5986 doc: /* Set width and type of scroll bars of window WINDOW.
5987If window is nil, set scroll bars of the currently selected window.
5988Second parameter WIDTH specifies the pixel width for the scroll bar;
5989this is automatically adjusted to a multiple of the frame column width.
5990Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
5991bar: left, right, or nil.
2f71b5ea
MY
5992If WIDTH is nil, use the frame's scroll-bar width.
5993If TYPE is t, use the frame's scroll-bar type. */)
79fd290e
JB
5994 (window, width, vertical_type, horizontal_type)
5995 Lisp_Object window, width, vertical_type, horizontal_type;
949cf20f
KS
5996{
5997 struct window *w = decode_window (window);
5998
5999 if (!NILP (width))
6000 CHECK_NUMBER (width);
6001
6002 if (XINT (width) == 0)
6003 vertical_type = Qnil;
6004
2f71b5ea
MY
6005 if (!(EQ (vertical_type, Qnil)
6006 || EQ (vertical_type, Qleft)
6007 || EQ (vertical_type, Qright)
6008 || EQ (vertical_type, Qt)))
6009 error ("Invalid type of vertical scroll bar");
6010
949cf20f
KS
6011 if (!EQ (w->scroll_bar_width, width)
6012 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6013 {
6014 w->scroll_bar_width = width;
6015 w->vertical_scroll_bar_type = vertical_type;
6016
6017 adjust_window_margins (w);
6018
6019 clear_glyph_matrix (w->current_matrix);
6020 w->window_end_valid = Qnil;
6021
6022 ++windows_or_buffers_changed;
6023 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6024 }
6025
6026 return Qnil;
6027}
6028
6029
6030DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6031 0, 1, 0,
6032 doc: /* Get width and type of scroll bars of window WINDOW.
6033If WINDOW is omitted or nil, use the currently selected window.
12853c58
KS
6034Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6035If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6036value. */)
949cf20f
KS
6037 (window)
6038 Lisp_Object window;
6039{
6040 struct window *w = decode_window (window);
6041 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6042 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6043 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6044 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6045 Fcons (w->vertical_scroll_bar_type,
6046 Fcons (Qnil, Qnil))));
5500c422
GM
6047}
6048
6049
7ab12479 6050\f
5500c422
GM
6051/***********************************************************************
6052 Smooth scrolling
6053 ***********************************************************************/
6054
6055DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
fdb82f93
PJ
6056 doc: /* Return the amount by which WINDOW is scrolled vertically.
6057Use the selected window if WINDOW is nil or omitted.
6058Value is a multiple of the canonical character height of WINDOW. */)
6059 (window)
5500c422
GM
6060 Lisp_Object window;
6061{
47004952 6062 Lisp_Object result;
5500c422
GM
6063 struct frame *f;
6064 struct window *w;
177c0ea7 6065
5500c422
GM
6066 if (NILP (window))
6067 window = selected_window;
47004952 6068 else
b7826503 6069 CHECK_WINDOW (window);
5500c422
GM
6070 w = XWINDOW (window);
6071 f = XFRAME (w->frame);
177c0ea7 6072
5500c422 6073 if (FRAME_WINDOW_P (f))
949cf20f 6074 result = FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
5500c422 6075 else
47004952
GM
6076 result = make_number (0);
6077 return result;
5500c422
GM
6078}
6079
6080
6081DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
47004952 6082 2, 2, 0,
fdb82f93 6083 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
b0f906c8
EZ
6084WINDOW nil means use the selected window. VSCROLL is a non-negative
6085multiple of the canonical character height of WINDOW. */)
fdb82f93 6086 (window, vscroll)
47004952 6087 Lisp_Object window, vscroll;
5500c422
GM
6088{
6089 struct window *w;
6090 struct frame *f;
177c0ea7 6091
5500c422
GM
6092 if (NILP (window))
6093 window = selected_window;
47004952 6094 else
b7826503
PJ
6095 CHECK_WINDOW (window);
6096 CHECK_NUMBER_OR_FLOAT (vscroll);
177c0ea7 6097
5500c422
GM
6098 w = XWINDOW (window);
6099 f = XFRAME (w->frame);
6100
6101 if (FRAME_WINDOW_P (f))
6102 {
6103 int old_dy = w->vscroll;
177c0ea7 6104
949cf20f 6105 w->vscroll = - FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll);
47004952 6106 w->vscroll = min (w->vscroll, 0);
5500c422
GM
6107
6108 /* Adjust glyph matrix of the frame if the virtual display
6109 area becomes larger than before. */
6110 if (w->vscroll < 0 && w->vscroll < old_dy)
6111 adjust_glyphs (f);
177c0ea7 6112
5500c422 6113 /* Prevent redisplay shortcuts. */
b1599b4c 6114 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5500c422 6115 }
177c0ea7 6116
47004952 6117 return Fwindow_vscroll (window);
5500c422 6118}
177c0ea7 6119
7bbb5782
GM
6120\f
6121/* Call FN for all leaf windows on frame F. FN is called with the
6122 first argument being a pointer to the leaf window, and with
f95464e4 6123 additional argument USER_DATA. Stops when FN returns 0. */
7bbb5782
GM
6124
6125void
f95464e4 6126foreach_window (f, fn, user_data)
7bbb5782 6127 struct frame *f;
f95464e4
GM
6128 int (* fn) P_ ((struct window *, void *));
6129 void *user_data;
7bbb5782 6130{
f95464e4 6131 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
7bbb5782
GM
6132}
6133
6134
6135/* Helper function for foreach_window. Call FN for all leaf windows
6136 reachable from W. FN is called with the first argument being a
f95464e4 6137 pointer to the leaf window, and with additional argument USER_DATA.
67492200 6138 Stop when FN returns 0. Value is 0 if stopped by FN. */
7bbb5782 6139
67492200 6140static int
f95464e4 6141foreach_window_1 (w, fn, user_data)
7bbb5782 6142 struct window *w;
f95464e4
GM
6143 int (* fn) P_ ((struct window *, void *));
6144 void *user_data;
7bbb5782 6145{
67492200 6146 int cont;
177c0ea7 6147
67492200 6148 for (cont = 1; w && cont;)
7bbb5782
GM
6149 {
6150 if (!NILP (w->hchild))
f95464e4 6151 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
7bbb5782 6152 else if (!NILP (w->vchild))
f95464e4 6153 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
177c0ea7 6154 else
0f532a9a 6155 cont = fn (w, user_data);
177c0ea7 6156
7bbb5782
GM
6157 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6158 }
67492200
GM
6159
6160 return cont;
7bbb5782
GM
6161}
6162
6163
6d194a45 6164/* Freeze or unfreeze the window start of W unless it is a
f95464e4 6165 mini-window or the selected window. FREEZE_P non-null means freeze
7bbb5782
GM
6166 the window start. */
6167
67492200 6168static int
7bbb5782
GM
6169freeze_window_start (w, freeze_p)
6170 struct window *w;
f95464e4 6171 void *freeze_p;
7bbb5782
GM
6172{
6173 if (w == XWINDOW (selected_window)
6174 || MINI_WINDOW_P (w)
6175 || (MINI_WINDOW_P (XWINDOW (selected_window))
24d744ac 6176 && ! NILP (Vminibuf_scroll_window)
7bbb5782 6177 && w == XWINDOW (Vminibuf_scroll_window)))
f95464e4 6178 freeze_p = NULL;
177c0ea7 6179
f95464e4 6180 w->frozen_window_start_p = freeze_p != NULL;
67492200 6181 return 1;
7bbb5782
GM
6182}
6183
6184
6185/* Freeze or unfreeze the window starts of all leaf windows on frame
6186 F, except the selected window and a mini-window. FREEZE_P non-zero
6187 means freeze the window start. */
6188
6189void
6190freeze_window_starts (f, freeze_p)
6191 struct frame *f;
6192 int freeze_p;
6193{
cbccabec 6194 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
7bbb5782 6195}
5500c422
GM
6196
6197\f
6198/***********************************************************************
6199 Initialization
6200 ***********************************************************************/
6201
cbff28e8
RS
6202/* Return 1 if window configurations C1 and C2
6203 describe the same state of affairs. This is used by Fequal. */
6204
6205int
2f8274be 6206compare_window_configurations (c1, c2, ignore_positions)
cbff28e8 6207 Lisp_Object c1, c2;
2f8274be 6208 int ignore_positions;
cbff28e8
RS
6209{
6210 register struct save_window_data *d1, *d2;
6211 struct Lisp_Vector *sw1, *sw2;
6212 int i;
6213
4d3edcb4
GM
6214 if (!WINDOW_CONFIGURATIONP (c1))
6215 wrong_type_argument (Qwindow_configuration_p, c1);
6216 if (!WINDOW_CONFIGURATIONP (c2))
6217 wrong_type_argument (Qwindow_configuration_p, c2);
177c0ea7 6218
cbff28e8
RS
6219 d1 = (struct save_window_data *) XVECTOR (c1);
6220 d2 = (struct save_window_data *) XVECTOR (c2);
6221 sw1 = XVECTOR (d1->saved_windows);
6222 sw2 = XVECTOR (d2->saved_windows);
6223
949cf20f 6224 if (! EQ (d1->frame_cols, d2->frame_cols))
cbff28e8 6225 return 0;
949cf20f 6226 if (! EQ (d1->frame_lines, d2->frame_lines))
cbff28e8
RS
6227 return 0;
6228 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
6229 return 0;
6230 if (! EQ (d1->selected_frame, d2->selected_frame))
6231 return 0;
6232 /* Don't compare the current_window field directly.
6233 Instead see w1_is_current and w2_is_current, below. */
6234 if (! EQ (d1->current_buffer, d2->current_buffer))
6235 return 0;
2f8274be 6236 if (! ignore_positions)
3f49fddc
KS
6237 {
6238 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
6239 return 0;
6240 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
6241 return 0;
6242 }
cbff28e8
RS
6243 /* Don't compare the root_window field.
6244 We don't require the two configurations
6245 to use the same window object,
6246 and the two root windows must be equivalent
6247 if everything else compares equal. */
6248 if (! EQ (d1->focus_frame, d2->focus_frame))
6249 return 0;
6250 if (! EQ (d1->min_width, d2->min_width))
6251 return 0;
6252 if (! EQ (d1->min_height, d2->min_height))
6253 return 0;
6254
6255 /* Verify that the two confis have the same number of windows. */
6256 if (sw1->size != sw2->size)
6257 return 0;
6258
6259 for (i = 0; i < sw1->size; i++)
6260 {
6261 struct saved_window *p1, *p2;
6262 int w1_is_current, w2_is_current;
6263
6264 p1 = SAVED_WINDOW_N (sw1, i);
6265 p2 = SAVED_WINDOW_N (sw2, i);
6266
6267 /* Verify that the current windows in the two
6268 configurations correspond to each other. */
6269 w1_is_current = EQ (d1->current_window, p1->window);
6270 w2_is_current = EQ (d2->current_window, p2->window);
6271
6272 if (w1_is_current != w2_is_current)
6273 return 0;
6274
6275 /* Verify that the corresponding windows do match. */
6276 if (! EQ (p1->buffer, p2->buffer))
6277 return 0;
949cf20f 6278 if (! EQ (p1->left_col, p2->left_col))
cbff28e8 6279 return 0;
949cf20f 6280 if (! EQ (p1->top_line, p2->top_line))
cbff28e8 6281 return 0;
949cf20f 6282 if (! EQ (p1->total_cols, p2->total_cols))
cbff28e8 6283 return 0;
949cf20f 6284 if (! EQ (p1->total_lines, p2->total_lines))
cbff28e8 6285 return 0;
cbff28e8
RS
6286 if (! EQ (p1->display_table, p2->display_table))
6287 return 0;
6288 if (! EQ (p1->parent, p2->parent))
6289 return 0;
6290 if (! EQ (p1->prev, p2->prev))
6291 return 0;
2f8274be
RS
6292 if (! ignore_positions)
6293 {
6294 if (! EQ (p1->hscroll, p2->hscroll))
6295 return 0;
ea68264b
GM
6296 if (!EQ (p1->min_hscroll, p2->min_hscroll))
6297 return 0;
2f8274be
RS
6298 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
6299 return 0;
6300 if (NILP (Fequal (p1->start, p2->start)))
6301 return 0;
6302 if (NILP (Fequal (p1->pointm, p2->pointm)))
6303 return 0;
6304 if (NILP (Fequal (p1->mark, p2->mark)))
6305 return 0;
6306 }
949cf20f
KS
6307 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
6308 return 0;
6309 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
6310 return 0;
6311 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
6312 return 0;
6313 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
6314 return 0;
6315 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
6316 return 0;
6317 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
6318 return 0;
6319 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
6320 return 0;
cbff28e8
RS
6321 }
6322
6323 return 1;
6324}
2f8274be
RS
6325
6326DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6327 Scompare_window_configurations, 2, 2, 0,
fdb82f93
PJ
6328 doc: /* Compare two window configurations as regards the structure of windows.
6329This function ignores details such as the values of point and mark
6330and scrolling positions. */)
6331 (x, y)
2f8274be
RS
6332 Lisp_Object x, y;
6333{
6334 if (compare_window_configurations (x, y, 1))
6335 return Qt;
6336 return Qnil;
6337}
cbff28e8 6338\f
dfcf069d 6339void
7ab12479
JB
6340init_window_once ()
6341{
1ae1a37d
GM
6342 struct frame *f = make_terminal_frame ();
6343 XSETFRAME (selected_frame, f);
6344 Vterminal_frame = selected_frame;
6345 minibuf_window = f->minibuffer_window;
6346 selected_window = f->selected_window;
6347 last_nonminibuf_frame = f;
5b03d3c0
RS
6348
6349 window_initialized = 1;
7ab12479
JB
6350}
6351
67492200
GM
6352void
6353init_window ()
6354{
6355 Vwindow_list = Qnil;
6356}
6357
dfcf069d 6358void
7ab12479
JB
6359syms_of_window ()
6360{
8a37516b
GM
6361 Qwindow_size_fixed = intern ("window-size-fixed");
6362 staticpro (&Qwindow_size_fixed);
177c0ea7 6363
543f5fb1
RS
6364 staticpro (&Qwindow_configuration_change_hook);
6365 Qwindow_configuration_change_hook
6366 = intern ("window-configuration-change-hook");
6367
7ab12479
JB
6368 Qwindowp = intern ("windowp");
6369 staticpro (&Qwindowp);
6370
3f8ab7bd
RS
6371 Qwindow_configuration_p = intern ("window-configuration-p");
6372 staticpro (&Qwindow_configuration_p);
6373
806b4d9b
JB
6374 Qwindow_live_p = intern ("window-live-p");
6375 staticpro (&Qwindow_live_p);
605be8af 6376
2cccc823 6377 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
a58ec57d
RS
6378 staticpro (&Qtemp_buffer_show_hook);
6379
67492200 6380 staticpro (&Vwindow_list);
8bfb170b
KS
6381
6382 minibuf_selected_window = Qnil;
3dbab091 6383 staticpro (&minibuf_selected_window);
67492200 6384
7ab12479 6385 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
fdb82f93
PJ
6386 doc: /* Non-nil means call as function to display a help buffer.
6387The function is called with one argument, the buffer to be displayed.
6388Used by `with-output-to-temp-buffer'.
6389If this function is used, then it must do the entire job of showing
6390the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7ab12479
JB
6391 Vtemp_buffer_show_function = Qnil;
6392
6393 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
fdb82f93
PJ
6394 doc: /* If non-nil, function to call to handle `display-buffer'.
6395It will receive two args, the buffer and a flag which if non-nil means
6396 that the currently selected window is not acceptable.
6397Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
6398work using this function. */);
7ab12479
JB
6399 Vdisplay_buffer_function = Qnil;
6400
6529ed87 6401 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
fdb82f93
PJ
6402 doc: /* *If non-nil, `display-buffer' should even the window heights.
6403If nil, `display-buffer' will leave the window configuration alone. */);
6529ed87
GM
6404 Veven_window_heights = Qt;
6405
7ab12479 6406 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
fdb82f93 6407 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7ab12479
JB
6408 Vminibuf_scroll_window = Qnil;
6409
cc91894c 6410 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
26124d5e 6411 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
cc91894c
KS
6412If the minibuffer is active, the `minibuffer-scroll-window' mode line
6413is displayed in the `mode-line' face. */);
6414 mode_line_in_non_selected_windows = 1;
26124d5e 6415
7ab12479 6416 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
fdb82f93 6417 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7ab12479
JB
6418 Vother_window_scroll_buffer = Qnil;
6419
44fa5b1e 6420 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
fdb82f93 6421 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
44fa5b1e 6422 pop_up_frames = 0;
7ab12479 6423
9c3da604 6424 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
fdb82f93
PJ
6425 doc: /* *Non-nil means `display-buffer' should reuse frames.
6426If the buffer in question is already displayed in a frame, raise that frame. */);
9c3da604
GM
6427 display_buffer_reuse_frames = 0;
6428
44fa5b1e 6429 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
fdb82f93
PJ
6430 doc: /* Function to call to handle automatic new frame creation.
6431It is called with no arguments and should return a newly created frame.
6432
6433A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
6434where `pop-up-frame-alist' would hold the default frame parameters. */);
44fa5b1e 6435 Vpop_up_frame_function = Qnil;
7ab12479 6436
a90712c2 6437 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
fdb82f93
PJ
6438 doc: /* *List of buffer names that should have their own special frames.
6439Displaying a buffer whose name is in this list makes a special frame for it
6440using `special-display-function'. See also `special-display-regexps'.
6441
6442An element of the list can be a list instead of just a string.
6443There are two ways to use a list as an element:
6444 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
6445In the first case, FRAME-PARAMETERS are used to create the frame.
6446In the latter case, FUNCTION is called with BUFFER as the first argument,
6447followed by OTHER-ARGS--it can display BUFFER in any way it likes.
6448All this is done by the function found in `special-display-function'.
6449
6450If this variable appears \"not to work\", because you add a name to it
6451but that buffer still appears in the selected window, look at the
6452values of `same-window-buffer-names' and `same-window-regexps'.
6453Those variables take precedence over this one. */);
a90712c2
RS
6454 Vspecial_display_buffer_names = Qnil;
6455
6456 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
fdb82f93
PJ
6457 doc: /* *List of regexps saying which buffers should have their own special frames.
6458If a buffer name matches one of these regexps, it gets its own frame.
6459Displaying a buffer whose name is in this list makes a special frame for it
6460using `special-display-function'.
6461
6462An element of the list can be a list instead of just a string.
6463There are two ways to use a list as an element:
6464 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
6465In the first case, FRAME-PARAMETERS are used to create the frame.
6466In the latter case, FUNCTION is called with the buffer as first argument,
6467followed by OTHER-ARGS--it can display the buffer in any way it likes.
6468All this is done by the function found in `special-display-function'.
6469
6470If this variable appears \"not to work\", because you add a regexp to it
6471but the matching buffers still appear in the selected window, look at the
6472values of `same-window-buffer-names' and `same-window-regexps'.
6473Those variables take precedence over this one. */);
a90712c2
RS
6474 Vspecial_display_regexps = Qnil;
6475
6476 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
fdb82f93
PJ
6477 doc: /* Function to call to make a new frame for a special buffer.
6478It is called with two arguments, the buffer and optional buffer specific
6479data, and should return a window displaying that buffer.
a5731348
SM
6480The default value normally makes a separate frame for the buffer,
6481 using `special-display-frame-alist' to specify the frame parameters.
6482But if the buffer specific data includes (same-buffer . t) then the
6483 buffer is displayed in the current selected window.
6484Otherwise if it includes (same-frame . t) then the buffer is displayed in
6485 a new window in the currently selected frame.
6486
6487A buffer is special if it is listed in `special-display-buffer-names'
fdb82f93 6488or matches a regexp in `special-display-regexps'. */);
a90712c2
RS
6489 Vspecial_display_function = Qnil;
6490
855d8627 6491 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
fdb82f93
PJ
6492 doc: /* *List of buffer names that should appear in the selected window.
6493Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
6494switches to it in the selected window, rather than making it appear
6495in some other window.
6496
6497An element of the list can be a cons cell instead of just a string.
6498Then the car must be a string, which specifies the buffer name.
6499This is for compatibility with `special-display-buffer-names';
6500the cdr of the cons cell is ignored.
6501
6502See also `same-window-regexps'. */);
855d8627
RS
6503 Vsame_window_buffer_names = Qnil;
6504
6505 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
fdb82f93
PJ
6506 doc: /* *List of regexps saying which buffers should appear in the selected window.
6507If a buffer name matches one of these regexps, then displaying it
6508using `display-buffer' or `pop-to-buffer' switches to it
6509in the selected window, rather than making it appear in some other window.
6510
6511An element of the list can be a cons cell instead of just a string.
6512Then the car must be a string, which specifies the buffer name.
6513This is for compatibility with `special-display-buffer-names';
6514the cdr of the cons cell is ignored.
6515
6516See also `same-window-buffer-names'. */);
855d8627
RS
6517 Vsame_window_regexps = Qnil;
6518
7ab12479 6519 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
fdb82f93 6520 doc: /* *Non-nil means display-buffer should make new windows. */);
7ab12479
JB
6521 pop_up_windows = 1;
6522
6523 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
fdb82f93 6524 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
7ab12479
JB
6525 next_screen_context_lines = 2;
6526
6527 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
fdb82f93
PJ
6528 doc: /* *display-buffer would prefer to split the largest window if this large.
6529If there is only one window, it is split regardless of this value. */);
7ab12479
JB
6530 split_height_threshold = 500;
6531
6532 DEFVAR_INT ("window-min-height", &window_min_height,
fdb82f93 6533 doc: /* *Delete any window less than this tall (including its mode line). */);
7ab12479
JB
6534 window_min_height = 4;
6535
6536 DEFVAR_INT ("window-min-width", &window_min_width,
fdb82f93 6537 doc: /* *Delete any window less than this wide. */);
7ab12479
JB
6538 window_min_width = 10;
6539
5500c422
GM
6540 DEFVAR_LISP ("scroll-preserve-screen-position",
6541 &Vscroll_preserve_screen_position,
fdb82f93 6542 doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged. */);
5500c422 6543 Vscroll_preserve_screen_position = Qnil;
9317a85d 6544
543f5fb1
RS
6545 DEFVAR_LISP ("window-configuration-change-hook",
6546 &Vwindow_configuration_change_hook,
fdb82f93
PJ
6547 doc: /* Functions to call when window configuration changes.
6548The selected frame is the one whose configuration has changed. */);
543f5fb1
RS
6549 Vwindow_configuration_change_hook = Qnil;
6550
b0b7ed0e 6551 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed,
fdb82f93
PJ
6552 doc: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
6553Emacs won't change the size of any window displaying that buffer,
6554unless you explicitly change the size, or Emacs has no other choice.
6555This variable automatically becomes buffer-local when set. */);
b0b7ed0e
GM
6556 Fmake_variable_buffer_local (Qwindow_size_fixed);
6557 window_size_fixed = 0;
6558
7ab12479
JB
6559 defsubr (&Sselected_window);
6560 defsubr (&Sminibuffer_window);
6561 defsubr (&Swindow_minibuffer_p);
6562 defsubr (&Swindowp);
806b4d9b 6563 defsubr (&Swindow_live_p);
7ab12479
JB
6564 defsubr (&Spos_visible_in_window_p);
6565 defsubr (&Swindow_buffer);
6566 defsubr (&Swindow_height);
6567 defsubr (&Swindow_width);
6568 defsubr (&Swindow_hscroll);
6569 defsubr (&Sset_window_hscroll);
190eb263
RS
6570 defsubr (&Swindow_redisplay_end_trigger);
6571 defsubr (&Sset_window_redisplay_end_trigger);
7ab12479 6572 defsubr (&Swindow_edges);
c99a9eb3
RS
6573 defsubr (&Swindow_pixel_edges);
6574 defsubr (&Swindow_inside_edges);
6575 defsubr (&Swindow_inside_pixel_edges);
d5783c40
JB
6576 defsubr (&Scoordinates_in_window_p);
6577 defsubr (&Swindow_at);
7ab12479
JB
6578 defsubr (&Swindow_point);
6579 defsubr (&Swindow_start);
6580 defsubr (&Swindow_end);
6581 defsubr (&Sset_window_point);
6582 defsubr (&Sset_window_start);
6583 defsubr (&Swindow_dedicated_p);
d207b766 6584 defsubr (&Sset_window_dedicated_p);
7ab12479
JB
6585 defsubr (&Swindow_display_table);
6586 defsubr (&Sset_window_display_table);
6587 defsubr (&Snext_window);
6588 defsubr (&Sprevious_window);
6589 defsubr (&Sother_window);
6590 defsubr (&Sget_lru_window);
6591 defsubr (&Sget_largest_window);
6592 defsubr (&Sget_buffer_window);
6593 defsubr (&Sdelete_other_windows);
6594 defsubr (&Sdelete_windows_on);
6595 defsubr (&Sreplace_buffer_in_windows);
6596 defsubr (&Sdelete_window);
6597 defsubr (&Sset_window_buffer);
6598 defsubr (&Sselect_window);
4628f7a4
EN
6599 defsubr (&Sspecial_display_p);
6600 defsubr (&Ssame_window_p);
7ab12479
JB
6601 defsubr (&Sdisplay_buffer);
6602 defsubr (&Ssplit_window);
6603 defsubr (&Senlarge_window);
6604 defsubr (&Sshrink_window);
6605 defsubr (&Sscroll_up);
6606 defsubr (&Sscroll_down);
6607 defsubr (&Sscroll_left);
6608 defsubr (&Sscroll_right);
ccd0664b 6609 defsubr (&Sother_window_for_scrolling);
7ab12479 6610 defsubr (&Sscroll_other_window);
fa832261 6611 defsubr (&Sminibuffer_selected_window);
7ab12479 6612 defsubr (&Srecenter);
81fe0836 6613 defsubr (&Swindow_text_height);
7ab12479
JB
6614 defsubr (&Smove_to_window_line);
6615 defsubr (&Swindow_configuration_p);
3f8ab7bd 6616 defsubr (&Swindow_configuration_frame);
7ab12479
JB
6617 defsubr (&Sset_window_configuration);
6618 defsubr (&Scurrent_window_configuration);
6619 defsubr (&Ssave_window_excursion);
5500c422
GM
6620 defsubr (&Sset_window_margins);
6621 defsubr (&Swindow_margins);
949cf20f
KS
6622 defsubr (&Sset_window_fringes);
6623 defsubr (&Swindow_fringes);
6624 defsubr (&Sset_window_scroll_bars);
6625 defsubr (&Swindow_scroll_bars);
5500c422
GM
6626 defsubr (&Swindow_vscroll);
6627 defsubr (&Sset_window_vscroll);
2f8274be 6628 defsubr (&Scompare_window_configurations);
67492200 6629 defsubr (&Swindow_list);
7ab12479
JB
6630}
6631
dfcf069d 6632void
7ab12479
JB
6633keys_of_window ()
6634{
6635 initial_define_key (control_x_map, '1', "delete-other-windows");
6636 initial_define_key (control_x_map, '2', "split-window");
6637 initial_define_key (control_x_map, '0', "delete-window");
6638 initial_define_key (control_x_map, 'o', "other-window");
6639 initial_define_key (control_x_map, '^', "enlarge-window");
6640 initial_define_key (control_x_map, '<', "scroll-left");
6641 initial_define_key (control_x_map, '>', "scroll-right");
6642
6643 initial_define_key (global_map, Ctl ('V'), "scroll-up");
6644 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6645 initial_define_key (meta_map, 'v', "scroll-down");
6646
6647 initial_define_key (global_map, Ctl('L'), "recenter");
6648 initial_define_key (meta_map, 'r', "move-to-window-line");
6649}
ab5796a9
MB
6650
6651/* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
6652 (do not change this comment) */