* frame.el (set-frame-configuration): Don't try to set a frame's
[bpt/emacs.git] / src / window.c
CommitLineData
7ab12479
JB
1/* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
c6c5df7f 3 Copyright (C) 1985, 1986, 1987, 1993 Free Software Foundation, Inc.
7ab12479
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
1113d9db 9the Free Software Foundation; either version 2, or (at your option)
7ab12479
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
7ab12479
JB
21#include "config.h"
22#include "lisp.h"
23#include "buffer.h"
44fa5b1e 24#include "frame.h"
7ab12479
JB
25#include "window.h"
26#include "commands.h"
27#include "indent.h"
28#include "termchar.h"
29#include "disptab.h"
f8026fd8 30#include "keyboard.h"
7ab12479 31
806b4d9b 32Lisp_Object Qwindowp, Qwindow_live_p;
7ab12479
JB
33
34Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
35Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
36
fd482be5 37void delete_all_subwindows ();
7ab12479
JB
38static struct window *decode_window();
39
40/* This is the window in which the terminal's cursor should
41 be left when nothing is being done with it. This must
42 always be a leaf window, and its buffer is selected by
43 the top level editing loop at the end of each command.
44
45 This value is always the same as
44fa5b1e 46 FRAME_SELECTED_WINDOW (selected_frame). */
7ab12479
JB
47
48Lisp_Object selected_window;
49
44fa5b1e 50/* The minibuffer window of the selected frame.
7ab12479
JB
51 Note that you cannot test for minibufferness of an arbitrary window
52 by comparing against this; but you can test for minibufferness of
53 the selected window. */
54Lisp_Object minibuf_window;
55
56/* Non-nil means it is the window for C-M-v to scroll
57 when the minibuffer is selected. */
58Lisp_Object Vminibuf_scroll_window;
59
60/* Non-nil means this is the buffer whose window C-M-v should scroll. */
61Lisp_Object Vother_window_scroll_buffer;
62
7ab12479
JB
63/* Non-nil means it's function to call to display temp buffers. */
64Lisp_Object Vtemp_buffer_show_function;
65
66/* If a window gets smaller than either of these, it is removed. */
67int window_min_height;
68int window_min_width;
69
70/* Nonzero implies Fdisplay_buffer should create windows. */
71int pop_up_windows;
72
44fa5b1e
JB
73/* Nonzero implies make new frames for Fdisplay_buffer. */
74int pop_up_frames;
7ab12479
JB
75
76/* Non-nil means use this function instead of default */
44fa5b1e 77Lisp_Object Vpop_up_frame_function;
7ab12479
JB
78
79/* Function to call to handle Fdisplay_buffer. */
80Lisp_Object Vdisplay_buffer_function;
81
82/* Fdisplay_buffer always splits the largest window
83 if that window is more than this high. */
84int split_height_threshold;
85
86/* Number of lines of continuity in scrolling by screenfuls. */
87int next_screen_context_lines;
88
89/* Incremented for each window created. */
90static int sequence_number;
91
92#define min(a, b) ((a) < (b) ? (a) : (b))
93\f
94DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
95 "Returns t if OBJ is a window.")
96 (obj)
97 Lisp_Object obj;
98{
99 return XTYPE (obj) == Lisp_Window ? Qt : Qnil;
100}
101
806b4d9b 102DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
605be8af
JB
103 "Returns t if OBJ is a window which is currently visible.")
104 (obj)
105 Lisp_Object obj;
106{
107 return ((XTYPE (obj) == Lisp_Window
108 && ! NILP (XWINDOW (obj)->buffer))
109 ? Qt : Qnil);
110}
111
7ab12479
JB
112Lisp_Object
113make_window ()
114{
115 register Lisp_Object val;
116 register struct window *p;
117
118 /* Add sizeof (Lisp_Object) here because sizeof (struct Lisp_Vector)
119 includes the first element. */
120 val = Fmake_vector (
121 make_number ((sizeof (struct window) - sizeof (struct Lisp_Vector)
122 + sizeof (Lisp_Object))
123 / sizeof (Lisp_Object)),
124 Qnil);
125 XSETTYPE (val, Lisp_Window);
126 p = XWINDOW (val);
127 XFASTINT (p->sequence_number) = ++sequence_number;
128 XFASTINT (p->left) = XFASTINT (p->top)
129 = XFASTINT (p->height) = XFASTINT (p->width)
130 = XFASTINT (p->hscroll) = 0;
131 XFASTINT (p->last_point_x) = XFASTINT (p->last_point_y) = 0;
132 p->start = Fmake_marker ();
133 p->pointm = Fmake_marker ();
134 XFASTINT (p->use_time) = 0;
44fa5b1e 135 p->frame = Qnil;
7ab12479
JB
136 p->display_table = Qnil;
137 p->dedicated = Qnil;
138 return val;
139}
140
141DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
142 "Return the window that the cursor now appears in and commands apply to.")
143 ()
144{
145 return selected_window;
146}
147
83762ba4
JB
148DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
149 "Return the window used now for minibuffers.\n\
150If the optional argument FRAME is specified, return the minibuffer window\n\
151used by that frame.")
152 (frame)
153 Lisp_Object frame;
7ab12479 154{
44fa5b1e 155#ifdef MULTI_FRAME
83762ba4
JB
156 if (NILP (frame))
157 XSET (frame, Lisp_Frame, selected_frame);
158 else
159 CHECK_LIVE_FRAME (frame, 0);
160#endif
161
162 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
7ab12479
JB
163}
164
605be8af 165DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
7ab12479
JB
166 "Returns non-nil if WINDOW is a minibuffer window.")
167 (window)
168 Lisp_Object window;
169{
170 struct window *w = decode_window (window);
171 return (MINI_WINDOW_P (w) ? Qt : Qnil);
172}
173
174DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
175 Spos_visible_in_window_p, 0, 2, 0,
44fa5b1e 176 "Return t if position POS is currently on the frame in WINDOW.\n\
7ab12479
JB
177Returns nil if that position is scrolled vertically out of view.\n\
178POS defaults to point; WINDOW, to the selected window.")
179 (pos, window)
180 Lisp_Object pos, window;
181{
182 register struct window *w;
183 register int top;
184 register int height;
185 register int posint;
186 register struct buffer *buf;
187 struct position posval;
188
265a9e55 189 if (NILP (pos))
7ab12479
JB
190 posint = point;
191 else
192 {
193 CHECK_NUMBER_COERCE_MARKER (pos, 0);
194 posint = XINT (pos);
195 }
196
605be8af 197 w = decode_window (window);
7ab12479
JB
198 top = marker_position (w->start);
199
200 if (posint < top)
201 return Qnil;
202
203 height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
204
205 buf = XBUFFER (w->buffer);
206 if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf))
207 {
44fa5b1e 208 /* If frame is up to date,
7ab12479
JB
209 use the info recorded about how much text fit on it. */
210 if (posint < BUF_Z (buf) - XFASTINT (w->window_end_pos)
211 || (XFASTINT (w->window_end_vpos) < height))
212 return Qt;
213 return Qnil;
214 }
215 else
216 {
217 if (posint > BUF_Z (buf))
218 return Qnil;
219
220 /* If that info is not correct, calculate afresh */
221 posval = *compute_motion (top, 0, 0, posint, height, 0,
535e0b8e 222 window_internal_width (w) - 1,
7ab12479
JB
223 XINT (w->hscroll), 0);
224
225 return posval.vpos < height ? Qt : Qnil;
226 }
227}
228\f
229static struct window *
230decode_window (window)
231 register Lisp_Object window;
232{
265a9e55 233 if (NILP (window))
7ab12479
JB
234 return XWINDOW (selected_window);
235
605be8af 236 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
237 return XWINDOW (window);
238}
239
240DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
241 "Return the buffer that WINDOW is displaying.")
242 (window)
243 Lisp_Object window;
244{
245 return decode_window (window)->buffer;
246}
247
248DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
249 "Return the number of lines in WINDOW (including its mode line).")
250 (window)
251 Lisp_Object window;
252{
253 return decode_window (window)->height;
254}
255
256DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
257 "Return the number of columns in WINDOW.")
258 (window)
259 Lisp_Object window;
260{
261 register struct window *w = decode_window (window);
7f4161e0 262 register int width = XFASTINT (w->width);
7ab12479 263
535e0b8e 264 return make_number (window_internal_width (w));
7ab12479
JB
265}
266
267DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
268 "Return the number of columns by which WINDOW is scrolled from left margin.")
269 (window)
270 Lisp_Object window;
271{
272 return decode_window (window)->hscroll;
273}
274
275DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
276 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
277NCOL should be zero or positive.")
278 (window, ncol)
279 register Lisp_Object window, ncol;
280{
281 register struct window *w;
282
283 CHECK_NUMBER (ncol, 1);
284 if (XINT (ncol) < 0) XFASTINT (ncol) = 0;
285 if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1)))
286 args_out_of_range (ncol, Qnil);
287 w = decode_window (window);
7f4161e0 288 if (XINT (w->hscroll) != XINT (ncol))
7ab12479
JB
289 clip_changed = 1; /* Prevent redisplay shortcuts */
290 w->hscroll = ncol;
291 return ncol;
292}
293
294DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
295 "Return a list of the edge coordinates of WINDOW.\n\
44fa5b1e 296\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
7ab12479
JB
297RIGHT is one more than the rightmost column used by WINDOW,\n\
298and BOTTOM is one more than the bottommost row used by WINDOW\n\
299 and its mode-line.")
300 (window)
301 Lisp_Object window;
302{
303 register struct window *w = decode_window (window);
304
305 return Fcons (w->left, Fcons (w->top,
306 Fcons (make_number (XFASTINT (w->left) + XFASTINT (w->width)),
307 Fcons (make_number (XFASTINT (w->top)
308 + XFASTINT (w->height)),
309 Qnil))));
310}
311
d5783c40
JB
312/* Test if the character at column *x, row *y is within window *w.
313 If it is not, return 0;
314 if it is in the window's text area,
315 set *x and *y to its location relative to the upper left corner
316 of the window, and
317 return 1;
318 if it is on the window's modeline, return 2;
319 if it is on the border between the window and its right sibling,
320 return 3. */
321static int
322coordinates_in_window (w, x, y)
323 register struct window *w;
324 register int *x, *y;
325{
326 register int left = XINT (w->left);
327 register int width = XINT (w->width);
328 register int window_height = XINT (w->height);
329 register int top = XFASTINT (w->top);
330
331 if ( *x < left || *x >= left + width
332 || *y < top || *y >= top + window_height)
333 return 0;
334
335 /* Is the character is the mode line? */
336 if (*y == top + window_height - 1
05c2896a 337 && ! MINI_WINDOW_P (w))
d5783c40
JB
338 return 2;
339
340 /* Is the character in the right border? */
341 if (*x == left + width - 1
44fa5b1e 342 && left + width != FRAME_WIDTH (XFRAME (w->frame)))
d5783c40
JB
343 return 3;
344
345 *x -= left;
346 *y -= top;
347 return 1;
348}
349
350DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
351 Scoordinates_in_window_p, 2, 2, 0,
352 "Return non-nil if COORDINATES are in WINDOW.\n\
1113d9db 353COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
44fa5b1e 354measured in characters from the upper-left corner of the frame.\n\
1113d9db 355(0 . 0) denotes the character in the upper left corner of the\n\
44fa5b1e 356frame.\n\
d5783c40
JB
357If COORDINATES are in the text portion of WINDOW,\n\
358 the coordinates relative to the window are returned.\n\
e5d77022 359If they are in the mode line of WINDOW, `mode-line' is returned.\n\
d5783c40 360If they are on the border between WINDOW and its right sibling,\n\
e5d77022 361 `vertical-line' is returned.")
d5783c40
JB
362 (coordinates, window)
363 register Lisp_Object coordinates, window;
364{
365 int x, y;
366
605be8af 367 CHECK_LIVE_WINDOW (window, 0);
d5783c40
JB
368 CHECK_CONS (coordinates, 1);
369 x = XINT (Fcar (coordinates));
370 y = XINT (Fcdr (coordinates));
371
372 switch (coordinates_in_window (XWINDOW (window), &x, &y))
373 {
374 case 0: /* NOT in window at all. */
375 return Qnil;
376
377 case 1: /* In text part of window. */
378 return Fcons (x, y);
379
380 case 2: /* In mode line of window. */
381 return Qmode_line;
382
383 case 3: /* On right border of window. */
e5d77022 384 return Qvertical_line;
d5783c40
JB
385
386 default:
387 abort ();
388 }
389}
390
7ab12479 391/* Find the window containing column x, row y, and return it as a
d5783c40
JB
392 Lisp_Object. If x, y is on the window's modeline, set *part
393 to 1; if it is on the separating line between the window and its
394 right sibling, set it to 2; otherwise set it to 0. If there is no
395 window under x, y return nil and leave *part unmodified. */
7ab12479 396Lisp_Object
44fa5b1e
JB
397window_from_coordinates (frame, x, y, part)
398 FRAME_PTR frame;
7ab12479 399 int x, y;
d5783c40 400 int *part;
7ab12479
JB
401{
402 register Lisp_Object tem, first;
403
44fa5b1e 404 tem = first = FRAME_SELECTED_WINDOW (frame);
7ab12479 405
d5783c40 406 do
7ab12479
JB
407 {
408 int found = coordinates_in_window (XWINDOW (tem), &x, &y);
409
410 if (found)
411 {
d5783c40 412 *part = found - 1;
7ab12479
JB
413 return tem;
414 }
415
d5783c40 416 tem = Fnext_window (tem, Qt, Qlambda);
7ab12479 417 }
d5783c40
JB
418 while (! EQ (tem, first));
419
420 return Qnil;
7ab12479
JB
421}
422
ab17c3f2 423DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
b0c33a94 424 "Return window containing coordinates X and Y on FRAME.\n\
44fa5b1e
JB
425If omitted, FRAME defaults to the currently selected frame.\n\
426The top left corner of the frame is considered to be row 0,\n\
95605e15 427column 0.")
b0c33a94
RS
428 (x, y, frame)
429 Lisp_Object x, y, frame;
7ab12479
JB
430{
431 int part;
432
4b206065 433#ifdef MULTI_FRAME
44fa5b1e
JB
434 if (NILP (frame))
435 XSET (frame, Lisp_Frame, selected_frame);
d5783c40 436 else
44fa5b1e 437 CHECK_LIVE_FRAME (frame, 2);
4b206065 438#endif
b0c33a94
RS
439 CHECK_NUMBER (x, 0);
440 CHECK_NUMBER (y, 1);
7ab12479 441
44fa5b1e 442 return window_from_coordinates (XFRAME (frame),
b0c33a94 443 XINT (x), XINT (y),
7ab12479
JB
444 &part);
445}
446
447DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
448 "Return current value of point in WINDOW.\n\
449For a nonselected window, this is the value point would have\n\
450if that window were selected.\n\
451\n\
452Note that, when WINDOW is the selected window and its buffer\n\
453is also currently selected, the value returned is the same as (point).\n\
454It would be more strictly correct to return the `top-level' value\n\
455of point, outside of any save-excursion forms.\n\
456But that is hard to define.")
457 (window)
458 Lisp_Object window;
459{
460 register struct window *w = decode_window (window);
461
462 if (w == XWINDOW (selected_window)
463 && current_buffer == XBUFFER (w->buffer))
464 return Fpoint ();
465 return Fmarker_position (w->pointm);
466}
467
468DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
469 "Return position at which display currently starts in WINDOW.")
470 (window)
471 Lisp_Object window;
472{
473 return Fmarker_position (decode_window (window)->start);
474}
475
476DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
477 "Return position at which display currently ends in WINDOW.")
478 (window)
479 Lisp_Object window;
480{
481 Lisp_Object value;
482 struct window *w = decode_window (window);
483
484 XSET (value, Lisp_Int,
485 BUF_Z (current_buffer) - XFASTINT (w->window_end_pos));
486
487 return value;
488}
489
490DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
491 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
492 (window, pos)
493 Lisp_Object window, pos;
494{
495 register struct window *w = decode_window (window);
496
497 CHECK_NUMBER_COERCE_MARKER (pos, 1);
498 if (w == XWINDOW (selected_window))
499 Fgoto_char (pos);
500 else
501 set_marker_restricted (w->pointm, pos, w->buffer);
502
503 return pos;
504}
505
506DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
507 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
508Optional third arg NOFORCE non-nil inhibits next redisplay\n\
509from overriding motion of point in order to display at this exact start.")
510 (window, pos, noforce)
511 Lisp_Object window, pos, noforce;
512{
513 register struct window *w = decode_window (window);
514
515 CHECK_NUMBER_COERCE_MARKER (pos, 1);
516 set_marker_restricted (w->start, pos, w->buffer);
517 /* this is not right, but much easier than doing what is right. */
518 w->start_at_line_beg = Qnil;
265a9e55 519 if (NILP (noforce))
7ab12479
JB
520 w->force_start = Qt;
521 w->update_mode_line = Qt;
522 XFASTINT (w->last_modified) = 0;
62c07cc7
JB
523 if (!EQ (window, selected_window))
524 windows_or_buffers_changed++;
7ab12479
JB
525 return pos;
526}
527
528DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
529 1, 1, 0,
530 "Return WINDOW's dedicated object, usually t or nil.\n\
1f18c48f 531See also `set-window-dedicated-p'.")
7ab12479
JB
532 (window)
533 Lisp_Object window;
534{
535 return decode_window (window)->dedicated;
536}
537
d207b766
RS
538DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
539 Sset_window_dedicated_p, 2, 2, 0,
540 "Control whether WINDOW is dedicated to the buffer it displays.\n\
541If it is dedicated, Emacs will not automatically change\n\
542which buffer appears in it.\n\
543The second argument is the new value for the dedication flag;\n\
544non-nil means yes.")
7ab12479
JB
545 (window, arg)
546 Lisp_Object window, arg;
547{
548 register struct window *w = decode_window (window);
549
265a9e55 550 if (NILP (arg))
7ab12479
JB
551 w->dedicated = Qnil;
552 else
d207b766 553 w->dedicated = Qt;
7ab12479
JB
554
555 return w->dedicated;
556}
557
558DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
559 0, 1, 0,
560 "Return the display-table that WINDOW is using.")
561 (window)
562 Lisp_Object window;
563{
564 return decode_window (window)->display_table;
565}
566
567/* Get the display table for use currently on window W.
568 This is either W's display table or W's buffer's display table.
569 Ignore the specified tables if they are not valid;
570 if no valid table is specified, return 0. */
571
572struct Lisp_Vector *
573window_display_table (w)
574 struct window *w;
575{
576 Lisp_Object tem;
577 tem = w->display_table;
578 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
579 return XVECTOR (tem);
580 tem = XBUFFER (w->buffer)->display_table;
581 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
582 return XVECTOR (tem);
583 tem = Vstandard_display_table;
584 if (XTYPE (tem) == Lisp_Vector && XVECTOR (tem)->size == DISP_TABLE_SIZE)
585 return XVECTOR (tem);
586 return 0;
587}
588
3a2712f9 589DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
7ab12479
JB
590 "Set WINDOW's display-table to TABLE.")
591 (window, table)
592 register Lisp_Object window, table;
593{
594 register struct window *w;
595 register Lisp_Object z; /* Return value. */
596
597 w = decode_window (window);
598 w->display_table = table;
599 return table;
600}
601\f
602/* Record info on buffer window w is displaying
603 when it is about to cease to display that buffer. */
604static
605unshow_buffer (w)
606 register struct window *w;
607{
608 Lisp_Object buf = w->buffer;
609
610 if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
611 abort ();
612
613 if (w == XWINDOW (selected_window)
614 || ! EQ (buf, XWINDOW (selected_window)->buffer))
615 /* Do this except when the selected window's buffer
616 is being removed from some other window. */
617 XBUFFER (buf)->last_window_start = marker_position (w->start);
618
619 /* Point in the selected window's buffer
620 is actually stored in that buffer, and the window's pointm isn't used.
621 So don't clobber point in that buffer. */
622 if (! EQ (buf, XWINDOW (selected_window)->buffer))
623 BUF_PT (XBUFFER (buf))
624 = clip_to_bounds (BUF_BEGV (XBUFFER (buf)),
625 marker_position (w->pointm),
626 BUF_ZV (XBUFFER (buf)));
627}
628
629/* Put replacement into the window structure in place of old. */
630static
631replace_window (old, replacement)
632 Lisp_Object old, replacement;
633{
634 register Lisp_Object tem;
635 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
636
44fa5b1e
JB
637 /* If OLD is its frame's root_window, then replacement is the new
638 root_window for that frame. */
7ab12479 639
7f4161e0 640 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
44fa5b1e 641 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
7ab12479
JB
642
643 p->left = o->left;
644 p->top = o->top;
645 p->width = o->width;
646 p->height = o->height;
647
648 p->next = tem = o->next;
265a9e55 649 if (!NILP (tem))
7ab12479
JB
650 XWINDOW (tem)->prev = replacement;
651
652 p->prev = tem = o->prev;
265a9e55 653 if (!NILP (tem))
7ab12479
JB
654 XWINDOW (tem)->next = replacement;
655
656 p->parent = tem = o->parent;
265a9e55 657 if (!NILP (tem))
7ab12479
JB
658 {
659 if (EQ (XWINDOW (tem)->vchild, old))
660 XWINDOW (tem)->vchild = replacement;
661 if (EQ (XWINDOW (tem)->hchild, old))
662 XWINDOW (tem)->hchild = replacement;
663 }
664
665/*** Here, if replacement is a vertical combination
666and so is its new parent, we should make replacement's
667children be children of that parent instead. ***/
668}
669
670DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
671 "Remove WINDOW from the display. Default is selected window.")
672 (window)
673 register Lisp_Object window;
674{
675 register Lisp_Object tem, parent, sib;
676 register struct window *p;
677 register struct window *par;
678
605be8af
JB
679 /* Because this function is called by other C code on non-leaf
680 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
681 so we can't decode_window here. */
265a9e55 682 if (NILP (window))
7ab12479
JB
683 window = selected_window;
684 else
685 CHECK_WINDOW (window, 0);
7ab12479 686 p = XWINDOW (window);
605be8af
JB
687
688 /* It's okay to delete an already-deleted window. */
689 if (NILP (p->buffer)
690 && NILP (p->hchild)
691 && NILP (p->vchild))
692 return Qnil;
693
7ab12479 694 parent = p->parent;
265a9e55 695 if (NILP (parent))
7ab12479
JB
696 error ("Attempt to delete minibuffer or sole ordinary window");
697 par = XWINDOW (parent);
698
699 windows_or_buffers_changed++;
700
605be8af
JB
701 /* Are we trying to delete any frame's selected window? */
702 {
0def0403 703 Lisp_Object frame, pwindow;
605be8af 704
0def0403
RS
705 /* See if the frame's selected window is either WINDOW
706 or any subwindow of it, by finding all that window's parents
707 and comparing each one with WINDOW. */
708 frame = WINDOW_FRAME (XWINDOW (window));
709 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
710
711 while (!NILP (pwindow))
712 {
713 if (EQ (window, pwindow))
714 break;
715 pwindow = XWINDOW (pwindow)->parent;
716 }
717
718 if (EQ (window, pwindow))
605be8af
JB
719 {
720 Lisp_Object alternative = Fnext_window (window, Qlambda, Qnil);
721
722 /* If we're about to delete the selected window on the
723 selected frame, then we should use Fselect_window to select
724 the new window. On the other hand, if we're about to
725 delete the selected window on any other frame, we shouldn't do
726 anything but set the frame's selected_window slot. */
727 if (EQ (window, selected_window))
728 Fselect_window (alternative);
729 else
0def0403 730 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
605be8af
JB
731 }
732 }
7ab12479
JB
733
734 tem = p->buffer;
735 /* tem is null for dummy parent windows
736 (which have inferiors but not any contents themselves) */
265a9e55 737 if (!NILP (tem))
7ab12479
JB
738 {
739 unshow_buffer (p);
740 unchain_marker (p->pointm);
741 unchain_marker (p->start);
7ab12479
JB
742 }
743
744 tem = p->next;
265a9e55 745 if (!NILP (tem))
7ab12479
JB
746 XWINDOW (tem)->prev = p->prev;
747
748 tem = p->prev;
265a9e55 749 if (!NILP (tem))
7ab12479
JB
750 XWINDOW (tem)->next = p->next;
751
752 if (EQ (window, par->hchild))
753 par->hchild = p->next;
754 if (EQ (window, par->vchild))
755 par->vchild = p->next;
756
757 /* Find one of our siblings to give our space to. */
758 sib = p->prev;
265a9e55 759 if (NILP (sib))
7ab12479
JB
760 {
761 /* If p gives its space to its next sibling, that sibling needs
762 to have its top/left side pulled back to where p's is.
763 set_window_{height,width} will re-position the sibling's
764 children. */
765 sib = p->next;
7f4161e0
JB
766 XWINDOW (sib)->top = p->top;
767 XWINDOW (sib)->left = p->left;
7ab12479
JB
768 }
769
770 /* Stretch that sibling. */
265a9e55 771 if (!NILP (par->vchild))
7ab12479
JB
772 set_window_height (sib,
773 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
774 1);
265a9e55 775 if (!NILP (par->hchild))
7ab12479
JB
776 set_window_width (sib,
777 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
778 1);
779
780 /* If parent now has only one child,
781 put the child into the parent's place. */
7ab12479 782 tem = par->hchild;
265a9e55 783 if (NILP (tem))
7ab12479 784 tem = par->vchild;
265a9e55 785 if (NILP (XWINDOW (tem)->next))
7ab12479 786 replace_window (parent, tem);
605be8af
JB
787
788 /* Since we may be deleting combination windows, we must make sure that
789 not only p but all its children have been marked as deleted. */
790 if (! NILP (p->hchild))
791 delete_all_subwindows (XWINDOW (p->hchild));
792 else if (! NILP (p->vchild))
793 delete_all_subwindows (XWINDOW (p->vchild));
794
795 /* Mark this window as deleted. */
796 p->buffer = p->hchild = p->vchild = Qnil;
797
7ab12479
JB
798 return Qnil;
799}
800\f
7ab12479 801
44fa5b1e 802extern Lisp_Object next_frame (), prev_frame ();
7ab12479
JB
803
804DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
805 "Return next window after WINDOW in canonical ordering of windows.\n\
d5783c40
JB
806If omitted, WINDOW defaults to the selected window.\n\
807\n\
808Optional second arg MINIBUF t means count the minibuffer window even\n\
809if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
810it is active. MINIBUF neither t nor nil means not to count the\n\
811minibuffer even if it is active.\n\
812\n\
44fa5b1e
JB
813Several frames may share a single minibuffer; if the minibuffer\n\
814counts, all windows on all frames that share that minibuffer count\n\
d5783c40 815too. This means that next-window may be used to iterate through the\n\
44fa5b1e
JB
816set of windows even when the minibuffer is on another frame. If the\n\
817minibuffer does not count, only windows from WINDOW's frame count.\n\
d5783c40 818\n\
44fa5b1e
JB
819Optional third arg ALL-FRAMES t means include windows on all frames.\n\
820ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
dbc4e1c1
JB
821above. If neither nil nor t, restrict to WINDOW's frame.\n\
822\n\
823If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
824`next-window' to iterate through the entire cycle of acceptable\n\
825windows, eventually ending up back at the window you started with.\n\
826`previous-window' traverses the same cycle, in the reverse order.")
44fa5b1e
JB
827 (window, minibuf, all_frames)
828 register Lisp_Object window, minibuf, all_frames;
7ab12479
JB
829{
830 register Lisp_Object tem;
d5783c40 831 Lisp_Object start_window;
7ab12479 832
265a9e55 833 if (NILP (window))
7ab12479
JB
834 window = selected_window;
835 else
605be8af 836 CHECK_LIVE_WINDOW (window, 0);
7ab12479 837
d5783c40
JB
838 start_window = window;
839
840 /* minibuf == nil may or may not include minibuffers.
841 Decide if it does. */
265a9e55 842 if (NILP (minibuf))
d5783c40
JB
843 minibuf = (minibuf_level ? Qt : Qlambda);
844
44fa5b1e
JB
845 /* all_frames == nil doesn't specify which frames to include.
846 Decide which frames it includes. */
847 if (NILP (all_frames))
848 all_frames = (EQ (minibuf, Qt)
849 ? (FRAME_MINIBUF_WINDOW
850 (XFRAME
851 (WINDOW_FRAME
d5783c40
JB
852 (XWINDOW (window)))))
853 : Qnil);
44fa5b1e
JB
854 else if (! EQ (all_frames, Qt))
855 all_frames = Qnil;
644b477c
RS
856 /* Now all_frames is t meaning search all frames,
857 nil meaning search just current frame,
858 or a window, meaning search the frame that window belongs to. */
7ab12479
JB
859
860 /* Do this loop at least once, to get the next window, and perhaps
861 again, if we hit the minibuffer and that is not acceptable. */
862 do
863 {
864 /* Find a window that actually has a next one. This loop
865 climbs up the tree. */
265a9e55
JB
866 while (tem = XWINDOW (window)->next, NILP (tem))
867 if (tem = XWINDOW (window)->parent, !NILP (tem))
7ab12479 868 window = tem;
d5783c40 869 else
7ab12479 870 {
44fa5b1e
JB
871 /* We've reached the end of this frame.
872 Which other frames are acceptable? */
873 tem = WINDOW_FRAME (XWINDOW (window));
874#ifdef MULTI_FRAME
875 if (! NILP (all_frames))
876 tem = next_frame (tem, all_frames);
7ab12479 877#endif
44fa5b1e 878 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
d5783c40 879
7ab12479
JB
880 break;
881 }
882
883 window = tem;
d5783c40 884
7ab12479
JB
885 /* If we're in a combination window, find its first child and
886 recurse on that. Otherwise, we've found the window we want. */
887 while (1)
888 {
265a9e55 889 if (!NILP (XWINDOW (window)->hchild))
7ab12479 890 window = XWINDOW (window)->hchild;
265a9e55 891 else if (!NILP (XWINDOW (window)->vchild))
7ab12479
JB
892 window = XWINDOW (window)->vchild;
893 else break;
894 }
895 }
d5783c40
JB
896 /* Which windows are acceptible?
897 Exit the loop and accept this window if
7ab12479 898 this isn't a minibuffer window, or
d5783c40
JB
899 we're accepting minibuffer windows, or
900 we've come all the way around and we're back at the original window. */
7ab12479 901 while (MINI_WINDOW_P (XWINDOW (window))
d5783c40 902 && ! EQ (minibuf, Qt)
7f4161e0 903 && ! EQ (window, start_window));
7ab12479
JB
904
905 return window;
906}
907
908DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
d5783c40
JB
909 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
910If omitted, WINDOW defaults to the selected window.\n\
911\n\
912Optional second arg MINIBUF t means count the minibuffer window even\n\
913if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
914it is active. MINIBUF neither t nor nil means not to count the\n\
915minibuffer even if it is active.\n\
916\n\
44fa5b1e
JB
917Several frames may share a single minibuffer; if the minibuffer\n\
918counts, all windows on all frames that share that minibuffer count\n\
d5783c40 919too. This means that previous-window may be used to iterate through\n\
44fa5b1e
JB
920the set of windows even when the minibuffer is on another frame. If\n\
921the minibuffer does not count, only windows from WINDOW's frame\n\
d5783c40
JB
922count.\n\
923\n\
44fa5b1e
JB
924Optional third arg ALL-FRAMES t means include windows on all frames.\n\
925ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
dbc4e1c1
JB
926above. If neither nil nor t, restrict to WINDOW's frame.\n\
927\n\
928If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
929`previous-window' to iterate through the entire cycle of acceptable\n\
930windows, eventually ending up back at the window you started with.\n\
931`next-window' traverses the same cycle, in the reverse order.")
44fa5b1e
JB
932 (window, minibuf, all_frames)
933 register Lisp_Object window, minibuf, all_frames;
7ab12479
JB
934{
935 register Lisp_Object tem;
d5783c40 936 Lisp_Object start_window;
7ab12479 937
265a9e55 938 if (NILP (window))
7ab12479
JB
939 window = selected_window;
940 else
605be8af 941 CHECK_LIVE_WINDOW (window, 0);
7ab12479 942
d5783c40
JB
943 start_window = window;
944
945 /* minibuf == nil may or may not include minibuffers.
946 Decide if it does. */
265a9e55 947 if (NILP (minibuf))
d5783c40
JB
948 minibuf = (minibuf_level ? Qt : Qlambda);
949
44fa5b1e
JB
950 /* all_frames == nil doesn't specify which frames to include.
951 Decide which frames it includes. */
952 if (NILP (all_frames))
953 all_frames = (EQ (minibuf, Qt)
954 ? (FRAME_MINIBUF_WINDOW
955 (XFRAME
956 (WINDOW_FRAME
d5783c40
JB
957 (XWINDOW (window)))))
958 : Qnil);
44fa5b1e
JB
959 else if (! EQ (all_frames, Qt))
960 all_frames = Qnil;
644b477c
RS
961 /* Now all_frames is t meaning search all frames,
962 nil meaning search just current frame,
963 or a window, meaning search the frame that window belongs to. */
7ab12479
JB
964
965 /* Do this loop at least once, to get the previous window, and perhaps
966 again, if we hit the minibuffer and that is not acceptable. */
967 do
968 {
969 /* Find a window that actually has a previous one. This loop
970 climbs up the tree. */
265a9e55
JB
971 while (tem = XWINDOW (window)->prev, NILP (tem))
972 if (tem = XWINDOW (window)->parent, !NILP (tem))
7ab12479 973 window = tem;
d5783c40 974 else
7ab12479 975 {
44fa5b1e
JB
976 /* We have found the top window on the frame.
977 Which frames are acceptable? */
978 tem = WINDOW_FRAME (XWINDOW (window));
979#ifdef MULTI_FRAME
980 if (! NILP (all_frames))
dbc4e1c1
JB
981 /* It's actually important that we use prev_frame here,
982 rather than next_frame. All the windows acceptable
983 according to the given parameters should form a ring;
984 Fnext_window and Fprevious_window should go back and
985 forth around the ring. If we use next_frame here,
986 then Fnext_window and Fprevious_window take different
987 paths through the set of acceptable windows.
988 window_loop assumes that these `ring' requirement are
989 met. */
990 tem = prev_frame (tem, all_frames);
7ab12479 991#endif
644b477c
RS
992 /* If this frame has a minibuffer, find that window first,
993 because it is conceptually the last window in that frame. */
5e12e32f
JB
994 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
995 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
996 else
644b477c 997 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
d5783c40 998
7ab12479
JB
999 break;
1000 }
1001
1002 window = tem;
1003 /* If we're in a combination window, find its last child and
1004 recurse on that. Otherwise, we've found the window we want. */
1005 while (1)
1006 {
265a9e55 1007 if (!NILP (XWINDOW (window)->hchild))
7ab12479 1008 window = XWINDOW (window)->hchild;
265a9e55 1009 else if (!NILP (XWINDOW (window)->vchild))
7ab12479
JB
1010 window = XWINDOW (window)->vchild;
1011 else break;
265a9e55 1012 while (tem = XWINDOW (window)->next, !NILP (tem))
7ab12479
JB
1013 window = tem;
1014 }
1015 }
d5783c40
JB
1016 /* Which windows are acceptable?
1017 Exit the loop and accept this window if
7ab12479 1018 this isn't a minibuffer window, or
d5783c40
JB
1019 we're accepting minibuffer windows, or
1020 we've come all the way around and we're back at the original window. */
7ab12479 1021 while (MINI_WINDOW_P (XWINDOW (window))
d5783c40 1022 && !EQ (minibuf, Qt)
7f4161e0 1023 && !EQ (window, start_window));
7ab12479
JB
1024
1025 return window;
1026}
1027
62c07cc7 1028DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
44fa5b1e
JB
1029 "Select the ARG'th different window on this frame.\n\
1030All windows on current frame are arranged in a cyclic order.\n\
7ab12479
JB
1031This command selects the window ARG steps away in that order.\n\
1032A negative ARG moves in the opposite order. If the optional second\n\
44fa5b1e
JB
1033argument ALL_FRAMES is non-nil, cycle through all frames.")
1034 (n, all_frames)
1035 register Lisp_Object n, all_frames;
7ab12479
JB
1036{
1037 register int i;
1038 register Lisp_Object w;
1039
1040 CHECK_NUMBER (n, 0);
1041 w = selected_window;
1042 i = XINT (n);
1043
1044 while (i > 0)
1045 {
44fa5b1e 1046 w = Fnext_window (w, Qnil, all_frames);
7ab12479
JB
1047 i--;
1048 }
1049 while (i < 0)
1050 {
44fa5b1e 1051 w = Fprevious_window (w, Qnil, all_frames);
7ab12479
JB
1052 i++;
1053 }
1054 Fselect_window (w);
1055 return Qnil;
1056}
1057\f
1058/* Look at all windows, performing an operation specified by TYPE
1059 with argument OBJ.
44fa5b1e
JB
1060 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
1061 frame. If FRAMES is a frame, just look at windows on that frame.
7ab12479
JB
1062 If MINI is non-zero, perform the operation on minibuffer windows too.
1063*/
1064
1065enum window_loop
1066{
1067 WINDOW_LOOP_UNUSED,
1068 GET_BUFFER_WINDOW, /* Arg is buffer */
1069 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1070 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1071 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1072 GET_LARGEST_WINDOW,
1073 UNSHOW_BUFFER, /* Arg is buffer */
1074};
1075
1076static Lisp_Object
44fa5b1e 1077window_loop (type, obj, mini, frames)
7ab12479 1078 enum window_loop type;
44fa5b1e 1079 register Lisp_Object obj, frames;
7ab12479
JB
1080 int mini;
1081{
1082 register Lisp_Object w;
1083 register Lisp_Object best_window;
1084 register Lisp_Object next_window;
4b206065 1085 register Lisp_Object last_window;
44fa5b1e
JB
1086 FRAME_PTR frame;
1087
4b206065 1088#ifdef MULTI_FRAME
44fa5b1e
JB
1089 /* If we're only looping through windows on a particular frame,
1090 frame points to that frame. If we're looping through windows
1091 on all frames, frame is 0. */
1092 if (FRAMEP (frames))
1093 frame = XFRAME (frames);
1094 else if (NILP (frames))
1095 frame = selected_frame;
7ab12479 1096 else
44fa5b1e 1097 frame = 0;
4b206065
JB
1098#else
1099 frame = 0;
1100#endif
7ab12479
JB
1101
1102 /* Pick a window to start with. */
1103 if (XTYPE (obj) == Lisp_Window)
4b206065 1104 w = obj;
44fa5b1e 1105 else if (frame)
4b206065 1106 w = FRAME_SELECTED_WINDOW (frame);
7ab12479 1107 else
4b206065
JB
1108 w = FRAME_SELECTED_WINDOW (selected_frame);
1109
1110 /* Figure out the last window we're going to mess with. Since
1111 Fnext_window, given the same options, is guaranteed to go in a
1112 ring, we can just use Fprevious_window to find the last one.
1113
1114 We can't just wait until we hit the first window again, because
1115 it might be deleted. */
1116
1117#ifdef MULTI_FRAME
1118 if (frame)
1119 last_window = Fprevious_window (w, (mini ? Qt : Qnil), Qlambda);
1120 else
1121#endif /* MULTI_FRAME */
1122 /* We know frame is 0, so we're looping through all frames.
1123 Or we know this isn't a MULTI_FRAME Emacs, so who cares? */
1124 last_window = Fprevious_window (w, mini ? Qt : Qnil, Qt);
7ab12479 1125
7ab12479 1126 best_window = Qnil;
4b206065 1127 for (;;)
7ab12479
JB
1128 {
1129 /* Pick the next window now, since some operations will delete
1130 the current window. */
44fa5b1e
JB
1131#ifdef MULTI_FRAME
1132 if (frame)
d5783c40 1133 next_window = Fnext_window (w, (mini ? Qt : Qnil), Qlambda);
7ab12479 1134 else
4b206065 1135#endif /* MULTI_FRAME */
44fa5b1e
JB
1136 /* We know frame is 0, so we're looping through all frames.
1137 Or we know this isn't a MULTI_FRAME Emacs, so who cares? */
7ab12479
JB
1138 next_window = Fnext_window (w, mini ? Qt : Qnil, Qt);
1139
1140 if (!MINI_WINDOW_P (XWINDOW (w))
1141 || (mini && minibuf_level > 0))
1142 switch (type)
1143 {
1144 case GET_BUFFER_WINDOW:
1145#if 0
44fa5b1e
JB
1146 /* Ignore invisible and iconified frames. */
1147 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
1148 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
7ab12479
JB
1149 break;
1150#endif
1151 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj))
1152 return w;
1153 break;
1154
1155 case GET_LRU_WINDOW:
1156 /* t as arg means consider only full-width windows */
e5d77022 1157 if (!NILP (obj) && XFASTINT (XWINDOW (w)->width)
a2db42d6 1158 != FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
7ab12479
JB
1159 break;
1160#if 0
44fa5b1e
JB
1161 /* Ignore invisible and iconified frames. */
1162 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
1163 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
7ab12479
JB
1164 break;
1165#endif
1166 /* Ignore dedicated windows and minibuffers. */
1167 if (MINI_WINDOW_P (XWINDOW (w))
265a9e55 1168 || !NILP (XWINDOW (w)->dedicated))
7ab12479 1169 break;
265a9e55 1170 if (NILP (best_window)
7ab12479
JB
1171 || (XFASTINT (XWINDOW (best_window)->use_time)
1172 > XFASTINT (XWINDOW (w)->use_time)))
1173 best_window = w;
1174 break;
1175
1176 case DELETE_OTHER_WINDOWS:
1177 if (XWINDOW (w) != XWINDOW (obj))
1178 Fdelete_window (w);
1179 break;
1180
1181 case DELETE_BUFFER_WINDOWS:
1182 if (EQ (XWINDOW (w)->buffer, obj))
1183 {
1184 /* If we're deleting the buffer displayed in the only window
44fa5b1e 1185 on the frame, find a new buffer to display there. */
265a9e55 1186 if (NILP (XWINDOW (w)->parent))
7ab12479 1187 {
faa64cf7 1188 Lisp_Object new_buffer = Fother_buffer (obj, Qnil);
265a9e55 1189 if (NILP (new_buffer))
7ab12479
JB
1190 new_buffer
1191 = Fget_buffer_create (build_string ("*scratch*"));
1192 Fset_window_buffer (w, new_buffer);
1193 Fset_buffer (XWINDOW (w)->buffer);
1194 }
1195 else
1196 Fdelete_window (w);
1197 }
1198 break;
1199
1200 case GET_LARGEST_WINDOW:
1201#if 0
44fa5b1e
JB
1202 /* Ignore invisible and iconified frames. */
1203 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
1204 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
7ab12479
JB
1205 break;
1206#endif
1207 /* Ignore dedicated windows and minibuffers. */
1208 if (MINI_WINDOW_P (XWINDOW (w))
265a9e55 1209 || !NILP (XWINDOW (w)->dedicated))
7ab12479
JB
1210 break;
1211 {
1212 struct window *best_window_ptr = XWINDOW (best_window);
1213 struct window *w_ptr = XWINDOW (w);
265a9e55 1214 if (NILP (best_window) ||
7ab12479
JB
1215 (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width))
1216 > (XFASTINT (best_window_ptr->height)
1217 * XFASTINT (best_window_ptr->width)))
1218 best_window = w;
1219 }
1220 break;
1221
1222 case UNSHOW_BUFFER:
1223 if (EQ (XWINDOW (w)->buffer, obj))
1224 {
1225 /* Find another buffer to show in this window. */
faa64cf7 1226 Lisp_Object another_buffer = Fother_buffer (obj, Qnil);
265a9e55 1227 if (NILP (another_buffer))
7ab12479
JB
1228 another_buffer
1229 = Fget_buffer_create (build_string ("*scratch*"));
1230 Fset_window_buffer (w, another_buffer);
1231 if (EQ (w, selected_window))
1232 Fset_buffer (XWINDOW (w)->buffer);
1233 }
1234 break;
1235 }
4b206065
JB
1236
1237 if (EQ (w, last_window))
1238 break;
1239
7ab12479
JB
1240 w = next_window;
1241 }
7ab12479
JB
1242
1243 return best_window;
1244}
605be8af 1245
7ab12479
JB
1246DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1247 "Return the window least recently selected or used for display.\n\
44fa5b1e
JB
1248If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1249frame, search only that frame.\n")
1250 (frames)
1251 Lisp_Object frames;
7ab12479
JB
1252{
1253 register Lisp_Object w;
1254 /* First try for a window that is full-width */
44fa5b1e 1255 w = window_loop (GET_LRU_WINDOW, Qt, 0, frames);
265a9e55 1256 if (!NILP (w) && !EQ (w, selected_window))
7ab12479
JB
1257 return w;
1258 /* If none of them, try the rest */
44fa5b1e 1259 return window_loop (GET_LRU_WINDOW, Qnil, 0, frames);
7ab12479
JB
1260}
1261
1262DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1263 "Return the largest window in area.\n\
44fa5b1e
JB
1264If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1265frame, search only that frame.\n")
1266 (frame)
1267 Lisp_Object frame;
7ab12479
JB
1268{
1269 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
44fa5b1e 1270 frame);
7ab12479
JB
1271}
1272
1273DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1274 "Return a window currently displaying BUFFER, or nil if none.\n\
44fa5b1e
JB
1275If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1276frame, search only that frame.\n")
1277 (buffer, frame)
1278 Lisp_Object buffer, frame;
7ab12479
JB
1279{
1280 buffer = Fget_buffer (buffer);
1281 if (XTYPE (buffer) == Lisp_Buffer)
44fa5b1e 1282 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
7ab12479
JB
1283 else
1284 return Qnil;
1285}
1286
1287DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1288 0, 1, "",
44fa5b1e
JB
1289 "Make WINDOW (or the selected window) fill its frame.\n\
1290Only the frame WINDOW is on is affected.")
7ab12479
JB
1291 (window)
1292 Lisp_Object window;
1293{
1294 struct window *w;
1295 int opoint = point;
1296 struct buffer *obuf = current_buffer;
1297 int top;
1298
265a9e55 1299 if (NILP (window))
7ab12479
JB
1300 window = selected_window;
1301 else
605be8af 1302 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1303
1304 w = XWINDOW (window);
1305 top = XFASTINT (w->top);
1306
70728a80 1307 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
7ab12479
JB
1308
1309 Fset_buffer (w->buffer);
1310 SET_PT (marker_position (w->start));
70728a80 1311 Frecenter (make_number (top - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w)))));
7ab12479
JB
1312
1313 set_buffer_internal (obuf);
1314 SET_PT (opoint);
1315 return Qnil;
1316}
1317
1318DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1319 1, 1, "bDelete windows on (buffer): ",
1320 "Delete all windows showing BUFFER.")
1321 (buffer)
1322 Lisp_Object buffer;
1323{
265a9e55 1324 if (!NILP (buffer))
7ab12479
JB
1325 {
1326 buffer = Fget_buffer (buffer);
1327 CHECK_BUFFER (buffer, 0);
1328 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, Qt);
1329 }
1330 return Qnil;
1331}
1332
1333DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1334 Sreplace_buffer_in_windows,
1335 1, 1, "bReplace buffer in windows: ",
1336 "Replace BUFFER with some other buffer in all windows showing it.")
1337 (buffer)
1338 Lisp_Object buffer;
1339{
265a9e55 1340 if (!NILP (buffer))
7ab12479
JB
1341 {
1342 buffer = Fget_buffer (buffer);
1343 CHECK_BUFFER (buffer, 0);
1344 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1345 }
1346 return Qnil;
1347}
1348\f
1349/* Set the height of WINDOW and all its inferiors. */
a481b3ea
JB
1350
1351/* The smallest acceptable dimensions for a window. Anything smaller
1352 might crash Emacs. */
1353#define MIN_SAFE_WINDOW_WIDTH (2)
1354#define MIN_SAFE_WINDOW_HEIGHT (2)
1355
1356/* Make sure that window_min_height and window_min_width are
1357 not too small; if they are, set them to safe minima. */
1358
1359static void
1360check_min_window_sizes ()
1361{
1362 /* Smaller values might permit a crash. */
1363 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1364 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1365 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1366 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1367}
1368
1369/* If *ROWS or *COLS are too small a size for FRAME, set them to the
1370 minimum allowable size. */
605be8af 1371void
a481b3ea 1372check_frame_size (frame, rows, cols)
605be8af
JB
1373 FRAME_PTR frame;
1374 int *rows, *cols;
a481b3ea
JB
1375{
1376 /* For height, we have to see whether the frame has a minibuffer, and
1377 whether it wants a mode line. */
1378 int min_height =
1379 ((FRAME_MINIBUF_ONLY_P (frame)
1380 || ! FRAME_HAS_MINIBUF_P (frame))
1381 ? MIN_SAFE_WINDOW_HEIGHT
1382 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
1383
1384 if (*rows < min_height)
1385 *rows = min_height;
1386 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1387 *cols = MIN_SAFE_WINDOW_WIDTH;
1388}
1389
7ab12479
JB
1390/* Normally the window is deleted if it gets too small.
1391 nodelete nonzero means do not do this.
1392 (The caller should check later and do so if appropriate) */
1393
1394set_window_height (window, height, nodelete)
1395 Lisp_Object window;
1396 int height;
1397 int nodelete;
1398{
1399 register struct window *w = XWINDOW (window);
1400 register struct window *c;
1401 int oheight = XFASTINT (w->height);
1402 int top, pos, lastbot, opos, lastobot;
1403 Lisp_Object child;
1404
a481b3ea
JB
1405 check_min_window_sizes ();
1406
7ab12479 1407 if (!nodelete
265a9e55 1408 && ! NILP (w->parent)
7ab12479
JB
1409 && height < window_min_height)
1410 {
1411 Fdelete_window (window);
1412 return;
1413 }
1414
1415 XFASTINT (w->last_modified) = 0;
1416 windows_or_buffers_changed++;
1417 XFASTINT (w->height) = height;
265a9e55 1418 if (!NILP (w->hchild))
7ab12479 1419 {
265a9e55 1420 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1421 {
1422 XWINDOW (child)->top = w->top;
1423 set_window_height (child, height, nodelete);
1424 }
1425 }
265a9e55 1426 else if (!NILP (w->vchild))
7ab12479
JB
1427 {
1428 lastbot = top = XFASTINT (w->top);
1429 lastobot = 0;
265a9e55 1430 for (child = w->vchild; !NILP (child); child = c->next)
7ab12479
JB
1431 {
1432 c = XWINDOW (child);
1433
1434 opos = lastobot + XFASTINT (c->height);
1435
1436 XFASTINT (c->top) = lastbot;
1437
1438 pos = (((opos * height) << 1) + oheight) / (oheight << 1);
1439
1440 /* Avoid confusion: inhibit deletion of child if becomes too small */
1441 set_window_height (child, pos + top - lastbot, 1);
1442
1443 /* Now advance child to next window,
1444 and set lastbot if child was not just deleted. */
1445 lastbot = pos + top;
1446 lastobot = opos;
1447 }
1448 /* Now delete any children that became too small. */
1449 if (!nodelete)
265a9e55 1450 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1451 {
1452 set_window_height (child, XINT (XWINDOW (child)->height), 0);
1453 }
1454 }
1455}
1456
1457/* Recursively set width of WINDOW and its inferiors. */
1458
1459set_window_width (window, width, nodelete)
1460 Lisp_Object window;
1461 int width;
1462 int nodelete;
1463{
1464 register struct window *w = XWINDOW (window);
1465 register struct window *c;
1466 int owidth = XFASTINT (w->width);
1467 int left, pos, lastright, opos, lastoright;
1468 Lisp_Object child;
1469
1470 if (!nodelete && width < window_min_width)
1471 {
1472 Fdelete_window (window);
1473 return;
1474 }
1475
1476 XFASTINT (w->last_modified) = 0;
1477 windows_or_buffers_changed++;
1478 XFASTINT (w->width) = width;
265a9e55 1479 if (!NILP (w->vchild))
7ab12479 1480 {
265a9e55 1481 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1482 {
1483 XWINDOW (child)->left = w->left;
1484 set_window_width (child, width, nodelete);
1485 }
1486 }
265a9e55 1487 else if (!NILP (w->hchild))
7ab12479
JB
1488 {
1489 lastright = left = XFASTINT (w->left);
1490 lastoright = 0;
265a9e55 1491 for (child = w->hchild; !NILP (child); child = c->next)
7ab12479
JB
1492 {
1493 c = XWINDOW (child);
1494
1495 opos = lastoright + XFASTINT (c->width);
1496
1497 XFASTINT (c->left) = lastright;
1498
1499 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
1500
1501 /* Inhibit deletion for becoming too small */
1502 set_window_width (child, pos + left - lastright, 1);
1503
1504 /* Now advance child to next window,
1505 and set lastright if child was not just deleted. */
1506 lastright = pos + left, lastoright = opos;
1507 }
1508 /* Delete children that became too small */
1509 if (!nodelete)
265a9e55 1510 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1511 {
1512 set_window_width (child, XINT (XWINDOW (child)->width), 0);
1513 }
1514 }
1515}
1516\f
1d8d96fa 1517int window_select_count;
7ab12479
JB
1518
1519DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1520 "Make WINDOW display BUFFER as its contents.\n\
1521BUFFER can be a buffer or buffer name.")
1522 (window, buffer)
1523 register Lisp_Object window, buffer;
1524{
1525 register Lisp_Object tem;
1526 register struct window *w = decode_window (window);
1527
1528 buffer = Fget_buffer (buffer);
1529 CHECK_BUFFER (buffer, 1);
1530
265a9e55 1531 if (NILP (XBUFFER (buffer)->name))
7ab12479
JB
1532 error ("Attempt to display deleted buffer");
1533
1534 tem = w->buffer;
265a9e55 1535 if (NILP (tem))
7ab12479
JB
1536 error ("Window is deleted");
1537 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
1538 is first being set up. */
1539 {
265a9e55 1540 if (!NILP (w->dedicated) && !EQ (tem, buffer))
7ab12479
JB
1541 error ("Window is dedicated to %s\n", tem);
1542
1543 unshow_buffer (w);
1544 }
1545
1546 w->buffer = buffer;
270967b2 1547 w->hscroll = 0;
7ab12479
JB
1548 Fset_marker (w->pointm,
1549 make_number (BUF_PT (XBUFFER (buffer))),
1550 buffer);
1551 set_marker_restricted (w->start,
1552 make_number (XBUFFER (buffer)->last_window_start),
1553 buffer);
1554 w->start_at_line_beg = Qnil;
e36ab06b 1555 w->force_start = Qnil;
7ab12479
JB
1556 XFASTINT (w->last_modified) = 0;
1557 windows_or_buffers_changed++;
1558 if (EQ (window, selected_window))
1559 Fset_buffer (buffer);
1560
1561 return Qnil;
1562}
1563
1564DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1565 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1566The main editor command loop selects the buffer of the selected window\n\
1567before each command.")
1568 (window)
1569 register Lisp_Object window;
1570{
1571 register struct window *w;
1572 register struct window *ow = XWINDOW (selected_window);
1573
605be8af 1574 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1575
1576 w = XWINDOW (window);
1577
265a9e55 1578 if (NILP (w->buffer))
7ab12479
JB
1579 error ("Trying to select deleted window or non-leaf window");
1580
1581 XFASTINT (w->use_time) = ++window_select_count;
1582 if (EQ (window, selected_window))
1583 return window;
1584
1585 Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
1586 ow->buffer);
1587
1588 selected_window = window;
44fa5b1e
JB
1589#ifdef MULTI_FRAME
1590 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
7ab12479 1591 {
44fa5b1e 1592 XFRAME (WINDOW_FRAME (w))->selected_window = window;
d5b2799e 1593 Fhandle_switch_frame (WINDOW_FRAME (w), Qnil);
7ab12479
JB
1594 }
1595 else
44fa5b1e 1596 selected_frame->selected_window = window;
7ab12479
JB
1597#endif
1598
1599 record_buffer (w->buffer);
1600 Fset_buffer (w->buffer);
1601
1602 /* Go to the point recorded in the window.
1603 This is important when the buffer is in more
1604 than one window. It also matters when
1605 redisplay_window has altered point after scrolling,
1606 because it makes the change only in the window. */
1607 {
1608 register int new_point = marker_position (w->pointm);
1609 if (new_point < BEGV)
1610 SET_PT (BEGV);
1611 if (new_point > ZV)
1612 SET_PT (ZV);
1613 else
1614 SET_PT (new_point);
1615 }
1616
1617 windows_or_buffers_changed++;
1618 return window;
1619}
1620
35aaf00c 1621DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
6648f23a 1622 "BDisplay buffer: \nP",
7ab12479
JB
1623 "Make BUFFER appear in some window but don't select it.\n\
1624BUFFER can be a buffer or a buffer name.\n\
1625If BUFFER is shown already in some window, just use that one,\n\
1626unless the window is the selected window and the optional second\n\
46d3268a 1627argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
7ab12479
JB
1628Returns the window displaying BUFFER.")
1629 (buffer, not_this_window)
1630 register Lisp_Object buffer, not_this_window;
1631{
1632 register Lisp_Object window;
1633
1634 buffer = Fget_buffer (buffer);
1635 CHECK_BUFFER (buffer, 0);
1636
265a9e55 1637 if (!NILP (Vdisplay_buffer_function))
7ab12479
JB
1638 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
1639
265a9e55 1640 if (NILP (not_this_window)
7ab12479
JB
1641 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
1642 return selected_window;
1643
1644 window = Fget_buffer_window (buffer, Qnil);
265a9e55
JB
1645 if (!NILP (window)
1646 && (NILP (not_this_window) || !EQ (window, selected_window)))
7ab12479
JB
1647 return window;
1648
44fa5b1e
JB
1649#ifdef MULTI_FRAME
1650 /* If there are no frames open that have more than a minibuffer,
1651 we need to create a new frame. */
1652 if (pop_up_frames || last_nonminibuf_frame == 0)
7ab12479
JB
1653 {
1654 window
44fa5b1e 1655 = Fframe_selected_window (call0 (Vpop_up_frame_function));
7ab12479
JB
1656 Fset_window_buffer (window, buffer);
1657#if 0
d5b2799e 1658 Fhandle_switch_frame (XWINDOW (window)->frame, Qnil);
7ab12479
JB
1659#endif
1660 return window;
1661 }
44fa5b1e 1662#endif /* MULTI_FRAME */
7ab12479 1663
43bad991 1664 if (pop_up_windows
44fa5b1e
JB
1665#ifdef MULTI_FRAME
1666 || FRAME_MINIBUF_ONLY_P (selected_frame)
43bad991
JB
1667#endif
1668 )
7ab12479 1669 {
44fa5b1e 1670 Lisp_Object frames = Qnil;
43bad991 1671
44fa5b1e
JB
1672#ifdef MULTI_FRAME
1673 if (FRAME_MINIBUF_ONLY_P (selected_frame))
1674 XSET (frames, Lisp_Frame, last_nonminibuf_frame);
7ab12479
JB
1675#endif
1676 /* Don't try to create a window if would get an error */
1677 if (split_height_threshold < window_min_height << 1)
1678 split_height_threshold = window_min_height << 1;
1679
44fa5b1e 1680 window = Fget_largest_window (frames);
7ab12479 1681
265a9e55 1682 if (!NILP (window)
7ab12479 1683 && window_height (window) >= split_height_threshold
535e0b8e
JB
1684 && (XFASTINT (XWINDOW (window)->width)
1685 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
7ab12479
JB
1686 window = Fsplit_window (window, Qnil, Qnil);
1687 else
1688 {
44fa5b1e 1689 window = Fget_lru_window (frames);
7ab12479
JB
1690 if ((EQ (window, selected_window)
1691 || EQ (XWINDOW (window)->parent, Qnil))
1692 && window_height (window) >= window_min_height << 1)
1693 window = Fsplit_window (window, Qnil, Qnil);
1694 }
1695 }
1696 else
1697 window = Fget_lru_window (Qnil);
1698
1699 Fset_window_buffer (window, buffer);
1700 return window;
1701}
1702
1703void
1704temp_output_buffer_show (buf)
1705 register Lisp_Object buf;
1706{
1707 register struct buffer *old = current_buffer;
1708 register Lisp_Object window;
1709 register struct window *w;
1710
1711 Fset_buffer (buf);
1712 XBUFFER (buf)->save_modified = MODIFF;
1713 BEGV = BEG;
1714 ZV = Z;
1715 SET_PT (BEG);
1716 clip_changed = 1;
1717 set_buffer_internal (old);
1718
1719 if (!EQ (Vtemp_buffer_show_function, Qnil))
1720 call1 (Vtemp_buffer_show_function, buf);
1721 else
1722 {
1723 window = Fdisplay_buffer (buf, Qnil);
1724
44fa5b1e
JB
1725#ifdef MULTI_FRAME
1726 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
1727 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
1728#endif /* MULTI_FRAME */
7ab12479
JB
1729 Vminibuf_scroll_window = window;
1730 w = XWINDOW (window);
1731 XFASTINT (w->hscroll) = 0;
1732 set_marker_restricted (w->start, make_number (1), buf);
1733 set_marker_restricted (w->pointm, make_number (1), buf);
1734 }
1735}
1736\f
1737static
1738make_dummy_parent (window)
1739 Lisp_Object window;
1740{
1741 register Lisp_Object old, new;
1742 register struct window *o, *p;
1743
1744 old = window;
1745 XSETTYPE (old, Lisp_Vector);
1746 new = Fcopy_sequence (old);
1747 XSETTYPE (new, Lisp_Window);
1748
1749 o = XWINDOW (old);
1750 p = XWINDOW (new);
1751 XFASTINT (p->sequence_number) = ++sequence_number;
1752
1753 /* Put new into window structure in place of window */
1754 replace_window (window, new);
1755
1756 o->next = Qnil;
1757 o->prev = Qnil;
1758 o->vchild = Qnil;
1759 o->hchild = Qnil;
1760 o->parent = new;
1761
1762 p->start = Qnil;
1763 p->pointm = Qnil;
1764 p->buffer = Qnil;
1765}
1766
1767DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
1768 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1769WINDOW defaults to selected one and SIZE to half its size.\n\
1770If optional third arg HOR-FLAG is non-nil, split side by side\n\
1771and put SIZE columns in the first of the pair.")
1772 (window, chsize, horflag)
1773 Lisp_Object window, chsize, horflag;
1774{
1775 register Lisp_Object new;
1776 register struct window *o, *p;
1777 register int size;
1778
265a9e55 1779 if (NILP (window))
7ab12479
JB
1780 window = selected_window;
1781 else
605be8af 1782 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1783
1784 o = XWINDOW (window);
1785
265a9e55 1786 if (NILP (chsize))
7ab12479 1787 {
265a9e55 1788 if (!NILP (horflag))
7ab12479
JB
1789 /* Round odd size up, since this is for the left-hand window,
1790 and it will lose a column for the separators. */
1791 size = ((XFASTINT (o->width) + 1) & -2) >> 1;
1792 else
1793 size = XFASTINT (o->height) >> 1;
1794 }
1795 else
1796 {
1797 CHECK_NUMBER (chsize, 1);
1798 size = XINT (chsize);
1799 }
1800
1801 if (MINI_WINDOW_P (o))
1802 error ("Attempt to split minibuffer window");
44fa5b1e
JB
1803 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
1804 error ("Attempt to split unsplittable frame");
7ab12479 1805
a481b3ea 1806 check_min_window_sizes ();
7ab12479 1807
265a9e55 1808 if (NILP (horflag))
7ab12479
JB
1809 {
1810 if (size < window_min_height
1811 || size + window_min_height > XFASTINT (o->height))
1812 args_out_of_range_3 (window, chsize, horflag);
265a9e55
JB
1813 if (NILP (o->parent)
1814 || NILP (XWINDOW (o->parent)->vchild))
7ab12479
JB
1815 {
1816 make_dummy_parent (window);
1817 new = o->parent;
1818 XWINDOW (new)->vchild = window;
1819 }
1820 }
1821 else
1822 {
1823 if (size < window_min_width
1824 || size + window_min_width > XFASTINT (o->width))
1825 args_out_of_range_3 (window, chsize, horflag);
265a9e55
JB
1826 if (NILP (o->parent)
1827 || NILP (XWINDOW (o->parent)->hchild))
7ab12479
JB
1828 {
1829 make_dummy_parent (window);
1830 new = o->parent;
1831 XWINDOW (new)->hchild = window;
1832 }
1833 }
1834
1835 /* Now we know that window's parent is a vertical combination
1836 if we are dividing vertically, or a horizontal combination
1837 if we are making side-by-side windows */
1838
1839 windows_or_buffers_changed++;
1840 new = make_window ();
1841 p = XWINDOW (new);
1842
44fa5b1e 1843 p->frame = o->frame;
7ab12479 1844 p->next = o->next;
265a9e55 1845 if (!NILP (p->next))
7ab12479
JB
1846 XWINDOW (p->next)->prev = new;
1847 p->prev = window;
1848 o->next = new;
1849 p->parent = o->parent;
1850 p->buffer = Qt;
1851
1852 Fset_window_buffer (new, o->buffer);
1853
44fa5b1e 1854 /* Apportion the available frame space among the two new windows */
7ab12479 1855
265a9e55 1856 if (!NILP (horflag))
7ab12479
JB
1857 {
1858 p->height = o->height;
1859 p->top = o->top;
1860 XFASTINT (p->width) = XFASTINT (o->width) - size;
1861 XFASTINT (o->width) = size;
1862 XFASTINT (p->left) = XFASTINT (o->left) + size;
1863 }
1864 else
1865 {
1866 p->left = o->left;
1867 p->width = o->width;
1868 XFASTINT (p->height) = XFASTINT (o->height) - size;
1869 XFASTINT (o->height) = size;
1870 XFASTINT (p->top) = XFASTINT (o->top) + size;
1871 }
1872
1873 return new;
1874}
1875\f
1876DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
1877 "Make current window ARG lines bigger.\n\
1878From program, optional second arg non-nil means grow sideways ARG columns.")
1879 (n, side)
1880 register Lisp_Object n, side;
1881{
1882 CHECK_NUMBER (n, 0);
265a9e55 1883 change_window_height (XINT (n), !NILP (side));
7ab12479
JB
1884 return Qnil;
1885}
1886
1887DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
1888 "Make current window ARG lines smaller.\n\
1889From program, optional second arg non-nil means shrink sideways ARG columns.")
1890 (n, side)
1891 register Lisp_Object n, side;
1892{
1893 CHECK_NUMBER (n, 0);
265a9e55 1894 change_window_height (-XINT (n), !NILP (side));
7ab12479
JB
1895 return Qnil;
1896}
1897
1898int
1899window_height (window)
1900 Lisp_Object window;
1901{
1902 register struct window *p = XWINDOW (window);
1903 return XFASTINT (p->height);
1904}
1905
1906int
1907window_width (window)
1908 Lisp_Object window;
1909{
1910 register struct window *p = XWINDOW (window);
1911 return XFASTINT (p->width);
1912}
1913
05c2896a
JB
1914#define MINSIZE(w) \
1915 (widthflag \
1916 ? window_min_width \
1917 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
7ab12479
JB
1918
1919#define CURBEG(w) \
05c2896a 1920 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
7ab12479
JB
1921
1922#define CURSIZE(w) \
05c2896a 1923 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
7ab12479
JB
1924
1925/* Unlike set_window_height, this function
1926 also changes the heights of the siblings so as to
1927 keep everything consistent. */
1928
1929change_window_height (delta, widthflag)
1930 register int delta;
1931 int widthflag;
1932{
1933 register Lisp_Object parent;
1934 Lisp_Object window;
1935 register struct window *p;
1936 int *sizep;
1937 int (*sizefun) () = widthflag ? window_width : window_height;
1938 register int (*setsizefun) () = (widthflag
1939 ? set_window_width
1940 : set_window_height);
1941
a481b3ea 1942 check_min_window_sizes ();
7ab12479
JB
1943
1944 window = selected_window;
1945 while (1)
1946 {
1947 p = XWINDOW (window);
1948 parent = p->parent;
265a9e55 1949 if (NILP (parent))
7ab12479
JB
1950 {
1951 if (widthflag)
1952 error ("No other window to side of this one");
1953 break;
1954 }
265a9e55
JB
1955 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
1956 : !NILP (XWINDOW (parent)->vchild))
7ab12479
JB
1957 break;
1958 window = parent;
1959 }
1960
05c2896a 1961 sizep = &CURSIZE (window);
7ab12479 1962
05c2896a 1963 if (*sizep + delta < MINSIZE (window))
7ab12479
JB
1964 {
1965 Fdelete_window (window);
1966 return;
1967 }
1968
1969 {
1970 register int maxdelta;
7ab12479 1971
265a9e55
JB
1972 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
1973 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
1974 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
44fa5b1e
JB
1975 /* This is a frame with only one window, a minibuffer-only
1976 or a minibufferless frame. */
d5783c40 1977 : (delta = 0));
7ab12479
JB
1978
1979 if (delta > maxdelta)
1980 /* This case traps trying to make the minibuffer
44fa5b1e
JB
1981 the full frame, or make the only window aside from the
1982 minibuffer the full frame. */
7ab12479 1983 delta = maxdelta;
d5783c40
JB
1984
1985 if (delta == 0)
1986 return;
7ab12479
JB
1987 }
1988
265a9e55 1989 if (!NILP (p->next) &&
7ab12479
JB
1990 (*sizefun) (p->next) - delta >= MINSIZE (p->next))
1991 {
1992 (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
1993 (*setsizefun) (window, *sizep + delta, 0);
05c2896a 1994 CURBEG (p->next) += delta;
7ab12479
JB
1995 /* This does not change size of p->next,
1996 but it propagates the new top edge to its children */
1997 (*setsizefun) (p->next, (*sizefun) (p->next), 0);
1998 }
265a9e55 1999 else if (!NILP (p->prev) &&
7ab12479
JB
2000 (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
2001 {
2002 (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
05c2896a 2003 CURBEG (window) -= delta;
7ab12479
JB
2004 (*setsizefun) (window, *sizep + delta, 0);
2005 }
2006 else
2007 {
2008 register int delta1;
2009 register int opht = (*sizefun) (parent);
2010
2011 /* If trying to grow this window to or beyond size of the parent,
2012 make delta1 so big that, on shrinking back down,
2013 all the siblings end up with less than one line and are deleted. */
2014 if (opht <= *sizep + delta)
2015 delta1 = opht * opht * 2;
2016 /* Otherwise, make delta1 just right so that if we add delta1
2017 lines to this window and to the parent, and then shrink
2018 the parent back to its original size, the new proportional
2019 size of this window will increase by delta. */
2020 else
2021 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
2022
2023 /* Add delta1 lines or columns to this window, and to the parent,
2024 keeping things consistent while not affecting siblings. */
05c2896a 2025 CURSIZE (parent) = opht + delta1;
7ab12479
JB
2026 (*setsizefun) (window, *sizep + delta1, 0);
2027
2028 /* Squeeze out delta1 lines or columns from our parent,
2029 shriking this window and siblings proportionately.
2030 This brings parent back to correct size.
2031 Delta1 was calculated so this makes this window the desired size,
2032 taking it all out of the siblings. */
2033 (*setsizefun) (parent, opht, 0);
2034 }
2035
2036 XFASTINT (p->last_modified) = 0;
2037}
2038#undef MINSIZE
2039#undef CURBEG
2040#undef CURSIZE
2041
2042\f
2043/* Return number of lines of text (not counting mode line) in W. */
2044
2045int
2046window_internal_height (w)
2047 struct window *w;
2048{
2049 int ht = XFASTINT (w->height);
2050
2051 if (MINI_WINDOW_P (w))
2052 return ht;
2053
265a9e55
JB
2054 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2055 || !NILP (w->next) || !NILP (w->prev)
44fa5b1e 2056 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
7ab12479
JB
2057 return ht - 1;
2058
2059 return ht;
2060}
2061
535e0b8e
JB
2062
2063/* Return the number of columns in W.
a3c87d4e 2064 Don't count columns occupied by scroll bars or the vertical bar
535e0b8e
JB
2065 separating W from the sibling to its right. */
2066int
2067window_internal_width (w)
2068 struct window *w;
2069{
2070 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2071 int left = XINT (w->left);
2072 int width = XINT (w->width);
2073
2074 /* If this window is flush against the right edge of the frame, its
2075 internal width is its full width. */
2076 if (left + width >= FRAME_WIDTH (f))
2077 return width;
2078
2079 /* If we are not flush right, then our rightmost columns are
2080 occupied by some sort of separator. */
2081
a3c87d4e
JB
2082 /* Scroll bars occupy a few columns. */
2083 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2084 return width - VERTICAL_SCROLL_BAR_WIDTH;
535e0b8e
JB
2085
2086 /* The column of `|' characters separating side-by-side windows
2087 occupies one column only. */
2088 return width - 1;
2089}
2090
2091
7ab12479
JB
2092/* Scroll contents of window WINDOW up N lines. */
2093
2094void
f8026fd8 2095window_scroll (window, n, noerror)
7ab12479
JB
2096 Lisp_Object window;
2097 int n;
f8026fd8 2098 int noerror;
7ab12479
JB
2099{
2100 register struct window *w = XWINDOW (window);
2101 register int opoint = point;
2102 register int pos;
2103 register int ht = window_internal_height (w);
2104 register Lisp_Object tem;
2105 int lose;
2106 Lisp_Object bolp, nmoved;
2107
2108 XFASTINT (tem) = point;
2109 tem = Fpos_visible_in_window_p (tem, window);
2110
265a9e55 2111 if (NILP (tem))
7ab12479
JB
2112 {
2113 Fvertical_motion (make_number (- ht / 2));
2114 XFASTINT (tem) = point;
2115 Fset_marker (w->start, tem, w->buffer);
2116 w->force_start = Qt;
2117 }
2118
2119 SET_PT (marker_position (w->start));
2120 lose = n < 0 && point == BEGV;
2121 Fvertical_motion (make_number (n));
2122 pos = point;
2123 bolp = Fbolp ();
2124 SET_PT (opoint);
2125
2126 if (lose)
f8026fd8
JB
2127 {
2128 if (noerror)
2129 return;
2130 else
2131 Fsignal (Qbeginning_of_buffer, Qnil);
2132 }
7ab12479
JB
2133
2134 if (pos < ZV)
7ab12479
JB
2135 {
2136 set_marker_restricted (w->start, make_number (pos), w->buffer);
2137 w->start_at_line_beg = bolp;
2138 w->update_mode_line = Qt;
2139 XFASTINT (w->last_modified) = 0;
2140 if (pos > opoint)
2141 SET_PT (pos);
2142 if (n < 0)
2143 {
2144 SET_PT (pos);
2145 tem = Fvertical_motion (make_number (ht));
2146 if (point > opoint || XFASTINT (tem) < ht)
2147 SET_PT (opoint);
2148 else
2149 Fvertical_motion (make_number (-1));
2150 }
2151 }
2152 else
f8026fd8
JB
2153 {
2154 if (noerror)
2155 return;
2156 else
2157 Fsignal (Qend_of_buffer, Qnil);
2158 }
7ab12479
JB
2159}
2160\f
2161/* This is the guts of Fscroll_up and Fscroll_down. */
2162
2163static void
2164scroll_command (n, direction)
2165 register Lisp_Object n;
2166 int direction;
2167{
2168 register int defalt;
2169 int count = specpdl_ptr - specpdl;
2170
95605e15
JB
2171 /* If selected window's buffer isn't current, make it current for the moment.
2172 But don't screw up if window_scroll gets an error. */
7ab12479 2173 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
95605e15
JB
2174 {
2175 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2176 Fset_buffer (XWINDOW (selected_window)->buffer);
2177 }
7ab12479
JB
2178
2179 defalt = (window_internal_height (XWINDOW (selected_window))
2180 - next_screen_context_lines);
2181 defalt = direction * (defalt < 1 ? 1 : defalt);
2182
265a9e55 2183 if (NILP (n))
f8026fd8 2184 window_scroll (selected_window, defalt, 0);
7ab12479 2185 else if (EQ (n, Qminus))
f8026fd8 2186 window_scroll (selected_window, - defalt, 0);
7ab12479
JB
2187 else
2188 {
2189 n = Fprefix_numeric_value (n);
f8026fd8 2190 window_scroll (selected_window, XINT (n) * direction, 0);
7ab12479 2191 }
95605e15
JB
2192
2193 unbind_to (count, Qnil);
7ab12479
JB
2194}
2195
2196DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2197 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2198A near full screen is `next-screen-context-lines' less than a full screen.\n\
2199When calling from a program, supply a number as argument or nil.")
2200 (n)
2201 Lisp_Object n;
2202{
2203 scroll_command (n, 1);
2204 return Qnil;
2205}
2206
2207DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2208 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2209A near full screen is `next-screen-context-lines' less than a full screen.\n\
2210When calling from a program, supply a number as argument or nil.")
2211 (n)
2212 Lisp_Object n;
2213{
2214 scroll_command (n, -1);
2215 return Qnil;
2216}
2217
2218DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
99e5add3 2219 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
7ab12479
JB
2220The next window is the one below the current one; or the one at the top\n\
2221if the current one is at the bottom.\n\
2222When calling from a program, supply a number as argument or nil.\n\
2223\n\
2224If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
2225specifies the window to scroll.\n\
2226If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2227showing that buffer, popping the buffer up if necessary.")
2228 (n)
2229 register Lisp_Object n;
2230{
2231 register Lisp_Object window;
2232 register int ht;
2233 register struct window *w;
2234 register int count = specpdl_ptr - specpdl;
2235
2236 if (MINI_WINDOW_P (XWINDOW (selected_window))
265a9e55 2237 && !NILP (Vminibuf_scroll_window))
7ab12479
JB
2238 window = Vminibuf_scroll_window;
2239 /* If buffer is specified, scroll that buffer. */
265a9e55 2240 else if (!NILP (Vother_window_scroll_buffer))
7ab12479
JB
2241 {
2242 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
265a9e55 2243 if (NILP (window))
7ab12479
JB
2244 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2245 }
2246 else
dbc4e1c1
JB
2247 {
2248 /* Nothing specified; look for a neighboring window on the same
2249 frame. */
2250 window = Fnext_window (selected_window, Qnil, Qnil);
2251
2252 if (EQ (window, selected_window))
2253 /* That didn't get us anywhere; look for a window on another
2254 visible frame. */
2255 do
2256 window = Fnext_window (window, Qnil, Qt);
2257 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
2258 && ! EQ (window, selected_window));
2259 }
2260
605be8af 2261 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2262
2263 if (EQ (window, selected_window))
2264 error ("There is no other window");
2265
2266 w = XWINDOW (window);
2267 ht = window_internal_height (w);
2268
2269 /* Don't screw up if window_scroll gets an error. */
2270 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2271
2272 Fset_buffer (w->buffer);
2273 SET_PT (marker_position (w->pointm));
2274
265a9e55 2275 if (NILP (n))
f8026fd8 2276 window_scroll (window, ht - next_screen_context_lines, 1);
7ab12479 2277 else if (EQ (n, Qminus))
f8026fd8 2278 window_scroll (window, next_screen_context_lines - ht, 1);
7ab12479
JB
2279 else
2280 {
2281 if (XTYPE (n) == Lisp_Cons)
2282 n = Fcar (n);
2283 CHECK_NUMBER (n, 0);
f8026fd8 2284 window_scroll (window, XINT (n), 1);
7ab12479
JB
2285 }
2286
2287 Fset_marker (w->pointm, make_number (point), Qnil);
f4e7b2c2 2288 unbind_to (count, Qnil);
7ab12479
JB
2289
2290 return Qnil;
2291}
2292\f
644b477c 2293DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
7ab12479
JB
2294 "Scroll selected window display ARG columns left.\n\
2295Default for ARG is window width minus 2.")
2296 (arg)
2297 register Lisp_Object arg;
2298{
2299
265a9e55 2300 if (NILP (arg))
b8baad40 2301 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
7ab12479
JB
2302 else
2303 arg = Fprefix_numeric_value (arg);
2304
2305 return
2306 Fset_window_hscroll (selected_window,
2307 make_number (XINT (XWINDOW (selected_window)->hscroll)
2308 + XINT (arg)));
2309}
2310
644b477c 2311DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
7ab12479
JB
2312 "Scroll selected window display ARG columns right.\n\
2313Default for ARG is window width minus 2.")
2314 (arg)
2315 register Lisp_Object arg;
2316{
265a9e55 2317 if (NILP (arg))
b8baad40 2318 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
7ab12479
JB
2319 else
2320 arg = Fprefix_numeric_value (arg);
2321
2322 return
2323 Fset_window_hscroll (selected_window,
2324 make_number (XINT (XWINDOW (selected_window)->hscroll)
2325 - XINT (arg)));
2326}
2327
2328DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
44fa5b1e 2329 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
7ab12479 2330The desired position of point is always relative to the current window.\n\
44fa5b1e
JB
2331Just C-u as prefix means put point in the center of the window.\n\
2332No arg (i.e., it is nil) erases the entire frame and then\n\
2333redraws with point in the center of the current window.")
7ab12479
JB
2334 (n)
2335 register Lisp_Object n;
2336{
2337 register struct window *w = XWINDOW (selected_window);
2338 register int ht = window_internal_height (w);
2339 register int opoint = point;
2340
265a9e55 2341 if (NILP (n))
7ab12479 2342 {
44fa5b1e 2343 extern int frame_garbaged;
7ab12479 2344
44fa5b1e 2345 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
7ab12479
JB
2346 XFASTINT (n) = ht / 2;
2347 }
2348 else if (XTYPE (n) == Lisp_Cons) /* Just C-u. */
2349 {
2350 XFASTINT (n) = ht / 2;
2351 }
2352 else
2353 {
2354 n = Fprefix_numeric_value (n);
2355 CHECK_NUMBER (n, 0);
2356 }
2357
2358 if (XINT (n) < 0)
2359 XSETINT (n, XINT (n) + ht);
2360
2361 XSETINT (n, - XINT (n));
2362
2363 Fvertical_motion (n);
2364 Fset_marker (w->start, make_number (point), w->buffer);
2365 w->start_at_line_beg = Fbolp ();
2366
2367 SET_PT (opoint);
2368 w->force_start = Qt;
2369
2370 return Qnil;
2371}
2372\f
2373DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
2374 1, 1, "P",
2375 "Position point relative to window.\n\
2376With no argument, position text at center of window.\n\
44fa5b1e 2377An argument specifies frame line; zero means top of window,\n\
7ab12479
JB
2378negative means relative to bottom of window.")
2379 (arg)
2380 register Lisp_Object arg;
2381{
2382 register struct window *w = XWINDOW (selected_window);
2383 register int height = window_internal_height (w);
2384 register int start;
2385
265a9e55 2386 if (NILP (arg))
7ab12479
JB
2387 XFASTINT (arg) = height / 2;
2388 else
2389 {
2390 arg = Fprefix_numeric_value (arg);
2391 if (XINT (arg) < 0)
2392 XSETINT (arg, XINT (arg) + height);
2393 }
2394
2395 start = marker_position (w->start);
2396 if (start < BEGV || start > ZV)
2397 {
2398 Fvertical_motion (make_number (- height / 2));
2399 Fset_marker (w->start, make_number (point), w->buffer);
2400 w->start_at_line_beg = Fbolp ();
2401 w->force_start = Qt;
2402 }
2403 else
2404 SET_PT (start);
2405
2406 return Fvertical_motion (arg);
2407}
2408\f
2409struct save_window_data
2410 {
2411 int size_from_Lisp_Vector_struct;
2412 struct Lisp_Vector *next_from_Lisp_Vector_struct;
44fa5b1e 2413 Lisp_Object frame_width, frame_height;
bdc727bf 2414 Lisp_Object selected_frame;
7ab12479
JB
2415 Lisp_Object current_window;
2416 Lisp_Object current_buffer;
2417 Lisp_Object minibuf_scroll_window;
2418 Lisp_Object root_window;
bdc727bf 2419 Lisp_Object focus_frame;
7ab12479
JB
2420 /* A vector, interpreted as a struct saved_window */
2421 Lisp_Object saved_windows;
2422 };
ff06df24
JB
2423
2424/* Arg to Fmake_vector */
2425#define SAVE_WINDOW_DATA_SIZE \
2426 ((sizeof (struct save_window_data) \
2427 - (sizeof (struct Lisp_Vector) \
2428 /* Don't count the contents member of the struct Lisp_Vector */ \
2429 - sizeof (Lisp_Object))) \
2430 / sizeof (Lisp_Object))
7ab12479
JB
2431
2432/* This is saved as a Lisp_Vector */
2433struct saved_window
2434 {
2435 /* these first two must agree with struct Lisp_Vector in lisp.h */
2436 int size_from_Lisp_Vector_struct;
2437 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2438
2439 Lisp_Object window;
2440 Lisp_Object buffer, start, pointm, mark;
2441 Lisp_Object left, top, width, height, hscroll;
2442 Lisp_Object parent, prev;
2443 Lisp_Object start_at_line_beg;
2444 Lisp_Object display_table;
2445 };
2446#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2447
2448#define SAVED_WINDOW_N(swv,n) \
2449 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2450
2451DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
2452 "T if OBJECT is a window-configration object.")
2453 (obj)
2454 Lisp_Object obj;
2455{
2456 if (XTYPE (obj) == Lisp_Window_Configuration)
2457 return Qt;
2458 return Qnil;
2459}
2460
2461
d5b2799e
RS
2462DEFUN ("set-window-configuration", Fset_window_configuration,
2463 Sset_window_configuration, 1, 1, 0,
7ab12479
JB
2464 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2465CONFIGURATION must be a value previously returned\n\
2466by `current-window-configuration' (which see).")
2f83aebe
JB
2467 (configuration)
2468 Lisp_Object configuration;
7ab12479 2469{
7ab12479
JB
2470 register struct save_window_data *data;
2471 struct Lisp_Vector *saved_windows;
7ab12479 2472 Lisp_Object new_current_buffer;
fd482be5 2473 Lisp_Object frame;
44fa5b1e 2474 FRAME_PTR f;
7ab12479 2475
2f83aebe 2476 while (XTYPE (configuration) != Lisp_Window_Configuration)
7ab12479 2477 {
2f83aebe
JB
2478 configuration = wrong_type_argument (intern ("window-configuration-p"),
2479 configuration);
7ab12479
JB
2480 }
2481
2f83aebe 2482 data = (struct save_window_data *) XVECTOR (configuration);
7ab12479
JB
2483 saved_windows = XVECTOR (data->saved_windows);
2484
7ab12479 2485 new_current_buffer = data->current_buffer;
265a9e55 2486 if (NILP (XBUFFER (new_current_buffer)->name))
7ab12479
JB
2487 new_current_buffer = Qnil;
2488
fd482be5
JB
2489 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
2490 f = XFRAME (frame);
9ace597f 2491
fd482be5
JB
2492 /* If f is a dead frame, don't bother rebuilding its window tree.
2493 However, there is other stuff we should still try to do below. */
2494 if (FRAME_LIVE_P (f))
7ab12479 2495 {
fd482be5
JB
2496 register struct window *w;
2497 register struct saved_window *p;
2498 int k;
2499
2500 /* If the frame has been resized since this window configuration was
2501 made, we change the frame to the size specified in the
2502 configuration, restore the configuration, and then resize it
2503 back. We keep track of the prevailing height in these variables. */
2504 int previous_frame_height = FRAME_HEIGHT (f);
2505 int previous_frame_width = FRAME_WIDTH (f);
2506
2507 if (XFASTINT (data->frame_height) != previous_frame_height
2508 || XFASTINT (data->frame_width) != previous_frame_width)
2509 change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
2510
2511 windows_or_buffers_changed++;
2512
2513 /* Kludge Alert!
2514 Mark all windows now on frame as "deleted".
2515 Restoring the new configuration "undeletes" any that are in it.
2516
2517 Save their current buffers in their height fields, since we may
2518 need it later, if a buffer saved in the configuration is now
2519 dead. */
2520 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
2521
2522 for (k = 0; k < saved_windows->size; k++)
2523 {
2524 p = SAVED_WINDOW_N (saved_windows, k);
2525 w = XWINDOW (p->window);
2526 w->next = Qnil;
7ab12479 2527
fd482be5
JB
2528 if (!NILP (p->parent))
2529 w->parent = SAVED_WINDOW_N (saved_windows,
2530 XFASTINT (p->parent))->window;
2531 else
2532 w->parent = Qnil;
7ab12479 2533
fd482be5 2534 if (!NILP (p->prev))
7ab12479 2535 {
fd482be5
JB
2536 w->prev = SAVED_WINDOW_N (saved_windows,
2537 XFASTINT (p->prev))->window;
2538 XWINDOW (w->prev)->next = p->window;
2539 }
2540 else
2541 {
2542 w->prev = Qnil;
2543 if (!NILP (w->parent))
2544 {
2545 if (EQ (p->width, XWINDOW (w->parent)->width))
2546 {
2547 XWINDOW (w->parent)->vchild = p->window;
2548 XWINDOW (w->parent)->hchild = Qnil;
2549 }
2550 else
2551 {
2552 XWINDOW (w->parent)->hchild = p->window;
2553 XWINDOW (w->parent)->vchild = Qnil;
2554 }
2555 }
2556 }
2557
2558 /* If we squirreled away the buffer in the window's height,
2559 restore it now. */
2560 if (XTYPE (w->height) == Lisp_Buffer)
2561 w->buffer = w->height;
2562 w->left = p->left;
2563 w->top = p->top;
2564 w->width = p->width;
2565 w->height = p->height;
2566 w->hscroll = p->hscroll;
2567 w->display_table = p->display_table;
2568 XFASTINT (w->last_modified) = 0;
2569
2570 /* Reinstall the saved buffer and pointers into it. */
2571 if (NILP (p->buffer))
2572 w->buffer = p->buffer;
2573 else
2574 {
2575 if (!NILP (XBUFFER (p->buffer)->name))
2576 /* If saved buffer is alive, install it. */
2577 {
2578 w->buffer = p->buffer;
2579 w->start_at_line_beg = p->start_at_line_beg;
2580 set_marker_restricted (w->start,
2581 Fmarker_position (p->start),
2582 w->buffer);
2583 set_marker_restricted (w->pointm,
2584 Fmarker_position (p->pointm),
2585 w->buffer);
2586 Fset_marker (XBUFFER (w->buffer)->mark,
2587 Fmarker_position (p->mark), w->buffer);
2588
2589 /* As documented in Fcurrent_window_configuration, don't
2590 save the location of point in the buffer which was current
2591 when the window configuration was recorded. */
2592 if (!EQ (p->buffer, new_current_buffer) &&
2593 XBUFFER (p->buffer) == current_buffer)
2594 Fgoto_char (w->pointm);
2595 }
52a68e98
RS
2596 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
2597 /* Else unless window has a live buffer, get one. */
7ab12479 2598 {
fd482be5
JB
2599 w->buffer = Fcdr (Fcar (Vbuffer_alist));
2600 /* This will set the markers to beginning of visible
2601 range. */
2602 set_marker_restricted (w->start, make_number (0), w->buffer);
2603 set_marker_restricted (w->pointm, make_number (0),w->buffer);
2604 w->start_at_line_beg = Qt;
7ab12479
JB
2605 }
2606 else
fd482be5 2607 /* Keeping window's old buffer; make sure the markers
52a68e98 2608 are real. */
7ab12479 2609 {
fd482be5
JB
2610 /* Set window markers at start of visible range. */
2611 if (XMARKER (w->start)->buffer == 0)
2612 set_marker_restricted (w->start, make_number (0),
2613 w->buffer);
2614 if (XMARKER (w->pointm)->buffer == 0)
2615 set_marker_restricted (w->pointm,
2616 (make_number
2617 (BUF_PT (XBUFFER (w->buffer)))),
2618 w->buffer);
2619 w->start_at_line_beg = Qt;
7ab12479
JB
2620 }
2621 }
2622 }
9ace597f 2623
fd482be5
JB
2624 FRAME_ROOT_WINDOW (f) = data->root_window;
2625 Fselect_window (data->current_window);
7ab12479 2626
fd482be5 2627#ifdef MULTI_FRAME
db269683
JB
2628 if (NILP (data->focus_frame)
2629 || (XTYPE (data->focus_frame) == Lisp_Frame
2630 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
2631 Fredirect_frame_focus (frame, data->focus_frame);
fd482be5 2632#endif
7ab12479 2633
fd482be5
JB
2634#if 0 /* I don't understand why this is needed, and it causes problems
2635 when the frame's old selected window has been deleted. */
2636#ifdef MULTI_FRAME
2637 if (f != selected_frame && ! FRAME_TERMCAP_P (f))
d5b2799e 2638 Fhandle_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
fd482be5
JB
2639#endif
2640#endif
2641
2642 /* Set the screen height to the value it had before this function. */
2643 if (previous_frame_height != FRAME_HEIGHT (f)
2644 || previous_frame_width != FRAME_WIDTH (f))
2645 change_frame_size (f, previous_frame_height, previous_frame_width,
2646 0, 0);
2647 }
bdc727bf 2648
ad854249 2649#ifdef MULTI_FRAME
bdc727bf 2650 /* Fselect_window will have made f the selected frame, so we
d5b2799e 2651 reselect the proper frame here. Fhandle_switch_frame will change the
bdc727bf
JB
2652 selected window too, but that doesn't make the call to
2653 Fselect_window above totally superfluous; it still sets f's
2654 selected window. */
fd482be5 2655 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
d5b2799e 2656 Fhandle_switch_frame (data->selected_frame, Qnil);
ad854249 2657#endif
bdc727bf
JB
2658
2659 if (!NILP (new_current_buffer))
2660 Fset_buffer (new_current_buffer);
2661
7ab12479
JB
2662 Vminibuf_scroll_window = data->minibuf_scroll_window;
2663 return (Qnil);
2664}
2665
44fa5b1e 2666/* Mark all windows now on frame as deleted
7ab12479
JB
2667 by setting their buffers to nil. */
2668
fd482be5 2669void
7ab12479
JB
2670delete_all_subwindows (w)
2671 register struct window *w;
2672{
265a9e55 2673 if (!NILP (w->next))
7ab12479 2674 delete_all_subwindows (XWINDOW (w->next));
265a9e55 2675 if (!NILP (w->vchild))
7ab12479 2676 delete_all_subwindows (XWINDOW (w->vchild));
265a9e55 2677 if (!NILP (w->hchild))
7ab12479 2678 delete_all_subwindows (XWINDOW (w->hchild));
605be8af
JB
2679
2680 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
2681
2682 /* We set all three of these fields to nil, to make sure that we can
2683 distinguish this dead window from any live window. Live leaf
2684 windows will have buffer set, and combination windows will have
2685 vchild or hchild set. */
2686 w->buffer = Qnil;
2687 w->vchild = Qnil;
2688 w->hchild = Qnil;
7ab12479
JB
2689}
2690\f
2691static int
2692count_windows (window)
2693 register struct window *window;
2694{
2695 register int count = 1;
265a9e55 2696 if (!NILP (window->next))
7ab12479 2697 count += count_windows (XWINDOW (window->next));
265a9e55 2698 if (!NILP (window->vchild))
7ab12479 2699 count += count_windows (XWINDOW (window->vchild));
265a9e55 2700 if (!NILP (window->hchild))
7ab12479
JB
2701 count += count_windows (XWINDOW (window->hchild));
2702 return count;
2703}
2704
2705static int
2706save_window_save (window, vector, i)
2707 Lisp_Object window;
2708 struct Lisp_Vector *vector;
2709 int i;
2710{
2711 register struct saved_window *p;
2712 register struct window *w;
2713 register Lisp_Object tem;
2714
265a9e55 2715 for (;!NILP (window); window = w->next)
7ab12479
JB
2716 {
2717 p = SAVED_WINDOW_N (vector, i);
2718 w = XWINDOW (window);
2719
2720 XFASTINT (w->temslot) = i++;
2721 p->window = window;
2722 p->buffer = w->buffer;
2723 p->left = w->left;
2724 p->top = w->top;
2725 p->width = w->width;
2726 p->height = w->height;
2727 p->hscroll = w->hscroll;
2728 p->display_table = w->display_table;
265a9e55 2729 if (!NILP (w->buffer))
7ab12479
JB
2730 {
2731 /* Save w's value of point in the window configuration.
2732 If w is the selected window, then get the value of point
2733 from the buffer; pointm is garbage in the selected window. */
2734 if (EQ (window, selected_window))
2735 {
2736 p->pointm = Fmake_marker ();
2737 Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
2738 w->buffer);
2739 }
2740 else
2741 p->pointm = Fcopy_marker (w->pointm);
2742
2743 p->start = Fcopy_marker (w->start);
2744 p->start_at_line_beg = w->start_at_line_beg;
2745
2746 tem = XBUFFER (w->buffer)->mark;
2747 p->mark = Fcopy_marker (tem);
2748 }
2749 else
2750 {
2751 p->pointm = Qnil;
2752 p->start = Qnil;
2753 p->mark = Qnil;
2754 p->start_at_line_beg = Qnil;
2755 }
2756
265a9e55 2757 if (NILP (w->parent))
7ab12479
JB
2758 p->parent = Qnil;
2759 else
2760 p->parent = XWINDOW (w->parent)->temslot;
2761
265a9e55 2762 if (NILP (w->prev))
7ab12479
JB
2763 p->prev = Qnil;
2764 else
2765 p->prev = XWINDOW (w->prev)->temslot;
2766
265a9e55 2767 if (!NILP (w->vchild))
7ab12479 2768 i = save_window_save (w->vchild, vector, i);
265a9e55 2769 if (!NILP (w->hchild))
7ab12479
JB
2770 i = save_window_save (w->hchild, vector, i);
2771 }
2772
2773 return i;
2774}
2775
2776DEFUN ("current-window-configuration",
43bad991 2777 Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
44fa5b1e
JB
2778 "Return an object representing the current window configuration of FRAME.\n\
2779If FRAME is nil or omitted, use the selected frame.\n\
7ab12479
JB
2780This describes the number of windows, their sizes and current buffers,\n\
2781and for each displayed buffer, where display starts, and the positions of\n\
2782point and mark. An exception is made for point in the current buffer:\n\
bdc727bf
JB
2783its value is -not- saved.\n\
2784This also records the currently selected frame, and FRAME's focus\n\
2785redirection (see `redirect-frame-focus').")
44fa5b1e
JB
2786 (frame)
2787 Lisp_Object frame;
7ab12479
JB
2788{
2789 register Lisp_Object tem;
2790 register int n_windows;
2791 register struct save_window_data *data;
2792 register int i;
44fa5b1e 2793 FRAME_PTR f;
43bad991 2794
44fa5b1e
JB
2795 if (NILP (frame))
2796 f = selected_frame;
43bad991
JB
2797 else
2798 {
44fa5b1e
JB
2799 CHECK_LIVE_FRAME (frame, 0);
2800 f = XFRAME (frame);
43bad991 2801 }
7ab12479 2802
44fa5b1e 2803 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
7ab12479
JB
2804 data = (struct save_window_data *)
2805 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE),
2806 Qnil));
44fa5b1e
JB
2807 XFASTINT (data->frame_width) = FRAME_WIDTH (f);
2808 XFASTINT (data->frame_height) = FRAME_HEIGHT (f);
ad854249 2809#ifdef MULTI_FRAME
bdc727bf 2810 XSET (data->selected_frame, Lisp_Frame, selected_frame);
ad854249 2811#endif
44fa5b1e 2812 data->current_window = FRAME_SELECTED_WINDOW (f);
7ab12479
JB
2813 XSET (data->current_buffer, Lisp_Buffer, current_buffer);
2814 data->minibuf_scroll_window = Vminibuf_scroll_window;
44fa5b1e 2815 data->root_window = FRAME_ROOT_WINDOW (f);
bdc727bf 2816 data->focus_frame = FRAME_FOCUS_FRAME (f);
7ab12479
JB
2817 tem = Fmake_vector (make_number (n_windows), Qnil);
2818 data->saved_windows = tem;
2819 for (i = 0; i < n_windows; i++)
2820 XVECTOR (tem)->contents[i]
2821 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
44fa5b1e 2822 save_window_save (FRAME_ROOT_WINDOW (f),
7ab12479
JB
2823 XVECTOR (tem), 0);
2824 XSET (tem, Lisp_Window_Configuration, data);
2825 return (tem);
2826}
2827
2828DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
2829 0, UNEVALLED, 0,
2830 "Execute body, preserving window sizes and contents.\n\
2831Restores which buffer appears in which window, where display starts,\n\
2832as well as the current buffer.\n\
2833Does not restore the value of point in current buffer.")
2834 (args)
2835 Lisp_Object args;
2836{
2837 register Lisp_Object val;
2838 register int count = specpdl_ptr - specpdl;
2839
2840 record_unwind_protect (Fset_window_configuration,
43bad991 2841 Fcurrent_window_configuration (Qnil));
7ab12479
JB
2842 val = Fprogn (args);
2843 return unbind_to (count, val);
2844}
2845\f
2846init_window_once ()
2847{
44fa5b1e
JB
2848#ifdef MULTI_FRAME
2849 selected_frame = make_terminal_frame ();
2850 minibuf_window = selected_frame->minibuffer_window;
2851 selected_window = selected_frame->selected_window;
2852 last_nonminibuf_frame = selected_frame;
2853#else /* not MULTI_FRAME */
7ab12479
JB
2854 extern Lisp_Object get_minibuffer ();
2855
95605e15 2856 minibuf_window = make_window ();
4b206065 2857 FRAME_ROOT_WINDOW (selected_frame) = make_window ();
7ab12479 2858
44fa5b1e
JB
2859 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->next = minibuf_window;
2860 XWINDOW (minibuf_window)->prev = FRAME_ROOT_WINDOW (selected_frame);
4b206065 2861 XWINDOW (minibuf_window)->mini_p = Qt;
7ab12479
JB
2862
2863 /* These values 9 and 10 are arbitrary,
2864 just so that there is "something there."
2865 Correct values are put in in init_xdisp */
2866
44fa5b1e 2867 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->width) = 10;
7ab12479
JB
2868 XFASTINT (XWINDOW (minibuf_window)->width) = 10;
2869
44fa5b1e 2870 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->height) = 9;
7ab12479
JB
2871 XFASTINT (XWINDOW (minibuf_window)->top) = 9;
2872 XFASTINT (XWINDOW (minibuf_window)->height) = 1;
2873
2874 /* Prevent error in Fset_window_buffer. */
44fa5b1e 2875 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->buffer = Qt;
7ab12479
JB
2876 XWINDOW (minibuf_window)->buffer = Qt;
2877
2878 /* Now set them up for real. */
44fa5b1e 2879 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame),
e5d77022 2880 Fcurrent_buffer ());
7ab12479
JB
2881 Fset_window_buffer (minibuf_window, get_minibuffer (0));
2882
44fa5b1e 2883 selected_window = FRAME_ROOT_WINDOW (selected_frame);
1d8d96fa
JB
2884 /* Make sure this window seems more recently used than
2885 a newly-created, never-selected window. Increment
2886 window_select_count so the first selection ever will get
2887 something newer than this. */
2888 XFASTINT (XWINDOW (selected_window)->use_time) = ++window_select_count;
44fa5b1e 2889#endif /* not MULTI_FRAME */
7ab12479
JB
2890}
2891
2892syms_of_window ()
2893{
2894 Qwindowp = intern ("windowp");
2895 staticpro (&Qwindowp);
2896
806b4d9b
JB
2897 Qwindow_live_p = intern ("window-live-p");
2898 staticpro (&Qwindow_live_p);
605be8af 2899
2f83aebe 2900#ifndef MULTI_FRAME
7ab12479
JB
2901 /* Make sure all windows get marked */
2902 staticpro (&minibuf_window);
2f83aebe 2903#endif
7ab12479
JB
2904
2905 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
2906 "Non-nil means call as function to display a help buffer.\n\
2907Used by `with-output-to-temp-buffer'.");
2908 Vtemp_buffer_show_function = Qnil;
2909
2910 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
2911 "If non-nil, function to call to handle `display-buffer'.\n\
2912It will receive two args, the buffer and a flag which if non-nil means\n\
2913 that the currently selected window is not acceptable.\n\
2914Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
2915work using this function.");
2916 Vdisplay_buffer_function = Qnil;
2917
7ab12479
JB
2918 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
2919 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
2920 Vminibuf_scroll_window = Qnil;
2921
2922 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
2923 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
2924 Vother_window_scroll_buffer = Qnil;
2925
44fa5b1e 2926 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
700f75a4 2927 "*Non-nil means `display-buffer' should make a separate frame.");
44fa5b1e 2928 pop_up_frames = 0;
7ab12479 2929
44fa5b1e
JB
2930 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
2931 "*If non-nil, function to call to handle automatic new frame creation.\n\
2932It is called with no arguments and should return a newly created frame.\n\
7ab12479 2933\n\
44fa5b1e
JB
2934A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
2935where `pop-up-frame-alist' would hold the default frame parameters.");
2936 Vpop_up_frame_function = Qnil;
7ab12479
JB
2937
2938 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
2939 "*Non-nil means display-buffer should make new windows.");
2940 pop_up_windows = 1;
2941
2942 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
2943 "*Number of lines of continuity when scrolling by screenfuls.");
2944 next_screen_context_lines = 2;
2945
2946 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
2947 "*display-buffer would prefer to split the largest window if this large.\n\
2948If there is only one window, it is split regardless of this value.");
2949 split_height_threshold = 500;
2950
2951 DEFVAR_INT ("window-min-height", &window_min_height,
2952 "*Delete any window less than this tall (including its mode line).");
2953 window_min_height = 4;
2954
2955 DEFVAR_INT ("window-min-width", &window_min_width,
2956 "*Delete any window less than this wide.");
2957 window_min_width = 10;
2958
2959 defsubr (&Sselected_window);
2960 defsubr (&Sminibuffer_window);
2961 defsubr (&Swindow_minibuffer_p);
2962 defsubr (&Swindowp);
806b4d9b 2963 defsubr (&Swindow_live_p);
7ab12479
JB
2964 defsubr (&Spos_visible_in_window_p);
2965 defsubr (&Swindow_buffer);
2966 defsubr (&Swindow_height);
2967 defsubr (&Swindow_width);
2968 defsubr (&Swindow_hscroll);
2969 defsubr (&Sset_window_hscroll);
2970 defsubr (&Swindow_edges);
d5783c40
JB
2971 defsubr (&Scoordinates_in_window_p);
2972 defsubr (&Swindow_at);
7ab12479
JB
2973 defsubr (&Swindow_point);
2974 defsubr (&Swindow_start);
2975 defsubr (&Swindow_end);
2976 defsubr (&Sset_window_point);
2977 defsubr (&Sset_window_start);
2978 defsubr (&Swindow_dedicated_p);
d207b766 2979 defsubr (&Sset_window_dedicated_p);
7ab12479
JB
2980 defsubr (&Swindow_display_table);
2981 defsubr (&Sset_window_display_table);
2982 defsubr (&Snext_window);
2983 defsubr (&Sprevious_window);
2984 defsubr (&Sother_window);
2985 defsubr (&Sget_lru_window);
2986 defsubr (&Sget_largest_window);
2987 defsubr (&Sget_buffer_window);
2988 defsubr (&Sdelete_other_windows);
2989 defsubr (&Sdelete_windows_on);
2990 defsubr (&Sreplace_buffer_in_windows);
2991 defsubr (&Sdelete_window);
2992 defsubr (&Sset_window_buffer);
2993 defsubr (&Sselect_window);
2994 defsubr (&Sdisplay_buffer);
2995 defsubr (&Ssplit_window);
2996 defsubr (&Senlarge_window);
2997 defsubr (&Sshrink_window);
2998 defsubr (&Sscroll_up);
2999 defsubr (&Sscroll_down);
3000 defsubr (&Sscroll_left);
3001 defsubr (&Sscroll_right);
3002 defsubr (&Sscroll_other_window);
3003 defsubr (&Srecenter);
3004 defsubr (&Smove_to_window_line);
3005 defsubr (&Swindow_configuration_p);
3006 defsubr (&Sset_window_configuration);
3007 defsubr (&Scurrent_window_configuration);
3008 defsubr (&Ssave_window_excursion);
3009}
3010
3011keys_of_window ()
3012{
3013 initial_define_key (control_x_map, '1', "delete-other-windows");
3014 initial_define_key (control_x_map, '2', "split-window");
3015 initial_define_key (control_x_map, '0', "delete-window");
3016 initial_define_key (control_x_map, 'o', "other-window");
3017 initial_define_key (control_x_map, '^', "enlarge-window");
3018 initial_define_key (control_x_map, '<', "scroll-left");
3019 initial_define_key (control_x_map, '>', "scroll-right");
3020
3021 initial_define_key (global_map, Ctl ('V'), "scroll-up");
3022 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
3023 initial_define_key (meta_map, 'v', "scroll-down");
3024
3025 initial_define_key (global_map, Ctl('L'), "recenter");
3026 initial_define_key (meta_map, 'r', "move-to-window-line");
3027}