Initial revision
[bpt/emacs.git] / src / window.c
CommitLineData
7ab12479
JB
1/* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 1, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
7ab12479
JB
21#include "config.h"
22#include "lisp.h"
23#include "buffer.h"
24#include "screen.h"
25#include "window.h"
26#include "commands.h"
27#include "indent.h"
28#include "termchar.h"
29#include "disptab.h"
30
31Lisp_Object Qwindowp;
32
33Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
34Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
35
36static void delete_all_subwindows ();
37static 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
47Lisp_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). */
53Lisp_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. */
61Lisp_Object minibuf_window;
62
63/* Non-nil means it is the window for C-M-v to scroll
64 when the minibuffer is selected. */
65Lisp_Object Vminibuf_scroll_window;
66
67/* Non-nil means this is the buffer whose window C-M-v should scroll. */
68Lisp_Object Vother_window_scroll_buffer;
69
70/* Window that the mouse is over (nil if no mouse support). */
71Lisp_Object Vmouse_window;
72
73/* Last mouse click data structure (nil if no mouse support). */
74Lisp_Object Vmouse_event;
75
76/* Non-nil means it's function to call to display temp buffers. */
77Lisp_Object Vtemp_buffer_show_function;
78
79/* If a window gets smaller than either of these, it is removed. */
80int window_min_height;
81int window_min_width;
82
83/* Nonzero implies Fdisplay_buffer should create windows. */
84int pop_up_windows;
85
86/* Nonzero implies make new X screens for Fdisplay_buffer. */
43bad991 87int pop_up_screens;
7ab12479
JB
88
89/* Non-nil means use this function instead of default */
43bad991 90Lisp_Object Vpop_up_screen_function;
7ab12479
JB
91
92/* Function to call to handle Fdisplay_buffer. */
93Lisp_Object Vdisplay_buffer_function;
94
95/* Fdisplay_buffer always splits the largest window
96 if that window is more than this high. */
97int split_height_threshold;
98
99/* Number of lines of continuity in scrolling by screenfuls. */
100int next_screen_context_lines;
101
102/* Incremented for each window created. */
103static int sequence_number;
104
105#define min(a, b) ((a) < (b) ? (a) : (b))
106\f
107DEFUN ("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
115Lisp_Object
116make_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
144DEFUN ("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
151DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 0, 0,
152 "Return the window used now for minibuffers.")
153 ()
154{
155#ifdef MULTI_SCREEN
156 if (minibuf_level == 0
157 && !EQ (minibuf_window, selected_screen->minibuffer_window)
158 && !EQ (Qnil, selected_screen->minibuffer_window))
159 {
160 Fset_window_buffer (selected_screen->minibuffer_window,
161 XWINDOW (minibuf_window)->buffer);
162 minibuf_window = selected_screen->minibuffer_window;
163 }
164
165 if (SCREENP (Vglobal_minibuffer_screen))
166 minibuf_window = XSCREEN (Vglobal_minibuffer_screen)->minibuffer_window;
167 else
168 minibuf_window = selected_screen->minibuffer_window;
169
170#endif /* MULTI_SCREEN */
171 return minibuf_window;
172}
173
174DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 1, 1, 0,
175 "Returns non-nil if WINDOW is a minibuffer window.")
176 (window)
177 Lisp_Object window;
178{
179 struct window *w = decode_window (window);
180 return (MINI_WINDOW_P (w) ? Qt : Qnil);
181}
182
183DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
184 Spos_visible_in_window_p, 0, 2, 0,
185 "Return t if position POS is currently on the screen in WINDOW.\n\
186Returns nil if that position is scrolled vertically out of view.\n\
187POS defaults to point; WINDOW, to the selected window.")
188 (pos, window)
189 Lisp_Object pos, window;
190{
191 register struct window *w;
192 register int top;
193 register int height;
194 register int posint;
195 register struct buffer *buf;
196 struct position posval;
197
198 if (NULL (pos))
199 posint = point;
200 else
201 {
202 CHECK_NUMBER_COERCE_MARKER (pos, 0);
203 posint = XINT (pos);
204 }
205
206 if (NULL (window))
207 window = selected_window;
208 else
209 CHECK_WINDOW (window, 1);
210 w = XWINDOW (window);
211 top = marker_position (w->start);
212
213 if (posint < top)
214 return Qnil;
215
216 height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
217
218 buf = XBUFFER (w->buffer);
219 if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf))
220 {
221 /* If screen is up to date,
222 use the info recorded about how much text fit on it. */
223 if (posint < BUF_Z (buf) - XFASTINT (w->window_end_pos)
224 || (XFASTINT (w->window_end_vpos) < height))
225 return Qt;
226 return Qnil;
227 }
228 else
229 {
230 if (posint > BUF_Z (buf))
231 return Qnil;
232
233 /* If that info is not correct, calculate afresh */
234 posval = *compute_motion (top, 0, 0, posint, height, 0,
235 XFASTINT (w->width) - 1
236 - (XFASTINT (w->width) + XFASTINT (w->left)
237 != XSCREEN (w->screen)->width),
238 XINT (w->hscroll), 0);
239
240 return posval.vpos < height ? Qt : Qnil;
241 }
242}
243\f
244static struct window *
245decode_window (window)
246 register Lisp_Object window;
247{
248 if (NULL (window))
249 return XWINDOW (selected_window);
250
251 CHECK_WINDOW (window, 0);
252 return XWINDOW (window);
253}
254
255DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
256 "Return the buffer that WINDOW is displaying.")
257 (window)
258 Lisp_Object window;
259{
260 return decode_window (window)->buffer;
261}
262
263DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
264 "Return the number of lines in WINDOW (including its mode line).")
265 (window)
266 Lisp_Object window;
267{
268 return decode_window (window)->height;
269}
270
271DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
272 "Return the number of columns in WINDOW.")
273 (window)
274 Lisp_Object window;
275{
276 register struct window *w = decode_window (window);
277 register int width = w->width;
278
279 /* If this window does not end at the right margin,
280 must deduct one column for the border */
281 if ((width + w->left) == SCREEN_WIDTH (XSCREEN (WINDOW_SCREEN (w))))
282 return width;
283 return width - 1;
284}
285
286DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
287 "Return the number of columns by which WINDOW is scrolled from left margin.")
288 (window)
289 Lisp_Object window;
290{
291 return decode_window (window)->hscroll;
292}
293
294DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
295 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
296NCOL should be zero or positive.")
297 (window, ncol)
298 register Lisp_Object window, ncol;
299{
300 register struct window *w;
301
302 CHECK_NUMBER (ncol, 1);
303 if (XINT (ncol) < 0) XFASTINT (ncol) = 0;
304 if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1)))
305 args_out_of_range (ncol, Qnil);
306 w = decode_window (window);
307 if (w->hscroll != ncol)
308 clip_changed = 1; /* Prevent redisplay shortcuts */
309 w->hscroll = ncol;
310 return ncol;
311}
312
313DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
314 "Return a list of the edge coordinates of WINDOW.\n\
315\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of screen.\n\
316RIGHT is one more than the rightmost column used by WINDOW,\n\
317and BOTTOM is one more than the bottommost row used by WINDOW\n\
318 and its mode-line.")
319 (window)
320 Lisp_Object window;
321{
322 register struct window *w = decode_window (window);
323
324 return Fcons (w->left, Fcons (w->top,
325 Fcons (make_number (XFASTINT (w->left) + XFASTINT (w->width)),
326 Fcons (make_number (XFASTINT (w->top)
327 + XFASTINT (w->height)),
328 Qnil))));
329}
330
331/* Find the window containing column x, row y, and return it as a
332 Lisp_Object. If x, y is on the window's modeline, set *modeline_p
333 to 1; otherwise set it to 0. If there is no window under x, y
334 return nil and leave *modeline_p unmodified. */
335Lisp_Object
336window_from_coordinates (screen, x, y, modeline_p)
337 SCREEN_PTR screen;
338 int x, y;
339 int *modeline_p;
340{
341 register Lisp_Object tem, first;
342
343 first = SCREEN_SELECTED_WINDOW (screen);
344 tem = next_screen_window (screen, first, Qt);
345
346 while (1)
347 {
348 int found = coordinates_in_window (XWINDOW (tem), &x, &y);
349
350 if (found)
351 {
7ab12479
JB
352 *modeline_p = (found == -1);
353 return tem;
354 }
355
356 if (EQ (tem, first))
357 return Qnil;
358
359 tem = next_screen_window (screen, tem, Qt);
360 }
361}
362
363DEFUN ("locate-window-from-coordinates",
364 Flocate_window_from_coordinates, Slocate_window_from_coordinates,
365 2, 2, 0,
366 "Return window on SCREEN containing position COORDINATES.\n\
367COORDINATES is a list (SCREEN-X SCREEN-Y) of coordinates\n\
368which are relative to 0,0 at the top left corner of the screen.")
369 (screen, coordinates)
370 Lisp_Object screen, coordinates;
371{
372 int part;
373
374 CHECK_SCREEN (screen, 0);
375 CHECK_CONS (coordinates, 1);
376
377 return window_from_coordinates (XSCREEN (screen),
378 XINT (Fcar (coordinates)),
379 XINT (Fcar (Fcdr (coordinates))),
380 &part);
381}
382
383DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
384 "Return current value of point in WINDOW.\n\
385For a nonselected window, this is the value point would have\n\
386if that window were selected.\n\
387\n\
388Note that, when WINDOW is the selected window and its buffer\n\
389is also currently selected, the value returned is the same as (point).\n\
390It would be more strictly correct to return the `top-level' value\n\
391of point, outside of any save-excursion forms.\n\
392But that is hard to define.")
393 (window)
394 Lisp_Object window;
395{
396 register struct window *w = decode_window (window);
397
398 if (w == XWINDOW (selected_window)
399 && current_buffer == XBUFFER (w->buffer))
400 return Fpoint ();
401 return Fmarker_position (w->pointm);
402}
403
404DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
405 "Return position at which display currently starts in WINDOW.")
406 (window)
407 Lisp_Object window;
408{
409 return Fmarker_position (decode_window (window)->start);
410}
411
412DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
413 "Return position at which display currently ends in WINDOW.")
414 (window)
415 Lisp_Object window;
416{
417 Lisp_Object value;
418 struct window *w = decode_window (window);
419
420 XSET (value, Lisp_Int,
421 BUF_Z (current_buffer) - XFASTINT (w->window_end_pos));
422
423 return value;
424}
425
426DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
427 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
428 (window, pos)
429 Lisp_Object window, pos;
430{
431 register struct window *w = decode_window (window);
432
433 CHECK_NUMBER_COERCE_MARKER (pos, 1);
434 if (w == XWINDOW (selected_window))
435 Fgoto_char (pos);
436 else
437 set_marker_restricted (w->pointm, pos, w->buffer);
438
439 return pos;
440}
441
442DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
443 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
444Optional third arg NOFORCE non-nil inhibits next redisplay\n\
445from overriding motion of point in order to display at this exact start.")
446 (window, pos, noforce)
447 Lisp_Object window, pos, noforce;
448{
449 register struct window *w = decode_window (window);
450
451 CHECK_NUMBER_COERCE_MARKER (pos, 1);
452 set_marker_restricted (w->start, pos, w->buffer);
453 /* this is not right, but much easier than doing what is right. */
454 w->start_at_line_beg = Qnil;
455 if (NULL (noforce))
456 w->force_start = Qt;
457 w->update_mode_line = Qt;
458 XFASTINT (w->last_modified) = 0;
62c07cc7
JB
459 if (!EQ (window, selected_window))
460 windows_or_buffers_changed++;
7ab12479
JB
461 return pos;
462}
463
464DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
465 1, 1, 0,
466 "Return WINDOW's dedicated object, usually t or nil.\n\
467See also `set-window-buffer-dedicated'.")
468 (window)
469 Lisp_Object window;
470{
471 return decode_window (window)->dedicated;
472}
473
474DEFUN ("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\
477Then Emacs will not automatically change which buffer appears in WINDOW.\n\
478If BUFFER is nil, make WINDOW not be dedicated (but don't change which\n\
479buffer 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
496DEFUN ("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
510struct Lisp_Vector *
511window_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
527DEFUN ("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. */
543static
544unshow_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. */
569static
570replace_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
605and so is its new parent, we should make replacement's
606children be children of that parent instead. ***/
607}
608
609DEFUN ("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
693Lisp_Object
694next_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
744extern Lisp_Object next_screen (), prev_screen ();
745
746DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
747 "Return next window after WINDOW in canonical ordering of windows.\n\
748Optional second arg MINIBUF t means count the minibuffer window\n\
749even if not active. If MINIBUF is neither t nor nil it means\n\
750not to count the minibuffer even if it is active.\n\
751Optional third arg ALL-SCREENS t means include all windows in all screens;\n\
752otherwise cycle within the selected screen, with the exception that if a\n\
753global 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
822DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
823 "Return previous window before WINDOW in canonical ordering of windows.\n\
824Optional second arg MINIBUF t means count the minibuffer window\n\
825even if not active. If MINIBUF is neither t nor nil it means\n\
826not to count the minibuffer even if it is active.\n\
827Optional third arg ALL-SCREENS t means include all windows in all screens;\n\
828otherwise cycle within the selected screen, with the exception that if a\n\
829global 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
62c07cc7 900DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
7ab12479
JB
901 "Select the ARG'th different window on this screen.\n\
902All windows on current screen are arranged in a cyclic order.\n\
903This command selects the window ARG steps away in that order.\n\
904A negative ARG moves in the opposite order. If the optional second\n\
905argument 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
937enum 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
948static Lisp_Object
949window_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
1095DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1096 "Return the window least recently selected or used for display.\n\
1097If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1098screen, 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
1111DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1112 "Return the largest window in area.\n\
1113If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1114screen, 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
1122DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1123 "Return a window currently displaying BUFFER, or nil if none.\n\
1124If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1125screen, 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
1136DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1137 0, 1, "",
1138 "Make WINDOW (or the selected window) fill its screen.\n\
1139Only 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
1167DEFUN ("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
1182DEFUN ("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
1203set_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
1266set_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
1324static int window_select_count;
1325
1326DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1327 "Make WINDOW display BUFFER as its contents.\n\
1328BUFFER 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
1369DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1370 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1371The main editor command loop selects the buffer of the selected window\n\
1372before 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
43bad991 1395 if (XSCREEN (WINDOW_SCREEN (w)) != selected_screen)
7ab12479
JB
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
1426DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2, 0,
1427 "Make BUFFER appear in some window but don't select it.\n\
1428BUFFER can be a buffer or a buffer name.\n\
1429If BUFFER is shown already in some window, just use that one,\n\
1430unless the window is the selected window and the optional second\n\
1431argument NOT_THIS_WINDOW is non-nil.\n\
1432Returns 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
43bad991
JB
1454 /* If there are no screens open that have more than a minibuffer,
1455 we need to create a new screen. */
1456 if (pop_up_screens || last_nonminibuf_screen == 0)
7ab12479
JB
1457 {
1458 window
43bad991 1459 = Fscreen_selected_window (call0 (Vpop_up_screen_function));
7ab12479
JB
1460 Fset_window_buffer (window, buffer);
1461#if 0
43bad991 1462 Fselect_screen (XWINDOW (window)->screen, Qnil);
7ab12479
JB
1463#endif
1464 return window;
1465 }
1466#endif /* MULTI_SCREEN */
1467
43bad991
JB
1468 if (pop_up_windows
1469#ifdef MULTI_SCREEN
1470 || EQ (SCREEN_ROOT_WINDOW (selected_screen),
1471 SCREEN_MINIBUF_WINDOW (selected_screen))
1472#endif
1473 )
7ab12479 1474 {
43bad991
JB
1475 Lisp_Object screens = Qnil;
1476
7ab12479 1477#ifdef MULTI_SCREEN
43bad991
JB
1478 if (EQ (SCREEN_ROOT_WINDOW (selected_screen),
1479 SCREEN_MINIBUF_WINDOW (selected_screen)))
1480 XSET (screens, Lisp_Screen, last_nonminibuf_screen);
7ab12479
JB
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
1510void
1511temp_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
1544static
1545make_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
1574DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
1575 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1576WINDOW defaults to selected one and SIZE to half its size.\n\
1577If optional third arg HOR-FLAG is non-nil, split side by side\n\
1578and 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
1687DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
1688 "Make current window ARG lines bigger.\n\
1689From 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
1698DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
1699 "Make current window ARG lines smaller.\n\
1700From 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
1709int
1710window_height (window)
1711 Lisp_Object window;
1712{
1713 register struct window *p = XWINDOW (window);
1714 return XFASTINT (p->height);
1715}
1716
1717int
1718window_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
1738change_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
1854int
1855window_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
1873void
1874window_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
1936static void
1937scroll_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
1969DEFUN ("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\
1971A near full screen is `next-screen-context-lines' less than a full screen.\n\
1972When 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
1980DEFUN ("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\
1982A near full screen is `next-screen-context-lines' less than a full screen.\n\
1983When 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
1991DEFUN ("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\
1993The next window is the one below the current one; or the one at the top\n\
1994if the current one is at the bottom.\n\
1995When calling from a program, supply a number as argument or nil.\n\
1996\n\
1997If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
1998specifies the window to scroll.\n\
1999If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2000showing 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
2054DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 1, 1, "P",
2055 "Scroll selected window display ARG columns left.\n\
2056Default 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
2072DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 1, 1, "P",
2073 "Scroll selected window display ARG columns right.\n\
2074Default 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
2089DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
2090 "Center point in window and redisplay screen. With ARG, put point on line ARG.\n\
2091The desired position of point is always relative to the current window.\n\
2092Just C-u as prefix means put point in the center of the screen.\n\
2093No arg (i.e., it is nil) erases the entire screen and then\n\
2094redraws 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
2134DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
2135 1, 1, "P",
2136 "Position point relative to window.\n\
2137With no argument, position text at center of window.\n\
2138An argument specifies screen line; zero means top of window,\n\
2139negative 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
2170struct 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 */
2185struct 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
2203DEFUN ("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
2214DEFUN ("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\
2218CONFIGURATION must be a value previously returned\n\
2219by `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;
43bad991 2230 SCREEN_PTR s;
7ab12479
JB
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
43bad991 2260 delete_all_subwindows (XWINDOW (SCREEN_ROOT_WINDOW (s)));
7ab12479
JB
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
2380static void
2381delete_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
2394static int
2395count_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
2408static int
2409save_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
2479DEFUN ("current-window-configuration",
43bad991
JB
2480 Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
2481 "Return an object representing the current window configuration of SCREEN.\n\
2482If SCREEN is nil or omitted, use the selected screen.\n\
7ab12479
JB
2483This describes the number of windows, their sizes and current buffers,\n\
2484and for each displayed buffer, where display starts, and the positions of\n\
2485point and mark. An exception is made for point in the current buffer:\n\
2486its value is -not- saved.")
43bad991
JB
2487 (screen)
2488 Lisp_Object screen;
7ab12479
JB
2489{
2490 register Lisp_Object tem;
2491 register int n_windows;
2492 register struct save_window_data *data;
2493 register int i;
43bad991
JB
2494 SCREEN_PTR s;
2495
2496 if (NULL (screen))
2497 s = selected_screen;
2498 else
2499 {
2500 CHECK_SCREEN (screen, 0);
2501 s = XSCREEN (screen);
2502 }
7ab12479 2503
43bad991 2504 n_windows = count_windows (XWINDOW (SCREEN_ROOT_WINDOW (s)));
7ab12479
JB
2505 data = (struct save_window_data *)
2506 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE),
2507 Qnil));
43bad991
JB
2508 XFASTINT (data->screen_width) = SCREEN_WIDTH (s);
2509 XFASTINT (data->screen_height) = SCREEN_HEIGHT (s);
2510 data->current_window = SCREEN_SELECTED_WINDOW (s);
7ab12479
JB
2511 XSET (data->current_buffer, Lisp_Buffer, current_buffer);
2512 data->minibuf_scroll_window = Vminibuf_scroll_window;
43bad991 2513 data->root_window = SCREEN_ROOT_WINDOW (s);
7ab12479
JB
2514 tem = Fmake_vector (make_number (n_windows), Qnil);
2515 data->saved_windows = tem;
2516 for (i = 0; i < n_windows; i++)
2517 XVECTOR (tem)->contents[i]
2518 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
43bad991 2519 save_window_save (SCREEN_ROOT_WINDOW (s),
7ab12479
JB
2520 XVECTOR (tem), 0);
2521 XSET (tem, Lisp_Window_Configuration, data);
2522 return (tem);
2523}
2524
2525DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
2526 0, UNEVALLED, 0,
2527 "Execute body, preserving window sizes and contents.\n\
2528Restores which buffer appears in which window, where display starts,\n\
2529as well as the current buffer.\n\
2530Does not restore the value of point in current buffer.")
2531 (args)
2532 Lisp_Object args;
2533{
2534 register Lisp_Object val;
2535 register int count = specpdl_ptr - specpdl;
2536
2537 record_unwind_protect (Fset_window_configuration,
43bad991 2538 Fcurrent_window_configuration (Qnil));
7ab12479
JB
2539 val = Fprogn (args);
2540 return unbind_to (count, val);
2541}
2542\f
2543init_window_once ()
2544{
2545#ifdef MULTI_SCREEN
2546 selected_screen = make_terminal_screen ();
2547 minibuf_window = selected_screen->minibuffer_window;
2548 selected_window = selected_screen->selected_window;
2549#else /* not MULTI_SCREEN */
2550 extern Lisp_Object get_minibuffer ();
2551
2552 root_window = make_window (0);
2553 minibuf_window = make_window (0);
2554
2555 XWINDOW (root_window)->next = minibuf_window;
2556 XWINDOW (minibuf_window)->prev = root_window;
2557
2558 /* These values 9 and 10 are arbitrary,
2559 just so that there is "something there."
2560 Correct values are put in in init_xdisp */
2561
2562 XFASTINT (XWINDOW (root_window)->width) = 10;
2563 XFASTINT (XWINDOW (minibuf_window)->width) = 10;
2564
2565 XFASTINT (XWINDOW (root_window)->height) = 9;
2566 XFASTINT (XWINDOW (minibuf_window)->top) = 9;
2567 XFASTINT (XWINDOW (minibuf_window)->height) = 1;
2568
2569 /* Prevent error in Fset_window_buffer. */
2570 XWINDOW (root_window)->buffer = Qt;
2571 XWINDOW (minibuf_window)->buffer = Qt;
2572
2573 /* Now set them up for real. */
2574 Fset_window_buffer (root_window, Fcurrent_buffer ());
2575 Fset_window_buffer (minibuf_window, get_minibuffer (0));
2576
2577 selected_window = root_window;
2578#endif /* not MULTI_SCREEN */
2579}
2580
2581syms_of_window ()
2582{
2583 Qwindowp = intern ("windowp");
2584 staticpro (&Qwindowp);
2585
2586 /* Make sure all windows get marked */
2587 staticpro (&minibuf_window);
2588
2589 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
2590 "Non-nil means call as function to display a help buffer.\n\
2591Used by `with-output-to-temp-buffer'.");
2592 Vtemp_buffer_show_function = Qnil;
2593
2594 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
2595 "If non-nil, function to call to handle `display-buffer'.\n\
2596It will receive two args, the buffer and a flag which if non-nil means\n\
2597 that the currently selected window is not acceptable.\n\
2598Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
2599work using this function.");
2600 Vdisplay_buffer_function = Qnil;
2601
2602 DEFVAR_LISP ("mouse-window", &Vmouse_window,
2603 "Window that the last mouse click occurred on.");
2604 Vmouse_window = Qnil;
2605
2606 DEFVAR_LISP ("mouse-event", &Vmouse_event,
2607 "The last mouse-event object. A list of four elements:\n\
2608 ((X-POS Y-POS) WINDOW SCREEN-PART KEYSEQ).\n\
2609KEYSEQ is a string, the key sequence to be looked up in the mouse maps.\n\
2610WINDOW is the window that the click applies do.\n\
2611If SCREEN-PART is non-nil, the event was on a scrollbar;\n\
2612then Y-POS is really the total length of the scrollbar, while X-POS is\n\
2613the relative position of the scrollbar's value within that total length.\n\
2614SCREEN-PART is one of the following symbols:\n\
2615 `vertical-scrollbar', `vertical-slider',\n\
2616 `vertical-thumbup', `vertical-thumbdown',\n\
2617 `horizontal-scrollbar', `horizontal-slider',\n\
2618 `horizontal-thumbleft', `horizontal-thumbright'");
2619 Vmouse_event = Qnil;
2620
2621 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
2622 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
2623 Vminibuf_scroll_window = Qnil;
2624
2625 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
2626 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
2627 Vother_window_scroll_buffer = Qnil;
2628
2629#ifdef MULTI_SCREEN
43bad991 2630 DEFVAR_BOOL ("pop-up-screens", &pop_up_screens,
7ab12479 2631 "*Non-nil means `display-buffer' should make a separate X-window.");
43bad991 2632 pop_up_screens = 0;
7ab12479 2633
43bad991 2634 DEFVAR_LISP ("pop-up-screen-function", &Vpop_up_screen_function,
7ab12479
JB
2635 "*If non-nil, function to call to handle automatic new screen creation.\n\
2636It is called with no arguments and should return a newly created screen.\n\
7ab12479
JB
2637\n\
2638A typical value might be `(lambda () (x-create-screen auto-screen-parms))'\n\
2639where `auto-screen-parms' would hold the default screen parameters.");
43bad991 2640 Vpop_up_screen_function = Qnil;
7ab12479
JB
2641#endif
2642
2643 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
2644 "*Non-nil means display-buffer should make new windows.");
2645 pop_up_windows = 1;
2646
2647 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
2648 "*Number of lines of continuity when scrolling by screenfuls.");
2649 next_screen_context_lines = 2;
2650
2651 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
2652 "*display-buffer would prefer to split the largest window if this large.\n\
2653If there is only one window, it is split regardless of this value.");
2654 split_height_threshold = 500;
2655
2656 DEFVAR_INT ("window-min-height", &window_min_height,
2657 "*Delete any window less than this tall (including its mode line).");
2658 window_min_height = 4;
2659
2660 DEFVAR_INT ("window-min-width", &window_min_width,
2661 "*Delete any window less than this wide.");
2662 window_min_width = 10;
2663
2664 defsubr (&Sselected_window);
2665 defsubr (&Sminibuffer_window);
2666 defsubr (&Swindow_minibuffer_p);
2667 defsubr (&Swindowp);
2668 defsubr (&Spos_visible_in_window_p);
2669 defsubr (&Swindow_buffer);
2670 defsubr (&Swindow_height);
2671 defsubr (&Swindow_width);
2672 defsubr (&Swindow_hscroll);
2673 defsubr (&Sset_window_hscroll);
2674 defsubr (&Swindow_edges);
2675 defsubr (&Slocate_window_from_coordinates);
2676 defsubr (&Swindow_point);
2677 defsubr (&Swindow_start);
2678 defsubr (&Swindow_end);
2679 defsubr (&Sset_window_point);
2680 defsubr (&Sset_window_start);
2681 defsubr (&Swindow_dedicated_p);
2682 defsubr (&Sset_window_buffer_dedicated);
2683 defsubr (&Swindow_display_table);
2684 defsubr (&Sset_window_display_table);
2685 defsubr (&Snext_window);
2686 defsubr (&Sprevious_window);
2687 defsubr (&Sother_window);
2688 defsubr (&Sget_lru_window);
2689 defsubr (&Sget_largest_window);
2690 defsubr (&Sget_buffer_window);
2691 defsubr (&Sdelete_other_windows);
2692 defsubr (&Sdelete_windows_on);
2693 defsubr (&Sreplace_buffer_in_windows);
2694 defsubr (&Sdelete_window);
2695 defsubr (&Sset_window_buffer);
2696 defsubr (&Sselect_window);
2697 defsubr (&Sdisplay_buffer);
2698 defsubr (&Ssplit_window);
2699 defsubr (&Senlarge_window);
2700 defsubr (&Sshrink_window);
2701 defsubr (&Sscroll_up);
2702 defsubr (&Sscroll_down);
2703 defsubr (&Sscroll_left);
2704 defsubr (&Sscroll_right);
2705 defsubr (&Sscroll_other_window);
2706 defsubr (&Srecenter);
2707 defsubr (&Smove_to_window_line);
2708 defsubr (&Swindow_configuration_p);
2709 defsubr (&Sset_window_configuration);
2710 defsubr (&Scurrent_window_configuration);
2711 defsubr (&Ssave_window_excursion);
2712}
2713
2714keys_of_window ()
2715{
2716 initial_define_key (control_x_map, '1', "delete-other-windows");
2717 initial_define_key (control_x_map, '2', "split-window");
2718 initial_define_key (control_x_map, '0', "delete-window");
2719 initial_define_key (control_x_map, 'o', "other-window");
2720 initial_define_key (control_x_map, '^', "enlarge-window");
2721 initial_define_key (control_x_map, '<', "scroll-left");
2722 initial_define_key (control_x_map, '>', "scroll-right");
2723
2724 initial_define_key (global_map, Ctl ('V'), "scroll-up");
2725 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
2726 initial_define_key (meta_map, 'v', "scroll-down");
2727
2728 initial_define_key (global_map, Ctl('L'), "recenter");
2729 initial_define_key (meta_map, 'r', "move-to-window-line");
2730}