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 SCREEN_SELECTED_WINDOW (selected_screen). */
48 Lisp_Object selected_window
;
52 /* The root window for the screen.
53 This is accessed via SCREEN_ROOT_WINDOW (selected_screen). */
54 Lisp_Object root_window
;
58 /* The minibuffer window of the selected screen.
59 Note that you cannot test for minibufferness of an arbitrary window
60 by comparing against this; but you can test for minibufferness of
61 the selected window. */
62 Lisp_Object minibuf_window
;
64 /* Non-nil means it is the window for C-M-v to scroll
65 when the minibuffer is selected. */
66 Lisp_Object Vminibuf_scroll_window
;
68 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
69 Lisp_Object Vother_window_scroll_buffer
;
71 /* Window that the mouse is over (nil if no mouse support). */
72 Lisp_Object Vmouse_window
;
74 /* Last mouse click data structure (nil if no mouse support). */
75 Lisp_Object Vmouse_event
;
77 /* Non-nil means it's function to call to display temp buffers. */
78 Lisp_Object Vtemp_buffer_show_function
;
80 /* If a window gets smaller than either of these, it is removed. */
81 int window_min_height
;
84 /* Nonzero implies Fdisplay_buffer should create windows. */
87 /* Nonzero implies make new X screens for Fdisplay_buffer. */
90 /* Non-nil means use this function instead of default */
91 Lisp_Object Vpop_up_screen_function
;
93 /* Function to call to handle Fdisplay_buffer. */
94 Lisp_Object Vdisplay_buffer_function
;
96 /* Fdisplay_buffer always splits the largest window
97 if that window is more than this high. */
98 int split_height_threshold
;
100 /* Number of lines of continuity in scrolling by screenfuls. */
101 int next_screen_context_lines
;
103 /* Incremented for each window created. */
104 static int sequence_number
;
106 #define min(a, b) ((a) < (b) ? (a) : (b))
108 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
109 "Returns t if OBJ is a window.")
113 return XTYPE (obj
) == Lisp_Window
? Qt
: Qnil
;
119 register Lisp_Object val
;
120 register struct window
*p
;
122 /* Add sizeof (Lisp_Object) here because sizeof (struct Lisp_Vector)
123 includes the first element. */
125 make_number ((sizeof (struct window
) - sizeof (struct Lisp_Vector
)
126 + sizeof (Lisp_Object
))
127 / sizeof (Lisp_Object
)),
129 XSETTYPE (val
, Lisp_Window
);
131 XFASTINT (p
->sequence_number
) = ++sequence_number
;
132 XFASTINT (p
->left
) = XFASTINT (p
->top
)
133 = XFASTINT (p
->height
) = XFASTINT (p
->width
)
134 = XFASTINT (p
->hscroll
) = 0;
135 XFASTINT (p
->last_point_x
) = XFASTINT (p
->last_point_y
) = 0;
136 p
->start
= Fmake_marker ();
137 p
->pointm
= Fmake_marker ();
138 XFASTINT (p
->use_time
) = 0;
140 p
->display_table
= Qnil
;
145 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
146 "Return the window that the cursor now appears in and commands apply to.")
149 return selected_window
;
152 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 0, 0,
153 "Return the window used now for minibuffers.")
157 choose_minibuf_screen ();
158 #endif /* MULTI_SCREEN */
159 return minibuf_window
;
162 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 1, 1, 0,
163 "Returns non-nil if WINDOW is a minibuffer window.")
167 struct window
*w
= decode_window (window
);
168 return (MINI_WINDOW_P (w
) ? Qt
: Qnil
);
171 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
172 Spos_visible_in_window_p
, 0, 2, 0,
173 "Return t if position POS is currently on the screen in WINDOW.\n\
174 Returns nil if that position is scrolled vertically out of view.\n\
175 POS defaults to point; WINDOW, to the selected window.")
177 Lisp_Object pos
, window
;
179 register struct window
*w
;
183 register struct buffer
*buf
;
184 struct position posval
;
190 CHECK_NUMBER_COERCE_MARKER (pos
, 0);
195 window
= selected_window
;
197 CHECK_WINDOW (window
, 1);
198 w
= XWINDOW (window
);
199 top
= marker_position (w
->start
);
204 height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
206 buf
= XBUFFER (w
->buffer
);
207 if (XFASTINT (w
->last_modified
) >= BUF_MODIFF (buf
))
209 /* If screen is up to date,
210 use the info recorded about how much text fit on it. */
211 if (posint
< BUF_Z (buf
) - XFASTINT (w
->window_end_pos
)
212 || (XFASTINT (w
->window_end_vpos
) < height
))
218 if (posint
> BUF_Z (buf
))
221 /* If that info is not correct, calculate afresh */
222 posval
= *compute_motion (top
, 0, 0, posint
, height
, 0,
223 XFASTINT (w
->width
) - 1
224 - (XFASTINT (w
->width
) + XFASTINT (w
->left
)
225 != XSCREEN (w
->screen
)->width
),
226 XINT (w
->hscroll
), 0);
228 return posval
.vpos
< height
? Qt
: Qnil
;
232 static struct window
*
233 decode_window (window
)
234 register Lisp_Object window
;
237 return XWINDOW (selected_window
);
239 CHECK_WINDOW (window
, 0);
240 return XWINDOW (window
);
243 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
244 "Return the buffer that WINDOW is displaying.")
248 return decode_window (window
)->buffer
;
251 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
252 "Return the number of lines in WINDOW (including its mode line).")
256 return decode_window (window
)->height
;
259 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
260 "Return the number of columns in WINDOW.")
264 register struct window
*w
= decode_window (window
);
265 register int width
= w
->width
;
267 /* If this window does not end at the right margin,
268 must deduct one column for the border */
269 if ((width
+ w
->left
) == SCREEN_WIDTH (XSCREEN (WINDOW_SCREEN (w
))))
274 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
275 "Return the number of columns by which WINDOW is scrolled from left margin.")
279 return decode_window (window
)->hscroll
;
282 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
283 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
284 NCOL should be zero or positive.")
286 register Lisp_Object window
, ncol
;
288 register struct window
*w
;
290 CHECK_NUMBER (ncol
, 1);
291 if (XINT (ncol
) < 0) XFASTINT (ncol
) = 0;
292 if (XFASTINT (ncol
) >= (1 << (SHORTBITS
- 1)))
293 args_out_of_range (ncol
, Qnil
);
294 w
= decode_window (window
);
295 if (w
->hscroll
!= ncol
)
296 clip_changed
= 1; /* Prevent redisplay shortcuts */
301 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
302 "Return a list of the edge coordinates of WINDOW.\n\
303 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of screen.\n\
304 RIGHT is one more than the rightmost column used by WINDOW,\n\
305 and BOTTOM is one more than the bottommost row used by WINDOW\n\
310 register struct window
*w
= decode_window (window
);
312 return Fcons (w
->left
, Fcons (w
->top
,
313 Fcons (make_number (XFASTINT (w
->left
) + XFASTINT (w
->width
)),
314 Fcons (make_number (XFASTINT (w
->top
)
315 + XFASTINT (w
->height
)),
319 /* Test if the character at column *x, row *y is within window *w.
320 If it is not, return 0;
321 if it is in the window's text area,
322 set *x and *y to its location relative to the upper left corner
325 if it is on the window's modeline, return 2;
326 if it is on the border between the window and its right sibling,
329 coordinates_in_window (w
, x
, y
)
330 register struct window
*w
;
333 register int left
= XINT (w
->left
);
334 register int width
= XINT (w
->width
);
335 register int window_height
= XINT (w
->height
);
336 register int top
= XFASTINT (w
->top
);
338 if ( *x
< left
|| *x
>= left
+ width
339 || *y
< top
|| *y
>= top
+ window_height
)
342 /* Is the character is the mode line? */
343 if (*y
== top
+ window_height
- 1
344 && window_height
> 1) /* 1 line => minibuffer */
347 /* Is the character in the right border? */
348 if (*x
== left
+ width
- 1
349 && left
+ width
!= SCREEN_WIDTH (XSCREEN (w
->screen
)))
357 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
358 Scoordinates_in_window_p
, 2, 2, 0,
359 "Return non-nil if COORDINATES are in WINDOW.\n\
360 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
361 measured in characters from the upper-left corner of the screen.\n\
362 (0 . 0) denotes the character in the upper left corner of the\n\
364 If COORDINATES are in the text portion of WINDOW,\n\
365 the coordinates relative to the window are returned.\n\
366 If they are in the mode line of WINDOW, 'mode-line is returned.\n\
367 If they are on the border between WINDOW and its right sibling,\n\
368 'vertical-split is returned.")
369 (coordinates
, window
)
370 register Lisp_Object coordinates
, window
;
374 CHECK_WINDOW (window
, 0);
375 CHECK_CONS (coordinates
, 1);
376 x
= XINT (Fcar (coordinates
));
377 y
= XINT (Fcdr (coordinates
));
379 switch (coordinates_in_window (XWINDOW (window
), &x
, &y
))
381 case 0: /* NOT in window at all. */
384 case 1: /* In text part of window. */
387 case 2: /* In mode line of window. */
390 case 3: /* On right border of window. */
391 return Qvertical_split
;
398 /* Find the window containing column x, row y, and return it as a
399 Lisp_Object. If x, y is on the window's modeline, set *part
400 to 1; if it is on the separating line between the window and its
401 right sibling, set it to 2; otherwise set it to 0. If there is no
402 window under x, y return nil and leave *part unmodified. */
404 window_from_coordinates (screen
, x
, y
, part
)
409 register Lisp_Object tem
, first
;
411 tem
= first
= SCREEN_SELECTED_WINDOW (screen
);
415 int found
= coordinates_in_window (XWINDOW (tem
), &x
, &y
);
423 tem
= Fnext_window (tem
, Qt
, Qlambda
);
425 while (! EQ (tem
, first
));
430 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
431 "Return window containing row ROW, column COLUMN on SCREEN.\n\
432 If omitted, SCREEN defaults to the currently selected screen.\n\
433 The top left corner of the screen is considered to be row 0,\n\
435 (row
, column
, screen
)
436 Lisp_Object row
, column
, screen
;
441 XSET (screen
, Lisp_Screen
, selected_screen
);
443 CHECK_LIVE_SCREEN (screen
, 2);
444 CHECK_NUMBER (row
, 0);
445 CHECK_NUMBER (column
, 1);
447 return window_from_coordinates (XSCREEN (screen
),
448 XINT (row
), XINT (column
),
452 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
453 "Return current value of point in WINDOW.\n\
454 For a nonselected window, this is the value point would have\n\
455 if that window were selected.\n\
457 Note that, when WINDOW is the selected window and its buffer\n\
458 is also currently selected, the value returned is the same as (point).\n\
459 It would be more strictly correct to return the `top-level' value\n\
460 of point, outside of any save-excursion forms.\n\
461 But that is hard to define.")
465 register struct window
*w
= decode_window (window
);
467 if (w
== XWINDOW (selected_window
)
468 && current_buffer
== XBUFFER (w
->buffer
))
470 return Fmarker_position (w
->pointm
);
473 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
474 "Return position at which display currently starts in WINDOW.")
478 return Fmarker_position (decode_window (window
)->start
);
481 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 1, 0,
482 "Return position at which display currently ends in WINDOW.")
487 struct window
*w
= decode_window (window
);
489 XSET (value
, Lisp_Int
,
490 BUF_Z (current_buffer
) - XFASTINT (w
->window_end_pos
));
495 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
496 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
498 Lisp_Object window
, pos
;
500 register struct window
*w
= decode_window (window
);
502 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
503 if (w
== XWINDOW (selected_window
))
506 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
511 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
512 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
513 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
514 from overriding motion of point in order to display at this exact start.")
515 (window
, pos
, noforce
)
516 Lisp_Object window
, pos
, noforce
;
518 register struct window
*w
= decode_window (window
);
520 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
521 set_marker_restricted (w
->start
, pos
, w
->buffer
);
522 /* this is not right, but much easier than doing what is right. */
523 w
->start_at_line_beg
= Qnil
;
526 w
->update_mode_line
= Qt
;
527 XFASTINT (w
->last_modified
) = 0;
528 if (!EQ (window
, selected_window
))
529 windows_or_buffers_changed
++;
533 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
535 "Return WINDOW's dedicated object, usually t or nil.\n\
536 See also `set-window-buffer-dedicated'.")
540 return decode_window (window
)->dedicated
;
543 DEFUN ("set-window-buffer-dedicated", Fset_window_buffer_dedicated
,
544 Sset_window_buffer_dedicated
, 2, 2, 0,
545 "Make WINDOW display BUFFER and be dedicated to that buffer.\n\
546 Then Emacs will not automatically change which buffer appears in WINDOW.\n\
547 If BUFFER is nil, make WINDOW not be dedicated (but don't change which\n\
548 buffer appears in it currently).")
550 Lisp_Object window
, arg
;
552 register struct window
*w
= decode_window (window
);
558 Fset_window_buffer (window
, Fget_buffer_create (arg
));
565 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
567 "Return the display-table that WINDOW is using.")
571 return decode_window (window
)->display_table
;
574 /* Get the display table for use currently on window W.
575 This is either W's display table or W's buffer's display table.
576 Ignore the specified tables if they are not valid;
577 if no valid table is specified, return 0. */
580 window_display_table (w
)
584 tem
= w
->display_table
;
585 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
586 return XVECTOR (tem
);
587 tem
= XBUFFER (w
->buffer
)->display_table
;
588 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
589 return XVECTOR (tem
);
590 tem
= Vstandard_display_table
;
591 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
592 return XVECTOR (tem
);
596 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
597 "Set WINDOW's display-table to TABLE.")
599 register Lisp_Object window
, table
;
601 register struct window
*w
;
602 register Lisp_Object z
; /* Return value. */
604 w
= decode_window (window
);
605 w
->display_table
= table
;
609 /* Record info on buffer window w is displaying
610 when it is about to cease to display that buffer. */
613 register struct window
*w
;
615 Lisp_Object buf
= w
->buffer
;
617 if (XBUFFER (buf
) != XMARKER (w
->pointm
)->buffer
)
620 if (w
== XWINDOW (selected_window
)
621 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
622 /* Do this except when the selected window's buffer
623 is being removed from some other window. */
624 XBUFFER (buf
)->last_window_start
= marker_position (w
->start
);
626 /* Point in the selected window's buffer
627 is actually stored in that buffer, and the window's pointm isn't used.
628 So don't clobber point in that buffer. */
629 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
))
630 BUF_PT (XBUFFER (buf
))
631 = clip_to_bounds (BUF_BEGV (XBUFFER (buf
)),
632 marker_position (w
->pointm
),
633 BUF_ZV (XBUFFER (buf
)));
636 /* Put replacement into the window structure in place of old. */
638 replace_window (old
, replacement
)
639 Lisp_Object old
, replacement
;
641 register Lisp_Object tem
;
642 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
644 /* If OLD is its screen's root_window, then replacement is the new
645 root_window for that screen. */
647 if (old
== XSCREEN (o
->screen
)->root_window
)
648 XSCREEN (o
->screen
)->root_window
= replacement
;
653 p
->height
= o
->height
;
655 p
->next
= tem
= o
->next
;
657 XWINDOW (tem
)->prev
= replacement
;
659 p
->prev
= tem
= o
->prev
;
661 XWINDOW (tem
)->next
= replacement
;
663 p
->parent
= tem
= o
->parent
;
666 if (EQ (XWINDOW (tem
)->vchild
, old
))
667 XWINDOW (tem
)->vchild
= replacement
;
668 if (EQ (XWINDOW (tem
)->hchild
, old
))
669 XWINDOW (tem
)->hchild
= replacement
;
672 /*** Here, if replacement is a vertical combination
673 and so is its new parent, we should make replacement's
674 children be children of that parent instead. ***/
677 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
678 "Remove WINDOW from the display. Default is selected window.")
680 register Lisp_Object window
;
682 register Lisp_Object tem
, parent
, sib
;
683 register struct window
*p
;
684 register struct window
*par
;
687 window
= selected_window
;
689 CHECK_WINDOW (window
, 0);
691 p
= XWINDOW (window
);
694 error ("Attempt to delete minibuffer or sole ordinary window");
695 par
= XWINDOW (parent
);
697 windows_or_buffers_changed
++;
699 if (EQ (window
, selected_window
))
700 Fselect_window (Fnext_window (window
, Qnil
, Qnil
));
703 /* tem is null for dummy parent windows
704 (which have inferiors but not any contents themselves) */
708 unchain_marker (p
->pointm
);
709 unchain_marker (p
->start
);
715 XWINDOW (tem
)->prev
= p
->prev
;
719 XWINDOW (tem
)->next
= p
->next
;
721 if (EQ (window
, par
->hchild
))
722 par
->hchild
= p
->next
;
723 if (EQ (window
, par
->vchild
))
724 par
->vchild
= p
->next
;
726 /* Find one of our siblings to give our space to. */
730 /* If p gives its space to its next sibling, that sibling needs
731 to have its top/left side pulled back to where p's is.
732 set_window_{height,width} will re-position the sibling's
735 XFASTINT (XWINDOW (sib
)->top
) = p
->top
;
736 XFASTINT (XWINDOW (sib
)->left
) = p
->left
;
739 /* Stretch that sibling. */
740 if (!NILP (par
->vchild
))
741 set_window_height (sib
,
742 XFASTINT (XWINDOW (sib
)->height
) + XFASTINT (p
->height
),
744 if (!NILP (par
->hchild
))
745 set_window_width (sib
,
746 XFASTINT (XWINDOW (sib
)->width
) + XFASTINT (p
->width
),
749 /* If parent now has only one child,
750 put the child into the parent's place. */
755 if (NILP (XWINDOW (tem
)->next
))
756 replace_window (parent
, tem
);
761 extern Lisp_Object
next_screen (), prev_screen ();
763 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
764 "Return next window after WINDOW in canonical ordering of windows.\n\
765 If omitted, WINDOW defaults to the selected window.\n\
767 Optional second arg MINIBUF t means count the minibuffer window even\n\
768 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
769 it is active. MINIBUF neither t nor nil means not to count the\n\
770 minibuffer even if it is active.\n\
772 Several screens may share a single minibuffer; if the minibuffer\n\
773 counts, all windows on all screens that share that minibuffer count\n\
774 too. This means that next-window may be used to iterate through the\n\
775 set of windows even when the minibuffer is on another screen. If the\n\
776 minibuffer does not count, only windows from WINDOW's screen count.\n\
778 Optional third arg ALL-SCREENS t means include windows on all screens.\n\
779 ALL-SCREENS nil or omitted means cycle within the screens as specified\n\
780 above. If neither nil nor t, restrict to WINDOW's screen.")
781 (window
, minibuf
, all_screens
)
782 register Lisp_Object window
, minibuf
, all_screens
;
784 register Lisp_Object tem
;
785 Lisp_Object start_window
;
788 window
= selected_window
;
790 CHECK_WINDOW (window
, 0);
792 start_window
= window
;
794 /* minibuf == nil may or may not include minibuffers.
795 Decide if it does. */
797 minibuf
= (minibuf_level
? Qt
: Qlambda
);
799 /* all_screens == nil doesn't specify which screens to include.
800 Decide which screens it includes. */
801 if (NILP (all_screens
))
802 all_screens
= (EQ (minibuf
, Qt
)
803 ? (SCREEN_MINIBUF_WINDOW
806 (XWINDOW (window
)))))
808 else if (! EQ (all_screens
, Qt
))
811 /* Do this loop at least once, to get the next window, and perhaps
812 again, if we hit the minibuffer and that is not acceptable. */
815 /* Find a window that actually has a next one. This loop
816 climbs up the tree. */
817 while (tem
= XWINDOW (window
)->next
, NILP (tem
))
818 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
822 /* We've reached the end of this screen.
823 Which other screens are acceptable? */
824 tem
= WINDOW_SCREEN (XWINDOW (window
));
826 if (! NILP (all_screens
))
827 tem
= next_screen (tem
, all_screens
);
829 tem
= SCREEN_ROOT_WINDOW (XSCREEN (tem
));
836 /* If we're in a combination window, find its first child and
837 recurse on that. Otherwise, we've found the window we want. */
840 if (!NILP (XWINDOW (window
)->hchild
))
841 window
= XWINDOW (window
)->hchild
;
842 else if (!NILP (XWINDOW (window
)->vchild
))
843 window
= XWINDOW (window
)->vchild
;
847 /* Which windows are acceptible?
848 Exit the loop and accept this window if
849 this isn't a minibuffer window, or
850 we're accepting minibuffer windows, or
851 we've come all the way around and we're back at the original window. */
852 while (MINI_WINDOW_P (XWINDOW (window
))
853 && ! EQ (minibuf
, Qt
)
854 && window
!= start_window
);
859 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
860 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
861 If omitted, WINDOW defaults to the selected window.\n\
863 Optional second arg MINIBUF t means count the minibuffer window even\n\
864 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
865 it is active. MINIBUF neither t nor nil means not to count the\n\
866 minibuffer even if it is active.\n\
868 Several screens may share a single minibuffer; if the minibuffer\n\
869 counts, all windows on all screens that share that minibuffer count\n\
870 too. This means that previous-window may be used to iterate through\n\
871 the set of windows even when the minibuffer is on another screen. If\n\
872 the minibuffer does not count, only windows from WINDOW's screen\n\
875 Optional third arg ALL-SCREENS t means include windows on all screens.\n\
876 ALL-SCREENS nil or omitted means cycle within the screens as specified\n\
877 above. If neither nil nor t, restrict to WINDOW's screen.")
878 (window
, minibuf
, all_screens
)
879 register Lisp_Object window
, minibuf
, all_screens
;
881 register Lisp_Object tem
;
882 Lisp_Object start_window
;
885 window
= selected_window
;
887 CHECK_WINDOW (window
, 0);
889 start_window
= window
;
891 /* minibuf == nil may or may not include minibuffers.
892 Decide if it does. */
894 minibuf
= (minibuf_level
? Qt
: Qlambda
);
896 /* all_screens == nil doesn't specify which screens to include.
897 Decide which screens it includes. */
898 if (NILP (all_screens
))
899 all_screens
= (EQ (minibuf
, Qt
)
900 ? (SCREEN_MINIBUF_WINDOW
903 (XWINDOW (window
)))))
905 else if (! EQ (all_screens
, Qt
))
908 /* Do this loop at least once, to get the previous window, and perhaps
909 again, if we hit the minibuffer and that is not acceptable. */
912 /* Find a window that actually has a previous one. This loop
913 climbs up the tree. */
914 while (tem
= XWINDOW (window
)->prev
, NILP (tem
))
915 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
919 /* We have found the top window on the screen.
920 Which screens are acceptable? */
921 tem
= WINDOW_SCREEN (XWINDOW (window
));
923 if (! NILP (all_screens
))
924 tem
= next_screen (tem
, all_screens
);
926 tem
= SCREEN_ROOT_WINDOW (XSCREEN (tem
));
932 /* If we're in a combination window, find its last child and
933 recurse on that. Otherwise, we've found the window we want. */
936 if (!NILP (XWINDOW (window
)->hchild
))
937 window
= XWINDOW (window
)->hchild
;
938 else if (!NILP (XWINDOW (window
)->vchild
))
939 window
= XWINDOW (window
)->vchild
;
941 while (tem
= XWINDOW (window
)->next
, !NILP (tem
))
945 /* Which windows are acceptable?
946 Exit the loop and accept this window if
947 this isn't a minibuffer window, or
948 we're accepting minibuffer windows, or
949 we've come all the way around and we're back at the original window. */
950 while (MINI_WINDOW_P (XWINDOW (window
))
952 && window
!= start_window
);
957 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
958 "Select the ARG'th different window on this screen.\n\
959 All windows on current screen are arranged in a cyclic order.\n\
960 This command selects the window ARG steps away in that order.\n\
961 A negative ARG moves in the opposite order. If the optional second\n\
962 argument ALL_SCREENS is non-nil, cycle through all screens.")
964 register Lisp_Object n
, all_screens
;
967 register Lisp_Object w
;
975 w
= Fnext_window (w
, Qnil
, all_screens
);
980 w
= Fprevious_window (w
, Qnil
, all_screens
);
987 /* Look at all windows, performing an operation specified by TYPE
989 If SCREENS is Qt, look at all screens, if Qnil, look at just the selected
990 screen. If SCREENS is a screen, just look at windows on that screen.
991 If MINI is non-zero, perform the operation on minibuffer windows too.
997 GET_BUFFER_WINDOW
, /* Arg is buffer */
998 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
999 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
1000 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
1002 UNSHOW_BUFFER
, /* Arg is buffer */
1006 window_loop (type
, obj
, mini
, screens
)
1007 enum window_loop type
;
1008 register Lisp_Object obj
, screens
;
1011 register Lisp_Object w
;
1012 register Lisp_Object best_window
;
1013 register Lisp_Object next_window
;
1014 register Lisp_Object first_window
;
1017 /* If we're only looping through windows on a particular screen,
1018 screen points to that screen. If we're looping through windows
1019 on all screens, screen is 0. */
1020 if (SCREENP (screens
))
1021 screen
= XSCREEN (screens
);
1022 else if (NILP (screens
))
1023 screen
= selected_screen
;
1027 /* Pick a window to start with. */
1028 if (XTYPE (obj
) == Lisp_Window
)
1031 first_window
= SCREEN_SELECTED_WINDOW (screen
);
1033 first_window
= SCREEN_SELECTED_WINDOW (selected_screen
);
1039 /* Pick the next window now, since some operations will delete
1040 the current window. */
1043 next_window
= Fnext_window (w
, (mini
? Qt
: Qnil
), Qlambda
);
1045 #endif /* MULTI_SCREEN */
1046 /* We know screen is 0, so we're looping through all screens.
1047 Or we know this isn't a MULTI_SCREEN Emacs, so who cares? */
1048 next_window
= Fnext_window (w
, mini
? Qt
: Qnil
, Qt
);
1050 if (!MINI_WINDOW_P (XWINDOW (w
))
1051 || (mini
&& minibuf_level
> 0))
1054 case GET_BUFFER_WINDOW
:
1056 /* Ignore invisible and iconified screens. */
1057 if (! SCREEN_VISIBLE_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
))))
1058 || SCREEN_ICONIFIED_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
)))))
1061 if (XBUFFER (XWINDOW (w
)->buffer
) == XBUFFER (obj
))
1065 case GET_LRU_WINDOW
:
1066 /* t as arg means consider only full-width windows */
1067 if (!NILP (obj
) && XFASTINT (XWINDOW (w
)->width
) != screen
->width
)
1070 /* Ignore invisible and iconified screens. */
1071 if (! SCREEN_VISIBLE_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
))))
1072 || SCREEN_ICONIFIED_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
)))))
1075 /* Ignore dedicated windows and minibuffers. */
1076 if (MINI_WINDOW_P (XWINDOW (w
))
1077 || !NILP (XWINDOW (w
)->dedicated
))
1079 if (NILP (best_window
)
1080 || (XFASTINT (XWINDOW (best_window
)->use_time
)
1081 > XFASTINT (XWINDOW (w
)->use_time
)))
1085 case DELETE_OTHER_WINDOWS
:
1086 if (XWINDOW (w
) != XWINDOW (obj
))
1090 case DELETE_BUFFER_WINDOWS
:
1091 if (EQ (XWINDOW (w
)->buffer
, obj
))
1093 /* If we're deleting the buffer displayed in the only window
1094 on the screen, find a new buffer to display there. */
1095 if (NILP (XWINDOW (w
)->parent
))
1097 Lisp_Object new_buffer
= Fother_buffer (obj
);
1098 if (NILP (new_buffer
))
1100 = Fget_buffer_create (build_string ("*scratch*"));
1101 Fset_window_buffer (w
, new_buffer
);
1102 Fset_buffer (XWINDOW (w
)->buffer
);
1109 case GET_LARGEST_WINDOW
:
1111 /* Ignore invisible and iconified screens. */
1112 if (! SCREEN_VISIBLE_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
))))
1113 || SCREEN_ICONIFIED_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
)))))
1116 /* Ignore dedicated windows and minibuffers. */
1117 if (MINI_WINDOW_P (XWINDOW (w
))
1118 || !NILP (XWINDOW (w
)->dedicated
))
1121 struct window
*best_window_ptr
= XWINDOW (best_window
);
1122 struct window
*w_ptr
= XWINDOW (w
);
1123 if (NILP (best_window
) ||
1124 (XFASTINT (w_ptr
->height
) * XFASTINT (w_ptr
->width
))
1125 > (XFASTINT (best_window_ptr
->height
)
1126 * XFASTINT (best_window_ptr
->width
)))
1132 if (EQ (XWINDOW (w
)->buffer
, obj
))
1134 /* Find another buffer to show in this window. */
1135 Lisp_Object another_buffer
= Fother_buffer (obj
);
1136 if (NILP (another_buffer
))
1138 = Fget_buffer_create (build_string ("*scratch*"));
1139 Fset_window_buffer (w
, another_buffer
);
1140 if (EQ (w
, selected_window
))
1141 Fset_buffer (XWINDOW (w
)->buffer
);
1147 while (! EQ (w
, first_window
));
1152 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 1, 0,
1153 "Return the window least recently selected or used for display.\n\
1154 If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1155 screen, search only that screen.\n")
1157 Lisp_Object screens
;
1159 register Lisp_Object w
;
1160 /* First try for a window that is full-width */
1161 w
= window_loop (GET_LRU_WINDOW
, Qt
, 0, screens
);
1162 if (!NILP (w
) && !EQ (w
, selected_window
))
1164 /* If none of them, try the rest */
1165 return window_loop (GET_LRU_WINDOW
, Qnil
, 0, screens
);
1168 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 1, 0,
1169 "Return the largest window in area.\n\
1170 If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1171 screen, search only that screen.\n")
1175 return window_loop (GET_LARGEST_WINDOW
, Qnil
, 0,
1179 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 1, 2, 0,
1180 "Return a window currently displaying BUFFER, or nil if none.\n\
1181 If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1182 screen, search only that screen.\n")
1184 Lisp_Object buffer
, screen
;
1186 buffer
= Fget_buffer (buffer
);
1187 if (XTYPE (buffer
) == Lisp_Buffer
)
1188 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, screen
);
1193 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
1195 "Make WINDOW (or the selected window) fill its screen.\n\
1196 Only the screen WINDOW is on is affected.")
1202 struct buffer
*obuf
= current_buffer
;
1206 window
= selected_window
;
1208 CHECK_WINDOW (window
, 0);
1210 w
= XWINDOW (window
);
1211 top
= XFASTINT (w
->top
);
1213 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_SCREEN(w
));
1215 Fset_buffer (w
->buffer
);
1216 SET_PT (marker_position (w
->start
));
1217 Frecenter (make_number (top
));
1219 set_buffer_internal (obuf
);
1224 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
1225 1, 1, "bDelete windows on (buffer): ",
1226 "Delete all windows showing BUFFER.")
1232 buffer
= Fget_buffer (buffer
);
1233 CHECK_BUFFER (buffer
, 0);
1234 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, Qt
);
1239 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
1240 Sreplace_buffer_in_windows
,
1241 1, 1, "bReplace buffer in windows: ",
1242 "Replace BUFFER with some other buffer in all windows showing it.")
1248 buffer
= Fget_buffer (buffer
);
1249 CHECK_BUFFER (buffer
, 0);
1250 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
1255 /* Set the height of WINDOW and all its inferiors. */
1256 /* Normally the window is deleted if it gets too small.
1257 nodelete nonzero means do not do this.
1258 (The caller should check later and do so if appropriate) */
1260 set_window_height (window
, height
, nodelete
)
1265 register struct window
*w
= XWINDOW (window
);
1266 register struct window
*c
;
1267 int oheight
= XFASTINT (w
->height
);
1268 int top
, pos
, lastbot
, opos
, lastobot
;
1272 && ! NILP (w
->parent
)
1273 && height
< window_min_height
)
1275 Fdelete_window (window
);
1279 XFASTINT (w
->last_modified
) = 0;
1280 windows_or_buffers_changed
++;
1281 XFASTINT (w
->height
) = height
;
1282 if (!NILP (w
->hchild
))
1284 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1286 XWINDOW (child
)->top
= w
->top
;
1287 set_window_height (child
, height
, nodelete
);
1290 else if (!NILP (w
->vchild
))
1292 lastbot
= top
= XFASTINT (w
->top
);
1294 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
1296 c
= XWINDOW (child
);
1298 opos
= lastobot
+ XFASTINT (c
->height
);
1300 XFASTINT (c
->top
) = lastbot
;
1302 pos
= (((opos
* height
) << 1) + oheight
) / (oheight
<< 1);
1304 /* Avoid confusion: inhibit deletion of child if becomes too small */
1305 set_window_height (child
, pos
+ top
- lastbot
, 1);
1307 /* Now advance child to next window,
1308 and set lastbot if child was not just deleted. */
1309 lastbot
= pos
+ top
;
1312 /* Now delete any children that became too small. */
1314 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1316 set_window_height (child
, XINT (XWINDOW (child
)->height
), 0);
1321 /* Recursively set width of WINDOW and its inferiors. */
1323 set_window_width (window
, width
, nodelete
)
1328 register struct window
*w
= XWINDOW (window
);
1329 register struct window
*c
;
1330 int owidth
= XFASTINT (w
->width
);
1331 int left
, pos
, lastright
, opos
, lastoright
;
1334 if (!nodelete
&& width
< window_min_width
)
1336 Fdelete_window (window
);
1340 XFASTINT (w
->last_modified
) = 0;
1341 windows_or_buffers_changed
++;
1342 XFASTINT (w
->width
) = width
;
1343 if (!NILP (w
->vchild
))
1345 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1347 XWINDOW (child
)->left
= w
->left
;
1348 set_window_width (child
, width
, nodelete
);
1351 else if (!NILP (w
->hchild
))
1353 lastright
= left
= XFASTINT (w
->left
);
1355 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
1357 c
= XWINDOW (child
);
1359 opos
= lastoright
+ XFASTINT (c
->width
);
1361 XFASTINT (c
->left
) = lastright
;
1363 pos
= (((opos
* width
) << 1) + owidth
) / (owidth
<< 1);
1365 /* Inhibit deletion for becoming too small */
1366 set_window_width (child
, pos
+ left
- lastright
, 1);
1368 /* Now advance child to next window,
1369 and set lastright if child was not just deleted. */
1370 lastright
= pos
+ left
, lastoright
= opos
;
1372 /* Delete children that became too small */
1374 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1376 set_window_width (child
, XINT (XWINDOW (child
)->width
), 0);
1381 int window_select_count
;
1383 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 2, 0,
1384 "Make WINDOW display BUFFER as its contents.\n\
1385 BUFFER can be a buffer or buffer name.")
1387 register Lisp_Object window
, buffer
;
1389 register Lisp_Object tem
;
1390 register struct window
*w
= decode_window (window
);
1392 buffer
= Fget_buffer (buffer
);
1393 CHECK_BUFFER (buffer
, 1);
1395 if (NILP (XBUFFER (buffer
)->name
))
1396 error ("Attempt to display deleted buffer");
1400 error ("Window is deleted");
1401 else if (! EQ (tem
, Qt
)) /* w->buffer is t when the window
1402 is first being set up. */
1404 if (!NILP (w
->dedicated
) && !EQ (tem
, buffer
))
1405 error ("Window is dedicated to %s\n", tem
);
1411 Fset_marker (w
->pointm
,
1412 make_number (BUF_PT (XBUFFER (buffer
))),
1414 set_marker_restricted (w
->start
,
1415 make_number (XBUFFER (buffer
)->last_window_start
),
1417 w
->start_at_line_beg
= Qnil
;
1418 XFASTINT (w
->last_modified
) = 0;
1419 windows_or_buffers_changed
++;
1420 if (EQ (window
, selected_window
))
1421 Fset_buffer (buffer
);
1426 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 1, 0,
1427 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1428 The main editor command loop selects the buffer of the selected window\n\
1429 before each command.")
1431 register Lisp_Object window
;
1433 register struct window
*w
;
1434 register struct window
*ow
= XWINDOW (selected_window
);
1436 CHECK_WINDOW (window
, 0);
1438 w
= XWINDOW (window
);
1440 if (NILP (w
->buffer
))
1441 error ("Trying to select deleted window or non-leaf window");
1443 XFASTINT (w
->use_time
) = ++window_select_count
;
1444 if (EQ (window
, selected_window
))
1447 Fset_marker (ow
->pointm
, make_number (BUF_PT (XBUFFER (ow
->buffer
))),
1450 selected_window
= window
;
1452 if (XSCREEN (WINDOW_SCREEN (w
)) != selected_screen
)
1454 XSCREEN (WINDOW_SCREEN (w
))->selected_window
= window
;
1455 Fselect_screen (WINDOW_SCREEN (w
), Qnil
);
1458 selected_screen
->selected_window
= window
;
1461 record_buffer (w
->buffer
);
1462 Fset_buffer (w
->buffer
);
1464 /* Go to the point recorded in the window.
1465 This is important when the buffer is in more
1466 than one window. It also matters when
1467 redisplay_window has altered point after scrolling,
1468 because it makes the change only in the window. */
1470 register int new_point
= marker_position (w
->pointm
);
1471 if (new_point
< BEGV
)
1479 windows_or_buffers_changed
++;
1483 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 2, 0,
1484 "Make BUFFER appear in some window but don't select it.\n\
1485 BUFFER can be a buffer or a buffer name.\n\
1486 If BUFFER is shown already in some window, just use that one,\n\
1487 unless the window is the selected window and the optional second\n\
1488 argument NOT_THIS_WINDOW is non-nil.\n\
1489 Returns the window displaying BUFFER.")
1490 (buffer
, not_this_window
)
1491 register Lisp_Object buffer
, not_this_window
;
1493 register Lisp_Object window
;
1495 buffer
= Fget_buffer (buffer
);
1496 CHECK_BUFFER (buffer
, 0);
1498 if (!NILP (Vdisplay_buffer_function
))
1499 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
1501 if (NILP (not_this_window
)
1502 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
1503 return selected_window
;
1505 window
= Fget_buffer_window (buffer
, Qnil
);
1507 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
1511 /* If there are no screens open that have more than a minibuffer,
1512 we need to create a new screen. */
1513 if (pop_up_screens
|| last_nonminibuf_screen
== 0)
1516 = Fscreen_selected_window (call0 (Vpop_up_screen_function
));
1517 Fset_window_buffer (window
, buffer
);
1519 Fselect_screen (XWINDOW (window
)->screen
, Qnil
);
1523 #endif /* MULTI_SCREEN */
1527 || SCREEN_MINIBUF_ONLY_P (selected_screen
)
1531 Lisp_Object screens
= Qnil
;
1534 if (SCREEN_MINIBUF_ONLY_P (selected_screen
))
1535 XSET (screens
, Lisp_Screen
, last_nonminibuf_screen
);
1537 /* Don't try to create a window if would get an error */
1538 if (split_height_threshold
< window_min_height
<< 1)
1539 split_height_threshold
= window_min_height
<< 1;
1541 window
= Fget_largest_window (screens
);
1544 && window_height (window
) >= split_height_threshold
1546 (XFASTINT (XWINDOW (window
)->width
)
1547 == SCREEN_WIDTH (XSCREEN (WINDOW_SCREEN (XWINDOW (window
))))))
1548 window
= Fsplit_window (window
, Qnil
, Qnil
);
1551 window
= Fget_lru_window (screens
);
1552 if ((EQ (window
, selected_window
)
1553 || EQ (XWINDOW (window
)->parent
, Qnil
))
1554 && window_height (window
) >= window_min_height
<< 1)
1555 window
= Fsplit_window (window
, Qnil
, Qnil
);
1559 window
= Fget_lru_window (Qnil
);
1561 Fset_window_buffer (window
, buffer
);
1566 temp_output_buffer_show (buf
)
1567 register Lisp_Object buf
;
1569 register struct buffer
*old
= current_buffer
;
1570 register Lisp_Object window
;
1571 register struct window
*w
;
1574 XBUFFER (buf
)->save_modified
= MODIFF
;
1579 set_buffer_internal (old
);
1581 if (!EQ (Vtemp_buffer_show_function
, Qnil
))
1582 call1 (Vtemp_buffer_show_function
, buf
);
1585 window
= Fdisplay_buffer (buf
, Qnil
);
1588 if (XSCREEN (XWINDOW (window
)->screen
) != selected_screen
)
1589 Fmake_screen_visible (XWINDOW (window
)->screen
);
1590 #endif /* MULTI_SCREEN */
1591 Vminibuf_scroll_window
= window
;
1592 w
= XWINDOW (window
);
1593 XFASTINT (w
->hscroll
) = 0;
1594 set_marker_restricted (w
->start
, make_number (1), buf
);
1595 set_marker_restricted (w
->pointm
, make_number (1), buf
);
1600 make_dummy_parent (window
)
1603 register Lisp_Object old
, new;
1604 register struct window
*o
, *p
;
1607 XSETTYPE (old
, Lisp_Vector
);
1608 new = Fcopy_sequence (old
);
1609 XSETTYPE (new, Lisp_Window
);
1613 XFASTINT (p
->sequence_number
) = ++sequence_number
;
1615 /* Put new into window structure in place of window */
1616 replace_window (window
, new);
1629 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
1630 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1631 WINDOW defaults to selected one and SIZE to half its size.\n\
1632 If optional third arg HOR-FLAG is non-nil, split side by side\n\
1633 and put SIZE columns in the first of the pair.")
1634 (window
, chsize
, horflag
)
1635 Lisp_Object window
, chsize
, horflag
;
1637 register Lisp_Object
new;
1638 register struct window
*o
, *p
;
1642 window
= selected_window
;
1644 CHECK_WINDOW (window
, 0);
1646 o
= XWINDOW (window
);
1650 if (!NILP (horflag
))
1651 /* Round odd size up, since this is for the left-hand window,
1652 and it will lose a column for the separators. */
1653 size
= ((XFASTINT (o
->width
) + 1) & -2) >> 1;
1655 size
= XFASTINT (o
->height
) >> 1;
1659 CHECK_NUMBER (chsize
, 1);
1660 size
= XINT (chsize
);
1663 if (MINI_WINDOW_P (o
))
1664 error ("Attempt to split minibuffer window");
1665 else if (SCREEN_NO_SPLIT_P (XSCREEN (WINDOW_SCREEN (o
))))
1666 error ("Attempt to split unsplittable screen");
1668 /* Smaller values might permit a crash. */
1669 if (window_min_width
< 2)
1670 window_min_width
= 2;
1671 if (window_min_height
< 2)
1672 window_min_height
= 2;
1676 if (size
< window_min_height
1677 || size
+ window_min_height
> XFASTINT (o
->height
))
1678 args_out_of_range_3 (window
, chsize
, horflag
);
1679 if (NILP (o
->parent
)
1680 || NILP (XWINDOW (o
->parent
)->vchild
))
1682 make_dummy_parent (window
);
1684 XWINDOW (new)->vchild
= window
;
1689 if (size
< window_min_width
1690 || size
+ window_min_width
> XFASTINT (o
->width
))
1691 args_out_of_range_3 (window
, chsize
, horflag
);
1692 if (NILP (o
->parent
)
1693 || NILP (XWINDOW (o
->parent
)->hchild
))
1695 make_dummy_parent (window
);
1697 XWINDOW (new)->hchild
= window
;
1701 /* Now we know that window's parent is a vertical combination
1702 if we are dividing vertically, or a horizontal combination
1703 if we are making side-by-side windows */
1705 windows_or_buffers_changed
++;
1706 new = make_window ();
1709 p
->screen
= o
->screen
;
1711 if (!NILP (p
->next
))
1712 XWINDOW (p
->next
)->prev
= new;
1715 p
->parent
= o
->parent
;
1718 Fset_window_buffer (new, o
->buffer
);
1720 /* Apportion the available screen space among the two new windows */
1722 if (!NILP (horflag
))
1724 p
->height
= o
->height
;
1726 XFASTINT (p
->width
) = XFASTINT (o
->width
) - size
;
1727 XFASTINT (o
->width
) = size
;
1728 XFASTINT (p
->left
) = XFASTINT (o
->left
) + size
;
1733 p
->width
= o
->width
;
1734 XFASTINT (p
->height
) = XFASTINT (o
->height
) - size
;
1735 XFASTINT (o
->height
) = size
;
1736 XFASTINT (p
->top
) = XFASTINT (o
->top
) + size
;
1742 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
1743 "Make current window ARG lines bigger.\n\
1744 From program, optional second arg non-nil means grow sideways ARG columns.")
1746 register Lisp_Object n
, side
;
1748 CHECK_NUMBER (n
, 0);
1749 change_window_height (XINT (n
), !NILP (side
));
1753 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
1754 "Make current window ARG lines smaller.\n\
1755 From program, optional second arg non-nil means shrink sideways ARG columns.")
1757 register Lisp_Object n
, side
;
1759 CHECK_NUMBER (n
, 0);
1760 change_window_height (-XINT (n
), !NILP (side
));
1765 window_height (window
)
1768 register struct window
*p
= XWINDOW (window
);
1769 return XFASTINT (p
->height
);
1773 window_width (window
)
1776 register struct window
*p
= XWINDOW (window
);
1777 return XFASTINT (p
->width
);
1780 #define MINSIZE(w) \
1781 (widthflag ? window_min_width : window_min_height)
1784 *(widthflag ? (int *) &(w)->left : (int *) &(w)->top)
1786 #define CURSIZE(w) \
1787 *(widthflag ? (int *) &(w)->width : (int *) &(w)->height)
1789 /* Unlike set_window_height, this function
1790 also changes the heights of the siblings so as to
1791 keep everything consistent. */
1793 change_window_height (delta
, widthflag
)
1797 register Lisp_Object parent
;
1799 register struct window
*p
;
1801 int (*sizefun
) () = widthflag
? window_width
: window_height
;
1802 register int (*setsizefun
) () = (widthflag
1804 : set_window_height
);
1806 /* Smaller values might permit a crash. */
1807 if (window_min_width
< 2)
1808 window_min_width
= 2;
1809 if (window_min_height
< 2)
1810 window_min_height
= 2;
1812 window
= selected_window
;
1815 p
= XWINDOW (window
);
1820 error ("No other window to side of this one");
1823 if (widthflag
? !NILP (XWINDOW (parent
)->hchild
)
1824 : !NILP (XWINDOW (parent
)->vchild
))
1829 sizep
= &CURSIZE (p
);
1831 if (*sizep
+ delta
< MINSIZE (p
)
1832 && !NILP (XWINDOW (window
)->parent
))
1834 Fdelete_window (window
);
1839 register int maxdelta
;
1841 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - *sizep
1842 : !NILP (p
->next
) ? (*sizefun
) (p
->next
) - MINSIZE (p
->next
)
1843 : !NILP (p
->prev
) ? (*sizefun
) (p
->prev
) - MINSIZE (p
->prev
)
1844 /* This is a screen with only one window, a minibuffer-only
1845 or a minibufferless screen. */
1848 if (delta
> maxdelta
)
1849 /* This case traps trying to make the minibuffer
1850 the full screen, or make the only window aside from the
1851 minibuffer the full screen. */
1858 if (!NILP (p
->next
) &&
1859 (*sizefun
) (p
->next
) - delta
>= MINSIZE (p
->next
))
1861 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
) - delta
, 0);
1862 (*setsizefun
) (window
, *sizep
+ delta
, 0);
1863 CURBEG (XWINDOW (p
->next
)) += delta
;
1864 /* This does not change size of p->next,
1865 but it propagates the new top edge to its children */
1866 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
), 0);
1868 else if (!NILP (p
->prev
) &&
1869 (*sizefun
) (p
->prev
) - delta
>= MINSIZE (p
->prev
))
1871 (*setsizefun
) (p
->prev
, (*sizefun
) (p
->prev
) - delta
, 0);
1872 CURBEG (p
) -= delta
;
1873 (*setsizefun
) (window
, *sizep
+ delta
, 0);
1877 register int delta1
;
1878 register int opht
= (*sizefun
) (parent
);
1880 /* If trying to grow this window to or beyond size of the parent,
1881 make delta1 so big that, on shrinking back down,
1882 all the siblings end up with less than one line and are deleted. */
1883 if (opht
<= *sizep
+ delta
)
1884 delta1
= opht
* opht
* 2;
1885 /* Otherwise, make delta1 just right so that if we add delta1
1886 lines to this window and to the parent, and then shrink
1887 the parent back to its original size, the new proportional
1888 size of this window will increase by delta. */
1890 delta1
= (delta
* opht
* 100) / ((opht
- *sizep
- delta
) * 100);
1892 /* Add delta1 lines or columns to this window, and to the parent,
1893 keeping things consistent while not affecting siblings. */
1894 CURSIZE (XWINDOW (parent
)) = opht
+ delta1
;
1895 (*setsizefun
) (window
, *sizep
+ delta1
, 0);
1897 /* Squeeze out delta1 lines or columns from our parent,
1898 shriking this window and siblings proportionately.
1899 This brings parent back to correct size.
1900 Delta1 was calculated so this makes this window the desired size,
1901 taking it all out of the siblings. */
1902 (*setsizefun
) (parent
, opht
, 0);
1905 XFASTINT (p
->last_modified
) = 0;
1912 /* Return number of lines of text (not counting mode line) in W. */
1915 window_internal_height (w
)
1918 int ht
= XFASTINT (w
->height
);
1920 if (MINI_WINDOW_P (w
))
1923 if (!NILP (w
->parent
) || !NILP (w
->vchild
) || !NILP (w
->hchild
)
1924 || !NILP (w
->next
) || !NILP (w
->prev
)
1925 || SCREEN_WANTS_MODELINE_P (XSCREEN (WINDOW_SCREEN (w
))))
1931 /* Scroll contents of window WINDOW up N lines. */
1934 window_scroll (window
, n
, noerror
)
1939 register struct window
*w
= XWINDOW (window
);
1940 register int opoint
= point
;
1942 register int ht
= window_internal_height (w
);
1943 register Lisp_Object tem
;
1945 Lisp_Object bolp
, nmoved
;
1947 XFASTINT (tem
) = point
;
1948 tem
= Fpos_visible_in_window_p (tem
, window
);
1952 Fvertical_motion (make_number (- ht
/ 2));
1953 XFASTINT (tem
) = point
;
1954 Fset_marker (w
->start
, tem
, w
->buffer
);
1955 w
->force_start
= Qt
;
1958 SET_PT (marker_position (w
->start
));
1959 lose
= n
< 0 && point
== BEGV
;
1960 Fvertical_motion (make_number (n
));
1970 Fsignal (Qbeginning_of_buffer
, Qnil
);
1975 set_marker_restricted (w
->start
, make_number (pos
), w
->buffer
);
1976 w
->start_at_line_beg
= bolp
;
1977 w
->update_mode_line
= Qt
;
1978 XFASTINT (w
->last_modified
) = 0;
1984 tem
= Fvertical_motion (make_number (ht
));
1985 if (point
> opoint
|| XFASTINT (tem
) < ht
)
1988 Fvertical_motion (make_number (-1));
1996 Fsignal (Qend_of_buffer
, Qnil
);
2000 /* This is the guts of Fscroll_up and Fscroll_down. */
2003 scroll_command (n
, direction
)
2004 register Lisp_Object n
;
2007 register int defalt
;
2008 int count
= specpdl_ptr
- specpdl
;
2010 /* If selected window's buffer isn't current, make it current for the moment.
2011 But don't screw up if window_scroll gets an error. */
2012 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
2014 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2015 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2018 defalt
= (window_internal_height (XWINDOW (selected_window
))
2019 - next_screen_context_lines
);
2020 defalt
= direction
* (defalt
< 1 ? 1 : defalt
);
2023 window_scroll (selected_window
, defalt
, 0);
2024 else if (EQ (n
, Qminus
))
2025 window_scroll (selected_window
, - defalt
, 0);
2028 n
= Fprefix_numeric_value (n
);
2029 window_scroll (selected_window
, XINT (n
) * direction
, 0);
2032 unbind_to (count
, Qnil
);
2035 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "P",
2036 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2037 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2038 When calling from a program, supply a number as argument or nil.")
2042 scroll_command (n
, 1);
2046 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "P",
2047 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2048 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2049 When calling from a program, supply a number as argument or nil.")
2053 scroll_command (n
, -1);
2057 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
2058 "Scroll text of next window upward ARG lines; or near full screen if no ARG.\n\
2059 The next window is the one below the current one; or the one at the top\n\
2060 if the current one is at the bottom.\n\
2061 When calling from a program, supply a number as argument or nil.\n\
2063 If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
2064 specifies the window to scroll.\n\
2065 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2066 showing that buffer, popping the buffer up if necessary.")
2068 register Lisp_Object n
;
2070 register Lisp_Object window
;
2072 register struct window
*w
;
2073 register int count
= specpdl_ptr
- specpdl
;
2075 if (MINI_WINDOW_P (XWINDOW (selected_window
))
2076 && !NILP (Vminibuf_scroll_window
))
2077 window
= Vminibuf_scroll_window
;
2078 /* If buffer is specified, scroll that buffer. */
2079 else if (!NILP (Vother_window_scroll_buffer
))
2081 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
2083 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
);
2086 /* Nothing specified; pick a neighboring window. */
2087 window
= Fnext_window (selected_window
, Qnil
, Qt
);
2088 CHECK_WINDOW (window
, 0);
2090 if (EQ (window
, selected_window
))
2091 error ("There is no other window");
2093 w
= XWINDOW (window
);
2094 ht
= window_internal_height (w
);
2096 /* Don't screw up if window_scroll gets an error. */
2097 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2099 Fset_buffer (w
->buffer
);
2100 SET_PT (marker_position (w
->pointm
));
2103 window_scroll (window
, ht
- next_screen_context_lines
, 1);
2104 else if (EQ (n
, Qminus
))
2105 window_scroll (window
, next_screen_context_lines
- ht
, 1);
2108 if (XTYPE (n
) == Lisp_Cons
)
2110 CHECK_NUMBER (n
, 0);
2111 window_scroll (window
, XINT (n
), 1);
2114 Fset_marker (w
->pointm
, make_number (point
), Qnil
);
2120 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 1, 1, "P",
2121 "Scroll selected window display ARG columns left.\n\
2122 Default for ARG is window width minus 2.")
2124 register Lisp_Object arg
;
2128 XFASTINT (arg
) = XFASTINT (XWINDOW (selected_window
)->width
) - 2;
2130 arg
= Fprefix_numeric_value (arg
);
2133 Fset_window_hscroll (selected_window
,
2134 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2138 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 1, 1, "P",
2139 "Scroll selected window display ARG columns right.\n\
2140 Default for ARG is window width minus 2.")
2142 register Lisp_Object arg
;
2145 XFASTINT (arg
) = XFASTINT (XWINDOW (selected_window
)->width
) - 2;
2147 arg
= Fprefix_numeric_value (arg
);
2150 Fset_window_hscroll (selected_window
,
2151 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2155 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
2156 "Center point in window and redisplay screen. With ARG, put point on line ARG.\n\
2157 The desired position of point is always relative to the current window.\n\
2158 Just C-u as prefix means put point in the center of the screen.\n\
2159 No arg (i.e., it is nil) erases the entire screen and then\n\
2160 redraws with point in the center.")
2162 register Lisp_Object n
;
2164 register struct window
*w
= XWINDOW (selected_window
);
2165 register int ht
= window_internal_height (w
);
2166 register int opoint
= point
;
2170 extern int screen_garbaged
;
2172 SET_SCREEN_GARBAGED (XSCREEN (WINDOW_SCREEN (w
)));
2173 XFASTINT (n
) = ht
/ 2;
2175 else if (XTYPE (n
) == Lisp_Cons
) /* Just C-u. */
2177 XFASTINT (n
) = ht
/ 2;
2181 n
= Fprefix_numeric_value (n
);
2182 CHECK_NUMBER (n
, 0);
2186 XSETINT (n
, XINT (n
) + ht
);
2188 XSETINT (n
, - XINT (n
));
2190 Fvertical_motion (n
);
2191 Fset_marker (w
->start
, make_number (point
), w
->buffer
);
2192 w
->start_at_line_beg
= Fbolp ();
2195 w
->force_start
= Qt
;
2200 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
2202 "Position point relative to window.\n\
2203 With no argument, position text at center of window.\n\
2204 An argument specifies screen line; zero means top of window,\n\
2205 negative means relative to bottom of window.")
2207 register Lisp_Object arg
;
2209 register struct window
*w
= XWINDOW (selected_window
);
2210 register int height
= window_internal_height (w
);
2214 XFASTINT (arg
) = height
/ 2;
2217 arg
= Fprefix_numeric_value (arg
);
2219 XSETINT (arg
, XINT (arg
) + height
);
2222 start
= marker_position (w
->start
);
2223 if (start
< BEGV
|| start
> ZV
)
2225 Fvertical_motion (make_number (- height
/ 2));
2226 Fset_marker (w
->start
, make_number (point
), w
->buffer
);
2227 w
->start_at_line_beg
= Fbolp ();
2228 w
->force_start
= Qt
;
2233 return Fvertical_motion (arg
);
2236 struct save_window_data
2238 int size_from_Lisp_Vector_struct
;
2239 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2240 Lisp_Object screen_width
, screen_height
;
2241 Lisp_Object current_window
;
2242 Lisp_Object current_buffer
;
2243 Lisp_Object minibuf_scroll_window
;
2244 Lisp_Object root_window
;
2245 /* A vector, interpreted as a struct saved_window */
2246 Lisp_Object saved_windows
;
2248 #define SAVE_WINDOW_DATA_SIZE 7 /* Arg to Fmake_vector */
2250 /* This is saved as a Lisp_Vector */
2253 /* these first two must agree with struct Lisp_Vector in lisp.h */
2254 int size_from_Lisp_Vector_struct
;
2255 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2258 Lisp_Object buffer
, start
, pointm
, mark
;
2259 Lisp_Object left
, top
, width
, height
, hscroll
;
2260 Lisp_Object parent
, prev
;
2261 Lisp_Object start_at_line_beg
;
2262 Lisp_Object display_table
;
2264 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2266 #define SAVED_WINDOW_N(swv,n) \
2267 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2269 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
2270 "T if OBJECT is a window-configration object.")
2274 if (XTYPE (obj
) == Lisp_Window_Configuration
)
2280 DEFUN ("set-window-configuration",
2281 Fset_window_configuration
, Sset_window_configuration
,
2283 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2284 CONFIGURATION must be a value previously returned\n\
2285 by `current-window-configuration' (which see).")
2289 register struct window
*w
;
2290 register struct save_window_data
*data
;
2291 struct Lisp_Vector
*saved_windows
;
2292 register struct saved_window
*p
;
2293 register Lisp_Object tem
;
2294 Lisp_Object new_current_buffer
;
2298 while (XTYPE (arg
) != Lisp_Window_Configuration
)
2300 arg
= wrong_type_argument (intern ("window-configuration-p"), arg
);
2303 data
= (struct save_window_data
*) XVECTOR (arg
);
2304 saved_windows
= XVECTOR (data
->saved_windows
);
2306 s
= XSCREEN (XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->screen
);
2308 if (XFASTINT (data
->screen_height
) != SCREEN_HEIGHT (s
)
2309 || XFASTINT (data
->screen_width
) != SCREEN_WIDTH (s
))
2311 /* Presumably something clever could be done.
2312 However, it doesn't seem worth the effort */
2313 error ("Screen size %dx%d in saved window configuration mismatches screen.",
2314 XFASTINT (data
->screen_height
),
2315 XFASTINT (data
->screen_width
));
2318 windows_or_buffers_changed
++;
2319 new_current_buffer
= data
->current_buffer
;
2320 if (NILP (XBUFFER (new_current_buffer
)->name
))
2321 new_current_buffer
= Qnil
;
2323 /* Mark all windows now on screen as "deleted".
2324 Restoring the new configuration "undeletes" any that are in it. */
2326 delete_all_subwindows (XWINDOW (SCREEN_ROOT_WINDOW (s
)));
2328 /* This loses when the minibuf screen is not s. */
2329 delete_all_subwindows (XWINDOW (XWINDOW (minibuf_window
)->prev
));
2332 for (k
= 0; k
< saved_windows
->size
; k
++)
2334 p
= SAVED_WINDOW_N (saved_windows
, k
);
2335 w
= XWINDOW (p
->window
);
2338 if (!NILP (p
->parent
))
2339 w
->parent
= SAVED_WINDOW_N (saved_windows
, XFASTINT (p
->parent
))->window
;
2343 if (!NILP (p
->prev
))
2345 w
->prev
= SAVED_WINDOW_N (saved_windows
, XFASTINT (p
->prev
))->window
;
2347 /* This is true for a minibuffer-only screen. */
2348 if (w
->mini_p
&& EQ (w
->prev
, p
->window
))
2351 #endif /* MULTI_SCREEN */
2352 XWINDOW (w
->prev
)->next
= p
->window
;
2357 if (!NILP (w
->parent
))
2359 if (EQ (p
->width
, XWINDOW (w
->parent
)->width
))
2361 XWINDOW (w
->parent
)->vchild
= p
->window
;
2362 XWINDOW (w
->parent
)->hchild
= Qnil
;
2366 XWINDOW (w
->parent
)->hchild
= p
->window
;
2367 XWINDOW (w
->parent
)->vchild
= Qnil
;
2373 w
->width
= p
->width
;
2374 w
->height
= p
->height
;
2375 w
->hscroll
= p
->hscroll
;
2376 w
->display_table
= p
->display_table
;
2377 XFASTINT (w
->last_modified
) = 0;
2379 /* Reinstall the saved buffer and pointers into it. */
2380 if (NILP (p
->buffer
))
2381 w
->buffer
= p
->buffer
;
2384 if (!NILP (XBUFFER (p
->buffer
)->name
))
2385 /* If saved buffer is alive, install it. */
2387 w
->buffer
= p
->buffer
;
2388 w
->start_at_line_beg
= p
->start_at_line_beg
;
2389 set_marker_restricted (w
->start
, Fmarker_position (p
->start
), w
->buffer
);
2390 set_marker_restricted (w
->pointm
, Fmarker_position (p
->pointm
), w
->buffer
);
2391 Fset_marker (XBUFFER (w
->buffer
)->mark
,
2392 Fmarker_position (p
->mark
), w
->buffer
);
2394 if (!EQ (p
->buffer
, new_current_buffer
) &&
2395 XBUFFER (p
->buffer
) == current_buffer
)
2396 Fgoto_char (w
->pointm
);
2398 else if (NILP (XBUFFER (w
->buffer
)->name
))
2399 /* Else if window's old buffer is dead too, get a live one. */
2401 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
2402 /* This will set the markers to beginning of visible range. */
2403 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
2404 set_marker_restricted (w
->pointm
, make_number (0), w
->buffer
);
2405 w
->start_at_line_beg
= Qt
;
2408 /* Keeping window's old buffer; make sure the markers are real. */
2409 /* Else if window's old buffer is dead too, get a live one. */
2411 /* Set window markers at start of visible range. */
2412 if (XMARKER (w
->start
)->buffer
== 0)
2413 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
2414 if (XMARKER (w
->pointm
)->buffer
== 0)
2415 set_marker_restricted (w
->pointm
,
2416 make_number (BUF_PT (XBUFFER (w
->buffer
))),
2418 w
->start_at_line_beg
= Qt
;
2423 SCREEN_ROOT_WINDOW (s
) = data
->root_window
;
2426 if (s
!= selected_screen
&& ! SCREEN_IS_TERMCAP (s
))
2427 Fselect_screen (WINDOW_SCREEN (XWINDOW (data
->root_window
)), Qnil
);
2430 if (s
== selected_screen
)
2432 Fselect_window (data
->current_window
);
2433 if (!NILP (new_current_buffer
))
2434 Fset_buffer (new_current_buffer
);
2436 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2439 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
2443 /* Mark all windows now on screen as deleted
2444 by setting their buffers to nil. */
2447 delete_all_subwindows (w
)
2448 register struct window
*w
;
2450 register int count
= 1;
2452 if (!NILP (w
->next
))
2453 delete_all_subwindows (XWINDOW (w
->next
));
2454 if (!NILP (w
->vchild
))
2455 delete_all_subwindows (XWINDOW (w
->vchild
));
2456 if (!NILP (w
->hchild
))
2457 delete_all_subwindows (XWINDOW (w
->hchild
));
2461 count_windows (window
)
2462 register struct window
*window
;
2464 register int count
= 1;
2465 if (!NILP (window
->next
))
2466 count
+= count_windows (XWINDOW (window
->next
));
2467 if (!NILP (window
->vchild
))
2468 count
+= count_windows (XWINDOW (window
->vchild
));
2469 if (!NILP (window
->hchild
))
2470 count
+= count_windows (XWINDOW (window
->hchild
));
2475 save_window_save (window
, vector
, i
)
2477 struct Lisp_Vector
*vector
;
2480 register struct saved_window
*p
;
2481 register struct window
*w
;
2482 register Lisp_Object tem
;
2484 for (;!NILP (window
); window
= w
->next
)
2486 p
= SAVED_WINDOW_N (vector
, i
);
2487 w
= XWINDOW (window
);
2489 XFASTINT (w
->temslot
) = i
++;
2491 p
->buffer
= w
->buffer
;
2494 p
->width
= w
->width
;
2495 p
->height
= w
->height
;
2496 p
->hscroll
= w
->hscroll
;
2497 p
->display_table
= w
->display_table
;
2498 if (!NILP (w
->buffer
))
2500 /* Save w's value of point in the window configuration.
2501 If w is the selected window, then get the value of point
2502 from the buffer; pointm is garbage in the selected window. */
2503 if (EQ (window
, selected_window
))
2505 p
->pointm
= Fmake_marker ();
2506 Fset_marker (p
->pointm
, BUF_PT (XBUFFER (w
->buffer
)),
2510 p
->pointm
= Fcopy_marker (w
->pointm
);
2512 p
->start
= Fcopy_marker (w
->start
);
2513 p
->start_at_line_beg
= w
->start_at_line_beg
;
2515 tem
= XBUFFER (w
->buffer
)->mark
;
2516 p
->mark
= Fcopy_marker (tem
);
2523 p
->start_at_line_beg
= Qnil
;
2526 if (NILP (w
->parent
))
2529 p
->parent
= XWINDOW (w
->parent
)->temslot
;
2534 p
->prev
= XWINDOW (w
->prev
)->temslot
;
2536 if (!NILP (w
->vchild
))
2537 i
= save_window_save (w
->vchild
, vector
, i
);
2538 if (!NILP (w
->hchild
))
2539 i
= save_window_save (w
->hchild
, vector
, i
);
2545 DEFUN ("current-window-configuration",
2546 Fcurrent_window_configuration
, Scurrent_window_configuration
, 0, 1, 0,
2547 "Return an object representing the current window configuration of SCREEN.\n\
2548 If SCREEN is nil or omitted, use the selected screen.\n\
2549 This describes the number of windows, their sizes and current buffers,\n\
2550 and for each displayed buffer, where display starts, and the positions of\n\
2551 point and mark. An exception is made for point in the current buffer:\n\
2552 its value is -not- saved.")
2556 register Lisp_Object tem
;
2557 register int n_windows
;
2558 register struct save_window_data
*data
;
2563 s
= selected_screen
;
2566 CHECK_LIVE_SCREEN (screen
, 0);
2567 s
= XSCREEN (screen
);
2570 n_windows
= count_windows (XWINDOW (SCREEN_ROOT_WINDOW (s
)));
2571 data
= (struct save_window_data
*)
2572 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE
),
2574 XFASTINT (data
->screen_width
) = SCREEN_WIDTH (s
);
2575 XFASTINT (data
->screen_height
) = SCREEN_HEIGHT (s
);
2576 data
->current_window
= SCREEN_SELECTED_WINDOW (s
);
2577 XSET (data
->current_buffer
, Lisp_Buffer
, current_buffer
);
2578 data
->minibuf_scroll_window
= Vminibuf_scroll_window
;
2579 data
->root_window
= SCREEN_ROOT_WINDOW (s
);
2580 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
2581 data
->saved_windows
= tem
;
2582 for (i
= 0; i
< n_windows
; i
++)
2583 XVECTOR (tem
)->contents
[i
]
2584 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE
), Qnil
);
2585 save_window_save (SCREEN_ROOT_WINDOW (s
),
2587 XSET (tem
, Lisp_Window_Configuration
, data
);
2591 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
2593 "Execute body, preserving window sizes and contents.\n\
2594 Restores which buffer appears in which window, where display starts,\n\
2595 as well as the current buffer.\n\
2596 Does not restore the value of point in current buffer.")
2600 register Lisp_Object val
;
2601 register int count
= specpdl_ptr
- specpdl
;
2603 record_unwind_protect (Fset_window_configuration
,
2604 Fcurrent_window_configuration (Qnil
));
2605 val
= Fprogn (args
);
2606 return unbind_to (count
, val
);
2612 selected_screen
= make_terminal_screen ();
2613 minibuf_window
= selected_screen
->minibuffer_window
;
2614 selected_window
= selected_screen
->selected_window
;
2615 last_nonminibuf_screen
= selected_screen
;
2616 #else /* not MULTI_SCREEN */
2617 extern Lisp_Object
get_minibuffer ();
2619 root_window
= make_window ();
2620 minibuf_window
= make_window ();
2622 XWINDOW (root_window
)->next
= minibuf_window
;
2623 XWINDOW (minibuf_window
)->prev
= root_window
;
2625 /* These values 9 and 10 are arbitrary,
2626 just so that there is "something there."
2627 Correct values are put in in init_xdisp */
2629 XFASTINT (XWINDOW (root_window
)->width
) = 10;
2630 XFASTINT (XWINDOW (minibuf_window
)->width
) = 10;
2632 XFASTINT (XWINDOW (root_window
)->height
) = 9;
2633 XFASTINT (XWINDOW (minibuf_window
)->top
) = 9;
2634 XFASTINT (XWINDOW (minibuf_window
)->height
) = 1;
2636 /* Prevent error in Fset_window_buffer. */
2637 XWINDOW (root_window
)->buffer
= Qt
;
2638 XWINDOW (minibuf_window
)->buffer
= Qt
;
2640 /* Now set them up for real. */
2641 Fset_window_buffer (root_window
, Fcurrent_buffer ());
2642 Fset_window_buffer (minibuf_window
, get_minibuffer (0));
2644 selected_window
= root_window
;
2645 /* Make sure this window seems more recently used than
2646 a newly-created, never-selected window. Increment
2647 window_select_count so the first selection ever will get
2648 something newer than this. */
2649 XFASTINT (XWINDOW (selected_window
)->use_time
) = ++window_select_count
;
2650 #endif /* not MULTI_SCREEN */
2655 Qwindowp
= intern ("windowp");
2656 staticpro (&Qwindowp
);
2658 /* Make sure all windows get marked */
2659 staticpro (&minibuf_window
);
2661 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
2662 "Non-nil means call as function to display a help buffer.\n\
2663 Used by `with-output-to-temp-buffer'.");
2664 Vtemp_buffer_show_function
= Qnil
;
2666 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
2667 "If non-nil, function to call to handle `display-buffer'.\n\
2668 It will receive two args, the buffer and a flag which if non-nil means\n\
2669 that the currently selected window is not acceptable.\n\
2670 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
2671 work using this function.");
2672 Vdisplay_buffer_function
= Qnil
;
2674 DEFVAR_LISP ("mouse-window", &Vmouse_window
,
2675 "Window that the last mouse click occurred on.");
2676 Vmouse_window
= Qnil
;
2678 DEFVAR_LISP ("mouse-event", &Vmouse_event
,
2679 "The last mouse-event object. A list of four elements:\n\
2680 ((X-POS Y-POS) WINDOW SCREEN-PART KEYSEQ).\n\
2681 KEYSEQ is a string, the key sequence to be looked up in the mouse maps.\n\
2682 WINDOW is the window that the click applies do.\n\
2683 If SCREEN-PART is non-nil, the event was on a scrollbar;\n\
2684 then Y-POS is really the total length of the scrollbar, while X-POS is\n\
2685 the relative position of the scrollbar's value within that total length.\n\
2686 SCREEN-PART is one of the following symbols:\n\
2687 `vertical-scrollbar', `vertical-slider',\n\
2688 `vertical-thumbup', `vertical-thumbdown',\n\
2689 `horizontal-scrollbar', `horizontal-slider',\n\
2690 `horizontal-thumbleft', `horizontal-thumbright'");
2691 Vmouse_event
= Qnil
;
2693 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
2694 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
2695 Vminibuf_scroll_window
= Qnil
;
2697 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
2698 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
2699 Vother_window_scroll_buffer
= Qnil
;
2702 DEFVAR_BOOL ("pop-up-screens", &pop_up_screens
,
2703 "*Non-nil means `display-buffer' should make a separate X-window.");
2706 DEFVAR_LISP ("pop-up-screen-function", &Vpop_up_screen_function
,
2707 "*If non-nil, function to call to handle automatic new screen creation.\n\
2708 It is called with no arguments and should return a newly created screen.\n\
2710 A typical value might be `(lambda () (x-create-screen auto-screen-parms))'\n\
2711 where `auto-screen-parms' would hold the default screen parameters.");
2712 Vpop_up_screen_function
= Qnil
;
2715 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
2716 "*Non-nil means display-buffer should make new windows.");
2719 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
2720 "*Number of lines of continuity when scrolling by screenfuls.");
2721 next_screen_context_lines
= 2;
2723 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
2724 "*display-buffer would prefer to split the largest window if this large.\n\
2725 If there is only one window, it is split regardless of this value.");
2726 split_height_threshold
= 500;
2728 DEFVAR_INT ("window-min-height", &window_min_height
,
2729 "*Delete any window less than this tall (including its mode line).");
2730 window_min_height
= 4;
2732 DEFVAR_INT ("window-min-width", &window_min_width
,
2733 "*Delete any window less than this wide.");
2734 window_min_width
= 10;
2736 defsubr (&Sselected_window
);
2737 defsubr (&Sminibuffer_window
);
2738 defsubr (&Swindow_minibuffer_p
);
2739 defsubr (&Swindowp
);
2740 defsubr (&Spos_visible_in_window_p
);
2741 defsubr (&Swindow_buffer
);
2742 defsubr (&Swindow_height
);
2743 defsubr (&Swindow_width
);
2744 defsubr (&Swindow_hscroll
);
2745 defsubr (&Sset_window_hscroll
);
2746 defsubr (&Swindow_edges
);
2747 defsubr (&Scoordinates_in_window_p
);
2748 defsubr (&Swindow_at
);
2749 defsubr (&Swindow_point
);
2750 defsubr (&Swindow_start
);
2751 defsubr (&Swindow_end
);
2752 defsubr (&Sset_window_point
);
2753 defsubr (&Sset_window_start
);
2754 defsubr (&Swindow_dedicated_p
);
2755 defsubr (&Sset_window_buffer_dedicated
);
2756 defsubr (&Swindow_display_table
);
2757 defsubr (&Sset_window_display_table
);
2758 defsubr (&Snext_window
);
2759 defsubr (&Sprevious_window
);
2760 defsubr (&Sother_window
);
2761 defsubr (&Sget_lru_window
);
2762 defsubr (&Sget_largest_window
);
2763 defsubr (&Sget_buffer_window
);
2764 defsubr (&Sdelete_other_windows
);
2765 defsubr (&Sdelete_windows_on
);
2766 defsubr (&Sreplace_buffer_in_windows
);
2767 defsubr (&Sdelete_window
);
2768 defsubr (&Sset_window_buffer
);
2769 defsubr (&Sselect_window
);
2770 defsubr (&Sdisplay_buffer
);
2771 defsubr (&Ssplit_window
);
2772 defsubr (&Senlarge_window
);
2773 defsubr (&Sshrink_window
);
2774 defsubr (&Sscroll_up
);
2775 defsubr (&Sscroll_down
);
2776 defsubr (&Sscroll_left
);
2777 defsubr (&Sscroll_right
);
2778 defsubr (&Sscroll_other_window
);
2779 defsubr (&Srecenter
);
2780 defsubr (&Smove_to_window_line
);
2781 defsubr (&Swindow_configuration_p
);
2782 defsubr (&Sset_window_configuration
);
2783 defsubr (&Scurrent_window_configuration
);
2784 defsubr (&Ssave_window_excursion
);
2789 initial_define_key (control_x_map
, '1', "delete-other-windows");
2790 initial_define_key (control_x_map
, '2', "split-window");
2791 initial_define_key (control_x_map
, '0', "delete-window");
2792 initial_define_key (control_x_map
, 'o', "other-window");
2793 initial_define_key (control_x_map
, '^', "enlarge-window");
2794 initial_define_key (control_x_map
, '<', "scroll-left");
2795 initial_define_key (control_x_map
, '>', "scroll-right");
2797 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
2798 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
2799 initial_define_key (meta_map
, 'v', "scroll-down");
2801 initial_define_key (global_map
, Ctl('L'), "recenter");
2802 initial_define_key (meta_map
, 'r', "move-to-window-line");