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