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, 2008
5 Free Software Foundation, Inc.
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
35 #include "dispextern.h"
36 #include "blockinput.h"
37 #include "intervals.h"
38 #include "termhooks.h" /* For FRAME_TERMINAL. */
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, int));
67 static int window_min_size_2
P_ ((struct window
*, int, int));
68 static int window_min_size
P_ ((struct window
*, int, 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 /* How to split windows (horizontally/vertically/hybrid). */
197 Lisp_Object Vsplit_window_preferred_function
;
199 /* Number of lines of continuity in scrolling by screenfuls. */
201 EMACS_INT next_screen_context_lines
;
203 /* Incremented for each window created. */
205 static int sequence_number
;
207 /* Nonzero after init_window_once has finished. */
209 static int window_initialized
;
211 /* Hook to run when window config changes. */
213 static Lisp_Object Qwindow_configuration_change_hook
;
214 static Lisp_Object Vwindow_configuration_change_hook
;
216 /* Non-nil means scroll commands try to put point
217 at the same screen height as previously. */
219 Lisp_Object Vscroll_preserve_screen_position
;
221 /* Incremented by 1 whenever a window is deleted. */
223 int window_deletion_count
;
225 /* Used by the function window_scroll_pixel_based */
227 static int window_scroll_pixel_based_preserve_x
;
228 static int window_scroll_pixel_based_preserve_y
;
230 /* Same for window_scroll_line_based. */
232 static int window_scroll_preserve_hpos
;
233 static int window_scroll_preserve_vpos
;
235 #if 0 /* This isn't used anywhere. */
236 /* Nonzero means we can split a frame even if it is "unsplittable". */
237 static int inhibit_frame_unsplittable
;
240 extern EMACS_INT scroll_margin
;
242 extern Lisp_Object Qwindow_scroll_functions
, Vwindow_scroll_functions
;
244 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
245 doc
: /* Returns t if OBJECT is a window. */)
249 return WINDOWP (object
) ? Qt
: Qnil
;
252 DEFUN ("window-live-p", Fwindow_live_p
, Swindow_live_p
, 1, 1, 0,
253 doc
: /* Returns t if OBJECT is a window which is currently visible. */)
257 return WINDOW_LIVE_P (object
) ? Qt
: Qnil
;
264 register struct window
*p
;
266 p
= allocate_window ();
268 XSETFASTINT (p
->sequence_number
, sequence_number
);
269 XSETFASTINT (p
->left_col
, 0);
270 XSETFASTINT (p
->top_line
, 0);
271 XSETFASTINT (p
->total_lines
, 0);
272 XSETFASTINT (p
->total_cols
, 0);
273 XSETFASTINT (p
->hscroll
, 0);
274 XSETFASTINT (p
->min_hscroll
, 0);
275 p
->orig_top_line
= p
->orig_total_lines
= Qnil
;
276 p
->start
= Fmake_marker ();
277 p
->pointm
= Fmake_marker ();
278 XSETFASTINT (p
->use_time
, 0);
280 p
->display_table
= Qnil
;
282 p
->window_parameters
= Qnil
;
283 p
->pseudo_window_p
= 0;
284 bzero (&p
->cursor
, sizeof (p
->cursor
));
285 bzero (&p
->last_cursor
, sizeof (p
->last_cursor
));
286 bzero (&p
->phys_cursor
, sizeof (p
->phys_cursor
));
287 p
->desired_matrix
= p
->current_matrix
= 0;
288 p
->nrows_scale_factor
= p
->ncols_scale_factor
= 1;
289 p
->phys_cursor_type
= -1;
290 p
->phys_cursor_width
= -1;
291 p
->must_be_updated_p
= 0;
292 XSETFASTINT (p
->window_end_vpos
, 0);
293 XSETFASTINT (p
->window_end_pos
, 0);
294 p
->window_end_valid
= Qnil
;
297 XSETFASTINT (p
->last_point
, 0);
298 p
->frozen_window_start_p
= 0;
299 p
->last_cursor_off_p
= p
->cursor_off_p
= 0;
300 p
->left_margin_cols
= Qnil
;
301 p
->right_margin_cols
= Qnil
;
302 p
->left_fringe_width
= Qnil
;
303 p
->right_fringe_width
= Qnil
;
304 p
->fringes_outside_margins
= Qnil
;
305 p
->scroll_bar_width
= Qnil
;
306 p
->vertical_scroll_bar_type
= Qt
;
307 p
->resize_proportionally
= Qnil
;
313 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
314 doc
: /* Return the window that the cursor now appears in and commands apply to. */)
317 return selected_window
;
320 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 1, 0,
321 doc
: /* Return the window used now for minibuffers.
322 If the optional argument FRAME is specified, return the minibuffer window
323 used by that frame. */)
328 frame
= selected_frame
;
329 CHECK_LIVE_FRAME (frame
);
330 return FRAME_MINIBUF_WINDOW (XFRAME (frame
));
333 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 0, 1, 0,
334 doc
: /* Returns non-nil if WINDOW is a minibuffer window.
335 WINDOW defaults to the selected window. */)
339 struct window
*w
= decode_window (window
);
340 return MINI_WINDOW_P (w
) ? Qt
: Qnil
;
344 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
345 Spos_visible_in_window_p
, 0, 3, 0,
346 doc
: /* Return non-nil if position POS is currently on the frame in WINDOW.
347 Return nil if that position is scrolled vertically out of view.
348 If a character is only partially visible, nil is returned, unless the
349 optional argument PARTIALLY is non-nil.
350 If POS is only out of view because of horizontal scrolling, return non-nil.
351 If POS is t, it specifies the position of the last visible glyph in WINDOW.
352 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
354 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
355 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
356 where X and Y are the pixel coordinates relative to the top left corner
357 of the window. The remaining elements are omitted if the character after
358 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
359 off-window at the top and bottom of the row, ROWH is the height of the
360 display row, and VPOS is the row number (0-based) containing POS. */)
361 (pos
, window
, partially
)
362 Lisp_Object pos
, window
, partially
;
364 register struct window
*w
;
366 register struct buffer
*buf
;
368 Lisp_Object in_window
= Qnil
;
369 int rtop
, rbot
, rowh
, vpos
, fully_p
= 1;
372 w
= decode_window (window
);
373 buf
= XBUFFER (w
->buffer
);
374 SET_TEXT_POS_FROM_MARKER (top
, w
->start
);
378 else if (!NILP (pos
))
380 CHECK_NUMBER_COERCE_MARKER (pos
);
383 else if (w
== XWINDOW (selected_window
))
386 posint
= XMARKER (w
->pointm
)->charpos
;
388 /* If position is above window start or outside buffer boundaries,
389 or if window start is out of range, position is not visible. */
391 || (posint
>= CHARPOS (top
) && posint
<= BUF_ZV (buf
)))
392 && CHARPOS (top
) >= BUF_BEGV (buf
)
393 && CHARPOS (top
) <= BUF_ZV (buf
)
394 && pos_visible_p (w
, posint
, &x
, &y
, &rtop
, &rbot
, &rowh
, &vpos
)
395 && (fully_p
= !rtop
&& !rbot
, (!NILP (partially
) || fully_p
)))
398 if (!NILP (in_window
) && !NILP (partially
))
400 Lisp_Object part
= Qnil
;
402 part
= list4 (make_number (rtop
), make_number (rbot
),
403 make_number (rowh
), make_number (vpos
));
404 in_window
= Fcons (make_number (x
),
405 Fcons (make_number (y
), part
));
411 DEFUN ("window-line-height", Fwindow_line_height
,
412 Swindow_line_height
, 0, 2, 0,
413 doc
: /* Return height in pixels of text line LINE in window WINDOW.
414 If WINDOW is nil or omitted, use selected window.
416 Return height of current line if LINE is omitted or nil. Return height of
417 header or mode line if LINE is `header-line' and `mode-line'.
418 Otherwise, LINE is a text line number starting from 0. A negative number
419 counts from the end of the window.
421 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
422 in pixels of the visible part of the line, VPOS and YPOS are the
423 vertical position in lines and pixels of the line, relative to the top
424 of the first text line, and OFFBOT is the number of off-window pixels at
425 the bottom of the text line. If there are off-window pixels at the top
426 of the (first) text line, YPOS is negative.
428 Return nil if window display is not up-to-date. In that case, use
429 `pos-visible-in-window-p' to obtain the information. */)
431 Lisp_Object line
, window
;
433 register struct window
*w
;
434 register struct buffer
*b
;
435 struct glyph_row
*row
, *end_row
;
436 int max_y
, crop
, i
, n
;
438 w
= decode_window (window
);
441 || w
->pseudo_window_p
)
444 CHECK_BUFFER (w
->buffer
);
445 b
= XBUFFER (w
->buffer
);
447 /* Fail if current matrix is not up-to-date. */
448 if (NILP (w
->window_end_valid
)
449 || current_buffer
->clip_changed
450 || current_buffer
->prevent_redisplay_optimizations_p
451 || XFASTINT (w
->last_modified
) < BUF_MODIFF (b
)
452 || XFASTINT (w
->last_overlay_modified
) < BUF_OVERLAY_MODIFF (b
))
458 if (i
< 0 || i
>= w
->current_matrix
->nrows
459 || (row
= MATRIX_ROW (w
->current_matrix
, i
), !row
->enabled_p
))
461 max_y
= window_text_bottom_y (w
);
465 if (EQ (line
, Qheader_line
))
467 if (!WINDOW_WANTS_HEADER_LINE_P (w
))
469 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
472 return list4 (make_number (row
->height
),
473 make_number (0), make_number (0),
477 if (EQ (line
, Qmode_line
))
479 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
482 return list4 (make_number (row
->height
),
483 make_number (0), /* not accurate */
484 make_number (WINDOW_HEADER_LINE_HEIGHT (w
)
485 + window_text_bottom_y (w
)),
492 row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
493 end_row
= MATRIX_BOTTOM_TEXT_ROW (w
->current_matrix
, w
);
494 max_y
= window_text_bottom_y (w
);
497 while ((n
< 0 || i
< n
)
498 && row
<= end_row
&& row
->enabled_p
499 && row
->y
+ row
->height
< max_y
)
502 if (row
> end_row
|| !row
->enabled_p
)
514 crop
= max (0, (row
->y
+ row
->height
) - max_y
);
515 return list4 (make_number (row
->height
+ min (0, row
->y
) - crop
),
517 make_number (row
->y
),
523 static struct window
*
524 decode_window (window
)
525 register Lisp_Object window
;
528 return XWINDOW (selected_window
);
530 CHECK_LIVE_WINDOW (window
);
531 return XWINDOW (window
);
534 static struct window
*
535 decode_any_window (window
)
536 register Lisp_Object window
;
539 return XWINDOW (selected_window
);
541 CHECK_WINDOW (window
);
542 return XWINDOW (window
);
545 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
546 doc
: /* Return the buffer that WINDOW is displaying.
547 WINDOW defaults to the selected window. */)
551 return decode_window (window
)->buffer
;
554 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
555 doc
: /* Return the number of lines in WINDOW (including its mode line).
556 WINDOW defaults to the selected window. */)
560 return decode_any_window (window
)->total_lines
;
563 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
564 doc
: /* Return the number of display columns in WINDOW.
565 This is the width that is usable columns available for text in WINDOW.
566 If you want to find out how many columns WINDOW takes up,
567 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
571 return make_number (window_box_text_cols (decode_any_window (window
)));
574 DEFUN ("window-full-width-p", Fwindow_full_width_p
, Swindow_full_width_p
, 0, 1, 0,
575 doc
: /* Return t if WINDOW is as wide as its frame.
576 WINDOW defaults to the selected window. */)
580 return WINDOW_FULL_WIDTH_P (decode_any_window (window
)) ? Qt
: Qnil
;
583 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
584 doc
: /* Return the number of columns by which WINDOW is scrolled from left margin.
585 WINDOW defaults to the selected window. */)
589 return decode_window (window
)->hscroll
;
592 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
593 doc
: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
594 Return NCOL. NCOL should be zero or positive.
596 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
597 window so that the location of point moves off-window. */)
599 Lisp_Object window
, ncol
;
601 struct window
*w
= decode_window (window
);
605 hscroll
= max (0, XINT (ncol
));
607 /* Prevent redisplay shortcuts when changing the hscroll. */
608 if (XINT (w
->hscroll
) != hscroll
)
609 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
611 w
->hscroll
= make_number (hscroll
);
615 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger
,
616 Swindow_redisplay_end_trigger
, 0, 1, 0,
617 doc
: /* Return WINDOW's redisplay end trigger value.
618 WINDOW defaults to the selected window.
619 See `set-window-redisplay-end-trigger' for more information. */)
623 return decode_window (window
)->redisplay_end_trigger
;
626 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger
,
627 Sset_window_redisplay_end_trigger
, 2, 2, 0,
628 doc
: /* Set WINDOW's redisplay end trigger value to VALUE.
629 VALUE should be a buffer position (typically a marker) or nil.
630 If it is a buffer position, then if redisplay in WINDOW reaches a position
631 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
632 with two arguments: WINDOW, and the end trigger value.
633 Afterwards the end-trigger value is reset to nil. */)
635 register Lisp_Object window
, value
;
637 register struct window
*w
;
639 w
= decode_window (window
);
640 w
->redisplay_end_trigger
= value
;
644 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
645 doc
: /* Return a list of the edge coordinates of WINDOW.
646 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
647 RIGHT is one more than the rightmost column occupied by WINDOW,
648 and BOTTOM is one more than the bottommost row occupied by WINDOW.
649 The edges include the space used by the window's scroll bar,
650 display margins, fringes, header line, and mode line, if it has them.
651 To get the edges of the actual text area, use `window-inside-edges'. */)
655 register struct window
*w
= decode_any_window (window
);
657 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w
)),
658 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w
)),
659 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w
)),
660 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w
)),
664 DEFUN ("window-pixel-edges", Fwindow_pixel_edges
, Swindow_pixel_edges
, 0, 1, 0,
665 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
666 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
667 RIGHT is one more than the rightmost x position occupied by WINDOW,
668 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
669 The pixel edges include the space used by the window's scroll bar,
670 display margins, fringes, header line, and mode line, if it has them.
671 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
675 register struct window
*w
= decode_any_window (window
);
677 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w
)),
678 Fcons (make_number (WINDOW_TOP_EDGE_Y (w
)),
679 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w
)),
680 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w
)),
684 DEFUN ("window-inside-edges", Fwindow_inside_edges
, Swindow_inside_edges
, 0, 1, 0,
685 doc
: /* Return a list of the edge coordinates of WINDOW.
686 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
687 RIGHT is one more than the rightmost column used by text in WINDOW,
688 and BOTTOM is one more than the bottommost row used by text in WINDOW.
689 The inside edges do not include the space used by the window's scroll bar,
690 display margins, fringes, header line, and/or mode line. */)
694 register struct window
*w
= decode_any_window (window
);
696 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w
)
697 + WINDOW_LEFT_MARGIN_COLS (w
)
698 + WINDOW_LEFT_FRINGE_COLS (w
)),
699 make_number (WINDOW_TOP_EDGE_LINE (w
)
700 + WINDOW_HEADER_LINE_LINES (w
)),
701 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w
)
702 - WINDOW_RIGHT_MARGIN_COLS (w
)
703 - WINDOW_RIGHT_FRINGE_COLS (w
)),
704 make_number (WINDOW_BOTTOM_EDGE_LINE (w
)
705 - WINDOW_MODE_LINE_LINES (w
)));
708 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges
, Swindow_inside_pixel_edges
, 0, 1, 0,
709 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
710 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
711 RIGHT is one more than the rightmost x position used by text in WINDOW,
712 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
713 The inside edges do not include the space used by the window's scroll bar,
714 display margins, fringes, header line, and/or mode line. */)
718 register struct window
*w
= decode_any_window (window
);
720 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w
)
721 + WINDOW_LEFT_MARGIN_WIDTH (w
)
722 + WINDOW_LEFT_FRINGE_WIDTH (w
)),
723 make_number (WINDOW_TOP_EDGE_Y (w
)
724 + WINDOW_HEADER_LINE_HEIGHT (w
)),
725 make_number (WINDOW_BOX_RIGHT_EDGE_X (w
)
726 - WINDOW_RIGHT_MARGIN_WIDTH (w
)
727 - WINDOW_RIGHT_FRINGE_WIDTH (w
)),
728 make_number (WINDOW_BOTTOM_EDGE_Y (w
)
729 - WINDOW_MODE_LINE_HEIGHT (w
)));
732 /* Test if the character at column *X, row *Y is within window W.
733 If it is not, return ON_NOTHING;
734 if it is in the window's text area,
735 set *x and *y to its location relative to the upper left corner
738 if it is on the window's modeline, return ON_MODE_LINE;
739 if it is on the border between the window and its right sibling,
740 return ON_VERTICAL_BORDER.
741 if it is on a scroll bar,
742 return ON_SCROLL_BAR.
743 if it is on the window's top line, return ON_HEADER_LINE;
744 if it is in left or right fringe of the window,
745 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
746 to window-relative coordinates;
747 if it is in the marginal area to the left/right of the window,
748 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
749 to window-relative coordinates.
751 X and Y are frame relative pixel coordinates. */
753 static enum window_part
754 coordinates_in_window (w
, x
, y
)
755 register struct window
*w
;
758 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
759 int left_x
, right_x
, top_y
, bottom_y
;
760 enum window_part part
;
761 int ux
= FRAME_COLUMN_WIDTH (f
);
762 int x0
= WINDOW_LEFT_EDGE_X (w
);
763 int x1
= WINDOW_RIGHT_EDGE_X (w
);
764 /* The width of the area where the vertical line can be dragged.
765 (Between mode lines for instance. */
766 int grabbable_width
= ux
;
767 int lmargin_width
, rmargin_width
, text_left
, text_right
;
769 /* In what's below, we subtract 1 when computing right_x because we
770 want the rightmost pixel, which is given by left_pixel+width-1. */
771 if (w
->pseudo_window_p
)
774 right_x
= WINDOW_TOTAL_WIDTH (w
) - 1;
775 top_y
= WINDOW_TOP_EDGE_Y (w
);
776 bottom_y
= WINDOW_BOTTOM_EDGE_Y (w
);
780 left_x
= WINDOW_BOX_LEFT_EDGE_X (w
);
781 right_x
= WINDOW_BOX_RIGHT_EDGE_X (w
) - 1;
782 top_y
= WINDOW_TOP_EDGE_Y (w
);
783 bottom_y
= WINDOW_BOTTOM_EDGE_Y (w
);
786 /* Outside any interesting row? */
787 if (*y
< top_y
|| *y
>= bottom_y
)
790 /* On the mode line or header line? If it's near the start of
791 the mode or header line of window that's has a horizontal
792 sibling, say it's on the vertical line. That's to be able
793 to resize windows horizontally in case we're using toolkit
796 if (WINDOW_WANTS_MODELINE_P (w
)
797 && *y
>= bottom_y
- CURRENT_MODE_LINE_HEIGHT (w
))
801 header_vertical_border_check
:
802 /* We're somewhere on the mode line. We consider the place
803 between mode lines of horizontally adjacent mode lines
804 as the vertical border. If scroll bars on the left,
805 return the right window. */
806 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
)
807 || WINDOW_RIGHTMOST_P (w
))
809 if (!WINDOW_LEFTMOST_P (w
) && eabs (*x
- x0
) < grabbable_width
)
811 /* Convert X and Y to window relative coordinates.
812 Vertical border is at the left edge of window. */
813 *x
= max (0, *x
- x0
);
815 return ON_VERTICAL_BORDER
;
820 if (eabs (*x
- x1
) < grabbable_width
)
822 /* Convert X and Y to window relative coordinates.
823 Vertical border is at the right edge of window. */
824 *x
= min (x1
, *x
) - x0
;
826 return ON_VERTICAL_BORDER
;
830 if (*x
< x0
|| *x
>= x1
)
833 /* Convert X and Y to window relative coordinates.
834 Mode line starts at left edge of window. */
840 if (WINDOW_WANTS_HEADER_LINE_P (w
)
841 && *y
< top_y
+ CURRENT_HEADER_LINE_HEIGHT (w
))
843 part
= ON_HEADER_LINE
;
844 goto header_vertical_border_check
;
847 if (*x
< x0
|| *x
>= x1
)
850 /* Outside any interesting column? */
851 if (*x
< left_x
|| *x
> right_x
)
854 return ON_SCROLL_BAR
;
857 lmargin_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
858 rmargin_width
= window_box_width (w
, RIGHT_MARGIN_AREA
);
860 text_left
= window_box_left (w
, TEXT_AREA
);
861 text_right
= text_left
+ window_box_width (w
, TEXT_AREA
);
863 if (FRAME_WINDOW_P (f
))
865 if (!w
->pseudo_window_p
866 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w
)
867 && !WINDOW_RIGHTMOST_P (w
)
868 && (eabs (*x
- right_x
) < grabbable_width
))
870 /* Convert X and Y to window relative coordinates.
871 Vertical border is at the right edge of window. */
872 *x
= min (right_x
, *x
) - left_x
;
874 return ON_VERTICAL_BORDER
;
879 /* Need to say "*x > right_x" rather than >=, since on character
880 terminals, the vertical line's x coordinate is right_x. */
881 if (!w
->pseudo_window_p
882 && !WINDOW_RIGHTMOST_P (w
)
883 && *x
> right_x
- ux
)
885 /* On the border on the right side of the window? Assume that
886 this area begins at RIGHT_X minus a canonical char width. */
887 *x
= min (right_x
, *x
) - left_x
;
889 return ON_VERTICAL_BORDER
;
895 if (lmargin_width
> 0
896 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
897 ? (*x
>= left_x
+ WINDOW_LEFT_FRINGE_WIDTH (w
))
898 : (*x
< left_x
+ lmargin_width
)))
901 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
))
902 *x
-= WINDOW_LEFT_FRINGE_WIDTH (w
);
904 return ON_LEFT_MARGIN
;
907 /* Convert X and Y to window-relative pixel coordinates. */
910 return ON_LEFT_FRINGE
;
913 if (*x
>= text_right
)
915 if (rmargin_width
> 0
916 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
917 ? (*x
< right_x
- WINDOW_RIGHT_FRINGE_WIDTH (w
))
918 : (*x
>= right_x
- rmargin_width
)))
920 *x
-= right_x
- rmargin_width
;
921 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
))
922 *x
+= WINDOW_RIGHT_FRINGE_WIDTH (w
);
924 return ON_RIGHT_MARGIN
;
927 /* Convert X and Y to window-relative pixel coordinates. */
928 *x
-= left_x
+ WINDOW_LEFT_FRINGE_WIDTH (w
);
930 return ON_RIGHT_FRINGE
;
933 /* Everything special ruled out - must be on text area */
940 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
941 Scoordinates_in_window_p
, 2, 2, 0,
942 doc
: /* Return non-nil if COORDINATES are in WINDOW.
943 COORDINATES is a cons of the form (X . Y), X and Y being distances
944 measured in characters from the upper-left corner of the frame.
945 \(0 . 0) denotes the character in the upper left corner of the
947 If COORDINATES are in the text portion of WINDOW,
948 the coordinates relative to the window are returned.
949 If they are in the mode line of WINDOW, `mode-line' is returned.
950 If they are in the top mode line of WINDOW, `header-line' is returned.
951 If they are in the left fringe of WINDOW, `left-fringe' is returned.
952 If they are in the right fringe of WINDOW, `right-fringe' is returned.
953 If they are on the border between WINDOW and its right sibling,
954 `vertical-line' is returned.
955 If they are in the windows's left or right marginal areas, `left-margin'\n\
956 or `right-margin' is returned. */)
957 (coordinates
, window
)
958 register Lisp_Object coordinates
, window
;
965 CHECK_WINDOW (window
);
966 w
= XWINDOW (window
);
967 f
= XFRAME (w
->frame
);
968 CHECK_CONS (coordinates
);
969 lx
= Fcar (coordinates
);
970 ly
= Fcdr (coordinates
);
971 CHECK_NUMBER_OR_FLOAT (lx
);
972 CHECK_NUMBER_OR_FLOAT (ly
);
973 x
= FRAME_PIXEL_X_FROM_CANON_X (f
, lx
) + FRAME_INTERNAL_BORDER_WIDTH (f
);
974 y
= FRAME_PIXEL_Y_FROM_CANON_Y (f
, ly
) + FRAME_INTERNAL_BORDER_WIDTH (f
);
976 switch (coordinates_in_window (w
, &x
, &y
))
982 /* X and Y are now window relative pixel coordinates. Convert
983 them to canonical char units before returning them. */
984 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f
, x
),
985 FRAME_CANON_Y_FROM_PIXEL_Y (f
, y
));
990 case ON_VERTICAL_BORDER
:
991 return Qvertical_line
;
999 case ON_RIGHT_FRINGE
:
1000 return Qright_fringe
;
1002 case ON_LEFT_MARGIN
:
1003 return Qleft_margin
;
1005 case ON_RIGHT_MARGIN
:
1006 return Qright_margin
;
1009 /* Historically we are supposed to return nil in this case. */
1018 /* Callback for foreach_window, used in window_from_coordinates.
1019 Check if window W contains coordinates specified by USER_DATA which
1020 is actually a pointer to a struct check_window_data CW.
1022 Check if window W contains coordinates *CW->x and *CW->y. If it
1023 does, return W in *CW->window, as Lisp_Object, and return in
1024 *CW->part the part of the window under coordinates *X,*Y. Return
1025 zero from this function to stop iterating over windows. */
1027 struct check_window_data
1029 Lisp_Object
*window
;
1031 enum window_part
*part
;
1035 check_window_containing (w
, user_data
)
1039 struct check_window_data
*cw
= (struct check_window_data
*) user_data
;
1040 enum window_part found
;
1043 found
= coordinates_in_window (w
, cw
->x
, cw
->y
);
1044 if (found
!= ON_NOTHING
)
1047 XSETWINDOW (*cw
->window
, w
);
1055 /* Find the window containing frame-relative pixel position X/Y and
1056 return it as a Lisp_Object.
1058 If X, Y is on one of the window's special `window_part' elements,
1059 set *PART to the id of that element, and return X and Y converted
1060 to window relative coordinates in WX and WY.
1062 If there is no window under X, Y return nil and leave *PART
1063 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1065 This function was previously implemented with a loop cycling over
1066 windows with Fnext_window, and starting with the frame's selected
1067 window. It turned out that this doesn't work with an
1068 implementation of next_window using Vwindow_list, because
1069 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1070 tree of F when this function is called asynchronously from
1071 note_mouse_highlight. The original loop didn't terminate in this
1075 window_from_coordinates (f
, x
, y
, part
, wx
, wy
, tool_bar_p
)
1078 enum window_part
*part
;
1083 struct check_window_data cw
;
1084 enum window_part dummy
;
1090 cw
.window
= &window
, cw
.x
= &x
, cw
.y
= &y
; cw
.part
= part
;
1091 foreach_window (f
, check_window_containing
, &cw
);
1093 /* If not found above, see if it's in the tool bar window, if a tool
1097 && WINDOWP (f
->tool_bar_window
)
1098 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)) > 0
1099 && (coordinates_in_window (XWINDOW (f
->tool_bar_window
), &x
, &y
)
1103 window
= f
->tool_bar_window
;
1112 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
1113 doc
: /* Return window containing coordinates X and Y on FRAME.
1114 If omitted, FRAME defaults to the currently selected frame.
1115 The top left corner of the frame is considered to be row 0,
1118 Lisp_Object x
, y
, frame
;
1123 frame
= selected_frame
;
1124 CHECK_LIVE_FRAME (frame
);
1127 /* Check that arguments are integers or floats. */
1128 CHECK_NUMBER_OR_FLOAT (x
);
1129 CHECK_NUMBER_OR_FLOAT (y
);
1131 return window_from_coordinates (f
,
1132 (FRAME_PIXEL_X_FROM_CANON_X (f
, x
)
1133 + FRAME_INTERNAL_BORDER_WIDTH (f
)),
1134 (FRAME_PIXEL_Y_FROM_CANON_Y (f
, y
)
1135 + FRAME_INTERNAL_BORDER_WIDTH (f
)),
1139 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
1140 doc
: /* Return current value of point in WINDOW.
1141 WINDOW defaults to the selected window.
1143 For a nonselected window, this is the value point would have
1144 if that window were selected.
1146 Note that, when WINDOW is the selected window and its buffer
1147 is also currently selected, the value returned is the same as (point).
1148 It would be more strictly correct to return the `top-level' value
1149 of point, outside of any save-excursion forms.
1150 But that is hard to define. */)
1154 register struct window
*w
= decode_window (window
);
1156 if (w
== XWINDOW (selected_window
)
1157 && current_buffer
== XBUFFER (w
->buffer
))
1159 return Fmarker_position (w
->pointm
);
1162 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
1163 doc
: /* Return position at which display currently starts in WINDOW.
1164 WINDOW defaults to the selected window.
1165 This is updated by redisplay or by calling `set-window-start'. */)
1169 return Fmarker_position (decode_window (window
)->start
);
1172 /* This is text temporarily removed from the doc string below.
1174 This function returns nil if the position is not currently known.
1175 That happens when redisplay is preempted and doesn't finish.
1176 If in that case you want to compute where the end of the window would
1177 have been if redisplay had finished, do this:
1179 (goto-char (window-start window))
1180 (vertical-motion (1- (window-height window)) window)
1183 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 2, 0,
1184 doc
: /* Return position at which display currently ends in WINDOW.
1185 WINDOW defaults to the selected window.
1186 This is updated by redisplay, when it runs to completion.
1187 Simply changing the buffer text or setting `window-start'
1188 does not update this value.
1189 Return nil if there is no recorded value. \(This can happen if the
1190 last redisplay of WINDOW was preempted, and did not finish.)
1191 If UPDATE is non-nil, compute the up-to-date position
1192 if it isn't already recorded. */)
1194 Lisp_Object window
, update
;
1197 struct window
*w
= decode_window (window
);
1205 #if 0 /* This change broke some things. We should make it later. */
1206 /* If we don't know the end position, return nil.
1207 The user can compute it with vertical-motion if he wants to.
1208 It would be nicer to do it automatically,
1209 but that's so slow that it would probably bother people. */
1210 if (NILP (w
->window_end_valid
))
1215 && ! (! NILP (w
->window_end_valid
)
1216 && XFASTINT (w
->last_modified
) >= BUF_MODIFF (b
)
1217 && XFASTINT (w
->last_overlay_modified
) >= BUF_OVERLAY_MODIFF (b
))
1220 struct text_pos startp
;
1222 struct buffer
*old_buffer
= NULL
;
1224 /* Cannot use Fvertical_motion because that function doesn't
1225 cope with variable-height lines. */
1226 if (b
!= current_buffer
)
1228 old_buffer
= current_buffer
;
1229 set_buffer_internal (b
);
1232 /* In case W->start is out of the range, use something
1233 reasonable. This situation occurred when loading a file with
1234 `-l' containing a call to `rmail' with subsequent other
1235 commands. At the end, W->start happened to be BEG, while
1236 rmail had already narrowed the buffer. */
1237 if (XMARKER (w
->start
)->charpos
< BEGV
)
1238 SET_TEXT_POS (startp
, BEGV
, BEGV_BYTE
);
1239 else if (XMARKER (w
->start
)->charpos
> ZV
)
1240 SET_TEXT_POS (startp
, ZV
, ZV_BYTE
);
1242 SET_TEXT_POS_FROM_MARKER (startp
, w
->start
);
1244 start_display (&it
, w
, startp
);
1245 move_it_vertically (&it
, window_box_height (w
));
1246 if (it
.current_y
< it
.last_visible_y
)
1247 move_it_past_eol (&it
);
1248 value
= make_number (IT_CHARPOS (it
));
1251 set_buffer_internal (old_buffer
);
1254 XSETINT (value
, BUF_Z (b
) - XFASTINT (w
->window_end_pos
));
1259 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
1260 doc
: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1263 Lisp_Object window
, pos
;
1265 register struct window
*w
= decode_window (window
);
1267 CHECK_NUMBER_COERCE_MARKER (pos
);
1268 if (w
== XWINDOW (selected_window
)
1269 && XBUFFER (w
->buffer
) == current_buffer
)
1272 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
1274 /* We have to make sure that redisplay updates the window to show
1275 the new value of point. */
1276 if (!EQ (window
, selected_window
))
1277 ++windows_or_buffers_changed
;
1282 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
1283 doc
: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1285 Optional third arg NOFORCE non-nil inhibits next redisplay
1286 from overriding motion of point in order to display at this exact start. */)
1287 (window
, pos
, noforce
)
1288 Lisp_Object window
, pos
, noforce
;
1290 register struct window
*w
= decode_window (window
);
1292 CHECK_NUMBER_COERCE_MARKER (pos
);
1293 set_marker_restricted (w
->start
, pos
, w
->buffer
);
1294 /* this is not right, but much easier than doing what is right. */
1295 w
->start_at_line_beg
= Qnil
;
1297 w
->force_start
= Qt
;
1298 w
->update_mode_line
= Qt
;
1299 XSETFASTINT (w
->last_modified
, 0);
1300 XSETFASTINT (w
->last_overlay_modified
, 0);
1301 if (!EQ (window
, selected_window
))
1302 windows_or_buffers_changed
++;
1307 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
1309 doc
: /* Return WINDOW's dedicated object, usually t or nil.
1310 See also `set-window-dedicated-p'. */)
1314 return decode_window (window
)->dedicated
;
1317 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
1318 Sset_window_dedicated_p
, 2, 2, 0,
1319 doc
: /* Control whether WINDOW is dedicated to the buffer it displays.
1320 If it is dedicated, Emacs will not automatically change
1321 which buffer appears in it.
1322 The second argument is the new value for the dedication flag;
1323 non-nil means yes. */)
1325 Lisp_Object window
, arg
;
1327 register struct window
*w
= decode_window (window
);
1331 return w
->dedicated
;
1334 DEFUN ("window-parameters", Fwindow_parameters
, Swindow_parameters
,
1336 doc
: /* Return the parameters-alist of window WINDOW.
1337 It is a list of elements of the form (PARAMETER . VALUE).
1338 If WINDOW is omitted, return information on the currently selected window. */)
1342 return Fcopy_alist (decode_window (window
)->window_parameters
);
1345 DEFUN ("window-parameter", Fwindow_parameter
, Swindow_parameter
,
1347 doc
: /* Return WINDOW's value for parameter PARAMETER.
1348 If WINDOW is nil, describe the currently selected window. */)
1350 Lisp_Object window
, parameter
;
1354 result
= Fassq (parameter
, decode_window (window
)->window_parameters
);
1355 return CDR_SAFE (result
);
1359 DEFUN ("set-window-parameter", Fset_window_parameter
,
1360 Sset_window_parameter
, 3, 3, 0,
1361 doc
: /* Set window parameter PARAMETER to VALUE on WINDOW.
1362 If WINDOW is nil, use the currently selected window.
1364 (window
, parameter
, value
)
1365 Lisp_Object window
, parameter
, value
;
1367 register struct window
*w
= decode_window (window
);
1368 Lisp_Object old_alist_elt
;
1370 old_alist_elt
= Fassq (parameter
, w
->window_parameters
);
1371 if (EQ (old_alist_elt
, Qnil
))
1372 w
->window_parameters
= Fcons (Fcons (parameter
, value
), w
->window_parameters
);
1374 Fsetcdr (old_alist_elt
, value
);
1379 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
1381 doc
: /* Return the display-table that WINDOW is using.
1382 WINDOW defaults to the selected window. */)
1386 return decode_window (window
)->display_table
;
1389 /* Get the display table for use on window W. This is either W's
1390 display table or W's buffer's display table. Ignore the specified
1391 tables if they are not valid; if no valid table is specified,
1394 struct Lisp_Char_Table
*
1395 window_display_table (w
)
1398 struct Lisp_Char_Table
*dp
= NULL
;
1400 if (DISP_TABLE_P (w
->display_table
))
1401 dp
= XCHAR_TABLE (w
->display_table
);
1402 else if (BUFFERP (w
->buffer
))
1404 struct buffer
*b
= XBUFFER (w
->buffer
);
1406 if (DISP_TABLE_P (b
->display_table
))
1407 dp
= XCHAR_TABLE (b
->display_table
);
1408 else if (DISP_TABLE_P (Vstandard_display_table
))
1409 dp
= XCHAR_TABLE (Vstandard_display_table
);
1415 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
1416 doc
: /* Set WINDOW's display-table to TABLE. */)
1418 register Lisp_Object window
, table
;
1420 register struct window
*w
;
1422 w
= decode_window (window
);
1423 w
->display_table
= table
;
1427 /* Record info on buffer window w is displaying
1428 when it is about to cease to display that buffer. */
1431 register struct window
*w
;
1438 if (b
!= XMARKER (w
->pointm
)->buffer
)
1442 if (w
== XWINDOW (selected_window
)
1443 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
1444 /* Do this except when the selected window's buffer
1445 is being removed from some other window. */
1447 /* last_window_start records the start position that this buffer
1448 had in the last window to be disconnected from it.
1449 Now that this statement is unconditional,
1450 it is possible for the buffer to be displayed in the
1451 selected window, while last_window_start reflects another
1452 window which was recently showing the same buffer.
1453 Some people might say that might be a good thing. Let's see. */
1454 b
->last_window_start
= marker_position (w
->start
);
1456 /* Point in the selected window's buffer
1457 is actually stored in that buffer, and the window's pointm isn't used.
1458 So don't clobber point in that buffer. */
1459 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
)
1460 /* This line helps to fix Horsley's testbug.el bug. */
1461 && !(WINDOWP (b
->last_selected_window
)
1462 && w
!= XWINDOW (b
->last_selected_window
)
1463 && EQ (buf
, XWINDOW (b
->last_selected_window
)->buffer
)))
1464 temp_set_point_both (b
,
1465 clip_to_bounds (BUF_BEGV (b
),
1466 XMARKER (w
->pointm
)->charpos
,
1468 clip_to_bounds (BUF_BEGV_BYTE (b
),
1469 marker_byte_position (w
->pointm
),
1472 if (WINDOWP (b
->last_selected_window
)
1473 && w
== XWINDOW (b
->last_selected_window
))
1474 b
->last_selected_window
= Qnil
;
1477 /* Put replacement into the window structure in place of old. */
1479 replace_window (old
, replacement
)
1480 Lisp_Object old
, replacement
;
1482 register Lisp_Object tem
;
1483 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
1485 /* If OLD is its frame's root_window, then replacement is the new
1486 root_window for that frame. */
1488 if (EQ (old
, FRAME_ROOT_WINDOW (XFRAME (o
->frame
))))
1489 FRAME_ROOT_WINDOW (XFRAME (o
->frame
)) = replacement
;
1491 p
->left_col
= o
->left_col
;
1492 p
->top_line
= o
->top_line
;
1493 p
->total_cols
= o
->total_cols
;
1494 p
->total_lines
= o
->total_lines
;
1495 p
->desired_matrix
= p
->current_matrix
= 0;
1497 bzero (&p
->cursor
, sizeof (p
->cursor
));
1498 bzero (&p
->last_cursor
, sizeof (p
->last_cursor
));
1499 bzero (&p
->phys_cursor
, sizeof (p
->phys_cursor
));
1500 p
->phys_cursor_type
= -1;
1501 p
->phys_cursor_width
= -1;
1502 p
->must_be_updated_p
= 0;
1503 p
->pseudo_window_p
= 0;
1504 XSETFASTINT (p
->window_end_vpos
, 0);
1505 XSETFASTINT (p
->window_end_pos
, 0);
1506 p
->window_end_valid
= Qnil
;
1507 p
->frozen_window_start_p
= 0;
1508 p
->orig_top_line
= p
->orig_total_lines
= Qnil
;
1510 p
->next
= tem
= o
->next
;
1512 XWINDOW (tem
)->prev
= replacement
;
1514 p
->prev
= tem
= o
->prev
;
1516 XWINDOW (tem
)->next
= replacement
;
1518 p
->parent
= tem
= o
->parent
;
1521 if (EQ (XWINDOW (tem
)->vchild
, old
))
1522 XWINDOW (tem
)->vchild
= replacement
;
1523 if (EQ (XWINDOW (tem
)->hchild
, old
))
1524 XWINDOW (tem
)->hchild
= replacement
;
1527 /*** Here, if replacement is a vertical combination
1528 and so is its new parent, we should make replacement's
1529 children be children of that parent instead. ***/
1532 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
1533 doc
: /* Remove WINDOW from the display. Default is selected window. */)
1535 register Lisp_Object window
;
1539 window
= selected_window
;
1540 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
1541 delete_window (window
);
1543 run_window_configuration_change_hook (f
);
1549 delete_window (window
)
1550 register Lisp_Object window
;
1552 register Lisp_Object tem
, parent
, sib
;
1553 register struct window
*p
;
1554 register struct window
*par
;
1557 /* Because this function is called by other C code on non-leaf
1558 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1559 so we can't decode_window here. */
1560 CHECK_WINDOW (window
);
1561 p
= XWINDOW (window
);
1563 /* It's a no-op to delete an already-deleted window. */
1564 if (NILP (p
->buffer
)
1566 && NILP (p
->vchild
))
1571 error ("Attempt to delete minibuffer or sole ordinary window");
1572 par
= XWINDOW (parent
);
1574 windows_or_buffers_changed
++;
1575 Vwindow_list
= Qnil
;
1576 f
= XFRAME (WINDOW_FRAME (p
));
1577 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
1579 /* Are we trying to delete any frame's selected window? */
1581 Lisp_Object swindow
, pwindow
;
1583 /* See if the frame's selected window is either WINDOW
1584 or any subwindow of it, by finding all that window's parents
1585 and comparing each one with WINDOW. */
1586 swindow
= FRAME_SELECTED_WINDOW (f
);
1591 while (!NILP (pwindow
))
1593 if (EQ (window
, pwindow
))
1595 pwindow
= XWINDOW (pwindow
)->parent
;
1598 /* If the window being deleted is not a parent of SWINDOW,
1599 then SWINDOW is ok as the new selected window. */
1600 if (!EQ (window
, pwindow
))
1602 /* Otherwise, try another window for SWINDOW. */
1603 swindow
= Fnext_window (swindow
, Qlambda
, Qnil
);
1605 /* If we get back to the frame's selected window,
1606 it means there was no acceptable alternative,
1607 so we cannot delete. */
1608 if (EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1609 error ("Cannot delete window");
1612 /* If we need to change SWINDOW, do it. */
1613 if (! EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1615 /* If we're about to delete the selected window on the
1616 selected frame, then we should use Fselect_window to select
1617 the new window. On the other hand, if we're about to
1618 delete the selected window on any other frame, we shouldn't do
1619 anything but set the frame's selected_window slot. */
1620 if (EQ (FRAME_SELECTED_WINDOW (f
), selected_window
))
1621 Fselect_window (swindow
, Qnil
);
1623 FRAME_SELECTED_WINDOW (f
) = swindow
;
1627 /* Now we know we can delete this one. */
1628 window_deletion_count
++;
1631 /* tem is null for dummy parent windows
1632 (which have inferiors but not any contents themselves) */
1636 unchain_marker (XMARKER (p
->pointm
));
1637 unchain_marker (XMARKER (p
->start
));
1640 /* Free window glyph matrices. It is sure that they are allocated
1641 again when ADJUST_GLYPHS is called. Block input so that expose
1642 events and other events that access glyph matrices are not
1643 processed while we are changing them. */
1645 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f
)));
1649 XWINDOW (tem
)->prev
= p
->prev
;
1653 XWINDOW (tem
)->next
= p
->next
;
1655 if (EQ (window
, par
->hchild
))
1656 par
->hchild
= p
->next
;
1657 if (EQ (window
, par
->vchild
))
1658 par
->vchild
= p
->next
;
1660 /* Find one of our siblings to give our space to. */
1664 /* If p gives its space to its next sibling, that sibling needs
1665 to have its top/left side pulled back to where p's is.
1666 set_window_{height,width} will re-position the sibling's
1669 XWINDOW (sib
)->top_line
= p
->top_line
;
1670 XWINDOW (sib
)->left_col
= p
->left_col
;
1673 /* Stretch that sibling. */
1674 if (!NILP (par
->vchild
))
1675 set_window_height (sib
,
1676 XFASTINT (XWINDOW (sib
)->total_lines
) + XFASTINT (p
->total_lines
),
1678 if (!NILP (par
->hchild
))
1679 set_window_width (sib
,
1680 XFASTINT (XWINDOW (sib
)->total_cols
) + XFASTINT (p
->total_cols
),
1683 /* If parent now has only one child,
1684 put the child into the parent's place. */
1688 if (NILP (XWINDOW (tem
)->next
)) {
1689 replace_window (parent
, tem
);
1690 par
= XWINDOW (tem
);
1693 /* Since we may be deleting combination windows, we must make sure that
1694 not only p but all its children have been marked as deleted. */
1695 if (! NILP (p
->hchild
))
1696 delete_all_subwindows (XWINDOW (p
->hchild
));
1697 else if (! NILP (p
->vchild
))
1698 delete_all_subwindows (XWINDOW (p
->vchild
));
1700 /* Mark this window as deleted. */
1701 p
->buffer
= p
->hchild
= p
->vchild
= Qnil
;
1703 if (! NILP (par
->parent
))
1704 par
= XWINDOW (par
->parent
);
1706 /* Check if we have a v/hchild with a v/hchild. In that case remove
1709 if (! NILP (par
->vchild
) && ! NILP (XWINDOW (par
->vchild
)->vchild
))
1711 p
= XWINDOW (par
->vchild
);
1712 par
->vchild
= p
->vchild
;
1715 else if (! NILP (par
->hchild
) && ! NILP (XWINDOW (par
->hchild
)->hchild
))
1717 p
= XWINDOW (par
->hchild
);
1718 par
->hchild
= p
->hchild
;
1726 while (! NILP (tem
)) {
1727 XWINDOW (tem
)->parent
= p
->parent
;
1728 if (NILP (XWINDOW (tem
)->next
))
1730 tem
= XWINDOW (tem
)->next
;
1733 /* The next of the v/hchild we are removing is now the next of the
1734 last child for the v/hchild:
1735 Before v/hchild -> v/hchild -> next1 -> next2
1738 After: v/hchild -> next1 -> next2 -> next3
1740 XWINDOW (tem
)->next
= p
->next
;
1741 if (! NILP (p
->next
))
1742 XWINDOW (p
->next
)->prev
= tem
;
1744 p
->next
= p
->prev
= p
->vchild
= p
->hchild
= p
->buffer
= Qnil
;
1748 /* Adjust glyph matrices. */
1755 /***********************************************************************
1757 ***********************************************************************/
1759 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1760 pointer. This is a callback function for foreach_window, used in
1761 function window_list. */
1764 add_window_to_list (w
, user_data
)
1768 Lisp_Object
*list
= (Lisp_Object
*) user_data
;
1770 XSETWINDOW (window
, w
);
1771 *list
= Fcons (window
, *list
);
1776 /* Return a list of all windows, for use by next_window. If
1777 Vwindow_list is a list, return that list. Otherwise, build a new
1778 list, cache it in Vwindow_list, and return that. */
1783 if (!CONSP (Vwindow_list
))
1787 Vwindow_list
= Qnil
;
1788 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
1790 Lisp_Object args
[2];
1792 /* We are visiting windows in canonical order, and add
1793 new windows at the front of args[1], which means we
1794 have to reverse this list at the end. */
1796 foreach_window (XFRAME (XCAR (tail
)), add_window_to_list
, &args
[1]);
1797 args
[0] = Vwindow_list
;
1798 args
[1] = Fnreverse (args
[1]);
1799 Vwindow_list
= Fnconc (2, args
);
1803 return Vwindow_list
;
1807 /* Value is non-zero if WINDOW satisfies the constraints given by
1808 OWINDOW, MINIBUF and ALL_FRAMES.
1810 MINIBUF t means WINDOW may be minibuffer windows.
1811 `lambda' means WINDOW may not be a minibuffer window.
1812 a window means a specific minibuffer window
1814 ALL_FRAMES t means search all frames,
1815 nil means search just current frame,
1816 `visible' means search just visible frames,
1817 0 means search visible and iconified frames,
1818 a window means search the frame that window belongs to,
1819 a frame means consider windows on that frame, only. */
1822 candidate_window_p (window
, owindow
, minibuf
, all_frames
)
1823 Lisp_Object window
, owindow
, minibuf
, all_frames
;
1825 struct window
*w
= XWINDOW (window
);
1826 struct frame
*f
= XFRAME (w
->frame
);
1827 int candidate_p
= 1;
1829 if (!BUFFERP (w
->buffer
))
1831 else if (MINI_WINDOW_P (w
)
1832 && (EQ (minibuf
, Qlambda
)
1833 || (WINDOWP (minibuf
) && !EQ (minibuf
, window
))))
1835 /* If MINIBUF is `lambda' don't consider any mini-windows.
1836 If it is a window, consider only that one. */
1839 else if (EQ (all_frames
, Qt
))
1841 else if (NILP (all_frames
))
1843 xassert (WINDOWP (owindow
));
1844 candidate_p
= EQ (w
->frame
, XWINDOW (owindow
)->frame
);
1846 else if (EQ (all_frames
, Qvisible
))
1848 FRAME_SAMPLE_VISIBILITY (f
);
1849 candidate_p
= FRAME_VISIBLE_P (f
)
1850 && (FRAME_TERMINAL (XFRAME (w
->frame
))
1851 == FRAME_TERMINAL (XFRAME (selected_frame
)));
1854 else if (INTEGERP (all_frames
) && XINT (all_frames
) == 0)
1856 FRAME_SAMPLE_VISIBILITY (f
);
1857 candidate_p
= (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
)
1858 #ifdef HAVE_X_WINDOWS
1859 /* Yuck!! If we've just created the frame and the
1860 window-manager requested the user to place it
1861 manually, the window may still not be considered
1862 `visible'. I'd argue it should be at least
1863 something like `iconified', but don't know how to do
1865 || (FRAME_X_P (f
) && f
->output_data
.x
->asked_for_visible
1866 && !f
->output_data
.x
->has_been_visible
)
1869 && (FRAME_TERMINAL (XFRAME (w
->frame
))
1870 == FRAME_TERMINAL (XFRAME (selected_frame
)));
1872 else if (WINDOWP (all_frames
))
1873 candidate_p
= (EQ (FRAME_MINIBUF_WINDOW (f
), all_frames
)
1874 || EQ (XWINDOW (all_frames
)->frame
, w
->frame
)
1875 || EQ (XWINDOW (all_frames
)->frame
, FRAME_FOCUS_FRAME (f
)));
1876 else if (FRAMEP (all_frames
))
1877 candidate_p
= EQ (all_frames
, w
->frame
);
1883 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1884 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1888 decode_next_window_args (window
, minibuf
, all_frames
)
1889 Lisp_Object
*window
, *minibuf
, *all_frames
;
1892 *window
= selected_window
;
1894 CHECK_LIVE_WINDOW (*window
);
1896 /* MINIBUF nil may or may not include minibuffers. Decide if it
1898 if (NILP (*minibuf
))
1899 *minibuf
= minibuf_level
? minibuf_window
: Qlambda
;
1900 else if (!EQ (*minibuf
, Qt
))
1903 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1904 => count none of them, or a specific minibuffer window (the
1905 active one) to count. */
1907 /* ALL_FRAMES nil doesn't specify which frames to include. */
1908 if (NILP (*all_frames
))
1909 *all_frames
= (!EQ (*minibuf
, Qlambda
)
1910 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window
)->frame
))
1912 else if (EQ (*all_frames
, Qvisible
))
1914 else if (EQ (*all_frames
, make_number (0)))
1916 else if (FRAMEP (*all_frames
))
1918 else if (!EQ (*all_frames
, Qt
))
1921 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1922 search just current frame, `visible' meaning search just visible
1923 frames, 0 meaning search visible and iconified frames, or a
1924 window, meaning search the frame that window belongs to, or a
1925 frame, meaning consider windows on that frame, only. */
1929 /* Return the next or previous window of WINDOW in canonical ordering
1930 of windows. NEXT_P non-zero means return the next window. See the
1931 documentation string of next-window for the meaning of MINIBUF and
1935 next_window (window
, minibuf
, all_frames
, next_p
)
1936 Lisp_Object window
, minibuf
, all_frames
;
1939 decode_next_window_args (&window
, &minibuf
, &all_frames
);
1941 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1942 return the first window on the frame. */
1943 if (FRAMEP (all_frames
)
1944 && !EQ (all_frames
, XWINDOW (window
)->frame
))
1945 return Fframe_first_window (all_frames
);
1951 /* Find WINDOW in the list of all windows. */
1952 list
= Fmemq (window
, window_list ());
1954 /* Scan forward from WINDOW to the end of the window list. */
1956 for (list
= XCDR (list
); CONSP (list
); list
= XCDR (list
))
1957 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1960 /* Scan from the start of the window list up to WINDOW. */
1962 for (list
= Vwindow_list
;
1963 CONSP (list
) && !EQ (XCAR (list
), window
);
1965 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1969 window
= XCAR (list
);
1973 Lisp_Object candidate
, list
;
1975 /* Scan through the list of windows for candidates. If there are
1976 candidate windows in front of WINDOW, the last one of these
1977 is the one we want. If there are candidates following WINDOW
1978 in the list, again the last one of these is the one we want. */
1980 for (list
= window_list (); CONSP (list
); list
= XCDR (list
))
1982 if (EQ (XCAR (list
), window
))
1984 if (WINDOWP (candidate
))
1987 else if (candidate_window_p (XCAR (list
), window
, minibuf
,
1989 candidate
= XCAR (list
);
1992 if (WINDOWP (candidate
))
2000 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
2001 doc
: /* Return next window after WINDOW in canonical ordering of windows.
2002 If omitted, WINDOW defaults to the selected window.
2004 Optional second arg MINIBUF t means count the minibuffer window even
2005 if not active. MINIBUF nil or omitted means count the minibuffer iff
2006 it is active. MINIBUF neither t nor nil means not to count the
2007 minibuffer even if it is active.
2009 Several frames may share a single minibuffer; if the minibuffer
2010 counts, all windows on all frames that share that minibuffer count
2011 too. Therefore, `next-window' can be used to iterate through the
2012 set of windows even when the minibuffer is on another frame. If the
2013 minibuffer does not count, only windows from WINDOW's frame count.
2015 Optional third arg ALL-FRAMES t means include windows on all frames.
2016 ALL-FRAMES nil or omitted means cycle within the frames as specified
2017 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2018 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2019 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2020 Anything else means restrict to WINDOW's frame.
2022 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2023 `next-window' to iterate through the entire cycle of acceptable
2024 windows, eventually ending up back at the window you started with.
2025 `previous-window' traverses the same cycle, in the reverse order. */)
2026 (window
, minibuf
, all_frames
)
2027 Lisp_Object window
, minibuf
, all_frames
;
2029 return next_window (window
, minibuf
, all_frames
, 1);
2033 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
2034 doc
: /* Return the window preceding WINDOW in canonical ordering of windows.
2035 If omitted, WINDOW defaults to the selected window.
2037 Optional second arg MINIBUF t means count the minibuffer window even
2038 if not active. MINIBUF nil or omitted means count the minibuffer iff
2039 it is active. MINIBUF neither t nor nil means not to count the
2040 minibuffer even if it is active.
2042 Several frames may share a single minibuffer; if the minibuffer
2043 counts, all windows on all frames that share that minibuffer count
2044 too. Therefore, `previous-window' can be used to iterate through
2045 the set of windows even when the minibuffer is on another frame. If
2046 the minibuffer does not count, only windows from WINDOW's frame count
2048 Optional third arg ALL-FRAMES t means include windows on all frames.
2049 ALL-FRAMES nil or omitted means cycle within the frames as specified
2050 above. ALL-FRAMES = `visible' means include windows on all visible frames.
2051 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2052 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2053 Anything else means restrict to WINDOW's frame.
2055 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2056 `previous-window' to iterate through the entire cycle of acceptable
2057 windows, eventually ending up back at the window you started with.
2058 `next-window' traverses the same cycle, in the reverse order. */)
2059 (window
, minibuf
, all_frames
)
2060 Lisp_Object window
, minibuf
, all_frames
;
2062 return next_window (window
, minibuf
, all_frames
, 0);
2066 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
2067 doc
: /* Select the ARG'th different window on this frame.
2068 All windows on current frame are arranged in a cyclic order.
2069 This command selects the window ARG steps away in that order.
2070 A negative ARG moves in the opposite order. The optional second
2071 argument ALL-FRAMES has the same meaning as in `next-window', which see. */)
2073 Lisp_Object arg
, all_frames
;
2079 window
= selected_window
;
2081 for (i
= XINT (arg
); i
> 0; --i
)
2082 window
= Fnext_window (window
, Qnil
, all_frames
);
2084 window
= Fprevious_window (window
, Qnil
, all_frames
);
2086 Fselect_window (window
, Qnil
);
2091 DEFUN ("window-list", Fwindow_list
, Swindow_list
, 0, 3, 0,
2092 doc
: /* Return a list of windows on FRAME, starting with WINDOW.
2093 FRAME nil or omitted means use the selected frame.
2094 WINDOW nil or omitted means use the selected window.
2095 MINIBUF t means include the minibuffer window, even if it isn't active.
2096 MINIBUF nil or omitted means include the minibuffer window only
2098 MINIBUF neither nil nor t means never include the minibuffer window. */)
2099 (frame
, minibuf
, window
)
2100 Lisp_Object frame
, minibuf
, window
;
2103 window
= FRAMEP (frame
) ? XFRAME (frame
)->selected_window
: selected_window
;
2104 CHECK_WINDOW (window
);
2106 frame
= selected_frame
;
2108 if (!EQ (frame
, XWINDOW (window
)->frame
))
2109 error ("Window is on a different frame");
2111 return window_list_1 (window
, minibuf
, frame
);
2115 /* Return a list of windows in canonical ordering. Arguments are like
2116 for `next-window'. */
2119 window_list_1 (window
, minibuf
, all_frames
)
2120 Lisp_Object window
, minibuf
, all_frames
;
2122 Lisp_Object tail
, list
, rest
;
2124 decode_next_window_args (&window
, &minibuf
, &all_frames
);
2127 for (tail
= window_list (); CONSP (tail
); tail
= XCDR (tail
))
2128 if (candidate_window_p (XCAR (tail
), window
, minibuf
, all_frames
))
2129 list
= Fcons (XCAR (tail
), list
);
2131 /* Rotate the list to start with WINDOW. */
2132 list
= Fnreverse (list
);
2133 rest
= Fmemq (window
, list
);
2134 if (!NILP (rest
) && !EQ (rest
, list
))
2136 for (tail
= list
; !EQ (XCDR (tail
), rest
); tail
= XCDR (tail
))
2138 XSETCDR (tail
, Qnil
);
2139 list
= nconc2 (rest
, list
);
2146 /* Look at all windows, performing an operation specified by TYPE
2148 If FRAMES is Qt, look at all frames;
2149 Qnil, look at just the selected frame;
2150 Qvisible, look at visible frames;
2151 a frame, just look at windows on that frame.
2152 If MINI is non-zero, perform the operation on minibuffer windows too. */
2157 GET_BUFFER_WINDOW
, /* Arg is buffer */
2158 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
2159 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
2160 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
2162 UNSHOW_BUFFER
, /* Arg is buffer */
2163 REDISPLAY_BUFFER_WINDOWS
, /* Arg is buffer */
2168 window_loop (type
, obj
, mini
, frames
)
2169 enum window_loop type
;
2170 Lisp_Object obj
, frames
;
2173 Lisp_Object window
, windows
, best_window
, frame_arg
;
2175 struct gcpro gcpro1
;
2177 /* If we're only looping through windows on a particular frame,
2178 frame points to that frame. If we're looping through windows
2179 on all frames, frame is 0. */
2180 if (FRAMEP (frames
))
2181 f
= XFRAME (frames
);
2182 else if (NILP (frames
))
2183 f
= SELECTED_FRAME ();
2188 frame_arg
= Qlambda
;
2189 else if (EQ (frames
, make_number (0)))
2191 else if (EQ (frames
, Qvisible
))
2196 /* frame_arg is Qlambda to stick to one frame,
2197 Qvisible to consider all visible frames,
2200 /* Pick a window to start with. */
2204 window
= FRAME_SELECTED_WINDOW (f
);
2206 window
= FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2208 windows
= window_list_1 (window
, mini
? Qt
: Qnil
, frame_arg
);
2212 for (; CONSP (windows
); windows
= XCDR (windows
))
2216 window
= XCAR (windows
);
2217 w
= XWINDOW (window
);
2219 /* Note that we do not pay attention here to whether the frame
2220 is visible, since Fwindow_list skips non-visible frames if
2221 that is desired, under the control of frame_arg. */
2222 if (!MINI_WINDOW_P (w
)
2223 /* For UNSHOW_BUFFER, we must always consider all windows. */
2224 || type
== UNSHOW_BUFFER
2225 || (mini
&& minibuf_level
> 0))
2228 case GET_BUFFER_WINDOW
:
2229 if (EQ (w
->buffer
, obj
)
2230 /* Don't find any minibuffer window
2231 except the one that is currently in use. */
2232 && (MINI_WINDOW_P (w
)
2233 ? EQ (window
, minibuf_window
)
2236 if (NILP (best_window
))
2237 best_window
= window
;
2238 else if (EQ (window
, selected_window
))
2239 /* Prefer to return selected-window. */
2240 RETURN_UNGCPRO (window
);
2241 else if (EQ (Fwindow_frame (window
), selected_frame
))
2242 /* Prefer windows on the current frame. */
2243 best_window
= window
;
2247 case GET_LRU_WINDOW
:
2248 /* `obj' is an integer encoding a bitvector.
2249 `obj & 1' means consider only full-width windows.
2250 `obj & 2' means consider also dedicated windows. */
2251 if (((XINT (obj
) & 1) && !WINDOW_FULL_WIDTH_P (w
))
2252 || (!(XINT (obj
) & 2) && !NILP (w
->dedicated
))
2253 /* Minibuffer windows are always ignored. */
2254 || MINI_WINDOW_P (w
))
2256 if (NILP (best_window
)
2257 || (XFASTINT (XWINDOW (best_window
)->use_time
)
2258 > XFASTINT (w
->use_time
)))
2259 best_window
= window
;
2262 case DELETE_OTHER_WINDOWS
:
2263 if (!EQ (window
, obj
))
2264 Fdelete_window (window
);
2267 case DELETE_BUFFER_WINDOWS
:
2268 if (EQ (w
->buffer
, obj
))
2270 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2272 /* If this window is dedicated, and in a frame of its own,
2274 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
2275 && !NILP (w
->dedicated
)
2276 && other_visible_frames (f
))
2278 /* Skip the other windows on this frame.
2279 There might be one, the minibuffer! */
2280 while (CONSP (XCDR (windows
))
2281 && EQ (XWINDOW (XCAR (windows
))->frame
,
2282 XWINDOW (XCAR (XCDR (windows
)))->frame
))
2283 windows
= XCDR (windows
);
2285 /* Now we can safely delete the frame. */
2286 Fdelete_frame (w
->frame
, Qnil
);
2288 else if (NILP (w
->parent
))
2290 /* If we're deleting the buffer displayed in the
2291 only window on the frame, find a new buffer to
2294 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
2295 Fset_window_buffer (window
, buffer
, Qnil
);
2296 if (EQ (window
, selected_window
))
2297 Fset_buffer (w
->buffer
);
2300 Fdelete_window (window
);
2304 case GET_LARGEST_WINDOW
:
2305 { /* nil `obj' means to ignore dedicated windows. */
2306 /* Ignore dedicated windows and minibuffers. */
2307 if (MINI_WINDOW_P (w
) || (NILP (obj
) && !NILP (w
->dedicated
)))
2310 if (NILP (best_window
))
2311 best_window
= window
;
2314 struct window
*b
= XWINDOW (best_window
);
2315 if (XFASTINT (w
->total_lines
) * XFASTINT (w
->total_cols
)
2316 > XFASTINT (b
->total_lines
) * XFASTINT (b
->total_cols
))
2317 best_window
= window
;
2323 if (EQ (w
->buffer
, obj
))
2326 struct frame
*f
= XFRAME (w
->frame
);
2328 /* Find another buffer to show in this window. */
2329 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
2331 /* If this window is dedicated, and in a frame of its own,
2333 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
2334 && !NILP (w
->dedicated
)
2335 && other_visible_frames (f
))
2337 /* Skip the other windows on this frame.
2338 There might be one, the minibuffer! */
2339 while (CONSP (XCDR (windows
))
2340 && EQ (XWINDOW (XCAR (windows
))->frame
,
2341 XWINDOW (XCAR (XCDR (windows
)))->frame
))
2342 windows
= XCDR (windows
);
2344 /* Now we can safely delete the frame. */
2345 Fdelete_frame (w
->frame
, Qnil
);
2347 else if (!NILP (w
->dedicated
) && !NILP (w
->parent
))
2350 XSETWINDOW (window
, w
);
2351 /* If this window is dedicated and not the only window
2352 in its frame, then kill it. */
2353 Fdelete_window (window
);
2357 /* Otherwise show a different buffer in the window. */
2358 w
->dedicated
= Qnil
;
2359 Fset_window_buffer (window
, buffer
, Qnil
);
2360 if (EQ (window
, selected_window
))
2361 Fset_buffer (w
->buffer
);
2366 case REDISPLAY_BUFFER_WINDOWS
:
2367 if (EQ (w
->buffer
, obj
))
2369 mark_window_display_accurate (window
, 0);
2370 w
->update_mode_line
= Qt
;
2371 XBUFFER (obj
)->prevent_redisplay_optimizations_p
= 1;
2372 ++update_mode_lines
;
2373 best_window
= window
;
2377 /* Check for a window that has a killed buffer. */
2378 case CHECK_ALL_WINDOWS
:
2379 if (! NILP (w
->buffer
)
2380 && NILP (XBUFFER (w
->buffer
)->name
))
2384 case WINDOW_LOOP_UNUSED
:
2393 /* Used for debugging. Abort if any window has a dead buffer. */
2396 check_all_windows ()
2398 window_loop (CHECK_ALL_WINDOWS
, Qnil
, 1, Qt
);
2401 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 2, 0,
2402 doc
: /* Return the window least recently selected or used for display.
2403 \(LRU means Least Recently Used.)
2405 Return a full-width window if possible.
2406 A minibuffer window is never a candidate.
2407 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2408 so if all windows are dedicated, the value is nil.
2409 If optional argument FRAME is `visible', search all visible frames.
2410 If FRAME is 0, search all visible and iconified frames.
2411 If FRAME is t, search all frames.
2412 If FRAME is nil, search only the selected frame.
2413 If FRAME is a frame, search only that frame. */)
2415 Lisp_Object frame
, dedicated
;
2417 register Lisp_Object w
;
2418 /* First try for a window that is full-width */
2419 w
= window_loop (GET_LRU_WINDOW
,
2420 NILP (dedicated
) ? make_number (1) : make_number (3),
2422 if (!NILP (w
) && !EQ (w
, selected_window
))
2424 /* If none of them, try the rest */
2425 return window_loop (GET_LRU_WINDOW
,
2426 NILP (dedicated
) ? make_number (0) : make_number (2),
2430 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 2, 0,
2431 doc
: /* Return the largest window in area.
2432 A minibuffer window is never a candidate.
2433 A dedicated window is never a candidate unless DEDICATED is non-nil,
2434 so if all windows are dedicated, the value is nil.
2435 If optional argument FRAME is `visible', search all visible frames.
2436 If FRAME is 0, search all visible and iconified frames.
2437 If FRAME is t, search all frames.
2438 If FRAME is nil, search only the selected frame.
2439 If FRAME is a frame, search only that frame. */)
2441 Lisp_Object frame
, dedicated
;
2443 return window_loop (GET_LARGEST_WINDOW
, dedicated
, 0,
2447 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 1, 2, 0,
2448 doc
: /* Return a window currently displaying BUFFER, or nil if none.
2449 BUFFER can be a buffer or a buffer name.
2450 If optional argument FRAME is `visible', search all visible frames.
2451 If optional argument FRAME is 0, search all visible and iconified frames.
2452 If FRAME is t, search all frames.
2453 If FRAME is nil, search only the selected frame.
2454 If FRAME is a frame, search only that frame. */)
2456 Lisp_Object buffer
, frame
;
2458 buffer
= Fget_buffer (buffer
);
2459 if (BUFFERP (buffer
))
2460 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
2465 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
2467 doc
: /* Make WINDOW (or the selected window) fill its frame.
2468 Only the frame WINDOW is on is affected.
2469 This function tries to reduce display jumps
2470 by keeping the text previously visible in WINDOW
2471 in the same place on the frame. Doing this depends on
2472 the value of (window-start WINDOW), so if calling this function
2473 in a program gives strange scrolling, make sure the window-start
2474 value is reasonable when this function is called. */)
2483 window
= selected_window
;
2485 CHECK_LIVE_WINDOW (window
);
2486 w
= XWINDOW (window
);
2488 startpos
= marker_position (w
->start
);
2489 top
= WINDOW_TOP_EDGE_LINE (w
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2491 if (MINI_WINDOW_P (w
) && top
> 0)
2492 error ("Can't expand minibuffer to full frame");
2494 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_FRAME (w
));
2496 /* Try to minimize scrolling, by setting the window start to the point
2497 will cause the text at the old window start to be at the same place
2498 on the frame. But don't try to do this if the window start is
2499 outside the visible portion (as might happen when the display is
2500 not current, due to typeahead). */
2501 new_top
= WINDOW_TOP_EDGE_LINE (w
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2503 && startpos
>= BUF_BEGV (XBUFFER (w
->buffer
))
2504 && startpos
<= BUF_ZV (XBUFFER (w
->buffer
)))
2506 struct position pos
;
2507 struct buffer
*obuf
= current_buffer
;
2509 Fset_buffer (w
->buffer
);
2510 /* This computation used to temporarily move point, but that can
2511 have unwanted side effects due to text properties. */
2512 pos
= *vmotion (startpos
, -top
, w
);
2514 set_marker_both (w
->start
, w
->buffer
, pos
.bufpos
, pos
.bytepos
);
2515 w
->window_end_valid
= Qnil
;
2516 w
->start_at_line_beg
= ((pos
.bytepos
== BEGV_BYTE
2517 || FETCH_BYTE (pos
.bytepos
- 1) == '\n') ? Qt
2519 /* We need to do this, so that the window-scroll-functions
2521 w
->optional_new_start
= Qt
;
2523 set_buffer_internal (obuf
);
2529 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
2530 1, 2, "bDelete windows on (buffer): ",
2531 doc
: /* Delete all windows showing BUFFER.
2532 BUFFER must be a buffer or the name of an existing buffer.
2533 Optional second argument FRAME controls which frames are affected.
2534 If optional argument FRAME is `visible', search all visible frames.
2535 If FRAME is 0, search all visible and iconified frames.
2536 If FRAME is nil, search all frames.
2537 If FRAME is t, search only the selected frame.
2538 If FRAME is a frame, search only that frame. */)
2540 Lisp_Object buffer
, frame
;
2542 /* FRAME uses t and nil to mean the opposite of what window_loop
2546 else if (EQ (frame
, Qt
))
2551 buffer
= Fget_buffer (buffer
);
2552 CHECK_BUFFER (buffer
);
2553 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, frame
);
2559 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
2560 Sreplace_buffer_in_windows
,
2561 1, 1, "bReplace buffer in windows: ",
2562 doc
: /* Replace BUFFER with some other buffer in all windows showing it.
2563 BUFFER may be a buffer or the name of an existing buffer. */)
2569 buffer
= Fget_buffer (buffer
);
2570 CHECK_BUFFER (buffer
);
2571 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
2576 /* Replace BUFFER with some other buffer in all windows
2577 of all frames, even those on other keyboards. */
2580 replace_buffer_in_all_windows (buffer
)
2584 Lisp_Object tail
, frame
;
2586 /* A single call to window_loop won't do the job
2587 because it only considers frames on the current keyboard.
2588 So loop manually over frames, and handle each one. */
2589 FOR_EACH_FRAME (tail
, frame
)
2590 window_loop (UNSHOW_BUFFER
, buffer
, 1, frame
);
2592 window_loop (UNSHOW_BUFFER
, buffer
, 1, Qt
);
2596 /* Set the height of WINDOW and all its inferiors. */
2598 /* The smallest acceptable dimensions for a window. Anything smaller
2599 might crash Emacs. */
2601 #define MIN_SAFE_WINDOW_WIDTH (2)
2602 #define MIN_SAFE_WINDOW_HEIGHT (1)
2604 /* For wp non-zero the total number of columns of window w. Otherwise
2605 the total number of lines of w. */
2607 #define WINDOW_TOTAL_SIZE(w, wp) \
2608 (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
2610 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2611 minimum allowable size. */
2614 check_frame_size (frame
, rows
, cols
)
2618 /* For height, we have to see:
2619 how many windows the frame has at minimum (one or two),
2620 and whether it has a menu bar or other special stuff at the top. */
2622 = ((FRAME_MINIBUF_ONLY_P (frame
) || ! FRAME_HAS_MINIBUF_P (frame
))
2623 ? MIN_SAFE_WINDOW_HEIGHT
2624 : 2 * MIN_SAFE_WINDOW_HEIGHT
);
2626 if (FRAME_TOP_MARGIN (frame
) > 0)
2627 min_height
+= FRAME_TOP_MARGIN (frame
);
2629 if (*rows
< min_height
)
2631 if (*cols
< MIN_SAFE_WINDOW_WIDTH
)
2632 *cols
= MIN_SAFE_WINDOW_WIDTH
;
2635 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2636 check if W's width can be changed, otherwise check W's height.
2637 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2638 siblings, too. If none of the siblings is resizable, WINDOW isn't
2642 window_fixed_size_p (w
, width_p
, check_siblings_p
)
2644 int width_p
, check_siblings_p
;
2649 if (!NILP (w
->hchild
))
2651 c
= XWINDOW (w
->hchild
);
2655 /* A horizontal combination is fixed-width if all of if its
2657 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2658 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2659 fixed_p
= c
== NULL
;
2663 /* A horizontal combination is fixed-height if one of if its
2665 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2666 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2667 fixed_p
= c
!= NULL
;
2670 else if (!NILP (w
->vchild
))
2672 c
= XWINDOW (w
->vchild
);
2676 /* A vertical combination is fixed-width if one of if its
2678 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2679 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2680 fixed_p
= c
!= NULL
;
2684 /* A vertical combination is fixed-height if all of if its
2686 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2687 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2688 fixed_p
= c
== NULL
;
2691 else if (BUFFERP (w
->buffer
))
2693 struct buffer
*old
= current_buffer
;
2696 current_buffer
= XBUFFER (w
->buffer
);
2697 val
= find_symbol_value (Qwindow_size_fixed
);
2698 current_buffer
= old
;
2701 if (!EQ (val
, Qunbound
))
2703 fixed_p
= !NILP (val
);
2706 && ((EQ (val
, Qheight
) && width_p
)
2707 || (EQ (val
, Qwidth
) && !width_p
)))
2711 /* Can't tell if this one is resizable without looking at
2712 siblings. If all siblings are fixed-size this one is too. */
2713 if (!fixed_p
&& check_siblings_p
&& WINDOWP (w
->parent
))
2717 for (child
= w
->prev
; WINDOWP (child
); child
= XWINDOW (child
)->prev
)
2718 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2722 for (child
= w
->next
; WINDOWP (child
); child
= XWINDOW (child
)->next
)
2723 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2736 /* Return minimum size of leaf window W. WIDTH_P non-zero means return
2737 the minimum width of W, WIDTH_P zero means return the minimum height
2738 of W. SAFE_P non-zero means ignore window-min-height|width but just
2739 return values that won't crash Emacs and don't hide components like
2740 fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the
2741 minibuffer window, always return 1. */
2744 window_min_size_2 (w
, width_p
, safe_p
)
2746 int width_p
, safe_p
;
2748 /* We should consider buffer-local values of window_min_height and
2749 window_min_width here. */
2752 int safe_size
= (MIN_SAFE_WINDOW_WIDTH
2753 + WINDOW_FRINGE_COLS (w
)
2754 + WINDOW_SCROLL_BAR_COLS (w
));
2756 return safe_p
? safe_size
: max (window_min_width
, safe_size
);
2758 else if (MINI_WINDOW_P (w
))
2762 int safe_size
= (MIN_SAFE_WINDOW_HEIGHT
2763 + ((BUFFERP (w
->buffer
)
2764 && !NILP (XBUFFER (w
->buffer
)->mode_line_format
))
2767 return safe_p
? safe_size
: max (window_min_height
, safe_size
);
2771 /* Return minimum size of window W, not taking fixed-width windows into
2772 account. WIDTH_P non-zero means return the minimum width, otherwise
2773 return the minimum height. SAFE_P non-zero means ignore
2774 window-min-height|width but just return values that won't crash Emacs
2775 and don't hide components like fringes, scrollbars, or modelines. If
2776 W is a combination window, compute the minimum size from the minimum
2777 sizes of W's children. */
2780 window_min_size_1 (w
, width_p
, safe_p
)
2782 int width_p
, safe_p
;
2787 if (!NILP (w
->hchild
))
2789 /* W is a horizontal combination. */
2790 c
= XWINDOW (w
->hchild
);
2795 /* The minimum width of a horizontal combination is the sum of
2796 the minimum widths of its children. */
2799 size
+= window_min_size_1 (c
, 1, safe_p
);
2800 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2805 /* The minimum height of a horizontal combination is the
2806 maximum of the minimum heights of its children. */
2809 size
= max (window_min_size_1 (c
, 0, safe_p
), size
);
2810 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2814 else if (!NILP (w
->vchild
))
2816 /* W is a vertical combination. */
2817 c
= XWINDOW (w
->vchild
);
2822 /* The minimum width of a vertical combination is the maximum
2823 of the minimum widths of its children. */
2826 size
= max (window_min_size_1 (c
, 1, safe_p
), size
);
2827 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2832 /* The minimum height of a vertical combination is the sum of
2833 the minimum height of its children. */
2836 size
+= window_min_size_1 (c
, 0, safe_p
);
2837 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2842 /* W is a leaf window. */
2843 size
= window_min_size_2 (w
, width_p
, safe_p
);
2848 /* Return the minimum size of window W, taking fixed-size windows into
2849 account. WIDTH_P non-zero means return the minimum width, otherwise
2850 return the minimum height. SAFE_P non-zero means ignore
2851 window-min-height|width but just return values that won't crash Emacs
2852 and don't hide components like fringes, scrollbars, or modelines.
2853 IGNORE_FIXED_P non-zero means ignore if W is fixed-size. Set *FIXED
2854 to 1 if W is fixed-size unless FIXED is null. */
2857 window_min_size (w
, width_p
, safe_p
, ignore_fixed_p
, fixed
)
2859 int width_p
, safe_p
, ignore_fixed_p
, *fixed
;
2866 fixed_p
= window_fixed_size_p (w
, width_p
, 1);
2872 size
= WINDOW_TOTAL_SIZE (w
, width_p
);
2874 size
= window_min_size_1 (w
, width_p
, safe_p
);
2880 /* Adjust the margins of window W if text area is too small.
2881 Return 1 if window width is ok after adjustment; 0 if window
2882 is still too narrow. */
2885 adjust_window_margins (w
)
2888 int box_cols
= (WINDOW_TOTAL_COLS (w
)
2889 - WINDOW_FRINGE_COLS (w
)
2890 - WINDOW_SCROLL_BAR_COLS (w
));
2891 int margin_cols
= (WINDOW_LEFT_MARGIN_COLS (w
)
2892 + WINDOW_RIGHT_MARGIN_COLS (w
));
2894 if (box_cols
- margin_cols
>= MIN_SAFE_WINDOW_WIDTH
)
2897 if (margin_cols
< 0 || box_cols
< MIN_SAFE_WINDOW_WIDTH
)
2900 /* Window's text area is too narrow, but reducing the window
2901 margins will fix that. */
2902 margin_cols
= box_cols
- MIN_SAFE_WINDOW_WIDTH
;
2903 if (WINDOW_RIGHT_MARGIN_COLS (w
) > 0)
2905 if (WINDOW_LEFT_MARGIN_COLS (w
) > 0)
2906 w
->left_margin_cols
= w
->right_margin_cols
2907 = make_number (margin_cols
/2);
2909 w
->right_margin_cols
= make_number (margin_cols
);
2912 w
->left_margin_cols
= make_number (margin_cols
);
2916 /* Calculate new sizes for windows in the list FORWARD when their
2917 compound size goes from TOTAL to SIZE. TOTAL must be greater than
2918 SIZE. The number of windows in FORWARD is NCHILDREN, and the number
2919 that can shrink is SHRINKABLE. Fixed-size windows may be shrunk if
2920 and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means
2921 shrink columns, otherwise shrink lines.
2923 SAFE_P zero means windows may be sized down to window-min-height
2924 lines (window-min-window columns for WIDTH_P non-zero). SAFE_P
2925 non-zero means windows may be sized down to their minimum safe sizes
2926 taking into account the space needed to display modelines, fringes,
2929 This function returns an allocated array of new sizes that the caller
2930 must free. A size -1 means the window is fixed and RESIZE_FIXED_P is
2931 zero. A size zero means the window shall be deleted. Array index 0
2932 refers to the first window in FORWARD, 1 to the second, and so on.
2934 This function resizes windows proportionally to their size. It also
2935 tries to preserve smaller windows by resizing larger windows before
2936 resizing any window to zero. If resize_proportionally is non-nil for
2937 a specific window, it will attempt to strictly resize that window
2938 proportionally, even at the expense of deleting smaller windows. */
2940 shrink_windows (total
, size
, nchildren
, shrinkable
, resize_fixed_p
,
2941 forward
, width_p
, safe_p
)
2942 int total
, size
, nchildren
, shrinkable
;
2943 int resize_fixed_p
, width_p
, safe_p
;
2944 Lisp_Object forward
;
2946 int available_resize
= 0;
2947 int *new_sizes
, *min_sizes
;
2950 int smallest
= total
;
2951 int total_removed
= 0;
2952 int total_shrink
= total
- size
;
2955 new_sizes
= xmalloc (sizeof (*new_sizes
) * nchildren
);
2956 min_sizes
= xmalloc (sizeof (*min_sizes
) * nchildren
);
2958 for (i
= 0, child
= forward
; !NILP (child
); child
= c
->next
, ++i
)
2962 c
= XWINDOW (child
);
2963 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
2965 if (!resize_fixed_p
&& window_fixed_size_p (c
, width_p
, 0))
2969 new_sizes
[i
] = child_size
;
2970 min_sizes
[i
] = window_min_size_1 (c
, width_p
, safe_p
);
2971 if (child_size
> min_sizes
[i
]
2972 && NILP (c
->resize_proportionally
))
2973 available_resize
+= child_size
- min_sizes
[i
];
2976 /* We might need to shrink some windows to zero. Find the smallest
2977 windows and set them to 0 until we can fulfil the new size. */
2979 while (shrinkable
> 1 && size
+ available_resize
< total
)
2981 for (i
= 0; i
< nchildren
; ++i
)
2982 if (new_sizes
[i
] > 0 && smallest
> new_sizes
[i
])
2983 smallest
= new_sizes
[i
];
2985 for (i
= 0; i
< nchildren
; ++i
)
2986 if (new_sizes
[i
] == smallest
)
2988 /* Resize this window down to zero. */
2990 if (smallest
> min_sizes
[i
])
2991 available_resize
-= smallest
- min_sizes
[i
];
2992 available_resize
+= smallest
;
2994 total_removed
+= smallest
;
2996 /* We don't know what the smallest is now. */
2999 /* Out of for, just remove one window at the time and
3000 check again if we have enough space. */
3005 /* Now, calculate the new sizes. Try to shrink each window
3006 proportional to its size. */
3007 for (i
= 0; i
< nchildren
; ++i
)
3009 if (new_sizes
[i
] > min_sizes
[i
])
3011 int to_shrink
= total_shrink
* new_sizes
[i
] / total
;
3013 if (new_sizes
[i
] - to_shrink
< min_sizes
[i
])
3014 to_shrink
= new_sizes
[i
] - min_sizes
[i
];
3015 new_sizes
[i
] -= to_shrink
;
3016 total_removed
+= to_shrink
;
3020 /* Any reminder due to rounding, we just subtract from windows
3021 that are left and still can be shrunk. */
3022 while (total_shrink
> total_removed
)
3024 int nonzero_sizes
= 0;
3025 int nonzero_idx
= -1;
3027 for (i
= 0; i
< nchildren
; ++i
)
3028 if (new_sizes
[i
] > 0)
3034 for (i
= 0; i
< nchildren
; ++i
)
3035 if (new_sizes
[i
] > min_sizes
[i
])
3040 /* Out of for, just shrink one window at the time and
3041 check again if we have enough space. */
3045 /* Special case, only one window left. */
3046 if (nonzero_sizes
== 1)
3050 /* Any surplus due to rounding, we add to windows that are left. */
3051 while (total_shrink
< total_removed
)
3053 for (i
= 0; i
< nchildren
; ++i
)
3055 if (new_sizes
[i
] != 0 && total_shrink
< total_removed
)
3069 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
3070 WINDOW's width. Resize WINDOW's children, if any, so that they keep
3071 their proportionate size relative to WINDOW.
3073 If FIRST_ONLY is 1, change only the first of WINDOW's children when
3074 they are in series. If LAST_ONLY is 1, change only the last of
3075 WINDOW's children when they are in series.
3077 Propagate WINDOW's top or left edge position to children. Delete
3078 windows that become too small unless NODELETE_P is 1. When
3079 NODELETE_P equals 2 do not honor settings for window-min-height and
3080 window-min-width when resizing windows but use safe defaults instead.
3081 This should give better behavior when resizing frames. */
3084 size_window (window
, size
, width_p
, nodelete_p
, first_only
, last_only
)
3086 int size
, width_p
, nodelete_p
;
3087 int first_only
, last_only
;
3089 struct window
*w
= XWINDOW (window
);
3091 Lisp_Object child
, *forward
, *sideward
;
3092 int old_size
= WINDOW_TOTAL_SIZE (w
, width_p
);
3094 size
= max (0, size
);
3096 /* Delete WINDOW if it's too small. */
3097 if (nodelete_p
!= 1 && !NILP (w
->parent
)
3098 && size
< window_min_size_1 (w
, width_p
, nodelete_p
== 2))
3100 delete_window (window
);
3104 /* Set redisplay hints. */
3105 w
->last_modified
= make_number (0);
3106 w
->last_overlay_modified
= make_number (0);
3107 windows_or_buffers_changed
++;
3108 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w
->frame
)) = 1;
3112 sideward
= &w
->vchild
;
3113 forward
= &w
->hchild
;
3114 w
->total_cols
= make_number (size
);
3115 adjust_window_margins (w
);
3119 sideward
= &w
->hchild
;
3120 forward
= &w
->vchild
;
3121 w
->total_lines
= make_number (size
);
3122 w
->orig_total_lines
= Qnil
;
3125 if (!NILP (*sideward
))
3127 /* We have a chain of parallel siblings whose size should all change. */
3128 for (child
= *sideward
; !NILP (child
); child
= c
->next
)
3130 c
= XWINDOW (child
);
3132 c
->left_col
= w
->left_col
;
3134 c
->top_line
= w
->top_line
;
3135 size_window (child
, size
, width_p
, nodelete_p
,
3136 first_only
, last_only
);
3139 else if (!NILP (*forward
) && last_only
)
3141 /* Change the last in a series of siblings. */
3142 Lisp_Object last_child
;
3145 for (child
= *forward
; !NILP (child
); child
= c
->next
)
3147 c
= XWINDOW (child
);
3151 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3152 size_window (last_child
, size
- old_size
+ child_size
,
3153 width_p
, nodelete_p
, first_only
, last_only
);
3155 else if (!NILP (*forward
) && first_only
)
3157 /* Change the first in a series of siblings. */
3161 c
= XWINDOW (child
);
3164 c
->left_col
= w
->left_col
;
3166 c
->top_line
= w
->top_line
;
3168 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3169 size_window (child
, size
- old_size
+ child_size
,
3170 width_p
, nodelete_p
, first_only
, last_only
);
3172 else if (!NILP (*forward
))
3174 int fixed_size
, each
, extra
, n
;
3175 int resize_fixed_p
, nfixed
;
3176 int last_pos
, first_pos
, nchildren
, total
;
3177 int *new_sizes
= NULL
;
3179 /* Determine the fixed-size portion of this window, and the
3180 number of child windows. */
3181 fixed_size
= nchildren
= nfixed
= total
= 0;
3182 for (child
= *forward
; !NILP (child
); child
= c
->next
, ++nchildren
)
3186 c
= XWINDOW (child
);
3187 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3188 total
+= child_size
;
3190 if (window_fixed_size_p (c
, width_p
, 0))
3192 fixed_size
+= child_size
;
3197 /* If the new size is smaller than fixed_size, or if there
3198 aren't any resizable windows, allow resizing fixed-size
3200 resize_fixed_p
= nfixed
== nchildren
|| size
< fixed_size
;
3202 /* Compute how many lines/columns to add/remove to each child. The
3203 value of extra takes care of rounding errors. */
3204 n
= resize_fixed_p
? nchildren
: nchildren
- nfixed
;
3205 if (size
< total
&& n
> 1)
3206 new_sizes
= shrink_windows (total
, size
, nchildren
, n
,
3207 resize_fixed_p
, *forward
, width_p
,
3211 each
= (size
- total
) / n
;
3212 extra
= (size
- total
) - n
* each
;
3215 /* Compute new children heights and edge positions. */
3216 first_pos
= width_p
? XINT (w
->left_col
) : XINT (w
->top_line
);
3217 last_pos
= first_pos
;
3218 for (n
= 0, child
= *forward
; !NILP (child
); child
= c
->next
, ++n
)
3220 int new_size
, old_size
;
3222 c
= XWINDOW (child
);
3223 old_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3224 new_size
= old_size
;
3226 /* The top or left edge position of this child equals the
3227 bottom or right edge of its predecessor. */
3229 c
->left_col
= make_number (last_pos
);
3231 c
->top_line
= make_number (last_pos
);
3233 /* If this child can be resized, do it. */
3234 if (resize_fixed_p
|| !window_fixed_size_p (c
, width_p
, 0))
3236 new_size
= new_sizes
? new_sizes
[n
] : old_size
+ each
+ extra
;
3240 /* Set new size. Note that size_window also propagates
3241 edge positions to children, so it's not a no-op if we
3242 didn't change the child's size. */
3243 size_window (child
, new_size
, width_p
, 1, first_only
, last_only
);
3245 /* Remember the bottom/right edge position of this child; it
3246 will be used to set the top/left edge of the next child. */
3247 last_pos
+= new_size
;
3252 /* We should have covered the parent exactly with child windows. */
3253 xassert (size
== last_pos
- first_pos
);
3255 /* Now delete any children that became too small. */
3256 if (nodelete_p
!= 1)
3257 for (child
= *forward
; !NILP (child
); child
= c
->next
)
3261 c
= XWINDOW (child
);
3262 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3263 size_window (child
, child_size
, width_p
, nodelete_p
,
3264 first_only
, last_only
);
3269 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3270 WINDOW's children. NODELETE zero means windows that have become
3271 smaller than window-min-height in the process may be deleted.
3272 NODELETE 1 means never delete windows that become too small in the
3273 process. (The caller should check later and do so if appropriate.)
3274 NODELETE 2 means delete only windows that have become too small to be
3275 displayed correctly. */
3278 set_window_height (window
, height
, nodelete
)
3283 size_window (window
, height
, 0, nodelete
, 0, 0);
3286 /* Set WINDOW's width to WIDTH, and recursively change the width of
3287 WINDOW's children. NODELETE zero means windows that have become
3288 smaller than window-min-width in the process may be deleted.
3289 NODELETE 1 means never delete windows that become too small in the
3290 process. (The caller should check later and do so if appropriate.)
3291 NODELETE 2 means delete only windows that have become too small to be
3292 displayed correctly. */
3295 set_window_width (window
, width
, nodelete
)
3300 size_window (window
, width
, 1, nodelete
, 0, 0);
3303 /* Change window heights in windows rooted in WINDOW by N lines. */
3306 change_window_heights (window
, n
)
3310 struct window
*w
= XWINDOW (window
);
3312 XSETFASTINT (w
->top_line
, XFASTINT (w
->top_line
) + n
);
3313 XSETFASTINT (w
->total_lines
, XFASTINT (w
->total_lines
) - n
);
3315 if (INTEGERP (w
->orig_top_line
))
3316 XSETFASTINT (w
->orig_top_line
, XFASTINT (w
->orig_top_line
) + n
);
3317 if (INTEGERP (w
->orig_total_lines
))
3318 XSETFASTINT (w
->orig_total_lines
, XFASTINT (w
->orig_total_lines
) - n
);
3320 /* Handle just the top child in a vertical split. */
3321 if (!NILP (w
->vchild
))
3322 change_window_heights (w
->vchild
, n
);
3324 /* Adjust all children in a horizontal split. */
3325 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
3327 w
= XWINDOW (window
);
3328 change_window_heights (window
, n
);
3333 int window_select_count
;
3336 Fset_window_buffer_unwind (obuf
)
3343 EXFUN (Fset_window_fringes
, 4);
3344 EXFUN (Fset_window_scroll_bars
, 4);
3347 run_funs (Lisp_Object funs
)
3349 for (; CONSP (funs
); funs
= XCDR (funs
))
3350 if (!EQ (XCAR (funs
), Qt
))
3351 call0 (XCAR (funs
));
3354 static Lisp_Object
select_window_norecord (Lisp_Object window
);
3357 run_window_configuration_change_hook (struct frame
*f
)
3359 int count
= SPECPDL_INDEX ();
3360 Lisp_Object frame
, global_wcch
3361 = Fdefault_value (Qwindow_configuration_change_hook
);
3362 XSETFRAME (frame
, f
);
3364 if (NILP (Vrun_hooks
))
3367 if (SELECTED_FRAME () != f
)
3369 record_unwind_protect (Fselect_frame
, Fselected_frame ());
3370 Fselect_frame (frame
);
3373 /* Use the right buffer. Matters when running the local hooks. */
3374 if (current_buffer
!= XBUFFER (Fwindow_buffer (Qnil
)))
3376 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
3377 Fset_buffer (Fwindow_buffer (Qnil
));
3380 /* Look for buffer-local values. */
3382 Lisp_Object windows
= Fwindow_list (frame
, Qlambda
, Qnil
);
3383 for (; CONSP (windows
); windows
= XCDR (windows
))
3385 Lisp_Object window
= XCAR (windows
);
3386 Lisp_Object buffer
= Fwindow_buffer (window
);
3387 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook
,
3390 int count
= SPECPDL_INDEX ();
3391 record_unwind_protect (select_window_norecord
, Fselected_window ());
3392 select_window_norecord (window
);
3393 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook
,
3395 unbind_to (count
, Qnil
);
3400 run_funs (global_wcch
);
3401 unbind_to (count
, Qnil
);
3404 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3405 means it's allowed to run hooks. See make_frame for a case where
3406 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3407 margins, fringes, and scroll-bar settings of the window are not
3408 reset from the buffer's local settings. */
3411 set_window_buffer (window
, buffer
, run_hooks_p
, keep_margins_p
)
3412 Lisp_Object window
, buffer
;
3413 int run_hooks_p
, keep_margins_p
;
3415 struct window
*w
= XWINDOW (window
);
3416 struct buffer
*b
= XBUFFER (buffer
);
3417 int count
= SPECPDL_INDEX ();
3418 int samebuf
= EQ (buffer
, w
->buffer
);
3422 if (EQ (window
, selected_window
))
3423 b
->last_selected_window
= window
;
3425 /* Let redisplay errors through. */
3426 b
->display_error_modiff
= 0;
3428 /* Update time stamps of buffer display. */
3429 if (INTEGERP (b
->display_count
))
3430 XSETINT (b
->display_count
, XINT (b
->display_count
) + 1);
3431 b
->display_time
= Fcurrent_time ();
3433 XSETFASTINT (w
->window_end_pos
, 0);
3434 XSETFASTINT (w
->window_end_vpos
, 0);
3435 bzero (&w
->last_cursor
, sizeof w
->last_cursor
);
3436 w
->window_end_valid
= Qnil
;
3437 if (!(keep_margins_p
&& samebuf
))
3438 { /* If we're not actually changing the buffer, Don't reset hscroll and
3439 vscroll. This case happens for example when called from
3440 change_frame_size_1, where we use a dummy call to
3441 Fset_window_buffer on the frame's selected window (and no other)
3442 just in order to run window-configuration-change-hook.
3443 Resetting hscroll and vscroll here is problematic for things like
3444 image-mode and doc-view-mode since it resets the image's position
3445 whenever we resize the frame. */
3446 w
->hscroll
= w
->min_hscroll
= make_number (0);
3448 set_marker_both (w
->pointm
, buffer
, BUF_PT (b
), BUF_PT_BYTE (b
));
3449 set_marker_restricted (w
->start
,
3450 make_number (b
->last_window_start
),
3452 w
->start_at_line_beg
= Qnil
;
3453 w
->force_start
= Qnil
;
3454 XSETFASTINT (w
->last_modified
, 0);
3455 XSETFASTINT (w
->last_overlay_modified
, 0);
3457 /* Maybe we could move this into the `if' but it's not obviously safe and
3458 I doubt it's worth the trouble. */
3459 windows_or_buffers_changed
++;
3461 /* We must select BUFFER for running the window-scroll-functions.
3462 If WINDOW is selected, switch permanently.
3463 Otherwise, switch but go back to the ambient buffer afterward. */
3464 if (EQ (window
, selected_window
))
3465 Fset_buffer (buffer
);
3466 /* We can't check ! NILP (Vwindow_scroll_functions) here
3467 because that might itself be a local variable. */
3468 else if (window_initialized
)
3470 record_unwind_protect (Fset_window_buffer_unwind
, Fcurrent_buffer ());
3471 Fset_buffer (buffer
);
3474 if (!keep_margins_p
)
3476 /* Set left and right marginal area width etc. from buffer. */
3478 /* This may call adjust_window_margins three times, so
3479 temporarily disable window margins. */
3480 Lisp_Object save_left
= w
->left_margin_cols
;
3481 Lisp_Object save_right
= w
->right_margin_cols
;
3483 w
->left_margin_cols
= w
->right_margin_cols
= Qnil
;
3485 Fset_window_fringes (window
,
3486 b
->left_fringe_width
, b
->right_fringe_width
,
3487 b
->fringes_outside_margins
);
3489 Fset_window_scroll_bars (window
,
3490 b
->scroll_bar_width
,
3491 b
->vertical_scroll_bar_type
, Qnil
);
3493 w
->left_margin_cols
= save_left
;
3494 w
->right_margin_cols
= save_right
;
3496 Fset_window_margins (window
,
3497 b
->left_margin_cols
, b
->right_margin_cols
);
3502 if (! NILP (Vwindow_scroll_functions
))
3503 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
3504 Fmarker_position (w
->start
));
3505 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w
)));
3508 unbind_to (count
, Qnil
);
3512 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 3, 0,
3513 doc
: /* Make WINDOW display BUFFER as its contents.
3514 BUFFER can be a buffer or the name of an existing buffer.
3515 Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
3516 display margins, fringe widths, and scroll bar settings are maintained;
3517 the default is to reset these from BUFFER's local settings or the frame
3520 This function runs the hook `window-scroll-functions'. */)
3521 (window
, buffer
, keep_margins
)
3522 register Lisp_Object window
, buffer
, keep_margins
;
3524 register Lisp_Object tem
;
3525 register struct window
*w
= decode_window (window
);
3527 XSETWINDOW (window
, w
);
3528 buffer
= Fget_buffer (buffer
);
3529 CHECK_BUFFER (buffer
);
3531 if (NILP (XBUFFER (buffer
)->name
))
3532 error ("Attempt to display deleted buffer");
3536 error ("Window is deleted");
3537 else if (! EQ (tem
, Qt
)) /* w->buffer is t when the window
3538 is first being set up. */
3540 if (!NILP (w
->dedicated
) && !EQ (tem
, buffer
))
3541 error ("Window is dedicated to `%s'",
3542 SDATA (XBUFFER (tem
)->name
));
3547 set_window_buffer (window
, buffer
, 1, !NILP (keep_margins
));
3551 /* Note that selected_window can be nil
3552 when this is called from Fset_window_configuration. */
3554 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 2, 0,
3555 doc
: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3556 If WINDOW is not already selected, make WINDOW's buffer current
3557 and make WINDOW the frame's selected window. Return WINDOW.
3558 Optional second arg NORECORD non-nil means
3559 do not put this buffer at the front of the list of recently selected ones.
3561 Note that the main editor command loop
3562 selects the buffer of the selected window before each command. */)
3564 register Lisp_Object window
, norecord
;
3566 register struct window
*w
;
3567 register struct window
*ow
;
3570 CHECK_LIVE_WINDOW (window
);
3572 w
= XWINDOW (window
);
3573 w
->frozen_window_start_p
= 0;
3575 ++window_select_count
;
3576 XSETFASTINT (w
->use_time
, window_select_count
);
3577 if (EQ (window
, selected_window
))
3580 sf
= SELECTED_FRAME ();
3581 if (XFRAME (WINDOW_FRAME (w
)) != sf
)
3583 XFRAME (WINDOW_FRAME (w
))->selected_window
= window
;
3584 /* Use this rather than Fhandle_switch_frame
3585 so that FRAME_FOCUS_FRAME is moved appropriately as we
3586 move around in the state where a minibuffer in a separate
3588 Fselect_frame (WINDOW_FRAME (w
));
3589 /* Fselect_frame called us back so we've done all the work already. */
3590 eassert (EQ (window
, selected_window
));
3594 sf
->selected_window
= window
;
3596 /* Store the current buffer's actual point into the
3597 old selected window. It belongs to that window,
3598 and when the window is not selected, must be in the window. */
3599 if (!NILP (selected_window
))
3601 ow
= XWINDOW (selected_window
);
3602 if (! NILP (ow
->buffer
))
3603 set_marker_both (ow
->pointm
, ow
->buffer
,
3604 BUF_PT (XBUFFER (ow
->buffer
)),
3605 BUF_PT_BYTE (XBUFFER (ow
->buffer
)));
3608 selected_window
= window
;
3610 if (NILP (norecord
))
3611 record_buffer (w
->buffer
);
3612 Fset_buffer (w
->buffer
);
3614 XBUFFER (w
->buffer
)->last_selected_window
= window
;
3616 /* Go to the point recorded in the window.
3617 This is important when the buffer is in more
3618 than one window. It also matters when
3619 redisplay_window has altered point after scrolling,
3620 because it makes the change only in the window. */
3622 register int new_point
= marker_position (w
->pointm
);
3623 if (new_point
< BEGV
)
3625 else if (new_point
> ZV
)
3631 windows_or_buffers_changed
++;
3636 select_window_norecord (window
)
3639 return Fselect_window (window
, Qt
);
3642 /* Deiconify the frame containing the window WINDOW,
3643 unless it is the selected frame;
3646 The reason for the exception for the selected frame
3647 is that it seems better not to change the selected frames visibility
3648 merely because of displaying a different buffer in it.
3649 The deiconification is useful when a buffer gets shown in
3650 another frame that you were not using lately. */
3653 display_buffer_1 (window
)
3656 Lisp_Object frame
= XWINDOW (window
)->frame
;
3657 FRAME_PTR f
= XFRAME (frame
);
3659 FRAME_SAMPLE_VISIBILITY (f
);
3661 if (EQ (frame
, selected_frame
))
3662 ; /* Assume the selected frame is already visible enough. */
3663 else if (minibuf_level
> 0
3664 && MINI_WINDOW_P (XWINDOW (selected_window
))
3665 && WINDOW_LIVE_P (minibuf_selected_window
)
3666 && EQ (frame
, WINDOW_FRAME (XWINDOW (minibuf_selected_window
))))
3667 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3670 if (FRAME_ICONIFIED_P (f
))
3671 Fmake_frame_visible (frame
);
3672 else if (FRAME_VISIBLE_P (f
))
3673 Fraise_frame (frame
);
3679 DEFUN ("special-display-p", Fspecial_display_p
, Sspecial_display_p
, 1, 1, 0,
3680 doc
: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
3681 If the value is t, `display-buffer' or `pop-to-buffer' would create a
3682 special frame for that buffer using the default frame parameters.
3684 If the value is a list, it is a list of frame parameters that would be used
3685 to make a frame for that buffer.
3686 The variables `special-display-buffer-names'
3687 and `special-display-regexps' control this. */)
3689 Lisp_Object buffer_name
;
3693 CHECK_STRING (buffer_name
);
3695 tem
= Fmember (buffer_name
, Vspecial_display_buffer_names
);
3699 tem
= Fassoc (buffer_name
, Vspecial_display_buffer_names
);
3703 for (tem
= Vspecial_display_regexps
; CONSP (tem
); tem
= XCDR (tem
))
3705 Lisp_Object car
= XCAR (tem
);
3707 && fast_string_match (car
, buffer_name
) >= 0)
3709 else if (CONSP (car
)
3710 && STRINGP (XCAR (car
))
3711 && fast_string_match (XCAR (car
), buffer_name
) >= 0)
3717 DEFUN ("same-window-p", Fsame_window_p
, Ssame_window_p
, 1, 1, 0,
3718 doc
: /* Returns non-nil if a buffer named BUFFER-NAME would use the same window.
3719 More precisely, if `display-buffer' or `pop-to-buffer' would display
3720 that buffer in the selected window rather than (as usual) in some other window.
3721 See `same-window-buffer-names' and `same-window-regexps'. */)
3723 Lisp_Object buffer_name
;
3727 CHECK_STRING (buffer_name
);
3729 tem
= Fmember (buffer_name
, Vsame_window_buffer_names
);
3733 tem
= Fassoc (buffer_name
, Vsame_window_buffer_names
);
3737 for (tem
= Vsame_window_regexps
; CONSP (tem
); tem
= XCDR (tem
))
3739 Lisp_Object car
= XCAR (tem
);
3741 && fast_string_match (car
, buffer_name
) >= 0)
3743 else if (CONSP (car
)
3744 && STRINGP (XCAR (car
))
3745 && fast_string_match (XCAR (car
), buffer_name
) >= 0)
3751 /* Use B so the default is (other-buffer). */
3752 DEFUN ("display-buffer", Fdisplay_buffer
, Sdisplay_buffer
, 1, 3,
3753 "BDisplay buffer: \nP",
3754 doc
: /* Make BUFFER appear in some window but don't select it.
3755 BUFFER must be the name of an existing buffer, or, when called from Lisp,
3757 If BUFFER is shown already in some window, just use that one,
3758 unless the window is the selected window and the optional second
3759 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3760 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3761 Returns the window displaying BUFFER.
3762 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3763 displaying BUFFER, then simply raise that frame.
3765 The variables `special-display-buffer-names',
3766 `special-display-regexps', `same-window-buffer-names', and
3767 `same-window-regexps' customize how certain buffer names are handled.
3768 The latter two take effect only if NOT-THIS-WINDOW is nil.
3770 If optional argument FRAME is `visible', check all visible frames
3771 for a window to use.
3772 If FRAME is 0, check all visible and iconified frames.
3773 If FRAME is t, check all frames.
3774 If FRAME is a frame, check only that frame.
3775 If FRAME is nil, check only the selected frame
3776 (actually the last nonminibuffer frame),
3777 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3778 which means search visible and iconified frames.
3780 If a full-width window on a splittable frame is available to display
3781 the buffer, it may be split, subject to the value of the variable
3782 `split-height-threshold'.
3784 If `even-window-heights' is non-nil, window heights will be evened out
3785 if displaying the buffer causes two vertically adjacent windows to be
3787 (buffer
, not_this_window
, frame
)
3788 Lisp_Object buffer
, not_this_window
, frame
;
3790 register Lisp_Object window
, tem
, swp
;
3794 buffer
= Fget_buffer (buffer
);
3795 CHECK_BUFFER (buffer
);
3797 if (!NILP (Vdisplay_buffer_function
))
3798 return call2 (Vdisplay_buffer_function
, buffer
, not_this_window
);
3800 if (NILP (not_this_window
)
3801 && XBUFFER (XWINDOW (selected_window
)->buffer
) == XBUFFER (buffer
))
3802 return display_buffer_1 (selected_window
);
3804 /* See if the user has specified this buffer should appear
3805 in the selected window. */
3806 if (NILP (not_this_window
))
3808 swp
= Fsame_window_p (XBUFFER (buffer
)->name
);
3809 if (!NILP (swp
) && !no_switch_window (selected_window
))
3811 Fswitch_to_buffer (buffer
, Qnil
);
3812 return display_buffer_1 (selected_window
);
3816 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3817 look for a window showing BUFFER on any visible or iconified frame.
3818 Otherwise search only the current frame. */
3821 else if (pop_up_frames
3822 || display_buffer_reuse_frames
3823 || last_nonminibuf_frame
== 0)
3824 XSETFASTINT (tem
, 0);
3826 XSETFRAME (tem
, last_nonminibuf_frame
);
3828 window
= Fget_buffer_window (buffer
, tem
);
3830 && (NILP (not_this_window
) || !EQ (window
, selected_window
)))
3831 return display_buffer_1 (window
);
3833 /* Certain buffer names get special handling. */
3834 if (!NILP (Vspecial_display_function
) && NILP (swp
))
3836 tem
= Fspecial_display_p (XBUFFER (buffer
)->name
);
3838 return call1 (Vspecial_display_function
, buffer
);
3840 return call2 (Vspecial_display_function
, buffer
, tem
);
3843 /* If there are no frames open that have more than a minibuffer,
3844 we need to create a new frame. */
3845 if (pop_up_frames
|| last_nonminibuf_frame
== 0)
3847 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
3848 Fset_window_buffer (window
, buffer
, Qnil
);
3849 return display_buffer_1 (window
);
3852 f
= SELECTED_FRAME ();
3854 || FRAME_MINIBUF_ONLY_P (f
)
3855 /* If the current frame is a special display frame,
3856 don't try to reuse its windows. */
3857 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f
))->dedicated
))
3860 struct gcpro gcpro1
;
3864 if (FRAME_MINIBUF_ONLY_P (f
))
3865 XSETFRAME (frames
, last_nonminibuf_frame
);
3867 /* Note that both Fget_largest_window and Fget_lru_window
3868 ignore minibuffers and dedicated windows.
3869 This means they can return nil. */
3871 /* If the frame we would try to split cannot be split,
3872 try other frames. */
3873 if (FRAME_NO_SPLIT_P (NILP (frames
) ? f
: last_nonminibuf_frame
))
3875 /* Try visible frames first. */
3876 window
= Fget_largest_window (Qvisible
, Qt
);
3877 /* If that didn't work, try iconified frames. */
3879 window
= Fget_largest_window (make_number (0), Qt
);
3880 #if 0 /* Don't try windows on other displays. */
3882 window
= Fget_largest_window (Qt
, Qt
);
3886 window
= Fget_largest_window (frames
, Qt
);
3889 if (!NILP (Vsplit_window_preferred_function
))
3890 tem
= call1 (Vsplit_window_preferred_function
, window
);
3895 /* If the largest window is tall enough, full-width, and either eligible
3896 for splitting or the only window, split it. */
3898 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
3899 && WINDOW_FULL_WIDTH_P (XWINDOW (window
))
3900 && (window_height (window
) >= split_height_threshold
3901 || (NILP (XWINDOW (window
)->parent
)))
3902 && (window_height (window
)
3903 >= (2 * window_min_size_2 (XWINDOW (window
), 0, 0))))
3904 window
= Fsplit_window (window
, Qnil
, Qnil
);
3907 Lisp_Object upper
, other
;
3909 window
= Fget_lru_window (frames
, Qt
);
3910 /* If the LRU window is tall enough, and either eligible for
3911 splitting and selected or the only window, split it. */
3913 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window
)->frame
))
3914 && ((EQ (window
, selected_window
)
3915 && window_height (window
) >= split_height_threshold
)
3916 || (NILP (XWINDOW (window
)->parent
)))
3917 && (window_height (window
)
3918 >= (2 * window_min_size_2 (XWINDOW (window
), 0, 0))))
3919 window
= Fsplit_window (window
, Qnil
, Qnil
);
3921 window
= Fget_lru_window (frames
, Qnil
);
3922 /* If Fget_lru_window returned nil, try other approaches. */
3924 /* Try visible frames first. */
3926 window
= Fget_buffer_window (buffer
, Qvisible
);
3928 window
= Fget_largest_window (Qvisible
, Qnil
);
3929 /* If that didn't work, try iconified frames. */
3931 window
= Fget_buffer_window (buffer
, make_number (0));
3933 window
= Fget_largest_window (make_number (0), Qnil
);
3935 #if 0 /* Don't try frames on other displays. */
3937 window
= Fget_buffer_window (buffer
, Qt
);
3939 window
= Fget_largest_window (Qt
, Qnil
);
3941 /* As a last resort, make a new frame. */
3943 window
= Fframe_selected_window (call0 (Vpop_up_frame_function
));
3944 /* If window appears above or below another,
3945 even out their heights. */
3946 other
= upper
= Qnil
;
3947 if (!NILP (XWINDOW (window
)->prev
))
3948 other
= upper
= XWINDOW (window
)->prev
;
3949 if (!NILP (XWINDOW (window
)->next
))
3950 other
= XWINDOW (window
)->next
, upper
= window
;
3952 && !NILP (Veven_window_heights
)
3953 /* Check that OTHER and WINDOW are vertically arrayed. */
3954 && !EQ (XWINDOW (other
)->top_line
, XWINDOW (window
)->top_line
)
3955 && (XFASTINT (XWINDOW (other
)->total_lines
)
3956 > XFASTINT (XWINDOW (window
)->total_lines
)))
3958 int total
= (XFASTINT (XWINDOW (other
)->total_lines
)
3959 + XFASTINT (XWINDOW (window
)->total_lines
));
3960 enlarge_window (upper
,
3961 total
/ 2 - XFASTINT (XWINDOW (upper
)->total_lines
),
3968 window
= Fget_lru_window (Qnil
, Qnil
);
3970 Fset_window_buffer (window
, buffer
, Qnil
);
3971 return display_buffer_1 (window
);
3975 DEFUN ("force-window-update", Fforce_window_update
, Sforce_window_update
,
3977 doc
: /* Force all windows to be updated on next redisplay.
3978 If optional arg OBJECT is a window, force redisplay of that window only.
3979 If OBJECT is a buffer or buffer name, force redisplay of all windows
3980 displaying that buffer. */)
3986 windows_or_buffers_changed
++;
3987 update_mode_lines
++;
3991 if (WINDOWP (object
))
3993 struct window
*w
= XWINDOW (object
);
3994 mark_window_display_accurate (object
, 0);
3995 w
->update_mode_line
= Qt
;
3996 if (BUFFERP (w
->buffer
))
3997 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
3998 ++update_mode_lines
;
4002 if (STRINGP (object
))
4003 object
= Fget_buffer (object
);
4004 if (BUFFERP (object
) && !NILP (XBUFFER (object
)->name
))
4006 /* Walk all windows looking for buffer, and force update
4007 of each of those windows. */
4009 object
= window_loop (REDISPLAY_BUFFER_WINDOWS
, object
, 0, Qvisible
);
4010 return NILP (object
) ? Qnil
: Qt
;
4013 /* If nothing suitable was found, just return.
4014 We could signal an error, but this feature will typically be used
4015 asynchronously in timers or process sentinels, so we don't. */
4021 temp_output_buffer_show (buf
)
4022 register Lisp_Object buf
;
4024 register struct buffer
*old
= current_buffer
;
4025 register Lisp_Object window
;
4026 register struct window
*w
;
4028 XBUFFER (buf
)->directory
= current_buffer
->directory
;
4031 BUF_SAVE_MODIFF (XBUFFER (buf
)) = MODIFF
;
4035 #if 0 /* rms: there should be no reason for this. */
4036 XBUFFER (buf
)->prevent_redisplay_optimizations_p
= 1;
4038 set_buffer_internal (old
);
4040 if (!NILP (Vtemp_buffer_show_function
))
4041 call1 (Vtemp_buffer_show_function
, buf
);
4044 window
= Fdisplay_buffer (buf
, Qnil
, Qnil
);
4046 if (!EQ (XWINDOW (window
)->frame
, selected_frame
))
4047 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
4048 Vminibuf_scroll_window
= window
;
4049 w
= XWINDOW (window
);
4050 XSETFASTINT (w
->hscroll
, 0);
4051 XSETFASTINT (w
->min_hscroll
, 0);
4052 set_marker_restricted_both (w
->start
, buf
, BEG
, BEG
);
4053 set_marker_restricted_both (w
->pointm
, buf
, BEG
, BEG
);
4055 /* Run temp-buffer-show-hook, with the chosen window selected
4056 and its buffer current. */
4058 if (!NILP (Vrun_hooks
)
4059 && !NILP (Fboundp (Qtemp_buffer_show_hook
))
4060 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook
)))
4062 int count
= SPECPDL_INDEX ();
4063 Lisp_Object prev_window
, prev_buffer
;
4064 prev_window
= selected_window
;
4065 XSETBUFFER (prev_buffer
, old
);
4067 /* Select the window that was chosen, for running the hook.
4068 Note: Both Fselect_window and select_window_norecord may
4069 set-buffer to the buffer displayed in the window,
4070 so we need to save the current buffer. --stef */
4071 record_unwind_protect (Fset_buffer
, prev_buffer
);
4072 record_unwind_protect (select_window_norecord
, prev_window
);
4073 Fselect_window (window
, Qt
);
4074 Fset_buffer (w
->buffer
);
4075 call1 (Vrun_hooks
, Qtemp_buffer_show_hook
);
4076 unbind_to (count
, Qnil
);
4082 make_dummy_parent (window
)
4086 register struct window
*o
, *p
;
4089 o
= XWINDOW (window
);
4090 p
= allocate_window ();
4091 for (i
= 0; i
< VECSIZE (struct window
); ++i
)
4092 ((struct Lisp_Vector
*) p
)->contents
[i
]
4093 = ((struct Lisp_Vector
*)o
)->contents
[i
];
4094 XSETWINDOW (new, p
);
4097 XSETFASTINT (p
->sequence_number
, sequence_number
);
4099 /* Put new into window structure in place of window */
4100 replace_window (window
, new);
4113 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
4114 doc
: /* Split WINDOW, putting SIZE lines in the first of the pair.
4115 WINDOW defaults to selected one and SIZE to half its size.
4116 If optional third arg HORFLAG is non-nil, split side by side
4117 and put SIZE columns in the first of the pair. In that case,
4118 SIZE includes that window's scroll bar, or the divider column to its right.
4119 Interactively, all arguments are nil.
4121 Returns the newly created window (which is the lower or rightmost one).
4122 The upper or leftmost window is the original one, and remains selected
4123 if it was selected before.
4125 See Info node `(elisp)Splitting Windows' for more details and examples.*/)
4126 (window
, size
, horflag
)
4127 Lisp_Object window
, size
, horflag
;
4129 register Lisp_Object
new;
4130 register struct window
*o
, *p
;
4132 register int size_int
;
4135 window
= selected_window
;
4137 CHECK_LIVE_WINDOW (window
);
4139 o
= XWINDOW (window
);
4140 fo
= XFRAME (WINDOW_FRAME (o
));
4144 if (!NILP (horflag
))
4145 /* Calculate the size of the left-hand window, by dividing
4146 the usable space in columns by two.
4147 We round up, since the left-hand window may include
4148 a dividing line, while the right-hand may not. */
4149 size_int
= (XFASTINT (o
->total_cols
) + 1) >> 1;
4151 size_int
= XFASTINT (o
->total_lines
) >> 1;
4155 CHECK_NUMBER (size
);
4156 size_int
= XINT (size
);
4159 if (MINI_WINDOW_P (o
))
4160 error ("Attempt to split minibuffer window");
4161 else if (window_fixed_size_p (o
, !NILP (horflag
), 0))
4162 error ("Attempt to split fixed-size window");
4166 int window_safe_height
= window_min_size_2 (o
, 0, 0);
4168 if (size_int
< window_safe_height
)
4169 error ("Window height %d too small (after splitting)", size_int
);
4170 if (size_int
+ window_safe_height
> XFASTINT (o
->total_lines
))
4171 error ("Window height %d too small (after splitting)",
4172 XFASTINT (o
->total_lines
) - size_int
);
4173 if (NILP (o
->parent
)
4174 || NILP (XWINDOW (o
->parent
)->vchild
))
4176 make_dummy_parent (window
);
4178 XWINDOW (new)->vchild
= window
;
4183 int window_safe_width
= window_min_size_2 (o
, 1, 0);
4185 if (size_int
< window_safe_width
)
4186 error ("Window width %d too small (after splitting)", size_int
);
4187 if (size_int
+ window_safe_width
> XFASTINT (o
->total_cols
))
4188 error ("Window width %d too small (after splitting)",
4189 XFASTINT (o
->total_cols
) - size_int
);
4190 if (NILP (o
->parent
)
4191 || NILP (XWINDOW (o
->parent
)->hchild
))
4193 make_dummy_parent (window
);
4195 XWINDOW (new)->hchild
= window
;
4199 /* Now we know that window's parent is a vertical combination
4200 if we are dividing vertically, or a horizontal combination
4201 if we are making side-by-side windows */
4203 windows_or_buffers_changed
++;
4204 FRAME_WINDOW_SIZES_CHANGED (fo
) = 1;
4205 new = make_window ();
4208 p
->frame
= o
->frame
;
4210 if (!NILP (p
->next
))
4211 XWINDOW (p
->next
)->prev
= new;
4214 p
->parent
= o
->parent
;
4216 p
->window_end_valid
= Qnil
;
4217 bzero (&p
->last_cursor
, sizeof p
->last_cursor
);
4219 /* Duplicate special geometry settings. */
4221 p
->left_margin_cols
= o
->left_margin_cols
;
4222 p
->right_margin_cols
= o
->right_margin_cols
;
4223 p
->left_fringe_width
= o
->left_fringe_width
;
4224 p
->right_fringe_width
= o
->right_fringe_width
;
4225 p
->fringes_outside_margins
= o
->fringes_outside_margins
;
4226 p
->scroll_bar_width
= o
->scroll_bar_width
;
4227 p
->vertical_scroll_bar_type
= o
->vertical_scroll_bar_type
;
4229 /* Apportion the available frame space among the two new windows */
4231 if (!NILP (horflag
))
4233 p
->total_lines
= o
->total_lines
;
4234 p
->top_line
= o
->top_line
;
4235 XSETFASTINT (p
->total_cols
, XFASTINT (o
->total_cols
) - size_int
);
4236 XSETFASTINT (o
->total_cols
, size_int
);
4237 XSETFASTINT (p
->left_col
, XFASTINT (o
->left_col
) + size_int
);
4238 adjust_window_margins (p
);
4239 adjust_window_margins (o
);
4243 p
->left_col
= o
->left_col
;
4244 p
->total_cols
= o
->total_cols
;
4245 XSETFASTINT (p
->total_lines
, XFASTINT (o
->total_lines
) - size_int
);
4246 XSETFASTINT (o
->total_lines
, size_int
);
4247 XSETFASTINT (p
->top_line
, XFASTINT (o
->top_line
) + size_int
);
4250 /* Adjust glyph matrices. */
4253 Fset_window_buffer (new, o
->buffer
, Qt
);
4257 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
4258 doc
: /* Make current window ARG lines bigger.
4259 From program, optional second arg non-nil means grow sideways ARG columns.
4260 Interactively, if an argument is not given, make the window one line bigger.
4261 If HORIZONTAL is non-nil, enlarge horizontally instead of vertically.
4262 This function can delete windows, even the second window, if they get
4265 Lisp_Object arg
, horizontal
;
4268 enlarge_window (selected_window
, XINT (arg
), !NILP (horizontal
));
4270 run_window_configuration_change_hook (SELECTED_FRAME ());
4275 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
4276 doc
: /* Make current window ARG lines smaller.
4277 From program, optional second arg non-nil means shrink sideways arg columns.
4278 Interactively, if an argument is not given, make the window one line smaller.
4279 Only siblings to the right or below are changed. */)
4281 Lisp_Object arg
, side
;
4284 enlarge_window (selected_window
, -XINT (arg
), !NILP (side
));
4286 run_window_configuration_change_hook (SELECTED_FRAME ());
4292 window_height (window
)
4295 register struct window
*p
= XWINDOW (window
);
4296 return WINDOW_TOTAL_LINES (p
);
4300 window_width (window
)
4303 register struct window
*p
= XWINDOW (window
);
4304 return WINDOW_TOTAL_COLS (p
);
4309 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
4311 #define CURSIZE(w) \
4312 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
4315 /* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it
4316 horizontally; zero means do it vertically.
4318 Siblings of the selected window are resized to fulfill the size
4319 request. If they become too small in the process, they may be
4323 enlarge_window (window
, delta
, horiz_flag
)
4325 int delta
, horiz_flag
;
4327 Lisp_Object parent
, next
, prev
;
4331 int (*sizefun
) P_ ((Lisp_Object
))
4332 = horiz_flag
? window_width
: window_height
;
4333 void (*setsizefun
) P_ ((Lisp_Object
, int, int))
4334 = (horiz_flag
? set_window_width
: set_window_height
);
4336 /* Give up if this window cannot be resized. */
4337 if (window_fixed_size_p (XWINDOW (window
), horiz_flag
, 1))
4338 error ("Window is not resizable");
4340 /* Find the parent of the selected window. */
4343 p
= XWINDOW (window
);
4349 error ("No other window to side of this one");
4354 ? !NILP (XWINDOW (parent
)->hchild
)
4355 : !NILP (XWINDOW (parent
)->vchild
))
4361 sizep
= &CURSIZE (window
);
4364 register int maxdelta
;
4366 /* Compute the maximum size increment this window can have. */
4368 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - XINT (*sizep
)
4369 /* This is a main window followed by a minibuffer. */
4370 : !NILP (p
->next
) ? ((*sizefun
) (p
->next
)
4371 - window_min_size (XWINDOW (p
->next
),
4372 horiz_flag
, 0, 0, 0))
4373 /* This is a minibuffer following a main window. */
4374 : !NILP (p
->prev
) ? ((*sizefun
) (p
->prev
)
4375 - window_min_size (XWINDOW (p
->prev
),
4376 horiz_flag
, 0, 0, 0))
4377 /* This is a frame with only one window, a minibuffer-only
4378 or a minibufferless frame. */
4381 if (delta
> maxdelta
)
4382 /* This case traps trying to make the minibuffer
4383 the full frame, or make the only window aside from the
4384 minibuffer the full frame. */
4388 if (XINT (*sizep
) + delta
< window_min_size (XWINDOW (window
),
4389 horiz_flag
, 0, 0, 0))
4391 delete_window (window
);
4398 /* Find the total we can get from other siblings without deleting them. */
4400 for (next
= p
->next
; WINDOWP (next
); next
= XWINDOW (next
)->next
)
4401 maximum
+= (*sizefun
) (next
) - window_min_size (XWINDOW (next
),
4402 horiz_flag
, 0, 0, 0);
4403 for (prev
= p
->prev
; WINDOWP (prev
); prev
= XWINDOW (prev
)->prev
)
4404 maximum
+= (*sizefun
) (prev
) - window_min_size (XWINDOW (prev
),
4405 horiz_flag
, 0, 0, 0);
4407 /* If we can get it all from them without deleting them, do so. */
4408 if (delta
<= maximum
)
4410 Lisp_Object first_unaffected
;
4411 Lisp_Object first_affected
;
4416 first_affected
= window
;
4417 /* Look at one sibling at a time,
4418 moving away from this window in both directions alternately,
4419 and take as much as we can get without deleting that sibling. */
4421 && (!NILP (next
) || !NILP (prev
)))
4425 int this_one
= ((*sizefun
) (next
)
4426 - window_min_size (XWINDOW (next
), horiz_flag
,
4430 if (this_one
> delta
)
4433 (*setsizefun
) (next
, (*sizefun
) (next
) - this_one
, 0);
4434 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
4439 next
= XWINDOW (next
)->next
;
4447 int this_one
= ((*sizefun
) (prev
)
4448 - window_min_size (XWINDOW (prev
), horiz_flag
,
4452 if (this_one
> delta
)
4455 first_affected
= prev
;
4457 (*setsizefun
) (prev
, (*sizefun
) (prev
) - this_one
, 0);
4458 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
4463 prev
= XWINDOW (prev
)->prev
;
4467 xassert (delta
== 0);
4469 /* Now recalculate the edge positions of all the windows affected,
4470 based on the new sizes. */
4471 first_unaffected
= next
;
4472 prev
= first_affected
;
4473 for (next
= XWINDOW (prev
)->next
; ! EQ (next
, first_unaffected
);
4474 prev
= next
, next
= XWINDOW (next
)->next
)
4476 XSETINT (CURBEG (next
), XINT (CURBEG (prev
)) + (*sizefun
) (prev
));
4477 /* This does not change size of NEXT,
4478 but it propagates the new top edge to its children */
4479 (*setsizefun
) (next
, (*sizefun
) (next
), 0);
4484 register int delta1
;
4485 register int opht
= (*sizefun
) (parent
);
4487 if (opht
<= XINT (*sizep
) + delta
)
4489 /* If trying to grow this window to or beyond size of the parent,
4490 just delete all the sibling windows. */
4491 Lisp_Object start
, tem
, next
;
4493 start
= XWINDOW (parent
)->vchild
;
4495 start
= XWINDOW (parent
)->hchild
;
4497 /* Delete any siblings that come after WINDOW. */
4498 tem
= XWINDOW (window
)->next
;
4499 while (! NILP (tem
))
4501 next
= XWINDOW (tem
)->next
;
4502 delete_window (tem
);
4506 /* Delete any siblings that come after WINDOW.
4507 Note that if START is not WINDOW, then WINDOW still
4508 has siblings, so WINDOW has not yet replaced its parent. */
4510 while (! EQ (tem
, window
))
4512 next
= XWINDOW (tem
)->next
;
4513 delete_window (tem
);
4519 /* Otherwise, make delta1 just right so that if we add
4520 delta1 lines to this window and to the parent, and then
4521 shrink the parent back to its original size, the new
4522 proportional size of this window will increase by delta.
4524 The function size_window will compute the new height h'
4525 of the window from delta1 as:
4528 x = delta1 - delta1/n * n for the 1st resizable child
4531 where n is the number of children that can be resized.
4532 We can ignore x by choosing a delta1 that is a multiple of
4533 n. We want the height of this window to come out as
4543 The number of children n equals the number of resizable
4544 children of this window + 1 because we know window itself
4545 is resizable (otherwise we would have signalled an error).
4547 This reasoning is not correct when other windows become too
4548 small and shrink_windows refuses to delete them. Below we
4549 use resize_proportionally to work around this problem. */
4551 struct window
*w
= XWINDOW (window
);
4555 for (s
= w
->next
; WINDOWP (s
); s
= XWINDOW (s
)->next
)
4556 if (!window_fixed_size_p (XWINDOW (s
), horiz_flag
, 0))
4558 for (s
= w
->prev
; WINDOWP (s
); s
= XWINDOW (s
)->prev
)
4559 if (!window_fixed_size_p (XWINDOW (s
), horiz_flag
, 0))
4564 /* Add delta1 lines or columns to this window, and to the parent,
4565 keeping things consistent while not affecting siblings. */
4566 XSETINT (CURSIZE (parent
), opht
+ delta1
);
4567 (*setsizefun
) (window
, XINT (*sizep
) + delta1
, 0);
4569 /* Squeeze out delta1 lines or columns from our parent,
4570 shrinking this window and siblings proportionately. This
4571 brings parent back to correct size. Delta1 was calculated
4572 so this makes this window the desired size, taking it all
4573 out of the siblings.
4575 Temporarily set resize_proportionally to Qt to assure that,
4576 if necessary, shrink_windows deletes smaller windows rather
4577 than shrink this window. */
4578 w
->resize_proportionally
= Qt
;
4579 (*setsizefun
) (parent
, opht
, 0);
4580 w
->resize_proportionally
= Qnil
;
4584 XSETFASTINT (p
->last_modified
, 0);
4585 XSETFASTINT (p
->last_overlay_modified
, 0);
4587 /* Adjust glyph matrices. */
4588 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4592 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4593 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4594 zero means adjust the height, moving the bottom edge.
4596 Following siblings of the selected window are resized to fulfill
4597 the size request. If they become too small in the process, they
4598 are not deleted; instead, we signal an error. */
4601 adjust_window_trailing_edge (window
, delta
, horiz_flag
)
4603 int delta
, horiz_flag
;
4605 Lisp_Object parent
, child
;
4607 Lisp_Object old_config
= Fcurrent_window_configuration (Qnil
);
4608 int delcount
= window_deletion_count
;
4610 CHECK_WINDOW (window
);
4612 /* Give up if this window cannot be resized. */
4613 if (window_fixed_size_p (XWINDOW (window
), horiz_flag
, 1))
4614 error ("Window is not resizable");
4618 Lisp_Object first_parallel
= Qnil
;
4622 /* This happens if WINDOW on the previous iteration was
4623 at top level of the window tree. */
4624 Fset_window_configuration (old_config
);
4625 error ("Specified window edge is fixed");
4628 p
= XWINDOW (window
);
4631 /* See if this level has windows in parallel in the specified
4632 direction. If so, set FIRST_PARALLEL to the first one. */
4635 if (! NILP (parent
) && !NILP (XWINDOW (parent
)->vchild
))
4636 first_parallel
= XWINDOW (parent
)->vchild
;
4637 else if (NILP (parent
) && !NILP (p
->next
))
4639 /* Handle the vertical chain of main window and minibuffer
4640 which has no parent. */
4641 first_parallel
= window
;
4642 while (! NILP (XWINDOW (first_parallel
)->prev
))
4643 first_parallel
= XWINDOW (first_parallel
)->prev
;
4648 if (! NILP (parent
) && !NILP (XWINDOW (parent
)->hchild
))
4649 first_parallel
= XWINDOW (parent
)->hchild
;
4652 /* If this level's succession is in the desired dimension,
4653 and this window is the last one, and there is no higher level,
4654 its trailing edge is fixed. */
4655 if (NILP (XWINDOW (window
)->next
) && NILP (first_parallel
)
4658 Fset_window_configuration (old_config
);
4659 error ("Specified window edge is fixed");
4662 /* Don't make this window too small. */
4663 if (XINT (CURSIZE (window
)) + delta
4664 < window_min_size_2 (XWINDOW (window
), horiz_flag
, 0))
4666 Fset_window_configuration (old_config
);
4667 error ("Cannot adjust window size as specified");
4670 /* Clear out some redisplay caches. */
4671 XSETFASTINT (p
->last_modified
, 0);
4672 XSETFASTINT (p
->last_overlay_modified
, 0);
4674 /* Adjust this window's edge. */
4675 XSETINT (CURSIZE (window
),
4676 XINT (CURSIZE (window
)) + delta
);
4678 /* If this window has following siblings in the desired dimension,
4679 make them smaller, and exit the loop.
4681 (If we reach the top of the tree and can never do this,
4682 we will fail and report an error, above.) */
4683 if (NILP (first_parallel
))
4685 if (!NILP (p
->next
))
4687 /* This may happen for the minibuffer. In that case
4688 the window_deletion_count check below does not work. */
4689 if (XINT (CURSIZE (p
->next
)) - delta
<= 0)
4691 Fset_window_configuration (old_config
);
4692 error ("Cannot adjust window size as specified");
4695 XSETINT (CURBEG (p
->next
),
4696 XINT (CURBEG (p
->next
)) + delta
);
4697 size_window (p
->next
, XINT (CURSIZE (p
->next
)) - delta
,
4698 horiz_flag
, 0, 1, 0);
4703 /* Here we have a chain of parallel siblings, in the other dimension.
4704 Change the size of the other siblings. */
4705 for (child
= first_parallel
;
4707 child
= XWINDOW (child
)->next
)
4708 if (! EQ (child
, window
))
4709 size_window (child
, XINT (CURSIZE (child
)) + delta
,
4710 horiz_flag
, 0, 0, 1);
4715 /* If we made a window so small it got deleted,
4716 we failed. Report failure. */
4717 if (delcount
!= window_deletion_count
)
4719 Fset_window_configuration (old_config
);
4720 error ("Cannot adjust window size as specified");
4723 /* Adjust glyph matrices. */
4724 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4730 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge
,
4731 Sadjust_window_trailing_edge
, 3, 3, 0,
4732 doc
: /* Adjust the bottom or right edge of WINDOW by DELTA.
4733 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4734 Otherwise, adjust the height, moving the bottom edge.
4736 Following siblings of the selected window are resized to fulfill
4737 the size request. If they become too small in the process, they
4738 are not deleted; instead, we signal an error. */)
4739 (window
, delta
, horizontal
)
4740 Lisp_Object window
, delta
, horizontal
;
4742 CHECK_NUMBER (delta
);
4744 window
= selected_window
;
4745 adjust_window_trailing_edge (window
, XINT (delta
), !NILP (horizontal
));
4747 run_window_configuration_change_hook
4748 (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4755 /***********************************************************************
4756 Resizing Mini-Windows
4757 ***********************************************************************/
4759 static void shrink_window_lowest_first
P_ ((struct window
*, int));
4761 enum save_restore_action
4768 static int save_restore_orig_size
P_ ((struct window
*,
4769 enum save_restore_action
));
4771 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4772 from lowest windows first. */
4775 shrink_window_lowest_first (w
, height
)
4783 xassert (!MINI_WINDOW_P (w
));
4785 /* Set redisplay hints. */
4786 XSETFASTINT (w
->last_modified
, 0);
4787 XSETFASTINT (w
->last_overlay_modified
, 0);
4788 windows_or_buffers_changed
++;
4789 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w
))) = 1;
4791 old_height
= XFASTINT (w
->total_lines
);
4792 XSETFASTINT (w
->total_lines
, height
);
4794 if (!NILP (w
->hchild
))
4796 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
4798 c
= XWINDOW (child
);
4799 c
->top_line
= w
->top_line
;
4800 shrink_window_lowest_first (c
, height
);
4803 else if (!NILP (w
->vchild
))
4805 Lisp_Object last_child
;
4806 int delta
= old_height
- height
;
4811 /* Find the last child. We are taking space from lowest windows
4812 first, so we iterate over children from the last child
4814 for (child
= w
->vchild
; WINDOWP (child
); child
= XWINDOW (child
)->next
)
4817 /* Size children down to their safe heights. */
4818 for (child
= last_child
; delta
&& !NILP (child
); child
= c
->prev
)
4822 c
= XWINDOW (child
);
4823 this_one
= XFASTINT (c
->total_lines
) - window_min_size_1 (c
, 0, 1);
4825 if (this_one
> delta
)
4828 shrink_window_lowest_first (c
, XFASTINT (c
->total_lines
) - this_one
);
4832 /* Compute new positions. */
4833 last_top
= XINT (w
->top_line
);
4834 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
4836 c
= XWINDOW (child
);
4837 c
->top_line
= make_number (last_top
);
4838 shrink_window_lowest_first (c
, XFASTINT (c
->total_lines
));
4839 last_top
+= XFASTINT (c
->total_lines
);
4845 /* Save, restore, or check positions and sizes in the window tree
4846 rooted at W. ACTION says what to do.
4848 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4849 orig_total_lines members are valid for all windows in the window
4850 tree. Value is non-zero if they are valid.
4852 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4853 orig_top_line and orig_total_lines for all windows in the tree.
4855 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4856 stored in orig_top_line and orig_total_lines for all windows. */
4859 save_restore_orig_size (w
, action
)
4861 enum save_restore_action action
;
4867 if (!NILP (w
->hchild
))
4869 if (!save_restore_orig_size (XWINDOW (w
->hchild
), action
))
4872 else if (!NILP (w
->vchild
))
4874 if (!save_restore_orig_size (XWINDOW (w
->vchild
), action
))
4880 case CHECK_ORIG_SIZES
:
4881 if (!INTEGERP (w
->orig_top_line
) || !INTEGERP (w
->orig_total_lines
))
4885 case SAVE_ORIG_SIZES
:
4886 w
->orig_top_line
= w
->top_line
;
4887 w
->orig_total_lines
= w
->total_lines
;
4888 XSETFASTINT (w
->last_modified
, 0);
4889 XSETFASTINT (w
->last_overlay_modified
, 0);
4892 case RESTORE_ORIG_SIZES
:
4893 xassert (INTEGERP (w
->orig_top_line
) && INTEGERP (w
->orig_total_lines
));
4894 w
->top_line
= w
->orig_top_line
;
4895 w
->total_lines
= w
->orig_total_lines
;
4896 w
->orig_total_lines
= w
->orig_top_line
= Qnil
;
4897 XSETFASTINT (w
->last_modified
, 0);
4898 XSETFASTINT (w
->last_overlay_modified
, 0);
4905 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
4912 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4913 without deleting other windows. */
4916 grow_mini_window (w
, delta
)
4920 struct frame
*f
= XFRAME (w
->frame
);
4921 struct window
*root
;
4923 xassert (MINI_WINDOW_P (w
));
4924 xassert (delta
>= 0);
4926 /* Compute how much we can enlarge the mini-window without deleting
4928 root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4931 int min_height
= window_min_size (root
, 0, 0, 0, 0);
4932 if (XFASTINT (root
->total_lines
) - delta
< min_height
)
4933 /* Note that the root window may already be smaller than
4935 delta
= max (0, XFASTINT (root
->total_lines
) - min_height
);
4940 /* Save original window sizes and positions, if not already done. */
4941 if (!save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
4942 save_restore_orig_size (root
, SAVE_ORIG_SIZES
);
4944 /* Shrink other windows. */
4945 shrink_window_lowest_first (root
, XFASTINT (root
->total_lines
) - delta
);
4947 /* Grow the mini-window. */
4948 w
->top_line
= make_number (XFASTINT (root
->top_line
) + XFASTINT (root
->total_lines
));
4949 w
->total_lines
= make_number (XFASTINT (w
->total_lines
) + delta
);
4950 XSETFASTINT (w
->last_modified
, 0);
4951 XSETFASTINT (w
->last_overlay_modified
, 0);
4958 /* Shrink mini-window W. If there is recorded info about window sizes
4959 before a call to grow_mini_window, restore recorded window sizes.
4960 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4964 shrink_mini_window (w
)
4967 struct frame
*f
= XFRAME (w
->frame
);
4968 struct window
*root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4970 if (save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
4972 save_restore_orig_size (root
, RESTORE_ORIG_SIZES
);
4974 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
4975 windows_or_buffers_changed
= 1;
4977 else if (XFASTINT (w
->total_lines
) > 1)
4979 /* Distribute the additional lines of the mini-window
4980 among the other windows. */
4982 XSETWINDOW (window
, w
);
4983 enlarge_window (window
, 1 - XFASTINT (w
->total_lines
), 0);
4989 /* Mark window cursors off for all windows in the window tree rooted
4990 at W by setting their phys_cursor_on_p flag to zero. Called from
4991 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4992 the frame are cleared. */
4995 mark_window_cursors_off (w
)
5000 if (!NILP (w
->hchild
))
5001 mark_window_cursors_off (XWINDOW (w
->hchild
));
5002 else if (!NILP (w
->vchild
))
5003 mark_window_cursors_off (XWINDOW (w
->vchild
));
5005 w
->phys_cursor_on_p
= 0;
5007 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
5012 /* Return number of lines of text (not counting mode lines) in W. */
5015 window_internal_height (w
)
5018 int ht
= XFASTINT (w
->total_lines
);
5020 if (!MINI_WINDOW_P (w
))
5022 if (!NILP (w
->parent
)
5023 || !NILP (w
->vchild
)
5024 || !NILP (w
->hchild
)
5027 || WINDOW_WANTS_MODELINE_P (w
))
5030 if (WINDOW_WANTS_HEADER_LINE_P (w
))
5038 /* Return the number of columns in W.
5039 Don't count columns occupied by scroll bars or the vertical bar
5040 separating W from the sibling to its right. */
5043 window_box_text_cols (w
)
5046 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5047 int width
= XINT (w
->total_cols
);
5049 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w
))
5050 /* Scroll bars occupy a few columns. */
5051 width
-= WINDOW_CONFIG_SCROLL_BAR_COLS (w
);
5052 else if (!FRAME_WINDOW_P (f
)
5053 && !WINDOW_RIGHTMOST_P (w
) && !WINDOW_FULL_WIDTH_P (w
))
5054 /* The column of `|' characters separating side-by-side windows
5055 occupies one column only. */
5058 if (FRAME_WINDOW_P (f
))
5059 /* On window-systems, fringes and display margins cannot be
5060 used for normal text. */
5061 width
-= (WINDOW_FRINGE_COLS (w
)
5062 + WINDOW_LEFT_MARGIN_COLS (w
)
5063 + WINDOW_RIGHT_MARGIN_COLS (w
));
5069 /************************************************************************
5071 ***********************************************************************/
5073 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
5074 N screen-fulls, which is defined as the height of the window minus
5075 next_screen_context_lines. If WHOLE is zero, scroll up N lines
5076 instead. Negative values of N mean scroll down. NOERROR non-zero
5077 means don't signal an error if we try to move over BEGV or ZV,
5081 window_scroll (window
, n
, whole
, noerror
)
5089 /* If we must, use the pixel-based version which is much slower than
5090 the line-based one but can handle varying line heights. */
5091 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window
)->frame
)))
5092 window_scroll_pixel_based (window
, n
, whole
, noerror
);
5094 window_scroll_line_based (window
, n
, whole
, noerror
);
5100 /* Implementation of window_scroll that works based on pixel line
5101 heights. See the comment of window_scroll for parameter
5105 window_scroll_pixel_based (window
, n
, whole
, noerror
)
5112 struct window
*w
= XWINDOW (window
);
5113 struct text_pos start
;
5114 int this_scroll_margin
;
5115 /* True if we fiddled the window vscroll field without really scrolling. */
5117 int x
, y
, rtop
, rbot
, rowh
, vpos
;
5119 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
5121 /* If PT is not visible in WINDOW, move back one half of
5122 the screen. Allow PT to be partially visible, otherwise
5123 something like (scroll-down 1) with PT in the line before
5124 the partially visible one would recenter. */
5126 if (!pos_visible_p (w
, PT
, &x
, &y
, &rtop
, &rbot
, &rowh
, &vpos
))
5128 /* Move backward half the height of the window. Performance note:
5129 vmotion used here is about 10% faster, but would give wrong
5130 results for variable height lines. */
5131 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
5132 it
.current_y
= it
.last_visible_y
;
5133 move_it_vertically_backward (&it
, window_box_height (w
) / 2);
5135 /* The function move_iterator_vertically may move over more than
5136 the specified y-distance. If it->w is small, e.g. a
5137 mini-buffer window, we may end up in front of the window's
5138 display area. This is the case when Start displaying at the
5139 start of the line containing PT in this case. */
5140 if (it
.current_y
<= 0)
5142 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
5143 move_it_vertically_backward (&it
, 0);
5147 start
= it
.current
.pos
;
5149 else if (auto_window_vscroll_p
)
5151 if (rtop
|| rbot
) /* partially visible */
5154 int dy
= WINDOW_FRAME_LINE_HEIGHT (w
);
5156 dy
= max ((window_box_height (w
)
5157 - next_screen_context_lines
* dy
),
5163 /* Only vscroll backwards if already vscrolled forwards. */
5164 if (w
->vscroll
< 0 && rtop
> 0)
5166 px
= max (0, -w
->vscroll
- min (rtop
, -dy
));
5167 Fset_window_vscroll (window
, make_number (px
), Qt
);
5173 /* Do vscroll if already vscrolled or only display line. */
5174 if (rbot
> 0 && (w
->vscroll
< 0 || vpos
== 0))
5176 px
= max (0, -w
->vscroll
+ min (rbot
, dy
));
5177 Fset_window_vscroll (window
, make_number (px
), Qt
);
5181 /* Maybe modify window start instead of scrolling. */
5182 if (rbot
> 0 || w
->vscroll
< 0)
5186 Fset_window_vscroll (window
, make_number (0), Qt
);
5187 /* If there are other text lines above the current row,
5188 move window start to current row. Else to next row. */
5190 spos
= XINT (Fline_beginning_position (Qnil
));
5192 spos
= min (XINT (Fline_end_position (Qnil
)) + 1, ZV
);
5193 set_marker_restricted (w
->start
, make_number (spos
),
5195 w
->start_at_line_beg
= Qt
;
5196 w
->update_mode_line
= Qt
;
5197 XSETFASTINT (w
->last_modified
, 0);
5198 XSETFASTINT (w
->last_overlay_modified
, 0);
5199 /* Set force_start so that redisplay_window will run the
5200 window-scroll-functions. */
5201 w
->force_start
= Qt
;
5206 /* Cancel previous vscroll. */
5207 Fset_window_vscroll (window
, make_number (0), Qt
);
5210 /* If scroll_preserve_screen_position is non-nil, we try to set
5211 point in the same window line as it is now, so get that line. */
5212 if (!NILP (Vscroll_preserve_screen_position
))
5214 /* We preserve the goal pixel coordinate across consecutive
5215 calls to scroll-up or scroll-down. This avoids the
5216 possibility of point becoming "stuck" on a tall line when
5217 scrolling by one line. */
5218 if (window_scroll_pixel_based_preserve_y
< 0
5219 || (!EQ (current_kboard
->Vlast_command
, Qscroll_up
)
5220 && !EQ (current_kboard
->Vlast_command
, Qscroll_down
)))
5222 start_display (&it
, w
, start
);
5223 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
5224 window_scroll_pixel_based_preserve_y
= it
.current_y
;
5225 window_scroll_pixel_based_preserve_x
= it
.current_x
;
5229 window_scroll_pixel_based_preserve_y
5230 = window_scroll_pixel_based_preserve_x
= -1;
5232 /* Move iterator it from start the specified distance forward or
5233 backward. The result is the new window start. */
5234 start_display (&it
, w
, start
);
5237 int start_pos
= IT_CHARPOS (it
);
5238 int dy
= WINDOW_FRAME_LINE_HEIGHT (w
);
5239 dy
= max ((window_box_height (w
)
5240 - next_screen_context_lines
* dy
),
5243 /* Note that move_it_vertically always moves the iterator to the
5244 start of a line. So, if the last line doesn't have a newline,
5245 we would end up at the start of the line ending at ZV. */
5248 move_it_vertically_backward (&it
, -dy
);
5249 /* Ensure we actually do move, e.g. in case we are currently
5250 looking at an image that is taller that the window height. */
5251 while (start_pos
== IT_CHARPOS (it
)
5252 && start_pos
> BEGV
)
5253 move_it_by_lines (&it
, -1, 1);
5257 move_it_to (&it
, ZV
, -1, it
.current_y
+ dy
, -1,
5258 MOVE_TO_POS
| MOVE_TO_Y
);
5259 /* Ensure we actually do move, e.g. in case we are currently
5260 looking at an image that is taller that the window height. */
5261 while (start_pos
== IT_CHARPOS (it
)
5263 move_it_by_lines (&it
, 1, 1);
5267 move_it_by_lines (&it
, n
, 1);
5269 /* We failed if we find ZV is already on the screen (scrolling up,
5270 means there's nothing past the end), or if we can't start any
5271 earlier (scrolling down, means there's nothing past the top). */
5272 if ((n
> 0 && IT_CHARPOS (it
) == ZV
)
5273 || (n
< 0 && IT_CHARPOS (it
) == CHARPOS (start
)))
5275 if (IT_CHARPOS (it
) == ZV
)
5277 if (it
.current_y
< it
.last_visible_y
5278 && (it
.current_y
+ it
.max_ascent
+ it
.max_descent
5279 > it
.last_visible_y
))
5281 /* The last line was only partially visible, make it fully
5283 w
->vscroll
= (it
.last_visible_y
5284 - it
.current_y
+ it
.max_ascent
+ it
.max_descent
);
5285 adjust_glyphs (it
.f
);
5289 else if (n
< 0) /* could happen with empty buffers */
5290 xsignal0 (Qbeginning_of_buffer
);
5292 xsignal0 (Qend_of_buffer
);
5296 if (w
->vscroll
!= 0)
5297 /* The first line was only partially visible, make it fully
5303 xsignal0 (Qbeginning_of_buffer
);
5306 /* If control gets here, then we vscrolled. */
5308 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
5310 /* Don't try to change the window start below. */
5316 int pos
= IT_CHARPOS (it
);
5319 /* If in the middle of a multi-glyph character move forward to
5320 the next character. */
5321 if (in_display_vector_p (&it
))
5324 move_it_to (&it
, pos
, -1, -1, -1, MOVE_TO_POS
);
5327 /* Set the window start, and set up the window for redisplay. */
5328 set_marker_restricted (w
->start
, make_number (pos
),
5330 bytepos
= XMARKER (w
->start
)->bytepos
;
5331 w
->start_at_line_beg
= ((pos
== BEGV
|| FETCH_BYTE (bytepos
- 1) == '\n')
5333 w
->update_mode_line
= Qt
;
5334 XSETFASTINT (w
->last_modified
, 0);
5335 XSETFASTINT (w
->last_overlay_modified
, 0);
5336 /* Set force_start so that redisplay_window will run the
5337 window-scroll-functions. */
5338 w
->force_start
= Qt
;
5341 /* The rest of this function uses current_y in a nonstandard way,
5342 not including the height of the header line if any. */
5343 it
.current_y
= it
.vpos
= 0;
5345 /* Move PT out of scroll margins.
5346 This code wants current_y to be zero at the window start position
5347 even if there is a header line. */
5348 this_scroll_margin
= max (0, scroll_margin
);
5349 this_scroll_margin
= min (this_scroll_margin
, XFASTINT (w
->total_lines
) / 4);
5350 this_scroll_margin
*= FRAME_LINE_HEIGHT (it
.f
);
5354 /* We moved the window start towards ZV, so PT may be now
5355 in the scroll margin at the top. */
5356 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
5357 if (IT_CHARPOS (it
) == PT
&& it
.current_y
>= this_scroll_margin
5358 && (NILP (Vscroll_preserve_screen_position
)
5359 || EQ (Vscroll_preserve_screen_position
, Qt
)))
5360 /* We found PT at a legitimate height. Leave it alone. */
5362 else if (window_scroll_pixel_based_preserve_y
>= 0)
5364 /* If we have a header line, take account of it.
5365 This is necessary because we set it.current_y to 0, above. */
5366 move_it_to (&it
, -1,
5367 window_scroll_pixel_based_preserve_x
,
5368 window_scroll_pixel_based_preserve_y
5369 - (WINDOW_WANTS_HEADER_LINE_P (w
) ? 1 : 0 ),
5370 -1, MOVE_TO_Y
| MOVE_TO_X
);
5371 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5375 while (it
.current_y
< this_scroll_margin
)
5377 int prev
= it
.current_y
;
5378 move_it_by_lines (&it
, 1, 1);
5379 if (prev
== it
.current_y
)
5382 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5387 int charpos
, bytepos
;
5390 /* Save our position, for the
5391 window_scroll_pixel_based_preserve_y case. */
5392 charpos
= IT_CHARPOS (it
);
5393 bytepos
= IT_BYTEPOS (it
);
5395 /* We moved the window start towards BEGV, so PT may be now
5396 in the scroll margin at the bottom. */
5397 move_it_to (&it
, PT
, -1,
5398 (it
.last_visible_y
- CURRENT_HEADER_LINE_HEIGHT (w
)
5399 - this_scroll_margin
- 1),
5401 MOVE_TO_POS
| MOVE_TO_Y
);
5403 /* Save our position, in case it's correct. */
5404 charpos
= IT_CHARPOS (it
);
5405 bytepos
= IT_BYTEPOS (it
);
5407 /* See if point is on a partially visible line at the end. */
5408 if (it
.what
== IT_EOB
)
5409 partial_p
= it
.current_y
+ it
.ascent
+ it
.descent
> it
.last_visible_y
;
5412 move_it_by_lines (&it
, 1, 1);
5413 partial_p
= it
.current_y
> it
.last_visible_y
;
5416 if (charpos
== PT
&& !partial_p
5417 && (NILP (Vscroll_preserve_screen_position
)
5418 || EQ (Vscroll_preserve_screen_position
, Qt
)))
5419 /* We found PT before we found the display margin, so PT is ok. */
5421 else if (window_scroll_pixel_based_preserve_y
>= 0)
5423 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
5424 start_display (&it
, w
, start
);
5425 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5426 here because we called start_display again and did not
5427 alter it.current_y this time. */
5428 move_it_to (&it
, -1, window_scroll_pixel_based_preserve_x
,
5429 window_scroll_pixel_based_preserve_y
, -1,
5430 MOVE_TO_Y
| MOVE_TO_X
);
5431 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5436 /* The last line was only partially visible, so back up two
5437 lines to make sure we're on a fully visible line. */
5439 move_it_by_lines (&it
, -2, 0);
5440 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5443 /* No, the position we saved is OK, so use it. */
5444 SET_PT_BOTH (charpos
, bytepos
);
5450 /* Implementation of window_scroll that works based on screen lines.
5451 See the comment of window_scroll for parameter descriptions. */
5454 window_scroll_line_based (window
, n
, whole
, noerror
)
5460 register struct window
*w
= XWINDOW (window
);
5461 register int opoint
= PT
, opoint_byte
= PT_BYTE
;
5462 register int pos
, pos_byte
;
5463 register int ht
= window_internal_height (w
);
5464 register Lisp_Object tem
;
5468 Lisp_Object original_pos
= Qnil
;
5470 /* If scrolling screen-fulls, compute the number of lines to
5471 scroll from the window's height. */
5473 n
*= max (1, ht
- next_screen_context_lines
);
5475 startpos
= marker_position (w
->start
);
5477 if (!NILP (Vscroll_preserve_screen_position
))
5479 if (window_scroll_preserve_vpos
<= 0
5480 || (!EQ (current_kboard
->Vlast_command
, Qscroll_up
)
5481 && !EQ (current_kboard
->Vlast_command
, Qscroll_down
)))
5483 struct position posit
5484 = *compute_motion (startpos
, 0, 0, 0,
5486 -1, XINT (w
->hscroll
),
5488 window_scroll_preserve_vpos
= posit
.vpos
;
5489 window_scroll_preserve_hpos
= posit
.hpos
+ XINT (w
->hscroll
);
5492 original_pos
= Fcons (make_number (window_scroll_preserve_hpos
),
5493 make_number (window_scroll_preserve_vpos
));
5496 XSETFASTINT (tem
, PT
);
5497 tem
= Fpos_visible_in_window_p (tem
, window
, Qnil
);
5501 Fvertical_motion (make_number (- (ht
/ 2)), window
);
5506 lose
= n
< 0 && PT
== BEGV
;
5507 Fvertical_motion (make_number (n
), window
);
5511 SET_PT_BOTH (opoint
, opoint_byte
);
5518 xsignal0 (Qbeginning_of_buffer
);
5523 int this_scroll_margin
= scroll_margin
;
5525 /* Don't use a scroll margin that is negative or too large. */
5526 if (this_scroll_margin
< 0)
5527 this_scroll_margin
= 0;
5529 if (XINT (w
->total_lines
) < 4 * scroll_margin
)
5530 this_scroll_margin
= XINT (w
->total_lines
) / 4;
5532 set_marker_restricted_both (w
->start
, w
->buffer
, pos
, pos_byte
);
5533 w
->start_at_line_beg
= bolp
;
5534 w
->update_mode_line
= Qt
;
5535 XSETFASTINT (w
->last_modified
, 0);
5536 XSETFASTINT (w
->last_overlay_modified
, 0);
5537 /* Set force_start so that redisplay_window will run
5538 the window-scroll-functions. */
5539 w
->force_start
= Qt
;
5541 if (!NILP (Vscroll_preserve_screen_position
)
5542 && (whole
|| !EQ (Vscroll_preserve_screen_position
, Qt
)))
5544 SET_PT_BOTH (pos
, pos_byte
);
5545 Fvertical_motion (original_pos
, window
);
5547 /* If we scrolled forward, put point enough lines down
5548 that it is outside the scroll margin. */
5553 if (this_scroll_margin
> 0)
5555 SET_PT_BOTH (pos
, pos_byte
);
5556 Fvertical_motion (make_number (this_scroll_margin
), window
);
5562 if (top_margin
<= opoint
)
5563 SET_PT_BOTH (opoint
, opoint_byte
);
5564 else if (!NILP (Vscroll_preserve_screen_position
))
5566 SET_PT_BOTH (pos
, pos_byte
);
5567 Fvertical_motion (original_pos
, window
);
5570 SET_PT (top_margin
);
5576 /* If we scrolled backward, put point near the end of the window
5577 but not within the scroll margin. */
5578 SET_PT_BOTH (pos
, pos_byte
);
5579 tem
= Fvertical_motion (make_number (ht
- this_scroll_margin
), window
);
5580 if (XFASTINT (tem
) == ht
- this_scroll_margin
)
5583 bottom_margin
= PT
+ 1;
5585 if (bottom_margin
> opoint
)
5586 SET_PT_BOTH (opoint
, opoint_byte
);
5589 if (!NILP (Vscroll_preserve_screen_position
))
5591 SET_PT_BOTH (pos
, pos_byte
);
5592 Fvertical_motion (original_pos
, window
);
5595 Fvertical_motion (make_number (-1), window
);
5604 xsignal0 (Qend_of_buffer
);
5609 /* Scroll selected_window up or down. If N is nil, scroll a
5610 screen-full which is defined as the height of the window minus
5611 next_screen_context_lines. If N is the symbol `-', scroll.
5612 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5613 up. This is the guts of Fscroll_up and Fscroll_down. */
5616 scroll_command (n
, direction
)
5620 int count
= SPECPDL_INDEX ();
5622 xassert (eabs (direction
) == 1);
5624 /* If selected window's buffer isn't current, make it current for
5625 the moment. But don't screw up if window_scroll gets an error. */
5626 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
5628 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
5629 Fset_buffer (XWINDOW (selected_window
)->buffer
);
5631 /* Make redisplay consider other windows than just selected_window. */
5632 ++windows_or_buffers_changed
;
5636 window_scroll (selected_window
, direction
, 1, 0);
5637 else if (EQ (n
, Qminus
))
5638 window_scroll (selected_window
, -direction
, 1, 0);
5641 n
= Fprefix_numeric_value (n
);
5642 window_scroll (selected_window
, XINT (n
) * direction
, 0, 0);
5645 unbind_to (count
, Qnil
);
5648 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "^P",
5649 doc
: /* Scroll text of current window upward ARG lines.
5650 If ARG is omitted or nil, scroll upward by a near full screen.
5651 A near full screen is `next-screen-context-lines' less than a full screen.
5652 Negative ARG means scroll downward.
5653 If ARG is the atom `-', scroll downward by nearly full screen.
5654 When calling from a program, supply as argument a number, nil, or `-'. */)
5658 scroll_command (arg
, 1);
5662 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "^P",
5663 doc
: /* Scroll text of current window down ARG lines.
5664 If ARG is omitted or nil, scroll down by a near full screen.
5665 A near full screen is `next-screen-context-lines' less than a full screen.
5666 Negative ARG means scroll upward.
5667 If ARG is the atom `-', scroll upward by nearly full screen.
5668 When calling from a program, supply as argument a number, nil, or `-'. */)
5672 scroll_command (arg
, -1);
5676 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling
, Sother_window_for_scrolling
, 0, 0, 0,
5677 doc
: /* Return the other window for \"other window scroll\" commands.
5678 If `other-window-scroll-buffer' is non-nil, a window
5679 showing that buffer is used.
5680 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5681 specifies the window. This takes precedence over
5682 `other-window-scroll-buffer'. */)
5687 if (MINI_WINDOW_P (XWINDOW (selected_window
))
5688 && !NILP (Vminibuf_scroll_window
))
5689 window
= Vminibuf_scroll_window
;
5690 /* If buffer is specified, scroll that buffer. */
5691 else if (!NILP (Vother_window_scroll_buffer
))
5693 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
5695 window
= Fdisplay_buffer (Vother_window_scroll_buffer
, Qt
, Qnil
);
5699 /* Nothing specified; look for a neighboring window on the same
5701 window
= Fnext_window (selected_window
, Qnil
, Qnil
);
5703 if (EQ (window
, selected_window
))
5704 /* That didn't get us anywhere; look for a window on another
5707 window
= Fnext_window (window
, Qnil
, Qt
);
5708 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window
))))
5709 && ! EQ (window
, selected_window
));
5712 CHECK_LIVE_WINDOW (window
);
5714 if (EQ (window
, selected_window
))
5715 error ("There is no other window");
5720 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
5721 doc
: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5722 A near full screen is `next-screen-context-lines' less than a full screen.
5723 The next window is the one below the current one; or the one at the top
5724 if the current one is at the bottom. Negative ARG means scroll downward.
5725 If ARG is the atom `-', scroll downward by nearly full screen.
5726 When calling from a program, supply as argument a number, nil, or `-'.
5728 If `other-window-scroll-buffer' is non-nil, scroll the window
5729 showing that buffer, popping the buffer up if necessary.
5730 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5731 specifies the window to scroll. This takes precedence over
5732 `other-window-scroll-buffer'. */)
5738 int count
= SPECPDL_INDEX ();
5740 window
= Fother_window_for_scrolling ();
5741 w
= XWINDOW (window
);
5743 /* Don't screw up if window_scroll gets an error. */
5744 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
5745 ++windows_or_buffers_changed
;
5747 Fset_buffer (w
->buffer
);
5748 SET_PT (marker_position (w
->pointm
));
5751 window_scroll (window
, 1, 1, 1);
5752 else if (EQ (arg
, Qminus
))
5753 window_scroll (window
, -1, 1, 1);
5759 window_scroll (window
, XINT (arg
), 0, 1);
5762 set_marker_both (w
->pointm
, Qnil
, PT
, PT_BYTE
);
5763 unbind_to (count
, Qnil
);
5768 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 0, 2, "^P\np",
5769 doc
: /* Scroll selected window display ARG columns left.
5770 Default for ARG is window width minus 2.
5771 Value is the total amount of leftward horizontal scrolling in
5772 effect after the change.
5773 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5774 lower bound for automatic scrolling, i.e. automatic scrolling
5775 will not scroll a window to a column less than the value returned
5776 by this function. This happens in an interactive call. */)
5778 register Lisp_Object arg
, set_minimum
;
5782 struct window
*w
= XWINDOW (selected_window
);
5785 XSETFASTINT (arg
, window_box_text_cols (w
) - 2);
5787 arg
= Fprefix_numeric_value (arg
);
5789 hscroll
= XINT (w
->hscroll
) + XINT (arg
);
5790 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
5792 if (!NILP (set_minimum
))
5793 w
->min_hscroll
= w
->hscroll
;
5798 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 0, 2, "^P\np",
5799 doc
: /* Scroll selected window display ARG columns right.
5800 Default for ARG is window width minus 2.
5801 Value is the total amount of leftward horizontal scrolling in
5802 effect after the change.
5803 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5804 lower bound for automatic scrolling, i.e. automatic scrolling
5805 will not scroll a window to a column less than the value returned
5806 by this function. This happens in an interactive call. */)
5808 register Lisp_Object arg
, set_minimum
;
5812 struct window
*w
= XWINDOW (selected_window
);
5815 XSETFASTINT (arg
, window_box_text_cols (w
) - 2);
5817 arg
= Fprefix_numeric_value (arg
);
5819 hscroll
= XINT (w
->hscroll
) - XINT (arg
);
5820 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
5822 if (!NILP (set_minimum
))
5823 w
->min_hscroll
= w
->hscroll
;
5828 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window
, Sminibuffer_selected_window
, 0, 0, 0,
5829 doc
: /* Return the window which was selected when entering the minibuffer.
5830 Returns nil, if current window is not a minibuffer window. */)
5833 if (minibuf_level
> 0
5834 && MINI_WINDOW_P (XWINDOW (selected_window
))
5835 && WINDOW_LIVE_P (minibuf_selected_window
))
5836 return minibuf_selected_window
;
5841 /* Value is the number of lines actually displayed in window W,
5842 as opposed to its height. */
5845 displayed_window_lines (w
)
5849 struct text_pos start
;
5850 int height
= window_box_height (w
);
5851 struct buffer
*old_buffer
;
5854 if (XBUFFER (w
->buffer
) != current_buffer
)
5856 old_buffer
= current_buffer
;
5857 set_buffer_internal (XBUFFER (w
->buffer
));
5862 /* In case W->start is out of the accessible range, do something
5863 reasonable. This happens in Info mode when Info-scroll-down
5864 calls (recenter -1) while W->start is 1. */
5865 if (XMARKER (w
->start
)->charpos
< BEGV
)
5866 SET_TEXT_POS (start
, BEGV
, BEGV_BYTE
);
5867 else if (XMARKER (w
->start
)->charpos
> ZV
)
5868 SET_TEXT_POS (start
, ZV
, ZV_BYTE
);
5870 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
5872 start_display (&it
, w
, start
);
5873 move_it_vertically (&it
, height
);
5874 bottom_y
= line_bottom_y (&it
);
5876 /* rms: On a non-window display,
5877 the value of it.vpos at the bottom of the screen
5878 seems to be 1 larger than window_box_height (w).
5879 This kludge fixes a bug whereby (move-to-window-line -1)
5880 when ZV is on the last screen line
5881 moves to the previous screen line instead of the last one. */
5882 if (! FRAME_WINDOW_P (XFRAME (w
->frame
)))
5885 /* Add in empty lines at the bottom of the window. */
5886 if (bottom_y
< height
)
5888 int uy
= FRAME_LINE_HEIGHT (it
.f
);
5889 it
.vpos
+= (height
- bottom_y
+ uy
- 1) / uy
;
5893 set_buffer_internal (old_buffer
);
5899 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
5900 doc
: /* Center point in window and redisplay frame.
5901 With prefix argument ARG, recenter putting point on screen line ARG
5902 relative to the current window. If ARG is negative, it counts up from the
5903 bottom of the window. (ARG should be less than the height of the window.)
5905 If ARG is omitted or nil, erase the entire frame and then redraw with point
5906 in the center of the current window. If `auto-resize-tool-bars' is set to
5907 `grow-only', this resets the tool-bar's height to the minimum height needed.
5909 Just C-u as prefix means put point in the center of the window
5910 and redisplay normally--don't erase and redraw the frame. */)
5912 register Lisp_Object arg
;
5914 struct window
*w
= XWINDOW (selected_window
);
5915 struct buffer
*buf
= XBUFFER (w
->buffer
);
5916 struct buffer
*obuf
= current_buffer
;
5918 int charpos
, bytepos
;
5920 int this_scroll_margin
;
5922 /* If redisplay is suppressed due to an error, try again. */
5923 obuf
->display_error_modiff
= 0;
5929 /* Invalidate pixel data calculated for all compositions. */
5930 for (i
= 0; i
< n_compositions
; i
++)
5931 composition_table
[i
]->font
= NULL
;
5933 WINDOW_XFRAME (w
)->minimize_tool_bar_window_p
= 1;
5935 Fredraw_frame (WINDOW_FRAME (w
));
5936 SET_FRAME_GARBAGED (WINDOW_XFRAME (w
));
5939 else if (CONSP (arg
)) /* Just C-u. */
5943 arg
= Fprefix_numeric_value (arg
);
5948 set_buffer_internal (buf
);
5950 /* Do this after making BUF current
5951 in case scroll_margin is buffer-local. */
5952 this_scroll_margin
= max (0, scroll_margin
);
5953 this_scroll_margin
= min (this_scroll_margin
,
5954 XFASTINT (w
->total_lines
) / 4);
5956 /* Handle centering on a graphical frame specially. Such frames can
5957 have variable-height lines and centering point on the basis of
5958 line counts would lead to strange effects. */
5959 if (FRAME_WINDOW_P (XFRAME (w
->frame
)))
5966 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
5967 start_display (&it
, w
, pt
);
5968 move_it_vertically_backward (&it
, window_box_height (w
) / 2);
5969 charpos
= IT_CHARPOS (it
);
5970 bytepos
= IT_BYTEPOS (it
);
5977 int extra_line_spacing
;
5978 int h
= window_box_height (w
);
5980 iarg
= - max (-iarg
, this_scroll_margin
);
5982 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
5983 start_display (&it
, w
, pt
);
5985 /* Be sure we have the exact height of the full line containing PT. */
5986 move_it_by_lines (&it
, 0, 1);
5988 /* The amount of pixels we have to move back is the window
5989 height minus what's displayed in the line containing PT,
5990 and the lines below. */
5993 move_it_by_lines (&it
, nlines
, 1);
5995 if (it
.vpos
== nlines
)
5999 /* Last line has no newline */
6000 h
-= line_bottom_y (&it
);
6004 /* Don't reserve space for extra line spacing of last line. */
6005 extra_line_spacing
= it
.max_extra_line_spacing
;
6007 /* If we can't move down NLINES lines because we hit
6008 the end of the buffer, count in some empty lines. */
6009 if (it
.vpos
< nlines
)
6012 extra_line_spacing
= it
.extra_line_spacing
;
6013 h
-= nlines
* (FRAME_LINE_HEIGHT (it
.f
) + extra_line_spacing
);
6018 /* Now find the new top line (starting position) of the window. */
6019 start_display (&it
, w
, pt
);
6021 move_it_vertically_backward (&it
, h
);
6023 /* If extra line spacing is present, we may move too far
6024 back. This causes the last line to be only partially
6025 visible (which triggers redisplay to recenter that line
6026 in the middle), so move forward.
6027 But ignore extra line spacing on last line, as it is not
6028 considered to be part of the visible height of the line.
6030 h
+= extra_line_spacing
;
6031 while (-it
.current_y
> h
)
6032 move_it_by_lines (&it
, 1, 1);
6034 charpos
= IT_CHARPOS (it
);
6035 bytepos
= IT_BYTEPOS (it
);
6039 struct position pos
;
6041 iarg
= max (iarg
, this_scroll_margin
);
6043 pos
= *vmotion (PT
, -iarg
, w
);
6044 charpos
= pos
.bufpos
;
6045 bytepos
= pos
.bytepos
;
6050 struct position pos
;
6051 int ht
= window_internal_height (w
);
6058 /* Don't let it get into the margin at either top or bottom. */
6059 iarg
= max (iarg
, this_scroll_margin
);
6060 iarg
= min (iarg
, ht
- this_scroll_margin
- 1);
6062 pos
= *vmotion (PT
, - iarg
, w
);
6063 charpos
= pos
.bufpos
;
6064 bytepos
= pos
.bytepos
;
6067 /* Set the new window start. */
6068 set_marker_both (w
->start
, w
->buffer
, charpos
, bytepos
);
6069 w
->window_end_valid
= Qnil
;
6071 w
->optional_new_start
= Qt
;
6073 if (bytepos
== BEGV_BYTE
|| FETCH_BYTE (bytepos
- 1) == '\n')
6074 w
->start_at_line_beg
= Qt
;
6076 w
->start_at_line_beg
= Qnil
;
6078 set_buffer_internal (obuf
);
6083 DEFUN ("window-text-height", Fwindow_text_height
, Swindow_text_height
,
6085 doc
: /* Return the height in lines of the text display area of WINDOW.
6086 WINDOW defaults to the selected window.
6087 This doesn't include the mode-line (or header-line if any) or any
6088 partial-height lines in the text display area. */)
6092 struct window
*w
= decode_window (window
);
6093 int pixel_height
= window_box_height (w
);
6094 int line_height
= pixel_height
/ FRAME_LINE_HEIGHT (XFRAME (w
->frame
));
6095 return make_number (line_height
);
6100 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
6102 doc
: /* Position point relative to window.
6103 With no argument, position point at center of window.
6104 An argument specifies vertical position within the window;
6105 zero means top of window, negative means relative to bottom of window. */)
6109 struct window
*w
= XWINDOW (selected_window
);
6113 int this_scroll_margin
;
6116 window
= selected_window
;
6117 start
= marker_position (w
->start
);
6118 if (start
< BEGV
|| start
> ZV
)
6120 int height
= window_internal_height (w
);
6121 Fvertical_motion (make_number (- (height
/ 2)), window
);
6122 set_marker_both (w
->start
, w
->buffer
, PT
, PT_BYTE
);
6123 w
->start_at_line_beg
= Fbolp ();
6124 w
->force_start
= Qt
;
6127 Fgoto_char (w
->start
);
6129 lines
= displayed_window_lines (w
);
6132 this_scroll_margin
= max (0, scroll_margin
);
6133 this_scroll_margin
= min (this_scroll_margin
, lines
/ 4);
6137 XSETFASTINT (arg
, lines
/ 2);
6140 int iarg
= XINT (Fprefix_numeric_value (arg
));
6143 iarg
= iarg
+ lines
;
6145 #if 0 /* This code would prevent move-to-window-line from moving point
6146 to a place inside the scroll margins (which would cause the
6147 next redisplay to scroll). I wrote this code, but then concluded
6148 it is probably better not to install it. However, it is here
6149 inside #if 0 so as not to lose it. -- rms. */
6151 /* Don't let it get into the margin at either top or bottom. */
6152 iarg
= max (iarg
, this_scroll_margin
);
6153 iarg
= min (iarg
, lines
- this_scroll_margin
- 1);
6156 arg
= make_number (iarg
);
6159 /* Skip past a partially visible first line. */
6161 XSETINT (arg
, XINT (arg
) + 1);
6163 return Fvertical_motion (arg
, window
);
6168 /***********************************************************************
6169 Window Configuration
6170 ***********************************************************************/
6172 struct save_window_data
6175 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
6176 Lisp_Object selected_frame
;
6177 Lisp_Object current_window
;
6178 Lisp_Object current_buffer
;
6179 Lisp_Object minibuf_scroll_window
;
6180 Lisp_Object minibuf_selected_window
;
6181 Lisp_Object root_window
;
6182 Lisp_Object focus_frame
;
6183 /* A vector, each of whose elements is a struct saved_window
6185 Lisp_Object saved_windows
;
6187 /* All fields above are traced by the GC.
6188 From `fame-cols' down, the fields are ignored by the GC. */
6190 int frame_cols
, frame_lines
, frame_menu_bar_lines
;
6191 int frame_tool_bar_lines
;
6194 /* This is saved as a Lisp_Vector */
6197 /* these first two must agree with struct Lisp_Vector in lisp.h */
6199 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
6202 Lisp_Object buffer
, start
, pointm
, mark
;
6203 Lisp_Object left_col
, top_line
, total_cols
, total_lines
;
6204 Lisp_Object hscroll
, min_hscroll
;
6205 Lisp_Object parent
, prev
;
6206 Lisp_Object start_at_line_beg
;
6207 Lisp_Object display_table
;
6208 Lisp_Object orig_top_line
, orig_total_lines
;
6209 Lisp_Object left_margin_cols
, right_margin_cols
;
6210 Lisp_Object left_fringe_width
, right_fringe_width
, fringes_outside_margins
;
6211 Lisp_Object scroll_bar_width
, vertical_scroll_bar_type
;
6212 Lisp_Object dedicated
, resize_proportionally
;
6215 #define SAVED_WINDOW_N(swv,n) \
6216 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
6218 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
6219 doc
: /* Return t if OBJECT is a window-configuration object. */)
6223 return WINDOW_CONFIGURATIONP (object
) ? Qt
: Qnil
;
6226 DEFUN ("window-configuration-frame", Fwindow_configuration_frame
, Swindow_configuration_frame
, 1, 1, 0,
6227 doc
: /* Return the frame that CONFIG, a window-configuration object, is about. */)
6231 register struct save_window_data
*data
;
6232 struct Lisp_Vector
*saved_windows
;
6234 CHECK_WINDOW_CONFIGURATION (config
);
6236 data
= (struct save_window_data
*) XVECTOR (config
);
6237 saved_windows
= XVECTOR (data
->saved_windows
);
6238 return XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
6241 DEFUN ("set-window-configuration", Fset_window_configuration
,
6242 Sset_window_configuration
, 1, 1, 0,
6243 doc
: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
6244 CONFIGURATION must be a value previously returned
6245 by `current-window-configuration' (which see).
6246 If CONFIGURATION was made from a frame that is now deleted,
6247 only frame-independent values can be restored. In this case,
6248 the return value is nil. Otherwise the value is t. */)
6250 Lisp_Object configuration
;
6252 register struct save_window_data
*data
;
6253 struct Lisp_Vector
*saved_windows
;
6254 Lisp_Object new_current_buffer
;
6259 CHECK_WINDOW_CONFIGURATION (configuration
);
6261 data
= (struct save_window_data
*) XVECTOR (configuration
);
6262 saved_windows
= XVECTOR (data
->saved_windows
);
6264 new_current_buffer
= data
->current_buffer
;
6265 if (NILP (XBUFFER (new_current_buffer
)->name
))
6266 new_current_buffer
= Qnil
;
6269 if (XBUFFER (new_current_buffer
) == current_buffer
)
6270 /* The code further down "preserves point" by saving here PT in
6271 old_point and then setting it later back into PT. When the
6272 current-selected-window and the final-selected-window both show
6273 the current buffer, this suffers from the problem that the
6274 current PT is the window-point of the current-selected-window,
6275 while the final PT is the point of the final-selected-window, so
6276 this copy from one PT to the other would end up moving the
6277 window-point of the final-selected-window to the window-point of
6278 the current-selected-window. So we have to be careful which
6279 point of the current-buffer we copy into old_point. */
6280 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
)
6281 && WINDOWP (selected_window
)
6282 && EQ (XWINDOW (selected_window
)->buffer
, new_current_buffer
)
6283 && !EQ (selected_window
, data
->current_window
))
6284 old_point
= XMARKER (XWINDOW (data
->current_window
)->pointm
)->charpos
;
6288 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6289 point in new_current_buffer as of the last time this buffer was
6290 used. This can be non-deterministic since it can be changed by
6291 things like jit-lock by mere temporary selection of some random
6292 window that happens to show this buffer.
6293 So if possible we want this arbitrary choice of "which point" to
6294 be the one from the to-be-selected-window so as to prevent this
6295 window's cursor from being copied from another window. */
6296 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
)
6297 /* If current_window = selected_window, its point is in BUF_PT. */
6298 && !EQ (selected_window
, data
->current_window
))
6299 old_point
= XMARKER (XWINDOW (data
->current_window
)->pointm
)->charpos
;
6301 old_point
= BUF_PT (XBUFFER (new_current_buffer
));
6304 frame
= XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
6307 /* If f is a dead frame, don't bother rebuilding its window tree.
6308 However, there is other stuff we should still try to do below. */
6309 if (FRAME_LIVE_P (f
))
6311 register struct window
*w
;
6312 register struct saved_window
*p
;
6313 struct window
*root_window
;
6314 struct window
**leaf_windows
;
6318 /* If the frame has been resized since this window configuration was
6319 made, we change the frame to the size specified in the
6320 configuration, restore the configuration, and then resize it
6321 back. We keep track of the prevailing height in these variables. */
6322 int previous_frame_lines
= FRAME_LINES (f
);
6323 int previous_frame_cols
= FRAME_COLS (f
);
6324 int previous_frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
6325 int previous_frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
6327 /* The mouse highlighting code could get screwed up
6328 if it runs during this. */
6331 if (data
->frame_lines
!= previous_frame_lines
6332 || data
->frame_cols
!= previous_frame_cols
)
6333 change_frame_size (f
, data
->frame_lines
,
6334 data
->frame_cols
, 0, 0, 0);
6335 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6336 if (data
->frame_menu_bar_lines
6337 != previous_frame_menu_bar_lines
)
6338 x_set_menu_bar_lines (f
, make_number (data
->frame_menu_bar_lines
),
6340 #ifdef HAVE_WINDOW_SYSTEM
6341 if (data
->frame_tool_bar_lines
6342 != previous_frame_tool_bar_lines
)
6343 x_set_tool_bar_lines (f
, make_number (data
->frame_tool_bar_lines
),
6348 /* "Swap out" point from the selected window's buffer
6349 into the window itself. (Normally the pointm of the selected
6350 window holds garbage.) We do this now, before
6351 restoring the window contents, and prevent it from
6352 being done later on when we select a new window. */
6353 if (! NILP (XWINDOW (selected_window
)->buffer
))
6355 w
= XWINDOW (selected_window
);
6356 set_marker_both (w
->pointm
,
6358 BUF_PT (XBUFFER (w
->buffer
)),
6359 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6362 windows_or_buffers_changed
++;
6363 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
6365 /* Problem: Freeing all matrices and later allocating them again
6366 is a serious redisplay flickering problem. What we would
6367 really like to do is to free only those matrices not reused
6369 root_window
= XWINDOW (FRAME_ROOT_WINDOW (f
));
6371 = (struct window
**) alloca (count_windows (root_window
)
6372 * sizeof (struct window
*));
6373 n_leaf_windows
= get_leaf_windows (root_window
, leaf_windows
, 0);
6376 Mark all windows now on frame as "deleted".
6377 Restoring the new configuration "undeletes" any that are in it.
6379 Save their current buffers in their height fields, since we may
6380 need it later, if a buffer saved in the configuration is now
6382 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6384 for (k
= 0; k
< saved_windows
->size
; k
++)
6386 p
= SAVED_WINDOW_N (saved_windows
, k
);
6387 w
= XWINDOW (p
->window
);
6390 if (!NILP (p
->parent
))
6391 w
->parent
= SAVED_WINDOW_N (saved_windows
,
6392 XFASTINT (p
->parent
))->window
;
6396 if (!NILP (p
->prev
))
6398 w
->prev
= SAVED_WINDOW_N (saved_windows
,
6399 XFASTINT (p
->prev
))->window
;
6400 XWINDOW (w
->prev
)->next
= p
->window
;
6405 if (!NILP (w
->parent
))
6407 if (EQ (p
->total_cols
, XWINDOW (w
->parent
)->total_cols
))
6409 XWINDOW (w
->parent
)->vchild
= p
->window
;
6410 XWINDOW (w
->parent
)->hchild
= Qnil
;
6414 XWINDOW (w
->parent
)->hchild
= p
->window
;
6415 XWINDOW (w
->parent
)->vchild
= Qnil
;
6420 /* If we squirreled away the buffer in the window's height,
6422 if (BUFFERP (w
->total_lines
))
6423 w
->buffer
= w
->total_lines
;
6424 w
->left_col
= p
->left_col
;
6425 w
->top_line
= p
->top_line
;
6426 w
->total_cols
= p
->total_cols
;
6427 w
->total_lines
= p
->total_lines
;
6428 w
->hscroll
= p
->hscroll
;
6429 w
->min_hscroll
= p
->min_hscroll
;
6430 w
->display_table
= p
->display_table
;
6431 w
->orig_top_line
= p
->orig_top_line
;
6432 w
->orig_total_lines
= p
->orig_total_lines
;
6433 w
->left_margin_cols
= p
->left_margin_cols
;
6434 w
->right_margin_cols
= p
->right_margin_cols
;
6435 w
->left_fringe_width
= p
->left_fringe_width
;
6436 w
->right_fringe_width
= p
->right_fringe_width
;
6437 w
->fringes_outside_margins
= p
->fringes_outside_margins
;
6438 w
->scroll_bar_width
= p
->scroll_bar_width
;
6439 w
->vertical_scroll_bar_type
= p
->vertical_scroll_bar_type
;
6440 w
->dedicated
= p
->dedicated
;
6441 w
->resize_proportionally
= p
->resize_proportionally
;
6442 XSETFASTINT (w
->last_modified
, 0);
6443 XSETFASTINT (w
->last_overlay_modified
, 0);
6445 /* Reinstall the saved buffer and pointers into it. */
6446 if (NILP (p
->buffer
))
6447 w
->buffer
= p
->buffer
;
6450 if (!NILP (XBUFFER (p
->buffer
)->name
))
6451 /* If saved buffer is alive, install it. */
6453 w
->buffer
= p
->buffer
;
6454 w
->start_at_line_beg
= p
->start_at_line_beg
;
6455 set_marker_restricted (w
->start
, p
->start
, w
->buffer
);
6456 set_marker_restricted (w
->pointm
, p
->pointm
, w
->buffer
);
6457 Fset_marker (XBUFFER (w
->buffer
)->mark
,
6458 p
->mark
, w
->buffer
);
6460 /* As documented in Fcurrent_window_configuration, don't
6461 restore the location of point in the buffer which was
6462 current when the window configuration was recorded. */
6463 if (!EQ (p
->buffer
, new_current_buffer
)
6464 && XBUFFER (p
->buffer
) == current_buffer
)
6465 Fgoto_char (w
->pointm
);
6467 else if (NILP (w
->buffer
) || NILP (XBUFFER (w
->buffer
)->name
))
6468 /* Else unless window has a live buffer, get one. */
6470 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
6471 /* This will set the markers to beginning of visible
6473 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
6474 set_marker_restricted (w
->pointm
, make_number (0),w
->buffer
);
6475 w
->start_at_line_beg
= Qt
;
6478 /* Keeping window's old buffer; make sure the markers
6481 /* Set window markers at start of visible range. */
6482 if (XMARKER (w
->start
)->buffer
== 0)
6483 set_marker_restricted (w
->start
, make_number (0),
6485 if (XMARKER (w
->pointm
)->buffer
== 0)
6486 set_marker_restricted_both (w
->pointm
, w
->buffer
,
6487 BUF_PT (XBUFFER (w
->buffer
)),
6488 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6489 w
->start_at_line_beg
= Qt
;
6494 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
6495 /* Prevent "swapping out point" in the old selected window
6496 using the buffer that has been restored into it.
6497 We already swapped out point that from that window's old buffer. */
6498 selected_window
= Qnil
;
6500 /* Arrange *not* to restore point in the buffer that was
6501 current when the window configuration was saved. */
6502 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
))
6503 set_marker_restricted (XWINDOW (data
->current_window
)->pointm
,
6504 make_number (old_point
),
6505 XWINDOW (data
->current_window
)->buffer
);
6507 Fselect_window (data
->current_window
, Qnil
);
6508 XBUFFER (XWINDOW (selected_window
)->buffer
)->last_selected_window
6511 if (NILP (data
->focus_frame
)
6512 || (FRAMEP (data
->focus_frame
)
6513 && FRAME_LIVE_P (XFRAME (data
->focus_frame
))))
6514 Fredirect_frame_focus (frame
, data
->focus_frame
);
6516 #if 0 /* I don't understand why this is needed, and it causes problems
6517 when the frame's old selected window has been deleted. */
6518 if (f
!= selected_frame
&& FRAME_WINDOW_P (f
))
6519 do_switch_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)),
6523 /* Set the screen height to the value it had before this function. */
6524 if (previous_frame_lines
!= FRAME_LINES (f
)
6525 || previous_frame_cols
!= FRAME_COLS (f
))
6526 change_frame_size (f
, previous_frame_lines
, previous_frame_cols
,
6528 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6529 if (previous_frame_menu_bar_lines
!= FRAME_MENU_BAR_LINES (f
))
6530 x_set_menu_bar_lines (f
, make_number (previous_frame_menu_bar_lines
),
6532 #ifdef HAVE_WINDOW_SYSTEM
6533 if (previous_frame_tool_bar_lines
!= FRAME_TOOL_BAR_LINES (f
))
6534 x_set_tool_bar_lines (f
, make_number (previous_frame_tool_bar_lines
),
6539 /* Now, free glyph matrices in windows that were not reused. */
6540 for (i
= n
= 0; i
< n_leaf_windows
; ++i
)
6542 if (NILP (leaf_windows
[i
]->buffer
))
6544 /* Assert it's not reused as a combination. */
6545 xassert (NILP (leaf_windows
[i
]->hchild
)
6546 && NILP (leaf_windows
[i
]->vchild
));
6547 free_window_matrices (leaf_windows
[i
]);
6549 else if (EQ (leaf_windows
[i
]->buffer
, new_current_buffer
))
6557 /* Fselect_window will have made f the selected frame, so we
6558 reselect the proper frame here. Fhandle_switch_frame will change the
6559 selected window too, but that doesn't make the call to
6560 Fselect_window above totally superfluous; it still sets f's
6562 if (FRAME_LIVE_P (XFRAME (data
->selected_frame
)))
6563 do_switch_frame (data
->selected_frame
, 0, 0);
6565 run_window_configuration_change_hook (f
);
6568 if (!NILP (new_current_buffer
))
6569 Fset_buffer (new_current_buffer
);
6571 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
6572 minibuf_selected_window
= data
->minibuf_selected_window
;
6574 return (FRAME_LIVE_P (f
) ? Qt
: Qnil
);
6577 /* Mark all windows now on frame as deleted
6578 by setting their buffers to nil. */
6581 delete_all_subwindows (w
)
6582 register struct window
*w
;
6584 if (!NILP (w
->next
))
6585 delete_all_subwindows (XWINDOW (w
->next
));
6586 if (!NILP (w
->vchild
))
6587 delete_all_subwindows (XWINDOW (w
->vchild
));
6588 if (!NILP (w
->hchild
))
6589 delete_all_subwindows (XWINDOW (w
->hchild
));
6591 w
->total_lines
= w
->buffer
; /* See Fset_window_configuration for excuse. */
6593 if (!NILP (w
->buffer
))
6596 /* We set all three of these fields to nil, to make sure that we can
6597 distinguish this dead window from any live window. Live leaf
6598 windows will have buffer set, and combination windows will have
6599 vchild or hchild set. */
6604 Vwindow_list
= Qnil
;
6608 count_windows (window
)
6609 register struct window
*window
;
6611 register int count
= 1;
6612 if (!NILP (window
->next
))
6613 count
+= count_windows (XWINDOW (window
->next
));
6614 if (!NILP (window
->vchild
))
6615 count
+= count_windows (XWINDOW (window
->vchild
));
6616 if (!NILP (window
->hchild
))
6617 count
+= count_windows (XWINDOW (window
->hchild
));
6622 /* Fill vector FLAT with leaf windows under W, starting at index I.
6623 Value is last index + 1. */
6626 get_leaf_windows (w
, flat
, i
)
6628 struct window
**flat
;
6633 if (!NILP (w
->hchild
))
6634 i
= get_leaf_windows (XWINDOW (w
->hchild
), flat
, i
);
6635 else if (!NILP (w
->vchild
))
6636 i
= get_leaf_windows (XWINDOW (w
->vchild
), flat
, i
);
6640 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6647 /* Return a pointer to the glyph W's physical cursor is on. Value is
6648 null if W's current matrix is invalid, so that no meaningfull glyph
6652 get_phys_cursor_glyph (w
)
6655 struct glyph_row
*row
;
6656 struct glyph
*glyph
;
6658 if (w
->phys_cursor
.vpos
>= 0
6659 && w
->phys_cursor
.vpos
< w
->current_matrix
->nrows
6660 && (row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
),
6662 && row
->used
[TEXT_AREA
] > w
->phys_cursor
.hpos
)
6663 glyph
= row
->glyphs
[TEXT_AREA
] + w
->phys_cursor
.hpos
;
6672 save_window_save (window
, vector
, i
)
6674 struct Lisp_Vector
*vector
;
6677 register struct saved_window
*p
;
6678 register struct window
*w
;
6679 register Lisp_Object tem
;
6681 for (;!NILP (window
); window
= w
->next
)
6683 p
= SAVED_WINDOW_N (vector
, i
);
6684 w
= XWINDOW (window
);
6686 XSETFASTINT (w
->temslot
, i
); i
++;
6688 p
->buffer
= w
->buffer
;
6689 p
->left_col
= w
->left_col
;
6690 p
->top_line
= w
->top_line
;
6691 p
->total_cols
= w
->total_cols
;
6692 p
->total_lines
= w
->total_lines
;
6693 p
->hscroll
= w
->hscroll
;
6694 p
->min_hscroll
= w
->min_hscroll
;
6695 p
->display_table
= w
->display_table
;
6696 p
->orig_top_line
= w
->orig_top_line
;
6697 p
->orig_total_lines
= w
->orig_total_lines
;
6698 p
->left_margin_cols
= w
->left_margin_cols
;
6699 p
->right_margin_cols
= w
->right_margin_cols
;
6700 p
->left_fringe_width
= w
->left_fringe_width
;
6701 p
->right_fringe_width
= w
->right_fringe_width
;
6702 p
->fringes_outside_margins
= w
->fringes_outside_margins
;
6703 p
->scroll_bar_width
= w
->scroll_bar_width
;
6704 p
->vertical_scroll_bar_type
= w
->vertical_scroll_bar_type
;
6705 p
->dedicated
= w
->dedicated
;
6706 p
->resize_proportionally
= w
->resize_proportionally
;
6707 if (!NILP (w
->buffer
))
6709 /* Save w's value of point in the window configuration.
6710 If w is the selected window, then get the value of point
6711 from the buffer; pointm is garbage in the selected window. */
6712 if (EQ (window
, selected_window
))
6714 p
->pointm
= Fmake_marker ();
6715 set_marker_both (p
->pointm
, w
->buffer
,
6716 BUF_PT (XBUFFER (w
->buffer
)),
6717 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6720 p
->pointm
= Fcopy_marker (w
->pointm
, Qnil
);
6722 p
->start
= Fcopy_marker (w
->start
, Qnil
);
6723 p
->start_at_line_beg
= w
->start_at_line_beg
;
6725 tem
= XBUFFER (w
->buffer
)->mark
;
6726 p
->mark
= Fcopy_marker (tem
, Qnil
);
6733 p
->start_at_line_beg
= Qnil
;
6736 if (NILP (w
->parent
))
6739 p
->parent
= XWINDOW (w
->parent
)->temslot
;
6744 p
->prev
= XWINDOW (w
->prev
)->temslot
;
6746 if (!NILP (w
->vchild
))
6747 i
= save_window_save (w
->vchild
, vector
, i
);
6748 if (!NILP (w
->hchild
))
6749 i
= save_window_save (w
->hchild
, vector
, i
);
6755 DEFUN ("current-window-configuration", Fcurrent_window_configuration
,
6756 Scurrent_window_configuration
, 0, 1, 0,
6757 doc
: /* Return an object representing the current window configuration of FRAME.
6758 If FRAME is nil or omitted, use the selected frame.
6759 This describes the number of windows, their sizes and current buffers,
6760 and for each displayed buffer, where display starts, and the positions of
6761 point and mark. An exception is made for point in the current buffer:
6762 its value is -not- saved.
6763 This also records the currently selected frame, and FRAME's focus
6764 redirection (see `redirect-frame-focus'). */)
6768 register Lisp_Object tem
;
6769 register int n_windows
;
6770 register struct save_window_data
*data
;
6775 frame
= selected_frame
;
6776 CHECK_LIVE_FRAME (frame
);
6779 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6780 data
= ALLOCATE_PSEUDOVECTOR (struct save_window_data
, frame_cols
,
6781 PVEC_WINDOW_CONFIGURATION
);
6783 data
->frame_cols
= FRAME_COLS (f
);
6784 data
->frame_lines
= FRAME_LINES (f
);
6785 data
->frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
6786 data
->frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
6787 data
->selected_frame
= selected_frame
;
6788 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
6789 XSETBUFFER (data
->current_buffer
, current_buffer
);
6790 data
->minibuf_scroll_window
= minibuf_level
> 0 ? Vminibuf_scroll_window
: Qnil
;
6791 data
->minibuf_selected_window
= minibuf_level
> 0 ? minibuf_selected_window
: Qnil
;
6792 data
->root_window
= FRAME_ROOT_WINDOW (f
);
6793 data
->focus_frame
= FRAME_FOCUS_FRAME (f
);
6794 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
6795 data
->saved_windows
= tem
;
6796 for (i
= 0; i
< n_windows
; i
++)
6797 XVECTOR (tem
)->contents
[i
]
6798 = Fmake_vector (make_number (VECSIZE (struct saved_window
)), Qnil
);
6799 save_window_save (FRAME_ROOT_WINDOW (f
), XVECTOR (tem
), 0);
6800 XSETWINDOW_CONFIGURATION (tem
, data
);
6804 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
6806 doc
: /* Execute BODY, preserving window sizes and contents.
6807 Return the value of the last form in BODY.
6808 Restore which buffer appears in which window, where display starts,
6809 and the value of point and mark for each window.
6810 Also restore the choice of selected window.
6811 Also restore which buffer is current.
6812 Does not restore the value of point in current buffer.
6813 usage: (save-window-excursion BODY...) */)
6817 register Lisp_Object val
;
6818 register int count
= SPECPDL_INDEX ();
6820 record_unwind_protect (Fset_window_configuration
,
6821 Fcurrent_window_configuration (Qnil
));
6822 val
= Fprogn (args
);
6823 return unbind_to (count
, val
);
6828 /***********************************************************************
6830 ***********************************************************************/
6836 Lisp_Object tail
= Qnil
;
6837 Lisp_Object result
= Qnil
;
6844 if (!NILP (w
->hchild
))
6845 wn
= Fcons (Qnil
, Fcons (Fwindow_edges (wn
),
6846 window_tree (XWINDOW (w
->hchild
))));
6847 else if (!NILP (w
->vchild
))
6848 wn
= Fcons (Qt
, Fcons (Fwindow_edges (wn
),
6849 window_tree (XWINDOW (w
->vchild
))));
6853 result
= tail
= Fcons (wn
, Qnil
);
6857 XSETCDR (tail
, Fcons (wn
, Qnil
));
6861 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6869 DEFUN ("window-tree", Fwindow_tree
, Swindow_tree
,
6871 doc
: /* Return the window tree for frame FRAME.
6873 The return value is a list of the form (ROOT MINI), where ROOT
6874 represents the window tree of the frame's root window, and MINI
6875 is the frame's minibuffer window.
6877 If the root window is not split, ROOT is the root window itself.
6878 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6879 horizontal split, and t for a vertical split, EDGES gives the combined
6880 size and position of the subwindows in the split, and the rest of the
6881 elements are the subwindows in the split. Each of the subwindows may
6882 again be a window or a list representing a window split, and so on.
6883 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6885 If FRAME is nil or omitted, return information on the currently
6893 frame
= selected_frame
;
6895 CHECK_FRAME (frame
);
6898 if (!FRAME_LIVE_P (f
))
6901 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6905 /***********************************************************************
6907 ***********************************************************************/
6909 DEFUN ("set-window-margins", Fset_window_margins
, Sset_window_margins
,
6911 doc
: /* Set width of marginal areas of window WINDOW.
6912 If WINDOW is nil, set margins of the currently selected window.
6913 Second arg LEFT-WIDTH specifies the number of character cells to
6914 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6915 does the same for the right marginal area. A nil width parameter
6916 means no margin. */)
6917 (window
, left_width
, right_width
)
6918 Lisp_Object window
, left_width
, right_width
;
6920 struct window
*w
= decode_window (window
);
6922 /* Translate negative or zero widths to nil.
6923 Margins that are too wide have to be checked elsewhere. */
6925 if (!NILP (left_width
))
6927 CHECK_NUMBER (left_width
);
6928 if (XINT (left_width
) <= 0)
6932 if (!NILP (right_width
))
6934 CHECK_NUMBER (right_width
);
6935 if (XINT (right_width
) <= 0)
6939 if (!EQ (w
->left_margin_cols
, left_width
)
6940 || !EQ (w
->right_margin_cols
, right_width
))
6942 w
->left_margin_cols
= left_width
;
6943 w
->right_margin_cols
= right_width
;
6945 adjust_window_margins (w
);
6947 ++windows_or_buffers_changed
;
6948 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6955 DEFUN ("window-margins", Fwindow_margins
, Swindow_margins
,
6957 doc
: /* Get width of marginal areas of window WINDOW.
6958 If WINDOW is omitted or nil, use the currently selected window.
6959 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6960 If a marginal area does not exist, its width will be returned
6965 struct window
*w
= decode_window (window
);
6966 return Fcons (w
->left_margin_cols
, w
->right_margin_cols
);
6971 /***********************************************************************
6973 ***********************************************************************/
6975 DEFUN ("set-window-fringes", Fset_window_fringes
, Sset_window_fringes
,
6977 doc
: /* Set the fringe widths of window WINDOW.
6978 If WINDOW is nil, set the fringe widths of the currently selected
6980 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6981 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6982 fringe width. If a fringe width arg is nil, that means to use the
6983 frame's default fringe width. Default fringe widths can be set with
6984 the command `set-fringe-style'.
6985 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6986 outside of the display margins. By default, fringes are drawn between
6987 display marginal areas and the text area. */)
6988 (window
, left_width
, right_width
, outside_margins
)
6989 Lisp_Object window
, left_width
, right_width
, outside_margins
;
6991 struct window
*w
= decode_window (window
);
6993 if (!NILP (left_width
))
6994 CHECK_NATNUM (left_width
);
6995 if (!NILP (right_width
))
6996 CHECK_NATNUM (right_width
);
6998 /* Do nothing on a tty. */
6999 if (FRAME_WINDOW_P (WINDOW_XFRAME (w
))
7000 && (!EQ (w
->left_fringe_width
, left_width
)
7001 || !EQ (w
->right_fringe_width
, right_width
)
7002 || !EQ (w
->fringes_outside_margins
, outside_margins
)))
7004 w
->left_fringe_width
= left_width
;
7005 w
->right_fringe_width
= right_width
;
7006 w
->fringes_outside_margins
= outside_margins
;
7008 adjust_window_margins (w
);
7010 clear_glyph_matrix (w
->current_matrix
);
7011 w
->window_end_valid
= Qnil
;
7013 ++windows_or_buffers_changed
;
7014 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
7021 DEFUN ("window-fringes", Fwindow_fringes
, Swindow_fringes
,
7023 doc
: /* Get width of fringes of window WINDOW.
7024 If WINDOW is omitted or nil, use the currently selected window.
7025 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
7029 struct window
*w
= decode_window (window
);
7031 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w
)),
7032 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w
)),
7033 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
7034 ? Qt
: Qnil
), Qnil
)));
7039 /***********************************************************************
7041 ***********************************************************************/
7043 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars
, Sset_window_scroll_bars
,
7045 doc
: /* Set width and type of scroll bars of window WINDOW.
7046 If window is nil, set scroll bars of the currently selected window.
7047 Second parameter WIDTH specifies the pixel width for the scroll bar;
7048 this is automatically adjusted to a multiple of the frame column width.
7049 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
7050 bar: left, right, or nil.
7051 If WIDTH is nil, use the frame's scroll-bar width.
7052 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
7053 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
7054 (window
, width
, vertical_type
, horizontal_type
)
7055 Lisp_Object window
, width
, vertical_type
, horizontal_type
;
7057 struct window
*w
= decode_window (window
);
7061 CHECK_NATNUM (width
);
7063 if (XINT (width
) == 0)
7064 vertical_type
= Qnil
;
7067 if (!(NILP (vertical_type
)
7068 || EQ (vertical_type
, Qleft
)
7069 || EQ (vertical_type
, Qright
)
7070 || EQ (vertical_type
, Qt
)))
7071 error ("Invalid type of vertical scroll bar");
7073 if (!EQ (w
->scroll_bar_width
, width
)
7074 || !EQ (w
->vertical_scroll_bar_type
, vertical_type
))
7076 w
->scroll_bar_width
= width
;
7077 w
->vertical_scroll_bar_type
= vertical_type
;
7079 adjust_window_margins (w
);
7081 clear_glyph_matrix (w
->current_matrix
);
7082 w
->window_end_valid
= Qnil
;
7084 ++windows_or_buffers_changed
;
7085 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
7092 DEFUN ("window-scroll-bars", Fwindow_scroll_bars
, Swindow_scroll_bars
,
7094 doc
: /* Get width and type of scroll bars of window WINDOW.
7095 If WINDOW is omitted or nil, use the currently selected window.
7096 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
7097 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
7102 struct window
*w
= decode_window (window
);
7103 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
)
7104 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
)
7105 : WINDOW_SCROLL_BAR_AREA_WIDTH (w
))),
7106 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w
)),
7107 Fcons (w
->vertical_scroll_bar_type
,
7108 Fcons (Qnil
, Qnil
))));
7113 /***********************************************************************
7115 ***********************************************************************/
7117 DEFUN ("window-vscroll", Fwindow_vscroll
, Swindow_vscroll
, 0, 2, 0,
7118 doc
: /* Return the amount by which WINDOW is scrolled vertically.
7119 Use the selected window if WINDOW is nil or omitted.
7120 Normally, value is a multiple of the canonical character height of WINDOW;
7121 optional second arg PIXELS-P means value is measured in pixels. */)
7123 Lisp_Object window
, pixels_p
;
7130 window
= selected_window
;
7132 CHECK_WINDOW (window
);
7133 w
= XWINDOW (window
);
7134 f
= XFRAME (w
->frame
);
7136 if (FRAME_WINDOW_P (f
))
7137 result
= (NILP (pixels_p
)
7138 ? FRAME_CANON_Y_FROM_PIXEL_Y (f
, -w
->vscroll
)
7139 : make_number (-w
->vscroll
));
7141 result
= make_number (0);
7146 DEFUN ("set-window-vscroll", Fset_window_vscroll
, Sset_window_vscroll
,
7148 doc
: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
7149 WINDOW nil means use the selected window. Normally, VSCROLL is a
7150 non-negative multiple of the canonical character height of WINDOW;
7151 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
7152 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
7153 corresponds to an integral number of pixels. The return value is the
7154 result of this rounding.
7155 If PIXELS-P is non-nil, the return value is VSCROLL. */)
7156 (window
, vscroll
, pixels_p
)
7157 Lisp_Object window
, vscroll
, pixels_p
;
7163 window
= selected_window
;
7165 CHECK_WINDOW (window
);
7166 CHECK_NUMBER_OR_FLOAT (vscroll
);
7168 w
= XWINDOW (window
);
7169 f
= XFRAME (w
->frame
);
7171 if (FRAME_WINDOW_P (f
))
7173 int old_dy
= w
->vscroll
;
7175 w
->vscroll
= - (NILP (pixels_p
)
7176 ? FRAME_LINE_HEIGHT (f
) * XFLOATINT (vscroll
)
7177 : XFLOATINT (vscroll
));
7178 w
->vscroll
= min (w
->vscroll
, 0);
7180 if (w
->vscroll
!= old_dy
)
7182 /* Adjust glyph matrix of the frame if the virtual display
7183 area becomes larger than before. */
7184 if (w
->vscroll
< 0 && w
->vscroll
< old_dy
)
7187 /* Prevent redisplay shortcuts. */
7188 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
7192 return Fwindow_vscroll (window
, pixels_p
);
7196 /* Call FN for all leaf windows on frame F. FN is called with the
7197 first argument being a pointer to the leaf window, and with
7198 additional argument USER_DATA. Stops when FN returns 0. */
7201 foreach_window (f
, fn
, user_data
)
7203 int (* fn
) P_ ((struct window
*, void *));
7206 /* Fdelete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
7207 if (WINDOWP (FRAME_ROOT_WINDOW (f
)))
7208 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f
)), fn
, user_data
);
7212 /* Helper function for foreach_window. Call FN for all leaf windows
7213 reachable from W. FN is called with the first argument being a
7214 pointer to the leaf window, and with additional argument USER_DATA.
7215 Stop when FN returns 0. Value is 0 if stopped by FN. */
7218 foreach_window_1 (w
, fn
, user_data
)
7220 int (* fn
) P_ ((struct window
*, void *));
7225 for (cont
= 1; w
&& cont
;)
7227 if (!NILP (w
->hchild
))
7228 cont
= foreach_window_1 (XWINDOW (w
->hchild
), fn
, user_data
);
7229 else if (!NILP (w
->vchild
))
7230 cont
= foreach_window_1 (XWINDOW (w
->vchild
), fn
, user_data
);
7232 cont
= fn (w
, user_data
);
7234 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
7241 /* Freeze or unfreeze the window start of W unless it is a
7242 mini-window or the selected window. FREEZE_P non-null means freeze
7243 the window start. */
7246 freeze_window_start (w
, freeze_p
)
7250 if (MINI_WINDOW_P (w
)
7251 || (WINDOWP (selected_window
) /* Can be nil in corner cases. */
7252 && (w
== XWINDOW (selected_window
)
7253 || (MINI_WINDOW_P (XWINDOW (selected_window
))
7254 && ! NILP (Vminibuf_scroll_window
)
7255 && w
== XWINDOW (Vminibuf_scroll_window
)))))
7258 w
->frozen_window_start_p
= freeze_p
!= NULL
;
7263 /* Freeze or unfreeze the window starts of all leaf windows on frame
7264 F, except the selected window and a mini-window. FREEZE_P non-zero
7265 means freeze the window start. */
7268 freeze_window_starts (f
, freeze_p
)
7272 foreach_window (f
, freeze_window_start
, (void *) (freeze_p
? f
: 0));
7276 /***********************************************************************
7278 ***********************************************************************/
7280 /* Return 1 if window configurations C1 and C2
7281 describe the same state of affairs. This is used by Fequal. */
7284 compare_window_configurations (c1
, c2
, ignore_positions
)
7286 int ignore_positions
;
7288 register struct save_window_data
*d1
, *d2
;
7289 struct Lisp_Vector
*sw1
, *sw2
;
7292 CHECK_WINDOW_CONFIGURATION (c1
);
7293 CHECK_WINDOW_CONFIGURATION (c2
);
7295 d1
= (struct save_window_data
*) XVECTOR (c1
);
7296 d2
= (struct save_window_data
*) XVECTOR (c2
);
7297 sw1
= XVECTOR (d1
->saved_windows
);
7298 sw2
= XVECTOR (d2
->saved_windows
);
7300 if (d1
->frame_cols
!= d2
->frame_cols
)
7302 if (d1
->frame_lines
!= d2
->frame_lines
)
7304 if (d1
->frame_menu_bar_lines
!= d2
->frame_menu_bar_lines
)
7306 if (! EQ (d1
->selected_frame
, d2
->selected_frame
))
7308 /* Don't compare the current_window field directly.
7309 Instead see w1_is_current and w2_is_current, below. */
7310 if (! EQ (d1
->current_buffer
, d2
->current_buffer
))
7312 if (! ignore_positions
)
7314 if (! EQ (d1
->minibuf_scroll_window
, d2
->minibuf_scroll_window
))
7316 if (! EQ (d1
->minibuf_selected_window
, d2
->minibuf_selected_window
))
7319 /* Don't compare the root_window field.
7320 We don't require the two configurations
7321 to use the same window object,
7322 and the two root windows must be equivalent
7323 if everything else compares equal. */
7324 if (! EQ (d1
->focus_frame
, d2
->focus_frame
))
7327 /* Verify that the two confis have the same number of windows. */
7328 if (sw1
->size
!= sw2
->size
)
7331 for (i
= 0; i
< sw1
->size
; i
++)
7333 struct saved_window
*p1
, *p2
;
7334 int w1_is_current
, w2_is_current
;
7336 p1
= SAVED_WINDOW_N (sw1
, i
);
7337 p2
= SAVED_WINDOW_N (sw2
, i
);
7339 /* Verify that the current windows in the two
7340 configurations correspond to each other. */
7341 w1_is_current
= EQ (d1
->current_window
, p1
->window
);
7342 w2_is_current
= EQ (d2
->current_window
, p2
->window
);
7344 if (w1_is_current
!= w2_is_current
)
7347 /* Verify that the corresponding windows do match. */
7348 if (! EQ (p1
->buffer
, p2
->buffer
))
7350 if (! EQ (p1
->left_col
, p2
->left_col
))
7352 if (! EQ (p1
->top_line
, p2
->top_line
))
7354 if (! EQ (p1
->total_cols
, p2
->total_cols
))
7356 if (! EQ (p1
->total_lines
, p2
->total_lines
))
7358 if (! EQ (p1
->display_table
, p2
->display_table
))
7360 if (! EQ (p1
->parent
, p2
->parent
))
7362 if (! EQ (p1
->prev
, p2
->prev
))
7364 if (! ignore_positions
)
7366 if (! EQ (p1
->hscroll
, p2
->hscroll
))
7368 if (!EQ (p1
->min_hscroll
, p2
->min_hscroll
))
7370 if (! EQ (p1
->start_at_line_beg
, p2
->start_at_line_beg
))
7372 if (NILP (Fequal (p1
->start
, p2
->start
)))
7374 if (NILP (Fequal (p1
->pointm
, p2
->pointm
)))
7376 if (NILP (Fequal (p1
->mark
, p2
->mark
)))
7379 if (! EQ (p1
->left_margin_cols
, p2
->left_margin_cols
))
7381 if (! EQ (p1
->right_margin_cols
, p2
->right_margin_cols
))
7383 if (! EQ (p1
->left_fringe_width
, p2
->left_fringe_width
))
7385 if (! EQ (p1
->right_fringe_width
, p2
->right_fringe_width
))
7387 if (! EQ (p1
->fringes_outside_margins
, p2
->fringes_outside_margins
))
7389 if (! EQ (p1
->scroll_bar_width
, p2
->scroll_bar_width
))
7391 if (! EQ (p1
->vertical_scroll_bar_type
, p2
->vertical_scroll_bar_type
))
7398 DEFUN ("compare-window-configurations", Fcompare_window_configurations
,
7399 Scompare_window_configurations
, 2, 2, 0,
7400 doc
: /* Compare two window configurations as regards the structure of windows.
7401 This function ignores details such as the values of point and mark
7402 and scrolling positions. */)
7406 if (compare_window_configurations (x
, y
, 1))
7414 struct frame
*f
= make_initial_frame ();
7415 XSETFRAME (selected_frame
, f
);
7416 Vterminal_frame
= selected_frame
;
7417 minibuf_window
= f
->minibuffer_window
;
7418 selected_window
= f
->selected_window
;
7419 last_nonminibuf_frame
= f
;
7421 window_initialized
= 1;
7427 Vwindow_list
= Qnil
;
7433 Qscroll_up
= intern ("scroll-up");
7434 staticpro (&Qscroll_up
);
7436 Qscroll_down
= intern ("scroll-down");
7437 staticpro (&Qscroll_down
);
7439 Qwindow_size_fixed
= intern ("window-size-fixed");
7440 staticpro (&Qwindow_size_fixed
);
7441 Fset (Qwindow_size_fixed
, Qnil
);
7443 staticpro (&Qwindow_configuration_change_hook
);
7444 Qwindow_configuration_change_hook
7445 = intern ("window-configuration-change-hook");
7447 Qwindowp
= intern ("windowp");
7448 staticpro (&Qwindowp
);
7450 Qwindow_configuration_p
= intern ("window-configuration-p");
7451 staticpro (&Qwindow_configuration_p
);
7453 Qwindow_live_p
= intern ("window-live-p");
7454 staticpro (&Qwindow_live_p
);
7456 Qtemp_buffer_show_hook
= intern ("temp-buffer-show-hook");
7457 staticpro (&Qtemp_buffer_show_hook
);
7459 staticpro (&Vwindow_list
);
7461 minibuf_selected_window
= Qnil
;
7462 staticpro (&minibuf_selected_window
);
7464 window_scroll_pixel_based_preserve_x
= -1;
7465 window_scroll_pixel_based_preserve_y
= -1;
7466 window_scroll_preserve_hpos
= -1;
7467 window_scroll_preserve_vpos
= -1;
7469 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
7470 doc
: /* Non-nil means call as function to display a help buffer.
7471 The function is called with one argument, the buffer to be displayed.
7472 Used by `with-output-to-temp-buffer'.
7473 If this function is used, then it must do the entire job of showing
7474 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7475 Vtemp_buffer_show_function
= Qnil
;
7477 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function
,
7478 doc
: /* If non-nil, function to call to handle `display-buffer'.
7479 It will receive two args, the buffer and a flag which if non-nil means
7480 that the currently selected window is not acceptable.
7481 It should choose or create a window, display the specified buffer in it,
7482 and return the window.
7483 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
7484 work using this function. */);
7485 Vdisplay_buffer_function
= Qnil
;
7487 DEFVAR_LISP ("even-window-heights", &Veven_window_heights
,
7488 doc
: /* *If non-nil, `display-buffer' should even the window heights.
7489 If nil, `display-buffer' will leave the window configuration alone. */);
7490 Veven_window_heights
= Qt
;
7492 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
7493 doc
: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7494 Vminibuf_scroll_window
= Qnil
;
7496 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows
,
7497 doc
: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7498 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7499 is displayed in the `mode-line' face. */);
7500 mode_line_in_non_selected_windows
= 1;
7502 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
7503 doc
: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7504 Vother_window_scroll_buffer
= Qnil
;
7506 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames
,
7507 doc
: /* *Non-nil means `display-buffer' should make a separate frame. */);
7510 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p
,
7511 doc
: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7512 auto_window_vscroll_p
= 1;
7514 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames
,
7515 doc
: /* *Non-nil means `display-buffer' should reuse frames.
7516 If the buffer in question is already displayed in a frame, raise that frame. */);
7517 display_buffer_reuse_frames
= 0;
7519 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function
,
7520 doc
: /* Function to call to handle automatic new frame creation.
7521 It is called with no arguments and should return a newly created frame.
7523 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
7524 where `pop-up-frame-alist' would hold the default frame parameters. */);
7525 Vpop_up_frame_function
= Qnil
;
7527 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names
,
7528 doc
: /* *List of buffer names that should have their own special frames.
7529 Displaying a buffer with `display-buffer' or `pop-to-buffer',
7530 if its name is in this list, makes a special frame for it
7531 using `special-display-function'. See also `special-display-regexps'.
7533 An element of the list can be a list instead of just a string.
7534 There are two ways to use a list as an element:
7535 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
7536 In the first case, the FRAME-PARAMETERS are pairs of the form
7537 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7538 In the second case, FUNCTION is called with BUFFER as the first argument,
7539 followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
7540 All this is done by the function found in `special-display-function'.
7542 If the specified frame parameters include (same-buffer . t), the
7543 buffer is displayed in the currently selected window. Otherwise, if
7544 they include (same-frame . t), the buffer is displayed in a new window
7545 in the currently selected frame.
7547 If this variable appears \"not to work\", because you add a name to it
7548 but that buffer still appears in the selected window, look at the
7549 values of `same-window-buffer-names' and `same-window-regexps'.
7550 Those variables take precedence over this one. */);
7551 Vspecial_display_buffer_names
= Qnil
;
7553 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps
,
7554 doc
: /* *List of regexps saying which buffers should have their own special frames.
7555 When displaying a buffer with `display-buffer' or `pop-to-buffer',
7556 if any regexp in this list matches the buffer name, it makes a
7557 special frame for the buffer by calling `special-display-function'.
7559 An element of the list can be a list instead of just a string.
7560 There are two ways to use a list as an element:
7561 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
7562 In the first case, the FRAME-PARAMETERS are pairs of the form
7563 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7564 In the second case, FUNCTION is called with BUFFER as the first argument,
7565 followed by the OTHER-ARGS--it can display the buffer in any way it likes.
7566 All this is done by the function found in `special-display-function'.
7568 If the specified frame parameters include (same-buffer . t), the
7569 buffer is displayed in the currently selected window. Otherwise, if
7570 they include (same-frame . t), the buffer is displayed in a new window
7571 in the currently selected frame.
7573 If this variable appears \"not to work\", because you add a regexp to it
7574 but the matching buffers still appear in the selected window, look at the
7575 values of `same-window-buffer-names' and `same-window-regexps'.
7576 Those variables take precedence over this one. */);
7577 Vspecial_display_regexps
= Qnil
;
7579 DEFVAR_LISP ("special-display-function", &Vspecial_display_function
,
7580 doc
: /* Function to call to make a new frame for a special buffer.
7581 It is called with two arguments, the buffer and optional buffer specific
7582 data, and should return a window displaying that buffer.
7583 The default value normally makes a separate frame for the buffer,
7584 using `special-display-frame-alist' to specify the frame parameters.
7585 But if the buffer specific data includes (same-buffer . t) then the
7586 buffer is displayed in the current selected window.
7587 Otherwise if it includes (same-frame . t) then the buffer is displayed in
7588 a new window in the currently selected frame.
7590 A buffer is special if it is listed in `special-display-buffer-names'
7591 or matches a regexp in `special-display-regexps'. */);
7592 Vspecial_display_function
= Qnil
;
7594 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names
,
7595 doc
: /* *List of buffer names that should appear in the selected window.
7596 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
7597 switches to it in the selected window, rather than making it appear
7598 in some other window.
7600 An element of the list can be a cons cell instead of just a string.
7601 Then the car must be a string, which specifies the buffer name.
7602 This is for compatibility with `special-display-buffer-names';
7603 the cdr of the cons cell is ignored.
7605 See also `same-window-regexps'. */);
7606 Vsame_window_buffer_names
= Qnil
;
7608 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps
,
7609 doc
: /* *List of regexps saying which buffers should appear in the selected window.
7610 If a buffer name matches one of these regexps, then displaying it
7611 using `display-buffer' or `pop-to-buffer' switches to it
7612 in the selected window, rather than making it appear in some other window.
7614 An element of the list can be a cons cell instead of just a string.
7615 Then the car must be a string, which specifies the buffer name.
7616 This is for compatibility with `special-display-buffer-names';
7617 the cdr of the cons cell is ignored.
7619 See also `same-window-buffer-names'. */);
7620 Vsame_window_regexps
= Qnil
;
7622 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows
,
7623 doc
: /* *Non-nil means display-buffer should make new windows. */);
7626 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
7627 doc
: /* *Number of lines of continuity when scrolling by screenfuls. */);
7628 next_screen_context_lines
= 2;
7630 DEFVAR_INT ("split-height-threshold", &split_height_threshold
,
7631 doc
: /* *A window must be at least this tall to be eligible for splitting
7632 by `display-buffer'. The value is in line units.
7633 If there is only one window, it is split regardless of this value. */);
7634 split_height_threshold
= 500;
7636 DEFVAR_LISP ("split-window-preferred-function",
7637 &Vsplit_window_preferred_function
,
7638 doc
: /* Function to use to split a window.
7639 This is used by `display-buffer' to allow the user to choose whether
7640 to split windows horizontally or vertically or some mix of the two.
7641 When this variable is nil, `display-buffer' splits windows vertically.
7642 Otherwise, `display-buffer' calls this function to split a window.
7643 It is called with a window as single argument and should split it in two
7644 and return the new window, or return an appropriate existing window
7645 if splitting is not eligible. */);
7646 Vsplit_window_preferred_function
= Qnil
;
7648 DEFVAR_INT ("window-min-height", &window_min_height
,
7649 doc
: /* Allow deleting windows less than this tall.
7650 The value is measured in line units. If a window wants a modeline it
7651 is counted as one line.
7653 Emacs honors settings of this variable when enlarging or shrinking
7654 windows vertically. A value less than 1 is invalid. */);
7655 window_min_height
= 4;
7657 DEFVAR_INT ("window-min-width", &window_min_width
,
7658 doc
: /* Allow deleting windows less than this wide.
7659 The value is measured in characters and includes any fringes or
7662 Emacs honors settings of this variable when enlarging or shrinking
7663 windows horizontally. A value less than 2 is invalid. */);
7664 window_min_width
= 10;
7666 DEFVAR_LISP ("scroll-preserve-screen-position",
7667 &Vscroll_preserve_screen_position
,
7668 doc
: /* *Controls if scroll commands move point to keep its screen position unchanged.
7669 A value of nil means point does not keep its screen position except
7670 at the scroll margin or window boundary respectively.
7671 A value of t means point keeps its screen position if the scroll
7672 command moved it vertically out of the window, e.g. when scrolling
7674 Any other value means point always keeps its screen position. */);
7675 Vscroll_preserve_screen_position
= Qnil
;
7677 DEFVAR_LISP ("window-configuration-change-hook",
7678 &Vwindow_configuration_change_hook
,
7679 doc
: /* Functions to call when window configuration changes.
7680 The buffer-local part is run once per window, with the relevant window
7681 selected; while the global part is run only once for the modified frame,
7682 with the relevant frame selected. */);
7683 Vwindow_configuration_change_hook
= Qnil
;
7685 defsubr (&Sselected_window
);
7686 defsubr (&Sminibuffer_window
);
7687 defsubr (&Swindow_minibuffer_p
);
7688 defsubr (&Swindowp
);
7689 defsubr (&Swindow_live_p
);
7690 defsubr (&Spos_visible_in_window_p
);
7691 defsubr (&Swindow_line_height
);
7692 defsubr (&Swindow_buffer
);
7693 defsubr (&Swindow_height
);
7694 defsubr (&Swindow_width
);
7695 defsubr (&Swindow_full_width_p
);
7696 defsubr (&Swindow_hscroll
);
7697 defsubr (&Sset_window_hscroll
);
7698 defsubr (&Swindow_redisplay_end_trigger
);
7699 defsubr (&Sset_window_redisplay_end_trigger
);
7700 defsubr (&Swindow_edges
);
7701 defsubr (&Swindow_pixel_edges
);
7702 defsubr (&Swindow_inside_edges
);
7703 defsubr (&Swindow_inside_pixel_edges
);
7704 defsubr (&Scoordinates_in_window_p
);
7705 defsubr (&Swindow_at
);
7706 defsubr (&Swindow_point
);
7707 defsubr (&Swindow_start
);
7708 defsubr (&Swindow_end
);
7709 defsubr (&Sset_window_point
);
7710 defsubr (&Sset_window_start
);
7711 defsubr (&Swindow_dedicated_p
);
7712 defsubr (&Sset_window_dedicated_p
);
7713 defsubr (&Swindow_display_table
);
7714 defsubr (&Sset_window_display_table
);
7715 defsubr (&Snext_window
);
7716 defsubr (&Sprevious_window
);
7717 defsubr (&Sother_window
);
7718 defsubr (&Sget_lru_window
);
7719 defsubr (&Sget_largest_window
);
7720 defsubr (&Sget_buffer_window
);
7721 defsubr (&Sdelete_other_windows
);
7722 defsubr (&Sdelete_windows_on
);
7723 defsubr (&Sreplace_buffer_in_windows
);
7724 defsubr (&Sdelete_window
);
7725 defsubr (&Sset_window_buffer
);
7726 defsubr (&Sselect_window
);
7727 defsubr (&Sspecial_display_p
);
7728 defsubr (&Ssame_window_p
);
7729 defsubr (&Sdisplay_buffer
);
7730 defsubr (&Sforce_window_update
);
7731 defsubr (&Ssplit_window
);
7732 defsubr (&Senlarge_window
);
7733 defsubr (&Sshrink_window
);
7734 defsubr (&Sadjust_window_trailing_edge
);
7735 defsubr (&Sscroll_up
);
7736 defsubr (&Sscroll_down
);
7737 defsubr (&Sscroll_left
);
7738 defsubr (&Sscroll_right
);
7739 defsubr (&Sother_window_for_scrolling
);
7740 defsubr (&Sscroll_other_window
);
7741 defsubr (&Sminibuffer_selected_window
);
7742 defsubr (&Srecenter
);
7743 defsubr (&Swindow_text_height
);
7744 defsubr (&Smove_to_window_line
);
7745 defsubr (&Swindow_configuration_p
);
7746 defsubr (&Swindow_configuration_frame
);
7747 defsubr (&Sset_window_configuration
);
7748 defsubr (&Scurrent_window_configuration
);
7749 defsubr (&Ssave_window_excursion
);
7750 defsubr (&Swindow_tree
);
7751 defsubr (&Sset_window_margins
);
7752 defsubr (&Swindow_margins
);
7753 defsubr (&Sset_window_fringes
);
7754 defsubr (&Swindow_fringes
);
7755 defsubr (&Sset_window_scroll_bars
);
7756 defsubr (&Swindow_scroll_bars
);
7757 defsubr (&Swindow_vscroll
);
7758 defsubr (&Sset_window_vscroll
);
7759 defsubr (&Scompare_window_configurations
);
7760 defsubr (&Swindow_list
);
7761 defsubr (&Swindow_parameters
);
7762 defsubr (&Swindow_parameter
);
7763 defsubr (&Sset_window_parameter
);
7770 initial_define_key (control_x_map
, '1', "delete-other-windows");
7771 initial_define_key (control_x_map
, '2', "split-window");
7772 initial_define_key (control_x_map
, '0', "delete-window");
7773 initial_define_key (control_x_map
, 'o', "other-window");
7774 initial_define_key (control_x_map
, '^', "enlarge-window");
7775 initial_define_key (control_x_map
, '<', "scroll-left");
7776 initial_define_key (control_x_map
, '>', "scroll-right");
7778 initial_define_key (global_map
, Ctl ('V'), "scroll-up");
7779 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
7780 initial_define_key (meta_map
, 'v', "scroll-down");
7782 initial_define_key (global_map
, Ctl('L'), "recenter");
7783 initial_define_key (meta_map
, 'r', "move-to-window-line");
7786 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7787 (do not change this comment) */