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