1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
4 2001, 2002, 2003, 2004, 2005, 2006, 2007 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 3, 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., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
36 #include "dispextern.h"
37 #include "blockinput.h"
38 #include "intervals.h"
42 #endif /* HAVE_X_WINDOWS */
54 Lisp_Object Qwindowp
, Qwindow_live_p
, Qwindow_configuration_p
;
55 Lisp_Object Qscroll_up
, Qscroll_down
;
56 Lisp_Object Qwindow_size_fixed
;
57 extern Lisp_Object Qleft_margin
, Qright_margin
;
59 static int displayed_window_lines
P_ ((struct window
*));
60 static struct window
*decode_window
P_ ((Lisp_Object
));
61 static int count_windows
P_ ((struct window
*));
62 static int get_leaf_windows
P_ ((struct window
*, struct window
**, int));
63 static void window_scroll
P_ ((Lisp_Object
, int, int, int));
64 static void window_scroll_pixel_based
P_ ((Lisp_Object
, int, int, int));
65 static void window_scroll_line_based
P_ ((Lisp_Object
, int, int, int));
66 static int window_min_size_1
P_ ((struct window
*, int));
67 static int window_min_size_2
P_ ((struct window
*, int));
68 static int window_min_size
P_ ((struct window
*, int, int, int *));
69 static void size_window
P_ ((Lisp_Object
, int, int, int, int, int));
70 static int freeze_window_start
P_ ((struct window
*, void *));
71 static int window_fixed_size_p
P_ ((struct window
*, int, int));
72 static void enlarge_window
P_ ((Lisp_Object
, int, int));
73 static Lisp_Object window_list
P_ ((void));
74 static int add_window_to_list
P_ ((struct window
*, void *));
75 static int candidate_window_p
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
77 static Lisp_Object next_window
P_ ((Lisp_Object
, Lisp_Object
,
79 static void decode_next_window_args
P_ ((Lisp_Object
*, Lisp_Object
*,
81 static int foreach_window_1
P_ ((struct window
*,
82 int (* fn
) (struct window
*, void *),
84 static Lisp_Object window_list_1
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
));
86 /* This is the window in which the terminal's cursor should
87 be left when nothing is being done with it. This must
88 always be a leaf window, and its buffer is selected by
89 the top level editing loop at the end of each command.
91 This value is always the same as
92 FRAME_SELECTED_WINDOW (selected_frame). */
94 Lisp_Object selected_window
;
96 /* A list of all windows for use by next_window and Fwindow_list.
97 Functions creating or deleting windows should invalidate this cache
98 by setting it to nil. */
100 Lisp_Object Vwindow_list
;
102 /* The mini-buffer window of the selected frame.
103 Note that you cannot test for mini-bufferness of an arbitrary window
104 by comparing against this; but you can test for mini-bufferness of
105 the selected window. */
107 Lisp_Object minibuf_window
;
109 /* Non-nil means it is the window whose mode line should be
110 shown as the selected window when the minibuffer is selected. */
112 Lisp_Object minibuf_selected_window
;
114 /* Non-nil means it is the window for C-M-v to scroll
115 when the mini-buffer is selected. */
117 Lisp_Object Vminibuf_scroll_window
;
119 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
121 Lisp_Object Vother_window_scroll_buffer
;
123 /* Non-nil means it's function to call to display temp buffers. */
125 Lisp_Object Vtemp_buffer_show_function
;
127 /* Non-zero means line and page scrolling on tall lines (with images)
128 does partial scrolling by modifying window-vscroll. */
130 int auto_window_vscroll_p
;
132 /* Non-zero means to use mode-line-inactive face in all windows but the
133 selected-window and the minibuffer-scroll-window when the
134 minibuffer is active. */
135 int mode_line_in_non_selected_windows
;
137 /* If a window gets smaller than either of these, it is removed. */
139 EMACS_INT window_min_height
;
140 EMACS_INT window_min_width
;
142 /* Nonzero implies Fdisplay_buffer should create windows. */
146 /* Nonzero implies make new frames for Fdisplay_buffer. */
150 /* Nonzero means reuse existing frames for displaying buffers. */
152 int display_buffer_reuse_frames
;
154 /* Non-nil means use this function instead of default */
156 Lisp_Object Vpop_up_frame_function
;
158 /* Function to call to handle Fdisplay_buffer. */
160 Lisp_Object Vdisplay_buffer_function
;
162 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
164 Lisp_Object Veven_window_heights
;
166 /* List of buffer *names* for buffers that should have their own frames. */
168 Lisp_Object Vspecial_display_buffer_names
;
170 /* List of regexps for buffer names that should have their own frames. */
172 Lisp_Object Vspecial_display_regexps
;
174 /* Function to pop up a special frame. */
176 Lisp_Object Vspecial_display_function
;
178 /* List of buffer *names* for buffers to appear in selected window. */
180 Lisp_Object Vsame_window_buffer_names
;
182 /* List of regexps for buffer names to appear in selected window. */
184 Lisp_Object Vsame_window_regexps
;
186 /* Hook run at end of temp_output_buffer_show. */
188 Lisp_Object Qtemp_buffer_show_hook
;
190 /* Fdisplay_buffer always splits the largest window
191 if that window is more than this high. */
193 EMACS_INT split_height_threshold
;
195 /* Number of lines of continuity in scrolling by screenfuls. */
197 EMACS_INT next_screen_context_lines
;
199 /* Incremented for each window created. */
201 static int sequence_number
;
203 /* Nonzero after init_window_once has finished. */
205 static int window_initialized
;
207 /* Hook to run when window config changes. */
209 Lisp_Object Qwindow_configuration_change_hook
;
210 Lisp_Object Vwindow_configuration_change_hook
;
212 /* Non-nil means scroll commands try to put point
213 at the same screen height as previously. */
215 Lisp_Object Vscroll_preserve_screen_position
;
217 /* Incremented by 1 whenever a window is deleted. */
219 int window_deletion_count
;
221 /* Used by the function window_scroll_pixel_based */
223 static int window_scroll_pixel_based_preserve_y
;
225 #if 0 /* This isn't used anywhere. */
226 /* Nonzero means we can split a frame even if it is "unsplittable". */
227 static int inhibit_frame_unsplittable
;
230 extern EMACS_INT scroll_margin
;
232 extern Lisp_Object Qwindow_scroll_functions
, Vwindow_scroll_functions
;
234 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
235 doc
: /* Returns t if OBJECT is a window. */)
239 return WINDOWP (object
) ? Qt
: Qnil
;
242 DEFUN ("window-live-p", Fwindow_live_p
, Swindow_live_p
, 1, 1, 0,
243 doc
: /* Returns t if OBJECT is a window which is currently visible. */)
247 return WINDOW_LIVE_P (object
) ? Qt
: Qnil
;
254 register struct window
*p
;
256 p
= allocate_window ();
258 XSETFASTINT (p
->sequence_number
, sequence_number
);
259 XSETFASTINT (p
->left_col
, 0);
260 XSETFASTINT (p
->top_line
, 0);
261 XSETFASTINT (p
->total_lines
, 0);
262 XSETFASTINT (p
->total_cols
, 0);
263 XSETFASTINT (p
->hscroll
, 0);
264 XSETFASTINT (p
->min_hscroll
, 0);
265 p
->orig_top_line
= p
->orig_total_lines
= 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
->nrows_scale_factor
= p
->ncols_scale_factor
= 1;
278 p
->phys_cursor_type
= -1;
279 p
->phys_cursor_width
= -1;
280 p
->must_be_updated_p
= 0;
281 XSETFASTINT (p
->window_end_vpos
, 0);
282 XSETFASTINT (p
->window_end_pos
, 0);
283 p
->window_end_valid
= Qnil
;
286 XSETFASTINT (p
->last_point
, 0);
287 p
->frozen_window_start_p
= 0;
288 p
->last_cursor_off_p
= p
->cursor_off_p
= 0;
289 p
->left_margin_cols
= Qnil
;
290 p
->right_margin_cols
= Qnil
;
291 p
->left_fringe_width
= Qnil
;
292 p
->right_fringe_width
= Qnil
;
293 p
->fringes_outside_margins
= Qnil
;
294 p
->scroll_bar_width
= Qnil
;
295 p
->vertical_scroll_bar_type
= Qt
;
301 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
302 doc
: /* Return the window that the cursor now appears in and commands apply to. */)
305 return selected_window
;
308 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 1, 0,
309 doc
: /* Return the window used now for minibuffers.
310 If the optional argument FRAME is specified, return the minibuffer window
311 used by that frame. */)
316 frame
= selected_frame
;
317 CHECK_LIVE_FRAME (frame
);
318 return FRAME_MINIBUF_WINDOW (XFRAME (frame
));
321 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 0, 1, 0,
322 doc
: /* Returns non-nil if WINDOW is a minibuffer window.
323 WINDOW defaults to the selected window. */)
327 struct window
*w
= decode_window (window
);
328 return MINI_WINDOW_P (w
) ? Qt
: Qnil
;
332 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
333 Spos_visible_in_window_p
, 0, 3, 0,
334 doc
: /* Return non-nil if position POS is currently on the frame in WINDOW.
335 Return nil if that position is scrolled vertically out of view.
336 If a character is only partially visible, nil is returned, unless the
337 optional argument PARTIALLY is non-nil.
338 If POS is only out of view because of horizontal scrolling, return non-nil.
339 If POS is t, it specifies the position of the last visible glyph in WINDOW.
340 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
342 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
343 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
344 where X and Y are the pixel coordinates relative to the top left corner
345 of the window. The remaining elements are omitted if the character after
346 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
347 off-window at the top and bottom of the row, ROWH is the height of the
348 display row, and VPOS is the row number (0-based) containing POS. */)
349 (pos
, window
, partially
)
350 Lisp_Object pos
, window
, partially
;
352 register struct window
*w
;
354 register struct buffer
*buf
;
356 Lisp_Object in_window
= Qnil
;
357 int rtop
, rbot
, rowh
, vpos
, fully_p
= 1;
360 w
= decode_window (window
);
361 buf
= XBUFFER (w
->buffer
);
362 SET_TEXT_POS_FROM_MARKER (top
, w
->start
);
366 else if (!NILP (pos
))
368 CHECK_NUMBER_COERCE_MARKER (pos
);
371 else if (w
== XWINDOW (selected_window
))
374 posint
= XMARKER (w
->pointm
)->charpos
;
376 /* If position is above window start or outside buffer boundaries,
377 or if window start is out of range, position is not visible. */
379 || (posint
>= CHARPOS (top
) && posint
<= BUF_ZV (buf
)))
380 && CHARPOS (top
) >= BUF_BEGV (buf
)
381 && CHARPOS (top
) <= BUF_ZV (buf
)
382 && pos_visible_p (w
, posint
, &x
, &y
, &rtop
, &rbot
, &rowh
, &vpos
)
383 && (fully_p
= !rtop
&& !rbot
, (!NILP (partially
) || fully_p
)))
386 if (!NILP (in_window
) && !NILP (partially
))
388 Lisp_Object part
= Qnil
;
390 part
= list4 (make_number (rtop
), make_number (rbot
),
391 make_number (rowh
), make_number (vpos
));
392 in_window
= Fcons (make_number (x
),
393 Fcons (make_number (y
), part
));
399 DEFUN ("window-line-height", Fwindow_line_height
,
400 Swindow_line_height
, 0, 2, 0,
401 doc
: /* Return height in pixels of text line LINE in window WINDOW.
402 If WINDOW is nil or omitted, use selected window.
404 Return height of current line if LINE is omitted or nil. Return height of
405 header or mode line if LINE is `header-line' and `mode-line'.
406 Otherwise, LINE is a text line number starting from 0. A negative number
407 counts from the end of the window.
409 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
410 in pixels of the visible part of the line, VPOS and YPOS are the
411 vertical position in lines and pixels of the line, relative to the top
412 of the first text line, and OFFBOT is the number of off-window pixels at
413 the bottom of the text line. If there are off-window pixels at the top
414 of the (first) text line, YPOS is negative.
416 Return nil if window display is not up-to-date. In that case, use
417 `pos-visible-in-window-p' to obtain the information. */)
419 Lisp_Object line
, window
;
421 register struct window
*w
;
422 register struct buffer
*b
;
423 struct glyph_row
*row
, *end_row
;
424 int max_y
, crop
, i
, n
;
426 w
= decode_window (window
);
429 || w
->pseudo_window_p
)
432 CHECK_BUFFER (w
->buffer
);
433 b
= XBUFFER (w
->buffer
);
435 /* Fail if current matrix is not up-to-date. */
436 if (NILP (w
->window_end_valid
)
437 || current_buffer
->clip_changed
438 || current_buffer
->prevent_redisplay_optimizations_p
439 || XFASTINT (w
->last_modified
) < BUF_MODIFF (b
)
440 || XFASTINT (w
->last_overlay_modified
) < BUF_OVERLAY_MODIFF (b
))
446 if (i
< 0 || i
>= w
->current_matrix
->nrows
447 || (row
= MATRIX_ROW (w
->current_matrix
, i
), !row
->enabled_p
))
449 max_y
= window_text_bottom_y (w
);
453 if (EQ (line
, Qheader_line
))
455 if (!WINDOW_WANTS_HEADER_LINE_P (w
))
457 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
460 return list4 (make_number (row
->height
),
461 make_number (0), make_number (0),
465 if (EQ (line
, Qmode_line
))
467 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
470 return list4 (make_number (row
->height
),
471 make_number (0), /* not accurate */
472 make_number (WINDOW_HEADER_LINE_HEIGHT (w
)
473 + window_text_bottom_y (w
)),
480 row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
481 end_row
= MATRIX_BOTTOM_TEXT_ROW (w
->current_matrix
, w
);
482 max_y
= window_text_bottom_y (w
);
485 while ((n
< 0 || i
< n
)
486 && row
<= end_row
&& row
->enabled_p
487 && row
->y
+ row
->height
< max_y
)
490 if (row
> end_row
|| !row
->enabled_p
)
502 crop
= max (0, (row
->y
+ row
->height
) - max_y
);
503 return list4 (make_number (row
->height
+ min (0, row
->y
) - crop
),
505 make_number (row
->y
),
511 static struct window
*
512 decode_window (window
)
513 register Lisp_Object window
;
516 return XWINDOW (selected_window
);
518 CHECK_LIVE_WINDOW (window
);
519 return XWINDOW (window
);
522 static struct window
*
523 decode_any_window (window
)
524 register Lisp_Object window
;
527 return XWINDOW (selected_window
);
529 CHECK_WINDOW (window
);
530 return XWINDOW (window
);
533 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
534 doc
: /* Return the buffer that WINDOW is displaying.
535 WINDOW defaults to the selected window. */)
539 return decode_window (window
)->buffer
;
542 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
543 doc
: /* Return the number of lines in WINDOW (including its mode line).
544 WINDOW defaults to the selected window. */)
548 return decode_any_window (window
)->total_lines
;
551 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
552 doc
: /* Return the number of display columns in WINDOW.
553 This is the width that is usable columns available for text in WINDOW.
554 If you want to find out how many columns WINDOW takes up,
555 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
559 return make_number (window_box_text_cols (decode_any_window (window
)));
562 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
563 doc
: /* Return the number of columns by which WINDOW is scrolled from left margin.
564 WINDOW defaults to the selected window. */)
568 return decode_window (window
)->hscroll
;
571 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
572 doc
: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
573 Return NCOL. NCOL should be zero or positive.
575 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
576 window so that the location of point moves off-window. */)
578 Lisp_Object window
, ncol
;
580 struct window
*w
= decode_window (window
);
584 hscroll
= max (0, XINT (ncol
));
586 /* Prevent redisplay shortcuts when changing the hscroll. */
587 if (XINT (w
->hscroll
) != hscroll
)
588 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
590 w
->hscroll
= make_number (hscroll
);
594 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger
,
595 Swindow_redisplay_end_trigger
, 0, 1, 0,
596 doc
: /* Return WINDOW's redisplay end trigger value.
597 WINDOW defaults to the selected window.
598 See `set-window-redisplay-end-trigger' for more information. */)
602 return decode_window (window
)->redisplay_end_trigger
;
605 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger
,
606 Sset_window_redisplay_end_trigger
, 2, 2, 0,
607 doc
: /* Set WINDOW's redisplay end trigger value to VALUE.
608 VALUE should be a buffer position (typically a marker) or nil.
609 If it is a buffer position, then if redisplay in WINDOW reaches a position
610 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
611 with two arguments: WINDOW, and the end trigger value.
612 Afterwards the end-trigger value is reset to nil. */)
614 register Lisp_Object window
, value
;
616 register struct window
*w
;
618 w
= decode_window (window
);
619 w
->redisplay_end_trigger
= value
;
623 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
624 doc
: /* Return a list of the edge coordinates of WINDOW.
625 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
626 RIGHT is one more than the rightmost column occupied by WINDOW,
627 and BOTTOM is one more than the bottommost row occupied by WINDOW.
628 The edges include the space used by the window's scroll bar,
629 display margins, fringes, header line, and mode line, if it has them.
630 To get the edges of the actual text area, use `window-inside-edges'. */)
634 register struct window
*w
= decode_any_window (window
);
636 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w
)),
637 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w
)),
638 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w
)),
639 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w
)),
643 DEFUN ("window-pixel-edges", Fwindow_pixel_edges
, Swindow_pixel_edges
, 0, 1, 0,
644 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
645 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
646 RIGHT is one more than the rightmost x position occupied by WINDOW,
647 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
648 The pixel edges include the space used by the window's scroll bar,
649 display margins, fringes, header line, and mode line, if it has them.
650 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
654 register struct window
*w
= decode_any_window (window
);
656 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w
)),
657 Fcons (make_number (WINDOW_TOP_EDGE_Y (w
)),
658 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w
)),
659 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w
)),
663 DEFUN ("window-inside-edges", Fwindow_inside_edges
, Swindow_inside_edges
, 0, 1, 0,
664 doc
: /* Return a list of the edge coordinates of WINDOW.
665 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
666 RIGHT is one more than the rightmost column used by text in WINDOW,
667 and BOTTOM is one more than the bottommost row used by text in WINDOW.
668 The inside edges do not include the space used by the window's scroll bar,
669 display margins, fringes, header line, and/or mode line. */)
673 register struct window
*w
= decode_any_window (window
);
675 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w
)
676 + WINDOW_LEFT_MARGIN_COLS (w
)
677 + WINDOW_LEFT_FRINGE_COLS (w
)),
678 make_number (WINDOW_TOP_EDGE_LINE (w
)
679 + WINDOW_HEADER_LINE_LINES (w
)),
680 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w
)
681 - WINDOW_RIGHT_MARGIN_COLS (w
)
682 - WINDOW_RIGHT_FRINGE_COLS (w
)),
683 make_number (WINDOW_BOTTOM_EDGE_LINE (w
)
684 - WINDOW_MODE_LINE_LINES (w
)));
687 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges
, Swindow_inside_pixel_edges
, 0, 1, 0,
688 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
689 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
690 RIGHT is one more than the rightmost x position used by text in WINDOW,
691 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
692 The inside edges do not include the space used by the window's scroll bar,
693 display margins, fringes, header line, and/or mode line. */)
697 register struct window
*w
= decode_any_window (window
);
699 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w
)
700 + WINDOW_LEFT_MARGIN_WIDTH (w
)
701 + WINDOW_LEFT_FRINGE_WIDTH (w
)),
702 make_number (WINDOW_TOP_EDGE_Y (w
)
703 + WINDOW_HEADER_LINE_HEIGHT (w
)),
704 make_number (WINDOW_BOX_RIGHT_EDGE_X (w
)
705 - WINDOW_RIGHT_MARGIN_WIDTH (w
)
706 - WINDOW_RIGHT_FRINGE_WIDTH (w
)),
707 make_number (WINDOW_BOTTOM_EDGE_Y (w
)
708 - WINDOW_MODE_LINE_HEIGHT (w
)));
711 /* Test if the character at column *X, row *Y is within window W.
712 If it is not, return ON_NOTHING;
713 if it is in the window's text area,
714 set *x and *y to its location relative to the upper left corner
717 if it is on the window's modeline, return ON_MODE_LINE;
718 if it is on the border between the window and its right sibling,
719 return ON_VERTICAL_BORDER.
720 if it is on a scroll bar,
721 return ON_SCROLL_BAR.
722 if it is on the window's top line, return ON_HEADER_LINE;
723 if it is in left or right fringe of the window,
724 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
725 to window-relative coordinates;
726 if it is in the marginal area to the left/right of the window,
727 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
728 to window-relative coordinates.
730 X and Y are frame relative pixel coordinates. */
732 static enum window_part
733 coordinates_in_window (w
, x
, y
)
734 register struct window
*w
;
737 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
738 int left_x
, right_x
, top_y
, bottom_y
;
739 enum window_part part
;
740 int ux
= FRAME_COLUMN_WIDTH (f
);
741 int x0
= WINDOW_LEFT_EDGE_X (w
);
742 int x1
= WINDOW_RIGHT_EDGE_X (w
);
743 /* The width of the area where the vertical line can be dragged.
744 (Between mode lines for instance. */
745 int grabbable_width
= ux
;
746 int lmargin_width
, rmargin_width
, text_left
, text_right
;
748 /* In what's below, we subtract 1 when computing right_x because we
749 want the rightmost pixel, which is given by left_pixel+width-1. */
750 if (w
->pseudo_window_p
)
753 right_x
= WINDOW_TOTAL_WIDTH (w
) - 1;
754 top_y
= WINDOW_TOP_EDGE_Y (w
);
755 bottom_y
= WINDOW_BOTTOM_EDGE_Y (w
);
759 left_x
= WINDOW_BOX_LEFT_EDGE_X (w
);
760 right_x
= WINDOW_BOX_RIGHT_EDGE_X (w
) - 1;
761 top_y
= WINDOW_TOP_EDGE_Y (w
);
762 bottom_y
= WINDOW_BOTTOM_EDGE_Y (w
);
765 /* Outside any interesting row? */
766 if (*y
< top_y
|| *y
>= bottom_y
)
769 /* On the mode line or header line? If it's near the start of
770 the mode or header line of window that's has a horizontal
771 sibling, say it's on the vertical line. That's to be able
772 to resize windows horizontally in case we're using toolkit
775 if (WINDOW_WANTS_MODELINE_P (w
)
776 && *y
>= bottom_y
- CURRENT_MODE_LINE_HEIGHT (w
))
780 header_vertical_border_check
:
781 /* We're somewhere on the mode line. We consider the place
782 between mode lines of horizontally adjacent mode lines
783 as the vertical border. If scroll bars on the left,
784 return the right window. */
785 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
)
786 || WINDOW_RIGHTMOST_P (w
))
788 if (!WINDOW_LEFTMOST_P (w
) && abs (*x
- x0
) < grabbable_width
)
790 /* Convert X and Y to window relative coordinates.
791 Vertical border is at the left edge of window. */
792 *x
= max (0, *x
- x0
);
794 return ON_VERTICAL_BORDER
;
799 if (abs (*x
- x1
) < grabbable_width
)
801 /* Convert X and Y to window relative coordinates.
802 Vertical border is at the right edge of window. */
803 *x
= min (x1
, *x
) - x0
;
805 return ON_VERTICAL_BORDER
;
809 if (*x
< x0
|| *x
>= x1
)
812 /* Convert X and Y to window relative coordinates.
813 Mode line starts at left edge of window. */
819 if (WINDOW_WANTS_HEADER_LINE_P (w
)
820 && *y
< top_y
+ CURRENT_HEADER_LINE_HEIGHT (w
))
822 part
= ON_HEADER_LINE
;
823 goto header_vertical_border_check
;
826 if (*x
< x0
|| *x
>= x1
)
829 /* Outside any interesting column? */
830 if (*x
< left_x
|| *x
> right_x
)
833 return ON_SCROLL_BAR
;
836 lmargin_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
837 rmargin_width
= window_box_width (w
, RIGHT_MARGIN_AREA
);
839 text_left
= window_box_left (w
, TEXT_AREA
);
840 text_right
= text_left
+ window_box_width (w
, TEXT_AREA
);
842 if (FRAME_WINDOW_P (f
))
844 if (!w
->pseudo_window_p
845 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w
)
846 && !WINDOW_RIGHTMOST_P (w
)
847 && (abs (*x
- right_x
) < grabbable_width
))
849 /* Convert X and Y to window relative coordinates.
850 Vertical border is at the right edge of window. */
851 *x
= min (right_x
, *x
) - left_x
;
853 return ON_VERTICAL_BORDER
;
858 /* Need to say "*x > right_x" rather than >=, since on character
859 terminals, the vertical line's x coordinate is right_x. */
860 if (!w
->pseudo_window_p
861 && !WINDOW_RIGHTMOST_P (w
)
862 && *x
> right_x
- ux
)
864 /* On the border on the right side of the window? Assume that
865 this area begins at RIGHT_X minus a canonical char width. */
866 *x
= min (right_x
, *x
) - left_x
;
868 return ON_VERTICAL_BORDER
;
874 if (lmargin_width
> 0
875 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
876 ? (*x
>= left_x
+ WINDOW_LEFT_FRINGE_WIDTH (w
))
877 : (*x
< left_x
+ lmargin_width
)))
880 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
))
881 *x
-= WINDOW_LEFT_FRINGE_WIDTH (w
);
883 return ON_LEFT_MARGIN
;
886 /* Convert X and Y to window-relative pixel coordinates. */
889 return ON_LEFT_FRINGE
;
892 if (*x
>= text_right
)
894 if (rmargin_width
> 0
895 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
896 ? (*x
< right_x
- WINDOW_RIGHT_FRINGE_WIDTH (w
))
897 : (*x
>= right_x
- rmargin_width
)))
899 *x
-= right_x
- rmargin_width
;
900 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
))
901 *x
+= WINDOW_RIGHT_FRINGE_WIDTH (w
);
903 return ON_RIGHT_MARGIN
;
906 /* Convert X and Y to window-relative pixel coordinates. */
907 *x
-= left_x
+ WINDOW_LEFT_FRINGE_WIDTH (w
);
909 return ON_RIGHT_FRINGE
;
912 /* Everything special ruled out - must be on text area */
919 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
920 Scoordinates_in_window_p
, 2, 2, 0,
921 doc
: /* Return non-nil if COORDINATES are in WINDOW.
922 COORDINATES is a cons of the form (X . Y), X and Y being distances
923 measured in characters from the upper-left corner of the frame.
924 \(0 . 0) denotes the character in the upper left corner of the
926 If COORDINATES are in the text portion of WINDOW,
927 the coordinates relative to the window are returned.
928 If they are in the mode line of WINDOW, `mode-line' is returned.
929 If they are in the top mode line of WINDOW, `header-line' is returned.
930 If they are in the left fringe of WINDOW, `left-fringe' is returned.
931 If they are in the right fringe of WINDOW, `right-fringe' is returned.
932 If they are on the border between WINDOW and its right sibling,
933 `vertical-line' is returned.
934 If they are in the windows's left or right marginal areas, `left-margin'\n\
935 or `right-margin' is returned. */)
936 (coordinates
, window
)
937 register Lisp_Object coordinates
, window
;
944 CHECK_WINDOW (window
);
945 w
= XWINDOW (window
);
946 f
= XFRAME (w
->frame
);
947 CHECK_CONS (coordinates
);
948 lx
= Fcar (coordinates
);
949 ly
= Fcdr (coordinates
);
950 CHECK_NUMBER_OR_FLOAT (lx
);
951 CHECK_NUMBER_OR_FLOAT (ly
);
952 x
= FRAME_PIXEL_X_FROM_CANON_X (f
, lx
) + FRAME_INTERNAL_BORDER_WIDTH (f
);
953 y
= FRAME_PIXEL_Y_FROM_CANON_Y (f
, ly
) + FRAME_INTERNAL_BORDER_WIDTH (f
);
955 switch (coordinates_in_window (w
, &x
, &y
))
961 /* X and Y are now window relative pixel coordinates. Convert
962 them to canonical char units before returning them. */
963 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f
, x
),
964 FRAME_CANON_Y_FROM_PIXEL_Y (f
, y
));
969 case ON_VERTICAL_BORDER
:
970 return Qvertical_line
;
978 case ON_RIGHT_FRINGE
:
979 return Qright_fringe
;
984 case ON_RIGHT_MARGIN
:
985 return Qright_margin
;
988 /* Historically we are supposed to return nil in this case. */
997 /* Callback for foreach_window, used in window_from_coordinates.
998 Check if window W contains coordinates specified by USER_DATA which
999 is actually a pointer to a struct check_window_data CW.
1001 Check if window W contains coordinates *CW->x and *CW->y. If it
1002 does, return W in *CW->window, as Lisp_Object, and return in
1003 *CW->part the part of the window under coordinates *X,*Y. Return
1004 zero from this function to stop iterating over windows. */
1006 struct check_window_data
1008 Lisp_Object
*window
;
1010 enum window_part
*part
;
1014 check_window_containing (w
, user_data
)
1018 struct check_window_data
*cw
= (struct check_window_data
*) user_data
;
1019 enum window_part found
;
1022 found
= coordinates_in_window (w
, cw
->x
, cw
->y
);
1023 if (found
!= ON_NOTHING
)
1026 XSETWINDOW (*cw
->window
, w
);
1034 /* Find the window containing frame-relative pixel position X/Y and
1035 return it as a Lisp_Object.
1037 If X, Y is on one of the window's special `window_part' elements,
1038 set *PART to the id of that element, and return X and Y converted
1039 to window relative coordinates in WX and WY.
1041 If there is no window under X, Y return nil and leave *PART
1042 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1044 This function was previously implemented with a loop cycling over
1045 windows with Fnext_window, and starting with the frame's selected
1046 window. It turned out that this doesn't work with an
1047 implementation of next_window using Vwindow_list, because
1048 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1049 tree of F when this function is called asynchronously from
1050 note_mouse_highlight. The original loop didn't terminate in this
1054 window_from_coordinates (f
, x
, y
, part
, wx
, wy
, tool_bar_p
)
1057 enum window_part
*part
;
1062 struct check_window_data cw
;
1063 enum window_part dummy
;
1069 cw
.window
= &window
, cw
.x
= &x
, cw
.y
= &y
; cw
.part
= part
;
1070 foreach_window (f
, check_window_containing
, &cw
);
1072 /* If not found above, see if it's in the tool bar window, if a tool
1076 && WINDOWP (f
->tool_bar_window
)
1077 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)) > 0
1078 && (coordinates_in_window (XWINDOW (f
->tool_bar_window
), &x
, &y
)
1082 window
= f
->tool_bar_window
;
1091 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
1092 doc
: /* Return window containing coordinates X and Y on FRAME.
1093 If omitted, FRAME defaults to the currently selected frame.
1094 The top left corner of the frame is considered to be row 0,
1097 Lisp_Object x
, y
, frame
;
1102 frame
= selected_frame
;
1103 CHECK_LIVE_FRAME (frame
);
1106 /* Check that arguments are integers or floats. */
1107 CHECK_NUMBER_OR_FLOAT (x
);
1108 CHECK_NUMBER_OR_FLOAT (y
);
1110 return window_from_coordinates (f
,
1111 (FRAME_PIXEL_X_FROM_CANON_X (f
, x
)
1112 + FRAME_INTERNAL_BORDER_WIDTH (f
)),
1113 (FRAME_PIXEL_Y_FROM_CANON_Y (f
, y
)
1114 + FRAME_INTERNAL_BORDER_WIDTH (f
)),
1118 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
1119 doc
: /* Return current value of point in WINDOW.
1120 WINDOW defaults to the selected window.
1122 For a nonselected window, this is the value point would have
1123 if that window were selected.
1125 Note that, when WINDOW is the selected window and its buffer
1126 is also currently selected, the value returned is the same as (point).
1127 It would be more strictly correct to return the `top-level' value
1128 of point, outside of any save-excursion forms.
1129 But that is hard to define. */)
1133 register struct window
*w
= decode_window (window
);
1135 if (w
== XWINDOW (selected_window
)
1136 && current_buffer
== XBUFFER (w
->buffer
))
1138 return Fmarker_position (w
->pointm
);
1141 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
1142 doc
: /* Return position at which display currently starts in WINDOW.
1143 WINDOW defaults to the selected window.
1144 This is updated by redisplay or by calling `set-window-start'. */)
1148 return Fmarker_position (decode_window (window
)->start
);
1151 /* This is text temporarily removed from the doc string below.
1153 This function returns nil if the position is not currently known.
1154 That happens when redisplay is preempted and doesn't finish.
1155 If in that case you want to compute where the end of the window would
1156 have been if redisplay had finished, do this:
1158 (goto-char (window-start window))
1159 (vertical-motion (1- (window-height window)) window)
1162 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 2, 0,
1163 doc
: /* Return position at which display currently ends in WINDOW.
1164 WINDOW defaults to the selected window.
1165 This is updated by redisplay, when it runs to completion.
1166 Simply changing the buffer text or setting `window-start'
1167 does not update this value.
1168 Return nil if there is no recorded value. \(This can happen if the
1169 last redisplay of WINDOW was preempted, and did not finish.)
1170 If UPDATE is non-nil, compute the up-to-date position
1171 if it isn't already recorded. */)
1173 Lisp_Object window
, update
;
1176 struct window
*w
= decode_window (window
);
1184 #if 0 /* This change broke some things. We should make it later. */
1185 /* If we don't know the end position, return nil.
1186 The user can compute it with vertical-motion if he wants to.
1187 It would be nicer to do it automatically,
1188 but that's so slow that it would probably bother people. */
1189 if (NILP (w
->window_end_valid
))
1194 && ! (! NILP (w
->window_end_valid
)
1195 && XFASTINT (w
->last_modified
) >= BUF_MODIFF (b
)
1196 && XFASTINT (w
->last_overlay_modified
) >= BUF_OVERLAY_MODIFF (b
))
1199 struct text_pos startp
;
1201 struct buffer
*old_buffer
= NULL
;
1203 /* Cannot use Fvertical_motion because that function doesn't
1204 cope with variable-height lines. */
1205 if (b
!= current_buffer
)
1207 old_buffer
= current_buffer
;
1208 set_buffer_internal (b
);
1211 /* In case W->start is out of the range, use something
1212 reasonable. This situation occurred when loading a file with
1213 `-l' containing a call to `rmail' with subsequent other
1214 commands. At the end, W->start happened to be BEG, while
1215 rmail had already narrowed the buffer. */
1216 if (XMARKER (w
->start
)->charpos
< BEGV
)
1217 SET_TEXT_POS (startp
, BEGV
, BEGV_BYTE
);
1218 else if (XMARKER (w
->start
)->charpos
> ZV
)
1219 SET_TEXT_POS (startp
, ZV
, ZV_BYTE
);
1221 SET_TEXT_POS_FROM_MARKER (startp
, w
->start
);
1223 start_display (&it
, w
, startp
);
1224 move_it_vertically (&it
, window_box_height (w
));
1225 if (it
.current_y
< it
.last_visible_y
)
1226 move_it_past_eol (&it
);
1227 value
= make_number (IT_CHARPOS (it
));
1230 set_buffer_internal (old_buffer
);
1233 XSETINT (value
, BUF_Z (b
) - XFASTINT (w
->window_end_pos
));
1238 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
1239 doc
: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1242 Lisp_Object window
, pos
;
1244 register struct window
*w
= decode_window (window
);
1246 CHECK_NUMBER_COERCE_MARKER (pos
);
1247 if (w
== XWINDOW (selected_window
)
1248 && XBUFFER (w
->buffer
) == current_buffer
)
1251 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
1253 /* We have to make sure that redisplay updates the window to show
1254 the new value of point. */
1255 if (!EQ (window
, selected_window
))
1256 ++windows_or_buffers_changed
;
1261 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
1262 doc
: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1264 Optional third arg NOFORCE non-nil inhibits next redisplay
1265 from overriding motion of point in order to display at this exact start. */)
1266 (window
, pos
, noforce
)
1267 Lisp_Object window
, pos
, noforce
;
1269 register struct window
*w
= decode_window (window
);
1271 CHECK_NUMBER_COERCE_MARKER (pos
);
1272 set_marker_restricted (w
->start
, pos
, w
->buffer
);
1273 /* this is not right, but much easier than doing what is right. */
1274 w
->start_at_line_beg
= Qnil
;
1276 w
->force_start
= Qt
;
1277 w
->update_mode_line
= Qt
;
1278 XSETFASTINT (w
->last_modified
, 0);
1279 XSETFASTINT (w
->last_overlay_modified
, 0);
1280 if (!EQ (window
, selected_window
))
1281 windows_or_buffers_changed
++;
1286 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
1288 doc
: /* Return WINDOW's dedicated object, usually t or nil.
1289 See also `set-window-dedicated-p'. */)
1293 return decode_window (window
)->dedicated
;
1296 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
1297 Sset_window_dedicated_p
, 2, 2, 0,
1298 doc
: /* Control whether WINDOW is dedicated to the buffer it displays.
1299 If it is dedicated, Emacs will not automatically change
1300 which buffer appears in it.
1301 The second argument is the new value for the dedication flag;
1302 non-nil means yes. */)
1304 Lisp_Object window
, arg
;
1306 register struct window
*w
= decode_window (window
);
1310 return w
->dedicated
;
1313 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
1315 doc
: /* Return the display-table that WINDOW is using.
1316 WINDOW defaults to the selected window. */)
1320 return decode_window (window
)->display_table
;
1323 /* Get the display table for use on window W. This is either W's
1324 display table or W's buffer's display table. Ignore the specified
1325 tables if they are not valid; if no valid table is specified,
1328 struct Lisp_Char_Table
*
1329 window_display_table (w
)
1332 struct Lisp_Char_Table
*dp
= NULL
;
1334 if (DISP_TABLE_P (w
->display_table
))
1335 dp
= XCHAR_TABLE (w
->display_table
);
1336 else if (BUFFERP (w
->buffer
))
1338 struct buffer
*b
= XBUFFER (w
->buffer
);
1340 if (DISP_TABLE_P (b
->display_table
))
1341 dp
= XCHAR_TABLE (b
->display_table
);
1342 else if (DISP_TABLE_P (Vstandard_display_table
))
1343 dp
= XCHAR_TABLE (Vstandard_display_table
);
1349 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
1350 doc
: /* Set WINDOW's display-table to TABLE. */)
1352 register Lisp_Object window
, table
;
1354 register struct window
*w
;
1356 w
= decode_window (window
);
1357 w
->display_table
= table
;
1361 /* Record info on buffer window w is displaying
1362 when it is about to cease to display that buffer. */
1365 register struct window
*w
;
1372 if (b
!= XMARKER (w
->pointm
)->buffer
)
1376 if (w
== XWINDOW (selected_window
)
1377 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
1378 /* Do this except when the selected window's buffer
1379 is being removed from some other window. */
1381 /* last_window_start records the start position that this buffer
1382 had in the last window to be disconnected from it.
1383 Now that this statement is unconditional,
1384 it is possible for the buffer to be displayed in the
1385 selected window, while last_window_start reflects another
1386 window which was recently showing the same buffer.
1387 Some people might say that might be a good thing. Let's see. */
1388 b
->last_window_start
= marker_position (w
->start
);
1390 /* Point in the selected window's buffer
1391 is actually stored in that buffer, and the window's pointm isn't used.
1392 So don't clobber point in that buffer. */
1393 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
)
1394 /* This line helps to fix Horsley's testbug.el bug. */
1395 && !(WINDOWP (b
->last_selected_window
)
1396 && w
!= XWINDOW (b
->last_selected_window
)
1397 && EQ (buf
, XWINDOW (b
->last_selected_window
)->buffer
)))
1398 temp_set_point_both (b
,
1399 clip_to_bounds (BUF_BEGV (b
),
1400 XMARKER (w
->pointm
)->charpos
,
1402 clip_to_bounds (BUF_BEGV_BYTE (b
),
1403 marker_byte_position (w
->pointm
),
1406 if (WINDOWP (b
->last_selected_window
)
1407 && w
== XWINDOW (b
->last_selected_window
))
1408 b
->last_selected_window
= Qnil
;
1411 /* Put replacement into the window structure in place of old. */
1413 replace_window (old
, replacement
)
1414 Lisp_Object old
, replacement
;
1416 register Lisp_Object tem
;
1417 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
1419 /* If OLD is its frame's root_window, then replacement is the new
1420 root_window for that frame. */
1422 if (EQ (old
, FRAME_ROOT_WINDOW (XFRAME (o
->frame
))))
1423 FRAME_ROOT_WINDOW (XFRAME (o
->frame
)) = replacement
;
1425 p
->left_col
= o
->left_col
;
1426 p
->top_line
= o
->top_line
;
1427 p
->total_cols
= o
->total_cols
;
1428 p
->total_lines
= o
->total_lines
;
1429 p
->desired_matrix
= p
->current_matrix
= 0;
1431 bzero (&p
->cursor
, sizeof (p
->cursor
));
1432 bzero (&p
->last_cursor
, sizeof (p
->last_cursor
));
1433 bzero (&p
->phys_cursor
, sizeof (p
->phys_cursor
));
1434 p
->phys_cursor_type
= -1;
1435 p
->phys_cursor_width
= -1;
1436 p
->must_be_updated_p
= 0;
1437 p
->pseudo_window_p
= 0;
1438 XSETFASTINT (p
->window_end_vpos
, 0);
1439 XSETFASTINT (p
->window_end_pos
, 0);
1440 p
->window_end_valid
= Qnil
;
1441 p
->frozen_window_start_p
= 0;
1442 p
->orig_top_line
= p
->orig_total_lines
= Qnil
;
1444 p
->next
= tem
= o
->next
;
1446 XWINDOW (tem
)->prev
= replacement
;
1448 p
->prev
= tem
= o
->prev
;
1450 XWINDOW (tem
)->next
= replacement
;
1452 p
->parent
= tem
= o
->parent
;
1455 if (EQ (XWINDOW (tem
)->vchild
, old
))
1456 XWINDOW (tem
)->vchild
= replacement
;
1457 if (EQ (XWINDOW (tem
)->hchild
, old
))
1458 XWINDOW (tem
)->hchild
= replacement
;
1461 /*** Here, if replacement is a vertical combination
1462 and so is its new parent, we should make replacement's
1463 children be children of that parent instead. ***/
1466 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
1467 doc
: /* Remove WINDOW from the display. Default is selected window. */)
1469 register Lisp_Object window
;
1471 delete_window (window
);
1473 if (! NILP (Vwindow_configuration_change_hook
)
1474 && ! NILP (Vrun_hooks
))
1475 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
1481 delete_window (window
)
1482 register Lisp_Object window
;
1484 register Lisp_Object tem
, parent
, sib
;
1485 register struct window
*p
;
1486 register struct window
*par
;
1489 /* Because this function is called by other C code on non-leaf
1490 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1491 so we can't decode_window here. */
1493 window
= selected_window
;
1495 CHECK_WINDOW (window
);
1496 p
= XWINDOW (window
);
1498 /* It's a no-op to delete an already-deleted window. */
1499 if (NILP (p
->buffer
)
1501 && NILP (p
->vchild
))
1506 error ("Attempt to delete minibuffer or sole ordinary window");
1507 par
= XWINDOW (parent
);
1509 windows_or_buffers_changed
++;
1510 Vwindow_list
= Qnil
;
1511 f
= XFRAME (WINDOW_FRAME (p
));
1512 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
1514 /* Are we trying to delete any frame's selected window? */
1516 Lisp_Object swindow
, pwindow
;
1518 /* See if the frame's selected window is either WINDOW
1519 or any subwindow of it, by finding all that window's parents
1520 and comparing each one with WINDOW. */
1521 swindow
= FRAME_SELECTED_WINDOW (f
);
1526 while (!NILP (pwindow
))
1528 if (EQ (window
, pwindow
))
1530 pwindow
= XWINDOW (pwindow
)->parent
;
1533 /* If the window being deleted is not a parent of SWINDOW,
1534 then SWINDOW is ok as the new selected window. */
1535 if (!EQ (window
, pwindow
))
1537 /* Otherwise, try another window for SWINDOW. */
1538 swindow
= Fnext_window (swindow
, Qlambda
, Qnil
);
1540 /* If we get back to the frame's selected window,
1541 it means there was no acceptable alternative,
1542 so we cannot delete. */
1543 if (EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1544 error ("Cannot delete window");
1547 /* If we need to change SWINDOW, do it. */
1548 if (! EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1550 /* If we're about to delete the selected window on the
1551 selected frame, then we should use Fselect_window to select
1552 the new window. On the other hand, if we're about to
1553 delete the selected window on any other frame, we shouldn't do
1554 anything but set the frame's selected_window slot. */
1555 if (EQ (FRAME_SELECTED_WINDOW (f
), selected_window
))
1556 Fselect_window (swindow
, Qnil
);
1558 FRAME_SELECTED_WINDOW (f
) = swindow
;
1562 /* Now we know we can delete this one. */
1563 window_deletion_count
++;
1566 /* tem is null for dummy parent windows
1567 (which have inferiors but not any contents themselves) */
1571 unchain_marker (XMARKER (p
->pointm
));
1572 unchain_marker (XMARKER (p
->start
));
1575 /* Free window glyph matrices. It is sure that they are allocated
1576 again when ADJUST_GLYPHS is called. Block input so that expose
1577 events and other events that access glyph matrices are not
1578 processed while we are changing them. */
1580 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f
)));
1584 XWINDOW (tem
)->prev
= p
->prev
;
1588 XWINDOW (tem
)->next
= p
->next
;
1590 if (EQ (window
, par
->hchild
))
1591 par
->hchild
= p
->next
;
1592 if (EQ (window
, par
->vchild
))
1593 par
->vchild
= p
->next
;
1595 /* Find one of our siblings to give our space to. */
1599 /* If p gives its space to its next sibling, that sibling needs
1600 to have its top/left side pulled back to where p's is.
1601 set_window_{height,width} will re-position the sibling's
1604 XWINDOW (sib
)->top_line
= p
->top_line
;
1605 XWINDOW (sib
)->left_col
= p
->left_col
;
1608 /* Stretch that sibling. */
1609 if (!NILP (par
->vchild
))
1610 set_window_height (sib
,
1611 XFASTINT (XWINDOW (sib
)->total_lines
) + XFASTINT (p
->total_lines
),
1613 if (!NILP (par
->hchild
))
1614 set_window_width (sib
,
1615 XFASTINT (XWINDOW (sib
)->total_cols
) + XFASTINT (p
->total_cols
),
1618 /* If parent now has only one child,
1619 put the child into the parent's place. */
1623 if (NILP (XWINDOW (tem
)->next
)) {
1624 replace_window (parent
, tem
);
1625 par
= XWINDOW (tem
);
1628 /* Since we may be deleting combination windows, we must make sure that
1629 not only p but all its children have been marked as deleted. */
1630 if (! NILP (p
->hchild
))
1631 delete_all_subwindows (XWINDOW (p
->hchild
));
1632 else if (! NILP (p
->vchild
))
1633 delete_all_subwindows (XWINDOW (p
->vchild
));
1635 /* Mark this window as deleted. */
1636 p
->buffer
= p
->hchild
= p
->vchild
= Qnil
;
1638 if (! NILP (par
->parent
))
1639 par
= XWINDOW (par
->parent
);
1641 /* Check if we have a v/hchild with a v/hchild. In that case remove
1644 if (! NILP (par
->vchild
) && ! NILP (XWINDOW (par
->vchild
)->vchild
))
1646 p
= XWINDOW (par
->vchild
);
1647 par
->vchild
= p
->vchild
;
1650 else if (! NILP (par
->hchild
) && ! NILP (XWINDOW (par
->hchild
)->hchild
))
1652 p
= XWINDOW (par
->hchild
);
1653 par
->hchild
= p
->hchild
;
1661 while (! NILP (tem
)) {
1662 XWINDOW (tem
)->parent
= p
->parent
;
1663 if (NILP (XWINDOW (tem
)->next
))
1665 tem
= XWINDOW (tem
)->next
;
1668 /* The next of the v/hchild we are removing is now the next of the
1669 last child for the v/hchild:
1670 Before v/hchild -> v/hchild -> next1 -> next2
1673 After: v/hchild -> next1 -> next2 -> next3
1675 XWINDOW (tem
)->next
= p
->next
;
1676 if (! NILP (p
->next
))
1677 XWINDOW (p
->next
)->prev
= tem
;
1679 p
->next
= p
->prev
= p
->vchild
= p
->hchild
= p
->buffer
= Qnil
;
1683 /* Adjust glyph matrices. */
1690 /***********************************************************************
1692 ***********************************************************************/
1694 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1695 pointer. This is a callback function for foreach_window, used in
1696 function window_list. */
1699 add_window_to_list (w
, user_data
)
1703 Lisp_Object
*list
= (Lisp_Object
*) user_data
;
1705 XSETWINDOW (window
, w
);
1706 *list
= Fcons (window
, *list
);
1711 /* Return a list of all windows, for use by next_window. If
1712 Vwindow_list is a list, return that list. Otherwise, build a new
1713 list, cache it in Vwindow_list, and return that. */
1718 if (!CONSP (Vwindow_list
))
1722 Vwindow_list
= Qnil
;
1723 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
1725 Lisp_Object args
[2];
1727 /* We are visiting windows in canonical order, and add
1728 new windows at the front of args[1], which means we
1729 have to reverse this list at the end. */
1731 foreach_window (XFRAME (XCAR (tail
)), add_window_to_list
, &args
[1]);
1732 args
[0] = Vwindow_list
;
1733 args
[1] = Fnreverse (args
[1]);
1734 Vwindow_list
= Fnconc (2, args
);
1738 return Vwindow_list
;
1742 /* Value is non-zero if WINDOW satisfies the constraints given by
1743 OWINDOW, MINIBUF and ALL_FRAMES.
1745 MINIBUF t means WINDOW may be minibuffer windows.
1746 `lambda' means WINDOW may not be a minibuffer window.
1747 a window means a specific minibuffer window
1749 ALL_FRAMES t means search all frames,
1750 nil means search just current frame,
1751 `visible' means search just visible frames,
1752 0 means search visible and iconified frames,
1753 a window means search the frame that window belongs to,
1754 a frame means consider windows on that frame, only. */
1757 candidate_window_p (window
, owindow
, minibuf
, all_frames
)
1758 Lisp_Object window
, owindow
, minibuf
, all_frames
;
1760 struct window
*w
= XWINDOW (window
);
1761 struct frame
*f
= XFRAME (w
->frame
);
1762 int candidate_p
= 1;
1764 if (!BUFFERP (w
->buffer
))
1766 else if (MINI_WINDOW_P (w
)
1767 && (EQ (minibuf
, Qlambda
)
1768 || (WINDOWP (minibuf
) && !EQ (minibuf
, window
))))
1770 /* If MINIBUF is `lambda' don't consider any mini-windows.
1771 If it is a window, consider only that one. */
1774 else if (EQ (all_frames
, Qt
))
1776 else if (NILP (all_frames
))
1778 xassert (WINDOWP (owindow
));
1779 candidate_p
= EQ (w
->frame
, XWINDOW (owindow
)->frame
);
1781 else if (EQ (all_frames
, Qvisible
))
1783 FRAME_SAMPLE_VISIBILITY (f
);
1784 candidate_p
= FRAME_VISIBLE_P (f
);
1786 else if (INTEGERP (all_frames
) && XINT (all_frames
) == 0)
1788 FRAME_SAMPLE_VISIBILITY (f
);
1789 candidate_p
= FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
);
1791 else if (WINDOWP (all_frames
))
1792 candidate_p
= (EQ (FRAME_MINIBUF_WINDOW (f
), all_frames
)
1793 || EQ (XWINDOW (all_frames
)->frame
, w
->frame
)
1794 || EQ (XWINDOW (all_frames
)->frame
, FRAME_FOCUS_FRAME (f
)));
1795 else if (FRAMEP (all_frames
))
1796 candidate_p
= EQ (all_frames
, w
->frame
);
1802 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1803 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1807 decode_next_window_args (window
, minibuf
, all_frames
)
1808 Lisp_Object
*window
, *minibuf
, *all_frames
;
1811 *window
= selected_window
;
1813 CHECK_LIVE_WINDOW (*window
);
1815 /* MINIBUF nil may or may not include minibuffers. Decide if it
1817 if (NILP (*minibuf
))
1818 *minibuf
= minibuf_level
? minibuf_window
: Qlambda
;
1819 else if (!EQ (*minibuf
, Qt
))
1822 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1823 => count none of them, or a specific minibuffer window (the
1824 active one) to count. */
1826 /* ALL_FRAMES nil doesn't specify which frames to include. */
1827 if (NILP (*all_frames
))
1828 *all_frames
= (!EQ (*minibuf
, Qlambda
)
1829 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window
)->frame
))
1831 else if (EQ (*all_frames
, Qvisible
))
1833 else if (EQ (*all_frames
, make_number (0)))
1835 else if (FRAMEP (*all_frames
))
1837 else if (!EQ (*all_frames
, Qt
))
1840 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1841 search just current frame, `visible' meaning search just visible
1842 frames, 0 meaning search visible and iconified frames, or a
1843 window, meaning search the frame that window belongs to, or a
1844 frame, meaning consider windows on that frame, only. */
1848 /* Return the next or previous window of WINDOW in canonical ordering
1849 of windows. NEXT_P non-zero means return the next window. See the
1850 documentation string of next-window for the meaning of MINIBUF and
1854 next_window (window
, minibuf
, all_frames
, next_p
)
1855 Lisp_Object window
, minibuf
, all_frames
;
1858 decode_next_window_args (&window
, &minibuf
, &all_frames
);
1860 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1861 return the first window on the frame. */
1862 if (FRAMEP (all_frames
)
1863 && !EQ (all_frames
, XWINDOW (window
)->frame
))
1864 return Fframe_first_window (all_frames
);
1870 /* Find WINDOW in the list of all windows. */
1871 list
= Fmemq (window
, window_list ());
1873 /* Scan forward from WINDOW to the end of the window list. */
1875 for (list
= XCDR (list
); CONSP (list
); list
= XCDR (list
))
1876 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1879 /* Scan from the start of the window list up to WINDOW. */
1881 for (list
= Vwindow_list
;
1882 CONSP (list
) && !EQ (XCAR (list
), window
);
1884 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1888 window
= XCAR (list
);
1892 Lisp_Object candidate
, list
;
1894 /* Scan through the list of windows for candidates. If there are
1895 candidate windows in front of WINDOW, the last one of these
1896 is the one we want. If there are candidates following WINDOW
1897 in the list, again the last one of these is the one we want. */
1899 for (list
= window_list (); CONSP (list
); list
= XCDR (list
))
1901 if (EQ (XCAR (list
), window
))
1903 if (WINDOWP (candidate
))
1906 else if (candidate_window_p (XCAR (list
), window
, minibuf
,
1908 candidate
= XCAR (list
);
1911 if (WINDOWP (candidate
))
1919 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
1920 doc
: /* Return next window after WINDOW in canonical ordering of windows.
1921 If omitted, WINDOW defaults to the selected window.
1923 Optional second arg MINIBUF t means count the minibuffer window even
1924 if not active. MINIBUF nil or omitted means count the minibuffer iff
1925 it is active. MINIBUF neither t nor nil means not to count the
1926 minibuffer even if it is active.
1928 Several frames may share a single minibuffer; if the minibuffer
1929 counts, all windows on all frames that share that minibuffer count
1930 too. Therefore, `next-window' can be used to iterate through the
1931 set of windows even when the minibuffer is on another frame. If the
1932 minibuffer does not count, only windows from WINDOW's frame count.
1934 Optional third arg ALL-FRAMES t means include windows on all frames.
1935 ALL-FRAMES nil or omitted means cycle within the frames as specified
1936 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1937 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1938 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1939 Anything else means restrict to WINDOW's frame.
1941 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1942 `next-window' to iterate through the entire cycle of acceptable
1943 windows, eventually ending up back at the window you started with.
1944 `previous-window' traverses the same cycle, in the reverse order. */)
1945 (window
, minibuf
, all_frames
)
1946 Lisp_Object window
, minibuf
, all_frames
;
1948 return next_window (window
, minibuf
, all_frames
, 1);
1952 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
1953 doc
: /* Return the window preceding WINDOW in canonical ordering of windows.
1954 If omitted, WINDOW defaults to the selected window.
1956 Optional second arg MINIBUF t means count the minibuffer window even
1957 if not active. MINIBUF nil or omitted means count the minibuffer iff
1958 it is active. MINIBUF neither t nor nil means not to count the
1959 minibuffer even if it is active.
1961 Several frames may share a single minibuffer; if the minibuffer
1962 counts, all windows on all frames that share that minibuffer count
1963 too. Therefore, `previous-window' can be used to iterate through
1964 the set of windows even when the minibuffer is on another frame. If
1965 the minibuffer does not count, only windows from WINDOW's frame count
1967 Optional third arg ALL-FRAMES t means include windows on all frames.
1968 ALL-FRAMES nil or omitted means cycle within the frames as specified
1969 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1970 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1971 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1972 Anything else means restrict to WINDOW's frame.
1974 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1975 `previous-window' to iterate through the entire cycle of acceptable
1976 windows, eventually ending up back at the window you started with.
1977 `next-window' traverses the same cycle, in the reverse order. */)
1978 (window
, minibuf
, all_frames
)
1979 Lisp_Object window
, minibuf
, all_frames
;
1981 return next_window (window
, minibuf
, all_frames
, 0);
1985 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
1986 doc
: /* Select the ARG'th different window on this frame.
1987 All windows on current frame are arranged in a cyclic order.
1988 This command selects the window ARG steps away in that order.
1989 A negative ARG moves in the opposite order. The optional second
1990 argument ALL-FRAMES has the same meaning as in `next-window', which see. */)
1992 Lisp_Object arg
, all_frames
;
1998 window
= selected_window
;
2000 for (i
= XINT (arg
); i
> 0; --i
)
2001 window
= Fnext_window (window
, Qnil
, all_frames
);
2003 window
= Fprevious_window (window
, Qnil
, all_frames
);
2005 Fselect_window (window
, Qnil
);
2010 DEFUN ("window-list", Fwindow_list
, Swindow_list
, 0, 3, 0,
2011 doc
: /* Return a list of windows on FRAME, starting with WINDOW.
2012 FRAME nil or omitted means use the selected frame.
2013 WINDOW nil or omitted means use the selected window.
2014 MINIBUF t means include the minibuffer window, even if it isn't active.
2015 MINIBUF nil or omitted means include the minibuffer window only
2017 MINIBUF neither nil nor t means never include the minibuffer window. */)
2018 (frame
, minibuf
, window
)
2019 Lisp_Object frame
, minibuf
, window
;
2022 window
= FRAMEP (frame
) ? XFRAME (frame
)->selected_window
: selected_window
;
2023 CHECK_WINDOW (window
);
2025 frame
= selected_frame
;
2027 if (!EQ (frame
, XWINDOW (window
)->frame
))
2028 error ("Window is on a different frame");
2030 return window_list_1 (window
, minibuf
, frame
);
2034 /* Return a list of windows in canonical ordering. Arguments are like
2035 for `next-window'. */
2038 window_list_1 (window
, minibuf
, all_frames
)
2039 Lisp_Object window
, minibuf
, all_frames
;
2041 Lisp_Object tail
, list
, rest
;
2043 decode_next_window_args (&window
, &minibuf
, &all_frames
);
2046 for (tail
= window_list (); CONSP (tail
); tail
= XCDR (tail
))
2047 if (candidate_window_p (XCAR (tail
), window
, minibuf
, all_frames
))
2048 list
= Fcons (XCAR (tail
), list
);
2050 /* Rotate the list to start with WINDOW. */
2051 list
= Fnreverse (list
);
2052 rest
= Fmemq (window
, list
);
2053 if (!NILP (rest
) && !EQ (rest
, list
))
2055 for (tail
= list
; !EQ (XCDR (tail
), rest
); tail
= XCDR (tail
))
2057 XSETCDR (tail
, Qnil
);
2058 list
= nconc2 (rest
, list
);
2065 /* Look at all windows, performing an operation specified by TYPE
2067 If FRAMES is Qt, look at all frames;
2068 Qnil, look at just the selected frame;
2069 Qvisible, look at visible frames;
2070 a frame, just look at windows on that frame.
2071 If MINI is non-zero, perform the operation on minibuffer windows too. */
2076 GET_BUFFER_WINDOW
, /* Arg is buffer */
2077 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
2078 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
2079 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
2081 UNSHOW_BUFFER
, /* Arg is buffer */
2082 REDISPLAY_BUFFER_WINDOWS
, /* Arg is buffer */
2087 window_loop (type
, obj
, mini
, frames
)
2088 enum window_loop type
;
2089 Lisp_Object obj
, frames
;
2092 Lisp_Object window
, windows
, best_window
, frame_arg
;
2094 struct gcpro gcpro1
;
2096 /* If we're only looping through windows on a particular frame,
2097 frame points to that frame. If we're looping through windows
2098 on all frames, frame is 0. */
2099 if (FRAMEP (frames
))
2100 f
= XFRAME (frames
);
2101 else if (NILP (frames
))
2102 f
= SELECTED_FRAME ();
2107 frame_arg
= Qlambda
;
2108 else if (EQ (frames
, make_number (0)))
2110 else if (EQ (frames
, Qvisible
))
2115 /* frame_arg is Qlambda to stick to one frame,
2116 Qvisible to consider all visible frames,
2119 /* Pick a window to start with. */
2123 window
= FRAME_SELECTED_WINDOW (f
);
2125 window
= FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2127 windows
= window_list_1 (window
, mini
? Qt
: Qnil
, frame_arg
);
2131 for (; CONSP (windows
); windows
= XCDR (windows
))
2135 window
= XCAR (windows
);
2136 w
= XWINDOW (window
);
2138 /* Note that we do not pay attention here to whether the frame
2139 is visible, since Fwindow_list skips non-visible frames if
2140 that is desired, under the control of frame_arg. */
2141 if (!MINI_WINDOW_P (w
)
2142 /* For UNSHOW_BUFFER, we must always consider all windows. */
2143 || type
== UNSHOW_BUFFER
2144 || (mini
&& minibuf_level
> 0))
2147 case GET_BUFFER_WINDOW
:
2148 if (EQ (w
->buffer
, obj
)
2149 /* Don't find any minibuffer window
2150 except the one that is currently in use. */
2151 && (MINI_WINDOW_P (w
)
2152 ? EQ (window
, minibuf_window
)
2155 if (NILP (best_window
))
2156 best_window
= window
;
2157 else if (EQ (window
, selected_window
))
2158 /* For compatibility with 20.x, prefer to return
2160 best_window
= window
;
2164 case GET_LRU_WINDOW
:
2165 /* `obj' is an integer encoding a bitvector.
2166 `obj & 1' means consider only full-width windows.
2167 `obj & 2' means consider also dedicated windows. */
2168 if (((XINT (obj
) & 1) && !WINDOW_FULL_WIDTH_P (w
))
2169 || (!(XINT (obj
) & 2) && !NILP (w
->dedicated
))
2170 /* Minibuffer windows are always ignored. */
2171 || MINI_WINDOW_P (w
))
2173 if (NILP (best_window
)
2174 || (XFASTINT (XWINDOW (best_window
)->use_time
)
2175 > XFASTINT (w
->use_time
)))
2176 best_window
= window
;
2179 case DELETE_OTHER_WINDOWS
:
2180 if (!EQ (window
, obj
))
2181 Fdelete_window (window
);
2184 case DELETE_BUFFER_WINDOWS
:
2185 if (EQ (w
->buffer
, obj
))
2187 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2189 /* If this window is dedicated, and in a frame of its own,
2191 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
2192 && !NILP (w
->dedicated
)
2193 && other_visible_frames (f
))
2195 /* Skip the other windows on this frame.
2196 There might be one, the minibuffer! */
2197 while (CONSP (XCDR (windows
))
2198 && EQ (XWINDOW (XCAR (windows
))->frame
,
2199 XWINDOW (XCAR (XCDR (windows
)))->frame
))
2200 windows
= XCDR (windows
);
2202 /* Now we can safely delete the frame. */
2203 Fdelete_frame (w
->frame
, Qnil
);
2205 else if (NILP (w
->parent
))
2207 /* If we're deleting the buffer displayed in the
2208 only window on the frame, find a new buffer to
2211 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
2212 Fset_window_buffer (window
, buffer
, Qnil
);
2213 if (EQ (window
, selected_window
))
2214 Fset_buffer (w
->buffer
);
2217 Fdelete_window (window
);
2221 case GET_LARGEST_WINDOW
:
2222 { /* nil `obj' means to ignore dedicated windows. */
2223 /* Ignore dedicated windows and minibuffers. */
2224 if (MINI_WINDOW_P (w
) || (NILP (obj
) && !NILP (w
->dedicated
)))
2227 if (NILP (best_window
))
2228 best_window
= window
;
2231 struct window
*b
= XWINDOW (best_window
);
2232 if (XFASTINT (w
->total_lines
) * XFASTINT (w
->total_cols
)
2233 > XFASTINT (b
->total_lines
) * XFASTINT (b
->total_cols
))
2234 best_window
= window
;
2240 if (EQ (w
->buffer
, obj
))
2243 struct frame
*f
= XFRAME (w
->frame
);
2245 /* Find another buffer to show in this window. */
2246 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
2248 /* If this window is dedicated, and in a frame of its own,
2250 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
2251 && !NILP (w
->dedicated
)
2252 && other_visible_frames (f
))
2254 /* Skip the other windows on this frame.
2255 There might be one, the minibuffer! */
2256 while (CONSP (XCDR (windows
))
2257 && EQ (XWINDOW (XCAR (windows
))->frame
,
2258 XWINDOW (XCAR (XCDR (windows
)))->frame
))
2259 windows
= XCDR (windows
);
2261 /* Now we can safely delete the frame. */
2262 Fdelete_frame (w
->frame
, Qnil
);
2264 else if (!NILP (w
->dedicated
) && !NILP (w
->parent
))
2267 XSETWINDOW (window
, w
);
2268 /* If this window is dedicated and not the only window
2269 in its frame, then kill it. */
2270 Fdelete_window (window
);
2274 /* Otherwise show a different buffer in the window. */
2275 w
->dedicated
= Qnil
;
2276 Fset_window_buffer (window
, buffer
, Qnil
);
2277 if (EQ (window
, selected_window
))
2278 Fset_buffer (w
->buffer
);
2283 case REDISPLAY_BUFFER_WINDOWS
:
2284 if (EQ (w
->buffer
, obj
))
2286 mark_window_display_accurate (window
, 0);
2287 w
->update_mode_line
= Qt
;
2288 XBUFFER (obj
)->prevent_redisplay_optimizations_p
= 1;
2289 ++update_mode_lines
;
2290 best_window
= window
;
2294 /* Check for a window that has a killed buffer. */
2295 case CHECK_ALL_WINDOWS
:
2296 if (! NILP (w
->buffer
)
2297 && NILP (XBUFFER (w
->buffer
)->name
))
2301 case WINDOW_LOOP_UNUSED
:
2310 /* Used for debugging. Abort if any window has a dead buffer. */
2313 check_all_windows ()
2315 window_loop (CHECK_ALL_WINDOWS
, Qnil
, 1, Qt
);
2318 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 2, 0,
2319 doc
: /* Return the window least recently selected or used for display.
2320 \(LRU means Least Recently Used.)
2322 Return a full-width window if possible.
2323 A minibuffer window is never a candidate.
2324 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2325 so if all windows are dedicated, the value is nil.
2326 If optional argument FRAME is `visible', search all visible frames.
2327 If FRAME is 0, search all visible and iconified frames.
2328 If FRAME is t, search all frames.
2329 If FRAME is nil, search only the selected frame.
2330 If FRAME is a frame, search only that frame. */)
2332 Lisp_Object frame
, dedicated
;
2334 register Lisp_Object w
;
2335 /* First try for a window that is full-width */
2336 w
= window_loop (GET_LRU_WINDOW
,
2337 NILP (dedicated
) ? make_number (1) : make_number (3),
2339 if (!NILP (w
) && !EQ (w
, selected_window
))
2341 /* If none of them, try the rest */
2342 return window_loop (GET_LRU_WINDOW
,
2343 NILP (dedicated
) ? make_number (0) : make_number (2),
2347 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 2, 0,
2348 doc
: /* Return the largest window in area.
2349 A minibuffer window is never a candidate.
2350 A dedicated window is never a candidate unless DEDICATED is non-nil,
2351 so if all windows are dedicated, the value is nil.
2352 If optional argument FRAME is `visible', search all visible frames.
2353 If FRAME is 0, search all visible and iconified frames.
2354 If FRAME is t, search all frames.
2355 If FRAME is nil, search only the selected frame.
2356 If FRAME is a frame, search only that frame. */)
2358 Lisp_Object frame
, dedicated
;
2360 return window_loop (GET_LARGEST_WINDOW
, dedicated
, 0,
2364 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 1, 2, 0,
2365 doc
: /* Return a window currently displaying BUFFER, or nil if none.
2366 BUFFER can be a buffer or a buffer name.
2367 If optional argument FRAME is `visible', search all visible frames.
2368 If optional argument FRAME is 0, search all visible and iconified frames.
2369 If FRAME is t, search all frames.
2370 If FRAME is nil, search only the selected frame.
2371 If FRAME is a frame, search only that frame. */)
2373 Lisp_Object buffer
, frame
;
2375 buffer
= Fget_buffer (buffer
);
2376 if (BUFFERP (buffer
))
2377 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
2382 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
2384 doc
: /* Make WINDOW (or the selected window) fill its frame.
2385 Only the frame WINDOW is on is affected.
2386 This function tries to reduce display jumps
2387 by keeping the text previously visible in WINDOW
2388 in the same place on the frame. Doing this depends on
2389 the value of (window-start WINDOW), so if calling this function
2390 in a program gives strange scrolling, make sure the window-start
2391 value is reasonable when this function is called. */)
2400 window
= selected_window
;
2402 CHECK_LIVE_WINDOW (window
);
2403 w
= XWINDOW (window
);
2405 startpos
= marker_position (w
->start
);
2406 top
= WINDOW_TOP_EDGE_LINE (w
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2408 if (MINI_WINDOW_P (w
) && top
> 0)
2409 error ("Can't expand minibuffer to full frame");
2411 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_FRAME (w
));
2413 /* Try to minimize scrolling, by setting the window start to the point
2414 will cause the text at the old window start to be at the same place
2415 on the frame. But don't try to do this if the window start is
2416 outside the visible portion (as might happen when the display is
2417 not current, due to typeahead). */
2418 new_top
= WINDOW_TOP_EDGE_LINE (w
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2420 && startpos
>= BUF_BEGV (XBUFFER (w
->buffer
))
2421 && startpos
<= BUF_ZV (XBUFFER (w
->buffer
)))
2423 struct position pos
;
2424 struct buffer
*obuf
= current_buffer
;
2426 Fset_buffer (w
->buffer
);
2427 /* This computation used to temporarily move point, but that can
2428 have unwanted side effects due to text properties. */
2429 pos
= *vmotion (startpos
, -top
, w
);
2431 set_marker_both (w
->start
, w
->buffer
, pos
.bufpos
, pos
.bytepos
);
2432 w
->window_end_valid
= Qnil
;
2433 w
->start_at_line_beg
= ((pos
.bytepos
== BEGV_BYTE
2434 || FETCH_BYTE (pos
.bytepos
- 1) == '\n') ? Qt
2436 /* We need to do this, so that the window-scroll-functions
2438 w
->optional_new_start
= Qt
;
2440 set_buffer_internal (obuf
);
2446 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
2447 1, 2, "bDelete windows on (buffer): ",
2448 doc
: /* Delete all windows showing BUFFER.
2449 BUFFER must be a buffer or the name of an existing buffer.
2450 Optional second argument FRAME controls which frames are affected.
2451 If optional argument FRAME is `visible', search all visible frames.
2452 If FRAME is 0, search all visible and iconified frames.
2453 If FRAME is nil, search all frames.
2454 If FRAME is t, search only the selected frame.
2455 If FRAME is a frame, search only that frame. */)
2457 Lisp_Object buffer
, frame
;
2459 /* FRAME uses t and nil to mean the opposite of what window_loop
2463 else if (EQ (frame
, Qt
))
2468 buffer
= Fget_buffer (buffer
);
2469 CHECK_BUFFER (buffer
);
2470 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, frame
);
2476 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
2477 Sreplace_buffer_in_windows
,
2478 1, 1, "bReplace buffer in windows: ",
2479 doc
: /* Replace BUFFER with some other buffer in all windows showing it.
2480 BUFFER may be a buffer or the name of an existing buffer. */)
2486 buffer
= Fget_buffer (buffer
);
2487 CHECK_BUFFER (buffer
);
2488 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
2493 /* Replace BUFFER with some other buffer in all windows
2494 of all frames, even those on other keyboards. */
2497 replace_buffer_in_all_windows (buffer
)
2501 Lisp_Object tail
, frame
;
2503 /* A single call to window_loop won't do the job
2504 because it only considers frames on the current keyboard.
2505 So loop manually over frames, and handle each one. */
2506 FOR_EACH_FRAME (tail
, frame
)
2507 window_loop (UNSHOW_BUFFER
, buffer
, 1, frame
);
2509 window_loop (UNSHOW_BUFFER
, buffer
, 1, Qt
);
2513 /* Set the height of WINDOW and all its inferiors. */
2515 /* The smallest acceptable dimensions for a window. Anything smaller
2516 might crash Emacs. */
2518 #define MIN_SAFE_WINDOW_WIDTH (2)
2519 #define MIN_SAFE_WINDOW_HEIGHT (1)
2521 /* Make sure that window_min_height and window_min_width are
2522 not too small; if they are, set them to safe minima. */
2525 check_min_window_sizes ()
2527 /* Smaller values might permit a crash. */
2528 if (window_min_width
< MIN_SAFE_WINDOW_WIDTH
)
2529 window_min_width
= MIN_SAFE_WINDOW_WIDTH
;
2530 if (window_min_height
< MIN_SAFE_WINDOW_HEIGHT
)
2531 window_min_height
= MIN_SAFE_WINDOW_HEIGHT
;
2534 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2535 minimum allowable size. */
2538 check_frame_size (frame
, rows
, cols
)
2542 /* For height, we have to see:
2543 how many windows the frame has at minimum (one or two),
2544 and whether it has a menu bar or other special stuff at the top. */
2546 = ((FRAME_MINIBUF_ONLY_P (frame
) || ! FRAME_HAS_MINIBUF_P (frame
))
2547 ? MIN_SAFE_WINDOW_HEIGHT
2548 : 2 * MIN_SAFE_WINDOW_HEIGHT
);
2550 if (FRAME_TOP_MARGIN (frame
) > 0)
2551 min_height
+= FRAME_TOP_MARGIN (frame
);
2553 if (*rows
< min_height
)
2555 if (*cols
< MIN_SAFE_WINDOW_WIDTH
)
2556 *cols
= MIN_SAFE_WINDOW_WIDTH
;
2559 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2560 check if W's width can be changed, otherwise check W's height.
2561 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2562 siblings, too. If none of the siblings is resizable, WINDOW isn't
2566 window_fixed_size_p (w
, width_p
, check_siblings_p
)
2568 int width_p
, check_siblings_p
;
2573 if (!NILP (w
->hchild
))
2575 c
= XWINDOW (w
->hchild
);
2579 /* A horiz. combination is fixed-width if all of if its
2581 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2582 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2583 fixed_p
= c
== NULL
;
2587 /* A horiz. combination is fixed-height if one of if its
2589 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2590 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2591 fixed_p
= c
!= NULL
;
2594 else if (!NILP (w
->vchild
))
2596 c
= XWINDOW (w
->vchild
);
2600 /* A vert. combination is fixed-width if one of if its
2602 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2603 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2604 fixed_p
= c
!= NULL
;
2608 /* A vert. combination is fixed-height if all of if its
2610 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2611 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2612 fixed_p
= c
== NULL
;
2615 else if (BUFFERP (w
->buffer
))
2617 struct buffer
*old
= current_buffer
;
2620 current_buffer
= XBUFFER (w
->buffer
);
2621 val
= find_symbol_value (Qwindow_size_fixed
);
2622 current_buffer
= old
;
2625 if (!EQ (val
, Qunbound
))
2627 fixed_p
= !NILP (val
);
2630 && ((EQ (val
, Qheight
) && width_p
)
2631 || (EQ (val
, Qwidth
) && !width_p
)))
2635 /* Can't tell if this one is resizable without looking at
2636 siblings. If all siblings are fixed-size this one is too. */
2637 if (!fixed_p
&& check_siblings_p
&& WINDOWP (w
->parent
))
2641 for (child
= w
->prev
; !NILP (child
); child
= XWINDOW (child
)->prev
)
2642 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2646 for (child
= w
->next
; !NILP (child
); child
= XWINDOW (child
)->next
)
2647 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2660 /* Return the minimum size for leaf window W. WIDTH_P non-zero means
2661 take into account fringes and the scrollbar of W. WIDTH_P zero
2662 means take into account mode-line and header-line of W. Return 1
2663 for the minibuffer. */
2666 window_min_size_2 (w
, width_p
)
2673 size
= max (window_min_width
,
2674 (MIN_SAFE_WINDOW_WIDTH
2675 + WINDOW_FRINGE_COLS (w
)
2676 + WINDOW_SCROLL_BAR_COLS (w
)));
2677 else if (MINI_WINDOW_P (w
))
2680 size
= max (window_min_height
,
2681 (MIN_SAFE_WINDOW_HEIGHT
2682 + (WINDOW_WANTS_MODELINE_P (w
) ? 1 : 0)
2683 + (WINDOW_WANTS_HEADER_LINE_P (w
) ? 1 : 0 )));
2688 /* Return the minimum size of window W, not taking fixed-width windows
2689 into account. WIDTH_P non-zero means return the minimum width,
2690 otherwise return the minimum height. If W is a combination window,
2691 compute the minimum size from the minimum sizes of W's children. */
2694 window_min_size_1 (w
, width_p
)
2701 if (!NILP (w
->hchild
))
2703 c
= XWINDOW (w
->hchild
);
2708 /* The min width of a horizontal combination is
2709 the sum of the min widths of its children. */
2712 size
+= window_min_size_1 (c
, width_p
);
2713 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2718 /* The min height a horizontal combination equals
2719 the maximum of all min height of its children. */
2722 int min_size
= window_min_size_1 (c
, width_p
);
2723 size
= max (min_size
, size
);
2724 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2728 else if (!NILP (w
->vchild
))
2730 c
= XWINDOW (w
->vchild
);
2735 /* The min width of a vertical combination is
2736 the maximum of the min widths of its children. */
2739 int min_size
= window_min_size_1 (c
, width_p
);
2740 size
= max (min_size
, size
);
2741 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2746 /* The min height of a vertical combination equals
2747 the sum of the min height of its children. */
2750 size
+= window_min_size_1 (c
, width_p
);
2751 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2756 size
= window_min_size_2 (w
, width_p
);
2762 /* Return the minimum size of window W, taking fixed-size windows into
2763 account. WIDTH_P non-zero means return the minimum width,
2764 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2765 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2766 unless FIXED is null. */
2769 window_min_size (w
, width_p
, ignore_fixed_p
, fixed
)
2771 int width_p
, ignore_fixed_p
, *fixed
;
2778 fixed_p
= window_fixed_size_p (w
, width_p
, 1);
2784 size
= width_p
? XFASTINT (w
->total_cols
) : XFASTINT (w
->total_lines
);
2786 size
= window_min_size_1 (w
, width_p
);
2792 /* Adjust the margins of window W if text area is too small.
2793 Return 1 if window width is ok after adjustment; 0 if window
2794 is still too narrow. */
2797 adjust_window_margins (w
)
2800 int box_cols
= (WINDOW_TOTAL_COLS (w
)
2801 - WINDOW_FRINGE_COLS (w
)
2802 - WINDOW_SCROLL_BAR_COLS (w
));
2803 int margin_cols
= (WINDOW_LEFT_MARGIN_COLS (w
)
2804 + WINDOW_RIGHT_MARGIN_COLS (w
));
2806 if (box_cols
- margin_cols
>= MIN_SAFE_WINDOW_WIDTH
)
2809 if (margin_cols
< 0 || box_cols
< MIN_SAFE_WINDOW_WIDTH
)
2812 /* Window's text area is too narrow, but reducing the window
2813 margins will fix that. */
2814 margin_cols
= box_cols
- MIN_SAFE_WINDOW_WIDTH
;
2815 if (WINDOW_RIGHT_MARGIN_COLS (w
) > 0)
2817 if (WINDOW_LEFT_MARGIN_COLS (w
) > 0)
2818 w
->left_margin_cols
= w
->right_margin_cols
2819 = make_number (margin_cols
/2);
2821 w
->right_margin_cols
= make_number (margin_cols
);
2824 w
->left_margin_cols
= make_number (margin_cols
);
2828 /* Calculate new sizes for windows in the list FORWARD when the window size
2829 goes from TOTAL to SIZE. TOTAL must be greater than SIZE.
2830 The number of windows in FORWARD is NCHILDREN, and the number that
2831 can shrink is SHRINKABLE.
2832 The minimum size a window can have is MIN_SIZE.
2833 If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
2834 If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
2837 This function returns an allocated array of new sizes that the caller
2838 must free. The size -1 means the window is fixed and RESIZE_FIXED_P
2839 is zero. Array index 0 refers to the first window in FORWARD, 1 to
2840 the second, and so on.
2842 This function tries to keep windows at least at the minimum size
2843 and resize other windows before it resizes any window to zero (i.e.
2844 delete that window).
2846 Windows are resized proportional to their size, so bigger windows
2847 shrink more than smaller windows. */
2849 shrink_windows (total
, size
, nchildren
, shrinkable
,
2850 min_size
, resize_fixed_p
, forward
, width_p
)
2851 int total
, size
, nchildren
, shrinkable
, min_size
;
2852 int resize_fixed_p
, width_p
;
2853 Lisp_Object forward
;
2855 int available_resize
= 0;
2859 int smallest
= total
;
2860 int total_removed
= 0;
2861 int total_shrink
= total
- size
;
2864 new_sizes
= xmalloc (sizeof (*new_sizes
) * nchildren
);
2866 for (i
= 0, child
= forward
; !NILP (child
); child
= c
->next
, ++i
)
2870 c
= XWINDOW (child
);
2871 child_size
= width_p
? XINT (c
->total_cols
) : XINT (c
->total_lines
);
2873 if (! resize_fixed_p
&& window_fixed_size_p (c
, width_p
, 0))
2877 new_sizes
[i
] = child_size
;
2878 if (child_size
> min_size
)
2879 available_resize
+= child_size
- min_size
;
2882 /* We might need to shrink some windows to zero. Find the smallest
2883 windows and set them to 0 until we can fulfil the new size. */
2885 while (shrinkable
> 1 && size
+ available_resize
< total
)
2887 for (i
= 0; i
< nchildren
; ++i
)
2888 if (new_sizes
[i
] > 0 && smallest
> new_sizes
[i
])
2889 smallest
= new_sizes
[i
];
2891 for (i
= 0; i
< nchildren
; ++i
)
2892 if (new_sizes
[i
] == smallest
)
2894 /* Resize this window down to zero. */
2896 if (smallest
> min_size
)
2897 available_resize
-= smallest
- min_size
;
2898 available_resize
+= smallest
;
2900 total_removed
+= smallest
;
2902 /* We don't know what the smallest is now. */
2905 /* Out of for, just remove one window at the time and
2906 check again if we have enough space. */
2911 /* Now, calculate the new sizes. Try to shrink each window
2912 proportional to its size. */
2913 for (i
= 0; i
< nchildren
; ++i
)
2915 if (new_sizes
[i
] > min_size
)
2917 int to_shrink
= total_shrink
*new_sizes
[i
]/total
;
2918 if (new_sizes
[i
] - to_shrink
< min_size
)
2919 to_shrink
= new_sizes
[i
] - min_size
;
2920 new_sizes
[i
] -= to_shrink
;
2921 total_removed
+= to_shrink
;
2925 /* Any reminder due to rounding, we just subtract from windows
2926 that are left and still can be shrunk. */
2927 while (total_shrink
> total_removed
)
2929 int nonzero_sizes
= 0;
2930 int nonzero_idx
= -1;
2932 for (i
= 0; i
< nchildren
; ++i
)
2933 if (new_sizes
[i
] > 0)
2939 for (i
= 0; i
< nchildren
; ++i
)
2940 if (new_sizes
[i
] > min_size
)
2945 /* Out of for, just shrink one window at the time and
2946 check again if we have enough space. */
2951 /* Special case, only one window left. */
2952 if (nonzero_sizes
== 1)
2956 /* Any surplus due to rounding, we add to windows that are left. */
2957 while (total_shrink
< total_removed
)
2959 for (i
= 0; i
< nchildren
; ++i
)
2961 if (new_sizes
[i
] != 0 && total_shrink
< total_removed
)
2973 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2974 WINDOW's width. Resize WINDOW's children, if any, so that they
2975 keep their proportionate size relative to WINDOW.
2977 If FIRST_ONLY is 1, change only the first of WINDOW's children when
2978 they are in series. If LAST_ONLY is 1, change only the last of
2979 WINDOW's children when they are in series.
2981 Propagate WINDOW's top or left edge position to children. Delete
2982 windows that become too small unless NODELETE_P is non-zero.
2984 If NODELETE_P is 2, that means we do delete windows that are
2985 too small, even if they were too small before! */
2988 size_window (window
, size
, width_p
, nodelete_p
, first_only
, last_only
)
2990 int size
, width_p
, nodelete_p
;
2991 int first_only
, last_only
;
2993 struct window
*w
= XWINDOW (window
);
2995 Lisp_Object child
, *forward
, *sideward
;
2996 int old_size
, min_size
, safe_min_size
;
2998 check_min_window_sizes ();
2999 size
= max (0, size
);
3001 /* If the window has been "too small" at one point,
3002 don't delete it for being "too small" in the future.
3003 Preserve it as long as that is at all possible. */
3006 old_size
= WINDOW_TOTAL_COLS (w
);
3007 min_size
= window_min_width
;
3008 safe_min_size
= window_min_size_2 (w
, 1);
3012 old_size
= XINT (w
->total_lines
);
3013 min_size
= window_min_height
;
3014 safe_min_size
= window_min_size_2 (w
, 0);
3017 if (old_size
< min_size
&& nodelete_p
!= 2)
3018 w
->too_small_ok
= Qt
;
3020 /* Move the following test here since otherwise the
3021 preceding test doesn't make sense. martin. */
3022 if (nodelete_p
== 2)
3025 /* Maybe delete WINDOW if it's too small. */
3026 if (nodelete_p
!= 1 && !NILP (w
->parent
))
3028 if (!MINI_WINDOW_P (w
) && !NILP (w
->too_small_ok
))
3029 min_size
= width_p
? MIN_SAFE_WINDOW_WIDTH
: MIN_SAFE_WINDOW_HEIGHT
;
3030 if (min_size
< safe_min_size
)
3031 min_size
= safe_min_size
;
3032 if (size
< min_size
)
3034 delete_window (window
);
3039 /* Set redisplay hints. */
3040 w
->last_modified
= make_number (0);
3041 w
->last_overlay_modified
= make_number (0);
3042 windows_or_buffers_changed
++;
3043 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w
->frame
)) = 1;
3047 sideward
= &w
->vchild
;
3048 forward
= &w
->hchild
;
3049 w
->total_cols
= make_number (size
);
3050 adjust_window_margins (w
);
3054 sideward
= &w
->hchild
;
3055 forward
= &w
->vchild
;
3056 w
->total_lines
= make_number (size
);
3057 w
->orig_total_lines
= Qnil
;
3060 if (!NILP (*sideward
))
3062 /* We have a chain of parallel siblings whose size should all change. */
3063 for (child
= *sideward
; !NILP (child
); child
= c
->next
)
3065 c
= XWINDOW (child
);
3067 c
->left_col
= w
->left_col
;
3069 c
->top_line
= w
->top_line
;
3070 size_window (child
, size
, width_p
, nodelete_p
,
3071 first_only
, last_only
);
3074 else if (!NILP (*forward
) && last_only
)
3076 /* Change the last in a series of siblings. */
3077 Lisp_Object last_child
;
3080 for (child
= *forward
; !NILP (child
); child
= c
->next
)
3082 c
= XWINDOW (child
);
3086 child_size
= XINT (width_p
? c
->total_cols
: c
->total_lines
);
3087 size_window (last_child
,
3088 size
- old_size
+ child_size
,
3089 width_p
, nodelete_p
, first_only
, last_only
);
3091 else if (!NILP (*forward
) && first_only
)
3093 /* Change the first in a series of siblings. */
3097 c
= XWINDOW (child
);
3100 c
->left_col
= w
->left_col
;
3102 c
->top_line
= w
->top_line
;
3104 child_size
= XINT (width_p
? c
->total_cols
: c
->total_lines
);
3106 size
- old_size
+ child_size
,
3107 width_p
, nodelete_p
, first_only
, last_only
);
3109 else if (!NILP (*forward
))
3111 int fixed_size
, each
, extra
, n
;
3112 int resize_fixed_p
, nfixed
;
3113 int last_pos
, first_pos
, nchildren
, total
;
3114 int *new_sizes
= NULL
;
3116 /* Determine the fixed-size portion of this window, and the
3117 number of child windows. */
3118 fixed_size
= nchildren
= nfixed
= total
= 0;
3119 for (child
= *forward
; !NILP (child
); child
= c
->next
, ++nchildren
)
3123 c
= XWINDOW (child
);
3124 child_size
= width_p
? XINT (c
->total_cols
) : XINT (c
->total_lines
);
3125 total
+= child_size
;
3127 if (window_fixed_size_p (c
, width_p
, 0))
3129 fixed_size
+= child_size
;
3134 /* If the new size is smaller than fixed_size, or if there
3135 aren't any resizable windows, allow resizing fixed-size
3137 resize_fixed_p
= nfixed
== nchildren
|| size
< fixed_size
;
3139 /* Compute how many lines/columns to add/remove to each child. The
3140 value of extra takes care of rounding errors. */
3141 n
= resize_fixed_p
? nchildren
: nchildren
- nfixed
;
3142 if (size
< total
&& n
> 1)
3143 new_sizes
= shrink_windows (total
, size
, nchildren
, n
, min_size
,
3144 resize_fixed_p
, *forward
, width_p
);
3147 each
= (size
- total
) / n
;
3148 extra
= (size
- total
) - n
* each
;
3151 /* Compute new children heights and edge positions. */
3152 first_pos
= width_p
? XINT (w
->left_col
) : XINT (w
->top_line
);
3153 last_pos
= first_pos
;
3154 for (n
= 0, child
= *forward
; !NILP (child
); child
= c
->next
, ++n
)
3156 int new_size
, old_size
;
3158 c
= XWINDOW (child
);
3159 old_size
= width_p
? XFASTINT (c
->total_cols
) : XFASTINT (c
->total_lines
);
3160 new_size
= old_size
;
3162 /* The top or left edge position of this child equals the
3163 bottom or right edge of its predecessor. */
3165 c
->left_col
= make_number (last_pos
);
3167 c
->top_line
= make_number (last_pos
);
3169 /* If this child can be resized, do it. */
3170 if (resize_fixed_p
|| !window_fixed_size_p (c
, width_p
, 0))
3172 new_size
= new_sizes
? new_sizes
[n
] : old_size
+ each
+ extra
;
3176 /* Set new height. Note that size_window also propagates
3177 edge positions to children, so it's not a no-op if we
3178 didn't change the child's size. */
3179 size_window (child
, new_size
, width_p
, 1, first_only
, last_only
);
3181 /* Remember the bottom/right edge position of this child; it
3182 will be used to set the top/left edge of the next child. */
3183 last_pos
+= new_size
;
3186 if (new_sizes
) xfree (new_sizes
);
3188 /* We should have covered the parent exactly with child windows. */
3189 xassert (size
== last_pos
- first_pos
);
3191 /* Now delete any children that became too small. */
3193 for (child
= *forward
; !NILP (child
); child
= c
->next
)
3196 c
= XWINDOW (child
);
3197 child_size
= width_p
? XINT (c
->total_cols
) : XINT (c
->total_lines
);
3198 size_window (child
, child_size
, width_p
, 2, first_only
, last_only
);
3203 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3204 WINDOW's children. NODELETE non-zero means don't delete windows
3205 that become too small in the process. (The caller should check
3206 later and do so if appropriate.) */
3209 set_window_height (window
, height
, nodelete
)
3214 size_window (window
, height
, 0, nodelete
, 0, 0);
3218 /* Set WINDOW's width to WIDTH, and recursively change the width of
3219 WINDOW's children. NODELETE non-zero means don't delete windows
3220 that become too small in the process. (The caller should check
3221 later and do so if appropriate.) */
3224 set_window_width (window
, width
, nodelete
)
3229 size_window (window
, width
, 1, nodelete
, 0, 0);
3232 /* Change window heights in windows rooted in WINDOW by N lines. */
3235 change_window_heights (window
, n
)
3239 struct window
*w
= XWINDOW (window
);
3241 XSETFASTINT (w
->top_line
, XFASTINT (w
->top_line
) + n
);
3242 XSETFASTINT (w
->total_lines
, XFASTINT (w
->total_lines
) - n
);
3244 if (INTEGERP (w
->orig_top_line
))
3245 XSETFASTINT (w
->orig_top_line
, XFASTINT (w
->orig_top_line
) + n
);
3246 if (INTEGERP (w
->orig_total_lines
))
3247 XSETFASTINT (w
->orig_total_lines
, XFASTINT (w
->orig_total_lines
) - n
);
3249 /* Handle just the top child in a vertical split. */
3250 if (!NILP (w
->vchild
))
3251 change_window_heights (w
->vchild
, n
);
3253 /* Adjust all children in a horizontal split. */
3254 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
3256 w
= XWINDOW (window
);
3257 change_window_heights (window
, n
);
3262 int window_select_count
;
3265 Fset_window_buffer_unwind (obuf
)
3272 EXFUN (Fset_window_fringes
, 4);
3273 EXFUN (Fset_window_scroll_bars
, 4);
3275 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3276 means it's allowed to run hooks. See make_frame for a case where
3277 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3278 margins, fringes, and scroll-bar settings of the window are not
3279 reset from the buffer's local settings. */
3282 set_window_buffer (window
, buffer
, run_hooks_p
, keep_margins_p
)
3283 Lisp_Object window
, buffer
;
3284 int run_hooks_p
, keep_margins_p
;
3286 struct window
*w
= XWINDOW (window
);
3287 struct buffer
*b
= XBUFFER (buffer
);
3288 int count
= SPECPDL_INDEX ();
3292 if (EQ (window
, selected_window
))
3293 b
->last_selected_window
= window
;
3295 /* Let redisplay errors through. */
3296 b
->display_error_modiff
= 0;
3298 /* Update time stamps of buffer display. */
3299 if (INTEGERP (b
->display_count
))
3300 XSETINT (b
->display_count
, XINT (b
->display_count
) + 1);
3301 b
->display_time
= Fcurrent_time ();
3303 XSETFASTINT (w
->window_end_pos
, 0);
3304 XSETFASTINT (w
->window_end_vpos
, 0);
3305 bzero (&w
->last_cursor
, sizeof w
->last_cursor
);
3306 w
->window_end_valid
= Qnil
;
3307 w
->hscroll
= w
->min_hscroll
= make_number (0);
3309 set_marker_both (w
->pointm
, buffer
, BUF_PT (b
), BUF_PT_BYTE (b
));
3310 set_marker_restricted (w
->start
,
3311 make_number (b
->last_window_start
),
3313 w
->start_at_line_beg
= Qnil
;
3314 w
->force_start
= Qnil
;
3315 XSETFASTINT (w
->last_modified
, 0);
3316 XSETFASTINT (w
->last_overlay_modified
, 0);
3317 windows_or_buffers_changed
++;
3319 /* We must select BUFFER for running the window-scroll-functions.
3320 If WINDOW is selected, switch permanently.
3321 Otherwise, switch but go back to the ambient buffer afterward. */
3322 if (EQ (window
, selected_window
))
3323 Fset_buffer (buffer
);
3324 /* We can't check ! NILP (Vwindow_scroll_functions) here
3325 because that might itself be a local variable. */
3326 else if (window_initialized
)
3328 record_unwind_protect (Fset_window_buffer_unwind
, Fcurrent_buffer ());
3329 Fset_buffer (buffer
);
3332 if (!keep_margins_p
)
3334 /* Set left and right marginal area width etc. from buffer. */
3336 /* This may call adjust_window_margins three times, so
3337 temporarily disable window margins. */
3338 Lisp_Object save_left
= w
->left_margin_cols
;
3339 Lisp_Object save_right
= w
->right_margin_cols
;
3341 w
->left_margin_cols
= w
->right_margin_cols
= Qnil
;
3343 Fset_window_fringes (window
,
3344 b
->left_fringe_width
, b
->right_fringe_width
,
3345 b
->fringes_outside_margins
);
3347 Fset_window_scroll_bars (window
,
3348 b
->scroll_bar_width
,
3349 b
->vertical_scroll_bar_type
, Qnil
);
3351 w
->left_margin_cols
= save_left
;
3352 w
->right_margin_cols
= save_right
;
3354 Fset_window_margins (window
,
3355 b
->left_margin_cols
, b
->right_margin_cols
);
3360 if (! NILP (Vwindow_scroll_functions
))
3361 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
3362 Fmarker_position (w
->start
));
3364 if (! NILP (Vwindow_configuration_change_hook
)
3365 && ! NILP (Vrun_hooks
))
3366 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
3369 unbind_to (count
, Qnil
);
3373 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 3, 0,
3374 doc
: /* Make WINDOW display BUFFER as its contents.
3375 BUFFER can be a buffer or the name of an existing buffer.
3376 Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
3377 display margins, fringe widths, and scroll bar settings are maintained;
3378 the default is to reset these from BUFFER's local settings or the frame
3381 This function runs the hook `window-scroll-functions'. */)
3382 (window
, buffer
, keep_margins
)
3383 register Lisp_Object window
, buffer
, keep_margins
;
3385 register Lisp_Object tem
;
3386 register struct window
*w
= decode_window (window
);
3388 XSETWINDOW (window
, w
);
3389 buffer
= Fget_buffer (buffer
);
3390 CHECK_BUFFER (buffer
);
3392 if (NILP (XBUFFER (buffer
)->name
))
3393 error ("Attempt to display deleted buffer");
3397 error ("Window is deleted");
3398 else if (! EQ (tem
, Qt
)) /* w->buffer is t when the window
3399 is first being set up. */
3401 if (!NILP (w
->dedicated
) && !EQ (tem
, buffer
))
3402 error ("Window is dedicated to `%s'",
3403 SDATA (XBUFFER (tem
)->name
));
3408 set_window_buffer (window
, buffer
, 1, !NILP (keep_margins
));
3412 /* Note that selected_window can be nil
3413 when this is called from Fset_window_configuration. */
3415 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 2, 0,
3416 doc
: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3417 If WINDOW is not already selected, make WINDOW's buffer current
3418 and make WINDOW the frame's selected window. Return WINDOW.
3419 Optional second arg NORECORD non-nil means
3420 do not put this buffer at the front of the list of recently selected ones.
3422 Note that the main editor command loop
3423 selects the buffer of the selected window before each command. */)
3425 register Lisp_Object window
, norecord
;
3427 register struct window
*w
;
3428 register struct window
*ow
;
3431 CHECK_LIVE_WINDOW (window
);
3433 w
= XWINDOW (window
);
3434 w
->frozen_window_start_p
= 0;
3436 ++window_select_count
;
3437 XSETFASTINT (w
->use_time
, window_select_count
);
3438 if (EQ (window
, selected_window
))
3441 /* Store the current buffer's actual point into the
3442 old selected window. It belongs to that window,
3443 and when the window is not selected, must be in the window. */
3444 if (!NILP (selected_window
))
3446 ow
= XWINDOW (selected_window
);
3447 if (! NILP (ow
->buffer
))
3448 set_marker_both (ow
->pointm
, ow
->buffer
,
3449 BUF_PT (XBUFFER (ow
->buffer
)),
3450 BUF_PT_BYTE (XBUFFER (ow
->buffer
)));
3453 selected_window
= window
;
3454 sf
= SELECTED_FRAME ();
3455 if (XFRAME (WINDOW_FRAME (w
)) != sf
)
3457 XFRAME (WINDOW_FRAME (w
))->selected_window
= window
;
3458 /* Use this rather than Fhandle_switch_frame
3459 so that FRAME_FOCUS_FRAME is moved appropriately as we
3460 move around in the state where a minibuffer in a separate
3462 Fselect_frame (WINDOW_FRAME (w
));
3465 sf
->selected_window
= window
;
3467 if (NILP (norecord
))
3468 record_buffer (w
->buffer
);
3469 Fset_buffer (w
->buffer
);
3471 XBUFFER (w
->buffer
)->last_selected_window
= window
;
3473 /* Go to the point recorded in the window.
3474 This is important when the buffer is in more
3475 than one window. It also matters when
3476 redisplay_window has altered point after scrolling,
3477 because it makes the change only in the window. */
3479 register int new_point
= marker_position (w
->pointm
);
3480 if (new_point
< BEGV
)
3482 else if (new_point
> ZV
)
3488 windows_or_buffers_changed
++;
3493 select_window_norecord (window
)
3496 return Fselect_window (window
, Qt
);
3499 /* Deiconify the frame containing the window WINDOW,
3500 unless it is the selected frame;
3503 The reason for the exception for the selected frame
3504 is that it seems better not to change the selected frames visibility
3505 merely because of displaying a different buffer in it.
3506 The deiconification is useful when a buffer gets shown in
3507 another frame that you were not using lately. */
3510 display_buffer_1 (window
)
3513 Lisp_Object frame
= XWINDOW (window
)->frame
;
3514 FRAME_PTR f
= XFRAME (frame
);
3516 FRAME_SAMPLE_VISIBILITY (f
);
3518 if (EQ (frame
, selected_frame
))
3519 ; /* Assume the selected frame is already visible enough. */
3520 else if (minibuf_level
> 0
3521 && MINI_WINDOW_P (XWINDOW (selected_window
))
3522 && WINDOW_LIVE_P (minibuf_selected_window
)
3523 && EQ (frame
, WINDOW_FRAME (XWINDOW (minibuf_selected_window
))))
3524 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3527 if (FRAME_ICONIFIED_P (f
))
3528 Fmake_frame_visible (frame
);
3529 else if (FRAME_VISIBLE_P (f
))
3530 Fraise_frame (frame
);
3536 DEFUN ("special-display-p", Fspecial_display_p
, Sspecial_display_p
, 1, 1, 0,
3537 doc
: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
3538 If the value is t, `display-buffer' or `pop-to-buffer' would create a
3539 special frame for that buffer using the default frame parameters.
3541 If the value is a list, it is a list of frame parameters that would be used
3542 to make a frame for that buffer.
3543 The variables `special-display-buffer-names'
3544 and `special-display-regexps' control this. */)
3546 Lisp_Object buffer_name
;
3550 CHECK_STRING (buffer_name
);
3552 tem
= Fmember (buffer_name
, Vspecial_display_buffer_names
);
3556 tem
= Fassoc (buffer_name
, Vspecial_display_buffer_names
);
3560 for (tem
= Vspecial_display_regexps
; CONSP (tem
); tem
= XCDR (tem
))
3562 Lisp_Object car
= XCAR (tem
);
3564 && fast_string_match (car
, buffer_name
) >= 0)
3566 else if (CONSP (car
)
3567 && STRINGP (XCAR (car
))
3568 && fast_string_match (XCAR (car
), buffer_name
) >= 0)
3574 DEFUN ("same-window-p", Fsame_window_p
, Ssame_window_p
, 1, 1, 0,
3575 doc
: /* Returns non-nil if a buffer named BUFFER-NAME would use the same window.
3576 More precisely, if `display-buffer' or `pop-to-buffer' would display
3577 that buffer in the selected window rather than (as usual) in some other window.
3578 See `same-window-buffer-names' and `same-window-regexps'. */)
3580 Lisp_Object buffer_name
;
3584 CHECK_STRING (buffer_name
);
3586 tem
= Fmember (buffer_name
, Vsame_window_buffer_names
);
3590 tem
= Fassoc (buffer_name
, Vsame_window_buffer_names
);
3594 for (tem
= Vsame_window_regexps
; CONSP (tem
); tem
= XCDR (tem
))
3596 Lisp_Object car
= XCAR (tem
);
3598 && fast_string_match (car
, buffer_name
) >= 0)
3600 else if (CONSP (car
)
3601 && STRINGP (XCAR (car
))
3602 && fast_string_match (XCAR (car
), buffer_name
) >= 0)
3608 /* Use B so the default is (other-buffer). */
3609 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 3,
3610 "BDisplay buffer: \nP",
3611 doc
: /* Make BUFFER appear in some window but don't select it.
3612 BUFFER must be the name of an existing buffer, or, when called from Lisp,
3614 If BUFFER is shown already in some window, just use that one,
3615 unless the window is the selected window and the optional second
3616 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3617 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3618 Returns the window displaying BUFFER.
3619 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3620 displaying BUFFER, then simply raise that frame.
3622 The variables `special-display-buffer-names',
3623 `special-display-regexps', `same-window-buffer-names', and
3624 `same-window-regexps' customize how certain buffer names are handled.
3625 The latter two take effect only if NOT-THIS-WINDOW is nil.
3627 If optional argument FRAME is `visible', check all visible frames
3628 for a window to use.
3629 If FRAME is 0, check all visible and iconified frames.
3630 If FRAME is t, check all frames.
3631 If FRAME is a frame, check only that frame.
3632 If FRAME is nil, check only the selected frame
3633 (actually the last nonminibuffer frame),
3634 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3635 which means search visible and iconified frames.
3637 If a full-width window on a splittable frame is available to display
3638 the buffer, it may be split, subject to the value of the variable
3639 `split-height-threshold'.
3641 If `even-window-heights' is non-nil, window heights will be evened out
3642 if displaying the buffer causes two vertically adjacent windows to be
3644 (buffer
, not_this_window
, frame
)
3645 register Lisp_Object buffer
, not_this_window
, frame
;
3647 register Lisp_Object window
, tem
, swp
;
3651 buffer
= Fget_buffer (buffer
);
3652 CHECK_BUFFER (buffer
);
3654 if (!NILP (Vdisplay_buffer_function
))
3655 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
3657 if (NILP (not_this_window
)
3658 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
3659 return display_buffer_1 (selected_window
);
3661 /* See if the user has specified this buffer should appear
3662 in the selected window. */
3663 if (NILP (not_this_window
))
3665 swp
= Fsame_window_p (XBUFFER (buffer
)->name
);
3666 if (!NILP (swp
) && !no_switch_window (selected_window
))
3668 Fswitch_to_buffer (buffer
, Qnil
);
3669 return display_buffer_1 (selected_window
);
3673 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3674 look for a window showing BUFFER on any visible or iconified frame.
3675 Otherwise search only the current frame. */
3678 else if (pop_up_frames
3679 || display_buffer_reuse_frames
3680 || last_nonminibuf_frame
== 0)
3681 XSETFASTINT (tem
, 0);
3683 XSETFRAME (tem
, last_nonminibuf_frame
);
3685 window
= Fget_buffer_window (buffer
, tem
);
3687 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
3688 return display_buffer_1 (window
);
3690 /* Certain buffer names get special handling. */
3691 if (!NILP (Vspecial_display_function
) && NILP (swp
))
3693 tem
= Fspecial_display_p (XBUFFER (buffer
)->name
);
3695 return call1 (Vspecial_display_function
, buffer
);
3697 return call2 (Vspecial_display_function
, buffer
, tem
);
3700 /* If there are no frames open that have more than a minibuffer,
3701 we need to create a new frame. */
3702 if (pop_up_frames
|| last_nonminibuf_frame
== 0)
3704 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
3705 Fset_window_buffer (window
, buffer
, Qnil
);
3706 return display_buffer_1 (window
);
3709 f
= SELECTED_FRAME ();
3711 || FRAME_MINIBUF_ONLY_P (f
)
3712 /* If the current frame is a special display frame,
3713 don't try to reuse its windows. */
3714 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f
))->dedicated
))
3719 if (FRAME_MINIBUF_ONLY_P (f
))
3720 XSETFRAME (frames
, last_nonminibuf_frame
);
3722 /* Note that both Fget_largest_window and Fget_lru_window
3723 ignore minibuffers and dedicated windows.
3724 This means they can return nil. */
3726 /* If the frame we would try to split cannot be split,
3727 try other frames. */
3728 if (FRAME_NO_SPLIT_P (NILP (frames
) ? f
: last_nonminibuf_frame
))
3730 /* Try visible frames first. */
3731 window
= Fget_largest_window (Qvisible
, Qt
);
3732 /* If that didn't work, try iconified frames. */
3734 window
= Fget_largest_window (make_number (0), Qt
);
3735 #if 0 /* Don't try windows on other displays. */
3737 window
= Fget_largest_window (Qt
, Qt
);
3741 window
= Fget_largest_window (frames
, Qt
);
3743 /* If the largest window is tall enough, full-width, and either eligible
3744 for splitting or the only window, split it. */
3746 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
3747 && WINDOW_FULL_WIDTH_P (XWINDOW (window
))
3748 && (window_height (window
) >= split_height_threshold
3749 || (NILP (XWINDOW (window
)->parent
)))
3750 && (window_height (window
)
3751 >= (2 * window_min_size_2 (XWINDOW (window
), 0))))
3752 window
= Fsplit_window (window
, Qnil
, Qnil
);
3755 Lisp_Object upper
, lower
, other
;
3757 window
= Fget_lru_window (frames
, Qt
);
3758 /* If the LRU window is tall enough, and either eligible for splitting
3759 and selected or the only window, split it. */
3761 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
3762 && ((EQ (window
, selected_window
)
3763 && window_height (window
) >= split_height_threshold
)
3764 || (NILP (XWINDOW (window
)->parent
)))
3765 && (window_height (window
)
3766 >= (2 * window_min_size_2 (XWINDOW (window
), 0))))
3767 window
= Fsplit_window (window
, Qnil
, Qnil
);
3769 window
= Fget_lru_window (frames
, Qnil
);
3770 /* If Fget_lru_window returned nil, try other approaches. */
3772 /* Try visible frames first. */
3774 window
= Fget_buffer_window (buffer
, Qvisible
);
3776 window
= Fget_largest_window (Qvisible
, Qnil
);
3777 /* If that didn't work, try iconified frames. */
3779 window
= Fget_buffer_window (buffer
, make_number (0));
3781 window
= Fget_largest_window (make_number (0), Qnil
);
3783 #if 0 /* Don't try frames on other displays. */
3785 window
= Fget_buffer_window (buffer
, Qt
);
3787 window
= Fget_largest_window (Qt
, Qnil
);
3789 /* As a last resort, make a new frame. */
3791 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
3792 /* If window appears above or below another,
3793 even out their heights. */
3794 other
= upper
= lower
= Qnil
;
3795 if (!NILP (XWINDOW (window
)->prev
))
3796 other
= upper
= XWINDOW (window
)->prev
, lower
= window
;
3797 if (!NILP (XWINDOW (window
)->next
))
3798 other
= lower
= XWINDOW (window
)->next
, upper
= window
;
3800 && !NILP (Veven_window_heights
)
3801 /* Check that OTHER and WINDOW are vertically arrayed. */
3802 && !EQ (XWINDOW (other
)->top_line
, XWINDOW (window
)->top_line
)
3803 && (XFASTINT (XWINDOW (other
)->total_lines
)
3804 > XFASTINT (XWINDOW (window
)->total_lines
)))
3806 int total
= (XFASTINT (XWINDOW (other
)->total_lines
)
3807 + XFASTINT (XWINDOW (window
)->total_lines
));
3808 enlarge_window (upper
,
3809 total
/ 2 - XFASTINT (XWINDOW (upper
)->total_lines
),
3815 window
= Fget_lru_window (Qnil
, Qnil
);
3817 Fset_window_buffer (window
, buffer
, Qnil
);
3818 return display_buffer_1 (window
);
3822 DEFUN ("force-window-update", Fforce_window_update
, Sforce_window_update
,
3824 doc
: /* Force all windows to be updated on next redisplay.
3825 If optional arg OBJECT is a window, force redisplay of that window only.
3826 If OBJECT is a buffer or buffer name, force redisplay of all windows
3827 displaying that buffer. */)
3833 windows_or_buffers_changed
++;
3834 update_mode_lines
++;
3838 if (WINDOWP (object
))
3840 struct window
*w
= XWINDOW (object
);
3841 mark_window_display_accurate (object
, 0);
3842 w
->update_mode_line
= Qt
;
3843 if (BUFFERP (w
->buffer
))
3844 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
3845 ++update_mode_lines
;
3849 if (STRINGP (object
))
3850 object
= Fget_buffer (object
);
3851 if (BUFFERP (object
) && !NILP (XBUFFER (object
)->name
))
3853 /* Walk all windows looking for buffer, and force update
3854 of each of those windows. */
3856 object
= window_loop (REDISPLAY_BUFFER_WINDOWS
, object
, 0, Qvisible
);
3857 return NILP (object
) ? Qnil
: Qt
;
3860 /* If nothing suitable was found, just return.
3861 We could signal an error, but this feature will typically be used
3862 asynchronously in timers or process sentinels, so we don't. */
3868 temp_output_buffer_show (buf
)
3869 register Lisp_Object buf
;
3871 register struct buffer
*old
= current_buffer
;
3872 register Lisp_Object window
;
3873 register struct window
*w
;
3875 XBUFFER (buf
)->directory
= current_buffer
->directory
;
3878 BUF_SAVE_MODIFF (XBUFFER (buf
)) = MODIFF
;
3882 #if 0 /* rms: there should be no reason for this. */
3883 XBUFFER (buf
)->prevent_redisplay_optimizations_p
= 1;
3885 set_buffer_internal (old
);
3887 if (!NILP (Vtemp_buffer_show_function
))
3888 call1 (Vtemp_buffer_show_function
, buf
);
3891 window
= Fdisplay_buffer (buf
, Qnil
, Qnil
);
3893 if (!EQ (XWINDOW (window
)->frame
, selected_frame
))
3894 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
3895 Vminibuf_scroll_window
= window
;
3896 w
= XWINDOW (window
);
3897 XSETFASTINT (w
->hscroll
, 0);
3898 XSETFASTINT (w
->min_hscroll
, 0);
3899 set_marker_restricted_both (w
->start
, buf
, BEG
, BEG
);
3900 set_marker_restricted_both (w
->pointm
, buf
, BEG
, BEG
);
3902 /* Run temp-buffer-show-hook, with the chosen window selected
3903 and its buffer current. */
3905 if (!NILP (Vrun_hooks
)
3906 && !NILP (Fboundp (Qtemp_buffer_show_hook
))
3907 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook
)))
3909 int count
= SPECPDL_INDEX ();
3910 Lisp_Object prev_window
, prev_buffer
;
3911 prev_window
= selected_window
;
3912 XSETBUFFER (prev_buffer
, old
);
3914 /* Select the window that was chosen, for running the hook.
3915 Note: Both Fselect_window and select_window_norecord may
3916 set-buffer to the buffer displayed in the window,
3917 so we need to save the current buffer. --stef */
3918 record_unwind_protect (Fset_buffer
, prev_buffer
);
3919 record_unwind_protect (select_window_norecord
, prev_window
);
3920 Fselect_window (window
, Qt
);
3921 Fset_buffer (w
->buffer
);
3922 call1 (Vrun_hooks
, Qtemp_buffer_show_hook
);
3923 unbind_to (count
, Qnil
);
3929 make_dummy_parent (window
)
3933 register struct window
*o
, *p
;
3936 o
= XWINDOW (window
);
3937 p
= allocate_window ();
3938 for (i
= 0; i
< VECSIZE (struct window
); ++i
)
3939 ((struct Lisp_Vector
*) p
)->contents
[i
]
3940 = ((struct Lisp_Vector
*)o
)->contents
[i
];
3941 XSETWINDOW (new, p
);
3944 XSETFASTINT (p
->sequence_number
, sequence_number
);
3946 /* Put new into window structure in place of window */
3947 replace_window (window
, new);
3960 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
3961 doc
: /* Split WINDOW, putting SIZE lines in the first of the pair.
3962 WINDOW defaults to selected one and SIZE to half its size.
3963 If optional third arg HORFLAG is non-nil, split side by side
3964 and put SIZE columns in the first of the pair. In that case,
3965 SIZE includes that window's scroll bar, or the divider column to its right.
3966 Interactively, all arguments are nil.
3968 Returns the newly created window (which is the lower or rightmost one).
3969 The upper or leftmost window is the original one, and remains selected
3970 if it was selected before.
3972 See Info node `(elisp)Splitting Windows' for more details and examples.*/)
3973 (window
, size
, horflag
)
3974 Lisp_Object window
, size
, horflag
;
3976 register Lisp_Object
new;
3977 register struct window
*o
, *p
;
3979 register int size_int
;
3982 window
= selected_window
;
3984 CHECK_LIVE_WINDOW (window
);
3986 o
= XWINDOW (window
);
3987 fo
= XFRAME (WINDOW_FRAME (o
));
3991 if (!NILP (horflag
))
3992 /* Calculate the size of the left-hand window, by dividing
3993 the usable space in columns by two.
3994 We round up, since the left-hand window may include
3995 a dividing line, while the right-hand may not. */
3996 size_int
= (XFASTINT (o
->total_cols
) + 1) >> 1;
3998 size_int
= XFASTINT (o
->total_lines
) >> 1;
4002 CHECK_NUMBER (size
);
4003 size_int
= XINT (size
);
4006 if (MINI_WINDOW_P (o
))
4007 error ("Attempt to split minibuffer window");
4008 else if (window_fixed_size_p (o
, !NILP (horflag
), 0))
4009 error ("Attempt to split fixed-size window");
4011 check_min_window_sizes ();
4015 int window_safe_height
= window_min_size_2 (o
, 0);
4017 if (size_int
< window_safe_height
)
4018 error ("Window height %d too small (after splitting)", size_int
);
4019 if (size_int
+ window_safe_height
> XFASTINT (o
->total_lines
))
4020 error ("Window height %d too small (after splitting)",
4021 XFASTINT (o
->total_lines
) - size_int
);
4022 if (NILP (o
->parent
)
4023 || NILP (XWINDOW (o
->parent
)->vchild
))
4025 make_dummy_parent (window
);
4027 XWINDOW (new)->vchild
= window
;
4032 int window_safe_width
= window_min_size_2 (o
, 1);
4034 if (size_int
< window_safe_width
)
4035 error ("Window width %d too small (after splitting)", size_int
);
4036 if (size_int
+ window_safe_width
> XFASTINT (o
->total_cols
))
4037 error ("Window width %d too small (after splitting)",
4038 XFASTINT (o
->total_cols
) - size_int
);
4039 if (NILP (o
->parent
)
4040 || NILP (XWINDOW (o
->parent
)->hchild
))
4042 make_dummy_parent (window
);
4044 XWINDOW (new)->hchild
= window
;
4048 /* Now we know that window's parent is a vertical combination
4049 if we are dividing vertically, or a horizontal combination
4050 if we are making side-by-side windows */
4052 windows_or_buffers_changed
++;
4053 FRAME_WINDOW_SIZES_CHANGED (fo
) = 1;
4054 new = make_window ();
4057 p
->frame
= o
->frame
;
4059 if (!NILP (p
->next
))
4060 XWINDOW (p
->next
)->prev
= new;
4063 p
->parent
= o
->parent
;
4065 p
->window_end_valid
= Qnil
;
4066 bzero (&p
->last_cursor
, sizeof p
->last_cursor
);
4068 /* Duplicate special geometry settings. */
4070 p
->left_margin_cols
= o
->left_margin_cols
;
4071 p
->right_margin_cols
= o
->right_margin_cols
;
4072 p
->left_fringe_width
= o
->left_fringe_width
;
4073 p
->right_fringe_width
= o
->right_fringe_width
;
4074 p
->fringes_outside_margins
= o
->fringes_outside_margins
;
4075 p
->scroll_bar_width
= o
->scroll_bar_width
;
4076 p
->vertical_scroll_bar_type
= o
->vertical_scroll_bar_type
;
4078 /* Apportion the available frame space among the two new windows */
4080 if (!NILP (horflag
))
4082 p
->total_lines
= o
->total_lines
;
4083 p
->top_line
= o
->top_line
;
4084 XSETFASTINT (p
->total_cols
, XFASTINT (o
->total_cols
) - size_int
);
4085 XSETFASTINT (o
->total_cols
, size_int
);
4086 XSETFASTINT (p
->left_col
, XFASTINT (o
->left_col
) + size_int
);
4087 adjust_window_margins (p
);
4088 adjust_window_margins (o
);
4092 p
->left_col
= o
->left_col
;
4093 p
->total_cols
= o
->total_cols
;
4094 XSETFASTINT (p
->total_lines
, XFASTINT (o
->total_lines
) - size_int
);
4095 XSETFASTINT (o
->total_lines
, size_int
);
4096 XSETFASTINT (p
->top_line
, XFASTINT (o
->top_line
) + size_int
);
4099 /* Adjust glyph matrices. */
4102 Fset_window_buffer (new, o
->buffer
, Qt
);
4106 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
4107 doc
: /* Make current window ARG lines bigger.
4108 From program, optional second arg non-nil means grow sideways ARG columns.
4109 Interactively, if an argument is not given, make the window one line bigger.
4110 If HORIZONTAL is non-nil, enlarge horizontally instead of vertically.
4111 This function can delete windows, even the second window, if they get
4114 Lisp_Object arg
, horizontal
;
4117 enlarge_window (selected_window
, XINT (arg
), !NILP (horizontal
));
4119 if (! NILP (Vwindow_configuration_change_hook
))
4120 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
4125 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
4126 doc
: /* Make current window ARG lines smaller.
4127 From program, optional second arg non-nil means shrink sideways arg columns.
4128 Interactively, if an argument is not given, make the window one line smaller.
4129 Only siblings to the right or below are changed. */)
4131 Lisp_Object arg
, side
;
4134 enlarge_window (selected_window
, -XINT (arg
), !NILP (side
));
4136 if (! NILP (Vwindow_configuration_change_hook
))
4137 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
4143 window_height (window
)
4146 register struct window
*p
= XWINDOW (window
);
4147 return WINDOW_TOTAL_LINES (p
);
4151 window_width (window
)
4154 register struct window
*p
= XWINDOW (window
);
4155 return WINDOW_TOTAL_COLS (p
);
4160 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
4162 #define CURSIZE(w) \
4163 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
4166 /* Enlarge WINDOW by DELTA.
4167 HORIZ_FLAG nonzero means enlarge it horizontally;
4168 zero means do it vertically.
4170 Siblings of the selected window are resized to fulfill the size
4171 request. If they become too small in the process, they will be
4175 enlarge_window (window
, delta
, horiz_flag
)
4177 int delta
, horiz_flag
;
4179 Lisp_Object parent
, next
, prev
;
4183 int (*sizefun
) P_ ((Lisp_Object
))
4184 = horiz_flag
? window_width
: window_height
;
4185 void (*setsizefun
) P_ ((Lisp_Object
, int, int))
4186 = (horiz_flag
? set_window_width
: set_window_height
);
4188 /* Check values of window_min_width and window_min_height for
4190 check_min_window_sizes ();
4192 /* Give up if this window cannot be resized. */
4193 if (window_fixed_size_p (XWINDOW (window
), horiz_flag
, 1))
4194 error ("Window is not resizable");
4196 /* Find the parent of the selected window. */
4199 p
= XWINDOW (window
);
4205 error ("No other window to side of this one");
4210 ? !NILP (XWINDOW (parent
)->hchild
)
4211 : !NILP (XWINDOW (parent
)->vchild
))
4217 sizep
= &CURSIZE (window
);
4220 register int maxdelta
;
4222 /* Compute the maximum size increment this window can have. */
4224 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - XINT (*sizep
)
4225 /* This is a main window followed by a minibuffer. */
4226 : !NILP (p
->next
) ? ((*sizefun
) (p
->next
)
4227 - window_min_size (XWINDOW (p
->next
),
4229 /* This is a minibuffer following a main window. */
4230 : !NILP (p
->prev
) ? ((*sizefun
) (p
->prev
)
4231 - window_min_size (XWINDOW (p
->prev
),
4233 /* This is a frame with only one window, a minibuffer-only
4234 or a minibufferless frame. */
4237 if (delta
> maxdelta
)
4238 /* This case traps trying to make the minibuffer
4239 the full frame, or make the only window aside from the
4240 minibuffer the full frame. */
4244 if (XINT (*sizep
) + delta
< window_min_size (XWINDOW (window
), horiz_flag
, 0, 0))
4246 delete_window (window
);
4253 /* Find the total we can get from other siblings without deleting them. */
4255 for (next
= p
->next
; ! NILP (next
); next
= XWINDOW (next
)->next
)
4256 maximum
+= (*sizefun
) (next
) - window_min_size (XWINDOW (next
),
4258 for (prev
= p
->prev
; ! NILP (prev
); prev
= XWINDOW (prev
)->prev
)
4259 maximum
+= (*sizefun
) (prev
) - window_min_size (XWINDOW (prev
),
4262 /* If we can get it all from them without deleting them, do so. */
4263 if (delta
<= maximum
)
4265 Lisp_Object first_unaffected
;
4266 Lisp_Object first_affected
;
4271 first_affected
= window
;
4272 /* Look at one sibling at a time,
4273 moving away from this window in both directions alternately,
4274 and take as much as we can get without deleting that sibling. */
4276 && (!NILP (next
) || !NILP (prev
)))
4280 int this_one
= ((*sizefun
) (next
)
4281 - window_min_size (XWINDOW (next
),
4282 horiz_flag
, 0, &fixed_p
));
4285 if (this_one
> delta
)
4288 (*setsizefun
) (next
, (*sizefun
) (next
) - this_one
, 0);
4289 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
4294 next
= XWINDOW (next
)->next
;
4302 int this_one
= ((*sizefun
) (prev
)
4303 - window_min_size (XWINDOW (prev
),
4304 horiz_flag
, 0, &fixed_p
));
4307 if (this_one
> delta
)
4310 first_affected
= prev
;
4312 (*setsizefun
) (prev
, (*sizefun
) (prev
) - this_one
, 0);
4313 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
4318 prev
= XWINDOW (prev
)->prev
;
4322 xassert (delta
== 0);
4324 /* Now recalculate the edge positions of all the windows affected,
4325 based on the new sizes. */
4326 first_unaffected
= next
;
4327 prev
= first_affected
;
4328 for (next
= XWINDOW (prev
)->next
; ! EQ (next
, first_unaffected
);
4329 prev
= next
, next
= XWINDOW (next
)->next
)
4331 XSETINT (CURBEG (next
), XINT (CURBEG (prev
)) + (*sizefun
) (prev
));
4332 /* This does not change size of NEXT,
4333 but it propagates the new top edge to its children */
4334 (*setsizefun
) (next
, (*sizefun
) (next
), 0);
4339 register int delta1
;
4340 register int opht
= (*sizefun
) (parent
);
4342 if (opht
<= XINT (*sizep
) + delta
)
4344 /* If trying to grow this window to or beyond size of the parent,
4345 just delete all the sibling windows. */
4346 Lisp_Object start
, tem
, next
;
4348 start
= XWINDOW (parent
)->vchild
;
4350 start
= XWINDOW (parent
)->hchild
;
4352 /* Delete any siblings that come after WINDOW. */
4353 tem
= XWINDOW (window
)->next
;
4354 while (! NILP (tem
))
4356 next
= XWINDOW (tem
)->next
;
4357 delete_window (tem
);
4361 /* Delete any siblings that come after WINDOW.
4362 Note that if START is not WINDOW, then WINDOW still
4363 Fhas siblings, so WINDOW has not yet replaced its parent. */
4365 while (! EQ (tem
, window
))
4367 next
= XWINDOW (tem
)->next
;
4368 delete_window (tem
);
4374 /* Otherwise, make delta1 just right so that if we add
4375 delta1 lines to this window and to the parent, and then
4376 shrink the parent back to its original size, the new
4377 proportional size of this window will increase by delta.
4379 The function size_window will compute the new height h'
4380 of the window from delta1 as:
4383 x = delta1 - delta1/n * n for the 1st resizable child
4386 where n is the number of children that can be resized.
4387 We can ignore x by choosing a delta1 that is a multiple of
4388 n. We want the height of this window to come out as
4398 The number of children n equals the number of resizable
4399 children of this window + 1 because we know window itself
4400 is resizable (otherwise we would have signalled an error). */
4402 struct window
*w
= XWINDOW (window
);
4406 for (s
= w
->next
; !NILP (s
); s
= XWINDOW (s
)->next
)
4407 if (!window_fixed_size_p (XWINDOW (s
), horiz_flag
, 0))
4409 for (s
= w
->prev
; !NILP (s
); s
= XWINDOW (s
)->prev
)
4410 if (!window_fixed_size_p (XWINDOW (s
), horiz_flag
, 0))
4415 /* Add delta1 lines or columns to this window, and to the parent,
4416 keeping things consistent while not affecting siblings. */
4417 XSETINT (CURSIZE (parent
), opht
+ delta1
);
4418 (*setsizefun
) (window
, XINT (*sizep
) + delta1
, 0);
4420 /* Squeeze out delta1 lines or columns from our parent,
4421 shriking this window and siblings proportionately.
4422 This brings parent back to correct size.
4423 Delta1 was calculated so this makes this window the desired size,
4424 taking it all out of the siblings. */
4425 (*setsizefun
) (parent
, opht
, 0);
4430 XSETFASTINT (p
->last_modified
, 0);
4431 XSETFASTINT (p
->last_overlay_modified
, 0);
4433 /* Adjust glyph matrices. */
4434 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4438 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4439 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4440 zero means adjust the height, moving the bottom edge.
4442 Following siblings of the selected window are resized to fulfill
4443 the size request. If they become too small in the process, they
4444 are not deleted; instead, we signal an error. */
4447 adjust_window_trailing_edge (window
, delta
, horiz_flag
)
4449 int delta
, horiz_flag
;
4451 Lisp_Object parent
, child
;
4453 Lisp_Object old_config
= Fcurrent_window_configuration (Qnil
);
4454 int delcount
= window_deletion_count
;
4456 /* Check values of window_min_width and window_min_height for
4458 check_min_window_sizes ();
4461 window
= Fselected_window ();
4463 CHECK_WINDOW (window
);
4465 /* Give up if this window cannot be resized. */
4466 if (window_fixed_size_p (XWINDOW (window
), horiz_flag
, 1))
4467 error ("Window is not resizable");
4471 Lisp_Object first_parallel
= Qnil
;
4475 /* This happens if WINDOW on the previous iteration was
4476 at top level of the window tree. */
4477 Fset_window_configuration (old_config
);
4478 error ("Specified window edge is fixed");
4481 p
= XWINDOW (window
);
4484 /* See if this level has windows in parallel in the specified
4485 direction. If so, set FIRST_PARALLEL to the first one. */
4488 if (! NILP (parent
) && !NILP (XWINDOW (parent
)->vchild
))
4489 first_parallel
= XWINDOW (parent
)->vchild
;
4490 else if (NILP (parent
) && !NILP (p
->next
))
4492 /* Handle the vertical chain of main window and minibuffer
4493 which has no parent. */
4494 first_parallel
= window
;
4495 while (! NILP (XWINDOW (first_parallel
)->prev
))
4496 first_parallel
= XWINDOW (first_parallel
)->prev
;
4501 if (! NILP (parent
) && !NILP (XWINDOW (parent
)->hchild
))
4502 first_parallel
= XWINDOW (parent
)->hchild
;
4505 /* If this level's succession is in the desired dimension,
4506 and this window is the last one, and there is no higher level,
4507 its trailing edge is fixed. */
4508 if (NILP (XWINDOW (window
)->next
) && NILP (first_parallel
)
4511 Fset_window_configuration (old_config
);
4512 error ("Specified window edge is fixed");
4515 /* Don't make this window too small. */
4516 if (XINT (CURSIZE (window
)) + delta
4517 < window_min_size_2 (XWINDOW (window
), horiz_flag
))
4519 Fset_window_configuration (old_config
);
4520 error ("Cannot adjust window size as specified");
4523 /* Clear out some redisplay caches. */
4524 XSETFASTINT (p
->last_modified
, 0);
4525 XSETFASTINT (p
->last_overlay_modified
, 0);
4527 /* Adjust this window's edge. */
4528 XSETINT (CURSIZE (window
),
4529 XINT (CURSIZE (window
)) + delta
);
4531 /* If this window has following siblings in the desired dimension,
4532 make them smaller, and exit the loop.
4534 (If we reach the top of the tree and can never do this,
4535 we will fail and report an error, above.) */
4536 if (NILP (first_parallel
))
4538 if (!NILP (p
->next
))
4540 /* This may happen for the minibuffer. In that case
4541 the window_deletion_count check below does not work. */
4542 if (XINT (CURSIZE (p
->next
)) - delta
<= 0)
4544 Fset_window_configuration (old_config
);
4545 error ("Cannot adjust window size as specified");
4548 XSETINT (CURBEG (p
->next
),
4549 XINT (CURBEG (p
->next
)) + delta
);
4550 size_window (p
->next
, XINT (CURSIZE (p
->next
)) - delta
,
4551 horiz_flag
, 0, 1, 0);
4556 /* Here we have a chain of parallel siblings, in the other dimension.
4557 Change the size of the other siblings. */
4558 for (child
= first_parallel
;
4560 child
= XWINDOW (child
)->next
)
4561 if (! EQ (child
, window
))
4562 size_window (child
, XINT (CURSIZE (child
)) + delta
,
4563 horiz_flag
, 0, 0, 1);
4568 /* If we made a window so small it got deleted,
4569 we failed. Report failure. */
4570 if (delcount
!= window_deletion_count
)
4572 Fset_window_configuration (old_config
);
4573 error ("Cannot adjust window size as specified");
4576 /* Adjust glyph matrices. */
4577 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4583 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge
,
4584 Sadjust_window_trailing_edge
, 3, 3, 0,
4585 doc
: /* Adjust the bottom or right edge of WINDOW by DELTA.
4586 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4587 Otherwise, adjust the height, moving the bottom edge.
4589 Following siblings of the selected window are resized to fulfill
4590 the size request. If they become too small in the process, they
4591 are not deleted; instead, we signal an error. */)
4592 (window
, delta
, horizontal
)
4593 Lisp_Object window
, delta
, horizontal
;
4595 CHECK_NUMBER (delta
);
4596 adjust_window_trailing_edge (window
, XINT (delta
), !NILP (horizontal
));
4598 if (! NILP (Vwindow_configuration_change_hook
))
4599 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
4606 /***********************************************************************
4607 Resizing Mini-Windows
4608 ***********************************************************************/
4610 static void shrink_window_lowest_first
P_ ((struct window
*, int));
4612 enum save_restore_action
4619 static int save_restore_orig_size
P_ ((struct window
*,
4620 enum save_restore_action
));
4622 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4623 from lowest windows first. */
4626 shrink_window_lowest_first (w
, height
)
4634 xassert (!MINI_WINDOW_P (w
));
4636 /* Set redisplay hints. */
4637 XSETFASTINT (w
->last_modified
, 0);
4638 XSETFASTINT (w
->last_overlay_modified
, 0);
4639 windows_or_buffers_changed
++;
4640 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w
))) = 1;
4642 old_height
= XFASTINT (w
->total_lines
);
4643 XSETFASTINT (w
->total_lines
, height
);
4645 if (!NILP (w
->hchild
))
4647 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
4649 c
= XWINDOW (child
);
4650 c
->top_line
= w
->top_line
;
4651 shrink_window_lowest_first (c
, height
);
4654 else if (!NILP (w
->vchild
))
4656 Lisp_Object last_child
;
4657 int delta
= old_height
- height
;
4662 /* Find the last child. We are taking space from lowest windows
4663 first, so we iterate over children from the last child
4665 for (child
= w
->vchild
; !NILP (child
); child
= XWINDOW (child
)->next
)
4668 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
4669 for (child
= last_child
; delta
&& !NILP (child
); child
= c
->prev
)
4673 c
= XWINDOW (child
);
4674 this_one
= XFASTINT (c
->total_lines
) - MIN_SAFE_WINDOW_HEIGHT
;
4676 if (this_one
> delta
)
4679 shrink_window_lowest_first (c
, XFASTINT (c
->total_lines
) - this_one
);
4683 /* Compute new positions. */
4684 last_top
= XINT (w
->top_line
);
4685 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
4687 c
= XWINDOW (child
);
4688 c
->top_line
= make_number (last_top
);
4689 shrink_window_lowest_first (c
, XFASTINT (c
->total_lines
));
4690 last_top
+= XFASTINT (c
->total_lines
);
4696 /* Save, restore, or check positions and sizes in the window tree
4697 rooted at W. ACTION says what to do.
4699 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4700 orig_total_lines members are valid for all windows in the window
4701 tree. Value is non-zero if they are valid.
4703 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4704 orig_top_line and orig_total_lines for all windows in the tree.
4706 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4707 stored in orig_top_line and orig_total_lines for all windows. */
4710 save_restore_orig_size (w
, action
)
4712 enum save_restore_action action
;
4718 if (!NILP (w
->hchild
))
4720 if (!save_restore_orig_size (XWINDOW (w
->hchild
), action
))
4723 else if (!NILP (w
->vchild
))
4725 if (!save_restore_orig_size (XWINDOW (w
->vchild
), action
))
4731 case CHECK_ORIG_SIZES
:
4732 if (!INTEGERP (w
->orig_top_line
) || !INTEGERP (w
->orig_total_lines
))
4736 case SAVE_ORIG_SIZES
:
4737 w
->orig_top_line
= w
->top_line
;
4738 w
->orig_total_lines
= w
->total_lines
;
4739 XSETFASTINT (w
->last_modified
, 0);
4740 XSETFASTINT (w
->last_overlay_modified
, 0);
4743 case RESTORE_ORIG_SIZES
:
4744 xassert (INTEGERP (w
->orig_top_line
) && INTEGERP (w
->orig_total_lines
));
4745 w
->top_line
= w
->orig_top_line
;
4746 w
->total_lines
= w
->orig_total_lines
;
4747 w
->orig_total_lines
= w
->orig_top_line
= Qnil
;
4748 XSETFASTINT (w
->last_modified
, 0);
4749 XSETFASTINT (w
->last_overlay_modified
, 0);
4756 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
4763 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4764 without deleting other windows. */
4767 grow_mini_window (w
, delta
)
4771 struct frame
*f
= XFRAME (w
->frame
);
4772 struct window
*root
;
4774 xassert (MINI_WINDOW_P (w
));
4775 xassert (delta
>= 0);
4777 /* Check values of window_min_width and window_min_height for
4779 check_min_window_sizes ();
4781 /* Compute how much we can enlarge the mini-window without deleting
4783 root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4786 int min_height
= window_min_size (root
, 0, 0, 0);
4787 if (XFASTINT (root
->total_lines
) - delta
< min_height
)
4788 /* Note that the root window may already be smaller than
4790 delta
= max (0, XFASTINT (root
->total_lines
) - min_height
);
4795 /* Save original window sizes and positions, if not already done. */
4796 if (!save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
4797 save_restore_orig_size (root
, SAVE_ORIG_SIZES
);
4799 /* Shrink other windows. */
4800 shrink_window_lowest_first (root
, XFASTINT (root
->total_lines
) - delta
);
4802 /* Grow the mini-window. */
4803 w
->top_line
= make_number (XFASTINT (root
->top_line
) + XFASTINT (root
->total_lines
));
4804 w
->total_lines
= make_number (XFASTINT (w
->total_lines
) + delta
);
4805 XSETFASTINT (w
->last_modified
, 0);
4806 XSETFASTINT (w
->last_overlay_modified
, 0);
4813 /* Shrink mini-window W. If there is recorded info about window sizes
4814 before a call to grow_mini_window, restore recorded window sizes.
4815 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4819 shrink_mini_window (w
)
4822 struct frame
*f
= XFRAME (w
->frame
);
4823 struct window
*root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4825 if (save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
4827 save_restore_orig_size (root
, RESTORE_ORIG_SIZES
);
4829 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
4830 windows_or_buffers_changed
= 1;
4832 else if (XFASTINT (w
->total_lines
) > 1)
4834 /* Distribute the additional lines of the mini-window
4835 among the other windows. */
4837 XSETWINDOW (window
, w
);
4838 enlarge_window (window
, 1 - XFASTINT (w
->total_lines
), 0);
4844 /* Mark window cursors off for all windows in the window tree rooted
4845 at W by setting their phys_cursor_on_p flag to zero. Called from
4846 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4847 the frame are cleared. */
4850 mark_window_cursors_off (w
)
4855 if (!NILP (w
->hchild
))
4856 mark_window_cursors_off (XWINDOW (w
->hchild
));
4857 else if (!NILP (w
->vchild
))
4858 mark_window_cursors_off (XWINDOW (w
->vchild
));
4860 w
->phys_cursor_on_p
= 0;
4862 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
4867 /* Return number of lines of text (not counting mode lines) in W. */
4870 window_internal_height (w
)
4873 int ht
= XFASTINT (w
->total_lines
);
4875 if (!MINI_WINDOW_P (w
))
4877 if (!NILP (w
->parent
)
4878 || !NILP (w
->vchild
)
4879 || !NILP (w
->hchild
)
4882 || WINDOW_WANTS_MODELINE_P (w
))
4885 if (WINDOW_WANTS_HEADER_LINE_P (w
))
4893 /* Return the number of columns in W.
4894 Don't count columns occupied by scroll bars or the vertical bar
4895 separating W from the sibling to its right. */
4898 window_box_text_cols (w
)
4901 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4902 int width
= XINT (w
->total_cols
);
4904 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w
))
4905 /* Scroll bars occupy a few columns. */
4906 width
-= WINDOW_CONFIG_SCROLL_BAR_COLS (w
);
4907 else if (!FRAME_WINDOW_P (f
)
4908 && !WINDOW_RIGHTMOST_P (w
) && !WINDOW_FULL_WIDTH_P (w
))
4909 /* The column of `|' characters separating side-by-side windows
4910 occupies one column only. */
4913 if (FRAME_WINDOW_P (f
))
4914 /* On window-systems, fringes and display margins cannot be
4915 used for normal text. */
4916 width
-= (WINDOW_FRINGE_COLS (w
)
4917 + WINDOW_LEFT_MARGIN_COLS (w
)
4918 + WINDOW_RIGHT_MARGIN_COLS (w
));
4924 /************************************************************************
4926 ***********************************************************************/
4928 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4929 N screen-fulls, which is defined as the height of the window minus
4930 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4931 instead. Negative values of N mean scroll down. NOERROR non-zero
4932 means don't signal an error if we try to move over BEGV or ZV,
4936 window_scroll (window
, n
, whole
, noerror
)
4944 /* If we must, use the pixel-based version which is much slower than
4945 the line-based one but can handle varying line heights. */
4946 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window
)->frame
)))
4947 window_scroll_pixel_based (window
, n
, whole
, noerror
);
4949 window_scroll_line_based (window
, n
, whole
, noerror
);
4955 /* Implementation of window_scroll that works based on pixel line
4956 heights. See the comment of window_scroll for parameter
4960 window_scroll_pixel_based (window
, n
, whole
, noerror
)
4967 struct window
*w
= XWINDOW (window
);
4968 struct text_pos start
;
4969 int this_scroll_margin
;
4970 /* True if we fiddled the window vscroll field without really scrolling. */
4972 int x
, y
, rtop
, rbot
, rowh
, vpos
;
4974 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
4976 /* If PT is not visible in WINDOW, move back one half of
4977 the screen. Allow PT to be partially visible, otherwise
4978 something like (scroll-down 1) with PT in the line before
4979 the partially visible one would recenter. */
4981 if (!pos_visible_p (w
, PT
, &x
, &y
, &rtop
, &rbot
, &rowh
, &vpos
))
4983 /* Move backward half the height of the window. Performance note:
4984 vmotion used here is about 10% faster, but would give wrong
4985 results for variable height lines. */
4986 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4987 it
.current_y
= it
.last_visible_y
;
4988 move_it_vertically_backward (&it
, window_box_height (w
) / 2);
4990 /* The function move_iterator_vertically may move over more than
4991 the specified y-distance. If it->w is small, e.g. a
4992 mini-buffer window, we may end up in front of the window's
4993 display area. This is the case when Start displaying at the
4994 start of the line containing PT in this case. */
4995 if (it
.current_y
<= 0)
4997 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4998 move_it_vertically_backward (&it
, 0);
5002 start
= it
.current
.pos
;
5004 else if (auto_window_vscroll_p
)
5006 if (rtop
|| rbot
) /* partially visible */
5009 int dy
= WINDOW_FRAME_LINE_HEIGHT (w
);
5011 dy
= max ((window_box_height (w
)
5012 - next_screen_context_lines
* dy
),
5018 /* Only vscroll backwards if already vscrolled forwards. */
5019 if (w
->vscroll
< 0 && rtop
> 0)
5021 px
= max (0, -w
->vscroll
- min (rtop
, -dy
));
5022 Fset_window_vscroll (window
, make_number (px
), Qt
);
5028 /* Do vscroll if already vscrolled or only display line. */
5029 if (rbot
> 0 && (w
->vscroll
< 0 || vpos
== 0))
5031 px
= max (0, -w
->vscroll
+ min (rbot
, dy
));
5032 Fset_window_vscroll (window
, make_number (px
), Qt
);
5036 /* Maybe modify window start instead of scrolling. */
5037 if (rbot
> 0 || w
->vscroll
< 0)
5041 Fset_window_vscroll (window
, make_number (0), Qt
);
5042 /* If there are other text lines above the current row,
5043 move window start to current row. Else to next row. */
5045 spos
= XINT (Fline_beginning_position (Qnil
));
5047 spos
= min (XINT (Fline_end_position (Qnil
)) + 1, ZV
);
5048 set_marker_restricted (w
->start
, make_number (spos
),
5050 w
->start_at_line_beg
= Qt
;
5051 w
->update_mode_line
= Qt
;
5052 XSETFASTINT (w
->last_modified
, 0);
5053 XSETFASTINT (w
->last_overlay_modified
, 0);
5054 /* Set force_start so that redisplay_window will run the
5055 window-scroll-functions. */
5056 w
->force_start
= Qt
;
5061 /* Cancel previous vscroll. */
5062 Fset_window_vscroll (window
, make_number (0), Qt
);
5065 /* If scroll_preserve_screen_position is non-nil, we try to set
5066 point in the same window line as it is now, so get that line. */
5067 if (!NILP (Vscroll_preserve_screen_position
))
5069 /* We preserve the goal pixel coordinate across consecutive
5070 calls to scroll-up or scroll-down. This avoids the
5071 possibility of point becoming "stuck" on a tall line when
5072 scrolling by one line. */
5073 if (window_scroll_pixel_based_preserve_y
< 0
5074 || (!EQ (current_kboard
->Vlast_command
, Qscroll_up
)
5075 && !EQ (current_kboard
->Vlast_command
, Qscroll_down
)))
5077 start_display (&it
, w
, start
);
5078 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
5079 window_scroll_pixel_based_preserve_y
= it
.current_y
;
5083 window_scroll_pixel_based_preserve_y
= -1;
5085 /* Move iterator it from start the specified distance forward or
5086 backward. The result is the new window start. */
5087 start_display (&it
, w
, start
);
5090 int start_pos
= IT_CHARPOS (it
);
5091 int dy
= WINDOW_FRAME_LINE_HEIGHT (w
);
5092 dy
= max ((window_box_height (w
)
5093 - next_screen_context_lines
* dy
),
5096 /* Note that move_it_vertically always moves the iterator to the
5097 start of a line. So, if the last line doesn't have a newline,
5098 we would end up at the start of the line ending at ZV. */
5101 move_it_vertically_backward (&it
, -dy
);
5102 /* Ensure we actually do move, e.g. in case we are currently
5103 looking at an image that is taller that the window height. */
5104 while (start_pos
== IT_CHARPOS (it
)
5105 && start_pos
> BEGV
)
5106 move_it_by_lines (&it
, -1, 1);
5110 move_it_to (&it
, ZV
, -1, it
.current_y
+ dy
, -1,
5111 MOVE_TO_POS
| MOVE_TO_Y
);
5112 /* Ensure we actually do move, e.g. in case we are currently
5113 looking at an image that is taller that the window height. */
5114 while (start_pos
== IT_CHARPOS (it
)
5116 move_it_by_lines (&it
, 1, 1);
5120 move_it_by_lines (&it
, n
, 1);
5122 /* We failed if we find ZV is already on the screen (scrolling up,
5123 means there's nothing past the end), or if we can't start any
5124 earlier (scrolling down, means there's nothing past the top). */
5125 if ((n
> 0 && IT_CHARPOS (it
) == ZV
)
5126 || (n
< 0 && IT_CHARPOS (it
) == CHARPOS (start
)))
5128 if (IT_CHARPOS (it
) == ZV
)
5130 if (it
.current_y
< it
.last_visible_y
5131 && (it
.current_y
+ it
.max_ascent
+ it
.max_descent
5132 > it
.last_visible_y
))
5134 /* The last line was only partially visible, make it fully
5136 w
->vscroll
= (it
.last_visible_y
5137 - it
.current_y
+ it
.max_ascent
+ it
.max_descent
);
5138 adjust_glyphs (it
.f
);
5142 else if (n
< 0) /* could happen with empty buffers */
5143 xsignal0 (Qbeginning_of_buffer
);
5145 xsignal0 (Qend_of_buffer
);
5149 if (w
->vscroll
!= 0)
5150 /* The first line was only partially visible, make it fully
5156 xsignal0 (Qbeginning_of_buffer
);
5159 /* If control gets here, then we vscrolled. */
5161 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
5163 /* Don't try to change the window start below. */
5169 int pos
= IT_CHARPOS (it
);
5172 /* If in the middle of a multi-glyph character move forward to
5173 the next character. */
5174 if (in_display_vector_p (&it
))
5177 move_it_to (&it
, pos
, -1, -1, -1, MOVE_TO_POS
);
5180 /* Set the window start, and set up the window for redisplay. */
5181 set_marker_restricted (w
->start
, make_number (pos
),
5183 bytepos
= XMARKER (w
->start
)->bytepos
;
5184 w
->start_at_line_beg
= ((pos
== BEGV
|| FETCH_BYTE (bytepos
- 1) == '\n')
5186 w
->update_mode_line
= Qt
;
5187 XSETFASTINT (w
->last_modified
, 0);
5188 XSETFASTINT (w
->last_overlay_modified
, 0);
5189 /* Set force_start so that redisplay_window will run the
5190 window-scroll-functions. */
5191 w
->force_start
= Qt
;
5194 /* The rest of this function uses current_y in a nonstandard way,
5195 not including the height of the header line if any. */
5196 it
.current_y
= it
.vpos
= 0;
5198 /* Move PT out of scroll margins.
5199 This code wants current_y to be zero at the window start position
5200 even if there is a header line. */
5201 this_scroll_margin
= max (0, scroll_margin
);
5202 this_scroll_margin
= min (this_scroll_margin
, XFASTINT (w
->total_lines
) / 4);
5203 this_scroll_margin
*= FRAME_LINE_HEIGHT (it
.f
);
5207 /* We moved the window start towards ZV, so PT may be now
5208 in the scroll margin at the top. */
5209 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
5210 if (IT_CHARPOS (it
) == PT
&& it
.current_y
>= this_scroll_margin
5211 && (NILP (Vscroll_preserve_screen_position
)
5212 || EQ (Vscroll_preserve_screen_position
, Qt
)))
5213 /* We found PT at a legitimate height. Leave it alone. */
5215 else if (window_scroll_pixel_based_preserve_y
>= 0)
5217 /* If we have a header line, take account of it.
5218 This is necessary because we set it.current_y to 0, above. */
5219 move_it_to (&it
, -1, -1,
5220 window_scroll_pixel_based_preserve_y
5221 - (WINDOW_WANTS_HEADER_LINE_P (w
) ? 1 : 0 ),
5223 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5227 while (it
.current_y
< this_scroll_margin
)
5229 int prev
= it
.current_y
;
5230 move_it_by_lines (&it
, 1, 1);
5231 if (prev
== it
.current_y
)
5234 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5239 int charpos
, bytepos
;
5242 /* Save our position, for the
5243 window_scroll_pixel_based_preserve_y case. */
5244 charpos
= IT_CHARPOS (it
);
5245 bytepos
= IT_BYTEPOS (it
);
5247 /* We moved the window start towards BEGV, so PT may be now
5248 in the scroll margin at the bottom. */
5249 move_it_to (&it
, PT
, -1,
5250 (it
.last_visible_y
- CURRENT_HEADER_LINE_HEIGHT (w
)
5251 - this_scroll_margin
- 1),
5253 MOVE_TO_POS
| MOVE_TO_Y
);
5255 /* Save our position, in case it's correct. */
5256 charpos
= IT_CHARPOS (it
);
5257 bytepos
= IT_BYTEPOS (it
);
5259 /* See if point is on a partially visible line at the end. */
5260 if (it
.what
== IT_EOB
)
5261 partial_p
= it
.current_y
+ it
.ascent
+ it
.descent
> it
.last_visible_y
;
5264 move_it_by_lines (&it
, 1, 1);
5265 partial_p
= it
.current_y
> it
.last_visible_y
;
5268 if (charpos
== PT
&& !partial_p
5269 && (NILP (Vscroll_preserve_screen_position
)
5270 || EQ (Vscroll_preserve_screen_position
, Qt
)))
5271 /* We found PT before we found the display margin, so PT is ok. */
5273 else if (window_scroll_pixel_based_preserve_y
>= 0)
5275 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
5276 start_display (&it
, w
, start
);
5277 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5278 here because we called start_display again and did not
5279 alter it.current_y this time. */
5280 move_it_to (&it
, -1, -1, window_scroll_pixel_based_preserve_y
, -1,
5282 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5287 /* The last line was only partially visible, so back up two
5288 lines to make sure we're on a fully visible line. */
5290 move_it_by_lines (&it
, -2, 0);
5291 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5294 /* No, the position we saved is OK, so use it. */
5295 SET_PT_BOTH (charpos
, bytepos
);
5301 /* Implementation of window_scroll that works based on screen lines.
5302 See the comment of window_scroll for parameter descriptions. */
5305 window_scroll_line_based (window
, n
, whole
, noerror
)
5311 register struct window
*w
= XWINDOW (window
);
5312 register int opoint
= PT
, opoint_byte
= PT_BYTE
;
5313 register int pos
, pos_byte
;
5314 register int ht
= window_internal_height (w
);
5315 register Lisp_Object tem
;
5319 struct position posit
;
5322 /* If scrolling screen-fulls, compute the number of lines to
5323 scroll from the window's height. */
5325 n
*= max (1, ht
- next_screen_context_lines
);
5327 startpos
= marker_position (w
->start
);
5329 posit
= *compute_motion (startpos
, 0, 0, 0,
5331 -1, XINT (w
->hscroll
),
5333 original_vpos
= posit
.vpos
;
5335 XSETFASTINT (tem
, PT
);
5336 tem
= Fpos_visible_in_window_p (tem
, window
, Qnil
);
5340 Fvertical_motion (make_number (- (ht
/ 2)), window
);
5345 lose
= n
< 0 && PT
== BEGV
;
5346 Fvertical_motion (make_number (n
), window
);
5350 SET_PT_BOTH (opoint
, opoint_byte
);
5357 xsignal0 (Qbeginning_of_buffer
);
5362 int this_scroll_margin
= scroll_margin
;
5364 /* Don't use a scroll margin that is negative or too large. */
5365 if (this_scroll_margin
< 0)
5366 this_scroll_margin
= 0;
5368 if (XINT (w
->total_lines
) < 4 * scroll_margin
)
5369 this_scroll_margin
= XINT (w
->total_lines
) / 4;
5371 set_marker_restricted_both (w
->start
, w
->buffer
, pos
, pos_byte
);
5372 w
->start_at_line_beg
= bolp
;
5373 w
->update_mode_line
= Qt
;
5374 XSETFASTINT (w
->last_modified
, 0);
5375 XSETFASTINT (w
->last_overlay_modified
, 0);
5376 /* Set force_start so that redisplay_window will run
5377 the window-scroll-functions. */
5378 w
->force_start
= Qt
;
5380 if (!NILP (Vscroll_preserve_screen_position
)
5381 && (whole
|| !EQ (Vscroll_preserve_screen_position
, Qt
)))
5383 SET_PT_BOTH (pos
, pos_byte
);
5384 Fvertical_motion (make_number (original_vpos
), window
);
5386 /* If we scrolled forward, put point enough lines down
5387 that it is outside the scroll margin. */
5392 if (this_scroll_margin
> 0)
5394 SET_PT_BOTH (pos
, pos_byte
);
5395 Fvertical_motion (make_number (this_scroll_margin
), window
);
5401 if (top_margin
<= opoint
)
5402 SET_PT_BOTH (opoint
, opoint_byte
);
5403 else if (!NILP (Vscroll_preserve_screen_position
))
5405 SET_PT_BOTH (pos
, pos_byte
);
5406 Fvertical_motion (make_number (original_vpos
), window
);
5409 SET_PT (top_margin
);
5415 /* If we scrolled backward, put point near the end of the window
5416 but not within the scroll margin. */
5417 SET_PT_BOTH (pos
, pos_byte
);
5418 tem
= Fvertical_motion (make_number (ht
- this_scroll_margin
), window
);
5419 if (XFASTINT (tem
) == ht
- this_scroll_margin
)
5422 bottom_margin
= PT
+ 1;
5424 if (bottom_margin
> opoint
)
5425 SET_PT_BOTH (opoint
, opoint_byte
);
5428 if (!NILP (Vscroll_preserve_screen_position
))
5430 SET_PT_BOTH (pos
, pos_byte
);
5431 Fvertical_motion (make_number (original_vpos
), window
);
5434 Fvertical_motion (make_number (-1), window
);
5443 xsignal0 (Qend_of_buffer
);
5448 /* Scroll selected_window up or down. If N is nil, scroll a
5449 screen-full which is defined as the height of the window minus
5450 next_screen_context_lines. If N is the symbol `-', scroll.
5451 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5452 up. This is the guts of Fscroll_up and Fscroll_down. */
5455 scroll_command (n
, direction
)
5459 int count
= SPECPDL_INDEX ();
5461 xassert (abs (direction
) == 1);
5463 /* If selected window's buffer isn't current, make it current for
5464 the moment. But don't screw up if window_scroll gets an error. */
5465 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
5467 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
5468 Fset_buffer (XWINDOW (selected_window
)->buffer
);
5470 /* Make redisplay consider other windows than just selected_window. */
5471 ++windows_or_buffers_changed
;
5475 window_scroll (selected_window
, direction
, 1, 0);
5476 else if (EQ (n
, Qminus
))
5477 window_scroll (selected_window
, -direction
, 1, 0);
5480 n
= Fprefix_numeric_value (n
);
5481 window_scroll (selected_window
, XINT (n
) * direction
, 0, 0);
5484 unbind_to (count
, Qnil
);
5487 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "P",
5488 doc
: /* Scroll text of current window upward ARG lines.
5489 If ARG is omitted or nil, scroll upward by a near full screen.
5490 A near full screen is `next-screen-context-lines' less than a full screen.
5491 Negative ARG means scroll downward.
5492 If ARG is the atom `-', scroll downward by nearly full screen.
5493 When calling from a program, supply as argument a number, nil, or `-'. */)
5497 scroll_command (arg
, 1);
5501 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "P",
5502 doc
: /* Scroll text of current window down ARG lines.
5503 If ARG is omitted or nil, scroll down by a near full screen.
5504 A near full screen is `next-screen-context-lines' less than a full screen.
5505 Negative ARG means scroll upward.
5506 If ARG is the atom `-', scroll upward by nearly full screen.
5507 When calling from a program, supply as argument a number, nil, or `-'. */)
5511 scroll_command (arg
, -1);
5515 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling
, Sother_window_for_scrolling
, 0, 0, 0,
5516 doc
: /* Return the other window for \"other window scroll\" commands.
5517 If `other-window-scroll-buffer' is non-nil, a window
5518 showing that buffer is used.
5519 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5520 specifies the window. This takes precedence over
5521 `other-window-scroll-buffer'. */)
5526 if (MINI_WINDOW_P (XWINDOW (selected_window
))
5527 && !NILP (Vminibuf_scroll_window
))
5528 window
= Vminibuf_scroll_window
;
5529 /* If buffer is specified, scroll that buffer. */
5530 else if (!NILP (Vother_window_scroll_buffer
))
5532 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
5534 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
, Qnil
);
5538 /* Nothing specified; look for a neighboring window on the same
5540 window
= Fnext_window (selected_window
, Qnil
, Qnil
);
5542 if (EQ (window
, selected_window
))
5543 /* That didn't get us anywhere; look for a window on another
5546 window
= Fnext_window (window
, Qnil
, Qt
);
5547 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window
))))
5548 && ! EQ (window
, selected_window
));
5551 CHECK_LIVE_WINDOW (window
);
5553 if (EQ (window
, selected_window
))
5554 error ("There is no other window");
5559 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
5560 doc
: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5561 A near full screen is `next-screen-context-lines' less than a full screen.
5562 The next window is the one below the current one; or the one at the top
5563 if the current one is at the bottom. Negative ARG means scroll downward.
5564 If ARG is the atom `-', scroll downward by nearly full screen.
5565 When calling from a program, supply as argument a number, nil, or `-'.
5567 If `other-window-scroll-buffer' is non-nil, scroll the window
5568 showing that buffer, popping the buffer up if necessary.
5569 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5570 specifies the window to scroll. This takes precedence over
5571 `other-window-scroll-buffer'. */)
5577 int count
= SPECPDL_INDEX ();
5579 window
= Fother_window_for_scrolling ();
5580 w
= XWINDOW (window
);
5582 /* Don't screw up if window_scroll gets an error. */
5583 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
5584 ++windows_or_buffers_changed
;
5586 Fset_buffer (w
->buffer
);
5587 SET_PT (marker_position (w
->pointm
));
5590 window_scroll (window
, 1, 1, 1);
5591 else if (EQ (arg
, Qminus
))
5592 window_scroll (window
, -1, 1, 1);
5598 window_scroll (window
, XINT (arg
), 0, 1);
5601 set_marker_both (w
->pointm
, Qnil
, PT
, PT_BYTE
);
5602 unbind_to (count
, Qnil
);
5607 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 0, 2, "P\np",
5608 doc
: /* Scroll selected window display ARG columns left.
5609 Default for ARG is window width minus 2.
5610 Value is the total amount of leftward horizontal scrolling in
5611 effect after the change.
5612 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5613 lower bound for automatic scrolling, i.e. automatic scrolling
5614 will not scroll a window to a column less than the value returned
5615 by this function. This happens in an interactive call. */)
5617 register Lisp_Object arg
, set_minimum
;
5621 struct window
*w
= XWINDOW (selected_window
);
5624 XSETFASTINT (arg
, window_box_text_cols (w
) - 2);
5626 arg
= Fprefix_numeric_value (arg
);
5628 hscroll
= XINT (w
->hscroll
) + XINT (arg
);
5629 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
5631 if (!NILP (set_minimum
))
5632 w
->min_hscroll
= w
->hscroll
;
5637 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 0, 2, "P\np",
5638 doc
: /* Scroll selected window display ARG columns right.
5639 Default for ARG is window width minus 2.
5640 Value is the total amount of leftward horizontal scrolling in
5641 effect after the change.
5642 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5643 lower bound for automatic scrolling, i.e. automatic scrolling
5644 will not scroll a window to a column less than the value returned
5645 by this function. This happens in an interactive call. */)
5647 register Lisp_Object arg
, set_minimum
;
5651 struct window
*w
= XWINDOW (selected_window
);
5654 XSETFASTINT (arg
, window_box_text_cols (w
) - 2);
5656 arg
= Fprefix_numeric_value (arg
);
5658 hscroll
= XINT (w
->hscroll
) - XINT (arg
);
5659 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
5661 if (!NILP (set_minimum
))
5662 w
->min_hscroll
= w
->hscroll
;
5667 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window
, Sminibuffer_selected_window
, 0, 0, 0,
5668 doc
: /* Return the window which was selected when entering the minibuffer.
5669 Returns nil, if current window is not a minibuffer window. */)
5672 if (minibuf_level
> 0
5673 && MINI_WINDOW_P (XWINDOW (selected_window
))
5674 && WINDOW_LIVE_P (minibuf_selected_window
))
5675 return minibuf_selected_window
;
5680 /* Value is the number of lines actually displayed in window W,
5681 as opposed to its height. */
5684 displayed_window_lines (w
)
5688 struct text_pos start
;
5689 int height
= window_box_height (w
);
5690 struct buffer
*old_buffer
;
5693 if (XBUFFER (w
->buffer
) != current_buffer
)
5695 old_buffer
= current_buffer
;
5696 set_buffer_internal (XBUFFER (w
->buffer
));
5701 /* In case W->start is out of the accessible range, do something
5702 reasonable. This happens in Info mode when Info-scroll-down
5703 calls (recenter -1) while W->start is 1. */
5704 if (XMARKER (w
->start
)->charpos
< BEGV
)
5705 SET_TEXT_POS (start
, BEGV
, BEGV_BYTE
);
5706 else if (XMARKER (w
->start
)->charpos
> ZV
)
5707 SET_TEXT_POS (start
, ZV
, ZV_BYTE
);
5709 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
5711 start_display (&it
, w
, start
);
5712 move_it_vertically (&it
, height
);
5713 bottom_y
= line_bottom_y (&it
);
5715 /* rms: On a non-window display,
5716 the value of it.vpos at the bottom of the screen
5717 seems to be 1 larger than window_box_height (w).
5718 This kludge fixes a bug whereby (move-to-window-line -1)
5719 when ZV is on the last screen line
5720 moves to the previous screen line instead of the last one. */
5721 if (! FRAME_WINDOW_P (XFRAME (w
->frame
)))
5724 /* Add in empty lines at the bottom of the window. */
5725 if (bottom_y
< height
)
5727 int uy
= FRAME_LINE_HEIGHT (it
.f
);
5728 it
.vpos
+= (height
- bottom_y
+ uy
- 1) / uy
;
5732 set_buffer_internal (old_buffer
);
5738 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
5739 doc
: /* Center point in window and redisplay frame.
5740 With prefix argument ARG, recenter putting point on screen line ARG
5741 relative to the current window. If ARG is negative, it counts up from the
5742 bottom of the window. (ARG should be less than the height of the window.)
5744 If ARG is omitted or nil, erase the entire frame and then redraw with point
5745 in the center of the current window. If `auto-resize-tool-bars' is set to
5746 `grow-only', this resets the tool-bar's height to the minimum height needed.
5748 Just C-u as prefix means put point in the center of the window
5749 and redisplay normally--don't erase and redraw the frame. */)
5751 register Lisp_Object arg
;
5753 struct window
*w
= XWINDOW (selected_window
);
5754 struct buffer
*buf
= XBUFFER (w
->buffer
);
5755 struct buffer
*obuf
= current_buffer
;
5757 int charpos
, bytepos
;
5759 int this_scroll_margin
;
5761 /* If redisplay is suppressed due to an error, try again. */
5762 obuf
->display_error_modiff
= 0;
5768 /* Invalidate pixel data calculated for all compositions. */
5769 for (i
= 0; i
< n_compositions
; i
++)
5770 composition_table
[i
]->font
= NULL
;
5772 WINDOW_XFRAME (w
)->minimize_tool_bar_window_p
= 1;
5774 Fredraw_frame (WINDOW_FRAME (w
));
5775 SET_FRAME_GARBAGED (WINDOW_XFRAME (w
));
5778 else if (CONSP (arg
)) /* Just C-u. */
5782 arg
= Fprefix_numeric_value (arg
);
5787 set_buffer_internal (buf
);
5789 /* Do this after making BUF current
5790 in case scroll_margin is buffer-local. */
5791 this_scroll_margin
= max (0, scroll_margin
);
5792 this_scroll_margin
= min (this_scroll_margin
,
5793 XFASTINT (w
->total_lines
) / 4);
5795 /* Handle centering on a graphical frame specially. Such frames can
5796 have variable-height lines and centering point on the basis of
5797 line counts would lead to strange effects. */
5798 if (FRAME_WINDOW_P (XFRAME (w
->frame
)))
5805 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
5806 start_display (&it
, w
, pt
);
5807 move_it_vertically_backward (&it
, window_box_height (w
) / 2);
5808 charpos
= IT_CHARPOS (it
);
5809 bytepos
= IT_BYTEPOS (it
);
5816 int extra_line_spacing
;
5817 int h
= window_box_height (w
);
5819 iarg
= - max (-iarg
, this_scroll_margin
);
5821 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
5822 start_display (&it
, w
, pt
);
5824 /* Be sure we have the exact height of the full line containing PT. */
5825 move_it_by_lines (&it
, 0, 1);
5827 /* The amount of pixels we have to move back is the window
5828 height minus what's displayed in the line containing PT,
5829 and the lines below. */
5832 move_it_by_lines (&it
, nlines
, 1);
5834 if (it
.vpos
== nlines
)
5838 /* Last line has no newline */
5839 h
-= line_bottom_y (&it
);
5843 /* Don't reserve space for extra line spacing of last line. */
5844 extra_line_spacing
= it
.max_extra_line_spacing
;
5846 /* If we can't move down NLINES lines because we hit
5847 the end of the buffer, count in some empty lines. */
5848 if (it
.vpos
< nlines
)
5851 extra_line_spacing
= it
.extra_line_spacing
;
5852 h
-= nlines
* (FRAME_LINE_HEIGHT (it
.f
) + extra_line_spacing
);
5857 /* Now find the new top line (starting position) of the window. */
5858 start_display (&it
, w
, pt
);
5860 move_it_vertically_backward (&it
, h
);
5862 /* If extra line spacing is present, we may move too far
5863 back. This causes the last line to be only partially
5864 visible (which triggers redisplay to recenter that line
5865 in the middle), so move forward.
5866 But ignore extra line spacing on last line, as it is not
5867 considered to be part of the visible height of the line.
5869 h
+= extra_line_spacing
;
5870 while (-it
.current_y
> h
)
5871 move_it_by_lines (&it
, 1, 1);
5873 charpos
= IT_CHARPOS (it
);
5874 bytepos
= IT_BYTEPOS (it
);
5878 struct position pos
;
5880 iarg
= max (iarg
, this_scroll_margin
);
5882 pos
= *vmotion (PT
, -iarg
, w
);
5883 charpos
= pos
.bufpos
;
5884 bytepos
= pos
.bytepos
;
5889 struct position pos
;
5890 int ht
= window_internal_height (w
);
5897 /* Don't let it get into the margin at either top or bottom. */
5898 iarg
= max (iarg
, this_scroll_margin
);
5899 iarg
= min (iarg
, ht
- this_scroll_margin
- 1);
5901 pos
= *vmotion (PT
, - iarg
, w
);
5902 charpos
= pos
.bufpos
;
5903 bytepos
= pos
.bytepos
;
5906 /* Set the new window start. */
5907 set_marker_both (w
->start
, w
->buffer
, charpos
, bytepos
);
5908 w
->window_end_valid
= Qnil
;
5910 w
->optional_new_start
= Qt
;
5912 if (bytepos
== BEGV_BYTE
|| FETCH_BYTE (bytepos
- 1) == '\n')
5913 w
->start_at_line_beg
= Qt
;
5915 w
->start_at_line_beg
= Qnil
;
5917 set_buffer_internal (obuf
);
5922 DEFUN ("window-text-height", Fwindow_text_height
, Swindow_text_height
,
5924 doc
: /* Return the height in lines of the text display area of WINDOW.
5925 WINDOW defaults to the selected window.
5926 This doesn't include the mode-line (or header-line if any) or any
5927 partial-height lines in the text display area. */)
5931 struct window
*w
= decode_window (window
);
5932 int pixel_height
= window_box_height (w
);
5933 int line_height
= pixel_height
/ FRAME_LINE_HEIGHT (XFRAME (w
->frame
));
5934 return make_number (line_height
);
5939 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
5941 doc
: /* Position point relative to window.
5942 With no argument, position point at center of window.
5943 An argument specifies vertical position within the window;
5944 zero means top of window, negative means relative to bottom of window. */)
5948 struct window
*w
= XWINDOW (selected_window
);
5952 int this_scroll_margin
;
5955 window
= selected_window
;
5956 start
= marker_position (w
->start
);
5957 if (start
< BEGV
|| start
> ZV
)
5959 int height
= window_internal_height (w
);
5960 Fvertical_motion (make_number (- (height
/ 2)), window
);
5961 set_marker_both (w
->start
, w
->buffer
, PT
, PT_BYTE
);
5962 w
->start_at_line_beg
= Fbolp ();
5963 w
->force_start
= Qt
;
5966 Fgoto_char (w
->start
);
5968 lines
= displayed_window_lines (w
);
5971 this_scroll_margin
= max (0, scroll_margin
);
5972 this_scroll_margin
= min (this_scroll_margin
, lines
/ 4);
5976 XSETFASTINT (arg
, lines
/ 2);
5979 int iarg
= XINT (Fprefix_numeric_value (arg
));
5982 iarg
= iarg
+ lines
;
5984 #if 0 /* This code would prevent move-to-window-line from moving point
5985 to a place inside the scroll margins (which would cause the
5986 next redisplay to scroll). I wrote this code, but then concluded
5987 it is probably better not to install it. However, it is here
5988 inside #if 0 so as not to lose it. -- rms. */
5990 /* Don't let it get into the margin at either top or bottom. */
5991 iarg
= max (iarg
, this_scroll_margin
);
5992 iarg
= min (iarg
, lines
- this_scroll_margin
- 1);
5995 arg
= make_number (iarg
);
5998 /* Skip past a partially visible first line. */
6000 XSETINT (arg
, XINT (arg
) + 1);
6002 return Fvertical_motion (arg
, window
);
6007 /***********************************************************************
6008 Window Configuration
6009 ***********************************************************************/
6011 struct save_window_data
6013 EMACS_INT size_from_Lisp_Vector_struct
;
6014 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
6015 Lisp_Object frame_cols
, frame_lines
, frame_menu_bar_lines
;
6016 Lisp_Object frame_tool_bar_lines
;
6017 Lisp_Object selected_frame
;
6018 Lisp_Object current_window
;
6019 Lisp_Object current_buffer
;
6020 Lisp_Object minibuf_scroll_window
;
6021 Lisp_Object minibuf_selected_window
;
6022 Lisp_Object root_window
;
6023 Lisp_Object focus_frame
;
6024 /* Record the values of window-min-width and window-min-height
6025 so that window sizes remain consistent with them. */
6026 Lisp_Object min_width
, min_height
;
6027 /* A vector, each of whose elements is a struct saved_window
6029 Lisp_Object saved_windows
;
6032 /* This is saved as a Lisp_Vector */
6035 /* these first two must agree with struct Lisp_Vector in lisp.h */
6036 EMACS_INT size_from_Lisp_Vector_struct
;
6037 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
6040 Lisp_Object buffer
, start
, pointm
, mark
;
6041 Lisp_Object left_col
, top_line
, total_cols
, total_lines
;
6042 Lisp_Object hscroll
, min_hscroll
;
6043 Lisp_Object parent
, prev
;
6044 Lisp_Object start_at_line_beg
;
6045 Lisp_Object display_table
;
6046 Lisp_Object orig_top_line
, orig_total_lines
;
6047 Lisp_Object left_margin_cols
, right_margin_cols
;
6048 Lisp_Object left_fringe_width
, right_fringe_width
, fringes_outside_margins
;
6049 Lisp_Object scroll_bar_width
, vertical_scroll_bar_type
;
6050 Lisp_Object dedicated
;
6053 #define SAVED_WINDOW_N(swv,n) \
6054 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
6056 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
6057 doc
: /* Return t if OBJECT is a window-configuration object. */)
6061 return WINDOW_CONFIGURATIONP (object
) ? Qt
: Qnil
;
6064 DEFUN ("window-configuration-frame", Fwindow_configuration_frame
, Swindow_configuration_frame
, 1, 1, 0,
6065 doc
: /* Return the frame that CONFIG, a window-configuration object, is about. */)
6069 register struct save_window_data
*data
;
6070 struct Lisp_Vector
*saved_windows
;
6072 CHECK_WINDOW_CONFIGURATION (config
);
6074 data
= (struct save_window_data
*) XVECTOR (config
);
6075 saved_windows
= XVECTOR (data
->saved_windows
);
6076 return XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
6079 DEFUN ("set-window-configuration", Fset_window_configuration
,
6080 Sset_window_configuration
, 1, 1, 0,
6081 doc
: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
6082 CONFIGURATION must be a value previously returned
6083 by `current-window-configuration' (which see).
6084 If CONFIGURATION was made from a frame that is now deleted,
6085 only frame-independent values can be restored. In this case,
6086 the return value is nil. Otherwise the value is t. */)
6088 Lisp_Object configuration
;
6090 register struct save_window_data
*data
;
6091 struct Lisp_Vector
*saved_windows
;
6092 Lisp_Object new_current_buffer
;
6097 CHECK_WINDOW_CONFIGURATION (configuration
);
6099 data
= (struct save_window_data
*) XVECTOR (configuration
);
6100 saved_windows
= XVECTOR (data
->saved_windows
);
6102 new_current_buffer
= data
->current_buffer
;
6103 if (NILP (XBUFFER (new_current_buffer
)->name
))
6104 new_current_buffer
= Qnil
;
6107 if (XBUFFER (new_current_buffer
) == current_buffer
)
6108 /* The code further down "preserves point" by saving here PT in
6109 old_point and then setting it later back into PT. When the
6110 current-selected-window and the final-selected-window both show
6111 the current buffer, this suffers from the problem that the
6112 current PT is the window-point of the current-selected-window,
6113 while the final PT is the point of the final-selected-window, so
6114 this copy from one PT to the other would end up moving the
6115 window-point of the final-selected-window to the window-point of
6116 the current-selected-window. So we have to be careful which
6117 point of the current-buffer we copy into old_point. */
6118 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
)
6119 && WINDOWP (selected_window
)
6120 && EQ (XWINDOW (selected_window
)->buffer
, new_current_buffer
)
6121 && !EQ (selected_window
, data
->current_window
))
6122 old_point
= XMARKER (XWINDOW (data
->current_window
)->pointm
)->charpos
;
6126 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6127 point in new_current_buffer as of the last time this buffer was
6128 used. This can be non-deterministic since it can be changed by
6129 things like jit-lock by mere temporary selection of some random
6130 window that happens to show this buffer.
6131 So if possible we want this arbitrary choice of "which point" to
6132 be the one from the to-be-selected-window so as to prevent this
6133 window's cursor from being copied from another window. */
6134 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
)
6135 /* If current_window = selected_window, its point is in BUF_PT. */
6136 && !EQ (selected_window
, data
->current_window
))
6137 old_point
= XMARKER (XWINDOW (data
->current_window
)->pointm
)->charpos
;
6139 old_point
= BUF_PT (XBUFFER (new_current_buffer
));
6142 frame
= XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
6145 /* If f is a dead frame, don't bother rebuilding its window tree.
6146 However, there is other stuff we should still try to do below. */
6147 if (FRAME_LIVE_P (f
))
6149 register struct window
*w
;
6150 register struct saved_window
*p
;
6151 struct window
*root_window
;
6152 struct window
**leaf_windows
;
6156 /* If the frame has been resized since this window configuration was
6157 made, we change the frame to the size specified in the
6158 configuration, restore the configuration, and then resize it
6159 back. We keep track of the prevailing height in these variables. */
6160 int previous_frame_lines
= FRAME_LINES (f
);
6161 int previous_frame_cols
= FRAME_COLS (f
);
6162 int previous_frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
6163 int previous_frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
6165 /* The mouse highlighting code could get screwed up
6166 if it runs during this. */
6169 if (XFASTINT (data
->frame_lines
) != previous_frame_lines
6170 || XFASTINT (data
->frame_cols
) != previous_frame_cols
)
6171 change_frame_size (f
, XFASTINT (data
->frame_lines
),
6172 XFASTINT (data
->frame_cols
), 0, 0, 0);
6173 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6174 if (XFASTINT (data
->frame_menu_bar_lines
)
6175 != previous_frame_menu_bar_lines
)
6176 x_set_menu_bar_lines (f
, data
->frame_menu_bar_lines
, make_number (0));
6177 #ifdef HAVE_WINDOW_SYSTEM
6178 if (XFASTINT (data
->frame_tool_bar_lines
)
6179 != previous_frame_tool_bar_lines
)
6180 x_set_tool_bar_lines (f
, data
->frame_tool_bar_lines
, make_number (0));
6184 /* "Swap out" point from the selected window's buffer
6185 into the window itself. (Normally the pointm of the selected
6186 window holds garbage.) We do this now, before
6187 restoring the window contents, and prevent it from
6188 being done later on when we select a new window. */
6189 if (! NILP (XWINDOW (selected_window
)->buffer
))
6191 w
= XWINDOW (selected_window
);
6192 set_marker_both (w
->pointm
,
6194 BUF_PT (XBUFFER (w
->buffer
)),
6195 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6198 windows_or_buffers_changed
++;
6199 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
6201 /* Problem: Freeing all matrices and later allocating them again
6202 is a serious redisplay flickering problem. What we would
6203 really like to do is to free only those matrices not reused
6205 root_window
= XWINDOW (FRAME_ROOT_WINDOW (f
));
6207 = (struct window
**) alloca (count_windows (root_window
)
6208 * sizeof (struct window
*));
6209 n_leaf_windows
= get_leaf_windows (root_window
, leaf_windows
, 0);
6211 /* Temporarily avoid any problems with windows that are smaller
6212 than they are supposed to be. */
6213 window_min_height
= 1;
6214 window_min_width
= 1;
6217 Mark all windows now on frame as "deleted".
6218 Restoring the new configuration "undeletes" any that are in it.
6220 Save their current buffers in their height fields, since we may
6221 need it later, if a buffer saved in the configuration is now
6223 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6225 for (k
= 0; k
< saved_windows
->size
; k
++)
6227 p
= SAVED_WINDOW_N (saved_windows
, k
);
6228 w
= XWINDOW (p
->window
);
6231 if (!NILP (p
->parent
))
6232 w
->parent
= SAVED_WINDOW_N (saved_windows
,
6233 XFASTINT (p
->parent
))->window
;
6237 if (!NILP (p
->prev
))
6239 w
->prev
= SAVED_WINDOW_N (saved_windows
,
6240 XFASTINT (p
->prev
))->window
;
6241 XWINDOW (w
->prev
)->next
= p
->window
;
6246 if (!NILP (w
->parent
))
6248 if (EQ (p
->total_cols
, XWINDOW (w
->parent
)->total_cols
))
6250 XWINDOW (w
->parent
)->vchild
= p
->window
;
6251 XWINDOW (w
->parent
)->hchild
= Qnil
;
6255 XWINDOW (w
->parent
)->hchild
= p
->window
;
6256 XWINDOW (w
->parent
)->vchild
= Qnil
;
6261 /* If we squirreled away the buffer in the window's height,
6263 if (BUFFERP (w
->total_lines
))
6264 w
->buffer
= w
->total_lines
;
6265 w
->left_col
= p
->left_col
;
6266 w
->top_line
= p
->top_line
;
6267 w
->total_cols
= p
->total_cols
;
6268 w
->total_lines
= p
->total_lines
;
6269 w
->hscroll
= p
->hscroll
;
6270 w
->min_hscroll
= p
->min_hscroll
;
6271 w
->display_table
= p
->display_table
;
6272 w
->orig_top_line
= p
->orig_top_line
;
6273 w
->orig_total_lines
= p
->orig_total_lines
;
6274 w
->left_margin_cols
= p
->left_margin_cols
;
6275 w
->right_margin_cols
= p
->right_margin_cols
;
6276 w
->left_fringe_width
= p
->left_fringe_width
;
6277 w
->right_fringe_width
= p
->right_fringe_width
;
6278 w
->fringes_outside_margins
= p
->fringes_outside_margins
;
6279 w
->scroll_bar_width
= p
->scroll_bar_width
;
6280 w
->vertical_scroll_bar_type
= p
->vertical_scroll_bar_type
;
6281 w
->dedicated
= p
->dedicated
;
6282 XSETFASTINT (w
->last_modified
, 0);
6283 XSETFASTINT (w
->last_overlay_modified
, 0);
6285 /* Reinstall the saved buffer and pointers into it. */
6286 if (NILP (p
->buffer
))
6287 w
->buffer
= p
->buffer
;
6290 if (!NILP (XBUFFER (p
->buffer
)->name
))
6291 /* If saved buffer is alive, install it. */
6293 w
->buffer
= p
->buffer
;
6294 w
->start_at_line_beg
= p
->start_at_line_beg
;
6295 set_marker_restricted (w
->start
, p
->start
, w
->buffer
);
6296 set_marker_restricted (w
->pointm
, p
->pointm
, w
->buffer
);
6297 Fset_marker (XBUFFER (w
->buffer
)->mark
,
6298 p
->mark
, w
->buffer
);
6300 /* As documented in Fcurrent_window_configuration, don't
6301 restore the location of point in the buffer which was
6302 current when the window configuration was recorded. */
6303 if (!EQ (p
->buffer
, new_current_buffer
)
6304 && XBUFFER (p
->buffer
) == current_buffer
)
6305 Fgoto_char (w
->pointm
);
6307 else if (NILP (w
->buffer
) || NILP (XBUFFER (w
->buffer
)->name
))
6308 /* Else unless window has a live buffer, get one. */
6310 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
6311 /* This will set the markers to beginning of visible
6313 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
6314 set_marker_restricted (w
->pointm
, make_number (0),w
->buffer
);
6315 w
->start_at_line_beg
= Qt
;
6318 /* Keeping window's old buffer; make sure the markers
6321 /* Set window markers at start of visible range. */
6322 if (XMARKER (w
->start
)->buffer
== 0)
6323 set_marker_restricted (w
->start
, make_number (0),
6325 if (XMARKER (w
->pointm
)->buffer
== 0)
6326 set_marker_restricted_both (w
->pointm
, w
->buffer
,
6327 BUF_PT (XBUFFER (w
->buffer
)),
6328 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6329 w
->start_at_line_beg
= Qt
;
6334 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
6335 /* Prevent "swapping out point" in the old selected window
6336 using the buffer that has been restored into it.
6337 We already swapped out point that from that window's old buffer. */
6338 selected_window
= Qnil
;
6340 /* Arrange *not* to restore point in the buffer that was
6341 current when the window configuration was saved. */
6342 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
))
6343 set_marker_restricted (XWINDOW (data
->current_window
)->pointm
,
6344 make_number (old_point
),
6345 XWINDOW (data
->current_window
)->buffer
);
6347 Fselect_window (data
->current_window
, Qnil
);
6348 XBUFFER (XWINDOW (selected_window
)->buffer
)->last_selected_window
6351 if (NILP (data
->focus_frame
)
6352 || (FRAMEP (data
->focus_frame
)
6353 && FRAME_LIVE_P (XFRAME (data
->focus_frame
))))
6354 Fredirect_frame_focus (frame
, data
->focus_frame
);
6356 #if 0 /* I don't understand why this is needed, and it causes problems
6357 when the frame's old selected window has been deleted. */
6358 if (f
!= selected_frame
&& FRAME_WINDOW_P (f
))
6359 do_switch_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)),
6363 /* Set the screen height to the value it had before this function. */
6364 if (previous_frame_lines
!= FRAME_LINES (f
)
6365 || previous_frame_cols
!= FRAME_COLS (f
))
6366 change_frame_size (f
, previous_frame_lines
, previous_frame_cols
,
6368 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6369 if (previous_frame_menu_bar_lines
!= FRAME_MENU_BAR_LINES (f
))
6370 x_set_menu_bar_lines (f
, make_number (previous_frame_menu_bar_lines
),
6372 #ifdef HAVE_WINDOW_SYSTEM
6373 if (previous_frame_tool_bar_lines
!= FRAME_TOOL_BAR_LINES (f
))
6374 x_set_tool_bar_lines (f
, make_number (previous_frame_tool_bar_lines
),
6379 /* Now, free glyph matrices in windows that were not reused. */
6380 for (i
= n
= 0; i
< n_leaf_windows
; ++i
)
6382 if (NILP (leaf_windows
[i
]->buffer
))
6384 /* Assert it's not reused as a combination. */
6385 xassert (NILP (leaf_windows
[i
]->hchild
)
6386 && NILP (leaf_windows
[i
]->vchild
));
6387 free_window_matrices (leaf_windows
[i
]);
6389 else if (EQ (leaf_windows
[i
]->buffer
, new_current_buffer
))
6397 /* Fselect_window will have made f the selected frame, so we
6398 reselect the proper frame here. Fhandle_switch_frame will change the
6399 selected window too, but that doesn't make the call to
6400 Fselect_window above totally superfluous; it still sets f's
6402 if (FRAME_LIVE_P (XFRAME (data
->selected_frame
)))
6403 do_switch_frame (data
->selected_frame
, 0, 0);
6405 if (! NILP (Vwindow_configuration_change_hook
)
6406 && ! NILP (Vrun_hooks
))
6407 call1 (Vrun_hooks
, Qwindow_configuration_change_hook
);
6410 if (!NILP (new_current_buffer
))
6411 Fset_buffer (new_current_buffer
);
6413 /* Restore the minimum heights recorded in the configuration. */
6414 window_min_height
= XINT (data
->min_height
);
6415 window_min_width
= XINT (data
->min_width
);
6417 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
6418 minibuf_selected_window
= data
->minibuf_selected_window
;
6420 return (FRAME_LIVE_P (f
) ? Qt
: Qnil
);
6423 /* Mark all windows now on frame as deleted
6424 by setting their buffers to nil. */
6427 delete_all_subwindows (w
)
6428 register struct window
*w
;
6430 if (!NILP (w
->next
))
6431 delete_all_subwindows (XWINDOW (w
->next
));
6432 if (!NILP (w
->vchild
))
6433 delete_all_subwindows (XWINDOW (w
->vchild
));
6434 if (!NILP (w
->hchild
))
6435 delete_all_subwindows (XWINDOW (w
->hchild
));
6437 w
->total_lines
= w
->buffer
; /* See Fset_window_configuration for excuse. */
6439 if (!NILP (w
->buffer
))
6442 /* We set all three of these fields to nil, to make sure that we can
6443 distinguish this dead window from any live window. Live leaf
6444 windows will have buffer set, and combination windows will have
6445 vchild or hchild set. */
6450 Vwindow_list
= Qnil
;
6454 count_windows (window
)
6455 register struct window
*window
;
6457 register int count
= 1;
6458 if (!NILP (window
->next
))
6459 count
+= count_windows (XWINDOW (window
->next
));
6460 if (!NILP (window
->vchild
))
6461 count
+= count_windows (XWINDOW (window
->vchild
));
6462 if (!NILP (window
->hchild
))
6463 count
+= count_windows (XWINDOW (window
->hchild
));
6468 /* Fill vector FLAT with leaf windows under W, starting at index I.
6469 Value is last index + 1. */
6472 get_leaf_windows (w
, flat
, i
)
6474 struct window
**flat
;
6479 if (!NILP (w
->hchild
))
6480 i
= get_leaf_windows (XWINDOW (w
->hchild
), flat
, i
);
6481 else if (!NILP (w
->vchild
))
6482 i
= get_leaf_windows (XWINDOW (w
->vchild
), flat
, i
);
6486 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6493 /* Return a pointer to the glyph W's physical cursor is on. Value is
6494 null if W's current matrix is invalid, so that no meaningfull glyph
6498 get_phys_cursor_glyph (w
)
6501 struct glyph_row
*row
;
6502 struct glyph
*glyph
;
6504 if (w
->phys_cursor
.vpos
>= 0
6505 && w
->phys_cursor
.vpos
< w
->current_matrix
->nrows
6506 && (row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
),
6508 && row
->used
[TEXT_AREA
] > w
->phys_cursor
.hpos
)
6509 glyph
= row
->glyphs
[TEXT_AREA
] + w
->phys_cursor
.hpos
;
6518 save_window_save (window
, vector
, i
)
6520 struct Lisp_Vector
*vector
;
6523 register struct saved_window
*p
;
6524 register struct window
*w
;
6525 register Lisp_Object tem
;
6527 for (;!NILP (window
); window
= w
->next
)
6529 p
= SAVED_WINDOW_N (vector
, i
);
6530 w
= XWINDOW (window
);
6532 XSETFASTINT (w
->temslot
, i
); i
++;
6534 p
->buffer
= w
->buffer
;
6535 p
->left_col
= w
->left_col
;
6536 p
->top_line
= w
->top_line
;
6537 p
->total_cols
= w
->total_cols
;
6538 p
->total_lines
= w
->total_lines
;
6539 p
->hscroll
= w
->hscroll
;
6540 p
->min_hscroll
= w
->min_hscroll
;
6541 p
->display_table
= w
->display_table
;
6542 p
->orig_top_line
= w
->orig_top_line
;
6543 p
->orig_total_lines
= w
->orig_total_lines
;
6544 p
->left_margin_cols
= w
->left_margin_cols
;
6545 p
->right_margin_cols
= w
->right_margin_cols
;
6546 p
->left_fringe_width
= w
->left_fringe_width
;
6547 p
->right_fringe_width
= w
->right_fringe_width
;
6548 p
->fringes_outside_margins
= w
->fringes_outside_margins
;
6549 p
->scroll_bar_width
= w
->scroll_bar_width
;
6550 p
->vertical_scroll_bar_type
= w
->vertical_scroll_bar_type
;
6551 p
->dedicated
= w
->dedicated
;
6552 if (!NILP (w
->buffer
))
6554 /* Save w's value of point in the window configuration.
6555 If w is the selected window, then get the value of point
6556 from the buffer; pointm is garbage in the selected window. */
6557 if (EQ (window
, selected_window
))
6559 p
->pointm
= Fmake_marker ();
6560 set_marker_both (p
->pointm
, w
->buffer
,
6561 BUF_PT (XBUFFER (w
->buffer
)),
6562 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6565 p
->pointm
= Fcopy_marker (w
->pointm
, Qnil
);
6567 p
->start
= Fcopy_marker (w
->start
, Qnil
);
6568 p
->start_at_line_beg
= w
->start_at_line_beg
;
6570 tem
= XBUFFER (w
->buffer
)->mark
;
6571 p
->mark
= Fcopy_marker (tem
, Qnil
);
6578 p
->start_at_line_beg
= Qnil
;
6581 if (NILP (w
->parent
))
6584 p
->parent
= XWINDOW (w
->parent
)->temslot
;
6589 p
->prev
= XWINDOW (w
->prev
)->temslot
;
6591 if (!NILP (w
->vchild
))
6592 i
= save_window_save (w
->vchild
, vector
, i
);
6593 if (!NILP (w
->hchild
))
6594 i
= save_window_save (w
->hchild
, vector
, i
);
6600 DEFUN ("current-window-configuration", Fcurrent_window_configuration
,
6601 Scurrent_window_configuration
, 0, 1, 0,
6602 doc
: /* Return an object representing the current window configuration of FRAME.
6603 If FRAME is nil or omitted, use the selected frame.
6604 This describes the number of windows, their sizes and current buffers,
6605 and for each displayed buffer, where display starts, and the positions of
6606 point and mark. An exception is made for point in the current buffer:
6607 its value is -not- saved.
6608 This also records the currently selected frame, and FRAME's focus
6609 redirection (see `redirect-frame-focus'). */)
6613 register Lisp_Object tem
;
6614 register int n_windows
;
6615 register struct save_window_data
*data
;
6616 register struct Lisp_Vector
*vec
;
6621 frame
= selected_frame
;
6622 CHECK_LIVE_FRAME (frame
);
6625 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6626 vec
= allocate_other_vector (VECSIZE (struct save_window_data
));
6627 data
= (struct save_window_data
*)vec
;
6629 XSETFASTINT (data
->frame_cols
, FRAME_COLS (f
));
6630 XSETFASTINT (data
->frame_lines
, FRAME_LINES (f
));
6631 XSETFASTINT (data
->frame_menu_bar_lines
, FRAME_MENU_BAR_LINES (f
));
6632 XSETFASTINT (data
->frame_tool_bar_lines
, FRAME_TOOL_BAR_LINES (f
));
6633 data
->selected_frame
= selected_frame
;
6634 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
6635 XSETBUFFER (data
->current_buffer
, current_buffer
);
6636 data
->minibuf_scroll_window
= minibuf_level
> 0 ? Vminibuf_scroll_window
: Qnil
;
6637 data
->minibuf_selected_window
= minibuf_level
> 0 ? minibuf_selected_window
: Qnil
;
6638 data
->root_window
= FRAME_ROOT_WINDOW (f
);
6639 data
->focus_frame
= FRAME_FOCUS_FRAME (f
);
6640 XSETINT (data
->min_height
, window_min_height
);
6641 XSETINT (data
->min_width
, window_min_width
);
6642 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
6643 data
->saved_windows
= tem
;
6644 for (i
= 0; i
< n_windows
; i
++)
6645 XVECTOR (tem
)->contents
[i
]
6646 = Fmake_vector (make_number (VECSIZE (struct saved_window
)), Qnil
);
6647 save_window_save (FRAME_ROOT_WINDOW (f
), XVECTOR (tem
), 0);
6648 XSETWINDOW_CONFIGURATION (tem
, data
);
6652 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
6654 doc
: /* Execute BODY, preserving window sizes and contents.
6655 Return the value of the last form in BODY.
6656 Restore which buffer appears in which window, where display starts,
6657 and the value of point and mark for each window.
6658 Also restore the choice of selected window.
6659 Also restore which buffer is current.
6660 Does not restore the value of point in current buffer.
6661 usage: (save-window-excursion BODY...) */)
6665 register Lisp_Object val
;
6666 register int count
= SPECPDL_INDEX ();
6668 record_unwind_protect (Fset_window_configuration
,
6669 Fcurrent_window_configuration (Qnil
));
6670 val
= Fprogn (args
);
6671 return unbind_to (count
, val
);
6676 /***********************************************************************
6678 ***********************************************************************/
6684 Lisp_Object tail
= Qnil
;
6685 Lisp_Object result
= Qnil
;
6692 if (!NILP (w
->hchild
))
6693 wn
= Fcons (Qnil
, Fcons (Fwindow_edges (wn
),
6694 window_tree (XWINDOW (w
->hchild
))));
6695 else if (!NILP (w
->vchild
))
6696 wn
= Fcons (Qt
, Fcons (Fwindow_edges (wn
),
6697 window_tree (XWINDOW (w
->vchild
))));
6701 result
= tail
= Fcons (wn
, Qnil
);
6705 XSETCDR (tail
, Fcons (wn
, Qnil
));
6709 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6717 DEFUN ("window-tree", Fwindow_tree
, Swindow_tree
,
6719 doc
: /* Return the window tree for frame FRAME.
6721 The return value is a list of the form (ROOT MINI), where ROOT
6722 represents the window tree of the frame's root window, and MINI
6723 is the frame's minibuffer window.
6725 If the root window is not split, ROOT is the root window itself.
6726 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6727 horizontal split, and t for a vertical split, EDGES gives the combined
6728 size and position of the subwindows in the split, and the rest of the
6729 elements are the subwindows in the split. Each of the subwindows may
6730 again be a window or a list representing a window split, and so on.
6731 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6733 If FRAME is nil or omitted, return information on the currently
6741 frame
= selected_frame
;
6743 CHECK_FRAME (frame
);
6746 if (!FRAME_LIVE_P (f
))
6749 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6753 /***********************************************************************
6755 ***********************************************************************/
6757 DEFUN ("set-window-margins", Fset_window_margins
, Sset_window_margins
,
6759 doc
: /* Set width of marginal areas of window WINDOW.
6760 If WINDOW is nil, set margins of the currently selected window.
6761 Second arg LEFT-WIDTH specifies the number of character cells to
6762 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6763 does the same for the right marginal area. A nil width parameter
6764 means no margin. */)
6765 (window
, left_width
, right_width
)
6766 Lisp_Object window
, left_width
, right_width
;
6768 struct window
*w
= decode_window (window
);
6770 /* Translate negative or zero widths to nil.
6771 Margins that are too wide have to be checked elsewhere. */
6773 if (!NILP (left_width
))
6775 CHECK_NUMBER (left_width
);
6776 if (XINT (left_width
) <= 0)
6780 if (!NILP (right_width
))
6782 CHECK_NUMBER (right_width
);
6783 if (XINT (right_width
) <= 0)
6787 if (!EQ (w
->left_margin_cols
, left_width
)
6788 || !EQ (w
->right_margin_cols
, right_width
))
6790 w
->left_margin_cols
= left_width
;
6791 w
->right_margin_cols
= right_width
;
6793 adjust_window_margins (w
);
6795 ++windows_or_buffers_changed
;
6796 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6803 DEFUN ("window-margins", Fwindow_margins
, Swindow_margins
,
6805 doc
: /* Get width of marginal areas of window WINDOW.
6806 If WINDOW is omitted or nil, use the currently selected window.
6807 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6808 If a marginal area does not exist, its width will be returned
6813 struct window
*w
= decode_window (window
);
6814 return Fcons (w
->left_margin_cols
, w
->right_margin_cols
);
6819 /***********************************************************************
6821 ***********************************************************************/
6823 DEFUN ("set-window-fringes", Fset_window_fringes
, Sset_window_fringes
,
6825 doc
: /* Set the fringe widths of window WINDOW.
6826 If WINDOW is nil, set the fringe widths of the currently selected
6828 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6829 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6830 fringe width. If a fringe width arg is nil, that means to use the
6831 frame's default fringe width. Default fringe widths can be set with
6832 the command `set-fringe-style'.
6833 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6834 outside of the display margins. By default, fringes are drawn between
6835 display marginal areas and the text area. */)
6836 (window
, left_width
, right_width
, outside_margins
)
6837 Lisp_Object window
, left_width
, right_width
, outside_margins
;
6839 struct window
*w
= decode_window (window
);
6841 if (!NILP (left_width
))
6842 CHECK_NATNUM (left_width
);
6843 if (!NILP (right_width
))
6844 CHECK_NATNUM (right_width
);
6846 /* Do nothing on a tty. */
6847 if (FRAME_WINDOW_P (WINDOW_XFRAME (w
))
6848 && (!EQ (w
->left_fringe_width
, left_width
)
6849 || !EQ (w
->right_fringe_width
, right_width
)
6850 || !EQ (w
->fringes_outside_margins
, outside_margins
)))
6852 w
->left_fringe_width
= left_width
;
6853 w
->right_fringe_width
= right_width
;
6854 w
->fringes_outside_margins
= outside_margins
;
6856 adjust_window_margins (w
);
6858 clear_glyph_matrix (w
->current_matrix
);
6859 w
->window_end_valid
= Qnil
;
6861 ++windows_or_buffers_changed
;
6862 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6869 DEFUN ("window-fringes", Fwindow_fringes
, Swindow_fringes
,
6871 doc
: /* Get width of fringes of window WINDOW.
6872 If WINDOW is omitted or nil, use the currently selected window.
6873 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6877 struct window
*w
= decode_window (window
);
6879 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w
)),
6880 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w
)),
6881 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
6882 ? Qt
: Qnil
), Qnil
)));
6887 /***********************************************************************
6889 ***********************************************************************/
6891 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars
, Sset_window_scroll_bars
,
6893 doc
: /* Set width and type of scroll bars of window WINDOW.
6894 If window is nil, set scroll bars of the currently selected window.
6895 Second parameter WIDTH specifies the pixel width for the scroll bar;
6896 this is automatically adjusted to a multiple of the frame column width.
6897 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6898 bar: left, right, or nil.
6899 If WIDTH is nil, use the frame's scroll-bar width.
6900 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6901 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6902 (window
, width
, vertical_type
, horizontal_type
)
6903 Lisp_Object window
, width
, vertical_type
, horizontal_type
;
6905 struct window
*w
= decode_window (window
);
6909 CHECK_NATNUM (width
);
6911 if (XINT (width
) == 0)
6912 vertical_type
= Qnil
;
6915 if (!(NILP (vertical_type
)
6916 || EQ (vertical_type
, Qleft
)
6917 || EQ (vertical_type
, Qright
)
6918 || EQ (vertical_type
, Qt
)))
6919 error ("Invalid type of vertical scroll bar");
6921 if (!EQ (w
->scroll_bar_width
, width
)
6922 || !EQ (w
->vertical_scroll_bar_type
, vertical_type
))
6924 w
->scroll_bar_width
= width
;
6925 w
->vertical_scroll_bar_type
= vertical_type
;
6927 adjust_window_margins (w
);
6929 clear_glyph_matrix (w
->current_matrix
);
6930 w
->window_end_valid
= Qnil
;
6932 ++windows_or_buffers_changed
;
6933 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6940 DEFUN ("window-scroll-bars", Fwindow_scroll_bars
, Swindow_scroll_bars
,
6942 doc
: /* Get width and type of scroll bars of window WINDOW.
6943 If WINDOW is omitted or nil, use the currently selected window.
6944 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6945 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6950 struct window
*w
= decode_window (window
);
6951 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
)
6952 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
)
6953 : WINDOW_SCROLL_BAR_AREA_WIDTH (w
))),
6954 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w
)),
6955 Fcons (w
->vertical_scroll_bar_type
,
6956 Fcons (Qnil
, Qnil
))));
6961 /***********************************************************************
6963 ***********************************************************************/
6965 DEFUN ("window-vscroll", Fwindow_vscroll
, Swindow_vscroll
, 0, 2, 0,
6966 doc
: /* Return the amount by which WINDOW is scrolled vertically.
6967 Use the selected window if WINDOW is nil or omitted.
6968 Normally, value is a multiple of the canonical character height of WINDOW;
6969 optional second arg PIXELS-P means value is measured in pixels. */)
6971 Lisp_Object window
, pixels_p
;
6978 window
= selected_window
;
6980 CHECK_WINDOW (window
);
6981 w
= XWINDOW (window
);
6982 f
= XFRAME (w
->frame
);
6984 if (FRAME_WINDOW_P (f
))
6985 result
= (NILP (pixels_p
)
6986 ? FRAME_CANON_Y_FROM_PIXEL_Y (f
, -w
->vscroll
)
6987 : make_number (-w
->vscroll
));
6989 result
= make_number (0);
6994 DEFUN ("set-window-vscroll", Fset_window_vscroll
, Sset_window_vscroll
,
6996 doc
: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6997 WINDOW nil means use the selected window. Normally, VSCROLL is a
6998 non-negative multiple of the canonical character height of WINDOW;
6999 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
7000 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
7001 corresponds to an integral number of pixels. The return value is the
7002 result of this rounding.
7003 If PIXELS-P is non-nil, the return value is VSCROLL. */)
7004 (window
, vscroll
, pixels_p
)
7005 Lisp_Object window
, vscroll
, pixels_p
;
7011 window
= selected_window
;
7013 CHECK_WINDOW (window
);
7014 CHECK_NUMBER_OR_FLOAT (vscroll
);
7016 w
= XWINDOW (window
);
7017 f
= XFRAME (w
->frame
);
7019 if (FRAME_WINDOW_P (f
))
7021 int old_dy
= w
->vscroll
;
7023 w
->vscroll
= - (NILP (pixels_p
)
7024 ? FRAME_LINE_HEIGHT (f
) * XFLOATINT (vscroll
)
7025 : XFLOATINT (vscroll
));
7026 w
->vscroll
= min (w
->vscroll
, 0);
7028 if (w
->vscroll
!= old_dy
)
7030 /* Adjust glyph matrix of the frame if the virtual display
7031 area becomes larger than before. */
7032 if (w
->vscroll
< 0 && w
->vscroll
< old_dy
)
7035 /* Prevent redisplay shortcuts. */
7036 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
7040 return Fwindow_vscroll (window
, pixels_p
);
7044 /* Call FN for all leaf windows on frame F. FN is called with the
7045 first argument being a pointer to the leaf window, and with
7046 additional argument USER_DATA. Stops when FN returns 0. */
7049 foreach_window (f
, fn
, user_data
)
7051 int (* fn
) P_ ((struct window
*, void *));
7054 /* Fdelete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
7055 if (WINDOWP (FRAME_ROOT_WINDOW (f
)))
7056 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f
)), fn
, user_data
);
7060 /* Helper function for foreach_window. Call FN for all leaf windows
7061 reachable from W. FN is called with the first argument being a
7062 pointer to the leaf window, and with additional argument USER_DATA.
7063 Stop when FN returns 0. Value is 0 if stopped by FN. */
7066 foreach_window_1 (w
, fn
, user_data
)
7068 int (* fn
) P_ ((struct window
*, void *));
7073 for (cont
= 1; w
&& cont
;)
7075 if (!NILP (w
->hchild
))
7076 cont
= foreach_window_1 (XWINDOW (w
->hchild
), fn
, user_data
);
7077 else if (!NILP (w
->vchild
))
7078 cont
= foreach_window_1 (XWINDOW (w
->vchild
), fn
, user_data
);
7080 cont
= fn (w
, user_data
);
7082 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
7089 /* Freeze or unfreeze the window start of W unless it is a
7090 mini-window or the selected window. FREEZE_P non-null means freeze
7091 the window start. */
7094 freeze_window_start (w
, freeze_p
)
7098 if (w
== XWINDOW (selected_window
)
7099 || MINI_WINDOW_P (w
)
7100 || (MINI_WINDOW_P (XWINDOW (selected_window
))
7101 && ! NILP (Vminibuf_scroll_window
)
7102 && w
== XWINDOW (Vminibuf_scroll_window
)))
7105 w
->frozen_window_start_p
= freeze_p
!= NULL
;
7110 /* Freeze or unfreeze the window starts of all leaf windows on frame
7111 F, except the selected window and a mini-window. FREEZE_P non-zero
7112 means freeze the window start. */
7115 freeze_window_starts (f
, freeze_p
)
7119 foreach_window (f
, freeze_window_start
, (void *) (freeze_p
? f
: 0));
7123 /***********************************************************************
7125 ***********************************************************************/
7127 /* Return 1 if window configurations C1 and C2
7128 describe the same state of affairs. This is used by Fequal. */
7131 compare_window_configurations (c1
, c2
, ignore_positions
)
7133 int ignore_positions
;
7135 register struct save_window_data
*d1
, *d2
;
7136 struct Lisp_Vector
*sw1
, *sw2
;
7139 CHECK_WINDOW_CONFIGURATION (c1
);
7140 CHECK_WINDOW_CONFIGURATION (c2
);
7142 d1
= (struct save_window_data
*) XVECTOR (c1
);
7143 d2
= (struct save_window_data
*) XVECTOR (c2
);
7144 sw1
= XVECTOR (d1
->saved_windows
);
7145 sw2
= XVECTOR (d2
->saved_windows
);
7147 if (! EQ (d1
->frame_cols
, d2
->frame_cols
))
7149 if (! EQ (d1
->frame_lines
, d2
->frame_lines
))
7151 if (! EQ (d1
->frame_menu_bar_lines
, d2
->frame_menu_bar_lines
))
7153 if (! EQ (d1
->selected_frame
, d2
->selected_frame
))
7155 /* Don't compare the current_window field directly.
7156 Instead see w1_is_current and w2_is_current, below. */
7157 if (! EQ (d1
->current_buffer
, d2
->current_buffer
))
7159 if (! ignore_positions
)
7161 if (! EQ (d1
->minibuf_scroll_window
, d2
->minibuf_scroll_window
))
7163 if (! EQ (d1
->minibuf_selected_window
, d2
->minibuf_selected_window
))
7166 /* Don't compare the root_window field.
7167 We don't require the two configurations
7168 to use the same window object,
7169 and the two root windows must be equivalent
7170 if everything else compares equal. */
7171 if (! EQ (d1
->focus_frame
, d2
->focus_frame
))
7173 if (! EQ (d1
->min_width
, d2
->min_width
))
7175 if (! EQ (d1
->min_height
, d2
->min_height
))
7178 /* Verify that the two confis have the same number of windows. */
7179 if (sw1
->size
!= sw2
->size
)
7182 for (i
= 0; i
< sw1
->size
; i
++)
7184 struct saved_window
*p1
, *p2
;
7185 int w1_is_current
, w2_is_current
;
7187 p1
= SAVED_WINDOW_N (sw1
, i
);
7188 p2
= SAVED_WINDOW_N (sw2
, i
);
7190 /* Verify that the current windows in the two
7191 configurations correspond to each other. */
7192 w1_is_current
= EQ (d1
->current_window
, p1
->window
);
7193 w2_is_current
= EQ (d2
->current_window
, p2
->window
);
7195 if (w1_is_current
!= w2_is_current
)
7198 /* Verify that the corresponding windows do match. */
7199 if (! EQ (p1
->buffer
, p2
->buffer
))
7201 if (! EQ (p1
->left_col
, p2
->left_col
))
7203 if (! EQ (p1
->top_line
, p2
->top_line
))
7205 if (! EQ (p1
->total_cols
, p2
->total_cols
))
7207 if (! EQ (p1
->total_lines
, p2
->total_lines
))
7209 if (! EQ (p1
->display_table
, p2
->display_table
))
7211 if (! EQ (p1
->parent
, p2
->parent
))
7213 if (! EQ (p1
->prev
, p2
->prev
))
7215 if (! ignore_positions
)
7217 if (! EQ (p1
->hscroll
, p2
->hscroll
))
7219 if (!EQ (p1
->min_hscroll
, p2
->min_hscroll
))
7221 if (! EQ (p1
->start_at_line_beg
, p2
->start_at_line_beg
))
7223 if (NILP (Fequal (p1
->start
, p2
->start
)))
7225 if (NILP (Fequal (p1
->pointm
, p2
->pointm
)))
7227 if (NILP (Fequal (p1
->mark
, p2
->mark
)))
7230 if (! EQ (p1
->left_margin_cols
, p2
->left_margin_cols
))
7232 if (! EQ (p1
->right_margin_cols
, p2
->right_margin_cols
))
7234 if (! EQ (p1
->left_fringe_width
, p2
->left_fringe_width
))
7236 if (! EQ (p1
->right_fringe_width
, p2
->right_fringe_width
))
7238 if (! EQ (p1
->fringes_outside_margins
, p2
->fringes_outside_margins
))
7240 if (! EQ (p1
->scroll_bar_width
, p2
->scroll_bar_width
))
7242 if (! EQ (p1
->vertical_scroll_bar_type
, p2
->vertical_scroll_bar_type
))
7249 DEFUN ("compare-window-configurations", Fcompare_window_configurations
,
7250 Scompare_window_configurations
, 2, 2, 0,
7251 doc
: /* Compare two window configurations as regards the structure of windows.
7252 This function ignores details such as the values of point and mark
7253 and scrolling positions. */)
7257 if (compare_window_configurations (x
, y
, 1))
7265 struct frame
*f
= make_initial_frame ();
7266 XSETFRAME (selected_frame
, f
);
7267 Vterminal_frame
= selected_frame
;
7268 minibuf_window
= f
->minibuffer_window
;
7269 selected_window
= f
->selected_window
;
7270 last_nonminibuf_frame
= f
;
7272 window_initialized
= 1;
7278 Vwindow_list
= Qnil
;
7284 Qscroll_up
= intern ("scroll-up");
7285 staticpro (&Qscroll_up
);
7287 Qscroll_down
= intern ("scroll-down");
7288 staticpro (&Qscroll_down
);
7290 Qwindow_size_fixed
= intern ("window-size-fixed");
7291 staticpro (&Qwindow_size_fixed
);
7292 Fset (Qwindow_size_fixed
, Qnil
);
7294 staticpro (&Qwindow_configuration_change_hook
);
7295 Qwindow_configuration_change_hook
7296 = intern ("window-configuration-change-hook");
7298 Qwindowp
= intern ("windowp");
7299 staticpro (&Qwindowp
);
7301 Qwindow_configuration_p
= intern ("window-configuration-p");
7302 staticpro (&Qwindow_configuration_p
);
7304 Qwindow_live_p
= intern ("window-live-p");
7305 staticpro (&Qwindow_live_p
);
7307 Qtemp_buffer_show_hook
= intern ("temp-buffer-show-hook");
7308 staticpro (&Qtemp_buffer_show_hook
);
7310 staticpro (&Vwindow_list
);
7312 minibuf_selected_window
= Qnil
;
7313 staticpro (&minibuf_selected_window
);
7315 window_scroll_pixel_based_preserve_y
= -1;
7317 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
7318 doc
: /* Non-nil means call as function to display a help buffer.
7319 The function is called with one argument, the buffer to be displayed.
7320 Used by `with-output-to-temp-buffer'.
7321 If this function is used, then it must do the entire job of showing
7322 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7323 Vtemp_buffer_show_function
= Qnil
;
7325 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
7326 doc
: /* If non-nil, function to call to handle `display-buffer'.
7327 It will receive two args, the buffer and a flag which if non-nil means
7328 that the currently selected window is not acceptable.
7329 It should choose or create a window, display the specified buffer in it,
7330 and return the window.
7331 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
7332 work using this function. */);
7333 Vdisplay_buffer_function
= Qnil
;
7335 DEFVAR_LISP ("even-window-heights", &Veven_window_heights
,
7336 doc
: /* *If non-nil, `display-buffer' should even the window heights.
7337 If nil, `display-buffer' will leave the window configuration alone. */);
7338 Veven_window_heights
= Qt
;
7340 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
7341 doc
: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7342 Vminibuf_scroll_window
= Qnil
;
7344 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows
,
7345 doc
: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7346 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7347 is displayed in the `mode-line' face. */);
7348 mode_line_in_non_selected_windows
= 1;
7350 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
7351 doc
: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7352 Vother_window_scroll_buffer
= Qnil
;
7354 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames
,
7355 doc
: /* *Non-nil means `display-buffer' should make a separate frame. */);
7358 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p
,
7359 doc
: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7360 auto_window_vscroll_p
= 1;
7362 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames
,
7363 doc
: /* *Non-nil means `display-buffer' should reuse frames.
7364 If the buffer in question is already displayed in a frame, raise that frame. */);
7365 display_buffer_reuse_frames
= 0;
7367 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function
,
7368 doc
: /* Function to call to handle automatic new frame creation.
7369 It is called with no arguments and should return a newly created frame.
7371 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
7372 where `pop-up-frame-alist' would hold the default frame parameters. */);
7373 Vpop_up_frame_function
= Qnil
;
7375 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names
,
7376 doc
: /* *List of buffer names that should have their own special frames.
7377 Displaying a buffer with `display-buffer' or `pop-to-buffer',
7378 if its name is in this list, makes a special frame for it
7379 using `special-display-function'. See also `special-display-regexps'.
7381 An element of the list can be a list instead of just a string.
7382 There are two ways to use a list as an element:
7383 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
7384 In the first case, the FRAME-PARAMETERS are pairs of the form
7385 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7386 In the second case, FUNCTION is called with BUFFER as the first argument,
7387 followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
7388 All this is done by the function found in `special-display-function'.
7390 If the specified frame parameters include (same-buffer . t), the
7391 buffer is displayed in the currently selected window. Otherwise, if
7392 they include (same-frame . t), the buffer is displayed in a new window
7393 in the currently selected frame.
7395 If this variable appears \"not to work\", because you add a name to it
7396 but that buffer still appears in the selected window, look at the
7397 values of `same-window-buffer-names' and `same-window-regexps'.
7398 Those variables take precedence over this one. */);
7399 Vspecial_display_buffer_names
= Qnil
;
7401 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps
,
7402 doc
: /* *List of regexps saying which buffers should have their own special frames.
7403 When displaying a buffer with `display-buffer' or `pop-to-buffer',
7404 if any regexp in this list matches the buffer name, it makes a
7405 special frame for the buffer by calling `special-display-function'.
7407 An element of the list can be a list instead of just a string.
7408 There are two ways to use a list as an element:
7409 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
7410 In the first case, the FRAME-PARAMETERS are pairs of the form
7411 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7412 In the second case, FUNCTION is called with BUFFER as the first argument,
7413 followed by the OTHER-ARGS--it can display the buffer in any way it likes.
7414 All this is done by the function found in `special-display-function'.
7416 If the specified frame parameters include (same-buffer . t), the
7417 buffer is displayed in the currently selected window. Otherwise, if
7418 they include (same-frame . t), the buffer is displayed in a new window
7419 in the currently selected frame.
7421 If this variable appears \"not to work\", because you add a regexp to it
7422 but the matching buffers still appear in the selected window, look at the
7423 values of `same-window-buffer-names' and `same-window-regexps'.
7424 Those variables take precedence over this one. */);
7425 Vspecial_display_regexps
= Qnil
;
7427 DEFVAR_LISP ("special-display-function", &Vspecial_display_function
,
7428 doc
: /* Function to call to make a new frame for a special buffer.
7429 It is called with two arguments, the buffer and optional buffer specific
7430 data, and should return a window displaying that buffer.
7431 The default value normally makes a separate frame for the buffer,
7432 using `special-display-frame-alist' to specify the frame parameters.
7433 But if the buffer specific data includes (same-buffer . t) then the
7434 buffer is displayed in the current selected window.
7435 Otherwise if it includes (same-frame . t) then the buffer is displayed in
7436 a new window in the currently selected frame.
7438 A buffer is special if it is listed in `special-display-buffer-names'
7439 or matches a regexp in `special-display-regexps'. */);
7440 Vspecial_display_function
= Qnil
;
7442 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names
,
7443 doc
: /* *List of buffer names that should appear in the selected window.
7444 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
7445 switches to it in the selected window, rather than making it appear
7446 in some other window.
7448 An element of the list can be a cons cell instead of just a string.
7449 Then the car must be a string, which specifies the buffer name.
7450 This is for compatibility with `special-display-buffer-names';
7451 the cdr of the cons cell is ignored.
7453 See also `same-window-regexps'. */);
7454 Vsame_window_buffer_names
= Qnil
;
7456 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps
,
7457 doc
: /* *List of regexps saying which buffers should appear in the selected window.
7458 If a buffer name matches one of these regexps, then displaying it
7459 using `display-buffer' or `pop-to-buffer' switches to it
7460 in the selected window, rather than making it appear in some other window.
7462 An element of the list can be a cons cell instead of just a string.
7463 Then the car must be a string, which specifies the buffer name.
7464 This is for compatibility with `special-display-buffer-names';
7465 the cdr of the cons cell is ignored.
7467 See also `same-window-buffer-names'. */);
7468 Vsame_window_regexps
= Qnil
;
7470 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
7471 doc
: /* *Non-nil means display-buffer should make new windows. */);
7474 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
7475 doc
: /* *Number of lines of continuity when scrolling by screenfuls. */);
7476 next_screen_context_lines
= 2;
7478 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
7479 doc
: /* *A window must be at least this tall to be eligible for splitting
7480 by `display-buffer'. The value is in line units.
7481 If there is only one window, it is split regardless of this value. */);
7482 split_height_threshold
= 500;
7484 DEFVAR_INT ("window-min-height", &window_min_height
,
7485 doc
: /* *Delete any window less than this tall (including its mode line).
7486 The value is in line units. */);
7487 window_min_height
= 4;
7489 DEFVAR_INT ("window-min-width", &window_min_width
,
7490 doc
: /* *Delete any window less than this wide (measured in characters). */);
7491 window_min_width
= 10;
7493 DEFVAR_LISP ("scroll-preserve-screen-position",
7494 &Vscroll_preserve_screen_position
,
7495 doc
: /* *Controls if scroll commands move point to keep its screen line unchanged.
7496 A value of nil means point does not keep its screen position except
7497 at the scroll margin or window boundary respectively.
7498 A value of t means point keeps its screen position if the scroll
7499 command moved it vertically out of the window, e.g. when scrolling
7501 Any other value means point always keeps its screen position. */);
7502 Vscroll_preserve_screen_position
= Qnil
;
7504 DEFVAR_LISP ("window-configuration-change-hook",
7505 &Vwindow_configuration_change_hook
,
7506 doc
: /* Functions to call when window configuration changes.
7507 The selected frame is the one whose configuration has changed. */);
7508 Vwindow_configuration_change_hook
= Qnil
;
7510 defsubr (&Sselected_window
);
7511 defsubr (&Sminibuffer_window
);
7512 defsubr (&Swindow_minibuffer_p
);
7513 defsubr (&Swindowp
);
7514 defsubr (&Swindow_live_p
);
7515 defsubr (&Spos_visible_in_window_p
);
7516 defsubr (&Swindow_line_height
);
7517 defsubr (&Swindow_buffer
);
7518 defsubr (&Swindow_height
);
7519 defsubr (&Swindow_width
);
7520 defsubr (&Swindow_hscroll
);
7521 defsubr (&Sset_window_hscroll
);
7522 defsubr (&Swindow_redisplay_end_trigger
);
7523 defsubr (&Sset_window_redisplay_end_trigger
);
7524 defsubr (&Swindow_edges
);
7525 defsubr (&Swindow_pixel_edges
);
7526 defsubr (&Swindow_inside_edges
);
7527 defsubr (&Swindow_inside_pixel_edges
);
7528 defsubr (&Scoordinates_in_window_p
);
7529 defsubr (&Swindow_at
);
7530 defsubr (&Swindow_point
);
7531 defsubr (&Swindow_start
);
7532 defsubr (&Swindow_end
);
7533 defsubr (&Sset_window_point
);
7534 defsubr (&Sset_window_start
);
7535 defsubr (&Swindow_dedicated_p
);
7536 defsubr (&Sset_window_dedicated_p
);
7537 defsubr (&Swindow_display_table
);
7538 defsubr (&Sset_window_display_table
);
7539 defsubr (&Snext_window
);
7540 defsubr (&Sprevious_window
);
7541 defsubr (&Sother_window
);
7542 defsubr (&Sget_lru_window
);
7543 defsubr (&Sget_largest_window
);
7544 defsubr (&Sget_buffer_window
);
7545 defsubr (&Sdelete_other_windows
);
7546 defsubr (&Sdelete_windows_on
);
7547 defsubr (&Sreplace_buffer_in_windows
);
7548 defsubr (&Sdelete_window
);
7549 defsubr (&Sset_window_buffer
);
7550 defsubr (&Sselect_window
);
7551 defsubr (&Sspecial_display_p
);
7552 defsubr (&Ssame_window_p
);
7553 defsubr (&Sdisplay_buffer
);
7554 defsubr (&Sforce_window_update
);
7555 defsubr (&Ssplit_window
);
7556 defsubr (&Senlarge_window
);
7557 defsubr (&Sshrink_window
);
7558 defsubr (&Sadjust_window_trailing_edge
);
7559 defsubr (&Sscroll_up
);
7560 defsubr (&Sscroll_down
);
7561 defsubr (&Sscroll_left
);
7562 defsubr (&Sscroll_right
);
7563 defsubr (&Sother_window_for_scrolling
);
7564 defsubr (&Sscroll_other_window
);
7565 defsubr (&Sminibuffer_selected_window
);
7566 defsubr (&Srecenter
);
7567 defsubr (&Swindow_text_height
);
7568 defsubr (&Smove_to_window_line
);
7569 defsubr (&Swindow_configuration_p
);
7570 defsubr (&Swindow_configuration_frame
);
7571 defsubr (&Sset_window_configuration
);
7572 defsubr (&Scurrent_window_configuration
);
7573 defsubr (&Ssave_window_excursion
);
7574 defsubr (&Swindow_tree
);
7575 defsubr (&Sset_window_margins
);
7576 defsubr (&Swindow_margins
);
7577 defsubr (&Sset_window_fringes
);
7578 defsubr (&Swindow_fringes
);
7579 defsubr (&Sset_window_scroll_bars
);
7580 defsubr (&Swindow_scroll_bars
);
7581 defsubr (&Swindow_vscroll
);
7582 defsubr (&Sset_window_vscroll
);
7583 defsubr (&Scompare_window_configurations
);
7584 defsubr (&Swindow_list
);
7590 initial_define_key (control_x_map
, '1', "delete-other-windows");
7591 initial_define_key (control_x_map
, '2', "split-window");
7592 initial_define_key (control_x_map
, '0', "delete-window");
7593 initial_define_key (control_x_map
, 'o', "other-window");
7594 initial_define_key (control_x_map
, '^', "enlarge-window");
7595 initial_define_key (control_x_map
, '<', "scroll-left");
7596 initial_define_key (control_x_map
, '>', "scroll-right");
7598 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
7599 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
7600 initial_define_key (meta_map
, 'v', "scroll-down");
7602 initial_define_key (global_map
, Ctl('L'), "recenter");
7603 initial_define_key (meta_map
, 'r', "move-to-window-line");
7606 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7607 (do not change this comment) */