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, 1, 0,
145 "Return the window used now for minibuffers.\n\
146 If the optional argument FRAME is specified, return the minibuffer window\n\
147 used by that frame.")
153 XSET (frame
, Lisp_Frame
, selected_frame
);
155 CHECK_LIVE_FRAME (frame
, 0);
158 return FRAME_MINIBUF_WINDOW (XFRAME (frame
));
161 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 1, 1, 0,
162 "Returns non-nil if WINDOW is a minibuffer window.")
166 struct window
*w
= decode_window (window
);
167 return (MINI_WINDOW_P (w
) ? Qt
: Qnil
);
170 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
171 Spos_visible_in_window_p
, 0, 2, 0,
172 "Return t if position POS is currently on the frame in WINDOW.\n\
173 Returns nil if that position is scrolled vertically out of view.\n\
174 POS defaults to point; WINDOW, to the selected window.")
176 Lisp_Object pos
, window
;
178 register struct window
*w
;
182 register struct buffer
*buf
;
183 struct position posval
;
189 CHECK_NUMBER_COERCE_MARKER (pos
, 0);
194 window
= selected_window
;
196 CHECK_WINDOW (window
, 1);
197 w
= XWINDOW (window
);
198 top
= marker_position (w
->start
);
203 height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
205 buf
= XBUFFER (w
->buffer
);
206 if (XFASTINT (w
->last_modified
) >= BUF_MODIFF (buf
))
208 /* If frame is up to date,
209 use the info recorded about how much text fit on it. */
210 if (posint
< BUF_Z (buf
) - XFASTINT (w
->window_end_pos
)
211 || (XFASTINT (w
->window_end_vpos
) < height
))
217 if (posint
> BUF_Z (buf
))
220 /* If that info is not correct, calculate afresh */
221 posval
= *compute_motion (top
, 0, 0, posint
, height
, 0,
222 XFASTINT (w
->width
) - 1
223 - (XFASTINT (w
->width
) + XFASTINT (w
->left
)
224 != FRAME_WIDTH (XFRAME (w
->frame
))),
225 XINT (w
->hscroll
), 0);
227 return posval
.vpos
< height
? Qt
: Qnil
;
231 static struct window
*
232 decode_window (window
)
233 register Lisp_Object window
;
236 return XWINDOW (selected_window
);
238 CHECK_WINDOW (window
, 0);
239 return XWINDOW (window
);
242 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
243 "Return the buffer that WINDOW is displaying.")
247 return decode_window (window
)->buffer
;
250 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
251 "Return the number of lines in WINDOW (including its mode line).")
255 return decode_window (window
)->height
;
258 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
259 "Return the number of columns in WINDOW.")
263 register struct window
*w
= decode_window (window
);
264 register int width
= w
->width
;
266 /* If this window does not end at the right margin,
267 must deduct one column for the border */
268 if ((width
+ w
->left
) == FRAME_WIDTH (XFRAME (WINDOW_FRAME (w
))))
273 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
274 "Return the number of columns by which WINDOW is scrolled from left margin.")
278 return decode_window (window
)->hscroll
;
281 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
282 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
283 NCOL should be zero or positive.")
285 register Lisp_Object window
, ncol
;
287 register struct window
*w
;
289 CHECK_NUMBER (ncol
, 1);
290 if (XINT (ncol
) < 0) XFASTINT (ncol
) = 0;
291 if (XFASTINT (ncol
) >= (1 << (SHORTBITS
- 1)))
292 args_out_of_range (ncol
, Qnil
);
293 w
= decode_window (window
);
294 if (w
->hscroll
!= ncol
)
295 clip_changed
= 1; /* Prevent redisplay shortcuts */
300 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
301 "Return a list of the edge coordinates of WINDOW.\n\
302 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
303 RIGHT is one more than the rightmost column used by WINDOW,\n\
304 and BOTTOM is one more than the bottommost row used by WINDOW\n\
309 register struct window
*w
= decode_window (window
);
311 return Fcons (w
->left
, Fcons (w
->top
,
312 Fcons (make_number (XFASTINT (w
->left
) + XFASTINT (w
->width
)),
313 Fcons (make_number (XFASTINT (w
->top
)
314 + XFASTINT (w
->height
)),
318 /* Test if the character at column *x, row *y is within window *w.
319 If it is not, return 0;
320 if it is in the window's text area,
321 set *x and *y to its location relative to the upper left corner
324 if it is on the window's modeline, return 2;
325 if it is on the border between the window and its right sibling,
328 coordinates_in_window (w
, x
, y
)
329 register struct window
*w
;
332 register int left
= XINT (w
->left
);
333 register int width
= XINT (w
->width
);
334 register int window_height
= XINT (w
->height
);
335 register int top
= XFASTINT (w
->top
);
337 if ( *x
< left
|| *x
>= left
+ width
338 || *y
< top
|| *y
>= top
+ window_height
)
341 /* Is the character is the mode line? */
342 if (*y
== top
+ window_height
- 1
343 && ! MINI_WINDOW_P (w
))
346 /* Is the character in the right border? */
347 if (*x
== left
+ width
- 1
348 && left
+ width
!= FRAME_WIDTH (XFRAME (w
->frame
)))
356 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
357 Scoordinates_in_window_p
, 2, 2, 0,
358 "Return non-nil if COORDINATES are in WINDOW.\n\
359 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
360 measured in characters from the upper-left corner of the frame.\n\
361 (0 . 0) denotes the character in the upper left corner of the\n\
363 If COORDINATES are in the text portion of WINDOW,\n\
364 the coordinates relative to the window are returned.\n\
365 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
366 If they are on the border between WINDOW and its right sibling,\n\
367 `vertical-line' is returned.")
368 (coordinates
, window
)
369 register Lisp_Object coordinates
, window
;
373 CHECK_WINDOW (window
, 0);
374 CHECK_CONS (coordinates
, 1);
375 x
= XINT (Fcar (coordinates
));
376 y
= XINT (Fcdr (coordinates
));
378 switch (coordinates_in_window (XWINDOW (window
), &x
, &y
))
380 case 0: /* NOT in window at all. */
383 case 1: /* In text part of window. */
386 case 2: /* In mode line of window. */
389 case 3: /* On right border of window. */
390 return Qvertical_line
;
397 /* Find the window containing column x, row y, and return it as a
398 Lisp_Object. If x, y is on the window's modeline, set *part
399 to 1; if it is on the separating line between the window and its
400 right sibling, set it to 2; otherwise set it to 0. If there is no
401 window under x, y return nil and leave *part unmodified. */
403 window_from_coordinates (frame
, x
, y
, part
)
408 register Lisp_Object tem
, first
;
410 tem
= first
= FRAME_SELECTED_WINDOW (frame
);
414 int found
= coordinates_in_window (XWINDOW (tem
), &x
, &y
);
422 tem
= Fnext_window (tem
, Qt
, Qlambda
);
424 while (! EQ (tem
, first
));
429 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
430 "Return window containing row ROW, column COLUMN on FRAME.\n\
431 If omitted, FRAME defaults to the currently selected frame.\n\
432 The top left corner of the frame is considered to be row 0,\n\
435 Lisp_Object row
, column
, frame
;
441 XSET (frame
, Lisp_Frame
, selected_frame
);
443 CHECK_LIVE_FRAME (frame
, 2);
445 CHECK_NUMBER (row
, 0);
446 CHECK_NUMBER (column
, 1);
448 return window_from_coordinates (XFRAME (frame
),
449 XINT (row
), XINT (column
),
453 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
454 "Return current value of point in WINDOW.\n\
455 For a nonselected window, this is the value point would have\n\
456 if that window were selected.\n\
458 Note that, when WINDOW is the selected window and its buffer\n\
459 is also currently selected, the value returned is the same as (point).\n\
460 It would be more strictly correct to return the `top-level' value\n\
461 of point, outside of any save-excursion forms.\n\
462 But that is hard to define.")
466 register struct window
*w
= decode_window (window
);
468 if (w
== XWINDOW (selected_window
)
469 && current_buffer
== XBUFFER (w
->buffer
))
471 return Fmarker_position (w
->pointm
);
474 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
475 "Return position at which display currently starts in WINDOW.")
479 return Fmarker_position (decode_window (window
)->start
);
482 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 1, 0,
483 "Return position at which display currently ends in WINDOW.")
488 struct window
*w
= decode_window (window
);
490 XSET (value
, Lisp_Int
,
491 BUF_Z (current_buffer
) - XFASTINT (w
->window_end_pos
));
496 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
497 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
499 Lisp_Object window
, pos
;
501 register struct window
*w
= decode_window (window
);
503 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
504 if (w
== XWINDOW (selected_window
))
507 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
512 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
513 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
514 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
515 from overriding motion of point in order to display at this exact start.")
516 (window
, pos
, noforce
)
517 Lisp_Object window
, pos
, noforce
;
519 register struct window
*w
= decode_window (window
);
521 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
522 set_marker_restricted (w
->start
, pos
, w
->buffer
);
523 /* this is not right, but much easier than doing what is right. */
524 w
->start_at_line_beg
= Qnil
;
527 w
->update_mode_line
= Qt
;
528 XFASTINT (w
->last_modified
) = 0;
529 if (!EQ (window
, selected_window
))
530 windows_or_buffers_changed
++;
534 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
536 "Return WINDOW's dedicated object, usually t or nil.\n\
537 See also `set-window-buffer-dedicated'.")
541 return decode_window (window
)->dedicated
;
544 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
545 Sset_window_dedicated_p
, 2, 2, 0,
546 "Control whether WINDOW is dedicated to the buffer it displays.\n\
547 If it is dedicated, Emacs will not automatically change\n\
548 which buffer appears in it.\n\
549 The second argument is the new value for the dedication flag;\n\
552 Lisp_Object window
, arg
;
554 register struct window
*w
= decode_window (window
);
564 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
566 "Return the display-table that WINDOW is using.")
570 return decode_window (window
)->display_table
;
573 /* Get the display table for use currently on window W.
574 This is either W's display table or W's buffer's display table.
575 Ignore the specified tables if they are not valid;
576 if no valid table is specified, return 0. */
579 window_display_table (w
)
583 tem
= w
->display_table
;
584 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
585 return XVECTOR (tem
);
586 tem
= XBUFFER (w
->buffer
)->display_table
;
587 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
588 return XVECTOR (tem
);
589 tem
= Vstandard_display_table
;
590 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
591 return XVECTOR (tem
);
595 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
596 "Set WINDOW's display-table to TABLE.")
598 register Lisp_Object window
, table
;
600 register struct window
*w
;
601 register Lisp_Object z
; /* Return value. */
603 w
= decode_window (window
);
604 w
->display_table
= table
;
608 /* Record info on buffer window w is displaying
609 when it is about to cease to display that buffer. */
612 register struct window
*w
;
614 Lisp_Object buf
= w
->buffer
;
616 if (XBUFFER (buf
) != XMARKER (w
->pointm
)->buffer
)
619 if (w
== XWINDOW (selected_window
)
620 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
621 /* Do this except when the selected window's buffer
622 is being removed from some other window. */
623 XBUFFER (buf
)->last_window_start
= marker_position (w
->start
);
625 /* Point in the selected window's buffer
626 is actually stored in that buffer, and the window's pointm isn't used.
627 So don't clobber point in that buffer. */
628 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
))
629 BUF_PT (XBUFFER (buf
))
630 = clip_to_bounds (BUF_BEGV (XBUFFER (buf
)),
631 marker_position (w
->pointm
),
632 BUF_ZV (XBUFFER (buf
)));
635 /* Put replacement into the window structure in place of old. */
637 replace_window (old
, replacement
)
638 Lisp_Object old
, replacement
;
640 register Lisp_Object tem
;
641 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
643 /* If OLD is its frame's root_window, then replacement is the new
644 root_window for that frame. */
646 if (old
== FRAME_ROOT_WINDOW (XFRAME (o
->frame
)))
647 FRAME_ROOT_WINDOW (XFRAME (o
->frame
)) = replacement
;
652 p
->height
= o
->height
;
654 p
->next
= tem
= o
->next
;
656 XWINDOW (tem
)->prev
= replacement
;
658 p
->prev
= tem
= o
->prev
;
660 XWINDOW (tem
)->next
= replacement
;
662 p
->parent
= tem
= o
->parent
;
665 if (EQ (XWINDOW (tem
)->vchild
, old
))
666 XWINDOW (tem
)->vchild
= replacement
;
667 if (EQ (XWINDOW (tem
)->hchild
, old
))
668 XWINDOW (tem
)->hchild
= replacement
;
671 /*** Here, if replacement is a vertical combination
672 and so is its new parent, we should make replacement's
673 children be children of that parent instead. ***/
676 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
677 "Remove WINDOW from the display. Default is selected window.")
679 register Lisp_Object window
;
681 register Lisp_Object tem
, parent
, sib
;
682 register struct window
*p
;
683 register struct window
*par
;
686 window
= selected_window
;
688 CHECK_WINDOW (window
, 0);
690 p
= XWINDOW (window
);
693 error ("Attempt to delete minibuffer or sole ordinary window");
694 par
= XWINDOW (parent
);
696 windows_or_buffers_changed
++;
698 if (EQ (window
, selected_window
))
699 Fselect_window (Fnext_window (window
, Qnil
, Qnil
));
702 /* tem is null for dummy parent windows
703 (which have inferiors but not any contents themselves) */
707 unchain_marker (p
->pointm
);
708 unchain_marker (p
->start
);
714 XWINDOW (tem
)->prev
= p
->prev
;
718 XWINDOW (tem
)->next
= p
->next
;
720 if (EQ (window
, par
->hchild
))
721 par
->hchild
= p
->next
;
722 if (EQ (window
, par
->vchild
))
723 par
->vchild
= p
->next
;
725 /* Find one of our siblings to give our space to. */
729 /* If p gives its space to its next sibling, that sibling needs
730 to have its top/left side pulled back to where p's is.
731 set_window_{height,width} will re-position the sibling's
734 XFASTINT (XWINDOW (sib
)->top
) = p
->top
;
735 XFASTINT (XWINDOW (sib
)->left
) = p
->left
;
738 /* Stretch that sibling. */
739 if (!NILP (par
->vchild
))
740 set_window_height (sib
,
741 XFASTINT (XWINDOW (sib
)->height
) + XFASTINT (p
->height
),
743 if (!NILP (par
->hchild
))
744 set_window_width (sib
,
745 XFASTINT (XWINDOW (sib
)->width
) + XFASTINT (p
->width
),
748 /* If parent now has only one child,
749 put the child into the parent's place. */
754 if (NILP (XWINDOW (tem
)->next
))
755 replace_window (parent
, tem
);
760 extern Lisp_Object
next_frame (), prev_frame ();
762 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
763 "Return next window after WINDOW in canonical ordering of windows.\n\
764 If omitted, WINDOW defaults to the selected window.\n\
766 Optional second arg MINIBUF t means count the minibuffer window even\n\
767 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
768 it is active. MINIBUF neither t nor nil means not to count the\n\
769 minibuffer even if it is active.\n\
771 Several frames may share a single minibuffer; if the minibuffer\n\
772 counts, all windows on all frames that share that minibuffer count\n\
773 too. This means that next-window may be used to iterate through the\n\
774 set of windows even when the minibuffer is on another frame. If the\n\
775 minibuffer does not count, only windows from WINDOW's frame count.\n\
777 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
778 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
779 above. If neither nil nor t, restrict to WINDOW's frame.")
780 (window
, minibuf
, all_frames
)
781 register Lisp_Object window
, minibuf
, all_frames
;
783 register Lisp_Object tem
;
784 Lisp_Object start_window
;
787 window
= selected_window
;
789 CHECK_WINDOW (window
, 0);
791 start_window
= window
;
793 /* minibuf == nil may or may not include minibuffers.
794 Decide if it does. */
796 minibuf
= (minibuf_level
? Qt
: Qlambda
);
798 /* all_frames == nil doesn't specify which frames to include.
799 Decide which frames it includes. */
800 if (NILP (all_frames
))
801 all_frames
= (EQ (minibuf
, Qt
)
802 ? (FRAME_MINIBUF_WINDOW
805 (XWINDOW (window
)))))
807 else if (! EQ (all_frames
, Qt
))
810 /* Do this loop at least once, to get the next window, and perhaps
811 again, if we hit the minibuffer and that is not acceptable. */
814 /* Find a window that actually has a next one. This loop
815 climbs up the tree. */
816 while (tem
= XWINDOW (window
)->next
, NILP (tem
))
817 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
821 /* We've reached the end of this frame.
822 Which other frames are acceptable? */
823 tem
= WINDOW_FRAME (XWINDOW (window
));
825 if (! NILP (all_frames
))
826 tem
= next_frame (tem
, all_frames
);
828 tem
= FRAME_ROOT_WINDOW (XFRAME (tem
));
835 /* If we're in a combination window, find its first child and
836 recurse on that. Otherwise, we've found the window we want. */
839 if (!NILP (XWINDOW (window
)->hchild
))
840 window
= XWINDOW (window
)->hchild
;
841 else if (!NILP (XWINDOW (window
)->vchild
))
842 window
= XWINDOW (window
)->vchild
;
846 /* Which windows are acceptible?
847 Exit the loop and accept this window if
848 this isn't a minibuffer window, or
849 we're accepting minibuffer windows, or
850 we've come all the way around and we're back at the original window. */
851 while (MINI_WINDOW_P (XWINDOW (window
))
852 && ! EQ (minibuf
, Qt
)
853 && window
!= start_window
);
858 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
859 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
860 If omitted, WINDOW defaults to the selected window.\n\
862 Optional second arg MINIBUF t means count the minibuffer window even\n\
863 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
864 it is active. MINIBUF neither t nor nil means not to count the\n\
865 minibuffer even if it is active.\n\
867 Several frames may share a single minibuffer; if the minibuffer\n\
868 counts, all windows on all frames that share that minibuffer count\n\
869 too. This means that previous-window may be used to iterate through\n\
870 the set of windows even when the minibuffer is on another frame. If\n\
871 the minibuffer does not count, only windows from WINDOW's frame\n\
874 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
875 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
876 above. If neither nil nor t, restrict to WINDOW's frame.")
877 (window
, minibuf
, all_frames
)
878 register Lisp_Object window
, minibuf
, all_frames
;
880 register Lisp_Object tem
;
881 Lisp_Object start_window
;
884 window
= selected_window
;
886 CHECK_WINDOW (window
, 0);
888 start_window
= window
;
890 /* minibuf == nil may or may not include minibuffers.
891 Decide if it does. */
893 minibuf
= (minibuf_level
? Qt
: Qlambda
);
895 /* all_frames == nil doesn't specify which frames to include.
896 Decide which frames it includes. */
897 if (NILP (all_frames
))
898 all_frames
= (EQ (minibuf
, Qt
)
899 ? (FRAME_MINIBUF_WINDOW
902 (XWINDOW (window
)))))
904 else if (! EQ (all_frames
, Qt
))
907 /* Do this loop at least once, to get the previous window, and perhaps
908 again, if we hit the minibuffer and that is not acceptable. */
911 /* Find a window that actually has a previous one. This loop
912 climbs up the tree. */
913 while (tem
= XWINDOW (window
)->prev
, NILP (tem
))
914 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
918 /* We have found the top window on the frame.
919 Which frames are acceptable? */
920 tem
= WINDOW_FRAME (XWINDOW (window
));
922 if (! NILP (all_frames
))
923 tem
= next_frame (tem
, all_frames
);
925 tem
= FRAME_ROOT_WINDOW (XFRAME (tem
));
931 /* If we're in a combination window, find its last child and
932 recurse on that. Otherwise, we've found the window we want. */
935 if (!NILP (XWINDOW (window
)->hchild
))
936 window
= XWINDOW (window
)->hchild
;
937 else if (!NILP (XWINDOW (window
)->vchild
))
938 window
= XWINDOW (window
)->vchild
;
940 while (tem
= XWINDOW (window
)->next
, !NILP (tem
))
944 /* Which windows are acceptable?
945 Exit the loop and accept this window if
946 this isn't a minibuffer window, or
947 we're accepting minibuffer windows, or
948 we've come all the way around and we're back at the original window. */
949 while (MINI_WINDOW_P (XWINDOW (window
))
951 && window
!= start_window
);
956 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
957 "Select the ARG'th different window on this frame.\n\
958 All windows on current frame are arranged in a cyclic order.\n\
959 This command selects the window ARG steps away in that order.\n\
960 A negative ARG moves in the opposite order. If the optional second\n\
961 argument ALL_FRAMES is non-nil, cycle through all frames.")
963 register Lisp_Object n
, all_frames
;
966 register Lisp_Object w
;
974 w
= Fnext_window (w
, Qnil
, all_frames
);
979 w
= Fprevious_window (w
, Qnil
, all_frames
);
986 /* Look at all windows, performing an operation specified by TYPE
988 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
989 frame. If FRAMES is a frame, just look at windows on that frame.
990 If MINI is non-zero, perform the operation on minibuffer windows too.
996 GET_BUFFER_WINDOW
, /* Arg is buffer */
997 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
998 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
999 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
1001 UNSHOW_BUFFER
, /* Arg is buffer */
1005 window_loop (type
, obj
, mini
, frames
)
1006 enum window_loop type
;
1007 register Lisp_Object obj
, frames
;
1010 register Lisp_Object w
;
1011 register Lisp_Object best_window
;
1012 register Lisp_Object next_window
;
1013 register Lisp_Object last_window
;
1017 /* If we're only looping through windows on a particular frame,
1018 frame points to that frame. If we're looping through windows
1019 on all frames, frame is 0. */
1020 if (FRAMEP (frames
))
1021 frame
= XFRAME (frames
);
1022 else if (NILP (frames
))
1023 frame
= selected_frame
;
1030 /* Pick a window to start with. */
1031 if (XTYPE (obj
) == Lisp_Window
)
1034 w
= FRAME_SELECTED_WINDOW (frame
);
1036 w
= FRAME_SELECTED_WINDOW (selected_frame
);
1038 /* Figure out the last window we're going to mess with. Since
1039 Fnext_window, given the same options, is guaranteed to go in a
1040 ring, we can just use Fprevious_window to find the last one.
1042 We can't just wait until we hit the first window again, because
1043 it might be deleted. */
1047 last_window
= Fprevious_window (w
, (mini
? Qt
: Qnil
), Qlambda
);
1049 #endif /* MULTI_FRAME */
1050 /* We know frame is 0, so we're looping through all frames.
1051 Or we know this isn't a MULTI_FRAME Emacs, so who cares? */
1052 last_window
= Fprevious_window (w
, mini
? Qt
: Qnil
, Qt
);
1057 /* Pick the next window now, since some operations will delete
1058 the current window. */
1061 next_window
= Fnext_window (w
, (mini
? Qt
: Qnil
), Qlambda
);
1063 #endif /* MULTI_FRAME */
1064 /* We know frame is 0, so we're looping through all frames.
1065 Or we know this isn't a MULTI_FRAME Emacs, so who cares? */
1066 next_window
= Fnext_window (w
, mini
? Qt
: Qnil
, Qt
);
1068 if (!MINI_WINDOW_P (XWINDOW (w
))
1069 || (mini
&& minibuf_level
> 0))
1072 case GET_BUFFER_WINDOW
:
1074 /* Ignore invisible and iconified frames. */
1075 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w
))))
1076 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w
)))))
1079 if (XBUFFER (XWINDOW (w
)->buffer
) == XBUFFER (obj
))
1083 case GET_LRU_WINDOW
:
1084 /* t as arg means consider only full-width windows */
1085 if (!NILP (obj
) && XFASTINT (XWINDOW (w
)->width
)
1086 != FRAME_WIDTH (frame
))
1089 /* Ignore invisible and iconified frames. */
1090 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w
))))
1091 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w
)))))
1094 /* Ignore dedicated windows and minibuffers. */
1095 if (MINI_WINDOW_P (XWINDOW (w
))
1096 || !NILP (XWINDOW (w
)->dedicated
))
1098 if (NILP (best_window
)
1099 || (XFASTINT (XWINDOW (best_window
)->use_time
)
1100 > XFASTINT (XWINDOW (w
)->use_time
)))
1104 case DELETE_OTHER_WINDOWS
:
1105 if (XWINDOW (w
) != XWINDOW (obj
))
1109 case DELETE_BUFFER_WINDOWS
:
1110 if (EQ (XWINDOW (w
)->buffer
, obj
))
1112 /* If we're deleting the buffer displayed in the only window
1113 on the frame, find a new buffer to display there. */
1114 if (NILP (XWINDOW (w
)->parent
))
1116 Lisp_Object new_buffer
= Fother_buffer (obj
);
1117 if (NILP (new_buffer
))
1119 = Fget_buffer_create (build_string ("*scratch*"));
1120 Fset_window_buffer (w
, new_buffer
);
1121 Fset_buffer (XWINDOW (w
)->buffer
);
1128 case GET_LARGEST_WINDOW
:
1130 /* Ignore invisible and iconified frames. */
1131 if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w
))))
1132 || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w
)))))
1135 /* Ignore dedicated windows and minibuffers. */
1136 if (MINI_WINDOW_P (XWINDOW (w
))
1137 || !NILP (XWINDOW (w
)->dedicated
))
1140 struct window
*best_window_ptr
= XWINDOW (best_window
);
1141 struct window
*w_ptr
= XWINDOW (w
);
1142 if (NILP (best_window
) ||
1143 (XFASTINT (w_ptr
->height
) * XFASTINT (w_ptr
->width
))
1144 > (XFASTINT (best_window_ptr
->height
)
1145 * XFASTINT (best_window_ptr
->width
)))
1151 if (EQ (XWINDOW (w
)->buffer
, obj
))
1153 /* Find another buffer to show in this window. */
1154 Lisp_Object another_buffer
= Fother_buffer (obj
);
1155 if (NILP (another_buffer
))
1157 = Fget_buffer_create (build_string ("*scratch*"));
1158 Fset_window_buffer (w
, another_buffer
);
1159 if (EQ (w
, selected_window
))
1160 Fset_buffer (XWINDOW (w
)->buffer
);
1165 if (EQ (w
, last_window
))
1174 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 1, 0,
1175 "Return the window least recently selected or used for display.\n\
1176 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1177 frame, search only that frame.\n")
1181 register Lisp_Object w
;
1182 /* First try for a window that is full-width */
1183 w
= window_loop (GET_LRU_WINDOW
, Qt
, 0, frames
);
1184 if (!NILP (w
) && !EQ (w
, selected_window
))
1186 /* If none of them, try the rest */
1187 return window_loop (GET_LRU_WINDOW
, Qnil
, 0, frames
);
1190 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 1, 0,
1191 "Return the largest window in area.\n\
1192 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1193 frame, search only that frame.\n")
1197 return window_loop (GET_LARGEST_WINDOW
, Qnil
, 0,
1201 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 1, 2, 0,
1202 "Return a window currently displaying BUFFER, or nil if none.\n\
1203 If optional argument FRAMES is t, search all frames. If FRAME is a\n\
1204 frame, search only that frame.\n")
1206 Lisp_Object buffer
, frame
;
1208 buffer
= Fget_buffer (buffer
);
1209 if (XTYPE (buffer
) == Lisp_Buffer
)
1210 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
1215 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
1217 "Make WINDOW (or the selected window) fill its frame.\n\
1218 Only the frame WINDOW is on is affected.")
1224 struct buffer
*obuf
= current_buffer
;
1228 window
= selected_window
;
1230 CHECK_WINDOW (window
, 0);
1232 w
= XWINDOW (window
);
1233 top
= XFASTINT (w
->top
);
1235 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_FRAME(w
));
1237 Fset_buffer (w
->buffer
);
1238 SET_PT (marker_position (w
->start
));
1239 Frecenter (make_number (top
));
1241 set_buffer_internal (obuf
);
1246 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
1247 1, 1, "bDelete windows on (buffer): ",
1248 "Delete all windows showing BUFFER.")
1254 buffer
= Fget_buffer (buffer
);
1255 CHECK_BUFFER (buffer
, 0);
1256 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, Qt
);
1261 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
1262 Sreplace_buffer_in_windows
,
1263 1, 1, "bReplace buffer in windows: ",
1264 "Replace BUFFER with some other buffer in all windows showing it.")
1270 buffer
= Fget_buffer (buffer
);
1271 CHECK_BUFFER (buffer
, 0);
1272 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
1277 /* Set the height of WINDOW and all its inferiors. */
1279 /* The smallest acceptable dimensions for a window. Anything smaller
1280 might crash Emacs. */
1281 #define MIN_SAFE_WINDOW_WIDTH (2)
1282 #define MIN_SAFE_WINDOW_HEIGHT (2)
1284 /* Make sure that window_min_height and window_min_width are
1285 not too small; if they are, set them to safe minima. */
1288 check_min_window_sizes ()
1290 /* Smaller values might permit a crash. */
1291 if (window_min_width
< MIN_SAFE_WINDOW_WIDTH
)
1292 window_min_width
= MIN_SAFE_WINDOW_WIDTH
;
1293 if (window_min_height
< MIN_SAFE_WINDOW_HEIGHT
)
1294 window_min_height
= MIN_SAFE_WINDOW_HEIGHT
;
1297 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
1298 minimum allowable size. */
1300 check_frame_size (frame
, rows
, cols
)
1304 /* For height, we have to see whether the frame has a minibuffer, and
1305 whether it wants a mode line. */
1307 ((FRAME_MINIBUF_ONLY_P (frame
)
1308 || ! FRAME_HAS_MINIBUF_P (frame
))
1309 ? MIN_SAFE_WINDOW_HEIGHT
1310 : 2 * MIN_SAFE_WINDOW_HEIGHT
- 1);
1312 if (*rows
< min_height
)
1314 if (*cols
< MIN_SAFE_WINDOW_WIDTH
)
1315 *cols
= MIN_SAFE_WINDOW_WIDTH
;
1318 /* Normally the window is deleted if it gets too small.
1319 nodelete nonzero means do not do this.
1320 (The caller should check later and do so if appropriate) */
1322 set_window_height (window
, height
, nodelete
)
1327 register struct window
*w
= XWINDOW (window
);
1328 register struct window
*c
;
1329 int oheight
= XFASTINT (w
->height
);
1330 int top
, pos
, lastbot
, opos
, lastobot
;
1333 check_min_window_sizes ();
1336 && ! NILP (w
->parent
)
1337 && height
< window_min_height
)
1339 Fdelete_window (window
);
1343 XFASTINT (w
->last_modified
) = 0;
1344 windows_or_buffers_changed
++;
1345 XFASTINT (w
->height
) = height
;
1346 if (!NILP (w
->hchild
))
1348 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1350 XWINDOW (child
)->top
= w
->top
;
1351 set_window_height (child
, height
, nodelete
);
1354 else if (!NILP (w
->vchild
))
1356 lastbot
= top
= XFASTINT (w
->top
);
1358 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
1360 c
= XWINDOW (child
);
1362 opos
= lastobot
+ XFASTINT (c
->height
);
1364 XFASTINT (c
->top
) = lastbot
;
1366 pos
= (((opos
* height
) << 1) + oheight
) / (oheight
<< 1);
1368 /* Avoid confusion: inhibit deletion of child if becomes too small */
1369 set_window_height (child
, pos
+ top
- lastbot
, 1);
1371 /* Now advance child to next window,
1372 and set lastbot if child was not just deleted. */
1373 lastbot
= pos
+ top
;
1376 /* Now delete any children that became too small. */
1378 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1380 set_window_height (child
, XINT (XWINDOW (child
)->height
), 0);
1385 /* Recursively set width of WINDOW and its inferiors. */
1387 set_window_width (window
, width
, nodelete
)
1392 register struct window
*w
= XWINDOW (window
);
1393 register struct window
*c
;
1394 int owidth
= XFASTINT (w
->width
);
1395 int left
, pos
, lastright
, opos
, lastoright
;
1398 if (!nodelete
&& width
< window_min_width
)
1400 Fdelete_window (window
);
1404 XFASTINT (w
->last_modified
) = 0;
1405 windows_or_buffers_changed
++;
1406 XFASTINT (w
->width
) = width
;
1407 if (!NILP (w
->vchild
))
1409 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1411 XWINDOW (child
)->left
= w
->left
;
1412 set_window_width (child
, width
, nodelete
);
1415 else if (!NILP (w
->hchild
))
1417 lastright
= left
= XFASTINT (w
->left
);
1419 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
1421 c
= XWINDOW (child
);
1423 opos
= lastoright
+ XFASTINT (c
->width
);
1425 XFASTINT (c
->left
) = lastright
;
1427 pos
= (((opos
* width
) << 1) + owidth
) / (owidth
<< 1);
1429 /* Inhibit deletion for becoming too small */
1430 set_window_width (child
, pos
+ left
- lastright
, 1);
1432 /* Now advance child to next window,
1433 and set lastright if child was not just deleted. */
1434 lastright
= pos
+ left
, lastoright
= opos
;
1436 /* Delete children that became too small */
1438 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1440 set_window_width (child
, XINT (XWINDOW (child
)->width
), 0);
1445 int window_select_count
;
1447 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 2, 0,
1448 "Make WINDOW display BUFFER as its contents.\n\
1449 BUFFER can be a buffer or buffer name.")
1451 register Lisp_Object window
, buffer
;
1453 register Lisp_Object tem
;
1454 register struct window
*w
= decode_window (window
);
1456 buffer
= Fget_buffer (buffer
);
1457 CHECK_BUFFER (buffer
, 1);
1459 if (NILP (XBUFFER (buffer
)->name
))
1460 error ("Attempt to display deleted buffer");
1464 error ("Window is deleted");
1465 else if (! EQ (tem
, Qt
)) /* w->buffer is t when the window
1466 is first being set up. */
1468 if (!NILP (w
->dedicated
) && !EQ (tem
, buffer
))
1469 error ("Window is dedicated to %s\n", tem
);
1475 Fset_marker (w
->pointm
,
1476 make_number (BUF_PT (XBUFFER (buffer
))),
1478 set_marker_restricted (w
->start
,
1479 make_number (XBUFFER (buffer
)->last_window_start
),
1481 w
->start_at_line_beg
= Qnil
;
1482 XFASTINT (w
->last_modified
) = 0;
1483 windows_or_buffers_changed
++;
1484 if (EQ (window
, selected_window
))
1485 Fset_buffer (buffer
);
1490 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 1, 0,
1491 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1492 The main editor command loop selects the buffer of the selected window\n\
1493 before each command.")
1495 register Lisp_Object window
;
1497 register struct window
*w
;
1498 register struct window
*ow
= XWINDOW (selected_window
);
1500 CHECK_WINDOW (window
, 0);
1502 w
= XWINDOW (window
);
1504 if (NILP (w
->buffer
))
1505 error ("Trying to select deleted window or non-leaf window");
1507 XFASTINT (w
->use_time
) = ++window_select_count
;
1508 if (EQ (window
, selected_window
))
1511 Fset_marker (ow
->pointm
, make_number (BUF_PT (XBUFFER (ow
->buffer
))),
1514 selected_window
= window
;
1516 if (XFRAME (WINDOW_FRAME (w
)) != selected_frame
)
1518 XFRAME (WINDOW_FRAME (w
))->selected_window
= window
;
1519 Fselect_frame (WINDOW_FRAME (w
), Qnil
);
1522 selected_frame
->selected_window
= window
;
1525 record_buffer (w
->buffer
);
1526 Fset_buffer (w
->buffer
);
1528 /* Go to the point recorded in the window.
1529 This is important when the buffer is in more
1530 than one window. It also matters when
1531 redisplay_window has altered point after scrolling,
1532 because it makes the change only in the window. */
1534 register int new_point
= marker_position (w
->pointm
);
1535 if (new_point
< BEGV
)
1543 windows_or_buffers_changed
++;
1547 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 2,
1548 "BDisplay buffer:\nP",
1549 "Make BUFFER appear in some window but don't select it.\n\
1550 BUFFER can be a buffer or a buffer name.\n\
1551 If BUFFER is shown already in some window, just use that one,\n\
1552 unless the window is the selected window and the optional second\n\
1553 argument NOT_THIS_WINDOW is non-nil.\n\
1554 Returns the window displaying BUFFER.")
1555 (buffer
, not_this_window
)
1556 register Lisp_Object buffer
, not_this_window
;
1558 register Lisp_Object window
;
1560 buffer
= Fget_buffer (buffer
);
1561 CHECK_BUFFER (buffer
, 0);
1563 if (!NILP (Vdisplay_buffer_function
))
1564 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
1566 if (NILP (not_this_window
)
1567 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
1568 return selected_window
;
1570 window
= Fget_buffer_window (buffer
, Qnil
);
1572 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
1576 /* If there are no frames open that have more than a minibuffer,
1577 we need to create a new frame. */
1578 if (pop_up_frames
|| last_nonminibuf_frame
== 0)
1581 = Fframe_selected_window (call0 (Vpop_up_frame_function
));
1582 Fset_window_buffer (window
, buffer
);
1584 Fselect_frame (XWINDOW (window
)->frame
, Qnil
);
1588 #endif /* MULTI_FRAME */
1592 || FRAME_MINIBUF_ONLY_P (selected_frame
)
1596 Lisp_Object frames
= Qnil
;
1599 if (FRAME_MINIBUF_ONLY_P (selected_frame
))
1600 XSET (frames
, Lisp_Frame
, last_nonminibuf_frame
);
1602 /* Don't try to create a window if would get an error */
1603 if (split_height_threshold
< window_min_height
<< 1)
1604 split_height_threshold
= window_min_height
<< 1;
1606 window
= Fget_largest_window (frames
);
1609 && window_height (window
) >= split_height_threshold
1611 (XFASTINT (XWINDOW (window
)->width
)
1612 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window
))))))
1613 window
= Fsplit_window (window
, Qnil
, Qnil
);
1616 window
= Fget_lru_window (frames
);
1617 if ((EQ (window
, selected_window
)
1618 || EQ (XWINDOW (window
)->parent
, Qnil
))
1619 && window_height (window
) >= window_min_height
<< 1)
1620 window
= Fsplit_window (window
, Qnil
, Qnil
);
1624 window
= Fget_lru_window (Qnil
);
1626 Fset_window_buffer (window
, buffer
);
1631 temp_output_buffer_show (buf
)
1632 register Lisp_Object buf
;
1634 register struct buffer
*old
= current_buffer
;
1635 register Lisp_Object window
;
1636 register struct window
*w
;
1639 XBUFFER (buf
)->save_modified
= MODIFF
;
1644 set_buffer_internal (old
);
1646 if (!EQ (Vtemp_buffer_show_function
, Qnil
))
1647 call1 (Vtemp_buffer_show_function
, buf
);
1650 window
= Fdisplay_buffer (buf
, Qnil
);
1653 if (XFRAME (XWINDOW (window
)->frame
) != selected_frame
)
1654 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
1655 #endif /* MULTI_FRAME */
1656 Vminibuf_scroll_window
= window
;
1657 w
= XWINDOW (window
);
1658 XFASTINT (w
->hscroll
) = 0;
1659 set_marker_restricted (w
->start
, make_number (1), buf
);
1660 set_marker_restricted (w
->pointm
, make_number (1), buf
);
1665 make_dummy_parent (window
)
1668 register Lisp_Object old
, new;
1669 register struct window
*o
, *p
;
1672 XSETTYPE (old
, Lisp_Vector
);
1673 new = Fcopy_sequence (old
);
1674 XSETTYPE (new, Lisp_Window
);
1678 XFASTINT (p
->sequence_number
) = ++sequence_number
;
1680 /* Put new into window structure in place of window */
1681 replace_window (window
, new);
1694 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
1695 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1696 WINDOW defaults to selected one and SIZE to half its size.\n\
1697 If optional third arg HOR-FLAG is non-nil, split side by side\n\
1698 and put SIZE columns in the first of the pair.")
1699 (window
, chsize
, horflag
)
1700 Lisp_Object window
, chsize
, horflag
;
1702 register Lisp_Object
new;
1703 register struct window
*o
, *p
;
1707 window
= selected_window
;
1709 CHECK_WINDOW (window
, 0);
1711 o
= XWINDOW (window
);
1715 if (!NILP (horflag
))
1716 /* Round odd size up, since this is for the left-hand window,
1717 and it will lose a column for the separators. */
1718 size
= ((XFASTINT (o
->width
) + 1) & -2) >> 1;
1720 size
= XFASTINT (o
->height
) >> 1;
1724 CHECK_NUMBER (chsize
, 1);
1725 size
= XINT (chsize
);
1728 if (MINI_WINDOW_P (o
))
1729 error ("Attempt to split minibuffer window");
1730 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o
))))
1731 error ("Attempt to split unsplittable frame");
1733 check_min_window_sizes ();
1737 if (size
< window_min_height
1738 || size
+ window_min_height
> XFASTINT (o
->height
))
1739 args_out_of_range_3 (window
, chsize
, horflag
);
1740 if (NILP (o
->parent
)
1741 || NILP (XWINDOW (o
->parent
)->vchild
))
1743 make_dummy_parent (window
);
1745 XWINDOW (new)->vchild
= window
;
1750 if (size
< window_min_width
1751 || size
+ window_min_width
> XFASTINT (o
->width
))
1752 args_out_of_range_3 (window
, chsize
, horflag
);
1753 if (NILP (o
->parent
)
1754 || NILP (XWINDOW (o
->parent
)->hchild
))
1756 make_dummy_parent (window
);
1758 XWINDOW (new)->hchild
= window
;
1762 /* Now we know that window's parent is a vertical combination
1763 if we are dividing vertically, or a horizontal combination
1764 if we are making side-by-side windows */
1766 windows_or_buffers_changed
++;
1767 new = make_window ();
1770 p
->frame
= o
->frame
;
1772 if (!NILP (p
->next
))
1773 XWINDOW (p
->next
)->prev
= new;
1776 p
->parent
= o
->parent
;
1779 Fset_window_buffer (new, o
->buffer
);
1781 /* Apportion the available frame space among the two new windows */
1783 if (!NILP (horflag
))
1785 p
->height
= o
->height
;
1787 XFASTINT (p
->width
) = XFASTINT (o
->width
) - size
;
1788 XFASTINT (o
->width
) = size
;
1789 XFASTINT (p
->left
) = XFASTINT (o
->left
) + size
;
1794 p
->width
= o
->width
;
1795 XFASTINT (p
->height
) = XFASTINT (o
->height
) - size
;
1796 XFASTINT (o
->height
) = size
;
1797 XFASTINT (p
->top
) = XFASTINT (o
->top
) + size
;
1803 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
1804 "Make current window ARG lines bigger.\n\
1805 From program, optional second arg non-nil means grow sideways ARG columns.")
1807 register Lisp_Object n
, side
;
1809 CHECK_NUMBER (n
, 0);
1810 change_window_height (XINT (n
), !NILP (side
));
1814 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
1815 "Make current window ARG lines smaller.\n\
1816 From program, optional second arg non-nil means shrink sideways ARG columns.")
1818 register Lisp_Object n
, side
;
1820 CHECK_NUMBER (n
, 0);
1821 change_window_height (-XINT (n
), !NILP (side
));
1826 window_height (window
)
1829 register struct window
*p
= XWINDOW (window
);
1830 return XFASTINT (p
->height
);
1834 window_width (window
)
1837 register struct window
*p
= XWINDOW (window
);
1838 return XFASTINT (p
->width
);
1841 #define MINSIZE(w) \
1843 ? window_min_width \
1844 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
1847 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
1849 #define CURSIZE(w) \
1850 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
1852 /* Unlike set_window_height, this function
1853 also changes the heights of the siblings so as to
1854 keep everything consistent. */
1856 change_window_height (delta
, widthflag
)
1860 register Lisp_Object parent
;
1862 register struct window
*p
;
1864 int (*sizefun
) () = widthflag
? window_width
: window_height
;
1865 register int (*setsizefun
) () = (widthflag
1867 : set_window_height
);
1869 check_min_window_sizes ();
1871 window
= selected_window
;
1874 p
= XWINDOW (window
);
1879 error ("No other window to side of this one");
1882 if (widthflag
? !NILP (XWINDOW (parent
)->hchild
)
1883 : !NILP (XWINDOW (parent
)->vchild
))
1888 sizep
= &CURSIZE (window
);
1890 if (*sizep
+ delta
< MINSIZE (window
))
1892 Fdelete_window (window
);
1897 register int maxdelta
;
1899 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - *sizep
1900 : !NILP (p
->next
) ? (*sizefun
) (p
->next
) - MINSIZE (p
->next
)
1901 : !NILP (p
->prev
) ? (*sizefun
) (p
->prev
) - MINSIZE (p
->prev
)
1902 /* This is a frame with only one window, a minibuffer-only
1903 or a minibufferless frame. */
1906 if (delta
> maxdelta
)
1907 /* This case traps trying to make the minibuffer
1908 the full frame, or make the only window aside from the
1909 minibuffer the full frame. */
1916 if (!NILP (p
->next
) &&
1917 (*sizefun
) (p
->next
) - delta
>= MINSIZE (p
->next
))
1919 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
) - delta
, 0);
1920 (*setsizefun
) (window
, *sizep
+ delta
, 0);
1921 CURBEG (p
->next
) += delta
;
1922 /* This does not change size of p->next,
1923 but it propagates the new top edge to its children */
1924 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
), 0);
1926 else if (!NILP (p
->prev
) &&
1927 (*sizefun
) (p
->prev
) - delta
>= MINSIZE (p
->prev
))
1929 (*setsizefun
) (p
->prev
, (*sizefun
) (p
->prev
) - delta
, 0);
1930 CURBEG (window
) -= delta
;
1931 (*setsizefun
) (window
, *sizep
+ delta
, 0);
1935 register int delta1
;
1936 register int opht
= (*sizefun
) (parent
);
1938 /* If trying to grow this window to or beyond size of the parent,
1939 make delta1 so big that, on shrinking back down,
1940 all the siblings end up with less than one line and are deleted. */
1941 if (opht
<= *sizep
+ delta
)
1942 delta1
= opht
* opht
* 2;
1943 /* Otherwise, make delta1 just right so that if we add delta1
1944 lines to this window and to the parent, and then shrink
1945 the parent back to its original size, the new proportional
1946 size of this window will increase by delta. */
1948 delta1
= (delta
* opht
* 100) / ((opht
- *sizep
- delta
) * 100);
1950 /* Add delta1 lines or columns to this window, and to the parent,
1951 keeping things consistent while not affecting siblings. */
1952 CURSIZE (parent
) = opht
+ delta1
;
1953 (*setsizefun
) (window
, *sizep
+ delta1
, 0);
1955 /* Squeeze out delta1 lines or columns from our parent,
1956 shriking this window and siblings proportionately.
1957 This brings parent back to correct size.
1958 Delta1 was calculated so this makes this window the desired size,
1959 taking it all out of the siblings. */
1960 (*setsizefun
) (parent
, opht
, 0);
1963 XFASTINT (p
->last_modified
) = 0;
1970 /* Return number of lines of text (not counting mode line) in W. */
1973 window_internal_height (w
)
1976 int ht
= XFASTINT (w
->height
);
1978 if (MINI_WINDOW_P (w
))
1981 if (!NILP (w
->parent
) || !NILP (w
->vchild
) || !NILP (w
->hchild
)
1982 || !NILP (w
->next
) || !NILP (w
->prev
)
1983 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w
))))
1989 /* Scroll contents of window WINDOW up N lines. */
1992 window_scroll (window
, n
, noerror
)
1997 register struct window
*w
= XWINDOW (window
);
1998 register int opoint
= point
;
2000 register int ht
= window_internal_height (w
);
2001 register Lisp_Object tem
;
2003 Lisp_Object bolp
, nmoved
;
2005 XFASTINT (tem
) = point
;
2006 tem
= Fpos_visible_in_window_p (tem
, window
);
2010 Fvertical_motion (make_number (- ht
/ 2));
2011 XFASTINT (tem
) = point
;
2012 Fset_marker (w
->start
, tem
, w
->buffer
);
2013 w
->force_start
= Qt
;
2016 SET_PT (marker_position (w
->start
));
2017 lose
= n
< 0 && point
== BEGV
;
2018 Fvertical_motion (make_number (n
));
2028 Fsignal (Qbeginning_of_buffer
, Qnil
);
2033 set_marker_restricted (w
->start
, make_number (pos
), w
->buffer
);
2034 w
->start_at_line_beg
= bolp
;
2035 w
->update_mode_line
= Qt
;
2036 XFASTINT (w
->last_modified
) = 0;
2042 tem
= Fvertical_motion (make_number (ht
));
2043 if (point
> opoint
|| XFASTINT (tem
) < ht
)
2046 Fvertical_motion (make_number (-1));
2054 Fsignal (Qend_of_buffer
, Qnil
);
2058 /* This is the guts of Fscroll_up and Fscroll_down. */
2061 scroll_command (n
, direction
)
2062 register Lisp_Object n
;
2065 register int defalt
;
2066 int count
= specpdl_ptr
- specpdl
;
2068 /* If selected window's buffer isn't current, make it current for the moment.
2069 But don't screw up if window_scroll gets an error. */
2070 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
2072 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2073 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2076 defalt
= (window_internal_height (XWINDOW (selected_window
))
2077 - next_screen_context_lines
);
2078 defalt
= direction
* (defalt
< 1 ? 1 : defalt
);
2081 window_scroll (selected_window
, defalt
, 0);
2082 else if (EQ (n
, Qminus
))
2083 window_scroll (selected_window
, - defalt
, 0);
2086 n
= Fprefix_numeric_value (n
);
2087 window_scroll (selected_window
, XINT (n
) * direction
, 0);
2090 unbind_to (count
, Qnil
);
2093 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "P",
2094 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2095 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2096 When calling from a program, supply a number as argument or nil.")
2100 scroll_command (n
, 1);
2104 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "P",
2105 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2106 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2107 When calling from a program, supply a number as argument or nil.")
2111 scroll_command (n
, -1);
2115 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
2116 "Scroll text of next window upward ARG lines; or near full screen if no ARG.\n\
2117 The next window is the one below the current one; or the one at the top\n\
2118 if the current one is at the bottom.\n\
2119 When calling from a program, supply a number as argument or nil.\n\
2121 If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
2122 specifies the window to scroll.\n\
2123 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2124 showing that buffer, popping the buffer up if necessary.")
2126 register Lisp_Object n
;
2128 register Lisp_Object window
;
2130 register struct window
*w
;
2131 register int count
= specpdl_ptr
- specpdl
;
2133 if (MINI_WINDOW_P (XWINDOW (selected_window
))
2134 && !NILP (Vminibuf_scroll_window
))
2135 window
= Vminibuf_scroll_window
;
2136 /* If buffer is specified, scroll that buffer. */
2137 else if (!NILP (Vother_window_scroll_buffer
))
2139 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
2141 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
);
2144 /* Nothing specified; pick a neighboring window. */
2145 window
= Fnext_window (selected_window
, Qnil
, Qt
);
2146 CHECK_WINDOW (window
, 0);
2148 if (EQ (window
, selected_window
))
2149 error ("There is no other window");
2151 w
= XWINDOW (window
);
2152 ht
= window_internal_height (w
);
2154 /* Don't screw up if window_scroll gets an error. */
2155 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2157 Fset_buffer (w
->buffer
);
2158 SET_PT (marker_position (w
->pointm
));
2161 window_scroll (window
, ht
- next_screen_context_lines
, 1);
2162 else if (EQ (n
, Qminus
))
2163 window_scroll (window
, next_screen_context_lines
- ht
, 1);
2166 if (XTYPE (n
) == Lisp_Cons
)
2168 CHECK_NUMBER (n
, 0);
2169 window_scroll (window
, XINT (n
), 1);
2172 Fset_marker (w
->pointm
, make_number (point
), Qnil
);
2178 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 1, 1, "P",
2179 "Scroll selected window display ARG columns left.\n\
2180 Default for ARG is window width minus 2.")
2182 register Lisp_Object arg
;
2186 XFASTINT (arg
) = XFASTINT (XWINDOW (selected_window
)->width
) - 2;
2188 arg
= Fprefix_numeric_value (arg
);
2191 Fset_window_hscroll (selected_window
,
2192 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2196 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 1, 1, "P",
2197 "Scroll selected window display ARG columns right.\n\
2198 Default for ARG is window width minus 2.")
2200 register Lisp_Object arg
;
2203 XFASTINT (arg
) = XFASTINT (XWINDOW (selected_window
)->width
) - 2;
2205 arg
= Fprefix_numeric_value (arg
);
2208 Fset_window_hscroll (selected_window
,
2209 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2213 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
2214 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
2215 The desired position of point is always relative to the current window.\n\
2216 Just C-u as prefix means put point in the center of the window.\n\
2217 No arg (i.e., it is nil) erases the entire frame and then\n\
2218 redraws with point in the center of the current window.")
2220 register Lisp_Object n
;
2222 register struct window
*w
= XWINDOW (selected_window
);
2223 register int ht
= window_internal_height (w
);
2224 register int opoint
= point
;
2228 extern int frame_garbaged
;
2230 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w
)));
2231 XFASTINT (n
) = ht
/ 2;
2233 else if (XTYPE (n
) == Lisp_Cons
) /* Just C-u. */
2235 XFASTINT (n
) = ht
/ 2;
2239 n
= Fprefix_numeric_value (n
);
2240 CHECK_NUMBER (n
, 0);
2244 XSETINT (n
, XINT (n
) + ht
);
2246 XSETINT (n
, - XINT (n
));
2248 Fvertical_motion (n
);
2249 Fset_marker (w
->start
, make_number (point
), w
->buffer
);
2250 w
->start_at_line_beg
= Fbolp ();
2253 w
->force_start
= Qt
;
2258 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
2260 "Position point relative to window.\n\
2261 With no argument, position text at center of window.\n\
2262 An argument specifies frame line; zero means top of window,\n\
2263 negative means relative to bottom of window.")
2265 register Lisp_Object arg
;
2267 register struct window
*w
= XWINDOW (selected_window
);
2268 register int height
= window_internal_height (w
);
2272 XFASTINT (arg
) = height
/ 2;
2275 arg
= Fprefix_numeric_value (arg
);
2277 XSETINT (arg
, XINT (arg
) + height
);
2280 start
= marker_position (w
->start
);
2281 if (start
< BEGV
|| start
> ZV
)
2283 Fvertical_motion (make_number (- height
/ 2));
2284 Fset_marker (w
->start
, make_number (point
), w
->buffer
);
2285 w
->start_at_line_beg
= Fbolp ();
2286 w
->force_start
= Qt
;
2291 return Fvertical_motion (arg
);
2294 struct save_window_data
2296 int size_from_Lisp_Vector_struct
;
2297 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2298 Lisp_Object frame_width
, frame_height
;
2299 Lisp_Object current_window
;
2300 Lisp_Object current_buffer
;
2301 Lisp_Object minibuf_scroll_window
;
2302 Lisp_Object root_window
;
2303 /* A vector, interpreted as a struct saved_window */
2304 Lisp_Object saved_windows
;
2306 #define SAVE_WINDOW_DATA_SIZE 7 /* Arg to Fmake_vector */
2308 /* This is saved as a Lisp_Vector */
2311 /* these first two must agree with struct Lisp_Vector in lisp.h */
2312 int size_from_Lisp_Vector_struct
;
2313 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2316 Lisp_Object buffer
, start
, pointm
, mark
;
2317 Lisp_Object left
, top
, width
, height
, hscroll
;
2318 Lisp_Object parent
, prev
;
2319 Lisp_Object start_at_line_beg
;
2320 Lisp_Object display_table
;
2322 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2324 #define SAVED_WINDOW_N(swv,n) \
2325 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2327 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
2328 "T if OBJECT is a window-configration object.")
2332 if (XTYPE (obj
) == Lisp_Window_Configuration
)
2338 DEFUN ("set-window-configuration",
2339 Fset_window_configuration
, Sset_window_configuration
,
2341 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2342 CONFIGURATION must be a value previously returned\n\
2343 by `current-window-configuration' (which see).")
2345 Lisp_Object configuration
;
2347 register struct window
*w
;
2348 register struct save_window_data
*data
;
2349 struct Lisp_Vector
*saved_windows
;
2350 register struct saved_window
*p
;
2351 register Lisp_Object tem
;
2352 Lisp_Object new_current_buffer
;
2356 /* Save screen height here so we can go back to it at the end. */
2357 int previous_frame_height
;
2358 int previous_frame_width
;
2359 int frame_size_change
;
2361 while (XTYPE (configuration
) != Lisp_Window_Configuration
)
2363 configuration
= wrong_type_argument (intern ("window-configuration-p"),
2367 data
= (struct save_window_data
*) XVECTOR (configuration
);
2368 saved_windows
= XVECTOR (data
->saved_windows
);
2370 f
= XFRAME (XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
);
2372 if (XFASTINT (data
->frame_height
) != FRAME_HEIGHT (f
)
2373 || XFASTINT (data
->frame_width
) != FRAME_WIDTH (f
))
2375 previous_frame_height
= FRAME_HEIGHT (f
);
2376 previous_frame_width
= FRAME_WIDTH (f
);
2377 frame_size_change
= 1;
2379 change_frame_size (f
, data
->frame_height
, data
->frame_width
, 0, 0);
2382 frame_size_change
= 0;
2384 windows_or_buffers_changed
++;
2385 new_current_buffer
= data
->current_buffer
;
2386 if (NILP (XBUFFER (new_current_buffer
)->name
))
2387 new_current_buffer
= Qnil
;
2390 Mark all windows now on frame as "deleted".
2391 Restoring the new configuration "undeletes" any that are in it.
2393 Save their current buffers in their height fields, since we may
2394 need it later, if the buffer saved in the configuration is now
2396 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2398 for (k
= 0; k
< saved_windows
->size
; k
++)
2400 p
= SAVED_WINDOW_N (saved_windows
, k
);
2401 w
= XWINDOW (p
->window
);
2404 if (!NILP (p
->parent
))
2405 w
->parent
= SAVED_WINDOW_N (saved_windows
, XFASTINT (p
->parent
))->window
;
2409 if (!NILP (p
->prev
))
2411 w
->prev
= SAVED_WINDOW_N (saved_windows
, XFASTINT (p
->prev
))->window
;
2412 XWINDOW (w
->prev
)->next
= p
->window
;
2417 if (!NILP (w
->parent
))
2419 if (EQ (p
->width
, XWINDOW (w
->parent
)->width
))
2421 XWINDOW (w
->parent
)->vchild
= p
->window
;
2422 XWINDOW (w
->parent
)->hchild
= Qnil
;
2426 XWINDOW (w
->parent
)->hchild
= p
->window
;
2427 XWINDOW (w
->parent
)->vchild
= Qnil
;
2432 /* If we squirreled away the buffer in the window's height,
2434 if (XTYPE (w
->height
) == Lisp_Buffer
)
2435 w
->buffer
= w
->height
;
2438 w
->width
= p
->width
;
2439 w
->height
= p
->height
;
2440 w
->hscroll
= p
->hscroll
;
2441 w
->display_table
= p
->display_table
;
2442 XFASTINT (w
->last_modified
) = 0;
2444 /* Reinstall the saved buffer and pointers into it. */
2445 if (NILP (p
->buffer
))
2446 w
->buffer
= p
->buffer
;
2449 if (!NILP (XBUFFER (p
->buffer
)->name
))
2450 /* If saved buffer is alive, install it. */
2452 w
->buffer
= p
->buffer
;
2453 w
->start_at_line_beg
= p
->start_at_line_beg
;
2454 set_marker_restricted (w
->start
, Fmarker_position (p
->start
), w
->buffer
);
2455 set_marker_restricted (w
->pointm
, Fmarker_position (p
->pointm
), w
->buffer
);
2456 Fset_marker (XBUFFER (w
->buffer
)->mark
,
2457 Fmarker_position (p
->mark
), w
->buffer
);
2459 if (!EQ (p
->buffer
, new_current_buffer
) &&
2460 XBUFFER (p
->buffer
) == current_buffer
)
2461 Fgoto_char (w
->pointm
);
2463 else if (NILP (XBUFFER (w
->buffer
)->name
))
2464 /* Else if window's old buffer is dead too, get a live one. */
2466 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
2467 /* This will set the markers to beginning of visible range. */
2468 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
2469 set_marker_restricted (w
->pointm
, make_number (0), w
->buffer
);
2470 w
->start_at_line_beg
= Qt
;
2473 /* Keeping window's old buffer; make sure the markers are real. */
2474 /* Else if window's old buffer is dead too, get a live one. */
2476 /* Set window markers at start of visible range. */
2477 if (XMARKER (w
->start
)->buffer
== 0)
2478 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
2479 if (XMARKER (w
->pointm
)->buffer
== 0)
2480 set_marker_restricted (w
->pointm
,
2481 make_number (BUF_PT (XBUFFER (w
->buffer
))),
2483 w
->start_at_line_beg
= Qt
;
2488 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
2491 if (f
!= selected_frame
&& ! FRAME_TERMCAP_P (f
))
2492 Fselect_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)), Qnil
);
2495 /* Set the screen height to the value it had before this function. */
2496 if (frame_size_change
)
2497 change_frame_size (f
, previous_frame_height
, previous_frame_width
, 0, 0);
2499 if (f
== selected_frame
)
2501 Fselect_window (data
->current_window
);
2502 if (!NILP (new_current_buffer
))
2503 Fset_buffer (new_current_buffer
);
2505 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2508 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
2512 /* Mark all windows now on frame as deleted
2513 by setting their buffers to nil. */
2516 delete_all_subwindows (w
)
2517 register struct window
*w
;
2519 w
->height
= w
->buffer
; /* See Fset_window_configuration for excuse. */
2521 if (!NILP (w
->next
))
2522 delete_all_subwindows (XWINDOW (w
->next
));
2523 if (!NILP (w
->vchild
))
2524 delete_all_subwindows (XWINDOW (w
->vchild
));
2525 if (!NILP (w
->hchild
))
2526 delete_all_subwindows (XWINDOW (w
->hchild
));
2530 count_windows (window
)
2531 register struct window
*window
;
2533 register int count
= 1;
2534 if (!NILP (window
->next
))
2535 count
+= count_windows (XWINDOW (window
->next
));
2536 if (!NILP (window
->vchild
))
2537 count
+= count_windows (XWINDOW (window
->vchild
));
2538 if (!NILP (window
->hchild
))
2539 count
+= count_windows (XWINDOW (window
->hchild
));
2544 save_window_save (window
, vector
, i
)
2546 struct Lisp_Vector
*vector
;
2549 register struct saved_window
*p
;
2550 register struct window
*w
;
2551 register Lisp_Object tem
;
2553 for (;!NILP (window
); window
= w
->next
)
2555 p
= SAVED_WINDOW_N (vector
, i
);
2556 w
= XWINDOW (window
);
2558 XFASTINT (w
->temslot
) = i
++;
2560 p
->buffer
= w
->buffer
;
2563 p
->width
= w
->width
;
2564 p
->height
= w
->height
;
2565 p
->hscroll
= w
->hscroll
;
2566 p
->display_table
= w
->display_table
;
2567 if (!NILP (w
->buffer
))
2569 /* Save w's value of point in the window configuration.
2570 If w is the selected window, then get the value of point
2571 from the buffer; pointm is garbage in the selected window. */
2572 if (EQ (window
, selected_window
))
2574 p
->pointm
= Fmake_marker ();
2575 Fset_marker (p
->pointm
, BUF_PT (XBUFFER (w
->buffer
)),
2579 p
->pointm
= Fcopy_marker (w
->pointm
);
2581 p
->start
= Fcopy_marker (w
->start
);
2582 p
->start_at_line_beg
= w
->start_at_line_beg
;
2584 tem
= XBUFFER (w
->buffer
)->mark
;
2585 p
->mark
= Fcopy_marker (tem
);
2592 p
->start_at_line_beg
= Qnil
;
2595 if (NILP (w
->parent
))
2598 p
->parent
= XWINDOW (w
->parent
)->temslot
;
2603 p
->prev
= XWINDOW (w
->prev
)->temslot
;
2605 if (!NILP (w
->vchild
))
2606 i
= save_window_save (w
->vchild
, vector
, i
);
2607 if (!NILP (w
->hchild
))
2608 i
= save_window_save (w
->hchild
, vector
, i
);
2614 DEFUN ("current-window-configuration",
2615 Fcurrent_window_configuration
, Scurrent_window_configuration
, 0, 1, 0,
2616 "Return an object representing the current window configuration of FRAME.\n\
2617 If FRAME is nil or omitted, use the selected frame.\n\
2618 This describes the number of windows, their sizes and current buffers,\n\
2619 and for each displayed buffer, where display starts, and the positions of\n\
2620 point and mark. An exception is made for point in the current buffer:\n\
2621 its value is -not- saved.")
2625 register Lisp_Object tem
;
2626 register int n_windows
;
2627 register struct save_window_data
*data
;
2635 CHECK_LIVE_FRAME (frame
, 0);
2639 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
2640 data
= (struct save_window_data
*)
2641 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE
),
2643 XFASTINT (data
->frame_width
) = FRAME_WIDTH (f
);
2644 XFASTINT (data
->frame_height
) = FRAME_HEIGHT (f
);
2645 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
2646 XSET (data
->current_buffer
, Lisp_Buffer
, current_buffer
);
2647 data
->minibuf_scroll_window
= Vminibuf_scroll_window
;
2648 data
->root_window
= FRAME_ROOT_WINDOW (f
);
2649 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
2650 data
->saved_windows
= tem
;
2651 for (i
= 0; i
< n_windows
; i
++)
2652 XVECTOR (tem
)->contents
[i
]
2653 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE
), Qnil
);
2654 save_window_save (FRAME_ROOT_WINDOW (f
),
2656 XSET (tem
, Lisp_Window_Configuration
, data
);
2660 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
2662 "Execute body, preserving window sizes and contents.\n\
2663 Restores which buffer appears in which window, where display starts,\n\
2664 as well as the current buffer.\n\
2665 Does not restore the value of point in current buffer.")
2669 register Lisp_Object val
;
2670 register int count
= specpdl_ptr
- specpdl
;
2672 record_unwind_protect (Fset_window_configuration
,
2673 Fcurrent_window_configuration (Qnil
));
2674 val
= Fprogn (args
);
2675 return unbind_to (count
, val
);
2681 selected_frame
= make_terminal_frame ();
2682 minibuf_window
= selected_frame
->minibuffer_window
;
2683 selected_window
= selected_frame
->selected_window
;
2684 last_nonminibuf_frame
= selected_frame
;
2685 #else /* not MULTI_FRAME */
2686 extern Lisp_Object
get_minibuffer ();
2688 minibuf_window
= make_window ();
2689 FRAME_ROOT_WINDOW (selected_frame
) = make_window ();
2691 XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->next
= minibuf_window
;
2692 XWINDOW (minibuf_window
)->prev
= FRAME_ROOT_WINDOW (selected_frame
);
2693 XWINDOW (minibuf_window
)->mini_p
= Qt
;
2695 /* These values 9 and 10 are arbitrary,
2696 just so that there is "something there."
2697 Correct values are put in in init_xdisp */
2699 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->width
) = 10;
2700 XFASTINT (XWINDOW (minibuf_window
)->width
) = 10;
2702 XFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->height
) = 9;
2703 XFASTINT (XWINDOW (minibuf_window
)->top
) = 9;
2704 XFASTINT (XWINDOW (minibuf_window
)->height
) = 1;
2706 /* Prevent error in Fset_window_buffer. */
2707 XWINDOW (FRAME_ROOT_WINDOW (selected_frame
))->buffer
= Qt
;
2708 XWINDOW (minibuf_window
)->buffer
= Qt
;
2710 /* Now set them up for real. */
2711 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame
),
2712 Fcurrent_buffer ());
2713 Fset_window_buffer (minibuf_window
, get_minibuffer (0));
2715 selected_window
= FRAME_ROOT_WINDOW (selected_frame
);
2716 /* Make sure this window seems more recently used than
2717 a newly-created, never-selected window. Increment
2718 window_select_count so the first selection ever will get
2719 something newer than this. */
2720 XFASTINT (XWINDOW (selected_window
)->use_time
) = ++window_select_count
;
2721 #endif /* not MULTI_FRAME */
2726 Qwindowp
= intern ("windowp");
2727 staticpro (&Qwindowp
);
2730 /* Make sure all windows get marked */
2731 staticpro (&minibuf_window
);
2734 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
2735 "Non-nil means call as function to display a help buffer.\n\
2736 Used by `with-output-to-temp-buffer'.");
2737 Vtemp_buffer_show_function
= Qnil
;
2739 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
2740 "If non-nil, function to call to handle `display-buffer'.\n\
2741 It will receive two args, the buffer and a flag which if non-nil means\n\
2742 that the currently selected window is not acceptable.\n\
2743 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
2744 work using this function.");
2745 Vdisplay_buffer_function
= Qnil
;
2747 DEFVAR_LISP ("mouse-window", &Vmouse_window
,
2748 "Window that the last mouse click occurred on.");
2749 Vmouse_window
= Qnil
;
2751 DEFVAR_LISP ("mouse-event", &Vmouse_event
,
2752 "The last mouse-event object. A list of four elements:\n\
2753 ((X-POS Y-POS) WINDOW FRAME-PART KEYSEQ).\n\
2754 KEYSEQ is a string, the key sequence to be looked up in the mouse maps.\n\
2755 WINDOW is the window that the click applies do.\n\
2756 If FRAME-PART is non-nil, the event was on a scrollbar;\n\
2757 then Y-POS is really the total length of the scrollbar, while X-POS is\n\
2758 the relative position of the scrollbar's value within that total length.\n\
2759 FRAME-PART is one of the following symbols:\n\
2760 `vertical-scrollbar', `vertical-slider',\n\
2761 `vertical-thumbup', `vertical-thumbdown',\n\
2762 `horizontal-scrollbar', `horizontal-slider',\n\
2763 `horizontal-thumbleft', `horizontal-thumbright'");
2764 Vmouse_event
= Qnil
;
2766 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
2767 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
2768 Vminibuf_scroll_window
= Qnil
;
2770 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
2771 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
2772 Vother_window_scroll_buffer
= Qnil
;
2775 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames
,
2776 "*Non-nil means `display-buffer' should make a separate frame.");
2779 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function
,
2780 "*If non-nil, function to call to handle automatic new frame creation.\n\
2781 It is called with no arguments and should return a newly created frame.\n\
2783 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
2784 where `pop-up-frame-alist' would hold the default frame parameters.");
2785 Vpop_up_frame_function
= Qnil
;
2788 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
2789 "*Non-nil means display-buffer should make new windows.");
2792 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
2793 "*Number of lines of continuity when scrolling by screenfuls.");
2794 next_screen_context_lines
= 2;
2796 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
2797 "*display-buffer would prefer to split the largest window if this large.\n\
2798 If there is only one window, it is split regardless of this value.");
2799 split_height_threshold
= 500;
2801 DEFVAR_INT ("window-min-height", &window_min_height
,
2802 "*Delete any window less than this tall (including its mode line).");
2803 window_min_height
= 4;
2805 DEFVAR_INT ("window-min-width", &window_min_width
,
2806 "*Delete any window less than this wide.");
2807 window_min_width
= 10;
2809 defsubr (&Sselected_window
);
2810 defsubr (&Sminibuffer_window
);
2811 defsubr (&Swindow_minibuffer_p
);
2812 defsubr (&Swindowp
);
2813 defsubr (&Spos_visible_in_window_p
);
2814 defsubr (&Swindow_buffer
);
2815 defsubr (&Swindow_height
);
2816 defsubr (&Swindow_width
);
2817 defsubr (&Swindow_hscroll
);
2818 defsubr (&Sset_window_hscroll
);
2819 defsubr (&Swindow_edges
);
2820 defsubr (&Scoordinates_in_window_p
);
2821 defsubr (&Swindow_at
);
2822 defsubr (&Swindow_point
);
2823 defsubr (&Swindow_start
);
2824 defsubr (&Swindow_end
);
2825 defsubr (&Sset_window_point
);
2826 defsubr (&Sset_window_start
);
2827 defsubr (&Swindow_dedicated_p
);
2828 defsubr (&Sset_window_dedicated_p
);
2829 defsubr (&Swindow_display_table
);
2830 defsubr (&Sset_window_display_table
);
2831 defsubr (&Snext_window
);
2832 defsubr (&Sprevious_window
);
2833 defsubr (&Sother_window
);
2834 defsubr (&Sget_lru_window
);
2835 defsubr (&Sget_largest_window
);
2836 defsubr (&Sget_buffer_window
);
2837 defsubr (&Sdelete_other_windows
);
2838 defsubr (&Sdelete_windows_on
);
2839 defsubr (&Sreplace_buffer_in_windows
);
2840 defsubr (&Sdelete_window
);
2841 defsubr (&Sset_window_buffer
);
2842 defsubr (&Sselect_window
);
2843 defsubr (&Sdisplay_buffer
);
2844 defsubr (&Ssplit_window
);
2845 defsubr (&Senlarge_window
);
2846 defsubr (&Sshrink_window
);
2847 defsubr (&Sscroll_up
);
2848 defsubr (&Sscroll_down
);
2849 defsubr (&Sscroll_left
);
2850 defsubr (&Sscroll_right
);
2851 defsubr (&Sscroll_other_window
);
2852 defsubr (&Srecenter
);
2853 defsubr (&Smove_to_window_line
);
2854 defsubr (&Swindow_configuration_p
);
2855 defsubr (&Sset_window_configuration
);
2856 defsubr (&Scurrent_window_configuration
);
2857 defsubr (&Ssave_window_excursion
);
2862 initial_define_key (control_x_map
, '1', "delete-other-windows");
2863 initial_define_key (control_x_map
, '2', "split-window");
2864 initial_define_key (control_x_map
, '0', "delete-window");
2865 initial_define_key (control_x_map
, 'o', "other-window");
2866 initial_define_key (control_x_map
, '^', "enlarge-window");
2867 initial_define_key (control_x_map
, '<', "scroll-left");
2868 initial_define_key (control_x_map
, '>', "scroll-right");
2870 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
2871 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
2872 initial_define_key (meta_map
, 'v', "scroll-down");
2874 initial_define_key (global_map
, Ctl('L'), "recenter");
2875 initial_define_key (meta_map
, 'r', "move-to-window-line");