1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985,86,87,93,94,95,96,97,1998,2000, 2001
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
34 #include "dispextern.h"
35 #include "blockinput.h"
36 #include "intervals.h"
40 #endif /* HAVE_X_WINDOWS */
51 /* Values returned from coordinates_in_window. */
65 Lisp_Object Qwindowp
, Qwindow_live_p
, Qwindow_configuration_p
;
66 Lisp_Object Qwindow_size_fixed
;
67 extern Lisp_Object Qheight
, Qwidth
;
69 static int displayed_window_lines
P_ ((struct window
*));
70 static struct window
*decode_window
P_ ((Lisp_Object
));
71 static Lisp_Object select_window_1
P_ ((Lisp_Object
, int));
72 static int count_windows
P_ ((struct window
*));
73 static int get_leaf_windows
P_ ((struct window
*, struct window
**, int));
74 static void window_scroll
P_ ((Lisp_Object
, int, int, int));
75 static void window_scroll_pixel_based
P_ ((Lisp_Object
, int, int, int));
76 static void window_scroll_line_based
P_ ((Lisp_Object
, int, int, int));
77 static int window_min_size_1
P_ ((struct window
*, int));
78 static int window_min_size
P_ ((struct window
*, int, int, int *));
79 static void size_window
P_ ((Lisp_Object
, int, int, int));
80 static int freeze_window_start
P_ ((struct window
*, void *));
81 static int window_fixed_size_p
P_ ((struct window
*, int, int));
82 static void enlarge_window
P_ ((Lisp_Object
, int, int, int));
83 static Lisp_Object window_list
P_ ((void));
84 static int add_window_to_list
P_ ((struct window
*, void *));
85 static int candidate_window_p
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
87 static Lisp_Object next_window
P_ ((Lisp_Object
, Lisp_Object
,
89 static void decode_next_window_args
P_ ((Lisp_Object
*, Lisp_Object
*,
91 static int foreach_window_1
P_ ((struct window
*,
92 int (* fn
) (struct window
*, void *),
94 static Lisp_Object window_list_1
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
));
96 /* The value of `window-size-fixed'. */
98 int window_size_fixed
;
100 /* This is the window in which the terminal's cursor should
101 be left when nothing is being done with it. This must
102 always be a leaf window, and its buffer is selected by
103 the top level editing loop at the end of each command.
105 This value is always the same as
106 FRAME_SELECTED_WINDOW (selected_frame). */
108 Lisp_Object selected_window
;
110 /* A list of all windows for use by next_window and Fwindow_list.
111 Functions creating or deleting windows should invalidate this cache
112 by setting it to nil. */
114 Lisp_Object Vwindow_list
;
116 /* The mini-buffer window of the selected frame.
117 Note that you cannot test for mini-bufferness of an arbitrary window
118 by comparing against this; but you can test for mini-bufferness of
119 the selected window. */
121 Lisp_Object minibuf_window
;
123 /* Non-nil means it is the window whose mode line should be
124 shown as the selected window when the minibuffer is selected. */
126 Lisp_Object minibuf_selected_window
;
128 /* Non-nil means it is the window for C-M-v to scroll
129 when the mini-buffer is selected. */
131 Lisp_Object Vminibuf_scroll_window
;
133 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
135 Lisp_Object Vother_window_scroll_buffer
;
137 /* Non-nil means it's function to call to display temp buffers. */
139 Lisp_Object Vtemp_buffer_show_function
;
141 /* Non-zero means to use mode-line-inactive face in all windows but the
142 selected-window and the minibuffer-scroll-window when the
143 minibuffer is active. */
144 int mode_line_in_non_selected_windows
;
146 /* If a window gets smaller than either of these, it is removed. */
148 EMACS_INT window_min_height
;
149 EMACS_INT window_min_width
;
151 /* Nonzero implies Fdisplay_buffer should create windows. */
155 /* Nonzero implies make new frames for Fdisplay_buffer. */
159 /* Nonzero means reuse existing frames for displaying buffers. */
161 int display_buffer_reuse_frames
;
163 /* Non-nil means use this function instead of default */
165 Lisp_Object Vpop_up_frame_function
;
167 /* Function to call to handle Fdisplay_buffer. */
169 Lisp_Object Vdisplay_buffer_function
;
171 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
173 Lisp_Object Veven_window_heights
;
175 /* List of buffer *names* for buffers that should have their own frames. */
177 Lisp_Object Vspecial_display_buffer_names
;
179 /* List of regexps for buffer names that should have their own frames. */
181 Lisp_Object Vspecial_display_regexps
;
183 /* Function to pop up a special frame. */
185 Lisp_Object Vspecial_display_function
;
187 /* List of buffer *names* for buffers to appear in selected window. */
189 Lisp_Object Vsame_window_buffer_names
;
191 /* List of regexps for buffer names to appear in selected window. */
193 Lisp_Object Vsame_window_regexps
;
195 /* Hook run at end of temp_output_buffer_show. */
197 Lisp_Object Qtemp_buffer_show_hook
;
199 /* Fdisplay_buffer always splits the largest window
200 if that window is more than this high. */
202 EMACS_INT split_height_threshold
;
204 /* Number of lines of continuity in scrolling by screenfuls. */
206 EMACS_INT next_screen_context_lines
;
208 /* Incremented for each window created. */
210 static int sequence_number
;
212 /* Nonzero after init_window_once has finished. */
214 static int window_initialized
;
216 /* Hook to run when window config changes. */
218 Lisp_Object Qwindow_configuration_change_hook
;
219 Lisp_Object Vwindow_configuration_change_hook
;
221 /* Nonzero means scroll commands try to put point
222 at the same screen height as previously. */
224 Lisp_Object Vscroll_preserve_screen_position
;
226 #if 0 /* This isn't used anywhere. */
227 /* Nonzero means we can split a frame even if it is "unsplittable". */
228 static int inhibit_frame_unsplittable
;
231 extern EMACS_INT scroll_margin
;
233 extern Lisp_Object Qwindow_scroll_functions
, Vwindow_scroll_functions
;
235 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
236 doc
: /* Returns t if OBJECT is a window. */)
240 return WINDOWP (object
) ? Qt
: Qnil
;
243 DEFUN ("window-live-p", Fwindow_live_p
, Swindow_live_p
, 1, 1, 0,
244 doc
: /* Returns t if OBJECT is a window which is currently visible. */)
248 return WINDOW_LIVE_P (object
) ? Qt
: Qnil
;
255 register struct window
*p
;
257 p
= allocate_window ();
258 XSETFASTINT (p
->sequence_number
, ++sequence_number
);
259 XSETFASTINT (p
->left
, 0);
260 XSETFASTINT (p
->top
, 0);
261 XSETFASTINT (p
->height
, 0);
262 XSETFASTINT (p
->width
, 0);
263 XSETFASTINT (p
->hscroll
, 0);
264 XSETFASTINT (p
->min_hscroll
, 0);
265 p
->orig_top
= p
->orig_height
= Qnil
;
266 p
->start
= Fmake_marker ();
267 p
->pointm
= Fmake_marker ();
268 XSETFASTINT (p
->use_time
, 0);
270 p
->display_table
= Qnil
;
272 p
->pseudo_window_p
= 0;
273 bzero (&p
->cursor
, sizeof (p
->cursor
));
274 bzero (&p
->last_cursor
, sizeof (p
->last_cursor
));
275 bzero (&p
->phys_cursor
, sizeof (p
->phys_cursor
));
276 p
->desired_matrix
= p
->current_matrix
= 0;
277 p
->phys_cursor_type
= -1;
278 p
->phys_cursor_width
= -1;
279 p
->must_be_updated_p
= 0;
280 XSETFASTINT (p
->window_end_vpos
, 0);
281 XSETFASTINT (p
->window_end_pos
, 0);
282 p
->window_end_valid
= Qnil
;
285 XSETFASTINT (p
->last_point
, 0);
286 p
->frozen_window_start_p
= 0;
292 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
293 doc
: /* Return the window that the cursor now appears in and commands apply to. */)
296 return selected_window
;
299 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 1, 0,
300 doc
: /* Return the window used now for minibuffers.
301 If the optional argument FRAME is specified, return the minibuffer window
302 used by that frame. */)
307 frame
= selected_frame
;
308 CHECK_LIVE_FRAME (frame
);
309 return FRAME_MINIBUF_WINDOW (XFRAME (frame
));
312 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 0, 1, 0,
313 doc
: /* Returns non-nil if WINDOW is a minibuffer window. */)
317 struct window
*w
= decode_window (window
);
318 return MINI_WINDOW_P (w
) ? Qt
: Qnil
;
322 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
323 Spos_visible_in_window_p
, 0, 3, 0,
324 doc
: /* Return t if position POS is currently on the frame in WINDOW.
325 Return nil if that position is scrolled vertically out of view.
326 If a character is only partially visible, nil is returned, unless the
327 optional argument PARTIALLY is non-nil.
328 POS defaults to point in WINDOW; WINDOW defaults to the selected window. */)
329 (pos
, window
, partially
)
330 Lisp_Object pos
, window
, partially
;
332 register struct window
*w
;
334 register struct buffer
*buf
;
336 Lisp_Object in_window
;
339 w
= decode_window (window
);
340 buf
= XBUFFER (w
->buffer
);
341 SET_TEXT_POS_FROM_MARKER (top
, w
->start
);
345 CHECK_NUMBER_COERCE_MARKER (pos
);
348 else if (w
== XWINDOW (selected_window
))
351 posint
= XMARKER (w
->pointm
)->charpos
;
353 /* If position is above window start, it's not visible. */
354 if (posint
< CHARPOS (top
))
356 else if (XFASTINT (w
->last_modified
) >= BUF_MODIFF (buf
)
357 && XFASTINT (w
->last_overlay_modified
) >= BUF_OVERLAY_MODIFF (buf
)
358 && posint
< BUF_Z (buf
) - XFASTINT (w
->window_end_pos
))
360 /* If frame is up-to-date, and POSINT is < window end pos, use
361 that info. This doesn't work for POSINT == end pos, because
362 the window end pos is actually the position _after_ the last
363 char in the window. */
364 if (NILP (partially
))
366 pos_visible_p (w
, posint
, &fully_p
, NILP (partially
));
367 in_window
= fully_p
? Qt
: Qnil
;
372 else if (posint
> BUF_ZV (buf
))
374 else if (CHARPOS (top
) < BUF_BEGV (buf
) || CHARPOS (top
) > BUF_ZV (buf
))
375 /* If window start is out of range, do something reasonable. */
379 if (pos_visible_p (w
, posint
, &fully_p
, NILP (partially
)))
380 in_window
= !NILP (partially
) || fully_p
? Qt
: Qnil
;
389 static struct window
*
390 decode_window (window
)
391 register Lisp_Object window
;
394 return XWINDOW (selected_window
);
396 CHECK_LIVE_WINDOW (window
);
397 return XWINDOW (window
);
400 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
401 doc
: /* Return the buffer that WINDOW is displaying. */)
405 return decode_window (window
)->buffer
;
408 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
409 doc
: /* Return the number of lines in WINDOW (including its mode line). */)
413 return decode_window (window
)->height
;
416 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
417 doc
: /* Return the number of display columns in WINDOW.
418 This is the width that is usable columns available for text in WINDOW.
419 If you want to find out how many columns WINDOW takes up,
420 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
424 return make_number (window_internal_width (decode_window (window
)));
427 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
428 doc
: /* Return the number of columns by which WINDOW is scrolled from left margin. */)
432 return decode_window (window
)->hscroll
;
435 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
436 doc
: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
437 NCOL should be zero or positive. */)
439 Lisp_Object window
, ncol
;
441 struct window
*w
= decode_window (window
);
445 hscroll
= max (0, XINT (ncol
));
447 /* Prevent redisplay shortcuts when changing the hscroll. */
448 if (XINT (w
->hscroll
) != hscroll
)
449 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
451 w
->hscroll
= make_number (hscroll
);
455 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger
,
456 Swindow_redisplay_end_trigger
, 0, 1, 0,
457 doc
: /* Return WINDOW's redisplay end trigger value.
458 See `set-window-redisplay-end-trigger' for more information. */)
462 return decode_window (window
)->redisplay_end_trigger
;
465 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger
,
466 Sset_window_redisplay_end_trigger
, 2, 2, 0,
467 doc
: /* Set WINDOW's redisplay end trigger value to VALUE.
468 VALUE should be a buffer position (typically a marker) or nil.
469 If it is a buffer position, then if redisplay in WINDOW reaches a position
470 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
471 with two arguments: WINDOW, and the end trigger value.
472 Afterwards the end-trigger value is reset to nil. */)
474 register Lisp_Object window
, value
;
476 register struct window
*w
;
478 w
= decode_window (window
);
479 w
->redisplay_end_trigger
= value
;
483 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
484 doc
: /* Return a list of the edge coordinates of WINDOW.
485 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
486 RIGHT is one more than the rightmost column used by WINDOW,
487 and BOTTOM is one more than the bottommost row used by WINDOW
488 and its mode-line. */)
492 register struct window
*w
= decode_window (window
);
494 return Fcons (w
->left
, Fcons (w
->top
,
495 Fcons (make_number (WINDOW_RIGHT_EDGE (w
)),
496 Fcons (make_number (XFASTINT (w
->top
)
497 + XFASTINT (w
->height
)),
501 /* Test if the character at column *X, row *Y is within window W.
502 If it is not, return 0;
503 if it is in the window's text area,
504 set *x and *y to its location relative to the upper left corner
507 if it is on the window's modeline, return 2;
508 if it is on the border between the window and its right sibling,
510 if it is on the window's top line, return 4;
511 if it is in left or right fringe of the window,
512 return 5 or 6, and convert *X and *Y to window-relative corrdinates.
514 X and Y are frame relative pixel coordinates. */
516 static enum window_part
517 coordinates_in_window (w
, x
, y
)
518 register struct window
*w
;
521 /* Let's make this a global enum later, instead of using numbers
523 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
524 int left_x
, right_x
, top_y
, bottom_y
;
525 enum window_part part
;
526 int ux
= CANON_X_UNIT (f
);
527 int x0
= XFASTINT (w
->left
) * ux
;
528 int x1
= x0
+ XFASTINT (w
->width
) * ux
;
529 /* The width of the area where the vertical line can be dragged.
530 (Between mode lines for instance. */
531 int grabbable_width
= ux
;
533 if (*x
< x0
|| *x
>= x1
)
536 /* In what's below, we subtract 1 when computing right_x because we
537 want the rightmost pixel, which is given by left_pixel+width-1. */
538 if (w
->pseudo_window_p
)
541 right_x
= XFASTINT (w
->width
) * CANON_X_UNIT (f
) - 1;
542 top_y
= WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w
);
543 bottom_y
= WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w
);
547 left_x
= (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w
)
548 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
));
549 right_x
= WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w
) - 1;
550 top_y
= (WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w
)
551 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f
));
552 bottom_y
= WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w
);
555 /* On the mode line or header line? If it's near the start of
556 the mode or header line of window that's has a horizontal
557 sibling, say it's on the vertical line. That's to be able
558 to resize windows horizontally in case we're using toolkit
561 if (WINDOW_WANTS_MODELINE_P (w
)
562 && *y
>= bottom_y
- CURRENT_MODE_LINE_HEIGHT (w
)
565 /* We're somewhere on the mode line. We consider the place
566 between mode lines of horizontally adjacent mode lines
567 as the vertical border. If scroll bars on the left,
568 return the right window. */
571 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
573 if (abs (*x
- x0
) < grabbable_width
)
574 part
= ON_VERTICAL_BORDER
;
576 else if (!WINDOW_RIGHTMOST_P (w
) && abs (*x
- x1
) < grabbable_width
)
577 part
= ON_VERTICAL_BORDER
;
579 else if (WINDOW_WANTS_HEADER_LINE_P (w
)
580 && *y
< top_y
+ CURRENT_HEADER_LINE_HEIGHT (w
)
583 part
= ON_HEADER_LINE
;
585 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f
))
587 if (abs (*x
- x0
) < grabbable_width
)
588 part
= ON_VERTICAL_BORDER
;
590 else if (!WINDOW_RIGHTMOST_P (w
) && abs (*x
- x1
) < grabbable_width
)
591 part
= ON_VERTICAL_BORDER
;
593 /* Outside anything interesting? */
597 - FRAME_LEFT_FRINGE_WIDTH (f
)
598 - FRAME_LEFT_SCROLL_BAR_WIDTH (f
) * ux
)
600 + FRAME_RIGHT_FRINGE_WIDTH (f
)
601 + FRAME_RIGHT_SCROLL_BAR_WIDTH (f
) * ux
))
605 else if (FRAME_WINDOW_P (f
))
607 if (!w
->pseudo_window_p
608 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
609 && !WINDOW_RIGHTMOST_P (w
)
610 && (abs (*x
- right_x
- FRAME_RIGHT_FRINGE_WIDTH (f
)) < grabbable_width
))
612 part
= ON_VERTICAL_BORDER
;
614 else if (*x
< left_x
|| *x
> right_x
)
616 /* Other lines than the mode line don't include fringes and
617 scroll bars on the left. */
619 /* Convert X and Y to window-relative pixel coordinates. */
622 part
= *x
< left_x
? ON_LEFT_FRINGE
: ON_RIGHT_FRINGE
;
633 /* Need to say "*x > right_x" rather than >=, since on character
634 terminals, the vertical line's x coordinate is right_x. */
635 if (*x
< left_x
|| *x
> right_x
)
637 /* Other lines than the mode line don't include fringes and
638 scroll bars on the left. */
640 /* Convert X and Y to window-relative pixel coordinates. */
643 part
= *x
< left_x
? ON_LEFT_FRINGE
: ON_RIGHT_FRINGE
;
645 /* Here, too, "*x > right_x" is because of character terminals. */
646 else if (!w
->pseudo_window_p
647 && !WINDOW_RIGHTMOST_P (w
)
648 && *x
> right_x
- ux
)
650 /* On the border on the right side of the window? Assume that
651 this area begins at RIGHT_X minus a canonical char width. */
652 part
= ON_VERTICAL_BORDER
;
656 /* Convert X and Y to window-relative pixel coordinates. */
667 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
668 Scoordinates_in_window_p
, 2, 2, 0,
669 doc
: /* Return non-nil if COORDINATES are in WINDOW.
670 COORDINATES is a cons of the form (X . Y), X and Y being distances
671 measured in characters from the upper-left corner of the frame.
672 \(0 . 0) denotes the character in the upper left corner of the
674 If COORDINATES are in the text portion of WINDOW,
675 the coordinates relative to the window are returned.
676 If they are in the mode line of WINDOW, `mode-line' is returned.
677 If they are in the top mode line of WINDOW, `header-line' is returned.
678 If they are in the left fringe of WINDOW, `left-fringe' is returned.
679 If they are in the right fringe of WINDOW, `right-fringe' is returned.
680 If they are on the border between WINDOW and its right sibling,
681 `vertical-line' is returned. */)
682 (coordinates
, window
)
683 register Lisp_Object coordinates
, window
;
690 CHECK_LIVE_WINDOW (window
);
691 w
= XWINDOW (window
);
692 f
= XFRAME (w
->frame
);
693 CHECK_CONS (coordinates
);
694 lx
= Fcar (coordinates
);
695 ly
= Fcdr (coordinates
);
696 CHECK_NUMBER_OR_FLOAT (lx
);
697 CHECK_NUMBER_OR_FLOAT (ly
);
698 x
= PIXEL_X_FROM_CANON_X (f
, lx
);
699 y
= PIXEL_Y_FROM_CANON_Y (f
, ly
);
701 switch (coordinates_in_window (w
, &x
, &y
))
707 /* X and Y are now window relative pixel coordinates. Convert
708 them to canonical char units before returning them. */
709 return Fcons (CANON_X_FROM_PIXEL_X (f
, x
),
710 CANON_Y_FROM_PIXEL_Y (f
, y
));
715 case ON_VERTICAL_BORDER
:
716 return Qvertical_line
;
724 case ON_RIGHT_FRINGE
:
725 return Qright_fringe
;
733 /* Callback for foreach_window, used in window_from_coordinates.
734 Check if window W contains coordinates specified by USER_DATA which
735 is actually a pointer to a struct check_window_data CW.
737 Check if window W contains coordinates *CW->x and *CW->y. If it
738 does, return W in *CW->window, as Lisp_Object, and return in
739 *CW->part the part of the window under coordinates *X,*Y. Return
740 zero from this function to stop iterating over windows. */
742 struct check_window_data
749 check_window_containing (w
, user_data
)
753 struct check_window_data
*cw
= (struct check_window_data
*) user_data
;
754 enum window_part found
;
757 found
= coordinates_in_window (w
, cw
->x
, cw
->y
);
758 if (found
!= ON_NOTHING
)
760 *cw
->part
= found
- 1;
761 XSETWINDOW (*cw
->window
, w
);
769 /* Find the window containing frame-relative pixel position X/Y and
770 return it as a Lisp_Object. If X, Y is on the window's modeline,
771 set *PART to 1; if it is on the separating line between the window
772 and its right sibling, set it to 2; otherwise set it to 0. If
773 there is no window under X, Y return nil and leave *PART
774 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
776 This function was previously implemented with a loop cycling over
777 windows with Fnext_window, and starting with the frame's selected
778 window. It turned out that this doesn't work with an
779 implementation of next_window using Vwindow_list, because
780 FRAME_SELECTED_WINDOW (F) is not always contained in the window
781 tree of F when this function is called asynchronously from
782 note_mouse_highlight. The original loop didn't terminate in this
786 window_from_coordinates (f
, x
, y
, part
, tool_bar_p
)
793 struct check_window_data cw
;
796 cw
.window
= &window
, cw
.x
= &x
, cw
.y
= &y
; cw
.part
= part
;
797 foreach_window (f
, check_window_containing
, &cw
);
799 /* If not found above, see if it's in the tool bar window, if a tool
803 && WINDOWP (f
->tool_bar_window
)
804 && XINT (XWINDOW (f
->tool_bar_window
)->height
) > 0
805 && (coordinates_in_window (XWINDOW (f
->tool_bar_window
), &x
, &y
)
809 window
= f
->tool_bar_window
;
815 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
816 doc
: /* Return window containing coordinates X and Y on FRAME.
817 If omitted, FRAME defaults to the currently selected frame.
818 The top left corner of the frame is considered to be row 0,
821 Lisp_Object x
, y
, frame
;
827 frame
= selected_frame
;
828 CHECK_LIVE_FRAME (frame
);
831 /* Check that arguments are integers or floats. */
832 CHECK_NUMBER_OR_FLOAT (x
);
833 CHECK_NUMBER_OR_FLOAT (y
);
835 return window_from_coordinates (f
,
836 PIXEL_X_FROM_CANON_X (f
, x
),
837 PIXEL_Y_FROM_CANON_Y (f
, y
),
841 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
842 doc
: /* Return current value of point in WINDOW.
843 For a nonselected window, this is the value point would have
844 if that window were selected.
846 Note that, when WINDOW is the selected window and its buffer
847 is also currently selected, the value returned is the same as (point).
848 It would be more strictly correct to return the `top-level' value
849 of point, outside of any save-excursion forms.
850 But that is hard to define. */)
854 register struct window
*w
= decode_window (window
);
856 if (w
== XWINDOW (selected_window
)
857 && current_buffer
== XBUFFER (w
->buffer
))
859 return Fmarker_position (w
->pointm
);
862 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
863 doc
: /* Return position at which display currently starts in WINDOW.
864 This is updated by redisplay or by calling `set-window-start'. */)
868 return Fmarker_position (decode_window (window
)->start
);
871 /* This is text temporarily removed from the doc string below.
873 This function returns nil if the position is not currently known.
874 That happens when redisplay is preempted and doesn't finish.
875 If in that case you want to compute where the end of the window would
876 have been if redisplay had finished, do this:
878 (goto-char (window-start window))
879 (vertical-motion (1- (window-height window)) window)
882 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 2, 0,
883 doc
: /* Return position at which display currently ends in WINDOW.
884 This is updated by redisplay, when it runs to completion.
885 Simply changing the buffer text or setting `window-start'
886 does not update this value.
887 If UPDATE is non-nil, compute the up-to-date position
888 if it isn't already recorded. */)
890 Lisp_Object window
, update
;
893 struct window
*w
= decode_window (window
);
899 #if 0 /* This change broke some things. We should make it later. */
900 /* If we don't know the end position, return nil.
901 The user can compute it with vertical-motion if he wants to.
902 It would be nicer to do it automatically,
903 but that's so slow that it would probably bother people. */
904 if (NILP (w
->window_end_valid
))
909 && ! (! NILP (w
->window_end_valid
)
910 && XFASTINT (w
->last_modified
) >= MODIFF
))
912 struct text_pos startp
;
914 struct buffer
*old_buffer
= NULL
, *b
= XBUFFER (buf
);
916 /* In case W->start is out of the range, use something
917 reasonable. This situation occured when loading a file with
918 `-l' containing a call to `rmail' with subsequent other
919 commands. At the end, W->start happened to be BEG, while
920 rmail had already narrowed the buffer. */
921 if (XMARKER (w
->start
)->charpos
< BEGV
)
922 SET_TEXT_POS (startp
, BEGV
, BEGV_BYTE
);
923 else if (XMARKER (w
->start
)->charpos
> ZV
)
924 SET_TEXT_POS (startp
, ZV
, ZV_BYTE
);
926 SET_TEXT_POS_FROM_MARKER (startp
, w
->start
);
928 /* Cannot use Fvertical_motion because that function doesn't
929 cope with variable-height lines. */
930 if (b
!= current_buffer
)
932 old_buffer
= current_buffer
;
933 set_buffer_internal (b
);
936 start_display (&it
, w
, startp
);
937 move_it_vertically (&it
, window_box_height (w
));
938 if (it
.current_y
< it
.last_visible_y
)
939 move_it_past_eol (&it
);
940 value
= make_number (IT_CHARPOS (it
));
943 set_buffer_internal (old_buffer
);
946 XSETINT (value
, BUF_Z (XBUFFER (buf
)) - XFASTINT (w
->window_end_pos
));
951 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
952 doc
: /* Make point value in WINDOW be at position POS in WINDOW's buffer. */)
954 Lisp_Object window
, pos
;
956 register struct window
*w
= decode_window (window
);
958 CHECK_NUMBER_COERCE_MARKER (pos
);
959 if (w
== XWINDOW (selected_window
)
960 && XBUFFER (w
->buffer
) == current_buffer
)
963 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
965 /* We have to make sure that redisplay updates the window to show
966 the new value of point. */
967 if (!EQ (window
, selected_window
))
968 ++windows_or_buffers_changed
;
973 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
974 doc
: /* Make display in WINDOW start at position POS in WINDOW's buffer.
975 Optional third arg NOFORCE non-nil inhibits next redisplay
976 from overriding motion of point in order to display at this exact start. */)
977 (window
, pos
, noforce
)
978 Lisp_Object window
, pos
, noforce
;
980 register struct window
*w
= decode_window (window
);
982 CHECK_NUMBER_COERCE_MARKER (pos
);
983 set_marker_restricted (w
->start
, pos
, w
->buffer
);
984 /* this is not right, but much easier than doing what is right. */
985 w
->start_at_line_beg
= Qnil
;
988 w
->update_mode_line
= Qt
;
989 XSETFASTINT (w
->last_modified
, 0);
990 XSETFASTINT (w
->last_overlay_modified
, 0);
991 if (!EQ (window
, selected_window
))
992 windows_or_buffers_changed
++;
997 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
999 doc
: /* Return WINDOW's dedicated object, usually t or nil.
1000 See also `set-window-dedicated-p'. */)
1004 return decode_window (window
)->dedicated
;
1007 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
1008 Sset_window_dedicated_p
, 2, 2, 0,
1009 doc
: /* Control whether WINDOW is dedicated to the buffer it displays.
1010 If it is dedicated, Emacs will not automatically change
1011 which buffer appears in it.
1012 The second argument is the new value for the dedication flag;
1013 non-nil means yes. */)
1015 Lisp_Object window
, arg
;
1017 register struct window
*w
= decode_window (window
);
1020 w
->dedicated
= Qnil
;
1024 return w
->dedicated
;
1027 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
1029 doc
: /* Return the display-table that WINDOW is using. */)
1033 return decode_window (window
)->display_table
;
1036 /* Get the display table for use on window W. This is either W's
1037 display table or W's buffer's display table. Ignore the specified
1038 tables if they are not valid; if no valid table is specified,
1041 struct Lisp_Char_Table
*
1042 window_display_table (w
)
1045 struct Lisp_Char_Table
*dp
= NULL
;
1047 if (DISP_TABLE_P (w
->display_table
))
1048 dp
= XCHAR_TABLE (w
->display_table
);
1049 else if (BUFFERP (w
->buffer
))
1051 struct buffer
*b
= XBUFFER (w
->buffer
);
1053 if (DISP_TABLE_P (b
->display_table
))
1054 dp
= XCHAR_TABLE (b
->display_table
);
1055 else if (DISP_TABLE_P (Vstandard_display_table
))
1056 dp
= XCHAR_TABLE (Vstandard_display_table
);
1062 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
1063 doc
: /* Set WINDOW's display-table to TABLE. */)
1065 register Lisp_Object window
, table
;
1067 register struct window
*w
;
1069 w
= decode_window (window
);
1070 w
->display_table
= table
;
1074 /* Record info on buffer window w is displaying
1075 when it is about to cease to display that buffer. */
1078 register struct window
*w
;
1085 if (b
!= XMARKER (w
->pointm
)->buffer
)
1089 if (w
== XWINDOW (selected_window
)
1090 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
1091 /* Do this except when the selected window's buffer
1092 is being removed from some other window. */
1094 /* last_window_start records the start position that this buffer
1095 had in the last window to be disconnected from it.
1096 Now that this statement is unconditional,
1097 it is possible for the buffer to be displayed in the
1098 selected window, while last_window_start reflects another
1099 window which was recently showing the same buffer.
1100 Some people might say that might be a good thing. Let's see. */
1101 b
->last_window_start
= marker_position (w
->start
);
1103 /* Point in the selected window's buffer
1104 is actually stored in that buffer, and the window's pointm isn't used.
1105 So don't clobber point in that buffer. */
1106 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
)
1107 /* This line helps to fix Horsley's testbug.el bug. */
1108 && !(WINDOWP (b
->last_selected_window
)
1109 && w
!= XWINDOW (b
->last_selected_window
)
1110 && EQ (buf
, XWINDOW (b
->last_selected_window
)->buffer
)))
1111 temp_set_point_both (b
,
1112 clip_to_bounds (BUF_BEGV (b
),
1113 XMARKER (w
->pointm
)->charpos
,
1115 clip_to_bounds (BUF_BEGV_BYTE (b
),
1116 marker_byte_position (w
->pointm
),
1119 if (WINDOWP (b
->last_selected_window
)
1120 && w
== XWINDOW (b
->last_selected_window
))
1121 b
->last_selected_window
= Qnil
;
1124 /* Put replacement into the window structure in place of old. */
1126 replace_window (old
, replacement
)
1127 Lisp_Object old
, replacement
;
1129 register Lisp_Object tem
;
1130 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
1132 /* If OLD is its frame's root_window, then replacement is the new
1133 root_window for that frame. */
1135 if (EQ (old
, FRAME_ROOT_WINDOW (XFRAME (o
->frame
))))
1136 FRAME_ROOT_WINDOW (XFRAME (o
->frame
)) = replacement
;
1140 p
->width
= o
->width
;
1141 p
->height
= o
->height
;
1142 p
->desired_matrix
= p
->current_matrix
= 0;
1144 bzero (&p
->cursor
, sizeof (p
->cursor
));
1145 bzero (&p
->last_cursor
, sizeof (p
->last_cursor
));
1146 bzero (&p
->phys_cursor
, sizeof (p
->phys_cursor
));
1147 p
->phys_cursor_type
= -1;
1148 p
->phys_cursor_width
= -1;
1149 p
->must_be_updated_p
= 0;
1150 p
->pseudo_window_p
= 0;
1151 XSETFASTINT (p
->window_end_vpos
, 0);
1152 XSETFASTINT (p
->window_end_pos
, 0);
1153 p
->window_end_valid
= Qnil
;
1154 p
->frozen_window_start_p
= 0;
1155 p
->orig_top
= p
->orig_height
= Qnil
;
1157 p
->next
= tem
= o
->next
;
1159 XWINDOW (tem
)->prev
= replacement
;
1161 p
->prev
= tem
= o
->prev
;
1163 XWINDOW (tem
)->next
= replacement
;
1165 p
->parent
= tem
= o
->parent
;
1168 if (EQ (XWINDOW (tem
)->vchild
, old
))
1169 XWINDOW (tem
)->vchild
= replacement
;
1170 if (EQ (XWINDOW (tem
)->hchild
, old
))
1171 XWINDOW (tem
)->hchild
= replacement
;
1174 /*** Here, if replacement is a vertical combination
1175 and so is its new parent, we should make replacement's
1176 children be children of that parent instead. ***/
1179 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
1180 doc
: /* Remove WINDOW from the display. Default is selected window. */)
1182 register Lisp_Object window
;
1184 delete_window (window
);
1186 if (! NILP (Vwindow_configuration_change_hook
)
1187 && ! NILP (Vrun_hooks
))
1188 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
1194 delete_window (window
)
1195 register Lisp_Object window
;
1197 register Lisp_Object tem
, parent
, sib
;
1198 register struct window
*p
;
1199 register struct window
*par
;
1202 /* Because this function is called by other C code on non-leaf
1203 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1204 so we can't decode_window here. */
1206 window
= selected_window
;
1208 CHECK_WINDOW (window
);
1209 p
= XWINDOW (window
);
1211 /* It's okay to delete an already-deleted window. */
1212 if (NILP (p
->buffer
)
1214 && NILP (p
->vchild
))
1219 error ("Attempt to delete minibuffer or sole ordinary window");
1220 par
= XWINDOW (parent
);
1222 windows_or_buffers_changed
++;
1223 Vwindow_list
= Qnil
;
1224 f
= XFRAME (WINDOW_FRAME (p
));
1225 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
1227 /* Are we trying to delete any frame's selected window? */
1229 Lisp_Object swindow
, pwindow
;
1231 /* See if the frame's selected window is either WINDOW
1232 or any subwindow of it, by finding all that window's parents
1233 and comparing each one with WINDOW. */
1234 swindow
= FRAME_SELECTED_WINDOW (f
);
1239 while (!NILP (pwindow
))
1241 if (EQ (window
, pwindow
))
1243 pwindow
= XWINDOW (pwindow
)->parent
;
1246 /* If the window being deleted is not a parent of SWINDOW,
1247 then SWINDOW is ok as the new selected window. */
1248 if (!EQ (window
, pwindow
))
1250 /* Otherwise, try another window for SWINDOW. */
1251 swindow
= Fnext_window (swindow
, Qlambda
, Qnil
);;
1253 /* If we get back to the frame's selected window,
1254 it means there was no acceptable alternative,
1255 so we cannot delete. */
1256 if (EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1257 error ("Cannot delete window");
1260 /* If we need to change SWINDOW, do it. */
1261 if (! EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1263 /* If we're about to delete the selected window on the
1264 selected frame, then we should use Fselect_window to select
1265 the new window. On the other hand, if we're about to
1266 delete the selected window on any other frame, we shouldn't do
1267 anything but set the frame's selected_window slot. */
1268 if (EQ (FRAME_SELECTED_WINDOW (f
), selected_window
))
1269 Fselect_window (swindow
);
1271 FRAME_SELECTED_WINDOW (f
) = swindow
;
1276 /* tem is null for dummy parent windows
1277 (which have inferiors but not any contents themselves) */
1281 unchain_marker (p
->pointm
);
1282 unchain_marker (p
->start
);
1285 /* Free window glyph matrices. It is sure that they are allocated
1286 again when ADJUST_GLYPHS is called. Block input so that expose
1287 events and other events that access glyph matrices are not
1288 processed while we are changing them. */
1290 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f
)));
1294 XWINDOW (tem
)->prev
= p
->prev
;
1298 XWINDOW (tem
)->next
= p
->next
;
1300 if (EQ (window
, par
->hchild
))
1301 par
->hchild
= p
->next
;
1302 if (EQ (window
, par
->vchild
))
1303 par
->vchild
= p
->next
;
1305 /* Find one of our siblings to give our space to. */
1309 /* If p gives its space to its next sibling, that sibling needs
1310 to have its top/left side pulled back to where p's is.
1311 set_window_{height,width} will re-position the sibling's
1314 XWINDOW (sib
)->top
= p
->top
;
1315 XWINDOW (sib
)->left
= p
->left
;
1318 /* Stretch that sibling. */
1319 if (!NILP (par
->vchild
))
1320 set_window_height (sib
,
1321 XFASTINT (XWINDOW (sib
)->height
) + XFASTINT (p
->height
),
1323 if (!NILP (par
->hchild
))
1324 set_window_width (sib
,
1325 XFASTINT (XWINDOW (sib
)->width
) + XFASTINT (p
->width
),
1328 /* If parent now has only one child,
1329 put the child into the parent's place. */
1333 if (NILP (XWINDOW (tem
)->next
))
1334 replace_window (parent
, tem
);
1336 /* Since we may be deleting combination windows, we must make sure that
1337 not only p but all its children have been marked as deleted. */
1338 if (! NILP (p
->hchild
))
1339 delete_all_subwindows (XWINDOW (p
->hchild
));
1340 else if (! NILP (p
->vchild
))
1341 delete_all_subwindows (XWINDOW (p
->vchild
));
1343 /* Mark this window as deleted. */
1344 p
->buffer
= p
->hchild
= p
->vchild
= Qnil
;
1346 /* Adjust glyph matrices. */
1353 /***********************************************************************
1355 ***********************************************************************/
1357 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1358 pointer. This is a callback function for foreach_window, used in
1359 function window_list. */
1362 add_window_to_list (w
, user_data
)
1366 Lisp_Object
*list
= (Lisp_Object
*) user_data
;
1368 XSETWINDOW (window
, w
);
1369 *list
= Fcons (window
, *list
);
1374 /* Return a list of all windows, for use by next_window. If
1375 Vwindow_list is a list, return that list. Otherwise, build a new
1376 list, cache it in Vwindow_list, and return that. */
1381 if (!CONSP (Vwindow_list
))
1385 Vwindow_list
= Qnil
;
1386 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
1388 Lisp_Object args
[2];
1390 /* We are visiting windows in canonical order, and add
1391 new windows at the front of args[1], which means we
1392 have to reverse this list at the end. */
1394 foreach_window (XFRAME (XCAR (tail
)), add_window_to_list
, &args
[1]);
1395 args
[0] = Vwindow_list
;
1396 args
[1] = Fnreverse (args
[1]);
1397 Vwindow_list
= Fnconc (2, args
);
1401 return Vwindow_list
;
1405 /* Value is non-zero if WINDOW satisfies the constraints given by
1406 OWINDOW, MINIBUF and ALL_FRAMES.
1408 MINIBUF t means WINDOW may be minibuffer windows.
1409 `lambda' means WINDOW may not be a minibuffer window.
1410 a window means a specific minibuffer window
1412 ALL_FRAMES t means search all frames,
1413 nil means search just current frame,
1414 `visible' means search just visible frames,
1415 0 means search visible and iconified frames,
1416 a window means search the frame that window belongs to,
1417 a frame means consider windows on that frame, only. */
1420 candidate_window_p (window
, owindow
, minibuf
, all_frames
)
1421 Lisp_Object window
, owindow
, minibuf
, all_frames
;
1423 struct window
*w
= XWINDOW (window
);
1424 struct frame
*f
= XFRAME (w
->frame
);
1425 int candidate_p
= 1;
1427 if (!BUFFERP (w
->buffer
))
1429 else if (MINI_WINDOW_P (w
)
1430 && (EQ (minibuf
, Qlambda
)
1431 || (WINDOWP (minibuf
) && !EQ (minibuf
, window
))))
1433 /* If MINIBUF is `lambda' don't consider any mini-windows.
1434 If it is a window, consider only that one. */
1437 else if (EQ (all_frames
, Qt
))
1439 else if (NILP (all_frames
))
1441 xassert (WINDOWP (owindow
));
1442 candidate_p
= EQ (w
->frame
, XWINDOW (owindow
)->frame
);
1444 else if (EQ (all_frames
, Qvisible
))
1446 FRAME_SAMPLE_VISIBILITY (f
);
1447 candidate_p
= FRAME_VISIBLE_P (f
);
1449 else if (INTEGERP (all_frames
) && XINT (all_frames
) == 0)
1451 FRAME_SAMPLE_VISIBILITY (f
);
1452 candidate_p
= FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
);
1454 else if (WINDOWP (all_frames
))
1455 candidate_p
= (EQ (FRAME_MINIBUF_WINDOW (f
), all_frames
)
1456 || EQ (XWINDOW (all_frames
)->frame
, w
->frame
)
1457 || EQ (XWINDOW (all_frames
)->frame
, FRAME_FOCUS_FRAME (f
)));
1458 else if (FRAMEP (all_frames
))
1459 candidate_p
= EQ (all_frames
, w
->frame
);
1465 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1466 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1470 decode_next_window_args (window
, minibuf
, all_frames
)
1471 Lisp_Object
*window
, *minibuf
, *all_frames
;
1474 *window
= selected_window
;
1476 CHECK_LIVE_WINDOW (*window
);
1478 /* MINIBUF nil may or may not include minibuffers. Decide if it
1480 if (NILP (*minibuf
))
1481 *minibuf
= minibuf_level
? minibuf_window
: Qlambda
;
1482 else if (!EQ (*minibuf
, Qt
))
1485 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1486 => count none of them, or a specific minibuffer window (the
1487 active one) to count. */
1489 /* ALL_FRAMES nil doesn't specify which frames to include. */
1490 if (NILP (*all_frames
))
1491 *all_frames
= (!EQ (*minibuf
, Qlambda
)
1492 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window
)->frame
))
1494 else if (EQ (*all_frames
, Qvisible
))
1496 else if (XFASTINT (*all_frames
) == 0)
1498 else if (FRAMEP (*all_frames
))
1500 else if (!EQ (*all_frames
, Qt
))
1503 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1504 search just current frame, `visible' meaning search just visible
1505 frames, 0 meaning search visible and iconified frames, or a
1506 window, meaning search the frame that window belongs to, or a
1507 frame, meaning consider windows on that frame, only. */
1511 /* Return the next or previous window of WINDOW in canonical ordering
1512 of windows. NEXT_P non-zero means return the next window. See the
1513 documentation string of next-window for the meaning of MINIBUF and
1517 next_window (window
, minibuf
, all_frames
, next_p
)
1518 Lisp_Object window
, minibuf
, all_frames
;
1521 decode_next_window_args (&window
, &minibuf
, &all_frames
);
1523 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1524 return the first window on the frame. */
1525 if (FRAMEP (all_frames
)
1526 && !EQ (all_frames
, XWINDOW (window
)->frame
))
1527 return Fframe_first_window (all_frames
);
1533 /* Find WINDOW in the list of all windows. */
1534 list
= Fmemq (window
, window_list ());
1536 /* Scan forward from WINDOW to the end of the window list. */
1538 for (list
= XCDR (list
); CONSP (list
); list
= XCDR (list
))
1539 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1542 /* Scan from the start of the window list up to WINDOW. */
1544 for (list
= Vwindow_list
;
1545 CONSP (list
) && !EQ (XCAR (list
), window
);
1547 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1551 window
= XCAR (list
);
1555 Lisp_Object candidate
, list
;
1557 /* Scan through the list of windows for candidates. If there are
1558 candidate windows in front of WINDOW, the last one of these
1559 is the one we want. If there are candidates following WINDOW
1560 in the list, again the last one of these is the one we want. */
1562 for (list
= window_list (); CONSP (list
); list
= XCDR (list
))
1564 if (EQ (XCAR (list
), window
))
1566 if (WINDOWP (candidate
))
1569 else if (candidate_window_p (XCAR (list
), window
, minibuf
,
1571 candidate
= XCAR (list
);
1574 if (WINDOWP (candidate
))
1582 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
1583 doc
: /* Return next window after WINDOW in canonical ordering of windows.
1584 If omitted, WINDOW defaults to the selected window.
1586 Optional second arg MINIBUF t means count the minibuffer window even
1587 if not active. MINIBUF nil or omitted means count the minibuffer iff
1588 it is active. MINIBUF neither t nor nil means not to count the
1589 minibuffer even if it is active.
1591 Several frames may share a single minibuffer; if the minibuffer
1592 counts, all windows on all frames that share that minibuffer count
1593 too. Therefore, `next-window' can be used to iterate through the
1594 set of windows even when the minibuffer is on another frame. If the
1595 minibuffer does not count, only windows from WINDOW's frame count.
1597 Optional third arg ALL-FRAMES t means include windows on all frames.
1598 ALL-FRAMES nil or omitted means cycle within the frames as specified
1599 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1600 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1601 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1602 Anything else means restrict to WINDOW's frame.
1604 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1605 `next-window' to iterate through the entire cycle of acceptable
1606 windows, eventually ending up back at the window you started with.
1607 `previous-window' traverses the same cycle, in the reverse order. */)
1608 (window
, minibuf
, all_frames
)
1609 Lisp_Object window
, minibuf
, all_frames
;
1611 return next_window (window
, minibuf
, all_frames
, 1);
1615 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
1616 doc
: /* Return the window preceding WINDOW in canonical ordering of windows.
1617 If omitted, WINDOW defaults to the selected window.
1619 Optional second arg MINIBUF t means count the minibuffer window even
1620 if not active. MINIBUF nil or omitted means count the minibuffer iff
1621 it is active. MINIBUF neither t nor nil means not to count the
1622 minibuffer even if it is active.
1624 Several frames may share a single minibuffer; if the minibuffer
1625 counts, all windows on all frames that share that minibuffer count
1626 too. Therefore, `previous-window' can be used to iterate through
1627 the set of windows even when the minibuffer is on another frame. If
1628 the minibuffer does not count, only windows from WINDOW's frame count
1630 Optional third arg ALL-FRAMES t means include windows on all frames.
1631 ALL-FRAMES nil or omitted means cycle within the frames as specified
1632 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1633 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1634 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1635 Anything else means restrict to WINDOW's frame.
1637 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1638 `previous-window' to iterate through the entire cycle of acceptable
1639 windows, eventually ending up back at the window you started with.
1640 `next-window' traverses the same cycle, in the reverse order. */)
1641 (window
, minibuf
, all_frames
)
1642 Lisp_Object window
, minibuf
, all_frames
;
1644 return next_window (window
, minibuf
, all_frames
, 0);
1648 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
1649 doc
: /* Select the ARG'th different window on this frame.
1650 All windows on current frame are arranged in a cyclic order.
1651 This command selects the window ARG steps away in that order.
1652 A negative ARG moves in the opposite order. If the optional second
1653 argument ALL_FRAMES is non-nil, cycle through all frames. */)
1655 Lisp_Object arg
, all_frames
;
1661 window
= selected_window
;
1663 for (i
= XINT (arg
); i
> 0; --i
)
1664 window
= Fnext_window (window
, Qnil
, all_frames
);
1666 window
= Fprevious_window (window
, Qnil
, all_frames
);
1668 Fselect_window (window
);
1673 DEFUN ("window-list", Fwindow_list
, Swindow_list
, 0, 3, 0,
1674 doc
: /* Return a list of windows on FRAME, starting with WINDOW.
1675 FRAME nil or omitted means use the selected frame.
1676 WINDOW nil or omitted means use the selected window.
1677 MINIBUF t means include the minibuffer window, even if it isn't active.
1678 MINIBUF nil or omitted means include the minibuffer window only
1680 MINIBUF neither nil nor t means never include the minibuffer window. */)
1681 (frame
, minibuf
, window
)
1682 Lisp_Object frame
, minibuf
, window
;
1685 window
= selected_window
;
1687 frame
= selected_frame
;
1689 if (!EQ (frame
, XWINDOW (window
)->frame
))
1690 error ("Window is on a different frame");
1692 return window_list_1 (window
, minibuf
, frame
);
1696 /* Return a list of windows in canonical ordering. Arguments are like
1697 for `next-window'. */
1700 window_list_1 (window
, minibuf
, all_frames
)
1701 Lisp_Object window
, minibuf
, all_frames
;
1703 Lisp_Object tail
, list
;
1705 decode_next_window_args (&window
, &minibuf
, &all_frames
);
1708 for (tail
= window_list (); CONSP (tail
); tail
= XCDR (tail
))
1709 if (candidate_window_p (XCAR (tail
), window
, minibuf
, all_frames
))
1710 list
= Fcons (XCAR (tail
), list
);
1712 return Fnreverse (list
);
1717 /* Look at all windows, performing an operation specified by TYPE
1719 If FRAMES is Qt, look at all frames;
1720 Qnil, look at just the selected frame;
1721 Qvisible, look at visible frames;
1722 a frame, just look at windows on that frame.
1723 If MINI is non-zero, perform the operation on minibuffer windows too. */
1728 GET_BUFFER_WINDOW
, /* Arg is buffer */
1729 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
1730 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
1731 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
1733 UNSHOW_BUFFER
, /* Arg is buffer */
1738 window_loop (type
, obj
, mini
, frames
)
1739 enum window_loop type
;
1740 Lisp_Object obj
, frames
;
1743 Lisp_Object window
, windows
, best_window
, frame_arg
;
1745 struct gcpro gcpro1
;
1747 /* If we're only looping through windows on a particular frame,
1748 frame points to that frame. If we're looping through windows
1749 on all frames, frame is 0. */
1750 if (FRAMEP (frames
))
1751 f
= XFRAME (frames
);
1752 else if (NILP (frames
))
1753 f
= SELECTED_FRAME ();
1758 frame_arg
= Qlambda
;
1759 else if (XFASTINT (frames
) == 0)
1761 else if (EQ (frames
, Qvisible
))
1766 /* frame_arg is Qlambda to stick to one frame,
1767 Qvisible to consider all visible frames,
1770 /* Pick a window to start with. */
1774 window
= FRAME_SELECTED_WINDOW (f
);
1776 window
= FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1778 windows
= window_list_1 (window
, mini
? Qt
: Qnil
, frame_arg
);
1782 for (; CONSP (windows
); windows
= CDR (windows
))
1786 window
= XCAR (windows
);
1787 w
= XWINDOW (window
);
1789 /* Note that we do not pay attention here to whether the frame
1790 is visible, since Fwindow_list skips non-visible frames if
1791 that is desired, under the control of frame_arg. */
1792 if (!MINI_WINDOW_P (w
)
1793 /* For UNSHOW_BUFFER, we must always consider all windows. */
1794 || type
== UNSHOW_BUFFER
1795 || (mini
&& minibuf_level
> 0))
1798 case GET_BUFFER_WINDOW
:
1799 if (EQ (w
->buffer
, obj
)
1800 /* Don't find any minibuffer window
1801 except the one that is currently in use. */
1802 && (MINI_WINDOW_P (w
)
1803 ? EQ (window
, minibuf_window
)
1806 if (NILP (best_window
))
1807 best_window
= window
;
1808 else if (EQ (window
, selected_window
))
1809 /* For compatibility with 20.x, prefer to return
1811 best_window
= window
;
1815 case GET_LRU_WINDOW
:
1816 /* t as arg means consider only full-width windows */
1817 if (!NILP (obj
) && !WINDOW_FULL_WIDTH_P (w
))
1819 /* Ignore dedicated windows and minibuffers. */
1820 if (MINI_WINDOW_P (w
) || !NILP (w
->dedicated
))
1822 if (NILP (best_window
)
1823 || (XFASTINT (XWINDOW (best_window
)->use_time
)
1824 > XFASTINT (w
->use_time
)))
1825 best_window
= window
;
1828 case DELETE_OTHER_WINDOWS
:
1829 if (!EQ (window
, obj
))
1830 Fdelete_window (window
);
1833 case DELETE_BUFFER_WINDOWS
:
1834 if (EQ (w
->buffer
, obj
))
1836 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1838 /* If this window is dedicated, and in a frame of its own,
1840 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
1841 && !NILP (w
->dedicated
)
1842 && other_visible_frames (f
))
1844 /* Skip the other windows on this frame.
1845 There might be one, the minibuffer! */
1846 while (CONSP (XCDR (windows
))
1847 && EQ (XWINDOW (XCAR (windows
))->frame
,
1848 XWINDOW (XCAR (XCDR (windows
)))->frame
))
1849 windows
= XCDR (windows
);
1851 /* Now we can safely delete the frame. */
1852 Fdelete_frame (w
->frame
, Qnil
);
1854 else if (NILP (w
->parent
))
1856 /* If we're deleting the buffer displayed in the
1857 only window on the frame, find a new buffer to
1860 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
1861 Fset_window_buffer (window
, buffer
);
1862 if (EQ (window
, selected_window
))
1863 Fset_buffer (w
->buffer
);
1866 Fdelete_window (window
);
1870 case GET_LARGEST_WINDOW
:
1872 /* Ignore dedicated windows and minibuffers. */
1873 if (MINI_WINDOW_P (w
) || !NILP (w
->dedicated
))
1876 if (NILP (best_window
))
1877 best_window
= window
;
1880 struct window
*b
= XWINDOW (best_window
);
1881 if (XFASTINT (w
->height
) * XFASTINT (w
->width
)
1882 > XFASTINT (b
->height
) * XFASTINT (b
->width
))
1883 best_window
= window
;
1889 if (EQ (w
->buffer
, obj
))
1892 struct frame
*f
= XFRAME (w
->frame
);
1894 /* Find another buffer to show in this window. */
1895 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
1897 /* If this window is dedicated, and in a frame of its own,
1899 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
1900 && !NILP (w
->dedicated
)
1901 && other_visible_frames (f
))
1903 /* Skip the other windows on this frame.
1904 There might be one, the minibuffer! */
1905 while (CONSP (XCDR (windows
))
1906 && EQ (XWINDOW (XCAR (windows
))->frame
,
1907 XWINDOW (XCAR (XCDR (windows
)))->frame
))
1908 windows
= XCDR (windows
);
1910 /* Now we can safely delete the frame. */
1911 Fdelete_frame (w
->frame
, Qnil
);
1915 /* Otherwise show a different buffer in the window. */
1916 w
->dedicated
= Qnil
;
1917 Fset_window_buffer (window
, buffer
);
1918 if (EQ (window
, selected_window
))
1919 Fset_buffer (w
->buffer
);
1924 /* Check for a window that has a killed buffer. */
1925 case CHECK_ALL_WINDOWS
:
1926 if (! NILP (w
->buffer
)
1927 && NILP (XBUFFER (w
->buffer
)->name
))
1931 case WINDOW_LOOP_UNUSED
:
1940 /* Used for debugging. Abort if any window has a dead buffer. */
1943 check_all_windows ()
1945 window_loop (CHECK_ALL_WINDOWS
, Qnil
, 1, Qt
);
1948 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 1, 0,
1949 doc
: /* Return the window least recently selected or used for display.
1950 If optional argument FRAME is `visible', search all visible frames.
1951 If FRAME is 0, search all visible and iconified frames.
1952 If FRAME is t, search all frames.
1953 If FRAME is nil, search only the selected frame.
1954 If FRAME is a frame, search only that frame. */)
1958 register Lisp_Object w
;
1959 /* First try for a window that is full-width */
1960 w
= window_loop (GET_LRU_WINDOW
, Qt
, 0, frame
);
1961 if (!NILP (w
) && !EQ (w
, selected_window
))
1963 /* If none of them, try the rest */
1964 return window_loop (GET_LRU_WINDOW
, Qnil
, 0, frame
);
1967 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 1, 0,
1968 doc
: /* Return the largest window in area.
1969 If optional argument FRAME is `visible', search all visible frames.
1970 If FRAME is 0, search all visible and iconified frames.
1971 If FRAME is t, search all frames.
1972 If FRAME is nil, search only the selected frame.
1973 If FRAME is a frame, search only that frame. */)
1977 return window_loop (GET_LARGEST_WINDOW
, Qnil
, 0,
1981 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 1, 2, 0,
1982 doc
: /* Return a window currently displaying BUFFER, or nil if none.
1983 If optional argument FRAME is `visible', search all visible frames.
1984 If optional argument FRAME is 0, search all visible and iconified frames.
1985 If FRAME is t, search all frames.
1986 If FRAME is nil, search only the selected frame.
1987 If FRAME is a frame, search only that frame. */)
1989 Lisp_Object buffer
, frame
;
1991 buffer
= Fget_buffer (buffer
);
1992 if (BUFFERP (buffer
))
1993 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
1998 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
2000 doc
: /* Make WINDOW (or the selected window) fill its frame.
2001 Only the frame WINDOW is on is affected.
2002 This function tries to reduce display jumps
2003 by keeping the text previously visible in WINDOW
2004 in the same place on the frame. Doing this depends on
2005 the value of (window-start WINDOW), so if calling this function
2006 in a program gives strange scrolling, make sure the window-start
2007 value is reasonable when this function is called. */)
2016 window
= selected_window
;
2018 CHECK_LIVE_WINDOW (window
);
2019 w
= XWINDOW (window
);
2021 startpos
= marker_position (w
->start
);
2022 top
= XFASTINT (w
->top
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2024 if (MINI_WINDOW_P (w
) && top
> 0)
2025 error ("Can't expand minibuffer to full frame");
2027 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_FRAME (w
));
2029 /* Try to minimize scrolling, by setting the window start to the point
2030 will cause the text at the old window start to be at the same place
2031 on the frame. But don't try to do this if the window start is
2032 outside the visible portion (as might happen when the display is
2033 not current, due to typeahead). */
2034 new_top
= XFASTINT (w
->top
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2036 && startpos
>= BUF_BEGV (XBUFFER (w
->buffer
))
2037 && startpos
<= BUF_ZV (XBUFFER (w
->buffer
)))
2039 struct position pos
;
2040 struct buffer
*obuf
= current_buffer
;
2042 Fset_buffer (w
->buffer
);
2043 /* This computation used to temporarily move point, but that can
2044 have unwanted side effects due to text properties. */
2045 pos
= *vmotion (startpos
, -top
, w
);
2047 set_marker_both (w
->start
, w
->buffer
, pos
.bufpos
, pos
.bytepos
);
2048 w
->window_end_valid
= Qnil
;
2049 w
->start_at_line_beg
= ((pos
.bytepos
== BEGV_BYTE
2050 || FETCH_BYTE (pos
.bytepos
- 1) == '\n') ? Qt
2052 /* We need to do this, so that the window-scroll-functions
2054 w
->optional_new_start
= Qt
;
2056 set_buffer_internal (obuf
);
2062 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
2063 1, 2, "bDelete windows on (buffer): ",
2064 doc
: /* Delete all windows showing BUFFER.
2065 Optional second argument FRAME controls which frames are affected.
2066 If optional argument FRAME is `visible', search all visible frames.
2067 If FRAME is 0, search all visible and iconified frames.
2068 If FRAME is nil, search all frames.
2069 If FRAME is t, search only the selected frame.
2070 If FRAME is a frame, search only that frame. */)
2072 Lisp_Object buffer
, frame
;
2074 /* FRAME uses t and nil to mean the opposite of what window_loop
2078 else if (EQ (frame
, Qt
))
2083 buffer
= Fget_buffer (buffer
);
2084 CHECK_BUFFER (buffer
);
2085 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, frame
);
2091 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
2092 Sreplace_buffer_in_windows
,
2093 1, 1, "bReplace buffer in windows: ",
2094 doc
: /* Replace BUFFER with some other buffer in all windows showing it. */)
2100 buffer
= Fget_buffer (buffer
);
2101 CHECK_BUFFER (buffer
);
2102 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
2107 /* Replace BUFFER with some other buffer in all windows
2108 of all frames, even those on other keyboards. */
2111 replace_buffer_in_all_windows (buffer
)
2115 Lisp_Object tail
, frame
;
2117 /* A single call to window_loop won't do the job
2118 because it only considers frames on the current keyboard.
2119 So loop manually over frames, and handle each one. */
2120 FOR_EACH_FRAME (tail
, frame
)
2121 window_loop (UNSHOW_BUFFER
, buffer
, 1, frame
);
2123 window_loop (UNSHOW_BUFFER
, buffer
, 1, Qt
);
2127 /* Set the height of WINDOW and all its inferiors. */
2129 /* The smallest acceptable dimensions for a window. Anything smaller
2130 might crash Emacs. */
2132 #define MIN_SAFE_WINDOW_WIDTH (2)
2133 #define MIN_SAFE_WINDOW_HEIGHT (1)
2135 /* Make sure that window_min_height and window_min_width are
2136 not too small; if they are, set them to safe minima. */
2139 check_min_window_sizes ()
2141 /* Smaller values might permit a crash. */
2142 if (window_min_width
< MIN_SAFE_WINDOW_WIDTH
)
2143 window_min_width
= MIN_SAFE_WINDOW_WIDTH
;
2144 if (window_min_height
< MIN_SAFE_WINDOW_HEIGHT
)
2145 window_min_height
= MIN_SAFE_WINDOW_HEIGHT
;
2148 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2149 minimum allowable size. */
2152 check_frame_size (frame
, rows
, cols
)
2156 /* For height, we have to see:
2157 how many windows the frame has at minimum (one or two),
2158 and whether it has a menu bar or other special stuff at the top. */
2160 = ((FRAME_MINIBUF_ONLY_P (frame
) || ! FRAME_HAS_MINIBUF_P (frame
))
2161 ? MIN_SAFE_WINDOW_HEIGHT
2162 : 2 * MIN_SAFE_WINDOW_HEIGHT
);
2164 if (FRAME_TOP_MARGIN (frame
) > 0)
2165 min_height
+= FRAME_TOP_MARGIN (frame
);
2167 if (*rows
< min_height
)
2169 if (*cols
< MIN_SAFE_WINDOW_WIDTH
)
2170 *cols
= MIN_SAFE_WINDOW_WIDTH
;
2174 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2175 check if W's width can be changed, otherwise check W's height.
2176 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2177 siblings, too. If none of the siblings is resizable, WINDOW isn't
2181 window_fixed_size_p (w
, width_p
, check_siblings_p
)
2183 int width_p
, check_siblings_p
;
2188 if (!NILP (w
->hchild
))
2190 c
= XWINDOW (w
->hchild
);
2194 /* A horiz. combination is fixed-width if all of if its
2196 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2197 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2198 fixed_p
= c
== NULL
;
2202 /* A horiz. combination is fixed-height if one of if its
2204 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2205 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2206 fixed_p
= c
!= NULL
;
2209 else if (!NILP (w
->vchild
))
2211 c
= XWINDOW (w
->vchild
);
2215 /* A vert. combination is fixed-width if one of if its
2217 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2218 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2219 fixed_p
= c
!= NULL
;
2223 /* A vert. combination is fixed-height if all of if its
2225 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2226 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2227 fixed_p
= c
== NULL
;
2230 else if (BUFFERP (w
->buffer
))
2232 if (w
->height_fixed_p
&& !width_p
)
2236 struct buffer
*old
= current_buffer
;
2239 current_buffer
= XBUFFER (w
->buffer
);
2240 val
= find_symbol_value (Qwindow_size_fixed
);
2241 current_buffer
= old
;
2244 if (!EQ (val
, Qunbound
))
2246 fixed_p
= !NILP (val
);
2249 && ((EQ (val
, Qheight
) && width_p
)
2250 || (EQ (val
, Qwidth
) && !width_p
)))
2255 /* Can't tell if this one is resizable without looking at
2256 siblings. If all siblings are fixed-size this one is too. */
2257 if (!fixed_p
&& check_siblings_p
&& WINDOWP (w
->parent
))
2261 for (child
= w
->prev
; !NILP (child
); child
= XWINDOW (child
)->prev
)
2262 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2266 for (child
= w
->next
; !NILP (child
); child
= XWINDOW (child
)->next
)
2267 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2281 /* Return the minimum size of window W, not taking fixed-width windows
2282 into account. WIDTH_P non-zero means return the minimum width,
2283 otherwise return the minimum height. If W is a combination window,
2284 compute the minimum size from the minimum sizes of W's children. */
2287 window_min_size_1 (w
, width_p
)
2294 if (!NILP (w
->hchild
))
2296 c
= XWINDOW (w
->hchild
);
2301 /* The min width of a horizontal combination is
2302 the sum of the min widths of its children. */
2305 size
+= window_min_size_1 (c
, width_p
);
2306 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2311 /* The min height a horizontal combination equals
2312 the maximum of all min height of its children. */
2315 int min_size
= window_min_size_1 (c
, width_p
);
2316 size
= max (min_size
, size
);
2317 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2321 else if (!NILP (w
->vchild
))
2323 c
= XWINDOW (w
->vchild
);
2328 /* The min width of a vertical combination is
2329 the maximum of the min widths of its children. */
2332 int min_size
= window_min_size_1 (c
, width_p
);
2333 size
= max (min_size
, size
);
2334 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2339 /* The min height of a vertical combination equals
2340 the sum of the min height of its children. */
2343 size
+= window_min_size_1 (c
, width_p
);
2344 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2351 size
= window_min_width
;
2354 if (MINI_WINDOW_P (w
)
2355 || (!WINDOW_WANTS_MODELINE_P (w
)
2356 && !WINDOW_WANTS_HEADER_LINE_P (w
)))
2359 size
= window_min_height
;
2367 /* Return the minimum size of window W, taking fixed-size windows into
2368 account. WIDTH_P non-zero means return the minimum width,
2369 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2370 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2371 unless FIXED is null. */
2374 window_min_size (w
, width_p
, ignore_fixed_p
, fixed
)
2376 int width_p
, ignore_fixed_p
, *fixed
;
2383 fixed_p
= window_fixed_size_p (w
, width_p
, 1);
2389 size
= width_p
? XFASTINT (w
->width
) : XFASTINT (w
->height
);
2391 size
= window_min_size_1 (w
, width_p
);
2397 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2398 WINDOW's width. Resize WINDOW's children, if any, so that they
2399 keep their proportionate size relative to WINDOW. Propagate
2400 WINDOW's top or left edge position to children. Delete windows
2401 that become too small unless NODELETE_P is non-zero.
2403 If NODELETE_P is 2, that means we do delete windows that are
2404 too small, even if they were too small before! */
2407 size_window (window
, size
, width_p
, nodelete_p
)
2409 int size
, width_p
, nodelete_p
;
2411 struct window
*w
= XWINDOW (window
);
2413 Lisp_Object child
, *forward
, *sideward
;
2414 int old_size
, min_size
;
2416 if (nodelete_p
== 2)
2419 check_min_window_sizes ();
2420 size
= max (0, size
);
2422 /* If the window has been "too small" at one point,
2423 don't delete it for being "too small" in the future.
2424 Preserve it as long as that is at all possible. */
2427 old_size
= XINT (w
->width
);
2428 min_size
= window_min_width
;
2432 old_size
= XINT (w
->height
);
2433 min_size
= window_min_height
;
2436 if (old_size
< min_size
&& nodelete_p
!= 2)
2437 w
->too_small_ok
= Qt
;
2439 /* Maybe delete WINDOW if it's too small. */
2440 if (nodelete_p
!= 1 && !NILP (w
->parent
))
2442 if (!MINI_WINDOW_P (w
) && !NILP (w
->too_small_ok
))
2443 min_size
= width_p
? MIN_SAFE_WINDOW_WIDTH
: MIN_SAFE_WINDOW_HEIGHT
;
2445 min_size
= width_p
? window_min_width
: window_min_height
;
2447 if (size
< min_size
)
2449 delete_window (window
);
2454 /* Set redisplay hints. */
2455 w
->last_modified
= make_number (0);
2456 w
->last_overlay_modified
= make_number (0);
2457 windows_or_buffers_changed
++;
2458 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w
->frame
)) = 1;
2462 sideward
= &w
->vchild
;
2463 forward
= &w
->hchild
;
2464 w
->width
= make_number (size
);
2468 sideward
= &w
->hchild
;
2469 forward
= &w
->vchild
;
2470 w
->height
= make_number (size
);
2471 w
->orig_height
= Qnil
;
2474 if (!NILP (*sideward
))
2476 for (child
= *sideward
; !NILP (child
); child
= c
->next
)
2478 c
= XWINDOW (child
);
2483 size_window (child
, size
, width_p
, nodelete_p
);
2486 else if (!NILP (*forward
))
2488 int fixed_size
, each
, extra
, n
;
2489 int resize_fixed_p
, nfixed
;
2490 int last_pos
, first_pos
, nchildren
, total
;
2492 /* Determine the fixed-size portion of the this window, and the
2493 number of child windows. */
2494 fixed_size
= nchildren
= nfixed
= total
= 0;
2495 for (child
= *forward
; !NILP (child
); child
= c
->next
, ++nchildren
)
2499 c
= XWINDOW (child
);
2500 child_size
= width_p
? XINT (c
->width
) : XINT (c
->height
);
2501 total
+= child_size
;
2503 if (window_fixed_size_p (c
, width_p
, 0))
2505 fixed_size
+= child_size
;
2510 /* If the new size is smaller than fixed_size, or if there
2511 aren't any resizable windows, allow resizing fixed-size
2513 resize_fixed_p
= nfixed
== nchildren
|| size
< fixed_size
;
2515 /* Compute how many lines/columns to add to each child. The
2516 value of extra takes care of rounding errors. */
2517 n
= resize_fixed_p
? nchildren
: nchildren
- nfixed
;
2518 each
= (size
- total
) / n
;
2519 extra
= (size
- total
) - n
* each
;
2521 /* Compute new children heights and edge positions. */
2522 first_pos
= width_p
? XINT (w
->left
) : XINT (w
->top
);
2523 last_pos
= first_pos
;
2524 for (child
= *forward
; !NILP (child
); child
= c
->next
)
2526 int new_size
, old_size
;
2528 c
= XWINDOW (child
);
2529 old_size
= width_p
? XFASTINT (c
->width
) : XFASTINT (c
->height
);
2530 new_size
= old_size
;
2532 /* The top or left edge position of this child equals the
2533 bottom or right edge of its predecessor. */
2535 c
->left
= make_number (last_pos
);
2537 c
->top
= make_number (last_pos
);
2539 /* If this child can be resized, do it. */
2540 if (resize_fixed_p
|| !window_fixed_size_p (c
, width_p
, 0))
2542 new_size
= old_size
+ each
+ extra
;
2546 /* Set new height. Note that size_window also propagates
2547 edge positions to children, so it's not a no-op if we
2548 didn't change the child's size. */
2549 size_window (child
, new_size
, width_p
, 1);
2551 /* Remember the bottom/right edge position of this child; it
2552 will be used to set the top/left edge of the next child. */
2553 last_pos
+= new_size
;
2556 /* We should have covered the parent exactly with child windows. */
2557 xassert (size
== last_pos
- first_pos
);
2559 /* Now delete any children that became too small. */
2561 for (child
= *forward
; !NILP (child
); child
= c
->next
)
2564 c
= XWINDOW (child
);
2565 child_size
= width_p
? XINT (c
->width
) : XINT (c
->height
);
2566 size_window (child
, child_size
, width_p
, 2);
2571 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2572 WINDOW's children. NODELETE non-zero means don't delete windows
2573 that become too small in the process. (The caller should check
2574 later and do so if appropriate.) */
2577 set_window_height (window
, height
, nodelete
)
2582 size_window (window
, height
, 0, nodelete
);
2586 /* Set WINDOW's width to WIDTH, and recursively change the width of
2587 WINDOW's children. NODELETE non-zero means don't delete windows
2588 that become too small in the process. (The caller should check
2589 later and do so if appropriate.) */
2592 set_window_width (window
, width
, nodelete
)
2597 size_window (window
, width
, 1, nodelete
);
2601 int window_select_count
;
2604 Fset_window_buffer_unwind (obuf
)
2612 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2613 means it's allowed to run hooks. See make_frame for a case where
2614 it's not allowed. */
2617 set_window_buffer (window
, buffer
, run_hooks_p
)
2618 Lisp_Object window
, buffer
;
2621 struct window
*w
= XWINDOW (window
);
2622 struct buffer
*b
= XBUFFER (buffer
);
2623 int count
= specpdl_ptr
- specpdl
;
2627 if (EQ (window
, selected_window
))
2628 b
->last_selected_window
= window
;
2630 /* Update time stamps of buffer display. */
2631 if (INTEGERP (b
->display_count
))
2632 XSETINT (b
->display_count
, XINT (b
->display_count
) + 1);
2633 b
->display_time
= Fcurrent_time ();
2635 XSETFASTINT (w
->window_end_pos
, 0);
2636 XSETFASTINT (w
->window_end_vpos
, 0);
2637 bzero (&w
->last_cursor
, sizeof w
->last_cursor
);
2638 w
->window_end_valid
= Qnil
;
2639 w
->hscroll
= w
->min_hscroll
= make_number (0);
2641 set_marker_both (w
->pointm
, buffer
, BUF_PT (b
), BUF_PT_BYTE (b
));
2642 set_marker_restricted (w
->start
,
2643 make_number (b
->last_window_start
),
2645 w
->start_at_line_beg
= Qnil
;
2646 w
->force_start
= Qnil
;
2647 XSETFASTINT (w
->last_modified
, 0);
2648 XSETFASTINT (w
->last_overlay_modified
, 0);
2649 windows_or_buffers_changed
++;
2651 /* We must select BUFFER for running the window-scroll-functions.
2652 If WINDOW is selected, switch permanently.
2653 Otherwise, switch but go back to the ambient buffer afterward. */
2654 if (EQ (window
, selected_window
))
2655 Fset_buffer (buffer
);
2656 /* We can't check ! NILP (Vwindow_scroll_functions) here
2657 because that might itself be a local variable. */
2658 else if (window_initialized
)
2660 record_unwind_protect (Fset_window_buffer_unwind
, Fcurrent_buffer ());
2661 Fset_buffer (buffer
);
2664 /* Set left and right marginal area width from buffer. */
2665 Fset_window_margins (window
, b
->left_margin_width
, b
->right_margin_width
);
2669 if (! NILP (Vwindow_scroll_functions
))
2670 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
2671 Fmarker_position (w
->start
));
2673 if (! NILP (Vwindow_configuration_change_hook
)
2674 && ! NILP (Vrun_hooks
))
2675 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
2678 unbind_to (count
, Qnil
);
2682 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 2, 0,
2683 doc
: /* Make WINDOW display BUFFER as its contents.
2684 BUFFER can be a buffer or buffer name. */)
2686 register Lisp_Object window
, buffer
;
2688 register Lisp_Object tem
;
2689 register struct window
*w
= decode_window (window
);
2691 XSETWINDOW (window
, w
);
2692 buffer
= Fget_buffer (buffer
);
2693 CHECK_BUFFER (buffer
);
2695 if (NILP (XBUFFER (buffer
)->name
))
2696 error ("Attempt to display deleted buffer");
2700 error ("Window is deleted");
2701 else if (! EQ (tem
, Qt
)) /* w->buffer is t when the window
2702 is first being set up. */
2704 if (!NILP (w
->dedicated
) && !EQ (tem
, buffer
))
2705 error ("Window is dedicated to `%s'",
2706 XSTRING (XBUFFER (tem
)->name
)->data
);
2711 set_window_buffer (window
, buffer
, 1);
2715 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 1, 0,
2716 doc
: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
2717 If WINDOW is not already selected, also make WINDOW's buffer current.
2718 Note that the main editor command loop
2719 selects the buffer of the selected window before each command. */)
2721 register Lisp_Object window
;
2723 return select_window_1 (window
, 1);
2726 /* Note that selected_window can be nil
2727 when this is called from Fset_window_configuration. */
2730 select_window_1 (window
, recordflag
)
2731 register Lisp_Object window
;
2734 register struct window
*w
;
2735 register struct window
*ow
;
2738 CHECK_LIVE_WINDOW (window
);
2740 w
= XWINDOW (window
);
2741 w
->frozen_window_start_p
= 0;
2743 XSETFASTINT (w
->use_time
, ++window_select_count
);
2744 if (EQ (window
, selected_window
))
2747 if (!NILP (selected_window
))
2749 ow
= XWINDOW (selected_window
);
2750 if (! NILP (ow
->buffer
))
2751 set_marker_both (ow
->pointm
, ow
->buffer
,
2752 BUF_PT (XBUFFER (ow
->buffer
)),
2753 BUF_PT_BYTE (XBUFFER (ow
->buffer
)));
2756 selected_window
= window
;
2757 sf
= SELECTED_FRAME ();
2758 if (XFRAME (WINDOW_FRAME (w
)) != sf
)
2760 XFRAME (WINDOW_FRAME (w
))->selected_window
= window
;
2761 /* Use this rather than Fhandle_switch_frame
2762 so that FRAME_FOCUS_FRAME is moved appropriately as we
2763 move around in the state where a minibuffer in a separate
2765 Fselect_frame (WINDOW_FRAME (w
), Qnil
);
2768 sf
->selected_window
= window
;
2771 record_buffer (w
->buffer
);
2772 Fset_buffer (w
->buffer
);
2774 XBUFFER (w
->buffer
)->last_selected_window
= window
;
2776 /* Go to the point recorded in the window.
2777 This is important when the buffer is in more
2778 than one window. It also matters when
2779 redisplay_window has altered point after scrolling,
2780 because it makes the change only in the window. */
2782 register int new_point
= marker_position (w
->pointm
);
2783 if (new_point
< BEGV
)
2785 else if (new_point
> ZV
)
2791 windows_or_buffers_changed
++;
2795 /* Deiconify the frame containing the window WINDOW,
2796 unless it is the selected frame;
2799 The reason for the exception for the selected frame
2800 is that it seems better not to change the selected frames visibility
2801 merely because of displaying a different buffer in it.
2802 The deiconification is useful when a buffer gets shown in
2803 another frame that you were not using lately. */
2806 display_buffer_1 (window
)
2809 Lisp_Object frame
= XWINDOW (window
)->frame
;
2810 FRAME_PTR f
= XFRAME (frame
);
2812 FRAME_SAMPLE_VISIBILITY (f
);
2814 if (!EQ (frame
, selected_frame
))
2816 if (FRAME_ICONIFIED_P (f
))
2817 Fmake_frame_visible (frame
);
2818 else if (FRAME_VISIBLE_P (f
))
2819 Fraise_frame (frame
);
2825 DEFUN ("special-display-p", Fspecial_display_p
, Sspecial_display_p
, 1, 1, 0,
2826 doc
: /* Returns non-nil if a buffer named BUFFER-NAME would be created specially.
2827 The value is actually t if the frame should be called with default frame
2828 parameters, and a list of frame parameters if they were specified.
2829 See `special-display-buffer-names', and `special-display-regexps'. */)
2831 Lisp_Object buffer_name
;
2835 CHECK_STRING (buffer_name
);
2837 tem
= Fmember (buffer_name
, Vspecial_display_buffer_names
);
2841 tem
= Fassoc (buffer_name
, Vspecial_display_buffer_names
);
2845 for (tem
= Vspecial_display_regexps
; CONSP (tem
); tem
= XCDR (tem
))
2847 Lisp_Object car
= XCAR (tem
);
2849 && fast_string_match (car
, buffer_name
) >= 0)
2851 else if (CONSP (car
)
2852 && STRINGP (XCAR (car
))
2853 && fast_string_match (XCAR (car
), buffer_name
) >= 0)
2859 DEFUN ("same-window-p", Fsame_window_p
, Ssame_window_p
, 1, 1, 0,
2860 doc
: /* Returns non-nil if a new buffer named BUFFER-NAME would use the same window.
2861 See `same-window-buffer-names' and `same-window-regexps'. */)
2863 Lisp_Object buffer_name
;
2867 CHECK_STRING (buffer_name
);
2869 tem
= Fmember (buffer_name
, Vsame_window_buffer_names
);
2873 tem
= Fassoc (buffer_name
, Vsame_window_buffer_names
);
2877 for (tem
= Vsame_window_regexps
; CONSP (tem
); tem
= XCDR (tem
))
2879 Lisp_Object car
= XCAR (tem
);
2881 && fast_string_match (car
, buffer_name
) >= 0)
2883 else if (CONSP (car
)
2884 && STRINGP (XCAR (car
))
2885 && fast_string_match (XCAR (car
), buffer_name
) >= 0)
2891 /* Use B so the default is (other-buffer). */
2892 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 3,
2893 "BDisplay buffer: \nP",
2894 doc
: /* Make BUFFER appear in some window but don't select it.
2895 BUFFER can be a buffer or a buffer name.
2896 If BUFFER is shown already in some window, just use that one,
2897 unless the window is the selected window and the optional second
2898 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
2899 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
2900 Returns the window displaying BUFFER.
2901 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
2902 displaying BUFFER, then simply raise that frame.
2904 The variables `special-display-buffer-names', `special-display-regexps',
2905 `same-window-buffer-names', and `same-window-regexps' customize how certain
2906 buffer names are handled.
2908 If optional argument FRAME is `visible', search all visible frames.
2909 If FRAME is 0, search all visible and iconified frames.
2910 If FRAME is t, search all frames.
2911 If FRAME is a frame, search only that frame.
2912 If FRAME is nil, search only the selected frame
2913 (actually the last nonminibuffer frame),
2914 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
2915 which means search visible and iconified frames.
2917 If `even-window-heights' is non-nil, window heights will be evened out
2918 if displaying the buffer causes two vertically adjacent windows to be
2920 (buffer
, not_this_window
, frame
)
2921 register Lisp_Object buffer
, not_this_window
, frame
;
2923 register Lisp_Object window
, tem
, swp
;
2927 buffer
= Fget_buffer (buffer
);
2928 CHECK_BUFFER (buffer
);
2930 if (!NILP (Vdisplay_buffer_function
))
2931 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
2933 if (NILP (not_this_window
)
2934 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
2935 return display_buffer_1 (selected_window
);
2937 /* See if the user has specified this buffer should appear
2938 in the selected window. */
2939 if (NILP (not_this_window
))
2941 swp
= Fsame_window_p (XBUFFER (buffer
)->name
);
2942 if (!NILP (swp
) && !no_switch_window (selected_window
))
2944 Fswitch_to_buffer (buffer
, Qnil
);
2945 return display_buffer_1 (selected_window
);
2949 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
2950 look for a window showing BUFFER on any visible or iconified frame.
2951 Otherwise search only the current frame. */
2954 else if (pop_up_frames
2955 || display_buffer_reuse_frames
2956 || last_nonminibuf_frame
== 0)
2957 XSETFASTINT (tem
, 0);
2959 XSETFRAME (tem
, last_nonminibuf_frame
);
2961 window
= Fget_buffer_window (buffer
, tem
);
2963 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
2964 return display_buffer_1 (window
);
2966 /* Certain buffer names get special handling. */
2967 if (!NILP (Vspecial_display_function
) && NILP (swp
))
2969 tem
= Fspecial_display_p (XBUFFER (buffer
)->name
);
2971 return call1 (Vspecial_display_function
, buffer
);
2973 return call2 (Vspecial_display_function
, buffer
, tem
);
2976 /* If there are no frames open that have more than a minibuffer,
2977 we need to create a new frame. */
2978 if (pop_up_frames
|| last_nonminibuf_frame
== 0)
2980 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
2981 Fset_window_buffer (window
, buffer
);
2982 return display_buffer_1 (window
);
2985 f
= SELECTED_FRAME ();
2987 || FRAME_MINIBUF_ONLY_P (f
)
2988 /* If the current frame is a special display frame,
2989 don't try to reuse its windows. */
2990 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f
))->dedicated
))
2995 if (FRAME_MINIBUF_ONLY_P (f
))
2996 XSETFRAME (frames
, last_nonminibuf_frame
);
2997 /* Don't try to create a window if would get an error */
2998 if (split_height_threshold
< window_min_height
<< 1)
2999 split_height_threshold
= window_min_height
<< 1;
3001 /* Note that both Fget_largest_window and Fget_lru_window
3002 ignore minibuffers and dedicated windows.
3003 This means they can return nil. */
3005 /* If the frame we would try to split cannot be split,
3006 try other frames. */
3007 if (FRAME_NO_SPLIT_P (NILP (frames
) ? f
: last_nonminibuf_frame
))
3009 /* Try visible frames first. */
3010 window
= Fget_largest_window (Qvisible
);
3011 /* If that didn't work, try iconified frames. */
3013 window
= Fget_largest_window (make_number (0));
3015 window
= Fget_largest_window (Qt
);
3018 window
= Fget_largest_window (frames
);
3020 /* If we got a tall enough full-width window that can be split,
3023 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
3024 && window_height (window
) >= split_height_threshold
3025 && WINDOW_FULL_WIDTH_P (XWINDOW (window
)))
3026 window
= Fsplit_window (window
, Qnil
, Qnil
);
3029 Lisp_Object upper
, lower
, other
;
3031 window
= Fget_lru_window (frames
);
3032 /* If the LRU window is selected, and big enough,
3033 and can be split, split it. */
3035 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
3036 && (EQ (window
, selected_window
)
3037 || EQ (XWINDOW (window
)->parent
, Qnil
))
3038 && window_height (window
) >= window_min_height
<< 1)
3039 window
= Fsplit_window (window
, Qnil
, Qnil
);
3040 /* If Fget_lru_window returned nil, try other approaches. */
3042 /* Try visible frames first. */
3044 window
= Fget_buffer_window (buffer
, Qvisible
);
3046 window
= Fget_largest_window (Qvisible
);
3047 /* If that didn't work, try iconified frames. */
3049 window
= Fget_buffer_window (buffer
, make_number (0));
3051 window
= Fget_largest_window (make_number (0));
3052 /* Try invisible frames. */
3054 window
= Fget_buffer_window (buffer
, Qt
);
3056 window
= Fget_largest_window (Qt
);
3057 /* As a last resort, make a new frame. */
3059 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
3060 /* If window appears above or below another,
3061 even out their heights. */
3062 other
= upper
= lower
= Qnil
;
3063 if (!NILP (XWINDOW (window
)->prev
))
3064 other
= upper
= XWINDOW (window
)->prev
, lower
= window
;
3065 if (!NILP (XWINDOW (window
)->next
))
3066 other
= lower
= XWINDOW (window
)->next
, upper
= window
;
3068 && !NILP (Veven_window_heights
)
3069 /* Check that OTHER and WINDOW are vertically arrayed. */
3070 && !EQ (XWINDOW (other
)->top
, XWINDOW (window
)->top
)
3071 && (XFASTINT (XWINDOW (other
)->height
)
3072 > XFASTINT (XWINDOW (window
)->height
)))
3074 int total
= (XFASTINT (XWINDOW (other
)->height
)
3075 + XFASTINT (XWINDOW (window
)->height
));
3076 enlarge_window (upper
,
3077 total
/ 2 - XFASTINT (XWINDOW (upper
)->height
),
3083 window
= Fget_lru_window (Qnil
);
3085 Fset_window_buffer (window
, buffer
);
3086 return display_buffer_1 (window
);
3090 temp_output_buffer_show (buf
)
3091 register Lisp_Object buf
;
3093 register struct buffer
*old
= current_buffer
;
3094 register Lisp_Object window
;
3095 register struct window
*w
;
3097 XBUFFER (buf
)->directory
= current_buffer
->directory
;
3100 BUF_SAVE_MODIFF (XBUFFER (buf
)) = MODIFF
;
3104 XBUFFER (buf
)->prevent_redisplay_optimizations_p
= 1;
3105 set_buffer_internal (old
);
3107 if (!EQ (Vtemp_buffer_show_function
, Qnil
))
3108 call1 (Vtemp_buffer_show_function
, buf
);
3111 window
= Fdisplay_buffer (buf
, Qnil
, Qnil
);
3113 if (!EQ (XWINDOW (window
)->frame
, selected_frame
))
3114 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
3115 Vminibuf_scroll_window
= window
;
3116 w
= XWINDOW (window
);
3117 XSETFASTINT (w
->hscroll
, 0);
3118 XSETFASTINT (w
->min_hscroll
, 0);
3119 set_marker_restricted_both (w
->start
, buf
, 1, 1);
3120 set_marker_restricted_both (w
->pointm
, buf
, 1, 1);
3122 /* Run temp-buffer-show-hook, with the chosen window selected
3123 and it sbuffer current. */
3124 if (!NILP (Vrun_hooks
))
3127 tem
= Fboundp (Qtemp_buffer_show_hook
);
3130 tem
= Fsymbol_value (Qtemp_buffer_show_hook
);
3133 int count
= specpdl_ptr
- specpdl
;
3134 Lisp_Object prev_window
;
3135 prev_window
= selected_window
;
3137 /* Select the window that was chosen, for running the hook. */
3138 record_unwind_protect (Fselect_window
, prev_window
);
3139 select_window_1 (window
, 0);
3140 Fset_buffer (w
->buffer
);
3141 call1 (Vrun_hooks
, Qtemp_buffer_show_hook
);
3142 select_window_1 (prev_window
, 0);
3143 unbind_to (count
, Qnil
);
3151 make_dummy_parent (window
)
3155 register struct window
*o
, *p
;
3158 o
= XWINDOW (window
);
3159 p
= allocate_window ();
3160 for (i
= 0; i
< VECSIZE (struct window
); ++i
)
3161 ((struct Lisp_Vector
*) p
)->contents
[i
]
3162 = ((struct Lisp_Vector
*)o
)->contents
[i
];
3163 XSETWINDOW (new, p
);
3165 XSETFASTINT (p
->sequence_number
, ++sequence_number
);
3167 /* Put new into window structure in place of window */
3168 replace_window (window
, new);
3181 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
3182 doc
: /* Split WINDOW, putting SIZE lines in the first of the pair.
3183 WINDOW defaults to selected one and SIZE to half its size.
3184 If optional third arg HORFLAG is non-nil, split side by side
3185 and put SIZE columns in the first of the pair. In that case,
3186 SIZE includes that window's scroll bar, or the divider column to its right. */)
3187 (window
, size
, horflag
)
3188 Lisp_Object window
, size
, horflag
;
3190 register Lisp_Object
new;
3191 register struct window
*o
, *p
;
3193 register int size_int
;
3196 window
= selected_window
;
3198 CHECK_LIVE_WINDOW (window
);
3200 o
= XWINDOW (window
);
3201 fo
= XFRAME (WINDOW_FRAME (o
));
3205 if (!NILP (horflag
))
3206 /* Calculate the size of the left-hand window, by dividing
3207 the usable space in columns by two.
3208 We round up, since the left-hand window may include
3209 a dividing line, while the right-hand may not. */
3210 size_int
= (XFASTINT (o
->width
) + 1) >> 1;
3212 size_int
= XFASTINT (o
->height
) >> 1;
3216 CHECK_NUMBER (size
);
3217 size_int
= XINT (size
);
3220 if (MINI_WINDOW_P (o
))
3221 error ("Attempt to split minibuffer window");
3222 else if (window_fixed_size_p (o
, !NILP (horflag
), 0))
3223 error ("Attempt to split fixed-size window");
3225 check_min_window_sizes ();
3229 if (size_int
< window_min_height
)
3230 error ("Window height %d too small (after splitting)", size_int
);
3231 if (size_int
+ window_min_height
> XFASTINT (o
->height
))
3232 error ("Window height %d too small (after splitting)",
3233 XFASTINT (o
->height
) - size_int
);
3234 if (NILP (o
->parent
)
3235 || NILP (XWINDOW (o
->parent
)->vchild
))
3237 make_dummy_parent (window
);
3239 XWINDOW (new)->vchild
= window
;
3244 if (size_int
< window_min_width
)
3245 error ("Window width %d too small (after splitting)", size_int
);
3247 if (size_int
+ window_min_width
> XFASTINT (o
->width
))
3248 error ("Window width %d too small (after splitting)",
3249 XFASTINT (o
->width
) - size_int
);
3250 if (NILP (o
->parent
)
3251 || NILP (XWINDOW (o
->parent
)->hchild
))
3253 make_dummy_parent (window
);
3255 XWINDOW (new)->hchild
= window
;
3259 /* Now we know that window's parent is a vertical combination
3260 if we are dividing vertically, or a horizontal combination
3261 if we are making side-by-side windows */
3263 windows_or_buffers_changed
++;
3264 FRAME_WINDOW_SIZES_CHANGED (fo
) = 1;
3265 new = make_window ();
3268 p
->frame
= o
->frame
;
3270 if (!NILP (p
->next
))
3271 XWINDOW (p
->next
)->prev
= new;
3274 p
->parent
= o
->parent
;
3276 p
->window_end_valid
= Qnil
;
3277 bzero (&p
->last_cursor
, sizeof p
->last_cursor
);
3279 /* Apportion the available frame space among the two new windows */
3281 if (!NILP (horflag
))
3283 p
->height
= o
->height
;
3285 XSETFASTINT (p
->width
, XFASTINT (o
->width
) - size_int
);
3286 XSETFASTINT (o
->width
, size_int
);
3287 XSETFASTINT (p
->left
, XFASTINT (o
->left
) + size_int
);
3292 p
->width
= o
->width
;
3293 XSETFASTINT (p
->height
, XFASTINT (o
->height
) - size_int
);
3294 XSETFASTINT (o
->height
, size_int
);
3295 XSETFASTINT (p
->top
, XFASTINT (o
->top
) + size_int
);
3298 /* Adjust glyph matrices. */
3300 Fset_window_buffer (new, o
->buffer
);
3304 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 3, "p",
3305 doc
: /* Make current window ARG lines bigger.
3306 From program, optional second arg non-nil means grow sideways ARG columns.
3307 Interactively, if an argument is not given, make the window one line bigger.
3309 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3310 of the siblings above or to the left of the selected window. Only
3311 siblings to the right or below are changed. */)
3312 (arg
, side
, preserve_before
)
3313 register Lisp_Object arg
, side
, preserve_before
;
3316 enlarge_window (selected_window
, XINT (arg
), !NILP (side
),
3317 !NILP (preserve_before
));
3319 if (! NILP (Vwindow_configuration_change_hook
))
3320 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
3325 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
3326 doc
: /* Make current window ARG lines smaller.
3327 From program, optional second arg non-nil means shrink sideways arg columns.
3328 Interactively, if an argument is not given, make the window one line smaller. */)
3330 register Lisp_Object arg
, side
;
3333 enlarge_window (selected_window
, -XINT (arg
), !NILP (side
), 0);
3335 if (! NILP (Vwindow_configuration_change_hook
))
3336 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
3342 window_height (window
)
3345 register struct window
*p
= XWINDOW (window
);
3346 return XFASTINT (p
->height
);
3350 window_width (window
)
3353 register struct window
*p
= XWINDOW (window
);
3354 return XFASTINT (p
->width
);
3359 *(widthflag ? &(XWINDOW (w)->left) : &(XWINDOW (w)->top))
3361 #define CURSIZE(w) \
3362 *(widthflag ? &(XWINDOW (w)->width) : &(XWINDOW (w)->height))
3365 /* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means
3366 increase its width. Siblings of the selected window are resized to
3367 fulfill the size request. If they become too small in the process,
3368 they will be deleted.
3370 If PRESERVE_BEFORE is nonzero, that means don't alter
3371 the siblings to the left or above WINDOW. */
3374 enlarge_window (window
, delta
, widthflag
, preserve_before
)
3376 int delta
, widthflag
, preserve_before
;
3378 Lisp_Object parent
, next
, prev
;
3382 int (*sizefun
) P_ ((Lisp_Object
))
3383 = widthflag
? window_width
: window_height
;
3384 void (*setsizefun
) P_ ((Lisp_Object
, int, int))
3385 = (widthflag
? set_window_width
: set_window_height
);
3387 /* Check values of window_min_width and window_min_height for
3389 check_min_window_sizes ();
3391 /* Give up if this window cannot be resized. */
3392 if (window_fixed_size_p (XWINDOW (window
), widthflag
, 1))
3393 error ("Window is not resizable");
3395 /* Find the parent of the selected window. */
3398 p
= XWINDOW (window
);
3404 error ("No other window to side of this one");
3409 ? !NILP (XWINDOW (parent
)->hchild
)
3410 : !NILP (XWINDOW (parent
)->vchild
))
3416 sizep
= &CURSIZE (window
);
3419 register int maxdelta
;
3421 /* Compute the maximum size increment this window can have. */
3423 if (preserve_before
)
3427 maxdelta
= (*sizefun
) (parent
) - XINT (*sizep
);
3428 /* Subtract size of siblings before, since we can't take that. */
3429 maxdelta
-= XINT (CURBEG (window
)) - XINT (CURBEG (parent
));
3432 maxdelta
= (!NILP (p
->next
) ? ((*sizefun
) (p
->next
)
3433 - window_min_size (XWINDOW (p
->next
),
3438 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - XINT (*sizep
)
3439 /* This is a main window followed by a minibuffer. */
3440 : !NILP (p
->next
) ? ((*sizefun
) (p
->next
)
3441 - window_min_size (XWINDOW (p
->next
),
3443 /* This is a minibuffer following a main window. */
3444 : !NILP (p
->prev
) ? ((*sizefun
) (p
->prev
)
3445 - window_min_size (XWINDOW (p
->prev
),
3447 /* This is a frame with only one window, a minibuffer-only
3448 or a minibufferless frame. */
3451 if (delta
> maxdelta
)
3452 /* This case traps trying to make the minibuffer
3453 the full frame, or make the only window aside from the
3454 minibuffer the full frame. */
3458 if (XINT (*sizep
) + delta
< window_min_size (XWINDOW (window
), widthflag
, 0, 0))
3460 delete_window (window
);
3467 /* Find the total we can get from other siblings without deleting them. */
3469 for (next
= p
->next
; ! NILP (next
); next
= XWINDOW (next
)->next
)
3470 maximum
+= (*sizefun
) (next
) - window_min_size (XWINDOW (next
),
3472 if (! preserve_before
)
3473 for (prev
= p
->prev
; ! NILP (prev
); prev
= XWINDOW (prev
)->prev
)
3474 maximum
+= (*sizefun
) (prev
) - window_min_size (XWINDOW (prev
),
3477 /* If we can get it all from them without deleting them, do so. */
3478 if (delta
<= maximum
)
3480 Lisp_Object first_unaffected
;
3481 Lisp_Object first_affected
;
3486 first_affected
= window
;
3487 /* Look at one sibling at a time,
3488 moving away from this window in both directions alternately,
3489 and take as much as we can get without deleting that sibling. */
3491 && (!NILP (next
) || (!preserve_before
&& !NILP (prev
))))
3495 int this_one
= ((*sizefun
) (next
)
3496 - window_min_size (XWINDOW (next
),
3497 widthflag
, 0, &fixed_p
));
3500 if (this_one
> delta
)
3503 (*setsizefun
) (next
, (*sizefun
) (next
) - this_one
, 0);
3504 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
3509 next
= XWINDOW (next
)->next
;
3515 if (!preserve_before
&& ! NILP (prev
))
3517 int this_one
= ((*sizefun
) (prev
)
3518 - window_min_size (XWINDOW (prev
),
3519 widthflag
, 0, &fixed_p
));
3522 if (this_one
> delta
)
3525 first_affected
= prev
;
3527 (*setsizefun
) (prev
, (*sizefun
) (prev
) - this_one
, 0);
3528 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
3533 prev
= XWINDOW (prev
)->prev
;
3537 xassert (delta
== 0);
3539 /* Now recalculate the edge positions of all the windows affected,
3540 based on the new sizes. */
3541 first_unaffected
= next
;
3542 prev
= first_affected
;
3543 for (next
= XWINDOW (prev
)->next
; ! EQ (next
, first_unaffected
);
3544 prev
= next
, next
= XWINDOW (next
)->next
)
3546 XSETINT (CURBEG (next
), XINT (CURBEG (prev
)) + (*sizefun
) (prev
));
3547 /* This does not change size of NEXT,
3548 but it propagates the new top edge to its children */
3549 (*setsizefun
) (next
, (*sizefun
) (next
), 0);
3554 register int delta1
;
3555 register int opht
= (*sizefun
) (parent
);
3557 if (opht
<= XINT (*sizep
) + delta
)
3559 /* If trying to grow this window to or beyond size of the parent,
3560 just delete all the sibling windows. */
3561 Lisp_Object start
, tem
, next
;
3563 start
= XWINDOW (parent
)->vchild
;
3565 start
= XWINDOW (parent
)->hchild
;
3567 /* Delete any siblings that come after WINDOW. */
3568 tem
= XWINDOW (window
)->next
;
3569 while (! NILP (tem
))
3571 next
= XWINDOW (tem
)->next
;
3572 delete_window (tem
);
3576 /* Delete any siblings that come after WINDOW.
3577 Note that if START is not WINDOW, then WINDOW still
3578 Fhas siblings, so WINDOW has not yet replaced its parent. */
3580 while (! EQ (tem
, window
))
3582 next
= XWINDOW (tem
)->next
;
3583 delete_window (tem
);
3589 /* Otherwise, make delta1 just right so that if we add
3590 delta1 lines to this window and to the parent, and then
3591 shrink the parent back to its original size, the new
3592 proportional size of this window will increase by delta.
3594 The function size_window will compute the new height h'
3595 of the window from delta1 as:
3598 x = delta1 - delta1/n * n for the 1st resizable child
3601 where n is the number of children that can be resized.
3602 We can ignore x by choosing a delta1 that is a multiple of
3603 n. We want the height of this window to come out as
3613 The number of children n rquals the number of resizable
3614 children of this window + 1 because we know window itself
3615 is resizable (otherwise we would have signalled an error. */
3617 struct window
*w
= XWINDOW (window
);
3621 for (s
= w
->next
; !NILP (s
); s
= XWINDOW (s
)->next
)
3622 if (!window_fixed_size_p (XWINDOW (s
), widthflag
, 0))
3624 for (s
= w
->prev
; !NILP (s
); s
= XWINDOW (s
)->prev
)
3625 if (!window_fixed_size_p (XWINDOW (s
), widthflag
, 0))
3630 /* Add delta1 lines or columns to this window, and to the parent,
3631 keeping things consistent while not affecting siblings. */
3632 XSETINT (CURSIZE (parent
), opht
+ delta1
);
3633 (*setsizefun
) (window
, XINT (*sizep
) + delta1
, 0);
3635 /* Squeeze out delta1 lines or columns from our parent,
3636 shriking this window and siblings proportionately.
3637 This brings parent back to correct size.
3638 Delta1 was calculated so this makes this window the desired size,
3639 taking it all out of the siblings. */
3640 (*setsizefun
) (parent
, opht
, 0);
3645 XSETFASTINT (p
->last_modified
, 0);
3646 XSETFASTINT (p
->last_overlay_modified
, 0);
3648 /* Adjust glyph matrices. */
3649 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
3657 /***********************************************************************
3658 Resizing Mini-Windows
3659 ***********************************************************************/
3661 static void shrink_window_lowest_first
P_ ((struct window
*, int));
3663 enum save_restore_action
3670 static int save_restore_orig_size
P_ ((struct window
*,
3671 enum save_restore_action
));
3673 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
3674 from lowest windows first. */
3677 shrink_window_lowest_first (w
, height
)
3685 xassert (!MINI_WINDOW_P (w
));
3687 /* Set redisplay hints. */
3688 XSETFASTINT (w
->last_modified
, 0);
3689 XSETFASTINT (w
->last_overlay_modified
, 0);
3690 windows_or_buffers_changed
++;
3691 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w
))) = 1;
3693 old_height
= XFASTINT (w
->height
);
3694 XSETFASTINT (w
->height
, height
);
3696 if (!NILP (w
->hchild
))
3698 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
3700 c
= XWINDOW (child
);
3702 shrink_window_lowest_first (c
, height
);
3705 else if (!NILP (w
->vchild
))
3707 Lisp_Object last_child
;
3708 int delta
= old_height
- height
;
3713 /* Find the last child. We are taking space from lowest windows
3714 first, so we iterate over children from the last child
3716 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
3719 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
3720 for (child
= last_child
; delta
&& !NILP (child
); child
= c
->prev
)
3724 c
= XWINDOW (child
);
3725 this_one
= XFASTINT (c
->height
) - MIN_SAFE_WINDOW_HEIGHT
;
3727 if (this_one
> delta
)
3730 shrink_window_lowest_first (c
, XFASTINT (c
->height
) - this_one
);
3734 /* Compute new positions. */
3735 last_top
= XINT (w
->top
);
3736 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
3738 c
= XWINDOW (child
);
3739 c
->top
= make_number (last_top
);
3740 shrink_window_lowest_first (c
, XFASTINT (c
->height
));
3741 last_top
+= XFASTINT (c
->height
);
3747 /* Save, restore, or check positions and sizes in the window tree
3748 rooted at W. ACTION says what to do.
3750 If ACTION is CHECK_ORIG_SIZES, check if orig_top and orig_height
3751 members are valid for all windows in the window tree. Value is
3752 non-zero if they are valid.
3754 If ACTION is SAVE_ORIG_SIZES, save members top and height in
3755 orig_top and orig_height for all windows in the tree.
3757 If ACTION is RESTORE_ORIG_SIZES, restore top and height from
3758 values stored in orig_top and orig_height for all windows. */
3761 save_restore_orig_size (w
, action
)
3763 enum save_restore_action action
;
3769 if (!NILP (w
->hchild
))
3771 if (!save_restore_orig_size (XWINDOW (w
->hchild
), action
))
3774 else if (!NILP (w
->vchild
))
3776 if (!save_restore_orig_size (XWINDOW (w
->vchild
), action
))
3782 case CHECK_ORIG_SIZES
:
3783 if (!INTEGERP (w
->orig_top
) || !INTEGERP (w
->orig_height
))
3787 case SAVE_ORIG_SIZES
:
3788 w
->orig_top
= w
->top
;
3789 w
->orig_height
= w
->height
;
3790 XSETFASTINT (w
->last_modified
, 0);
3791 XSETFASTINT (w
->last_overlay_modified
, 0);
3794 case RESTORE_ORIG_SIZES
:
3795 xassert (INTEGERP (w
->orig_top
) && INTEGERP (w
->orig_height
));
3796 w
->top
= w
->orig_top
;
3797 w
->height
= w
->orig_height
;
3798 w
->orig_height
= w
->orig_top
= Qnil
;
3799 XSETFASTINT (w
->last_modified
, 0);
3800 XSETFASTINT (w
->last_overlay_modified
, 0);
3807 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
3814 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
3815 without deleting other windows. */
3818 grow_mini_window (w
, delta
)
3822 struct frame
*f
= XFRAME (w
->frame
);
3823 struct window
*root
;
3825 xassert (MINI_WINDOW_P (w
));
3826 xassert (delta
>= 0);
3828 /* Check values of window_min_width and window_min_height for
3830 check_min_window_sizes ();
3832 /* Compute how much we can enlarge the mini-window without deleting
3834 root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
3837 int min_height
= window_min_size (root
, 0, 0, 0);
3838 if (XFASTINT (root
->height
) - delta
< min_height
)
3839 /* Note that the root window may already be smaller than
3841 delta
= max (0, XFASTINT (root
->height
) - min_height
);
3846 /* Save original window sizes and positions, if not already done. */
3847 if (!save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
3848 save_restore_orig_size (root
, SAVE_ORIG_SIZES
);
3850 /* Shrink other windows. */
3851 shrink_window_lowest_first (root
, XFASTINT (root
->height
) - delta
);
3853 /* Grow the mini-window. */
3854 w
->top
= make_number (XFASTINT (root
->top
) + XFASTINT (root
->height
));
3855 w
->height
= make_number (XFASTINT (w
->height
) + delta
);
3856 XSETFASTINT (w
->last_modified
, 0);
3857 XSETFASTINT (w
->last_overlay_modified
, 0);
3864 /* Shrink mini-window W. If there is recorded info about window sizes
3865 before a call to grow_mini_window, restore recorded window sizes.
3866 Otherwise, if the mini-window is higher than 1 line, resize it to 1
3870 shrink_mini_window (w
)
3873 struct frame
*f
= XFRAME (w
->frame
);
3874 struct window
*root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
3876 if (save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
3878 save_restore_orig_size (root
, RESTORE_ORIG_SIZES
);
3880 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
3881 windows_or_buffers_changed
= 1;
3883 else if (XFASTINT (w
->height
) > 1)
3885 /* Distribute the additional lines of the mini-window
3886 among the other windows. */
3888 XSETWINDOW (window
, w
);
3889 enlarge_window (window
, 1 - XFASTINT (w
->height
), 0, 0);
3895 /* Mark window cursors off for all windows in the window tree rooted
3896 at W by setting their phys_cursor_on_p flag to zero. Called from
3897 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3898 the frame are cleared. */
3901 mark_window_cursors_off (w
)
3906 if (!NILP (w
->hchild
))
3907 mark_window_cursors_off (XWINDOW (w
->hchild
));
3908 else if (!NILP (w
->vchild
))
3909 mark_window_cursors_off (XWINDOW (w
->vchild
));
3911 w
->phys_cursor_on_p
= 0;
3913 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
3918 /* Return number of lines of text (not counting mode lines) in W. */
3921 window_internal_height (w
)
3924 int ht
= XFASTINT (w
->height
);
3926 if (!MINI_WINDOW_P (w
))
3928 if (!NILP (w
->parent
)
3929 || !NILP (w
->vchild
)
3930 || !NILP (w
->hchild
)
3933 || WINDOW_WANTS_MODELINE_P (w
))
3936 if (WINDOW_WANTS_HEADER_LINE_P (w
))
3944 /* Return the number of columns in W.
3945 Don't count columns occupied by scroll bars or the vertical bar
3946 separating W from the sibling to its right. */
3949 window_internal_width (w
)
3952 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
3953 int width
= XINT (w
->width
);
3955 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3956 /* Scroll bars occupy a few columns. */
3957 width
-= FRAME_SCROLL_BAR_COLS (f
);
3958 else if (!WINDOW_RIGHTMOST_P (w
) && !WINDOW_FULL_WIDTH_P (w
))
3959 /* The column of `|' characters separating side-by-side windows
3960 occupies one column only. */
3963 /* On window-systems, areas to the left and right of the window
3964 are used as fringes. */
3965 if (FRAME_WINDOW_P (f
))
3966 width
-= FRAME_FRINGE_COLS (f
);
3972 /************************************************************************
3974 ***********************************************************************/
3976 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
3977 N screen-fulls, which is defined as the height of the window minus
3978 next_screen_context_lines. If WHOLE is zero, scroll up N lines
3979 instead. Negative values of N mean scroll down. NOERROR non-zero
3980 means don't signal an error if we try to move over BEGV or ZV,
3984 window_scroll (window
, n
, whole
, noerror
)
3990 /* If we must, use the pixel-based version which is much slower than
3991 the line-based one but can handle varying line heights. */
3992 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window
)->frame
)))
3993 window_scroll_pixel_based (window
, n
, whole
, noerror
);
3995 window_scroll_line_based (window
, n
, whole
, noerror
);
3999 /* Implementation of window_scroll that works based on pixel line
4000 heights. See the comment of window_scroll for parameter
4004 window_scroll_pixel_based (window
, n
, whole
, noerror
)
4011 struct window
*w
= XWINDOW (window
);
4012 struct text_pos start
;
4014 int this_scroll_margin
;
4016 /* True if we fiddled the window vscroll field without really scrolling. */
4019 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
4021 /* If PT is not visible in WINDOW, move back one half of
4022 the screen. Allow PT to be partially visible, otherwise
4023 something like (scroll-down 1) with PT in the line before
4024 the partially visible one would recenter. */
4025 tem
= Fpos_visible_in_window_p (make_number (PT
), window
, Qt
);
4028 /* Move backward half the height of the window. Performance note:
4029 vmotion used here is about 10% faster, but would give wrong
4030 results for variable height lines. */
4031 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4032 it
.current_y
= it
.last_visible_y
;
4033 move_it_vertically (&it
, - window_box_height (w
) / 2);
4035 /* The function move_iterator_vertically may move over more than
4036 the specified y-distance. If it->w is small, e.g. a
4037 mini-buffer window, we may end up in front of the window's
4038 display area. This is the case when Start displaying at the
4039 start of the line containing PT in this case. */
4040 if (it
.current_y
<= 0)
4042 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4043 move_it_vertically (&it
, 0);
4047 start
= it
.current
.pos
;
4050 /* If scroll_preserve_screen_position is non-zero, we try to set
4051 point in the same window line as it is now, so get that line. */
4052 if (!NILP (Vscroll_preserve_screen_position
))
4054 start_display (&it
, w
, start
);
4055 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
4056 preserve_y
= it
.current_y
;
4061 /* Move iterator it from start the specified distance forward or
4062 backward. The result is the new window start. */
4063 start_display (&it
, w
, start
);
4066 int screen_full
= (window_box_height (w
)
4067 - next_screen_context_lines
* CANON_Y_UNIT (it
.f
));
4068 int dy
= n
* screen_full
;
4070 /* Note that move_it_vertically always moves the iterator to the
4071 start of a line. So, if the last line doesn't have a newline,
4072 we would end up at the start of the line ending at ZV. */
4074 move_it_vertically_backward (&it
, -dy
);
4076 move_it_to (&it
, ZV
, -1, it
.current_y
+ dy
, -1,
4077 MOVE_TO_POS
| MOVE_TO_Y
);
4080 move_it_by_lines (&it
, n
, 1);
4082 /* End if we end up at ZV or BEGV. */
4083 if ((n
> 0 && IT_CHARPOS (it
) == ZV
)
4084 || (n
< 0 && IT_CHARPOS (it
) == CHARPOS (start
)))
4086 if (IT_CHARPOS (it
) == ZV
)
4088 if (it
.current_y
+ it
.max_ascent
+ it
.max_descent
4089 > it
.last_visible_y
)
4091 /* The last line was only partially visible, make it fully
4093 w
->vscroll
= (it
.last_visible_y
4094 - it
.current_y
+ it
.max_ascent
+ it
.max_descent
);
4095 adjust_glyphs (it
.f
);
4100 Fsignal (Qend_of_buffer
, Qnil
);
4104 if (w
->vscroll
!= 0)
4105 /* The first line was only partially visible, make it fully
4111 Fsignal (Qbeginning_of_buffer
, Qnil
);
4114 /* If control gets here, then we vscrolled. */
4116 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
4118 /* Don't try to change the window start below. */
4124 /* Set the window start, and set up the window for redisplay. */
4125 set_marker_restricted (w
->start
, make_number (IT_CHARPOS (it
)),
4127 w
->start_at_line_beg
= Fbolp ();
4128 w
->update_mode_line
= Qt
;
4129 XSETFASTINT (w
->last_modified
, 0);
4130 XSETFASTINT (w
->last_overlay_modified
, 0);
4131 /* Set force_start so that redisplay_window will run the
4132 window-scroll-functions. */
4133 w
->force_start
= Qt
;
4136 it
.current_y
= it
.vpos
= 0;
4138 /* Preserve the screen position if we must. */
4139 if (preserve_y
>= 0)
4141 move_it_to (&it
, -1, -1, preserve_y
, -1, MOVE_TO_Y
);
4142 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
4146 /* Move PT out of scroll margins. */
4147 this_scroll_margin
= max (0, scroll_margin
);
4148 this_scroll_margin
= min (this_scroll_margin
, XFASTINT (w
->height
) / 4);
4149 this_scroll_margin
*= CANON_Y_UNIT (it
.f
);
4153 /* We moved the window start towards ZV, so PT may be now
4154 in the scroll margin at the top. */
4155 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
4156 while (it
.current_y
< this_scroll_margin
)
4158 int prev
= it
.current_y
;
4159 move_it_by_lines (&it
, 1, 1);
4160 if (prev
== it
.current_y
)
4163 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
4167 int charpos
, bytepos
;
4169 /* We moved the window start towards BEGV, so PT may be now
4170 in the scroll margin at the bottom. */
4171 move_it_to (&it
, PT
, -1,
4172 it
.last_visible_y
- this_scroll_margin
- 1, -1,
4173 MOVE_TO_POS
| MOVE_TO_Y
);
4175 /* Save our position, in case it's correct. */
4176 charpos
= IT_CHARPOS (it
);
4177 bytepos
= IT_BYTEPOS (it
);
4179 /* See if point is on a partially visible line at the end. */
4180 move_it_by_lines (&it
, 1, 1);
4181 if (it
.current_y
> it
.last_visible_y
)
4182 /* The last line was only partially visible, so back up two
4183 lines to make sure we're on a fully visible line. */
4185 move_it_by_lines (&it
, -2, 0);
4186 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
4189 /* No, the position we saved is OK, so use it. */
4190 SET_PT_BOTH (charpos
, bytepos
);
4196 /* Implementation of window_scroll that works based on screen lines.
4197 See the comment of window_scroll for parameter descriptions. */
4200 window_scroll_line_based (window
, n
, whole
, noerror
)
4206 register struct window
*w
= XWINDOW (window
);
4207 register int opoint
= PT
, opoint_byte
= PT_BYTE
;
4208 register int pos
, pos_byte
;
4209 register int ht
= window_internal_height (w
);
4210 register Lisp_Object tem
;
4214 struct position posit
;
4217 /* If scrolling screen-fulls, compute the number of lines to
4218 scroll from the window's height. */
4220 n
*= max (1, ht
- next_screen_context_lines
);
4222 startpos
= marker_position (w
->start
);
4224 posit
= *compute_motion (startpos
, 0, 0, 0,
4226 window_internal_width (w
), XINT (w
->hscroll
),
4228 original_vpos
= posit
.vpos
;
4230 XSETFASTINT (tem
, PT
);
4231 tem
= Fpos_visible_in_window_p (tem
, window
, Qnil
);
4235 Fvertical_motion (make_number (- (ht
/ 2)), window
);
4240 lose
= n
< 0 && PT
== BEGV
;
4241 Fvertical_motion (make_number (n
), window
);
4245 SET_PT_BOTH (opoint
, opoint_byte
);
4252 Fsignal (Qbeginning_of_buffer
, Qnil
);
4257 int this_scroll_margin
= scroll_margin
;
4259 /* Don't use a scroll margin that is negative or too large. */
4260 if (this_scroll_margin
< 0)
4261 this_scroll_margin
= 0;
4263 if (XINT (w
->height
) < 4 * scroll_margin
)
4264 this_scroll_margin
= XINT (w
->height
) / 4;
4266 set_marker_restricted_both (w
->start
, w
->buffer
, pos
, pos_byte
);
4267 w
->start_at_line_beg
= bolp
;
4268 w
->update_mode_line
= Qt
;
4269 XSETFASTINT (w
->last_modified
, 0);
4270 XSETFASTINT (w
->last_overlay_modified
, 0);
4271 /* Set force_start so that redisplay_window will run
4272 the window-scroll-functions. */
4273 w
->force_start
= Qt
;
4275 if (whole
&& !NILP (Vscroll_preserve_screen_position
))
4277 SET_PT_BOTH (pos
, pos_byte
);
4278 Fvertical_motion (make_number (original_vpos
), window
);
4280 /* If we scrolled forward, put point enough lines down
4281 that it is outside the scroll margin. */
4286 if (this_scroll_margin
> 0)
4288 SET_PT_BOTH (pos
, pos_byte
);
4289 Fvertical_motion (make_number (this_scroll_margin
), window
);
4295 if (top_margin
<= opoint
)
4296 SET_PT_BOTH (opoint
, opoint_byte
);
4297 else if (!NILP (Vscroll_preserve_screen_position
))
4299 SET_PT_BOTH (pos
, pos_byte
);
4300 Fvertical_motion (make_number (original_vpos
), window
);
4303 SET_PT (top_margin
);
4309 /* If we scrolled backward, put point near the end of the window
4310 but not within the scroll margin. */
4311 SET_PT_BOTH (pos
, pos_byte
);
4312 tem
= Fvertical_motion (make_number (ht
- this_scroll_margin
), window
);
4313 if (XFASTINT (tem
) == ht
- this_scroll_margin
)
4316 bottom_margin
= PT
+ 1;
4318 if (bottom_margin
> opoint
)
4319 SET_PT_BOTH (opoint
, opoint_byte
);
4322 if (!NILP (Vscroll_preserve_screen_position
))
4324 SET_PT_BOTH (pos
, pos_byte
);
4325 Fvertical_motion (make_number (original_vpos
), window
);
4328 Fvertical_motion (make_number (-1), window
);
4337 Fsignal (Qend_of_buffer
, Qnil
);
4342 /* Scroll selected_window up or down. If N is nil, scroll a
4343 screen-full which is defined as the height of the window minus
4344 next_screen_context_lines. If N is the symbol `-', scroll.
4345 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4346 up. This is the guts of Fscroll_up and Fscroll_down. */
4349 scroll_command (n
, direction
)
4353 int count
= BINDING_STACK_SIZE ();
4355 xassert (abs (direction
) == 1);
4357 /* If selected window's buffer isn't current, make it current for
4358 the moment. But don't screw up if window_scroll gets an error. */
4359 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
4361 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
4362 Fset_buffer (XWINDOW (selected_window
)->buffer
);
4364 /* Make redisplay consider other windows than just selected_window. */
4365 ++windows_or_buffers_changed
;
4369 window_scroll (selected_window
, direction
, 1, 0);
4370 else if (EQ (n
, Qminus
))
4371 window_scroll (selected_window
, -direction
, 1, 0);
4374 n
= Fprefix_numeric_value (n
);
4375 window_scroll (selected_window
, XINT (n
) * direction
, 0, 0);
4378 unbind_to (count
, Qnil
);
4381 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "P",
4382 doc
: /* Scroll text of current window upward ARG lines; or near full screen if no ARG.
4383 A near full screen is `next-screen-context-lines' less than a full screen.
4384 Negative ARG means scroll downward.
4385 If ARG is the atom `-', scroll downward by nearly full screen.
4386 When calling from a program, supply as argument a number, nil, or `-'. */)
4390 scroll_command (arg
, 1);
4394 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "P",
4395 doc
: /* Scroll text of current window down ARG lines; or near full screen if no ARG.
4396 A near full screen is `next-screen-context-lines' less than a full screen.
4397 Negative ARG means scroll upward.
4398 If ARG is the atom `-', scroll upward by nearly full screen.
4399 When calling from a program, supply as argument a number, nil, or `-'. */)
4403 scroll_command (arg
, -1);
4407 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling
, Sother_window_for_scrolling
, 0, 0, 0,
4408 doc
: /* Return the other window for \"other window scroll\" commands.
4409 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4410 specifies the window.
4411 If `other-window-scroll-buffer' is non-nil, a window
4412 showing that buffer is used. */)
4417 if (MINI_WINDOW_P (XWINDOW (selected_window
))
4418 && !NILP (Vminibuf_scroll_window
))
4419 window
= Vminibuf_scroll_window
;
4420 /* If buffer is specified, scroll that buffer. */
4421 else if (!NILP (Vother_window_scroll_buffer
))
4423 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
4425 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
, Qnil
);
4429 /* Nothing specified; look for a neighboring window on the same
4431 window
= Fnext_window (selected_window
, Qnil
, Qnil
);
4433 if (EQ (window
, selected_window
))
4434 /* That didn't get us anywhere; look for a window on another
4437 window
= Fnext_window (window
, Qnil
, Qt
);
4438 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window
))))
4439 && ! EQ (window
, selected_window
));
4442 CHECK_LIVE_WINDOW (window
);
4444 if (EQ (window
, selected_window
))
4445 error ("There is no other window");
4450 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
4451 doc
: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4452 A near full screen is `next-screen-context-lines' less than a full screen.
4453 The next window is the one below the current one; or the one at the top
4454 if the current one is at the bottom. Negative ARG means scroll downward.
4455 If ARG is the atom `-', scroll downward by nearly full screen.
4456 When calling from a program, supply as argument a number, nil, or `-'.
4458 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4459 specifies the window to scroll.
4460 If `other-window-scroll-buffer' is non-nil, scroll the window
4461 showing that buffer, popping the buffer up if necessary. */)
4467 int count
= BINDING_STACK_SIZE ();
4469 window
= Fother_window_for_scrolling ();
4470 w
= XWINDOW (window
);
4472 /* Don't screw up if window_scroll gets an error. */
4473 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
4474 ++windows_or_buffers_changed
;
4476 Fset_buffer (w
->buffer
);
4477 SET_PT (marker_position (w
->pointm
));
4480 window_scroll (window
, 1, 1, 1);
4481 else if (EQ (arg
, Qminus
))
4482 window_scroll (window
, -1, 1, 1);
4488 window_scroll (window
, XINT (arg
), 0, 1);
4491 set_marker_both (w
->pointm
, Qnil
, PT
, PT_BYTE
);
4492 unbind_to (count
, Qnil
);
4497 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 0, 1, "P",
4498 doc
: /* Scroll selected window display ARG columns left.
4499 Default for ARG is window width minus 2.
4500 Value is the total amount of leftward horizontal scrolling in
4501 effect after the change.
4502 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4503 a lower bound for automatic scrolling, i.e. automatic scrolling
4504 will not scroll a window to a column less than the value returned
4505 by this function. */)
4507 register Lisp_Object arg
;
4511 struct window
*w
= XWINDOW (selected_window
);
4514 XSETFASTINT (arg
, window_internal_width (w
) - 2);
4516 arg
= Fprefix_numeric_value (arg
);
4518 hscroll
= XINT (w
->hscroll
) + XINT (arg
);
4519 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
4521 if (interactive_p (0))
4522 w
->min_hscroll
= w
->hscroll
;
4527 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 0, 1, "P",
4528 doc
: /* Scroll selected window display ARG columns right.
4529 Default for ARG is window width minus 2.
4530 Value is the total amount of leftward horizontal scrolling in
4531 effect after the change.
4532 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4533 a lower bound for automatic scrolling, i.e. automatic scrolling
4534 will not scroll a window to a column less than the value returned
4535 by this function. */)
4537 register Lisp_Object arg
;
4541 struct window
*w
= XWINDOW (selected_window
);
4544 XSETFASTINT (arg
, window_internal_width (w
) - 2);
4546 arg
= Fprefix_numeric_value (arg
);
4548 hscroll
= XINT (w
->hscroll
) - XINT (arg
);
4549 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
4551 if (interactive_p (0))
4552 w
->min_hscroll
= w
->hscroll
;
4557 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window
, Sminibuffer_selected_window
, 0, 0, 0,
4558 doc
: /* Return the window which was selected when entering the minibuffer.
4559 Returns nil, if current window is not a minibuffer window. */)
4562 if (minibuf_level
> 0
4563 && MINI_WINDOW_P (XWINDOW (selected_window
))
4564 && !NILP (minibuf_selected_window
)
4565 && WINDOW_LIVE_P (minibuf_selected_window
))
4566 return minibuf_selected_window
;
4571 /* Value is the number of lines actually displayed in window W,
4572 as opposed to its height. */
4575 displayed_window_lines (w
)
4579 struct text_pos start
;
4580 int height
= window_box_height (w
);
4581 struct buffer
*old_buffer
;
4584 if (XBUFFER (w
->buffer
) != current_buffer
)
4586 old_buffer
= current_buffer
;
4587 set_buffer_internal (XBUFFER (w
->buffer
));
4592 /* In case W->start is out of the accessible range, do something
4593 reasonable. This happens in Info mode when Info-scroll-down
4594 calls (recenter -1) while W->start is 1. */
4595 if (XMARKER (w
->start
)->charpos
< BEGV
)
4596 SET_TEXT_POS (start
, BEGV
, BEGV_BYTE
);
4597 else if (XMARKER (w
->start
)->charpos
> ZV
)
4598 SET_TEXT_POS (start
, ZV
, ZV_BYTE
);
4600 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
4602 start_display (&it
, w
, start
);
4603 move_it_vertically (&it
, height
);
4604 bottom_y
= line_bottom_y (&it
);
4606 /* Add in empty lines at the bottom of the window. */
4607 if (bottom_y
< height
)
4609 int uy
= CANON_Y_UNIT (it
.f
);
4610 it
.vpos
+= (height
- bottom_y
+ uy
- 1) / uy
;
4614 set_buffer_internal (old_buffer
);
4620 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
4621 doc
: /* Center point in window and redisplay frame.
4622 With prefix argument ARG, recenter putting point on screen line ARG
4623 relative to the current window. If ARG is negative, it counts up from the
4624 bottom of the window. (ARG should be less than the height of the window.)
4626 If ARG is omitted or nil, erase the entire frame and then
4627 redraw with point in the center of the current window.
4628 Just C-u as prefix means put point in the center of the window
4629 and redisplay normally--don't erase and redraw the frame. */)
4631 register Lisp_Object arg
;
4633 struct window
*w
= XWINDOW (selected_window
);
4634 struct buffer
*buf
= XBUFFER (w
->buffer
);
4635 struct buffer
*obuf
= current_buffer
;
4637 int charpos
, bytepos
;
4639 /* If redisplay is suppressed due to an error, try again. */
4640 obuf
->display_error_modiff
= 0;
4646 /* Invalidate pixel data calculated for all compositions. */
4647 for (i
= 0; i
< n_compositions
; i
++)
4648 composition_table
[i
]->font
= NULL
;
4650 Fredraw_frame (w
->frame
);
4651 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w
)));
4654 else if (CONSP (arg
)) /* Just C-u. */
4658 arg
= Fprefix_numeric_value (arg
);
4662 set_buffer_internal (buf
);
4664 /* Handle centering on a graphical frame specially. Such frames can
4665 have variable-height lines and centering point on the basis of
4666 line counts would lead to strange effects. */
4667 if (FRAME_WINDOW_P (XFRAME (w
->frame
)))
4674 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
4675 start_display (&it
, w
, pt
);
4676 move_it_vertically (&it
, - window_box_height (w
) / 2);
4677 charpos
= IT_CHARPOS (it
);
4678 bytepos
= IT_BYTEPOS (it
);
4680 else if (XINT (arg
) < 0)
4684 int y0
, y1
, h
, nlines
;
4686 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
4687 start_display (&it
, w
, pt
);
4690 /* The amount of pixels we have to move back is the window
4691 height minus what's displayed in the line containing PT,
4692 and the lines below. */
4693 nlines
= - XINT (arg
) - 1;
4694 move_it_by_lines (&it
, nlines
, 1);
4696 y1
= line_bottom_y (&it
);
4698 /* If we can't move down NLINES lines because we hit
4699 the end of the buffer, count in some empty lines. */
4700 if (it
.vpos
< nlines
)
4701 y1
+= (nlines
- it
.vpos
) * CANON_Y_UNIT (it
.f
);
4703 h
= window_box_height (w
) - (y1
- y0
);
4705 start_display (&it
, w
, pt
);
4706 move_it_vertically (&it
, - h
);
4707 charpos
= IT_CHARPOS (it
);
4708 bytepos
= IT_BYTEPOS (it
);
4712 struct position pos
;
4713 pos
= *vmotion (PT
, - XINT (arg
), w
);
4714 charpos
= pos
.bufpos
;
4715 bytepos
= pos
.bytepos
;
4720 struct position pos
;
4721 int ht
= window_internal_height (w
);
4724 arg
= make_number (ht
/ 2);
4725 else if (XINT (arg
) < 0)
4726 arg
= make_number (XINT (arg
) + ht
);
4728 pos
= *vmotion (PT
, - XINT (arg
), w
);
4729 charpos
= pos
.bufpos
;
4730 bytepos
= pos
.bytepos
;
4733 /* Set the new window start. */
4734 set_marker_both (w
->start
, w
->buffer
, charpos
, bytepos
);
4735 w
->window_end_valid
= Qnil
;
4736 w
->force_start
= Qt
;
4737 if (bytepos
== BEGV_BYTE
|| FETCH_BYTE (bytepos
- 1) == '\n')
4738 w
->start_at_line_beg
= Qt
;
4740 w
->start_at_line_beg
= Qnil
;
4742 set_buffer_internal (obuf
);
4747 DEFUN ("window-text-height", Fwindow_text_height
, Swindow_text_height
,
4749 doc
: /* Return the height in lines of the text display area of WINDOW.
4750 This doesn't include the mode-line (or header-line if any) or any
4751 partial-height lines in the text display area. */)
4755 struct window
*w
= decode_window (window
);
4756 int pixel_height
= window_box_height (w
);
4757 int line_height
= pixel_height
/ CANON_Y_UNIT (XFRAME (w
->frame
));
4758 return make_number (line_height
);
4763 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
4765 doc
: /* Position point relative to window.
4766 With no argument, position point at center of window.
4767 An argument specifies vertical position within the window;
4768 zero means top of window, negative means relative to bottom of window. */)
4772 struct window
*w
= XWINDOW (selected_window
);
4776 window
= selected_window
;
4777 start
= marker_position (w
->start
);
4778 if (start
< BEGV
|| start
> ZV
)
4780 int height
= window_internal_height (w
);
4781 Fvertical_motion (make_number (- (height
/ 2)), window
);
4782 set_marker_both (w
->start
, w
->buffer
, PT
, PT_BYTE
);
4783 w
->start_at_line_beg
= Fbolp ();
4784 w
->force_start
= Qt
;
4787 Fgoto_char (w
->start
);
4789 lines
= displayed_window_lines (w
);
4791 XSETFASTINT (arg
, lines
/ 2);
4794 arg
= Fprefix_numeric_value (arg
);
4796 XSETINT (arg
, XINT (arg
) + lines
);
4799 /* Skip past a partially visible first line. */
4801 XSETINT (arg
, XINT (arg
) + 1);
4803 return Fvertical_motion (arg
, window
);
4808 /***********************************************************************
4809 Window Configuration
4810 ***********************************************************************/
4812 struct save_window_data
4814 EMACS_INT size_from_Lisp_Vector_struct
;
4815 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
4816 Lisp_Object frame_width
, frame_height
, frame_menu_bar_lines
;
4817 Lisp_Object frame_tool_bar_lines
;
4818 Lisp_Object selected_frame
;
4819 Lisp_Object current_window
;
4820 Lisp_Object current_buffer
;
4821 Lisp_Object minibuf_scroll_window
;
4822 Lisp_Object minibuf_selected_window
;
4823 Lisp_Object root_window
;
4824 Lisp_Object focus_frame
;
4825 /* Record the values of window-min-width and window-min-height
4826 so that window sizes remain consistent with them. */
4827 Lisp_Object min_width
, min_height
;
4828 /* A vector, each of whose elements is a struct saved_window
4830 Lisp_Object saved_windows
;
4833 /* This is saved as a Lisp_Vector */
4836 /* these first two must agree with struct Lisp_Vector in lisp.h */
4837 EMACS_INT size_from_Lisp_Vector_struct
;
4838 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
4841 Lisp_Object buffer
, start
, pointm
, mark
;
4842 Lisp_Object left
, top
, width
, height
, hscroll
, min_hscroll
;
4843 Lisp_Object parent
, prev
;
4844 Lisp_Object start_at_line_beg
;
4845 Lisp_Object display_table
;
4846 Lisp_Object orig_top
, orig_height
;
4849 #define SAVED_WINDOW_VECTOR_SIZE 17 /* Arg to Fmake_vector */
4851 #define SAVED_WINDOW_N(swv,n) \
4852 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4854 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
4855 doc
: /* Return t if OBJECT is a window-configuration object. */)
4859 if (WINDOW_CONFIGURATIONP (object
))
4864 DEFUN ("window-configuration-frame", Fwindow_configuration_frame
, Swindow_configuration_frame
, 1, 1, 0,
4865 doc
: /* Return the frame that CONFIG, a window-configuration object, is about. */)
4869 register struct save_window_data
*data
;
4870 struct Lisp_Vector
*saved_windows
;
4872 if (! WINDOW_CONFIGURATIONP (config
))
4873 wrong_type_argument (Qwindow_configuration_p
, config
);
4875 data
= (struct save_window_data
*) XVECTOR (config
);
4876 saved_windows
= XVECTOR (data
->saved_windows
);
4877 return XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
4880 DEFUN ("set-window-configuration", Fset_window_configuration
,
4881 Sset_window_configuration
, 1, 1, 0,
4882 doc
: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
4883 CONFIGURATION must be a value previously returned
4884 by `current-window-configuration' (which see).
4885 If CONFIGURATION was made from a frame that is now deleted,
4886 only frame-independent values can be restored. In this case,
4887 the return value is nil. Otherwise the value is t. */)
4889 Lisp_Object configuration
;
4891 register struct save_window_data
*data
;
4892 struct Lisp_Vector
*saved_windows
;
4893 Lisp_Object new_current_buffer
;
4898 while (!WINDOW_CONFIGURATIONP (configuration
))
4899 wrong_type_argument (Qwindow_configuration_p
, configuration
);
4901 data
= (struct save_window_data
*) XVECTOR (configuration
);
4902 saved_windows
= XVECTOR (data
->saved_windows
);
4904 new_current_buffer
= data
->current_buffer
;
4905 if (NILP (XBUFFER (new_current_buffer
)->name
))
4906 new_current_buffer
= Qnil
;
4909 if (XBUFFER (new_current_buffer
) == current_buffer
)
4913 frame
= XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
4916 /* If f is a dead frame, don't bother rebuilding its window tree.
4917 However, there is other stuff we should still try to do below. */
4918 if (FRAME_LIVE_P (f
))
4920 register struct window
*w
;
4921 register struct saved_window
*p
;
4922 struct window
*root_window
;
4923 struct window
**leaf_windows
;
4927 /* If the frame has been resized since this window configuration was
4928 made, we change the frame to the size specified in the
4929 configuration, restore the configuration, and then resize it
4930 back. We keep track of the prevailing height in these variables. */
4931 int previous_frame_height
= FRAME_HEIGHT (f
);
4932 int previous_frame_width
= FRAME_WIDTH (f
);
4933 int previous_frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
4934 int previous_frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
4936 /* The mouse highlighting code could get screwed up
4937 if it runs during this. */
4940 if (XFASTINT (data
->frame_height
) != previous_frame_height
4941 || XFASTINT (data
->frame_width
) != previous_frame_width
)
4942 change_frame_size (f
, XFASTINT (data
->frame_height
),
4943 XFASTINT (data
->frame_width
), 0, 0, 0);
4944 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4945 if (XFASTINT (data
->frame_menu_bar_lines
)
4946 != previous_frame_menu_bar_lines
)
4947 x_set_menu_bar_lines (f
, data
->frame_menu_bar_lines
, make_number (0));
4948 #ifdef HAVE_WINDOW_SYSTEM
4949 if (XFASTINT (data
->frame_tool_bar_lines
)
4950 != previous_frame_tool_bar_lines
)
4951 x_set_tool_bar_lines (f
, data
->frame_tool_bar_lines
, make_number (0));
4955 /* "Swap out" point from the selected window
4956 into its buffer. We do this now, before
4957 restoring the window contents, and prevent it from
4958 being done later on when we select a new window. */
4959 if (! NILP (XWINDOW (selected_window
)->buffer
))
4961 w
= XWINDOW (selected_window
);
4962 set_marker_both (w
->pointm
,
4964 BUF_PT (XBUFFER (w
->buffer
)),
4965 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
4968 windows_or_buffers_changed
++;
4969 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
4971 /* Problem: Freeing all matrices and later allocating them again
4972 is a serious redisplay flickering problem. What we would
4973 really like to do is to free only those matrices not reused
4975 root_window
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4977 = (struct window
**) alloca (count_windows (root_window
)
4978 * sizeof (struct window
*));
4979 n_leaf_windows
= get_leaf_windows (root_window
, leaf_windows
, 0);
4981 /* Temporarily avoid any problems with windows that are smaller
4982 than they are supposed to be. */
4983 window_min_height
= 1;
4984 window_min_width
= 1;
4987 Mark all windows now on frame as "deleted".
4988 Restoring the new configuration "undeletes" any that are in it.
4990 Save their current buffers in their height fields, since we may
4991 need it later, if a buffer saved in the configuration is now
4993 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
4995 for (k
= 0; k
< saved_windows
->size
; k
++)
4997 p
= SAVED_WINDOW_N (saved_windows
, k
);
4998 w
= XWINDOW (p
->window
);
5001 if (!NILP (p
->parent
))
5002 w
->parent
= SAVED_WINDOW_N (saved_windows
,
5003 XFASTINT (p
->parent
))->window
;
5007 if (!NILP (p
->prev
))
5009 w
->prev
= SAVED_WINDOW_N (saved_windows
,
5010 XFASTINT (p
->prev
))->window
;
5011 XWINDOW (w
->prev
)->next
= p
->window
;
5016 if (!NILP (w
->parent
))
5018 if (EQ (p
->width
, XWINDOW (w
->parent
)->width
))
5020 XWINDOW (w
->parent
)->vchild
= p
->window
;
5021 XWINDOW (w
->parent
)->hchild
= Qnil
;
5025 XWINDOW (w
->parent
)->hchild
= p
->window
;
5026 XWINDOW (w
->parent
)->vchild
= Qnil
;
5031 /* If we squirreled away the buffer in the window's height,
5033 if (BUFFERP (w
->height
))
5034 w
->buffer
= w
->height
;
5037 w
->width
= p
->width
;
5038 w
->height
= p
->height
;
5039 w
->hscroll
= p
->hscroll
;
5040 w
->min_hscroll
= p
->min_hscroll
;
5041 w
->display_table
= p
->display_table
;
5042 w
->orig_top
= p
->orig_top
;
5043 w
->orig_height
= p
->orig_height
;
5044 XSETFASTINT (w
->last_modified
, 0);
5045 XSETFASTINT (w
->last_overlay_modified
, 0);
5047 /* Reinstall the saved buffer and pointers into it. */
5048 if (NILP (p
->buffer
))
5049 w
->buffer
= p
->buffer
;
5052 if (!NILP (XBUFFER (p
->buffer
)->name
))
5053 /* If saved buffer is alive, install it. */
5055 w
->buffer
= p
->buffer
;
5056 w
->start_at_line_beg
= p
->start_at_line_beg
;
5057 set_marker_restricted (w
->start
, p
->start
, w
->buffer
);
5058 set_marker_restricted (w
->pointm
, p
->pointm
, w
->buffer
);
5059 Fset_marker (XBUFFER (w
->buffer
)->mark
,
5060 p
->mark
, w
->buffer
);
5062 /* As documented in Fcurrent_window_configuration, don't
5063 save the location of point in the buffer which was current
5064 when the window configuration was recorded. */
5065 if (!EQ (p
->buffer
, new_current_buffer
)
5066 && XBUFFER (p
->buffer
) == current_buffer
)
5067 Fgoto_char (w
->pointm
);
5069 else if (NILP (w
->buffer
) || NILP (XBUFFER (w
->buffer
)->name
))
5070 /* Else unless window has a live buffer, get one. */
5072 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
5073 /* This will set the markers to beginning of visible
5075 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
5076 set_marker_restricted (w
->pointm
, make_number (0),w
->buffer
);
5077 w
->start_at_line_beg
= Qt
;
5080 /* Keeping window's old buffer; make sure the markers
5083 /* Set window markers at start of visible range. */
5084 if (XMARKER (w
->start
)->buffer
== 0)
5085 set_marker_restricted (w
->start
, make_number (0),
5087 if (XMARKER (w
->pointm
)->buffer
== 0)
5088 set_marker_restricted_both (w
->pointm
, w
->buffer
,
5089 BUF_PT (XBUFFER (w
->buffer
)),
5090 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
5091 w
->start_at_line_beg
= Qt
;
5096 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
5097 /* Prevent "swapping out point" in the old selected window
5098 using the buffer that has been restored into it.
5099 That swapping out has already been done,
5100 near the beginning of this function. */
5101 selected_window
= Qnil
;
5102 Fselect_window (data
->current_window
);
5103 XBUFFER (XWINDOW (selected_window
)->buffer
)->last_selected_window
5106 if (NILP (data
->focus_frame
)
5107 || (FRAMEP (data
->focus_frame
)
5108 && FRAME_LIVE_P (XFRAME (data
->focus_frame
))))
5109 Fredirect_frame_focus (frame
, data
->focus_frame
);
5111 #if 0 /* I don't understand why this is needed, and it causes problems
5112 when the frame's old selected window has been deleted. */
5113 if (f
!= selected_frame
&& FRAME_WINDOW_P (f
))
5114 do_switch_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)),
5118 /* Set the screen height to the value it had before this function. */
5119 if (previous_frame_height
!= FRAME_HEIGHT (f
)
5120 || previous_frame_width
!= FRAME_WIDTH (f
))
5121 change_frame_size (f
, previous_frame_height
, previous_frame_width
,
5123 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5124 if (previous_frame_menu_bar_lines
!= FRAME_MENU_BAR_LINES (f
))
5125 x_set_menu_bar_lines (f
, make_number (previous_frame_menu_bar_lines
),
5127 #ifdef HAVE_WINDOW_SYSTEM
5128 if (previous_frame_tool_bar_lines
!= FRAME_TOOL_BAR_LINES (f
))
5129 x_set_tool_bar_lines (f
, make_number (previous_frame_tool_bar_lines
),
5134 /* Now, free glyph matrices in windows that were not reused. */
5135 for (i
= n
= 0; i
< n_leaf_windows
; ++i
)
5137 if (NILP (leaf_windows
[i
]->buffer
))
5139 /* Assert it's not reused as a combination. */
5140 xassert (NILP (leaf_windows
[i
]->hchild
)
5141 && NILP (leaf_windows
[i
]->vchild
));
5142 free_window_matrices (leaf_windows
[i
]);
5144 else if (EQ (leaf_windows
[i
]->buffer
, new_current_buffer
))
5148 /* If more than one window shows the new and old current buffer,
5149 don't try to preserve point in that buffer. */
5150 if (old_point
> 0 && n
> 1)
5157 /* Fselect_window will have made f the selected frame, so we
5158 reselect the proper frame here. Fhandle_switch_frame will change the
5159 selected window too, but that doesn't make the call to
5160 Fselect_window above totally superfluous; it still sets f's
5162 if (FRAME_LIVE_P (XFRAME (data
->selected_frame
)))
5163 do_switch_frame (data
->selected_frame
, 0, 0);
5165 if (! NILP (Vwindow_configuration_change_hook
)
5166 && ! NILP (Vrun_hooks
))
5167 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
5170 if (!NILP (new_current_buffer
))
5172 Fset_buffer (new_current_buffer
);
5174 /* If the buffer that is current now is the same
5175 that was current before setting the window configuration,
5176 don't alter its PT. */
5181 /* Restore the minimum heights recorded in the configuration. */
5182 window_min_height
= XINT (data
->min_height
);
5183 window_min_width
= XINT (data
->min_width
);
5185 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
5186 minibuf_selected_window
= data
->minibuf_selected_window
;
5188 return (FRAME_LIVE_P (f
) ? Qt
: Qnil
);
5191 /* Mark all windows now on frame as deleted
5192 by setting their buffers to nil. */
5195 delete_all_subwindows (w
)
5196 register struct window
*w
;
5198 if (!NILP (w
->next
))
5199 delete_all_subwindows (XWINDOW (w
->next
));
5200 if (!NILP (w
->vchild
))
5201 delete_all_subwindows (XWINDOW (w
->vchild
));
5202 if (!NILP (w
->hchild
))
5203 delete_all_subwindows (XWINDOW (w
->hchild
));
5205 w
->height
= w
->buffer
; /* See Fset_window_configuration for excuse. */
5207 if (!NILP (w
->buffer
))
5210 /* We set all three of these fields to nil, to make sure that we can
5211 distinguish this dead window from any live window. Live leaf
5212 windows will have buffer set, and combination windows will have
5213 vchild or hchild set. */
5218 Vwindow_list
= Qnil
;
5222 count_windows (window
)
5223 register struct window
*window
;
5225 register int count
= 1;
5226 if (!NILP (window
->next
))
5227 count
+= count_windows (XWINDOW (window
->next
));
5228 if (!NILP (window
->vchild
))
5229 count
+= count_windows (XWINDOW (window
->vchild
));
5230 if (!NILP (window
->hchild
))
5231 count
+= count_windows (XWINDOW (window
->hchild
));
5236 /* Fill vector FLAT with leaf windows under W, starting at index I.
5237 Value is last index + 1. */
5240 get_leaf_windows (w
, flat
, i
)
5242 struct window
**flat
;
5247 if (!NILP (w
->hchild
))
5248 i
= get_leaf_windows (XWINDOW (w
->hchild
), flat
, i
);
5249 else if (!NILP (w
->vchild
))
5250 i
= get_leaf_windows (XWINDOW (w
->vchild
), flat
, i
);
5254 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5261 /* Return a pointer to the glyph W's physical cursor is on. Value is
5262 null if W's current matrix is invalid, so that no meaningfull glyph
5266 get_phys_cursor_glyph (w
)
5269 struct glyph_row
*row
;
5270 struct glyph
*glyph
;
5272 if (w
->phys_cursor
.vpos
>= 0
5273 && w
->phys_cursor
.vpos
< w
->current_matrix
->nrows
5274 && (row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
),
5276 && row
->used
[TEXT_AREA
] > w
->phys_cursor
.hpos
)
5277 glyph
= row
->glyphs
[TEXT_AREA
] + w
->phys_cursor
.hpos
;
5286 save_window_save (window
, vector
, i
)
5288 struct Lisp_Vector
*vector
;
5291 register struct saved_window
*p
;
5292 register struct window
*w
;
5293 register Lisp_Object tem
;
5295 for (;!NILP (window
); window
= w
->next
)
5297 p
= SAVED_WINDOW_N (vector
, i
);
5298 w
= XWINDOW (window
);
5300 XSETFASTINT (w
->temslot
, i
++);
5302 p
->buffer
= w
->buffer
;
5305 p
->width
= w
->width
;
5306 p
->height
= w
->height
;
5307 p
->hscroll
= w
->hscroll
;
5308 p
->min_hscroll
= w
->min_hscroll
;
5309 p
->display_table
= w
->display_table
;
5310 p
->orig_top
= w
->orig_top
;
5311 p
->orig_height
= w
->orig_height
;
5312 if (!NILP (w
->buffer
))
5314 /* Save w's value of point in the window configuration.
5315 If w is the selected window, then get the value of point
5316 from the buffer; pointm is garbage in the selected window. */
5317 if (EQ (window
, selected_window
))
5319 p
->pointm
= Fmake_marker ();
5320 set_marker_both (p
->pointm
, w
->buffer
,
5321 BUF_PT (XBUFFER (w
->buffer
)),
5322 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
5325 p
->pointm
= Fcopy_marker (w
->pointm
, Qnil
);
5327 p
->start
= Fcopy_marker (w
->start
, Qnil
);
5328 p
->start_at_line_beg
= w
->start_at_line_beg
;
5330 tem
= XBUFFER (w
->buffer
)->mark
;
5331 p
->mark
= Fcopy_marker (tem
, Qnil
);
5338 p
->start_at_line_beg
= Qnil
;
5341 if (NILP (w
->parent
))
5344 p
->parent
= XWINDOW (w
->parent
)->temslot
;
5349 p
->prev
= XWINDOW (w
->prev
)->temslot
;
5351 if (!NILP (w
->vchild
))
5352 i
= save_window_save (w
->vchild
, vector
, i
);
5353 if (!NILP (w
->hchild
))
5354 i
= save_window_save (w
->hchild
, vector
, i
);
5360 DEFUN ("current-window-configuration", Fcurrent_window_configuration
,
5361 Scurrent_window_configuration
, 0, 1, 0,
5362 doc
: /* Return an object representing the current window configuration of FRAME.
5363 If FRAME is nil or omitted, use the selected frame.
5364 This describes the number of windows, their sizes and current buffers,
5365 and for each displayed buffer, where display starts, and the positions of
5366 point and mark. An exception is made for point in the current buffer:
5367 its value is -not- saved.
5368 This also records the currently selected frame, and FRAME's focus
5369 redirection (see `redirect-frame-focus'). */)
5373 register Lisp_Object tem
;
5374 register int n_windows
;
5375 register struct save_window_data
*data
;
5376 register struct Lisp_Vector
*vec
;
5381 frame
= selected_frame
;
5382 CHECK_LIVE_FRAME (frame
);
5385 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
5386 vec
= allocate_other_vector (VECSIZE (struct save_window_data
));
5387 data
= (struct save_window_data
*)vec
;
5389 XSETFASTINT (data
->frame_width
, FRAME_WIDTH (f
));
5390 XSETFASTINT (data
->frame_height
, FRAME_HEIGHT (f
));
5391 XSETFASTINT (data
->frame_menu_bar_lines
, FRAME_MENU_BAR_LINES (f
));
5392 XSETFASTINT (data
->frame_tool_bar_lines
, FRAME_TOOL_BAR_LINES (f
));
5393 data
->selected_frame
= selected_frame
;
5394 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
5395 XSETBUFFER (data
->current_buffer
, current_buffer
);
5396 data
->minibuf_scroll_window
= minibuf_level
> 0 ? Vminibuf_scroll_window
: Qnil
;
5397 data
->minibuf_selected_window
= minibuf_level
> 0 ? minibuf_selected_window
: Qnil
;
5398 data
->root_window
= FRAME_ROOT_WINDOW (f
);
5399 data
->focus_frame
= FRAME_FOCUS_FRAME (f
);
5400 XSETINT (data
->min_height
, window_min_height
);
5401 XSETINT (data
->min_width
, window_min_width
);
5402 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
5403 data
->saved_windows
= tem
;
5404 for (i
= 0; i
< n_windows
; i
++)
5405 XVECTOR (tem
)->contents
[i
]
5406 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE
), Qnil
);
5407 save_window_save (FRAME_ROOT_WINDOW (f
), XVECTOR (tem
), 0);
5408 XSETWINDOW_CONFIGURATION (tem
, data
);
5412 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
5414 doc
: /* Execute body, preserving window sizes and contents.
5415 Restore which buffer appears in which window, where display starts,
5416 and the value of point and mark for each window.
5417 Also restore the choice of selected window.
5418 Also restore which buffer is current.
5419 Does not restore the value of point in current buffer.
5420 usage: (save-window-excursion BODY ...) */)
5424 register Lisp_Object val
;
5425 register int count
= specpdl_ptr
- specpdl
;
5427 record_unwind_protect (Fset_window_configuration
,
5428 Fcurrent_window_configuration (Qnil
));
5429 val
= Fprogn (args
);
5430 return unbind_to (count
, val
);
5434 /***********************************************************************
5436 ***********************************************************************/
5438 DEFUN ("set-window-margins", Fset_window_margins
, Sset_window_margins
,
5440 doc
: /* Set width of marginal areas of window WINDOW.
5441 If window is nil, set margins of the currently selected window.
5442 First parameter LEFT-WIDTH specifies the number of character
5443 cells to reserve for the left marginal area. Second parameter
5444 RIGHT-WIDTH does the same for the right marginal area.
5445 A nil width parameter means no margin. */)
5446 (window
, left
, right
)
5447 Lisp_Object window
, left
, right
;
5449 struct window
*w
= decode_window (window
);
5452 CHECK_NUMBER_OR_FLOAT (left
);
5454 CHECK_NUMBER_OR_FLOAT (right
);
5456 /* Check widths < 0 and translate a zero width to nil.
5457 Margins that are too wide have to be checked elsewhere. */
5458 if ((INTEGERP (left
) && XINT (left
) < 0)
5459 || (FLOATP (left
) && XFLOAT_DATA (left
) <= 0))
5460 XSETFASTINT (left
, 0);
5461 if (INTEGERP (left
) && XFASTINT (left
) == 0)
5464 if ((INTEGERP (right
) && XINT (right
) < 0)
5465 || (FLOATP (right
) && XFLOAT_DATA (right
) <= 0))
5466 XSETFASTINT (right
, 0);
5467 if (INTEGERP (right
) && XFASTINT (right
) == 0)
5470 w
->left_margin_width
= left
;
5471 w
->right_margin_width
= right
;
5473 ++windows_or_buffers_changed
;
5474 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
5479 DEFUN ("window-margins", Fwindow_margins
, Swindow_margins
,
5481 doc
: /* Get width of marginal areas of window WINDOW.
5482 If WINDOW is omitted or nil, use the currently selected window.
5483 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
5484 If a marginal area does not exist, its width will be returned
5489 struct window
*w
= decode_window (window
);
5490 return Fcons (w
->left_margin_width
, w
->right_margin_width
);
5495 /***********************************************************************
5497 ***********************************************************************/
5499 DEFUN ("window-vscroll", Fwindow_vscroll
, Swindow_vscroll
, 0, 1, 0,
5500 doc
: /* Return the amount by which WINDOW is scrolled vertically.
5501 Use the selected window if WINDOW is nil or omitted.
5502 Value is a multiple of the canonical character height of WINDOW. */)
5511 window
= selected_window
;
5513 CHECK_WINDOW (window
);
5514 w
= XWINDOW (window
);
5515 f
= XFRAME (w
->frame
);
5517 if (FRAME_WINDOW_P (f
))
5518 result
= CANON_Y_FROM_PIXEL_Y (f
, -w
->vscroll
);
5520 result
= make_number (0);
5525 DEFUN ("set-window-vscroll", Fset_window_vscroll
, Sset_window_vscroll
,
5527 doc
: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
5528 WINDOW nil means use the selected window. VSCROLL is a non-negative
5529 multiple of the canonical character height of WINDOW. */)
5531 Lisp_Object window
, vscroll
;
5537 window
= selected_window
;
5539 CHECK_WINDOW (window
);
5540 CHECK_NUMBER_OR_FLOAT (vscroll
);
5542 w
= XWINDOW (window
);
5543 f
= XFRAME (w
->frame
);
5545 if (FRAME_WINDOW_P (f
))
5547 int old_dy
= w
->vscroll
;
5549 w
->vscroll
= - CANON_Y_UNIT (f
) * XFLOATINT (vscroll
);
5550 w
->vscroll
= min (w
->vscroll
, 0);
5552 /* Adjust glyph matrix of the frame if the virtual display
5553 area becomes larger than before. */
5554 if (w
->vscroll
< 0 && w
->vscroll
< old_dy
)
5557 /* Prevent redisplay shortcuts. */
5558 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
5561 return Fwindow_vscroll (window
);
5565 /* Call FN for all leaf windows on frame F. FN is called with the
5566 first argument being a pointer to the leaf window, and with
5567 additional argument USER_DATA. Stops when FN returns 0. */
5570 foreach_window (f
, fn
, user_data
)
5572 int (* fn
) P_ ((struct window
*, void *));
5575 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f
)), fn
, user_data
);
5579 /* Helper function for foreach_window. Call FN for all leaf windows
5580 reachable from W. FN is called with the first argument being a
5581 pointer to the leaf window, and with additional argument USER_DATA.
5582 Stop when FN returns 0. Value is 0 if stopped by FN. */
5585 foreach_window_1 (w
, fn
, user_data
)
5587 int (* fn
) P_ ((struct window
*, void *));
5592 for (cont
= 1; w
&& cont
;)
5594 if (!NILP (w
->hchild
))
5595 cont
= foreach_window_1 (XWINDOW (w
->hchild
), fn
, user_data
);
5596 else if (!NILP (w
->vchild
))
5597 cont
= foreach_window_1 (XWINDOW (w
->vchild
), fn
, user_data
);
5599 cont
= fn (w
, user_data
);
5601 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5608 /* Freeze or unfreeze the window start of W unless it is a
5609 mini-window or the selected window. FREEZE_P non-null means freeze
5610 the window start. */
5613 freeze_window_start (w
, freeze_p
)
5617 if (w
== XWINDOW (selected_window
)
5618 || MINI_WINDOW_P (w
)
5619 || (MINI_WINDOW_P (XWINDOW (selected_window
))
5620 && ! NILP (Vminibuf_scroll_window
)
5621 && w
== XWINDOW (Vminibuf_scroll_window
)))
5624 w
->frozen_window_start_p
= freeze_p
!= NULL
;
5629 /* Freeze or unfreeze the window starts of all leaf windows on frame
5630 F, except the selected window and a mini-window. FREEZE_P non-zero
5631 means freeze the window start. */
5634 freeze_window_starts (f
, freeze_p
)
5638 foreach_window (f
, freeze_window_start
, (void *) (freeze_p
? f
: 0));
5642 /***********************************************************************
5644 ***********************************************************************/
5646 /* Return 1 if window configurations C1 and C2
5647 describe the same state of affairs. This is used by Fequal. */
5650 compare_window_configurations (c1
, c2
, ignore_positions
)
5652 int ignore_positions
;
5654 register struct save_window_data
*d1
, *d2
;
5655 struct Lisp_Vector
*sw1
, *sw2
;
5658 if (!WINDOW_CONFIGURATIONP (c1
))
5659 wrong_type_argument (Qwindow_configuration_p
, c1
);
5660 if (!WINDOW_CONFIGURATIONP (c2
))
5661 wrong_type_argument (Qwindow_configuration_p
, c2
);
5663 d1
= (struct save_window_data
*) XVECTOR (c1
);
5664 d2
= (struct save_window_data
*) XVECTOR (c2
);
5665 sw1
= XVECTOR (d1
->saved_windows
);
5666 sw2
= XVECTOR (d2
->saved_windows
);
5668 if (! EQ (d1
->frame_width
, d2
->frame_width
))
5670 if (! EQ (d1
->frame_height
, d2
->frame_height
))
5672 if (! EQ (d1
->frame_menu_bar_lines
, d2
->frame_menu_bar_lines
))
5674 if (! EQ (d1
->selected_frame
, d2
->selected_frame
))
5676 /* Don't compare the current_window field directly.
5677 Instead see w1_is_current and w2_is_current, below. */
5678 if (! EQ (d1
->current_buffer
, d2
->current_buffer
))
5680 if (! ignore_positions
)
5682 if (! EQ (d1
->minibuf_scroll_window
, d2
->minibuf_scroll_window
))
5684 if (! EQ (d1
->minibuf_selected_window
, d2
->minibuf_selected_window
))
5687 /* Don't compare the root_window field.
5688 We don't require the two configurations
5689 to use the same window object,
5690 and the two root windows must be equivalent
5691 if everything else compares equal. */
5692 if (! EQ (d1
->focus_frame
, d2
->focus_frame
))
5694 if (! EQ (d1
->min_width
, d2
->min_width
))
5696 if (! EQ (d1
->min_height
, d2
->min_height
))
5699 /* Verify that the two confis have the same number of windows. */
5700 if (sw1
->size
!= sw2
->size
)
5703 for (i
= 0; i
< sw1
->size
; i
++)
5705 struct saved_window
*p1
, *p2
;
5706 int w1_is_current
, w2_is_current
;
5708 p1
= SAVED_WINDOW_N (sw1
, i
);
5709 p2
= SAVED_WINDOW_N (sw2
, i
);
5711 /* Verify that the current windows in the two
5712 configurations correspond to each other. */
5713 w1_is_current
= EQ (d1
->current_window
, p1
->window
);
5714 w2_is_current
= EQ (d2
->current_window
, p2
->window
);
5716 if (w1_is_current
!= w2_is_current
)
5719 /* Verify that the corresponding windows do match. */
5720 if (! EQ (p1
->buffer
, p2
->buffer
))
5722 if (! EQ (p1
->left
, p2
->left
))
5724 if (! EQ (p1
->top
, p2
->top
))
5726 if (! EQ (p1
->width
, p2
->width
))
5728 if (! EQ (p1
->height
, p2
->height
))
5730 if (! EQ (p1
->display_table
, p2
->display_table
))
5732 if (! EQ (p1
->parent
, p2
->parent
))
5734 if (! EQ (p1
->prev
, p2
->prev
))
5736 if (! ignore_positions
)
5738 if (! EQ (p1
->hscroll
, p2
->hscroll
))
5740 if (!EQ (p1
->min_hscroll
, p2
->min_hscroll
))
5742 if (! EQ (p1
->start_at_line_beg
, p2
->start_at_line_beg
))
5744 if (NILP (Fequal (p1
->start
, p2
->start
)))
5746 if (NILP (Fequal (p1
->pointm
, p2
->pointm
)))
5748 if (NILP (Fequal (p1
->mark
, p2
->mark
)))
5756 DEFUN ("compare-window-configurations", Fcompare_window_configurations
,
5757 Scompare_window_configurations
, 2, 2, 0,
5758 doc
: /* Compare two window configurations as regards the structure of windows.
5759 This function ignores details such as the values of point and mark
5760 and scrolling positions. */)
5764 if (compare_window_configurations (x
, y
, 1))
5772 struct frame
*f
= make_terminal_frame ();
5773 XSETFRAME (selected_frame
, f
);
5774 Vterminal_frame
= selected_frame
;
5775 minibuf_window
= f
->minibuffer_window
;
5776 selected_window
= f
->selected_window
;
5777 last_nonminibuf_frame
= f
;
5779 window_initialized
= 1;
5785 Vwindow_list
= Qnil
;
5791 Qwindow_size_fixed
= intern ("window-size-fixed");
5792 staticpro (&Qwindow_size_fixed
);
5794 staticpro (&Qwindow_configuration_change_hook
);
5795 Qwindow_configuration_change_hook
5796 = intern ("window-configuration-change-hook");
5798 Qwindowp
= intern ("windowp");
5799 staticpro (&Qwindowp
);
5801 Qwindow_configuration_p
= intern ("window-configuration-p");
5802 staticpro (&Qwindow_configuration_p
);
5804 Qwindow_live_p
= intern ("window-live-p");
5805 staticpro (&Qwindow_live_p
);
5807 Qtemp_buffer_show_hook
= intern ("temp-buffer-show-hook");
5808 staticpro (&Qtemp_buffer_show_hook
);
5810 staticpro (&Vwindow_list
);
5812 minibuf_selected_window
= Qnil
;
5813 staticpro (&minibuf_selected_window
);
5815 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
5816 doc
: /* Non-nil means call as function to display a help buffer.
5817 The function is called with one argument, the buffer to be displayed.
5818 Used by `with-output-to-temp-buffer'.
5819 If this function is used, then it must do the entire job of showing
5820 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
5821 Vtemp_buffer_show_function
= Qnil
;
5823 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
5824 doc
: /* If non-nil, function to call to handle `display-buffer'.
5825 It will receive two args, the buffer and a flag which if non-nil means
5826 that the currently selected window is not acceptable.
5827 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
5828 work using this function. */);
5829 Vdisplay_buffer_function
= Qnil
;
5831 DEFVAR_LISP ("even-window-heights", &Veven_window_heights
,
5832 doc
: /* *If non-nil, `display-buffer' should even the window heights.
5833 If nil, `display-buffer' will leave the window configuration alone. */);
5834 Veven_window_heights
= Qt
;
5836 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
5837 doc
: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
5838 Vminibuf_scroll_window
= Qnil
;
5840 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows
,
5841 doc
: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
5842 If the minibuffer is active, the `minibuffer-scroll-window' mode line
5843 is displayed in the `mode-line' face. */);
5844 mode_line_in_non_selected_windows
= 1;
5846 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
5847 doc
: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
5848 Vother_window_scroll_buffer
= Qnil
;
5850 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames
,
5851 doc
: /* *Non-nil means `display-buffer' should make a separate frame. */);
5854 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames
,
5855 doc
: /* *Non-nil means `display-buffer' should reuse frames.
5856 If the buffer in question is already displayed in a frame, raise that frame. */);
5857 display_buffer_reuse_frames
= 0;
5859 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function
,
5860 doc
: /* Function to call to handle automatic new frame creation.
5861 It is called with no arguments and should return a newly created frame.
5863 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
5864 where `pop-up-frame-alist' would hold the default frame parameters. */);
5865 Vpop_up_frame_function
= Qnil
;
5867 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names
,
5868 doc
: /* *List of buffer names that should have their own special frames.
5869 Displaying a buffer whose name is in this list makes a special frame for it
5870 using `special-display-function'. See also `special-display-regexps'.
5872 An element of the list can be a list instead of just a string.
5873 There are two ways to use a list as an element:
5874 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
5875 In the first case, FRAME-PARAMETERS are used to create the frame.
5876 In the latter case, FUNCTION is called with BUFFER as the first argument,
5877 followed by OTHER-ARGS--it can display BUFFER in any way it likes.
5878 All this is done by the function found in `special-display-function'.
5880 If this variable appears \"not to work\", because you add a name to it
5881 but that buffer still appears in the selected window, look at the
5882 values of `same-window-buffer-names' and `same-window-regexps'.
5883 Those variables take precedence over this one. */);
5884 Vspecial_display_buffer_names
= Qnil
;
5886 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps
,
5887 doc
: /* *List of regexps saying which buffers should have their own special frames.
5888 If a buffer name matches one of these regexps, it gets its own frame.
5889 Displaying a buffer whose name is in this list makes a special frame for it
5890 using `special-display-function'.
5892 An element of the list can be a list instead of just a string.
5893 There are two ways to use a list as an element:
5894 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
5895 In the first case, FRAME-PARAMETERS are used to create the frame.
5896 In the latter case, FUNCTION is called with the buffer as first argument,
5897 followed by OTHER-ARGS--it can display the buffer in any way it likes.
5898 All this is done by the function found in `special-display-function'.
5900 If this variable appears \"not to work\", because you add a regexp to it
5901 but the matching buffers still appear in the selected window, look at the
5902 values of `same-window-buffer-names' and `same-window-regexps'.
5903 Those variables take precedence over this one. */);
5904 Vspecial_display_regexps
= Qnil
;
5906 DEFVAR_LISP ("special-display-function", &Vspecial_display_function
,
5907 doc
: /* Function to call to make a new frame for a special buffer.
5908 It is called with two arguments, the buffer and optional buffer specific
5909 data, and should return a window displaying that buffer.
5910 The default value makes a separate frame for the buffer,
5911 using `special-display-frame-alist' to specify the frame parameters.
5913 A buffer is special if its is listed in `special-display-buffer-names'
5914 or matches a regexp in `special-display-regexps'. */);
5915 Vspecial_display_function
= Qnil
;
5917 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names
,
5918 doc
: /* *List of buffer names that should appear in the selected window.
5919 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
5920 switches to it in the selected window, rather than making it appear
5921 in some other window.
5923 An element of the list can be a cons cell instead of just a string.
5924 Then the car must be a string, which specifies the buffer name.
5925 This is for compatibility with `special-display-buffer-names';
5926 the cdr of the cons cell is ignored.
5928 See also `same-window-regexps'. */);
5929 Vsame_window_buffer_names
= Qnil
;
5931 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps
,
5932 doc
: /* *List of regexps saying which buffers should appear in the selected window.
5933 If a buffer name matches one of these regexps, then displaying it
5934 using `display-buffer' or `pop-to-buffer' switches to it
5935 in the selected window, rather than making it appear in some other window.
5937 An element of the list can be a cons cell instead of just a string.
5938 Then the car must be a string, which specifies the buffer name.
5939 This is for compatibility with `special-display-buffer-names';
5940 the cdr of the cons cell is ignored.
5942 See also `same-window-buffer-names'. */);
5943 Vsame_window_regexps
= Qnil
;
5945 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
5946 doc
: /* *Non-nil means display-buffer should make new windows. */);
5949 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
5950 doc
: /* *Number of lines of continuity when scrolling by screenfuls. */);
5951 next_screen_context_lines
= 2;
5953 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
5954 doc
: /* *display-buffer would prefer to split the largest window if this large.
5955 If there is only one window, it is split regardless of this value. */);
5956 split_height_threshold
= 500;
5958 DEFVAR_INT ("window-min-height", &window_min_height
,
5959 doc
: /* *Delete any window less than this tall (including its mode line). */);
5960 window_min_height
= 4;
5962 DEFVAR_INT ("window-min-width", &window_min_width
,
5963 doc
: /* *Delete any window less than this wide. */);
5964 window_min_width
= 10;
5966 DEFVAR_LISP ("scroll-preserve-screen-position",
5967 &Vscroll_preserve_screen_position
,
5968 doc
: /* *Non-nil means scroll commands move point to keep its screen line unchanged. */);
5969 Vscroll_preserve_screen_position
= Qnil
;
5971 DEFVAR_LISP ("window-configuration-change-hook",
5972 &Vwindow_configuration_change_hook
,
5973 doc
: /* Functions to call when window configuration changes.
5974 The selected frame is the one whose configuration has changed. */);
5975 Vwindow_configuration_change_hook
= Qnil
;
5977 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed
,
5978 doc
: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
5979 Emacs won't change the size of any window displaying that buffer,
5980 unless you explicitly change the size, or Emacs has no other choice.
5981 This variable automatically becomes buffer-local when set. */);
5982 Fmake_variable_buffer_local (Qwindow_size_fixed
);
5983 window_size_fixed
= 0;
5985 defsubr (&Sselected_window
);
5986 defsubr (&Sminibuffer_window
);
5987 defsubr (&Swindow_minibuffer_p
);
5988 defsubr (&Swindowp
);
5989 defsubr (&Swindow_live_p
);
5990 defsubr (&Spos_visible_in_window_p
);
5991 defsubr (&Swindow_buffer
);
5992 defsubr (&Swindow_height
);
5993 defsubr (&Swindow_width
);
5994 defsubr (&Swindow_hscroll
);
5995 defsubr (&Sset_window_hscroll
);
5996 defsubr (&Swindow_redisplay_end_trigger
);
5997 defsubr (&Sset_window_redisplay_end_trigger
);
5998 defsubr (&Swindow_edges
);
5999 defsubr (&Scoordinates_in_window_p
);
6000 defsubr (&Swindow_at
);
6001 defsubr (&Swindow_point
);
6002 defsubr (&Swindow_start
);
6003 defsubr (&Swindow_end
);
6004 defsubr (&Sset_window_point
);
6005 defsubr (&Sset_window_start
);
6006 defsubr (&Swindow_dedicated_p
);
6007 defsubr (&Sset_window_dedicated_p
);
6008 defsubr (&Swindow_display_table
);
6009 defsubr (&Sset_window_display_table
);
6010 defsubr (&Snext_window
);
6011 defsubr (&Sprevious_window
);
6012 defsubr (&Sother_window
);
6013 defsubr (&Sget_lru_window
);
6014 defsubr (&Sget_largest_window
);
6015 defsubr (&Sget_buffer_window
);
6016 defsubr (&Sdelete_other_windows
);
6017 defsubr (&Sdelete_windows_on
);
6018 defsubr (&Sreplace_buffer_in_windows
);
6019 defsubr (&Sdelete_window
);
6020 defsubr (&Sset_window_buffer
);
6021 defsubr (&Sselect_window
);
6022 defsubr (&Sspecial_display_p
);
6023 defsubr (&Ssame_window_p
);
6024 defsubr (&Sdisplay_buffer
);
6025 defsubr (&Ssplit_window
);
6026 defsubr (&Senlarge_window
);
6027 defsubr (&Sshrink_window
);
6028 defsubr (&Sscroll_up
);
6029 defsubr (&Sscroll_down
);
6030 defsubr (&Sscroll_left
);
6031 defsubr (&Sscroll_right
);
6032 defsubr (&Sother_window_for_scrolling
);
6033 defsubr (&Sscroll_other_window
);
6034 defsubr (&Sminibuffer_selected_window
);
6035 defsubr (&Srecenter
);
6036 defsubr (&Swindow_text_height
);
6037 defsubr (&Smove_to_window_line
);
6038 defsubr (&Swindow_configuration_p
);
6039 defsubr (&Swindow_configuration_frame
);
6040 defsubr (&Sset_window_configuration
);
6041 defsubr (&Scurrent_window_configuration
);
6042 defsubr (&Ssave_window_excursion
);
6043 defsubr (&Sset_window_margins
);
6044 defsubr (&Swindow_margins
);
6045 defsubr (&Swindow_vscroll
);
6046 defsubr (&Sset_window_vscroll
);
6047 defsubr (&Scompare_window_configurations
);
6048 defsubr (&Swindow_list
);
6054 initial_define_key (control_x_map
, '1', "delete-other-windows");
6055 initial_define_key (control_x_map
, '2', "split-window");
6056 initial_define_key (control_x_map
, '0', "delete-window");
6057 initial_define_key (control_x_map
, 'o', "other-window");
6058 initial_define_key (control_x_map
, '^', "enlarge-window");
6059 initial_define_key (control_x_map
, '<', "scroll-left");
6060 initial_define_key (control_x_map
, '>', "scroll-right");
6062 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
6063 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
6064 initial_define_key (meta_map
, 'v', "scroll-down");
6066 initial_define_key (global_map
, Ctl('L'), "recenter");
6067 initial_define_key (meta_map
, 'r', "move-to-window-line");