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