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