1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
34 Lisp_Object
Fnext_window (), Fdelete_window (), Fselect_window ();
35 Lisp_Object
Fset_window_buffer (), Fsplit_window (), Frecenter ();
37 static void delete_all_subwindows ();
38 static struct window
*decode_window();
40 /* This is the window in which the terminal's cursor should
41 be left when nothing is being done with it. This must
42 always be a leaf window, and its buffer is selected by
43 the top level editing loop at the end of each command.
45 This value is always the same as
46 FRAME_SELECTED_WINDOW (selected_frame). */
48 Lisp_Object selected_window
;
50 /* The minibuffer window of the selected frame.
51 Note that you cannot test for minibufferness of an arbitrary window
52 by comparing against this; but you can test for minibufferness of
53 the selected window. */
54 Lisp_Object minibuf_window
;
56 /* Non-nil means it is the window for C-M-v to scroll
57 when the minibuffer is selected. */
58 Lisp_Object Vminibuf_scroll_window
;
60 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
61 Lisp_Object Vother_window_scroll_buffer
;
63 /* Window that the mouse is over (nil if no mouse support). */
64 Lisp_Object Vmouse_window
;
66 /* Last mouse click data structure (nil if no mouse support). */
67 Lisp_Object Vmouse_event
;
69 /* Non-nil means it's function to call to display temp buffers. */
70 Lisp_Object Vtemp_buffer_show_function
;
72 /* If a window gets smaller than either of these, it is removed. */
73 int window_min_height
;
76 /* Nonzero implies Fdisplay_buffer should create windows. */
79 /* Nonzero implies make new frames for Fdisplay_buffer. */
82 /* Non-nil means use this function instead of default */
83 Lisp_Object Vpop_up_frame_function
;
85 /* Function to call to handle Fdisplay_buffer. */
86 Lisp_Object Vdisplay_buffer_function
;
88 /* Fdisplay_buffer always splits the largest window
89 if that window is more than this high. */
90 int split_height_threshold
;
92 /* Number of lines of continuity in scrolling by screenfuls. */
93 int next_screen_context_lines
;
95 /* Incremented for each window created. */
96 static int sequence_number
;
98 #define min(a, b) ((a) < (b) ? (a) : (b))
100 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
101 "Returns t if OBJ is a window.")
105 return XTYPE (obj
) == Lisp_Window
? Qt
: Qnil
;
111 register Lisp_Object val
;
112 register struct window
*p
;
114 /* Add sizeof (Lisp_Object) here because sizeof (struct Lisp_Vector)
115 includes the first element. */
117 make_number ((sizeof (struct window
) - sizeof (struct Lisp_Vector
)
118 + sizeof (Lisp_Object
))
119 / sizeof (Lisp_Object
)),
121 XSETTYPE (val
, Lisp_Window
);
123 XFASTINT (p
->sequence_number
) = ++sequence_number
;
124 XFASTINT (p
->left
) = XFASTINT (p
->top
)
125 = XFASTINT (p
->height
) = XFASTINT (p
->width
)
126 = XFASTINT (p
->hscroll
) = 0;
127 XFASTINT (p
->last_point_x
) = XFASTINT (p
->last_point_y
) = 0;
128 p
->start
= Fmake_marker ();
129 p
->pointm
= Fmake_marker ();
130 XFASTINT (p
->use_time
) = 0;
132 p
->display_table
= Qnil
;
137 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
138 "Return the window that the cursor now appears in and commands apply to.")
141 return selected_window
;
144 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 0, 0,
145 "Return the window used now for minibuffers.")
149 choose_minibuf_frame ();
150 #endif /* MULTI_FRAME */
151 return minibuf_window
;
154 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 1, 1, 0,
155 "Returns non-nil if WINDOW is a minibuffer window.")
159 struct window
*w
= decode_window (window
);
160 return (MINI_WINDOW_P (w
) ? Qt
: Qnil
);
163 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
164 Spos_visible_in_window_p
, 0, 2, 0,
165 "Return t if position POS is currently on the frame in WINDOW.\n\
166 Returns nil if that position is scrolled vertically out of view.\n\
167 POS defaults to point; WINDOW, to the selected window.")
169 Lisp_Object pos
, window
;
171 register struct window
*w
;
175 register struct buffer
*buf
;
176 struct position posval
;
182 CHECK_NUMBER_COERCE_MARKER (pos
, 0);
187 window
= selected_window
;
189 CHECK_WINDOW (window
, 1);
190 w
= XWINDOW (window
);
191 top
= marker_position (w
->start
);
196 height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
198 buf
= XBUFFER (w
->buffer
);
199 if (XFASTINT (w
->last_modified
) >= BUF_MODIFF (buf
))
201 /* If frame is up to date,
202 use the info recorded about how much text fit on it. */
203 if (posint
< BUF_Z (buf
) - XFASTINT (w
->window_end_pos
)
204 || (XFASTINT (w
->window_end_vpos
) < height
))
210 if (posint
> BUF_Z (buf
))
213 /* If that info is not correct, calculate afresh */
214 posval
= *compute_motion (top
, 0, 0, posint
, height
, 0,
215 XFASTINT (w
->width
) - 1
216 - (XFASTINT (w
->width
) + XFASTINT (w
->left
)
217 != FRAME_WIDTH (XFRAME (w
->frame
))),
218 XINT (w
->hscroll
), 0);
220 return posval
.vpos
< height
? Qt
: Qnil
;
224 static struct window
*
225 decode_window (window
)
226 register Lisp_Object window
;
229 return XWINDOW (selected_window
);
231 CHECK_WINDOW (window
, 0);
232 return XWINDOW (window
);
235 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
236 "Return the buffer that WINDOW is displaying.")
240 return decode_window (window
)->buffer
;
243 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
244 "Return the number of lines in WINDOW (including its mode line).")
248 return decode_window (window
)->height
;
251 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
252 "Return the number of columns in WINDOW.")
256 register struct window
*w
= decode_window (window
);
257 register int width
= w
->width
;
259 /* If this window does not end at the right margin,
260 must deduct one column for the border */
261 if ((width
+ w
->left
) == FRAME_WIDTH (XFRAME (WINDOW_FRAME (w
))))
266 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
267 "Return the number of columns by which WINDOW is scrolled from left margin.")
271 return decode_window (window
)->hscroll
;
274 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
275 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
276 NCOL should be zero or positive.")
278 register Lisp_Object window
, ncol
;
280 register struct window
*w
;
282 CHECK_NUMBER (ncol
, 1);
283 if (XINT (ncol
) < 0) XFASTINT (ncol
) = 0;
284 if (XFASTINT (ncol
) >= (1 << (SHORTBITS
- 1)))
285 args_out_of_range (ncol
, Qnil
);
286 w
= decode_window (window
);
287 if (w
->hscroll
!= ncol
)
288 clip_changed
= 1; /* Prevent redisplay shortcuts */
293 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
294 "Return a list of the edge coordinates of WINDOW.\n\
295 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
296 RIGHT is one more than the rightmost column used by WINDOW,\n\
297 and BOTTOM is one more than the bottommost row used by WINDOW\n\
302 register struct window
*w
= decode_window (window
);
304 return Fcons (w
->left
, Fcons (w
->top
,
305 Fcons (make_number (XFASTINT (w
->left
) + XFASTINT (w
->width
)),
306 Fcons (make_number (XFASTINT (w
->top
)
307 + XFASTINT (w
->height
)),
311 /* Test if the character at column *x, row *y is within window *w.
312 If it is not, return 0;
313 if it is in the window's text area,
314 set *x and *y to its location relative to the upper left corner
317 if it is on the window's modeline, return 2;
318 if it is on the border between the window and its right sibling,
321 coordinates_in_window (w
, x
, y
)
322 register struct window
*w
;
325 register int left
= XINT (w
->left
);
326 register int width
= XINT (w
->width
);
327 register int window_height
= XINT (w
->height
);
328 register int top
= XFASTINT (w
->top
);
330 if ( *x
< left
|| *x
>= left
+ width
331 || *y
< top
|| *y
>= top
+ window_height
)
334 /* Is the character is the mode line? */
335 if (*y
== top
+ window_height
- 1
336 && window_height
> 1) /* 1 line => minibuffer */
339 /* Is the character in the right border? */
340 if (*x
== left
+ width
- 1
341 && left
+ width
!= FRAME_WIDTH (XFRAME (w
->frame
)))
349 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
350 Scoordinates_in_window_p
, 2, 2, 0,
351 "Return non-nil if COORDINATES are in WINDOW.\n\
352 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
353 measured in characters from the upper-left corner of the frame.\n\
354 (0 . 0) denotes the character in the upper left corner of the\n\
356 If COORDINATES are in the text portion of WINDOW,\n\
357 the coordinates relative to the window are returned.\n\
358 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
359 If they are on the border between WINDOW and its right sibling,\n\
360 `vertical-line' is returned.")
361 (coordinates
, window
)
362 register Lisp_Object coordinates
, window
;
366 CHECK_WINDOW (window
, 0);
367 CHECK_CONS (coordinates
, 1);
368 x
= XINT (Fcar (coordinates
));
369 y
= XINT (Fcdr (coordinates
));
371 switch (coordinates_in_window (XWINDOW (window
), &x
, &y
))
373 case 0: /* NOT in window at all. */
376 case 1: /* In text part of window. */
379 case 2: /* In mode line of window. */
382 case 3: /* On right border of window. */
383 return Qvertical_line
;
390 /* Find the window containing column x, row y, and return it as a
391 Lisp_Object. If x, y is on the window's modeline, set *part
392 to 1; if it is on the separating line between the window and its
393 right sibling, set it to 2; otherwise set it to 0. If there is no
394 window under x, y return nil and leave *part unmodified. */
396 window_from_coordinates (frame
, x
, y
, part
)
401 register Lisp_Object tem
, first
;
403 tem
= first
= FRAME_SELECTED_WINDOW (frame
);
407 int found
= coordinates_in_window (XWINDOW (tem
), &x
, &y
);
415 tem
= Fnext_window (tem
, Qt
, Qlambda
);
417 while (! EQ (tem
, first
));
422 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
423 "Return window containing row ROW, column COLUMN on FRAME.\n\
424 If omitted, FRAME defaults to the currently selected frame.\n\
425 The top left corner of the frame is considered to be row 0,\n\
428 Lisp_Object row
, column
, frame
;
434 XSET (frame
, Lisp_Frame
, selected_frame
);
436 CHECK_LIVE_FRAME (frame
, 2);
438 CHECK_NUMBER (row
, 0);
439 CHECK_NUMBER (column
, 1);
441 return window_from_coordinates (XFRAME (frame
),
442 XINT (row
), XINT (column
),
446 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
447 "Return current value of point in WINDOW.\n\
448 For a nonselected window, this is the value point would have\n\
449 if that window were selected.\n\
451 Note that, when WINDOW is the selected window and its buffer\n\
452 is also currently selected, the value returned is the same as (point).\n\
453 It would be more strictly correct to return the `top-level' value\n\
454 of point, outside of any save-excursion forms.\n\
455 But that is hard to define.")
459 register struct window
*w
= decode_window (window
);
461 if (w
== XWINDOW (selected_window
)
462 && current_buffer
== XBUFFER (w
->buffer
))
464 return Fmarker_position (w
->pointm
);
467 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
468 "Return position at which display currently starts in WINDOW.")
472 return Fmarker_position (decode_window (window
)->start
);
475 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 1, 0,
476 "Return position at which display currently ends in WINDOW.")
481 struct window
*w
= decode_window (window
);
483 XSET (value
, Lisp_Int
,
484 BUF_Z (current_buffer
) - XFASTINT (w
->window_end_pos
));
489 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
490 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
492 Lisp_Object window
, pos
;
494 register struct window
*w
= decode_window (window
);
496 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
497 if (w
== XWINDOW (selected_window
))
500 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
505 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
506 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
507 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
508 from overriding motion of point in order to display at this exact start.")
509 (window
, pos
, noforce
)
510 Lisp_Object window
, pos
, noforce
;
512 register struct window
*w
= decode_window (window
);
514 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
515 set_marker_restricted (w
->start
, pos
, w
->buffer
);
516 /* this is not right, but much easier than doing what is right. */
517 w
->start_at_line_beg
= Qnil
;
520 w
->update_mode_line
= Qt
;
521 XFASTINT (w
->last_modified
) = 0;
522 if (!EQ (window
, selected_window
))
523 windows_or_buffers_changed
++;
527 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
529 "Return WINDOW's dedicated object, usually t or nil.\n\
530 See also `set-window-buffer-dedicated'.")
534 return decode_window (window
)->dedicated
;
537 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
538 Sset_window_dedicated_p
, 2, 2, 0,
539 "Control whether WINDOW is dedicated to the buffer it displays.\n\
540 If it is dedicated, Emacs will not automatically change\n\
541 which buffer appears in it.\n\
542 The second argument is the new value for the dedication flag;\n\
545 Lisp_Object window
, arg
;
547 register struct window
*w
= decode_window (window
);
557 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
559 "Return the display-table that WINDOW is using.")
563 return decode_window (window
)->display_table
;
566 /* Get the display table for use currently on window W.
567 This is either W's display table or W's buffer's display table.
568 Ignore the specified tables if they are not valid;
569 if no valid table is specified, return 0. */
572 window_display_table (w
)
576 tem
= w
->display_table
;
577 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
578 return XVECTOR (tem
);
579 tem
= XBUFFER (w
->buffer
)->display_table
;
580 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
581 return XVECTOR (tem
);
582 tem
= Vstandard_display_table
;
583 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
584 return XVECTOR (tem
);
588 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
589 "Set WINDOW's display-table to TABLE.")
591 register Lisp_Object window
, table
;
593 register struct window
*w
;
594 register Lisp_Object z
; /* Return value. */
596 w
= decode_window (window
);
597 w
->display_table
= table
;
601 /* Record info on buffer window w is displaying
602 when it is about to cease to display that buffer. */
605 register struct window
*w
;
607 Lisp_Object buf
= w
->buffer
;
609 if (XBUFFER (buf
) != XMARKER (w
->pointm
)->buffer
)
612 if (w
== XWINDOW (selected_window
)
613 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
614 /* Do this except when the selected window's buffer
615 is being removed from some other window. */
616 XBUFFER (buf
)->last_window_start
= marker_position (w
->start
);
618 /* Point in the selected window's buffer
619 is actually stored in that buffer, and the window's pointm isn't used.
620 So don't clobber point in that buffer. */
621 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
))
622 BUF_PT (XBUFFER (buf
))
623 = clip_to_bounds (BUF_BEGV (XBUFFER (buf
)),
624 marker_position (w
->pointm
),
625 BUF_ZV (XBUFFER (buf
)));
628 /* Put replacement into the window structure in place of old. */
630 replace_window (old
, replacement
)
631 Lisp_Object old
, replacement
;
633 register Lisp_Object tem
;
634 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
636 /* If OLD is its frame's root_window, then replacement is the new
637 root_window for that frame. */
639 if (old
== FRAME_ROOT_WINDOW (XFRAME (o
->frame
)))
640 FRAME_ROOT_WINDOW (XFRAME (o
->frame
)) = replacement
;
645 p
->height
= o
->height
;
647 p
->next
= tem
= o
->next
;
649 XWINDOW (tem
)->prev
= replacement
;
651 p
->prev
= tem
= o
->prev
;
653 XWINDOW (tem
)->next
= replacement
;
655 p
->parent
= tem
= o
->parent
;
658 if (EQ (XWINDOW (tem
)->vchild
, old
))
659 XWINDOW (tem
)->vchild
= replacement
;
660 if (EQ (XWINDOW (tem
)->hchild
, old
))
661 XWINDOW (tem
)->hchild
= replacement
;
664 /*** Here, if replacement is a vertical combination
665 and so is its new parent, we should make replacement's
666 children be children of that parent instead. ***/
669 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
670 "Remove WINDOW from the display. Default is selected window.")
672 register Lisp_Object window
;
674 register Lisp_Object tem
, parent
, sib
;
675 register struct window
*p
;
676 register struct window
*par
;
679 window
= selected_window
;
681 CHECK_WINDOW (window
, 0);
683 p
= XWINDOW (window
);
686 error ("Attempt to delete minibuffer or sole ordinary window");
687 par
= XWINDOW (parent
);
689 windows_or_buffers_changed
++;
691 if (EQ (window
, selected_window
))
692 Fselect_window (Fnext_window (window
, Qnil
, Qnil
));
695 /* tem is null for dummy parent windows
696 (which have inferiors but not any contents themselves) */
700 unchain_marker (p
->pointm
);
701 unchain_marker (p
->start
);
707 XWINDOW (tem
)->prev
= p
->prev
;
711 XWINDOW (tem
)->next
= p
->next
;
713 if (EQ (window
, par
->hchild
))
714 par
->hchild
= p
->next
;
715 if (EQ (window
, par
->vchild
))
716 par
->vchild
= p
->next
;
718 /* Find one of our siblings to give our space to. */
722 /* If p gives its space to its next sibling, that sibling needs
723 to have its top/left side pulled back to where p's is.
724 set_window_{height,width} will re-position the sibling's
727 XFASTINT (XWINDOW (sib
)->top
) = p
->top
;
728 XFASTINT (XWINDOW (sib
)->left
) = p
->left
;
731 /* Stretch that sibling. */
732 if (!NILP (par
->vchild
))
733 set_window_height (sib
,
734 XFASTINT (XWINDOW (sib
)->height
) + XFASTINT (p
->height
),
736 if (!NILP (par
->hchild
))
737 set_window_width (sib
,
738 XFASTINT (XWINDOW (sib
)->width
) + XFASTINT (p
->width
),
741 /* If parent now has only one child,
742 put the child into the parent's place. */
747 if (NILP (XWINDOW (tem
)->next
))
748 replace_window (parent
, tem
);
753 extern Lisp_Object
next_frame (), prev_frame ();
755 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
756 "Return next window after WINDOW in canonical ordering of windows.\n\
757 If omitted, WINDOW defaults to the selected window.\n\
759 Optional second arg MINIBUF t means count the minibuffer window even\n\
760 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
761 it is active. MINIBUF neither t nor nil means not to count the\n\
762 minibuffer even if it is active.\n\
764 Several frames may share a single minibuffer; if the minibuffer\n\
765 counts, all windows on all frames that share that minibuffer count\n\
766 too. This means that next-window may be used to iterate through the\n\
767 set of windows even when the minibuffer is on another frame. If the\n\
768 minibuffer does not count, only windows from WINDOW's frame count.\n\
770 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
771 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
772 above. If neither nil nor t, restrict to WINDOW's frame.")
773 (window
, minibuf
, all_frames
)
774 register Lisp_Object window
, minibuf
, all_frames
;
776 register Lisp_Object tem
;
777 Lisp_Object start_window
;
780 window
= selected_window
;
782 CHECK_WINDOW (window
, 0);
784 start_window
= window
;
786 /* minibuf == nil may or may not include minibuffers.
787 Decide if it does. */
789 minibuf
= (minibuf_level
? Qt
: Qlambda
);
791 /* all_frames == nil doesn't specify which frames to include.
792 Decide which frames it includes. */
793 if (NILP (all_frames
))
794 all_frames
= (EQ (minibuf
, Qt
)
795 ? (FRAME_MINIBUF_WINDOW
798 (XWINDOW (window
)))))
800 else if (! EQ (all_frames
, Qt
))
803 /* Do this loop at least once, to get the next window, and perhaps
804 again, if we hit the minibuffer and that is not acceptable. */
807 /* Find a window that actually has a next one. This loop
808 climbs up the tree. */
809 while (tem
= XWINDOW (window
)->next
, NILP (tem
))
810 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
814 /* We've reached the end of this frame.
815 Which other frames are acceptable? */
816 tem
= WINDOW_FRAME (XWINDOW (window
));
818 if (! NILP (all_frames
))
819 tem
= next_frame (tem
, all_frames
);
821 tem
= FRAME_ROOT_WINDOW (XFRAME (tem
));
828 /* If we're in a combination window, find its first child and
829 recurse on that. Otherwise, we've found the window we want. */
832 if (!NILP (XWINDOW (window
)->hchild
))
833 window
= XWINDOW (window
)->hchild
;
834 else if (!NILP (XWINDOW (window
)->vchild
))
835 window
= XWINDOW (window
)->vchild
;
839 /* Which windows are acceptible?
840 Exit the loop and accept this window if
841 this isn't a minibuffer window, or
842 we're accepting minibuffer windows, or
843 we've come all the way around and we're back at the original window. */
844 while (MINI_WINDOW_P (XWINDOW (window
))
845 && ! EQ (minibuf
, Qt
)
846 && window
!= start_window
);
851 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
852 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
853 If omitted, WINDOW defaults to the selected window.\n\
855 Optional second arg MINIBUF t means count the minibuffer window even\n\
856 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
857 it is active. MINIBUF neither t nor nil means not to count the\n\
858 minibuffer even if it is active.\n\
860 Several frames may share a single minibuffer; if the minibuffer\n\
861 counts, all windows on all frames that share that minibuffer count\n\
862 too. This means that previous-window may be used to iterate through\n\
863 the set of windows even when the minibuffer is on another frame. If\n\
864 the minibuffer does not count, only windows from WINDOW's frame\n\
867 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
868 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
869 above. If neither nil nor t, restrict to WINDOW's frame.")
870 (window
, minibuf
, all_frames
)
871 register Lisp_Object window
, minibuf
, all_frames
;
873 register Lisp_Object tem
;
874 Lisp_Object start_window
;
877 window
= selected_window
;
879 CHECK_WINDOW (window
, 0);
881 start_window
= window
;
883 /* minibuf == nil may or may not include minibuffers.
884 Decide if it does. */
886 minibuf
= (minibuf_level
? Qt
: Qlambda
);
888 /* all_frames == nil doesn't specify which frames to include.
889 Decide which frames it includes. */
890 if (NILP (all_frames
))
891 all_frames
= (EQ (minibuf
, Qt
)
892 ? (FRAME_MINIBUF_WINDOW
895 (XWINDOW (window
)))))
897 else if (! EQ (all_frames
, Qt
))
900 /* Do this loop at least once, to get the previous window, and perhaps
901 again, if we hit the minibuffer and that is not acceptable. */
904 /* Find a window that actually has a previous one. This loop
905 climbs up the tree. */
906 while (tem
= XWINDOW (window
)->prev
, NILP (tem
))
907 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
911 /* We have found the top window on the frame.
912 Which frames are acceptable? */
913 tem
= WINDOW_FRAME (XWINDOW (window
));
915 if (! NILP (all_frames
))
916 tem
= next_frame (tem
, all_frames
);
918 tem
= FRAME_ROOT_WINDOW (XFRAME (tem
));
924 /* If we're in a combination window, find its last child and
925 recurse on that. Otherwise, we've found the window we want. */
928 if (!NILP (XWINDOW (window
)->hchild
))
929 window
= XWINDOW (window
)->hchild
;
930 else if (!NILP (XWINDOW (window
)->vchild
))
931 window
= XWINDOW (window
)->vchild
;
933 while (tem
= XWINDOW (window
)->next
, !NILP (tem
))
937 /* Which windows are acceptable?
938 Exit the loop and accept this window if
939 this isn't a minibuffer window, or
940 we're accepting minibuffer windows, or
941 we've come all the way around and we're back at the original window. */
942 while (MINI_WINDOW_P (XWINDOW (window
))
944 && window
!= start_window
);
949 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
950 "Select the ARG'th different window on this frame.\n\
951 All windows on current frame are arranged in a cyclic order.\n\
952 This command selects the window ARG steps away in that order.\n\
953 A negative ARG moves in the opposite order. If the optional second\n\
954 argument ALL_FRAMES is non-nil, cycle through all frames.")
956 register Lisp_Object n
, all_frames
;
959 register Lisp_Object w
;
967 w
= Fnext_window (w
, Qnil
, all_frames
);
972 w
= Fprevious_window (w
, Qnil
, all_frames
);
979 /* Look at all windows, performing an operation specified by TYPE
981 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
982 frame. If FRAMES is a frame, just look at windows on that frame.
983 If MINI is non-zero, perform the operation on minibuffer windows too.
989 GET_BUFFER_WINDOW
, /* Arg is buffer */
990 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
991 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
992 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
994 UNSHOW_BUFFER
, /* Arg is buffer */
998 window_loop (type
, obj
, mini
, frames
)
999 enum window_loop type
;
1000 register Lisp_Object obj
, frames
;
1003 register Lisp_Object w
;
1004 register Lisp_Object best_window
;
1005 register Lisp_Object next_window
;
1006 register Lisp_Object last_window
;
1010 /* If we're only looping through windows on a particular frame,
1011 frame points to that frame. If we're looping through windows
1012 on all frames, frame is 0. */
1013 if (FRAMEP (frames
))
1014 frame
= XFRAME (frames
);
1015 else if (NILP (frames
))
1016 frame
= selected_frame
;
1023 /* Pick a window to start with. */
1024 if (XTYPE (obj
) == Lisp_Window
)
1027 w
= FRAME_SELECTED_WINDOW (frame
);
1029 w
= FRAME_SELECTED_WINDOW (selected_frame
);
1031 /* Figure out the last window we're going to mess with. Since
1032 Fnext_window, given the same options, is guaranteed to go in a
1033 ring, we can just use Fprevious_window to find the last one.
1035 We can't just wait until we hit the first window again, because
1036 it might be deleted. */
1040 last_window
= Fprevious_window (w
, (mini
? Qt
: Qnil
), Qlambda
);
1042 #endif /* MULTI_FRAME */
1043 /* We know frame is 0, so we're looping through all frames.
1044 Or we know this isn't a MULTI_FRAME Emacs, so who cares? */
1045 last_window
= Fprevious_window (w
, mini
? Qt
: Qnil
, Qt
);
1050 /* Pick the next window now, since some operations will delete
1051 the current window. */
1054 next_window
= Fnext_window (w
, (mini
? Qt
: Qnil
), Qlambda
);
1056 #endif /* MULTI_FRAME */
1057 /* We know frame is 0, so we're looping through all frames.
1058 Or we know this isn't a MULTI_FRAME Emacs, so who cares? */
1059 next_window
= Fnext_window (w
, mini
? Qt
: Qnil
, Qt
);
1061 if (!MINI_WINDOW_P (XWINDOW (w
))
1062 || (mini
&& minibuf_level
> 0))
1065 case GET_BUFFER_WINDOW
:
1067 /* Ignore invisible and iconified frames. */
1068 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w
))))
1069 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w
)))))
1072 if (XBUFFER (XWINDOW (w
)->buffer
) == XBUFFER (obj
))
1076 case GET_LRU_WINDOW
:
1077 /* t as arg means consider only full-width windows */
1078 if (!NILP (obj
) && XFASTINT (XWINDOW (w
)->width
)
1079 != FRAME_WIDTH (frame
))
1082 /* Ignore invisible and iconified frames. */
1083 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w
))))
1084 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w
)))))
1087 /* Ignore dedicated windows and minibuffers. */
1088 if (MINI_WINDOW_P (XWINDOW (w
))
1089 || !NILP (XWINDOW (w
)->dedicated
))
1091 if (NILP (best_window
)
1092 || (XFASTINT (XWINDOW (best_window
)->use_time
)
1093 > XFASTINT (XWINDOW (w
)->use_time
)))
1097 case DELETE_OTHER_WINDOWS
:
1098 if (XWINDOW (w
) != XWINDOW (obj
))
1102 case DELETE_BUFFER_WINDOWS
:
1103 if (EQ (XWINDOW (w
)->buffer
, obj
))
1105 /* If we're deleting the buffer displayed in the only window
1106 on the frame, find a new buffer to display there. */
1107 if (NILP (XWINDOW (w
)->parent
))
1109 Lisp_Object new_buffer
= Fother_buffer (obj
);
1110 if (NILP (new_buffer
))
1112 = Fget_buffer_create (build_string ("*scratch*"));
1113 Fset_window_buffer (w
, new_buffer
);
1114 Fset_buffer (XWINDOW (w
)->buffer
);
1121 case GET_LARGEST_WINDOW
:
1123 /* Ignore invisible and iconified frames. */
1124 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w
))))
1125 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w
)))))
1128 /* Ignore dedicated windows and minibuffers. */
1129 if (MINI_WINDOW_P (XWINDOW (w
))
1130 || !NILP (XWINDOW (w
)->dedicated
))
1133 struct window
*best_window_ptr
= XWINDOW (best_window
);
1134 struct window
*w_ptr
= XWINDOW (w
);
1135 if (NILP (best_window
) ||
1136 (XFASTINT (w_ptr
->height
) * XFASTINT (w_ptr
->width
))
1137 > (XFASTINT (best_window_ptr
->height
)
1138 * XFASTINT (best_window_ptr
->width
)))
1144 if (EQ (XWINDOW (w
)->buffer
, obj
))
1146 /* Find another buffer to show in this window. */
1147 Lisp_Object another_buffer
= Fother_buffer (obj
);
1148 if (NILP (another_buffer
))
1150 = Fget_buffer_create (build_string ("*scratch*"));
1151 Fset_window_buffer (w
, another_buffer
);
1152 if (EQ (w
, selected_window
))
1153 Fset_buffer (XWINDOW (w
)->buffer
);
1158 if (EQ (w
, last_window
))
1167 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 1, 0,
1168 "Return the window least recently selected or used for display.\n\
1169 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1170 frame, search only that frame.\n")
1174 register Lisp_Object w
;
1175 /* First try for a window that is full-width */
1176 w
= window_loop (GET_LRU_WINDOW
, Qt
, 0, frames
);
1177 if (!NILP (w
) && !EQ (w
, selected_window
))
1179 /* If none of them, try the rest */
1180 return window_loop (GET_LRU_WINDOW
, Qnil
, 0, frames
);
1183 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 1, 0,
1184 "Return the largest window in area.\n\
1185 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1186 frame, search only that frame.\n")
1190 return window_loop (GET_LARGEST_WINDOW
, Qnil
, 0,
1194 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 1, 2, 0,
1195 "Return a window currently displaying BUFFER, or nil if none.\n\
1196 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1197 frame, search only that frame.\n")
1199 Lisp_Object buffer
, frame
;
1201 buffer
= Fget_buffer (buffer
);
1202 if (XTYPE (buffer
) == Lisp_Buffer
)
1203 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
1208 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
1210 "Make WINDOW (or the selected window) fill its frame.\n\
1211 Only the frame WINDOW is on is affected.")
1217 struct buffer
*obuf
= current_buffer
;
1221 window
= selected_window
;
1223 CHECK_WINDOW (window
, 0);
1225 w
= XWINDOW (window
);
1226 top
= XFASTINT (w
->top
);
1228 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_FRAME(w
));
1230 Fset_buffer (w
->buffer
);
1231 SET_PT (marker_position (w
->start
));
1232 Frecenter (make_number (top
));
1234 set_buffer_internal (obuf
);
1239 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
1240 1, 1, "bDelete windows on (buffer): ",
1241 "Delete all windows showing BUFFER.")
1247 buffer
= Fget_buffer (buffer
);
1248 CHECK_BUFFER (buffer
, 0);
1249 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, Qt
);
1254 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
1255 Sreplace_buffer_in_windows
,
1256 1, 1, "bReplace buffer in windows: ",
1257 "Replace BUFFER with some other buffer in all windows showing it.")
1263 buffer
= Fget_buffer (buffer
);
1264 CHECK_BUFFER (buffer
, 0);
1265 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
1270 /* Set the height of WINDOW and all its inferiors. */
1272 /* The smallest acceptable dimensions for a window. Anything smaller
1273 might crash Emacs. */
1274 #define MIN_SAFE_WINDOW_WIDTH (2)
1275 #define MIN_SAFE_WINDOW_HEIGHT (2)
1277 /* Make sure that window_min_height and window_min_width are
1278 not too small; if they are, set them to safe minima. */
1281 check_min_window_sizes ()
1283 /* Smaller values might permit a crash. */
1284 if (window_min_width
< MIN_SAFE_WINDOW_WIDTH
)
1285 window_min_width
= MIN_SAFE_WINDOW_WIDTH
;
1286 if (window_min_height
< MIN_SAFE_WINDOW_HEIGHT
)
1287 window_min_height
= MIN_SAFE_WINDOW_HEIGHT
;
1290 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
1291 minimum allowable size. */
1293 check_frame_size (frame
, rows
, cols
)
1297 /* For height, we have to see whether the frame has a minibuffer, and
1298 whether it wants a mode line. */
1300 ((FRAME_MINIBUF_ONLY_P (frame
)
1301 || ! FRAME_HAS_MINIBUF_P (frame
))
1302 ? MIN_SAFE_WINDOW_HEIGHT
1303 : 2 * MIN_SAFE_WINDOW_HEIGHT
- 1);
1305 if (*rows
< min_height
)
1307 if (*cols
< MIN_SAFE_WINDOW_WIDTH
)
1308 *cols
= MIN_SAFE_WINDOW_WIDTH
;
1311 /* Normally the window is deleted if it gets too small.
1312 nodelete nonzero means do not do this.
1313 (The caller should check later and do so if appropriate) */
1315 set_window_height (window
, height
, nodelete
)
1320 register struct window
*w
= XWINDOW (window
);
1321 register struct window
*c
;
1322 int oheight
= XFASTINT (w
->height
);
1323 int top
, pos
, lastbot
, opos
, lastobot
;
1326 check_min_window_sizes ();
1329 && ! NILP (w
->parent
)
1330 && height
< window_min_height
)
1332 Fdelete_window (window
);
1336 XFASTINT (w
->last_modified
) = 0;
1337 windows_or_buffers_changed
++;
1338 XFASTINT (w
->height
) = height
;
1339 if (!NILP (w
->hchild
))
1341 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1343 XWINDOW (child
)->top
= w
->top
;
1344 set_window_height (child
, height
, nodelete
);
1347 else if (!NILP (w
->vchild
))
1349 lastbot
= top
= XFASTINT (w
->top
);
1351 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
1353 c
= XWINDOW (child
);
1355 opos
= lastobot
+ XFASTINT (c
->height
);
1357 XFASTINT (c
->top
) = lastbot
;
1359 pos
= (((opos
* height
) << 1) + oheight
) / (oheight
<< 1);
1361 /* Avoid confusion: inhibit deletion of child if becomes too small */
1362 set_window_height (child
, pos
+ top
- lastbot
, 1);
1364 /* Now advance child to next window,
1365 and set lastbot if child was not just deleted. */
1366 lastbot
= pos
+ top
;
1369 /* Now delete any children that became too small. */
1371 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1373 set_window_height (child
, XINT (XWINDOW (child
)->height
), 0);
1378 /* Recursively set width of WINDOW and its inferiors. */
1380 set_window_width (window
, width
, nodelete
)
1385 register struct window
*w
= XWINDOW (window
);
1386 register struct window
*c
;
1387 int owidth
= XFASTINT (w
->width
);
1388 int left
, pos
, lastright
, opos
, lastoright
;
1391 if (!nodelete
&& width
< window_min_width
)
1393 Fdelete_window (window
);
1397 XFASTINT (w
->last_modified
) = 0;
1398 windows_or_buffers_changed
++;
1399 XFASTINT (w
->width
) = width
;
1400 if (!NILP (w
->vchild
))
1402 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1404 XWINDOW (child
)->left
= w
->left
;
1405 set_window_width (child
, width
, nodelete
);
1408 else if (!NILP (w
->hchild
))
1410 lastright
= left
= XFASTINT (w
->left
);
1412 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
1414 c
= XWINDOW (child
);
1416 opos
= lastoright
+ XFASTINT (c
->width
);
1418 XFASTINT (c
->left
) = lastright
;
1420 pos
= (((opos
* width
) << 1) + owidth
) / (owidth
<< 1);
1422 /* Inhibit deletion for becoming too small */
1423 set_window_width (child
, pos
+ left
- lastright
, 1);
1425 /* Now advance child to next window,
1426 and set lastright if child was not just deleted. */
1427 lastright
= pos
+ left
, lastoright
= opos
;
1429 /* Delete children that became too small */
1431 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1433 set_window_width (child
, XINT (XWINDOW (child
)->width
), 0);
1438 int window_select_count
;
1440 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 2, 0,
1441 "Make WINDOW display BUFFER as its contents.\n\
1442 BUFFER can be a buffer or buffer name.")
1444 register Lisp_Object window
, buffer
;
1446 register Lisp_Object tem
;
1447 register struct window
*w
= decode_window (window
);
1449 buffer
= Fget_buffer (buffer
);
1450 CHECK_BUFFER (buffer
, 1);
1452 if (NILP (XBUFFER (buffer
)->name
))
1453 error ("Attempt to display deleted buffer");
1457 error ("Window is deleted");
1458 else if (! EQ (tem
, Qt
)) /* w->buffer is t when the window
1459 is first being set up. */
1461 if (!NILP (w
->dedicated
) && !EQ (tem
, buffer
))
1462 error ("Window is dedicated to %s\n", tem
);
1468 Fset_marker (w
->pointm
,
1469 make_number (BUF_PT (XBUFFER (buffer
))),
1471 set_marker_restricted (w
->start
,
1472 make_number (XBUFFER (buffer
)->last_window_start
),
1474 w
->start_at_line_beg
= Qnil
;
1475 XFASTINT (w
->last_modified
) = 0;
1476 windows_or_buffers_changed
++;
1477 if (EQ (window
, selected_window
))
1478 Fset_buffer (buffer
);
1483 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 1, 0,
1484 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1485 The main editor command loop selects the buffer of the selected window\n\
1486 before each command.")
1488 register Lisp_Object window
;
1490 register struct window
*w
;
1491 register struct window
*ow
= XWINDOW (selected_window
);
1493 CHECK_WINDOW (window
, 0);
1495 w
= XWINDOW (window
);
1497 if (NILP (w
->buffer
))
1498 error ("Trying to select deleted window or non-leaf window");
1500 XFASTINT (w
->use_time
) = ++window_select_count
;
1501 if (EQ (window
, selected_window
))
1504 Fset_marker (ow
->pointm
, make_number (BUF_PT (XBUFFER (ow
->buffer
))),
1507 selected_window
= window
;
1509 if (XFRAME (WINDOW_FRAME (w
)) != selected_frame
)
1511 XFRAME (WINDOW_FRAME (w
))->selected_window
= window
;
1512 Fselect_frame (WINDOW_FRAME (w
), Qnil
);
1515 selected_frame
->selected_window
= window
;
1518 record_buffer (w
->buffer
);
1519 Fset_buffer (w
->buffer
);
1521 /* Go to the point recorded in the window.
1522 This is important when the buffer is in more
1523 than one window. It also matters when
1524 redisplay_window has altered point after scrolling,
1525 because it makes the change only in the window. */
1527 register int new_point
= marker_position (w
->pointm
);
1528 if (new_point
< BEGV
)
1536 windows_or_buffers_changed
++;
1540 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 2,
1541 "BDisplay buffer:\nP",
1542 "Make BUFFER appear in some window but don't select it.\n\
1543 BUFFER can be a buffer or a buffer name.\n\
1544 If BUFFER is shown already in some window, just use that one,\n\
1545 unless the window is the selected window and the optional second\n\
1546 argument NOT_THIS_WINDOW is non-nil.\n\
1547 Returns the window displaying BUFFER.")
1548 (buffer
, not_this_window
)
1549 register Lisp_Object buffer
, not_this_window
;
1551 register Lisp_Object window
;
1553 buffer
= Fget_buffer (buffer
);
1554 CHECK_BUFFER (buffer
, 0);
1556 if (!NILP (Vdisplay_buffer_function
))
1557 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
1559 if (NILP (not_this_window
)
1560 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
1561 return selected_window
;
1563 window
= Fget_buffer_window (buffer
, Qnil
);
1565 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
1569 /* If there are no frames open that have more than a minibuffer,
1570 we need to create a new frame. */
1571 if (pop_up_frames
|| last_nonminibuf_frame
== 0)
1574 = Fframe_selected_window (call0 (Vpop_up_frame_function
));
1575 Fset_window_buffer (window
, buffer
);
1577 Fselect_frame (XWINDOW (window
)->frame
, Qnil
);
1581 #endif /* MULTI_FRAME */
1585 || FRAME_MINIBUF_ONLY_P (selected_frame
)
1589 Lisp_Object frames
= Qnil
;
1592 if (FRAME_MINIBUF_ONLY_P (selected_frame
))
1593 XSET (frames
, Lisp_Frame
, last_nonminibuf_frame
);
1595 /* Don't try to create a window if would get an error */
1596 if (split_height_threshold
< window_min_height
<< 1)
1597 split_height_threshold
= window_min_height
<< 1;
1599 window
= Fget_largest_window (frames
);
1602 && window_height (window
) >= split_height_threshold
1604 (XFASTINT (XWINDOW (window
)->width
)
1605 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window
))))))
1606 window
= Fsplit_window (window
, Qnil
, Qnil
);
1609 window
= Fget_lru_window (frames
);
1610 if ((EQ (window
, selected_window
)
1611 || EQ (XWINDOW (window
)->parent
, Qnil
))
1612 && window_height (window
) >= window_min_height
<< 1)
1613 window
= Fsplit_window (window
, Qnil
, Qnil
);
1617 window
= Fget_lru_window (Qnil
);
1619 Fset_window_buffer (window
, buffer
);
1624 temp_output_buffer_show (buf
)
1625 register Lisp_Object buf
;
1627 register struct buffer
*old
= current_buffer
;
1628 register Lisp_Object window
;
1629 register struct window
*w
;
1632 XBUFFER (buf
)->save_modified
= MODIFF
;
1637 set_buffer_internal (old
);
1639 if (!EQ (Vtemp_buffer_show_function
, Qnil
))
1640 call1 (Vtemp_buffer_show_function
, buf
);
1643 window
= Fdisplay_buffer (buf
, Qnil
);
1646 if (XFRAME (XWINDOW (window
)->frame
) != selected_frame
)
1647 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
1648 #endif /* MULTI_FRAME */
1649 Vminibuf_scroll_window
= window
;
1650 w
= XWINDOW (window
);
1651 XFASTINT (w
->hscroll
) = 0;
1652 set_marker_restricted (w
->start
, make_number (1), buf
);
1653 set_marker_restricted (w
->pointm
, make_number (1), buf
);
1658 make_dummy_parent (window
)
1661 register Lisp_Object old
, new;
1662 register struct window
*o
, *p
;
1665 XSETTYPE (old
, Lisp_Vector
);
1666 new = Fcopy_sequence (old
);
1667 XSETTYPE (new, Lisp_Window
);
1671 XFASTINT (p
->sequence_number
) = ++sequence_number
;
1673 /* Put new into window structure in place of window */
1674 replace_window (window
, new);
1687 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
1688 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1689 WINDOW defaults to selected one and SIZE to half its size.\n\
1690 If optional third arg HOR-FLAG is non-nil, split side by side\n\
1691 and put SIZE columns in the first of the pair.")
1692 (window
, chsize
, horflag
)
1693 Lisp_Object window
, chsize
, horflag
;
1695 register Lisp_Object
new;
1696 register struct window
*o
, *p
;
1700 window
= selected_window
;
1702 CHECK_WINDOW (window
, 0);
1704 o
= XWINDOW (window
);
1708 if (!NILP (horflag
))
1709 /* Round odd size up, since this is for the left-hand window,
1710 and it will lose a column for the separators. */
1711 size
= ((XFASTINT (o
->width
) + 1) & -2) >> 1;
1713 size
= XFASTINT (o
->height
) >> 1;
1717 CHECK_NUMBER (chsize
, 1);
1718 size
= XINT (chsize
);
1721 if (MINI_WINDOW_P (o
))
1722 error ("Attempt to split minibuffer window");
1723 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o
))))
1724 error ("Attempt to split unsplittable frame");
1726 check_min_window_sizes ();
1730 if (size
< window_min_height
1731 || size
+ window_min_height
> XFASTINT (o
->height
))
1732 args_out_of_range_3 (window
, chsize
, horflag
);
1733 if (NILP (o
->parent
)
1734 || NILP (XWINDOW (o
->parent
)->vchild
))
1736 make_dummy_parent (window
);
1738 XWINDOW (new)->vchild
= window
;
1743 if (size
< window_min_width
1744 || size
+ window_min_width
> XFASTINT (o
->width
))
1745 args_out_of_range_3 (window
, chsize
, horflag
);
1746 if (NILP (o
->parent
)
1747 || NILP (XWINDOW (o
->parent
)->hchild
))
1749 make_dummy_parent (window
);
1751 XWINDOW (new)->hchild
= window
;
1755 /* Now we know that window's parent is a vertical combination
1756 if we are dividing vertically, or a horizontal combination
1757 if we are making side-by-side windows */
1759 windows_or_buffers_changed
++;
1760 new = make_window ();
1763 p
->frame
= o
->frame
;
1765 if (!NILP (p
->next
))
1766 XWINDOW (p
->next
)->prev
= new;
1769 p
->parent
= o
->parent
;
1772 Fset_window_buffer (new, o
->buffer
);
1774 /* Apportion the available frame space among the two new windows */
1776 if (!NILP (horflag
))
1778 p
->height
= o
->height
;
1780 XFASTINT (p
->width
) = XFASTINT (o
->width
) - size
;
1781 XFASTINT (o
->width
) = size
;
1782 XFASTINT (p
->left
) = XFASTINT (o
->left
) + size
;
1787 p
->width
= o
->width
;
1788 XFASTINT (p
->height
) = XFASTINT (o
->height
) - size
;
1789 XFASTINT (o
->height
) = size
;
1790 XFASTINT (p
->top
) = XFASTINT (o
->top
) + size
;
1796 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
1797 "Make current window ARG lines bigger.\n\
1798 From program, optional second arg non-nil means grow sideways ARG columns.")
1800 register Lisp_Object n
, side
;
1802 CHECK_NUMBER (n
, 0);
1803 change_window_height (XINT (n
), !NILP (side
));
1807 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
1808 "Make current window ARG lines smaller.\n\
1809 From program, optional second arg non-nil means shrink sideways ARG columns.")
1811 register Lisp_Object n
, side
;
1813 CHECK_NUMBER (n
, 0);
1814 change_window_height (-XINT (n
), !NILP (side
));
1819 window_height (window
)
1822 register struct window
*p
= XWINDOW (window
);
1823 return XFASTINT (p
->height
);
1827 window_width (window
)
1830 register struct window
*p
= XWINDOW (window
);
1831 return XFASTINT (p
->width
);
1834 #define MINSIZE(w) \
1835 (widthflag ? window_min_width : window_min_height)
1838 *(widthflag ? (int *) &(w)->left : (int *) &(w)->top)
1840 #define CURSIZE(w) \
1841 *(widthflag ? (int *) &(w)->width : (int *) &(w)->height)
1843 /* Unlike set_window_height, this function
1844 also changes the heights of the siblings so as to
1845 keep everything consistent. */
1847 change_window_height (delta
, widthflag
)
1851 register Lisp_Object parent
;
1853 register struct window
*p
;
1855 int (*sizefun
) () = widthflag
? window_width
: window_height
;
1856 register int (*setsizefun
) () = (widthflag
1858 : set_window_height
);
1860 check_min_window_sizes ();
1862 window
= selected_window
;
1865 p
= XWINDOW (window
);
1870 error ("No other window to side of this one");
1873 if (widthflag
? !NILP (XWINDOW (parent
)->hchild
)
1874 : !NILP (XWINDOW (parent
)->vchild
))
1879 sizep
= &CURSIZE (p
);
1881 if (*sizep
+ delta
< MINSIZE (p
)
1882 && !NILP (XWINDOW (window
)->parent
))
1884 Fdelete_window (window
);
1889 register int maxdelta
;
1891 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - *sizep
1892 : !NILP (p
->next
) ? (*sizefun
) (p
->next
) - MINSIZE (p
->next
)
1893 : !NILP (p
->prev
) ? (*sizefun
) (p
->prev
) - MINSIZE (p
->prev
)
1894 /* This is a frame with only one window, a minibuffer-only
1895 or a minibufferless frame. */
1898 if (delta
> maxdelta
)
1899 /* This case traps trying to make the minibuffer
1900 the full frame, or make the only window aside from the
1901 minibuffer the full frame. */
1908 if (!NILP (p
->next
) &&
1909 (*sizefun
) (p
->next
) - delta
>= MINSIZE (p
->next
))
1911 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
) - delta
, 0);
1912 (*setsizefun
) (window
, *sizep
+ delta
, 0);
1913 CURBEG (XWINDOW (p
->next
)) += delta
;
1914 /* This does not change size of p->next,
1915 but it propagates the new top edge to its children */
1916 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
), 0);
1918 else if (!NILP (p
->prev
) &&
1919 (*sizefun
) (p
->prev
) - delta
>= MINSIZE (p
->prev
))
1921 (*setsizefun
) (p
->prev
, (*sizefun
) (p
->prev
) - delta
, 0);
1922 CURBEG (p
) -= delta
;
1923 (*setsizefun
) (window
, *sizep
+ delta
, 0);
1927 register int delta1
;
1928 register int opht
= (*sizefun
) (parent
);
1930 /* If trying to grow this window to or beyond size of the parent,
1931 make delta1 so big that, on shrinking back down,
1932 all the siblings end up with less than one line and are deleted. */
1933 if (opht
<= *sizep
+ delta
)
1934 delta1
= opht
* opht
* 2;
1935 /* Otherwise, make delta1 just right so that if we add delta1
1936 lines to this window and to the parent, and then shrink
1937 the parent back to its original size, the new proportional
1938 size of this window will increase by delta. */
1940 delta1
= (delta
* opht
* 100) / ((opht
- *sizep
- delta
) * 100);
1942 /* Add delta1 lines or columns to this window, and to the parent,
1943 keeping things consistent while not affecting siblings. */
1944 CURSIZE (XWINDOW (parent
)) = opht
+ delta1
;
1945 (*setsizefun
) (window
, *sizep
+ delta1
, 0);
1947 /* Squeeze out delta1 lines or columns from our parent,
1948 shriking this window and siblings proportionately.
1949 This brings parent back to correct size.
1950 Delta1 was calculated so this makes this window the desired size,
1951 taking it all out of the siblings. */
1952 (*setsizefun
) (parent
, opht
, 0);
1955 XFASTINT (p
->last_modified
) = 0;
1962 /* Return number of lines of text (not counting mode line) in W. */
1965 window_internal_height (w
)
1968 int ht
= XFASTINT (w
->height
);
1970 if (MINI_WINDOW_P (w
))
1973 if (!NILP (w
->parent
) || !NILP (w
->vchild
) || !NILP (w
->hchild
)
1974 || !NILP (w
->next
) || !NILP (w
->prev
)
1975 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w
))))
1981 /* Scroll contents of window WINDOW up N lines. */
1984 window_scroll (window
, n
, noerror
)
1989 register struct window
*w
= XWINDOW (window
);
1990 register int opoint
= point
;
1992 register int ht
= window_internal_height (w
);
1993 register Lisp_Object tem
;
1995 Lisp_Object bolp
, nmoved
;
1997 XFASTINT (tem
) = point
;
1998 tem
= Fpos_visible_in_window_p (tem
, window
);
2002 Fvertical_motion (make_number (- ht
/ 2));
2003 XFASTINT (tem
) = point
;
2004 Fset_marker (w
->start
, tem
, w
->buffer
);
2005 w
->force_start
= Qt
;
2008 SET_PT (marker_position (w
->start
));
2009 lose
= n
< 0 && point
== BEGV
;
2010 Fvertical_motion (make_number (n
));
2020 Fsignal (Qbeginning_of_buffer
, Qnil
);
2025 set_marker_restricted (w
->start
, make_number (pos
), w
->buffer
);
2026 w
->start_at_line_beg
= bolp
;
2027 w
->update_mode_line
= Qt
;
2028 XFASTINT (w
->last_modified
) = 0;
2034 tem
= Fvertical_motion (make_number (ht
));
2035 if (point
> opoint
|| XFASTINT (tem
) < ht
)
2038 Fvertical_motion (make_number (-1));
2046 Fsignal (Qend_of_buffer
, Qnil
);
2050 /* This is the guts of Fscroll_up and Fscroll_down. */
2053 scroll_command (n
, direction
)
2054 register Lisp_Object n
;
2057 register int defalt
;
2058 int count
= specpdl_ptr
- specpdl
;
2060 /* If selected window's buffer isn't current, make it current for the moment.
2061 But don't screw up if window_scroll gets an error. */
2062 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
2064 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2065 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2068 defalt
= (window_internal_height (XWINDOW (selected_window
))
2069 - next_screen_context_lines
);
2070 defalt
= direction
* (defalt
< 1 ? 1 : defalt
);
2073 window_scroll (selected_window
, defalt
, 0);
2074 else if (EQ (n
, Qminus
))
2075 window_scroll (selected_window
, - defalt
, 0);
2078 n
= Fprefix_numeric_value (n
);
2079 window_scroll (selected_window
, XINT (n
) * direction
, 0);
2082 unbind_to (count
, Qnil
);
2085 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "P",
2086 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2087 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2088 When calling from a program, supply a number as argument or nil.")
2092 scroll_command (n
, 1);
2096 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "P",
2097 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2098 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2099 When calling from a program, supply a number as argument or nil.")
2103 scroll_command (n
, -1);
2107 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
2108 "Scroll text of next window upward ARG lines; or near full screen if no ARG.\n\
2109 The next window is the one below the current one; or the one at the top\n\
2110 if the current one is at the bottom.\n\
2111 When calling from a program, supply a number as argument or nil.\n\
2113 If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
2114 specifies the window to scroll.\n\
2115 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2116 showing that buffer, popping the buffer up if necessary.")
2118 register Lisp_Object n
;
2120 register Lisp_Object window
;
2122 register struct window
*w
;
2123 register int count
= specpdl_ptr
- specpdl
;
2125 if (MINI_WINDOW_P (XWINDOW (selected_window
))
2126 && !NILP (Vminibuf_scroll_window
))
2127 window
= Vminibuf_scroll_window
;
2128 /* If buffer is specified, scroll that buffer. */
2129 else if (!NILP (Vother_window_scroll_buffer
))
2131 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
2133 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
);
2136 /* Nothing specified; pick a neighboring window. */
2137 window
= Fnext_window (selected_window
, Qnil
, Qt
);
2138 CHECK_WINDOW (window
, 0);
2140 if (EQ (window
, selected_window
))
2141 error ("There is no other window");
2143 w
= XWINDOW (window
);
2144 ht
= window_internal_height (w
);
2146 /* Don't screw up if window_scroll gets an error. */
2147 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2149 Fset_buffer (w
->buffer
);
2150 SET_PT (marker_position (w
->pointm
));
2153 window_scroll (window
, ht
- next_screen_context_lines
, 1);
2154 else if (EQ (n
, Qminus
))
2155 window_scroll (window
, next_screen_context_lines
- ht
, 1);
2158 if (XTYPE (n
) == Lisp_Cons
)
2160 CHECK_NUMBER (n
, 0);
2161 window_scroll (window
, XINT (n
), 1);
2164 Fset_marker (w
->pointm
, make_number (point
), Qnil
);
2170 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 1, 1, "P",
2171 "Scroll selected window display ARG columns left.\n\
2172 Default for ARG is window width minus 2.")
2174 register Lisp_Object arg
;
2178 XFASTINT (arg
) = XFASTINT (XWINDOW (selected_window
)->width
) - 2;
2180 arg
= Fprefix_numeric_value (arg
);
2183 Fset_window_hscroll (selected_window
,
2184 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2188 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 1, 1, "P",
2189 "Scroll selected window display ARG columns right.\n\
2190 Default for ARG is window width minus 2.")
2192 register Lisp_Object arg
;
2195 XFASTINT (arg
) = XFASTINT (XWINDOW (selected_window
)->width
) - 2;
2197 arg
= Fprefix_numeric_value (arg
);
2200 Fset_window_hscroll (selected_window
,
2201 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2205 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
2206 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
2207 The desired position of point is always relative to the current window.\n\
2208 Just C-u as prefix means put point in the center of the window.\n\
2209 No arg (i.e., it is nil) erases the entire frame and then\n\
2210 redraws with point in the center of the current window.")
2212 register Lisp_Object n
;
2214 register struct window
*w
= XWINDOW (selected_window
);
2215 register int ht
= window_internal_height (w
);
2216 register int opoint
= point
;
2220 extern int frame_garbaged
;
2222 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w
)));
2223 XFASTINT (n
) = ht
/ 2;
2225 else if (XTYPE (n
) == Lisp_Cons
) /* Just C-u. */
2227 XFASTINT (n
) = ht
/ 2;
2231 n
= Fprefix_numeric_value (n
);
2232 CHECK_NUMBER (n
, 0);
2236 XSETINT (n
, XINT (n
) + ht
);
2238 XSETINT (n
, - XINT (n
));
2240 Fvertical_motion (n
);
2241 Fset_marker (w
->start
, make_number (point
), w
->buffer
);
2242 w
->start_at_line_beg
= Fbolp ();
2245 w
->force_start
= Qt
;
2250 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
2252 "Position point relative to window.\n\
2253 With no argument, position text at center of window.\n\
2254 An argument specifies frame line; zero means top of window,\n\
2255 negative means relative to bottom of window.")
2257 register Lisp_Object arg
;
2259 register struct window
*w
= XWINDOW (selected_window
);
2260 register int height
= window_internal_height (w
);
2264 XFASTINT (arg
) = height
/ 2;
2267 arg
= Fprefix_numeric_value (arg
);
2269 XSETINT (arg
, XINT (arg
) + height
);
2272 start
= marker_position (w
->start
);
2273 if (start
< BEGV
|| start
> ZV
)
2275 Fvertical_motion (make_number (- height
/ 2));
2276 Fset_marker (w
->start
, make_number (point
), w
->buffer
);
2277 w
->start_at_line_beg
= Fbolp ();
2278 w
->force_start
= Qt
;
2283 return Fvertical_motion (arg
);
2286 struct save_window_data
2288 int size_from_Lisp_Vector_struct
;
2289 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2290 Lisp_Object frame_width
, frame_height
;
2291 Lisp_Object current_window
;
2292 Lisp_Object current_buffer
;
2293 Lisp_Object minibuf_scroll_window
;
2294 Lisp_Object root_window
;
2295 /* A vector, interpreted as a struct saved_window */
2296 Lisp_Object saved_windows
;
2298 #define SAVE_WINDOW_DATA_SIZE 7 /* Arg to Fmake_vector */
2300 /* This is saved as a Lisp_Vector */
2303 /* these first two must agree with struct Lisp_Vector in lisp.h */
2304 int size_from_Lisp_Vector_struct
;
2305 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2308 Lisp_Object buffer
, start
, pointm
, mark
;
2309 Lisp_Object left
, top
, width
, height
, hscroll
;
2310 Lisp_Object parent
, prev
;
2311 Lisp_Object start_at_line_beg
;
2312 Lisp_Object display_table
;
2314 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2316 #define SAVED_WINDOW_N(swv,n) \
2317 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2319 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
2320 "T if OBJECT is a window-configration object.")
2324 if (XTYPE (obj
) == Lisp_Window_Configuration
)
2330 DEFUN ("set-window-configuration",
2331 Fset_window_configuration
, Sset_window_configuration
,
2333 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2334 CONFIGURATION must be a value previously returned\n\
2335 by `current-window-configuration' (which see).")
2339 register struct window
*w
;
2340 register struct save_window_data
*data
;
2341 struct Lisp_Vector
*saved_windows
;
2342 register struct saved_window
*p
;
2343 register Lisp_Object tem
;
2344 Lisp_Object new_current_buffer
;
2348 while (XTYPE (arg
) != Lisp_Window_Configuration
)
2350 arg
= wrong_type_argument (intern ("window-configuration-p"), arg
);
2353 data
= (struct save_window_data
*) XVECTOR (arg
);
2354 saved_windows
= XVECTOR (data
->saved_windows
);
2356 f
= XFRAME (XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
);
2358 if (XFASTINT (data
->frame_height
) != FRAME_HEIGHT (f
)
2359 || XFASTINT (data
->frame_width
) != FRAME_WIDTH (f
))
2361 /* Presumably something clever could be done.
2362 However, it doesn't seem worth the effort */
2363 error ("Frame size %dx%d in saved window configuration mismatches frame.",
2364 XFASTINT (data
->frame_height
),
2365 XFASTINT (data
->frame_width
));
2368 windows_or_buffers_changed
++;
2369 new_current_buffer
= data
->current_buffer
;
2370 if (NILP (XBUFFER (new_current_buffer
)->name
))
2371 new_current_buffer
= Qnil
;
2373 /* Mark all windows now on frame as "deleted".
2374 Restoring the new configuration "undeletes" any that are in it. */
2376 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2378 /* This loses when the minibuf frame is not f. */
2379 delete_all_subwindows (XWINDOW (XWINDOW (minibuf_window
)->prev
));
2382 for (k
= 0; k
< saved_windows
->size
; k
++)
2384 p
= SAVED_WINDOW_N (saved_windows
, k
);
2385 w
= XWINDOW (p
->window
);
2388 if (!NILP (p
->parent
))
2389 w
->parent
= SAVED_WINDOW_N (saved_windows
, XFASTINT (p
->parent
))->window
;
2393 if (!NILP (p
->prev
))
2395 w
->prev
= SAVED_WINDOW_N (saved_windows
, XFASTINT (p
->prev
))->window
;
2397 /* This is true for a minibuffer-only frame. */
2398 if (w
->mini_p
&& EQ (w
->prev
, p
->window
))
2401 #endif /* MULTI_FRAME */
2402 XWINDOW (w
->prev
)->next
= p
->window
;
2407 if (!NILP (w
->parent
))
2409 if (EQ (p
->width
, XWINDOW (w
->parent
)->width
))
2411 XWINDOW (w
->parent
)->vchild
= p
->window
;
2412 XWINDOW (w
->parent
)->hchild
= Qnil
;
2416 XWINDOW (w
->parent
)->hchild
= p
->window
;
2417 XWINDOW (w
->parent
)->vchild
= Qnil
;
2423 w
->width
= p
->width
;
2424 w
->height
= p
->height
;
2425 w
->hscroll
= p
->hscroll
;
2426 w
->display_table
= p
->display_table
;
2427 XFASTINT (w
->last_modified
) = 0;
2429 /* Reinstall the saved buffer and pointers into it. */
2430 if (NILP (p
->buffer
))
2431 w
->buffer
= p
->buffer
;
2434 if (!NILP (XBUFFER (p
->buffer
)->name
))
2435 /* If saved buffer is alive, install it. */
2437 w
->buffer
= p
->buffer
;
2438 w
->start_at_line_beg
= p
->start_at_line_beg
;
2439 set_marker_restricted (w
->start
, Fmarker_position (p
->start
), w
->buffer
);
2440 set_marker_restricted (w
->pointm
, Fmarker_position (p
->pointm
), w
->buffer
);
2441 Fset_marker (XBUFFER (w
->buffer
)->mark
,
2442 Fmarker_position (p
->mark
), w
->buffer
);
2444 if (!EQ (p
->buffer
, new_current_buffer
) &&
2445 XBUFFER (p
->buffer
) == current_buffer
)
2446 Fgoto_char (w
->pointm
);
2448 else if (NILP (XBUFFER (w
->buffer
)->name
))
2449 /* Else if window's old buffer is dead too, get a live one. */
2451 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
2452 /* This will set the markers to beginning of visible range. */
2453 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
2454 set_marker_restricted (w
->pointm
, make_number (0), w
->buffer
);
2455 w
->start_at_line_beg
= Qt
;
2458 /* Keeping window's old buffer; make sure the markers are real. */
2459 /* Else if window's old buffer is dead too, get a live one. */
2461 /* Set window markers at start of visible range. */
2462 if (XMARKER (w
->start
)->buffer
== 0)
2463 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
2464 if (XMARKER (w
->pointm
)->buffer
== 0)
2465 set_marker_restricted (w
->pointm
,
2466 make_number (BUF_PT (XBUFFER (w
->buffer
))),
2468 w
->start_at_line_beg
= Qt
;
2473 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
2476 if (f
!= selected_frame
&& ! FRAME_TERMCAP_P (f
))
2477 Fselect_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)), Qnil
);
2480 if (f
== selected_frame
)
2482 Fselect_window (data
->current_window
);
2483 if (!NILP (new_current_buffer
))
2484 Fset_buffer (new_current_buffer
);
2486 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2489 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
2493 /* Mark all windows now on frame as deleted
2494 by setting their buffers to nil. */
2497 delete_all_subwindows (w
)
2498 register struct window
*w
;
2500 register int count
= 1;
2502 if (!NILP (w
->next
))
2503 delete_all_subwindows (XWINDOW (w
->next
));
2504 if (!NILP (w
->vchild
))
2505 delete_all_subwindows (XWINDOW (w
->vchild
));
2506 if (!NILP (w
->hchild
))
2507 delete_all_subwindows (XWINDOW (w
->hchild
));
2511 count_windows (window
)
2512 register struct window
*window
;
2514 register int count
= 1;
2515 if (!NILP (window
->next
))
2516 count
+= count_windows (XWINDOW (window
->next
));
2517 if (!NILP (window
->vchild
))
2518 count
+= count_windows (XWINDOW (window
->vchild
));
2519 if (!NILP (window
->hchild
))
2520 count
+= count_windows (XWINDOW (window
->hchild
));
2525 save_window_save (window
, vector
, i
)
2527 struct Lisp_Vector
*vector
;
2530 register struct saved_window
*p
;
2531 register struct window
*w
;
2532 register Lisp_Object tem
;
2534 for (;!NILP (window
); window
= w
->next
)
2536 p
= SAVED_WINDOW_N (vector
, i
);
2537 w
= XWINDOW (window
);
2539 XFASTINT (w
->temslot
) = i
++;
2541 p
->buffer
= w
->buffer
;
2544 p
->width
= w
->width
;
2545 p
->height
= w
->height
;
2546 p
->hscroll
= w
->hscroll
;
2547 p
->display_table
= w
->display_table
;
2548 if (!NILP (w
->buffer
))
2550 /* Save w's value of point in the window configuration.
2551 If w is the selected window, then get the value of point
2552 from the buffer; pointm is garbage in the selected window. */
2553 if (EQ (window
, selected_window
))
2555 p
->pointm
= Fmake_marker ();
2556 Fset_marker (p
->pointm
, BUF_PT (XBUFFER (w
->buffer
)),
2560 p
->pointm
= Fcopy_marker (w
->pointm
);
2562 p
->start
= Fcopy_marker (w
->start
);
2563 p
->start_at_line_beg
= w
->start_at_line_beg
;
2565 tem
= XBUFFER (w
->buffer
)->mark
;
2566 p
->mark
= Fcopy_marker (tem
);
2573 p
->start_at_line_beg
= Qnil
;
2576 if (NILP (w
->parent
))
2579 p
->parent
= XWINDOW (w
->parent
)->temslot
;
2584 p
->prev
= XWINDOW (w
->prev
)->temslot
;
2586 if (!NILP (w
->vchild
))
2587 i
= save_window_save (w
->vchild
, vector
, i
);
2588 if (!NILP (w
->hchild
))
2589 i
= save_window_save (w
->hchild
, vector
, i
);
2595 DEFUN ("current-window-configuration",
2596 Fcurrent_window_configuration
, Scurrent_window_configuration
, 0, 1, 0,
2597 "Return an object representing the current window configuration of FRAME.\n\
2598 If FRAME is nil or omitted, use the selected frame.\n\
2599 This describes the number of windows, their sizes and current buffers,\n\
2600 and for each displayed buffer, where display starts, and the positions of\n\
2601 point and mark. An exception is made for point in the current buffer:\n\
2602 its value is -not- saved.")
2606 register Lisp_Object tem
;
2607 register int n_windows
;
2608 register struct save_window_data
*data
;
2616 CHECK_LIVE_FRAME (frame
, 0);
2620 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2621 data
= (struct save_window_data
*)
2622 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE
),
2624 XFASTINT (data
->frame_width
) = FRAME_WIDTH (f
);
2625 XFASTINT (data
->frame_height
) = FRAME_HEIGHT (f
);
2626 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
2627 XSET (data
->current_buffer
, Lisp_Buffer
, current_buffer
);
2628 data
->minibuf_scroll_window
= Vminibuf_scroll_window
;
2629 data
->root_window
= FRAME_ROOT_WINDOW (f
);
2630 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
2631 data
->saved_windows
= tem
;
2632 for (i
= 0; i
< n_windows
; i
++)
2633 XVECTOR (tem
)->contents
[i
]
2634 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE
), Qnil
);
2635 save_window_save (FRAME_ROOT_WINDOW (f
),
2637 XSET (tem
, Lisp_Window_Configuration
, data
);
2641 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
2643 "Execute body, preserving window sizes and contents.\n\
2644 Restores which buffer appears in which window, where display starts,\n\
2645 as well as the current buffer.\n\
2646 Does not restore the value of point in current buffer.")
2650 register Lisp_Object val
;
2651 register int count
= specpdl_ptr
- specpdl
;
2653 record_unwind_protect (Fset_window_configuration
,
2654 Fcurrent_window_configuration (Qnil
));
2655 val
= Fprogn (args
);
2656 return unbind_to (count
, val
);
2662 selected_frame
= make_terminal_frame ();
2663 minibuf_window
= selected_frame
->minibuffer_window
;
2664 selected_window
= selected_frame
->selected_window
;
2665 last_nonminibuf_frame
= selected_frame
;
2666 #else /* not MULTI_FRAME */
2667 extern Lisp_Object
get_minibuffer ();
2669 minibuf_window
= make_window ();
2670 FRAME_ROOT_WINDOW (selected_frame
) = make_window ();
2672 XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->next
= minibuf_window
;
2673 XWINDOW (minibuf_window
)->prev
= FRAME_ROOT_WINDOW (selected_frame
);
2674 XWINDOW (minibuf_window
)->mini_p
= Qt
;
2676 /* These values 9 and 10 are arbitrary,
2677 just so that there is "something there."
2678 Correct values are put in in init_xdisp */
2680 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->width
) = 10;
2681 XFASTINT (XWINDOW (minibuf_window
)->width
) = 10;
2683 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->height
) = 9;
2684 XFASTINT (XWINDOW (minibuf_window
)->top
) = 9;
2685 XFASTINT (XWINDOW (minibuf_window
)->height
) = 1;
2687 /* Prevent error in Fset_window_buffer. */
2688 XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->buffer
= Qt
;
2689 XWINDOW (minibuf_window
)->buffer
= Qt
;
2691 /* Now set them up for real. */
2692 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame
),
2693 Fcurrent_buffer ());
2694 Fset_window_buffer (minibuf_window
, get_minibuffer (0));
2696 selected_window
= FRAME_ROOT_WINDOW (selected_frame
);
2697 /* Make sure this window seems more recently used than
2698 a newly-created, never-selected window. Increment
2699 window_select_count so the first selection ever will get
2700 something newer than this. */
2701 XFASTINT (XWINDOW (selected_window
)->use_time
) = ++window_select_count
;
2702 #endif /* not MULTI_FRAME */
2707 Qwindowp
= intern ("windowp");
2708 staticpro (&Qwindowp
);
2710 /* Make sure all windows get marked */
2711 staticpro (&minibuf_window
);
2713 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
2714 "Non-nil means call as function to display a help buffer.\n\
2715 Used by `with-output-to-temp-buffer'.");
2716 Vtemp_buffer_show_function
= Qnil
;
2718 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
2719 "If non-nil, function to call to handle `display-buffer'.\n\
2720 It will receive two args, the buffer and a flag which if non-nil means\n\
2721 that the currently selected window is not acceptable.\n\
2722 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
2723 work using this function.");
2724 Vdisplay_buffer_function
= Qnil
;
2726 DEFVAR_LISP ("mouse-window", &Vmouse_window
,
2727 "Window that the last mouse click occurred on.");
2728 Vmouse_window
= Qnil
;
2730 DEFVAR_LISP ("mouse-event", &Vmouse_event
,
2731 "The last mouse-event object. A list of four elements:\n\
2732 ((X-POS Y-POS) WINDOW FRAME-PART KEYSEQ).\n\
2733 KEYSEQ is a string, the key sequence to be looked up in the mouse maps.\n\
2734 WINDOW is the window that the click applies do.\n\
2735 If FRAME-PART is non-nil, the event was on a scrollbar;\n\
2736 then Y-POS is really the total length of the scrollbar, while X-POS is\n\
2737 the relative position of the scrollbar's value within that total length.\n\
2738 FRAME-PART is one of the following symbols:\n\
2739 `vertical-scrollbar', `vertical-slider',\n\
2740 `vertical-thumbup', `vertical-thumbdown',\n\
2741 `horizontal-scrollbar', `horizontal-slider',\n\
2742 `horizontal-thumbleft', `horizontal-thumbright'");
2743 Vmouse_event
= Qnil
;
2745 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
2746 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
2747 Vminibuf_scroll_window
= Qnil
;
2749 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
2750 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
2751 Vother_window_scroll_buffer
= Qnil
;
2754 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames
,
2755 "*Non-nil means `display-buffer' should make a separate frame.");
2758 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function
,
2759 "*If non-nil, function to call to handle automatic new frame creation.\n\
2760 It is called with no arguments and should return a newly created frame.\n\
2762 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
2763 where `pop-up-frame-alist' would hold the default frame parameters.");
2764 Vpop_up_frame_function
= Qnil
;
2767 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
2768 "*Non-nil means display-buffer should make new windows.");
2771 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
2772 "*Number of lines of continuity when scrolling by screenfuls.");
2773 next_screen_context_lines
= 2;
2775 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
2776 "*display-buffer would prefer to split the largest window if this large.\n\
2777 If there is only one window, it is split regardless of this value.");
2778 split_height_threshold
= 500;
2780 DEFVAR_INT ("window-min-height", &window_min_height
,
2781 "*Delete any window less than this tall (including its mode line).");
2782 window_min_height
= 4;
2784 DEFVAR_INT ("window-min-width", &window_min_width
,
2785 "*Delete any window less than this wide.");
2786 window_min_width
= 10;
2788 defsubr (&Sselected_window
);
2789 defsubr (&Sminibuffer_window
);
2790 defsubr (&Swindow_minibuffer_p
);
2791 defsubr (&Swindowp
);
2792 defsubr (&Spos_visible_in_window_p
);
2793 defsubr (&Swindow_buffer
);
2794 defsubr (&Swindow_height
);
2795 defsubr (&Swindow_width
);
2796 defsubr (&Swindow_hscroll
);
2797 defsubr (&Sset_window_hscroll
);
2798 defsubr (&Swindow_edges
);
2799 defsubr (&Scoordinates_in_window_p
);
2800 defsubr (&Swindow_at
);
2801 defsubr (&Swindow_point
);
2802 defsubr (&Swindow_start
);
2803 defsubr (&Swindow_end
);
2804 defsubr (&Sset_window_point
);
2805 defsubr (&Sset_window_start
);
2806 defsubr (&Swindow_dedicated_p
);
2807 defsubr (&Sset_window_dedicated_p
);
2808 defsubr (&Swindow_display_table
);
2809 defsubr (&Sset_window_display_table
);
2810 defsubr (&Snext_window
);
2811 defsubr (&Sprevious_window
);
2812 defsubr (&Sother_window
);
2813 defsubr (&Sget_lru_window
);
2814 defsubr (&Sget_largest_window
);
2815 defsubr (&Sget_buffer_window
);
2816 defsubr (&Sdelete_other_windows
);
2817 defsubr (&Sdelete_windows_on
);
2818 defsubr (&Sreplace_buffer_in_windows
);
2819 defsubr (&Sdelete_window
);
2820 defsubr (&Sset_window_buffer
);
2821 defsubr (&Sselect_window
);
2822 defsubr (&Sdisplay_buffer
);
2823 defsubr (&Ssplit_window
);
2824 defsubr (&Senlarge_window
);
2825 defsubr (&Sshrink_window
);
2826 defsubr (&Sscroll_up
);
2827 defsubr (&Sscroll_down
);
2828 defsubr (&Sscroll_left
);
2829 defsubr (&Sscroll_right
);
2830 defsubr (&Sscroll_other_window
);
2831 defsubr (&Srecenter
);
2832 defsubr (&Smove_to_window_line
);
2833 defsubr (&Swindow_configuration_p
);
2834 defsubr (&Sset_window_configuration
);
2835 defsubr (&Scurrent_window_configuration
);
2836 defsubr (&Ssave_window_excursion
);
2841 initial_define_key (control_x_map
, '1', "delete-other-windows");
2842 initial_define_key (control_x_map
, '2', "split-window");
2843 initial_define_key (control_x_map
, '0', "delete-window");
2844 initial_define_key (control_x_map
, 'o', "other-window");
2845 initial_define_key (control_x_map
, '^', "enlarge-window");
2846 initial_define_key (control_x_map
, '<', "scroll-left");
2847 initial_define_key (control_x_map
, '>', "scroll-right");
2849 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
2850 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
2851 initial_define_key (meta_map
, 'v', "scroll-down");
2853 initial_define_key (global_map
, Ctl('L'), "recenter");
2854 initial_define_key (meta_map
, 'r', "move-to-window-line");