(vc-backend-diff): Use diff-switches, not vc-diff-options.
[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;
270967b2 1526 w->hscroll = 0;
7ab12479
JB
1527 Fset_marker (w->pointm,
1528 make_number (BUF_PT (XBUFFER (buffer))),
1529 buffer);
1530 set_marker_restricted (w->start,
1531 make_number (XBUFFER (buffer)->last_window_start),
1532 buffer);
1533 w->start_at_line_beg = Qnil;
1534 XFASTINT (w->last_modified) = 0;
1535 windows_or_buffers_changed++;
1536 if (EQ (window, selected_window))
1537 Fset_buffer (buffer);
1538
1539 return Qnil;
1540}
1541
1542DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1543 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1544The main editor command loop selects the buffer of the selected window\n\
1545before each command.")
1546 (window)
1547 register Lisp_Object window;
1548{
1549 register struct window *w;
1550 register struct window *ow = XWINDOW (selected_window);
1551
605be8af 1552 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1553
1554 w = XWINDOW (window);
1555
265a9e55 1556 if (NILP (w->buffer))
7ab12479
JB
1557 error ("Trying to select deleted window or non-leaf window");
1558
1559 XFASTINT (w->use_time) = ++window_select_count;
1560 if (EQ (window, selected_window))
1561 return window;
1562
1563 Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
1564 ow->buffer);
1565
1566 selected_window = window;
44fa5b1e
JB
1567#ifdef MULTI_FRAME
1568 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
7ab12479 1569 {
44fa5b1e 1570 XFRAME (WINDOW_FRAME (w))->selected_window = window;
d5b2799e 1571 Fhandle_switch_frame (WINDOW_FRAME (w), Qnil);
7ab12479
JB
1572 }
1573 else
44fa5b1e 1574 selected_frame->selected_window = window;
7ab12479
JB
1575#endif
1576
1577 record_buffer (w->buffer);
1578 Fset_buffer (w->buffer);
1579
1580 /* Go to the point recorded in the window.
1581 This is important when the buffer is in more
1582 than one window. It also matters when
1583 redisplay_window has altered point after scrolling,
1584 because it makes the change only in the window. */
1585 {
1586 register int new_point = marker_position (w->pointm);
1587 if (new_point < BEGV)
1588 SET_PT (BEGV);
1589 if (new_point > ZV)
1590 SET_PT (ZV);
1591 else
1592 SET_PT (new_point);
1593 }
1594
1595 windows_or_buffers_changed++;
1596 return window;
1597}
1598
35aaf00c
RM
1599DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
1600 "BDisplay buffer:\nP",
7ab12479
JB
1601 "Make BUFFER appear in some window but don't select it.\n\
1602BUFFER can be a buffer or a buffer name.\n\
1603If BUFFER is shown already in some window, just use that one,\n\
1604unless the window is the selected window and the optional second\n\
46d3268a 1605argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
7ab12479
JB
1606Returns the window displaying BUFFER.")
1607 (buffer, not_this_window)
1608 register Lisp_Object buffer, not_this_window;
1609{
1610 register Lisp_Object window;
1611
1612 buffer = Fget_buffer (buffer);
1613 CHECK_BUFFER (buffer, 0);
1614
265a9e55 1615 if (!NILP (Vdisplay_buffer_function))
7ab12479
JB
1616 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
1617
265a9e55 1618 if (NILP (not_this_window)
7ab12479
JB
1619 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
1620 return selected_window;
1621
1622 window = Fget_buffer_window (buffer, Qnil);
265a9e55
JB
1623 if (!NILP (window)
1624 && (NILP (not_this_window) || !EQ (window, selected_window)))
7ab12479
JB
1625 return window;
1626
44fa5b1e
JB
1627#ifdef MULTI_FRAME
1628 /* If there are no frames open that have more than a minibuffer,
1629 we need to create a new frame. */
1630 if (pop_up_frames || last_nonminibuf_frame == 0)
7ab12479
JB
1631 {
1632 window
44fa5b1e 1633 = Fframe_selected_window (call0 (Vpop_up_frame_function));
7ab12479
JB
1634 Fset_window_buffer (window, buffer);
1635#if 0
d5b2799e 1636 Fhandle_switch_frame (XWINDOW (window)->frame, Qnil);
7ab12479
JB
1637#endif
1638 return window;
1639 }
44fa5b1e 1640#endif /* MULTI_FRAME */
7ab12479 1641
43bad991 1642 if (pop_up_windows
44fa5b1e
JB
1643#ifdef MULTI_FRAME
1644 || FRAME_MINIBUF_ONLY_P (selected_frame)
43bad991
JB
1645#endif
1646 )
7ab12479 1647 {
44fa5b1e 1648 Lisp_Object frames = Qnil;
43bad991 1649
44fa5b1e
JB
1650#ifdef MULTI_FRAME
1651 if (FRAME_MINIBUF_ONLY_P (selected_frame))
1652 XSET (frames, Lisp_Frame, last_nonminibuf_frame);
7ab12479
JB
1653#endif
1654 /* Don't try to create a window if would get an error */
1655 if (split_height_threshold < window_min_height << 1)
1656 split_height_threshold = window_min_height << 1;
1657
44fa5b1e 1658 window = Fget_largest_window (frames);
7ab12479 1659
265a9e55 1660 if (!NILP (window)
7ab12479 1661 && window_height (window) >= split_height_threshold
535e0b8e
JB
1662 && (XFASTINT (XWINDOW (window)->width)
1663 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
7ab12479
JB
1664 window = Fsplit_window (window, Qnil, Qnil);
1665 else
1666 {
44fa5b1e 1667 window = Fget_lru_window (frames);
7ab12479
JB
1668 if ((EQ (window, selected_window)
1669 || EQ (XWINDOW (window)->parent, Qnil))
1670 && window_height (window) >= window_min_height << 1)
1671 window = Fsplit_window (window, Qnil, Qnil);
1672 }
1673 }
1674 else
1675 window = Fget_lru_window (Qnil);
1676
1677 Fset_window_buffer (window, buffer);
1678 return window;
1679}
1680
1681void
1682temp_output_buffer_show (buf)
1683 register Lisp_Object buf;
1684{
1685 register struct buffer *old = current_buffer;
1686 register Lisp_Object window;
1687 register struct window *w;
1688
1689 Fset_buffer (buf);
1690 XBUFFER (buf)->save_modified = MODIFF;
1691 BEGV = BEG;
1692 ZV = Z;
1693 SET_PT (BEG);
1694 clip_changed = 1;
1695 set_buffer_internal (old);
1696
1697 if (!EQ (Vtemp_buffer_show_function, Qnil))
1698 call1 (Vtemp_buffer_show_function, buf);
1699 else
1700 {
1701 window = Fdisplay_buffer (buf, Qnil);
1702
44fa5b1e
JB
1703#ifdef MULTI_FRAME
1704 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
1705 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
1706#endif /* MULTI_FRAME */
7ab12479
JB
1707 Vminibuf_scroll_window = window;
1708 w = XWINDOW (window);
1709 XFASTINT (w->hscroll) = 0;
1710 set_marker_restricted (w->start, make_number (1), buf);
1711 set_marker_restricted (w->pointm, make_number (1), buf);
1712 }
1713}
1714\f
1715static
1716make_dummy_parent (window)
1717 Lisp_Object window;
1718{
1719 register Lisp_Object old, new;
1720 register struct window *o, *p;
1721
1722 old = window;
1723 XSETTYPE (old, Lisp_Vector);
1724 new = Fcopy_sequence (old);
1725 XSETTYPE (new, Lisp_Window);
1726
1727 o = XWINDOW (old);
1728 p = XWINDOW (new);
1729 XFASTINT (p->sequence_number) = ++sequence_number;
1730
1731 /* Put new into window structure in place of window */
1732 replace_window (window, new);
1733
1734 o->next = Qnil;
1735 o->prev = Qnil;
1736 o->vchild = Qnil;
1737 o->hchild = Qnil;
1738 o->parent = new;
1739
1740 p->start = Qnil;
1741 p->pointm = Qnil;
1742 p->buffer = Qnil;
1743}
1744
1745DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
1746 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1747WINDOW defaults to selected one and SIZE to half its size.\n\
1748If optional third arg HOR-FLAG is non-nil, split side by side\n\
1749and put SIZE columns in the first of the pair.")
1750 (window, chsize, horflag)
1751 Lisp_Object window, chsize, horflag;
1752{
1753 register Lisp_Object new;
1754 register struct window *o, *p;
1755 register int size;
1756
265a9e55 1757 if (NILP (window))
7ab12479
JB
1758 window = selected_window;
1759 else
605be8af 1760 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1761
1762 o = XWINDOW (window);
1763
265a9e55 1764 if (NILP (chsize))
7ab12479 1765 {
265a9e55 1766 if (!NILP (horflag))
7ab12479
JB
1767 /* Round odd size up, since this is for the left-hand window,
1768 and it will lose a column for the separators. */
1769 size = ((XFASTINT (o->width) + 1) & -2) >> 1;
1770 else
1771 size = XFASTINT (o->height) >> 1;
1772 }
1773 else
1774 {
1775 CHECK_NUMBER (chsize, 1);
1776 size = XINT (chsize);
1777 }
1778
1779 if (MINI_WINDOW_P (o))
1780 error ("Attempt to split minibuffer window");
44fa5b1e
JB
1781 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
1782 error ("Attempt to split unsplittable frame");
7ab12479 1783
a481b3ea 1784 check_min_window_sizes ();
7ab12479 1785
265a9e55 1786 if (NILP (horflag))
7ab12479
JB
1787 {
1788 if (size < window_min_height
1789 || size + window_min_height > XFASTINT (o->height))
1790 args_out_of_range_3 (window, chsize, horflag);
265a9e55
JB
1791 if (NILP (o->parent)
1792 || NILP (XWINDOW (o->parent)->vchild))
7ab12479
JB
1793 {
1794 make_dummy_parent (window);
1795 new = o->parent;
1796 XWINDOW (new)->vchild = window;
1797 }
1798 }
1799 else
1800 {
1801 if (size < window_min_width
1802 || size + window_min_width > XFASTINT (o->width))
1803 args_out_of_range_3 (window, chsize, horflag);
265a9e55
JB
1804 if (NILP (o->parent)
1805 || NILP (XWINDOW (o->parent)->hchild))
7ab12479
JB
1806 {
1807 make_dummy_parent (window);
1808 new = o->parent;
1809 XWINDOW (new)->hchild = window;
1810 }
1811 }
1812
1813 /* Now we know that window's parent is a vertical combination
1814 if we are dividing vertically, or a horizontal combination
1815 if we are making side-by-side windows */
1816
1817 windows_or_buffers_changed++;
1818 new = make_window ();
1819 p = XWINDOW (new);
1820
44fa5b1e 1821 p->frame = o->frame;
7ab12479 1822 p->next = o->next;
265a9e55 1823 if (!NILP (p->next))
7ab12479
JB
1824 XWINDOW (p->next)->prev = new;
1825 p->prev = window;
1826 o->next = new;
1827 p->parent = o->parent;
1828 p->buffer = Qt;
1829
1830 Fset_window_buffer (new, o->buffer);
1831
44fa5b1e 1832 /* Apportion the available frame space among the two new windows */
7ab12479 1833
265a9e55 1834 if (!NILP (horflag))
7ab12479
JB
1835 {
1836 p->height = o->height;
1837 p->top = o->top;
1838 XFASTINT (p->width) = XFASTINT (o->width) - size;
1839 XFASTINT (o->width) = size;
1840 XFASTINT (p->left) = XFASTINT (o->left) + size;
1841 }
1842 else
1843 {
1844 p->left = o->left;
1845 p->width = o->width;
1846 XFASTINT (p->height) = XFASTINT (o->height) - size;
1847 XFASTINT (o->height) = size;
1848 XFASTINT (p->top) = XFASTINT (o->top) + size;
1849 }
1850
1851 return new;
1852}
1853\f
1854DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
1855 "Make current window ARG lines bigger.\n\
1856From program, optional second arg non-nil means grow sideways ARG columns.")
1857 (n, side)
1858 register Lisp_Object n, side;
1859{
1860 CHECK_NUMBER (n, 0);
265a9e55 1861 change_window_height (XINT (n), !NILP (side));
7ab12479
JB
1862 return Qnil;
1863}
1864
1865DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
1866 "Make current window ARG lines smaller.\n\
1867From program, optional second arg non-nil means shrink sideways ARG columns.")
1868 (n, side)
1869 register Lisp_Object n, side;
1870{
1871 CHECK_NUMBER (n, 0);
265a9e55 1872 change_window_height (-XINT (n), !NILP (side));
7ab12479
JB
1873 return Qnil;
1874}
1875
1876int
1877window_height (window)
1878 Lisp_Object window;
1879{
1880 register struct window *p = XWINDOW (window);
1881 return XFASTINT (p->height);
1882}
1883
1884int
1885window_width (window)
1886 Lisp_Object window;
1887{
1888 register struct window *p = XWINDOW (window);
1889 return XFASTINT (p->width);
1890}
1891
05c2896a
JB
1892#define MINSIZE(w) \
1893 (widthflag \
1894 ? window_min_width \
1895 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
7ab12479
JB
1896
1897#define CURBEG(w) \
05c2896a 1898 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
7ab12479
JB
1899
1900#define CURSIZE(w) \
05c2896a 1901 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
7ab12479
JB
1902
1903/* Unlike set_window_height, this function
1904 also changes the heights of the siblings so as to
1905 keep everything consistent. */
1906
1907change_window_height (delta, widthflag)
1908 register int delta;
1909 int widthflag;
1910{
1911 register Lisp_Object parent;
1912 Lisp_Object window;
1913 register struct window *p;
1914 int *sizep;
1915 int (*sizefun) () = widthflag ? window_width : window_height;
1916 register int (*setsizefun) () = (widthflag
1917 ? set_window_width
1918 : set_window_height);
1919
a481b3ea 1920 check_min_window_sizes ();
7ab12479
JB
1921
1922 window = selected_window;
1923 while (1)
1924 {
1925 p = XWINDOW (window);
1926 parent = p->parent;
265a9e55 1927 if (NILP (parent))
7ab12479
JB
1928 {
1929 if (widthflag)
1930 error ("No other window to side of this one");
1931 break;
1932 }
265a9e55
JB
1933 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
1934 : !NILP (XWINDOW (parent)->vchild))
7ab12479
JB
1935 break;
1936 window = parent;
1937 }
1938
05c2896a 1939 sizep = &CURSIZE (window);
7ab12479 1940
05c2896a 1941 if (*sizep + delta < MINSIZE (window))
7ab12479
JB
1942 {
1943 Fdelete_window (window);
1944 return;
1945 }
1946
1947 {
1948 register int maxdelta;
7ab12479 1949
265a9e55
JB
1950 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
1951 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
1952 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
44fa5b1e
JB
1953 /* This is a frame with only one window, a minibuffer-only
1954 or a minibufferless frame. */
d5783c40 1955 : (delta = 0));
7ab12479
JB
1956
1957 if (delta > maxdelta)
1958 /* This case traps trying to make the minibuffer
44fa5b1e
JB
1959 the full frame, or make the only window aside from the
1960 minibuffer the full frame. */
7ab12479 1961 delta = maxdelta;
d5783c40
JB
1962
1963 if (delta == 0)
1964 return;
7ab12479
JB
1965 }
1966
265a9e55 1967 if (!NILP (p->next) &&
7ab12479
JB
1968 (*sizefun) (p->next) - delta >= MINSIZE (p->next))
1969 {
1970 (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
1971 (*setsizefun) (window, *sizep + delta, 0);
05c2896a 1972 CURBEG (p->next) += delta;
7ab12479
JB
1973 /* This does not change size of p->next,
1974 but it propagates the new top edge to its children */
1975 (*setsizefun) (p->next, (*sizefun) (p->next), 0);
1976 }
265a9e55 1977 else if (!NILP (p->prev) &&
7ab12479
JB
1978 (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
1979 {
1980 (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
05c2896a 1981 CURBEG (window) -= delta;
7ab12479
JB
1982 (*setsizefun) (window, *sizep + delta, 0);
1983 }
1984 else
1985 {
1986 register int delta1;
1987 register int opht = (*sizefun) (parent);
1988
1989 /* If trying to grow this window to or beyond size of the parent,
1990 make delta1 so big that, on shrinking back down,
1991 all the siblings end up with less than one line and are deleted. */
1992 if (opht <= *sizep + delta)
1993 delta1 = opht * opht * 2;
1994 /* Otherwise, make delta1 just right so that if we add delta1
1995 lines to this window and to the parent, and then shrink
1996 the parent back to its original size, the new proportional
1997 size of this window will increase by delta. */
1998 else
1999 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
2000
2001 /* Add delta1 lines or columns to this window, and to the parent,
2002 keeping things consistent while not affecting siblings. */
05c2896a 2003 CURSIZE (parent) = opht + delta1;
7ab12479
JB
2004 (*setsizefun) (window, *sizep + delta1, 0);
2005
2006 /* Squeeze out delta1 lines or columns from our parent,
2007 shriking this window and siblings proportionately.
2008 This brings parent back to correct size.
2009 Delta1 was calculated so this makes this window the desired size,
2010 taking it all out of the siblings. */
2011 (*setsizefun) (parent, opht, 0);
2012 }
2013
2014 XFASTINT (p->last_modified) = 0;
2015}
2016#undef MINSIZE
2017#undef CURBEG
2018#undef CURSIZE
2019
2020\f
2021/* Return number of lines of text (not counting mode line) in W. */
2022
2023int
2024window_internal_height (w)
2025 struct window *w;
2026{
2027 int ht = XFASTINT (w->height);
2028
2029 if (MINI_WINDOW_P (w))
2030 return ht;
2031
265a9e55
JB
2032 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2033 || !NILP (w->next) || !NILP (w->prev)
44fa5b1e 2034 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
7ab12479
JB
2035 return ht - 1;
2036
2037 return ht;
2038}
2039
535e0b8e
JB
2040
2041/* Return the number of columns in W.
a3c87d4e 2042 Don't count columns occupied by scroll bars or the vertical bar
535e0b8e
JB
2043 separating W from the sibling to its right. */
2044int
2045window_internal_width (w)
2046 struct window *w;
2047{
2048 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2049 int left = XINT (w->left);
2050 int width = XINT (w->width);
2051
2052 /* If this window is flush against the right edge of the frame, its
2053 internal width is its full width. */
2054 if (left + width >= FRAME_WIDTH (f))
2055 return width;
2056
2057 /* If we are not flush right, then our rightmost columns are
2058 occupied by some sort of separator. */
2059
a3c87d4e
JB
2060 /* Scroll bars occupy a few columns. */
2061 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2062 return width - VERTICAL_SCROLL_BAR_WIDTH;
535e0b8e
JB
2063
2064 /* The column of `|' characters separating side-by-side windows
2065 occupies one column only. */
2066 return width - 1;
2067}
2068
2069
7ab12479
JB
2070/* Scroll contents of window WINDOW up N lines. */
2071
2072void
f8026fd8 2073window_scroll (window, n, noerror)
7ab12479
JB
2074 Lisp_Object window;
2075 int n;
f8026fd8 2076 int noerror;
7ab12479
JB
2077{
2078 register struct window *w = XWINDOW (window);
2079 register int opoint = point;
2080 register int pos;
2081 register int ht = window_internal_height (w);
2082 register Lisp_Object tem;
2083 int lose;
2084 Lisp_Object bolp, nmoved;
2085
2086 XFASTINT (tem) = point;
2087 tem = Fpos_visible_in_window_p (tem, window);
2088
265a9e55 2089 if (NILP (tem))
7ab12479
JB
2090 {
2091 Fvertical_motion (make_number (- ht / 2));
2092 XFASTINT (tem) = point;
2093 Fset_marker (w->start, tem, w->buffer);
2094 w->force_start = Qt;
2095 }
2096
2097 SET_PT (marker_position (w->start));
2098 lose = n < 0 && point == BEGV;
2099 Fvertical_motion (make_number (n));
2100 pos = point;
2101 bolp = Fbolp ();
2102 SET_PT (opoint);
2103
2104 if (lose)
f8026fd8
JB
2105 {
2106 if (noerror)
2107 return;
2108 else
2109 Fsignal (Qbeginning_of_buffer, Qnil);
2110 }
7ab12479
JB
2111
2112 if (pos < ZV)
7ab12479
JB
2113 {
2114 set_marker_restricted (w->start, make_number (pos), w->buffer);
2115 w->start_at_line_beg = bolp;
2116 w->update_mode_line = Qt;
2117 XFASTINT (w->last_modified) = 0;
2118 if (pos > opoint)
2119 SET_PT (pos);
2120 if (n < 0)
2121 {
2122 SET_PT (pos);
2123 tem = Fvertical_motion (make_number (ht));
2124 if (point > opoint || XFASTINT (tem) < ht)
2125 SET_PT (opoint);
2126 else
2127 Fvertical_motion (make_number (-1));
2128 }
2129 }
2130 else
f8026fd8
JB
2131 {
2132 if (noerror)
2133 return;
2134 else
2135 Fsignal (Qend_of_buffer, Qnil);
2136 }
7ab12479
JB
2137}
2138\f
2139/* This is the guts of Fscroll_up and Fscroll_down. */
2140
2141static void
2142scroll_command (n, direction)
2143 register Lisp_Object n;
2144 int direction;
2145{
2146 register int defalt;
2147 int count = specpdl_ptr - specpdl;
2148
95605e15
JB
2149 /* If selected window's buffer isn't current, make it current for the moment.
2150 But don't screw up if window_scroll gets an error. */
7ab12479 2151 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
95605e15
JB
2152 {
2153 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2154 Fset_buffer (XWINDOW (selected_window)->buffer);
2155 }
7ab12479
JB
2156
2157 defalt = (window_internal_height (XWINDOW (selected_window))
2158 - next_screen_context_lines);
2159 defalt = direction * (defalt < 1 ? 1 : defalt);
2160
265a9e55 2161 if (NILP (n))
f8026fd8 2162 window_scroll (selected_window, defalt, 0);
7ab12479 2163 else if (EQ (n, Qminus))
f8026fd8 2164 window_scroll (selected_window, - defalt, 0);
7ab12479
JB
2165 else
2166 {
2167 n = Fprefix_numeric_value (n);
f8026fd8 2168 window_scroll (selected_window, XINT (n) * direction, 0);
7ab12479 2169 }
95605e15
JB
2170
2171 unbind_to (count, Qnil);
7ab12479
JB
2172}
2173
2174DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2175 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2176A near full screen is `next-screen-context-lines' less than a full screen.\n\
2177When calling from a program, supply a number as argument or nil.")
2178 (n)
2179 Lisp_Object n;
2180{
2181 scroll_command (n, 1);
2182 return Qnil;
2183}
2184
2185DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2186 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2187A near full screen is `next-screen-context-lines' less than a full screen.\n\
2188When calling from a program, supply a number as argument or nil.")
2189 (n)
2190 Lisp_Object n;
2191{
2192 scroll_command (n, -1);
2193 return Qnil;
2194}
2195
2196DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
99e5add3 2197 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
7ab12479
JB
2198The next window is the one below the current one; or the one at the top\n\
2199if the current one is at the bottom.\n\
2200When calling from a program, supply a number as argument or nil.\n\
2201\n\
2202If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
2203specifies the window to scroll.\n\
2204If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2205showing that buffer, popping the buffer up if necessary.")
2206 (n)
2207 register Lisp_Object n;
2208{
2209 register Lisp_Object window;
2210 register int ht;
2211 register struct window *w;
2212 register int count = specpdl_ptr - specpdl;
2213
2214 if (MINI_WINDOW_P (XWINDOW (selected_window))
265a9e55 2215 && !NILP (Vminibuf_scroll_window))
7ab12479
JB
2216 window = Vminibuf_scroll_window;
2217 /* If buffer is specified, scroll that buffer. */
265a9e55 2218 else if (!NILP (Vother_window_scroll_buffer))
7ab12479
JB
2219 {
2220 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
265a9e55 2221 if (NILP (window))
7ab12479
JB
2222 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2223 }
2224 else
dbc4e1c1
JB
2225 {
2226 /* Nothing specified; look for a neighboring window on the same
2227 frame. */
2228 window = Fnext_window (selected_window, Qnil, Qnil);
2229
2230 if (EQ (window, selected_window))
2231 /* That didn't get us anywhere; look for a window on another
2232 visible frame. */
2233 do
2234 window = Fnext_window (window, Qnil, Qt);
2235 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
2236 && ! EQ (window, selected_window));
2237 }
2238
605be8af 2239 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2240
2241 if (EQ (window, selected_window))
2242 error ("There is no other window");
2243
2244 w = XWINDOW (window);
2245 ht = window_internal_height (w);
2246
2247 /* Don't screw up if window_scroll gets an error. */
2248 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2249
2250 Fset_buffer (w->buffer);
2251 SET_PT (marker_position (w->pointm));
2252
265a9e55 2253 if (NILP (n))
f8026fd8 2254 window_scroll (window, ht - next_screen_context_lines, 1);
7ab12479 2255 else if (EQ (n, Qminus))
f8026fd8 2256 window_scroll (window, next_screen_context_lines - ht, 1);
7ab12479
JB
2257 else
2258 {
2259 if (XTYPE (n) == Lisp_Cons)
2260 n = Fcar (n);
2261 CHECK_NUMBER (n, 0);
f8026fd8 2262 window_scroll (window, XINT (n), 1);
7ab12479
JB
2263 }
2264
2265 Fset_marker (w->pointm, make_number (point), Qnil);
f4e7b2c2 2266 unbind_to (count, Qnil);
7ab12479
JB
2267
2268 return Qnil;
2269}
2270\f
2271DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 1, 1, "P",
2272 "Scroll selected window display ARG columns left.\n\
2273Default for ARG is window width minus 2.")
2274 (arg)
2275 register Lisp_Object arg;
2276{
2277
265a9e55 2278 if (NILP (arg))
b8baad40 2279 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
7ab12479
JB
2280 else
2281 arg = Fprefix_numeric_value (arg);
2282
2283 return
2284 Fset_window_hscroll (selected_window,
2285 make_number (XINT (XWINDOW (selected_window)->hscroll)
2286 + XINT (arg)));
2287}
2288
2289DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 1, 1, "P",
2290 "Scroll selected window display ARG columns right.\n\
2291Default for ARG is window width minus 2.")
2292 (arg)
2293 register Lisp_Object arg;
2294{
265a9e55 2295 if (NILP (arg))
b8baad40 2296 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
7ab12479
JB
2297 else
2298 arg = Fprefix_numeric_value (arg);
2299
2300 return
2301 Fset_window_hscroll (selected_window,
2302 make_number (XINT (XWINDOW (selected_window)->hscroll)
2303 - XINT (arg)));
2304}
2305
2306DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
44fa5b1e 2307 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
7ab12479 2308The desired position of point is always relative to the current window.\n\
44fa5b1e
JB
2309Just C-u as prefix means put point in the center of the window.\n\
2310No arg (i.e., it is nil) erases the entire frame and then\n\
2311redraws with point in the center of the current window.")
7ab12479
JB
2312 (n)
2313 register Lisp_Object n;
2314{
2315 register struct window *w = XWINDOW (selected_window);
2316 register int ht = window_internal_height (w);
2317 register int opoint = point;
2318
265a9e55 2319 if (NILP (n))
7ab12479 2320 {
44fa5b1e 2321 extern int frame_garbaged;
7ab12479 2322
44fa5b1e 2323 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
7ab12479
JB
2324 XFASTINT (n) = ht / 2;
2325 }
2326 else if (XTYPE (n) == Lisp_Cons) /* Just C-u. */
2327 {
2328 XFASTINT (n) = ht / 2;
2329 }
2330 else
2331 {
2332 n = Fprefix_numeric_value (n);
2333 CHECK_NUMBER (n, 0);
2334 }
2335
2336 if (XINT (n) < 0)
2337 XSETINT (n, XINT (n) + ht);
2338
2339 XSETINT (n, - XINT (n));
2340
2341 Fvertical_motion (n);
2342 Fset_marker (w->start, make_number (point), w->buffer);
2343 w->start_at_line_beg = Fbolp ();
2344
2345 SET_PT (opoint);
2346 w->force_start = Qt;
2347
2348 return Qnil;
2349}
2350\f
2351DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
2352 1, 1, "P",
2353 "Position point relative to window.\n\
2354With no argument, position text at center of window.\n\
44fa5b1e 2355An argument specifies frame line; zero means top of window,\n\
7ab12479
JB
2356negative means relative to bottom of window.")
2357 (arg)
2358 register Lisp_Object arg;
2359{
2360 register struct window *w = XWINDOW (selected_window);
2361 register int height = window_internal_height (w);
2362 register int start;
2363
265a9e55 2364 if (NILP (arg))
7ab12479
JB
2365 XFASTINT (arg) = height / 2;
2366 else
2367 {
2368 arg = Fprefix_numeric_value (arg);
2369 if (XINT (arg) < 0)
2370 XSETINT (arg, XINT (arg) + height);
2371 }
2372
2373 start = marker_position (w->start);
2374 if (start < BEGV || start > ZV)
2375 {
2376 Fvertical_motion (make_number (- height / 2));
2377 Fset_marker (w->start, make_number (point), w->buffer);
2378 w->start_at_line_beg = Fbolp ();
2379 w->force_start = Qt;
2380 }
2381 else
2382 SET_PT (start);
2383
2384 return Fvertical_motion (arg);
2385}
2386\f
2387struct save_window_data
2388 {
2389 int size_from_Lisp_Vector_struct;
2390 struct Lisp_Vector *next_from_Lisp_Vector_struct;
44fa5b1e 2391 Lisp_Object frame_width, frame_height;
bdc727bf 2392 Lisp_Object selected_frame;
7ab12479
JB
2393 Lisp_Object current_window;
2394 Lisp_Object current_buffer;
2395 Lisp_Object minibuf_scroll_window;
2396 Lisp_Object root_window;
bdc727bf 2397 Lisp_Object focus_frame;
7ab12479
JB
2398 /* A vector, interpreted as a struct saved_window */
2399 Lisp_Object saved_windows;
2400 };
ff06df24
JB
2401
2402/* Arg to Fmake_vector */
2403#define SAVE_WINDOW_DATA_SIZE \
2404 ((sizeof (struct save_window_data) \
2405 - (sizeof (struct Lisp_Vector) \
2406 /* Don't count the contents member of the struct Lisp_Vector */ \
2407 - sizeof (Lisp_Object))) \
2408 / sizeof (Lisp_Object))
7ab12479
JB
2409
2410/* This is saved as a Lisp_Vector */
2411struct saved_window
2412 {
2413 /* these first two must agree with struct Lisp_Vector in lisp.h */
2414 int size_from_Lisp_Vector_struct;
2415 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2416
2417 Lisp_Object window;
2418 Lisp_Object buffer, start, pointm, mark;
2419 Lisp_Object left, top, width, height, hscroll;
2420 Lisp_Object parent, prev;
2421 Lisp_Object start_at_line_beg;
2422 Lisp_Object display_table;
2423 };
2424#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2425
2426#define SAVED_WINDOW_N(swv,n) \
2427 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2428
2429DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
2430 "T if OBJECT is a window-configration object.")
2431 (obj)
2432 Lisp_Object obj;
2433{
2434 if (XTYPE (obj) == Lisp_Window_Configuration)
2435 return Qt;
2436 return Qnil;
2437}
2438
2439
d5b2799e
RS
2440DEFUN ("set-window-configuration", Fset_window_configuration,
2441 Sset_window_configuration, 1, 1, 0,
7ab12479
JB
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))
d5b2799e 2617 Fhandle_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
fd482be5
JB
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 2629 /* Fselect_window will have made f the selected frame, so we
d5b2799e 2630 reselect the proper frame here. Fhandle_switch_frame will change the
bdc727bf
JB
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)))
d5b2799e 2635 Fhandle_switch_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}