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
;
50 /* The minibuffer window of the selected screen.
51 Note that you cannot test for minibufferness of an arbitrary window
52 by comparing against this; but you can test for minibufferness of
53 the selected window. */
54 Lisp_Object minibuf_window
;
56 /* Non-nil means it is the window for C-M-v to scroll
57 when the minibuffer is selected. */
58 Lisp_Object Vminibuf_scroll_window
;
60 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
61 Lisp_Object Vother_window_scroll_buffer
;
63 /* Window that the mouse is over (nil if no mouse support). */
64 Lisp_Object Vmouse_window
;
66 /* Last mouse click data structure (nil if no mouse support). */
67 Lisp_Object Vmouse_event
;
69 /* Non-nil means it's function to call to display temp buffers. */
70 Lisp_Object Vtemp_buffer_show_function
;
72 /* If a window gets smaller than either of these, it is removed. */
73 int window_min_height
;
76 /* Nonzero implies Fdisplay_buffer should create windows. */
79 /* Nonzero implies make new X screens for Fdisplay_buffer. */
82 /* Non-nil means use this function instead of default */
83 Lisp_Object Vpop_up_screen_function
;
85 /* Function to call to handle Fdisplay_buffer. */
86 Lisp_Object Vdisplay_buffer_function
;
88 /* Fdisplay_buffer always splits the largest window
89 if that window is more than this high. */
90 int split_height_threshold
;
92 /* Number of lines of continuity in scrolling by screenfuls. */
93 int next_screen_context_lines
;
95 /* Incremented for each window created. */
96 static int sequence_number
;
98 #define min(a, b) ((a) < (b) ? (a) : (b))
100 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
101 "Returns t if OBJ is a window.")
105 return XTYPE (obj
) == Lisp_Window
? Qt
: Qnil
;
111 register Lisp_Object val
;
112 register struct window
*p
;
114 /* Add sizeof (Lisp_Object) here because sizeof (struct Lisp_Vector)
115 includes the first element. */
117 make_number ((sizeof (struct window
) - sizeof (struct Lisp_Vector
)
118 + sizeof (Lisp_Object
))
119 / sizeof (Lisp_Object
)),
121 XSETTYPE (val
, Lisp_Window
);
123 XFASTINT (p
->sequence_number
) = ++sequence_number
;
124 XFASTINT (p
->left
) = XFASTINT (p
->top
)
125 = XFASTINT (p
->height
) = XFASTINT (p
->width
)
126 = XFASTINT (p
->hscroll
) = 0;
127 XFASTINT (p
->last_point_x
) = XFASTINT (p
->last_point_y
) = 0;
128 p
->start
= Fmake_marker ();
129 p
->pointm
= Fmake_marker ();
130 XFASTINT (p
->use_time
) = 0;
132 p
->display_table
= Qnil
;
137 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
138 "Return the window that the cursor now appears in and commands apply to.")
141 return selected_window
;
144 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 0, 0,
145 "Return the window used now for minibuffers.")
149 choose_minibuf_screen ();
150 #endif /* MULTI_SCREEN */
151 return minibuf_window
;
154 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 1, 1, 0,
155 "Returns non-nil if WINDOW is a minibuffer window.")
159 struct window
*w
= decode_window (window
);
160 return (MINI_WINDOW_P (w
) ? Qt
: Qnil
);
163 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
164 Spos_visible_in_window_p
, 0, 2, 0,
165 "Return t if position POS is currently on the screen in WINDOW.\n\
166 Returns nil if that position is scrolled vertically out of view.\n\
167 POS defaults to point; WINDOW, to the selected window.")
169 Lisp_Object pos
, window
;
171 register struct window
*w
;
175 register struct buffer
*buf
;
176 struct position posval
;
182 CHECK_NUMBER_COERCE_MARKER (pos
, 0);
187 window
= selected_window
;
189 CHECK_WINDOW (window
, 1);
190 w
= XWINDOW (window
);
191 top
= marker_position (w
->start
);
196 height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
198 buf
= XBUFFER (w
->buffer
);
199 if (XFASTINT (w
->last_modified
) >= BUF_MODIFF (buf
))
201 /* If screen is up to date,
202 use the info recorded about how much text fit on it. */
203 if (posint
< BUF_Z (buf
) - XFASTINT (w
->window_end_pos
)
204 || (XFASTINT (w
->window_end_vpos
) < height
))
210 if (posint
> BUF_Z (buf
))
213 /* If that info is not correct, calculate afresh */
214 posval
= *compute_motion (top
, 0, 0, posint
, height
, 0,
215 XFASTINT (w
->width
) - 1
216 - (XFASTINT (w
->width
) + XFASTINT (w
->left
)
217 != SCREEN_WIDTH (XSCREEN (w
->screen
))),
218 XINT (w
->hscroll
), 0);
220 return posval
.vpos
< height
? Qt
: Qnil
;
224 static struct window
*
225 decode_window (window
)
226 register Lisp_Object window
;
229 return XWINDOW (selected_window
);
231 CHECK_WINDOW (window
, 0);
232 return XWINDOW (window
);
235 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
236 "Return the buffer that WINDOW is displaying.")
240 return decode_window (window
)->buffer
;
243 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
244 "Return the number of lines in WINDOW (including its mode line).")
248 return decode_window (window
)->height
;
251 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
252 "Return the number of columns in WINDOW.")
256 register struct window
*w
= decode_window (window
);
257 register int width
= w
->width
;
259 /* If this window does not end at the right margin,
260 must deduct one column for the border */
261 if ((width
+ w
->left
) == SCREEN_WIDTH (XSCREEN (WINDOW_SCREEN (w
))))
266 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
267 "Return the number of columns by which WINDOW is scrolled from left margin.")
271 return decode_window (window
)->hscroll
;
274 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
275 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
276 NCOL should be zero or positive.")
278 register Lisp_Object window
, ncol
;
280 register struct window
*w
;
282 CHECK_NUMBER (ncol
, 1);
283 if (XINT (ncol
) < 0) XFASTINT (ncol
) = 0;
284 if (XFASTINT (ncol
) >= (1 << (SHORTBITS
- 1)))
285 args_out_of_range (ncol
, Qnil
);
286 w
= decode_window (window
);
287 if (w
->hscroll
!= ncol
)
288 clip_changed
= 1; /* Prevent redisplay shortcuts */
293 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
294 "Return a list of the edge coordinates of WINDOW.\n\
295 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of screen.\n\
296 RIGHT is one more than the rightmost column used by WINDOW,\n\
297 and BOTTOM is one more than the bottommost row used by WINDOW\n\
302 register struct window
*w
= decode_window (window
);
304 return Fcons (w
->left
, Fcons (w
->top
,
305 Fcons (make_number (XFASTINT (w
->left
) + XFASTINT (w
->width
)),
306 Fcons (make_number (XFASTINT (w
->top
)
307 + XFASTINT (w
->height
)),
311 /* Test if the character at column *x, row *y is within window *w.
312 If it is not, return 0;
313 if it is in the window's text area,
314 set *x and *y to its location relative to the upper left corner
317 if it is on the window's modeline, return 2;
318 if it is on the border between the window and its right sibling,
321 coordinates_in_window (w
, x
, y
)
322 register struct window
*w
;
325 register int left
= XINT (w
->left
);
326 register int width
= XINT (w
->width
);
327 register int window_height
= XINT (w
->height
);
328 register int top
= XFASTINT (w
->top
);
330 if ( *x
< left
|| *x
>= left
+ width
331 || *y
< top
|| *y
>= top
+ window_height
)
334 /* Is the character is the mode line? */
335 if (*y
== top
+ window_height
- 1
336 && window_height
> 1) /* 1 line => minibuffer */
339 /* Is the character in the right border? */
340 if (*x
== left
+ width
- 1
341 && left
+ width
!= SCREEN_WIDTH (XSCREEN (w
->screen
)))
349 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
350 Scoordinates_in_window_p
, 2, 2, 0,
351 "Return non-nil if COORDINATES are in WINDOW.\n\
352 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
353 measured in characters from the upper-left corner of the screen.\n\
354 (0 . 0) denotes the character in the upper left corner of the\n\
356 If COORDINATES are in the text portion of WINDOW,\n\
357 the coordinates relative to the window are returned.\n\
358 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
359 If they are on the border between WINDOW and its right sibling,\n\
360 `vertical-line' is returned.")
361 (coordinates
, window
)
362 register Lisp_Object coordinates
, window
;
366 CHECK_WINDOW (window
, 0);
367 CHECK_CONS (coordinates
, 1);
368 x
= XINT (Fcar (coordinates
));
369 y
= XINT (Fcdr (coordinates
));
371 switch (coordinates_in_window (XWINDOW (window
), &x
, &y
))
373 case 0: /* NOT in window at all. */
376 case 1: /* In text part of window. */
379 case 2: /* In mode line of window. */
382 case 3: /* On right border of window. */
383 return Qvertical_line
;
390 /* Find the window containing column x, row y, and return it as a
391 Lisp_Object. If x, y is on the window's modeline, set *part
392 to 1; if it is on the separating line between the window and its
393 right sibling, set it to 2; otherwise set it to 0. If there is no
394 window under x, y return nil and leave *part unmodified. */
396 window_from_coordinates (screen
, x
, y
, part
)
401 register Lisp_Object tem
, first
;
403 tem
= first
= SCREEN_SELECTED_WINDOW (screen
);
407 int found
= coordinates_in_window (XWINDOW (tem
), &x
, &y
);
415 tem
= Fnext_window (tem
, Qt
, Qlambda
);
417 while (! EQ (tem
, first
));
422 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
423 "Return window containing row ROW, column COLUMN on SCREEN.\n\
424 If omitted, SCREEN defaults to the currently selected screen.\n\
425 The top left corner of the screen is considered to be row 0,\n\
427 (row
, column
, screen
)
428 Lisp_Object row
, column
, screen
;
433 XSET (screen
, Lisp_Screen
, selected_screen
);
435 CHECK_LIVE_SCREEN (screen
, 2);
436 CHECK_NUMBER (row
, 0);
437 CHECK_NUMBER (column
, 1);
439 return window_from_coordinates (XSCREEN (screen
),
440 XINT (row
), XINT (column
),
444 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
445 "Return current value of point in WINDOW.\n\
446 For a nonselected window, this is the value point would have\n\
447 if that window were selected.\n\
449 Note that, when WINDOW is the selected window and its buffer\n\
450 is also currently selected, the value returned is the same as (point).\n\
451 It would be more strictly correct to return the `top-level' value\n\
452 of point, outside of any save-excursion forms.\n\
453 But that is hard to define.")
457 register struct window
*w
= decode_window (window
);
459 if (w
== XWINDOW (selected_window
)
460 && current_buffer
== XBUFFER (w
->buffer
))
462 return Fmarker_position (w
->pointm
);
465 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
466 "Return position at which display currently starts in WINDOW.")
470 return Fmarker_position (decode_window (window
)->start
);
473 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 1, 0,
474 "Return position at which display currently ends in WINDOW.")
479 struct window
*w
= decode_window (window
);
481 XSET (value
, Lisp_Int
,
482 BUF_Z (current_buffer
) - XFASTINT (w
->window_end_pos
));
487 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
488 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
490 Lisp_Object window
, pos
;
492 register struct window
*w
= decode_window (window
);
494 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
495 if (w
== XWINDOW (selected_window
))
498 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
503 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
504 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
505 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
506 from overriding motion of point in order to display at this exact start.")
507 (window
, pos
, noforce
)
508 Lisp_Object window
, pos
, noforce
;
510 register struct window
*w
= decode_window (window
);
512 CHECK_NUMBER_COERCE_MARKER (pos
, 1);
513 set_marker_restricted (w
->start
, pos
, w
->buffer
);
514 /* this is not right, but much easier than doing what is right. */
515 w
->start_at_line_beg
= Qnil
;
518 w
->update_mode_line
= Qt
;
519 XFASTINT (w
->last_modified
) = 0;
520 if (!EQ (window
, selected_window
))
521 windows_or_buffers_changed
++;
525 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
527 "Return WINDOW's dedicated object, usually t or nil.\n\
528 See also `set-window-buffer-dedicated'.")
532 return decode_window (window
)->dedicated
;
535 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
536 Sset_window_dedicated_p
, 2, 2, 0,
537 "Control whether WINDOW is dedicated to the buffer it displays.\n\
538 If it is dedicated, Emacs will not automatically change\n\
539 which buffer appears in it.\n\
540 The second argument is the new value for the dedication flag;\n\
543 Lisp_Object window
, arg
;
545 register struct window
*w
= decode_window (window
);
555 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
557 "Return the display-table that WINDOW is using.")
561 return decode_window (window
)->display_table
;
564 /* Get the display table for use currently on window W.
565 This is either W's display table or W's buffer's display table.
566 Ignore the specified tables if they are not valid;
567 if no valid table is specified, return 0. */
570 window_display_table (w
)
574 tem
= w
->display_table
;
575 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
576 return XVECTOR (tem
);
577 tem
= XBUFFER (w
->buffer
)->display_table
;
578 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
579 return XVECTOR (tem
);
580 tem
= Vstandard_display_table
;
581 if (XTYPE (tem
) == Lisp_Vector
&& XVECTOR (tem
)->size
== DISP_TABLE_SIZE
)
582 return XVECTOR (tem
);
586 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
587 "Set WINDOW's display-table to TABLE.")
589 register Lisp_Object window
, table
;
591 register struct window
*w
;
592 register Lisp_Object z
; /* Return value. */
594 w
= decode_window (window
);
595 w
->display_table
= table
;
599 /* Record info on buffer window w is displaying
600 when it is about to cease to display that buffer. */
603 register struct window
*w
;
605 Lisp_Object buf
= w
->buffer
;
607 if (XBUFFER (buf
) != XMARKER (w
->pointm
)->buffer
)
610 if (w
== XWINDOW (selected_window
)
611 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
612 /* Do this except when the selected window's buffer
613 is being removed from some other window. */
614 XBUFFER (buf
)->last_window_start
= marker_position (w
->start
);
616 /* Point in the selected window's buffer
617 is actually stored in that buffer, and the window's pointm isn't used.
618 So don't clobber point in that buffer. */
619 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
))
620 BUF_PT (XBUFFER (buf
))
621 = clip_to_bounds (BUF_BEGV (XBUFFER (buf
)),
622 marker_position (w
->pointm
),
623 BUF_ZV (XBUFFER (buf
)));
626 /* Put replacement into the window structure in place of old. */
628 replace_window (old
, replacement
)
629 Lisp_Object old
, replacement
;
631 register Lisp_Object tem
;
632 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
634 /* If OLD is its screen's root_window, then replacement is the new
635 root_window for that screen. */
637 if (old
== SCREEN_ROOT_WINDOW (XSCREEN (o
->screen
)))
638 SCREEN_ROOT_WINDOW (XSCREEN (o
->screen
)) = replacement
;
643 p
->height
= o
->height
;
645 p
->next
= tem
= o
->next
;
647 XWINDOW (tem
)->prev
= replacement
;
649 p
->prev
= tem
= o
->prev
;
651 XWINDOW (tem
)->next
= replacement
;
653 p
->parent
= tem
= o
->parent
;
656 if (EQ (XWINDOW (tem
)->vchild
, old
))
657 XWINDOW (tem
)->vchild
= replacement
;
658 if (EQ (XWINDOW (tem
)->hchild
, old
))
659 XWINDOW (tem
)->hchild
= replacement
;
662 /*** Here, if replacement is a vertical combination
663 and so is its new parent, we should make replacement's
664 children be children of that parent instead. ***/
667 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
668 "Remove WINDOW from the display. Default is selected window.")
670 register Lisp_Object window
;
672 register Lisp_Object tem
, parent
, sib
;
673 register struct window
*p
;
674 register struct window
*par
;
677 window
= selected_window
;
679 CHECK_WINDOW (window
, 0);
681 p
= XWINDOW (window
);
684 error ("Attempt to delete minibuffer or sole ordinary window");
685 par
= XWINDOW (parent
);
687 windows_or_buffers_changed
++;
689 if (EQ (window
, selected_window
))
690 Fselect_window (Fnext_window (window
, Qnil
, Qnil
));
693 /* tem is null for dummy parent windows
694 (which have inferiors but not any contents themselves) */
698 unchain_marker (p
->pointm
);
699 unchain_marker (p
->start
);
705 XWINDOW (tem
)->prev
= p
->prev
;
709 XWINDOW (tem
)->next
= p
->next
;
711 if (EQ (window
, par
->hchild
))
712 par
->hchild
= p
->next
;
713 if (EQ (window
, par
->vchild
))
714 par
->vchild
= p
->next
;
716 /* Find one of our siblings to give our space to. */
720 /* If p gives its space to its next sibling, that sibling needs
721 to have its top/left side pulled back to where p's is.
722 set_window_{height,width} will re-position the sibling's
725 XFASTINT (XWINDOW (sib
)->top
) = p
->top
;
726 XFASTINT (XWINDOW (sib
)->left
) = p
->left
;
729 /* Stretch that sibling. */
730 if (!NILP (par
->vchild
))
731 set_window_height (sib
,
732 XFASTINT (XWINDOW (sib
)->height
) + XFASTINT (p
->height
),
734 if (!NILP (par
->hchild
))
735 set_window_width (sib
,
736 XFASTINT (XWINDOW (sib
)->width
) + XFASTINT (p
->width
),
739 /* If parent now has only one child,
740 put the child into the parent's place. */
745 if (NILP (XWINDOW (tem
)->next
))
746 replace_window (parent
, tem
);
751 extern Lisp_Object
next_screen (), prev_screen ();
753 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
754 "Return next window after WINDOW in canonical ordering of windows.\n\
755 If omitted, WINDOW defaults to the selected window.\n\
757 Optional second arg MINIBUF t means count the minibuffer window even\n\
758 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
759 it is active. MINIBUF neither t nor nil means not to count the\n\
760 minibuffer even if it is active.\n\
762 Several screens may share a single minibuffer; if the minibuffer\n\
763 counts, all windows on all screens that share that minibuffer count\n\
764 too. This means that next-window may be used to iterate through the\n\
765 set of windows even when the minibuffer is on another screen. If the\n\
766 minibuffer does not count, only windows from WINDOW's screen count.\n\
768 Optional third arg ALL-SCREENS t means include windows on all screens.\n\
769 ALL-SCREENS nil or omitted means cycle within the screens as specified\n\
770 above. If neither nil nor t, restrict to WINDOW's screen.")
771 (window
, minibuf
, all_screens
)
772 register Lisp_Object window
, minibuf
, all_screens
;
774 register Lisp_Object tem
;
775 Lisp_Object start_window
;
778 window
= selected_window
;
780 CHECK_WINDOW (window
, 0);
782 start_window
= window
;
784 /* minibuf == nil may or may not include minibuffers.
785 Decide if it does. */
787 minibuf
= (minibuf_level
? Qt
: Qlambda
);
789 /* all_screens == nil doesn't specify which screens to include.
790 Decide which screens it includes. */
791 if (NILP (all_screens
))
792 all_screens
= (EQ (minibuf
, Qt
)
793 ? (SCREEN_MINIBUF_WINDOW
796 (XWINDOW (window
)))))
798 else if (! EQ (all_screens
, Qt
))
801 /* Do this loop at least once, to get the next window, and perhaps
802 again, if we hit the minibuffer and that is not acceptable. */
805 /* Find a window that actually has a next one. This loop
806 climbs up the tree. */
807 while (tem
= XWINDOW (window
)->next
, NILP (tem
))
808 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
812 /* We've reached the end of this screen.
813 Which other screens are acceptable? */
814 tem
= WINDOW_SCREEN (XWINDOW (window
));
816 if (! NILP (all_screens
))
817 tem
= next_screen (tem
, all_screens
);
819 tem
= SCREEN_ROOT_WINDOW (XSCREEN (tem
));
826 /* If we're in a combination window, find its first child and
827 recurse on that. Otherwise, we've found the window we want. */
830 if (!NILP (XWINDOW (window
)->hchild
))
831 window
= XWINDOW (window
)->hchild
;
832 else if (!NILP (XWINDOW (window
)->vchild
))
833 window
= XWINDOW (window
)->vchild
;
837 /* Which windows are acceptible?
838 Exit the loop and accept this window if
839 this isn't a minibuffer window, or
840 we're accepting minibuffer windows, or
841 we've come all the way around and we're back at the original window. */
842 while (MINI_WINDOW_P (XWINDOW (window
))
843 && ! EQ (minibuf
, Qt
)
844 && window
!= start_window
);
849 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
850 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
851 If omitted, WINDOW defaults to the selected window.\n\
853 Optional second arg MINIBUF t means count the minibuffer window even\n\
854 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
855 it is active. MINIBUF neither t nor nil means not to count the\n\
856 minibuffer even if it is active.\n\
858 Several screens may share a single minibuffer; if the minibuffer\n\
859 counts, all windows on all screens that share that minibuffer count\n\
860 too. This means that previous-window may be used to iterate through\n\
861 the set of windows even when the minibuffer is on another screen. If\n\
862 the minibuffer does not count, only windows from WINDOW's screen\n\
865 Optional third arg ALL-SCREENS t means include windows on all screens.\n\
866 ALL-SCREENS nil or omitted means cycle within the screens as specified\n\
867 above. If neither nil nor t, restrict to WINDOW's screen.")
868 (window
, minibuf
, all_screens
)
869 register Lisp_Object window
, minibuf
, all_screens
;
871 register Lisp_Object tem
;
872 Lisp_Object start_window
;
875 window
= selected_window
;
877 CHECK_WINDOW (window
, 0);
879 start_window
= window
;
881 /* minibuf == nil may or may not include minibuffers.
882 Decide if it does. */
884 minibuf
= (minibuf_level
? Qt
: Qlambda
);
886 /* all_screens == nil doesn't specify which screens to include.
887 Decide which screens it includes. */
888 if (NILP (all_screens
))
889 all_screens
= (EQ (minibuf
, Qt
)
890 ? (SCREEN_MINIBUF_WINDOW
893 (XWINDOW (window
)))))
895 else if (! EQ (all_screens
, Qt
))
898 /* Do this loop at least once, to get the previous window, and perhaps
899 again, if we hit the minibuffer and that is not acceptable. */
902 /* Find a window that actually has a previous one. This loop
903 climbs up the tree. */
904 while (tem
= XWINDOW (window
)->prev
, NILP (tem
))
905 if (tem
= XWINDOW (window
)->parent
, !NILP (tem
))
909 /* We have found the top window on the screen.
910 Which screens are acceptable? */
911 tem
= WINDOW_SCREEN (XWINDOW (window
));
913 if (! NILP (all_screens
))
914 tem
= next_screen (tem
, all_screens
);
916 tem
= SCREEN_ROOT_WINDOW (XSCREEN (tem
));
922 /* If we're in a combination window, find its last child and
923 recurse on that. Otherwise, we've found the window we want. */
926 if (!NILP (XWINDOW (window
)->hchild
))
927 window
= XWINDOW (window
)->hchild
;
928 else if (!NILP (XWINDOW (window
)->vchild
))
929 window
= XWINDOW (window
)->vchild
;
931 while (tem
= XWINDOW (window
)->next
, !NILP (tem
))
935 /* Which windows are acceptable?
936 Exit the loop and accept this window if
937 this isn't a minibuffer window, or
938 we're accepting minibuffer windows, or
939 we've come all the way around and we're back at the original window. */
940 while (MINI_WINDOW_P (XWINDOW (window
))
942 && window
!= start_window
);
947 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
948 "Select the ARG'th different window on this screen.\n\
949 All windows on current screen are arranged in a cyclic order.\n\
950 This command selects the window ARG steps away in that order.\n\
951 A negative ARG moves in the opposite order. If the optional second\n\
952 argument ALL_SCREENS is non-nil, cycle through all screens.")
954 register Lisp_Object n
, all_screens
;
957 register Lisp_Object w
;
965 w
= Fnext_window (w
, Qnil
, all_screens
);
970 w
= Fprevious_window (w
, Qnil
, all_screens
);
977 /* Look at all windows, performing an operation specified by TYPE
979 If SCREENS is Qt, look at all screens, if Qnil, look at just the selected
980 screen. If SCREENS is a screen, just look at windows on that screen.
981 If MINI is non-zero, perform the operation on minibuffer windows too.
987 GET_BUFFER_WINDOW
, /* Arg is buffer */
988 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
989 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
990 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
992 UNSHOW_BUFFER
, /* Arg is buffer */
996 window_loop (type
, obj
, mini
, screens
)
997 enum window_loop type
;
998 register Lisp_Object obj
, screens
;
1001 register Lisp_Object w
;
1002 register Lisp_Object best_window
;
1003 register Lisp_Object next_window
;
1004 register Lisp_Object first_window
;
1007 /* If we're only looping through windows on a particular screen,
1008 screen points to that screen. If we're looping through windows
1009 on all screens, screen is 0. */
1010 if (SCREENP (screens
))
1011 screen
= XSCREEN (screens
);
1012 else if (NILP (screens
))
1013 screen
= selected_screen
;
1017 /* Pick a window to start with. */
1018 if (XTYPE (obj
) == Lisp_Window
)
1021 first_window
= SCREEN_SELECTED_WINDOW (screen
);
1023 first_window
= SCREEN_SELECTED_WINDOW (selected_screen
);
1029 /* Pick the next window now, since some operations will delete
1030 the current window. */
1033 next_window
= Fnext_window (w
, (mini
? Qt
: Qnil
), Qlambda
);
1035 #endif /* MULTI_SCREEN */
1036 /* We know screen is 0, so we're looping through all screens.
1037 Or we know this isn't a MULTI_SCREEN Emacs, so who cares? */
1038 next_window
= Fnext_window (w
, mini
? Qt
: Qnil
, Qt
);
1040 if (!MINI_WINDOW_P (XWINDOW (w
))
1041 || (mini
&& minibuf_level
> 0))
1044 case GET_BUFFER_WINDOW
:
1046 /* Ignore invisible and iconified screens. */
1047 if (! SCREEN_VISIBLE_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
))))
1048 || SCREEN_ICONIFIED_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
)))))
1051 if (XBUFFER (XWINDOW (w
)->buffer
) == XBUFFER (obj
))
1055 case GET_LRU_WINDOW
:
1056 /* t as arg means consider only full-width windows */
1057 if (!NILP (obj
) && XFASTINT (XWINDOW (w
)->width
)
1058 != SCREEN_WIDTH (screen
))
1061 /* Ignore invisible and iconified screens. */
1062 if (! SCREEN_VISIBLE_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
))))
1063 || SCREEN_ICONIFIED_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
)))))
1066 /* Ignore dedicated windows and minibuffers. */
1067 if (MINI_WINDOW_P (XWINDOW (w
))
1068 || !NILP (XWINDOW (w
)->dedicated
))
1070 if (NILP (best_window
)
1071 || (XFASTINT (XWINDOW (best_window
)->use_time
)
1072 > XFASTINT (XWINDOW (w
)->use_time
)))
1076 case DELETE_OTHER_WINDOWS
:
1077 if (XWINDOW (w
) != XWINDOW (obj
))
1081 case DELETE_BUFFER_WINDOWS
:
1082 if (EQ (XWINDOW (w
)->buffer
, obj
))
1084 /* If we're deleting the buffer displayed in the only window
1085 on the screen, find a new buffer to display there. */
1086 if (NILP (XWINDOW (w
)->parent
))
1088 Lisp_Object new_buffer
= Fother_buffer (obj
);
1089 if (NILP (new_buffer
))
1091 = Fget_buffer_create (build_string ("*scratch*"));
1092 Fset_window_buffer (w
, new_buffer
);
1093 Fset_buffer (XWINDOW (w
)->buffer
);
1100 case GET_LARGEST_WINDOW
:
1102 /* Ignore invisible and iconified screens. */
1103 if (! SCREEN_VISIBLE_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
))))
1104 || SCREEN_ICONIFIED_P (XSCREEN (WINDOW_SCREEN (XWINDOW (w
)))))
1107 /* Ignore dedicated windows and minibuffers. */
1108 if (MINI_WINDOW_P (XWINDOW (w
))
1109 || !NILP (XWINDOW (w
)->dedicated
))
1112 struct window
*best_window_ptr
= XWINDOW (best_window
);
1113 struct window
*w_ptr
= XWINDOW (w
);
1114 if (NILP (best_window
) ||
1115 (XFASTINT (w_ptr
->height
) * XFASTINT (w_ptr
->width
))
1116 > (XFASTINT (best_window_ptr
->height
)
1117 * XFASTINT (best_window_ptr
->width
)))
1123 if (EQ (XWINDOW (w
)->buffer
, obj
))
1125 /* Find another buffer to show in this window. */
1126 Lisp_Object another_buffer
= Fother_buffer (obj
);
1127 if (NILP (another_buffer
))
1129 = Fget_buffer_create (build_string ("*scratch*"));
1130 Fset_window_buffer (w
, another_buffer
);
1131 if (EQ (w
, selected_window
))
1132 Fset_buffer (XWINDOW (w
)->buffer
);
1138 while (! EQ (w
, first_window
));
1143 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 1, 0,
1144 "Return the window least recently selected or used for display.\n\
1145 If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1146 screen, search only that screen.\n")
1148 Lisp_Object screens
;
1150 register Lisp_Object w
;
1151 /* First try for a window that is full-width */
1152 w
= window_loop (GET_LRU_WINDOW
, Qt
, 0, screens
);
1153 if (!NILP (w
) && !EQ (w
, selected_window
))
1155 /* If none of them, try the rest */
1156 return window_loop (GET_LRU_WINDOW
, Qnil
, 0, screens
);
1159 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 1, 0,
1160 "Return the largest window in area.\n\
1161 If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1162 screen, search only that screen.\n")
1166 return window_loop (GET_LARGEST_WINDOW
, Qnil
, 0,
1170 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 1, 2, 0,
1171 "Return a window currently displaying BUFFER, or nil if none.\n\
1172 If optional argument SCREENS is t, search all screens. If SCREEN is a\n\
1173 screen, search only that screen.\n")
1175 Lisp_Object buffer
, screen
;
1177 buffer
= Fget_buffer (buffer
);
1178 if (XTYPE (buffer
) == Lisp_Buffer
)
1179 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, screen
);
1184 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
1186 "Make WINDOW (or the selected window) fill its screen.\n\
1187 Only the screen WINDOW is on is affected.")
1193 struct buffer
*obuf
= current_buffer
;
1197 window
= selected_window
;
1199 CHECK_WINDOW (window
, 0);
1201 w
= XWINDOW (window
);
1202 top
= XFASTINT (w
->top
);
1204 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_SCREEN(w
));
1206 Fset_buffer (w
->buffer
);
1207 SET_PT (marker_position (w
->start
));
1208 Frecenter (make_number (top
));
1210 set_buffer_internal (obuf
);
1215 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
1216 1, 1, "bDelete windows on (buffer): ",
1217 "Delete all windows showing BUFFER.")
1223 buffer
= Fget_buffer (buffer
);
1224 CHECK_BUFFER (buffer
, 0);
1225 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, Qt
);
1230 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
1231 Sreplace_buffer_in_windows
,
1232 1, 1, "bReplace buffer in windows: ",
1233 "Replace BUFFER with some other buffer in all windows showing it.")
1239 buffer
= Fget_buffer (buffer
);
1240 CHECK_BUFFER (buffer
, 0);
1241 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
1246 /* Set the height of WINDOW and all its inferiors. */
1247 /* Normally the window is deleted if it gets too small.
1248 nodelete nonzero means do not do this.
1249 (The caller should check later and do so if appropriate) */
1251 set_window_height (window
, height
, nodelete
)
1256 register struct window
*w
= XWINDOW (window
);
1257 register struct window
*c
;
1258 int oheight
= XFASTINT (w
->height
);
1259 int top
, pos
, lastbot
, opos
, lastobot
;
1263 && ! NILP (w
->parent
)
1264 && height
< window_min_height
)
1266 Fdelete_window (window
);
1270 XFASTINT (w
->last_modified
) = 0;
1271 windows_or_buffers_changed
++;
1272 XFASTINT (w
->height
) = height
;
1273 if (!NILP (w
->hchild
))
1275 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1277 XWINDOW (child
)->top
= w
->top
;
1278 set_window_height (child
, height
, nodelete
);
1281 else if (!NILP (w
->vchild
))
1283 lastbot
= top
= XFASTINT (w
->top
);
1285 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
1287 c
= XWINDOW (child
);
1289 opos
= lastobot
+ XFASTINT (c
->height
);
1291 XFASTINT (c
->top
) = lastbot
;
1293 pos
= (((opos
* height
) << 1) + oheight
) / (oheight
<< 1);
1295 /* Avoid confusion: inhibit deletion of child if becomes too small */
1296 set_window_height (child
, pos
+ top
- lastbot
, 1);
1298 /* Now advance child to next window,
1299 and set lastbot if child was not just deleted. */
1300 lastbot
= pos
+ top
;
1303 /* Now delete any children that became too small. */
1305 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1307 set_window_height (child
, XINT (XWINDOW (child
)->height
), 0);
1312 /* Recursively set width of WINDOW and its inferiors. */
1314 set_window_width (window
, width
, nodelete
)
1319 register struct window
*w
= XWINDOW (window
);
1320 register struct window
*c
;
1321 int owidth
= XFASTINT (w
->width
);
1322 int left
, pos
, lastright
, opos
, lastoright
;
1325 if (!nodelete
&& width
< window_min_width
)
1327 Fdelete_window (window
);
1331 XFASTINT (w
->last_modified
) = 0;
1332 windows_or_buffers_changed
++;
1333 XFASTINT (w
->width
) = width
;
1334 if (!NILP (w
->vchild
))
1336 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1338 XWINDOW (child
)->left
= w
->left
;
1339 set_window_width (child
, width
, nodelete
);
1342 else if (!NILP (w
->hchild
))
1344 lastright
= left
= XFASTINT (w
->left
);
1346 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
1348 c
= XWINDOW (child
);
1350 opos
= lastoright
+ XFASTINT (c
->width
);
1352 XFASTINT (c
->left
) = lastright
;
1354 pos
= (((opos
* width
) << 1) + owidth
) / (owidth
<< 1);
1356 /* Inhibit deletion for becoming too small */
1357 set_window_width (child
, pos
+ left
- lastright
, 1);
1359 /* Now advance child to next window,
1360 and set lastright if child was not just deleted. */
1361 lastright
= pos
+ left
, lastoright
= opos
;
1363 /* Delete children that became too small */
1365 for (child
= w
->hchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
1367 set_window_width (child
, XINT (XWINDOW (child
)->width
), 0);
1372 int window_select_count
;
1374 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 2, 0,
1375 "Make WINDOW display BUFFER as its contents.\n\
1376 BUFFER can be a buffer or buffer name.")
1378 register Lisp_Object window
, buffer
;
1380 register Lisp_Object tem
;
1381 register struct window
*w
= decode_window (window
);
1383 buffer
= Fget_buffer (buffer
);
1384 CHECK_BUFFER (buffer
, 1);
1386 if (NILP (XBUFFER (buffer
)->name
))
1387 error ("Attempt to display deleted buffer");
1391 error ("Window is deleted");
1392 else if (! EQ (tem
, Qt
)) /* w->buffer is t when the window
1393 is first being set up. */
1395 if (!NILP (w
->dedicated
) && !EQ (tem
, buffer
))
1396 error ("Window is dedicated to %s\n", tem
);
1402 Fset_marker (w
->pointm
,
1403 make_number (BUF_PT (XBUFFER (buffer
))),
1405 set_marker_restricted (w
->start
,
1406 make_number (XBUFFER (buffer
)->last_window_start
),
1408 w
->start_at_line_beg
= Qnil
;
1409 XFASTINT (w
->last_modified
) = 0;
1410 windows_or_buffers_changed
++;
1411 if (EQ (window
, selected_window
))
1412 Fset_buffer (buffer
);
1417 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 1, 0,
1418 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1419 The main editor command loop selects the buffer of the selected window\n\
1420 before each command.")
1422 register Lisp_Object window
;
1424 register struct window
*w
;
1425 register struct window
*ow
= XWINDOW (selected_window
);
1427 CHECK_WINDOW (window
, 0);
1429 w
= XWINDOW (window
);
1431 if (NILP (w
->buffer
))
1432 error ("Trying to select deleted window or non-leaf window");
1434 XFASTINT (w
->use_time
) = ++window_select_count
;
1435 if (EQ (window
, selected_window
))
1438 Fset_marker (ow
->pointm
, make_number (BUF_PT (XBUFFER (ow
->buffer
))),
1441 selected_window
= window
;
1443 if (XSCREEN (WINDOW_SCREEN (w
)) != selected_screen
)
1445 XSCREEN (WINDOW_SCREEN (w
))->selected_window
= window
;
1446 Fselect_screen (WINDOW_SCREEN (w
), Qnil
);
1449 selected_screen
->selected_window
= window
;
1452 record_buffer (w
->buffer
);
1453 Fset_buffer (w
->buffer
);
1455 /* Go to the point recorded in the window.
1456 This is important when the buffer is in more
1457 than one window. It also matters when
1458 redisplay_window has altered point after scrolling,
1459 because it makes the change only in the window. */
1461 register int new_point
= marker_position (w
->pointm
);
1462 if (new_point
< BEGV
)
1470 windows_or_buffers_changed
++;
1474 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 2,
1475 "BDisplay buffer:\nP",
1476 "Make BUFFER appear in some window but don't select it.\n\
1477 BUFFER can be a buffer or a buffer name.\n\
1478 If BUFFER is shown already in some window, just use that one,\n\
1479 unless the window is the selected window and the optional second\n\
1480 argument NOT_THIS_WINDOW is non-nil.\n\
1481 Returns the window displaying BUFFER.")
1482 (buffer
, not_this_window
)
1483 register Lisp_Object buffer
, not_this_window
;
1485 register Lisp_Object window
;
1487 buffer
= Fget_buffer (buffer
);
1488 CHECK_BUFFER (buffer
, 0);
1490 if (!NILP (Vdisplay_buffer_function
))
1491 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
1493 if (NILP (not_this_window
)
1494 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
1495 return selected_window
;
1497 window
= Fget_buffer_window (buffer
, Qnil
);
1499 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
1503 /* If there are no screens open that have more than a minibuffer,
1504 we need to create a new screen. */
1505 if (pop_up_screens
|| last_nonminibuf_screen
== 0)
1508 = Fscreen_selected_window (call0 (Vpop_up_screen_function
));
1509 Fset_window_buffer (window
, buffer
);
1511 Fselect_screen (XWINDOW (window
)->screen
, Qnil
);
1515 #endif /* MULTI_SCREEN */
1519 || SCREEN_MINIBUF_ONLY_P (selected_screen
)
1523 Lisp_Object screens
= Qnil
;
1526 if (SCREEN_MINIBUF_ONLY_P (selected_screen
))
1527 XSET (screens
, Lisp_Screen
, last_nonminibuf_screen
);
1529 /* Don't try to create a window if would get an error */
1530 if (split_height_threshold
< window_min_height
<< 1)
1531 split_height_threshold
= window_min_height
<< 1;
1533 window
= Fget_largest_window (screens
);
1536 && window_height (window
) >= split_height_threshold
1538 (XFASTINT (XWINDOW (window
)->width
)
1539 == SCREEN_WIDTH (XSCREEN (WINDOW_SCREEN (XWINDOW (window
))))))
1540 window
= Fsplit_window (window
, Qnil
, Qnil
);
1543 window
= Fget_lru_window (screens
);
1544 if ((EQ (window
, selected_window
)
1545 || EQ (XWINDOW (window
)->parent
, Qnil
))
1546 && window_height (window
) >= window_min_height
<< 1)
1547 window
= Fsplit_window (window
, Qnil
, Qnil
);
1551 window
= Fget_lru_window (Qnil
);
1553 Fset_window_buffer (window
, buffer
);
1558 temp_output_buffer_show (buf
)
1559 register Lisp_Object buf
;
1561 register struct buffer
*old
= current_buffer
;
1562 register Lisp_Object window
;
1563 register struct window
*w
;
1566 XBUFFER (buf
)->save_modified
= MODIFF
;
1571 set_buffer_internal (old
);
1573 if (!EQ (Vtemp_buffer_show_function
, Qnil
))
1574 call1 (Vtemp_buffer_show_function
, buf
);
1577 window
= Fdisplay_buffer (buf
, Qnil
);
1580 if (XSCREEN (XWINDOW (window
)->screen
) != selected_screen
)
1581 Fmake_screen_visible (XWINDOW (window
)->screen
);
1582 #endif /* MULTI_SCREEN */
1583 Vminibuf_scroll_window
= window
;
1584 w
= XWINDOW (window
);
1585 XFASTINT (w
->hscroll
) = 0;
1586 set_marker_restricted (w
->start
, make_number (1), buf
);
1587 set_marker_restricted (w
->pointm
, make_number (1), buf
);
1592 make_dummy_parent (window
)
1595 register Lisp_Object old
, new;
1596 register struct window
*o
, *p
;
1599 XSETTYPE (old
, Lisp_Vector
);
1600 new = Fcopy_sequence (old
);
1601 XSETTYPE (new, Lisp_Window
);
1605 XFASTINT (p
->sequence_number
) = ++sequence_number
;
1607 /* Put new into window structure in place of window */
1608 replace_window (window
, new);
1621 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
1622 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
1623 WINDOW defaults to selected one and SIZE to half its size.\n\
1624 If optional third arg HOR-FLAG is non-nil, split side by side\n\
1625 and put SIZE columns in the first of the pair.")
1626 (window
, chsize
, horflag
)
1627 Lisp_Object window
, chsize
, horflag
;
1629 register Lisp_Object
new;
1630 register struct window
*o
, *p
;
1634 window
= selected_window
;
1636 CHECK_WINDOW (window
, 0);
1638 o
= XWINDOW (window
);
1642 if (!NILP (horflag
))
1643 /* Round odd size up, since this is for the left-hand window,
1644 and it will lose a column for the separators. */
1645 size
= ((XFASTINT (o
->width
) + 1) & -2) >> 1;
1647 size
= XFASTINT (o
->height
) >> 1;
1651 CHECK_NUMBER (chsize
, 1);
1652 size
= XINT (chsize
);
1655 if (MINI_WINDOW_P (o
))
1656 error ("Attempt to split minibuffer window");
1657 else if (SCREEN_NO_SPLIT_P (XSCREEN (WINDOW_SCREEN (o
))))
1658 error ("Attempt to split unsplittable screen");
1660 /* Smaller values might permit a crash. */
1661 if (window_min_width
< 2)
1662 window_min_width
= 2;
1663 if (window_min_height
< 2)
1664 window_min_height
= 2;
1668 if (size
< window_min_height
1669 || size
+ window_min_height
> XFASTINT (o
->height
))
1670 args_out_of_range_3 (window
, chsize
, horflag
);
1671 if (NILP (o
->parent
)
1672 || NILP (XWINDOW (o
->parent
)->vchild
))
1674 make_dummy_parent (window
);
1676 XWINDOW (new)->vchild
= window
;
1681 if (size
< window_min_width
1682 || size
+ window_min_width
> XFASTINT (o
->width
))
1683 args_out_of_range_3 (window
, chsize
, horflag
);
1684 if (NILP (o
->parent
)
1685 || NILP (XWINDOW (o
->parent
)->hchild
))
1687 make_dummy_parent (window
);
1689 XWINDOW (new)->hchild
= window
;
1693 /* Now we know that window's parent is a vertical combination
1694 if we are dividing vertically, or a horizontal combination
1695 if we are making side-by-side windows */
1697 windows_or_buffers_changed
++;
1698 new = make_window ();
1701 p
->screen
= o
->screen
;
1703 if (!NILP (p
->next
))
1704 XWINDOW (p
->next
)->prev
= new;
1707 p
->parent
= o
->parent
;
1710 Fset_window_buffer (new, o
->buffer
);
1712 /* Apportion the available screen space among the two new windows */
1714 if (!NILP (horflag
))
1716 p
->height
= o
->height
;
1718 XFASTINT (p
->width
) = XFASTINT (o
->width
) - size
;
1719 XFASTINT (o
->width
) = size
;
1720 XFASTINT (p
->left
) = XFASTINT (o
->left
) + size
;
1725 p
->width
= o
->width
;
1726 XFASTINT (p
->height
) = XFASTINT (o
->height
) - size
;
1727 XFASTINT (o
->height
) = size
;
1728 XFASTINT (p
->top
) = XFASTINT (o
->top
) + size
;
1734 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
1735 "Make current window ARG lines bigger.\n\
1736 From program, optional second arg non-nil means grow sideways ARG columns.")
1738 register Lisp_Object n
, side
;
1740 CHECK_NUMBER (n
, 0);
1741 change_window_height (XINT (n
), !NILP (side
));
1745 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
1746 "Make current window ARG lines smaller.\n\
1747 From program, optional second arg non-nil means shrink sideways ARG columns.")
1749 register Lisp_Object n
, side
;
1751 CHECK_NUMBER (n
, 0);
1752 change_window_height (-XINT (n
), !NILP (side
));
1757 window_height (window
)
1760 register struct window
*p
= XWINDOW (window
);
1761 return XFASTINT (p
->height
);
1765 window_width (window
)
1768 register struct window
*p
= XWINDOW (window
);
1769 return XFASTINT (p
->width
);
1772 #define MINSIZE(w) \
1773 (widthflag ? window_min_width : window_min_height)
1776 *(widthflag ? (int *) &(w)->left : (int *) &(w)->top)
1778 #define CURSIZE(w) \
1779 *(widthflag ? (int *) &(w)->width : (int *) &(w)->height)
1781 /* Unlike set_window_height, this function
1782 also changes the heights of the siblings so as to
1783 keep everything consistent. */
1785 change_window_height (delta
, widthflag
)
1789 register Lisp_Object parent
;
1791 register struct window
*p
;
1793 int (*sizefun
) () = widthflag
? window_width
: window_height
;
1794 register int (*setsizefun
) () = (widthflag
1796 : set_window_height
);
1798 /* Smaller values might permit a crash. */
1799 if (window_min_width
< 2)
1800 window_min_width
= 2;
1801 if (window_min_height
< 2)
1802 window_min_height
= 2;
1804 window
= selected_window
;
1807 p
= XWINDOW (window
);
1812 error ("No other window to side of this one");
1815 if (widthflag
? !NILP (XWINDOW (parent
)->hchild
)
1816 : !NILP (XWINDOW (parent
)->vchild
))
1821 sizep
= &CURSIZE (p
);
1823 if (*sizep
+ delta
< MINSIZE (p
)
1824 && !NILP (XWINDOW (window
)->parent
))
1826 Fdelete_window (window
);
1831 register int maxdelta
;
1833 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - *sizep
1834 : !NILP (p
->next
) ? (*sizefun
) (p
->next
) - MINSIZE (p
->next
)
1835 : !NILP (p
->prev
) ? (*sizefun
) (p
->prev
) - MINSIZE (p
->prev
)
1836 /* This is a screen with only one window, a minibuffer-only
1837 or a minibufferless screen. */
1840 if (delta
> maxdelta
)
1841 /* This case traps trying to make the minibuffer
1842 the full screen, or make the only window aside from the
1843 minibuffer the full screen. */
1850 if (!NILP (p
->next
) &&
1851 (*sizefun
) (p
->next
) - delta
>= MINSIZE (p
->next
))
1853 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
) - delta
, 0);
1854 (*setsizefun
) (window
, *sizep
+ delta
, 0);
1855 CURBEG (XWINDOW (p
->next
)) += delta
;
1856 /* This does not change size of p->next,
1857 but it propagates the new top edge to its children */
1858 (*setsizefun
) (p
->next
, (*sizefun
) (p
->next
), 0);
1860 else if (!NILP (p
->prev
) &&
1861 (*sizefun
) (p
->prev
) - delta
>= MINSIZE (p
->prev
))
1863 (*setsizefun
) (p
->prev
, (*sizefun
) (p
->prev
) - delta
, 0);
1864 CURBEG (p
) -= delta
;
1865 (*setsizefun
) (window
, *sizep
+ delta
, 0);
1869 register int delta1
;
1870 register int opht
= (*sizefun
) (parent
);
1872 /* If trying to grow this window to or beyond size of the parent,
1873 make delta1 so big that, on shrinking back down,
1874 all the siblings end up with less than one line and are deleted. */
1875 if (opht
<= *sizep
+ delta
)
1876 delta1
= opht
* opht
* 2;
1877 /* Otherwise, make delta1 just right so that if we add delta1
1878 lines to this window and to the parent, and then shrink
1879 the parent back to its original size, the new proportional
1880 size of this window will increase by delta. */
1882 delta1
= (delta
* opht
* 100) / ((opht
- *sizep
- delta
) * 100);
1884 /* Add delta1 lines or columns to this window, and to the parent,
1885 keeping things consistent while not affecting siblings. */
1886 CURSIZE (XWINDOW (parent
)) = opht
+ delta1
;
1887 (*setsizefun
) (window
, *sizep
+ delta1
, 0);
1889 /* Squeeze out delta1 lines or columns from our parent,
1890 shriking this window and siblings proportionately.
1891 This brings parent back to correct size.
1892 Delta1 was calculated so this makes this window the desired size,
1893 taking it all out of the siblings. */
1894 (*setsizefun
) (parent
, opht
, 0);
1897 XFASTINT (p
->last_modified
) = 0;
1904 /* Return number of lines of text (not counting mode line) in W. */
1907 window_internal_height (w
)
1910 int ht
= XFASTINT (w
->height
);
1912 if (MINI_WINDOW_P (w
))
1915 if (!NILP (w
->parent
) || !NILP (w
->vchild
) || !NILP (w
->hchild
)
1916 || !NILP (w
->next
) || !NILP (w
->prev
)
1917 || SCREEN_WANTS_MODELINE_P (XSCREEN (WINDOW_SCREEN (w
))))
1923 /* Scroll contents of window WINDOW up N lines. */
1926 window_scroll (window
, n
, noerror
)
1931 register struct window
*w
= XWINDOW (window
);
1932 register int opoint
= point
;
1934 register int ht
= window_internal_height (w
);
1935 register Lisp_Object tem
;
1937 Lisp_Object bolp
, nmoved
;
1939 XFASTINT (tem
) = point
;
1940 tem
= Fpos_visible_in_window_p (tem
, window
);
1944 Fvertical_motion (make_number (- ht
/ 2));
1945 XFASTINT (tem
) = point
;
1946 Fset_marker (w
->start
, tem
, w
->buffer
);
1947 w
->force_start
= Qt
;
1950 SET_PT (marker_position (w
->start
));
1951 lose
= n
< 0 && point
== BEGV
;
1952 Fvertical_motion (make_number (n
));
1962 Fsignal (Qbeginning_of_buffer
, Qnil
);
1967 set_marker_restricted (w
->start
, make_number (pos
), w
->buffer
);
1968 w
->start_at_line_beg
= bolp
;
1969 w
->update_mode_line
= Qt
;
1970 XFASTINT (w
->last_modified
) = 0;
1976 tem
= Fvertical_motion (make_number (ht
));
1977 if (point
> opoint
|| XFASTINT (tem
) < ht
)
1980 Fvertical_motion (make_number (-1));
1988 Fsignal (Qend_of_buffer
, Qnil
);
1992 /* This is the guts of Fscroll_up and Fscroll_down. */
1995 scroll_command (n
, direction
)
1996 register Lisp_Object n
;
1999 register int defalt
;
2000 int count
= specpdl_ptr
- specpdl
;
2002 /* If selected window's buffer isn't current, make it current for the moment.
2003 But don't screw up if window_scroll gets an error. */
2004 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
2006 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2007 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2010 defalt
= (window_internal_height (XWINDOW (selected_window
))
2011 - next_screen_context_lines
);
2012 defalt
= direction
* (defalt
< 1 ? 1 : defalt
);
2015 window_scroll (selected_window
, defalt
, 0);
2016 else if (EQ (n
, Qminus
))
2017 window_scroll (selected_window
, - defalt
, 0);
2020 n
= Fprefix_numeric_value (n
);
2021 window_scroll (selected_window
, XINT (n
) * direction
, 0);
2024 unbind_to (count
, Qnil
);
2027 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "P",
2028 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2029 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2030 When calling from a program, supply a number as argument or nil.")
2034 scroll_command (n
, 1);
2038 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "P",
2039 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2040 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2041 When calling from a program, supply a number as argument or nil.")
2045 scroll_command (n
, -1);
2049 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
2050 "Scroll text of next window upward ARG lines; or near full screen if no ARG.\n\
2051 The next window is the one below the current one; or the one at the top\n\
2052 if the current one is at the bottom.\n\
2053 When calling from a program, supply a number as argument or nil.\n\
2055 If in the minibuffer, `minibuf-scroll-window' if non-nil\n\
2056 specifies the window to scroll.\n\
2057 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2058 showing that buffer, popping the buffer up if necessary.")
2060 register Lisp_Object n
;
2062 register Lisp_Object window
;
2064 register struct window
*w
;
2065 register int count
= specpdl_ptr
- specpdl
;
2067 if (MINI_WINDOW_P (XWINDOW (selected_window
))
2068 && !NILP (Vminibuf_scroll_window
))
2069 window
= Vminibuf_scroll_window
;
2070 /* If buffer is specified, scroll that buffer. */
2071 else if (!NILP (Vother_window_scroll_buffer
))
2073 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
2075 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
);
2078 /* Nothing specified; pick a neighboring window. */
2079 window
= Fnext_window (selected_window
, Qnil
, Qt
);
2080 CHECK_WINDOW (window
, 0);
2082 if (EQ (window
, selected_window
))
2083 error ("There is no other window");
2085 w
= XWINDOW (window
);
2086 ht
= window_internal_height (w
);
2088 /* Don't screw up if window_scroll gets an error. */
2089 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
2091 Fset_buffer (w
->buffer
);
2092 SET_PT (marker_position (w
->pointm
));
2095 window_scroll (window
, ht
- next_screen_context_lines
, 1);
2096 else if (EQ (n
, Qminus
))
2097 window_scroll (window
, next_screen_context_lines
- ht
, 1);
2100 if (XTYPE (n
) == Lisp_Cons
)
2102 CHECK_NUMBER (n
, 0);
2103 window_scroll (window
, XINT (n
), 1);
2106 Fset_marker (w
->pointm
, make_number (point
), Qnil
);
2112 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 1, 1, "P",
2113 "Scroll selected window display ARG columns left.\n\
2114 Default for ARG is window width minus 2.")
2116 register Lisp_Object arg
;
2120 XFASTINT (arg
) = XFASTINT (XWINDOW (selected_window
)->width
) - 2;
2122 arg
= Fprefix_numeric_value (arg
);
2125 Fset_window_hscroll (selected_window
,
2126 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2130 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 1, 1, "P",
2131 "Scroll selected window display ARG columns right.\n\
2132 Default for ARG is window width minus 2.")
2134 register Lisp_Object arg
;
2137 XFASTINT (arg
) = XFASTINT (XWINDOW (selected_window
)->width
) - 2;
2139 arg
= Fprefix_numeric_value (arg
);
2142 Fset_window_hscroll (selected_window
,
2143 make_number (XINT (XWINDOW (selected_window
)->hscroll
)
2147 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
2148 "Center point in window and redisplay screen. With ARG, put point on line ARG.\n\
2149 The desired position of point is always relative to the current window.\n\
2150 Just C-u as prefix means put point in the center of the screen.\n\
2151 No arg (i.e., it is nil) erases the entire screen and then\n\
2152 redraws with point in the center.")
2154 register Lisp_Object n
;
2156 register struct window
*w
= XWINDOW (selected_window
);
2157 register int ht
= window_internal_height (w
);
2158 register int opoint
= point
;
2162 extern int screen_garbaged
;
2164 SET_SCREEN_GARBAGED (XSCREEN (WINDOW_SCREEN (w
)));
2165 XFASTINT (n
) = ht
/ 2;
2167 else if (XTYPE (n
) == Lisp_Cons
) /* Just C-u. */
2169 XFASTINT (n
) = ht
/ 2;
2173 n
= Fprefix_numeric_value (n
);
2174 CHECK_NUMBER (n
, 0);
2178 XSETINT (n
, XINT (n
) + ht
);
2180 XSETINT (n
, - XINT (n
));
2182 Fvertical_motion (n
);
2183 Fset_marker (w
->start
, make_number (point
), w
->buffer
);
2184 w
->start_at_line_beg
= Fbolp ();
2187 w
->force_start
= Qt
;
2192 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
2194 "Position point relative to window.\n\
2195 With no argument, position text at center of window.\n\
2196 An argument specifies screen line; zero means top of window,\n\
2197 negative means relative to bottom of window.")
2199 register Lisp_Object arg
;
2201 register struct window
*w
= XWINDOW (selected_window
);
2202 register int height
= window_internal_height (w
);
2206 XFASTINT (arg
) = height
/ 2;
2209 arg
= Fprefix_numeric_value (arg
);
2211 XSETINT (arg
, XINT (arg
) + height
);
2214 start
= marker_position (w
->start
);
2215 if (start
< BEGV
|| start
> ZV
)
2217 Fvertical_motion (make_number (- height
/ 2));
2218 Fset_marker (w
->start
, make_number (point
), w
->buffer
);
2219 w
->start_at_line_beg
= Fbolp ();
2220 w
->force_start
= Qt
;
2225 return Fvertical_motion (arg
);
2228 struct save_window_data
2230 int size_from_Lisp_Vector_struct
;
2231 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2232 Lisp_Object screen_width
, screen_height
;
2233 Lisp_Object current_window
;
2234 Lisp_Object current_buffer
;
2235 Lisp_Object minibuf_scroll_window
;
2236 Lisp_Object root_window
;
2237 /* A vector, interpreted as a struct saved_window */
2238 Lisp_Object saved_windows
;
2240 #define SAVE_WINDOW_DATA_SIZE 7 /* Arg to Fmake_vector */
2242 /* This is saved as a Lisp_Vector */
2245 /* these first two must agree with struct Lisp_Vector in lisp.h */
2246 int size_from_Lisp_Vector_struct
;
2247 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
2250 Lisp_Object buffer
, start
, pointm
, mark
;
2251 Lisp_Object left
, top
, width
, height
, hscroll
;
2252 Lisp_Object parent
, prev
;
2253 Lisp_Object start_at_line_beg
;
2254 Lisp_Object display_table
;
2256 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2258 #define SAVED_WINDOW_N(swv,n) \
2259 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2261 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
2262 "T if OBJECT is a window-configration object.")
2266 if (XTYPE (obj
) == Lisp_Window_Configuration
)
2272 DEFUN ("set-window-configuration",
2273 Fset_window_configuration
, Sset_window_configuration
,
2275 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2276 CONFIGURATION must be a value previously returned\n\
2277 by `current-window-configuration' (which see).")
2281 register struct window
*w
;
2282 register struct save_window_data
*data
;
2283 struct Lisp_Vector
*saved_windows
;
2284 register struct saved_window
*p
;
2285 register Lisp_Object tem
;
2286 Lisp_Object new_current_buffer
;
2290 while (XTYPE (arg
) != Lisp_Window_Configuration
)
2292 arg
= wrong_type_argument (intern ("window-configuration-p"), arg
);
2295 data
= (struct save_window_data
*) XVECTOR (arg
);
2296 saved_windows
= XVECTOR (data
->saved_windows
);
2298 s
= XSCREEN (XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->screen
);
2300 if (XFASTINT (data
->screen_height
) != SCREEN_HEIGHT (s
)
2301 || XFASTINT (data
->screen_width
) != SCREEN_WIDTH (s
))
2303 /* Presumably something clever could be done.
2304 However, it doesn't seem worth the effort */
2305 error ("Screen size %dx%d in saved window configuration mismatches screen.",
2306 XFASTINT (data
->screen_height
),
2307 XFASTINT (data
->screen_width
));
2310 windows_or_buffers_changed
++;
2311 new_current_buffer
= data
->current_buffer
;
2312 if (NILP (XBUFFER (new_current_buffer
)->name
))
2313 new_current_buffer
= Qnil
;
2315 /* Mark all windows now on screen as "deleted".
2316 Restoring the new configuration "undeletes" any that are in it. */
2318 delete_all_subwindows (XWINDOW (SCREEN_ROOT_WINDOW (s
)));
2320 /* This loses when the minibuf screen is not s. */
2321 delete_all_subwindows (XWINDOW (XWINDOW (minibuf_window
)->prev
));
2324 for (k
= 0; k
< saved_windows
->size
; k
++)
2326 p
= SAVED_WINDOW_N (saved_windows
, k
);
2327 w
= XWINDOW (p
->window
);
2330 if (!NILP (p
->parent
))
2331 w
->parent
= SAVED_WINDOW_N (saved_windows
, XFASTINT (p
->parent
))->window
;
2335 if (!NILP (p
->prev
))
2337 w
->prev
= SAVED_WINDOW_N (saved_windows
, XFASTINT (p
->prev
))->window
;
2339 /* This is true for a minibuffer-only screen. */
2340 if (w
->mini_p
&& EQ (w
->prev
, p
->window
))
2343 #endif /* MULTI_SCREEN */
2344 XWINDOW (w
->prev
)->next
= p
->window
;
2349 if (!NILP (w
->parent
))
2351 if (EQ (p
->width
, XWINDOW (w
->parent
)->width
))
2353 XWINDOW (w
->parent
)->vchild
= p
->window
;
2354 XWINDOW (w
->parent
)->hchild
= Qnil
;
2358 XWINDOW (w
->parent
)->hchild
= p
->window
;
2359 XWINDOW (w
->parent
)->vchild
= Qnil
;
2365 w
->width
= p
->width
;
2366 w
->height
= p
->height
;
2367 w
->hscroll
= p
->hscroll
;
2368 w
->display_table
= p
->display_table
;
2369 XFASTINT (w
->last_modified
) = 0;
2371 /* Reinstall the saved buffer and pointers into it. */
2372 if (NILP (p
->buffer
))
2373 w
->buffer
= p
->buffer
;
2376 if (!NILP (XBUFFER (p
->buffer
)->name
))
2377 /* If saved buffer is alive, install it. */
2379 w
->buffer
= p
->buffer
;
2380 w
->start_at_line_beg
= p
->start_at_line_beg
;
2381 set_marker_restricted (w
->start
, Fmarker_position (p
->start
), w
->buffer
);
2382 set_marker_restricted (w
->pointm
, Fmarker_position (p
->pointm
), w
->buffer
);
2383 Fset_marker (XBUFFER (w
->buffer
)->mark
,
2384 Fmarker_position (p
->mark
), w
->buffer
);
2386 if (!EQ (p
->buffer
, new_current_buffer
) &&
2387 XBUFFER (p
->buffer
) == current_buffer
)
2388 Fgoto_char (w
->pointm
);
2390 else if (NILP (XBUFFER (w
->buffer
)->name
))
2391 /* Else if window's old buffer is dead too, get a live one. */
2393 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
2394 /* This will set the markers to beginning of visible range. */
2395 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
2396 set_marker_restricted (w
->pointm
, make_number (0), w
->buffer
);
2397 w
->start_at_line_beg
= Qt
;
2400 /* Keeping window's old buffer; make sure the markers are real. */
2401 /* Else if window's old buffer is dead too, get a live one. */
2403 /* Set window markers at start of visible range. */
2404 if (XMARKER (w
->start
)->buffer
== 0)
2405 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
2406 if (XMARKER (w
->pointm
)->buffer
== 0)
2407 set_marker_restricted (w
->pointm
,
2408 make_number (BUF_PT (XBUFFER (w
->buffer
))),
2410 w
->start_at_line_beg
= Qt
;
2415 SCREEN_ROOT_WINDOW (s
) = data
->root_window
;
2418 if (s
!= selected_screen
&& ! SCREEN_IS_TERMCAP (s
))
2419 Fselect_screen (WINDOW_SCREEN (XWINDOW (data
->root_window
)), Qnil
);
2422 if (s
== selected_screen
)
2424 Fselect_window (data
->current_window
);
2425 if (!NILP (new_current_buffer
))
2426 Fset_buffer (new_current_buffer
);
2428 Fset_buffer (XWINDOW (selected_window
)->buffer
);
2431 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
2435 /* Mark all windows now on screen as deleted
2436 by setting their buffers to nil. */
2439 delete_all_subwindows (w
)
2440 register struct window
*w
;
2442 register int count
= 1;
2444 if (!NILP (w
->next
))
2445 delete_all_subwindows (XWINDOW (w
->next
));
2446 if (!NILP (w
->vchild
))
2447 delete_all_subwindows (XWINDOW (w
->vchild
));
2448 if (!NILP (w
->hchild
))
2449 delete_all_subwindows (XWINDOW (w
->hchild
));
2453 count_windows (window
)
2454 register struct window
*window
;
2456 register int count
= 1;
2457 if (!NILP (window
->next
))
2458 count
+= count_windows (XWINDOW (window
->next
));
2459 if (!NILP (window
->vchild
))
2460 count
+= count_windows (XWINDOW (window
->vchild
));
2461 if (!NILP (window
->hchild
))
2462 count
+= count_windows (XWINDOW (window
->hchild
));
2467 save_window_save (window
, vector
, i
)
2469 struct Lisp_Vector
*vector
;
2472 register struct saved_window
*p
;
2473 register struct window
*w
;
2474 register Lisp_Object tem
;
2476 for (;!NILP (window
); window
= w
->next
)
2478 p
= SAVED_WINDOW_N (vector
, i
);
2479 w
= XWINDOW (window
);
2481 XFASTINT (w
->temslot
) = i
++;
2483 p
->buffer
= w
->buffer
;
2486 p
->width
= w
->width
;
2487 p
->height
= w
->height
;
2488 p
->hscroll
= w
->hscroll
;
2489 p
->display_table
= w
->display_table
;
2490 if (!NILP (w
->buffer
))
2492 /* Save w's value of point in the window configuration.
2493 If w is the selected window, then get the value of point
2494 from the buffer; pointm is garbage in the selected window. */
2495 if (EQ (window
, selected_window
))
2497 p
->pointm
= Fmake_marker ();
2498 Fset_marker (p
->pointm
, BUF_PT (XBUFFER (w
->buffer
)),
2502 p
->pointm
= Fcopy_marker (w
->pointm
);
2504 p
->start
= Fcopy_marker (w
->start
);
2505 p
->start_at_line_beg
= w
->start_at_line_beg
;
2507 tem
= XBUFFER (w
->buffer
)->mark
;
2508 p
->mark
= Fcopy_marker (tem
);
2515 p
->start_at_line_beg
= Qnil
;
2518 if (NILP (w
->parent
))
2521 p
->parent
= XWINDOW (w
->parent
)->temslot
;
2526 p
->prev
= XWINDOW (w
->prev
)->temslot
;
2528 if (!NILP (w
->vchild
))
2529 i
= save_window_save (w
->vchild
, vector
, i
);
2530 if (!NILP (w
->hchild
))
2531 i
= save_window_save (w
->hchild
, vector
, i
);
2537 DEFUN ("current-window-configuration",
2538 Fcurrent_window_configuration
, Scurrent_window_configuration
, 0, 1, 0,
2539 "Return an object representing the current window configuration of SCREEN.\n\
2540 If SCREEN is nil or omitted, use the selected screen.\n\
2541 This describes the number of windows, their sizes and current buffers,\n\
2542 and for each displayed buffer, where display starts, and the positions of\n\
2543 point and mark. An exception is made for point in the current buffer:\n\
2544 its value is -not- saved.")
2548 register Lisp_Object tem
;
2549 register int n_windows
;
2550 register struct save_window_data
*data
;
2555 s
= selected_screen
;
2558 CHECK_LIVE_SCREEN (screen
, 0);
2559 s
= XSCREEN (screen
);
2562 n_windows
= count_windows (XWINDOW (SCREEN_ROOT_WINDOW (s
)));
2563 data
= (struct save_window_data
*)
2564 XVECTOR (Fmake_vector (make_number (SAVE_WINDOW_DATA_SIZE
),
2566 XFASTINT (data
->screen_width
) = SCREEN_WIDTH (s
);
2567 XFASTINT (data
->screen_height
) = SCREEN_HEIGHT (s
);
2568 data
->current_window
= SCREEN_SELECTED_WINDOW (s
);
2569 XSET (data
->current_buffer
, Lisp_Buffer
, current_buffer
);
2570 data
->minibuf_scroll_window
= Vminibuf_scroll_window
;
2571 data
->root_window
= SCREEN_ROOT_WINDOW (s
);
2572 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
2573 data
->saved_windows
= tem
;
2574 for (i
= 0; i
< n_windows
; i
++)
2575 XVECTOR (tem
)->contents
[i
]
2576 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE
), Qnil
);
2577 save_window_save (SCREEN_ROOT_WINDOW (s
),
2579 XSET (tem
, Lisp_Window_Configuration
, data
);
2583 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
2585 "Execute body, preserving window sizes and contents.\n\
2586 Restores which buffer appears in which window, where display starts,\n\
2587 as well as the current buffer.\n\
2588 Does not restore the value of point in current buffer.")
2592 register Lisp_Object val
;
2593 register int count
= specpdl_ptr
- specpdl
;
2595 record_unwind_protect (Fset_window_configuration
,
2596 Fcurrent_window_configuration (Qnil
));
2597 val
= Fprogn (args
);
2598 return unbind_to (count
, val
);
2604 selected_screen
= make_terminal_screen ();
2605 minibuf_window
= selected_screen
->minibuffer_window
;
2606 selected_window
= selected_screen
->selected_window
;
2607 last_nonminibuf_screen
= selected_screen
;
2608 #else /* not MULTI_SCREEN */
2609 extern Lisp_Object
get_minibuffer ();
2611 SCREEN_ROOT_WINDOW (selected_screen
) = make_window ();
2612 minibuf_window
= make_window ();
2614 XWINDOW (SCREEN_ROOT_WINDOW (selected_screen
))->next
= minibuf_window
;
2615 XWINDOW (minibuf_window
)->prev
= SCREEN_ROOT_WINDOW (selected_screen
);
2617 /* These values 9 and 10 are arbitrary,
2618 just so that there is "something there."
2619 Correct values are put in in init_xdisp */
2621 XFASTINT (XWINDOW (SCREEN_ROOT_WINDOW (selected_screen
))->width
) = 10;
2622 XFASTINT (XWINDOW (minibuf_window
)->width
) = 10;
2624 XFASTINT (XWINDOW (SCREEN_ROOT_WINDOW (selected_screen
))->height
) = 9;
2625 XFASTINT (XWINDOW (minibuf_window
)->top
) = 9;
2626 XFASTINT (XWINDOW (minibuf_window
)->height
) = 1;
2628 /* Prevent error in Fset_window_buffer. */
2629 XWINDOW (SCREEN_ROOT_WINDOW (selected_screen
))->buffer
= Qt
;
2630 XWINDOW (minibuf_window
)->buffer
= Qt
;
2632 /* Now set them up for real. */
2633 Fset_window_buffer (SCREEN_ROOT_WINDOW (selected_screen
),
2634 Fcurrent_buffer ());
2635 Fset_window_buffer (minibuf_window
, get_minibuffer (0));
2637 selected_window
= SCREEN_ROOT_WINDOW (selected_screen
);
2638 /* Make sure this window seems more recently used than
2639 a newly-created, never-selected window. Increment
2640 window_select_count so the first selection ever will get
2641 something newer than this. */
2642 XFASTINT (XWINDOW (selected_window
)->use_time
) = ++window_select_count
;
2643 #endif /* not MULTI_SCREEN */
2648 Qwindowp
= intern ("windowp");
2649 staticpro (&Qwindowp
);
2651 /* Make sure all windows get marked */
2652 staticpro (&minibuf_window
);
2654 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
2655 "Non-nil means call as function to display a help buffer.\n\
2656 Used by `with-output-to-temp-buffer'.");
2657 Vtemp_buffer_show_function
= Qnil
;
2659 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
2660 "If non-nil, function to call to handle `display-buffer'.\n\
2661 It will receive two args, the buffer and a flag which if non-nil means\n\
2662 that the currently selected window is not acceptable.\n\
2663 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
2664 work using this function.");
2665 Vdisplay_buffer_function
= Qnil
;
2667 DEFVAR_LISP ("mouse-window", &Vmouse_window
,
2668 "Window that the last mouse click occurred on.");
2669 Vmouse_window
= Qnil
;
2671 DEFVAR_LISP ("mouse-event", &Vmouse_event
,
2672 "The last mouse-event object. A list of four elements:\n\
2673 ((X-POS Y-POS) WINDOW SCREEN-PART KEYSEQ).\n\
2674 KEYSEQ is a string, the key sequence to be looked up in the mouse maps.\n\
2675 WINDOW is the window that the click applies do.\n\
2676 If SCREEN-PART is non-nil, the event was on a scrollbar;\n\
2677 then Y-POS is really the total length of the scrollbar, while X-POS is\n\
2678 the relative position of the scrollbar's value within that total length.\n\
2679 SCREEN-PART is one of the following symbols:\n\
2680 `vertical-scrollbar', `vertical-slider',\n\
2681 `vertical-thumbup', `vertical-thumbdown',\n\
2682 `horizontal-scrollbar', `horizontal-slider',\n\
2683 `horizontal-thumbleft', `horizontal-thumbright'");
2684 Vmouse_event
= Qnil
;
2686 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
2687 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
2688 Vminibuf_scroll_window
= Qnil
;
2690 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
2691 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
2692 Vother_window_scroll_buffer
= Qnil
;
2695 DEFVAR_BOOL ("pop-up-screens", &pop_up_screens
,
2696 "*Non-nil means `display-buffer' should make a separate X-window.");
2699 DEFVAR_LISP ("pop-up-screen-function", &Vpop_up_screen_function
,
2700 "*If non-nil, function to call to handle automatic new screen creation.\n\
2701 It is called with no arguments and should return a newly created screen.\n\
2703 A typical value might be `(lambda () (x-create-screen auto-screen-parms))'\n\
2704 where `auto-screen-parms' would hold the default screen parameters.");
2705 Vpop_up_screen_function
= Qnil
;
2708 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
2709 "*Non-nil means display-buffer should make new windows.");
2712 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
2713 "*Number of lines of continuity when scrolling by screenfuls.");
2714 next_screen_context_lines
= 2;
2716 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
2717 "*display-buffer would prefer to split the largest window if this large.\n\
2718 If there is only one window, it is split regardless of this value.");
2719 split_height_threshold
= 500;
2721 DEFVAR_INT ("window-min-height", &window_min_height
,
2722 "*Delete any window less than this tall (including its mode line).");
2723 window_min_height
= 4;
2725 DEFVAR_INT ("window-min-width", &window_min_width
,
2726 "*Delete any window less than this wide.");
2727 window_min_width
= 10;
2729 defsubr (&Sselected_window
);
2730 defsubr (&Sminibuffer_window
);
2731 defsubr (&Swindow_minibuffer_p
);
2732 defsubr (&Swindowp
);
2733 defsubr (&Spos_visible_in_window_p
);
2734 defsubr (&Swindow_buffer
);
2735 defsubr (&Swindow_height
);
2736 defsubr (&Swindow_width
);
2737 defsubr (&Swindow_hscroll
);
2738 defsubr (&Sset_window_hscroll
);
2739 defsubr (&Swindow_edges
);
2740 defsubr (&Scoordinates_in_window_p
);
2741 defsubr (&Swindow_at
);
2742 defsubr (&Swindow_point
);
2743 defsubr (&Swindow_start
);
2744 defsubr (&Swindow_end
);
2745 defsubr (&Sset_window_point
);
2746 defsubr (&Sset_window_start
);
2747 defsubr (&Swindow_dedicated_p
);
2748 defsubr (&Sset_window_dedicated_p
);
2749 defsubr (&Swindow_display_table
);
2750 defsubr (&Sset_window_display_table
);
2751 defsubr (&Snext_window
);
2752 defsubr (&Sprevious_window
);
2753 defsubr (&Sother_window
);
2754 defsubr (&Sget_lru_window
);
2755 defsubr (&Sget_largest_window
);
2756 defsubr (&Sget_buffer_window
);
2757 defsubr (&Sdelete_other_windows
);
2758 defsubr (&Sdelete_windows_on
);
2759 defsubr (&Sreplace_buffer_in_windows
);
2760 defsubr (&Sdelete_window
);
2761 defsubr (&Sset_window_buffer
);
2762 defsubr (&Sselect_window
);
2763 defsubr (&Sdisplay_buffer
);
2764 defsubr (&Ssplit_window
);
2765 defsubr (&Senlarge_window
);
2766 defsubr (&Sshrink_window
);
2767 defsubr (&Sscroll_up
);
2768 defsubr (&Sscroll_down
);
2769 defsubr (&Sscroll_left
);
2770 defsubr (&Sscroll_right
);
2771 defsubr (&Sscroll_other_window
);
2772 defsubr (&Srecenter
);
2773 defsubr (&Smove_to_window_line
);
2774 defsubr (&Swindow_configuration_p
);
2775 defsubr (&Sset_window_configuration
);
2776 defsubr (&Scurrent_window_configuration
);
2777 defsubr (&Ssave_window_excursion
);
2782 initial_define_key (control_x_map
, '1', "delete-other-windows");
2783 initial_define_key (control_x_map
, '2', "split-window");
2784 initial_define_key (control_x_map
, '0', "delete-window");
2785 initial_define_key (control_x_map
, 'o', "other-window");
2786 initial_define_key (control_x_map
, '^', "enlarge-window");
2787 initial_define_key (control_x_map
, '<', "scroll-left");
2788 initial_define_key (control_x_map
, '>', "scroll-right");
2790 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
2791 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
2792 initial_define_key (meta_map
, 'v', "scroll-down");
2794 initial_define_key (global_map
, Ctl('L'), "recenter");
2795 initial_define_key (meta_map
, 'r', "move-to-window-line");