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)
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. */
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
;
70 /* Nonzero implies Fdisplay_buffer should create windows. */
73 /* Nonzero implies make new frames for Fdisplay_buffer. */
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.")
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.")
125 return (WINDOWP (obj
) && ! NILP (XWINDOW (obj
)->buffer
) ? Qt
: Qnil
);
132 register struct window
*p
;
133 register struct Lisp_Vector
*vec
;
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);
153 p
->display_table
= Qnil
;
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.")
175 XSETFRAME (frame
, selected_frame
);
177 CHECK_LIVE_FRAME (frame
, 0);
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.")
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.")
198 Lisp_Object pos
, window
;
200 register struct window
*w
;
204 register struct buffer
*buf
;
205 struct position posval
;
212 CHECK_NUMBER_COERCE_MARKER (pos
, 0);
216 w
= decode_window (window
);
217 top
= marker_position (w
->start
);
218 hscroll
= XINT (w
->hscroll
);
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
))
237 if (posint
> BUF_ZV (buf
))
240 /* w->start can be out of range. If it is, do something reasonable. */
241 if (top
< BUF_BEGV (buf
) || top
> BUF_ZV (buf
))
244 /* If that info is not correct, calculate afresh */
245 posval
= *compute_motion (top
, 0, (hscroll
? 1 - hscroll
: 0), 0,
247 window_internal_width (w
) - 1,
250 return posval
.vpos
< height
? Qt
: Qnil
;
254 static struct window
*
255 decode_window (window
)
256 register Lisp_Object 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.")
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).")
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))).")
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.")
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.")
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 */
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.")
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.")
336 register Lisp_Object window
, value
;
338 register struct window
*w
;
340 w
= decode_window (window
);
341 w
->redisplay_end_trigger
= 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\
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
)),
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
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,
373 coordinates_in_window (w
, x
, y
)
374 register struct window
*w
;
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
)
386 /* Is the character is the mode line? */
387 if (*y
== top
+ window_height
- 1
388 && ! MINI_WINDOW_P (w
))
391 /* Is the character in the right border? */
392 if (*x
== left
+ width
- 1
393 && left
+ width
!= FRAME_WIDTH (XFRAME (w
->frame
)))
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\
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
;
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. */
428 case 1: /* In text part of window. */
431 case 2: /* In mode line of window. */
434 case 3: /* On right border of window. */
435 return Qvertical_line
;
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. */
448 window_from_coordinates (frame
, x
, y
, part
)
453 register Lisp_Object tem
, first
;
455 tem
= first
= FRAME_SELECTED_WINDOW (frame
);
459 int found
= coordinates_in_window (XWINDOW (tem
), &x
, &y
);
467 tem
= Fnext_window (tem
, Qt
, Qlambda
);
469 while (! EQ (tem
, first
));
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\
480 Lisp_Object x
, y
, frame
;
486 XSETFRAME (frame
, selected_frame
);
488 CHECK_LIVE_FRAME (frame
, 2);
493 return window_from_coordinates (XFRAME (frame
),
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.")
511 register struct window
*w
= decode_window (window
);
513 if (w
== XWINDOW (selected_window
)
514 && current_buffer
== XBUFFER (w
->buffer
))
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'.")
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\
535 (goto-char (window-start window))\n\
536 (vertical-motion (1- (window-height window)) window)\n\
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.")
548 struct window
*w
= decode_window (window
);
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
))
564 BUF_Z (XBUFFER (buf
)) - XFASTINT (w
->window_end_pos
));
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.")
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
))
580 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
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
;
600 w
->update_mode_line
= Qt
;
601 XSETFASTINT (w
->last_modified
, 0);
602 if (!EQ (window
, selected_window
))
603 windows_or_buffers_changed
++;
607 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
609 "Return WINDOW's dedicated object, usually t or nil.\n\
610 See also `set-window-dedicated-p'.")
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\
625 Lisp_Object window
, arg
;
627 register struct window
*w
= decode_window (window
);
637 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
639 "Return the display-table that WINDOW is using.")
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
)
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
);
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.")
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
;
681 /* Record info on buffer window w is displaying
682 when it is about to cease to display that buffer. */
685 register struct window
*w
;
690 if (XBUFFER (buf
) != XMARKER (w
->pointm
)->buffer
)
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. */
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. */
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
;
735 p
->height
= o
->height
;
737 p
->next
= tem
= o
->next
;
739 XWINDOW (tem
)->prev
= replacement
;
741 p
->prev
= tem
= o
->prev
;
743 XWINDOW (tem
)->next
= replacement
;
745 p
->parent
= tem
= o
->parent
;
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.")
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. */
772 window
= selected_window
;
774 CHECK_WINDOW (window
, 0);
775 p
= XWINDOW (window
);
777 /* It's okay to delete an already-deleted window. */
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
))
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
);
821 FRAME_SELECTED_WINDOW (XFRAME (frame
)) = alternative
;
826 /* tem is null for dummy parent windows
827 (which have inferiors but not any contents themselves) */
831 unchain_marker (p
->pointm
);
832 unchain_marker (p
->start
);
837 XWINDOW (tem
)->prev
= p
->prev
;
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. */
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
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. */
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
;
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
;
936 window
= selected_window
;
938 CHECK_LIVE_WINDOW (window
, 0);
940 start_window
= window
;
942 /* minibuf == nil may or may not include minibuffers.
943 Decide if it does. */
945 minibuf
= (minibuf_level
? minibuf_window
: Qlambda
);
946 else if (! EQ (minibuf
, Qt
))
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. */
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
959 (XWINDOW (window
)))))
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
))
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. */
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
))
989 /* We've reached the end of this frame.
990 Which other frames are acceptable? */
991 tem
= WINDOW_FRAME (XWINDOW (window
));
993 if (! NILP (all_frames
))
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. */
1005 XSETFRAME (tem
, selected_frame
);
1008 tem
= FRAME_ROOT_WINDOW (XFRAME (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. */
1019 if (!NILP (XWINDOW (window
)->hchild
))
1020 window
= XWINDOW (window
)->hchild
;
1021 else if (!NILP (XWINDOW (window
)->vchild
))
1022 window
= XWINDOW (window
)->vchild
;
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
));
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
;
1082 window
= selected_window
;
1084 CHECK_LIVE_WINDOW (window
, 0);
1086 start_window
= window
;
1088 /* minibuf == nil may or may not include minibuffers.
1089 Decide if it does. */
1091 minibuf
= (minibuf_level
? minibuf_window
: Qlambda
);
1092 else if (! EQ (minibuf
, Qt
))
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. */
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
1106 (XWINDOW (window
)))))
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
))
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. */
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
))
1136 /* We have found the top window on the frame.
1137 Which frames are acceptable? */
1138 tem
= WINDOW_FRAME (XWINDOW (window
));
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
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. */
1161 XSETFRAME (tem
, selected_frame
);
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
));
1169 tem
= FRAME_ROOT_WINDOW (XFRAME (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. */
1179 if (!NILP (XWINDOW (window
)->hchild
))
1180 window
= XWINDOW (window
)->hchild
;
1181 else if (!NILP (XWINDOW (window
)->vchild
))
1182 window
= XWINDOW (window
)->vchild
;
1184 while (tem
= XWINDOW (window
)->next
, !NILP (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
));
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.")
1209 register Lisp_Object n
, all_frames
;
1212 register Lisp_Object w
;
1214 CHECK_NUMBER (n
, 0);
1215 w
= selected_window
;
1220 w
= Fnext_window (w
, Qnil
, all_frames
);
1225 w
= Fprevious_window (w
, Qnil
, all_frames
);
1232 /* Look at all windows, performing an operation specified by TYPE
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.
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 */
1249 UNSHOW_BUFFER
/* Arg is buffer */
1253 window_loop (type
, obj
, mini
, frames
)
1254 enum window_loop type
;
1255 register Lisp_Object obj
, frames
;
1258 register Lisp_Object w
;
1259 register Lisp_Object best_window
;
1260 register Lisp_Object next_window
;
1261 register Lisp_Object last_window
;
1263 Lisp_Object frame_arg
;
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
;
1277 frame_arg
= Qlambda
;
1278 else if (XFASTINT (frames
) == 0)
1280 else if (EQ (frames
, Qvisible
))
1286 /* frame_arg is Qlambda to stick to one frame,
1287 Qvisible to consider all visible frames,
1290 /* Pick a window to start with. */
1294 w
= FRAME_SELECTED_WINDOW (frame
);
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
);
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))
1323 case GET_BUFFER_WINDOW
:
1324 if (XBUFFER (XWINDOW (w
)->buffer
) == XBUFFER (obj
))
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
)))))
1333 /* Ignore dedicated windows and minibuffers. */
1334 if (MINI_WINDOW_P (XWINDOW (w
))
1335 || !NILP (XWINDOW (w
)->dedicated
))
1337 if (NILP (best_window
)
1338 || (XFASTINT (XWINDOW (best_window
)->use_time
)
1339 > XFASTINT (XWINDOW (w
)->use_time
)))
1343 case DELETE_OTHER_WINDOWS
:
1344 if (XWINDOW (w
) != XWINDOW (obj
))
1348 case DELETE_BUFFER_WINDOWS
:
1349 if (EQ (XWINDOW (w
)->buffer
, obj
))
1352 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (w
)));
1354 /* If this window is dedicated, and in a frame of its own,
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
))
1372 next_window
= Fnext_window (next_window
,
1376 /* Now we can safely delete the frame. */
1377 Fdelete_frame (WINDOW_FRAME (XWINDOW (w
)), Qnil
);
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
))
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
);
1399 case GET_LARGEST_WINDOW
:
1400 /* Ignore dedicated windows and minibuffers. */
1401 if (MINI_WINDOW_P (XWINDOW (w
))
1402 || !NILP (XWINDOW (w
)->dedicated
))
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
))))
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
))
1424 = Fget_buffer_create (build_string ("*scratch*"));
1426 /* If this window is dedicated, and in a frame of its own,
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
))
1444 next_window
= Fnext_window (next_window
,
1448 /* Now we can safely delete the frame. */
1449 Fdelete_frame (WINDOW_FRAME (XWINDOW (w
)), Qnil
);
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
);
1464 if (EQ (w
, last_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.")
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
))
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.")
1502 return window_loop (GET_LARGEST_WINDOW
, Qnil
, 0,
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.")
1514 Lisp_Object buffer
, frame
;
1516 buffer
= Fget_buffer (buffer
);
1517 if (BUFFERP (buffer
))
1518 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
1523 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
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.")
1541 window
= selected_window
;
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
1574 /* We need to do this, so that the window-scroll-functions
1576 w
->force_start
= Qt
;
1578 set_buffer_internal (obuf
);
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.")
1592 Lisp_Object buffer
, frame
;
1595 /* FRAME uses t and nil to mean the opposite of what window_loop
1597 if (! FRAMEP (frame
))
1598 frame
= NILP (frame
) ? Qt
: Qnil
;
1605 buffer
= Fget_buffer (buffer
);
1606 CHECK_BUFFER (buffer
, 0);
1607 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, frame
);
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.")
1621 buffer
= Fget_buffer (buffer
);
1622 CHECK_BUFFER (buffer
, 0);
1623 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
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. */
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. */
1651 check_frame_size (frame
, 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. */
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
)
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
)
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
;
1687 check_min_window_sizes ();
1690 && ! NILP (w
->parent
)
1691 && height
< window_min_height
)
1693 Fdelete_window (window
);
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
);
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
;
1732 /* Now delete any children that became too small. */
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
)
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
;
1754 if (!nodelete
&& width
< window_min_width
&& !NILP (w
->parent
))
1756 Fdelete_window (window
);
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
);
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 */
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.")
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");
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
);
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
))),
1840 set_marker_restricted (w
->start
,
1841 make_number (XBUFFER (buffer
)->last_window_start
),
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
);
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.")
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
))
1874 Fset_marker (ow
->pointm
, make_number (BUF_PT (XBUFFER (ow
->buffer
))),
1877 selected_window
= window
;
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
1886 Fselect_frame (WINDOW_FRAME (w
), Qnil
);
1889 selected_frame
->selected_window
= window
;
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
)
1904 else if (new_point
> ZV
)
1910 windows_or_buffers_changed
++;
1914 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 2,
1915 "bDisplay buffer: \nP",
1916 "Make BUFFER appear in some window but don't select it.\n\
1917 BUFFER can be a buffer or a buffer name.\n\
1918 If BUFFER is shown already in some window, just use that one,\n\
1919 unless the window is the selected window and the optional second\n\
1920 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
1921 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
1922 Returns the window displaying BUFFER.")
1923 (buffer
, not_this_window
)
1924 register Lisp_Object buffer
, not_this_window
;
1926 register Lisp_Object window
, tem
;
1928 buffer
= Fget_buffer (buffer
);
1929 CHECK_BUFFER (buffer
, 0);
1931 if (!NILP (Vdisplay_buffer_function
))
1932 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
1934 if (NILP (not_this_window
)
1935 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
1936 return selected_window
;
1938 /* See if the user has specified this buffer should appear
1939 in the selected window. */
1940 if (NILP (not_this_window
))
1942 tem
= Fmember (XBUFFER (buffer
)->name
, Vsame_window_buffer_names
);
1945 Fswitch_to_buffer (buffer
, Qnil
);
1946 return selected_window
;
1949 tem
= Fassoc (XBUFFER (buffer
)->name
, Vsame_window_buffer_names
);
1952 Fswitch_to_buffer (buffer
, Qnil
);
1953 return selected_window
;
1956 for (tem
= Vsame_window_regexps
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
1958 Lisp_Object car
= XCONS (tem
)->car
;
1960 && fast_string_match (car
, XBUFFER (buffer
)->name
) >= 0)
1962 Fswitch_to_buffer (buffer
, Qnil
);
1963 return selected_window
;
1965 else if (CONSP (car
)
1966 && STRINGP (XCONS (car
)->car
)
1967 && fast_string_match (XCONS (car
)->car
,
1968 XBUFFER (buffer
)->name
) >= 0)
1970 Fswitch_to_buffer (buffer
, Qnil
);
1971 return selected_window
;
1977 /* If pop_up_frames,
1978 look for a window showing BUFFER on any visible or iconified frame.
1979 Otherwise search only the current frame. */
1980 if (pop_up_frames
|| last_nonminibuf_frame
== 0)
1981 XSETFASTINT (tem
, 0);
1984 XSETFRAME (tem
, last_nonminibuf_frame
);
1985 window
= Fget_buffer_window (buffer
, tem
);
1987 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
1990 if (FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (window
)))))
1991 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
1996 /* Certain buffer names get special handling. */
1997 if (! NILP (Vspecial_display_function
))
1999 tem
= Fmember (XBUFFER (buffer
)->name
, Vspecial_display_buffer_names
);
2001 return call1 (Vspecial_display_function
, buffer
);
2003 tem
= Fassoc (XBUFFER (buffer
)->name
, Vspecial_display_buffer_names
);
2005 return call2 (Vspecial_display_function
, buffer
, XCONS (tem
)->cdr
);
2007 for (tem
= Vspecial_display_regexps
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
2009 Lisp_Object car
= XCONS (tem
)->car
;
2011 && fast_string_match (car
, XBUFFER (buffer
)->name
) >= 0)
2012 return call1 (Vspecial_display_function
, buffer
);
2013 else if (CONSP (car
)
2014 && STRINGP (XCONS (car
)->car
)
2015 && fast_string_match (XCONS (car
)->car
,
2016 XBUFFER (buffer
)->name
) >= 0)
2017 return call2 (Vspecial_display_function
,
2024 /* If there are no frames open that have more than a minibuffer,
2025 we need to create a new frame. */
2026 if (pop_up_frames
|| last_nonminibuf_frame
== 0)
2028 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
2029 Fset_window_buffer (window
, buffer
);
2032 #endif /* MULTI_FRAME */
2036 || FRAME_MINIBUF_ONLY_P (selected_frame
)
2037 /* If the current frame is a special display frame,
2038 don't try to reuse its windows. */
2039 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->dedicated
)
2047 if (FRAME_MINIBUF_ONLY_P (selected_frame
))
2048 XSETFRAME (frames
, last_nonminibuf_frame
);
2050 /* Don't try to create a window if would get an error */
2051 if (split_height_threshold
< window_min_height
<< 1)
2052 split_height_threshold
= window_min_height
<< 1;
2054 /* Note that both Fget_largest_window and Fget_lru_window
2055 ignore minibuffers and dedicated windows.
2056 This means they can return nil. */
2059 /* If the frame we would try to split cannot be split,
2060 try other frames. */
2061 if (FRAME_NO_SPLIT_P (NILP (frames
) ? selected_frame
2062 : last_nonminibuf_frame
))
2064 /* Try visible frames first. */
2065 window
= Fget_largest_window (Qvisible
);
2066 /* If that didn't work, try iconified frames. */
2068 window
= Fget_largest_window (make_number (0));
2070 window
= Fget_largest_window (Qt
);
2074 window
= Fget_largest_window (frames
);
2076 /* If we got a tall enough full-width window that can be split,
2079 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
2080 && window_height (window
) >= split_height_threshold
2081 && (XFASTINT (XWINDOW (window
)->width
)
2082 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window
))))))
2083 window
= Fsplit_window (window
, Qnil
, Qnil
);
2086 Lisp_Object upper
, lower
, other
;
2088 window
= Fget_lru_window (frames
);
2089 /* If the LRU window is selected, and big enough,
2090 and can be split, split it. */
2092 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
2093 && (EQ (window
, selected_window
)
2094 || EQ (XWINDOW (window
)->parent
, Qnil
))
2095 && window_height (window
) >= window_min_height
<< 1)
2096 window
= Fsplit_window (window
, Qnil
, Qnil
);
2098 /* If Fget_lru_window returned nil, try other approaches. */
2099 /* Try visible frames first. */
2101 window
= Fget_largest_window (Qvisible
);
2102 /* If that didn't work, try iconified frames. */
2104 window
= Fget_largest_window (make_number (0));
2105 /* Try invisible frames. */
2107 window
= Fget_largest_window (Qt
);
2108 /* As a last resort, make a new frame. */
2110 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
2112 /* As a last resort, use a non minibuffer window. */
2114 window
= Fframe_first_window (Fselected_frame ());
2116 /* If window appears above or below another,
2117 even out their heights. */
2118 other
= upper
= lower
= Qnil
;
2119 if (!NILP (XWINDOW (window
)->prev
))
2120 other
= upper
= XWINDOW (window
)->prev
, lower
= window
;
2121 if (!NILP (XWINDOW (window
)->next
))
2122 other
= lower
= XWINDOW (window
)->next
, upper
= window
;
2124 /* Check that OTHER and WINDOW are vertically arrayed. */
2125 && XWINDOW (other
)->top
!= XWINDOW (window
)->top
2126 && XWINDOW (other
)->height
> XWINDOW (window
)->height
)
2128 int total
= XWINDOW (other
)->height
+ XWINDOW (window
)->height
;
2129 Lisp_Object old_selected_window
;
2130 old_selected_window
= selected_window
;
2132 selected_window
= upper
;
2133 change_window_height (total
/ 2 - XWINDOW (upper
)->height
, 0);
2134 selected_window
= old_selected_window
;
2139 window
= Fget_lru_window (Qnil
);
2141 Fset_window_buffer (window
, buffer
);
2146 temp_output_buffer_show (buf
)
2147 register Lisp_Object buf
;
2149 register struct buffer
*old
= current_buffer
;
2150 register Lisp_Object window
;
2151 register struct window
*w
;
2154 BUF_SAVE_MODIFF (XBUFFER (buf
)) = MODIFF
;
2158 XBUFFER (buf
)->clip_changed
= 1;
2159 set_buffer_internal (old
);
2161 if (!EQ (Vtemp_buffer_show_function
, Qnil
))
2162 call1 (Vtemp_buffer_show_function
, buf
);
2165 window
= Fdisplay_buffer (buf
, Qnil
);
2168 if (XFRAME (XWINDOW (window
)->frame
) != selected_frame
)
2169 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
2170 #endif /* MULTI_FRAME */
2171 Vminibuf_scroll_window
= window
;
2172 w
= XWINDOW (window
);
2173 XSETFASTINT (w
->hscroll
, 0);
2174 set_marker_restricted (w
->start
, make_number (1), buf
);
2175 set_marker_restricted (w
->pointm
, make_number (1), buf
);
2177 /* Run temp-buffer-show-hook, with the chosen window selected. */
2178 if (!NILP (Vrun_hooks
))
2181 tem
= Fboundp (Qtemp_buffer_show_hook
);
2184 tem
= Fsymbol_value (Qtemp_buffer_show_hook
);
2187 int count
= specpdl_ptr
- specpdl
;
2189 /* Select the window that was chosen, for running the hook. */
2190 record_unwind_protect (Fset_window_configuration
,
2191 Fcurrent_window_configuration (Qnil
));
2193 Fselect_window (window
);
2194 call1 (Vrun_hooks
, Qtemp_buffer_show_hook
);
2195 unbind_to (count
, Qnil
);
2203 make_dummy_parent (window
)
2207 register struct window
*o
, *p
;
2208 register struct Lisp_Vector
*vec
;
2211 o
= XWINDOW (window
);
2212 vec
= allocate_vectorlike ((EMACS_INT
)VECSIZE (struct window
));
2213 for (i
= 0; i
< VECSIZE (struct window
); ++i
)
2214 vec
->contents
[i
] = ((struct Lisp_Vector
*)o
)->contents
[i
];
2215 vec
->size
= VECSIZE (struct window
);
2216 p
= (struct window
*)vec
;
2217 XSETWINDOW (new, p
);
2219 XSETFASTINT (p
->sequence_number
, ++sequence_number
);
2221 /* Put new into window structure in place of window */
2222 replace_window (window
, new);
2235 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
2236 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
2237 WINDOW defaults to selected one and SIZE to half its size.\n\
2238 If optional third arg HOR-FLAG is non-nil, split side by side\n\
2239 and put SIZE columns in the first of the pair.")
2240 (window
, chsize
, horflag
)
2241 Lisp_Object window
, chsize
, horflag
;
2243 register Lisp_Object
new;
2244 register struct window
*o
, *p
;
2248 window
= selected_window
;
2250 CHECK_LIVE_WINDOW (window
, 0);
2252 o
= XWINDOW (window
);
2256 if (!NILP (horflag
))
2257 /* Round odd size up, since this is for the left-hand window,
2258 and it will lose a column for the separators. */
2259 size
= ((XFASTINT (o
->width
) + 1) & -2) >> 1;
2261 size
= XFASTINT (o
->height
) >> 1;
2265 CHECK_NUMBER (chsize
, 1);
2266 size
= XINT (chsize
);
2269 if (MINI_WINDOW_P (o
))
2270 error ("Attempt to split minibuffer window");
2271 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o
))))
2272 error ("Attempt to split unsplittable frame");
2274 check_min_window_sizes ();
2278 if (size
< window_min_height
)
2279 error ("Window height %d too small (after splitting)", size
);
2280 if (size
+ window_min_height
> XFASTINT (o
->height
))
2281 error ("Window height %d too small (after splitting)",
2282 XFASTINT (o
->height
) - size
);
2283 if (NILP (o
->parent
)
2284 || NILP (XWINDOW (o
->parent
)->vchild
))
2286 make_dummy_parent (window
);
2288 XWINDOW (new)->vchild
= window
;
2293 if (size
< window_min_width
)
2294 error ("Window width %d too small (after splitting)", size
);
2295 if (size
+ window_min_width
> XFASTINT (o
->width
))
2296 error ("Window width %d too small (after splitting)",
2297 XFASTINT (o
->width
) - size
);
2298 if (NILP (o
->parent
)
2299 || NILP (XWINDOW (o
->parent
)->hchild
))
2301 make_dummy_parent (window
);
2303 XWINDOW (new)->hchild
= window
;
2307 /* Now we know that window's parent is a vertical combination
2308 if we are dividing vertically, or a horizontal combination
2309 if we are making side-by-side windows */
2311 windows_or_buffers_changed
++;
2312 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (o
))) = 1;
2313 new = make_window ();
2316 p
->frame
= o
->frame
;
2318 if (!NILP (p
->next
))
2319 XWINDOW (p
->next
)->prev
= new;
2322 p
->parent
= o
->parent
;
2325 Fset_window_buffer (new, o
->buffer
);
2327 /* Apportion the available frame space among the two new windows */
2329 if (!NILP (horflag
))
2331 p
->height
= o
->height
;
2333 XSETFASTINT (p
->width
, XFASTINT (o
->width
) - size
);
2334 XSETFASTINT (o
->width
, size
);
2335 XSETFASTINT (p
->left
, XFASTINT (o
->left
) + size
);
2340 p
->width
= o
->width
;
2341 XSETFASTINT (p
->height
, XFASTINT (o
->height
) - size
);
2342 XSETFASTINT (o
->height
, size
);
2343 XSETFASTINT (p
->top
, XFASTINT (o
->top
) + size
);
2349 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
2350 "Make current window ARG lines bigger.\n\
2351 From program, optional second arg non-nil means grow sideways ARG columns.")
2353 register Lisp_Object n
, side
;
2355 CHECK_NUMBER (n
, 0);
2356 change_window_height (XINT (n
), !NILP (side
));
2360 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
2361 "Make current window ARG lines smaller.\n\
2362 From program, optional second arg non-nil means shrink sideways ARG columns.")
2364 register Lisp_Object n
, side
;
2366 CHECK_NUMBER (n
, 0);
2367 change_window_height (-XINT (n
), !NILP (side
));
2372 window_height (window
)
2375 register struct window
*p
= XWINDOW (window
);
2376 return XFASTINT (p
->height
);
2380 window_width (window
)
2383 register struct window
*p
= XWINDOW (window
);
2384 return XFASTINT (p
->width
);
2387 #define MINSIZE(w) \
2389 ? window_min_width \
2390 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
2393 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
2395 #define CURSIZE(w) \
2396 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
2398 /* Unlike set_window_height, this function
2399 also changes the heights of the siblings so as to
2400 keep everything consistent. */
2402 change_window_height (delta
, widthflag
)
2406 register Lisp_Object parent
;
2408 register struct window
*p
;
2410 int (*sizefun
) () = widthflag
? window_width
: window_height
;
2411 register int (*setsizefun
) () = (widthflag
2413 : set_window_height
);
2415 check_min_window_sizes ();
2417 window
= selected_window
;
2420 p
= XWINDOW (window
);
2425 error ("No other window to side of this one");
2428 if (widthflag
? !NILP (XWINDOW (parent
)->hchild
)
2429 : !NILP (XWINDOW (parent
)->vchild
))
2434 sizep
= &CURSIZE (window
);
2437 register int maxdelta
;
2439 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - *sizep
2440 : !NILP (p
->next
) ? (*sizefun
) (p
->next
) - MINSIZE (p
->next
)
2441 : !NILP (p
->prev
) ? (*sizefun
) (p
->prev
) - MINSIZE (p
->prev
)
2442 /* This is a frame with only one window, a minibuffer-only
2443 or a minibufferless frame. */
2446 if (delta
> maxdelta
)
2447 /* This case traps trying to make the minibuffer
2448 the full frame, or make the only window aside from the
2449 minibuffer the full frame. */
2453 if (*sizep
+ delta
< MINSIZE (window
))
2455 Fdelete_window (window
);
2463 && (*sizefun
) (p
->next
) - delta
>= MINSIZE (p
->next
))
2465 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
) - delta
, 0);
2466 (*setsizefun
) (window
, *sizep
+ delta
, 0);
2467 CURBEG (p
->next
) += delta
;
2468 /* This does not change size of p->next,
2469 but it propagates the new top edge to its children */
2470 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
), 0);
2472 else if (!NILP (p
->prev
)
2473 && (*sizefun
) (p
->prev
) - delta
>= MINSIZE (p
->prev
))
2475 (*setsizefun
) (p
->prev
, (*sizefun
) (p
->prev
) - delta
, 0);
2476 CURBEG (window
) -= delta
;
2477 (*setsizefun
) (window
, *sizep
+ delta
, 0);
2481 register int delta1
;
2482 register int opht
= (*sizefun
) (parent
);
2484 /* If trying to grow this window to or beyond size of the parent,
2485 make delta1 so big that, on shrinking back down,
2486 all the siblings end up with less than one line and are deleted. */
2487 if (opht
<= *sizep
+ delta
)
2488 delta1
= opht
* opht
* 2;
2489 /* Otherwise, make delta1 just right so that if we add delta1
2490 lines to this window and to the parent, and then shrink
2491 the parent back to its original size, the new proportional
2492 size of this window will increase by delta. */
2494 delta1
= (delta
* opht
* 100) / ((opht
- *sizep
- delta
) * 100);
2496 /* Add delta1 lines or columns to this window, and to the parent,
2497 keeping things consistent while not affecting siblings. */
2498 CURSIZE (parent
) = opht
+ delta1
;
2499 (*setsizefun
) (window
, *sizep
+ delta1
, 0);
2501 /* Squeeze out delta1 lines or columns from our parent,
2502 shriking this window and siblings proportionately.
2503 This brings parent back to correct size.
2504 Delta1 was calculated so this makes this window the desired size,
2505 taking it all out of the siblings. */
2506 (*setsizefun
) (parent
, opht
, 0);
2509 XSETFASTINT (p
->last_modified
, 0);
2516 /* Return number of lines of text (not counting mode line) in W. */
2519 window_internal_height (w
)
2522 int ht
= XFASTINT (w
->height
);
2524 if (MINI_WINDOW_P (w
))
2527 if (!NILP (w
->parent
) || !NILP (w
->vchild
) || !NILP (w
->hchild
)
2528 || !NILP (w
->next
) || !NILP (w
->prev
)
2529 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w
))))
2536 /* Return the number of columns in W.
2537 Don't count columns occupied by scroll bars or the vertical bar
2538 separating W from the sibling to its right. */
2540 window_internal_width (w
)
2543 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2544 int left
= XINT (w
->left
);
2545 int width
= XINT (w
->width
);
2547 /* If this window is flush against the right edge of the frame, its
2548 internal width is its full width. */
2549 if (left
+ width
>= FRAME_WIDTH (f
))
2552 /* If we are not flush right, then our rightmost columns are
2553 occupied by some sort of separator. */
2555 /* Scroll bars occupy a few columns. */
2556 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2557 return width
- FRAME_SCROLL_BAR_COLS (f
);
2559 /* The column of `|' characters separating side-by-side windows
2560 occupies one column only. */
2565 /* Scroll contents of window WINDOW up N lines. */
2568 window_scroll (window
, n
, noerror
)
2573 register struct window
*w
= XWINDOW (window
);
2574 register int opoint
= PT
;
2576 register int ht
= window_internal_height (w
);
2577 register Lisp_Object tem
;
2579 Lisp_Object bolp
, nmoved
;
2581 /* Always set force_start so that redisplay_window will run
2582 thw window-scroll-functions. */
2583 w
->force_start
= Qt
;
2585 XSETFASTINT (tem
, PT
);
2586 tem
= Fpos_visible_in_window_p (tem
, window
);
2590 Fvertical_motion (make_number (- (ht
/ 2)), window
);
2591 XSETFASTINT (tem
, PT
);
2592 Fset_marker (w
->start
, tem
, w
->buffer
);
2595 SET_PT (marker_position (w
->start
));
2596 lose
= n
< 0 && PT
== BEGV
;
2597 Fvertical_motion (make_number (n
), window
);
2607 Fsignal (Qbeginning_of_buffer
, Qnil
);
2612 set_marker_restricted (w
->start
, make_number (pos
), w
->buffer
);
2613 w
->start_at_line_beg
= bolp
;
2614 w
->update_mode_line
= Qt
;
2615 XSETFASTINT (w
->last_modified
, 0);
2621 tem
= Fvertical_motion (make_number (ht
), window
);
2622 if (PT
> opoint
|| XFASTINT (tem
) < ht
)
2625 Fvertical_motion (make_number (-1), window
);
2633 Fsignal (Qend_of_buffer
, Qnil
);
2637 /* This is the guts of Fscroll_up and Fscroll_down. */
2640 scroll_command (n
, direction
)
2641 register Lisp_Object n
;
2644 register int defalt
;
2645 int count
= specpdl_ptr
- specpdl
;
2647 /* If selected window's buffer isn't current, make it current for the moment.
2648 But don't screw up if window_scroll gets an error. */
2649 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
2651 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2652 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2655 defalt
= (window_internal_height (XWINDOW (selected_window
))
2656 - next_screen_context_lines
);
2657 defalt
= direction
* (defalt
< 1 ? 1 : defalt
);
2660 window_scroll (selected_window
, defalt
, 0);
2661 else if (EQ (n
, Qminus
))
2662 window_scroll (selected_window
, - defalt
, 0);
2665 n
= Fprefix_numeric_value (n
);
2666 window_scroll (selected_window
, XINT (n
) * direction
, 0);
2669 unbind_to (count
, Qnil
);
2672 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "P",
2673 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2674 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2675 Negative ARG means scroll downward.\n\
2676 When calling from a program, supply a number as argument or nil.")
2680 scroll_command (n
, 1);
2684 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "P",
2685 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2686 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2687 Negative ARG means scroll upward.\n\
2688 When calling from a program, supply a number as argument or nil.")
2692 scroll_command (n
, -1);
2696 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling
, Sother_window_for_scrolling
, 0, 0, 0,
2697 "Return the other window for \"other window scroll\" commands.\n\
2698 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2699 specifies the window.\n\
2700 If `other-window-scroll-buffer' is non-nil, a window\n\
2701 showing that buffer is used.")
2706 if (MINI_WINDOW_P (XWINDOW (selected_window
))
2707 && !NILP (Vminibuf_scroll_window
))
2708 window
= Vminibuf_scroll_window
;
2709 /* If buffer is specified, scroll that buffer. */
2710 else if (!NILP (Vother_window_scroll_buffer
))
2712 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
2714 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
);
2718 /* Nothing specified; look for a neighboring window on the same
2720 window
= Fnext_window (selected_window
, Qnil
, Qnil
);
2722 if (EQ (window
, selected_window
))
2723 /* That didn't get us anywhere; look for a window on another
2726 window
= Fnext_window (window
, Qnil
, Qt
);
2727 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window
))))
2728 && ! EQ (window
, selected_window
));
2731 CHECK_LIVE_WINDOW (window
, 0);
2733 if (EQ (window
, selected_window
))
2734 error ("There is no other window");
2739 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
2740 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
2741 The next window is the one below the current one; or the one at the top\n\
2742 if the current one is at the bottom. Negative ARG means scroll downward.\n\
2743 When calling from a program, supply a number as argument or nil.\n\
2745 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2746 specifies the window to scroll.\n\
2747 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2748 showing that buffer, popping the buffer up if necessary.")
2750 register Lisp_Object n
;
2752 register Lisp_Object window
;
2753 register int defalt
;
2754 register struct window
*w
;
2755 register int count
= specpdl_ptr
- specpdl
;
2757 window
= Fother_window_for_scrolling ();
2759 w
= XWINDOW (window
);
2760 defalt
= window_internal_height (w
) - next_screen_context_lines
;
2761 if (defalt
< 1) defalt
= 1;
2763 /* Don't screw up if window_scroll gets an error. */
2764 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2766 Fset_buffer (w
->buffer
);
2767 SET_PT (marker_position (w
->pointm
));
2770 window_scroll (window
, defalt
, 1);
2771 else if (EQ (n
, Qminus
))
2772 window_scroll (window
, -defalt
, 1);
2777 CHECK_NUMBER (n
, 0);
2778 window_scroll (window
, XINT (n
), 1);
2781 Fset_marker (w
->pointm
, make_number (PT
), Qnil
);
2782 unbind_to (count
, Qnil
);
2787 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 0, 1, "P",
2788 "Scroll selected window display ARG columns left.\n\
2789 Default for ARG is window width minus 2.")
2791 register Lisp_Object arg
;
2795 XSETFASTINT (arg
, window_internal_width (XWINDOW (selected_window
)) - 2);
2797 arg
= Fprefix_numeric_value (arg
);
2800 Fset_window_hscroll (selected_window
,
2801 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2805 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 0, 1, "P",
2806 "Scroll selected window display ARG columns right.\n\
2807 Default for ARG is window width minus 2.")
2809 register Lisp_Object arg
;
2812 XSETFASTINT (arg
, window_internal_width (XWINDOW (selected_window
)) - 2);
2814 arg
= Fprefix_numeric_value (arg
);
2817 Fset_window_hscroll (selected_window
,
2818 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2822 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
2823 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
2824 The desired position of point is always relative to the current window.\n\
2825 Just C-u as prefix means put point in the center of the window.\n\
2826 No arg (i.e., it is nil) erases the entire frame and then\n\
2827 redraws with point in the center of the current window.")
2829 register Lisp_Object n
;
2831 register struct window
*w
= XWINDOW (selected_window
);
2832 register int ht
= window_internal_height (w
);
2833 struct position pos
;
2837 extern int frame_garbaged
;
2839 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w
)));
2840 XSETFASTINT (n
, ht
/ 2);
2842 else if (CONSP (n
)) /* Just C-u. */
2844 XSETFASTINT (n
, ht
/ 2);
2848 n
= Fprefix_numeric_value (n
);
2849 CHECK_NUMBER (n
, 0);
2853 XSETINT (n
, XINT (n
) + ht
);
2855 pos
= *vmotion (point
, - XINT (n
), w
);
2857 Fset_marker (w
->start
, make_number (pos
.bufpos
), w
->buffer
);
2858 w
->start_at_line_beg
= ((pos
.bufpos
== BEGV
2859 || FETCH_CHAR (pos
.bufpos
- 1) == '\n')
2861 w
->force_start
= Qt
;
2866 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
2868 "Position point relative to window.\n\
2869 With no argument, position point at center of window.\n\
2870 An argument specifies frame line; zero means top of window,\n\
2871 negative means relative to bottom of window.")
2873 register Lisp_Object arg
;
2875 register struct window
*w
= XWINDOW (selected_window
);
2876 register int height
= window_internal_height (w
);
2881 XSETFASTINT (arg
, height
/ 2);
2884 arg
= Fprefix_numeric_value (arg
);
2886 XSETINT (arg
, XINT (arg
) + height
);
2889 start
= marker_position (w
->start
);
2890 XSETWINDOW (window
, w
);
2891 if (start
< BEGV
|| start
> ZV
)
2893 Fvertical_motion (make_number (- (height
/ 2)), window
);
2894 Fset_marker (w
->start
, make_number (PT
), w
->buffer
);
2895 w
->start_at_line_beg
= Fbolp ();
2896 w
->force_start
= Qt
;
2901 return Fvertical_motion (arg
, window
);
2904 struct save_window_data
2906 int size_from_Lisp_Vector_struct
;
2907 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2908 Lisp_Object frame_width
, frame_height
, frame_menu_bar_lines
;
2909 Lisp_Object selected_frame
;
2910 Lisp_Object current_window
;
2911 Lisp_Object current_buffer
;
2912 Lisp_Object minibuf_scroll_window
;
2913 Lisp_Object root_window
;
2914 Lisp_Object focus_frame
;
2915 /* Record the values of window-min-width and window-min-height
2916 so that window sizes remain consistent with them. */
2917 Lisp_Object min_width
, min_height
;
2918 /* A vector, interpreted as a struct saved_window */
2919 Lisp_Object saved_windows
;
2922 /* This is saved as a Lisp_Vector */
2925 /* these first two must agree with struct Lisp_Vector in lisp.h */
2926 int size_from_Lisp_Vector_struct
;
2927 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2930 Lisp_Object buffer
, start
, pointm
, mark
;
2931 Lisp_Object left
, top
, width
, height
, hscroll
;
2932 Lisp_Object parent
, prev
;
2933 Lisp_Object start_at_line_beg
;
2934 Lisp_Object display_table
;
2936 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2938 #define SAVED_WINDOW_N(swv,n) \
2939 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2941 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
2942 "T if OBJECT is a window-configration object.")
2946 if (WINDOW_CONFIGURATIONP (obj
))
2952 DEFUN ("set-window-configuration", Fset_window_configuration
,
2953 Sset_window_configuration
, 1, 1, 0,
2954 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2955 CONFIGURATION must be a value previously returned\n\
2956 by `current-window-configuration' (which see).")
2958 Lisp_Object configuration
;
2960 register struct save_window_data
*data
;
2961 struct Lisp_Vector
*saved_windows
;
2962 Lisp_Object new_current_buffer
;
2966 while (!WINDOW_CONFIGURATIONP (configuration
))
2968 configuration
= wrong_type_argument (intern ("window-configuration-p"),
2972 data
= (struct save_window_data
*) XVECTOR (configuration
);
2973 saved_windows
= XVECTOR (data
->saved_windows
);
2975 new_current_buffer
= data
->current_buffer
;
2976 if (NILP (XBUFFER (new_current_buffer
)->name
))
2977 new_current_buffer
= Qnil
;
2979 frame
= XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
2982 /* If f is a dead frame, don't bother rebuilding its window tree.
2983 However, there is other stuff we should still try to do below. */
2984 if (FRAME_LIVE_P (f
))
2986 register struct window
*w
;
2987 register struct saved_window
*p
;
2990 /* If the frame has been resized since this window configuration was
2991 made, we change the frame to the size specified in the
2992 configuration, restore the configuration, and then resize it
2993 back. We keep track of the prevailing height in these variables. */
2994 int previous_frame_height
= FRAME_HEIGHT (f
);
2995 int previous_frame_width
= FRAME_WIDTH (f
);
2996 int previous_frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
2998 if (XFASTINT (data
->frame_height
) != previous_frame_height
2999 || XFASTINT (data
->frame_width
) != previous_frame_width
)
3000 change_frame_size (f
, data
->frame_height
, data
->frame_width
, 0, 0);
3001 #ifdef HAVE_WINDOW_SYSTEM
3002 if (XFASTINT (data
->frame_menu_bar_lines
)
3003 != previous_frame_menu_bar_lines
)
3004 x_set_menu_bar_lines (f
, data
->frame_menu_bar_lines
, 0);
3007 windows_or_buffers_changed
++;
3008 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
3010 /* Temporarily avoid any problems with windows that are smaller
3011 than they are supposed to be. */
3012 window_min_height
= 1;
3013 window_min_width
= 1;
3016 Mark all windows now on frame as "deleted".
3017 Restoring the new configuration "undeletes" any that are in it.
3019 Save their current buffers in their height fields, since we may
3020 need it later, if a buffer saved in the configuration is now
3022 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3024 for (k
= 0; k
< saved_windows
->size
; k
++)
3026 p
= SAVED_WINDOW_N (saved_windows
, k
);
3027 w
= XWINDOW (p
->window
);
3030 if (!NILP (p
->parent
))
3031 w
->parent
= SAVED_WINDOW_N (saved_windows
,
3032 XFASTINT (p
->parent
))->window
;
3036 if (!NILP (p
->prev
))
3038 w
->prev
= SAVED_WINDOW_N (saved_windows
,
3039 XFASTINT (p
->prev
))->window
;
3040 XWINDOW (w
->prev
)->next
= p
->window
;
3045 if (!NILP (w
->parent
))
3047 if (EQ (p
->width
, XWINDOW (w
->parent
)->width
))
3049 XWINDOW (w
->parent
)->vchild
= p
->window
;
3050 XWINDOW (w
->parent
)->hchild
= Qnil
;
3054 XWINDOW (w
->parent
)->hchild
= p
->window
;
3055 XWINDOW (w
->parent
)->vchild
= Qnil
;
3060 /* If we squirreled away the buffer in the window's height,
3062 if (BUFFERP (w
->height
))
3063 w
->buffer
= w
->height
;
3066 w
->width
= p
->width
;
3067 w
->height
= p
->height
;
3068 w
->hscroll
= p
->hscroll
;
3069 w
->display_table
= p
->display_table
;
3070 XSETFASTINT (w
->last_modified
, 0);
3072 /* Reinstall the saved buffer and pointers into it. */
3073 if (NILP (p
->buffer
))
3074 w
->buffer
= p
->buffer
;
3077 if (!NILP (XBUFFER (p
->buffer
)->name
))
3078 /* If saved buffer is alive, install it. */
3080 w
->buffer
= p
->buffer
;
3081 w
->start_at_line_beg
= p
->start_at_line_beg
;
3082 set_marker_restricted (w
->start
,
3083 Fmarker_position (p
->start
),
3085 set_marker_restricted (w
->pointm
,
3086 Fmarker_position (p
->pointm
),
3088 Fset_marker (XBUFFER (w
->buffer
)->mark
,
3089 Fmarker_position (p
->mark
), w
->buffer
);
3091 /* As documented in Fcurrent_window_configuration, don't
3092 save the location of point in the buffer which was current
3093 when the window configuration was recorded. */
3094 if (!EQ (p
->buffer
, new_current_buffer
)
3095 && XBUFFER (p
->buffer
) == current_buffer
)
3096 Fgoto_char (w
->pointm
);
3098 else if (NILP (w
->buffer
) || NILP (XBUFFER (w
->buffer
)->name
))
3099 /* Else unless window has a live buffer, get one. */
3101 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
3102 /* This will set the markers to beginning of visible
3104 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
3105 set_marker_restricted (w
->pointm
, make_number (0),w
->buffer
);
3106 w
->start_at_line_beg
= Qt
;
3109 /* Keeping window's old buffer; make sure the markers
3112 /* Set window markers at start of visible range. */
3113 if (XMARKER (w
->start
)->buffer
== 0)
3114 set_marker_restricted (w
->start
, make_number (0),
3116 if (XMARKER (w
->pointm
)->buffer
== 0)
3117 set_marker_restricted (w
->pointm
,
3119 (BUF_PT (XBUFFER (w
->buffer
)))),
3121 w
->start_at_line_beg
= Qt
;
3126 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
3127 Fselect_window (data
->current_window
);
3130 if (NILP (data
->focus_frame
)
3131 || (FRAMEP (data
->focus_frame
)
3132 && FRAME_LIVE_P (XFRAME (data
->focus_frame
))))
3133 Fredirect_frame_focus (frame
, data
->focus_frame
);
3136 #if 0 /* I don't understand why this is needed, and it causes problems
3137 when the frame's old selected window has been deleted. */
3139 if (f
!= selected_frame
&& ! FRAME_TERMCAP_P (f
))
3140 do_switch_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)),
3145 /* Set the screen height to the value it had before this function. */
3146 if (previous_frame_height
!= FRAME_HEIGHT (f
)
3147 || previous_frame_width
!= FRAME_WIDTH (f
))
3148 change_frame_size (f
, previous_frame_height
, previous_frame_width
,
3150 #ifdef HAVE_WINDOW_SYSTEM
3151 if (previous_frame_menu_bar_lines
!= FRAME_MENU_BAR_LINES (f
))
3152 x_set_menu_bar_lines (f
, previous_frame_menu_bar_lines
, 0);
3156 /* Restore the minimum heights recorded in the configuration. */
3157 window_min_height
= XINT (data
->min_height
);
3158 window_min_width
= XINT (data
->min_width
);
3161 /* Fselect_window will have made f the selected frame, so we
3162 reselect the proper frame here. Fhandle_switch_frame will change the
3163 selected window too, but that doesn't make the call to
3164 Fselect_window above totally superfluous; it still sets f's
3166 if (FRAME_LIVE_P (XFRAME (data
->selected_frame
)))
3167 do_switch_frame (data
->selected_frame
, Qnil
, 0);
3170 if (!NILP (new_current_buffer
))
3171 Fset_buffer (new_current_buffer
);
3173 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
3177 /* Mark all windows now on frame as deleted
3178 by setting their buffers to nil. */
3181 delete_all_subwindows (w
)
3182 register struct window
*w
;
3184 if (!NILP (w
->next
))
3185 delete_all_subwindows (XWINDOW (w
->next
));
3186 if (!NILP (w
->vchild
))
3187 delete_all_subwindows (XWINDOW (w
->vchild
));
3188 if (!NILP (w
->hchild
))
3189 delete_all_subwindows (XWINDOW (w
->hchild
));
3191 w
->height
= w
->buffer
; /* See Fset_window_configuration for excuse. */
3193 /* We set all three of these fields to nil, to make sure that we can
3194 distinguish this dead window from any live window. Live leaf
3195 windows will have buffer set, and combination windows will have
3196 vchild or hchild set. */
3203 count_windows (window
)
3204 register struct window
*window
;
3206 register int count
= 1;
3207 if (!NILP (window
->next
))
3208 count
+= count_windows (XWINDOW (window
->next
));
3209 if (!NILP (window
->vchild
))
3210 count
+= count_windows (XWINDOW (window
->vchild
));
3211 if (!NILP (window
->hchild
))
3212 count
+= count_windows (XWINDOW (window
->hchild
));
3217 save_window_save (window
, vector
, i
)
3219 struct Lisp_Vector
*vector
;
3222 register struct saved_window
*p
;
3223 register struct window
*w
;
3224 register Lisp_Object tem
;
3226 for (;!NILP (window
); window
= w
->next
)
3228 p
= SAVED_WINDOW_N (vector
, i
);
3229 w
= XWINDOW (window
);
3231 XSETFASTINT (w
->temslot
, i
++);
3233 p
->buffer
= w
->buffer
;
3236 p
->width
= w
->width
;
3237 p
->height
= w
->height
;
3238 p
->hscroll
= w
->hscroll
;
3239 p
->display_table
= w
->display_table
;
3240 if (!NILP (w
->buffer
))
3242 /* Save w's value of point in the window configuration.
3243 If w is the selected window, then get the value of point
3244 from the buffer; pointm is garbage in the selected window. */
3245 if (EQ (window
, selected_window
))
3247 p
->pointm
= Fmake_marker ();
3248 Fset_marker (p
->pointm
, BUF_PT (XBUFFER (w
->buffer
)),
3252 p
->pointm
= Fcopy_marker (w
->pointm
, Qnil
);
3254 p
->start
= Fcopy_marker (w
->start
, Qnil
);
3255 p
->start_at_line_beg
= w
->start_at_line_beg
;
3257 tem
= XBUFFER (w
->buffer
)->mark
;
3258 p
->mark
= Fcopy_marker (tem
, Qnil
);
3265 p
->start_at_line_beg
= Qnil
;
3268 if (NILP (w
->parent
))
3271 p
->parent
= XWINDOW (w
->parent
)->temslot
;
3276 p
->prev
= XWINDOW (w
->prev
)->temslot
;
3278 if (!NILP (w
->vchild
))
3279 i
= save_window_save (w
->vchild
, vector
, i
);
3280 if (!NILP (w
->hchild
))
3281 i
= save_window_save (w
->hchild
, vector
, i
);
3287 DEFUN ("current-window-configuration",
3288 Fcurrent_window_configuration
, Scurrent_window_configuration
, 0, 1, 0,
3289 "Return an object representing the current window configuration of FRAME.\n\
3290 If FRAME is nil or omitted, use the selected frame.\n\
3291 This describes the number of windows, their sizes and current buffers,\n\
3292 and for each displayed buffer, where display starts, and the positions of\n\
3293 point and mark. An exception is made for point in the current buffer:\n\
3294 its value is -not- saved.\n\
3295 This also records the currently selected frame, and FRAME's focus\n\
3296 redirection (see `redirect-frame-focus').")
3300 register Lisp_Object tem
;
3301 register int n_windows
;
3302 register struct save_window_data
*data
;
3303 register struct Lisp_Vector
*vec
;
3311 CHECK_LIVE_FRAME (frame
, 0);
3315 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3316 vec
= allocate_vectorlike (VECSIZE (struct save_window_data
));
3317 for (i
= 0; i
< VECSIZE (struct save_window_data
); i
++)
3318 vec
->contents
[i
] = Qnil
;
3319 vec
->size
= VECSIZE (struct save_window_data
);
3320 data
= (struct save_window_data
*)vec
;
3322 XSETFASTINT (data
->frame_width
, FRAME_WIDTH (f
));
3323 XSETFASTINT (data
->frame_height
, FRAME_HEIGHT (f
));
3324 XSETFASTINT (data
->frame_menu_bar_lines
, FRAME_MENU_BAR_LINES (f
));
3326 XSETFRAME (data
->selected_frame
, selected_frame
);
3328 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
3329 XSETBUFFER (data
->current_buffer
, current_buffer
);
3330 data
->minibuf_scroll_window
= Vminibuf_scroll_window
;
3331 data
->root_window
= FRAME_ROOT_WINDOW (f
);
3332 data
->focus_frame
= FRAME_FOCUS_FRAME (f
);
3333 XSETINT (data
->min_height
, window_min_height
);
3334 XSETINT (data
->min_width
, window_min_width
);
3335 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
3336 data
->saved_windows
= tem
;
3337 for (i
= 0; i
< n_windows
; i
++)
3338 XVECTOR (tem
)->contents
[i
]
3339 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE
), Qnil
);
3340 save_window_save (FRAME_ROOT_WINDOW (f
),
3342 XSETWINDOW_CONFIGURATION (tem
, data
);
3346 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
3348 "Execute body, preserving window sizes and contents.\n\
3349 Restore which buffer appears in which window, where display starts,\n\
3350 and the value of point and mark for each window.\n\
3351 Also restore which buffer is current.\n\
3352 But do not preserve point in the current buffer.\n\
3353 Does not restore the value of point in current buffer.")
3357 register Lisp_Object val
;
3358 register int count
= specpdl_ptr
- specpdl
;
3360 record_unwind_protect (Fset_window_configuration
,
3361 Fcurrent_window_configuration (Qnil
));
3362 val
= Fprogn (args
);
3363 return unbind_to (count
, val
);
3369 selected_frame
= make_terminal_frame ();
3370 XSETFRAME (Vterminal_frame
, selected_frame
);
3371 minibuf_window
= selected_frame
->minibuffer_window
;
3372 selected_window
= selected_frame
->selected_window
;
3373 last_nonminibuf_frame
= selected_frame
;
3374 #else /* not MULTI_FRAME */
3375 extern Lisp_Object
get_minibuffer ();
3377 selected_frame
= last_nonminibuf_frame
= &the_only_frame
;
3379 minibuf_window
= make_window ();
3380 FRAME_ROOT_WINDOW (selected_frame
) = make_window ();
3382 XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->next
= minibuf_window
;
3383 XWINDOW (minibuf_window
)->prev
= FRAME_ROOT_WINDOW (selected_frame
);
3384 XWINDOW (minibuf_window
)->mini_p
= Qt
;
3386 /* These values 9 and 10 are arbitrary,
3387 just so that there is "something there."
3388 Correct values are put in in init_xdisp */
3390 XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->width
, 10);
3391 XSETFASTINT (XWINDOW (minibuf_window
)->width
, 10);
3393 XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->height
, 9);
3394 XSETFASTINT (XWINDOW (minibuf_window
)->top
, 9);
3395 XSETFASTINT (XWINDOW (minibuf_window
)->height
, 1);
3397 /* Prevent error in Fset_window_buffer. */
3398 XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->buffer
= Qt
;
3399 XWINDOW (minibuf_window
)->buffer
= Qt
;
3401 /* Now set them up for real. */
3402 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame
),
3403 Fcurrent_buffer ());
3404 Fset_window_buffer (minibuf_window
, get_minibuffer (0));
3406 selected_window
= FRAME_ROOT_WINDOW (selected_frame
);
3407 /* Make sure this window seems more recently used than
3408 a newly-created, never-selected window. Increment
3409 window_select_count so the first selection ever will get
3410 something newer than this. */
3411 XSETFASTINT (XWINDOW (selected_window
)->use_time
, ++window_select_count
);
3412 #endif /* not MULTI_FRAME */
3417 Qwindowp
= intern ("windowp");
3418 staticpro (&Qwindowp
);
3420 Qwindow_live_p
= intern ("window-live-p");
3421 staticpro (&Qwindow_live_p
);
3423 Qtemp_buffer_show_hook
= intern ("temp-buffer-show-hook");
3424 staticpro (&Qtemp_buffer_show_hook
);
3427 /* Make sure all windows get marked */
3428 staticpro (&minibuf_window
);
3431 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
3432 "Non-nil means call as function to display a help buffer.\n\
3433 The function is called with one argument, the buffer to be displayed.\n\
3434 Used by `with-output-to-temp-buffer'.\n\
3435 If this function is used, then it must do the entire job of showing\n\
3436 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
3437 Vtemp_buffer_show_function
= Qnil
;
3439 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
3440 "If non-nil, function to call to handle `display-buffer'.\n\
3441 It will receive two args, the buffer and a flag which if non-nil means\n\
3442 that the currently selected window is not acceptable.\n\
3443 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
3444 work using this function.");
3445 Vdisplay_buffer_function
= Qnil
;
3447 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
3448 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
3449 Vminibuf_scroll_window
= Qnil
;
3451 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
3452 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
3453 Vother_window_scroll_buffer
= Qnil
;
3455 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames
,
3456 "*Non-nil means `display-buffer' should make a separate frame.");
3459 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function
,
3460 "Function to call to handle automatic new frame creation.\n\
3461 It is called with no arguments and should return a newly created frame.\n\
3463 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
3464 where `pop-up-frame-alist' would hold the default frame parameters.");
3465 Vpop_up_frame_function
= Qnil
;
3467 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names
,
3468 "*List of buffer names that should have their own special frames.\n\
3469 Displaying a buffer whose name is in this list makes a special frame for it\n\
3470 using `special-display-function'.\n\
3472 An element of the list can be a cons cell instead of just a string.\n\
3473 Then the car should be a buffer name, and the cdr specifies frame\n\
3474 parameters for creating the frame for that buffer.\n\
3475 More precisely, the cdr is passed as the second argument to\n\
3476 the function found in `special-display-function', when making that frame.\n\
3477 See also `special-display-regexps'.");
3478 Vspecial_display_buffer_names
= Qnil
;
3480 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps
,
3481 "*List of regexps saying which buffers should have their own special frames.\n\
3482 If a buffer name matches one of these regexps, it gets its own frame.\n\
3483 Displaying a buffer whose name is in this list makes a special frame for it\n\
3484 using `special-display-function'.\n\
3486 An element of the list can be a cons cell instead of just a string.\n\
3487 Then the car should be the regexp, and the cdr specifies frame\n\
3488 parameters for creating the frame for buffers that match.\n\
3489 More precisely, the cdr is passed as the second argument to\n\
3490 the function found in `special-display-function', when making that frame.\n\
3491 See also `special-display-buffer-names'.");
3492 Vspecial_display_regexps
= Qnil
;
3494 DEFVAR_LISP ("special-display-function", &Vspecial_display_function
,
3495 "Function to call to make a new frame for a special buffer.\n\
3496 It is called with two arguments, the buffer and optional buffer specific\n\
3497 data, and should return a window displaying that buffer.\n\
3498 The default value makes a separate frame for the buffer,\n\
3499 using `special-display-frame-alist' to specify the frame parameters.\n\
3501 A buffer is special if its is listed in `special-display-buffer-names'\n\
3502 or matches a regexp in `special-display-regexps'.");
3503 Vspecial_display_function
= Qnil
;
3505 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names
,
3506 "*List of buffer names that should appear in the selected window.\n\
3507 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
3508 switches to it in the selected window, rather than making it appear\n\
3509 in some other window.\n\
3511 An element of the list can be a cons cell instead of just a string.\n\
3512 Then the car must be a string, which specifies the buffer name.\n\
3513 This is for compatibility with `special-display-buffer-names';\n\
3514 the cdr of the cons cell is ignored.\n\
3516 See also `same-window-regexps'.");
3517 Vsame_window_buffer_names
= Qnil
;
3519 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps
,
3520 "*List of regexps saying which buffers should appear in the selected window.\n\
3521 If a buffer name matches one of these regexps, then displaying it\n\
3522 using `display-buffer' or `pop-to-buffer' switches to it\n\
3523 in the selected window, rather than making it appear in some other window.\n\
3525 An element of the list can be a cons cell instead of just a string.\n\
3526 Then the car must be a string, which specifies the buffer name.\n\
3527 This is for compatibility with `special-display-buffer-names';\n\
3528 the cdr of the cons cell is ignored.\n\
3530 See also `same-window-buffer-names'.");
3531 Vsame_window_regexps
= Qnil
;
3533 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
3534 "*Non-nil means display-buffer should make new windows.");
3537 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
3538 "*Number of lines of continuity when scrolling by screenfuls.");
3539 next_screen_context_lines
= 2;
3541 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
3542 "*display-buffer would prefer to split the largest window if this large.\n\
3543 If there is only one window, it is split regardless of this value.");
3544 split_height_threshold
= 500;
3546 DEFVAR_INT ("window-min-height", &window_min_height
,
3547 "*Delete any window less than this tall (including its mode line).");
3548 window_min_height
= 4;
3550 DEFVAR_INT ("window-min-width", &window_min_width
,
3551 "*Delete any window less than this wide.");
3552 window_min_width
= 10;
3554 defsubr (&Sselected_window
);
3555 defsubr (&Sminibuffer_window
);
3556 defsubr (&Swindow_minibuffer_p
);
3557 defsubr (&Swindowp
);
3558 defsubr (&Swindow_live_p
);
3559 defsubr (&Spos_visible_in_window_p
);
3560 defsubr (&Swindow_buffer
);
3561 defsubr (&Swindow_height
);
3562 defsubr (&Swindow_width
);
3563 defsubr (&Swindow_hscroll
);
3564 defsubr (&Sset_window_hscroll
);
3565 defsubr (&Swindow_redisplay_end_trigger
);
3566 defsubr (&Sset_window_redisplay_end_trigger
);
3567 defsubr (&Swindow_edges
);
3568 defsubr (&Scoordinates_in_window_p
);
3569 defsubr (&Swindow_at
);
3570 defsubr (&Swindow_point
);
3571 defsubr (&Swindow_start
);
3572 defsubr (&Swindow_end
);
3573 defsubr (&Sset_window_point
);
3574 defsubr (&Sset_window_start
);
3575 defsubr (&Swindow_dedicated_p
);
3576 defsubr (&Sset_window_dedicated_p
);
3577 defsubr (&Swindow_display_table
);
3578 defsubr (&Sset_window_display_table
);
3579 defsubr (&Snext_window
);
3580 defsubr (&Sprevious_window
);
3581 defsubr (&Sother_window
);
3582 defsubr (&Sget_lru_window
);
3583 defsubr (&Sget_largest_window
);
3584 defsubr (&Sget_buffer_window
);
3585 defsubr (&Sdelete_other_windows
);
3586 defsubr (&Sdelete_windows_on
);
3587 defsubr (&Sreplace_buffer_in_windows
);
3588 defsubr (&Sdelete_window
);
3589 defsubr (&Sset_window_buffer
);
3590 defsubr (&Sselect_window
);
3591 defsubr (&Sdisplay_buffer
);
3592 defsubr (&Ssplit_window
);
3593 defsubr (&Senlarge_window
);
3594 defsubr (&Sshrink_window
);
3595 defsubr (&Sscroll_up
);
3596 defsubr (&Sscroll_down
);
3597 defsubr (&Sscroll_left
);
3598 defsubr (&Sscroll_right
);
3599 defsubr (&Sother_window_for_scrolling
);
3600 defsubr (&Sscroll_other_window
);
3601 defsubr (&Srecenter
);
3602 defsubr (&Smove_to_window_line
);
3603 defsubr (&Swindow_configuration_p
);
3604 defsubr (&Sset_window_configuration
);
3605 defsubr (&Scurrent_window_configuration
);
3606 defsubr (&Ssave_window_excursion
);
3611 initial_define_key (control_x_map
, '1', "delete-other-windows");
3612 initial_define_key (control_x_map
, '2', "split-window");
3613 initial_define_key (control_x_map
, '0', "delete-window");
3614 initial_define_key (control_x_map
, 'o', "other-window");
3615 initial_define_key (control_x_map
, '^', "enlarge-window");
3616 initial_define_key (control_x_map
, '<', "scroll-left");
3617 initial_define_key (control_x_map
, '>', "scroll-right");
3619 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
3620 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
3621 initial_define_key (meta_map
, 'v', "scroll-down");
3623 initial_define_key (global_map
, Ctl('L'), "recenter");
3624 initial_define_key (meta_map
, 'r', "move-to-window-line");