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