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