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