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