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