1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 86, 87, 93, 94, 95, 96 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, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
33 Lisp_Object Qwindowp
, Qwindow_live_p
;
35 Lisp_Object
Fnext_window (), Fdelete_window (), Fselect_window ();
36 Lisp_Object
Fset_window_buffer (), Fsplit_window (), Frecenter ();
38 void delete_all_subwindows ();
39 static struct window
*decode_window();
41 /* This is the window in which the terminal's cursor should
42 be left when nothing is being done with it. This must
43 always be a leaf window, and its buffer is selected by
44 the top level editing loop at the end of each command.
46 This value is always the same as
47 FRAME_SELECTED_WINDOW (selected_frame). */
49 Lisp_Object selected_window
;
51 /* The minibuffer window of the selected frame.
52 Note that you cannot test for minibufferness of an arbitrary window
53 by comparing against this; but you can test for minibufferness of
54 the selected window. */
55 Lisp_Object minibuf_window
;
57 /* Non-nil means it is the window for C-M-v to scroll
58 when the minibuffer is selected. */
59 Lisp_Object Vminibuf_scroll_window
;
61 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
62 Lisp_Object Vother_window_scroll_buffer
;
64 /* Non-nil means it's function to call to display temp buffers. */
65 Lisp_Object Vtemp_buffer_show_function
;
67 /* If a window gets smaller than either of these, it is removed. */
68 int window_min_height
;
71 /* Nonzero implies Fdisplay_buffer should create windows. */
74 /* Nonzero implies make new frames for Fdisplay_buffer. */
77 /* Non-nil means use this function instead of default */
78 Lisp_Object Vpop_up_frame_function
;
80 /* Function to call to handle Fdisplay_buffer. */
81 Lisp_Object Vdisplay_buffer_function
;
83 /* List of buffer *names* for buffers that should have their own frames. */
84 Lisp_Object Vspecial_display_buffer_names
;
86 /* List of regexps for buffer names that should have their own frames. */
87 Lisp_Object Vspecial_display_regexps
;
89 /* Function to pop up a special frame. */
90 Lisp_Object Vspecial_display_function
;
92 /* List of buffer *names* for buffers to appear in selected window. */
93 Lisp_Object Vsame_window_buffer_names
;
95 /* List of regexps for buffer names to appear in selected window. */
96 Lisp_Object Vsame_window_regexps
;
98 /* Hook run at end of temp_output_buffer_show. */
99 Lisp_Object Qtemp_buffer_show_hook
;
101 /* Fdisplay_buffer always splits the largest window
102 if that window is more than this high. */
103 int split_height_threshold
;
105 /* Number of lines of continuity in scrolling by screenfuls. */
106 int next_screen_context_lines
;
108 /* Incremented for each window created. */
109 static int sequence_number
;
111 /* Nonzero after init_window_once has finished. */
112 static int window_initialized
;
114 #define min(a, b) ((a) < (b) ? (a) : (b))
116 extern Lisp_Object Qwindow_scroll_functions
, Vwindow_scroll_functions
;
118 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
119 "Returns t if OBJECT is a window.")
123 return WINDOWP (object
) ? Qt
: Qnil
;
126 DEFUN ("window-live-p", Fwindow_live_p
, Swindow_live_p
, 1, 1, 0,
127 "Returns t if OBJECT is a window which is currently visible.")
131 return (WINDOWP (object
) && ! NILP (XWINDOW (object
)->buffer
) ? Qt
: Qnil
);
138 register struct window
*p
;
139 register struct Lisp_Vector
*vec
;
142 vec
= allocate_vectorlike ((EMACS_INT
) VECSIZE (struct window
));
143 for (i
= 0; i
< VECSIZE (struct window
); i
++)
144 vec
->contents
[i
] = Qnil
;
145 vec
->size
= VECSIZE (struct window
);
146 p
= (struct window
*)vec
;
147 XSETFASTINT (p
->sequence_number
, ++sequence_number
);
148 XSETFASTINT (p
->left
, 0);
149 XSETFASTINT (p
->top
, 0);
150 XSETFASTINT (p
->height
, 0);
151 XSETFASTINT (p
->width
, 0);
152 XSETFASTINT (p
->hscroll
, 0);
153 XSETFASTINT (p
->last_point_x
, 0);
154 XSETFASTINT (p
->last_point_y
, 0);
155 p
->start
= Fmake_marker ();
156 p
->pointm
= Fmake_marker ();
157 XSETFASTINT (p
->use_time
, 0);
159 p
->display_table
= Qnil
;
165 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
166 "Return the window that the cursor now appears in and commands apply to.")
169 return selected_window
;
172 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 1, 0,
173 "Return the window used now for minibuffers.\n\
174 If the optional argument FRAME is specified, return the minibuffer window\n\
175 used by that frame.")
180 XSETFRAME (frame
, selected_frame
);
182 CHECK_LIVE_FRAME (frame
, 0);
184 return FRAME_MINIBUF_WINDOW (XFRAME (frame
));
187 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 0, 1, 0,
188 "Returns non-nil if WINDOW is a minibuffer window.")
192 struct window
*w
= decode_window (window
);
193 return (MINI_WINDOW_P (w
) ? Qt
: Qnil
);
196 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
197 Spos_visible_in_window_p
, 0, 2, 0,
198 "Return t if position POS is currently on the frame in WINDOW.\n\
199 Returns nil if that position is scrolled vertically out of view.\n\
200 POS defaults to point; WINDOW, to the selected window.")
202 Lisp_Object pos
, window
;
204 register struct window
*w
;
208 register struct buffer
*buf
;
209 struct position posval
;
216 CHECK_NUMBER_COERCE_MARKER (pos
, 0);
220 w
= decode_window (window
);
221 top
= marker_position (w
->start
);
222 hscroll
= XINT (w
->hscroll
);
227 height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
229 buf
= XBUFFER (w
->buffer
);
230 if (XFASTINT (w
->last_modified
) >= BUF_MODIFF (buf
)
231 && XFASTINT (w
->last_overlay_modified
) >= BUF_OVERLAY_MODIFF (buf
))
233 /* If frame is up to date,
234 use the info recorded about how much text fit on it. */
235 if (posint
< BUF_Z (buf
) - XFASTINT (w
->window_end_pos
)
236 || (XFASTINT (w
->window_end_vpos
) < height
))
242 if (posint
> BUF_ZV (buf
))
245 /* w->start can be out of range. If it is, do something reasonable. */
246 if (top
< BUF_BEGV (buf
) || top
> BUF_ZV (buf
))
249 /* If that info is not correct, calculate afresh */
250 posval
= *compute_motion (top
, 0, (hscroll
? 1 - hscroll
: 0), 0,
252 window_internal_width (w
) - 1,
255 return posval
.vpos
< height
? Qt
: Qnil
;
259 static struct window
*
260 decode_window (window
)
261 register Lisp_Object window
;
264 return XWINDOW (selected_window
);
266 CHECK_LIVE_WINDOW (window
, 0);
267 return XWINDOW (window
);
270 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
271 "Return the buffer that WINDOW is displaying.")
275 return decode_window (window
)->buffer
;
278 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
279 "Return the number of lines in WINDOW (including its mode line).")
283 return decode_window (window
)->height
;
286 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
287 "Return the number of display columns in WINDOW.\n\
288 This is the width that is usable columns available for text in WINDOW.\n\
289 If you want to find out how many columns WINDOW takes up,\n\
290 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
294 return make_number (window_internal_width (decode_window (window
)));
297 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
298 "Return the number of columns by which WINDOW is scrolled from left margin.")
302 return decode_window (window
)->hscroll
;
305 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
306 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
307 NCOL should be zero or positive.")
309 register Lisp_Object window
, ncol
;
311 register struct window
*w
;
313 CHECK_NUMBER (ncol
, 1);
314 if (XINT (ncol
) < 0) XSETFASTINT (ncol
, 0);
315 w
= decode_window (window
);
316 if (XINT (w
->hscroll
) != XINT (ncol
))
317 XBUFFER (w
->buffer
)->clip_changed
= 1; /* Prevent redisplay shortcuts */
322 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger
,
323 Swindow_redisplay_end_trigger
, 0, 1, 0,
324 "Return WINDOW's redisplay end trigger value.\n\
325 See `set-window-redisplay-end-trigger' for more information.")
329 return decode_window (window
)->redisplay_end_trigger
;
332 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger
,
333 Sset_window_redisplay_end_trigger
, 2, 2, 0,
334 "Set WINDOW's redisplay end trigger value to VALUE.\n\
335 VALUE should be a buffer position (typically a marker) or nil.\n\
336 If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
337 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
338 with two arguments: WINDOW, and the end trigger value.\n\
339 Afterwards the end-trigger value is reset to nil.")
341 register Lisp_Object window
, value
;
343 register struct window
*w
;
345 w
= decode_window (window
);
346 w
->redisplay_end_trigger
= value
;
350 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
351 "Return a list of the edge coordinates of WINDOW.\n\
352 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
353 RIGHT is one more than the rightmost column used by WINDOW,\n\
354 and BOTTOM is one more than the bottommost row used by WINDOW\n\
359 register struct window
*w
= decode_window (window
);
361 return Fcons (w
->left
, Fcons (w
->top
,
362 Fcons (make_number (XFASTINT (w
->left
) + XFASTINT (w
->width
)),
363 Fcons (make_number (XFASTINT (w
->top
)
364 + XFASTINT (w
->height
)),
368 /* Test if the character at column *x, row *y is within window *w.
369 If it is not, return 0;
370 if it is in the window's text area,
371 set *x and *y to its location relative to the upper left corner
374 if it is on the window's modeline, return 2;
375 if it is on the border between the window and its right sibling,
378 coordinates_in_window (w
, x
, y
)
379 register struct window
*w
;
382 register int left
= XINT (w
->left
);
383 register int width
= XINT (w
->width
);
384 register int window_height
= XINT (w
->height
);
385 register int top
= XFASTINT (w
->top
);
387 if ( *x
< left
|| *x
>= left
+ width
388 || *y
< top
|| *y
>= top
+ window_height
)
391 /* Is the character is the mode line? */
392 if (*y
== top
+ window_height
- 1
393 && ! MINI_WINDOW_P (w
))
396 /* Is the character in the right border? */
397 if (*x
== left
+ width
- 1
398 && left
+ width
!= FRAME_WIDTH (XFRAME (w
->frame
)))
406 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
407 Scoordinates_in_window_p
, 2, 2, 0,
408 "Return non-nil if COORDINATES are in WINDOW.\n\
409 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
410 measured in characters from the upper-left corner of the frame.\n\
411 (0 . 0) denotes the character in the upper left corner of the\n\
413 If COORDINATES are in the text portion of WINDOW,\n\
414 the coordinates relative to the window are returned.\n\
415 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
416 If they are on the border between WINDOW and its right sibling,\n\
417 `vertical-line' is returned.")
418 (coordinates
, window
)
419 register Lisp_Object coordinates
, window
;
423 CHECK_LIVE_WINDOW (window
, 0);
424 CHECK_CONS (coordinates
, 1);
425 x
= XINT (Fcar (coordinates
));
426 y
= XINT (Fcdr (coordinates
));
428 switch (coordinates_in_window (XWINDOW (window
), &x
, &y
))
430 case 0: /* NOT in window at all. */
433 case 1: /* In text part of window. */
436 case 2: /* In mode line of window. */
439 case 3: /* On right border of window. */
440 return Qvertical_line
;
447 /* Find the window containing column x, row y, and return it as a
448 Lisp_Object. If x, y is on the window's modeline, set *part
449 to 1; if it is on the separating line between the window and its
450 right sibling, set it to 2; otherwise set it to 0. If there is no
451 window under x, y return nil and leave *part unmodified. */
453 window_from_coordinates (frame
, x
, y
, part
)
458 register Lisp_Object tem
, first
;
460 tem
= first
= FRAME_SELECTED_WINDOW (frame
);
464 int found
= coordinates_in_window (XWINDOW (tem
), &x
, &y
);
472 tem
= Fnext_window (tem
, Qt
, Qlambda
);
474 while (! EQ (tem
, first
));
479 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
480 "Return window containing coordinates X and Y on FRAME.\n\
481 If omitted, FRAME defaults to the currently selected frame.\n\
482 The top left corner of the frame is considered to be row 0,\n\
485 Lisp_Object x
, y
, frame
;
490 XSETFRAME (frame
, selected_frame
);
492 CHECK_LIVE_FRAME (frame
, 2);
496 return window_from_coordinates (XFRAME (frame
),
501 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
502 "Return current value of point in WINDOW.\n\
503 For a nonselected window, this is the value point would have\n\
504 if that window were selected.\n\
506 Note that, when WINDOW is the selected window and its buffer\n\
507 is also currently selected, the value returned is the same as (point).\n\
508 It would be more strictly correct to return the `top-level' value\n\
509 of point, outside of any save-excursion forms.\n\
510 But that is hard to define.")
514 register struct window
*w
= decode_window (window
);
516 if (w
== XWINDOW (selected_window
)
517 && current_buffer
== XBUFFER (w
->buffer
))
519 return Fmarker_position (w
->pointm
);
522 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
523 "Return position at which display currently starts in WINDOW.\n\
524 This is updated by redisplay or by calling `set-window-start'.")
528 return Fmarker_position (decode_window (window
)->start
);
531 /* This is text temporarily removed from the doc string below.
533 This function returns nil if the position is not currently known.\n\
534 That happens when redisplay is preempted and doesn't finish.\n\
535 If in that case you want to compute where the end of the window would\n\
536 have been if redisplay had finished, do this:\n\
538 (goto-char (window-start window))\n\
539 (vertical-motion (1- (window-height window)) window)\n\
542 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 1, 0,
543 "Return position at which display currently ends in WINDOW.\n\
544 This is updated by redisplay, when it runs to completion.\n\
545 Simply changing the buffer text or setting `window-start'\n\
546 does not update this value.")
551 struct window
*w
= decode_window (window
);
555 CHECK_BUFFER (buf
, 0);
557 #if 0 /* This change broke some things. We should make it later. */
558 /* If we don't know the end position, return nil.
559 The user can compute it with vertical-motion if he wants to.
560 It would be nicer to do it automatically,
561 but that's so slow that it would probably bother people. */
562 if (NILP (w
->window_end_valid
))
567 BUF_Z (XBUFFER (buf
)) - XFASTINT (w
->window_end_pos
));
572 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
573 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
575 Lisp_Object window
, pos
;
577 register struct window
*w
= decode_window (window
);
579 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
580 if (w
== XWINDOW (selected_window
))
583 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
588 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
589 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
590 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
591 from overriding motion of point in order to display at this exact start.")
592 (window
, pos
, noforce
)
593 Lisp_Object window
, pos
, noforce
;
595 register struct window
*w
= decode_window (window
);
597 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
598 set_marker_restricted (w
->start
, pos
, w
->buffer
);
599 /* this is not right, but much easier than doing what is right. */
600 w
->start_at_line_beg
= Qnil
;
603 w
->update_mode_line
= Qt
;
604 XSETFASTINT (w
->last_modified
, 0);
605 XSETFASTINT (w
->last_overlay_modified
, 0);
606 if (!EQ (window
, selected_window
))
607 windows_or_buffers_changed
++;
611 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
613 "Return WINDOW's dedicated object, usually t or nil.\n\
614 See also `set-window-dedicated-p'.")
618 return decode_window (window
)->dedicated
;
621 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
622 Sset_window_dedicated_p
, 2, 2, 0,
623 "Control whether WINDOW is dedicated to the buffer it displays.\n\
624 If it is dedicated, Emacs will not automatically change\n\
625 which buffer appears in it.\n\
626 The second argument is the new value for the dedication flag;\n\
629 Lisp_Object window
, arg
;
631 register struct window
*w
= decode_window (window
);
641 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
643 "Return the display-table that WINDOW is using.")
647 return decode_window (window
)->display_table
;
650 /* Get the display table for use currently on window W.
651 This is either W's display table or W's buffer's display table.
652 Ignore the specified tables if they are not valid;
653 if no valid table is specified, return 0. */
655 struct Lisp_Char_Table
*
656 window_display_table (w
)
660 tem
= w
->display_table
;
661 if (DISP_TABLE_P (tem
))
662 return XCHAR_TABLE (tem
);
663 tem
= XBUFFER (w
->buffer
)->display_table
;
664 if (DISP_TABLE_P (tem
))
665 return XCHAR_TABLE (tem
);
666 tem
= Vstandard_display_table
;
667 if (DISP_TABLE_P (tem
))
668 return XCHAR_TABLE (tem
);
672 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
673 "Set WINDOW's display-table to TABLE.")
675 register Lisp_Object window
, table
;
677 register struct window
*w
;
678 register Lisp_Object z
; /* Return value. */
680 w
= decode_window (window
);
681 w
->display_table
= table
;
685 /* Record info on buffer window w is displaying
686 when it is about to cease to display that buffer. */
689 register struct window
*w
;
694 if (XBUFFER (buf
) != XMARKER (w
->pointm
)->buffer
)
697 if (w
== XWINDOW (XBUFFER (buf
)->last_selected_window
))
698 XBUFFER (buf
)->last_selected_window
= Qnil
;
701 if (w
== XWINDOW (selected_window
)
702 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
703 /* Do this except when the selected window's buffer
704 is being removed from some other window. */
706 /* last_window_start records the start position that this buffer
707 had in the last window to be disconnected from it.
708 Now that this statement is unconditional,
709 it is possible for the buffer to be displayed in the
710 selected window, while last_window_start reflects another
711 window which was recently showing the same buffer.
712 Some people might say that might be a good thing. Let's see. */
713 XBUFFER (buf
)->last_window_start
= marker_position (w
->start
);
715 /* Point in the selected window's buffer
716 is actually stored in that buffer, and the window's pointm isn't used.
717 So don't clobber point in that buffer. */
718 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
))
719 BUF_PT (XBUFFER (buf
))
720 = clip_to_bounds (BUF_BEGV (XBUFFER (buf
)),
721 marker_position (w
->pointm
),
722 BUF_ZV (XBUFFER (buf
)));
725 /* Put replacement into the window structure in place of old. */
727 replace_window (old
, replacement
)
728 Lisp_Object old
, replacement
;
730 register Lisp_Object tem
;
731 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
733 /* If OLD is its frame's root_window, then replacement is the new
734 root_window for that frame. */
736 if (EQ (old
, FRAME_ROOT_WINDOW (XFRAME (o
->frame
))))
737 FRAME_ROOT_WINDOW (XFRAME (o
->frame
)) = replacement
;
742 p
->height
= o
->height
;
744 p
->next
= tem
= o
->next
;
746 XWINDOW (tem
)->prev
= replacement
;
748 p
->prev
= tem
= o
->prev
;
750 XWINDOW (tem
)->next
= replacement
;
752 p
->parent
= tem
= o
->parent
;
755 if (EQ (XWINDOW (tem
)->vchild
, old
))
756 XWINDOW (tem
)->vchild
= replacement
;
757 if (EQ (XWINDOW (tem
)->hchild
, old
))
758 XWINDOW (tem
)->hchild
= replacement
;
761 /*** Here, if replacement is a vertical combination
762 and so is its new parent, we should make replacement's
763 children be children of that parent instead. ***/
766 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
767 "Remove WINDOW from the display. Default is selected window.")
769 register Lisp_Object window
;
771 register Lisp_Object tem
, parent
, sib
;
772 register struct window
*p
;
773 register struct window
*par
;
775 /* Because this function is called by other C code on non-leaf
776 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
777 so we can't decode_window here. */
779 window
= selected_window
;
781 CHECK_WINDOW (window
, 0);
782 p
= XWINDOW (window
);
784 /* It's okay to delete an already-deleted window. */
792 error ("Attempt to delete minibuffer or sole ordinary window");
793 par
= XWINDOW (parent
);
795 windows_or_buffers_changed
++;
796 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (p
))) = 1;
798 /* Are we trying to delete any frame's selected window? */
800 Lisp_Object frame
, pwindow
;
802 /* See if the frame's selected window is either WINDOW
803 or any subwindow of it, by finding all that window's parents
804 and comparing each one with WINDOW. */
805 frame
= WINDOW_FRAME (XWINDOW (window
));
806 pwindow
= FRAME_SELECTED_WINDOW (XFRAME (frame
));
808 while (!NILP (pwindow
))
810 if (EQ (window
, pwindow
))
812 pwindow
= XWINDOW (pwindow
)->parent
;
815 if (EQ (window
, pwindow
))
817 Lisp_Object alternative
;
818 alternative
= Fnext_window (window
, Qlambda
, Qnil
);
820 /* If we're about to delete the selected window on the
821 selected frame, then we should use Fselect_window to select
822 the new window. On the other hand, if we're about to
823 delete the selected window on any other frame, we shouldn't do
824 anything but set the frame's selected_window slot. */
825 if (EQ (window
, selected_window
))
826 Fselect_window (alternative
);
828 FRAME_SELECTED_WINDOW (XFRAME (frame
)) = alternative
;
833 /* tem is null for dummy parent windows
834 (which have inferiors but not any contents themselves) */
838 unchain_marker (p
->pointm
);
839 unchain_marker (p
->start
);
844 XWINDOW (tem
)->prev
= p
->prev
;
848 XWINDOW (tem
)->next
= p
->next
;
850 if (EQ (window
, par
->hchild
))
851 par
->hchild
= p
->next
;
852 if (EQ (window
, par
->vchild
))
853 par
->vchild
= p
->next
;
855 /* Find one of our siblings to give our space to. */
859 /* If p gives its space to its next sibling, that sibling needs
860 to have its top/left side pulled back to where p's is.
861 set_window_{height,width} will re-position the sibling's
864 XWINDOW (sib
)->top
= p
->top
;
865 XWINDOW (sib
)->left
= p
->left
;
868 /* Stretch that sibling. */
869 if (!NILP (par
->vchild
))
870 set_window_height (sib
,
871 XFASTINT (XWINDOW (sib
)->height
) + XFASTINT (p
->height
),
873 if (!NILP (par
->hchild
))
874 set_window_width (sib
,
875 XFASTINT (XWINDOW (sib
)->width
) + XFASTINT (p
->width
),
878 /* If parent now has only one child,
879 put the child into the parent's place. */
883 if (NILP (XWINDOW (tem
)->next
))
884 replace_window (parent
, tem
);
886 /* Since we may be deleting combination windows, we must make sure that
887 not only p but all its children have been marked as deleted. */
888 if (! NILP (p
->hchild
))
889 delete_all_subwindows (XWINDOW (p
->hchild
));
890 else if (! NILP (p
->vchild
))
891 delete_all_subwindows (XWINDOW (p
->vchild
));
893 /* Mark this window as deleted. */
894 p
->buffer
= p
->hchild
= p
->vchild
= Qnil
;
900 extern Lisp_Object
next_frame (), prev_frame ();
902 /* This comment supplies the doc string for `next-window',
903 for make-docfile to see. We cannot put this in the real DEFUN
904 due to limits in the Unix cpp.
906 DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
907 "Return next window after WINDOW in canonical ordering of windows.\n\
908 If omitted, WINDOW defaults to the selected window.\n\
910 Optional second arg MINIBUF t means count the minibuffer window even\n\
911 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
912 it is active. MINIBUF neither t nor nil means not to count the\n\
913 minibuffer even if it is active.\n\
915 Several frames may share a single minibuffer; if the minibuffer\n\
916 counts, all windows on all frames that share that minibuffer count\n\
917 too. Therefore, `next-window' can be used to iterate through the\n\
918 set of windows even when the minibuffer is on another frame. If the\n\
919 minibuffer does not count, only windows from WINDOW's frame count.\n\
921 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
922 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
923 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
924 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
925 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
926 Anything else means restrict to WINDOW's frame.\n\
928 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
929 `next-window' to iterate through the entire cycle of acceptable\n\
930 windows, eventually ending up back at the window you started with.\n\
931 `previous-window' traverses the same cycle, in the reverse order.")
932 (window, minibuf, all_frames) */
934 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
936 (window
, minibuf
, all_frames
)
937 register Lisp_Object window
, minibuf
, all_frames
;
939 register Lisp_Object tem
;
940 Lisp_Object start_window
;
943 window
= selected_window
;
945 CHECK_LIVE_WINDOW (window
, 0);
947 start_window
= window
;
949 /* minibuf == nil may or may not include minibuffers.
950 Decide if it does. */
952 minibuf
= (minibuf_level
? minibuf_window
: Qlambda
);
953 else if (! EQ (minibuf
, Qt
))
955 /* Now minibuf can be t => count all minibuffer windows,
956 lambda => count none of them,
957 or a specific minibuffer window (the active one) to count. */
959 /* all_frames == nil doesn't specify which frames to include. */
960 if (NILP (all_frames
))
961 all_frames
= (! EQ (minibuf
, Qlambda
)
962 ? (FRAME_MINIBUF_WINDOW
965 (XWINDOW (window
)))))
967 else if (EQ (all_frames
, Qvisible
))
969 else if (XFASTINT (all_frames
) == 0)
971 else if (FRAMEP (all_frames
) && ! EQ (all_frames
, Fwindow_frame (window
)))
972 /* If all_frames is a frame and window arg isn't on that frame, just
973 return the first window on the frame. */
974 return Fframe_first_window (all_frames
);
975 else if (! EQ (all_frames
, Qt
))
977 /* Now all_frames is t meaning search all frames,
978 nil meaning search just current frame,
979 visible meaning search just visible frames,
980 0 meaning search visible and iconified frames,
981 or a window, meaning search the frame that window belongs to. */
983 /* Do this loop at least once, to get the next window, and perhaps
984 again, if we hit the minibuffer and that is not acceptable. */
987 /* Find a window that actually has a next one. This loop
988 climbs up the tree. */
989 while (tem
= XWINDOW (window
)->next
, NILP (tem
))
990 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
994 /* We've reached the end of this frame.
995 Which other frames are acceptable? */
996 tem
= WINDOW_FRAME (XWINDOW (window
));
997 if (! NILP (all_frames
))
1002 tem
= next_frame (tem
, all_frames
);
1003 /* In the case where the minibuffer is active,
1004 and we include its frame as well as the selected one,
1005 next_frame may get stuck in that frame.
1006 If that happens, go back to the selected frame
1007 so we can complete the cycle. */
1009 XSETFRAME (tem
, selected_frame
);
1011 tem
= FRAME_ROOT_WINDOW (XFRAME (tem
));
1018 /* If we're in a combination window, find its first child and
1019 recurse on that. Otherwise, we've found the window we want. */
1022 if (!NILP (XWINDOW (window
)->hchild
))
1023 window
= XWINDOW (window
)->hchild
;
1024 else if (!NILP (XWINDOW (window
)->vchild
))
1025 window
= XWINDOW (window
)->vchild
;
1029 /* Which windows are acceptable?
1030 Exit the loop and accept this window if
1031 this isn't a minibuffer window,
1032 or we're accepting all minibuffer windows,
1033 or this is the active minibuffer and we are accepting that one, or
1034 we've come all the way around and we're back at the original window. */
1035 while (MINI_WINDOW_P (XWINDOW (window
))
1036 && ! EQ (minibuf
, Qt
)
1037 && ! EQ (minibuf
, window
)
1038 && ! EQ (window
, start_window
));
1043 /* This comment supplies the doc string for `previous-window',
1044 for make-docfile to see. We cannot put this in the real DEFUN
1045 due to limits in the Unix cpp.
1047 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
1048 "Return the window preceding WINDOW in canonical ordering of windows.\n\
1049 If omitted, WINDOW defaults to the selected window.\n\
1051 Optional second arg MINIBUF t means count the minibuffer window even\n\
1052 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1053 it is active. MINIBUF neither t nor nil means not to count the\n\
1054 minibuffer even if it is active.\n\
1056 Several frames may share a single minibuffer; if the minibuffer\n\
1057 counts, all windows on all frames that share that minibuffer count\n\
1058 too. Therefore, `previous-window' can be used to iterate through\n\
1059 the set of windows even when the minibuffer is on another frame. If\n\
1060 the minibuffer does not count, only windows from WINDOW's frame count\n\
1062 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1063 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1064 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1065 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1066 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1067 Anything else means restrict to WINDOW's frame.\n\
1069 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1070 `previous-window' to iterate through the entire cycle of acceptable\n\
1071 windows, eventually ending up back at the window you started with.\n\
1072 `next-window' traverses the same cycle, in the reverse order.")
1073 (window, minibuf, all_frames) */
1076 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
1078 (window
, minibuf
, all_frames
)
1079 register Lisp_Object window
, minibuf
, all_frames
;
1081 register Lisp_Object tem
;
1082 Lisp_Object start_window
;
1085 window
= selected_window
;
1087 CHECK_LIVE_WINDOW (window
, 0);
1089 start_window
= window
;
1091 /* minibuf == nil may or may not include minibuffers.
1092 Decide if it does. */
1094 minibuf
= (minibuf_level
? minibuf_window
: Qlambda
);
1095 else if (! EQ (minibuf
, Qt
))
1097 /* Now minibuf can be t => count all minibuffer windows,
1098 lambda => count none of them,
1099 or a specific minibuffer window (the active one) to count. */
1101 /* all_frames == nil doesn't specify which frames to include.
1102 Decide which frames it includes. */
1103 if (NILP (all_frames
))
1104 all_frames
= (! EQ (minibuf
, Qlambda
)
1105 ? (FRAME_MINIBUF_WINDOW
1108 (XWINDOW (window
)))))
1110 else if (EQ (all_frames
, Qvisible
))
1112 else if (XFASTINT (all_frames
) == 0)
1114 else if (FRAMEP (all_frames
) && ! EQ (all_frames
, Fwindow_frame (window
)))
1115 /* If all_frames is a frame and window arg isn't on that frame, just
1116 return the first window on the frame. */
1117 return Fframe_first_window (all_frames
);
1118 else if (! EQ (all_frames
, Qt
))
1120 /* Now all_frames is t meaning search all frames,
1121 nil meaning search just current frame,
1122 visible meaning search just visible frames,
1123 0 meaning search visible and iconified frames,
1124 or a window, meaning search the frame that window belongs to. */
1126 /* Do this loop at least once, to get the previous window, and perhaps
1127 again, if we hit the minibuffer and that is not acceptable. */
1130 /* Find a window that actually has a previous one. This loop
1131 climbs up the tree. */
1132 while (tem
= XWINDOW (window
)->prev
, NILP (tem
))
1133 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
1137 /* We have found the top window on the frame.
1138 Which frames are acceptable? */
1139 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
);
1163 /* If this frame has a minibuffer, find that window first,
1164 because it is conceptually the last window in that frame. */
1165 if (FRAME_HAS_MINIBUF_P (XFRAME (tem
)))
1166 tem
= FRAME_MINIBUF_WINDOW (XFRAME (tem
));
1168 tem
= FRAME_ROOT_WINDOW (XFRAME (tem
));
1174 /* If we're in a combination window, find its last child and
1175 recurse on that. Otherwise, we've found the window we want. */
1178 if (!NILP (XWINDOW (window
)->hchild
))
1179 window
= XWINDOW (window
)->hchild
;
1180 else if (!NILP (XWINDOW (window
)->vchild
))
1181 window
= XWINDOW (window
)->vchild
;
1183 while (tem
= XWINDOW (window
)->next
, !NILP (tem
))
1187 /* Which windows are acceptable?
1188 Exit the loop and accept this window if
1189 this isn't a minibuffer window,
1190 or we're accepting all minibuffer windows,
1191 or this is the active minibuffer and we are accepting that one, or
1192 we've come all the way around and we're back at the original window. */
1193 while (MINI_WINDOW_P (XWINDOW (window
))
1194 && ! EQ (minibuf
, Qt
)
1195 && ! EQ (minibuf
, window
)
1196 && ! EQ (window
, start_window
));
1201 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
1202 "Select the ARG'th different window on this frame.\n\
1203 All windows on current frame are arranged in a cyclic order.\n\
1204 This command selects the window ARG steps away in that order.\n\
1205 A negative ARG moves in the opposite order. If the optional second\n\
1206 argument ALL_FRAMES is non-nil, cycle through all frames.")
1208 register Lisp_Object arg
, all_frames
;
1211 register Lisp_Object w
;
1213 CHECK_NUMBER (arg
, 0);
1214 w
= selected_window
;
1219 w
= Fnext_window (w
, Qnil
, all_frames
);
1224 w
= Fprevious_window (w
, Qnil
, all_frames
);
1231 /* Look at all windows, performing an operation specified by TYPE
1233 If FRAMES is Qt, look at all frames;
1234 Qnil, look at just the selected frame;
1235 Qvisible, look at visible frames;
1236 a frame, just look at windows on that frame.
1237 If MINI is non-zero, perform the operation on minibuffer windows too.
1243 GET_BUFFER_WINDOW
, /* Arg is buffer */
1244 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
1245 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
1246 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
1248 UNSHOW_BUFFER
/* Arg is buffer */
1252 window_loop (type
, obj
, mini
, frames
)
1253 enum window_loop type
;
1254 register Lisp_Object obj
, frames
;
1257 register Lisp_Object w
;
1258 register Lisp_Object best_window
;
1259 register Lisp_Object next_window
;
1260 register Lisp_Object last_window
;
1262 Lisp_Object frame_arg
;
1265 /* If we're only looping through windows on a particular frame,
1266 frame points to that frame. If we're looping through windows
1267 on all frames, frame is 0. */
1268 if (FRAMEP (frames
))
1269 frame
= XFRAME (frames
);
1270 else if (NILP (frames
))
1271 frame
= selected_frame
;
1275 frame_arg
= Qlambda
;
1276 else if (XFASTINT (frames
) == 0)
1278 else if (EQ (frames
, Qvisible
))
1281 /* frame_arg is Qlambda to stick to one frame,
1282 Qvisible to consider all visible frames,
1285 /* Pick a window to start with. */
1289 w
= FRAME_SELECTED_WINDOW (frame
);
1291 w
= FRAME_SELECTED_WINDOW (selected_frame
);
1293 /* Figure out the last window we're going to mess with. Since
1294 Fnext_window, given the same options, is guaranteed to go in a
1295 ring, we can just use Fprevious_window to find the last one.
1297 We can't just wait until we hit the first window again, because
1298 it might be deleted. */
1300 last_window
= Fprevious_window (w
, mini
? Qt
: Qnil
, frame_arg
);
1305 FRAME_PTR w_frame
= XFRAME (WINDOW_FRAME (XWINDOW (w
)));
1307 /* Pick the next window now, since some operations will delete
1308 the current window. */
1309 next_window
= Fnext_window (w
, mini
? Qt
: Qnil
, frame_arg
);
1311 /* Note that we do not pay attention here to whether
1312 the frame is visible, since Fnext_window skips non-visible frames
1313 if that is desired, under the control of frame_arg. */
1314 if (! MINI_WINDOW_P (XWINDOW (w
))
1315 || (mini
&& minibuf_level
> 0))
1318 case GET_BUFFER_WINDOW
:
1319 if (XBUFFER (XWINDOW (w
)->buffer
) == XBUFFER (obj
))
1323 case GET_LRU_WINDOW
:
1324 /* t as arg means consider only full-width windows */
1325 if (!NILP (obj
) && XFASTINT (XWINDOW (w
)->width
)
1326 != FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (w
)))))
1328 /* Ignore dedicated windows and minibuffers. */
1329 if (MINI_WINDOW_P (XWINDOW (w
))
1330 || !NILP (XWINDOW (w
)->dedicated
))
1332 if (NILP (best_window
)
1333 || (XFASTINT (XWINDOW (best_window
)->use_time
)
1334 > XFASTINT (XWINDOW (w
)->use_time
)))
1338 case DELETE_OTHER_WINDOWS
:
1339 if (XWINDOW (w
) != XWINDOW (obj
))
1343 case DELETE_BUFFER_WINDOWS
:
1344 if (EQ (XWINDOW (w
)->buffer
, obj
))
1346 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (w
)));
1348 /* If this window is dedicated, and in a frame of its own,
1350 if (EQ (w
, FRAME_ROOT_WINDOW (f
))
1351 && !NILP (XWINDOW (w
)->dedicated
)
1352 && other_visible_frames (f
))
1354 /* Skip the other windows on this frame.
1355 There might be one, the minibuffer! */
1356 if (! EQ (w
, last_window
))
1357 while (f
== XFRAME (WINDOW_FRAME (XWINDOW (next_window
))))
1359 /* As we go, check for the end of the loop.
1360 We mustn't start going around a second time. */
1361 if (EQ (next_window
, last_window
))
1366 next_window
= Fnext_window (next_window
,
1370 /* Now we can safely delete the frame. */
1371 Fdelete_frame (WINDOW_FRAME (XWINDOW (w
)), Qnil
);
1374 /* If we're deleting the buffer displayed in the only window
1375 on the frame, find a new buffer to display there. */
1376 if (NILP (XWINDOW (w
)->parent
))
1378 Lisp_Object new_buffer
;
1379 new_buffer
= Fother_buffer (obj
, Qnil
);
1380 if (NILP (new_buffer
))
1382 = Fget_buffer_create (build_string ("*scratch*"));
1383 Fset_window_buffer (w
, new_buffer
);
1384 if (EQ (w
, selected_window
))
1385 Fset_buffer (XWINDOW (w
)->buffer
);
1392 case GET_LARGEST_WINDOW
:
1393 /* Ignore dedicated windows and minibuffers. */
1394 if (MINI_WINDOW_P (XWINDOW (w
))
1395 || !NILP (XWINDOW (w
)->dedicated
))
1398 struct window
*best_window_ptr
= XWINDOW (best_window
);
1399 struct window
*w_ptr
= XWINDOW (w
);
1400 if (NILP (best_window
)
1401 || (XFASTINT (w_ptr
->height
) * XFASTINT (w_ptr
->width
)
1402 > (XFASTINT (best_window_ptr
->height
)
1403 * XFASTINT (best_window_ptr
->width
))))
1409 if (EQ (XWINDOW (w
)->buffer
, obj
))
1411 /* Find another buffer to show in this window. */
1412 Lisp_Object another_buffer
;
1413 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (w
)));
1414 another_buffer
= Fother_buffer (obj
, Qnil
);
1415 if (NILP (another_buffer
))
1417 = Fget_buffer_create (build_string ("*scratch*"));
1418 /* If this window is dedicated, and in a frame of its own,
1420 if (EQ (w
, FRAME_ROOT_WINDOW (f
))
1421 && !NILP (XWINDOW (w
)->dedicated
)
1422 && other_visible_frames (f
))
1424 /* Skip the other windows on this frame.
1425 There might be one, the minibuffer! */
1426 if (! EQ (w
, last_window
))
1427 while (f
== XFRAME (WINDOW_FRAME (XWINDOW (next_window
))))
1429 /* As we go, check for the end of the loop.
1430 We mustn't start going around a second time. */
1431 if (EQ (next_window
, last_window
))
1436 next_window
= Fnext_window (next_window
,
1440 /* Now we can safely delete the frame. */
1441 Fdelete_frame (WINDOW_FRAME (XWINDOW (w
)), Qnil
);
1445 /* Otherwise show a different buffer in the window. */
1446 XWINDOW (w
)->dedicated
= Qnil
;
1447 Fset_window_buffer (w
, another_buffer
);
1448 if (EQ (w
, selected_window
))
1449 Fset_buffer (XWINDOW (w
)->buffer
);
1455 if (EQ (w
, last_window
))
1464 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 1, 0,
1465 "Return the window least recently selected or used for display.\n\
1466 If optional argument FRAME is `visible', search all visible frames.\n\
1467 If FRAME is 0, search all visible and iconified frames.\n\
1468 If FRAME is t, search all frames.\n\
1469 If FRAME is nil, search only the selected frame.\n\
1470 If FRAME is a frame, search only that frame.")
1474 register Lisp_Object w
;
1475 /* First try for a window that is full-width */
1476 w
= window_loop (GET_LRU_WINDOW
, Qt
, 0, frame
);
1477 if (!NILP (w
) && !EQ (w
, selected_window
))
1479 /* If none of them, try the rest */
1480 return window_loop (GET_LRU_WINDOW
, Qnil
, 0, frame
);
1483 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 1, 0,
1484 "Return the largest window in area.\n\
1485 If optional argument FRAME is `visible', search all visible frames.\n\
1486 If FRAME is 0, search all visible and iconified frames.\n\
1487 If FRAME is t, search all frames.\n\
1488 If FRAME is nil, search only the selected frame.\n\
1489 If FRAME is a frame, search only that frame.")
1493 return window_loop (GET_LARGEST_WINDOW
, Qnil
, 0,
1497 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 1, 2, 0,
1498 "Return a window currently displaying BUFFER, or nil if none.\n\
1499 If optional argument FRAME is `visible', search all visible frames.\n\
1500 If optional argument FRAME is 0, search all visible and iconified frames.\n\
1501 If FRAME is t, search all frames.\n\
1502 If FRAME is nil, search only the selected frame.\n\
1503 If FRAME is a frame, search only that frame.")
1505 Lisp_Object buffer
, frame
;
1507 buffer
= Fget_buffer (buffer
);
1508 if (BUFFERP (buffer
))
1509 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
1514 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
1516 "Make WINDOW (or the selected window) fill its frame.\n\
1517 Only the frame WINDOW is on is affected.\n\
1518 This function tries to reduce display jumps\n\
1519 by keeping the text previously visible in WINDOW\n\
1520 in the same place on the frame. Doing this depends on\n\
1521 the value of (window-start WINDOW), so if calling this function\n\
1522 in a program gives strange scrolling, make sure the window-start\n\
1523 value is reasonable when this function is called.")
1532 window
= selected_window
;
1534 CHECK_LIVE_WINDOW (window
, 0);
1536 w
= XWINDOW (window
);
1538 startpos
= marker_position (w
->start
);
1539 top
= XFASTINT (w
->top
) - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w
)));
1541 if (MINI_WINDOW_P (w
) && top
> 0)
1542 error ("Can't expand minibuffer to full frame");
1544 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_FRAME (w
));
1546 /* Try to minimize scrolling, by setting the window start to the point
1547 will cause the text at the old window start to be at the same place
1548 on the frame. But don't try to do this if the window start is
1549 outside the visible portion (as might happen when the display is
1550 not current, due to typeahead). */
1551 if (startpos
>= BUF_BEGV (XBUFFER (w
->buffer
))
1552 && startpos
<= BUF_ZV (XBUFFER (w
->buffer
)))
1554 struct position pos
;
1555 struct buffer
*obuf
= current_buffer
;
1557 Fset_buffer (w
->buffer
);
1558 /* This computation used to temporarily move point, but that can
1559 have unwanted side effects due to text properties. */
1560 pos
= *vmotion (startpos
, -top
, w
);
1561 Fset_marker (w
->start
, make_number (pos
.bufpos
), w
->buffer
);
1562 w
->start_at_line_beg
= ((pos
.bufpos
== BEGV
1563 || FETCH_CHAR (pos
.bufpos
- 1) == '\n') ? Qt
1565 /* We need to do this, so that the window-scroll-functions
1567 w
->force_start
= Qt
;
1569 set_buffer_internal (obuf
);
1574 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
1575 1, 2, "bDelete windows on (buffer): ",
1576 "Delete all windows showing BUFFER.\n\
1577 Optional second argument FRAME controls which frames are affected.\n\
1578 If nil or omitted, delete all windows showing BUFFER in any frame.\n\
1579 If t, delete only windows showing BUFFER in the selected frame.\n\
1580 If `visible', delete all windows showing BUFFER in any visible frame.\n\
1581 If a frame, delete only windows showing BUFFER in that frame.")
1583 Lisp_Object buffer
, frame
;
1585 /* FRAME uses t and nil to mean the opposite of what window_loop
1587 if (! FRAMEP (frame
))
1588 frame
= NILP (frame
) ? Qt
: Qnil
;
1592 buffer
= Fget_buffer (buffer
);
1593 CHECK_BUFFER (buffer
, 0);
1594 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, frame
);
1599 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
1600 Sreplace_buffer_in_windows
,
1601 1, 1, "bReplace buffer in windows: ",
1602 "Replace BUFFER with some other buffer in all windows showing it.")
1608 buffer
= Fget_buffer (buffer
);
1609 CHECK_BUFFER (buffer
, 0);
1610 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
1615 /* Replace BUFFER with some other buffer in all windows
1616 of all frames, even those on other keyboards. */
1619 replace_buffer_in_all_windows (buffer
)
1623 Lisp_Object tail
, frame
;
1625 /* A single call to window_loop won't do the job
1626 because it only considers frames on the current keyboard.
1627 So loop manually over frames, and handle each one. */
1628 FOR_EACH_FRAME (tail
, frame
)
1629 window_loop (UNSHOW_BUFFER
, buffer
, 0, frame
);
1631 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
1635 /* Set the height of WINDOW and all its inferiors. */
1637 /* The smallest acceptable dimensions for a window. Anything smaller
1638 might crash Emacs. */
1639 #define MIN_SAFE_WINDOW_WIDTH (2)
1640 #define MIN_SAFE_WINDOW_HEIGHT (2)
1642 /* Make sure that window_min_height and window_min_width are
1643 not too small; if they are, set them to safe minima. */
1646 check_min_window_sizes ()
1648 /* Smaller values might permit a crash. */
1649 if (window_min_width
< MIN_SAFE_WINDOW_WIDTH
)
1650 window_min_width
= MIN_SAFE_WINDOW_WIDTH
;
1651 if (window_min_height
< MIN_SAFE_WINDOW_HEIGHT
)
1652 window_min_height
= MIN_SAFE_WINDOW_HEIGHT
;
1655 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
1656 minimum allowable size. */
1658 check_frame_size (frame
, rows
, cols
)
1662 /* For height, we have to see:
1663 whether the frame has a minibuffer,
1664 whether it wants a mode line, and
1665 whether it has a menu bar. */
1667 (FRAME_MINIBUF_ONLY_P (frame
) ? MIN_SAFE_WINDOW_HEIGHT
- 1
1668 : (! FRAME_HAS_MINIBUF_P (frame
)) ? MIN_SAFE_WINDOW_HEIGHT
1669 : 2 * MIN_SAFE_WINDOW_HEIGHT
- 1);
1670 if (FRAME_MENU_BAR_LINES (frame
) > 0)
1671 min_height
+= FRAME_MENU_BAR_LINES (frame
);
1673 if (*rows
< min_height
)
1675 if (*cols
< MIN_SAFE_WINDOW_WIDTH
)
1676 *cols
= MIN_SAFE_WINDOW_WIDTH
;
1679 /* Normally the window is deleted if it gets too small.
1680 nodelete nonzero means do not do this.
1681 (The caller should check later and do so if appropriate) */
1683 set_window_height (window
, height
, nodelete
)
1688 register struct window
*w
= XWINDOW (window
);
1689 register struct window
*c
;
1690 int oheight
= XFASTINT (w
->height
);
1691 int top
, pos
, lastbot
, opos
, lastobot
;
1694 check_min_window_sizes ();
1697 && ! NILP (w
->parent
)
1698 && height
< window_min_height
)
1700 Fdelete_window (window
);
1704 XSETFASTINT (w
->last_modified
, 0);
1705 XSETFASTINT (w
->last_overlay_modified
, 0);
1706 windows_or_buffers_changed
++;
1707 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w
))) = 1;
1709 XSETFASTINT (w
->height
, height
);
1710 if (!NILP (w
->hchild
))
1712 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1714 XWINDOW (child
)->top
= w
->top
;
1715 set_window_height (child
, height
, nodelete
);
1718 else if (!NILP (w
->vchild
))
1720 lastbot
= top
= XFASTINT (w
->top
);
1722 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
1724 c
= XWINDOW (child
);
1726 opos
= lastobot
+ XFASTINT (c
->height
);
1728 XSETFASTINT (c
->top
, lastbot
);
1730 pos
= (((opos
* height
) << 1) + oheight
) / (oheight
<< 1);
1732 /* Avoid confusion: inhibit deletion of child if becomes too small */
1733 set_window_height (child
, pos
+ top
- lastbot
, 1);
1735 /* Now advance child to next window,
1736 and set lastbot if child was not just deleted. */
1737 lastbot
= pos
+ top
;
1740 /* Now delete any children that became too small. */
1742 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1744 set_window_height (child
, XINT (XWINDOW (child
)->height
), 0);
1749 /* Recursively set width of WINDOW and its inferiors. */
1751 set_window_width (window
, width
, nodelete
)
1756 register struct window
*w
= XWINDOW (window
);
1757 register struct window
*c
;
1758 int owidth
= XFASTINT (w
->width
);
1759 int left
, pos
, lastright
, opos
, lastoright
;
1762 if (!nodelete
&& width
< window_min_width
&& !NILP (w
->parent
))
1764 Fdelete_window (window
);
1768 XSETFASTINT (w
->last_modified
, 0);
1769 XSETFASTINT (w
->last_overlay_modified
, 0);
1770 windows_or_buffers_changed
++;
1771 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w
))) = 1;
1773 XSETFASTINT (w
->width
, width
);
1774 if (!NILP (w
->vchild
))
1776 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1778 XWINDOW (child
)->left
= w
->left
;
1779 set_window_width (child
, width
, nodelete
);
1782 else if (!NILP (w
->hchild
))
1784 lastright
= left
= XFASTINT (w
->left
);
1786 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
1788 c
= XWINDOW (child
);
1790 opos
= lastoright
+ XFASTINT (c
->width
);
1792 XSETFASTINT (c
->left
, lastright
);
1794 pos
= (((opos
* width
) << 1) + owidth
) / (owidth
<< 1);
1796 /* Inhibit deletion for becoming too small */
1797 set_window_width (child
, pos
+ left
- lastright
, 1);
1799 /* Now advance child to next window,
1800 and set lastright if child was not just deleted. */
1801 lastright
= pos
+ left
, lastoright
= opos
;
1803 /* Delete children that became too small */
1805 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1807 set_window_width (child
, XINT (XWINDOW (child
)->width
), 0);
1812 int window_select_count
;
1815 Fset_window_buffer_unwind (obuf
)
1822 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 2, 0,
1823 "Make WINDOW display BUFFER as its contents.\n\
1824 BUFFER can be a buffer or buffer name.")
1826 register Lisp_Object window
, buffer
;
1828 register Lisp_Object tem
;
1829 register struct window
*w
= decode_window (window
);
1830 int count
= specpdl_ptr
- specpdl
;
1832 buffer
= Fget_buffer (buffer
);
1833 CHECK_BUFFER (buffer
, 1);
1835 if (NILP (XBUFFER (buffer
)->name
))
1836 error ("Attempt to display deleted buffer");
1840 error ("Window is deleted");
1841 else if (! EQ (tem
, Qt
)) /* w->buffer is t when the window
1842 is first being set up. */
1844 if (!NILP (w
->dedicated
) && !EQ (tem
, buffer
))
1845 error ("Window is dedicated to `%s'",
1846 XSTRING (XBUFFER (tem
)->name
)->data
);
1853 if (EQ (window
, selected_window
))
1854 XBUFFER (w
->buffer
)->last_selected_window
= window
;
1856 XSETFASTINT (w
->window_end_pos
, 0);
1857 w
->window_end_valid
= Qnil
;
1858 XSETFASTINT (w
->hscroll
, 0);
1859 Fset_marker (w
->pointm
,
1860 make_number (BUF_PT (XBUFFER (buffer
))),
1862 set_marker_restricted (w
->start
,
1863 make_number (XBUFFER (buffer
)->last_window_start
),
1865 w
->start_at_line_beg
= Qnil
;
1866 w
->force_start
= Qnil
;
1867 XSETFASTINT (w
->last_modified
, 0);
1868 XSETFASTINT (w
->last_overlay_modified
, 0);
1869 windows_or_buffers_changed
++;
1871 /* We must select BUFFER for running the window-scroll-functions.
1872 If WINDOW is selected, switch permanently.
1873 Otherwise, switch but go back to the ambient buffer afterward. */
1874 if (EQ (window
, selected_window
))
1875 Fset_buffer (buffer
);
1876 /* We can't check ! NILP (Vwindow_scroll_functions) here
1877 because that might itself be a local variable. */
1878 else if (window_initialized
)
1880 record_unwind_protect (Fset_window_buffer_unwind
, Fcurrent_buffer ());
1881 Fset_buffer (buffer
);
1884 if (! NILP (Vwindow_scroll_functions
))
1885 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
1886 Fmarker_position (w
->start
));
1888 unbind_to (count
, Qnil
);
1893 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 1, 0,
1894 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1895 The main editor command loop selects the buffer of the selected window\n\
1896 before each command.")
1898 register Lisp_Object window
;
1900 register struct window
*w
;
1901 register struct window
*ow
= XWINDOW (selected_window
);
1903 CHECK_LIVE_WINDOW (window
, 0);
1905 w
= XWINDOW (window
);
1907 if (NILP (w
->buffer
))
1908 error ("Trying to select deleted window or non-leaf window");
1910 XSETFASTINT (w
->use_time
, ++window_select_count
);
1911 if (EQ (window
, selected_window
))
1914 Fset_marker (ow
->pointm
, make_number (BUF_PT (XBUFFER (ow
->buffer
))),
1917 selected_window
= window
;
1918 if (XFRAME (WINDOW_FRAME (w
)) != selected_frame
)
1920 XFRAME (WINDOW_FRAME (w
))->selected_window
= window
;
1921 /* Use this rather than Fhandle_switch_frame
1922 so that FRAME_FOCUS_FRAME is moved appropriately as we
1923 move around in the state where a minibuffer in a separate
1925 Fselect_frame (WINDOW_FRAME (w
), Qnil
);
1928 selected_frame
->selected_window
= window
;
1930 record_buffer (w
->buffer
);
1931 Fset_buffer (w
->buffer
);
1933 XBUFFER (w
->buffer
)->last_selected_window
= window
;
1935 /* Go to the point recorded in the window.
1936 This is important when the buffer is in more
1937 than one window. It also matters when
1938 redisplay_window has altered point after scrolling,
1939 because it makes the change only in the window. */
1941 register int new_point
= marker_position (w
->pointm
);
1942 if (new_point
< BEGV
)
1944 else if (new_point
> ZV
)
1950 windows_or_buffers_changed
++;
1954 /* Deiconify the frame containing the window WINDOW,
1955 unless it is the selected frame;
1958 The reason for the exception for the selected frame
1959 is that it seems better not to change the selected frames visibility
1960 merely because of displaying a different buffer in it.
1961 The deiconification is useful when a buffer gets shown in
1962 another frame that you were not using lately. */
1965 display_buffer_1 (window
)
1968 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
1969 FRAME_SAMPLE_VISIBILITY (f
);
1970 if (f
!= selected_frame
)
1972 if (FRAME_ICONIFIED_P (f
))
1973 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
1974 else if (FRAME_VISIBLE_P (f
))
1975 Fraise_frame (WINDOW_FRAME (XWINDOW (window
)));
1980 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 2,
1981 "bDisplay buffer: \nP",
1982 "Make BUFFER appear in some window but don't select it.\n\
1983 BUFFER can be a buffer or a buffer name.\n\
1984 If BUFFER is shown already in some window, just use that one,\n\
1985 unless the window is the selected window and the optional second\n\
1986 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
1987 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
1988 Returns the window displaying BUFFER.\n\
1990 The variables `special-display-buffer-names', `special-display-regexps',\n\
1991 `same-window-buffer-names', and `same-window-regexps' customize how certain\n\
1992 buffer names are handled.")
1993 (buffer
, not_this_window
)
1994 register Lisp_Object buffer
, not_this_window
;
1996 register Lisp_Object window
, tem
;
1998 buffer
= Fget_buffer (buffer
);
1999 CHECK_BUFFER (buffer
, 0);
2001 if (!NILP (Vdisplay_buffer_function
))
2002 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
2004 if (NILP (not_this_window
)
2005 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
2006 return display_buffer_1 (selected_window
);
2008 /* See if the user has specified this buffer should appear
2009 in the selected window. */
2010 if (NILP (not_this_window
))
2012 tem
= Fmember (XBUFFER (buffer
)->name
, Vsame_window_buffer_names
);
2015 Fswitch_to_buffer (buffer
, Qnil
);
2016 return display_buffer_1 (selected_window
);
2019 tem
= Fassoc (XBUFFER (buffer
)->name
, Vsame_window_buffer_names
);
2022 Fswitch_to_buffer (buffer
, Qnil
);
2023 return display_buffer_1 (selected_window
);
2026 for (tem
= Vsame_window_regexps
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
2028 Lisp_Object car
= XCONS (tem
)->car
;
2030 && fast_string_match (car
, XBUFFER (buffer
)->name
) >= 0)
2032 Fswitch_to_buffer (buffer
, Qnil
);
2033 return display_buffer_1 (selected_window
);
2035 else if (CONSP (car
)
2036 && STRINGP (XCONS (car
)->car
)
2037 && fast_string_match (XCONS (car
)->car
,
2038 XBUFFER (buffer
)->name
) >= 0)
2040 Fswitch_to_buffer (buffer
, Qnil
);
2041 return display_buffer_1 (selected_window
);
2046 /* If pop_up_frames,
2047 look for a window showing BUFFER on any visible or iconified frame.
2048 Otherwise search only the current frame. */
2049 if (pop_up_frames
|| last_nonminibuf_frame
== 0)
2050 XSETFASTINT (tem
, 0);
2052 XSETFRAME (tem
, last_nonminibuf_frame
);
2053 window
= Fget_buffer_window (buffer
, tem
);
2055 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
2057 return display_buffer_1 (window
);
2060 /* Certain buffer names get special handling. */
2061 if (! NILP (Vspecial_display_function
))
2063 tem
= Fmember (XBUFFER (buffer
)->name
, Vspecial_display_buffer_names
);
2065 return call1 (Vspecial_display_function
, buffer
);
2067 tem
= Fassoc (XBUFFER (buffer
)->name
, Vspecial_display_buffer_names
);
2069 return call2 (Vspecial_display_function
, buffer
, XCONS (tem
)->cdr
);
2071 for (tem
= Vspecial_display_regexps
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
2073 Lisp_Object car
= XCONS (tem
)->car
;
2075 && fast_string_match (car
, XBUFFER (buffer
)->name
) >= 0)
2076 return call1 (Vspecial_display_function
, buffer
);
2077 else if (CONSP (car
)
2078 && STRINGP (XCONS (car
)->car
)
2079 && fast_string_match (XCONS (car
)->car
,
2080 XBUFFER (buffer
)->name
) >= 0)
2081 return call2 (Vspecial_display_function
,
2087 /* If there are no frames open that have more than a minibuffer,
2088 we need to create a new frame. */
2089 if (pop_up_frames
|| last_nonminibuf_frame
== 0)
2091 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
2092 Fset_window_buffer (window
, buffer
);
2093 return display_buffer_1 (window
);
2097 || FRAME_MINIBUF_ONLY_P (selected_frame
)
2098 /* If the current frame is a special display frame,
2099 don't try to reuse its windows. */
2100 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->dedicated
)
2106 if (FRAME_MINIBUF_ONLY_P (selected_frame
))
2107 XSETFRAME (frames
, last_nonminibuf_frame
);
2108 /* Don't try to create a window if would get an error */
2109 if (split_height_threshold
< window_min_height
<< 1)
2110 split_height_threshold
= window_min_height
<< 1;
2112 /* Note that both Fget_largest_window and Fget_lru_window
2113 ignore minibuffers and dedicated windows.
2114 This means they can return nil. */
2116 /* If the frame we would try to split cannot be split,
2117 try other frames. */
2118 if (FRAME_NO_SPLIT_P (NILP (frames
) ? selected_frame
2119 : last_nonminibuf_frame
))
2121 /* Try visible frames first. */
2122 window
= Fget_largest_window (Qvisible
);
2123 /* If that didn't work, try iconified frames. */
2125 window
= Fget_largest_window (make_number (0));
2127 window
= Fget_largest_window (Qt
);
2130 window
= Fget_largest_window (frames
);
2132 /* If we got a tall enough full-width window that can be split,
2135 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
2136 && window_height (window
) >= split_height_threshold
2137 && (XFASTINT (XWINDOW (window
)->width
)
2138 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window
))))))
2139 window
= Fsplit_window (window
, Qnil
, Qnil
);
2142 Lisp_Object upper
, lower
, other
;
2144 window
= Fget_lru_window (frames
);
2145 /* If the LRU window is selected, and big enough,
2146 and can be split, split it. */
2148 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
2149 && (EQ (window
, selected_window
)
2150 || EQ (XWINDOW (window
)->parent
, Qnil
))
2151 && window_height (window
) >= window_min_height
<< 1)
2152 window
= Fsplit_window (window
, Qnil
, Qnil
);
2153 /* If Fget_lru_window returned nil, try other approaches. */
2154 /* Try visible frames first. */
2156 window
= Fget_largest_window (Qvisible
);
2157 /* If that didn't work, try iconified frames. */
2159 window
= Fget_largest_window (make_number (0));
2160 /* Try invisible frames. */
2162 window
= Fget_largest_window (Qt
);
2163 /* As a last resort, make a new frame. */
2165 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
2166 /* If window appears above or below another,
2167 even out their heights. */
2168 other
= upper
= lower
= Qnil
;
2169 if (!NILP (XWINDOW (window
)->prev
))
2170 other
= upper
= XWINDOW (window
)->prev
, lower
= window
;
2171 if (!NILP (XWINDOW (window
)->next
))
2172 other
= lower
= XWINDOW (window
)->next
, upper
= window
;
2174 /* Check that OTHER and WINDOW are vertically arrayed. */
2175 && XWINDOW (other
)->top
!= XWINDOW (window
)->top
2176 && XWINDOW (other
)->height
> XWINDOW (window
)->height
)
2178 int total
= XWINDOW (other
)->height
+ XWINDOW (window
)->height
;
2179 Lisp_Object old_selected_window
;
2180 old_selected_window
= selected_window
;
2182 selected_window
= upper
;
2183 change_window_height (total
/ 2 - XWINDOW (upper
)->height
, 0);
2184 selected_window
= old_selected_window
;
2189 window
= Fget_lru_window (Qnil
);
2191 Fset_window_buffer (window
, buffer
);
2192 return display_buffer_1 (window
);
2196 temp_output_buffer_show (buf
)
2197 register Lisp_Object buf
;
2199 register struct buffer
*old
= current_buffer
;
2200 register Lisp_Object window
;
2201 register struct window
*w
;
2204 BUF_SAVE_MODIFF (XBUFFER (buf
)) = MODIFF
;
2208 XBUFFER (buf
)->clip_changed
= 1;
2209 set_buffer_internal (old
);
2211 if (!EQ (Vtemp_buffer_show_function
, Qnil
))
2212 call1 (Vtemp_buffer_show_function
, buf
);
2215 window
= Fdisplay_buffer (buf
, Qnil
);
2217 if (XFRAME (XWINDOW (window
)->frame
) != selected_frame
)
2218 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
2219 Vminibuf_scroll_window
= window
;
2220 w
= XWINDOW (window
);
2221 XSETFASTINT (w
->hscroll
, 0);
2222 set_marker_restricted (w
->start
, make_number (1), buf
);
2223 set_marker_restricted (w
->pointm
, make_number (1), buf
);
2225 /* Run temp-buffer-show-hook, with the chosen window selected. */
2226 if (!NILP (Vrun_hooks
))
2229 tem
= Fboundp (Qtemp_buffer_show_hook
);
2232 tem
= Fsymbol_value (Qtemp_buffer_show_hook
);
2235 int count
= specpdl_ptr
- specpdl
;
2237 /* Select the window that was chosen, for running the hook. */
2238 record_unwind_protect (Fset_window_configuration
,
2239 Fcurrent_window_configuration (Qnil
));
2241 Fselect_window (window
);
2242 call1 (Vrun_hooks
, Qtemp_buffer_show_hook
);
2243 unbind_to (count
, Qnil
);
2251 make_dummy_parent (window
)
2255 register struct window
*o
, *p
;
2256 register struct Lisp_Vector
*vec
;
2259 o
= XWINDOW (window
);
2260 vec
= allocate_vectorlike ((EMACS_INT
)VECSIZE (struct window
));
2261 for (i
= 0; i
< VECSIZE (struct window
); ++i
)
2262 vec
->contents
[i
] = ((struct Lisp_Vector
*)o
)->contents
[i
];
2263 vec
->size
= VECSIZE (struct window
);
2264 p
= (struct window
*)vec
;
2265 XSETWINDOW (new, p
);
2267 XSETFASTINT (p
->sequence_number
, ++sequence_number
);
2269 /* Put new into window structure in place of window */
2270 replace_window (window
, new);
2283 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
2284 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
2285 WINDOW defaults to selected one and SIZE to half its size.\n\
2286 If optional third arg HORFLAG is non-nil, split side by side\n\
2287 and put SIZE columns in the first of the pair.")
2288 (window
, size
, horflag
)
2289 Lisp_Object window
, size
, horflag
;
2291 register Lisp_Object
new;
2292 register struct window
*o
, *p
;
2294 register int size_int
;
2297 window
= selected_window
;
2299 CHECK_LIVE_WINDOW (window
, 0);
2301 o
= XWINDOW (window
);
2302 fo
= XFRAME (WINDOW_FRAME (o
));
2306 if (!NILP (horflag
))
2307 /* Calculate the size of the left-hand window, by dividing
2308 the usable space in columns by two. */
2309 size_int
= XFASTINT (o
->width
) >> 1;
2311 size_int
= XFASTINT (o
->height
) >> 1;
2315 CHECK_NUMBER (size
, 1);
2316 size_int
= XINT (size
);
2319 if (MINI_WINDOW_P (o
))
2320 error ("Attempt to split minibuffer window");
2321 else if (FRAME_NO_SPLIT_P (fo
))
2322 error ("Attempt to split unsplittable frame");
2324 check_min_window_sizes ();
2328 if (size_int
< window_min_height
)
2329 error ("Window height %d too small (after splitting)", size_int
);
2330 if (size_int
+ window_min_height
> XFASTINT (o
->height
))
2331 error ("Window height %d too small (after splitting)",
2332 XFASTINT (o
->height
) - size_int
);
2333 if (NILP (o
->parent
)
2334 || NILP (XWINDOW (o
->parent
)->vchild
))
2336 make_dummy_parent (window
);
2338 XWINDOW (new)->vchild
= window
;
2343 if (size_int
< window_min_width
)
2344 error ("Window width %d too small (after splitting)", size_int
);
2346 if (size_int
+ window_min_width
> XFASTINT (o
->width
))
2347 error ("Window width %d too small (after splitting)",
2348 XFASTINT (o
->width
) - size_int
);
2349 if (NILP (o
->parent
)
2350 || NILP (XWINDOW (o
->parent
)->hchild
))
2352 make_dummy_parent (window
);
2354 XWINDOW (new)->hchild
= window
;
2358 /* Now we know that window's parent is a vertical combination
2359 if we are dividing vertically, or a horizontal combination
2360 if we are making side-by-side windows */
2362 windows_or_buffers_changed
++;
2363 FRAME_WINDOW_SIZES_CHANGED (fo
) = 1;
2364 new = make_window ();
2367 p
->frame
= o
->frame
;
2369 if (!NILP (p
->next
))
2370 XWINDOW (p
->next
)->prev
= new;
2373 p
->parent
= o
->parent
;
2376 Fset_window_buffer (new, o
->buffer
);
2378 /* Apportion the available frame space among the two new windows */
2380 if (!NILP (horflag
))
2382 p
->height
= o
->height
;
2384 XSETFASTINT (p
->width
, XFASTINT (o
->width
) - size_int
);
2385 XSETFASTINT (o
->width
, size_int
);
2386 XSETFASTINT (p
->left
, XFASTINT (o
->left
) + size_int
);
2391 p
->width
= o
->width
;
2392 XSETFASTINT (p
->height
, XFASTINT (o
->height
) - size_int
);
2393 XSETFASTINT (o
->height
, size_int
);
2394 XSETFASTINT (p
->top
, XFASTINT (o
->top
) + size_int
);
2400 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
2401 "Make current window ARG lines bigger.\n\
2402 From program, optional second arg non-nil means grow sideways ARG columns.")
2404 register Lisp_Object arg
, side
;
2406 CHECK_NUMBER (arg
, 0);
2407 change_window_height (XINT (arg
), !NILP (side
));
2411 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
2412 "Make current window ARG lines smaller.\n\
2413 From program, optional second arg non-nil means shrink sideways arg columns.")
2415 register Lisp_Object arg
, side
;
2417 CHECK_NUMBER (arg
, 0);
2418 change_window_height (-XINT (arg
), !NILP (side
));
2423 window_height (window
)
2426 register struct window
*p
= XWINDOW (window
);
2427 return XFASTINT (p
->height
);
2431 window_width (window
)
2434 register struct window
*p
= XWINDOW (window
);
2435 return XFASTINT (p
->width
);
2438 #define MINSIZE(w) \
2440 ? window_min_width \
2441 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
2444 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
2446 #define CURSIZE(w) \
2447 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
2449 /* Unlike set_window_height, this function
2450 also changes the heights of the siblings so as to
2451 keep everything consistent. */
2453 change_window_height (delta
, widthflag
)
2457 register Lisp_Object parent
;
2459 register struct window
*p
;
2461 int (*sizefun
) () = widthflag
? window_width
: window_height
;
2462 register int (*setsizefun
) () = (widthflag
2464 : set_window_height
);
2466 check_min_window_sizes ();
2468 window
= selected_window
;
2471 p
= XWINDOW (window
);
2476 error ("No other window to side of this one");
2479 if (widthflag
? !NILP (XWINDOW (parent
)->hchild
)
2480 : !NILP (XWINDOW (parent
)->vchild
))
2485 sizep
= &CURSIZE (window
);
2488 register int maxdelta
;
2490 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - *sizep
2491 : !NILP (p
->next
) ? (*sizefun
) (p
->next
) - MINSIZE (p
->next
)
2492 : !NILP (p
->prev
) ? (*sizefun
) (p
->prev
) - MINSIZE (p
->prev
)
2493 /* This is a frame with only one window, a minibuffer-only
2494 or a minibufferless frame. */
2497 if (delta
> maxdelta
)
2498 /* This case traps trying to make the minibuffer
2499 the full frame, or make the only window aside from the
2500 minibuffer the full frame. */
2504 if (*sizep
+ delta
< MINSIZE (window
))
2506 Fdelete_window (window
);
2514 && (*sizefun
) (p
->next
) - delta
>= MINSIZE (p
->next
))
2516 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
) - delta
, 0);
2517 (*setsizefun
) (window
, *sizep
+ delta
, 0);
2518 CURBEG (p
->next
) += delta
;
2519 /* This does not change size of p->next,
2520 but it propagates the new top edge to its children */
2521 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
), 0);
2523 else if (!NILP (p
->prev
)
2524 && (*sizefun
) (p
->prev
) - delta
>= MINSIZE (p
->prev
))
2526 (*setsizefun
) (p
->prev
, (*sizefun
) (p
->prev
) - delta
, 0);
2527 CURBEG (window
) -= delta
;
2528 (*setsizefun
) (window
, *sizep
+ delta
, 0);
2532 register int delta1
;
2533 register int opht
= (*sizefun
) (parent
);
2535 /* If trying to grow this window to or beyond size of the parent,
2536 make delta1 so big that, on shrinking back down,
2537 all the siblings end up with less than one line and are deleted. */
2538 if (opht
<= *sizep
+ delta
)
2539 delta1
= opht
* opht
* 2;
2540 /* Otherwise, make delta1 just right so that if we add delta1
2541 lines to this window and to the parent, and then shrink
2542 the parent back to its original size, the new proportional
2543 size of this window will increase by delta. */
2545 delta1
= (delta
* opht
* 100) / ((opht
- *sizep
- delta
) * 100);
2547 /* Add delta1 lines or columns to this window, and to the parent,
2548 keeping things consistent while not affecting siblings. */
2549 CURSIZE (parent
) = opht
+ delta1
;
2550 (*setsizefun
) (window
, *sizep
+ delta1
, 0);
2552 /* Squeeze out delta1 lines or columns from our parent,
2553 shriking this window and siblings proportionately.
2554 This brings parent back to correct size.
2555 Delta1 was calculated so this makes this window the desired size,
2556 taking it all out of the siblings. */
2557 (*setsizefun
) (parent
, opht
, 0);
2560 XSETFASTINT (p
->last_modified
, 0);
2561 XSETFASTINT (p
->last_overlay_modified
, 0);
2568 /* Return number of lines of text (not counting mode line) in W. */
2571 window_internal_height (w
)
2574 int ht
= XFASTINT (w
->height
);
2576 if (MINI_WINDOW_P (w
))
2579 if (!NILP (w
->parent
) || !NILP (w
->vchild
) || !NILP (w
->hchild
)
2580 || !NILP (w
->next
) || !NILP (w
->prev
)
2581 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w
))))
2588 /* Return the number of columns in W.
2589 Don't count columns occupied by scroll bars or the vertical bar
2590 separating W from the sibling to its right. */
2592 window_internal_width (w
)
2595 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2596 int left
= XINT (w
->left
);
2597 int width
= XINT (w
->width
);
2599 /* If this window is flush against the right edge of the frame, its
2600 internal width is its full width. */
2601 if (left
+ width
>= FRAME_WIDTH (f
))
2604 /* If we are not flush right, then our rightmost columns are
2605 occupied by some sort of separator. */
2607 /* Scroll bars occupy a few columns. */
2608 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
2609 return width
- FRAME_SCROLL_BAR_COLS (f
);
2611 /* The column of `|' characters separating side-by-side windows
2612 occupies one column only. */
2617 /* Scroll contents of window WINDOW up N lines. */
2620 window_scroll (window
, n
, noerror
)
2625 register struct window
*w
= XWINDOW (window
);
2626 register int opoint
= PT
;
2628 register int ht
= window_internal_height (w
);
2629 register Lisp_Object tem
;
2631 Lisp_Object bolp
, nmoved
;
2633 /* Always set force_start so that redisplay_window will run
2634 the window-scroll-functions. */
2635 w
->force_start
= Qt
;
2637 XSETFASTINT (tem
, PT
);
2638 tem
= Fpos_visible_in_window_p (tem
, window
);
2642 Fvertical_motion (make_number (- (ht
/ 2)), window
);
2643 XSETFASTINT (tem
, PT
);
2644 Fset_marker (w
->start
, tem
, w
->buffer
);
2647 SET_PT (marker_position (w
->start
));
2648 lose
= n
< 0 && PT
== BEGV
;
2649 Fvertical_motion (make_number (n
), window
);
2659 Fsignal (Qbeginning_of_buffer
, Qnil
);
2664 set_marker_restricted (w
->start
, make_number (pos
), w
->buffer
);
2665 w
->start_at_line_beg
= bolp
;
2666 w
->update_mode_line
= Qt
;
2667 XSETFASTINT (w
->last_modified
, 0);
2668 XSETFASTINT (w
->last_overlay_modified
, 0);
2674 tem
= Fvertical_motion (make_number (ht
), window
);
2675 if (PT
> opoint
|| XFASTINT (tem
) < ht
)
2678 Fvertical_motion (make_number (-1), window
);
2686 Fsignal (Qend_of_buffer
, Qnil
);
2690 /* This is the guts of Fscroll_up and Fscroll_down. */
2693 scroll_command (n
, direction
)
2694 register Lisp_Object n
;
2697 register int defalt
;
2698 int count
= specpdl_ptr
- specpdl
;
2700 /* If selected window's buffer isn't current, make it current for the moment.
2701 But don't screw up if window_scroll gets an error. */
2702 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
2704 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2705 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2708 defalt
= (window_internal_height (XWINDOW (selected_window
))
2709 - next_screen_context_lines
);
2710 defalt
= direction
* (defalt
< 1 ? 1 : defalt
);
2713 window_scroll (selected_window
, defalt
, 0);
2714 else if (EQ (n
, Qminus
))
2715 window_scroll (selected_window
, - defalt
, 0);
2718 n
= Fprefix_numeric_value (n
);
2719 window_scroll (selected_window
, XINT (n
) * direction
, 0);
2722 unbind_to (count
, Qnil
);
2725 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "P",
2726 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2727 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2728 Negative ARG means scroll downward.\n\
2729 When calling from a program, supply a number as argument or nil.")
2733 scroll_command (arg
, 1);
2737 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "P",
2738 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2739 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2740 Negative ARG means scroll upward.\n\
2741 When calling from a program, supply a number as argument or nil.")
2745 scroll_command (arg
, -1);
2749 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling
, Sother_window_for_scrolling
, 0, 0, 0,
2750 "Return the other window for \"other window scroll\" commands.\n\
2751 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2752 specifies the window.\n\
2753 If `other-window-scroll-buffer' is non-nil, a window\n\
2754 showing that buffer is used.")
2759 if (MINI_WINDOW_P (XWINDOW (selected_window
))
2760 && !NILP (Vminibuf_scroll_window
))
2761 window
= Vminibuf_scroll_window
;
2762 /* If buffer is specified, scroll that buffer. */
2763 else if (!NILP (Vother_window_scroll_buffer
))
2765 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
2767 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
);
2771 /* Nothing specified; look for a neighboring window on the same
2773 window
= Fnext_window (selected_window
, Qnil
, Qnil
);
2775 if (EQ (window
, selected_window
))
2776 /* That didn't get us anywhere; look for a window on another
2779 window
= Fnext_window (window
, Qnil
, Qt
);
2780 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window
))))
2781 && ! EQ (window
, selected_window
));
2784 CHECK_LIVE_WINDOW (window
, 0);
2786 if (EQ (window
, selected_window
))
2787 error ("There is no other window");
2792 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
2793 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
2794 The next window is the one below the current one; or the one at the top\n\
2795 if the current one is at the bottom. Negative ARG means scroll downward.\n\
2796 When calling from a program, supply a number as argument or nil.\n\
2798 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2799 specifies the window to scroll.\n\
2800 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2801 showing that buffer, popping the buffer up if necessary.")
2803 register Lisp_Object arg
;
2805 register Lisp_Object window
;
2806 register int defalt
;
2807 register struct window
*w
;
2808 register int count
= specpdl_ptr
- specpdl
;
2810 window
= Fother_window_for_scrolling ();
2812 w
= XWINDOW (window
);
2813 defalt
= window_internal_height (w
) - next_screen_context_lines
;
2814 if (defalt
< 1) defalt
= 1;
2816 /* Don't screw up if window_scroll gets an error. */
2817 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2819 Fset_buffer (w
->buffer
);
2820 SET_PT (marker_position (w
->pointm
));
2823 window_scroll (window
, defalt
, 1);
2824 else if (EQ (arg
, Qminus
))
2825 window_scroll (window
, -defalt
, 1);
2830 CHECK_NUMBER (arg
, 0);
2831 window_scroll (window
, XINT (arg
), 1);
2834 Fset_marker (w
->pointm
, make_number (PT
), Qnil
);
2835 unbind_to (count
, Qnil
);
2840 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 0, 1, "P",
2841 "Scroll selected window display ARG columns left.\n\
2842 Default for ARG is window width minus 2.")
2844 register Lisp_Object arg
;
2848 XSETFASTINT (arg
, window_internal_width (XWINDOW (selected_window
)) - 2);
2850 arg
= Fprefix_numeric_value (arg
);
2853 Fset_window_hscroll (selected_window
,
2854 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2858 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 0, 1, "P",
2859 "Scroll selected window display ARG columns right.\n\
2860 Default for ARG is window width minus 2.")
2862 register Lisp_Object arg
;
2865 XSETFASTINT (arg
, window_internal_width (XWINDOW (selected_window
)) - 2);
2867 arg
= Fprefix_numeric_value (arg
);
2870 Fset_window_hscroll (selected_window
,
2871 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2875 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
2876 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
2877 The desired position of point is always relative to the current window.\n\
2878 Just C-u as prefix means put point in the center of the window.\n\
2879 If ARG is omitted or nil, erases the entire frame and then\n\
2880 redraws with point in the center of the current window.")
2882 register Lisp_Object arg
;
2884 register struct window
*w
= XWINDOW (selected_window
);
2885 register int ht
= window_internal_height (w
);
2886 struct position pos
;
2890 extern int frame_garbaged
;
2892 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w
)));
2893 XSETFASTINT (arg
, ht
/ 2);
2895 else if (CONSP (arg
)) /* Just C-u. */
2897 XSETFASTINT (arg
, ht
/ 2);
2901 arg
= Fprefix_numeric_value (arg
);
2902 CHECK_NUMBER (arg
, 0);
2906 XSETINT (arg
, XINT (arg
) + ht
);
2908 pos
= *vmotion (PT
, - XINT (arg
), w
);
2910 Fset_marker (w
->start
, make_number (pos
.bufpos
), w
->buffer
);
2911 w
->start_at_line_beg
= ((pos
.bufpos
== BEGV
2912 || FETCH_CHAR (pos
.bufpos
- 1) == '\n')
2914 w
->force_start
= Qt
;
2919 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
2921 "Position point relative to window.\n\
2922 With no argument, position point at center of window.\n\
2923 An argument specifies frame line; zero means top of window,\n\
2924 negative means relative to bottom of window.")
2926 register Lisp_Object arg
;
2928 register struct window
*w
= XWINDOW (selected_window
);
2929 register int height
= window_internal_height (w
);
2934 XSETFASTINT (arg
, height
/ 2);
2937 arg
= Fprefix_numeric_value (arg
);
2939 XSETINT (arg
, XINT (arg
) + height
);
2942 start
= marker_position (w
->start
);
2943 XSETWINDOW (window
, w
);
2944 if (start
< BEGV
|| start
> ZV
)
2946 Fvertical_motion (make_number (- (height
/ 2)), window
);
2947 Fset_marker (w
->start
, make_number (PT
), w
->buffer
);
2948 w
->start_at_line_beg
= Fbolp ();
2949 w
->force_start
= Qt
;
2954 return Fvertical_motion (arg
, window
);
2957 struct save_window_data
2959 EMACS_INT size_from_Lisp_Vector_struct
;
2960 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2961 Lisp_Object frame_width
, frame_height
, frame_menu_bar_lines
;
2962 Lisp_Object selected_frame
;
2963 Lisp_Object current_window
;
2964 Lisp_Object current_buffer
;
2965 Lisp_Object minibuf_scroll_window
;
2966 Lisp_Object root_window
;
2967 Lisp_Object focus_frame
;
2968 /* Record the values of window-min-width and window-min-height
2969 so that window sizes remain consistent with them. */
2970 Lisp_Object min_width
, min_height
;
2971 /* A vector, interpreted as a struct saved_window */
2972 Lisp_Object saved_windows
;
2975 /* This is saved as a Lisp_Vector */
2978 /* these first two must agree with struct Lisp_Vector in lisp.h */
2979 EMACS_INT size_from_Lisp_Vector_struct
;
2980 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2983 Lisp_Object buffer
, start
, pointm
, mark
;
2984 Lisp_Object left
, top
, width
, height
, hscroll
;
2985 Lisp_Object parent
, prev
;
2986 Lisp_Object start_at_line_beg
;
2987 Lisp_Object display_table
;
2989 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2991 #define SAVED_WINDOW_N(swv,n) \
2992 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2994 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
2995 "T if OBJECT is a window-configuration object.")
2999 if (WINDOW_CONFIGURATIONP (object
))
3005 DEFUN ("set-window-configuration", Fset_window_configuration
,
3006 Sset_window_configuration
, 1, 1, 0,
3007 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
3008 CONFIGURATION must be a value previously returned\n\
3009 by `current-window-configuration' (which see).")
3011 Lisp_Object configuration
;
3013 register struct save_window_data
*data
;
3014 struct Lisp_Vector
*saved_windows
;
3015 Lisp_Object new_current_buffer
;
3019 while (!WINDOW_CONFIGURATIONP (configuration
))
3021 configuration
= wrong_type_argument (intern ("window-configuration-p"),
3025 data
= (struct save_window_data
*) XVECTOR (configuration
);
3026 saved_windows
= XVECTOR (data
->saved_windows
);
3028 new_current_buffer
= data
->current_buffer
;
3029 if (NILP (XBUFFER (new_current_buffer
)->name
))
3030 new_current_buffer
= Qnil
;
3032 frame
= XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
3035 /* If f is a dead frame, don't bother rebuilding its window tree.
3036 However, there is other stuff we should still try to do below. */
3037 if (FRAME_LIVE_P (f
))
3039 register struct window
*w
;
3040 register struct saved_window
*p
;
3043 /* If the frame has been resized since this window configuration was
3044 made, we change the frame to the size specified in the
3045 configuration, restore the configuration, and then resize it
3046 back. We keep track of the prevailing height in these variables. */
3047 int previous_frame_height
= FRAME_HEIGHT (f
);
3048 int previous_frame_width
= FRAME_WIDTH (f
);
3049 int previous_frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
3051 if (XFASTINT (data
->frame_height
) != previous_frame_height
3052 || XFASTINT (data
->frame_width
) != previous_frame_width
)
3053 change_frame_size (f
, data
->frame_height
, data
->frame_width
, 0, 0);
3054 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
3055 if (XFASTINT (data
->frame_menu_bar_lines
)
3056 != previous_frame_menu_bar_lines
)
3057 x_set_menu_bar_lines (f
, data
->frame_menu_bar_lines
, 0);
3060 windows_or_buffers_changed
++;
3061 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
3063 /* Temporarily avoid any problems with windows that are smaller
3064 than they are supposed to be. */
3065 window_min_height
= 1;
3066 window_min_width
= 1;
3069 Mark all windows now on frame as "deleted".
3070 Restoring the new configuration "undeletes" any that are in it.
3072 Save their current buffers in their height fields, since we may
3073 need it later, if a buffer saved in the configuration is now
3075 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3077 for (k
= 0; k
< saved_windows
->size
; k
++)
3079 p
= SAVED_WINDOW_N (saved_windows
, k
);
3080 w
= XWINDOW (p
->window
);
3083 if (!NILP (p
->parent
))
3084 w
->parent
= SAVED_WINDOW_N (saved_windows
,
3085 XFASTINT (p
->parent
))->window
;
3089 if (!NILP (p
->prev
))
3091 w
->prev
= SAVED_WINDOW_N (saved_windows
,
3092 XFASTINT (p
->prev
))->window
;
3093 XWINDOW (w
->prev
)->next
= p
->window
;
3098 if (!NILP (w
->parent
))
3100 if (EQ (p
->width
, XWINDOW (w
->parent
)->width
))
3102 XWINDOW (w
->parent
)->vchild
= p
->window
;
3103 XWINDOW (w
->parent
)->hchild
= Qnil
;
3107 XWINDOW (w
->parent
)->hchild
= p
->window
;
3108 XWINDOW (w
->parent
)->vchild
= Qnil
;
3113 /* If we squirreled away the buffer in the window's height,
3115 if (BUFFERP (w
->height
))
3116 w
->buffer
= w
->height
;
3119 w
->width
= p
->width
;
3120 w
->height
= p
->height
;
3121 w
->hscroll
= p
->hscroll
;
3122 w
->display_table
= p
->display_table
;
3123 XSETFASTINT (w
->last_modified
, 0);
3124 XSETFASTINT (w
->last_overlay_modified
, 0);
3126 /* Reinstall the saved buffer and pointers into it. */
3127 if (NILP (p
->buffer
))
3128 w
->buffer
= p
->buffer
;
3131 if (!NILP (XBUFFER (p
->buffer
)->name
))
3132 /* If saved buffer is alive, install it. */
3134 w
->buffer
= p
->buffer
;
3135 w
->start_at_line_beg
= p
->start_at_line_beg
;
3136 set_marker_restricted (w
->start
,
3137 Fmarker_position (p
->start
),
3139 set_marker_restricted (w
->pointm
,
3140 Fmarker_position (p
->pointm
),
3142 Fset_marker (XBUFFER (w
->buffer
)->mark
,
3143 Fmarker_position (p
->mark
), w
->buffer
);
3145 /* As documented in Fcurrent_window_configuration, don't
3146 save the location of point in the buffer which was current
3147 when the window configuration was recorded. */
3148 if (!EQ (p
->buffer
, new_current_buffer
)
3149 && XBUFFER (p
->buffer
) == current_buffer
)
3150 Fgoto_char (w
->pointm
);
3152 else if (NILP (w
->buffer
) || NILP (XBUFFER (w
->buffer
)->name
))
3153 /* Else unless window has a live buffer, get one. */
3155 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
3156 /* This will set the markers to beginning of visible
3158 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
3159 set_marker_restricted (w
->pointm
, make_number (0),w
->buffer
);
3160 w
->start_at_line_beg
= Qt
;
3163 /* Keeping window's old buffer; make sure the markers
3166 /* Set window markers at start of visible range. */
3167 if (XMARKER (w
->start
)->buffer
== 0)
3168 set_marker_restricted (w
->start
, make_number (0),
3170 if (XMARKER (w
->pointm
)->buffer
== 0)
3171 set_marker_restricted (w
->pointm
,
3173 (BUF_PT (XBUFFER (w
->buffer
)))),
3175 w
->start_at_line_beg
= Qt
;
3180 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
3181 Fselect_window (data
->current_window
);
3183 if (NILP (data
->focus_frame
)
3184 || (FRAMEP (data
->focus_frame
)
3185 && FRAME_LIVE_P (XFRAME (data
->focus_frame
))))
3186 Fredirect_frame_focus (frame
, data
->focus_frame
);
3188 #if 0 /* I don't understand why this is needed, and it causes problems
3189 when the frame's old selected window has been deleted. */
3190 if (f
!= selected_frame
&& FRAME_WINDOW_P (f
))
3191 do_switch_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)),
3195 /* Set the screen height to the value it had before this function. */
3196 if (previous_frame_height
!= FRAME_HEIGHT (f
)
3197 || previous_frame_width
!= FRAME_WIDTH (f
))
3198 change_frame_size (f
, previous_frame_height
, previous_frame_width
,
3200 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
3201 if (previous_frame_menu_bar_lines
!= FRAME_MENU_BAR_LINES (f
))
3202 x_set_menu_bar_lines (f
, previous_frame_menu_bar_lines
, 0);
3206 /* Restore the minimum heights recorded in the configuration. */
3207 window_min_height
= XINT (data
->min_height
);
3208 window_min_width
= XINT (data
->min_width
);
3210 /* Fselect_window will have made f the selected frame, so we
3211 reselect the proper frame here. Fhandle_switch_frame will change the
3212 selected window too, but that doesn't make the call to
3213 Fselect_window above totally superfluous; it still sets f's
3215 if (FRAME_LIVE_P (XFRAME (data
->selected_frame
)))
3216 do_switch_frame (data
->selected_frame
, Qnil
, 0);
3218 if (!NILP (new_current_buffer
))
3219 Fset_buffer (new_current_buffer
);
3221 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
3225 /* Mark all windows now on frame as deleted
3226 by setting their buffers to nil. */
3229 delete_all_subwindows (w
)
3230 register struct window
*w
;
3232 if (!NILP (w
->next
))
3233 delete_all_subwindows (XWINDOW (w
->next
));
3234 if (!NILP (w
->vchild
))
3235 delete_all_subwindows (XWINDOW (w
->vchild
));
3236 if (!NILP (w
->hchild
))
3237 delete_all_subwindows (XWINDOW (w
->hchild
));
3239 w
->height
= w
->buffer
; /* See Fset_window_configuration for excuse. */
3241 if (!NILP (w
->buffer
))
3244 /* We set all three of these fields to nil, to make sure that we can
3245 distinguish this dead window from any live window. Live leaf
3246 windows will have buffer set, and combination windows will have
3247 vchild or hchild set. */
3254 count_windows (window
)
3255 register struct window
*window
;
3257 register int count
= 1;
3258 if (!NILP (window
->next
))
3259 count
+= count_windows (XWINDOW (window
->next
));
3260 if (!NILP (window
->vchild
))
3261 count
+= count_windows (XWINDOW (window
->vchild
));
3262 if (!NILP (window
->hchild
))
3263 count
+= count_windows (XWINDOW (window
->hchild
));
3268 save_window_save (window
, vector
, i
)
3270 struct Lisp_Vector
*vector
;
3273 register struct saved_window
*p
;
3274 register struct window
*w
;
3275 register Lisp_Object tem
;
3277 for (;!NILP (window
); window
= w
->next
)
3279 p
= SAVED_WINDOW_N (vector
, i
);
3280 w
= XWINDOW (window
);
3282 XSETFASTINT (w
->temslot
, i
++);
3284 p
->buffer
= w
->buffer
;
3287 p
->width
= w
->width
;
3288 p
->height
= w
->height
;
3289 p
->hscroll
= w
->hscroll
;
3290 p
->display_table
= w
->display_table
;
3291 if (!NILP (w
->buffer
))
3293 /* Save w's value of point in the window configuration.
3294 If w is the selected window, then get the value of point
3295 from the buffer; pointm is garbage in the selected window. */
3296 if (EQ (window
, selected_window
))
3298 p
->pointm
= Fmake_marker ();
3299 Fset_marker (p
->pointm
, BUF_PT (XBUFFER (w
->buffer
)),
3303 p
->pointm
= Fcopy_marker (w
->pointm
, Qnil
);
3305 p
->start
= Fcopy_marker (w
->start
, Qnil
);
3306 p
->start_at_line_beg
= w
->start_at_line_beg
;
3308 tem
= XBUFFER (w
->buffer
)->mark
;
3309 p
->mark
= Fcopy_marker (tem
, Qnil
);
3316 p
->start_at_line_beg
= Qnil
;
3319 if (NILP (w
->parent
))
3322 p
->parent
= XWINDOW (w
->parent
)->temslot
;
3327 p
->prev
= XWINDOW (w
->prev
)->temslot
;
3329 if (!NILP (w
->vchild
))
3330 i
= save_window_save (w
->vchild
, vector
, i
);
3331 if (!NILP (w
->hchild
))
3332 i
= save_window_save (w
->hchild
, vector
, i
);
3338 DEFUN ("current-window-configuration",
3339 Fcurrent_window_configuration
, Scurrent_window_configuration
, 0, 1, 0,
3340 "Return an object representing the current window configuration of FRAME.\n\
3341 If FRAME is nil or omitted, use the selected frame.\n\
3342 This describes the number of windows, their sizes and current buffers,\n\
3343 and for each displayed buffer, where display starts, and the positions of\n\
3344 point and mark. An exception is made for point in the current buffer:\n\
3345 its value is -not- saved.\n\
3346 This also records the currently selected frame, and FRAME's focus\n\
3347 redirection (see `redirect-frame-focus').")
3351 register Lisp_Object tem
;
3352 register int n_windows
;
3353 register struct save_window_data
*data
;
3354 register struct Lisp_Vector
*vec
;
3362 CHECK_LIVE_FRAME (frame
, 0);
3366 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3367 vec
= allocate_vectorlike (VECSIZE (struct save_window_data
));
3368 for (i
= 0; i
< VECSIZE (struct save_window_data
); i
++)
3369 vec
->contents
[i
] = Qnil
;
3370 vec
->size
= VECSIZE (struct save_window_data
);
3371 data
= (struct save_window_data
*)vec
;
3373 XSETFASTINT (data
->frame_width
, FRAME_WIDTH (f
));
3374 XSETFASTINT (data
->frame_height
, FRAME_HEIGHT (f
));
3375 XSETFASTINT (data
->frame_menu_bar_lines
, FRAME_MENU_BAR_LINES (f
));
3376 XSETFRAME (data
->selected_frame
, selected_frame
);
3377 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
3378 XSETBUFFER (data
->current_buffer
, current_buffer
);
3379 data
->minibuf_scroll_window
= Vminibuf_scroll_window
;
3380 data
->root_window
= FRAME_ROOT_WINDOW (f
);
3381 data
->focus_frame
= FRAME_FOCUS_FRAME (f
);
3382 XSETINT (data
->min_height
, window_min_height
);
3383 XSETINT (data
->min_width
, window_min_width
);
3384 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
3385 data
->saved_windows
= tem
;
3386 for (i
= 0; i
< n_windows
; i
++)
3387 XVECTOR (tem
)->contents
[i
]
3388 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE
), Qnil
);
3389 save_window_save (FRAME_ROOT_WINDOW (f
),
3391 XSETWINDOW_CONFIGURATION (tem
, data
);
3395 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
3397 "Execute body, preserving window sizes and contents.\n\
3398 Restore which buffer appears in which window, where display starts,\n\
3399 and the value of point and mark for each window.\n\
3400 Also restore which buffer is current.\n\
3401 But do not preserve point in the current buffer.\n\
3402 Does not restore the value of point in current buffer.")
3406 register Lisp_Object val
;
3407 register int count
= specpdl_ptr
- specpdl
;
3409 record_unwind_protect (Fset_window_configuration
,
3410 Fcurrent_window_configuration (Qnil
));
3411 val
= Fprogn (args
);
3412 return unbind_to (count
, val
);
3417 selected_frame
= make_terminal_frame ();
3418 XSETFRAME (Vterminal_frame
, selected_frame
);
3419 minibuf_window
= selected_frame
->minibuffer_window
;
3420 selected_window
= selected_frame
->selected_window
;
3421 last_nonminibuf_frame
= selected_frame
;
3423 window_initialized
= 1;
3428 Qwindowp
= intern ("windowp");
3429 staticpro (&Qwindowp
);
3431 Qwindow_live_p
= intern ("window-live-p");
3432 staticpro (&Qwindow_live_p
);
3434 Qtemp_buffer_show_hook
= intern ("temp-buffer-show-hook");
3435 staticpro (&Qtemp_buffer_show_hook
);
3437 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
3438 "Non-nil means call as function to display a help buffer.\n\
3439 The function is called with one argument, the buffer to be displayed.\n\
3440 Used by `with-output-to-temp-buffer'.\n\
3441 If this function is used, then it must do the entire job of showing\n\
3442 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
3443 Vtemp_buffer_show_function
= Qnil
;
3445 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
3446 "If non-nil, function to call to handle `display-buffer'.\n\
3447 It will receive two args, the buffer and a flag which if non-nil means\n\
3448 that the currently selected window is not acceptable.\n\
3449 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
3450 work using this function.");
3451 Vdisplay_buffer_function
= Qnil
;
3453 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
3454 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
3455 Vminibuf_scroll_window
= Qnil
;
3457 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
3458 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
3459 Vother_window_scroll_buffer
= Qnil
;
3461 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames
,
3462 "*Non-nil means `display-buffer' should make a separate frame.");
3465 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function
,
3466 "Function to call to handle automatic new frame creation.\n\
3467 It is called with no arguments and should return a newly created frame.\n\
3469 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
3470 where `pop-up-frame-alist' would hold the default frame parameters.");
3471 Vpop_up_frame_function
= Qnil
;
3473 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names
,
3474 "*List of buffer names that should have their own special frames.\n\
3475 Displaying a buffer whose name is in this list makes a special frame for it\n\
3476 using `special-display-function'.\n\
3478 An element of the list can be a cons cell instead of just a string.\n\
3479 Then the car should be a buffer name, and the cdr specifies frame\n\
3480 parameters for creating the frame for that buffer.\n\
3481 More precisely, the cdr is passed as the second argument to\n\
3482 the function found in `special-display-function', when making that frame.\n\
3483 See also `special-display-regexps'.");
3484 Vspecial_display_buffer_names
= Qnil
;
3486 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps
,
3487 "*List of regexps saying which buffers should have their own special frames.\n\
3488 If a buffer name matches one of these regexps, it gets its own frame.\n\
3489 Displaying a buffer whose name is in this list makes a special frame for it\n\
3490 using `special-display-function'.\n\
3492 An element of the list can be a cons cell instead of just a string.\n\
3493 Then the car should be the regexp, and the cdr specifies frame\n\
3494 parameters for creating the frame for buffers that match.\n\
3495 More precisely, the cdr is passed as the second argument to\n\
3496 the function found in `special-display-function', when making that frame.\n\
3497 See also `special-display-buffer-names'.");
3498 Vspecial_display_regexps
= Qnil
;
3500 DEFVAR_LISP ("special-display-function", &Vspecial_display_function
,
3501 "Function to call to make a new frame for a special buffer.\n\
3502 It is called with two arguments, the buffer and optional buffer specific\n\
3503 data, and should return a window displaying that buffer.\n\
3504 The default value makes a separate frame for the buffer,\n\
3505 using `special-display-frame-alist' to specify the frame parameters.\n\
3507 A buffer is special if its is listed in `special-display-buffer-names'\n\
3508 or matches a regexp in `special-display-regexps'.");
3509 Vspecial_display_function
= Qnil
;
3511 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names
,
3512 "*List of buffer names that should appear in the selected window.\n\
3513 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
3514 switches to it in the selected window, rather than making it appear\n\
3515 in some other window.\n\
3517 An element of the list can be a cons cell instead of just a string.\n\
3518 Then the car must be a string, which specifies the buffer name.\n\
3519 This is for compatibility with `special-display-buffer-names';\n\
3520 the cdr of the cons cell is ignored.\n\
3522 See also `same-window-regexps'.");
3523 Vsame_window_buffer_names
= Qnil
;
3525 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps
,
3526 "*List of regexps saying which buffers should appear in the selected window.\n\
3527 If a buffer name matches one of these regexps, then displaying it\n\
3528 using `display-buffer' or `pop-to-buffer' switches to it\n\
3529 in the selected window, rather than making it appear in some other window.\n\
3531 An element of the list can be a cons cell instead of just a string.\n\
3532 Then the car must be a string, which specifies the buffer name.\n\
3533 This is for compatibility with `special-display-buffer-names';\n\
3534 the cdr of the cons cell is ignored.\n\
3536 See also `same-window-buffer-names'.");
3537 Vsame_window_regexps
= Qnil
;
3539 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
3540 "*Non-nil means display-buffer should make new windows.");
3543 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
3544 "*Number of lines of continuity when scrolling by screenfuls.");
3545 next_screen_context_lines
= 2;
3547 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
3548 "*display-buffer would prefer to split the largest window if this large.\n\
3549 If there is only one window, it is split regardless of this value.");
3550 split_height_threshold
= 500;
3552 DEFVAR_INT ("window-min-height", &window_min_height
,
3553 "*Delete any window less than this tall (including its mode line).");
3554 window_min_height
= 4;
3556 DEFVAR_INT ("window-min-width", &window_min_width
,
3557 "*Delete any window less than this wide.");
3558 window_min_width
= 10;
3560 defsubr (&Sselected_window
);
3561 defsubr (&Sminibuffer_window
);
3562 defsubr (&Swindow_minibuffer_p
);
3563 defsubr (&Swindowp
);
3564 defsubr (&Swindow_live_p
);
3565 defsubr (&Spos_visible_in_window_p
);
3566 defsubr (&Swindow_buffer
);
3567 defsubr (&Swindow_height
);
3568 defsubr (&Swindow_width
);
3569 defsubr (&Swindow_hscroll
);
3570 defsubr (&Sset_window_hscroll
);
3571 defsubr (&Swindow_redisplay_end_trigger
);
3572 defsubr (&Sset_window_redisplay_end_trigger
);
3573 defsubr (&Swindow_edges
);
3574 defsubr (&Scoordinates_in_window_p
);
3575 defsubr (&Swindow_at
);
3576 defsubr (&Swindow_point
);
3577 defsubr (&Swindow_start
);
3578 defsubr (&Swindow_end
);
3579 defsubr (&Sset_window_point
);
3580 defsubr (&Sset_window_start
);
3581 defsubr (&Swindow_dedicated_p
);
3582 defsubr (&Sset_window_dedicated_p
);
3583 defsubr (&Swindow_display_table
);
3584 defsubr (&Sset_window_display_table
);
3585 defsubr (&Snext_window
);
3586 defsubr (&Sprevious_window
);
3587 defsubr (&Sother_window
);
3588 defsubr (&Sget_lru_window
);
3589 defsubr (&Sget_largest_window
);
3590 defsubr (&Sget_buffer_window
);
3591 defsubr (&Sdelete_other_windows
);
3592 defsubr (&Sdelete_windows_on
);
3593 defsubr (&Sreplace_buffer_in_windows
);
3594 defsubr (&Sdelete_window
);
3595 defsubr (&Sset_window_buffer
);
3596 defsubr (&Sselect_window
);
3597 defsubr (&Sdisplay_buffer
);
3598 defsubr (&Ssplit_window
);
3599 defsubr (&Senlarge_window
);
3600 defsubr (&Sshrink_window
);
3601 defsubr (&Sscroll_up
);
3602 defsubr (&Sscroll_down
);
3603 defsubr (&Sscroll_left
);
3604 defsubr (&Sscroll_right
);
3605 defsubr (&Sother_window_for_scrolling
);
3606 defsubr (&Sscroll_other_window
);
3607 defsubr (&Srecenter
);
3608 defsubr (&Smove_to_window_line
);
3609 defsubr (&Swindow_configuration_p
);
3610 defsubr (&Sset_window_configuration
);
3611 defsubr (&Scurrent_window_configuration
);
3612 defsubr (&Ssave_window_excursion
);
3617 initial_define_key (control_x_map
, '1', "delete-other-windows");
3618 initial_define_key (control_x_map
, '2', "split-window");
3619 initial_define_key (control_x_map
, '0', "delete-window");
3620 initial_define_key (control_x_map
, 'o', "other-window");
3621 initial_define_key (control_x_map
, '^', "enlarge-window");
3622 initial_define_key (control_x_map
, '<', "scroll-left");
3623 initial_define_key (control_x_map
, '>', "scroll-right");
3625 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
3626 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
3627 initial_define_key (meta_map
, 'v', "scroll-down");
3629 initial_define_key (global_map
, Ctl('L'), "recenter");
3630 initial_define_key (meta_map
, 'r', "move-to-window-line");