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