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