(compute_motion): Add window argument.
[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,
afdb2485 226 hscroll, 0);
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
44fa5b1e
JB
872 /* all_frames == nil doesn't specify which frames to include.
873 Decide which frames it includes. */
874 if (NILP (all_frames))
875 all_frames = (EQ (minibuf, Qt)
876 ? (FRAME_MINIBUF_WINDOW
877 (XFRAME
878 (WINDOW_FRAME
d5783c40
JB
879 (XWINDOW (window)))))
880 : Qnil);
89bca612
RS
881 else if (EQ (all_frames, Qvisible))
882 ;
44fa5b1e
JB
883 else if (! EQ (all_frames, Qt))
884 all_frames = Qnil;
644b477c
RS
885 /* Now all_frames is t meaning search all frames,
886 nil meaning search just current frame,
887 or a window, meaning search the frame that window belongs to. */
7ab12479
JB
888
889 /* Do this loop at least once, to get the next window, and perhaps
890 again, if we hit the minibuffer and that is not acceptable. */
891 do
892 {
893 /* Find a window that actually has a next one. This loop
894 climbs up the tree. */
265a9e55
JB
895 while (tem = XWINDOW (window)->next, NILP (tem))
896 if (tem = XWINDOW (window)->parent, !NILP (tem))
7ab12479 897 window = tem;
d5783c40 898 else
7ab12479 899 {
44fa5b1e
JB
900 /* We've reached the end of this frame.
901 Which other frames are acceptable? */
902 tem = WINDOW_FRAME (XWINDOW (window));
903#ifdef MULTI_FRAME
904 if (! NILP (all_frames))
905 tem = next_frame (tem, all_frames);
7ab12479 906#endif
44fa5b1e 907 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
d5783c40 908
7ab12479
JB
909 break;
910 }
911
912 window = tem;
d5783c40 913
7ab12479
JB
914 /* If we're in a combination window, find its first child and
915 recurse on that. Otherwise, we've found the window we want. */
916 while (1)
917 {
265a9e55 918 if (!NILP (XWINDOW (window)->hchild))
7ab12479 919 window = XWINDOW (window)->hchild;
265a9e55 920 else if (!NILP (XWINDOW (window)->vchild))
7ab12479
JB
921 window = XWINDOW (window)->vchild;
922 else break;
923 }
924 }
d5783c40
JB
925 /* Which windows are acceptible?
926 Exit the loop and accept this window if
7ab12479 927 this isn't a minibuffer window, or
d5783c40
JB
928 we're accepting minibuffer windows, or
929 we've come all the way around and we're back at the original window. */
7ab12479 930 while (MINI_WINDOW_P (XWINDOW (window))
d5783c40 931 && ! EQ (minibuf, Qt)
7f4161e0 932 && ! EQ (window, start_window));
7ab12479
JB
933
934 return window;
935}
936
26f6279d
JB
937/* This comment supplies the doc string for `previous-window',
938 for make-docfile to see. We cannot put this in the real DEFUN
939 due to limits in the Unix cpp.
940
941DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
d5783c40
JB
942 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
943If omitted, WINDOW defaults to the selected window.\n\
944\n\
945Optional second arg MINIBUF t means count the minibuffer window even\n\
946if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
947it is active. MINIBUF neither t nor nil means not to count the\n\
948minibuffer even if it is active.\n\
949\n\
44fa5b1e
JB
950Several frames may share a single minibuffer; if the minibuffer\n\
951counts, all windows on all frames that share that minibuffer count\n\
d5783c40 952too. This means that previous-window may be used to iterate through\n\
44fa5b1e
JB
953the set of windows even when the minibuffer is on another frame. If\n\
954the minibuffer does not count, only windows from WINDOW's frame\n\
d5783c40
JB
955count.\n\
956\n\
44fa5b1e
JB
957Optional third arg ALL-FRAMES t means include windows on all frames.\n\
958ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
89bca612
RS
959above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
960Anything else means restrict to WINDOW's frame.\n\
dbc4e1c1
JB
961\n\
962If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
963`previous-window' to iterate through the entire cycle of acceptable\n\
964windows, eventually ending up back at the window you started with.\n\
965`next-window' traverses the same cycle, in the reverse order.")
26f6279d
JB
966 (window, minibuf, all_frames) */
967
968
969DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
970 0)
44fa5b1e
JB
971 (window, minibuf, all_frames)
972 register Lisp_Object window, minibuf, all_frames;
7ab12479
JB
973{
974 register Lisp_Object tem;
d5783c40 975 Lisp_Object start_window;
7ab12479 976
265a9e55 977 if (NILP (window))
7ab12479
JB
978 window = selected_window;
979 else
605be8af 980 CHECK_LIVE_WINDOW (window, 0);
7ab12479 981
d5783c40
JB
982 start_window = window;
983
984 /* minibuf == nil may or may not include minibuffers.
985 Decide if it does. */
265a9e55 986 if (NILP (minibuf))
d5783c40
JB
987 minibuf = (minibuf_level ? Qt : Qlambda);
988
44fa5b1e
JB
989 /* all_frames == nil doesn't specify which frames to include.
990 Decide which frames it includes. */
991 if (NILP (all_frames))
992 all_frames = (EQ (minibuf, Qt)
993 ? (FRAME_MINIBUF_WINDOW
994 (XFRAME
995 (WINDOW_FRAME
d5783c40
JB
996 (XWINDOW (window)))))
997 : Qnil);
89bca612
RS
998 else if (EQ (all_frames, Qvisible))
999 ;
44fa5b1e
JB
1000 else if (! EQ (all_frames, Qt))
1001 all_frames = Qnil;
644b477c
RS
1002 /* Now all_frames is t meaning search all frames,
1003 nil meaning search just current frame,
1004 or a window, meaning search the frame that window belongs to. */
7ab12479
JB
1005
1006 /* Do this loop at least once, to get the previous window, and perhaps
1007 again, if we hit the minibuffer and that is not acceptable. */
1008 do
1009 {
1010 /* Find a window that actually has a previous one. This loop
1011 climbs up the tree. */
265a9e55
JB
1012 while (tem = XWINDOW (window)->prev, NILP (tem))
1013 if (tem = XWINDOW (window)->parent, !NILP (tem))
7ab12479 1014 window = tem;
d5783c40 1015 else
7ab12479 1016 {
44fa5b1e
JB
1017 /* We have found the top window on the frame.
1018 Which frames are acceptable? */
1019 tem = WINDOW_FRAME (XWINDOW (window));
1020#ifdef MULTI_FRAME
1021 if (! NILP (all_frames))
dbc4e1c1
JB
1022 /* It's actually important that we use prev_frame here,
1023 rather than next_frame. All the windows acceptable
1024 according to the given parameters should form a ring;
1025 Fnext_window and Fprevious_window should go back and
1026 forth around the ring. If we use next_frame here,
1027 then Fnext_window and Fprevious_window take different
1028 paths through the set of acceptable windows.
1029 window_loop assumes that these `ring' requirement are
1030 met. */
1031 tem = prev_frame (tem, all_frames);
7ab12479 1032#endif
644b477c
RS
1033 /* If this frame has a minibuffer, find that window first,
1034 because it is conceptually the last window in that frame. */
5e12e32f
JB
1035 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
1036 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
1037 else
644b477c 1038 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
d5783c40 1039
7ab12479
JB
1040 break;
1041 }
1042
1043 window = tem;
1044 /* If we're in a combination window, find its last child and
1045 recurse on that. Otherwise, we've found the window we want. */
1046 while (1)
1047 {
265a9e55 1048 if (!NILP (XWINDOW (window)->hchild))
7ab12479 1049 window = XWINDOW (window)->hchild;
265a9e55 1050 else if (!NILP (XWINDOW (window)->vchild))
7ab12479
JB
1051 window = XWINDOW (window)->vchild;
1052 else break;
265a9e55 1053 while (tem = XWINDOW (window)->next, !NILP (tem))
7ab12479
JB
1054 window = tem;
1055 }
1056 }
d5783c40
JB
1057 /* Which windows are acceptable?
1058 Exit the loop and accept this window if
7ab12479 1059 this isn't a minibuffer window, or
d5783c40
JB
1060 we're accepting minibuffer windows, or
1061 we've come all the way around and we're back at the original window. */
7ab12479 1062 while (MINI_WINDOW_P (XWINDOW (window))
d5783c40 1063 && !EQ (minibuf, Qt)
7f4161e0 1064 && !EQ (window, start_window));
7ab12479
JB
1065
1066 return window;
1067}
1068
62c07cc7 1069DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
44fa5b1e
JB
1070 "Select the ARG'th different window on this frame.\n\
1071All windows on current frame are arranged in a cyclic order.\n\
7ab12479
JB
1072This command selects the window ARG steps away in that order.\n\
1073A negative ARG moves in the opposite order. If the optional second\n\
44fa5b1e
JB
1074argument ALL_FRAMES is non-nil, cycle through all frames.")
1075 (n, all_frames)
1076 register Lisp_Object n, all_frames;
7ab12479
JB
1077{
1078 register int i;
1079 register Lisp_Object w;
1080
1081 CHECK_NUMBER (n, 0);
1082 w = selected_window;
1083 i = XINT (n);
1084
1085 while (i > 0)
1086 {
44fa5b1e 1087 w = Fnext_window (w, Qnil, all_frames);
7ab12479
JB
1088 i--;
1089 }
1090 while (i < 0)
1091 {
44fa5b1e 1092 w = Fprevious_window (w, Qnil, all_frames);
7ab12479
JB
1093 i++;
1094 }
1095 Fselect_window (w);
1096 return Qnil;
1097}
1098\f
1099/* Look at all windows, performing an operation specified by TYPE
1100 with argument OBJ.
75d8f668 1101 If FRAMES is Qt, look at all frames;
75d8f668 1102 Qnil, look at just the selected frame;
89bca612 1103 Qvisible, look at visible frames;
75d8f668 1104 a frame, just look at windows on that frame.
7ab12479
JB
1105 If MINI is non-zero, perform the operation on minibuffer windows too.
1106*/
1107
1108enum window_loop
1109{
1110 WINDOW_LOOP_UNUSED,
1111 GET_BUFFER_WINDOW, /* Arg is buffer */
1112 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1113 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1114 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1115 GET_LARGEST_WINDOW,
a68c0d3b 1116 UNSHOW_BUFFER /* Arg is buffer */
7ab12479
JB
1117};
1118
1119static Lisp_Object
44fa5b1e 1120window_loop (type, obj, mini, frames)
7ab12479 1121 enum window_loop type;
44fa5b1e 1122 register Lisp_Object obj, frames;
7ab12479
JB
1123 int mini;
1124{
1125 register Lisp_Object w;
1126 register Lisp_Object best_window;
1127 register Lisp_Object next_window;
4b206065 1128 register Lisp_Object last_window;
44fa5b1e 1129 FRAME_PTR frame;
89bca612
RS
1130 Lisp_Object frame_arg;
1131 frame_arg = Qt;
44fa5b1e 1132
4b206065 1133#ifdef MULTI_FRAME
44fa5b1e
JB
1134 /* If we're only looping through windows on a particular frame,
1135 frame points to that frame. If we're looping through windows
1136 on all frames, frame is 0. */
1137 if (FRAMEP (frames))
1138 frame = XFRAME (frames);
1139 else if (NILP (frames))
1140 frame = selected_frame;
7ab12479 1141 else
44fa5b1e 1142 frame = 0;
89bca612
RS
1143 if (frame)
1144 frame_arg = Qlambda;
1145 else if (EQ (frames, Qvisible))
1146 frame_arg = frames;
4b206065
JB
1147#else
1148 frame = 0;
1149#endif
7ab12479 1150
89bca612
RS
1151 /* frame_arg is Qlambda to stick to one frame,
1152 Qvisible to consider all visible frames,
1153 or Qt otherwise. */
1154
7ab12479
JB
1155 /* Pick a window to start with. */
1156 if (XTYPE (obj) == Lisp_Window)
4b206065 1157 w = obj;
44fa5b1e 1158 else if (frame)
4b206065 1159 w = FRAME_SELECTED_WINDOW (frame);
7ab12479 1160 else
4b206065
JB
1161 w = FRAME_SELECTED_WINDOW (selected_frame);
1162
1163 /* Figure out the last window we're going to mess with. Since
1164 Fnext_window, given the same options, is guaranteed to go in a
1165 ring, we can just use Fprevious_window to find the last one.
1166
1167 We can't just wait until we hit the first window again, because
1168 it might be deleted. */
1169
89bca612 1170 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
7ab12479 1171
7ab12479 1172 best_window = Qnil;
4b206065 1173 for (;;)
7ab12479 1174 {
75d8f668
JB
1175 FRAME_PTR w_frame = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1176
7ab12479
JB
1177 /* Pick the next window now, since some operations will delete
1178 the current window. */
89bca612 1179 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
7ab12479 1180
d29a5631
RS
1181 /* Note that we do not pay attention here to whether
1182 the frame is visible, since Fnext_window skips non-visible frames
1183 if that is desired, under the control of frame_arg. */
75d8f668 1184 if (! MINI_WINDOW_P (XWINDOW (w))
7ab12479
JB
1185 || (mini && minibuf_level > 0))
1186 switch (type)
1187 {
1188 case GET_BUFFER_WINDOW:
7ab12479
JB
1189 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj))
1190 return w;
1191 break;
1192
1193 case GET_LRU_WINDOW:
1194 /* t as arg means consider only full-width windows */
e5d77022 1195 if (!NILP (obj) && XFASTINT (XWINDOW (w)->width)
a2db42d6 1196 != FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
7ab12479 1197 break;
7ab12479
JB
1198 /* Ignore dedicated windows and minibuffers. */
1199 if (MINI_WINDOW_P (XWINDOW (w))
265a9e55 1200 || !NILP (XWINDOW (w)->dedicated))
7ab12479 1201 break;
265a9e55 1202 if (NILP (best_window)
7ab12479
JB
1203 || (XFASTINT (XWINDOW (best_window)->use_time)
1204 > XFASTINT (XWINDOW (w)->use_time)))
1205 best_window = w;
1206 break;
1207
1208 case DELETE_OTHER_WINDOWS:
1209 if (XWINDOW (w) != XWINDOW (obj))
1210 Fdelete_window (w);
1211 break;
1212
1213 case DELETE_BUFFER_WINDOWS:
1214 if (EQ (XWINDOW (w)->buffer, obj))
1215 {
1216 /* If we're deleting the buffer displayed in the only window
44fa5b1e 1217 on the frame, find a new buffer to display there. */
265a9e55 1218 if (NILP (XWINDOW (w)->parent))
7ab12479 1219 {
12cae7c0
KH
1220 Lisp_Object new_buffer;
1221 new_buffer = Fother_buffer (obj, Qnil);
265a9e55 1222 if (NILP (new_buffer))
7ab12479
JB
1223 new_buffer
1224 = Fget_buffer_create (build_string ("*scratch*"));
1225 Fset_window_buffer (w, new_buffer);
d895abb0
RS
1226 if (EQ (w, selected_window))
1227 Fset_buffer (XWINDOW (w)->buffer);
7ab12479
JB
1228 }
1229 else
1230 Fdelete_window (w);
1231 }
1232 break;
1233
1234 case GET_LARGEST_WINDOW:
7ab12479
JB
1235 /* Ignore dedicated windows and minibuffers. */
1236 if (MINI_WINDOW_P (XWINDOW (w))
265a9e55 1237 || !NILP (XWINDOW (w)->dedicated))
7ab12479
JB
1238 break;
1239 {
1240 struct window *best_window_ptr = XWINDOW (best_window);
1241 struct window *w_ptr = XWINDOW (w);
265a9e55 1242 if (NILP (best_window) ||
7ab12479
JB
1243 (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width))
1244 > (XFASTINT (best_window_ptr->height)
1245 * XFASTINT (best_window_ptr->width)))
1246 best_window = w;
1247 }
1248 break;
1249
1250 case UNSHOW_BUFFER:
1251 if (EQ (XWINDOW (w)->buffer, obj))
1252 {
1253 /* Find another buffer to show in this window. */
12cae7c0
KH
1254 Lisp_Object another_buffer;
1255 another_buffer = Fother_buffer (obj, Qnil);
265a9e55 1256 if (NILP (another_buffer))
7ab12479
JB
1257 another_buffer
1258 = Fget_buffer_create (build_string ("*scratch*"));
1259 Fset_window_buffer (w, another_buffer);
1260 if (EQ (w, selected_window))
1261 Fset_buffer (XWINDOW (w)->buffer);
1262 }
1263 break;
1264 }
4b206065
JB
1265
1266 if (EQ (w, last_window))
1267 break;
1268
7ab12479
JB
1269 w = next_window;
1270 }
7ab12479
JB
1271
1272 return best_window;
1273}
605be8af 1274
7ab12479
JB
1275DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1276 "Return the window least recently selected or used for display.\n\
89bca612
RS
1277If optional argument FRAME is `visible', search all visible frames.\n\
1278If FRAME is t, search all frames.\n\
1279If FRAME is nil, search only the selected frame.\n\
1280If FRAME is a frame, search only that frame.")
1281 (frame)
1282 Lisp_Object frame;
7ab12479
JB
1283{
1284 register Lisp_Object w;
1285 /* First try for a window that is full-width */
89bca612 1286 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
265a9e55 1287 if (!NILP (w) && !EQ (w, selected_window))
7ab12479
JB
1288 return w;
1289 /* If none of them, try the rest */
89bca612 1290 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
7ab12479
JB
1291}
1292
1293DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1294 "Return the largest window in area.\n\
89bca612
RS
1295If optional argument FRAME is `visible', search all visible frames.\n\
1296If FRAME is t, search all frames.\n\
1297If FRAME is nil, search only the selected frame.\n\
1298If FRAME is a frame, search only that frame.")
44fa5b1e
JB
1299 (frame)
1300 Lisp_Object frame;
7ab12479
JB
1301{
1302 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
44fa5b1e 1303 frame);
7ab12479
JB
1304}
1305
1306DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1307 "Return a window currently displaying BUFFER, or nil if none.\n\
89bca612
RS
1308If optional argument FRAME is `visible', search all visible frames.\n\
1309If FRAME is t, search all frames.\n\
1bc981d2 1310If FRAME is nil, search only the selected frame.\n\
89bca612 1311If FRAME is a frame, search only that frame.")
44fa5b1e
JB
1312 (buffer, frame)
1313 Lisp_Object buffer, frame;
7ab12479
JB
1314{
1315 buffer = Fget_buffer (buffer);
1316 if (XTYPE (buffer) == Lisp_Buffer)
44fa5b1e 1317 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
7ab12479
JB
1318 else
1319 return Qnil;
1320}
1321
1322DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1323 0, 1, "",
44fa5b1e 1324 "Make WINDOW (or the selected window) fill its frame.\n\
f16a1ed3
RS
1325Only the frame WINDOW is on is affected.\n\
1326This function tries to reduce display jumps\n\
1327by keeping the text previously visible in WINDOW\n\
1328in the same place on the frame. Doing this depends on\n\
1329the value of (window-start WINDOW), so if calling this function\n\
1330in a program gives strange scrolling, make sure the window-start\n\
1331value is reasonable when this function is called.")
7ab12479
JB
1332 (window)
1333 Lisp_Object window;
1334{
1335 struct window *w;
7ab12479 1336 struct buffer *obuf = current_buffer;
f16a1ed3 1337 int opoint;
7ab12479
JB
1338 int top;
1339
265a9e55 1340 if (NILP (window))
7ab12479
JB
1341 window = selected_window;
1342 else
605be8af 1343 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1344
1345 w = XWINDOW (window);
1346 top = XFASTINT (w->top);
1347
70728a80 1348 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
7ab12479
JB
1349
1350 Fset_buffer (w->buffer);
f16a1ed3 1351 opoint = point;
7ab12479 1352 SET_PT (marker_position (w->start));
4f2eb61d 1353 /* Like Frecenter but avoid setting w->force_start. */
540b6aa0
RS
1354 Fvertical_motion (make_number (- (top - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w))))),
1355 window);
4f2eb61d
RS
1356 Fset_marker (w->start, make_number (PT), w->buffer);
1357 w->start_at_line_beg = Fbolp ();
7ab12479 1358
7ab12479 1359 SET_PT (opoint);
f16a1ed3 1360 set_buffer_internal (obuf);
7ab12479
JB
1361 return Qnil;
1362}
1363
1364DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
3cbbb729 1365 1, 2, "bDelete windows on (buffer): ",
26f6279d
JB
1366 "Delete all windows showing BUFFER.\n\
1367Optional second argument FRAME controls which frames are affected.\n\
1368If nil or omitted, delete all windows showing BUFFER in any frame.\n\
1369If t, delete only windows showing BUFFER in the selected frame.\n\
89bca612 1370If `visible', delete all windows showing BUFFER in any visible frame.\n\
26f6279d
JB
1371If a frame, delete only windows showing BUFFER in that frame.")
1372 (buffer, frame)
1373 Lisp_Object buffer, frame;
7ab12479 1374{
26f6279d
JB
1375#ifdef MULTI_FRAME
1376 /* FRAME uses t and nil to mean the opposite of what window_loop
1377 expects. */
1378 if (! FRAMEP (frame))
1379 frame = NILP (frame) ? Qt : Qnil;
1380#else
1381 frame = Qt;
1382#endif
1383
265a9e55 1384 if (!NILP (buffer))
7ab12479
JB
1385 {
1386 buffer = Fget_buffer (buffer);
1387 CHECK_BUFFER (buffer, 0);
26f6279d 1388 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
7ab12479
JB
1389 }
1390 return Qnil;
1391}
1392
1393DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1394 Sreplace_buffer_in_windows,
1395 1, 1, "bReplace buffer in windows: ",
1396 "Replace BUFFER with some other buffer in all windows showing it.")
1397 (buffer)
1398 Lisp_Object buffer;
1399{
265a9e55 1400 if (!NILP (buffer))
7ab12479
JB
1401 {
1402 buffer = Fget_buffer (buffer);
1403 CHECK_BUFFER (buffer, 0);
1404 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1405 }
1406 return Qnil;
1407}
1408\f
1409/* Set the height of WINDOW and all its inferiors. */
a481b3ea
JB
1410
1411/* The smallest acceptable dimensions for a window. Anything smaller
1412 might crash Emacs. */
1413#define MIN_SAFE_WINDOW_WIDTH (2)
1414#define MIN_SAFE_WINDOW_HEIGHT (2)
1415
1416/* Make sure that window_min_height and window_min_width are
1417 not too small; if they are, set them to safe minima. */
1418
1419static void
1420check_min_window_sizes ()
1421{
1422 /* Smaller values might permit a crash. */
1423 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1424 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1425 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1426 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1427}
1428
1429/* If *ROWS or *COLS are too small a size for FRAME, set them to the
1430 minimum allowable size. */
605be8af 1431void
a481b3ea 1432check_frame_size (frame, rows, cols)
605be8af
JB
1433 FRAME_PTR frame;
1434 int *rows, *cols;
a481b3ea 1435{
628df3bf
JB
1436 /* For height, we have to see:
1437 whether the frame has a minibuffer,
1438 whether it wants a mode line, and
1439 whether it has a menu bar. */
a481b3ea 1440 int min_height =
79f92720
JB
1441 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
1442 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
a481b3ea 1443 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
628df3bf
JB
1444 if (FRAME_MENU_BAR_LINES (frame) > 0)
1445 min_height += FRAME_MENU_BAR_LINES (frame);
a481b3ea
JB
1446
1447 if (*rows < min_height)
1448 *rows = min_height;
1449 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1450 *cols = MIN_SAFE_WINDOW_WIDTH;
1451}
1452
7ab12479
JB
1453/* Normally the window is deleted if it gets too small.
1454 nodelete nonzero means do not do this.
1455 (The caller should check later and do so if appropriate) */
1456
1457set_window_height (window, height, nodelete)
1458 Lisp_Object window;
1459 int height;
1460 int nodelete;
1461{
1462 register struct window *w = XWINDOW (window);
1463 register struct window *c;
1464 int oheight = XFASTINT (w->height);
1465 int top, pos, lastbot, opos, lastobot;
1466 Lisp_Object child;
1467
a481b3ea
JB
1468 check_min_window_sizes ();
1469
7ab12479 1470 if (!nodelete
265a9e55 1471 && ! NILP (w->parent)
7ab12479
JB
1472 && height < window_min_height)
1473 {
1474 Fdelete_window (window);
1475 return;
1476 }
1477
1478 XFASTINT (w->last_modified) = 0;
1479 windows_or_buffers_changed++;
1480 XFASTINT (w->height) = height;
265a9e55 1481 if (!NILP (w->hchild))
7ab12479 1482 {
265a9e55 1483 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1484 {
1485 XWINDOW (child)->top = w->top;
1486 set_window_height (child, height, nodelete);
1487 }
1488 }
265a9e55 1489 else if (!NILP (w->vchild))
7ab12479
JB
1490 {
1491 lastbot = top = XFASTINT (w->top);
1492 lastobot = 0;
265a9e55 1493 for (child = w->vchild; !NILP (child); child = c->next)
7ab12479
JB
1494 {
1495 c = XWINDOW (child);
1496
1497 opos = lastobot + XFASTINT (c->height);
1498
1499 XFASTINT (c->top) = lastbot;
1500
1501 pos = (((opos * height) << 1) + oheight) / (oheight << 1);
1502
1503 /* Avoid confusion: inhibit deletion of child if becomes too small */
1504 set_window_height (child, pos + top - lastbot, 1);
1505
1506 /* Now advance child to next window,
1507 and set lastbot if child was not just deleted. */
1508 lastbot = pos + top;
1509 lastobot = opos;
1510 }
1511 /* Now delete any children that became too small. */
1512 if (!nodelete)
265a9e55 1513 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1514 {
1515 set_window_height (child, XINT (XWINDOW (child)->height), 0);
1516 }
1517 }
1518}
1519
1520/* Recursively set width of WINDOW and its inferiors. */
1521
1522set_window_width (window, width, nodelete)
1523 Lisp_Object window;
1524 int width;
1525 int nodelete;
1526{
1527 register struct window *w = XWINDOW (window);
1528 register struct window *c;
1529 int owidth = XFASTINT (w->width);
1530 int left, pos, lastright, opos, lastoright;
1531 Lisp_Object child;
1532
1533 if (!nodelete && width < window_min_width)
1534 {
1535 Fdelete_window (window);
1536 return;
1537 }
1538
1539 XFASTINT (w->last_modified) = 0;
1540 windows_or_buffers_changed++;
1541 XFASTINT (w->width) = width;
265a9e55 1542 if (!NILP (w->vchild))
7ab12479 1543 {
265a9e55 1544 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1545 {
1546 XWINDOW (child)->left = w->left;
1547 set_window_width (child, width, nodelete);
1548 }
1549 }
265a9e55 1550 else if (!NILP (w->hchild))
7ab12479
JB
1551 {
1552 lastright = left = XFASTINT (w->left);
1553 lastoright = 0;
265a9e55 1554 for (child = w->hchild; !NILP (child); child = c->next)
7ab12479
JB
1555 {
1556 c = XWINDOW (child);
1557
1558 opos = lastoright + XFASTINT (c->width);
1559
1560 XFASTINT (c->left) = lastright;
1561
1562 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
1563
1564 /* Inhibit deletion for becoming too small */
1565 set_window_width (child, pos + left - lastright, 1);
1566
1567 /* Now advance child to next window,
1568 and set lastright if child was not just deleted. */
1569 lastright = pos + left, lastoright = opos;
1570 }
1571 /* Delete children that became too small */
1572 if (!nodelete)
265a9e55 1573 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1574 {
1575 set_window_width (child, XINT (XWINDOW (child)->width), 0);
1576 }
1577 }
1578}
1579\f
1d8d96fa 1580int window_select_count;
7ab12479
JB
1581
1582DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1583 "Make WINDOW display BUFFER as its contents.\n\
1584BUFFER can be a buffer or buffer name.")
1585 (window, buffer)
1586 register Lisp_Object window, buffer;
1587{
1588 register Lisp_Object tem;
1589 register struct window *w = decode_window (window);
1590
1591 buffer = Fget_buffer (buffer);
1592 CHECK_BUFFER (buffer, 1);
1593
265a9e55 1594 if (NILP (XBUFFER (buffer)->name))
7ab12479
JB
1595 error ("Attempt to display deleted buffer");
1596
1597 tem = w->buffer;
265a9e55 1598 if (NILP (tem))
7ab12479
JB
1599 error ("Window is deleted");
1600 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
1601 is first being set up. */
1602 {
265a9e55 1603 if (!NILP (w->dedicated) && !EQ (tem, buffer))
7ab12479
JB
1604 error ("Window is dedicated to %s\n", tem);
1605
1606 unshow_buffer (w);
1607 }
1608
1609 w->buffer = buffer;
5a41ab94
RS
1610 w->window_end_pos = 0;
1611 w->window_end_valid = Qnil;
270967b2 1612 w->hscroll = 0;
7ab12479
JB
1613 Fset_marker (w->pointm,
1614 make_number (BUF_PT (XBUFFER (buffer))),
1615 buffer);
1616 set_marker_restricted (w->start,
1617 make_number (XBUFFER (buffer)->last_window_start),
1618 buffer);
1619 w->start_at_line_beg = Qnil;
e36ab06b 1620 w->force_start = Qnil;
7ab12479
JB
1621 XFASTINT (w->last_modified) = 0;
1622 windows_or_buffers_changed++;
1623 if (EQ (window, selected_window))
1624 Fset_buffer (buffer);
1625
1626 return Qnil;
1627}
1628
1629DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1630 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1631The main editor command loop selects the buffer of the selected window\n\
1632before each command.")
1633 (window)
1634 register Lisp_Object window;
1635{
1636 register struct window *w;
1637 register struct window *ow = XWINDOW (selected_window);
1638
605be8af 1639 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1640
1641 w = XWINDOW (window);
1642
265a9e55 1643 if (NILP (w->buffer))
7ab12479
JB
1644 error ("Trying to select deleted window or non-leaf window");
1645
1646 XFASTINT (w->use_time) = ++window_select_count;
1647 if (EQ (window, selected_window))
1648 return window;
1649
1650 Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
1651 ow->buffer);
1652
1653 selected_window = window;
44fa5b1e
JB
1654#ifdef MULTI_FRAME
1655 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
7ab12479 1656 {
44fa5b1e 1657 XFRAME (WINDOW_FRAME (w))->selected_window = window;
d5b2799e 1658 Fhandle_switch_frame (WINDOW_FRAME (w), Qnil);
7ab12479
JB
1659 }
1660 else
44fa5b1e 1661 selected_frame->selected_window = window;
7ab12479
JB
1662#endif
1663
1664 record_buffer (w->buffer);
1665 Fset_buffer (w->buffer);
1666
1667 /* Go to the point recorded in the window.
1668 This is important when the buffer is in more
1669 than one window. It also matters when
1670 redisplay_window has altered point after scrolling,
1671 because it makes the change only in the window. */
1672 {
1673 register int new_point = marker_position (w->pointm);
1674 if (new_point < BEGV)
1675 SET_PT (BEGV);
1676 if (new_point > ZV)
1677 SET_PT (ZV);
1678 else
1679 SET_PT (new_point);
1680 }
1681
1682 windows_or_buffers_changed++;
1683 return window;
1684}
1685
35aaf00c 1686DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
6648f23a 1687 "BDisplay buffer: \nP",
7ab12479
JB
1688 "Make BUFFER appear in some window but don't select it.\n\
1689BUFFER can be a buffer or a buffer name.\n\
1690If BUFFER is shown already in some window, just use that one,\n\
1691unless the window is the selected window and the optional second\n\
46d3268a 1692argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
5141b901 1693If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
7ab12479
JB
1694Returns the window displaying BUFFER.")
1695 (buffer, not_this_window)
1696 register Lisp_Object buffer, not_this_window;
1697{
1698 register Lisp_Object window;
1699
1700 buffer = Fget_buffer (buffer);
1701 CHECK_BUFFER (buffer, 0);
1702
265a9e55 1703 if (!NILP (Vdisplay_buffer_function))
7ab12479
JB
1704 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
1705
265a9e55 1706 if (NILP (not_this_window)
7ab12479
JB
1707 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
1708 return selected_window;
1709
e8edb3ae
RS
1710 /* If pop_up_frames,
1711 look for a window showing BUFFER on any visible frame. */
1712 window = Fget_buffer_window (buffer, pop_up_frames ? Qvisible : Qnil);
265a9e55
JB
1713 if (!NILP (window)
1714 && (NILP (not_this_window) || !EQ (window, selected_window)))
7ab12479
JB
1715 return window;
1716
44fa5b1e
JB
1717#ifdef MULTI_FRAME
1718 /* If there are no frames open that have more than a minibuffer,
1719 we need to create a new frame. */
1720 if (pop_up_frames || last_nonminibuf_frame == 0)
7ab12479
JB
1721 {
1722 window
44fa5b1e 1723 = Fframe_selected_window (call0 (Vpop_up_frame_function));
7ab12479
JB
1724 Fset_window_buffer (window, buffer);
1725#if 0
d5b2799e 1726 Fhandle_switch_frame (XWINDOW (window)->frame, Qnil);
7ab12479
JB
1727#endif
1728 return window;
1729 }
44fa5b1e 1730#endif /* MULTI_FRAME */
7ab12479 1731
43bad991 1732 if (pop_up_windows
44fa5b1e
JB
1733#ifdef MULTI_FRAME
1734 || FRAME_MINIBUF_ONLY_P (selected_frame)
43bad991
JB
1735#endif
1736 )
7ab12479 1737 {
12cae7c0
KH
1738 Lisp_Object frames;
1739
1740 frames = Qnil;
44fa5b1e
JB
1741#ifdef MULTI_FRAME
1742 if (FRAME_MINIBUF_ONLY_P (selected_frame))
1743 XSET (frames, Lisp_Frame, last_nonminibuf_frame);
7ab12479
JB
1744#endif
1745 /* Don't try to create a window if would get an error */
1746 if (split_height_threshold < window_min_height << 1)
1747 split_height_threshold = window_min_height << 1;
1748
44fa5b1e 1749 window = Fget_largest_window (frames);
7ab12479 1750
265a9e55 1751 if (!NILP (window)
7ab12479 1752 && window_height (window) >= split_height_threshold
535e0b8e
JB
1753 && (XFASTINT (XWINDOW (window)->width)
1754 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
7ab12479
JB
1755 window = Fsplit_window (window, Qnil, Qnil);
1756 else
1757 {
44fa5b1e 1758 window = Fget_lru_window (frames);
7ab12479
JB
1759 if ((EQ (window, selected_window)
1760 || EQ (XWINDOW (window)->parent, Qnil))
1761 && window_height (window) >= window_min_height << 1)
1762 window = Fsplit_window (window, Qnil, Qnil);
1763 }
1764 }
1765 else
1766 window = Fget_lru_window (Qnil);
1767
1768 Fset_window_buffer (window, buffer);
1769 return window;
1770}
1771
1772void
1773temp_output_buffer_show (buf)
1774 register Lisp_Object buf;
1775{
1776 register struct buffer *old = current_buffer;
1777 register Lisp_Object window;
1778 register struct window *w;
1779
1780 Fset_buffer (buf);
1781 XBUFFER (buf)->save_modified = MODIFF;
1782 BEGV = BEG;
1783 ZV = Z;
1784 SET_PT (BEG);
1785 clip_changed = 1;
1786 set_buffer_internal (old);
1787
1788 if (!EQ (Vtemp_buffer_show_function, Qnil))
1789 call1 (Vtemp_buffer_show_function, buf);
1790 else
1791 {
1792 window = Fdisplay_buffer (buf, Qnil);
1793
44fa5b1e
JB
1794#ifdef MULTI_FRAME
1795 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
1796 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
1797#endif /* MULTI_FRAME */
7ab12479
JB
1798 Vminibuf_scroll_window = window;
1799 w = XWINDOW (window);
1800 XFASTINT (w->hscroll) = 0;
1801 set_marker_restricted (w->start, make_number (1), buf);
1802 set_marker_restricted (w->pointm, make_number (1), buf);
1803 }
1804}
1805\f
1806static
1807make_dummy_parent (window)
1808 Lisp_Object window;
1809{
1810 register Lisp_Object old, new;
1811 register struct window *o, *p;
1812
1813 old = window;
1814 XSETTYPE (old, Lisp_Vector);
1815 new = Fcopy_sequence (old);
1816 XSETTYPE (new, Lisp_Window);
1817
1818 o = XWINDOW (old);
1819 p = XWINDOW (new);
1820 XFASTINT (p->sequence_number) = ++sequence_number;
1821
1822 /* Put new into window structure in place of window */
1823 replace_window (window, new);
1824
1825 o->next = Qnil;
1826 o->prev = Qnil;
1827 o->vchild = Qnil;
1828 o->hchild = Qnil;
1829 o->parent = new;
1830
1831 p->start = Qnil;
1832 p->pointm = Qnil;
1833 p->buffer = Qnil;
1834}
1835
1836DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
1837 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1838WINDOW defaults to selected one and SIZE to half its size.\n\
1839If optional third arg HOR-FLAG is non-nil, split side by side\n\
1840and put SIZE columns in the first of the pair.")
1841 (window, chsize, horflag)
1842 Lisp_Object window, chsize, horflag;
1843{
1844 register Lisp_Object new;
1845 register struct window *o, *p;
1846 register int size;
1847
265a9e55 1848 if (NILP (window))
7ab12479
JB
1849 window = selected_window;
1850 else
605be8af 1851 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1852
1853 o = XWINDOW (window);
1854
265a9e55 1855 if (NILP (chsize))
7ab12479 1856 {
265a9e55 1857 if (!NILP (horflag))
7ab12479
JB
1858 /* Round odd size up, since this is for the left-hand window,
1859 and it will lose a column for the separators. */
1860 size = ((XFASTINT (o->width) + 1) & -2) >> 1;
1861 else
1862 size = XFASTINT (o->height) >> 1;
1863 }
1864 else
1865 {
1866 CHECK_NUMBER (chsize, 1);
1867 size = XINT (chsize);
1868 }
1869
1870 if (MINI_WINDOW_P (o))
1871 error ("Attempt to split minibuffer window");
44fa5b1e
JB
1872 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
1873 error ("Attempt to split unsplittable frame");
7ab12479 1874
a481b3ea 1875 check_min_window_sizes ();
7ab12479 1876
265a9e55 1877 if (NILP (horflag))
7ab12479
JB
1878 {
1879 if (size < window_min_height
1880 || size + window_min_height > XFASTINT (o->height))
1881 args_out_of_range_3 (window, chsize, horflag);
265a9e55
JB
1882 if (NILP (o->parent)
1883 || NILP (XWINDOW (o->parent)->vchild))
7ab12479
JB
1884 {
1885 make_dummy_parent (window);
1886 new = o->parent;
1887 XWINDOW (new)->vchild = window;
1888 }
1889 }
1890 else
1891 {
1892 if (size < window_min_width
1893 || size + window_min_width > XFASTINT (o->width))
1894 args_out_of_range_3 (window, chsize, horflag);
265a9e55
JB
1895 if (NILP (o->parent)
1896 || NILP (XWINDOW (o->parent)->hchild))
7ab12479
JB
1897 {
1898 make_dummy_parent (window);
1899 new = o->parent;
1900 XWINDOW (new)->hchild = window;
1901 }
1902 }
1903
1904 /* Now we know that window's parent is a vertical combination
1905 if we are dividing vertically, or a horizontal combination
1906 if we are making side-by-side windows */
1907
1908 windows_or_buffers_changed++;
1909 new = make_window ();
1910 p = XWINDOW (new);
1911
44fa5b1e 1912 p->frame = o->frame;
7ab12479 1913 p->next = o->next;
265a9e55 1914 if (!NILP (p->next))
7ab12479
JB
1915 XWINDOW (p->next)->prev = new;
1916 p->prev = window;
1917 o->next = new;
1918 p->parent = o->parent;
1919 p->buffer = Qt;
1920
1921 Fset_window_buffer (new, o->buffer);
1922
44fa5b1e 1923 /* Apportion the available frame space among the two new windows */
7ab12479 1924
265a9e55 1925 if (!NILP (horflag))
7ab12479
JB
1926 {
1927 p->height = o->height;
1928 p->top = o->top;
1929 XFASTINT (p->width) = XFASTINT (o->width) - size;
1930 XFASTINT (o->width) = size;
1931 XFASTINT (p->left) = XFASTINT (o->left) + size;
1932 }
1933 else
1934 {
1935 p->left = o->left;
1936 p->width = o->width;
1937 XFASTINT (p->height) = XFASTINT (o->height) - size;
1938 XFASTINT (o->height) = size;
1939 XFASTINT (p->top) = XFASTINT (o->top) + size;
1940 }
1941
1942 return new;
1943}
1944\f
1945DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
1946 "Make current window ARG lines bigger.\n\
1947From program, optional second arg non-nil means grow sideways ARG columns.")
1948 (n, side)
1949 register Lisp_Object n, side;
1950{
1951 CHECK_NUMBER (n, 0);
265a9e55 1952 change_window_height (XINT (n), !NILP (side));
7ab12479
JB
1953 return Qnil;
1954}
1955
1956DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
1957 "Make current window ARG lines smaller.\n\
1958From program, optional second arg non-nil means shrink sideways ARG columns.")
1959 (n, side)
1960 register Lisp_Object n, side;
1961{
1962 CHECK_NUMBER (n, 0);
265a9e55 1963 change_window_height (-XINT (n), !NILP (side));
7ab12479
JB
1964 return Qnil;
1965}
1966
1967int
1968window_height (window)
1969 Lisp_Object window;
1970{
1971 register struct window *p = XWINDOW (window);
1972 return XFASTINT (p->height);
1973}
1974
1975int
1976window_width (window)
1977 Lisp_Object window;
1978{
1979 register struct window *p = XWINDOW (window);
1980 return XFASTINT (p->width);
1981}
1982
05c2896a
JB
1983#define MINSIZE(w) \
1984 (widthflag \
1985 ? window_min_width \
1986 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
7ab12479
JB
1987
1988#define CURBEG(w) \
05c2896a 1989 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
7ab12479
JB
1990
1991#define CURSIZE(w) \
05c2896a 1992 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
7ab12479
JB
1993
1994/* Unlike set_window_height, this function
1995 also changes the heights of the siblings so as to
1996 keep everything consistent. */
1997
1998change_window_height (delta, widthflag)
1999 register int delta;
2000 int widthflag;
2001{
2002 register Lisp_Object parent;
2003 Lisp_Object window;
2004 register struct window *p;
2005 int *sizep;
2006 int (*sizefun) () = widthflag ? window_width : window_height;
2007 register int (*setsizefun) () = (widthflag
2008 ? set_window_width
2009 : set_window_height);
2010
a481b3ea 2011 check_min_window_sizes ();
7ab12479
JB
2012
2013 window = selected_window;
2014 while (1)
2015 {
2016 p = XWINDOW (window);
2017 parent = p->parent;
265a9e55 2018 if (NILP (parent))
7ab12479
JB
2019 {
2020 if (widthflag)
2021 error ("No other window to side of this one");
2022 break;
2023 }
265a9e55
JB
2024 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
2025 : !NILP (XWINDOW (parent)->vchild))
7ab12479
JB
2026 break;
2027 window = parent;
2028 }
2029
05c2896a 2030 sizep = &CURSIZE (window);
7ab12479 2031
05c2896a 2032 if (*sizep + delta < MINSIZE (window))
7ab12479
JB
2033 {
2034 Fdelete_window (window);
2035 return;
2036 }
2037
2038 {
2039 register int maxdelta;
7ab12479 2040
265a9e55
JB
2041 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
2042 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
2043 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
44fa5b1e
JB
2044 /* This is a frame with only one window, a minibuffer-only
2045 or a minibufferless frame. */
d5783c40 2046 : (delta = 0));
7ab12479
JB
2047
2048 if (delta > maxdelta)
2049 /* This case traps trying to make the minibuffer
44fa5b1e
JB
2050 the full frame, or make the only window aside from the
2051 minibuffer the full frame. */
7ab12479 2052 delta = maxdelta;
d5783c40
JB
2053
2054 if (delta == 0)
2055 return;
7ab12479
JB
2056 }
2057
265a9e55 2058 if (!NILP (p->next) &&
7ab12479
JB
2059 (*sizefun) (p->next) - delta >= MINSIZE (p->next))
2060 {
2061 (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
2062 (*setsizefun) (window, *sizep + delta, 0);
05c2896a 2063 CURBEG (p->next) += delta;
7ab12479
JB
2064 /* This does not change size of p->next,
2065 but it propagates the new top edge to its children */
2066 (*setsizefun) (p->next, (*sizefun) (p->next), 0);
2067 }
265a9e55 2068 else if (!NILP (p->prev) &&
7ab12479
JB
2069 (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
2070 {
2071 (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
05c2896a 2072 CURBEG (window) -= delta;
7ab12479
JB
2073 (*setsizefun) (window, *sizep + delta, 0);
2074 }
2075 else
2076 {
2077 register int delta1;
2078 register int opht = (*sizefun) (parent);
2079
2080 /* If trying to grow this window to or beyond size of the parent,
2081 make delta1 so big that, on shrinking back down,
2082 all the siblings end up with less than one line and are deleted. */
2083 if (opht <= *sizep + delta)
2084 delta1 = opht * opht * 2;
2085 /* Otherwise, make delta1 just right so that if we add delta1
2086 lines to this window and to the parent, and then shrink
2087 the parent back to its original size, the new proportional
2088 size of this window will increase by delta. */
2089 else
2090 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
2091
2092 /* Add delta1 lines or columns to this window, and to the parent,
2093 keeping things consistent while not affecting siblings. */
05c2896a 2094 CURSIZE (parent) = opht + delta1;
7ab12479
JB
2095 (*setsizefun) (window, *sizep + delta1, 0);
2096
2097 /* Squeeze out delta1 lines or columns from our parent,
2098 shriking this window and siblings proportionately.
2099 This brings parent back to correct size.
2100 Delta1 was calculated so this makes this window the desired size,
2101 taking it all out of the siblings. */
2102 (*setsizefun) (parent, opht, 0);
2103 }
2104
2105 XFASTINT (p->last_modified) = 0;
2106}
2107#undef MINSIZE
2108#undef CURBEG
2109#undef CURSIZE
2110
2111\f
2112/* Return number of lines of text (not counting mode line) in W. */
2113
2114int
2115window_internal_height (w)
2116 struct window *w;
2117{
2118 int ht = XFASTINT (w->height);
2119
2120 if (MINI_WINDOW_P (w))
2121 return ht;
2122
265a9e55
JB
2123 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2124 || !NILP (w->next) || !NILP (w->prev)
44fa5b1e 2125 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
7ab12479
JB
2126 return ht - 1;
2127
2128 return ht;
2129}
2130
535e0b8e
JB
2131
2132/* Return the number of columns in W.
a3c87d4e 2133 Don't count columns occupied by scroll bars or the vertical bar
535e0b8e
JB
2134 separating W from the sibling to its right. */
2135int
2136window_internal_width (w)
2137 struct window *w;
2138{
2139 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2140 int left = XINT (w->left);
2141 int width = XINT (w->width);
2142
2143 /* If this window is flush against the right edge of the frame, its
2144 internal width is its full width. */
2145 if (left + width >= FRAME_WIDTH (f))
2146 return width;
2147
2148 /* If we are not flush right, then our rightmost columns are
2149 occupied by some sort of separator. */
2150
a3c87d4e
JB
2151 /* Scroll bars occupy a few columns. */
2152 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2153 return width - VERTICAL_SCROLL_BAR_WIDTH;
535e0b8e
JB
2154
2155 /* The column of `|' characters separating side-by-side windows
2156 occupies one column only. */
2157 return width - 1;
2158}
2159
2160
7ab12479
JB
2161/* Scroll contents of window WINDOW up N lines. */
2162
2163void
f8026fd8 2164window_scroll (window, n, noerror)
7ab12479
JB
2165 Lisp_Object window;
2166 int n;
f8026fd8 2167 int noerror;
7ab12479
JB
2168{
2169 register struct window *w = XWINDOW (window);
2170 register int opoint = point;
2171 register int pos;
2172 register int ht = window_internal_height (w);
2173 register Lisp_Object tem;
2174 int lose;
2175 Lisp_Object bolp, nmoved;
2176
2177 XFASTINT (tem) = point;
2178 tem = Fpos_visible_in_window_p (tem, window);
2179
265a9e55 2180 if (NILP (tem))
7ab12479 2181 {
cd2be1dd 2182 Fvertical_motion (make_number (- (ht / 2)), window);
7ab12479
JB
2183 XFASTINT (tem) = point;
2184 Fset_marker (w->start, tem, w->buffer);
2185 w->force_start = Qt;
2186 }
2187
2188 SET_PT (marker_position (w->start));
2189 lose = n < 0 && point == BEGV;
540b6aa0 2190 Fvertical_motion (make_number (n), window);
7ab12479
JB
2191 pos = point;
2192 bolp = Fbolp ();
2193 SET_PT (opoint);
2194
2195 if (lose)
f8026fd8
JB
2196 {
2197 if (noerror)
2198 return;
2199 else
2200 Fsignal (Qbeginning_of_buffer, Qnil);
2201 }
7ab12479
JB
2202
2203 if (pos < ZV)
7ab12479
JB
2204 {
2205 set_marker_restricted (w->start, make_number (pos), w->buffer);
2206 w->start_at_line_beg = bolp;
2207 w->update_mode_line = Qt;
2208 XFASTINT (w->last_modified) = 0;
2209 if (pos > opoint)
2210 SET_PT (pos);
2211 if (n < 0)
2212 {
2213 SET_PT (pos);
540b6aa0 2214 tem = Fvertical_motion (make_number (ht), window);
7ab12479
JB
2215 if (point > opoint || XFASTINT (tem) < ht)
2216 SET_PT (opoint);
2217 else
540b6aa0 2218 Fvertical_motion (make_number (-1), window);
7ab12479
JB
2219 }
2220 }
2221 else
f8026fd8
JB
2222 {
2223 if (noerror)
2224 return;
2225 else
2226 Fsignal (Qend_of_buffer, Qnil);
2227 }
7ab12479
JB
2228}
2229\f
2230/* This is the guts of Fscroll_up and Fscroll_down. */
2231
2232static void
2233scroll_command (n, direction)
2234 register Lisp_Object n;
2235 int direction;
2236{
2237 register int defalt;
2238 int count = specpdl_ptr - specpdl;
2239
95605e15
JB
2240 /* If selected window's buffer isn't current, make it current for the moment.
2241 But don't screw up if window_scroll gets an error. */
7ab12479 2242 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
95605e15
JB
2243 {
2244 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2245 Fset_buffer (XWINDOW (selected_window)->buffer);
2246 }
7ab12479
JB
2247
2248 defalt = (window_internal_height (XWINDOW (selected_window))
2249 - next_screen_context_lines);
2250 defalt = direction * (defalt < 1 ? 1 : defalt);
2251
265a9e55 2252 if (NILP (n))
f8026fd8 2253 window_scroll (selected_window, defalt, 0);
7ab12479 2254 else if (EQ (n, Qminus))
f8026fd8 2255 window_scroll (selected_window, - defalt, 0);
7ab12479
JB
2256 else
2257 {
2258 n = Fprefix_numeric_value (n);
f8026fd8 2259 window_scroll (selected_window, XINT (n) * direction, 0);
7ab12479 2260 }
95605e15
JB
2261
2262 unbind_to (count, Qnil);
7ab12479
JB
2263}
2264
2265DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2266 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2267A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 2268Negative ARG means scroll downward.\n\
7ab12479
JB
2269When calling from a program, supply a number as argument or nil.")
2270 (n)
2271 Lisp_Object n;
2272{
2273 scroll_command (n, 1);
2274 return Qnil;
2275}
2276
2277DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2278 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2279A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 2280Negative ARG means scroll upward.\n\
7ab12479
JB
2281When calling from a program, supply a number as argument or nil.")
2282 (n)
2283 Lisp_Object n;
2284{
2285 scroll_command (n, -1);
2286 return Qnil;
2287}
2288
2289DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
99e5add3 2290 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
7ab12479 2291The next window is the one below the current one; or the one at the top\n\
279e0e0c 2292if the current one is at the bottom. Negative ARG means scroll downward.\n\
7ab12479
JB
2293When calling from a program, supply a number as argument or nil.\n\
2294\n\
77b24de6 2295If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
7ab12479
JB
2296specifies the window to scroll.\n\
2297If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2298showing that buffer, popping the buffer up if necessary.")
2299 (n)
2300 register Lisp_Object n;
2301{
2302 register Lisp_Object window;
2303 register int ht;
2304 register struct window *w;
2305 register int count = specpdl_ptr - specpdl;
2306
2307 if (MINI_WINDOW_P (XWINDOW (selected_window))
265a9e55 2308 && !NILP (Vminibuf_scroll_window))
7ab12479
JB
2309 window = Vminibuf_scroll_window;
2310 /* If buffer is specified, scroll that buffer. */
265a9e55 2311 else if (!NILP (Vother_window_scroll_buffer))
7ab12479
JB
2312 {
2313 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
265a9e55 2314 if (NILP (window))
7ab12479
JB
2315 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2316 }
2317 else
dbc4e1c1
JB
2318 {
2319 /* Nothing specified; look for a neighboring window on the same
2320 frame. */
2321 window = Fnext_window (selected_window, Qnil, Qnil);
2322
2323 if (EQ (window, selected_window))
2324 /* That didn't get us anywhere; look for a window on another
2325 visible frame. */
2326 do
2327 window = Fnext_window (window, Qnil, Qt);
2328 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
2329 && ! EQ (window, selected_window));
2330 }
2331
605be8af 2332 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2333
2334 if (EQ (window, selected_window))
2335 error ("There is no other window");
2336
2337 w = XWINDOW (window);
2338 ht = window_internal_height (w);
2339
2340 /* Don't screw up if window_scroll gets an error. */
2341 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2342
2343 Fset_buffer (w->buffer);
2344 SET_PT (marker_position (w->pointm));
2345
265a9e55 2346 if (NILP (n))
f8026fd8 2347 window_scroll (window, ht - next_screen_context_lines, 1);
7ab12479 2348 else if (EQ (n, Qminus))
f8026fd8 2349 window_scroll (window, next_screen_context_lines - ht, 1);
7ab12479
JB
2350 else
2351 {
2352 if (XTYPE (n) == Lisp_Cons)
2353 n = Fcar (n);
2354 CHECK_NUMBER (n, 0);
f8026fd8 2355 window_scroll (window, XINT (n), 1);
7ab12479
JB
2356 }
2357
2358 Fset_marker (w->pointm, make_number (point), Qnil);
f4e7b2c2 2359 unbind_to (count, Qnil);
7ab12479
JB
2360
2361 return Qnil;
2362}
2363\f
644b477c 2364DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
7ab12479
JB
2365 "Scroll selected window display ARG columns left.\n\
2366Default for ARG is window width minus 2.")
2367 (arg)
2368 register Lisp_Object arg;
2369{
2370
265a9e55 2371 if (NILP (arg))
b8baad40 2372 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
7ab12479
JB
2373 else
2374 arg = Fprefix_numeric_value (arg);
2375
2376 return
2377 Fset_window_hscroll (selected_window,
2378 make_number (XINT (XWINDOW (selected_window)->hscroll)
2379 + XINT (arg)));
2380}
2381
644b477c 2382DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
7ab12479
JB
2383 "Scroll selected window display ARG columns right.\n\
2384Default for ARG is window width minus 2.")
2385 (arg)
2386 register Lisp_Object arg;
2387{
265a9e55 2388 if (NILP (arg))
b8baad40 2389 XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
7ab12479
JB
2390 else
2391 arg = Fprefix_numeric_value (arg);
2392
2393 return
2394 Fset_window_hscroll (selected_window,
2395 make_number (XINT (XWINDOW (selected_window)->hscroll)
2396 - XINT (arg)));
2397}
2398
2399DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
44fa5b1e 2400 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
7ab12479 2401The desired position of point is always relative to the current window.\n\
44fa5b1e
JB
2402Just C-u as prefix means put point in the center of the window.\n\
2403No arg (i.e., it is nil) erases the entire frame and then\n\
2404redraws with point in the center of the current window.")
7ab12479
JB
2405 (n)
2406 register Lisp_Object n;
2407{
2408 register struct window *w = XWINDOW (selected_window);
2409 register int ht = window_internal_height (w);
2410 register int opoint = point;
540b6aa0 2411 Lisp_Object window;
7ab12479 2412
265a9e55 2413 if (NILP (n))
7ab12479 2414 {
44fa5b1e 2415 extern int frame_garbaged;
7ab12479 2416
44fa5b1e 2417 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
7ab12479
JB
2418 XFASTINT (n) = ht / 2;
2419 }
2420 else if (XTYPE (n) == Lisp_Cons) /* Just C-u. */
2421 {
2422 XFASTINT (n) = ht / 2;
2423 }
2424 else
2425 {
2426 n = Fprefix_numeric_value (n);
2427 CHECK_NUMBER (n, 0);
2428 }
2429
2430 if (XINT (n) < 0)
2431 XSETINT (n, XINT (n) + ht);
2432
2433 XSETINT (n, - XINT (n));
2434
540b6aa0
RS
2435 XSET (window, Lisp_Window, w);
2436 Fvertical_motion (n, window);
7ab12479
JB
2437 Fset_marker (w->start, make_number (point), w->buffer);
2438 w->start_at_line_beg = Fbolp ();
2439
2440 SET_PT (opoint);
2441 w->force_start = Qt;
2442
2443 return Qnil;
2444}
2445\f
2446DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
2447 1, 1, "P",
2448 "Position point relative to window.\n\
2449With no argument, position text at center of window.\n\
44fa5b1e 2450An argument specifies frame line; zero means top of window,\n\
7ab12479
JB
2451negative means relative to bottom of window.")
2452 (arg)
2453 register Lisp_Object arg;
2454{
2455 register struct window *w = XWINDOW (selected_window);
2456 register int height = window_internal_height (w);
2457 register int start;
540b6aa0 2458 Lisp_Object window;
7ab12479 2459
265a9e55 2460 if (NILP (arg))
7ab12479
JB
2461 XFASTINT (arg) = height / 2;
2462 else
2463 {
2464 arg = Fprefix_numeric_value (arg);
2465 if (XINT (arg) < 0)
2466 XSETINT (arg, XINT (arg) + height);
2467 }
2468
2469 start = marker_position (w->start);
540b6aa0 2470 XSET (window, Lisp_Window, w);
7ab12479
JB
2471 if (start < BEGV || start > ZV)
2472 {
cd2be1dd 2473 Fvertical_motion (make_number (- (height / 2)), window);
7ab12479
JB
2474 Fset_marker (w->start, make_number (point), w->buffer);
2475 w->start_at_line_beg = Fbolp ();
2476 w->force_start = Qt;
2477 }
2478 else
2479 SET_PT (start);
2480
540b6aa0 2481 return Fvertical_motion (arg, window);
7ab12479
JB
2482}
2483\f
2484struct save_window_data
2485 {
2486 int size_from_Lisp_Vector_struct;
2487 struct Lisp_Vector *next_from_Lisp_Vector_struct;
8f6ea2e9 2488 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
bdc727bf 2489 Lisp_Object selected_frame;
7ab12479
JB
2490 Lisp_Object current_window;
2491 Lisp_Object current_buffer;
2492 Lisp_Object minibuf_scroll_window;
2493 Lisp_Object root_window;
bdc727bf 2494 Lisp_Object focus_frame;
7ab12479
JB
2495 /* A vector, interpreted as a struct saved_window */
2496 Lisp_Object saved_windows;
2497 };
ff06df24
JB
2498
2499/* Arg to Fmake_vector */
2500#define SAVE_WINDOW_DATA_SIZE \
2501 ((sizeof (struct save_window_data) \
2502 - (sizeof (struct Lisp_Vector) \
2503 /* Don't count the contents member of the struct Lisp_Vector */ \
2504 - sizeof (Lisp_Object))) \
2505 / sizeof (Lisp_Object))
7ab12479
JB
2506
2507/* This is saved as a Lisp_Vector */
2508struct saved_window
2509 {
2510 /* these first two must agree with struct Lisp_Vector in lisp.h */
2511 int size_from_Lisp_Vector_struct;
2512 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2513
2514 Lisp_Object window;
2515 Lisp_Object buffer, start, pointm, mark;
2516 Lisp_Object left, top, width, height, hscroll;
2517 Lisp_Object parent, prev;
2518 Lisp_Object start_at_line_beg;
2519 Lisp_Object display_table;
2520 };
2521#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2522
2523#define SAVED_WINDOW_N(swv,n) \
2524 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2525
2526DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
2527 "T if OBJECT is a window-configration object.")
2528 (obj)
2529 Lisp_Object obj;
2530{
2531 if (XTYPE (obj) == Lisp_Window_Configuration)
2532 return Qt;
2533 return Qnil;
2534}
2535
2536
d5b2799e
RS
2537DEFUN ("set-window-configuration", Fset_window_configuration,
2538 Sset_window_configuration, 1, 1, 0,
7ab12479
JB
2539 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2540CONFIGURATION must be a value previously returned\n\
2541by `current-window-configuration' (which see).")
2f83aebe
JB
2542 (configuration)
2543 Lisp_Object configuration;
7ab12479 2544{
7ab12479
JB
2545 register struct save_window_data *data;
2546 struct Lisp_Vector *saved_windows;
7ab12479 2547 Lisp_Object new_current_buffer;
fd482be5 2548 Lisp_Object frame;
44fa5b1e 2549 FRAME_PTR f;
7ab12479 2550
2f83aebe 2551 while (XTYPE (configuration) != Lisp_Window_Configuration)
7ab12479 2552 {
2f83aebe
JB
2553 configuration = wrong_type_argument (intern ("window-configuration-p"),
2554 configuration);
7ab12479
JB
2555 }
2556
2f83aebe 2557 data = (struct save_window_data *) XVECTOR (configuration);
7ab12479
JB
2558 saved_windows = XVECTOR (data->saved_windows);
2559
7ab12479 2560 new_current_buffer = data->current_buffer;
265a9e55 2561 if (NILP (XBUFFER (new_current_buffer)->name))
7ab12479
JB
2562 new_current_buffer = Qnil;
2563
fd482be5
JB
2564 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
2565 f = XFRAME (frame);
9ace597f 2566
fd482be5
JB
2567 /* If f is a dead frame, don't bother rebuilding its window tree.
2568 However, there is other stuff we should still try to do below. */
2569 if (FRAME_LIVE_P (f))
7ab12479 2570 {
fd482be5
JB
2571 register struct window *w;
2572 register struct saved_window *p;
2573 int k;
2574
2575 /* If the frame has been resized since this window configuration was
2576 made, we change the frame to the size specified in the
2577 configuration, restore the configuration, and then resize it
2578 back. We keep track of the prevailing height in these variables. */
2579 int previous_frame_height = FRAME_HEIGHT (f);
2580 int previous_frame_width = FRAME_WIDTH (f);
8f6ea2e9 2581 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
fd482be5
JB
2582
2583 if (XFASTINT (data->frame_height) != previous_frame_height
2584 || XFASTINT (data->frame_width) != previous_frame_width)
2585 change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
8f6ea2e9
KH
2586 if (XFASTINT (data->frame_menu_bar_lines)
2587 != previous_frame_menu_bar_lines)
2588 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
fd482be5
JB
2589
2590 windows_or_buffers_changed++;
2591
2592 /* Kludge Alert!
2593 Mark all windows now on frame as "deleted".
2594 Restoring the new configuration "undeletes" any that are in it.
2595
2596 Save their current buffers in their height fields, since we may
2597 need it later, if a buffer saved in the configuration is now
2598 dead. */
2599 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
2600
2601 for (k = 0; k < saved_windows->size; k++)
2602 {
2603 p = SAVED_WINDOW_N (saved_windows, k);
2604 w = XWINDOW (p->window);
2605 w->next = Qnil;
7ab12479 2606
fd482be5
JB
2607 if (!NILP (p->parent))
2608 w->parent = SAVED_WINDOW_N (saved_windows,
2609 XFASTINT (p->parent))->window;
2610 else
2611 w->parent = Qnil;
7ab12479 2612
fd482be5 2613 if (!NILP (p->prev))
7ab12479 2614 {
fd482be5
JB
2615 w->prev = SAVED_WINDOW_N (saved_windows,
2616 XFASTINT (p->prev))->window;
2617 XWINDOW (w->prev)->next = p->window;
2618 }
2619 else
2620 {
2621 w->prev = Qnil;
2622 if (!NILP (w->parent))
2623 {
2624 if (EQ (p->width, XWINDOW (w->parent)->width))
2625 {
2626 XWINDOW (w->parent)->vchild = p->window;
2627 XWINDOW (w->parent)->hchild = Qnil;
2628 }
2629 else
2630 {
2631 XWINDOW (w->parent)->hchild = p->window;
2632 XWINDOW (w->parent)->vchild = Qnil;
2633 }
2634 }
2635 }
2636
2637 /* If we squirreled away the buffer in the window's height,
2638 restore it now. */
2639 if (XTYPE (w->height) == Lisp_Buffer)
2640 w->buffer = w->height;
2641 w->left = p->left;
2642 w->top = p->top;
2643 w->width = p->width;
2644 w->height = p->height;
2645 w->hscroll = p->hscroll;
2646 w->display_table = p->display_table;
2647 XFASTINT (w->last_modified) = 0;
2648
2649 /* Reinstall the saved buffer and pointers into it. */
2650 if (NILP (p->buffer))
2651 w->buffer = p->buffer;
2652 else
2653 {
2654 if (!NILP (XBUFFER (p->buffer)->name))
2655 /* If saved buffer is alive, install it. */
2656 {
2657 w->buffer = p->buffer;
2658 w->start_at_line_beg = p->start_at_line_beg;
2659 set_marker_restricted (w->start,
2660 Fmarker_position (p->start),
2661 w->buffer);
2662 set_marker_restricted (w->pointm,
2663 Fmarker_position (p->pointm),
2664 w->buffer);
2665 Fset_marker (XBUFFER (w->buffer)->mark,
2666 Fmarker_position (p->mark), w->buffer);
2667
2668 /* As documented in Fcurrent_window_configuration, don't
2669 save the location of point in the buffer which was current
2670 when the window configuration was recorded. */
2671 if (!EQ (p->buffer, new_current_buffer) &&
2672 XBUFFER (p->buffer) == current_buffer)
2673 Fgoto_char (w->pointm);
2674 }
52a68e98
RS
2675 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
2676 /* Else unless window has a live buffer, get one. */
7ab12479 2677 {
fd482be5
JB
2678 w->buffer = Fcdr (Fcar (Vbuffer_alist));
2679 /* This will set the markers to beginning of visible
2680 range. */
2681 set_marker_restricted (w->start, make_number (0), w->buffer);
2682 set_marker_restricted (w->pointm, make_number (0),w->buffer);
2683 w->start_at_line_beg = Qt;
7ab12479
JB
2684 }
2685 else
fd482be5 2686 /* Keeping window's old buffer; make sure the markers
52a68e98 2687 are real. */
7ab12479 2688 {
fd482be5
JB
2689 /* Set window markers at start of visible range. */
2690 if (XMARKER (w->start)->buffer == 0)
2691 set_marker_restricted (w->start, make_number (0),
2692 w->buffer);
2693 if (XMARKER (w->pointm)->buffer == 0)
2694 set_marker_restricted (w->pointm,
2695 (make_number
2696 (BUF_PT (XBUFFER (w->buffer)))),
2697 w->buffer);
2698 w->start_at_line_beg = Qt;
7ab12479
JB
2699 }
2700 }
2701 }
9ace597f 2702
fd482be5
JB
2703 FRAME_ROOT_WINDOW (f) = data->root_window;
2704 Fselect_window (data->current_window);
7ab12479 2705
fd482be5 2706#ifdef MULTI_FRAME
db269683
JB
2707 if (NILP (data->focus_frame)
2708 || (XTYPE (data->focus_frame) == Lisp_Frame
2709 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
2710 Fredirect_frame_focus (frame, data->focus_frame);
fd482be5 2711#endif
7ab12479 2712
fd482be5
JB
2713#if 0 /* I don't understand why this is needed, and it causes problems
2714 when the frame's old selected window has been deleted. */
2715#ifdef MULTI_FRAME
2716 if (f != selected_frame && ! FRAME_TERMCAP_P (f))
d5b2799e 2717 Fhandle_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
fd482be5
JB
2718#endif
2719#endif
2720
2721 /* Set the screen height to the value it had before this function. */
2722 if (previous_frame_height != FRAME_HEIGHT (f)
2723 || previous_frame_width != FRAME_WIDTH (f))
2724 change_frame_size (f, previous_frame_height, previous_frame_width,
2725 0, 0);
8f6ea2e9
KH
2726 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
2727 x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
fd482be5 2728 }
bdc727bf 2729
ad854249 2730#ifdef MULTI_FRAME
bdc727bf 2731 /* Fselect_window will have made f the selected frame, so we
d5b2799e 2732 reselect the proper frame here. Fhandle_switch_frame will change the
bdc727bf
JB
2733 selected window too, but that doesn't make the call to
2734 Fselect_window above totally superfluous; it still sets f's
2735 selected window. */
fd482be5 2736 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
d5b2799e 2737 Fhandle_switch_frame (data->selected_frame, Qnil);
ad854249 2738#endif
bdc727bf
JB
2739
2740 if (!NILP (new_current_buffer))
2741 Fset_buffer (new_current_buffer);
2742
7ab12479
JB
2743 Vminibuf_scroll_window = data->minibuf_scroll_window;
2744 return (Qnil);
2745}
2746
44fa5b1e 2747/* Mark all windows now on frame as deleted
7ab12479
JB
2748 by setting their buffers to nil. */
2749
fd482be5 2750void
7ab12479
JB
2751delete_all_subwindows (w)
2752 register struct window *w;
2753{
265a9e55 2754 if (!NILP (w->next))
7ab12479 2755 delete_all_subwindows (XWINDOW (w->next));
265a9e55 2756 if (!NILP (w->vchild))
7ab12479 2757 delete_all_subwindows (XWINDOW (w->vchild));
265a9e55 2758 if (!NILP (w->hchild))
7ab12479 2759 delete_all_subwindows (XWINDOW (w->hchild));
605be8af
JB
2760
2761 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
2762
2763 /* We set all three of these fields to nil, to make sure that we can
2764 distinguish this dead window from any live window. Live leaf
2765 windows will have buffer set, and combination windows will have
2766 vchild or hchild set. */
2767 w->buffer = Qnil;
2768 w->vchild = Qnil;
2769 w->hchild = Qnil;
7ab12479
JB
2770}
2771\f
2772static int
2773count_windows (window)
2774 register struct window *window;
2775{
2776 register int count = 1;
265a9e55 2777 if (!NILP (window->next))
7ab12479 2778 count += count_windows (XWINDOW (window->next));
265a9e55 2779 if (!NILP (window->vchild))
7ab12479 2780 count += count_windows (XWINDOW (window->vchild));
265a9e55 2781 if (!NILP (window->hchild))
7ab12479
JB
2782 count += count_windows (XWINDOW (window->hchild));
2783 return count;
2784}
2785
2786static int
2787save_window_save (window, vector, i)
2788 Lisp_Object window;
2789 struct Lisp_Vector *vector;
2790 int i;
2791{
2792 register struct saved_window *p;
2793 register struct window *w;
2794 register Lisp_Object tem;
2795
265a9e55 2796 for (;!NILP (window); window = w->next)
7ab12479
JB
2797 {
2798 p = SAVED_WINDOW_N (vector, i);
2799 w = XWINDOW (window);
2800
2801 XFASTINT (w->temslot) = i++;
2802 p->window = window;
2803 p->buffer = w->buffer;
2804 p->left = w->left;
2805 p->top = w->top;
2806 p->width = w->width;
2807 p->height = w->height;
2808 p->hscroll = w->hscroll;
2809 p->display_table = w->display_table;
265a9e55 2810 if (!NILP (w->buffer))
7ab12479
JB
2811 {
2812 /* Save w's value of point in the window configuration.
2813 If w is the selected window, then get the value of point
2814 from the buffer; pointm is garbage in the selected window. */
2815 if (EQ (window, selected_window))
2816 {
2817 p->pointm = Fmake_marker ();
2818 Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
2819 w->buffer);
2820 }
2821 else
2822 p->pointm = Fcopy_marker (w->pointm);
2823
2824 p->start = Fcopy_marker (w->start);
2825 p->start_at_line_beg = w->start_at_line_beg;
2826
2827 tem = XBUFFER (w->buffer)->mark;
2828 p->mark = Fcopy_marker (tem);
2829 }
2830 else
2831 {
2832 p->pointm = Qnil;
2833 p->start = Qnil;
2834 p->mark = Qnil;
2835 p->start_at_line_beg = Qnil;
2836 }
2837
265a9e55 2838 if (NILP (w->parent))
7ab12479
JB
2839 p->parent = Qnil;
2840 else
2841 p->parent = XWINDOW (w->parent)->temslot;
2842
265a9e55 2843 if (NILP (w->prev))
7ab12479
JB
2844 p->prev = Qnil;
2845 else
2846 p->prev = XWINDOW (w->prev)->temslot;
2847
265a9e55 2848 if (!NILP (w->vchild))
7ab12479 2849 i = save_window_save (w->vchild, vector, i);
265a9e55 2850 if (!NILP (w->hchild))
7ab12479
JB
2851 i = save_window_save (w->hchild, vector, i);
2852 }
2853
2854 return i;
2855}
2856
2857DEFUN ("current-window-configuration",
43bad991 2858 Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
44fa5b1e
JB
2859 "Return an object representing the current window configuration of FRAME.\n\
2860If FRAME is nil or omitted, use the selected frame.\n\
7ab12479
JB
2861This describes the number of windows, their sizes and current buffers,\n\
2862and for each displayed buffer, where display starts, and the positions of\n\
2863point and mark. An exception is made for point in the current buffer:\n\
bdc727bf
JB
2864its value is -not- saved.\n\
2865This also records the currently selected frame, and FRAME's focus\n\
2866redirection (see `redirect-frame-focus').")
44fa5b1e
JB
2867 (frame)
2868 Lisp_Object frame;
7ab12479
JB
2869{
2870 register Lisp_Object tem;
2871 register int n_windows;
2872 register struct save_window_data *data;
2873 register int i;
44fa5b1e 2874 FRAME_PTR f;
43bad991 2875
44fa5b1e
JB
2876 if (NILP (frame))
2877 f = selected_frame;
43bad991
JB
2878 else
2879 {
44fa5b1e
JB
2880 CHECK_LIVE_FRAME (frame, 0);
2881 f = XFRAME (frame);
43bad991 2882 }
7ab12479 2883
44fa5b1e 2884 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
7ab12479
JB
2885 data = (struct save_window_data *)
2886 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE),
2887 Qnil));
44fa5b1e
JB
2888 XFASTINT (data->frame_width) = FRAME_WIDTH (f);
2889 XFASTINT (data->frame_height) = FRAME_HEIGHT (f);
8f6ea2e9 2890 XFASTINT (data->frame_menu_bar_lines) = FRAME_MENU_BAR_LINES (f);
ad854249 2891#ifdef MULTI_FRAME
bdc727bf 2892 XSET (data->selected_frame, Lisp_Frame, selected_frame);
ad854249 2893#endif
44fa5b1e 2894 data->current_window = FRAME_SELECTED_WINDOW (f);
7ab12479
JB
2895 XSET (data->current_buffer, Lisp_Buffer, current_buffer);
2896 data->minibuf_scroll_window = Vminibuf_scroll_window;
44fa5b1e 2897 data->root_window = FRAME_ROOT_WINDOW (f);
bdc727bf 2898 data->focus_frame = FRAME_FOCUS_FRAME (f);
7ab12479
JB
2899 tem = Fmake_vector (make_number (n_windows), Qnil);
2900 data->saved_windows = tem;
2901 for (i = 0; i < n_windows; i++)
2902 XVECTOR (tem)->contents[i]
2903 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
44fa5b1e 2904 save_window_save (FRAME_ROOT_WINDOW (f),
7ab12479
JB
2905 XVECTOR (tem), 0);
2906 XSET (tem, Lisp_Window_Configuration, data);
2907 return (tem);
2908}
2909
2910DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
2911 0, UNEVALLED, 0,
2912 "Execute body, preserving window sizes and contents.\n\
2913Restores which buffer appears in which window, where display starts,\n\
2914as well as the current buffer.\n\
2915Does not restore the value of point in current buffer.")
2916 (args)
2917 Lisp_Object args;
2918{
2919 register Lisp_Object val;
2920 register int count = specpdl_ptr - specpdl;
2921
2922 record_unwind_protect (Fset_window_configuration,
43bad991 2923 Fcurrent_window_configuration (Qnil));
7ab12479
JB
2924 val = Fprogn (args);
2925 return unbind_to (count, val);
2926}
2927\f
2928init_window_once ()
2929{
44fa5b1e
JB
2930#ifdef MULTI_FRAME
2931 selected_frame = make_terminal_frame ();
2932 minibuf_window = selected_frame->minibuffer_window;
2933 selected_window = selected_frame->selected_window;
2934 last_nonminibuf_frame = selected_frame;
2935#else /* not MULTI_FRAME */
7ab12479
JB
2936 extern Lisp_Object get_minibuffer ();
2937
95605e15 2938 minibuf_window = make_window ();
4b206065 2939 FRAME_ROOT_WINDOW (selected_frame) = make_window ();
7ab12479 2940
44fa5b1e
JB
2941 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->next = minibuf_window;
2942 XWINDOW (minibuf_window)->prev = FRAME_ROOT_WINDOW (selected_frame);
4b206065 2943 XWINDOW (minibuf_window)->mini_p = Qt;
7ab12479
JB
2944
2945 /* These values 9 and 10 are arbitrary,
2946 just so that there is "something there."
2947 Correct values are put in in init_xdisp */
2948
44fa5b1e 2949 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->width) = 10;
7ab12479
JB
2950 XFASTINT (XWINDOW (minibuf_window)->width) = 10;
2951
44fa5b1e 2952 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->height) = 9;
7ab12479
JB
2953 XFASTINT (XWINDOW (minibuf_window)->top) = 9;
2954 XFASTINT (XWINDOW (minibuf_window)->height) = 1;
2955
2956 /* Prevent error in Fset_window_buffer. */
44fa5b1e 2957 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->buffer = Qt;
7ab12479
JB
2958 XWINDOW (minibuf_window)->buffer = Qt;
2959
2960 /* Now set them up for real. */
44fa5b1e 2961 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame),
e5d77022 2962 Fcurrent_buffer ());
7ab12479
JB
2963 Fset_window_buffer (minibuf_window, get_minibuffer (0));
2964
44fa5b1e 2965 selected_window = FRAME_ROOT_WINDOW (selected_frame);
1d8d96fa
JB
2966 /* Make sure this window seems more recently used than
2967 a newly-created, never-selected window. Increment
2968 window_select_count so the first selection ever will get
2969 something newer than this. */
2970 XFASTINT (XWINDOW (selected_window)->use_time) = ++window_select_count;
44fa5b1e 2971#endif /* not MULTI_FRAME */
7ab12479
JB
2972}
2973
2974syms_of_window ()
2975{
2976 Qwindowp = intern ("windowp");
2977 staticpro (&Qwindowp);
2978
806b4d9b
JB
2979 Qwindow_live_p = intern ("window-live-p");
2980 staticpro (&Qwindow_live_p);
605be8af 2981
2f83aebe 2982#ifndef MULTI_FRAME
7ab12479
JB
2983 /* Make sure all windows get marked */
2984 staticpro (&minibuf_window);
2f83aebe 2985#endif
7ab12479
JB
2986
2987 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
2988 "Non-nil means call as function to display a help buffer.\n\
2989Used by `with-output-to-temp-buffer'.");
2990 Vtemp_buffer_show_function = Qnil;
2991
2992 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
2993 "If non-nil, function to call to handle `display-buffer'.\n\
2994It will receive two args, the buffer and a flag which if non-nil means\n\
2995 that the currently selected window is not acceptable.\n\
2996Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
2997work using this function.");
2998 Vdisplay_buffer_function = Qnil;
2999
7ab12479
JB
3000 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
3001 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
3002 Vminibuf_scroll_window = Qnil;
3003
3004 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
3005 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
3006 Vother_window_scroll_buffer = Qnil;
3007
44fa5b1e 3008 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
700f75a4 3009 "*Non-nil means `display-buffer' should make a separate frame.");
44fa5b1e 3010 pop_up_frames = 0;
7ab12479 3011
44fa5b1e
JB
3012 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
3013 "*If non-nil, function to call to handle automatic new frame creation.\n\
3014It is called with no arguments and should return a newly created frame.\n\
7ab12479 3015\n\
44fa5b1e
JB
3016A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
3017where `pop-up-frame-alist' would hold the default frame parameters.");
3018 Vpop_up_frame_function = Qnil;
7ab12479
JB
3019
3020 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
3021 "*Non-nil means display-buffer should make new windows.");
3022 pop_up_windows = 1;
3023
3024 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
3025 "*Number of lines of continuity when scrolling by screenfuls.");
3026 next_screen_context_lines = 2;
3027
3028 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
3029 "*display-buffer would prefer to split the largest window if this large.\n\
3030If there is only one window, it is split regardless of this value.");
3031 split_height_threshold = 500;
3032
3033 DEFVAR_INT ("window-min-height", &window_min_height,
3034 "*Delete any window less than this tall (including its mode line).");
3035 window_min_height = 4;
3036
3037 DEFVAR_INT ("window-min-width", &window_min_width,
3038 "*Delete any window less than this wide.");
3039 window_min_width = 10;
3040
3041 defsubr (&Sselected_window);
3042 defsubr (&Sminibuffer_window);
3043 defsubr (&Swindow_minibuffer_p);
3044 defsubr (&Swindowp);
806b4d9b 3045 defsubr (&Swindow_live_p);
7ab12479
JB
3046 defsubr (&Spos_visible_in_window_p);
3047 defsubr (&Swindow_buffer);
3048 defsubr (&Swindow_height);
3049 defsubr (&Swindow_width);
3050 defsubr (&Swindow_hscroll);
3051 defsubr (&Sset_window_hscroll);
3052 defsubr (&Swindow_edges);
d5783c40
JB
3053 defsubr (&Scoordinates_in_window_p);
3054 defsubr (&Swindow_at);
7ab12479
JB
3055 defsubr (&Swindow_point);
3056 defsubr (&Swindow_start);
3057 defsubr (&Swindow_end);
3058 defsubr (&Sset_window_point);
3059 defsubr (&Sset_window_start);
3060 defsubr (&Swindow_dedicated_p);
d207b766 3061 defsubr (&Sset_window_dedicated_p);
7ab12479
JB
3062 defsubr (&Swindow_display_table);
3063 defsubr (&Sset_window_display_table);
3064 defsubr (&Snext_window);
3065 defsubr (&Sprevious_window);
3066 defsubr (&Sother_window);
3067 defsubr (&Sget_lru_window);
3068 defsubr (&Sget_largest_window);
3069 defsubr (&Sget_buffer_window);
3070 defsubr (&Sdelete_other_windows);
3071 defsubr (&Sdelete_windows_on);
3072 defsubr (&Sreplace_buffer_in_windows);
3073 defsubr (&Sdelete_window);
3074 defsubr (&Sset_window_buffer);
3075 defsubr (&Sselect_window);
3076 defsubr (&Sdisplay_buffer);
3077 defsubr (&Ssplit_window);
3078 defsubr (&Senlarge_window);
3079 defsubr (&Sshrink_window);
3080 defsubr (&Sscroll_up);
3081 defsubr (&Sscroll_down);
3082 defsubr (&Sscroll_left);
3083 defsubr (&Sscroll_right);
3084 defsubr (&Sscroll_other_window);
3085 defsubr (&Srecenter);
3086 defsubr (&Smove_to_window_line);
3087 defsubr (&Swindow_configuration_p);
3088 defsubr (&Sset_window_configuration);
3089 defsubr (&Scurrent_window_configuration);
3090 defsubr (&Ssave_window_excursion);
3091}
3092
3093keys_of_window ()
3094{
3095 initial_define_key (control_x_map, '1', "delete-other-windows");
3096 initial_define_key (control_x_map, '2', "split-window");
3097 initial_define_key (control_x_map, '0', "delete-window");
3098 initial_define_key (control_x_map, 'o', "other-window");
3099 initial_define_key (control_x_map, '^', "enlarge-window");
3100 initial_define_key (control_x_map, '<', "scroll-left");
3101 initial_define_key (control_x_map, '>', "scroll-right");
3102
3103 initial_define_key (global_map, Ctl ('V'), "scroll-up");
3104 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
3105 initial_define_key (meta_map, 'v', "scroll-down");
3106
3107 initial_define_key (global_map, Ctl('L'), "recenter");
3108 initial_define_key (meta_map, 'r', "move-to-window-line");
3109}