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