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