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