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-dedicated-p", Fset_window_dedicated_p
,
544 Sset_window_dedicated_p
, 2, 2, 0,
545 "Control whether WINDOW is dedicated to the buffer it displays.\n\
546 If it is dedicated, Emacs will not automatically change\n\
547 which buffer appears in it.\n\
548 The second argument is the new value for the dedication flag;\n\
551 Lisp_Object window
, arg
;
553 register struct window
*w
= decode_window (window
);
563 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
565 "Return the display-table that WINDOW is using.")
569 return decode_window (window
)->display_table
;
572 /* Get the display table for use currently on window W.
573 This is either W's display table or W's buffer's display table.
574 Ignore the specified tables if they are not valid;
575 if no valid table is specified, return 0. */
578 window_display_table (w
)
582 tem
= w
->display_table
;
583 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
584 return XVECTOR (tem
);
585 tem
= XBUFFER (w
->buffer
)->display_table
;
586 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
587 return XVECTOR (tem
);
588 tem
= Vstandard_display_table
;
589 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
590 return XVECTOR (tem
);
594 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
595 "Set WINDOW's display-table to TABLE.")
597 register Lisp_Object window
, table
;
599 register struct window
*w
;
600 register Lisp_Object z
; /* Return value. */
602 w
= decode_window (window
);
603 w
->display_table
= table
;
607 /* Record info on buffer window w is displaying
608 when it is about to cease to display that buffer. */
611 register struct window
*w
;
613 Lisp_Object buf
= w
->buffer
;
615 if (XBUFFER (buf
) != XMARKER (w
->pointm
)->buffer
)
618 if (w
== XWINDOW (selected_window
)
619 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
620 /* Do this except when the selected window's buffer
621 is being removed from some other window. */
622 XBUFFER (buf
)->last_window_start
= marker_position (w
->start
);
624 /* Point in the selected window's buffer
625 is actually stored in that buffer, and the window's pointm isn't used.
626 So don't clobber point in that buffer. */
627 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
))
628 BUF_PT (XBUFFER (buf
))
629 = clip_to_bounds (BUF_BEGV (XBUFFER (buf
)),
630 marker_position (w
->pointm
),
631 BUF_ZV (XBUFFER (buf
)));
634 /* Put replacement into the window structure in place of old. */
636 replace_window (old
, replacement
)
637 Lisp_Object old
, replacement
;
639 register Lisp_Object tem
;
640 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
642 /* If OLD is its screen's root_window, then replacement is the new
643 root_window for that screen. */
645 if (old
== XSCREEN (o
->screen
)->root_window
)
646 XSCREEN (o
->screen
)->root_window
= replacement
;
651 p
->height
= o
->height
;
653 p
->next
= tem
= o
->next
;
655 XWINDOW (tem
)->prev
= replacement
;
657 p
->prev
= tem
= o
->prev
;
659 XWINDOW (tem
)->next
= replacement
;
661 p
->parent
= tem
= o
->parent
;
664 if (EQ (XWINDOW (tem
)->vchild
, old
))
665 XWINDOW (tem
)->vchild
= replacement
;
666 if (EQ (XWINDOW (tem
)->hchild
, old
))
667 XWINDOW (tem
)->hchild
= replacement
;
670 /*** Here, if replacement is a vertical combination
671 and so is its new parent, we should make replacement's
672 children be children of that parent instead. ***/
675 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
676 "Remove WINDOW from the display. Default is selected window.")
678 register Lisp_Object window
;
680 register Lisp_Object tem
, parent
, sib
;
681 register struct window
*p
;
682 register struct window
*par
;
685 window
= selected_window
;
687 CHECK_WINDOW (window
, 0);
689 p
= XWINDOW (window
);
692 error ("Attempt to delete minibuffer or sole ordinary window");
693 par
= XWINDOW (parent
);
695 windows_or_buffers_changed
++;
697 if (EQ (window
, selected_window
))
698 Fselect_window (Fnext_window (window
, Qnil
, Qnil
));
701 /* tem is null for dummy parent windows
702 (which have inferiors but not any contents themselves) */
706 unchain_marker (p
->pointm
);
707 unchain_marker (p
->start
);
713 XWINDOW (tem
)->prev
= p
->prev
;
717 XWINDOW (tem
)->next
= p
->next
;
719 if (EQ (window
, par
->hchild
))
720 par
->hchild
= p
->next
;
721 if (EQ (window
, par
->vchild
))
722 par
->vchild
= p
->next
;
724 /* Find one of our siblings to give our space to. */
728 /* If p gives its space to its next sibling, that sibling needs
729 to have its top/left side pulled back to where p's is.
730 set_window_{height,width} will re-position the sibling's
733 XFASTINT (XWINDOW (sib
)->top
) = p
->top
;
734 XFASTINT (XWINDOW (sib
)->left
) = p
->left
;
737 /* Stretch that sibling. */
738 if (!NILP (par
->vchild
))
739 set_window_height (sib
,
740 XFASTINT (XWINDOW (sib
)->height
) + XFASTINT (p
->height
),
742 if (!NILP (par
->hchild
))
743 set_window_width (sib
,
744 XFASTINT (XWINDOW (sib
)->width
) + XFASTINT (p
->width
),
747 /* If parent now has only one child,
748 put the child into the parent's place. */
753 if (NILP (XWINDOW (tem
)->next
))
754 replace_window (parent
, tem
);
759 extern Lisp_Object
next_screen (), prev_screen ();
761 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
762 "Return next window after WINDOW in canonical ordering of windows.\n\
763 If omitted, WINDOW defaults to the selected window.\n\
765 Optional second arg MINIBUF t means count the minibuffer window even\n\
766 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
767 it is active. MINIBUF neither t nor nil means not to count the\n\
768 minibuffer even if it is active.\n\
770 Several screens may share a single minibuffer; if the minibuffer\n\
771 counts, all windows on all screens that share that minibuffer count\n\
772 too. This means that next-window may be used to iterate through the\n\
773 set of windows even when the minibuffer is on another screen. If the\n\
774 minibuffer does not count, only windows from WINDOW's screen count.\n\
776 Optional third arg ALL-SCREENS t means include windows on all screens.\n\
777 ALL-SCREENS nil or omitted means cycle within the screens as specified\n\
778 above. If neither nil nor t, restrict to WINDOW's screen.")
779 (window
, minibuf
, all_screens
)
780 register Lisp_Object window
, minibuf
, all_screens
;
782 register Lisp_Object tem
;
783 Lisp_Object start_window
;
786 window
= selected_window
;
788 CHECK_WINDOW (window
, 0);
790 start_window
= window
;
792 /* minibuf == nil may or may not include minibuffers.
793 Decide if it does. */
795 minibuf
= (minibuf_level
? Qt
: Qlambda
);
797 /* all_screens == nil doesn't specify which screens to include.
798 Decide which screens it includes. */
799 if (NILP (all_screens
))
800 all_screens
= (EQ (minibuf
, Qt
)
801 ? (SCREEN_MINIBUF_WINDOW
804 (XWINDOW (window
)))))
806 else if (! EQ (all_screens
, Qt
))
809 /* Do this loop at least once, to get the next window, and perhaps
810 again, if we hit the minibuffer and that is not acceptable. */
813 /* Find a window that actually has a next one. This loop
814 climbs up the tree. */
815 while (tem
= XWINDOW (window
)->next
, NILP (tem
))
816 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
820 /* We've reached the end of this screen.
821 Which other screens are acceptable? */
822 tem
= WINDOW_SCREEN (XWINDOW (window
));
824 if (! NILP (all_screens
))
825 tem
= next_screen (tem
, all_screens
);
827 tem
= SCREEN_ROOT_WINDOW (XSCREEN (tem
));
834 /* If we're in a combination window, find its first child and
835 recurse on that. Otherwise, we've found the window we want. */
838 if (!NILP (XWINDOW (window
)->hchild
))
839 window
= XWINDOW (window
)->hchild
;
840 else if (!NILP (XWINDOW (window
)->vchild
))
841 window
= XWINDOW (window
)->vchild
;
845 /* Which windows are acceptible?
846 Exit the loop and accept this window if
847 this isn't a minibuffer window, or
848 we're accepting minibuffer windows, or
849 we've come all the way around and we're back at the original window. */
850 while (MINI_WINDOW_P (XWINDOW (window
))
851 && ! EQ (minibuf
, Qt
)
852 && window
!= start_window
);
857 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
858 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
859 If omitted, WINDOW defaults to the selected window.\n\
861 Optional second arg MINIBUF t means count the minibuffer window even\n\
862 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
863 it is active. MINIBUF neither t nor nil means not to count the\n\
864 minibuffer even if it is active.\n\
866 Several screens may share a single minibuffer; if the minibuffer\n\
867 counts, all windows on all screens that share that minibuffer count\n\
868 too. This means that previous-window may be used to iterate through\n\
869 the set of windows even when the minibuffer is on another screen. If\n\
870 the minibuffer does not count, only windows from WINDOW's screen\n\
873 Optional third arg ALL-SCREENS t means include windows on all screens.\n\
874 ALL-SCREENS nil or omitted means cycle within the screens as specified\n\
875 above. If neither nil nor t, restrict to WINDOW's screen.")
876 (window
, minibuf
, all_screens
)
877 register Lisp_Object window
, minibuf
, all_screens
;
879 register Lisp_Object tem
;
880 Lisp_Object start_window
;
883 window
= selected_window
;
885 CHECK_WINDOW (window
, 0);
887 start_window
= window
;
889 /* minibuf == nil may or may not include minibuffers.
890 Decide if it does. */
892 minibuf
= (minibuf_level
? Qt
: Qlambda
);
894 /* all_screens == nil doesn't specify which screens to include.
895 Decide which screens it includes. */
896 if (NILP (all_screens
))
897 all_screens
= (EQ (minibuf
, Qt
)
898 ? (SCREEN_MINIBUF_WINDOW
901 (XWINDOW (window
)))))
903 else if (! EQ (all_screens
, Qt
))
906 /* Do this loop at least once, to get the previous window, and perhaps
907 again, if we hit the minibuffer and that is not acceptable. */
910 /* Find a window that actually has a previous one. This loop
911 climbs up the tree. */
912 while (tem
= XWINDOW (window
)->prev
, NILP (tem
))
913 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
917 /* We have found the top window on the screen.
918 Which screens are acceptable? */
919 tem
= WINDOW_SCREEN (XWINDOW (window
));
921 if (! NILP (all_screens
))
922 tem
= next_screen (tem
, all_screens
);
924 tem
= SCREEN_ROOT_WINDOW (XSCREEN (tem
));
930 /* If we're in a combination window, find its last child and
931 recurse on that. Otherwise, we've found the window we want. */
934 if (!NILP (XWINDOW (window
)->hchild
))
935 window
= XWINDOW (window
)->hchild
;
936 else if (!NILP (XWINDOW (window
)->vchild
))
937 window
= XWINDOW (window
)->vchild
;
939 while (tem
= XWINDOW (window
)->next
, !NILP (tem
))
943 /* Which windows are acceptable?
944 Exit the loop and accept this window if
945 this isn't a minibuffer window, or
946 we're accepting minibuffer windows, or
947 we've come all the way around and we're back at the original window. */
948 while (MINI_WINDOW_P (XWINDOW (window
))
950 && window
!= start_window
);
955 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
956 "Select the ARG'th different window on this screen.\n\
957 All windows on current screen are arranged in a cyclic order.\n\
958 This command selects the window ARG steps away in that order.\n\
959 A negative ARG moves in the opposite order. If the optional second\n\
960 argument ALL_SCREENS is non-nil, cycle through all screens.")
962 register Lisp_Object n
, all_screens
;
965 register Lisp_Object w
;
973 w
= Fnext_window (w
, Qnil
, all_screens
);
978 w
= Fprevious_window (w
, Qnil
, all_screens
);
985 /* Look at all windows, performing an operation specified by TYPE
987 If SCREENS is Qt, look at all screens, if Qnil, look at just the selected
988 screen. If SCREENS is a screen, just look at windows on that screen.
989 If MINI is non-zero, perform the operation on minibuffer windows too.
995 GET_BUFFER_WINDOW
, /* Arg is buffer */
996 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
997 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
998 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
1000 UNSHOW_BUFFER
, /* Arg is buffer */
1004 window_loop (type
, obj
, mini
, screens
)
1005 enum window_loop type
;
1006 register Lisp_Object obj
, screens
;
1009 register Lisp_Object w
;
1010 register Lisp_Object best_window
;
1011 register Lisp_Object next_window
;
1012 register Lisp_Object first_window
;
1015 /* If we're only looping through windows on a particular screen,
1016 screen points to that screen. If we're looping through windows
1017 on all screens, screen is 0. */
1018 if (SCREENP (screens
))
1019 screen
= XSCREEN (screens
);
1020 else if (NILP (screens
))
1021 screen
= selected_screen
;
1025 /* Pick a window to start with. */
1026 if (XTYPE (obj
) == Lisp_Window
)
1029 first_window
= SCREEN_SELECTED_WINDOW (screen
);
1031 first_window
= SCREEN_SELECTED_WINDOW (selected_screen
);
1037 /* Pick the next window now, since some operations will delete
1038 the current window. */
1041 next_window
= Fnext_window (w
, (mini
? Qt
: Qnil
), Qlambda
);
1043 #endif /* MULTI_SCREEN */
1044 /* We know screen is 0, so we're looping through all screens.
1045 Or we know this isn't a MULTI_SCREEN Emacs, so who cares? */
1046 next_window
= Fnext_window (w
, mini
? Qt
: Qnil
, Qt
);
1048 if (!MINI_WINDOW_P (XWINDOW (w
))
1049 || (mini
&& minibuf_level
> 0))
1052 case GET_BUFFER_WINDOW
:
1054 /* Ignore invisible and iconified screens. */
1055 if (! SCREEN_VISIBLE_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
))))
1056 || SCREEN_ICONIFIED_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
)))))
1059 if (XBUFFER (XWINDOW (w
)->buffer
) == XBUFFER (obj
))
1063 case GET_LRU_WINDOW
:
1064 /* t as arg means consider only full-width windows */
1065 if (!NILP (obj
) && XFASTINT (XWINDOW (w
)->width
) != screen
->width
)
1068 /* Ignore invisible and iconified screens. */
1069 if (! SCREEN_VISIBLE_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
))))
1070 || SCREEN_ICONIFIED_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
)))))
1073 /* Ignore dedicated windows and minibuffers. */
1074 if (MINI_WINDOW_P (XWINDOW (w
))
1075 || !NILP (XWINDOW (w
)->dedicated
))
1077 if (NILP (best_window
)
1078 || (XFASTINT (XWINDOW (best_window
)->use_time
)
1079 > XFASTINT (XWINDOW (w
)->use_time
)))
1083 case DELETE_OTHER_WINDOWS
:
1084 if (XWINDOW (w
) != XWINDOW (obj
))
1088 case DELETE_BUFFER_WINDOWS
:
1089 if (EQ (XWINDOW (w
)->buffer
, obj
))
1091 /* If we're deleting the buffer displayed in the only window
1092 on the screen, find a new buffer to display there. */
1093 if (NILP (XWINDOW (w
)->parent
))
1095 Lisp_Object new_buffer
= Fother_buffer (obj
);
1096 if (NILP (new_buffer
))
1098 = Fget_buffer_create (build_string ("*scratch*"));
1099 Fset_window_buffer (w
, new_buffer
);
1100 Fset_buffer (XWINDOW (w
)->buffer
);
1107 case GET_LARGEST_WINDOW
:
1109 /* Ignore invisible and iconified screens. */
1110 if (! SCREEN_VISIBLE_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
))))
1111 || SCREEN_ICONIFIED_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
)))))
1114 /* Ignore dedicated windows and minibuffers. */
1115 if (MINI_WINDOW_P (XWINDOW (w
))
1116 || !NILP (XWINDOW (w
)->dedicated
))
1119 struct window
*best_window_ptr
= XWINDOW (best_window
);
1120 struct window
*w_ptr
= XWINDOW (w
);
1121 if (NILP (best_window
) ||
1122 (XFASTINT (w_ptr
->height
) * XFASTINT (w_ptr
->width
))
1123 > (XFASTINT (best_window_ptr
->height
)
1124 * XFASTINT (best_window_ptr
->width
)))
1130 if (EQ (XWINDOW (w
)->buffer
, obj
))
1132 /* Find another buffer to show in this window. */
1133 Lisp_Object another_buffer
= Fother_buffer (obj
);
1134 if (NILP (another_buffer
))
1136 = Fget_buffer_create (build_string ("*scratch*"));
1137 Fset_window_buffer (w
, another_buffer
);
1138 if (EQ (w
, selected_window
))
1139 Fset_buffer (XWINDOW (w
)->buffer
);
1145 while (! EQ (w
, first_window
));
1150 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 1, 0,
1151 "Return the window least recently selected or used for display.\n\
1152 If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1153 screen, search only that screen.\n")
1155 Lisp_Object screens
;
1157 register Lisp_Object w
;
1158 /* First try for a window that is full-width */
1159 w
= window_loop (GET_LRU_WINDOW
, Qt
, 0, screens
);
1160 if (!NILP (w
) && !EQ (w
, selected_window
))
1162 /* If none of them, try the rest */
1163 return window_loop (GET_LRU_WINDOW
, Qnil
, 0, screens
);
1166 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 1, 0,
1167 "Return the largest window in area.\n\
1168 If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1169 screen, search only that screen.\n")
1173 return window_loop (GET_LARGEST_WINDOW
, Qnil
, 0,
1177 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 1, 2, 0,
1178 "Return a window currently displaying BUFFER, or nil if none.\n\
1179 If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1180 screen, search only that screen.\n")
1182 Lisp_Object buffer
, screen
;
1184 buffer
= Fget_buffer (buffer
);
1185 if (XTYPE (buffer
) == Lisp_Buffer
)
1186 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, screen
);
1191 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
1193 "Make WINDOW (or the selected window) fill its screen.\n\
1194 Only the screen WINDOW is on is affected.")
1200 struct buffer
*obuf
= current_buffer
;
1204 window
= selected_window
;
1206 CHECK_WINDOW (window
, 0);
1208 w
= XWINDOW (window
);
1209 top
= XFASTINT (w
->top
);
1211 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_SCREEN(w
));
1213 Fset_buffer (w
->buffer
);
1214 SET_PT (marker_position (w
->start
));
1215 Frecenter (make_number (top
));
1217 set_buffer_internal (obuf
);
1222 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
1223 1, 1, "bDelete windows on (buffer): ",
1224 "Delete all windows showing BUFFER.")
1230 buffer
= Fget_buffer (buffer
);
1231 CHECK_BUFFER (buffer
, 0);
1232 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, Qt
);
1237 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
1238 Sreplace_buffer_in_windows
,
1239 1, 1, "bReplace buffer in windows: ",
1240 "Replace BUFFER with some other buffer in all windows showing it.")
1246 buffer
= Fget_buffer (buffer
);
1247 CHECK_BUFFER (buffer
, 0);
1248 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
1253 /* Set the height of WINDOW and all its inferiors. */
1254 /* Normally the window is deleted if it gets too small.
1255 nodelete nonzero means do not do this.
1256 (The caller should check later and do so if appropriate) */
1258 set_window_height (window
, height
, nodelete
)
1263 register struct window
*w
= XWINDOW (window
);
1264 register struct window
*c
;
1265 int oheight
= XFASTINT (w
->height
);
1266 int top
, pos
, lastbot
, opos
, lastobot
;
1270 && ! NILP (w
->parent
)
1271 && height
< window_min_height
)
1273 Fdelete_window (window
);
1277 XFASTINT (w
->last_modified
) = 0;
1278 windows_or_buffers_changed
++;
1279 XFASTINT (w
->height
) = height
;
1280 if (!NILP (w
->hchild
))
1282 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1284 XWINDOW (child
)->top
= w
->top
;
1285 set_window_height (child
, height
, nodelete
);
1288 else if (!NILP (w
->vchild
))
1290 lastbot
= top
= XFASTINT (w
->top
);
1292 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
1294 c
= XWINDOW (child
);
1296 opos
= lastobot
+ XFASTINT (c
->height
);
1298 XFASTINT (c
->top
) = lastbot
;
1300 pos
= (((opos
* height
) << 1) + oheight
) / (oheight
<< 1);
1302 /* Avoid confusion: inhibit deletion of child if becomes too small */
1303 set_window_height (child
, pos
+ top
- lastbot
, 1);
1305 /* Now advance child to next window,
1306 and set lastbot if child was not just deleted. */
1307 lastbot
= pos
+ top
;
1310 /* Now delete any children that became too small. */
1312 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1314 set_window_height (child
, XINT (XWINDOW (child
)->height
), 0);
1319 /* Recursively set width of WINDOW and its inferiors. */
1321 set_window_width (window
, width
, nodelete
)
1326 register struct window
*w
= XWINDOW (window
);
1327 register struct window
*c
;
1328 int owidth
= XFASTINT (w
->width
);
1329 int left
, pos
, lastright
, opos
, lastoright
;
1332 if (!nodelete
&& width
< window_min_width
)
1334 Fdelete_window (window
);
1338 XFASTINT (w
->last_modified
) = 0;
1339 windows_or_buffers_changed
++;
1340 XFASTINT (w
->width
) = width
;
1341 if (!NILP (w
->vchild
))
1343 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1345 XWINDOW (child
)->left
= w
->left
;
1346 set_window_width (child
, width
, nodelete
);
1349 else if (!NILP (w
->hchild
))
1351 lastright
= left
= XFASTINT (w
->left
);
1353 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
1355 c
= XWINDOW (child
);
1357 opos
= lastoright
+ XFASTINT (c
->width
);
1359 XFASTINT (c
->left
) = lastright
;
1361 pos
= (((opos
* width
) << 1) + owidth
) / (owidth
<< 1);
1363 /* Inhibit deletion for becoming too small */
1364 set_window_width (child
, pos
+ left
- lastright
, 1);
1366 /* Now advance child to next window,
1367 and set lastright if child was not just deleted. */
1368 lastright
= pos
+ left
, lastoright
= opos
;
1370 /* Delete children that became too small */
1372 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1374 set_window_width (child
, XINT (XWINDOW (child
)->width
), 0);
1379 int window_select_count
;
1381 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 2, 0,
1382 "Make WINDOW display BUFFER as its contents.\n\
1383 BUFFER can be a buffer or buffer name.")
1385 register Lisp_Object window
, buffer
;
1387 register Lisp_Object tem
;
1388 register struct window
*w
= decode_window (window
);
1390 buffer
= Fget_buffer (buffer
);
1391 CHECK_BUFFER (buffer
, 1);
1393 if (NILP (XBUFFER (buffer
)->name
))
1394 error ("Attempt to display deleted buffer");
1398 error ("Window is deleted");
1399 else if (! EQ (tem
, Qt
)) /* w->buffer is t when the window
1400 is first being set up. */
1402 if (!NILP (w
->dedicated
) && !EQ (tem
, buffer
))
1403 error ("Window is dedicated to %s\n", tem
);
1409 Fset_marker (w
->pointm
,
1410 make_number (BUF_PT (XBUFFER (buffer
))),
1412 set_marker_restricted (w
->start
,
1413 make_number (XBUFFER (buffer
)->last_window_start
),
1415 w
->start_at_line_beg
= Qnil
;
1416 XFASTINT (w
->last_modified
) = 0;
1417 windows_or_buffers_changed
++;
1418 if (EQ (window
, selected_window
))
1419 Fset_buffer (buffer
);
1424 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 1, 0,
1425 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1426 The main editor command loop selects the buffer of the selected window\n\
1427 before each command.")
1429 register Lisp_Object window
;
1431 register struct window
*w
;
1432 register struct window
*ow
= XWINDOW (selected_window
);
1434 CHECK_WINDOW (window
, 0);
1436 w
= XWINDOW (window
);
1438 if (NILP (w
->buffer
))
1439 error ("Trying to select deleted window or non-leaf window");
1441 XFASTINT (w
->use_time
) = ++window_select_count
;
1442 if (EQ (window
, selected_window
))
1445 Fset_marker (ow
->pointm
, make_number (BUF_PT (XBUFFER (ow
->buffer
))),
1448 selected_window
= window
;
1450 if (XSCREEN (WINDOW_SCREEN (w
)) != selected_screen
)
1452 XSCREEN (WINDOW_SCREEN (w
))->selected_window
= window
;
1453 Fselect_screen (WINDOW_SCREEN (w
), Qnil
);
1456 selected_screen
->selected_window
= window
;
1459 record_buffer (w
->buffer
);
1460 Fset_buffer (w
->buffer
);
1462 /* Go to the point recorded in the window.
1463 This is important when the buffer is in more
1464 than one window. It also matters when
1465 redisplay_window has altered point after scrolling,
1466 because it makes the change only in the window. */
1468 register int new_point
= marker_position (w
->pointm
);
1469 if (new_point
< BEGV
)
1477 windows_or_buffers_changed
++;
1481 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 2, 0,
1482 "Make BUFFER appear in some window but don't select it.\n\
1483 BUFFER can be a buffer or a buffer name.\n\
1484 If BUFFER is shown already in some window, just use that one,\n\
1485 unless the window is the selected window and the optional second\n\
1486 argument NOT_THIS_WINDOW is non-nil.\n\
1487 Returns the window displaying BUFFER.")
1488 (buffer
, not_this_window
)
1489 register Lisp_Object buffer
, not_this_window
;
1491 register Lisp_Object window
;
1493 buffer
= Fget_buffer (buffer
);
1494 CHECK_BUFFER (buffer
, 0);
1496 if (!NILP (Vdisplay_buffer_function
))
1497 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
1499 if (NILP (not_this_window
)
1500 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
1501 return selected_window
;
1503 window
= Fget_buffer_window (buffer
, Qnil
);
1505 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
1509 /* If there are no screens open that have more than a minibuffer,
1510 we need to create a new screen. */
1511 if (pop_up_screens
|| last_nonminibuf_screen
== 0)
1514 = Fscreen_selected_window (call0 (Vpop_up_screen_function
));
1515 Fset_window_buffer (window
, buffer
);
1517 Fselect_screen (XWINDOW (window
)->screen
, Qnil
);
1521 #endif /* MULTI_SCREEN */
1525 || SCREEN_MINIBUF_ONLY_P (selected_screen
)
1529 Lisp_Object screens
= Qnil
;
1532 if (SCREEN_MINIBUF_ONLY_P (selected_screen
))
1533 XSET (screens
, Lisp_Screen
, last_nonminibuf_screen
);
1535 /* Don't try to create a window if would get an error */
1536 if (split_height_threshold
< window_min_height
<< 1)
1537 split_height_threshold
= window_min_height
<< 1;
1539 window
= Fget_largest_window (screens
);
1542 && window_height (window
) >= split_height_threshold
1544 (XFASTINT (XWINDOW (window
)->width
)
1545 == SCREEN_WIDTH (XSCREEN (WINDOW_SCREEN (XWINDOW (window
))))))
1546 window
= Fsplit_window (window
, Qnil
, Qnil
);
1549 window
= Fget_lru_window (screens
);
1550 if ((EQ (window
, selected_window
)
1551 || EQ (XWINDOW (window
)->parent
, Qnil
))
1552 && window_height (window
) >= window_min_height
<< 1)
1553 window
= Fsplit_window (window
, Qnil
, Qnil
);
1557 window
= Fget_lru_window (Qnil
);
1559 Fset_window_buffer (window
, buffer
);
1564 temp_output_buffer_show (buf
)
1565 register Lisp_Object buf
;
1567 register struct buffer
*old
= current_buffer
;
1568 register Lisp_Object window
;
1569 register struct window
*w
;
1572 XBUFFER (buf
)->save_modified
= MODIFF
;
1577 set_buffer_internal (old
);
1579 if (!EQ (Vtemp_buffer_show_function
, Qnil
))
1580 call1 (Vtemp_buffer_show_function
, buf
);
1583 window
= Fdisplay_buffer (buf
, Qnil
);
1586 if (XSCREEN (XWINDOW (window
)->screen
) != selected_screen
)
1587 Fmake_screen_visible (XWINDOW (window
)->screen
);
1588 #endif /* MULTI_SCREEN */
1589 Vminibuf_scroll_window
= window
;
1590 w
= XWINDOW (window
);
1591 XFASTINT (w
->hscroll
) = 0;
1592 set_marker_restricted (w
->start
, make_number (1), buf
);
1593 set_marker_restricted (w
->pointm
, make_number (1), buf
);
1598 make_dummy_parent (window
)
1601 register Lisp_Object old
, new;
1602 register struct window
*o
, *p
;
1605 XSETTYPE (old
, Lisp_Vector
);
1606 new = Fcopy_sequence (old
);
1607 XSETTYPE (new, Lisp_Window
);
1611 XFASTINT (p
->sequence_number
) = ++sequence_number
;
1613 /* Put new into window structure in place of window */
1614 replace_window (window
, new);
1627 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
1628 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1629 WINDOW defaults to selected one and SIZE to half its size.\n\
1630 If optional third arg HOR-FLAG is non-nil, split side by side\n\
1631 and put SIZE columns in the first of the pair.")
1632 (window
, chsize
, horflag
)
1633 Lisp_Object window
, chsize
, horflag
;
1635 register Lisp_Object
new;
1636 register struct window
*o
, *p
;
1640 window
= selected_window
;
1642 CHECK_WINDOW (window
, 0);
1644 o
= XWINDOW (window
);
1648 if (!NILP (horflag
))
1649 /* Round odd size up, since this is for the left-hand window,
1650 and it will lose a column for the separators. */
1651 size
= ((XFASTINT (o
->width
) + 1) & -2) >> 1;
1653 size
= XFASTINT (o
->height
) >> 1;
1657 CHECK_NUMBER (chsize
, 1);
1658 size
= XINT (chsize
);
1661 if (MINI_WINDOW_P (o
))
1662 error ("Attempt to split minibuffer window");
1663 else if (SCREEN_NO_SPLIT_P (XSCREEN (WINDOW_SCREEN (o
))))
1664 error ("Attempt to split unsplittable screen");
1666 /* Smaller values might permit a crash. */
1667 if (window_min_width
< 2)
1668 window_min_width
= 2;
1669 if (window_min_height
< 2)
1670 window_min_height
= 2;
1674 if (size
< window_min_height
1675 || size
+ window_min_height
> XFASTINT (o
->height
))
1676 args_out_of_range_3 (window
, chsize
, horflag
);
1677 if (NILP (o
->parent
)
1678 || NILP (XWINDOW (o
->parent
)->vchild
))
1680 make_dummy_parent (window
);
1682 XWINDOW (new)->vchild
= window
;
1687 if (size
< window_min_width
1688 || size
+ window_min_width
> XFASTINT (o
->width
))
1689 args_out_of_range_3 (window
, chsize
, horflag
);
1690 if (NILP (o
->parent
)
1691 || NILP (XWINDOW (o
->parent
)->hchild
))
1693 make_dummy_parent (window
);
1695 XWINDOW (new)->hchild
= window
;
1699 /* Now we know that window's parent is a vertical combination
1700 if we are dividing vertically, or a horizontal combination
1701 if we are making side-by-side windows */
1703 windows_or_buffers_changed
++;
1704 new = make_window ();
1707 p
->screen
= o
->screen
;
1709 if (!NILP (p
->next
))
1710 XWINDOW (p
->next
)->prev
= new;
1713 p
->parent
= o
->parent
;
1716 Fset_window_buffer (new, o
->buffer
);
1718 /* Apportion the available screen space among the two new windows */
1720 if (!NILP (horflag
))
1722 p
->height
= o
->height
;
1724 XFASTINT (p
->width
) = XFASTINT (o
->width
) - size
;
1725 XFASTINT (o
->width
) = size
;
1726 XFASTINT (p
->left
) = XFASTINT (o
->left
) + size
;
1731 p
->width
= o
->width
;
1732 XFASTINT (p
->height
) = XFASTINT (o
->height
) - size
;
1733 XFASTINT (o
->height
) = size
;
1734 XFASTINT (p
->top
) = XFASTINT (o
->top
) + size
;
1740 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
1741 "Make current window ARG lines bigger.\n\
1742 From program, optional second arg non-nil means grow sideways ARG columns.")
1744 register Lisp_Object n
, side
;
1746 CHECK_NUMBER (n
, 0);
1747 change_window_height (XINT (n
), !NILP (side
));
1751 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
1752 "Make current window ARG lines smaller.\n\
1753 From program, optional second arg non-nil means shrink sideways ARG columns.")
1755 register Lisp_Object n
, side
;
1757 CHECK_NUMBER (n
, 0);
1758 change_window_height (-XINT (n
), !NILP (side
));
1763 window_height (window
)
1766 register struct window
*p
= XWINDOW (window
);
1767 return XFASTINT (p
->height
);
1771 window_width (window
)
1774 register struct window
*p
= XWINDOW (window
);
1775 return XFASTINT (p
->width
);
1778 #define MINSIZE(w) \
1779 (widthflag ? window_min_width : window_min_height)
1782 *(widthflag ? (int *) &(w)->left : (int *) &(w)->top)
1784 #define CURSIZE(w) \
1785 *(widthflag ? (int *) &(w)->width : (int *) &(w)->height)
1787 /* Unlike set_window_height, this function
1788 also changes the heights of the siblings so as to
1789 keep everything consistent. */
1791 change_window_height (delta
, widthflag
)
1795 register Lisp_Object parent
;
1797 register struct window
*p
;
1799 int (*sizefun
) () = widthflag
? window_width
: window_height
;
1800 register int (*setsizefun
) () = (widthflag
1802 : set_window_height
);
1804 /* Smaller values might permit a crash. */
1805 if (window_min_width
< 2)
1806 window_min_width
= 2;
1807 if (window_min_height
< 2)
1808 window_min_height
= 2;
1810 window
= selected_window
;
1813 p
= XWINDOW (window
);
1818 error ("No other window to side of this one");
1821 if (widthflag
? !NILP (XWINDOW (parent
)->hchild
)
1822 : !NILP (XWINDOW (parent
)->vchild
))
1827 sizep
= &CURSIZE (p
);
1829 if (*sizep
+ delta
< MINSIZE (p
)
1830 && !NILP (XWINDOW (window
)->parent
))
1832 Fdelete_window (window
);
1837 register int maxdelta
;
1839 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - *sizep
1840 : !NILP (p
->next
) ? (*sizefun
) (p
->next
) - MINSIZE (p
->next
)
1841 : !NILP (p
->prev
) ? (*sizefun
) (p
->prev
) - MINSIZE (p
->prev
)
1842 /* This is a screen with only one window, a minibuffer-only
1843 or a minibufferless screen. */
1846 if (delta
> maxdelta
)
1847 /* This case traps trying to make the minibuffer
1848 the full screen, or make the only window aside from the
1849 minibuffer the full screen. */
1856 if (!NILP (p
->next
) &&
1857 (*sizefun
) (p
->next
) - delta
>= MINSIZE (p
->next
))
1859 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
) - delta
, 0);
1860 (*setsizefun
) (window
, *sizep
+ delta
, 0);
1861 CURBEG (XWINDOW (p
->next
)) += delta
;
1862 /* This does not change size of p->next,
1863 but it propagates the new top edge to its children */
1864 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
), 0);
1866 else if (!NILP (p
->prev
) &&
1867 (*sizefun
) (p
->prev
) - delta
>= MINSIZE (p
->prev
))
1869 (*setsizefun
) (p
->prev
, (*sizefun
) (p
->prev
) - delta
, 0);
1870 CURBEG (p
) -= delta
;
1871 (*setsizefun
) (window
, *sizep
+ delta
, 0);
1875 register int delta1
;
1876 register int opht
= (*sizefun
) (parent
);
1878 /* If trying to grow this window to or beyond size of the parent,
1879 make delta1 so big that, on shrinking back down,
1880 all the siblings end up with less than one line and are deleted. */
1881 if (opht
<= *sizep
+ delta
)
1882 delta1
= opht
* opht
* 2;
1883 /* Otherwise, make delta1 just right so that if we add delta1
1884 lines to this window and to the parent, and then shrink
1885 the parent back to its original size, the new proportional
1886 size of this window will increase by delta. */
1888 delta1
= (delta
* opht
* 100) / ((opht
- *sizep
- delta
) * 100);
1890 /* Add delta1 lines or columns to this window, and to the parent,
1891 keeping things consistent while not affecting siblings. */
1892 CURSIZE (XWINDOW (parent
)) = opht
+ delta1
;
1893 (*setsizefun
) (window
, *sizep
+ delta1
, 0);
1895 /* Squeeze out delta1 lines or columns from our parent,
1896 shriking this window and siblings proportionately.
1897 This brings parent back to correct size.
1898 Delta1 was calculated so this makes this window the desired size,
1899 taking it all out of the siblings. */
1900 (*setsizefun
) (parent
, opht
, 0);
1903 XFASTINT (p
->last_modified
) = 0;
1910 /* Return number of lines of text (not counting mode line) in W. */
1913 window_internal_height (w
)
1916 int ht
= XFASTINT (w
->height
);
1918 if (MINI_WINDOW_P (w
))
1921 if (!NILP (w
->parent
) || !NILP (w
->vchild
) || !NILP (w
->hchild
)
1922 || !NILP (w
->next
) || !NILP (w
->prev
)
1923 || SCREEN_WANTS_MODELINE_P (XSCREEN (WINDOW_SCREEN (w
))))
1929 /* Scroll contents of window WINDOW up N lines. */
1932 window_scroll (window
, n
, noerror
)
1937 register struct window
*w
= XWINDOW (window
);
1938 register int opoint
= point
;
1940 register int ht
= window_internal_height (w
);
1941 register Lisp_Object tem
;
1943 Lisp_Object bolp
, nmoved
;
1945 XFASTINT (tem
) = point
;
1946 tem
= Fpos_visible_in_window_p (tem
, window
);
1950 Fvertical_motion (make_number (- ht
/ 2));
1951 XFASTINT (tem
) = point
;
1952 Fset_marker (w
->start
, tem
, w
->buffer
);
1953 w
->force_start
= Qt
;
1956 SET_PT (marker_position (w
->start
));
1957 lose
= n
< 0 && point
== BEGV
;
1958 Fvertical_motion (make_number (n
));
1968 Fsignal (Qbeginning_of_buffer
, Qnil
);
1973 set_marker_restricted (w
->start
, make_number (pos
), w
->buffer
);
1974 w
->start_at_line_beg
= bolp
;
1975 w
->update_mode_line
= Qt
;
1976 XFASTINT (w
->last_modified
) = 0;
1982 tem
= Fvertical_motion (make_number (ht
));
1983 if (point
> opoint
|| XFASTINT (tem
) < ht
)
1986 Fvertical_motion (make_number (-1));
1994 Fsignal (Qend_of_buffer
, Qnil
);
1998 /* This is the guts of Fscroll_up and Fscroll_down. */
2001 scroll_command (n
, direction
)
2002 register Lisp_Object n
;
2005 register int defalt
;
2006 int count
= specpdl_ptr
- specpdl
;
2008 /* If selected window's buffer isn't current, make it current for the moment.
2009 But don't screw up if window_scroll gets an error. */
2010 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
2012 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2013 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2016 defalt
= (window_internal_height (XWINDOW (selected_window
))
2017 - next_screen_context_lines
);
2018 defalt
= direction
* (defalt
< 1 ? 1 : defalt
);
2021 window_scroll (selected_window
, defalt
, 0);
2022 else if (EQ (n
, Qminus
))
2023 window_scroll (selected_window
, - defalt
, 0);
2026 n
= Fprefix_numeric_value (n
);
2027 window_scroll (selected_window
, XINT (n
) * direction
, 0);
2030 unbind_to (count
, Qnil
);
2033 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "P",
2034 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2035 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2036 When calling from a program, supply a number as argument or nil.")
2040 scroll_command (n
, 1);
2044 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "P",
2045 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2046 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2047 When calling from a program, supply a number as argument or nil.")
2051 scroll_command (n
, -1);
2055 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
2056 "Scroll text of next window upward ARG lines; or near full screen if no ARG.\n\
2057 The next window is the one below the current one; or the one at the top\n\
2058 if the current one is at the bottom.\n\
2059 When calling from a program, supply a number as argument or nil.\n\
2061 If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
2062 specifies the window to scroll.\n\
2063 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2064 showing that buffer, popping the buffer up if necessary.")
2066 register Lisp_Object n
;
2068 register Lisp_Object window
;
2070 register struct window
*w
;
2071 register int count
= specpdl_ptr
- specpdl
;
2073 if (MINI_WINDOW_P (XWINDOW (selected_window
))
2074 && !NILP (Vminibuf_scroll_window
))
2075 window
= Vminibuf_scroll_window
;
2076 /* If buffer is specified, scroll that buffer. */
2077 else if (!NILP (Vother_window_scroll_buffer
))
2079 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
2081 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
);
2084 /* Nothing specified; pick a neighboring window. */
2085 window
= Fnext_window (selected_window
, Qnil
, Qt
);
2086 CHECK_WINDOW (window
, 0);
2088 if (EQ (window
, selected_window
))
2089 error ("There is no other window");
2091 w
= XWINDOW (window
);
2092 ht
= window_internal_height (w
);
2094 /* Don't screw up if window_scroll gets an error. */
2095 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2097 Fset_buffer (w
->buffer
);
2098 SET_PT (marker_position (w
->pointm
));
2101 window_scroll (window
, ht
- next_screen_context_lines
, 1);
2102 else if (EQ (n
, Qminus
))
2103 window_scroll (window
, next_screen_context_lines
- ht
, 1);
2106 if (XTYPE (n
) == Lisp_Cons
)
2108 CHECK_NUMBER (n
, 0);
2109 window_scroll (window
, XINT (n
), 1);
2112 Fset_marker (w
->pointm
, make_number (point
), Qnil
);
2118 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 1, 1, "P",
2119 "Scroll selected window display ARG columns left.\n\
2120 Default for ARG is window width minus 2.")
2122 register Lisp_Object arg
;
2126 XFASTINT (arg
) = XFASTINT (XWINDOW (selected_window
)->width
) - 2;
2128 arg
= Fprefix_numeric_value (arg
);
2131 Fset_window_hscroll (selected_window
,
2132 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2136 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 1, 1, "P",
2137 "Scroll selected window display ARG columns right.\n\
2138 Default for ARG is window width minus 2.")
2140 register Lisp_Object arg
;
2143 XFASTINT (arg
) = XFASTINT (XWINDOW (selected_window
)->width
) - 2;
2145 arg
= Fprefix_numeric_value (arg
);
2148 Fset_window_hscroll (selected_window
,
2149 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2153 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
2154 "Center point in window and redisplay screen. With ARG, put point on line ARG.\n\
2155 The desired position of point is always relative to the current window.\n\
2156 Just C-u as prefix means put point in the center of the screen.\n\
2157 No arg (i.e., it is nil) erases the entire screen and then\n\
2158 redraws with point in the center.")
2160 register Lisp_Object n
;
2162 register struct window
*w
= XWINDOW (selected_window
);
2163 register int ht
= window_internal_height (w
);
2164 register int opoint
= point
;
2168 extern int screen_garbaged
;
2170 SET_SCREEN_GARBAGED (XSCREEN (WINDOW_SCREEN (w
)));
2171 XFASTINT (n
) = ht
/ 2;
2173 else if (XTYPE (n
) == Lisp_Cons
) /* Just C-u. */
2175 XFASTINT (n
) = ht
/ 2;
2179 n
= Fprefix_numeric_value (n
);
2180 CHECK_NUMBER (n
, 0);
2184 XSETINT (n
, XINT (n
) + ht
);
2186 XSETINT (n
, - XINT (n
));
2188 Fvertical_motion (n
);
2189 Fset_marker (w
->start
, make_number (point
), w
->buffer
);
2190 w
->start_at_line_beg
= Fbolp ();
2193 w
->force_start
= Qt
;
2198 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
2200 "Position point relative to window.\n\
2201 With no argument, position text at center of window.\n\
2202 An argument specifies screen line; zero means top of window,\n\
2203 negative means relative to bottom of window.")
2205 register Lisp_Object arg
;
2207 register struct window
*w
= XWINDOW (selected_window
);
2208 register int height
= window_internal_height (w
);
2212 XFASTINT (arg
) = height
/ 2;
2215 arg
= Fprefix_numeric_value (arg
);
2217 XSETINT (arg
, XINT (arg
) + height
);
2220 start
= marker_position (w
->start
);
2221 if (start
< BEGV
|| start
> ZV
)
2223 Fvertical_motion (make_number (- height
/ 2));
2224 Fset_marker (w
->start
, make_number (point
), w
->buffer
);
2225 w
->start_at_line_beg
= Fbolp ();
2226 w
->force_start
= Qt
;
2231 return Fvertical_motion (arg
);
2234 struct save_window_data
2236 int size_from_Lisp_Vector_struct
;
2237 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2238 Lisp_Object screen_width
, screen_height
;
2239 Lisp_Object current_window
;
2240 Lisp_Object current_buffer
;
2241 Lisp_Object minibuf_scroll_window
;
2242 Lisp_Object root_window
;
2243 /* A vector, interpreted as a struct saved_window */
2244 Lisp_Object saved_windows
;
2246 #define SAVE_WINDOW_DATA_SIZE 7 /* Arg to Fmake_vector */
2248 /* This is saved as a Lisp_Vector */
2251 /* these first two must agree with struct Lisp_Vector in lisp.h */
2252 int size_from_Lisp_Vector_struct
;
2253 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2256 Lisp_Object buffer
, start
, pointm
, mark
;
2257 Lisp_Object left
, top
, width
, height
, hscroll
;
2258 Lisp_Object parent
, prev
;
2259 Lisp_Object start_at_line_beg
;
2260 Lisp_Object display_table
;
2262 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2264 #define SAVED_WINDOW_N(swv,n) \
2265 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2267 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
2268 "T if OBJECT is a window-configration object.")
2272 if (XTYPE (obj
) == Lisp_Window_Configuration
)
2278 DEFUN ("set-window-configuration",
2279 Fset_window_configuration
, Sset_window_configuration
,
2281 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2282 CONFIGURATION must be a value previously returned\n\
2283 by `current-window-configuration' (which see).")
2287 register struct window
*w
;
2288 register struct save_window_data
*data
;
2289 struct Lisp_Vector
*saved_windows
;
2290 register struct saved_window
*p
;
2291 register Lisp_Object tem
;
2292 Lisp_Object new_current_buffer
;
2296 while (XTYPE (arg
) != Lisp_Window_Configuration
)
2298 arg
= wrong_type_argument (intern ("window-configuration-p"), arg
);
2301 data
= (struct save_window_data
*) XVECTOR (arg
);
2302 saved_windows
= XVECTOR (data
->saved_windows
);
2304 s
= XSCREEN (XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->screen
);
2306 if (XFASTINT (data
->screen_height
) != SCREEN_HEIGHT (s
)
2307 || XFASTINT (data
->screen_width
) != SCREEN_WIDTH (s
))
2309 /* Presumably something clever could be done.
2310 However, it doesn't seem worth the effort */
2311 error ("Screen size %dx%d in saved window configuration mismatches screen.",
2312 XFASTINT (data
->screen_height
),
2313 XFASTINT (data
->screen_width
));
2316 windows_or_buffers_changed
++;
2317 new_current_buffer
= data
->current_buffer
;
2318 if (NILP (XBUFFER (new_current_buffer
)->name
))
2319 new_current_buffer
= Qnil
;
2321 /* Mark all windows now on screen as "deleted".
2322 Restoring the new configuration "undeletes" any that are in it. */
2324 delete_all_subwindows (XWINDOW (SCREEN_ROOT_WINDOW (s
)));
2326 /* This loses when the minibuf screen is not s. */
2327 delete_all_subwindows (XWINDOW (XWINDOW (minibuf_window
)->prev
));
2330 for (k
= 0; k
< saved_windows
->size
; k
++)
2332 p
= SAVED_WINDOW_N (saved_windows
, k
);
2333 w
= XWINDOW (p
->window
);
2336 if (!NILP (p
->parent
))
2337 w
->parent
= SAVED_WINDOW_N (saved_windows
, XFASTINT (p
->parent
))->window
;
2341 if (!NILP (p
->prev
))
2343 w
->prev
= SAVED_WINDOW_N (saved_windows
, XFASTINT (p
->prev
))->window
;
2345 /* This is true for a minibuffer-only screen. */
2346 if (w
->mini_p
&& EQ (w
->prev
, p
->window
))
2349 #endif /* MULTI_SCREEN */
2350 XWINDOW (w
->prev
)->next
= p
->window
;
2355 if (!NILP (w
->parent
))
2357 if (EQ (p
->width
, XWINDOW (w
->parent
)->width
))
2359 XWINDOW (w
->parent
)->vchild
= p
->window
;
2360 XWINDOW (w
->parent
)->hchild
= Qnil
;
2364 XWINDOW (w
->parent
)->hchild
= p
->window
;
2365 XWINDOW (w
->parent
)->vchild
= Qnil
;
2371 w
->width
= p
->width
;
2372 w
->height
= p
->height
;
2373 w
->hscroll
= p
->hscroll
;
2374 w
->display_table
= p
->display_table
;
2375 XFASTINT (w
->last_modified
) = 0;
2377 /* Reinstall the saved buffer and pointers into it. */
2378 if (NILP (p
->buffer
))
2379 w
->buffer
= p
->buffer
;
2382 if (!NILP (XBUFFER (p
->buffer
)->name
))
2383 /* If saved buffer is alive, install it. */
2385 w
->buffer
= p
->buffer
;
2386 w
->start_at_line_beg
= p
->start_at_line_beg
;
2387 set_marker_restricted (w
->start
, Fmarker_position (p
->start
), w
->buffer
);
2388 set_marker_restricted (w
->pointm
, Fmarker_position (p
->pointm
), w
->buffer
);
2389 Fset_marker (XBUFFER (w
->buffer
)->mark
,
2390 Fmarker_position (p
->mark
), w
->buffer
);
2392 if (!EQ (p
->buffer
, new_current_buffer
) &&
2393 XBUFFER (p
->buffer
) == current_buffer
)
2394 Fgoto_char (w
->pointm
);
2396 else if (NILP (XBUFFER (w
->buffer
)->name
))
2397 /* Else if window's old buffer is dead too, get a live one. */
2399 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
2400 /* This will set the markers to beginning of visible range. */
2401 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
2402 set_marker_restricted (w
->pointm
, make_number (0), w
->buffer
);
2403 w
->start_at_line_beg
= Qt
;
2406 /* Keeping window's old buffer; make sure the markers are real. */
2407 /* Else if window's old buffer is dead too, get a live one. */
2409 /* Set window markers at start of visible range. */
2410 if (XMARKER (w
->start
)->buffer
== 0)
2411 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
2412 if (XMARKER (w
->pointm
)->buffer
== 0)
2413 set_marker_restricted (w
->pointm
,
2414 make_number (BUF_PT (XBUFFER (w
->buffer
))),
2416 w
->start_at_line_beg
= Qt
;
2421 SCREEN_ROOT_WINDOW (s
) = data
->root_window
;
2424 if (s
!= selected_screen
&& ! SCREEN_IS_TERMCAP (s
))
2425 Fselect_screen (WINDOW_SCREEN (XWINDOW (data
->root_window
)), Qnil
);
2428 if (s
== selected_screen
)
2430 Fselect_window (data
->current_window
);
2431 if (!NILP (new_current_buffer
))
2432 Fset_buffer (new_current_buffer
);
2434 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2437 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
2441 /* Mark all windows now on screen as deleted
2442 by setting their buffers to nil. */
2445 delete_all_subwindows (w
)
2446 register struct window
*w
;
2448 register int count
= 1;
2450 if (!NILP (w
->next
))
2451 delete_all_subwindows (XWINDOW (w
->next
));
2452 if (!NILP (w
->vchild
))
2453 delete_all_subwindows (XWINDOW (w
->vchild
));
2454 if (!NILP (w
->hchild
))
2455 delete_all_subwindows (XWINDOW (w
->hchild
));
2459 count_windows (window
)
2460 register struct window
*window
;
2462 register int count
= 1;
2463 if (!NILP (window
->next
))
2464 count
+= count_windows (XWINDOW (window
->next
));
2465 if (!NILP (window
->vchild
))
2466 count
+= count_windows (XWINDOW (window
->vchild
));
2467 if (!NILP (window
->hchild
))
2468 count
+= count_windows (XWINDOW (window
->hchild
));
2473 save_window_save (window
, vector
, i
)
2475 struct Lisp_Vector
*vector
;
2478 register struct saved_window
*p
;
2479 register struct window
*w
;
2480 register Lisp_Object tem
;
2482 for (;!NILP (window
); window
= w
->next
)
2484 p
= SAVED_WINDOW_N (vector
, i
);
2485 w
= XWINDOW (window
);
2487 XFASTINT (w
->temslot
) = i
++;
2489 p
->buffer
= w
->buffer
;
2492 p
->width
= w
->width
;
2493 p
->height
= w
->height
;
2494 p
->hscroll
= w
->hscroll
;
2495 p
->display_table
= w
->display_table
;
2496 if (!NILP (w
->buffer
))
2498 /* Save w's value of point in the window configuration.
2499 If w is the selected window, then get the value of point
2500 from the buffer; pointm is garbage in the selected window. */
2501 if (EQ (window
, selected_window
))
2503 p
->pointm
= Fmake_marker ();
2504 Fset_marker (p
->pointm
, BUF_PT (XBUFFER (w
->buffer
)),
2508 p
->pointm
= Fcopy_marker (w
->pointm
);
2510 p
->start
= Fcopy_marker (w
->start
);
2511 p
->start_at_line_beg
= w
->start_at_line_beg
;
2513 tem
= XBUFFER (w
->buffer
)->mark
;
2514 p
->mark
= Fcopy_marker (tem
);
2521 p
->start_at_line_beg
= Qnil
;
2524 if (NILP (w
->parent
))
2527 p
->parent
= XWINDOW (w
->parent
)->temslot
;
2532 p
->prev
= XWINDOW (w
->prev
)->temslot
;
2534 if (!NILP (w
->vchild
))
2535 i
= save_window_save (w
->vchild
, vector
, i
);
2536 if (!NILP (w
->hchild
))
2537 i
= save_window_save (w
->hchild
, vector
, i
);
2543 DEFUN ("current-window-configuration",
2544 Fcurrent_window_configuration
, Scurrent_window_configuration
, 0, 1, 0,
2545 "Return an object representing the current window configuration of SCREEN.\n\
2546 If SCREEN is nil or omitted, use the selected screen.\n\
2547 This describes the number of windows, their sizes and current buffers,\n\
2548 and for each displayed buffer, where display starts, and the positions of\n\
2549 point and mark. An exception is made for point in the current buffer:\n\
2550 its value is -not- saved.")
2554 register Lisp_Object tem
;
2555 register int n_windows
;
2556 register struct save_window_data
*data
;
2561 s
= selected_screen
;
2564 CHECK_LIVE_SCREEN (screen
, 0);
2565 s
= XSCREEN (screen
);
2568 n_windows
= count_windows (XWINDOW (SCREEN_ROOT_WINDOW (s
)));
2569 data
= (struct save_window_data
*)
2570 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE
),
2572 XFASTINT (data
->screen_width
) = SCREEN_WIDTH (s
);
2573 XFASTINT (data
->screen_height
) = SCREEN_HEIGHT (s
);
2574 data
->current_window
= SCREEN_SELECTED_WINDOW (s
);
2575 XSET (data
->current_buffer
, Lisp_Buffer
, current_buffer
);
2576 data
->minibuf_scroll_window
= Vminibuf_scroll_window
;
2577 data
->root_window
= SCREEN_ROOT_WINDOW (s
);
2578 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
2579 data
->saved_windows
= tem
;
2580 for (i
= 0; i
< n_windows
; i
++)
2581 XVECTOR (tem
)->contents
[i
]
2582 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE
), Qnil
);
2583 save_window_save (SCREEN_ROOT_WINDOW (s
),
2585 XSET (tem
, Lisp_Window_Configuration
, data
);
2589 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
2591 "Execute body, preserving window sizes and contents.\n\
2592 Restores which buffer appears in which window, where display starts,\n\
2593 as well as the current buffer.\n\
2594 Does not restore the value of point in current buffer.")
2598 register Lisp_Object val
;
2599 register int count
= specpdl_ptr
- specpdl
;
2601 record_unwind_protect (Fset_window_configuration
,
2602 Fcurrent_window_configuration (Qnil
));
2603 val
= Fprogn (args
);
2604 return unbind_to (count
, val
);
2610 selected_screen
= make_terminal_screen ();
2611 minibuf_window
= selected_screen
->minibuffer_window
;
2612 selected_window
= selected_screen
->selected_window
;
2613 last_nonminibuf_screen
= selected_screen
;
2614 #else /* not MULTI_SCREEN */
2615 extern Lisp_Object
get_minibuffer ();
2617 root_window
= make_window ();
2618 minibuf_window
= make_window ();
2620 XWINDOW (root_window
)->next
= minibuf_window
;
2621 XWINDOW (minibuf_window
)->prev
= root_window
;
2623 /* These values 9 and 10 are arbitrary,
2624 just so that there is "something there."
2625 Correct values are put in in init_xdisp */
2627 XFASTINT (XWINDOW (root_window
)->width
) = 10;
2628 XFASTINT (XWINDOW (minibuf_window
)->width
) = 10;
2630 XFASTINT (XWINDOW (root_window
)->height
) = 9;
2631 XFASTINT (XWINDOW (minibuf_window
)->top
) = 9;
2632 XFASTINT (XWINDOW (minibuf_window
)->height
) = 1;
2634 /* Prevent error in Fset_window_buffer. */
2635 XWINDOW (root_window
)->buffer
= Qt
;
2636 XWINDOW (minibuf_window
)->buffer
= Qt
;
2638 /* Now set them up for real. */
2639 Fset_window_buffer (root_window
, Fcurrent_buffer ());
2640 Fset_window_buffer (minibuf_window
, get_minibuffer (0));
2642 selected_window
= root_window
;
2643 /* Make sure this window seems more recently used than
2644 a newly-created, never-selected window. Increment
2645 window_select_count so the first selection ever will get
2646 something newer than this. */
2647 XFASTINT (XWINDOW (selected_window
)->use_time
) = ++window_select_count
;
2648 #endif /* not MULTI_SCREEN */
2653 Qwindowp
= intern ("windowp");
2654 staticpro (&Qwindowp
);
2656 /* Make sure all windows get marked */
2657 staticpro (&minibuf_window
);
2659 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
2660 "Non-nil means call as function to display a help buffer.\n\
2661 Used by `with-output-to-temp-buffer'.");
2662 Vtemp_buffer_show_function
= Qnil
;
2664 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
2665 "If non-nil, function to call to handle `display-buffer'.\n\
2666 It will receive two args, the buffer and a flag which if non-nil means\n\
2667 that the currently selected window is not acceptable.\n\
2668 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
2669 work using this function.");
2670 Vdisplay_buffer_function
= Qnil
;
2672 DEFVAR_LISP ("mouse-window", &Vmouse_window
,
2673 "Window that the last mouse click occurred on.");
2674 Vmouse_window
= Qnil
;
2676 DEFVAR_LISP ("mouse-event", &Vmouse_event
,
2677 "The last mouse-event object. A list of four elements:\n\
2678 ((X-POS Y-POS) WINDOW SCREEN-PART KEYSEQ).\n\
2679 KEYSEQ is a string, the key sequence to be looked up in the mouse maps.\n\
2680 WINDOW is the window that the click applies do.\n\
2681 If SCREEN-PART is non-nil, the event was on a scrollbar;\n\
2682 then Y-POS is really the total length of the scrollbar, while X-POS is\n\
2683 the relative position of the scrollbar's value within that total length.\n\
2684 SCREEN-PART is one of the following symbols:\n\
2685 `vertical-scrollbar', `vertical-slider',\n\
2686 `vertical-thumbup', `vertical-thumbdown',\n\
2687 `horizontal-scrollbar', `horizontal-slider',\n\
2688 `horizontal-thumbleft', `horizontal-thumbright'");
2689 Vmouse_event
= Qnil
;
2691 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
2692 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
2693 Vminibuf_scroll_window
= Qnil
;
2695 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
2696 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
2697 Vother_window_scroll_buffer
= Qnil
;
2700 DEFVAR_BOOL ("pop-up-screens", &pop_up_screens
,
2701 "*Non-nil means `display-buffer' should make a separate X-window.");
2704 DEFVAR_LISP ("pop-up-screen-function", &Vpop_up_screen_function
,
2705 "*If non-nil, function to call to handle automatic new screen creation.\n\
2706 It is called with no arguments and should return a newly created screen.\n\
2708 A typical value might be `(lambda () (x-create-screen auto-screen-parms))'\n\
2709 where `auto-screen-parms' would hold the default screen parameters.");
2710 Vpop_up_screen_function
= Qnil
;
2713 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
2714 "*Non-nil means display-buffer should make new windows.");
2717 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
2718 "*Number of lines of continuity when scrolling by screenfuls.");
2719 next_screen_context_lines
= 2;
2721 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
2722 "*display-buffer would prefer to split the largest window if this large.\n\
2723 If there is only one window, it is split regardless of this value.");
2724 split_height_threshold
= 500;
2726 DEFVAR_INT ("window-min-height", &window_min_height
,
2727 "*Delete any window less than this tall (including its mode line).");
2728 window_min_height
= 4;
2730 DEFVAR_INT ("window-min-width", &window_min_width
,
2731 "*Delete any window less than this wide.");
2732 window_min_width
= 10;
2734 defsubr (&Sselected_window
);
2735 defsubr (&Sminibuffer_window
);
2736 defsubr (&Swindow_minibuffer_p
);
2737 defsubr (&Swindowp
);
2738 defsubr (&Spos_visible_in_window_p
);
2739 defsubr (&Swindow_buffer
);
2740 defsubr (&Swindow_height
);
2741 defsubr (&Swindow_width
);
2742 defsubr (&Swindow_hscroll
);
2743 defsubr (&Sset_window_hscroll
);
2744 defsubr (&Swindow_edges
);
2745 defsubr (&Scoordinates_in_window_p
);
2746 defsubr (&Swindow_at
);
2747 defsubr (&Swindow_point
);
2748 defsubr (&Swindow_start
);
2749 defsubr (&Swindow_end
);
2750 defsubr (&Sset_window_point
);
2751 defsubr (&Sset_window_start
);
2752 defsubr (&Swindow_dedicated_p
);
2753 defsubr (&Sset_window_dedicated_p
);
2754 defsubr (&Swindow_display_table
);
2755 defsubr (&Sset_window_display_table
);
2756 defsubr (&Snext_window
);
2757 defsubr (&Sprevious_window
);
2758 defsubr (&Sother_window
);
2759 defsubr (&Sget_lru_window
);
2760 defsubr (&Sget_largest_window
);
2761 defsubr (&Sget_buffer_window
);
2762 defsubr (&Sdelete_other_windows
);
2763 defsubr (&Sdelete_windows_on
);
2764 defsubr (&Sreplace_buffer_in_windows
);
2765 defsubr (&Sdelete_window
);
2766 defsubr (&Sset_window_buffer
);
2767 defsubr (&Sselect_window
);
2768 defsubr (&Sdisplay_buffer
);
2769 defsubr (&Ssplit_window
);
2770 defsubr (&Senlarge_window
);
2771 defsubr (&Sshrink_window
);
2772 defsubr (&Sscroll_up
);
2773 defsubr (&Sscroll_down
);
2774 defsubr (&Sscroll_left
);
2775 defsubr (&Sscroll_right
);
2776 defsubr (&Sscroll_other_window
);
2777 defsubr (&Srecenter
);
2778 defsubr (&Smove_to_window_line
);
2779 defsubr (&Swindow_configuration_p
);
2780 defsubr (&Sset_window_configuration
);
2781 defsubr (&Scurrent_window_configuration
);
2782 defsubr (&Ssave_window_excursion
);
2787 initial_define_key (control_x_map
, '1', "delete-other-windows");
2788 initial_define_key (control_x_map
, '2', "split-window");
2789 initial_define_key (control_x_map
, '0', "delete-window");
2790 initial_define_key (control_x_map
, 'o', "other-window");
2791 initial_define_key (control_x_map
, '^', "enlarge-window");
2792 initial_define_key (control_x_map
, '<', "scroll-left");
2793 initial_define_key (control_x_map
, '>', "scroll-right");
2795 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
2796 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
2797 initial_define_key (meta_map
, 'v', "scroll-down");
2799 initial_define_key (global_map
, Ctl('L'), "recenter");
2800 initial_define_key (meta_map
, 'r', "move-to-window-line");