Rewrote completely for better accuracy.
[emacs.git] / src / window.c
blobbe1722ae3e4e67772687b9853fb249ae335d7ec9
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
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.
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.
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. */
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"
32 Lisp_Object Qwindowp, Qwindow_live_p;
34 Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
35 Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
37 void delete_all_subwindows ();
38 static struct window *decode_window();
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.
45 This value is always the same as
46 FRAME_SELECTED_WINDOW (selected_frame). */
48 Lisp_Object selected_window;
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;
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;
60 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
61 Lisp_Object Vother_window_scroll_buffer;
63 /* Non-nil means it's function to call to display temp buffers. */
64 Lisp_Object Vtemp_buffer_show_function;
66 /* If a window gets smaller than either of these, it is removed. */
67 int window_min_height;
68 int window_min_width;
70 /* Nonzero implies Fdisplay_buffer should create windows. */
71 int pop_up_windows;
73 /* Nonzero implies make new frames for Fdisplay_buffer. */
74 int pop_up_frames;
76 /* Non-nil means use this function instead of default */
77 Lisp_Object Vpop_up_frame_function;
79 /* Function to call to handle Fdisplay_buffer. */
80 Lisp_Object Vdisplay_buffer_function;
82 /* List of buffer *names* for buffers that should have their own frames. */
83 Lisp_Object Vspecial_display_buffer_names;
85 /* List of regexps for buffer names that should have their own frames. */
86 Lisp_Object Vspecial_display_regexps;
88 /* Function to pop up a special frame. */
89 Lisp_Object Vspecial_display_function;
91 /* List of buffer *names* for buffers to appear in selected window. */
92 Lisp_Object Vsame_window_buffer_names;
94 /* List of regexps for buffer names to appear in selected window. */
95 Lisp_Object Vsame_window_regexps;
97 /* Hook run at end of temp_output_buffer_show. */
98 Lisp_Object Qtemp_buffer_show_hook;
100 /* Fdisplay_buffer always splits the largest window
101 if that window is more than this high. */
102 int split_height_threshold;
104 /* Number of lines of continuity in scrolling by screenfuls. */
105 int next_screen_context_lines;
107 /* Incremented for each window created. */
108 static int sequence_number;
110 #define min(a, b) ((a) < (b) ? (a) : (b))
112 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
113 "Returns t if OBJ is a window.")
114 (obj)
115 Lisp_Object obj;
117 return WINDOWP (obj) ? Qt : Qnil;
120 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
121 "Returns t if OBJ is a window which is currently visible.")
122 (obj)
123 Lisp_Object obj;
125 return (WINDOWP (obj) && ! NILP (XWINDOW (obj)->buffer) ? Qt : Qnil);
128 Lisp_Object
129 make_window ()
131 Lisp_Object val;
132 register struct window *p;
133 register struct Lisp_Vector *vec;
134 int i;
136 vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
137 for (i = 0; i < VECSIZE (struct window); i++)
138 vec->contents[i] = Qnil;
139 vec->size = VECSIZE (struct window);
140 p = (struct window *)vec;
141 XSETFASTINT (p->sequence_number, ++sequence_number);
142 XSETFASTINT (p->left, 0);
143 XSETFASTINT (p->top, 0);
144 XSETFASTINT (p->height, 0);
145 XSETFASTINT (p->width, 0);
146 XSETFASTINT (p->hscroll, 0);
147 XSETFASTINT (p->last_point_x, 0);
148 XSETFASTINT (p->last_point_y, 0);
149 p->start = Fmake_marker ();
150 p->pointm = Fmake_marker ();
151 XSETFASTINT (p->use_time, 0);
152 p->frame = Qnil;
153 p->display_table = Qnil;
154 p->dedicated = Qnil;
155 XSETWINDOW (val, p);
156 return val;
159 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
160 "Return the window that the cursor now appears in and commands apply to.")
163 return selected_window;
166 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
167 "Return the window used now for minibuffers.\n\
168 If the optional argument FRAME is specified, return the minibuffer window\n\
169 used by that frame.")
170 (frame)
171 Lisp_Object frame;
173 #ifdef MULTI_FRAME
174 if (NILP (frame))
175 XSETFRAME (frame, selected_frame);
176 else
177 CHECK_LIVE_FRAME (frame, 0);
178 #endif
180 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
183 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
184 "Returns non-nil if WINDOW is a minibuffer window.")
185 (window)
186 Lisp_Object window;
188 struct window *w = decode_window (window);
189 return (MINI_WINDOW_P (w) ? Qt : Qnil);
192 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
193 Spos_visible_in_window_p, 0, 2, 0,
194 "Return t if position POS is currently on the frame in WINDOW.\n\
195 Returns nil if that position is scrolled vertically out of view.\n\
196 POS defaults to point; WINDOW, to the selected window.")
197 (pos, window)
198 Lisp_Object pos, window;
200 register struct window *w;
201 register int top;
202 register int height;
203 register int posint;
204 register struct buffer *buf;
205 struct position posval;
206 int hscroll;
208 if (NILP (pos))
209 posint = PT;
210 else
212 CHECK_NUMBER_COERCE_MARKER (pos, 0);
213 posint = XINT (pos);
216 w = decode_window (window);
217 top = marker_position (w->start);
218 hscroll = XINT (w->hscroll);
220 if (posint < top)
221 return Qnil;
223 height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
225 buf = XBUFFER (w->buffer);
226 if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf))
228 /* If frame is up to date,
229 use the info recorded about how much text fit on it. */
230 if (posint < BUF_Z (buf) - XFASTINT (w->window_end_pos)
231 || (XFASTINT (w->window_end_vpos) < height))
232 return Qt;
233 return Qnil;
235 else
237 if (posint > BUF_ZV (buf))
238 return Qnil;
240 /* w->start can be out of range. If it is, do something reasonable. */
241 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
242 return Qnil;
244 /* If that info is not correct, calculate afresh */
245 posval = *compute_motion (top, 0, (hscroll ? 1 - hscroll : 0), 0,
246 posint, height, 0,
247 window_internal_width (w) - 1,
248 hscroll, 0, w);
250 return posval.vpos < height ? Qt : Qnil;
254 static struct window *
255 decode_window (window)
256 register Lisp_Object window;
258 if (NILP (window))
259 return XWINDOW (selected_window);
261 CHECK_LIVE_WINDOW (window, 0);
262 return XWINDOW (window);
265 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
266 "Return the buffer that WINDOW is displaying.")
267 (window)
268 Lisp_Object window;
270 return decode_window (window)->buffer;
273 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
274 "Return the number of lines in WINDOW (including its mode line).")
275 (window)
276 Lisp_Object window;
278 return decode_window (window)->height;
281 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
282 "Return the number of display columns in WINDOW.\n\
283 This is the width that is usable columns available for text in WINDOW.\n\
284 If you want to find out how many columns WINDOW takes up,\n\
285 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
286 (window)
287 Lisp_Object window;
289 return make_number (window_internal_width (decode_window (window)));
292 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
293 "Return the number of columns by which WINDOW is scrolled from left margin.")
294 (window)
295 Lisp_Object window;
297 return decode_window (window)->hscroll;
300 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
301 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
302 NCOL should be zero or positive.")
303 (window, ncol)
304 register Lisp_Object window, ncol;
306 register struct window *w;
308 CHECK_NUMBER (ncol, 1);
309 if (XINT (ncol) < 0) XSETFASTINT (ncol, 0);
310 w = decode_window (window);
311 if (XINT (w->hscroll) != XINT (ncol))
312 XBUFFER (w->buffer)->clip_changed = 1; /* Prevent redisplay shortcuts */
313 w->hscroll = ncol;
314 return ncol;
317 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
318 Swindow_redisplay_end_trigger, 0, 1, 0,
319 "Return WINDOW's redisplay end trigger value.\n\
320 See `set-window-redisplay-end-trigger' for more information.")
321 (window)
322 Lisp_Object window;
324 return decode_window (window)->redisplay_end_trigger;
327 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
328 Sset_window_redisplay_end_trigger, 2, 2, 0,
329 "Set WINDOW's redisplay end trigger value to VALUE.\n\
330 VALUE should be a buffer position (typically a marker) or nil.\n\
331 If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
332 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
333 with two arguments: WINDOW, and the end trigger value.\n\
334 Afterwards the end-trigger value is reset to nil.")
335 (window, value)
336 register Lisp_Object window, value;
338 register struct window *w;
340 w = decode_window (window);
341 w->redisplay_end_trigger = value;
342 return value;
345 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
346 "Return a list of the edge coordinates of WINDOW.\n\
347 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
348 RIGHT is one more than the rightmost column used by WINDOW,\n\
349 and BOTTOM is one more than the bottommost row used by WINDOW\n\
350 and its mode-line.")
351 (window)
352 Lisp_Object window;
354 register struct window *w = decode_window (window);
356 return Fcons (w->left, Fcons (w->top,
357 Fcons (make_number (XFASTINT (w->left) + XFASTINT (w->width)),
358 Fcons (make_number (XFASTINT (w->top)
359 + XFASTINT (w->height)),
360 Qnil))));
363 /* Test if the character at column *x, row *y is within window *w.
364 If it is not, return 0;
365 if it is in the window's text area,
366 set *x and *y to its location relative to the upper left corner
367 of the window, and
368 return 1;
369 if it is on the window's modeline, return 2;
370 if it is on the border between the window and its right sibling,
371 return 3. */
372 static int
373 coordinates_in_window (w, x, y)
374 register struct window *w;
375 register int *x, *y;
377 register int left = XINT (w->left);
378 register int width = XINT (w->width);
379 register int window_height = XINT (w->height);
380 register int top = XFASTINT (w->top);
382 if ( *x < left || *x >= left + width
383 || *y < top || *y >= top + window_height)
384 return 0;
386 /* Is the character is the mode line? */
387 if (*y == top + window_height - 1
388 && ! MINI_WINDOW_P (w))
389 return 2;
391 /* Is the character in the right border? */
392 if (*x == left + width - 1
393 && left + width != FRAME_WIDTH (XFRAME (w->frame)))
394 return 3;
396 *x -= left;
397 *y -= top;
398 return 1;
401 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
402 Scoordinates_in_window_p, 2, 2, 0,
403 "Return non-nil if COORDINATES are in WINDOW.\n\
404 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
405 measured in characters from the upper-left corner of the frame.\n\
406 (0 . 0) denotes the character in the upper left corner of the\n\
407 frame.\n\
408 If COORDINATES are in the text portion of WINDOW,\n\
409 the coordinates relative to the window are returned.\n\
410 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
411 If they are on the border between WINDOW and its right sibling,\n\
412 `vertical-line' is returned.")
413 (coordinates, window)
414 register Lisp_Object coordinates, window;
416 int x, y;
418 CHECK_LIVE_WINDOW (window, 0);
419 CHECK_CONS (coordinates, 1);
420 x = XINT (Fcar (coordinates));
421 y = XINT (Fcdr (coordinates));
423 switch (coordinates_in_window (XWINDOW (window), &x, &y))
425 case 0: /* NOT in window at all. */
426 return Qnil;
428 case 1: /* In text part of window. */
429 return Fcons (x, y);
431 case 2: /* In mode line of window. */
432 return Qmode_line;
434 case 3: /* On right border of window. */
435 return Qvertical_line;
437 default:
438 abort ();
442 /* Find the window containing column x, row y, and return it as a
443 Lisp_Object. If x, y is on the window's modeline, set *part
444 to 1; if it is on the separating line between the window and its
445 right sibling, set it to 2; otherwise set it to 0. If there is no
446 window under x, y return nil and leave *part unmodified. */
447 Lisp_Object
448 window_from_coordinates (frame, x, y, part)
449 FRAME_PTR frame;
450 int x, y;
451 int *part;
453 register Lisp_Object tem, first;
455 tem = first = FRAME_SELECTED_WINDOW (frame);
459 int found = coordinates_in_window (XWINDOW (tem), &x, &y);
461 if (found)
463 *part = found - 1;
464 return tem;
467 tem = Fnext_window (tem, Qt, Qlambda);
469 while (! EQ (tem, first));
471 return Qnil;
474 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
475 "Return window containing coordinates X and Y on FRAME.\n\
476 If omitted, FRAME defaults to the currently selected frame.\n\
477 The top left corner of the frame is considered to be row 0,\n\
478 column 0.")
479 (x, y, frame)
480 Lisp_Object x, y, frame;
482 int part;
484 #ifdef MULTI_FRAME
485 if (NILP (frame))
486 XSETFRAME (frame, selected_frame);
487 else
488 CHECK_LIVE_FRAME (frame, 2);
489 #endif
490 CHECK_NUMBER (x, 0);
491 CHECK_NUMBER (y, 1);
493 return window_from_coordinates (XFRAME (frame),
494 XINT (x), XINT (y),
495 &part);
498 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
499 "Return current value of point in WINDOW.\n\
500 For a nonselected window, this is the value point would have\n\
501 if that window were selected.\n\
503 Note that, when WINDOW is the selected window and its buffer\n\
504 is also currently selected, the value returned is the same as (point).\n\
505 It would be more strictly correct to return the `top-level' value\n\
506 of point, outside of any save-excursion forms.\n\
507 But that is hard to define.")
508 (window)
509 Lisp_Object window;
511 register struct window *w = decode_window (window);
513 if (w == XWINDOW (selected_window)
514 && current_buffer == XBUFFER (w->buffer))
515 return Fpoint ();
516 return Fmarker_position (w->pointm);
519 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
520 "Return position at which display currently starts in WINDOW.\n\
521 This is updated by redisplay or by calling `set-window-start'.")
522 (window)
523 Lisp_Object window;
525 return Fmarker_position (decode_window (window)->start);
528 /* This is text temporarily removed from the doc string below.
530 This function returns nil if the position is not currently known.\n\
531 That happens when redisplay is preempted and doesn't finish.\n\
532 If in that case you want to compute where the end of the window would\n\
533 have been if redisplay had finished, do this:\n\
534 (save-excursion\n\
535 (goto-char (window-start window))\n\
536 (vertical-motion (1- (window-height window)) window)\n\
537 (point))") */
539 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
540 "Return position at which display currently ends in WINDOW.\n\
541 This is updated by redisplay, when it runs to completion.\n\
542 Simply changing the buffer text or setting `window-start'\n\
543 does not update this value.")
544 (window)
545 Lisp_Object window;
547 Lisp_Object value;
548 struct window *w = decode_window (window);
549 Lisp_Object buf;
551 buf = w->buffer;
552 CHECK_BUFFER (buf, 0);
554 #if 0 /* This change broke some things. We should make it later. */
555 /* If we don't know the end position, return nil.
556 The user can compute it with vertical-motion if he wants to.
557 It would be nicer to do it automatically,
558 but that's so slow that it would probably bother people. */
559 if (NILP (w->window_end_valid))
560 return Qnil;
561 #endif
563 XSETINT (value,
564 BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
566 return value;
569 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
570 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
571 (window, pos)
572 Lisp_Object window, pos;
574 register struct window *w = decode_window (window);
576 CHECK_NUMBER_COERCE_MARKER (pos, 1);
577 if (w == XWINDOW (selected_window))
578 Fgoto_char (pos);
579 else
580 set_marker_restricted (w->pointm, pos, w->buffer);
582 return pos;
585 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
586 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
587 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
588 from overriding motion of point in order to display at this exact start.")
589 (window, pos, noforce)
590 Lisp_Object window, pos, noforce;
592 register struct window *w = decode_window (window);
594 CHECK_NUMBER_COERCE_MARKER (pos, 1);
595 set_marker_restricted (w->start, pos, w->buffer);
596 /* this is not right, but much easier than doing what is right. */
597 w->start_at_line_beg = Qnil;
598 if (NILP (noforce))
599 w->force_start = Qt;
600 w->update_mode_line = Qt;
601 XSETFASTINT (w->last_modified, 0);
602 if (!EQ (window, selected_window))
603 windows_or_buffers_changed++;
604 return pos;
607 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
608 1, 1, 0,
609 "Return WINDOW's dedicated object, usually t or nil.\n\
610 See also `set-window-dedicated-p'.")
611 (window)
612 Lisp_Object window;
614 return decode_window (window)->dedicated;
617 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
618 Sset_window_dedicated_p, 2, 2, 0,
619 "Control whether WINDOW is dedicated to the buffer it displays.\n\
620 If it is dedicated, Emacs will not automatically change\n\
621 which buffer appears in it.\n\
622 The second argument is the new value for the dedication flag;\n\
623 non-nil means yes.")
624 (window, arg)
625 Lisp_Object window, arg;
627 register struct window *w = decode_window (window);
629 if (NILP (arg))
630 w->dedicated = Qnil;
631 else
632 w->dedicated = Qt;
634 return w->dedicated;
637 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
638 0, 1, 0,
639 "Return the display-table that WINDOW is using.")
640 (window)
641 Lisp_Object window;
643 return decode_window (window)->display_table;
646 /* Get the display table for use currently on window W.
647 This is either W's display table or W's buffer's display table.
648 Ignore the specified tables if they are not valid;
649 if no valid table is specified, return 0. */
651 struct Lisp_Char_Table *
652 window_display_table (w)
653 struct window *w;
655 Lisp_Object tem;
656 tem = w->display_table;
657 if (DISP_TABLE_P (tem))
658 return XCHAR_TABLE (tem);
659 tem = XBUFFER (w->buffer)->display_table;
660 if (DISP_TABLE_P (tem))
661 return XCHAR_TABLE (tem);
662 tem = Vstandard_display_table;
663 if (DISP_TABLE_P (tem))
664 return XCHAR_TABLE (tem);
665 return 0;
668 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
669 "Set WINDOW's display-table to TABLE.")
670 (window, table)
671 register Lisp_Object window, table;
673 register struct window *w;
674 register Lisp_Object z; /* Return value. */
676 w = decode_window (window);
677 w->display_table = table;
678 return table;
681 /* Record info on buffer window w is displaying
682 when it is about to cease to display that buffer. */
683 static
684 unshow_buffer (w)
685 register struct window *w;
687 Lisp_Object buf;
689 buf = w->buffer;
690 if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
691 abort ();
693 #if 0
694 if (w == XWINDOW (selected_window)
695 || ! EQ (buf, XWINDOW (selected_window)->buffer))
696 /* Do this except when the selected window's buffer
697 is being removed from some other window. */
698 #endif
699 /* last_window_start records the start position that this buffer
700 had in the last window to be disconnected from it.
701 Now that this statement is unconditional,
702 it is possible for the buffer to be displayed in the
703 selected window, while last_window_start reflects another
704 window which was recently showing the same buffer.
705 Some people might say that might be a good thing. Let's see. */
706 XBUFFER (buf)->last_window_start = marker_position (w->start);
708 /* Point in the selected window's buffer
709 is actually stored in that buffer, and the window's pointm isn't used.
710 So don't clobber point in that buffer. */
711 if (! EQ (buf, XWINDOW (selected_window)->buffer))
712 BUF_PT (XBUFFER (buf))
713 = clip_to_bounds (BUF_BEGV (XBUFFER (buf)),
714 marker_position (w->pointm),
715 BUF_ZV (XBUFFER (buf)));
718 /* Put replacement into the window structure in place of old. */
719 static
720 replace_window (old, replacement)
721 Lisp_Object old, replacement;
723 register Lisp_Object tem;
724 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
726 /* If OLD is its frame's root_window, then replacement is the new
727 root_window for that frame. */
729 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
730 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
732 p->left = o->left;
733 p->top = o->top;
734 p->width = o->width;
735 p->height = o->height;
737 p->next = tem = o->next;
738 if (!NILP (tem))
739 XWINDOW (tem)->prev = replacement;
741 p->prev = tem = o->prev;
742 if (!NILP (tem))
743 XWINDOW (tem)->next = replacement;
745 p->parent = tem = o->parent;
746 if (!NILP (tem))
748 if (EQ (XWINDOW (tem)->vchild, old))
749 XWINDOW (tem)->vchild = replacement;
750 if (EQ (XWINDOW (tem)->hchild, old))
751 XWINDOW (tem)->hchild = replacement;
754 /*** Here, if replacement is a vertical combination
755 and so is its new parent, we should make replacement's
756 children be children of that parent instead. ***/
759 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
760 "Remove WINDOW from the display. Default is selected window.")
761 (window)
762 register Lisp_Object window;
764 register Lisp_Object tem, parent, sib;
765 register struct window *p;
766 register struct window *par;
768 /* Because this function is called by other C code on non-leaf
769 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
770 so we can't decode_window here. */
771 if (NILP (window))
772 window = selected_window;
773 else
774 CHECK_WINDOW (window, 0);
775 p = XWINDOW (window);
777 /* It's okay to delete an already-deleted window. */
778 if (NILP (p->buffer)
779 && NILP (p->hchild)
780 && NILP (p->vchild))
781 return Qnil;
783 parent = p->parent;
784 if (NILP (parent))
785 error ("Attempt to delete minibuffer or sole ordinary window");
786 par = XWINDOW (parent);
788 windows_or_buffers_changed++;
789 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (p))) = 1;
791 /* Are we trying to delete any frame's selected window? */
793 Lisp_Object frame, pwindow;
795 /* See if the frame's selected window is either WINDOW
796 or any subwindow of it, by finding all that window's parents
797 and comparing each one with WINDOW. */
798 frame = WINDOW_FRAME (XWINDOW (window));
799 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
801 while (!NILP (pwindow))
803 if (EQ (window, pwindow))
804 break;
805 pwindow = XWINDOW (pwindow)->parent;
808 if (EQ (window, pwindow))
810 Lisp_Object alternative;
811 alternative = Fnext_window (window, Qlambda, Qnil);
813 /* If we're about to delete the selected window on the
814 selected frame, then we should use Fselect_window to select
815 the new window. On the other hand, if we're about to
816 delete the selected window on any other frame, we shouldn't do
817 anything but set the frame's selected_window slot. */
818 if (EQ (window, selected_window))
819 Fselect_window (alternative);
820 else
821 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
825 tem = p->buffer;
826 /* tem is null for dummy parent windows
827 (which have inferiors but not any contents themselves) */
828 if (!NILP (tem))
830 unshow_buffer (p);
831 unchain_marker (p->pointm);
832 unchain_marker (p->start);
835 tem = p->next;
836 if (!NILP (tem))
837 XWINDOW (tem)->prev = p->prev;
839 tem = p->prev;
840 if (!NILP (tem))
841 XWINDOW (tem)->next = p->next;
843 if (EQ (window, par->hchild))
844 par->hchild = p->next;
845 if (EQ (window, par->vchild))
846 par->vchild = p->next;
848 /* Find one of our siblings to give our space to. */
849 sib = p->prev;
850 if (NILP (sib))
852 /* If p gives its space to its next sibling, that sibling needs
853 to have its top/left side pulled back to where p's is.
854 set_window_{height,width} will re-position the sibling's
855 children. */
856 sib = p->next;
857 XWINDOW (sib)->top = p->top;
858 XWINDOW (sib)->left = p->left;
861 /* Stretch that sibling. */
862 if (!NILP (par->vchild))
863 set_window_height (sib,
864 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
866 if (!NILP (par->hchild))
867 set_window_width (sib,
868 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
871 /* If parent now has only one child,
872 put the child into the parent's place. */
873 tem = par->hchild;
874 if (NILP (tem))
875 tem = par->vchild;
876 if (NILP (XWINDOW (tem)->next))
877 replace_window (parent, tem);
879 /* Since we may be deleting combination windows, we must make sure that
880 not only p but all its children have been marked as deleted. */
881 if (! NILP (p->hchild))
882 delete_all_subwindows (XWINDOW (p->hchild));
883 else if (! NILP (p->vchild))
884 delete_all_subwindows (XWINDOW (p->vchild));
886 /* Mark this window as deleted. */
887 p->buffer = p->hchild = p->vchild = Qnil;
889 return Qnil;
893 extern Lisp_Object next_frame (), prev_frame ();
895 /* This comment supplies the doc string for `next-window',
896 for make-docfile to see. We cannot put this in the real DEFUN
897 due to limits in the Unix cpp.
899 DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
900 "Return next window after WINDOW in canonical ordering of windows.\n\
901 If omitted, WINDOW defaults to the selected window.\n\
903 Optional second arg MINIBUF t means count the minibuffer window even\n\
904 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
905 it is active. MINIBUF neither t nor nil means not to count the\n\
906 minibuffer even if it is active.\n\
908 Several frames may share a single minibuffer; if the minibuffer\n\
909 counts, all windows on all frames that share that minibuffer count\n\
910 too. Therefore, `next-window' can be used to iterate through the\n\
911 set of windows even when the minibuffer is on another frame. If the\n\
912 minibuffer does not count, only windows from WINDOW's frame count.\n\
914 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
915 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
916 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
917 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
918 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
919 Anything else means restrict to WINDOW's frame.\n\
921 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
922 `next-window' to iterate through the entire cycle of acceptable\n\
923 windows, eventually ending up back at the window you started with.\n\
924 `previous-window' traverses the same cycle, in the reverse order.")
925 (window, minibuf, all_frames) */
927 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
929 (window, minibuf, all_frames)
930 register Lisp_Object window, minibuf, all_frames;
932 register Lisp_Object tem;
933 Lisp_Object start_window;
935 if (NILP (window))
936 window = selected_window;
937 else
938 CHECK_LIVE_WINDOW (window, 0);
940 start_window = window;
942 /* minibuf == nil may or may not include minibuffers.
943 Decide if it does. */
944 if (NILP (minibuf))
945 minibuf = (minibuf_level ? minibuf_window : Qlambda);
946 else if (! EQ (minibuf, Qt))
947 minibuf = Qlambda;
948 /* Now minibuf can be t => count all minibuffer windows,
949 lambda => count none of them,
950 or a specific minibuffer window (the active one) to count. */
952 #ifdef MULTI_FRAME
953 /* all_frames == nil doesn't specify which frames to include. */
954 if (NILP (all_frames))
955 all_frames = (! EQ (minibuf, Qlambda)
956 ? (FRAME_MINIBUF_WINDOW
957 (XFRAME
958 (WINDOW_FRAME
959 (XWINDOW (window)))))
960 : Qnil);
961 else if (EQ (all_frames, Qvisible))
963 else if (XFASTINT (all_frames) == 0)
965 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
966 /* If all_frames is a frame and window arg isn't on that frame, just
967 return the first window on the frame. */
968 return Fframe_first_window (all_frames);
969 else if (! EQ (all_frames, Qt))
970 all_frames = Qnil;
971 /* Now all_frames is t meaning search all frames,
972 nil meaning search just current frame,
973 visible meaning search just visible frames,
974 0 meaning search visible and iconified frames,
975 or a window, meaning search the frame that window belongs to. */
976 #endif
978 /* Do this loop at least once, to get the next window, and perhaps
979 again, if we hit the minibuffer and that is not acceptable. */
982 /* Find a window that actually has a next one. This loop
983 climbs up the tree. */
984 while (tem = XWINDOW (window)->next, NILP (tem))
985 if (tem = XWINDOW (window)->parent, !NILP (tem))
986 window = tem;
987 else
989 /* We've reached the end of this frame.
990 Which other frames are acceptable? */
991 tem = WINDOW_FRAME (XWINDOW (window));
992 #ifdef MULTI_FRAME
993 if (! NILP (all_frames))
995 Lisp_Object tem1;
997 tem1 = tem;
998 tem = next_frame (tem, all_frames);
999 /* In the case where the minibuffer is active,
1000 and we include its frame as well as the selected one,
1001 next_frame may get stuck in that frame.
1002 If that happens, go back to the selected frame
1003 so we can complete the cycle. */
1004 if (EQ (tem, tem1))
1005 XSETFRAME (tem, selected_frame);
1007 #endif
1008 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1010 break;
1013 window = tem;
1015 /* If we're in a combination window, find its first child and
1016 recurse on that. Otherwise, we've found the window we want. */
1017 while (1)
1019 if (!NILP (XWINDOW (window)->hchild))
1020 window = XWINDOW (window)->hchild;
1021 else if (!NILP (XWINDOW (window)->vchild))
1022 window = XWINDOW (window)->vchild;
1023 else break;
1026 /* Which windows are acceptible?
1027 Exit the loop and accept this window if
1028 this isn't a minibuffer window,
1029 or we're accepting all minibuffer windows,
1030 or this is the active minibuffer and we are accepting that one, or
1031 we've come all the way around and we're back at the original window. */
1032 while (MINI_WINDOW_P (XWINDOW (window))
1033 && ! EQ (minibuf, Qt)
1034 && ! EQ (minibuf, window)
1035 && ! EQ (window, start_window));
1037 return window;
1040 /* This comment supplies the doc string for `previous-window',
1041 for make-docfile to see. We cannot put this in the real DEFUN
1042 due to limits in the Unix cpp.
1044 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
1045 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
1046 If omitted, WINDOW defaults to the selected window.\n\
1048 Optional second arg MINIBUF t means count the minibuffer window even\n\
1049 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1050 it is active. MINIBUF neither t nor nil means not to count the\n\
1051 minibuffer even if it is active.\n\
1053 Several frames may share a single minibuffer; if the minibuffer\n\
1054 counts, all windows on all frames that share that minibuffer count\n\
1055 too. Therefore, `previous-window' can be used to iterate through\n\
1056 the set of windows even when the minibuffer is on another frame. If\n\
1057 the minibuffer does not count, only windows from WINDOW's frame count\n\
1059 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1060 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1061 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1062 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1063 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1064 Anything else means restrict to WINDOW's frame.\n\
1066 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1067 `previous-window' to iterate through the entire cycle of acceptable\n\
1068 windows, eventually ending up back at the window you started with.\n\
1069 `next-window' traverses the same cycle, in the reverse order.")
1070 (window, minibuf, all_frames) */
1073 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1075 (window, minibuf, all_frames)
1076 register Lisp_Object window, minibuf, all_frames;
1078 register Lisp_Object tem;
1079 Lisp_Object start_window;
1081 if (NILP (window))
1082 window = selected_window;
1083 else
1084 CHECK_LIVE_WINDOW (window, 0);
1086 start_window = window;
1088 /* minibuf == nil may or may not include minibuffers.
1089 Decide if it does. */
1090 if (NILP (minibuf))
1091 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1092 else if (! EQ (minibuf, Qt))
1093 minibuf = Qlambda;
1094 /* Now minibuf can be t => count all minibuffer windows,
1095 lambda => count none of them,
1096 or a specific minibuffer window (the active one) to count. */
1098 #ifdef MULTI_FRAME
1099 /* all_frames == nil doesn't specify which frames to include.
1100 Decide which frames it includes. */
1101 if (NILP (all_frames))
1102 all_frames = (! EQ (minibuf, Qlambda)
1103 ? (FRAME_MINIBUF_WINDOW
1104 (XFRAME
1105 (WINDOW_FRAME
1106 (XWINDOW (window)))))
1107 : Qnil);
1108 else if (EQ (all_frames, Qvisible))
1110 else if (XFASTINT (all_frames) == 0)
1112 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1113 /* If all_frames is a frame and window arg isn't on that frame, just
1114 return the first window on the frame. */
1115 return Fframe_first_window (all_frames);
1116 else if (! EQ (all_frames, Qt))
1117 all_frames = Qnil;
1118 /* Now all_frames is t meaning search all frames,
1119 nil meaning search just current frame,
1120 visible meaning search just visible frames,
1121 0 meaning search visible and iconified frames,
1122 or a window, meaning search the frame that window belongs to. */
1123 #endif
1125 /* Do this loop at least once, to get the previous window, and perhaps
1126 again, if we hit the minibuffer and that is not acceptable. */
1129 /* Find a window that actually has a previous one. This loop
1130 climbs up the tree. */
1131 while (tem = XWINDOW (window)->prev, NILP (tem))
1132 if (tem = XWINDOW (window)->parent, !NILP (tem))
1133 window = tem;
1134 else
1136 /* We have found the top window on the frame.
1137 Which frames are acceptable? */
1138 tem = WINDOW_FRAME (XWINDOW (window));
1139 #ifdef MULTI_FRAME
1140 if (! NILP (all_frames))
1141 /* It's actually important that we use prev_frame here,
1142 rather than next_frame. All the windows acceptable
1143 according to the given parameters should form a ring;
1144 Fnext_window and Fprevious_window should go back and
1145 forth around the ring. If we use next_frame here,
1146 then Fnext_window and Fprevious_window take different
1147 paths through the set of acceptable windows.
1148 window_loop assumes that these `ring' requirement are
1149 met. */
1151 Lisp_Object tem1;
1153 tem1 = tem;
1154 tem = prev_frame (tem, all_frames);
1155 /* In the case where the minibuffer is active,
1156 and we include its frame as well as the selected one,
1157 next_frame may get stuck in that frame.
1158 If that happens, go back to the selected frame
1159 so we can complete the cycle. */
1160 if (EQ (tem, tem1))
1161 XSETFRAME (tem, selected_frame);
1163 #endif
1164 /* If this frame has a minibuffer, find that window first,
1165 because it is conceptually the last window in that frame. */
1166 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
1167 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
1168 else
1169 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1171 break;
1174 window = tem;
1175 /* If we're in a combination window, find its last child and
1176 recurse on that. Otherwise, we've found the window we want. */
1177 while (1)
1179 if (!NILP (XWINDOW (window)->hchild))
1180 window = XWINDOW (window)->hchild;
1181 else if (!NILP (XWINDOW (window)->vchild))
1182 window = XWINDOW (window)->vchild;
1183 else break;
1184 while (tem = XWINDOW (window)->next, !NILP (tem))
1185 window = tem;
1188 /* Which windows are acceptible?
1189 Exit the loop and accept this window if
1190 this isn't a minibuffer window,
1191 or we're accepting all minibuffer windows,
1192 or this is the active minibuffer and we are accepting that one, or
1193 we've come all the way around and we're back at the original window. */
1194 while (MINI_WINDOW_P (XWINDOW (window))
1195 && ! EQ (minibuf, Qt)
1196 && ! EQ (minibuf, window)
1197 && ! EQ (window, start_window));
1199 return window;
1202 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1203 "Select the ARG'th different window on this frame.\n\
1204 All windows on current frame are arranged in a cyclic order.\n\
1205 This command selects the window ARG steps away in that order.\n\
1206 A negative ARG moves in the opposite order. If the optional second\n\
1207 argument ALL_FRAMES is non-nil, cycle through all frames.")
1208 (n, all_frames)
1209 register Lisp_Object n, all_frames;
1211 register int i;
1212 register Lisp_Object w;
1214 CHECK_NUMBER (n, 0);
1215 w = selected_window;
1216 i = XINT (n);
1218 while (i > 0)
1220 w = Fnext_window (w, Qnil, all_frames);
1221 i--;
1223 while (i < 0)
1225 w = Fprevious_window (w, Qnil, all_frames);
1226 i++;
1228 Fselect_window (w);
1229 return Qnil;
1232 /* Look at all windows, performing an operation specified by TYPE
1233 with argument OBJ.
1234 If FRAMES is Qt, look at all frames;
1235 Qnil, look at just the selected frame;
1236 Qvisible, look at visible frames;
1237 a frame, just look at windows on that frame.
1238 If MINI is non-zero, perform the operation on minibuffer windows too.
1241 enum window_loop
1243 WINDOW_LOOP_UNUSED,
1244 GET_BUFFER_WINDOW, /* Arg is buffer */
1245 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1246 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1247 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1248 GET_LARGEST_WINDOW,
1249 UNSHOW_BUFFER /* Arg is buffer */
1252 static Lisp_Object
1253 window_loop (type, obj, mini, frames)
1254 enum window_loop type;
1255 register Lisp_Object obj, frames;
1256 int mini;
1258 register Lisp_Object w;
1259 register Lisp_Object best_window;
1260 register Lisp_Object next_window;
1261 register Lisp_Object last_window;
1262 FRAME_PTR frame;
1263 Lisp_Object frame_arg;
1264 frame_arg = Qt;
1266 #ifdef MULTI_FRAME
1267 /* If we're only looping through windows on a particular frame,
1268 frame points to that frame. If we're looping through windows
1269 on all frames, frame is 0. */
1270 if (FRAMEP (frames))
1271 frame = XFRAME (frames);
1272 else if (NILP (frames))
1273 frame = selected_frame;
1274 else
1275 frame = 0;
1276 if (frame)
1277 frame_arg = Qlambda;
1278 else if (XFASTINT (frames) == 0)
1279 frame_arg = frames;
1280 else if (EQ (frames, Qvisible))
1281 frame_arg = frames;
1282 #else
1283 frame = 0;
1284 #endif
1286 /* frame_arg is Qlambda to stick to one frame,
1287 Qvisible to consider all visible frames,
1288 or Qt otherwise. */
1290 /* Pick a window to start with. */
1291 if (WINDOWP (obj))
1292 w = obj;
1293 else if (frame)
1294 w = FRAME_SELECTED_WINDOW (frame);
1295 else
1296 w = FRAME_SELECTED_WINDOW (selected_frame);
1298 /* Figure out the last window we're going to mess with. Since
1299 Fnext_window, given the same options, is guaranteed to go in a
1300 ring, we can just use Fprevious_window to find the last one.
1302 We can't just wait until we hit the first window again, because
1303 it might be deleted. */
1305 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
1307 best_window = Qnil;
1308 for (;;)
1310 FRAME_PTR w_frame = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1312 /* Pick the next window now, since some operations will delete
1313 the current window. */
1314 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
1316 /* Note that we do not pay attention here to whether
1317 the frame is visible, since Fnext_window skips non-visible frames
1318 if that is desired, under the control of frame_arg. */
1319 if (! MINI_WINDOW_P (XWINDOW (w))
1320 || (mini && minibuf_level > 0))
1321 switch (type)
1323 case GET_BUFFER_WINDOW:
1324 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj))
1325 return w;
1326 break;
1328 case GET_LRU_WINDOW:
1329 /* t as arg means consider only full-width windows */
1330 if (!NILP (obj) && XFASTINT (XWINDOW (w)->width)
1331 != FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
1332 break;
1333 /* Ignore dedicated windows and minibuffers. */
1334 if (MINI_WINDOW_P (XWINDOW (w))
1335 || !NILP (XWINDOW (w)->dedicated))
1336 break;
1337 if (NILP (best_window)
1338 || (XFASTINT (XWINDOW (best_window)->use_time)
1339 > XFASTINT (XWINDOW (w)->use_time)))
1340 best_window = w;
1341 break;
1343 case DELETE_OTHER_WINDOWS:
1344 if (XWINDOW (w) != XWINDOW (obj))
1345 Fdelete_window (w);
1346 break;
1348 case DELETE_BUFFER_WINDOWS:
1349 if (EQ (XWINDOW (w)->buffer, obj))
1351 #ifdef MULTI_FRAME
1352 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1354 /* If this window is dedicated, and in a frame of its own,
1355 kill the frame. */
1356 if (EQ (w, FRAME_ROOT_WINDOW (f))
1357 && !NILP (XWINDOW (w)->dedicated)
1358 && other_visible_frames (f))
1360 /* Skip the other windows on this frame.
1361 There might be one, the minibuffer! */
1362 if (! EQ (w, last_window))
1363 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1365 /* As we go, check for the end of the loop.
1366 We mustn't start going around a second time. */
1367 if (EQ (next_window, last_window))
1369 last_window = w;
1370 break;
1372 next_window = Fnext_window (next_window,
1373 mini ? Qt : Qnil,
1374 frame_arg);
1376 /* Now we can safely delete the frame. */
1377 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
1379 else
1380 #endif
1381 /* If we're deleting the buffer displayed in the only window
1382 on the frame, find a new buffer to display there. */
1383 if (NILP (XWINDOW (w)->parent))
1385 Lisp_Object new_buffer;
1386 new_buffer = Fother_buffer (obj, Qnil);
1387 if (NILP (new_buffer))
1388 new_buffer
1389 = Fget_buffer_create (build_string ("*scratch*"));
1390 Fset_window_buffer (w, new_buffer);
1391 if (EQ (w, selected_window))
1392 Fset_buffer (XWINDOW (w)->buffer);
1394 else
1395 Fdelete_window (w);
1397 break;
1399 case GET_LARGEST_WINDOW:
1400 /* Ignore dedicated windows and minibuffers. */
1401 if (MINI_WINDOW_P (XWINDOW (w))
1402 || !NILP (XWINDOW (w)->dedicated))
1403 break;
1405 struct window *best_window_ptr = XWINDOW (best_window);
1406 struct window *w_ptr = XWINDOW (w);
1407 if (NILP (best_window)
1408 || (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width)
1409 > (XFASTINT (best_window_ptr->height)
1410 * XFASTINT (best_window_ptr->width))))
1411 best_window = w;
1413 break;
1415 case UNSHOW_BUFFER:
1416 if (EQ (XWINDOW (w)->buffer, obj))
1418 /* Find another buffer to show in this window. */
1419 Lisp_Object another_buffer;
1420 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1421 another_buffer = Fother_buffer (obj, Qnil);
1422 if (NILP (another_buffer))
1423 another_buffer
1424 = Fget_buffer_create (build_string ("*scratch*"));
1425 #ifdef MULTI_FRAME
1426 /* If this window is dedicated, and in a frame of its own,
1427 kill the frame. */
1428 if (EQ (w, FRAME_ROOT_WINDOW (f))
1429 && !NILP (XWINDOW (w)->dedicated)
1430 && other_visible_frames (f))
1432 /* Skip the other windows on this frame.
1433 There might be one, the minibuffer! */
1434 if (! EQ (w, last_window))
1435 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1437 /* As we go, check for the end of the loop.
1438 We mustn't start going around a second time. */
1439 if (EQ (next_window, last_window))
1441 last_window = w;
1442 break;
1444 next_window = Fnext_window (next_window,
1445 mini ? Qt : Qnil,
1446 frame_arg);
1448 /* Now we can safely delete the frame. */
1449 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
1451 else
1452 #endif
1454 /* Otherwise show a different buffer in the window. */
1455 XWINDOW (w)->dedicated = Qnil;
1456 Fset_window_buffer (w, another_buffer);
1457 if (EQ (w, selected_window))
1458 Fset_buffer (XWINDOW (w)->buffer);
1461 break;
1464 if (EQ (w, last_window))
1465 break;
1467 w = next_window;
1470 return best_window;
1473 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1474 "Return the window least recently selected or used for display.\n\
1475 If optional argument FRAME is `visible', search all visible frames.\n\
1476 If FRAME is 0, search all visible and iconified frames.\n\
1477 If FRAME is t, search all frames.\n\
1478 If FRAME is nil, search only the selected frame.\n\
1479 If FRAME is a frame, search only that frame.")
1480 (frame)
1481 Lisp_Object frame;
1483 register Lisp_Object w;
1484 /* First try for a window that is full-width */
1485 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
1486 if (!NILP (w) && !EQ (w, selected_window))
1487 return w;
1488 /* If none of them, try the rest */
1489 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
1492 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1493 "Return the largest window in area.\n\
1494 If optional argument FRAME is `visible', search all visible frames.\n\
1495 If FRAME is 0, search all visible and iconified frames.\n\
1496 If FRAME is t, search all frames.\n\
1497 If FRAME is nil, search only the selected frame.\n\
1498 If FRAME is a frame, search only that frame.")
1499 (frame)
1500 Lisp_Object frame;
1502 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
1503 frame);
1506 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1507 "Return a window currently displaying BUFFER, or nil if none.\n\
1508 If optional argument FRAME is `visible', search all visible frames.\n\
1509 If optional argument FRAME is 0, search all visible and iconified frames.\n\
1510 If FRAME is t, search all frames.\n\
1511 If FRAME is nil, search only the selected frame.\n\
1512 If FRAME is a frame, search only that frame.")
1513 (buffer, frame)
1514 Lisp_Object buffer, frame;
1516 buffer = Fget_buffer (buffer);
1517 if (BUFFERP (buffer))
1518 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
1519 else
1520 return Qnil;
1523 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1524 0, 1, "",
1525 "Make WINDOW (or the selected window) fill its frame.\n\
1526 Only the frame WINDOW is on is affected.\n\
1527 This function tries to reduce display jumps\n\
1528 by keeping the text previously visible in WINDOW\n\
1529 in the same place on the frame. Doing this depends on\n\
1530 the value of (window-start WINDOW), so if calling this function\n\
1531 in a program gives strange scrolling, make sure the window-start\n\
1532 value is reasonable when this function is called.")
1533 (window)
1534 Lisp_Object window;
1536 struct window *w;
1537 int startpos;
1538 int top;
1540 if (NILP (window))
1541 window = selected_window;
1542 else
1543 CHECK_LIVE_WINDOW (window, 0);
1545 w = XWINDOW (window);
1547 startpos = marker_position (w->start);
1548 top = XFASTINT (w->top) - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w)));
1550 if (MINI_WINDOW_P (w) && top > 0)
1551 error ("Can't expand minibuffer to full frame");
1553 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
1555 /* Try to minimize scrolling, by setting the window start to the point
1556 will cause the text at the old window start to be at the same place
1557 on the frame. But don't try to do this if the window start is
1558 outside the visible portion (as might happen when the display is
1559 not current, due to typeahead). */
1560 if (startpos >= BUF_BEGV (XBUFFER (w->buffer))
1561 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
1563 struct position pos;
1564 struct buffer *obuf = current_buffer;
1566 Fset_buffer (w->buffer);
1567 /* This computation used to temporarily move point, but that can
1568 have unwanted side effects due to text properties. */
1569 pos = *vmotion (startpos, -top, w);
1570 Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
1571 w->start_at_line_beg = ((pos.bufpos == BEGV
1572 || FETCH_CHAR (pos.bufpos - 1) == '\n') ? Qt
1573 : Qnil);
1574 /* We need to do this, so that the window-scroll-functions
1575 get called. */
1576 w->force_start = Qt;
1578 set_buffer_internal (obuf);
1580 return Qnil;
1583 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1584 1, 2, "bDelete windows on (buffer): ",
1585 "Delete all windows showing BUFFER.\n\
1586 Optional second argument FRAME controls which frames are affected.\n\
1587 If nil or omitted, delete all windows showing BUFFER in any frame.\n\
1588 If t, delete only windows showing BUFFER in the selected frame.\n\
1589 If `visible', delete all windows showing BUFFER in any visible frame.\n\
1590 If a frame, delete only windows showing BUFFER in that frame.")
1591 (buffer, frame)
1592 Lisp_Object buffer, frame;
1594 #ifdef MULTI_FRAME
1595 /* FRAME uses t and nil to mean the opposite of what window_loop
1596 expects. */
1597 if (! FRAMEP (frame))
1598 frame = NILP (frame) ? Qt : Qnil;
1599 #else
1600 frame = Qt;
1601 #endif
1603 if (!NILP (buffer))
1605 buffer = Fget_buffer (buffer);
1606 CHECK_BUFFER (buffer, 0);
1607 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
1609 return Qnil;
1612 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1613 Sreplace_buffer_in_windows,
1614 1, 1, "bReplace buffer in windows: ",
1615 "Replace BUFFER with some other buffer in all windows showing it.")
1616 (buffer)
1617 Lisp_Object buffer;
1619 if (!NILP (buffer))
1621 buffer = Fget_buffer (buffer);
1622 CHECK_BUFFER (buffer, 0);
1623 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1625 return Qnil;
1628 /* Set the height of WINDOW and all its inferiors. */
1630 /* The smallest acceptable dimensions for a window. Anything smaller
1631 might crash Emacs. */
1632 #define MIN_SAFE_WINDOW_WIDTH (2)
1633 #define MIN_SAFE_WINDOW_HEIGHT (2)
1635 /* Make sure that window_min_height and window_min_width are
1636 not too small; if they are, set them to safe minima. */
1638 static void
1639 check_min_window_sizes ()
1641 /* Smaller values might permit a crash. */
1642 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1643 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1644 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1645 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1648 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
1649 minimum allowable size. */
1650 void
1651 check_frame_size (frame, rows, cols)
1652 FRAME_PTR frame;
1653 int *rows, *cols;
1655 /* For height, we have to see:
1656 whether the frame has a minibuffer,
1657 whether it wants a mode line, and
1658 whether it has a menu bar. */
1659 int min_height =
1660 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
1661 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
1662 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
1663 if (FRAME_MENU_BAR_LINES (frame) > 0)
1664 min_height += FRAME_MENU_BAR_LINES (frame);
1666 if (*rows < min_height)
1667 *rows = min_height;
1668 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1669 *cols = MIN_SAFE_WINDOW_WIDTH;
1672 /* Normally the window is deleted if it gets too small.
1673 nodelete nonzero means do not do this.
1674 (The caller should check later and do so if appropriate) */
1676 set_window_height (window, height, nodelete)
1677 Lisp_Object window;
1678 int height;
1679 int nodelete;
1681 register struct window *w = XWINDOW (window);
1682 register struct window *c;
1683 int oheight = XFASTINT (w->height);
1684 int top, pos, lastbot, opos, lastobot;
1685 Lisp_Object child;
1687 check_min_window_sizes ();
1689 if (!nodelete
1690 && ! NILP (w->parent)
1691 && height < window_min_height)
1693 Fdelete_window (window);
1694 return;
1697 XSETFASTINT (w->last_modified, 0);
1698 windows_or_buffers_changed++;
1699 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
1701 XSETFASTINT (w->height, height);
1702 if (!NILP (w->hchild))
1704 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1706 XWINDOW (child)->top = w->top;
1707 set_window_height (child, height, nodelete);
1710 else if (!NILP (w->vchild))
1712 lastbot = top = XFASTINT (w->top);
1713 lastobot = 0;
1714 for (child = w->vchild; !NILP (child); child = c->next)
1716 c = XWINDOW (child);
1718 opos = lastobot + XFASTINT (c->height);
1720 XSETFASTINT (c->top, lastbot);
1722 pos = (((opos * height) << 1) + oheight) / (oheight << 1);
1724 /* Avoid confusion: inhibit deletion of child if becomes too small */
1725 set_window_height (child, pos + top - lastbot, 1);
1727 /* Now advance child to next window,
1728 and set lastbot if child was not just deleted. */
1729 lastbot = pos + top;
1730 lastobot = opos;
1732 /* Now delete any children that became too small. */
1733 if (!nodelete)
1734 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1736 set_window_height (child, XINT (XWINDOW (child)->height), 0);
1741 /* Recursively set width of WINDOW and its inferiors. */
1743 set_window_width (window, width, nodelete)
1744 Lisp_Object window;
1745 int width;
1746 int nodelete;
1748 register struct window *w = XWINDOW (window);
1749 register struct window *c;
1750 int owidth = XFASTINT (w->width);
1751 int left, pos, lastright, opos, lastoright;
1752 Lisp_Object child;
1754 if (!nodelete && width < window_min_width && !NILP (w->parent))
1756 Fdelete_window (window);
1757 return;
1760 XSETFASTINT (w->last_modified, 0);
1761 windows_or_buffers_changed++;
1762 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
1764 XSETFASTINT (w->width, width);
1765 if (!NILP (w->vchild))
1767 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1769 XWINDOW (child)->left = w->left;
1770 set_window_width (child, width, nodelete);
1773 else if (!NILP (w->hchild))
1775 lastright = left = XFASTINT (w->left);
1776 lastoright = 0;
1777 for (child = w->hchild; !NILP (child); child = c->next)
1779 c = XWINDOW (child);
1781 opos = lastoright + XFASTINT (c->width);
1783 XSETFASTINT (c->left, lastright);
1785 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
1787 /* Inhibit deletion for becoming too small */
1788 set_window_width (child, pos + left - lastright, 1);
1790 /* Now advance child to next window,
1791 and set lastright if child was not just deleted. */
1792 lastright = pos + left, lastoright = opos;
1794 /* Delete children that became too small */
1795 if (!nodelete)
1796 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1798 set_window_width (child, XINT (XWINDOW (child)->width), 0);
1803 int window_select_count;
1805 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1806 "Make WINDOW display BUFFER as its contents.\n\
1807 BUFFER can be a buffer or buffer name.")
1808 (window, buffer)
1809 register Lisp_Object window, buffer;
1811 register Lisp_Object tem;
1812 register struct window *w = decode_window (window);
1814 buffer = Fget_buffer (buffer);
1815 CHECK_BUFFER (buffer, 1);
1817 if (NILP (XBUFFER (buffer)->name))
1818 error ("Attempt to display deleted buffer");
1820 tem = w->buffer;
1821 if (NILP (tem))
1822 error ("Window is deleted");
1823 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
1824 is first being set up. */
1826 if (!NILP (w->dedicated) && !EQ (tem, buffer))
1827 error ("Window is dedicated to `%s'",
1828 XSTRING (XBUFFER (tem)->name)->data);
1830 unshow_buffer (w);
1833 w->buffer = buffer;
1834 XSETFASTINT (w->window_end_pos, 0);
1835 w->window_end_valid = Qnil;
1836 XSETFASTINT(w->hscroll, 0);
1837 Fset_marker (w->pointm,
1838 make_number (BUF_PT (XBUFFER (buffer))),
1839 buffer);
1840 set_marker_restricted (w->start,
1841 make_number (XBUFFER (buffer)->last_window_start),
1842 buffer);
1843 w->start_at_line_beg = Qnil;
1844 w->force_start = Qnil;
1845 XSETFASTINT (w->last_modified, 0);
1846 windows_or_buffers_changed++;
1847 if (EQ (window, selected_window))
1848 Fset_buffer (buffer);
1850 return Qnil;
1853 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1854 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1855 The main editor command loop selects the buffer of the selected window\n\
1856 before each command.")
1857 (window)
1858 register Lisp_Object window;
1860 register struct window *w;
1861 register struct window *ow = XWINDOW (selected_window);
1863 CHECK_LIVE_WINDOW (window, 0);
1865 w = XWINDOW (window);
1867 if (NILP (w->buffer))
1868 error ("Trying to select deleted window or non-leaf window");
1870 XSETFASTINT (w->use_time, ++window_select_count);
1871 if (EQ (window, selected_window))
1872 return window;
1874 Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
1875 ow->buffer);
1877 selected_window = window;
1878 #ifdef MULTI_FRAME
1879 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
1881 XFRAME (WINDOW_FRAME (w))->selected_window = window;
1882 /* Use this rather than Fhandle_switch_frame
1883 so that FRAME_FOCUS_FRAME is moved appropriately as we
1884 move around in the state where a minibuffer in a separate
1885 frame is active. */
1886 Fselect_frame (WINDOW_FRAME (w), Qnil);
1888 else
1889 selected_frame->selected_window = window;
1890 #endif
1892 record_buffer (w->buffer);
1893 Fset_buffer (w->buffer);
1895 /* Go to the point recorded in the window.
1896 This is important when the buffer is in more
1897 than one window. It also matters when
1898 redisplay_window has altered point after scrolling,
1899 because it makes the change only in the window. */
1901 register int new_point = marker_position (w->pointm);
1902 if (new_point < BEGV)
1903 SET_PT (BEGV);
1904 else if (new_point > ZV)
1905 SET_PT (ZV);
1906 else
1907 SET_PT (new_point);
1910 windows_or_buffers_changed++;
1911 return window;
1914 /* Deiconify the frame containing the window WINDOW, then return WINDOW. */
1916 static Lisp_Object
1917 display_buffer_1 (window)
1918 Lisp_Object window;
1920 #ifdef MULTI_FRAME
1921 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1922 FRAME_SAMPLE_VISIBILITY (f);
1923 if (FRAME_ICONIFIED_P (f))
1924 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
1925 #endif
1926 return window;
1929 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
1930 "bDisplay buffer: \nP",
1931 "Make BUFFER appear in some window but don't select it.\n\
1932 BUFFER can be a buffer or a buffer name.\n\
1933 If BUFFER is shown already in some window, just use that one,\n\
1934 unless the window is the selected window and the optional second\n\
1935 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
1936 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
1937 Returns the window displaying BUFFER.")
1938 (buffer, not_this_window)
1939 register Lisp_Object buffer, not_this_window;
1941 register Lisp_Object window, tem;
1943 buffer = Fget_buffer (buffer);
1944 CHECK_BUFFER (buffer, 0);
1946 if (!NILP (Vdisplay_buffer_function))
1947 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
1949 if (NILP (not_this_window)
1950 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
1951 return display_buffer_1 (selected_window);
1953 /* See if the user has specified this buffer should appear
1954 in the selected window. */
1955 if (NILP (not_this_window))
1957 tem = Fmember (XBUFFER (buffer)->name, Vsame_window_buffer_names);
1958 if (!NILP (tem))
1960 Fswitch_to_buffer (buffer, Qnil);
1961 return display_buffer_1 (selected_window);
1964 tem = Fassoc (XBUFFER (buffer)->name, Vsame_window_buffer_names);
1965 if (!NILP (tem))
1967 Fswitch_to_buffer (buffer, Qnil);
1968 return display_buffer_1 (selected_window);
1971 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCONS (tem)->cdr)
1973 Lisp_Object car = XCONS (tem)->car;
1974 if (STRINGP (car)
1975 && fast_string_match (car, XBUFFER (buffer)->name) >= 0)
1977 Fswitch_to_buffer (buffer, Qnil);
1978 return display_buffer_1 (selected_window);
1980 else if (CONSP (car)
1981 && STRINGP (XCONS (car)->car)
1982 && fast_string_match (XCONS (car)->car,
1983 XBUFFER (buffer)->name) >= 0)
1985 Fswitch_to_buffer (buffer, Qnil);
1986 return display_buffer_1 (selected_window);
1991 #ifdef MULTI_FRAME
1992 /* If pop_up_frames,
1993 look for a window showing BUFFER on any visible or iconified frame.
1994 Otherwise search only the current frame. */
1995 if (pop_up_frames || last_nonminibuf_frame == 0)
1996 XSETFASTINT (tem, 0);
1997 else
1998 #endif
1999 XSETFRAME (tem, last_nonminibuf_frame);
2000 window = Fget_buffer_window (buffer, tem);
2001 if (!NILP (window)
2002 && (NILP (not_this_window) || !EQ (window, selected_window)))
2004 return display_buffer_1 (window);
2007 /* Certain buffer names get special handling. */
2008 if (! NILP (Vspecial_display_function))
2010 tem = Fmember (XBUFFER (buffer)->name, Vspecial_display_buffer_names);
2011 if (!NILP (tem))
2012 return call1 (Vspecial_display_function, buffer);
2014 tem = Fassoc (XBUFFER (buffer)->name, Vspecial_display_buffer_names);
2015 if (!NILP (tem))
2016 return call2 (Vspecial_display_function, buffer, XCONS (tem)->cdr);
2018 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCONS (tem)->cdr)
2020 Lisp_Object car = XCONS (tem)->car;
2021 if (STRINGP (car)
2022 && fast_string_match (car, XBUFFER (buffer)->name) >= 0)
2023 return call1 (Vspecial_display_function, buffer);
2024 else if (CONSP (car)
2025 && STRINGP (XCONS (car)->car)
2026 && fast_string_match (XCONS (car)->car,
2027 XBUFFER (buffer)->name) >= 0)
2028 return call2 (Vspecial_display_function,
2029 buffer,
2030 XCONS (car)->cdr);
2034 #ifdef MULTI_FRAME
2035 /* If there are no frames open that have more than a minibuffer,
2036 we need to create a new frame. */
2037 if (pop_up_frames || last_nonminibuf_frame == 0)
2039 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2040 Fset_window_buffer (window, buffer);
2041 return display_buffer_1 (window);
2043 #endif /* MULTI_FRAME */
2045 if (pop_up_windows
2046 #ifdef MULTI_FRAME
2047 || FRAME_MINIBUF_ONLY_P (selected_frame)
2048 /* If the current frame is a special display frame,
2049 don't try to reuse its windows. */
2050 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->dedicated)
2051 #endif
2054 Lisp_Object frames;
2056 frames = Qnil;
2057 #ifdef MULTI_FRAME
2058 if (FRAME_MINIBUF_ONLY_P (selected_frame))
2059 XSETFRAME (frames, last_nonminibuf_frame);
2060 #endif
2061 /* Don't try to create a window if would get an error */
2062 if (split_height_threshold < window_min_height << 1)
2063 split_height_threshold = window_min_height << 1;
2065 /* Note that both Fget_largest_window and Fget_lru_window
2066 ignore minibuffers and dedicated windows.
2067 This means they can return nil. */
2069 #ifdef MULTI_FRAME
2070 /* If the frame we would try to split cannot be split,
2071 try other frames. */
2072 if (FRAME_NO_SPLIT_P (NILP (frames) ? selected_frame
2073 : last_nonminibuf_frame))
2075 /* Try visible frames first. */
2076 window = Fget_largest_window (Qvisible);
2077 /* If that didn't work, try iconified frames. */
2078 if (NILP (window))
2079 window = Fget_largest_window (make_number (0));
2080 if (NILP (window))
2081 window = Fget_largest_window (Qt);
2083 else
2084 #endif
2085 window = Fget_largest_window (frames);
2087 /* If we got a tall enough full-width window that can be split,
2088 split it. */
2089 if (!NILP (window)
2090 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2091 && window_height (window) >= split_height_threshold
2092 && (XFASTINT (XWINDOW (window)->width)
2093 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
2094 window = Fsplit_window (window, Qnil, Qnil);
2095 else
2097 Lisp_Object upper, lower, other;
2099 window = Fget_lru_window (frames);
2100 /* If the LRU window is selected, and big enough,
2101 and can be split, split it. */
2102 if (!NILP (window)
2103 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2104 && (EQ (window, selected_window)
2105 || EQ (XWINDOW (window)->parent, Qnil))
2106 && window_height (window) >= window_min_height << 1)
2107 window = Fsplit_window (window, Qnil, Qnil);
2108 #ifdef MULTI_FRAME
2109 /* If Fget_lru_window returned nil, try other approaches. */
2110 /* Try visible frames first. */
2111 if (NILP (window))
2112 window = Fget_largest_window (Qvisible);
2113 /* If that didn't work, try iconified frames. */
2114 if (NILP (window))
2115 window = Fget_largest_window (make_number (0));
2116 /* Try invisible frames. */
2117 if (NILP (window))
2118 window = Fget_largest_window (Qt);
2119 /* As a last resort, make a new frame. */
2120 if (NILP (window))
2121 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2122 #else
2123 /* As a last resort, use a non minibuffer window. */
2124 if (NILP (window))
2125 window = Fframe_first_window (Fselected_frame ());
2126 #endif
2127 /* If window appears above or below another,
2128 even out their heights. */
2129 other = upper = lower = Qnil;
2130 if (!NILP (XWINDOW (window)->prev))
2131 other = upper = XWINDOW (window)->prev, lower = window;
2132 if (!NILP (XWINDOW (window)->next))
2133 other = lower = XWINDOW (window)->next, upper = window;
2134 if (!NILP (other)
2135 /* Check that OTHER and WINDOW are vertically arrayed. */
2136 && XWINDOW (other)->top != XWINDOW (window)->top
2137 && XWINDOW (other)->height > XWINDOW (window)->height)
2139 int total = XWINDOW (other)->height + XWINDOW (window)->height;
2140 Lisp_Object old_selected_window;
2141 old_selected_window = selected_window;
2143 selected_window = upper;
2144 change_window_height (total / 2 - XWINDOW (upper)->height, 0);
2145 selected_window = old_selected_window;
2149 else
2150 window = Fget_lru_window (Qnil);
2152 Fset_window_buffer (window, buffer);
2153 return display_buffer_1 (window);
2156 void
2157 temp_output_buffer_show (buf)
2158 register Lisp_Object buf;
2160 register struct buffer *old = current_buffer;
2161 register Lisp_Object window;
2162 register struct window *w;
2164 Fset_buffer (buf);
2165 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
2166 BEGV = BEG;
2167 ZV = Z;
2168 SET_PT (BEG);
2169 XBUFFER (buf)->clip_changed = 1;
2170 set_buffer_internal (old);
2172 if (!EQ (Vtemp_buffer_show_function, Qnil))
2173 call1 (Vtemp_buffer_show_function, buf);
2174 else
2176 window = Fdisplay_buffer (buf, Qnil);
2178 #ifdef MULTI_FRAME
2179 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
2180 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
2181 #endif /* MULTI_FRAME */
2182 Vminibuf_scroll_window = window;
2183 w = XWINDOW (window);
2184 XSETFASTINT (w->hscroll, 0);
2185 set_marker_restricted (w->start, make_number (1), buf);
2186 set_marker_restricted (w->pointm, make_number (1), buf);
2188 /* Run temp-buffer-show-hook, with the chosen window selected. */
2189 if (!NILP (Vrun_hooks))
2191 Lisp_Object tem;
2192 tem = Fboundp (Qtemp_buffer_show_hook);
2193 if (!NILP (tem))
2195 tem = Fsymbol_value (Qtemp_buffer_show_hook);
2196 if (!NILP (tem))
2198 int count = specpdl_ptr - specpdl;
2200 /* Select the window that was chosen, for running the hook. */
2201 record_unwind_protect (Fset_window_configuration,
2202 Fcurrent_window_configuration (Qnil));
2204 Fselect_window (window);
2205 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
2206 unbind_to (count, Qnil);
2213 static
2214 make_dummy_parent (window)
2215 Lisp_Object window;
2217 Lisp_Object new;
2218 register struct window *o, *p;
2219 register struct Lisp_Vector *vec;
2220 int i;
2222 o = XWINDOW (window);
2223 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
2224 for (i = 0; i < VECSIZE (struct window); ++i)
2225 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
2226 vec->size = VECSIZE (struct window);
2227 p = (struct window *)vec;
2228 XSETWINDOW (new, p);
2230 XSETFASTINT (p->sequence_number, ++sequence_number);
2232 /* Put new into window structure in place of window */
2233 replace_window (window, new);
2235 o->next = Qnil;
2236 o->prev = Qnil;
2237 o->vchild = Qnil;
2238 o->hchild = Qnil;
2239 o->parent = new;
2241 p->start = Qnil;
2242 p->pointm = Qnil;
2243 p->buffer = Qnil;
2246 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
2247 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
2248 WINDOW defaults to selected one and SIZE to half its size.\n\
2249 If optional third arg HORFLAG is non-nil, split side by side\n\
2250 and put SIZE columns in the first of the pair.")
2251 (window, size, horflag)
2252 Lisp_Object window, size, horflag;
2254 register Lisp_Object new;
2255 register struct window *o, *p;
2256 FRAME_PTR fo;
2257 register int size_int;
2258 int internal_width;
2259 int separator_width = 1;
2261 if (NILP (window))
2262 window = selected_window;
2263 else
2264 CHECK_LIVE_WINDOW (window, 0);
2266 o = XWINDOW (window);
2267 fo = XFRAME (WINDOW_FRAME (o));
2268 if (FRAME_HAS_VERTICAL_SCROLL_BARS (fo))
2269 separator_width = FRAME_SCROLL_BAR_COLS (fo);
2270 internal_width = window_internal_width (o);
2272 if (NILP (size))
2274 if (!NILP (horflag))
2275 /* Calculate the size of the left-hand window, by dividing
2276 the usable space in columns by two. */
2277 size_int = (internal_width - separator_width) >> 1;
2278 else
2279 size_int = XFASTINT (o->height) >> 1;
2281 else
2283 CHECK_NUMBER (size, 1);
2284 size_int = XINT (size);
2287 if (MINI_WINDOW_P (o))
2288 error ("Attempt to split minibuffer window");
2289 else if (FRAME_NO_SPLIT_P (fo))
2290 error ("Attempt to split unsplittable frame");
2292 check_min_window_sizes ();
2294 if (NILP (horflag))
2296 if (size_int < window_min_height)
2297 error ("Window height %d too small (after splitting)", size_int);
2298 if (size_int + window_min_height > XFASTINT (o->height))
2299 error ("Window height %d too small (after splitting)",
2300 XFASTINT (o->height) - size_int);
2301 if (NILP (o->parent)
2302 || NILP (XWINDOW (o->parent)->vchild))
2304 make_dummy_parent (window);
2305 new = o->parent;
2306 XWINDOW (new)->vchild = window;
2309 else
2311 if (size_int < window_min_width)
2312 error ("Window width %d too small (after splitting)", size_int);
2313 if (internal_width - size_int - separator_width < window_min_width)
2314 error ("Window width %d too small (after splitting)",
2315 internal_width - size_int - separator_width);
2316 if (NILP (o->parent)
2317 || NILP (XWINDOW (o->parent)->hchild))
2319 make_dummy_parent (window);
2320 new = o->parent;
2321 XWINDOW (new)->hchild = window;
2325 /* Now we know that window's parent is a vertical combination
2326 if we are dividing vertically, or a horizontal combination
2327 if we are making side-by-side windows */
2329 windows_or_buffers_changed++;
2330 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
2331 new = make_window ();
2332 p = XWINDOW (new);
2334 p->frame = o->frame;
2335 p->next = o->next;
2336 if (!NILP (p->next))
2337 XWINDOW (p->next)->prev = new;
2338 p->prev = window;
2339 o->next = new;
2340 p->parent = o->parent;
2341 p->buffer = Qt;
2343 Fset_window_buffer (new, o->buffer);
2345 /* Apportion the available frame space among the two new windows */
2347 if (!NILP (horflag))
2349 p->height = o->height;
2350 p->top = o->top;
2351 size_int += separator_width;
2352 XSETFASTINT (p->width, internal_width - size_int);
2353 XSETFASTINT (o->width, size_int);
2354 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
2356 else
2358 p->left = o->left;
2359 p->width = o->width;
2360 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
2361 XSETFASTINT (o->height, size_int);
2362 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
2365 return new;
2368 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
2369 "Make current window ARG lines bigger.\n\
2370 From program, optional second arg non-nil means grow sideways ARG columns.")
2371 (n, side)
2372 register Lisp_Object n, side;
2374 CHECK_NUMBER (n, 0);
2375 change_window_height (XINT (n), !NILP (side));
2376 return Qnil;
2379 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
2380 "Make current window ARG lines smaller.\n\
2381 From program, optional second arg non-nil means shrink sideways ARG columns.")
2382 (n, side)
2383 register Lisp_Object n, side;
2385 CHECK_NUMBER (n, 0);
2386 change_window_height (-XINT (n), !NILP (side));
2387 return Qnil;
2391 window_height (window)
2392 Lisp_Object window;
2394 register struct window *p = XWINDOW (window);
2395 return XFASTINT (p->height);
2399 window_width (window)
2400 Lisp_Object window;
2402 register struct window *p = XWINDOW (window);
2403 return XFASTINT (p->width);
2406 #define MINSIZE(w) \
2407 (widthflag \
2408 ? window_min_width \
2409 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
2411 #define CURBEG(w) \
2412 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
2414 #define CURSIZE(w) \
2415 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
2417 /* Unlike set_window_height, this function
2418 also changes the heights of the siblings so as to
2419 keep everything consistent. */
2421 change_window_height (delta, widthflag)
2422 register int delta;
2423 int widthflag;
2425 register Lisp_Object parent;
2426 Lisp_Object window;
2427 register struct window *p;
2428 int *sizep;
2429 int (*sizefun) () = widthflag ? window_width : window_height;
2430 register int (*setsizefun) () = (widthflag
2431 ? set_window_width
2432 : set_window_height);
2434 check_min_window_sizes ();
2436 window = selected_window;
2437 while (1)
2439 p = XWINDOW (window);
2440 parent = p->parent;
2441 if (NILP (parent))
2443 if (widthflag)
2444 error ("No other window to side of this one");
2445 break;
2447 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
2448 : !NILP (XWINDOW (parent)->vchild))
2449 break;
2450 window = parent;
2453 sizep = &CURSIZE (window);
2456 register int maxdelta;
2458 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
2459 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
2460 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
2461 /* This is a frame with only one window, a minibuffer-only
2462 or a minibufferless frame. */
2463 : (delta = 0));
2465 if (delta > maxdelta)
2466 /* This case traps trying to make the minibuffer
2467 the full frame, or make the only window aside from the
2468 minibuffer the full frame. */
2469 delta = maxdelta;
2472 if (*sizep + delta < MINSIZE (window))
2474 Fdelete_window (window);
2475 return;
2478 if (delta == 0)
2479 return;
2481 if (!NILP (p->next)
2482 && (*sizefun) (p->next) - delta >= MINSIZE (p->next))
2484 (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
2485 (*setsizefun) (window, *sizep + delta, 0);
2486 CURBEG (p->next) += delta;
2487 /* This does not change size of p->next,
2488 but it propagates the new top edge to its children */
2489 (*setsizefun) (p->next, (*sizefun) (p->next), 0);
2491 else if (!NILP (p->prev)
2492 && (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
2494 (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
2495 CURBEG (window) -= delta;
2496 (*setsizefun) (window, *sizep + delta, 0);
2498 else
2500 register int delta1;
2501 register int opht = (*sizefun) (parent);
2503 /* If trying to grow this window to or beyond size of the parent,
2504 make delta1 so big that, on shrinking back down,
2505 all the siblings end up with less than one line and are deleted. */
2506 if (opht <= *sizep + delta)
2507 delta1 = opht * opht * 2;
2508 /* Otherwise, make delta1 just right so that if we add delta1
2509 lines to this window and to the parent, and then shrink
2510 the parent back to its original size, the new proportional
2511 size of this window will increase by delta. */
2512 else
2513 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
2515 /* Add delta1 lines or columns to this window, and to the parent,
2516 keeping things consistent while not affecting siblings. */
2517 CURSIZE (parent) = opht + delta1;
2518 (*setsizefun) (window, *sizep + delta1, 0);
2520 /* Squeeze out delta1 lines or columns from our parent,
2521 shriking this window and siblings proportionately.
2522 This brings parent back to correct size.
2523 Delta1 was calculated so this makes this window the desired size,
2524 taking it all out of the siblings. */
2525 (*setsizefun) (parent, opht, 0);
2528 XSETFASTINT (p->last_modified, 0);
2530 #undef MINSIZE
2531 #undef CURBEG
2532 #undef CURSIZE
2535 /* Return number of lines of text (not counting mode line) in W. */
2538 window_internal_height (w)
2539 struct window *w;
2541 int ht = XFASTINT (w->height);
2543 if (MINI_WINDOW_P (w))
2544 return ht;
2546 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2547 || !NILP (w->next) || !NILP (w->prev)
2548 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
2549 return ht - 1;
2551 return ht;
2555 /* Return the number of columns in W.
2556 Don't count columns occupied by scroll bars or the vertical bar
2557 separating W from the sibling to its right. */
2559 window_internal_width (w)
2560 struct window *w;
2562 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2563 int left = XINT (w->left);
2564 int width = XINT (w->width);
2566 /* If this window is flush against the right edge of the frame, its
2567 internal width is its full width. */
2568 if (left + width >= FRAME_WIDTH (f))
2569 return width;
2571 /* If we are not flush right, then our rightmost columns are
2572 occupied by some sort of separator. */
2574 /* Scroll bars occupy a few columns. */
2575 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2576 return width - FRAME_SCROLL_BAR_COLS (f);
2578 /* The column of `|' characters separating side-by-side windows
2579 occupies one column only. */
2580 return width - 1;
2584 /* Scroll contents of window WINDOW up N lines. */
2586 void
2587 window_scroll (window, n, noerror)
2588 Lisp_Object window;
2589 int n;
2590 int noerror;
2592 register struct window *w = XWINDOW (window);
2593 register int opoint = PT;
2594 register int pos;
2595 register int ht = window_internal_height (w);
2596 register Lisp_Object tem;
2597 int lose;
2598 Lisp_Object bolp, nmoved;
2600 /* Always set force_start so that redisplay_window will run
2601 thw window-scroll-functions. */
2602 w->force_start = Qt;
2604 XSETFASTINT (tem, PT);
2605 tem = Fpos_visible_in_window_p (tem, window);
2607 if (NILP (tem))
2609 Fvertical_motion (make_number (- (ht / 2)), window);
2610 XSETFASTINT (tem, PT);
2611 Fset_marker (w->start, tem, w->buffer);
2614 SET_PT (marker_position (w->start));
2615 lose = n < 0 && PT == BEGV;
2616 Fvertical_motion (make_number (n), window);
2617 pos = PT;
2618 bolp = Fbolp ();
2619 SET_PT (opoint);
2621 if (lose)
2623 if (noerror)
2624 return;
2625 else
2626 Fsignal (Qbeginning_of_buffer, Qnil);
2629 if (pos < ZV)
2631 set_marker_restricted (w->start, make_number (pos), w->buffer);
2632 w->start_at_line_beg = bolp;
2633 w->update_mode_line = Qt;
2634 XSETFASTINT (w->last_modified, 0);
2635 if (pos > opoint)
2636 SET_PT (pos);
2637 if (n < 0)
2639 SET_PT (pos);
2640 tem = Fvertical_motion (make_number (ht), window);
2641 if (PT > opoint || XFASTINT (tem) < ht)
2642 SET_PT (opoint);
2643 else
2644 Fvertical_motion (make_number (-1), window);
2647 else
2649 if (noerror)
2650 return;
2651 else
2652 Fsignal (Qend_of_buffer, Qnil);
2656 /* This is the guts of Fscroll_up and Fscroll_down. */
2658 static void
2659 scroll_command (n, direction)
2660 register Lisp_Object n;
2661 int direction;
2663 register int defalt;
2664 int count = specpdl_ptr - specpdl;
2666 /* If selected window's buffer isn't current, make it current for the moment.
2667 But don't screw up if window_scroll gets an error. */
2668 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
2670 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2671 Fset_buffer (XWINDOW (selected_window)->buffer);
2674 defalt = (window_internal_height (XWINDOW (selected_window))
2675 - next_screen_context_lines);
2676 defalt = direction * (defalt < 1 ? 1 : defalt);
2678 if (NILP (n))
2679 window_scroll (selected_window, defalt, 0);
2680 else if (EQ (n, Qminus))
2681 window_scroll (selected_window, - defalt, 0);
2682 else
2684 n = Fprefix_numeric_value (n);
2685 window_scroll (selected_window, XINT (n) * direction, 0);
2688 unbind_to (count, Qnil);
2691 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2692 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2693 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2694 Negative ARG means scroll downward.\n\
2695 When calling from a program, supply a number as argument or nil.")
2697 Lisp_Object n;
2699 scroll_command (n, 1);
2700 return Qnil;
2703 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2704 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2705 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2706 Negative ARG means scroll upward.\n\
2707 When calling from a program, supply a number as argument or nil.")
2709 Lisp_Object n;
2711 scroll_command (n, -1);
2712 return Qnil;
2715 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
2716 "Return the other window for \"other window scroll\" commands.\n\
2717 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2718 specifies the window.\n\
2719 If `other-window-scroll-buffer' is non-nil, a window\n\
2720 showing that buffer is used.")
2723 Lisp_Object window;
2725 if (MINI_WINDOW_P (XWINDOW (selected_window))
2726 && !NILP (Vminibuf_scroll_window))
2727 window = Vminibuf_scroll_window;
2728 /* If buffer is specified, scroll that buffer. */
2729 else if (!NILP (Vother_window_scroll_buffer))
2731 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
2732 if (NILP (window))
2733 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2735 else
2737 /* Nothing specified; look for a neighboring window on the same
2738 frame. */
2739 window = Fnext_window (selected_window, Qnil, Qnil);
2741 if (EQ (window, selected_window))
2742 /* That didn't get us anywhere; look for a window on another
2743 visible frame. */
2745 window = Fnext_window (window, Qnil, Qt);
2746 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
2747 && ! EQ (window, selected_window));
2750 CHECK_LIVE_WINDOW (window, 0);
2752 if (EQ (window, selected_window))
2753 error ("There is no other window");
2755 return window;
2758 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
2759 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
2760 The next window is the one below the current one; or the one at the top\n\
2761 if the current one is at the bottom. Negative ARG means scroll downward.\n\
2762 When calling from a program, supply a number as argument or nil.\n\
2764 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2765 specifies the window to scroll.\n\
2766 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2767 showing that buffer, popping the buffer up if necessary.")
2769 register Lisp_Object n;
2771 register Lisp_Object window;
2772 register int defalt;
2773 register struct window *w;
2774 register int count = specpdl_ptr - specpdl;
2776 window = Fother_window_for_scrolling ();
2778 w = XWINDOW (window);
2779 defalt = window_internal_height (w) - next_screen_context_lines;
2780 if (defalt < 1) defalt = 1;
2782 /* Don't screw up if window_scroll gets an error. */
2783 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2785 Fset_buffer (w->buffer);
2786 SET_PT (marker_position (w->pointm));
2788 if (NILP (n))
2789 window_scroll (window, defalt, 1);
2790 else if (EQ (n, Qminus))
2791 window_scroll (window, -defalt, 1);
2792 else
2794 if (CONSP (n))
2795 n = Fcar (n);
2796 CHECK_NUMBER (n, 0);
2797 window_scroll (window, XINT (n), 1);
2800 Fset_marker (w->pointm, make_number (PT), Qnil);
2801 unbind_to (count, Qnil);
2803 return Qnil;
2806 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
2807 "Scroll selected window display ARG columns left.\n\
2808 Default for ARG is window width minus 2.")
2809 (arg)
2810 register Lisp_Object arg;
2813 if (NILP (arg))
2814 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
2815 else
2816 arg = Fprefix_numeric_value (arg);
2818 return
2819 Fset_window_hscroll (selected_window,
2820 make_number (XINT (XWINDOW (selected_window)->hscroll)
2821 + XINT (arg)));
2824 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
2825 "Scroll selected window display ARG columns right.\n\
2826 Default for ARG is window width minus 2.")
2827 (arg)
2828 register Lisp_Object arg;
2830 if (NILP (arg))
2831 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
2832 else
2833 arg = Fprefix_numeric_value (arg);
2835 return
2836 Fset_window_hscroll (selected_window,
2837 make_number (XINT (XWINDOW (selected_window)->hscroll)
2838 - XINT (arg)));
2841 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
2842 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
2843 The desired position of point is always relative to the current window.\n\
2844 Just C-u as prefix means put point in the center of the window.\n\
2845 No arg (i.e., it is nil) erases the entire frame and then\n\
2846 redraws with point in the center of the current window.")
2848 register Lisp_Object n;
2850 register struct window *w = XWINDOW (selected_window);
2851 register int ht = window_internal_height (w);
2852 struct position pos;
2854 if (NILP (n))
2856 extern int frame_garbaged;
2858 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
2859 XSETFASTINT (n, ht / 2);
2861 else if (CONSP (n)) /* Just C-u. */
2863 XSETFASTINT (n, ht / 2);
2865 else
2867 n = Fprefix_numeric_value (n);
2868 CHECK_NUMBER (n, 0);
2871 if (XINT (n) < 0)
2872 XSETINT (n, XINT (n) + ht);
2874 pos = *vmotion (point, - XINT (n), w);
2876 Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
2877 w->start_at_line_beg = ((pos.bufpos == BEGV
2878 || FETCH_CHAR (pos.bufpos - 1) == '\n')
2879 ? Qt : Qnil);
2880 w->force_start = Qt;
2882 return Qnil;
2885 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
2886 1, 1, "P",
2887 "Position point relative to window.\n\
2888 With no argument, position point at center of window.\n\
2889 An argument specifies frame line; zero means top of window,\n\
2890 negative means relative to bottom of window.")
2891 (arg)
2892 register Lisp_Object arg;
2894 register struct window *w = XWINDOW (selected_window);
2895 register int height = window_internal_height (w);
2896 register int start;
2897 Lisp_Object window;
2899 if (NILP (arg))
2900 XSETFASTINT (arg, height / 2);
2901 else
2903 arg = Fprefix_numeric_value (arg);
2904 if (XINT (arg) < 0)
2905 XSETINT (arg, XINT (arg) + height);
2908 start = marker_position (w->start);
2909 XSETWINDOW (window, w);
2910 if (start < BEGV || start > ZV)
2912 Fvertical_motion (make_number (- (height / 2)), window);
2913 Fset_marker (w->start, make_number (PT), w->buffer);
2914 w->start_at_line_beg = Fbolp ();
2915 w->force_start = Qt;
2917 else
2918 SET_PT (start);
2920 return Fvertical_motion (arg, window);
2923 struct save_window_data
2925 int size_from_Lisp_Vector_struct;
2926 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2927 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
2928 Lisp_Object selected_frame;
2929 Lisp_Object current_window;
2930 Lisp_Object current_buffer;
2931 Lisp_Object minibuf_scroll_window;
2932 Lisp_Object root_window;
2933 Lisp_Object focus_frame;
2934 /* Record the values of window-min-width and window-min-height
2935 so that window sizes remain consistent with them. */
2936 Lisp_Object min_width, min_height;
2937 /* A vector, interpreted as a struct saved_window */
2938 Lisp_Object saved_windows;
2941 /* This is saved as a Lisp_Vector */
2942 struct saved_window
2944 /* these first two must agree with struct Lisp_Vector in lisp.h */
2945 int size_from_Lisp_Vector_struct;
2946 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2948 Lisp_Object window;
2949 Lisp_Object buffer, start, pointm, mark;
2950 Lisp_Object left, top, width, height, hscroll;
2951 Lisp_Object parent, prev;
2952 Lisp_Object start_at_line_beg;
2953 Lisp_Object display_table;
2955 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2957 #define SAVED_WINDOW_N(swv,n) \
2958 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2960 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
2961 "T if OBJECT is a window-configration object.")
2962 (obj)
2963 Lisp_Object obj;
2965 if (WINDOW_CONFIGURATIONP (obj))
2966 return Qt;
2967 return Qnil;
2971 DEFUN ("set-window-configuration", Fset_window_configuration,
2972 Sset_window_configuration, 1, 1, 0,
2973 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2974 CONFIGURATION must be a value previously returned\n\
2975 by `current-window-configuration' (which see).")
2976 (configuration)
2977 Lisp_Object configuration;
2979 register struct save_window_data *data;
2980 struct Lisp_Vector *saved_windows;
2981 Lisp_Object new_current_buffer;
2982 Lisp_Object frame;
2983 FRAME_PTR f;
2985 while (!WINDOW_CONFIGURATIONP (configuration))
2987 configuration = wrong_type_argument (intern ("window-configuration-p"),
2988 configuration);
2991 data = (struct save_window_data *) XVECTOR (configuration);
2992 saved_windows = XVECTOR (data->saved_windows);
2994 new_current_buffer = data->current_buffer;
2995 if (NILP (XBUFFER (new_current_buffer)->name))
2996 new_current_buffer = Qnil;
2998 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
2999 f = XFRAME (frame);
3001 /* If f is a dead frame, don't bother rebuilding its window tree.
3002 However, there is other stuff we should still try to do below. */
3003 if (FRAME_LIVE_P (f))
3005 register struct window *w;
3006 register struct saved_window *p;
3007 int k;
3009 /* If the frame has been resized since this window configuration was
3010 made, we change the frame to the size specified in the
3011 configuration, restore the configuration, and then resize it
3012 back. We keep track of the prevailing height in these variables. */
3013 int previous_frame_height = FRAME_HEIGHT (f);
3014 int previous_frame_width = FRAME_WIDTH (f);
3015 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
3017 if (XFASTINT (data->frame_height) != previous_frame_height
3018 || XFASTINT (data->frame_width) != previous_frame_width)
3019 change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
3020 #ifdef HAVE_WINDOW_SYSTEM
3021 if (XFASTINT (data->frame_menu_bar_lines)
3022 != previous_frame_menu_bar_lines)
3023 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
3024 #endif
3026 windows_or_buffers_changed++;
3027 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3029 /* Temporarily avoid any problems with windows that are smaller
3030 than they are supposed to be. */
3031 window_min_height = 1;
3032 window_min_width = 1;
3034 /* Kludge Alert!
3035 Mark all windows now on frame as "deleted".
3036 Restoring the new configuration "undeletes" any that are in it.
3038 Save their current buffers in their height fields, since we may
3039 need it later, if a buffer saved in the configuration is now
3040 dead. */
3041 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
3043 for (k = 0; k < saved_windows->size; k++)
3045 p = SAVED_WINDOW_N (saved_windows, k);
3046 w = XWINDOW (p->window);
3047 w->next = Qnil;
3049 if (!NILP (p->parent))
3050 w->parent = SAVED_WINDOW_N (saved_windows,
3051 XFASTINT (p->parent))->window;
3052 else
3053 w->parent = Qnil;
3055 if (!NILP (p->prev))
3057 w->prev = SAVED_WINDOW_N (saved_windows,
3058 XFASTINT (p->prev))->window;
3059 XWINDOW (w->prev)->next = p->window;
3061 else
3063 w->prev = Qnil;
3064 if (!NILP (w->parent))
3066 if (EQ (p->width, XWINDOW (w->parent)->width))
3068 XWINDOW (w->parent)->vchild = p->window;
3069 XWINDOW (w->parent)->hchild = Qnil;
3071 else
3073 XWINDOW (w->parent)->hchild = p->window;
3074 XWINDOW (w->parent)->vchild = Qnil;
3079 /* If we squirreled away the buffer in the window's height,
3080 restore it now. */
3081 if (BUFFERP (w->height))
3082 w->buffer = w->height;
3083 w->left = p->left;
3084 w->top = p->top;
3085 w->width = p->width;
3086 w->height = p->height;
3087 w->hscroll = p->hscroll;
3088 w->display_table = p->display_table;
3089 XSETFASTINT (w->last_modified, 0);
3091 /* Reinstall the saved buffer and pointers into it. */
3092 if (NILP (p->buffer))
3093 w->buffer = p->buffer;
3094 else
3096 if (!NILP (XBUFFER (p->buffer)->name))
3097 /* If saved buffer is alive, install it. */
3099 w->buffer = p->buffer;
3100 w->start_at_line_beg = p->start_at_line_beg;
3101 set_marker_restricted (w->start,
3102 Fmarker_position (p->start),
3103 w->buffer);
3104 set_marker_restricted (w->pointm,
3105 Fmarker_position (p->pointm),
3106 w->buffer);
3107 Fset_marker (XBUFFER (w->buffer)->mark,
3108 Fmarker_position (p->mark), w->buffer);
3110 /* As documented in Fcurrent_window_configuration, don't
3111 save the location of point in the buffer which was current
3112 when the window configuration was recorded. */
3113 if (!EQ (p->buffer, new_current_buffer)
3114 && XBUFFER (p->buffer) == current_buffer)
3115 Fgoto_char (w->pointm);
3117 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
3118 /* Else unless window has a live buffer, get one. */
3120 w->buffer = Fcdr (Fcar (Vbuffer_alist));
3121 /* This will set the markers to beginning of visible
3122 range. */
3123 set_marker_restricted (w->start, make_number (0), w->buffer);
3124 set_marker_restricted (w->pointm, make_number (0),w->buffer);
3125 w->start_at_line_beg = Qt;
3127 else
3128 /* Keeping window's old buffer; make sure the markers
3129 are real. */
3131 /* Set window markers at start of visible range. */
3132 if (XMARKER (w->start)->buffer == 0)
3133 set_marker_restricted (w->start, make_number (0),
3134 w->buffer);
3135 if (XMARKER (w->pointm)->buffer == 0)
3136 set_marker_restricted (w->pointm,
3137 (make_number
3138 (BUF_PT (XBUFFER (w->buffer)))),
3139 w->buffer);
3140 w->start_at_line_beg = Qt;
3145 FRAME_ROOT_WINDOW (f) = data->root_window;
3146 Fselect_window (data->current_window);
3148 #ifdef MULTI_FRAME
3149 if (NILP (data->focus_frame)
3150 || (FRAMEP (data->focus_frame)
3151 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
3152 Fredirect_frame_focus (frame, data->focus_frame);
3153 #endif
3155 #if 0 /* I don't understand why this is needed, and it causes problems
3156 when the frame's old selected window has been deleted. */
3157 #ifdef MULTI_FRAME
3158 if (f != selected_frame && ! FRAME_TERMCAP_P (f))
3159 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
3160 Qnil, 0);
3161 #endif
3162 #endif
3164 /* Set the screen height to the value it had before this function. */
3165 if (previous_frame_height != FRAME_HEIGHT (f)
3166 || previous_frame_width != FRAME_WIDTH (f))
3167 change_frame_size (f, previous_frame_height, previous_frame_width,
3168 0, 0);
3169 #ifdef HAVE_WINDOW_SYSTEM
3170 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
3171 x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
3172 #endif
3175 /* Restore the minimum heights recorded in the configuration. */
3176 window_min_height = XINT (data->min_height);
3177 window_min_width = XINT (data->min_width);
3179 #ifdef MULTI_FRAME
3180 /* Fselect_window will have made f the selected frame, so we
3181 reselect the proper frame here. Fhandle_switch_frame will change the
3182 selected window too, but that doesn't make the call to
3183 Fselect_window above totally superfluous; it still sets f's
3184 selected window. */
3185 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
3186 do_switch_frame (data->selected_frame, Qnil, 0);
3187 #endif
3189 if (!NILP (new_current_buffer))
3190 Fset_buffer (new_current_buffer);
3192 Vminibuf_scroll_window = data->minibuf_scroll_window;
3193 return (Qnil);
3196 /* Mark all windows now on frame as deleted
3197 by setting their buffers to nil. */
3199 void
3200 delete_all_subwindows (w)
3201 register struct window *w;
3203 if (!NILP (w->next))
3204 delete_all_subwindows (XWINDOW (w->next));
3205 if (!NILP (w->vchild))
3206 delete_all_subwindows (XWINDOW (w->vchild));
3207 if (!NILP (w->hchild))
3208 delete_all_subwindows (XWINDOW (w->hchild));
3210 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
3212 /* We set all three of these fields to nil, to make sure that we can
3213 distinguish this dead window from any live window. Live leaf
3214 windows will have buffer set, and combination windows will have
3215 vchild or hchild set. */
3216 w->buffer = Qnil;
3217 w->vchild = Qnil;
3218 w->hchild = Qnil;
3221 static int
3222 count_windows (window)
3223 register struct window *window;
3225 register int count = 1;
3226 if (!NILP (window->next))
3227 count += count_windows (XWINDOW (window->next));
3228 if (!NILP (window->vchild))
3229 count += count_windows (XWINDOW (window->vchild));
3230 if (!NILP (window->hchild))
3231 count += count_windows (XWINDOW (window->hchild));
3232 return count;
3235 static int
3236 save_window_save (window, vector, i)
3237 Lisp_Object window;
3238 struct Lisp_Vector *vector;
3239 int i;
3241 register struct saved_window *p;
3242 register struct window *w;
3243 register Lisp_Object tem;
3245 for (;!NILP (window); window = w->next)
3247 p = SAVED_WINDOW_N (vector, i);
3248 w = XWINDOW (window);
3250 XSETFASTINT (w->temslot, i++);
3251 p->window = window;
3252 p->buffer = w->buffer;
3253 p->left = w->left;
3254 p->top = w->top;
3255 p->width = w->width;
3256 p->height = w->height;
3257 p->hscroll = w->hscroll;
3258 p->display_table = w->display_table;
3259 if (!NILP (w->buffer))
3261 /* Save w's value of point in the window configuration.
3262 If w is the selected window, then get the value of point
3263 from the buffer; pointm is garbage in the selected window. */
3264 if (EQ (window, selected_window))
3266 p->pointm = Fmake_marker ();
3267 Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
3268 w->buffer);
3270 else
3271 p->pointm = Fcopy_marker (w->pointm, Qnil);
3273 p->start = Fcopy_marker (w->start, Qnil);
3274 p->start_at_line_beg = w->start_at_line_beg;
3276 tem = XBUFFER (w->buffer)->mark;
3277 p->mark = Fcopy_marker (tem, Qnil);
3279 else
3281 p->pointm = Qnil;
3282 p->start = Qnil;
3283 p->mark = Qnil;
3284 p->start_at_line_beg = Qnil;
3287 if (NILP (w->parent))
3288 p->parent = Qnil;
3289 else
3290 p->parent = XWINDOW (w->parent)->temslot;
3292 if (NILP (w->prev))
3293 p->prev = Qnil;
3294 else
3295 p->prev = XWINDOW (w->prev)->temslot;
3297 if (!NILP (w->vchild))
3298 i = save_window_save (w->vchild, vector, i);
3299 if (!NILP (w->hchild))
3300 i = save_window_save (w->hchild, vector, i);
3303 return i;
3306 DEFUN ("current-window-configuration",
3307 Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
3308 "Return an object representing the current window configuration of FRAME.\n\
3309 If FRAME is nil or omitted, use the selected frame.\n\
3310 This describes the number of windows, their sizes and current buffers,\n\
3311 and for each displayed buffer, where display starts, and the positions of\n\
3312 point and mark. An exception is made for point in the current buffer:\n\
3313 its value is -not- saved.\n\
3314 This also records the currently selected frame, and FRAME's focus\n\
3315 redirection (see `redirect-frame-focus').")
3316 (frame)
3317 Lisp_Object frame;
3319 register Lisp_Object tem;
3320 register int n_windows;
3321 register struct save_window_data *data;
3322 register struct Lisp_Vector *vec;
3323 register int i;
3324 FRAME_PTR f;
3326 if (NILP (frame))
3327 f = selected_frame;
3328 else
3330 CHECK_LIVE_FRAME (frame, 0);
3331 f = XFRAME (frame);
3334 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
3335 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
3336 for (i = 0; i < VECSIZE (struct save_window_data); i++)
3337 vec->contents[i] = Qnil;
3338 vec->size = VECSIZE (struct save_window_data);
3339 data = (struct save_window_data *)vec;
3341 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
3342 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
3343 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
3344 #ifdef MULTI_FRAME
3345 XSETFRAME (data->selected_frame, selected_frame);
3346 #endif
3347 data->current_window = FRAME_SELECTED_WINDOW (f);
3348 XSETBUFFER (data->current_buffer, current_buffer);
3349 data->minibuf_scroll_window = Vminibuf_scroll_window;
3350 data->root_window = FRAME_ROOT_WINDOW (f);
3351 data->focus_frame = FRAME_FOCUS_FRAME (f);
3352 XSETINT (data->min_height, window_min_height);
3353 XSETINT (data->min_width, window_min_width);
3354 tem = Fmake_vector (make_number (n_windows), Qnil);
3355 data->saved_windows = tem;
3356 for (i = 0; i < n_windows; i++)
3357 XVECTOR (tem)->contents[i]
3358 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
3359 save_window_save (FRAME_ROOT_WINDOW (f),
3360 XVECTOR (tem), 0);
3361 XSETWINDOW_CONFIGURATION (tem, data);
3362 return (tem);
3365 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
3366 0, UNEVALLED, 0,
3367 "Execute body, preserving window sizes and contents.\n\
3368 Restore which buffer appears in which window, where display starts,\n\
3369 and the value of point and mark for each window.\n\
3370 Also restore which buffer is current.\n\
3371 But do not preserve point in the current buffer.\n\
3372 Does not restore the value of point in current buffer.")
3373 (args)
3374 Lisp_Object args;
3376 register Lisp_Object val;
3377 register int count = specpdl_ptr - specpdl;
3379 record_unwind_protect (Fset_window_configuration,
3380 Fcurrent_window_configuration (Qnil));
3381 val = Fprogn (args);
3382 return unbind_to (count, val);
3385 init_window_once ()
3387 #ifdef MULTI_FRAME
3388 selected_frame = make_terminal_frame ();
3389 XSETFRAME (Vterminal_frame, selected_frame);
3390 minibuf_window = selected_frame->minibuffer_window;
3391 selected_window = selected_frame->selected_window;
3392 last_nonminibuf_frame = selected_frame;
3393 #else /* not MULTI_FRAME */
3394 extern Lisp_Object get_minibuffer ();
3396 selected_frame = last_nonminibuf_frame = &the_only_frame;
3398 minibuf_window = make_window ();
3399 FRAME_ROOT_WINDOW (selected_frame) = make_window ();
3401 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->next = minibuf_window;
3402 XWINDOW (minibuf_window)->prev = FRAME_ROOT_WINDOW (selected_frame);
3403 XWINDOW (minibuf_window)->mini_p = Qt;
3405 /* These values 9 and 10 are arbitrary,
3406 just so that there is "something there."
3407 Correct values are put in in init_xdisp */
3409 XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->width, 10);
3410 XSETFASTINT (XWINDOW (minibuf_window)->width, 10);
3412 XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->height, 9);
3413 XSETFASTINT (XWINDOW (minibuf_window)->top, 9);
3414 XSETFASTINT (XWINDOW (minibuf_window)->height, 1);
3416 /* Prevent error in Fset_window_buffer. */
3417 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->buffer = Qt;
3418 XWINDOW (minibuf_window)->buffer = Qt;
3420 /* Now set them up for real. */
3421 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame),
3422 Fcurrent_buffer ());
3423 Fset_window_buffer (minibuf_window, get_minibuffer (0));
3425 selected_window = FRAME_ROOT_WINDOW (selected_frame);
3426 /* Make sure this window seems more recently used than
3427 a newly-created, never-selected window. Increment
3428 window_select_count so the first selection ever will get
3429 something newer than this. */
3430 XSETFASTINT (XWINDOW (selected_window)->use_time, ++window_select_count);
3431 #endif /* not MULTI_FRAME */
3434 syms_of_window ()
3436 Qwindowp = intern ("windowp");
3437 staticpro (&Qwindowp);
3439 Qwindow_live_p = intern ("window-live-p");
3440 staticpro (&Qwindow_live_p);
3442 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
3443 staticpro (&Qtemp_buffer_show_hook);
3445 #ifndef MULTI_FRAME
3446 /* Make sure all windows get marked */
3447 staticpro (&minibuf_window);
3448 #endif
3450 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
3451 "Non-nil means call as function to display a help buffer.\n\
3452 The function is called with one argument, the buffer to be displayed.\n\
3453 Used by `with-output-to-temp-buffer'.\n\
3454 If this function is used, then it must do the entire job of showing\n\
3455 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
3456 Vtemp_buffer_show_function = Qnil;
3458 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
3459 "If non-nil, function to call to handle `display-buffer'.\n\
3460 It will receive two args, the buffer and a flag which if non-nil means\n\
3461 that the currently selected window is not acceptable.\n\
3462 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
3463 work using this function.");
3464 Vdisplay_buffer_function = Qnil;
3466 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
3467 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
3468 Vminibuf_scroll_window = Qnil;
3470 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
3471 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
3472 Vother_window_scroll_buffer = Qnil;
3474 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
3475 "*Non-nil means `display-buffer' should make a separate frame.");
3476 pop_up_frames = 0;
3478 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
3479 "Function to call to handle automatic new frame creation.\n\
3480 It is called with no arguments and should return a newly created frame.\n\
3482 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
3483 where `pop-up-frame-alist' would hold the default frame parameters.");
3484 Vpop_up_frame_function = Qnil;
3486 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
3487 "*List of buffer names that should have their own special frames.\n\
3488 Displaying a buffer whose name is in this list makes a special frame for it\n\
3489 using `special-display-function'.\n\
3491 An element of the list can be a cons cell instead of just a string.\n\
3492 Then the car should be a buffer name, and the cdr specifies frame\n\
3493 parameters for creating the frame for that buffer.\n\
3494 More precisely, the cdr is passed as the second argument to\n\
3495 the function found in `special-display-function', when making that frame.\n\
3496 See also `special-display-regexps'.");
3497 Vspecial_display_buffer_names = Qnil;
3499 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
3500 "*List of regexps saying which buffers should have their own special frames.\n\
3501 If a buffer name matches one of these regexps, it gets its own frame.\n\
3502 Displaying a buffer whose name is in this list makes a special frame for it\n\
3503 using `special-display-function'.\n\
3505 An element of the list can be a cons cell instead of just a string.\n\
3506 Then the car should be the regexp, and the cdr specifies frame\n\
3507 parameters for creating the frame for buffers that match.\n\
3508 More precisely, the cdr is passed as the second argument to\n\
3509 the function found in `special-display-function', when making that frame.\n\
3510 See also `special-display-buffer-names'.");
3511 Vspecial_display_regexps = Qnil;
3513 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
3514 "Function to call to make a new frame for a special buffer.\n\
3515 It is called with two arguments, the buffer and optional buffer specific\n\
3516 data, and should return a window displaying that buffer.\n\
3517 The default value makes a separate frame for the buffer,\n\
3518 using `special-display-frame-alist' to specify the frame parameters.\n\
3520 A buffer is special if its is listed in `special-display-buffer-names'\n\
3521 or matches a regexp in `special-display-regexps'.");
3522 Vspecial_display_function = Qnil;
3524 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
3525 "*List of buffer names that should appear in the selected window.\n\
3526 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
3527 switches to it in the selected window, rather than making it appear\n\
3528 in some other window.\n\
3530 An element of the list can be a cons cell instead of just a string.\n\
3531 Then the car must be a string, which specifies the buffer name.\n\
3532 This is for compatibility with `special-display-buffer-names';\n\
3533 the cdr of the cons cell is ignored.\n\
3535 See also `same-window-regexps'.");
3536 Vsame_window_buffer_names = Qnil;
3538 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
3539 "*List of regexps saying which buffers should appear in the selected window.\n\
3540 If a buffer name matches one of these regexps, then displaying it\n\
3541 using `display-buffer' or `pop-to-buffer' switches to it\n\
3542 in the selected window, rather than making it appear in some other window.\n\
3544 An element of the list can be a cons cell instead of just a string.\n\
3545 Then the car must be a string, which specifies the buffer name.\n\
3546 This is for compatibility with `special-display-buffer-names';\n\
3547 the cdr of the cons cell is ignored.\n\
3549 See also `same-window-buffer-names'.");
3550 Vsame_window_regexps = Qnil;
3552 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
3553 "*Non-nil means display-buffer should make new windows.");
3554 pop_up_windows = 1;
3556 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
3557 "*Number of lines of continuity when scrolling by screenfuls.");
3558 next_screen_context_lines = 2;
3560 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
3561 "*display-buffer would prefer to split the largest window if this large.\n\
3562 If there is only one window, it is split regardless of this value.");
3563 split_height_threshold = 500;
3565 DEFVAR_INT ("window-min-height", &window_min_height,
3566 "*Delete any window less than this tall (including its mode line).");
3567 window_min_height = 4;
3569 DEFVAR_INT ("window-min-width", &window_min_width,
3570 "*Delete any window less than this wide.");
3571 window_min_width = 10;
3573 defsubr (&Sselected_window);
3574 defsubr (&Sminibuffer_window);
3575 defsubr (&Swindow_minibuffer_p);
3576 defsubr (&Swindowp);
3577 defsubr (&Swindow_live_p);
3578 defsubr (&Spos_visible_in_window_p);
3579 defsubr (&Swindow_buffer);
3580 defsubr (&Swindow_height);
3581 defsubr (&Swindow_width);
3582 defsubr (&Swindow_hscroll);
3583 defsubr (&Sset_window_hscroll);
3584 defsubr (&Swindow_redisplay_end_trigger);
3585 defsubr (&Sset_window_redisplay_end_trigger);
3586 defsubr (&Swindow_edges);
3587 defsubr (&Scoordinates_in_window_p);
3588 defsubr (&Swindow_at);
3589 defsubr (&Swindow_point);
3590 defsubr (&Swindow_start);
3591 defsubr (&Swindow_end);
3592 defsubr (&Sset_window_point);
3593 defsubr (&Sset_window_start);
3594 defsubr (&Swindow_dedicated_p);
3595 defsubr (&Sset_window_dedicated_p);
3596 defsubr (&Swindow_display_table);
3597 defsubr (&Sset_window_display_table);
3598 defsubr (&Snext_window);
3599 defsubr (&Sprevious_window);
3600 defsubr (&Sother_window);
3601 defsubr (&Sget_lru_window);
3602 defsubr (&Sget_largest_window);
3603 defsubr (&Sget_buffer_window);
3604 defsubr (&Sdelete_other_windows);
3605 defsubr (&Sdelete_windows_on);
3606 defsubr (&Sreplace_buffer_in_windows);
3607 defsubr (&Sdelete_window);
3608 defsubr (&Sset_window_buffer);
3609 defsubr (&Sselect_window);
3610 defsubr (&Sdisplay_buffer);
3611 defsubr (&Ssplit_window);
3612 defsubr (&Senlarge_window);
3613 defsubr (&Sshrink_window);
3614 defsubr (&Sscroll_up);
3615 defsubr (&Sscroll_down);
3616 defsubr (&Sscroll_left);
3617 defsubr (&Sscroll_right);
3618 defsubr (&Sother_window_for_scrolling);
3619 defsubr (&Sscroll_other_window);
3620 defsubr (&Srecenter);
3621 defsubr (&Smove_to_window_line);
3622 defsubr (&Swindow_configuration_p);
3623 defsubr (&Sset_window_configuration);
3624 defsubr (&Scurrent_window_configuration);
3625 defsubr (&Ssave_window_excursion);
3628 keys_of_window ()
3630 initial_define_key (control_x_map, '1', "delete-other-windows");
3631 initial_define_key (control_x_map, '2', "split-window");
3632 initial_define_key (control_x_map, '0', "delete-window");
3633 initial_define_key (control_x_map, 'o', "other-window");
3634 initial_define_key (control_x_map, '^', "enlarge-window");
3635 initial_define_key (control_x_map, '<', "scroll-left");
3636 initial_define_key (control_x_map, '>', "scroll-right");
3638 initial_define_key (global_map, Ctl ('V'), "scroll-up");
3639 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
3640 initial_define_key (meta_map, 'v', "scroll-down");
3642 initial_define_key (global_map, Ctl('L'), "recenter");
3643 initial_define_key (meta_map, 'r', "move-to-window-line");