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, 2009, 2010
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/>. */
36 #include "dispextern.h"
37 #include "blockinput.h"
38 #include "intervals.h"
39 #include "termhooks.h" /* For FRAME_TERMINAL. */
43 #endif /* HAVE_X_WINDOWS */
55 Lisp_Object Qwindowp
, Qwindow_live_p
, Qwindow_configuration_p
;
56 Lisp_Object Qdisplay_buffer
;
57 Lisp_Object Qscroll_up
, Qscroll_down
, Qscroll_command
;
58 Lisp_Object Qwindow_size_fixed
;
60 extern Lisp_Object Qleft_margin
, Qright_margin
;
62 static int displayed_window_lines (struct window
*);
63 static struct window
*decode_window (Lisp_Object
);
64 static int count_windows (struct window
*);
65 static int get_leaf_windows (struct window
*, struct window
**, int);
66 static void window_scroll (Lisp_Object
, int, int, int);
67 static void window_scroll_pixel_based (Lisp_Object
, int, int, int);
68 static void window_scroll_line_based (Lisp_Object
, int, int, int);
69 static int window_min_size_1 (struct window
*, int, int);
70 static int window_min_size_2 (struct window
*, int, int);
71 static int window_min_size (struct window
*, int, int, int, int *);
72 static void size_window (Lisp_Object
, int, int, int, int, int);
73 static int freeze_window_start (struct window
*, void *);
74 static int window_fixed_size_p (struct window
*, int, int);
75 static void enlarge_window (Lisp_Object
, int, int);
76 static Lisp_Object
window_list (void);
77 static int add_window_to_list (struct window
*, void *);
78 static int candidate_window_p (Lisp_Object
, Lisp_Object
, Lisp_Object
,
80 static Lisp_Object
next_window (Lisp_Object
, Lisp_Object
,
82 static void decode_next_window_args (Lisp_Object
*, Lisp_Object
*,
84 static int foreach_window_1 (struct window
*,
85 int (* fn
) (struct window
*, void *),
87 static Lisp_Object
window_list_1 (Lisp_Object
, Lisp_Object
, Lisp_Object
);
89 /* This is the window in which the terminal's cursor should
90 be left when nothing is being done with it. This must
91 always be a leaf window, and its buffer is selected by
92 the top level editing loop at the end of each command.
94 This value is always the same as
95 FRAME_SELECTED_WINDOW (selected_frame). */
97 Lisp_Object selected_window
;
99 /* A list of all windows for use by next_window and Fwindow_list.
100 Functions creating or deleting windows should invalidate this cache
101 by setting it to nil. */
103 Lisp_Object Vwindow_list
;
105 /* The mini-buffer window of the selected frame.
106 Note that you cannot test for mini-bufferness of an arbitrary window
107 by comparing against this; but you can test for mini-bufferness of
108 the selected window. */
110 Lisp_Object minibuf_window
;
112 /* Non-nil means it is the window whose mode line should be
113 shown as the selected window when the minibuffer is selected. */
115 Lisp_Object minibuf_selected_window
;
117 /* Non-nil means it is the window for C-M-v to scroll
118 when the mini-buffer is selected. */
120 Lisp_Object Vminibuf_scroll_window
;
122 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
124 Lisp_Object Vother_window_scroll_buffer
;
126 /* Non-nil means it's function to call to display temp buffers. */
128 Lisp_Object Vtemp_buffer_show_function
;
130 /* Non-zero means line and page scrolling on tall lines (with images)
131 does partial scrolling by modifying window-vscroll. */
133 int auto_window_vscroll_p
;
135 /* Non-zero means to use mode-line-inactive face in all windows but the
136 selected-window and the minibuffer-scroll-window when the
137 minibuffer is active. */
138 int mode_line_in_non_selected_windows
;
140 /* If a window gets smaller than either of these, it is removed. */
142 EMACS_INT window_min_height
;
143 EMACS_INT window_min_width
;
145 /* Hook run at end of temp_output_buffer_show. */
147 Lisp_Object Qtemp_buffer_show_hook
;
149 /* Number of lines of continuity in scrolling by screenfuls. */
151 EMACS_INT next_screen_context_lines
;
153 /* Incremented for each window created. */
155 static int sequence_number
;
157 /* Nonzero after init_window_once has finished. */
159 static int window_initialized
;
161 /* Hook to run when window config changes. */
163 static Lisp_Object Qwindow_configuration_change_hook
;
164 static Lisp_Object Vwindow_configuration_change_hook
;
166 /* Non-nil means scroll commands try to put point
167 at the same screen height as previously. */
169 Lisp_Object Vscroll_preserve_screen_position
;
171 /* Non-nil means that text is inserted before window's markers. */
173 Lisp_Object Vwindow_point_insertion_type
;
175 /* Incremented by 1 whenever a window is deleted. */
177 int window_deletion_count
;
179 /* Used by the function window_scroll_pixel_based */
181 static int window_scroll_pixel_based_preserve_x
;
182 static int window_scroll_pixel_based_preserve_y
;
184 /* Same for window_scroll_line_based. */
186 static int window_scroll_preserve_hpos
;
187 static int window_scroll_preserve_vpos
;
189 #if 0 /* This isn't used anywhere. */
190 /* Nonzero means we can split a frame even if it is "unsplittable". */
191 static int inhibit_frame_unsplittable
;
194 extern EMACS_INT scroll_margin
;
196 extern Lisp_Object Qwindow_scroll_functions
, Vwindow_scroll_functions
;
198 /* If non-nil, then the `recenter' command with a nil argument
199 the entire frame to be redrawn; the special value `tty' causes the
200 frame to be redrawn only if it is a tty frame. */
202 static Lisp_Object Vrecenter_redisplay
;
203 extern Lisp_Object Qtty
;
206 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
207 doc
: /* Return t if OBJECT is a window. */)
210 return WINDOWP (object
) ? Qt
: Qnil
;
213 DEFUN ("window-live-p", Fwindow_live_p
, Swindow_live_p
, 1, 1, 0,
214 doc
: /* Return t if OBJECT is a window which is currently visible. */)
217 return WINDOW_LIVE_P (object
) ? Qt
: Qnil
;
224 register struct window
*p
;
226 p
= allocate_window ();
228 XSETFASTINT (p
->sequence_number
, sequence_number
);
229 XSETFASTINT (p
->left_col
, 0);
230 XSETFASTINT (p
->top_line
, 0);
231 XSETFASTINT (p
->total_lines
, 0);
232 XSETFASTINT (p
->total_cols
, 0);
233 XSETFASTINT (p
->hscroll
, 0);
234 XSETFASTINT (p
->min_hscroll
, 0);
235 p
->orig_top_line
= p
->orig_total_lines
= Qnil
;
236 p
->start
= Fmake_marker ();
237 p
->pointm
= Fmake_marker ();
238 XSETFASTINT (p
->use_time
, 0);
240 p
->display_table
= Qnil
;
242 p
->window_parameters
= Qnil
;
243 p
->pseudo_window_p
= 0;
244 memset (&p
->cursor
, 0, sizeof (p
->cursor
));
245 memset (&p
->last_cursor
, 0, sizeof (p
->last_cursor
));
246 memset (&p
->phys_cursor
, 0, sizeof (p
->phys_cursor
));
247 p
->desired_matrix
= p
->current_matrix
= 0;
248 p
->nrows_scale_factor
= p
->ncols_scale_factor
= 1;
249 p
->phys_cursor_type
= -1;
250 p
->phys_cursor_width
= -1;
251 p
->must_be_updated_p
= 0;
252 XSETFASTINT (p
->window_end_vpos
, 0);
253 XSETFASTINT (p
->window_end_pos
, 0);
254 p
->window_end_valid
= Qnil
;
257 XSETFASTINT (p
->last_point
, 0);
258 p
->frozen_window_start_p
= 0;
259 p
->last_cursor_off_p
= p
->cursor_off_p
= 0;
260 p
->left_margin_cols
= Qnil
;
261 p
->right_margin_cols
= Qnil
;
262 p
->left_fringe_width
= Qnil
;
263 p
->right_fringe_width
= Qnil
;
264 p
->fringes_outside_margins
= Qnil
;
265 p
->scroll_bar_width
= Qnil
;
266 p
->vertical_scroll_bar_type
= Qt
;
267 p
->resize_proportionally
= Qnil
;
273 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
274 doc
: /* Return the window that the cursor now appears in and commands apply to. */)
277 return selected_window
;
280 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 1, 0,
281 doc
: /* Return the window used now for minibuffers.
282 If the optional argument FRAME is specified, return the minibuffer window
283 used by that frame. */)
287 frame
= selected_frame
;
288 CHECK_LIVE_FRAME (frame
);
289 return FRAME_MINIBUF_WINDOW (XFRAME (frame
));
292 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 0, 1, 0,
293 doc
: /* Return non-nil if WINDOW is a minibuffer window.
294 WINDOW defaults to the selected window. */)
297 struct window
*w
= decode_window (window
);
298 return MINI_WINDOW_P (w
) ? Qt
: Qnil
;
302 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
303 Spos_visible_in_window_p
, 0, 3, 0,
304 doc
: /* Return non-nil if position POS is currently on the frame in WINDOW.
305 Return nil if that position is scrolled vertically out of view.
306 If a character is only partially visible, nil is returned, unless the
307 optional argument PARTIALLY is non-nil.
308 If POS is only out of view because of horizontal scrolling, return non-nil.
309 If POS is t, it specifies the position of the last visible glyph in WINDOW.
310 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
312 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
313 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
314 where X and Y are the pixel coordinates relative to the top left corner
315 of the window. The remaining elements are omitted if the character after
316 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
317 off-window at the top and bottom of the row, ROWH is the height of the
318 display row, and VPOS is the row number (0-based) containing POS. */)
319 (Lisp_Object pos
, Lisp_Object window
, Lisp_Object partially
)
321 register struct window
*w
;
323 register struct buffer
*buf
;
325 Lisp_Object in_window
= Qnil
;
326 int rtop
, rbot
, rowh
, vpos
, fully_p
= 1;
329 w
= decode_window (window
);
330 buf
= XBUFFER (w
->buffer
);
331 SET_TEXT_POS_FROM_MARKER (top
, w
->start
);
335 else if (!NILP (pos
))
337 CHECK_NUMBER_COERCE_MARKER (pos
);
340 else if (w
== XWINDOW (selected_window
))
343 posint
= XMARKER (w
->pointm
)->charpos
;
345 /* If position is above window start or outside buffer boundaries,
346 or if window start is out of range, position is not visible. */
348 || (posint
>= CHARPOS (top
) && posint
<= BUF_ZV (buf
)))
349 && CHARPOS (top
) >= BUF_BEGV (buf
)
350 && CHARPOS (top
) <= BUF_ZV (buf
)
351 && pos_visible_p (w
, posint
, &x
, &y
, &rtop
, &rbot
, &rowh
, &vpos
)
352 && (fully_p
= !rtop
&& !rbot
, (!NILP (partially
) || fully_p
)))
355 if (!NILP (in_window
) && !NILP (partially
))
357 Lisp_Object part
= Qnil
;
359 part
= list4 (make_number (rtop
), make_number (rbot
),
360 make_number (rowh
), make_number (vpos
));
361 in_window
= Fcons (make_number (x
),
362 Fcons (make_number (y
), part
));
368 DEFUN ("window-line-height", Fwindow_line_height
,
369 Swindow_line_height
, 0, 2, 0,
370 doc
: /* Return height in pixels of text line LINE in window WINDOW.
371 If WINDOW is nil or omitted, use selected window.
373 Return height of current line if LINE is omitted or nil. Return height of
374 header or mode line if LINE is `header-line' and `mode-line'.
375 Otherwise, LINE is a text line number starting from 0. A negative number
376 counts from the end of the window.
378 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
379 in pixels of the visible part of the line, VPOS and YPOS are the
380 vertical position in lines and pixels of the line, relative to the top
381 of the first text line, and OFFBOT is the number of off-window pixels at
382 the bottom of the text line. If there are off-window pixels at the top
383 of the (first) text line, YPOS is negative.
385 Return nil if window display is not up-to-date. In that case, use
386 `pos-visible-in-window-p' to obtain the information. */)
387 (Lisp_Object line
, Lisp_Object window
)
389 register struct window
*w
;
390 register struct buffer
*b
;
391 struct glyph_row
*row
, *end_row
;
392 int max_y
, crop
, i
, n
;
394 w
= decode_window (window
);
397 || w
->pseudo_window_p
)
400 CHECK_BUFFER (w
->buffer
);
401 b
= XBUFFER (w
->buffer
);
403 /* Fail if current matrix is not up-to-date. */
404 if (NILP (w
->window_end_valid
)
405 || current_buffer
->clip_changed
406 || current_buffer
->prevent_redisplay_optimizations_p
407 || XFASTINT (w
->last_modified
) < BUF_MODIFF (b
)
408 || XFASTINT (w
->last_overlay_modified
) < BUF_OVERLAY_MODIFF (b
))
414 if (i
< 0 || i
>= w
->current_matrix
->nrows
415 || (row
= MATRIX_ROW (w
->current_matrix
, i
), !row
->enabled_p
))
417 max_y
= window_text_bottom_y (w
);
421 if (EQ (line
, Qheader_line
))
423 if (!WINDOW_WANTS_HEADER_LINE_P (w
))
425 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
428 return list4 (make_number (row
->height
),
429 make_number (0), make_number (0),
433 if (EQ (line
, Qmode_line
))
435 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
438 return list4 (make_number (row
->height
),
439 make_number (0), /* not accurate */
440 make_number (WINDOW_HEADER_LINE_HEIGHT (w
)
441 + window_text_bottom_y (w
)),
448 row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
449 end_row
= MATRIX_BOTTOM_TEXT_ROW (w
->current_matrix
, w
);
450 max_y
= window_text_bottom_y (w
);
453 while ((n
< 0 || i
< n
)
454 && row
<= end_row
&& row
->enabled_p
455 && row
->y
+ row
->height
< max_y
)
458 if (row
> end_row
|| !row
->enabled_p
)
470 crop
= max (0, (row
->y
+ row
->height
) - max_y
);
471 return list4 (make_number (row
->height
+ min (0, row
->y
) - crop
),
473 make_number (row
->y
),
479 static struct window
*
480 decode_window (register Lisp_Object window
)
483 return XWINDOW (selected_window
);
485 CHECK_LIVE_WINDOW (window
);
486 return XWINDOW (window
);
489 static struct window
*
490 decode_any_window (register Lisp_Object window
)
493 return XWINDOW (selected_window
);
495 CHECK_WINDOW (window
);
496 return XWINDOW (window
);
499 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
500 doc
: /* Return the buffer that WINDOW is displaying.
501 WINDOW defaults to the selected window. */)
504 return decode_window (window
)->buffer
;
507 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
508 doc
: /* Return the number of lines in WINDOW.
509 WINDOW defaults to the selected window.
511 The return value includes WINDOW's mode line and header line, if any.
513 Note: The function does not take into account the value of `line-spacing'
514 when calculating the number of lines in WINDOW. */)
517 return decode_any_window (window
)->total_lines
;
520 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
521 doc
: /* Return the number of display columns in WINDOW.
522 WINDOW defaults to the selected window.
524 Note: The return value is the number of columns available for text in
525 WINDOW. If you want to find out how many columns WINDOW takes up, use
526 (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
529 return make_number (window_box_text_cols (decode_any_window (window
)));
532 DEFUN ("window-full-width-p", Fwindow_full_width_p
, Swindow_full_width_p
, 0, 1, 0,
533 doc
: /* Return t if WINDOW is as wide as its frame.
534 WINDOW defaults to the selected window. */)
537 return WINDOW_FULL_WIDTH_P (decode_any_window (window
)) ? Qt
: Qnil
;
540 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
541 doc
: /* Return the number of columns by which WINDOW is scrolled from left margin.
542 WINDOW defaults to the selected window. */)
545 return decode_window (window
)->hscroll
;
548 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
549 doc
: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
550 Return NCOL. NCOL should be zero or positive.
552 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
553 window so that the location of point moves off-window. */)
554 (Lisp_Object window
, Lisp_Object ncol
)
556 struct window
*w
= decode_window (window
);
560 hscroll
= max (0, XINT (ncol
));
562 /* Prevent redisplay shortcuts when changing the hscroll. */
563 if (XINT (w
->hscroll
) != hscroll
)
564 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
566 w
->hscroll
= make_number (hscroll
);
570 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger
,
571 Swindow_redisplay_end_trigger
, 0, 1, 0,
572 doc
: /* Return WINDOW's redisplay end trigger value.
573 WINDOW defaults to the selected window.
574 See `set-window-redisplay-end-trigger' for more information. */)
577 return decode_window (window
)->redisplay_end_trigger
;
580 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger
,
581 Sset_window_redisplay_end_trigger
, 2, 2, 0,
582 doc
: /* Set WINDOW's redisplay end trigger value to VALUE.
583 VALUE should be a buffer position (typically a marker) or nil.
584 If it is a buffer position, then if redisplay in WINDOW reaches a position
585 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
586 with two arguments: WINDOW, and the end trigger value.
587 Afterwards the end-trigger value is reset to nil. */)
588 (register Lisp_Object window
, Lisp_Object value
)
590 register struct window
*w
;
592 w
= decode_window (window
);
593 w
->redisplay_end_trigger
= value
;
597 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
598 doc
: /* Return a list of the edge coordinates of WINDOW.
599 The list has the form (LEFT TOP RIGHT BOTTOM).
600 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
601 all relative to 0, 0 at top left corner of frame.
603 RIGHT is one more than the rightmost column occupied by WINDOW.
604 BOTTOM is one more than the bottommost row occupied by WINDOW.
605 The edges include the space used by WINDOW's scroll bar, display
606 margins, fringes, header line, and/or mode line. For the edges of
607 just the text area, use `window-inside-edges'. */)
610 register struct window
*w
= decode_any_window (window
);
612 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w
)),
613 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w
)),
614 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w
)),
615 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w
)),
619 DEFUN ("window-pixel-edges", Fwindow_pixel_edges
, Swindow_pixel_edges
, 0, 1, 0,
620 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
621 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
622 the top left corner of the frame.
624 RIGHT is one more than the rightmost x position occupied by WINDOW.
625 BOTTOM is one more than the bottommost y position occupied by WINDOW.
626 The pixel edges include the space used by WINDOW's scroll bar, display
627 margins, fringes, header line, and/or mode line. For the pixel edges
628 of just the text area, use `window-inside-pixel-edges'. */)
631 register struct window
*w
= decode_any_window (window
);
633 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w
)),
634 Fcons (make_number (WINDOW_TOP_EDGE_Y (w
)),
635 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w
)),
636 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w
)),
641 calc_absolute_offset(struct window
*w
, int *add_x
, int *add_y
)
643 struct frame
*f
= XFRAME (w
->frame
);
645 #ifdef FRAME_MENUBAR_HEIGHT
646 *add_y
+= FRAME_MENUBAR_HEIGHT (f
);
648 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
649 *add_y
+= FRAME_TOOLBAR_TOP_HEIGHT (f
);
650 #elif FRAME_TOOLBAR_HEIGHT
651 *add_y
+= FRAME_TOOLBAR_HEIGHT (f
);
653 #ifdef FRAME_NS_TITLEBAR_HEIGHT
654 *add_y
+= FRAME_NS_TITLEBAR_HEIGHT (f
);
656 *add_x
= f
->left_pos
;
657 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
658 *add_x
+= FRAME_TOOLBAR_LEFT_WIDTH (f
);
662 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges
,
663 Swindow_absolute_pixel_edges
, 0, 1, 0,
664 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
665 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
666 the top left corner of the display.
668 RIGHT is one more than the rightmost x position occupied by WINDOW.
669 BOTTOM is one more than the bottommost y position occupied by WINDOW.
670 The pixel edges include the space used by WINDOW's scroll bar, display
671 margins, fringes, header line, and/or mode line. For the pixel edges
672 of just the text area, use `window-inside-absolute-pixel-edges'. */)
675 register struct window
*w
= decode_any_window (window
);
677 calc_absolute_offset (w
, &add_x
, &add_y
);
679 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w
) + add_x
),
680 Fcons (make_number (WINDOW_TOP_EDGE_Y (w
) + add_y
),
681 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w
) + add_x
),
682 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w
) + add_y
),
686 DEFUN ("window-inside-edges", Fwindow_inside_edges
, Swindow_inside_edges
, 0, 1, 0,
687 doc
: /* Return a list of the edge coordinates of WINDOW.
688 The list has the form (LEFT TOP RIGHT BOTTOM).
689 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
690 all relative to 0, 0 at top left corner of frame.
692 RIGHT is one more than the rightmost column of WINDOW's text area.
693 BOTTOM is one more than the bottommost row of WINDOW's text area.
694 The inside edges do not include the space used by the WINDOW's scroll
695 bar, display margins, fringes, header line, and/or mode line. */)
698 register struct window
*w
= decode_any_window (window
);
700 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w
)
701 + WINDOW_LEFT_MARGIN_COLS (w
)
702 + WINDOW_LEFT_FRINGE_COLS (w
)),
703 make_number (WINDOW_TOP_EDGE_LINE (w
)
704 + WINDOW_HEADER_LINE_LINES (w
)),
705 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w
)
706 - WINDOW_RIGHT_MARGIN_COLS (w
)
707 - WINDOW_RIGHT_FRINGE_COLS (w
)),
708 make_number (WINDOW_BOTTOM_EDGE_LINE (w
)
709 - WINDOW_MODE_LINE_LINES (w
)));
712 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges
, Swindow_inside_pixel_edges
, 0, 1, 0,
713 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
714 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
715 the top left corner of the frame.
717 RIGHT is one more than the rightmost x position of WINDOW's text area.
718 BOTTOM is one more than the bottommost y position of WINDOW's text area.
719 The inside edges do not include the space used by WINDOW's scroll bar,
720 display margins, fringes, header line, and/or mode line. */)
723 register struct window
*w
= decode_any_window (window
);
725 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w
)
726 + WINDOW_LEFT_MARGIN_WIDTH (w
)
727 + WINDOW_LEFT_FRINGE_WIDTH (w
)),
728 make_number (WINDOW_TOP_EDGE_Y (w
)
729 + WINDOW_HEADER_LINE_HEIGHT (w
)),
730 make_number (WINDOW_BOX_RIGHT_EDGE_X (w
)
731 - WINDOW_RIGHT_MARGIN_WIDTH (w
)
732 - WINDOW_RIGHT_FRINGE_WIDTH (w
)),
733 make_number (WINDOW_BOTTOM_EDGE_Y (w
)
734 - WINDOW_MODE_LINE_HEIGHT (w
)));
737 DEFUN ("window-inside-absolute-pixel-edges",
738 Fwindow_inside_absolute_pixel_edges
,
739 Swindow_inside_absolute_pixel_edges
, 0, 1, 0,
740 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
741 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
742 the top left corner of the display.
744 RIGHT is one more than the rightmost x position of WINDOW's text area.
745 BOTTOM is one more than the bottommost y position of WINDOW's text area.
746 The inside edges do not include the space used by WINDOW's scroll bar,
747 display margins, fringes, header line, and/or mode line. */)
750 register struct window
*w
= decode_any_window (window
);
752 calc_absolute_offset (w
, &add_x
, &add_y
);
754 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w
)
755 + WINDOW_LEFT_MARGIN_WIDTH (w
)
756 + WINDOW_LEFT_FRINGE_WIDTH (w
) + add_x
),
757 make_number (WINDOW_TOP_EDGE_Y (w
)
758 + WINDOW_HEADER_LINE_HEIGHT (w
) + add_y
),
759 make_number (WINDOW_BOX_RIGHT_EDGE_X (w
)
760 - WINDOW_RIGHT_MARGIN_WIDTH (w
)
761 - WINDOW_RIGHT_FRINGE_WIDTH (w
) + add_x
),
762 make_number (WINDOW_BOTTOM_EDGE_Y (w
)
763 - WINDOW_MODE_LINE_HEIGHT (w
) + add_y
));
766 /* Test if the character at column *X, row *Y is within window W.
767 If it is not, return ON_NOTHING;
768 if it is in the window's text area,
769 set *x and *y to its location relative to the upper left corner
772 if it is on the window's modeline, return ON_MODE_LINE;
773 if it is on the border between the window and its right sibling,
774 return ON_VERTICAL_BORDER.
775 if it is on a scroll bar,
776 return ON_SCROLL_BAR.
777 if it is on the window's top line, return ON_HEADER_LINE;
778 if it is in left or right fringe of the window,
779 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
780 to window-relative coordinates;
781 if it is in the marginal area to the left/right of the window,
782 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
783 to window-relative coordinates.
785 X and Y are frame relative pixel coordinates. */
787 static enum window_part
788 coordinates_in_window (register struct window
*w
, register int *x
, register int *y
)
790 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
791 int left_x
, right_x
, top_y
, bottom_y
;
792 enum window_part part
;
793 int ux
= FRAME_COLUMN_WIDTH (f
);
794 int x0
= WINDOW_LEFT_EDGE_X (w
);
795 int x1
= WINDOW_RIGHT_EDGE_X (w
);
796 /* The width of the area where the vertical line can be dragged.
797 (Between mode lines for instance. */
798 int grabbable_width
= ux
;
799 int lmargin_width
, rmargin_width
, text_left
, text_right
;
801 /* In what's below, we subtract 1 when computing right_x because we
802 want the rightmost pixel, which is given by left_pixel+width-1. */
803 if (w
->pseudo_window_p
)
806 right_x
= WINDOW_TOTAL_WIDTH (w
) - 1;
807 top_y
= WINDOW_TOP_EDGE_Y (w
);
808 bottom_y
= WINDOW_BOTTOM_EDGE_Y (w
);
812 left_x
= WINDOW_BOX_LEFT_EDGE_X (w
);
813 right_x
= WINDOW_BOX_RIGHT_EDGE_X (w
) - 1;
814 top_y
= WINDOW_TOP_EDGE_Y (w
);
815 bottom_y
= WINDOW_BOTTOM_EDGE_Y (w
);
818 /* Outside any interesting row? */
819 if (*y
< top_y
|| *y
>= bottom_y
)
822 /* On the mode line or header line? If it's near the start of
823 the mode or header line of window that's has a horizontal
824 sibling, say it's on the vertical line. That's to be able
825 to resize windows horizontally in case we're using toolkit
828 if (WINDOW_WANTS_MODELINE_P (w
)
829 && *y
>= bottom_y
- CURRENT_MODE_LINE_HEIGHT (w
))
833 header_vertical_border_check
:
834 /* We're somewhere on the mode line. We consider the place
835 between mode lines of horizontally adjacent mode lines
836 as the vertical border. If scroll bars on the left,
837 return the right window. */
838 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
)
839 || WINDOW_RIGHTMOST_P (w
))
841 if (!WINDOW_LEFTMOST_P (w
) && eabs (*x
- x0
) < grabbable_width
)
843 /* Convert X and Y to window relative coordinates.
844 Vertical border is at the left edge of window. */
845 *x
= max (0, *x
- x0
);
847 return ON_VERTICAL_BORDER
;
852 /* Make sure we're not at the rightmost position of a
853 mode-/header-line and there's yet another window on
854 the right. (Bug#1372) */
855 if ((WINDOW_RIGHTMOST_P (w
) || *x
< x1
)
856 && eabs (*x
- x1
) < grabbable_width
)
858 /* Convert X and Y to window relative coordinates.
859 Vertical border is at the right edge of window. */
860 *x
= min (x1
, *x
) - x0
;
862 return ON_VERTICAL_BORDER
;
866 if (*x
< x0
|| *x
>= x1
)
869 /* Convert X and Y to window relative coordinates.
870 Mode line starts at left edge of window. */
876 if (WINDOW_WANTS_HEADER_LINE_P (w
)
877 && *y
< top_y
+ CURRENT_HEADER_LINE_HEIGHT (w
))
879 part
= ON_HEADER_LINE
;
880 goto header_vertical_border_check
;
883 if (*x
< x0
|| *x
>= x1
)
886 /* Outside any interesting column? */
887 if (*x
< left_x
|| *x
> right_x
)
890 return ON_SCROLL_BAR
;
893 lmargin_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
894 rmargin_width
= window_box_width (w
, RIGHT_MARGIN_AREA
);
896 text_left
= window_box_left (w
, TEXT_AREA
);
897 text_right
= text_left
+ window_box_width (w
, TEXT_AREA
);
899 if (FRAME_WINDOW_P (f
))
901 if (!w
->pseudo_window_p
902 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w
)
903 && !WINDOW_RIGHTMOST_P (w
)
904 && (eabs (*x
- right_x
) < grabbable_width
))
906 /* Convert X and Y to window relative coordinates.
907 Vertical border is at the right edge of window. */
908 *x
= min (right_x
, *x
) - left_x
;
910 return ON_VERTICAL_BORDER
;
915 /* Need to say "*x > right_x" rather than >=, since on character
916 terminals, the vertical line's x coordinate is right_x. */
917 if (!w
->pseudo_window_p
918 && !WINDOW_RIGHTMOST_P (w
)
919 && *x
> right_x
- ux
)
921 /* On the border on the right side of the window? Assume that
922 this area begins at RIGHT_X minus a canonical char width. */
923 *x
= min (right_x
, *x
) - left_x
;
925 return ON_VERTICAL_BORDER
;
931 if (lmargin_width
> 0
932 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
933 ? (*x
>= left_x
+ WINDOW_LEFT_FRINGE_WIDTH (w
))
934 : (*x
< left_x
+ lmargin_width
)))
937 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
))
938 *x
-= WINDOW_LEFT_FRINGE_WIDTH (w
);
940 return ON_LEFT_MARGIN
;
943 /* Convert X and Y to window-relative pixel coordinates. */
946 return ON_LEFT_FRINGE
;
949 if (*x
>= text_right
)
951 if (rmargin_width
> 0
952 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
953 ? (*x
< right_x
- WINDOW_RIGHT_FRINGE_WIDTH (w
))
954 : (*x
>= right_x
- rmargin_width
)))
956 *x
-= right_x
- rmargin_width
;
957 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
))
958 *x
+= WINDOW_RIGHT_FRINGE_WIDTH (w
);
960 return ON_RIGHT_MARGIN
;
963 /* Convert X and Y to window-relative pixel coordinates. */
964 *x
-= left_x
+ WINDOW_LEFT_FRINGE_WIDTH (w
);
966 return ON_RIGHT_FRINGE
;
969 /* Everything special ruled out - must be on text area */
976 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
977 Scoordinates_in_window_p
, 2, 2, 0,
978 doc
: /* Return non-nil if COORDINATES are in WINDOW.
979 COORDINATES is a cons of the form (X . Y), X and Y being distances
980 measured in characters from the upper-left corner of the frame.
981 \(0 . 0) denotes the character in the upper left corner of the
983 If COORDINATES are in the text portion of WINDOW,
984 the coordinates relative to the window are returned.
985 If they are in the mode line of WINDOW, `mode-line' is returned.
986 If they are in the top mode line of WINDOW, `header-line' is returned.
987 If they are in the left fringe of WINDOW, `left-fringe' is returned.
988 If they are in the right fringe of WINDOW, `right-fringe' is returned.
989 If they are on the border between WINDOW and its right sibling,
990 `vertical-line' is returned.
991 If they are in the windows's left or right marginal areas, `left-margin'\n\
992 or `right-margin' is returned. */)
993 (register Lisp_Object coordinates
, Lisp_Object window
)
1000 CHECK_WINDOW (window
);
1001 w
= XWINDOW (window
);
1002 f
= XFRAME (w
->frame
);
1003 CHECK_CONS (coordinates
);
1004 lx
= Fcar (coordinates
);
1005 ly
= Fcdr (coordinates
);
1006 CHECK_NUMBER_OR_FLOAT (lx
);
1007 CHECK_NUMBER_OR_FLOAT (ly
);
1008 x
= FRAME_PIXEL_X_FROM_CANON_X (f
, lx
) + FRAME_INTERNAL_BORDER_WIDTH (f
);
1009 y
= FRAME_PIXEL_Y_FROM_CANON_Y (f
, ly
) + FRAME_INTERNAL_BORDER_WIDTH (f
);
1011 switch (coordinates_in_window (w
, &x
, &y
))
1017 /* X and Y are now window relative pixel coordinates. Convert
1018 them to canonical char units before returning them. */
1019 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f
, x
),
1020 FRAME_CANON_Y_FROM_PIXEL_Y (f
, y
));
1025 case ON_VERTICAL_BORDER
:
1026 return Qvertical_line
;
1028 case ON_HEADER_LINE
:
1029 return Qheader_line
;
1031 case ON_LEFT_FRINGE
:
1032 return Qleft_fringe
;
1034 case ON_RIGHT_FRINGE
:
1035 return Qright_fringe
;
1037 case ON_LEFT_MARGIN
:
1038 return Qleft_margin
;
1040 case ON_RIGHT_MARGIN
:
1041 return Qright_margin
;
1044 /* Historically we are supposed to return nil in this case. */
1053 /* Callback for foreach_window, used in window_from_coordinates.
1054 Check if window W contains coordinates specified by USER_DATA which
1055 is actually a pointer to a struct check_window_data CW.
1057 Check if window W contains coordinates *CW->x and *CW->y. If it
1058 does, return W in *CW->window, as Lisp_Object, and return in
1059 *CW->part the part of the window under coordinates *X,*Y. Return
1060 zero from this function to stop iterating over windows. */
1062 struct check_window_data
1064 Lisp_Object
*window
;
1066 enum window_part
*part
;
1070 check_window_containing (struct window
*w
, void *user_data
)
1072 struct check_window_data
*cw
= (struct check_window_data
*) user_data
;
1073 enum window_part found
;
1076 found
= coordinates_in_window (w
, cw
->x
, cw
->y
);
1077 if (found
!= ON_NOTHING
)
1080 XSETWINDOW (*cw
->window
, w
);
1088 /* Find the window containing frame-relative pixel position X/Y and
1089 return it as a Lisp_Object.
1091 If X, Y is on one of the window's special `window_part' elements,
1092 set *PART to the id of that element, and return X and Y converted
1093 to window relative coordinates in WX and WY.
1095 If there is no window under X, Y return nil and leave *PART
1096 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1098 This function was previously implemented with a loop cycling over
1099 windows with Fnext_window, and starting with the frame's selected
1100 window. It turned out that this doesn't work with an
1101 implementation of next_window using Vwindow_list, because
1102 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1103 tree of F when this function is called asynchronously from
1104 note_mouse_highlight. The original loop didn't terminate in this
1108 window_from_coordinates (struct frame
*f
, int x
, int y
, enum window_part
*part
, int *wx
, int *wy
, int tool_bar_p
)
1111 struct check_window_data cw
;
1112 enum window_part dummy
;
1118 cw
.window
= &window
, cw
.x
= &x
, cw
.y
= &y
; cw
.part
= part
;
1119 foreach_window (f
, check_window_containing
, &cw
);
1121 /* If not found above, see if it's in the tool bar window, if a tool
1125 && WINDOWP (f
->tool_bar_window
)
1126 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)) > 0
1127 && (coordinates_in_window (XWINDOW (f
->tool_bar_window
), &x
, &y
)
1131 window
= f
->tool_bar_window
;
1140 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
1141 doc
: /* Return window containing coordinates X and Y on FRAME.
1142 If omitted, FRAME defaults to the currently selected frame.
1143 The top left corner of the frame is considered to be row 0,
1145 (Lisp_Object x
, Lisp_Object y
, Lisp_Object frame
)
1150 frame
= selected_frame
;
1151 CHECK_LIVE_FRAME (frame
);
1154 /* Check that arguments are integers or floats. */
1155 CHECK_NUMBER_OR_FLOAT (x
);
1156 CHECK_NUMBER_OR_FLOAT (y
);
1158 return window_from_coordinates (f
,
1159 (FRAME_PIXEL_X_FROM_CANON_X (f
, x
)
1160 + FRAME_INTERNAL_BORDER_WIDTH (f
)),
1161 (FRAME_PIXEL_Y_FROM_CANON_Y (f
, y
)
1162 + FRAME_INTERNAL_BORDER_WIDTH (f
)),
1166 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
1167 doc
: /* Return current value of point in WINDOW.
1168 WINDOW defaults to the selected window.
1170 For a nonselected window, this is the value point would have
1171 if that window were selected.
1173 Note that, when WINDOW is the selected window and its buffer
1174 is also currently selected, the value returned is the same as (point).
1175 It would be more strictly correct to return the `top-level' value
1176 of point, outside of any save-excursion forms.
1177 But that is hard to define. */)
1178 (Lisp_Object window
)
1180 register struct window
*w
= decode_window (window
);
1182 if (w
== XWINDOW (selected_window
)
1183 && current_buffer
== XBUFFER (w
->buffer
))
1185 return Fmarker_position (w
->pointm
);
1188 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
1189 doc
: /* Return position at which display currently starts in WINDOW.
1190 WINDOW defaults to the selected window.
1191 This is updated by redisplay or by calling `set-window-start'. */)
1192 (Lisp_Object window
)
1194 return Fmarker_position (decode_window (window
)->start
);
1197 /* This is text temporarily removed from the doc string below.
1199 This function returns nil if the position is not currently known.
1200 That happens when redisplay is preempted and doesn't finish.
1201 If in that case you want to compute where the end of the window would
1202 have been if redisplay had finished, do this:
1204 (goto-char (window-start window))
1205 (vertical-motion (1- (window-height window)) window)
1208 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 2, 0,
1209 doc
: /* Return position at which display currently ends in WINDOW.
1210 WINDOW defaults to the selected window.
1211 This is updated by redisplay, when it runs to completion.
1212 Simply changing the buffer text or setting `window-start'
1213 does not update this value.
1214 Return nil if there is no recorded value. \(This can happen if the
1215 last redisplay of WINDOW was preempted, and did not finish.)
1216 If UPDATE is non-nil, compute the up-to-date position
1217 if it isn't already recorded. */)
1218 (Lisp_Object window
, Lisp_Object update
)
1221 struct window
*w
= decode_window (window
);
1229 #if 0 /* This change broke some things. We should make it later. */
1230 /* If we don't know the end position, return nil.
1231 The user can compute it with vertical-motion if he wants to.
1232 It would be nicer to do it automatically,
1233 but that's so slow that it would probably bother people. */
1234 if (NILP (w
->window_end_valid
))
1239 && ! (! NILP (w
->window_end_valid
)
1240 && XFASTINT (w
->last_modified
) >= BUF_MODIFF (b
)
1241 && XFASTINT (w
->last_overlay_modified
) >= BUF_OVERLAY_MODIFF (b
))
1244 struct text_pos startp
;
1246 struct buffer
*old_buffer
= NULL
;
1248 /* Cannot use Fvertical_motion because that function doesn't
1249 cope with variable-height lines. */
1250 if (b
!= current_buffer
)
1252 old_buffer
= current_buffer
;
1253 set_buffer_internal (b
);
1256 /* In case W->start is out of the range, use something
1257 reasonable. This situation occurred when loading a file with
1258 `-l' containing a call to `rmail' with subsequent other
1259 commands. At the end, W->start happened to be BEG, while
1260 rmail had already narrowed the buffer. */
1261 if (XMARKER (w
->start
)->charpos
< BEGV
)
1262 SET_TEXT_POS (startp
, BEGV
, BEGV_BYTE
);
1263 else if (XMARKER (w
->start
)->charpos
> ZV
)
1264 SET_TEXT_POS (startp
, ZV
, ZV_BYTE
);
1266 SET_TEXT_POS_FROM_MARKER (startp
, w
->start
);
1268 start_display (&it
, w
, startp
);
1269 move_it_vertically (&it
, window_box_height (w
));
1270 if (it
.current_y
< it
.last_visible_y
)
1271 move_it_past_eol (&it
);
1272 value
= make_number (IT_CHARPOS (it
));
1275 set_buffer_internal (old_buffer
);
1278 XSETINT (value
, BUF_Z (b
) - XFASTINT (w
->window_end_pos
));
1283 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
1284 doc
: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1286 (Lisp_Object window
, Lisp_Object pos
)
1288 register struct window
*w
= decode_window (window
);
1290 CHECK_NUMBER_COERCE_MARKER (pos
);
1291 if (w
== XWINDOW (selected_window
)
1292 && XBUFFER (w
->buffer
) == current_buffer
)
1295 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
1297 /* We have to make sure that redisplay updates the window to show
1298 the new value of point. */
1299 if (!EQ (window
, selected_window
))
1300 ++windows_or_buffers_changed
;
1305 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
1306 doc
: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1307 WINDOW defaults to the selected window. Return POS.
1308 Optional third arg NOFORCE non-nil inhibits next redisplay from
1309 overriding motion of point in order to display at this exact start. */)
1310 (Lisp_Object window
, Lisp_Object pos
, Lisp_Object noforce
)
1312 register struct window
*w
= decode_window (window
);
1314 CHECK_NUMBER_COERCE_MARKER (pos
);
1315 set_marker_restricted (w
->start
, pos
, w
->buffer
);
1316 /* this is not right, but much easier than doing what is right. */
1317 w
->start_at_line_beg
= Qnil
;
1319 w
->force_start
= Qt
;
1320 w
->update_mode_line
= Qt
;
1321 XSETFASTINT (w
->last_modified
, 0);
1322 XSETFASTINT (w
->last_overlay_modified
, 0);
1323 if (!EQ (window
, selected_window
))
1324 windows_or_buffers_changed
++;
1330 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
1332 doc
: /* Return non-nil when WINDOW is dedicated to its buffer.
1333 More precisely, return the value assigned by the last call of
1334 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1335 never called with WINDOW as its argument, or the value set by that
1336 function was internally reset since its last call. WINDOW defaults to
1337 the selected window.
1339 When a window is dedicated to its buffer, `display-buffer' will refrain
1340 from displaying another buffer in it. `get-lru-window' and
1341 `get-largest-window' treat dedicated windows specially.
1342 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1343 `kill-buffer' can delete a dedicated window and the containing frame.
1345 Functions like `set-window-buffer' may change the buffer displayed by a
1346 window, unless that window is "strongly" dedicated to its buffer, that
1347 is the value returned by `window-dedicated-p' is t. */)
1348 (Lisp_Object window
)
1350 return decode_window (window
)->dedicated
;
1353 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
1354 Sset_window_dedicated_p
, 2, 2, 0,
1355 doc
: /* Mark WINDOW as dedicated according to FLAG.
1356 WINDOW defaults to the selected window. FLAG non-nil means mark WINDOW
1357 as dedicated to its buffer. FLAG nil means mark WINDOW as non-dedicated.
1360 When a window is dedicated to its buffer, `display-buffer' will refrain
1361 from displaying another buffer in it. `get-lru-window' and
1362 `get-largest-window' treat dedicated windows specially.
1363 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1364 `kill-buffer' can delete a dedicated window and the containing
1367 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1368 its buffer. Functions like `set-window-buffer' may change the buffer
1369 displayed by a window, unless that window is strongly dedicated to its
1370 buffer. If and when `set-window-buffer' displays another buffer in a
1371 window, it also makes sure that the window is not marked as dedicated. */)
1372 (Lisp_Object window
, Lisp_Object flag
)
1374 register struct window
*w
= decode_window (window
);
1376 w
->dedicated
= flag
;
1377 return w
->dedicated
;
1381 DEFUN ("window-parameters", Fwindow_parameters
, Swindow_parameters
,
1383 doc
: /* Return the parameters of WINDOW and their values.
1384 WINDOW defaults to the selected window. The return value is a list of
1385 elements of the form (PARAMETER . VALUE). */)
1386 (Lisp_Object window
)
1388 return Fcopy_alist (decode_window (window
)->window_parameters
);
1391 DEFUN ("window-parameter", Fwindow_parameter
, Swindow_parameter
,
1393 doc
: /* Return WINDOW's value for PARAMETER.
1394 WINDOW defaults to the selected window. */)
1395 (Lisp_Object window
, Lisp_Object parameter
)
1399 result
= Fassq (parameter
, decode_window (window
)->window_parameters
);
1400 return CDR_SAFE (result
);
1403 DEFUN ("set-window-parameter", Fset_window_parameter
,
1404 Sset_window_parameter
, 3, 3, 0,
1405 doc
: /* Set WINDOW's value of PARAMETER to VALUE.
1406 WINDOW defaults to the selected window. Return VALUE. */)
1407 (Lisp_Object window
, Lisp_Object parameter
, Lisp_Object value
)
1409 register struct window
*w
= decode_window (window
);
1410 Lisp_Object old_alist_elt
;
1412 old_alist_elt
= Fassq (parameter
, w
->window_parameters
);
1413 if (NILP (old_alist_elt
))
1414 w
->window_parameters
= Fcons (Fcons (parameter
, value
), w
->window_parameters
);
1416 Fsetcdr (old_alist_elt
, value
);
1421 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
1423 doc
: /* Return the display-table that WINDOW is using.
1424 WINDOW defaults to the selected window. */)
1425 (Lisp_Object window
)
1427 return decode_window (window
)->display_table
;
1430 /* Get the display table for use on window W. This is either W's
1431 display table or W's buffer's display table. Ignore the specified
1432 tables if they are not valid; if no valid table is specified,
1435 struct Lisp_Char_Table
*
1436 window_display_table (struct window
*w
)
1438 struct Lisp_Char_Table
*dp
= NULL
;
1440 if (DISP_TABLE_P (w
->display_table
))
1441 dp
= XCHAR_TABLE (w
->display_table
);
1442 else if (BUFFERP (w
->buffer
))
1444 struct buffer
*b
= XBUFFER (w
->buffer
);
1446 if (DISP_TABLE_P (b
->display_table
))
1447 dp
= XCHAR_TABLE (b
->display_table
);
1448 else if (DISP_TABLE_P (Vstandard_display_table
))
1449 dp
= XCHAR_TABLE (Vstandard_display_table
);
1455 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
1456 doc
: /* Set WINDOW's display-table to TABLE. */)
1457 (register Lisp_Object window
, Lisp_Object table
)
1459 register struct window
*w
;
1461 w
= decode_window (window
);
1462 w
->display_table
= table
;
1466 /* Record info on buffer window w is displaying
1467 when it is about to cease to display that buffer. */
1469 unshow_buffer (register struct window
*w
)
1476 if (b
!= XMARKER (w
->pointm
)->buffer
)
1480 if (w
== XWINDOW (selected_window
)
1481 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
1482 /* Do this except when the selected window's buffer
1483 is being removed from some other window. */
1485 /* last_window_start records the start position that this buffer
1486 had in the last window to be disconnected from it.
1487 Now that this statement is unconditional,
1488 it is possible for the buffer to be displayed in the
1489 selected window, while last_window_start reflects another
1490 window which was recently showing the same buffer.
1491 Some people might say that might be a good thing. Let's see. */
1492 b
->last_window_start
= marker_position (w
->start
);
1494 /* Point in the selected window's buffer
1495 is actually stored in that buffer, and the window's pointm isn't used.
1496 So don't clobber point in that buffer. */
1497 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
)
1498 /* This line helps to fix Horsley's testbug.el bug. */
1499 && !(WINDOWP (b
->last_selected_window
)
1500 && w
!= XWINDOW (b
->last_selected_window
)
1501 && EQ (buf
, XWINDOW (b
->last_selected_window
)->buffer
)))
1502 temp_set_point_both (b
,
1503 clip_to_bounds (BUF_BEGV (b
),
1504 XMARKER (w
->pointm
)->charpos
,
1506 clip_to_bounds (BUF_BEGV_BYTE (b
),
1507 marker_byte_position (w
->pointm
),
1510 if (WINDOWP (b
->last_selected_window
)
1511 && w
== XWINDOW (b
->last_selected_window
))
1512 b
->last_selected_window
= Qnil
;
1515 /* Put replacement into the window structure in place of old. */
1517 replace_window (Lisp_Object old
, Lisp_Object replacement
)
1519 register Lisp_Object tem
;
1520 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
1522 /* If OLD is its frame's root_window, then replacement is the new
1523 root_window for that frame. */
1525 if (EQ (old
, FRAME_ROOT_WINDOW (XFRAME (o
->frame
))))
1526 FRAME_ROOT_WINDOW (XFRAME (o
->frame
)) = replacement
;
1528 p
->left_col
= o
->left_col
;
1529 p
->top_line
= o
->top_line
;
1530 p
->total_cols
= o
->total_cols
;
1531 p
->total_lines
= o
->total_lines
;
1532 p
->desired_matrix
= p
->current_matrix
= 0;
1534 memset (&p
->cursor
, 0, sizeof (p
->cursor
));
1535 memset (&p
->last_cursor
, 0, sizeof (p
->last_cursor
));
1536 memset (&p
->phys_cursor
, 0, sizeof (p
->phys_cursor
));
1537 p
->phys_cursor_type
= -1;
1538 p
->phys_cursor_width
= -1;
1539 p
->must_be_updated_p
= 0;
1540 p
->pseudo_window_p
= 0;
1541 XSETFASTINT (p
->window_end_vpos
, 0);
1542 XSETFASTINT (p
->window_end_pos
, 0);
1543 p
->window_end_valid
= Qnil
;
1544 p
->frozen_window_start_p
= 0;
1545 p
->orig_top_line
= p
->orig_total_lines
= Qnil
;
1547 p
->next
= tem
= o
->next
;
1549 XWINDOW (tem
)->prev
= replacement
;
1551 p
->prev
= tem
= o
->prev
;
1553 XWINDOW (tem
)->next
= replacement
;
1555 p
->parent
= tem
= o
->parent
;
1558 if (EQ (XWINDOW (tem
)->vchild
, old
))
1559 XWINDOW (tem
)->vchild
= replacement
;
1560 if (EQ (XWINDOW (tem
)->hchild
, old
))
1561 XWINDOW (tem
)->hchild
= replacement
;
1564 /*** Here, if replacement is a vertical combination
1565 and so is its new parent, we should make replacement's
1566 children be children of that parent instead. ***/
1569 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
1570 doc
: /* Remove WINDOW from its frame.
1571 WINDOW defaults to the selected window. Return nil.
1572 Signal an error when WINDOW is the only window on its frame. */)
1573 (register Lisp_Object window
)
1577 window
= selected_window
;
1579 CHECK_LIVE_WINDOW (window
);
1581 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
1582 delete_window (window
);
1584 run_window_configuration_change_hook (f
);
1590 delete_window (register Lisp_Object window
)
1592 register Lisp_Object tem
, parent
, sib
;
1593 register struct window
*p
;
1594 register struct window
*par
;
1597 /* Because this function is called by other C code on non-leaf
1598 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1599 so we can't decode_window here. */
1600 CHECK_WINDOW (window
);
1601 p
= XWINDOW (window
);
1603 /* It's a no-op to delete an already-deleted window. */
1604 if (NILP (p
->buffer
)
1606 && NILP (p
->vchild
))
1611 error ("Attempt to delete minibuffer or sole ordinary window");
1612 par
= XWINDOW (parent
);
1614 windows_or_buffers_changed
++;
1615 Vwindow_list
= Qnil
;
1616 f
= XFRAME (WINDOW_FRAME (p
));
1617 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
1619 /* Are we trying to delete any frame's selected window? */
1621 Lisp_Object swindow
, pwindow
;
1623 /* See if the frame's selected window is either WINDOW
1624 or any subwindow of it, by finding all that window's parents
1625 and comparing each one with WINDOW. */
1626 swindow
= FRAME_SELECTED_WINDOW (f
);
1631 while (!NILP (pwindow
))
1633 if (EQ (window
, pwindow
))
1635 pwindow
= XWINDOW (pwindow
)->parent
;
1638 /* If the window being deleted is not a parent of SWINDOW,
1639 then SWINDOW is ok as the new selected window. */
1640 if (!EQ (window
, pwindow
))
1642 /* Otherwise, try another window for SWINDOW. */
1643 swindow
= Fnext_window (swindow
, Qlambda
, Qnil
);
1645 /* If we get back to the frame's selected window,
1646 it means there was no acceptable alternative,
1647 so we cannot delete. */
1648 if (EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1649 error ("Cannot delete window");
1652 /* If we need to change SWINDOW, do it. */
1653 if (! EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1655 /* If we're about to delete the selected window on the
1656 selected frame, then we should use Fselect_window to select
1657 the new window. On the other hand, if we're about to
1658 delete the selected window on any other frame, we shouldn't do
1659 anything but set the frame's selected_window slot. */
1660 if (EQ (FRAME_SELECTED_WINDOW (f
), selected_window
))
1661 Fselect_window (swindow
, Qnil
);
1663 FRAME_SELECTED_WINDOW (f
) = swindow
;
1667 /* Now we know we can delete this one. */
1668 window_deletion_count
++;
1671 /* tem is null for dummy parent windows
1672 (which have inferiors but not any contents themselves) */
1676 unchain_marker (XMARKER (p
->pointm
));
1677 unchain_marker (XMARKER (p
->start
));
1680 /* Free window glyph matrices. It is sure that they are allocated
1681 again when ADJUST_GLYPHS is called. Block input so that expose
1682 events and other events that access glyph matrices are not
1683 processed while we are changing them. */
1685 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f
)));
1689 XWINDOW (tem
)->prev
= p
->prev
;
1693 XWINDOW (tem
)->next
= p
->next
;
1695 if (EQ (window
, par
->hchild
))
1696 par
->hchild
= p
->next
;
1697 if (EQ (window
, par
->vchild
))
1698 par
->vchild
= p
->next
;
1700 /* Find one of our siblings to give our space to. */
1704 /* If p gives its space to its next sibling, that sibling needs
1705 to have its top/left side pulled back to where p's is.
1706 set_window_{height,width} will re-position the sibling's
1709 XWINDOW (sib
)->top_line
= p
->top_line
;
1710 XWINDOW (sib
)->left_col
= p
->left_col
;
1713 /* Stretch that sibling. */
1714 if (!NILP (par
->vchild
))
1715 set_window_height (sib
,
1716 XFASTINT (XWINDOW (sib
)->total_lines
) + XFASTINT (p
->total_lines
),
1718 if (!NILP (par
->hchild
))
1719 set_window_width (sib
,
1720 XFASTINT (XWINDOW (sib
)->total_cols
) + XFASTINT (p
->total_cols
),
1723 /* If parent now has only one child,
1724 put the child into the parent's place. */
1728 if (NILP (XWINDOW (tem
)->next
)) {
1729 replace_window (parent
, tem
);
1730 par
= XWINDOW (tem
);
1733 /* Since we may be deleting combination windows, we must make sure that
1734 not only p but all its children have been marked as deleted. */
1735 if (! NILP (p
->hchild
))
1736 delete_all_subwindows (XWINDOW (p
->hchild
));
1737 else if (! NILP (p
->vchild
))
1738 delete_all_subwindows (XWINDOW (p
->vchild
));
1740 /* Mark this window as deleted. */
1741 p
->buffer
= p
->hchild
= p
->vchild
= Qnil
;
1743 if (! NILP (par
->parent
))
1744 par
= XWINDOW (par
->parent
);
1746 /* Check if we have a v/hchild with a v/hchild. In that case remove
1749 if (! NILP (par
->vchild
) && ! NILP (XWINDOW (par
->vchild
)->vchild
))
1751 p
= XWINDOW (par
->vchild
);
1752 par
->vchild
= p
->vchild
;
1755 else if (! NILP (par
->hchild
) && ! NILP (XWINDOW (par
->hchild
)->hchild
))
1757 p
= XWINDOW (par
->hchild
);
1758 par
->hchild
= p
->hchild
;
1766 while (! NILP (tem
)) {
1767 XWINDOW (tem
)->parent
= p
->parent
;
1768 if (NILP (XWINDOW (tem
)->next
))
1770 tem
= XWINDOW (tem
)->next
;
1773 /* The next of the v/hchild we are removing is now the next of the
1774 last child for the v/hchild:
1775 Before v/hchild -> v/hchild -> next1 -> next2
1778 After: v/hchild -> next1 -> next2 -> next3
1780 XWINDOW (tem
)->next
= p
->next
;
1781 if (! NILP (p
->next
))
1782 XWINDOW (p
->next
)->prev
= tem
;
1784 p
->next
= p
->prev
= p
->vchild
= p
->hchild
= p
->buffer
= Qnil
;
1788 /* Adjust glyph matrices. */
1795 /***********************************************************************
1797 ***********************************************************************/
1799 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1800 pointer. This is a callback function for foreach_window, used in
1801 function window_list. */
1804 add_window_to_list (struct window
*w
, void *user_data
)
1806 Lisp_Object
*list
= (Lisp_Object
*) user_data
;
1808 XSETWINDOW (window
, w
);
1809 *list
= Fcons (window
, *list
);
1814 /* Return a list of all windows, for use by next_window. If
1815 Vwindow_list is a list, return that list. Otherwise, build a new
1816 list, cache it in Vwindow_list, and return that. */
1821 if (!CONSP (Vwindow_list
))
1825 Vwindow_list
= Qnil
;
1826 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
1828 Lisp_Object args
[2];
1830 /* We are visiting windows in canonical order, and add
1831 new windows at the front of args[1], which means we
1832 have to reverse this list at the end. */
1834 foreach_window (XFRAME (XCAR (tail
)), add_window_to_list
, &args
[1]);
1835 args
[0] = Vwindow_list
;
1836 args
[1] = Fnreverse (args
[1]);
1837 Vwindow_list
= Fnconc (2, args
);
1841 return Vwindow_list
;
1845 /* Value is non-zero if WINDOW satisfies the constraints given by
1846 OWINDOW, MINIBUF and ALL_FRAMES.
1848 MINIBUF t means WINDOW may be minibuffer windows.
1849 `lambda' means WINDOW may not be a minibuffer window.
1850 a window means a specific minibuffer window
1852 ALL_FRAMES t means search all frames,
1853 nil means search just current frame,
1854 `visible' means search just visible frames,
1855 0 means search visible and iconified frames,
1856 a window means search the frame that window belongs to,
1857 a frame means consider windows on that frame, only. */
1860 candidate_window_p (Lisp_Object window
, Lisp_Object owindow
, Lisp_Object minibuf
, Lisp_Object all_frames
)
1862 struct window
*w
= XWINDOW (window
);
1863 struct frame
*f
= XFRAME (w
->frame
);
1864 int candidate_p
= 1;
1866 if (!BUFFERP (w
->buffer
))
1868 else if (MINI_WINDOW_P (w
)
1869 && (EQ (minibuf
, Qlambda
)
1870 || (WINDOWP (minibuf
) && !EQ (minibuf
, window
))))
1872 /* If MINIBUF is `lambda' don't consider any mini-windows.
1873 If it is a window, consider only that one. */
1876 else if (EQ (all_frames
, Qt
))
1878 else if (NILP (all_frames
))
1880 xassert (WINDOWP (owindow
));
1881 candidate_p
= EQ (w
->frame
, XWINDOW (owindow
)->frame
);
1883 else if (EQ (all_frames
, Qvisible
))
1885 FRAME_SAMPLE_VISIBILITY (f
);
1886 candidate_p
= FRAME_VISIBLE_P (f
)
1887 && (FRAME_TERMINAL (XFRAME (w
->frame
))
1888 == FRAME_TERMINAL (XFRAME (selected_frame
)));
1891 else if (INTEGERP (all_frames
) && XINT (all_frames
) == 0)
1893 FRAME_SAMPLE_VISIBILITY (f
);
1894 candidate_p
= (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
)
1895 #ifdef HAVE_X_WINDOWS
1896 /* Yuck!! If we've just created the frame and the
1897 window-manager requested the user to place it
1898 manually, the window may still not be considered
1899 `visible'. I'd argue it should be at least
1900 something like `iconified', but don't know how to do
1902 || (FRAME_X_P (f
) && f
->output_data
.x
->asked_for_visible
1903 && !f
->output_data
.x
->has_been_visible
)
1906 && (FRAME_TERMINAL (XFRAME (w
->frame
))
1907 == FRAME_TERMINAL (XFRAME (selected_frame
)));
1909 else if (WINDOWP (all_frames
))
1910 candidate_p
= (EQ (FRAME_MINIBUF_WINDOW (f
), all_frames
)
1911 || EQ (XWINDOW (all_frames
)->frame
, w
->frame
)
1912 || EQ (XWINDOW (all_frames
)->frame
, FRAME_FOCUS_FRAME (f
)));
1913 else if (FRAMEP (all_frames
))
1914 candidate_p
= EQ (all_frames
, w
->frame
);
1920 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1921 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1925 decode_next_window_args (Lisp_Object
*window
, Lisp_Object
*minibuf
, Lisp_Object
*all_frames
)
1928 *window
= selected_window
;
1930 CHECK_LIVE_WINDOW (*window
);
1932 /* MINIBUF nil may or may not include minibuffers. Decide if it
1934 if (NILP (*minibuf
))
1935 *minibuf
= minibuf_level
? minibuf_window
: Qlambda
;
1936 else if (!EQ (*minibuf
, Qt
))
1939 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1940 => count none of them, or a specific minibuffer window (the
1941 active one) to count. */
1943 /* ALL_FRAMES nil doesn't specify which frames to include. */
1944 if (NILP (*all_frames
))
1945 *all_frames
= (!EQ (*minibuf
, Qlambda
)
1946 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window
)->frame
))
1948 else if (EQ (*all_frames
, Qvisible
))
1950 else if (EQ (*all_frames
, make_number (0)))
1952 else if (FRAMEP (*all_frames
))
1954 else if (!EQ (*all_frames
, Qt
))
1957 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1958 search just current frame, `visible' meaning search just visible
1959 frames, 0 meaning search visible and iconified frames, or a
1960 window, meaning search the frame that window belongs to, or a
1961 frame, meaning consider windows on that frame, only. */
1965 /* Return the next or previous window of WINDOW in cyclic ordering
1966 of windows. NEXT_P non-zero means return the next window. See the
1967 documentation string of next-window for the meaning of MINIBUF and
1971 next_window (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
, int next_p
)
1973 decode_next_window_args (&window
, &minibuf
, &all_frames
);
1975 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1976 return the first window on the frame. */
1977 if (FRAMEP (all_frames
)
1978 && !EQ (all_frames
, XWINDOW (window
)->frame
))
1979 return Fframe_first_window (all_frames
);
1985 /* Find WINDOW in the list of all windows. */
1986 list
= Fmemq (window
, window_list ());
1988 /* Scan forward from WINDOW to the end of the window list. */
1990 for (list
= XCDR (list
); CONSP (list
); list
= XCDR (list
))
1991 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1994 /* Scan from the start of the window list up to WINDOW. */
1996 for (list
= Vwindow_list
;
1997 CONSP (list
) && !EQ (XCAR (list
), window
);
1999 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
2003 window
= XCAR (list
);
2007 Lisp_Object candidate
, list
;
2009 /* Scan through the list of windows for candidates. If there are
2010 candidate windows in front of WINDOW, the last one of these
2011 is the one we want. If there are candidates following WINDOW
2012 in the list, again the last one of these is the one we want. */
2014 for (list
= window_list (); CONSP (list
); list
= XCDR (list
))
2016 if (EQ (XCAR (list
), window
))
2018 if (WINDOWP (candidate
))
2021 else if (candidate_window_p (XCAR (list
), window
, minibuf
,
2023 candidate
= XCAR (list
);
2026 if (WINDOWP (candidate
))
2034 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
2035 doc
: /* Return window following WINDOW in cyclic ordering of windows.
2036 WINDOW defaults to the selected window. The optional arguments
2037 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2039 MINIBUF t means consider the minibuffer window even if the
2040 minibuffer is not active. MINIBUF nil or omitted means consider
2041 the minibuffer window only if the minibuffer is active. Any
2042 other value means do not consider the minibuffer window even if
2043 the minibuffer is active.
2045 Several frames may share a single minibuffer; if the minibuffer
2046 is active, all windows on all frames that share that minibuffer
2047 are considered too. Therefore, if you are using a separate
2048 minibuffer frame and the minibuffer is active and MINIBUF says it
2049 counts, `next-window' considers the windows in the frame from
2050 which you entered the minibuffer, as well as the minibuffer
2053 ALL-FRAMES nil or omitted means consider all windows on WINDOW's
2054 frame, plus the minibuffer window if specified by the MINIBUF
2055 argument, see above. If the minibuffer counts, consider all
2056 windows on all frames that share that minibuffer too.
2057 ALL-FRAMES t means consider all windows on all existing frames.
2058 ALL-FRAMES `visible' means consider all windows on all visible
2060 ALL-FRAMES 0 means consider all windows on all visible and
2062 ALL-FRAMES a frame means consider all windows on that frame only.
2063 Anything else means consider all windows on WINDOW's frame and no
2066 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2067 `next-window' to iterate through the entire cycle of acceptable
2068 windows, eventually ending up back at the window you started with.
2069 `previous-window' traverses the same cycle, in the reverse order. */)
2070 (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
)
2072 return next_window (window
, minibuf
, all_frames
, 1);
2076 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
2077 doc
: /* Return window preceding WINDOW in cyclic ordering of windows.
2078 WINDOW defaults to the selected window. The optional arguments
2079 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2080 For the precise meaning of these arguments see `next-window'.
2082 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2083 use `previous-window' to iterate through the entire cycle of
2084 acceptable windows, eventually ending up back at the window you
2085 started with. `next-window' traverses the same cycle, in the
2087 (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
)
2089 return next_window (window
, minibuf
, all_frames
, 0);
2093 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
2094 doc
: /* Select another window in cyclic ordering of windows.
2095 COUNT specifies the number of windows to skip, starting with the
2096 selected window, before making the selection. If COUNT is
2097 positive, skip COUNT windows forwards. If COUNT is negative,
2098 skip -COUNT windows backwards. COUNT zero means do not skip any
2099 window, so select the selected window. In an interactive call,
2100 COUNT is the numeric prefix argument. Return nil.
2102 This function uses `next-window' for finding the window to select.
2103 The argument ALL-FRAMES has the same meaning as in `next-window',
2104 but the MINIBUF argument of `next-window' is always effectively
2106 (Lisp_Object count
, Lisp_Object all_frames
)
2111 CHECK_NUMBER (count
);
2112 window
= selected_window
;
2114 for (i
= XINT (count
); i
> 0; --i
)
2115 window
= Fnext_window (window
, Qnil
, all_frames
);
2117 window
= Fprevious_window (window
, Qnil
, all_frames
);
2119 Fselect_window (window
, Qnil
);
2124 DEFUN ("window-list", Fwindow_list
, Swindow_list
, 0, 3, 0,
2125 doc
: /* Return a list of windows on FRAME, starting with WINDOW.
2126 FRAME nil or omitted means use the selected frame.
2127 WINDOW nil or omitted means use the selected window.
2128 MINIBUF t means include the minibuffer window, even if it isn't active.
2129 MINIBUF nil or omitted means include the minibuffer window only
2131 MINIBUF neither nil nor t means never include the minibuffer window. */)
2132 (Lisp_Object frame
, Lisp_Object minibuf
, Lisp_Object window
)
2135 window
= FRAMEP (frame
) ? XFRAME (frame
)->selected_window
: selected_window
;
2136 CHECK_WINDOW (window
);
2138 frame
= selected_frame
;
2140 if (!EQ (frame
, XWINDOW (window
)->frame
))
2141 error ("Window is on a different frame");
2143 return window_list_1 (window
, minibuf
, frame
);
2147 /* Return a list of windows in cyclic ordering. Arguments are like
2148 for `next-window'. */
2151 window_list_1 (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
)
2153 Lisp_Object tail
, list
, rest
;
2155 decode_next_window_args (&window
, &minibuf
, &all_frames
);
2158 for (tail
= window_list (); CONSP (tail
); tail
= XCDR (tail
))
2159 if (candidate_window_p (XCAR (tail
), window
, minibuf
, all_frames
))
2160 list
= Fcons (XCAR (tail
), list
);
2162 /* Rotate the list to start with WINDOW. */
2163 list
= Fnreverse (list
);
2164 rest
= Fmemq (window
, list
);
2165 if (!NILP (rest
) && !EQ (rest
, list
))
2167 for (tail
= list
; !EQ (XCDR (tail
), rest
); tail
= XCDR (tail
))
2169 XSETCDR (tail
, Qnil
);
2170 list
= nconc2 (rest
, list
);
2177 /* Look at all windows, performing an operation specified by TYPE
2179 If FRAMES is Qt, look at all frames;
2180 Qnil, look at just the selected frame;
2181 Qvisible, look at visible frames;
2182 a frame, just look at windows on that frame.
2183 If MINI is non-zero, perform the operation on minibuffer windows too. */
2188 GET_BUFFER_WINDOW
, /* Arg is buffer */
2189 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
2190 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
2191 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
2193 UNSHOW_BUFFER
, /* Arg is buffer */
2194 REDISPLAY_BUFFER_WINDOWS
, /* Arg is buffer */
2199 window_loop (enum window_loop type
, Lisp_Object obj
, int mini
, Lisp_Object frames
)
2201 Lisp_Object window
, windows
, best_window
, frame_arg
;
2203 struct gcpro gcpro1
;
2205 /* If we're only looping through windows on a particular frame,
2206 frame points to that frame. If we're looping through windows
2207 on all frames, frame is 0. */
2208 if (FRAMEP (frames
))
2209 f
= XFRAME (frames
);
2210 else if (NILP (frames
))
2211 f
= SELECTED_FRAME ();
2216 frame_arg
= Qlambda
;
2217 else if (EQ (frames
, make_number (0)))
2219 else if (EQ (frames
, Qvisible
))
2224 /* frame_arg is Qlambda to stick to one frame,
2225 Qvisible to consider all visible frames,
2228 /* Pick a window to start with. */
2232 window
= FRAME_SELECTED_WINDOW (f
);
2234 window
= FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2236 windows
= window_list_1 (window
, mini
? Qt
: Qnil
, frame_arg
);
2240 for (; CONSP (windows
); windows
= XCDR (windows
))
2244 window
= XCAR (windows
);
2245 w
= XWINDOW (window
);
2247 /* Note that we do not pay attention here to whether the frame
2248 is visible, since Fwindow_list skips non-visible frames if
2249 that is desired, under the control of frame_arg. */
2250 if (!MINI_WINDOW_P (w
)
2251 /* For UNSHOW_BUFFER, we must always consider all windows. */
2252 || type
== UNSHOW_BUFFER
2253 || (mini
&& minibuf_level
> 0))
2256 case GET_BUFFER_WINDOW
:
2257 if (EQ (w
->buffer
, obj
)
2258 /* Don't find any minibuffer window
2259 except the one that is currently in use. */
2260 && (MINI_WINDOW_P (w
)
2261 ? EQ (window
, minibuf_window
)
2264 if (NILP (best_window
))
2265 best_window
= window
;
2266 else if (EQ (window
, selected_window
))
2267 /* Prefer to return selected-window. */
2268 RETURN_UNGCPRO (window
);
2269 else if (EQ (Fwindow_frame (window
), selected_frame
))
2270 /* Prefer windows on the current frame. */
2271 best_window
= window
;
2275 case GET_LRU_WINDOW
:
2276 /* `obj' is an integer encoding a bitvector.
2277 `obj & 1' means consider only full-width windows.
2278 `obj & 2' means consider also dedicated windows. */
2279 if (((XINT (obj
) & 1) && !WINDOW_FULL_WIDTH_P (w
))
2280 || (!(XINT (obj
) & 2) && !NILP (w
->dedicated
))
2281 /* Minibuffer windows are always ignored. */
2282 || MINI_WINDOW_P (w
))
2284 if (NILP (best_window
)
2285 || (XFASTINT (XWINDOW (best_window
)->use_time
)
2286 > XFASTINT (w
->use_time
)))
2287 best_window
= window
;
2290 case DELETE_OTHER_WINDOWS
:
2291 if (!EQ (window
, obj
))
2292 Fdelete_window (window
);
2295 case DELETE_BUFFER_WINDOWS
:
2296 if (EQ (w
->buffer
, obj
))
2298 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2300 /* If this window is dedicated, and in a frame of its own,
2302 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
2303 && !NILP (w
->dedicated
)
2304 && other_visible_frames (f
))
2306 /* Skip the other windows on this frame.
2307 There might be one, the minibuffer! */
2308 while (CONSP (XCDR (windows
))
2309 && EQ (XWINDOW (XCAR (windows
))->frame
,
2310 XWINDOW (XCAR (XCDR (windows
)))->frame
))
2311 windows
= XCDR (windows
);
2313 /* Now we can safely delete the frame. */
2314 delete_frame (w
->frame
, Qnil
);
2316 else if (NILP (w
->parent
))
2318 /* If we're deleting the buffer displayed in the
2319 only window on the frame, find a new buffer to
2322 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
2323 /* Reset dedicated state of window. */
2324 w
->dedicated
= Qnil
;
2325 Fset_window_buffer (window
, buffer
, Qnil
);
2326 if (EQ (window
, selected_window
))
2327 Fset_buffer (w
->buffer
);
2330 Fdelete_window (window
);
2334 case GET_LARGEST_WINDOW
:
2335 { /* nil `obj' means to ignore dedicated windows. */
2336 /* Ignore dedicated windows and minibuffers. */
2337 if (MINI_WINDOW_P (w
) || (NILP (obj
) && !NILP (w
->dedicated
)))
2340 if (NILP (best_window
))
2341 best_window
= window
;
2344 struct window
*b
= XWINDOW (best_window
);
2345 if (XFASTINT (w
->total_lines
) * XFASTINT (w
->total_cols
)
2346 > XFASTINT (b
->total_lines
) * XFASTINT (b
->total_cols
))
2347 best_window
= window
;
2353 if (EQ (w
->buffer
, obj
))
2356 struct frame
*f
= XFRAME (w
->frame
);
2358 /* Find another buffer to show in this window. */
2359 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
2361 /* If this window is dedicated, and in a frame of its own,
2363 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
2364 && !NILP (w
->dedicated
)
2365 && other_visible_frames (f
))
2367 /* Skip the other windows on this frame.
2368 There might be one, the minibuffer! */
2369 while (CONSP (XCDR (windows
))
2370 && EQ (XWINDOW (XCAR (windows
))->frame
,
2371 XWINDOW (XCAR (XCDR (windows
)))->frame
))
2372 windows
= XCDR (windows
);
2374 /* Now we can safely delete the frame. */
2375 delete_frame (w
->frame
, Qnil
);
2377 else if (!NILP (w
->dedicated
) && !NILP (w
->parent
))
2380 XSETWINDOW (window
, w
);
2381 /* If this window is dedicated and not the only window
2382 in its frame, then kill it. */
2383 Fdelete_window (window
);
2387 /* Otherwise show a different buffer in the window. */
2388 w
->dedicated
= Qnil
;
2389 Fset_window_buffer (window
, buffer
, Qnil
);
2390 if (EQ (window
, selected_window
))
2391 Fset_buffer (w
->buffer
);
2396 case REDISPLAY_BUFFER_WINDOWS
:
2397 if (EQ (w
->buffer
, obj
))
2399 mark_window_display_accurate (window
, 0);
2400 w
->update_mode_line
= Qt
;
2401 XBUFFER (obj
)->prevent_redisplay_optimizations_p
= 1;
2402 ++update_mode_lines
;
2403 best_window
= window
;
2407 /* Check for a window that has a killed buffer. */
2408 case CHECK_ALL_WINDOWS
:
2409 if (! NILP (w
->buffer
)
2410 && NILP (XBUFFER (w
->buffer
)->name
))
2414 case WINDOW_LOOP_UNUSED
:
2423 /* Used for debugging. Abort if any window has a dead buffer. */
2426 check_all_windows (void)
2428 window_loop (CHECK_ALL_WINDOWS
, Qnil
, 1, Qt
);
2431 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 2, 0,
2432 doc
: /* Return the window least recently selected or used for display.
2433 \(LRU means Least Recently Used.)
2435 Return a full-width window if possible.
2436 A minibuffer window is never a candidate.
2437 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2438 so if all windows are dedicated, the value is nil.
2439 If optional argument FRAME is `visible', search all visible frames.
2440 If FRAME is 0, search all visible and iconified frames.
2441 If FRAME is t, search all frames.
2442 If FRAME is nil, search only the selected frame.
2443 If FRAME is a frame, search only that frame. */)
2444 (Lisp_Object frame
, Lisp_Object dedicated
)
2446 register Lisp_Object w
;
2447 /* First try for a window that is full-width */
2448 w
= window_loop (GET_LRU_WINDOW
,
2449 NILP (dedicated
) ? make_number (1) : make_number (3),
2451 if (!NILP (w
) && !EQ (w
, selected_window
))
2453 /* If none of them, try the rest */
2454 return window_loop (GET_LRU_WINDOW
,
2455 NILP (dedicated
) ? make_number (0) : make_number (2),
2459 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 2, 0,
2460 doc
: /* Return the largest window in area.
2461 A minibuffer window is never a candidate.
2462 A dedicated window is never a candidate unless DEDICATED is non-nil,
2463 so if all windows are dedicated, the value is nil.
2464 If optional argument FRAME is `visible', search all visible frames.
2465 If FRAME is 0, search all visible and iconified frames.
2466 If FRAME is t, search all frames.
2467 If FRAME is nil, search only the selected frame.
2468 If FRAME is a frame, search only that frame. */)
2469 (Lisp_Object frame
, Lisp_Object dedicated
)
2471 return window_loop (GET_LARGEST_WINDOW
, dedicated
, 0,
2475 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 0, 2, 0,
2476 doc
: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2477 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to the
2479 If optional argument FRAME is `visible', search all visible frames.
2480 If optional argument FRAME is 0, search all visible and iconified frames.
2481 If FRAME is t, search all frames.
2482 If FRAME is nil, search only the selected frame.
2483 If FRAME is a frame, search only that frame. */)
2484 (Lisp_Object buffer_or_name
, Lisp_Object frame
)
2488 if (NILP (buffer_or_name
))
2489 buffer
= Fcurrent_buffer ();
2491 buffer
= Fget_buffer (buffer_or_name
);
2493 if (BUFFERP (buffer
))
2494 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
2499 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
2501 doc
: /* Make WINDOW (or the selected window) fill its frame.
2502 Only the frame WINDOW is on is affected.
2503 This function tries to reduce display jumps by keeping the text
2504 previously visible in WINDOW in the same place on the frame. Doing this
2505 depends on the value of (window-start WINDOW), so if calling this
2506 function in a program gives strange scrolling, make sure the
2507 window-start value is reasonable when this function is called. */)
2508 (Lisp_Object window
)
2515 window
= selected_window
;
2517 CHECK_LIVE_WINDOW (window
);
2518 w
= XWINDOW (window
);
2520 startpos
= marker_position (w
->start
);
2521 top
= WINDOW_TOP_EDGE_LINE (w
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2523 if (MINI_WINDOW_P (w
) && top
> 0)
2524 error ("Can't expand minibuffer to full frame");
2526 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_FRAME (w
));
2528 /* Try to minimize scrolling, by setting the window start to the point
2529 will cause the text at the old window start to be at the same place
2530 on the frame. But don't try to do this if the window start is
2531 outside the visible portion (as might happen when the display is
2532 not current, due to typeahead). */
2533 new_top
= WINDOW_TOP_EDGE_LINE (w
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2535 && startpos
>= BUF_BEGV (XBUFFER (w
->buffer
))
2536 && startpos
<= BUF_ZV (XBUFFER (w
->buffer
)))
2538 struct position pos
;
2539 struct buffer
*obuf
= current_buffer
;
2541 Fset_buffer (w
->buffer
);
2542 /* This computation used to temporarily move point, but that can
2543 have unwanted side effects due to text properties. */
2544 pos
= *vmotion (startpos
, -top
, w
);
2546 set_marker_both (w
->start
, w
->buffer
, pos
.bufpos
, pos
.bytepos
);
2547 w
->window_end_valid
= Qnil
;
2548 w
->start_at_line_beg
= ((pos
.bytepos
== BEGV_BYTE
2549 || FETCH_BYTE (pos
.bytepos
- 1) == '\n') ? Qt
2551 /* We need to do this, so that the window-scroll-functions
2553 w
->optional_new_start
= Qt
;
2555 set_buffer_internal (obuf
);
2561 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
2562 0, 2, "bDelete windows on (buffer): ",
2563 doc
: /* Delete all windows showing BUFFER-OR-NAME.
2564 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2565 defaults to the current buffer.
2567 Optional second argument FRAME controls which frames are affected.
2568 If optional argument FRAME is `visible', search all visible frames.
2569 If FRAME is 0, search all visible and iconified frames.
2570 If FRAME is nil, search all frames.
2571 If FRAME is t, search only the selected frame.
2572 If FRAME is a frame, search only that frame.
2573 When a window showing BUFFER-OR-NAME is dedicated and the only window of
2574 its frame, that frame is deleted when there are other frames left. */)
2575 (Lisp_Object buffer_or_name
, Lisp_Object frame
)
2579 /* FRAME uses t and nil to mean the opposite of what window_loop
2583 else if (EQ (frame
, Qt
))
2586 if (NILP (buffer_or_name
))
2587 buffer
= Fcurrent_buffer ();
2590 buffer
= Fget_buffer (buffer_or_name
);
2591 CHECK_BUFFER (buffer
);
2594 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, frame
);
2599 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
2600 Sreplace_buffer_in_windows
,
2601 0, 1, "bReplace buffer in windows: ",
2602 doc
: /* Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
2603 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2604 defaults to the current buffer.
2606 When a window showing BUFFER-OR-NAME is dedicated that window is
2607 deleted. If that window is the only window on its frame, that frame is
2608 deleted too when there are other frames left. If there are no other
2609 frames left, some other buffer is displayed in that window. */)
2610 (Lisp_Object buffer_or_name
)
2614 if (NILP (buffer_or_name
))
2615 buffer
= Fcurrent_buffer ();
2618 buffer
= Fget_buffer (buffer_or_name
);
2619 CHECK_BUFFER (buffer
);
2622 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
2627 /* Replace BUFFER with some other buffer in all windows
2628 of all frames, even those on other keyboards. */
2631 replace_buffer_in_all_windows (Lisp_Object buffer
)
2633 Lisp_Object tail
, frame
;
2635 /* A single call to window_loop won't do the job
2636 because it only considers frames on the current keyboard.
2637 So loop manually over frames, and handle each one. */
2638 FOR_EACH_FRAME (tail
, frame
)
2639 window_loop (UNSHOW_BUFFER
, buffer
, 1, frame
);
2642 /* Set the height of WINDOW and all its inferiors. */
2644 /* The smallest acceptable dimensions for a window. Anything smaller
2645 might crash Emacs. */
2647 #define MIN_SAFE_WINDOW_WIDTH (2)
2648 #define MIN_SAFE_WINDOW_HEIGHT (1)
2650 /* For wp non-zero the total number of columns of window w. Otherwise
2651 the total number of lines of w. */
2653 #define WINDOW_TOTAL_SIZE(w, wp) \
2654 (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
2656 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2657 minimum allowable size. */
2660 check_frame_size (FRAME_PTR frame
, int *rows
, int *cols
)
2662 /* For height, we have to see:
2663 how many windows the frame has at minimum (one or two),
2664 and whether it has a menu bar or other special stuff at the top. */
2666 = ((FRAME_MINIBUF_ONLY_P (frame
) || ! FRAME_HAS_MINIBUF_P (frame
))
2667 ? MIN_SAFE_WINDOW_HEIGHT
2668 : 2 * MIN_SAFE_WINDOW_HEIGHT
);
2670 if (FRAME_TOP_MARGIN (frame
) > 0)
2671 min_height
+= FRAME_TOP_MARGIN (frame
);
2673 if (*rows
< min_height
)
2675 if (*cols
< MIN_SAFE_WINDOW_WIDTH
)
2676 *cols
= MIN_SAFE_WINDOW_WIDTH
;
2679 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2680 check if W's width can be changed, otherwise check W's height.
2681 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2682 siblings, too. If none of the siblings is resizable, WINDOW isn't
2686 window_fixed_size_p (struct window
*w
, int width_p
, int check_siblings_p
)
2691 if (!NILP (w
->hchild
))
2693 c
= XWINDOW (w
->hchild
);
2697 /* A horizontal combination is fixed-width if all of if its
2699 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2700 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2701 fixed_p
= c
== NULL
;
2705 /* A horizontal combination is fixed-height if one of if its
2707 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2708 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2709 fixed_p
= c
!= NULL
;
2712 else if (!NILP (w
->vchild
))
2714 c
= XWINDOW (w
->vchild
);
2718 /* A vertical combination is fixed-width if one of if its
2720 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2721 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2722 fixed_p
= c
!= NULL
;
2726 /* A vertical combination is fixed-height if all of if its
2728 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2729 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2730 fixed_p
= c
== NULL
;
2733 else if (BUFFERP (w
->buffer
))
2735 struct buffer
*old
= current_buffer
;
2738 current_buffer
= XBUFFER (w
->buffer
);
2739 val
= find_symbol_value (Qwindow_size_fixed
);
2740 current_buffer
= old
;
2743 if (!EQ (val
, Qunbound
))
2745 fixed_p
= !NILP (val
);
2748 && ((EQ (val
, Qheight
) && width_p
)
2749 || (EQ (val
, Qwidth
) && !width_p
)))
2753 /* Can't tell if this one is resizable without looking at
2754 siblings. If all siblings are fixed-size this one is too. */
2755 if (!fixed_p
&& check_siblings_p
&& WINDOWP (w
->parent
))
2759 for (child
= w
->prev
; WINDOWP (child
); child
= XWINDOW (child
)->prev
)
2760 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2764 for (child
= w
->next
; WINDOWP (child
); child
= XWINDOW (child
)->next
)
2765 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2778 /* Return minimum size of leaf window W. WIDTH_P non-zero means return
2779 the minimum width of W, WIDTH_P zero means return the minimum height
2780 of W. SAFE_P non-zero means ignore window-min-height|width but just
2781 return values that won't crash Emacs and don't hide components like
2782 fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the
2783 minibuffer window, always return 1. */
2786 window_min_size_2 (struct window
*w
, int width_p
, int safe_p
)
2788 /* We should consider buffer-local values of window_min_height and
2789 window_min_width here. */
2792 int safe_size
= (MIN_SAFE_WINDOW_WIDTH
2793 + WINDOW_FRINGE_COLS (w
)
2794 + WINDOW_SCROLL_BAR_COLS (w
));
2796 return safe_p
? safe_size
: max (window_min_width
, safe_size
);
2798 else if (MINI_WINDOW_P (w
))
2802 int safe_size
= (MIN_SAFE_WINDOW_HEIGHT
2803 + ((BUFFERP (w
->buffer
)
2804 && !NILP (XBUFFER (w
->buffer
)->mode_line_format
))
2807 return safe_p
? safe_size
: max (window_min_height
, safe_size
);
2811 /* Return minimum size of window W, not taking fixed-width windows into
2812 account. WIDTH_P non-zero means return the minimum width, otherwise
2813 return the minimum height. SAFE_P non-zero means ignore
2814 window-min-height|width but just return values that won't crash Emacs
2815 and don't hide components like fringes, scrollbars, or modelines. If
2816 W is a combination window, compute the minimum size from the minimum
2817 sizes of W's children. */
2820 window_min_size_1 (struct window
*w
, int width_p
, int safe_p
)
2825 if (!NILP (w
->hchild
))
2827 /* W is a horizontal combination. */
2828 c
= XWINDOW (w
->hchild
);
2833 /* The minimum width of a horizontal combination is the sum of
2834 the minimum widths of its children. */
2837 size
+= window_min_size_1 (c
, 1, safe_p
);
2838 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2843 /* The minimum height of a horizontal combination is the
2844 maximum of the minimum heights of its children. */
2847 size
= max (window_min_size_1 (c
, 0, safe_p
), size
);
2848 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2852 else if (!NILP (w
->vchild
))
2854 /* W is a vertical combination. */
2855 c
= XWINDOW (w
->vchild
);
2860 /* The minimum width of a vertical combination is the maximum
2861 of the minimum widths of its children. */
2864 size
= max (window_min_size_1 (c
, 1, safe_p
), size
);
2865 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2870 /* The minimum height of a vertical combination is the sum of
2871 the minimum height of its children. */
2874 size
+= window_min_size_1 (c
, 0, safe_p
);
2875 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2880 /* W is a leaf window. */
2881 size
= window_min_size_2 (w
, width_p
, safe_p
);
2886 /* Return the minimum size of window W, taking fixed-size windows into
2887 account. WIDTH_P non-zero means return the minimum width, otherwise
2888 return the minimum height. SAFE_P non-zero means ignore
2889 window-min-height|width but just return values that won't crash Emacs
2890 and don't hide components like fringes, scrollbars, or modelines.
2891 IGNORE_FIXED_P non-zero means ignore if W is fixed-size. Set *FIXED
2892 to 1 if W is fixed-size unless FIXED is null. */
2895 window_min_size (struct window
*w
, int width_p
, int safe_p
, int ignore_fixed_p
, int *fixed
)
2902 fixed_p
= window_fixed_size_p (w
, width_p
, 1);
2908 size
= WINDOW_TOTAL_SIZE (w
, width_p
);
2910 size
= window_min_size_1 (w
, width_p
, safe_p
);
2916 /* Adjust the margins of window W if text area is too small.
2917 Return 1 if window width is ok after adjustment; 0 if window
2918 is still too narrow. */
2921 adjust_window_margins (struct window
*w
)
2923 int box_cols
= (WINDOW_TOTAL_COLS (w
)
2924 - WINDOW_FRINGE_COLS (w
)
2925 - WINDOW_SCROLL_BAR_COLS (w
));
2926 int margin_cols
= (WINDOW_LEFT_MARGIN_COLS (w
)
2927 + WINDOW_RIGHT_MARGIN_COLS (w
));
2929 if (box_cols
- margin_cols
>= MIN_SAFE_WINDOW_WIDTH
)
2932 if (margin_cols
< 0 || box_cols
< MIN_SAFE_WINDOW_WIDTH
)
2935 /* Window's text area is too narrow, but reducing the window
2936 margins will fix that. */
2937 margin_cols
= box_cols
- MIN_SAFE_WINDOW_WIDTH
;
2938 if (WINDOW_RIGHT_MARGIN_COLS (w
) > 0)
2940 if (WINDOW_LEFT_MARGIN_COLS (w
) > 0)
2941 w
->left_margin_cols
= w
->right_margin_cols
2942 = make_number (margin_cols
/2);
2944 w
->right_margin_cols
= make_number (margin_cols
);
2947 w
->left_margin_cols
= make_number (margin_cols
);
2951 /* Calculate new sizes for windows in the list FORWARD when their
2952 compound size goes from TOTAL to SIZE. TOTAL must be greater than
2953 SIZE. The number of windows in FORWARD is NCHILDREN, and the number
2954 that can shrink is SHRINKABLE. Fixed-size windows may be shrunk if
2955 and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means
2956 shrink columns, otherwise shrink lines.
2958 SAFE_P zero means windows may be sized down to window-min-height
2959 lines (window-min-window columns for WIDTH_P non-zero). SAFE_P
2960 non-zero means windows may be sized down to their minimum safe sizes
2961 taking into account the space needed to display modelines, fringes,
2964 This function returns an allocated array of new sizes that the caller
2965 must free. A size -1 means the window is fixed and RESIZE_FIXED_P is
2966 zero. A size zero means the window shall be deleted. Array index 0
2967 refers to the first window in FORWARD, 1 to the second, and so on.
2969 This function resizes windows proportionally to their size. It also
2970 tries to preserve smaller windows by resizing larger windows before
2971 resizing any window to zero. If resize_proportionally is non-nil for
2972 a specific window, it will attempt to strictly resize that window
2973 proportionally, even at the expense of deleting smaller windows. */
2975 shrink_windows (int total
, int size
, int nchildren
, int shrinkable
,
2976 int resize_fixed_p
, Lisp_Object forward
, int width_p
, int safe_p
)
2978 int available_resize
= 0;
2979 int *new_sizes
, *min_sizes
;
2982 int smallest
= total
;
2983 int total_removed
= 0;
2984 int total_shrink
= total
- size
;
2987 new_sizes
= xmalloc (sizeof (*new_sizes
) * nchildren
);
2988 min_sizes
= xmalloc (sizeof (*min_sizes
) * nchildren
);
2990 for (i
= 0, child
= forward
; !NILP (child
); child
= c
->next
, ++i
)
2994 c
= XWINDOW (child
);
2995 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
2997 if (!resize_fixed_p
&& window_fixed_size_p (c
, width_p
, 0))
3001 new_sizes
[i
] = child_size
;
3002 min_sizes
[i
] = window_min_size_1 (c
, width_p
, safe_p
);
3003 if (child_size
> min_sizes
[i
]
3004 && NILP (c
->resize_proportionally
))
3005 available_resize
+= child_size
- min_sizes
[i
];
3008 /* We might need to shrink some windows to zero. Find the smallest
3009 windows and set them to 0 until we can fulfil the new size. */
3011 while (shrinkable
> 1 && size
+ available_resize
< total
)
3013 for (i
= 0; i
< nchildren
; ++i
)
3014 if (new_sizes
[i
] > 0 && smallest
> new_sizes
[i
])
3015 smallest
= new_sizes
[i
];
3017 for (i
= 0; i
< nchildren
; ++i
)
3018 if (new_sizes
[i
] == smallest
)
3020 /* Resize this window down to zero. */
3022 if (smallest
> min_sizes
[i
])
3023 available_resize
-= smallest
- min_sizes
[i
];
3024 available_resize
+= smallest
;
3026 total_removed
+= smallest
;
3028 /* We don't know what the smallest is now. */
3031 /* Out of for, just remove one window at the time and
3032 check again if we have enough space. */
3037 /* Now, calculate the new sizes. Try to shrink each window
3038 proportional to its size. */
3039 for (i
= 0; i
< nchildren
; ++i
)
3041 if (new_sizes
[i
] > min_sizes
[i
])
3043 int to_shrink
= total_shrink
* new_sizes
[i
] / total
;
3045 if (new_sizes
[i
] - to_shrink
< min_sizes
[i
])
3046 to_shrink
= new_sizes
[i
] - min_sizes
[i
];
3047 new_sizes
[i
] -= to_shrink
;
3048 total_removed
+= to_shrink
;
3052 /* Any reminder due to rounding, we just subtract from windows
3053 that are left and still can be shrunk. */
3054 while (total_shrink
> total_removed
)
3056 int nonzero_sizes
= 0;
3057 int nonzero_idx
= -1;
3059 for (i
= 0; i
< nchildren
; ++i
)
3060 if (new_sizes
[i
] > 0)
3066 for (i
= 0; i
< nchildren
; ++i
)
3067 if (new_sizes
[i
] > min_sizes
[i
])
3072 /* Out of for, just shrink one window at the time and
3073 check again if we have enough space. */
3077 /* Special case, only one window left. */
3078 if (nonzero_sizes
== 1)
3082 /* Any surplus due to rounding, we add to windows that are left. */
3083 while (total_shrink
< total_removed
)
3085 for (i
= 0; i
< nchildren
; ++i
)
3087 if (new_sizes
[i
] != 0 && total_shrink
< total_removed
)
3101 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
3102 WINDOW's width. Resize WINDOW's children, if any, so that they keep
3103 their proportionate size relative to WINDOW.
3105 If FIRST_ONLY is 1, change only the first of WINDOW's children when
3106 they are in series. If LAST_ONLY is 1, change only the last of
3107 WINDOW's children when they are in series.
3109 Propagate WINDOW's top or left edge position to children. Delete
3110 windows that become too small unless NODELETE_P is 1. When
3111 NODELETE_P equals 2 do not honor settings for window-min-height and
3112 window-min-width when resizing windows but use safe defaults instead.
3113 This should give better behavior when resizing frames. */
3116 size_window (Lisp_Object window
, int size
, int width_p
, int nodelete_p
, int first_only
, int last_only
)
3118 struct window
*w
= XWINDOW (window
);
3120 Lisp_Object child
, *forward
, *sideward
;
3121 int old_size
= WINDOW_TOTAL_SIZE (w
, width_p
);
3123 size
= max (0, size
);
3125 /* Delete WINDOW if it's too small. */
3126 if (nodelete_p
!= 1 && !NILP (w
->parent
)
3127 && size
< window_min_size_1 (w
, width_p
, nodelete_p
== 2))
3129 delete_window (window
);
3133 /* Set redisplay hints. */
3134 w
->last_modified
= make_number (0);
3135 w
->last_overlay_modified
= make_number (0);
3136 windows_or_buffers_changed
++;
3137 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w
->frame
)) = 1;
3141 sideward
= &w
->vchild
;
3142 forward
= &w
->hchild
;
3143 w
->total_cols
= make_number (size
);
3144 adjust_window_margins (w
);
3148 sideward
= &w
->hchild
;
3149 forward
= &w
->vchild
;
3150 w
->total_lines
= make_number (size
);
3151 w
->orig_total_lines
= Qnil
;
3154 if (!NILP (*sideward
))
3156 /* We have a chain of parallel siblings whose size should all change. */
3157 for (child
= *sideward
; !NILP (child
); child
= c
->next
)
3159 c
= XWINDOW (child
);
3161 c
->left_col
= w
->left_col
;
3163 c
->top_line
= w
->top_line
;
3164 size_window (child
, size
, width_p
, nodelete_p
,
3165 first_only
, last_only
);
3168 else if (!NILP (*forward
) && last_only
)
3170 /* Change the last in a series of siblings. */
3171 Lisp_Object last_child
;
3174 for (child
= *forward
; !NILP (child
); child
= c
->next
)
3176 c
= XWINDOW (child
);
3180 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3181 size_window (last_child
, size
- old_size
+ child_size
,
3182 width_p
, nodelete_p
, first_only
, last_only
);
3184 else if (!NILP (*forward
) && first_only
)
3186 /* Change the first in a series of siblings. */
3190 c
= XWINDOW (child
);
3193 c
->left_col
= w
->left_col
;
3195 c
->top_line
= w
->top_line
;
3197 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3198 size_window (child
, size
- old_size
+ child_size
,
3199 width_p
, nodelete_p
, first_only
, last_only
);
3201 else if (!NILP (*forward
))
3203 int fixed_size
, each
, extra
, n
;
3204 int resize_fixed_p
, nfixed
;
3205 int last_pos
, first_pos
, nchildren
, total
;
3206 int *new_sizes
= NULL
;
3208 /* Determine the fixed-size portion of this window, and the
3209 number of child windows. */
3210 fixed_size
= nchildren
= nfixed
= total
= 0;
3211 for (child
= *forward
; !NILP (child
); child
= c
->next
, ++nchildren
)
3215 c
= XWINDOW (child
);
3216 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3217 total
+= child_size
;
3219 if (window_fixed_size_p (c
, width_p
, 0))
3221 fixed_size
+= child_size
;
3226 /* If the new size is smaller than fixed_size, or if there
3227 aren't any resizable windows, allow resizing fixed-size
3229 resize_fixed_p
= nfixed
== nchildren
|| size
< fixed_size
;
3231 /* Compute how many lines/columns to add/remove to each child. The
3232 value of extra takes care of rounding errors. */
3233 n
= resize_fixed_p
? nchildren
: nchildren
- nfixed
;
3234 if (size
< total
&& n
> 1)
3235 new_sizes
= shrink_windows (total
, size
, nchildren
, n
,
3236 resize_fixed_p
, *forward
, width_p
,
3240 each
= (size
- total
) / n
;
3241 extra
= (size
- total
) - n
* each
;
3244 /* Compute new children heights and edge positions. */
3245 first_pos
= width_p
? XINT (w
->left_col
) : XINT (w
->top_line
);
3246 last_pos
= first_pos
;
3247 for (n
= 0, child
= *forward
; !NILP (child
); child
= c
->next
, ++n
)
3249 int new_size
, old_size
;
3251 c
= XWINDOW (child
);
3252 old_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3253 new_size
= old_size
;
3255 /* The top or left edge position of this child equals the
3256 bottom or right edge of its predecessor. */
3258 c
->left_col
= make_number (last_pos
);
3260 c
->top_line
= make_number (last_pos
);
3262 /* If this child can be resized, do it. */
3263 if (resize_fixed_p
|| !window_fixed_size_p (c
, width_p
, 0))
3265 new_size
= new_sizes
? new_sizes
[n
] : old_size
+ each
+ extra
;
3269 /* Set new size. Note that size_window also propagates
3270 edge positions to children, so it's not a no-op if we
3271 didn't change the child's size. */
3272 size_window (child
, new_size
, width_p
, 1, first_only
, last_only
);
3274 /* Remember the bottom/right edge position of this child; it
3275 will be used to set the top/left edge of the next child. */
3276 last_pos
+= new_size
;
3281 /* We should have covered the parent exactly with child windows. */
3282 xassert (size
== last_pos
- first_pos
);
3284 /* Now delete any children that became too small. */
3285 if (nodelete_p
!= 1)
3286 for (child
= *forward
; !NILP (child
); child
= c
->next
)
3290 c
= XWINDOW (child
);
3291 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3292 size_window (child
, child_size
, width_p
, nodelete_p
,
3293 first_only
, last_only
);
3298 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3299 WINDOW's children. NODELETE zero means windows that have become
3300 smaller than window-min-height in the process may be deleted.
3301 NODELETE 1 means never delete windows that become too small in the
3302 process. (The caller should check later and do so if appropriate.)
3303 NODELETE 2 means delete only windows that have become too small to be
3304 displayed correctly. */
3307 set_window_height (Lisp_Object window
, int height
, int nodelete
)
3309 size_window (window
, height
, 0, nodelete
, 0, 0);
3312 /* Set WINDOW's width to WIDTH, and recursively change the width of
3313 WINDOW's children. NODELETE zero means windows that have become
3314 smaller than window-min-width in the process may be deleted.
3315 NODELETE 1 means never delete windows that become too small in the
3316 process. (The caller should check later and do so if appropriate.)
3317 NODELETE 2 means delete only windows that have become too small to be
3318 displayed correctly. */
3321 set_window_width (Lisp_Object window
, int width
, int nodelete
)
3323 size_window (window
, width
, 1, nodelete
, 0, 0);
3326 /* Change window heights in windows rooted in WINDOW by N lines. */
3329 change_window_heights (Lisp_Object window
, int n
)
3331 struct window
*w
= XWINDOW (window
);
3333 XSETFASTINT (w
->top_line
, XFASTINT (w
->top_line
) + n
);
3334 XSETFASTINT (w
->total_lines
, XFASTINT (w
->total_lines
) - n
);
3336 if (INTEGERP (w
->orig_top_line
))
3337 XSETFASTINT (w
->orig_top_line
, XFASTINT (w
->orig_top_line
) + n
);
3338 if (INTEGERP (w
->orig_total_lines
))
3339 XSETFASTINT (w
->orig_total_lines
, XFASTINT (w
->orig_total_lines
) - n
);
3341 /* Handle just the top child in a vertical split. */
3342 if (!NILP (w
->vchild
))
3343 change_window_heights (w
->vchild
, n
);
3345 /* Adjust all children in a horizontal split. */
3346 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
3348 w
= XWINDOW (window
);
3349 change_window_heights (window
, n
);
3354 int window_select_count
;
3356 EXFUN (Fset_window_fringes
, 4);
3357 EXFUN (Fset_window_scroll_bars
, 4);
3360 run_funs (Lisp_Object funs
)
3362 for (; CONSP (funs
); funs
= XCDR (funs
))
3363 if (!EQ (XCAR (funs
), Qt
))
3364 call0 (XCAR (funs
));
3367 static Lisp_Object
select_window_norecord (Lisp_Object window
);
3368 static Lisp_Object
select_frame_norecord (Lisp_Object frame
);
3371 run_window_configuration_change_hook (struct frame
*f
)
3373 int count
= SPECPDL_INDEX ();
3374 Lisp_Object frame
, global_wcch
3375 = Fdefault_value (Qwindow_configuration_change_hook
);
3376 XSETFRAME (frame
, f
);
3378 if (NILP (Vrun_hooks
))
3381 if (SELECTED_FRAME () != f
)
3383 record_unwind_protect (select_frame_norecord
, Fselected_frame ());
3384 Fselect_frame (frame
, Qt
);
3387 /* Use the right buffer. Matters when running the local hooks. */
3388 if (current_buffer
!= XBUFFER (Fwindow_buffer (Qnil
)))
3390 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
3391 Fset_buffer (Fwindow_buffer (Qnil
));
3394 /* Look for buffer-local values. */
3396 Lisp_Object windows
= Fwindow_list (frame
, Qlambda
, Qnil
);
3397 for (; CONSP (windows
); windows
= XCDR (windows
))
3399 Lisp_Object window
= XCAR (windows
);
3400 Lisp_Object buffer
= Fwindow_buffer (window
);
3401 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook
,
3404 int count
= SPECPDL_INDEX ();
3405 record_unwind_protect (select_window_norecord
, Fselected_window ());
3406 select_window_norecord (window
);
3407 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook
,
3409 unbind_to (count
, Qnil
);
3414 run_funs (global_wcch
);
3415 unbind_to (count
, Qnil
);
3418 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3419 means it's allowed to run hooks. See make_frame for a case where
3420 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3421 margins, fringes, and scroll-bar settings of the window are not
3422 reset from the buffer's local settings. */
3425 set_window_buffer (Lisp_Object window
, Lisp_Object buffer
, int run_hooks_p
, int keep_margins_p
)
3427 struct window
*w
= XWINDOW (window
);
3428 struct buffer
*b
= XBUFFER (buffer
);
3429 int count
= SPECPDL_INDEX ();
3430 int samebuf
= EQ (buffer
, w
->buffer
);
3434 if (EQ (window
, selected_window
))
3435 b
->last_selected_window
= window
;
3437 /* Let redisplay errors through. */
3438 b
->display_error_modiff
= 0;
3440 /* Update time stamps of buffer display. */
3441 if (INTEGERP (b
->display_count
))
3442 XSETINT (b
->display_count
, XINT (b
->display_count
) + 1);
3443 b
->display_time
= Fcurrent_time ();
3445 XSETFASTINT (w
->window_end_pos
, 0);
3446 XSETFASTINT (w
->window_end_vpos
, 0);
3447 memset (&w
->last_cursor
, 0, sizeof w
->last_cursor
);
3448 w
->window_end_valid
= Qnil
;
3449 if (!(keep_margins_p
&& samebuf
))
3450 { /* If we're not actually changing the buffer, don't reset hscroll and
3451 vscroll. This case happens for example when called from
3452 change_frame_size_1, where we use a dummy call to
3453 Fset_window_buffer on the frame's selected window (and no other)
3454 just in order to run window-configuration-change-hook.
3455 Resetting hscroll and vscroll here is problematic for things like
3456 image-mode and doc-view-mode since it resets the image's position
3457 whenever we resize the frame. */
3458 w
->hscroll
= w
->min_hscroll
= make_number (0);
3460 set_marker_both (w
->pointm
, buffer
, BUF_PT (b
), BUF_PT_BYTE (b
));
3461 set_marker_restricted (w
->start
,
3462 make_number (b
->last_window_start
),
3464 w
->start_at_line_beg
= Qnil
;
3465 w
->force_start
= Qnil
;
3466 XSETFASTINT (w
->last_modified
, 0);
3467 XSETFASTINT (w
->last_overlay_modified
, 0);
3469 /* Maybe we could move this into the `if' but it's not obviously safe and
3470 I doubt it's worth the trouble. */
3471 windows_or_buffers_changed
++;
3473 /* We must select BUFFER for running the window-scroll-functions. */
3474 /* We can't check ! NILP (Vwindow_scroll_functions) here
3475 because that might itself be a local variable. */
3476 if (window_initialized
)
3478 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
3479 Fset_buffer (buffer
);
3482 XMARKER (w
->pointm
)->insertion_type
= !NILP (Vwindow_point_insertion_type
);
3484 if (!keep_margins_p
)
3486 /* Set left and right marginal area width etc. from buffer. */
3488 /* This may call adjust_window_margins three times, so
3489 temporarily disable window margins. */
3490 Lisp_Object save_left
= w
->left_margin_cols
;
3491 Lisp_Object save_right
= w
->right_margin_cols
;
3493 w
->left_margin_cols
= w
->right_margin_cols
= Qnil
;
3495 Fset_window_fringes (window
,
3496 b
->left_fringe_width
, b
->right_fringe_width
,
3497 b
->fringes_outside_margins
);
3499 Fset_window_scroll_bars (window
,
3500 b
->scroll_bar_width
,
3501 b
->vertical_scroll_bar_type
, Qnil
);
3503 w
->left_margin_cols
= save_left
;
3504 w
->right_margin_cols
= save_right
;
3506 Fset_window_margins (window
,
3507 b
->left_margin_cols
, b
->right_margin_cols
);
3512 if (! NILP (Vwindow_scroll_functions
))
3513 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
3514 Fmarker_position (w
->start
));
3515 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w
)));
3518 unbind_to (count
, Qnil
);
3522 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 3, 0,
3523 doc
: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3524 WINDOW defaults to the selected window. BUFFER-OR-NAME must be a buffer
3525 or the name of an existing buffer. Optional third argument KEEP-MARGINS
3526 non-nil means that WINDOW's current display margins, fringe widths, and
3527 scroll bar settings are preserved; the default is to reset these from
3528 the local settings for BUFFER-OR-NAME or the frame defaults. Return nil.
3530 This function throws an error when WINDOW is strongly dedicated to its
3531 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3532 already display BUFFER-OR-NAME.
3534 This function runs `window-scroll-functions' before running
3535 `window-configuration-change-hook'. */)
3536 (register Lisp_Object window
, Lisp_Object buffer_or_name
, Lisp_Object keep_margins
)
3538 register Lisp_Object tem
, buffer
;
3539 register struct window
*w
= decode_window (window
);
3541 XSETWINDOW (window
, w
);
3542 buffer
= Fget_buffer (buffer_or_name
);
3543 CHECK_BUFFER (buffer
);
3544 if (NILP (XBUFFER (buffer
)->name
))
3545 error ("Attempt to display deleted buffer");
3549 error ("Window is deleted");
3550 else if (!EQ (tem
, Qt
))
3551 /* w->buffer is t when the window is first being set up. */
3553 if (!EQ (tem
, buffer
))
3554 if (EQ (w
->dedicated
, Qt
))
3555 error ("Window is dedicated to `%s'", SDATA (XBUFFER (tem
)->name
));
3557 w
->dedicated
= Qnil
;
3562 set_window_buffer (window
, buffer
, 1, !NILP (keep_margins
));
3566 /* Note that selected_window can be nil when this is called from
3567 Fset_window_configuration. */
3569 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 2, 0,
3570 doc
: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3571 If WINDOW is not already selected, make WINDOW's buffer current
3572 and make WINDOW the frame's selected window. Return WINDOW.
3573 Optional second arg NORECORD non-nil means do not put this buffer
3574 at the front of the list of recently selected ones and do not
3575 make this window the most recently selected one.
3577 Note that the main editor command loop selects the buffer of the
3578 selected window before each command. */)
3579 (register Lisp_Object window
, Lisp_Object norecord
)
3581 register struct window
*w
;
3582 register struct window
*ow
;
3585 CHECK_LIVE_WINDOW (window
);
3587 w
= XWINDOW (window
);
3588 w
->frozen_window_start_p
= 0;
3590 if (NILP (norecord
))
3592 ++window_select_count
;
3593 XSETFASTINT (w
->use_time
, window_select_count
);
3594 record_buffer (w
->buffer
);
3597 if (EQ (window
, selected_window
))
3600 sf
= SELECTED_FRAME ();
3601 if (XFRAME (WINDOW_FRAME (w
)) != sf
)
3603 XFRAME (WINDOW_FRAME (w
))->selected_window
= window
;
3604 /* Use this rather than Fhandle_switch_frame
3605 so that FRAME_FOCUS_FRAME is moved appropriately as we
3606 move around in the state where a minibuffer in a separate
3608 Fselect_frame (WINDOW_FRAME (w
), norecord
);
3609 /* Fselect_frame called us back so we've done all the work already. */
3610 eassert (EQ (window
, selected_window
));
3614 sf
->selected_window
= window
;
3616 /* Store the current buffer's actual point into the
3617 old selected window. It belongs to that window,
3618 and when the window is not selected, must be in the window. */
3619 if (!NILP (selected_window
))
3621 ow
= XWINDOW (selected_window
);
3622 if (! NILP (ow
->buffer
))
3623 set_marker_both (ow
->pointm
, ow
->buffer
,
3624 BUF_PT (XBUFFER (ow
->buffer
)),
3625 BUF_PT_BYTE (XBUFFER (ow
->buffer
)));
3628 selected_window
= window
;
3630 Fset_buffer (w
->buffer
);
3632 XBUFFER (w
->buffer
)->last_selected_window
= window
;
3634 /* Go to the point recorded in the window.
3635 This is important when the buffer is in more
3636 than one window. It also matters when
3637 redisplay_window has altered point after scrolling,
3638 because it makes the change only in the window. */
3640 register int new_point
= marker_position (w
->pointm
);
3641 if (new_point
< BEGV
)
3643 else if (new_point
> ZV
)
3649 windows_or_buffers_changed
++;
3654 select_window_norecord (Lisp_Object window
)
3656 return WINDOW_LIVE_P (window
)
3657 ? Fselect_window (window
, Qt
) : selected_window
;
3661 select_frame_norecord (Lisp_Object frame
)
3663 return FRAME_LIVE_P (XFRAME (frame
))
3664 ? Fselect_frame (frame
, Qt
) : selected_frame
;
3668 display_buffer (Lisp_Object buffer
, Lisp_Object not_this_window_p
, Lisp_Object override_frame
)
3670 return call3 (Qdisplay_buffer
, buffer
, not_this_window_p
, override_frame
);
3673 DEFUN ("force-window-update", Fforce_window_update
, Sforce_window_update
,
3675 doc
: /* Force all windows to be updated on next redisplay.
3676 If optional arg OBJECT is a window, force redisplay of that window only.
3677 If OBJECT is a buffer or buffer name, force redisplay of all windows
3678 displaying that buffer. */)
3679 (Lisp_Object object
)
3683 windows_or_buffers_changed
++;
3684 update_mode_lines
++;
3688 if (WINDOWP (object
))
3690 struct window
*w
= XWINDOW (object
);
3691 mark_window_display_accurate (object
, 0);
3692 w
->update_mode_line
= Qt
;
3693 if (BUFFERP (w
->buffer
))
3694 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
3695 ++update_mode_lines
;
3699 if (STRINGP (object
))
3700 object
= Fget_buffer (object
);
3701 if (BUFFERP (object
) && !NILP (XBUFFER (object
)->name
))
3703 /* Walk all windows looking for buffer, and force update
3704 of each of those windows. */
3706 object
= window_loop (REDISPLAY_BUFFER_WINDOWS
, object
, 0, Qvisible
);
3707 return NILP (object
) ? Qnil
: Qt
;
3710 /* If nothing suitable was found, just return.
3711 We could signal an error, but this feature will typically be used
3712 asynchronously in timers or process sentinels, so we don't. */
3718 temp_output_buffer_show (register Lisp_Object buf
)
3720 register struct buffer
*old
= current_buffer
;
3721 register Lisp_Object window
;
3722 register struct window
*w
;
3724 XBUFFER (buf
)->directory
= current_buffer
->directory
;
3727 BUF_SAVE_MODIFF (XBUFFER (buf
)) = MODIFF
;
3731 #if 0 /* rms: there should be no reason for this. */
3732 XBUFFER (buf
)->prevent_redisplay_optimizations_p
= 1;
3734 set_buffer_internal (old
);
3736 if (!NILP (Vtemp_buffer_show_function
))
3737 call1 (Vtemp_buffer_show_function
, buf
);
3740 window
= display_buffer (buf
, Qnil
, Qnil
);
3742 if (!EQ (XWINDOW (window
)->frame
, selected_frame
))
3743 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
3744 Vminibuf_scroll_window
= window
;
3745 w
= XWINDOW (window
);
3746 XSETFASTINT (w
->hscroll
, 0);
3747 XSETFASTINT (w
->min_hscroll
, 0);
3748 set_marker_restricted_both (w
->start
, buf
, BEG
, BEG
);
3749 set_marker_restricted_both (w
->pointm
, buf
, BEG
, BEG
);
3751 /* Run temp-buffer-show-hook, with the chosen window selected
3752 and its buffer current. */
3754 if (!NILP (Vrun_hooks
)
3755 && !NILP (Fboundp (Qtemp_buffer_show_hook
))
3756 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook
)))
3758 int count
= SPECPDL_INDEX ();
3759 Lisp_Object prev_window
, prev_buffer
;
3760 prev_window
= selected_window
;
3761 XSETBUFFER (prev_buffer
, old
);
3763 /* Select the window that was chosen, for running the hook.
3764 Note: Both Fselect_window and select_window_norecord may
3765 set-buffer to the buffer displayed in the window,
3766 so we need to save the current buffer. --stef */
3767 record_unwind_protect (Fset_buffer
, prev_buffer
);
3768 record_unwind_protect (select_window_norecord
, prev_window
);
3769 Fselect_window (window
, Qt
);
3770 Fset_buffer (w
->buffer
);
3771 call1 (Vrun_hooks
, Qtemp_buffer_show_hook
);
3772 unbind_to (count
, Qnil
);
3778 make_dummy_parent (Lisp_Object window
)
3781 register struct window
*o
, *p
;
3784 o
= XWINDOW (window
);
3785 p
= allocate_window ();
3786 for (i
= 0; i
< VECSIZE (struct window
); ++i
)
3787 ((struct Lisp_Vector
*) p
)->contents
[i
]
3788 = ((struct Lisp_Vector
*)o
)->contents
[i
];
3789 XSETWINDOW (new, p
);
3792 XSETFASTINT (p
->sequence_number
, sequence_number
);
3794 /* Put new into window structure in place of window */
3795 replace_window (window
, new);
3808 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
3809 doc
: /* Split WINDOW, putting SIZE lines in the first of the pair.
3810 WINDOW defaults to selected one and SIZE to half its size.
3811 If optional third arg HORIZONTAL is non-nil, split side by side and put
3812 SIZE columns in the first of the pair. In that case, SIZE includes that
3813 window's scroll bar, or the divider column to its right.
3814 Interactively, all arguments are nil.
3815 Returns the newly created window (which is the lower or rightmost one).
3816 The upper or leftmost window is the original one, and remains selected
3817 if it was selected before.
3819 See Info node `(elisp)Splitting Windows' for more details and examples. */)
3820 (Lisp_Object window
, Lisp_Object size
, Lisp_Object horizontal
)
3822 register Lisp_Object
new;
3823 register struct window
*o
, *p
;
3825 register int size_int
;
3828 window
= selected_window
;
3830 CHECK_LIVE_WINDOW (window
);
3832 o
= XWINDOW (window
);
3833 fo
= XFRAME (WINDOW_FRAME (o
));
3837 if (!NILP (horizontal
))
3838 /* Calculate the size of the left-hand window, by dividing
3839 the usable space in columns by two.
3840 We round up, since the left-hand window may include
3841 a dividing line, while the right-hand may not. */
3842 size_int
= (XFASTINT (o
->total_cols
) + 1) >> 1;
3844 size_int
= XFASTINT (o
->total_lines
) >> 1;
3848 CHECK_NUMBER (size
);
3849 size_int
= XINT (size
);
3852 if (MINI_WINDOW_P (o
))
3853 error ("Attempt to split minibuffer window");
3854 else if (window_fixed_size_p (o
, !NILP (horizontal
), 0))
3855 error ("Attempt to split fixed-size window");
3857 if (NILP (horizontal
))
3859 int window_safe_height
= window_min_size_2 (o
, 0, 0);
3861 if (size_int
< window_safe_height
)
3862 error ("Window height %d too small (after splitting)", size_int
);
3863 if (size_int
+ window_safe_height
> XFASTINT (o
->total_lines
))
3864 error ("Window height %d too small (after splitting)",
3865 XFASTINT (o
->total_lines
) - size_int
);
3866 if (NILP (o
->parent
)
3867 || NILP (XWINDOW (o
->parent
)->vchild
))
3869 make_dummy_parent (window
);
3871 XWINDOW (new)->vchild
= window
;
3876 int window_safe_width
= window_min_size_2 (o
, 1, 0);
3878 if (size_int
< window_safe_width
)
3879 error ("Window width %d too small (after splitting)", size_int
);
3880 if (size_int
+ window_safe_width
> XFASTINT (o
->total_cols
))
3881 error ("Window width %d too small (after splitting)",
3882 XFASTINT (o
->total_cols
) - size_int
);
3883 if (NILP (o
->parent
)
3884 || NILP (XWINDOW (o
->parent
)->hchild
))
3886 make_dummy_parent (window
);
3888 XWINDOW (new)->hchild
= window
;
3892 /* Now we know that window's parent is a vertical combination
3893 if we are dividing vertically, or a horizontal combination
3894 if we are making side-by-side windows */
3896 windows_or_buffers_changed
++;
3897 FRAME_WINDOW_SIZES_CHANGED (fo
) = 1;
3898 new = make_window ();
3901 p
->frame
= o
->frame
;
3903 if (!NILP (p
->next
))
3904 XWINDOW (p
->next
)->prev
= new;
3907 p
->parent
= o
->parent
;
3909 p
->window_end_valid
= Qnil
;
3910 memset (&p
->last_cursor
, 0, sizeof p
->last_cursor
);
3912 /* Duplicate special geometry settings. */
3914 p
->left_margin_cols
= o
->left_margin_cols
;
3915 p
->right_margin_cols
= o
->right_margin_cols
;
3916 p
->left_fringe_width
= o
->left_fringe_width
;
3917 p
->right_fringe_width
= o
->right_fringe_width
;
3918 p
->fringes_outside_margins
= o
->fringes_outside_margins
;
3919 p
->scroll_bar_width
= o
->scroll_bar_width
;
3920 p
->vertical_scroll_bar_type
= o
->vertical_scroll_bar_type
;
3922 /* Apportion the available frame space among the two new windows */
3924 if (!NILP (horizontal
))
3926 p
->total_lines
= o
->total_lines
;
3927 p
->top_line
= o
->top_line
;
3928 XSETFASTINT (p
->total_cols
, XFASTINT (o
->total_cols
) - size_int
);
3929 XSETFASTINT (o
->total_cols
, size_int
);
3930 XSETFASTINT (p
->left_col
, XFASTINT (o
->left_col
) + size_int
);
3931 adjust_window_margins (p
);
3932 adjust_window_margins (o
);
3936 p
->left_col
= o
->left_col
;
3937 p
->total_cols
= o
->total_cols
;
3938 XSETFASTINT (p
->total_lines
, XFASTINT (o
->total_lines
) - size_int
);
3939 XSETFASTINT (o
->total_lines
, size_int
);
3940 XSETFASTINT (p
->top_line
, XFASTINT (o
->top_line
) + size_int
);
3943 /* Adjust glyph matrices. */
3946 Fset_window_buffer (new, o
->buffer
, Qt
);
3950 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
3951 doc
: /* Make selected window SIZE lines taller.
3952 Interactively, if no argument is given, make the selected window one
3953 line taller. If optional argument HORIZONTAL is non-nil, make selected
3954 window wider by SIZE columns. If SIZE is negative, shrink the window by
3955 -SIZE lines or columns. Return nil.
3957 This function can delete windows if they get too small. The size of
3958 fixed size windows is not altered by this function. */)
3959 (Lisp_Object size
, Lisp_Object horizontal
)
3961 CHECK_NUMBER (size
);
3962 enlarge_window (selected_window
, XINT (size
), !NILP (horizontal
));
3964 run_window_configuration_change_hook (SELECTED_FRAME ());
3969 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
3970 doc
: /* Make selected window SIZE lines smaller.
3971 Interactively, if no argument is given, make the selected window one
3972 line smaller. If optional argument HORIZONTAL is non-nil, make the
3973 window narrower by SIZE columns. If SIZE is negative, enlarge selected
3974 window by -SIZE lines or columns. Return nil.
3976 This function can delete windows if they get too small. The size of
3977 fixed size windows is not altered by this function. */)
3978 (Lisp_Object size
, Lisp_Object horizontal
)
3980 CHECK_NUMBER (size
);
3981 enlarge_window (selected_window
, -XINT (size
), !NILP (horizontal
));
3983 run_window_configuration_change_hook (SELECTED_FRAME ());
3989 window_height (Lisp_Object window
)
3991 register struct window
*p
= XWINDOW (window
);
3992 return WINDOW_TOTAL_LINES (p
);
3996 window_width (Lisp_Object window
)
3998 register struct window
*p
= XWINDOW (window
);
3999 return WINDOW_TOTAL_COLS (p
);
4004 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
4006 #define CURSIZE(w) \
4007 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
4010 /* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it
4011 horizontally; zero means do it vertically.
4013 Siblings of the selected window are resized to fulfill the size
4014 request. If they become too small in the process, they may be
4018 enlarge_window (Lisp_Object window
, int delta
, int horiz_flag
)
4020 Lisp_Object parent
, next
, prev
;
4024 int (*sizefun
) (Lisp_Object
)
4025 = horiz_flag
? window_width
: window_height
;
4026 void (*setsizefun
) (Lisp_Object
, int, int)
4027 = (horiz_flag
? set_window_width
: set_window_height
);
4029 /* Give up if this window cannot be resized. */
4030 if (window_fixed_size_p (XWINDOW (window
), horiz_flag
, 1))
4031 error ("Window is not resizable");
4033 /* Find the parent of the selected window. */
4036 p
= XWINDOW (window
);
4042 error ("No other window to side of this one");
4047 ? !NILP (XWINDOW (parent
)->hchild
)
4048 : !NILP (XWINDOW (parent
)->vchild
))
4054 sizep
= &CURSIZE (window
);
4057 register int maxdelta
;
4059 /* Compute the maximum size increment this window can have. */
4061 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - XINT (*sizep
)
4062 /* This is a main window followed by a minibuffer. */
4063 : !NILP (p
->next
) ? ((*sizefun
) (p
->next
)
4064 - window_min_size (XWINDOW (p
->next
),
4065 horiz_flag
, 0, 0, 0))
4066 /* This is a minibuffer following a main window. */
4067 : !NILP (p
->prev
) ? ((*sizefun
) (p
->prev
)
4068 - window_min_size (XWINDOW (p
->prev
),
4069 horiz_flag
, 0, 0, 0))
4070 /* This is a frame with only one window, a minibuffer-only
4071 or a minibufferless frame. */
4074 if (delta
> maxdelta
)
4075 /* This case traps trying to make the minibuffer
4076 the full frame, or make the only window aside from the
4077 minibuffer the full frame. */
4081 if (XINT (*sizep
) + delta
< window_min_size (XWINDOW (window
),
4082 horiz_flag
, 0, 0, 0))
4084 delete_window (window
);
4091 /* Find the total we can get from other siblings without deleting them. */
4093 for (next
= p
->next
; WINDOWP (next
); next
= XWINDOW (next
)->next
)
4094 maximum
+= (*sizefun
) (next
) - window_min_size (XWINDOW (next
),
4095 horiz_flag
, 0, 0, 0);
4096 for (prev
= p
->prev
; WINDOWP (prev
); prev
= XWINDOW (prev
)->prev
)
4097 maximum
+= (*sizefun
) (prev
) - window_min_size (XWINDOW (prev
),
4098 horiz_flag
, 0, 0, 0);
4100 /* If we can get it all from them without deleting them, do so. */
4101 if (delta
<= maximum
)
4103 Lisp_Object first_unaffected
;
4104 Lisp_Object first_affected
;
4109 first_affected
= window
;
4110 /* Look at one sibling at a time,
4111 moving away from this window in both directions alternately,
4112 and take as much as we can get without deleting that sibling. */
4114 && (!NILP (next
) || !NILP (prev
)))
4118 int this_one
= ((*sizefun
) (next
)
4119 - window_min_size (XWINDOW (next
), horiz_flag
,
4123 if (this_one
> delta
)
4126 (*setsizefun
) (next
, (*sizefun
) (next
) - this_one
, 0);
4127 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
4132 next
= XWINDOW (next
)->next
;
4140 int this_one
= ((*sizefun
) (prev
)
4141 - window_min_size (XWINDOW (prev
), horiz_flag
,
4145 if (this_one
> delta
)
4148 first_affected
= prev
;
4150 (*setsizefun
) (prev
, (*sizefun
) (prev
) - this_one
, 0);
4151 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
4156 prev
= XWINDOW (prev
)->prev
;
4160 xassert (delta
== 0);
4162 /* Now recalculate the edge positions of all the windows affected,
4163 based on the new sizes. */
4164 first_unaffected
= next
;
4165 prev
= first_affected
;
4166 for (next
= XWINDOW (prev
)->next
; ! EQ (next
, first_unaffected
);
4167 prev
= next
, next
= XWINDOW (next
)->next
)
4169 XSETINT (CURBEG (next
), XINT (CURBEG (prev
)) + (*sizefun
) (prev
));
4170 /* This does not change size of NEXT,
4171 but it propagates the new top edge to its children */
4172 (*setsizefun
) (next
, (*sizefun
) (next
), 0);
4177 register int delta1
;
4178 register int opht
= (*sizefun
) (parent
);
4180 if (opht
<= XINT (*sizep
) + delta
)
4182 /* If trying to grow this window to or beyond size of the parent,
4183 just delete all the sibling windows. */
4184 Lisp_Object start
, tem
, next
;
4186 start
= XWINDOW (parent
)->vchild
;
4188 start
= XWINDOW (parent
)->hchild
;
4190 /* Delete any siblings that come after WINDOW. */
4191 tem
= XWINDOW (window
)->next
;
4192 while (! NILP (tem
))
4194 next
= XWINDOW (tem
)->next
;
4195 delete_window (tem
);
4199 /* Delete any siblings that come after WINDOW.
4200 Note that if START is not WINDOW, then WINDOW still
4201 has siblings, so WINDOW has not yet replaced its parent. */
4203 while (! EQ (tem
, window
))
4205 next
= XWINDOW (tem
)->next
;
4206 delete_window (tem
);
4212 /* Otherwise, make delta1 just right so that if we add
4213 delta1 lines to this window and to the parent, and then
4214 shrink the parent back to its original size, the new
4215 proportional size of this window will increase by delta.
4217 The function size_window will compute the new height h'
4218 of the window from delta1 as:
4221 x = delta1 - delta1/n * n for the 1st resizable child
4224 where n is the number of children that can be resized.
4225 We can ignore x by choosing a delta1 that is a multiple of
4226 n. We want the height of this window to come out as
4236 The number of children n equals the number of resizable
4237 children of this window + 1 because we know window itself
4238 is resizable (otherwise we would have signaled an error).
4240 This reasoning is not correct when other windows become too
4241 small and shrink_windows refuses to delete them. Below we
4242 use resize_proportionally to work around this problem. */
4244 struct window
*w
= XWINDOW (window
);
4248 for (s
= w
->next
; WINDOWP (s
); s
= XWINDOW (s
)->next
)
4249 if (!window_fixed_size_p (XWINDOW (s
), horiz_flag
, 0))
4251 for (s
= w
->prev
; WINDOWP (s
); s
= XWINDOW (s
)->prev
)
4252 if (!window_fixed_size_p (XWINDOW (s
), horiz_flag
, 0))
4257 /* Add delta1 lines or columns to this window, and to the parent,
4258 keeping things consistent while not affecting siblings. */
4259 XSETINT (CURSIZE (parent
), opht
+ delta1
);
4260 (*setsizefun
) (window
, XINT (*sizep
) + delta1
, 0);
4262 /* Squeeze out delta1 lines or columns from our parent,
4263 shrinking this window and siblings proportionately. This
4264 brings parent back to correct size. Delta1 was calculated
4265 so this makes this window the desired size, taking it all
4266 out of the siblings.
4268 Temporarily set resize_proportionally to Qt to assure that,
4269 if necessary, shrink_windows deletes smaller windows rather
4270 than shrink this window. */
4271 w
->resize_proportionally
= Qt
;
4272 (*setsizefun
) (parent
, opht
, 0);
4273 w
->resize_proportionally
= Qnil
;
4277 XSETFASTINT (p
->last_modified
, 0);
4278 XSETFASTINT (p
->last_overlay_modified
, 0);
4280 /* Adjust glyph matrices. */
4281 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4285 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4286 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4287 zero means adjust the height, moving the bottom edge.
4289 Following siblings of the selected window are resized to fulfill
4290 the size request. If they become too small in the process, they
4291 are not deleted; instead, we signal an error. */
4294 adjust_window_trailing_edge (Lisp_Object window
, int delta
, int horiz_flag
)
4296 Lisp_Object parent
, child
;
4298 Lisp_Object old_config
= Fcurrent_window_configuration (Qnil
);
4299 int delcount
= window_deletion_count
;
4301 CHECK_WINDOW (window
);
4303 /* Give up if this window cannot be resized. */
4304 if (window_fixed_size_p (XWINDOW (window
), horiz_flag
, 1))
4305 error ("Window is not resizable");
4309 Lisp_Object first_parallel
= Qnil
;
4313 /* This happens if WINDOW on the previous iteration was
4314 at top level of the window tree. */
4315 Fset_window_configuration (old_config
);
4316 error ("Specified window edge is fixed");
4319 p
= XWINDOW (window
);
4322 /* See if this level has windows in parallel in the specified
4323 direction. If so, set FIRST_PARALLEL to the first one. */
4326 if (! NILP (parent
) && !NILP (XWINDOW (parent
)->vchild
))
4327 first_parallel
= XWINDOW (parent
)->vchild
;
4328 else if (NILP (parent
) && !NILP (p
->next
))
4330 /* Handle the vertical chain of main window and minibuffer
4331 which has no parent. */
4332 first_parallel
= window
;
4333 while (! NILP (XWINDOW (first_parallel
)->prev
))
4334 first_parallel
= XWINDOW (first_parallel
)->prev
;
4339 if (! NILP (parent
) && !NILP (XWINDOW (parent
)->hchild
))
4340 first_parallel
= XWINDOW (parent
)->hchild
;
4343 /* If this level's succession is in the desired dimension,
4344 and this window is the last one, and there is no higher level,
4345 its trailing edge is fixed. */
4346 if (NILP (XWINDOW (window
)->next
) && NILP (first_parallel
)
4349 Fset_window_configuration (old_config
);
4350 error ("Specified window edge is fixed");
4353 /* Don't make this window too small. */
4354 if (XINT (CURSIZE (window
)) + delta
4355 < window_min_size_2 (XWINDOW (window
), horiz_flag
, 0))
4357 Fset_window_configuration (old_config
);
4358 error ("Cannot adjust window size as specified");
4361 /* Clear out some redisplay caches. */
4362 XSETFASTINT (p
->last_modified
, 0);
4363 XSETFASTINT (p
->last_overlay_modified
, 0);
4365 /* Adjust this window's edge. */
4366 XSETINT (CURSIZE (window
),
4367 XINT (CURSIZE (window
)) + delta
);
4369 /* If this window has following siblings in the desired dimension,
4370 make them smaller, and exit the loop.
4372 (If we reach the top of the tree and can never do this,
4373 we will fail and report an error, above.) */
4374 if (NILP (first_parallel
))
4376 if (!NILP (p
->next
))
4378 /* This may happen for the minibuffer. In that case
4379 the window_deletion_count check below does not work. */
4380 if (XINT (CURSIZE (p
->next
)) - delta
<= 0)
4382 Fset_window_configuration (old_config
);
4383 error ("Cannot adjust window size as specified");
4386 XSETINT (CURBEG (p
->next
),
4387 XINT (CURBEG (p
->next
)) + delta
);
4388 size_window (p
->next
, XINT (CURSIZE (p
->next
)) - delta
,
4389 horiz_flag
, 0, 1, 0);
4394 /* Here we have a chain of parallel siblings, in the other dimension.
4395 Change the size of the other siblings. */
4396 for (child
= first_parallel
;
4398 child
= XWINDOW (child
)->next
)
4399 if (! EQ (child
, window
))
4400 size_window (child
, XINT (CURSIZE (child
)) + delta
,
4401 horiz_flag
, 0, 0, 1);
4406 /* If we made a window so small it got deleted,
4407 we failed. Report failure. */
4408 if (delcount
!= window_deletion_count
)
4410 Fset_window_configuration (old_config
);
4411 error ("Cannot adjust window size as specified");
4414 /* Adjust glyph matrices. */
4415 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4421 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge
,
4422 Sadjust_window_trailing_edge
, 3, 3, 0,
4423 doc
: /* Adjust the bottom or right edge of WINDOW by DELTA.
4424 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4425 Otherwise, adjust the height, moving the bottom edge.
4427 Following siblings of the selected window are resized to fulfill
4428 the size request. If they become too small in the process, they
4429 are not deleted; instead, we signal an error. */)
4430 (Lisp_Object window
, Lisp_Object delta
, Lisp_Object horizontal
)
4432 CHECK_NUMBER (delta
);
4434 window
= selected_window
;
4435 adjust_window_trailing_edge (window
, XINT (delta
), !NILP (horizontal
));
4437 run_window_configuration_change_hook
4438 (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4445 /***********************************************************************
4446 Resizing Mini-Windows
4447 ***********************************************************************/
4449 static void shrink_window_lowest_first (struct window
*, int);
4451 enum save_restore_action
4458 static int save_restore_orig_size (struct window
*,
4459 enum save_restore_action
);
4461 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4462 from lowest windows first. */
4465 shrink_window_lowest_first (struct window
*w
, int height
)
4471 xassert (!MINI_WINDOW_P (w
));
4473 /* Set redisplay hints. */
4474 XSETFASTINT (w
->last_modified
, 0);
4475 XSETFASTINT (w
->last_overlay_modified
, 0);
4476 windows_or_buffers_changed
++;
4477 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w
))) = 1;
4479 old_height
= XFASTINT (w
->total_lines
);
4480 XSETFASTINT (w
->total_lines
, height
);
4482 if (!NILP (w
->hchild
))
4484 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
4486 c
= XWINDOW (child
);
4487 c
->top_line
= w
->top_line
;
4488 shrink_window_lowest_first (c
, height
);
4491 else if (!NILP (w
->vchild
))
4493 Lisp_Object last_child
;
4494 int delta
= old_height
- height
;
4499 /* Find the last child. We are taking space from lowest windows
4500 first, so we iterate over children from the last child
4502 for (child
= w
->vchild
; WINDOWP (child
); child
= XWINDOW (child
)->next
)
4505 /* Size children down to their safe heights. */
4506 for (child
= last_child
; delta
&& !NILP (child
); child
= c
->prev
)
4510 c
= XWINDOW (child
);
4511 this_one
= XFASTINT (c
->total_lines
) - window_min_size_1 (c
, 0, 1);
4513 if (this_one
> delta
)
4516 shrink_window_lowest_first (c
, XFASTINT (c
->total_lines
) - this_one
);
4520 /* Compute new positions. */
4521 last_top
= XINT (w
->top_line
);
4522 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
4524 c
= XWINDOW (child
);
4525 c
->top_line
= make_number (last_top
);
4526 shrink_window_lowest_first (c
, XFASTINT (c
->total_lines
));
4527 last_top
+= XFASTINT (c
->total_lines
);
4533 /* Save, restore, or check positions and sizes in the window tree
4534 rooted at W. ACTION says what to do.
4536 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4537 orig_total_lines members are valid for all windows in the window
4538 tree. Value is non-zero if they are valid.
4540 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4541 orig_top_line and orig_total_lines for all windows in the tree.
4543 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4544 stored in orig_top_line and orig_total_lines for all windows. */
4547 save_restore_orig_size (struct window
*w
, enum save_restore_action action
)
4553 if (!NILP (w
->hchild
))
4555 if (!save_restore_orig_size (XWINDOW (w
->hchild
), action
))
4558 else if (!NILP (w
->vchild
))
4560 if (!save_restore_orig_size (XWINDOW (w
->vchild
), action
))
4566 case CHECK_ORIG_SIZES
:
4567 if (!INTEGERP (w
->orig_top_line
) || !INTEGERP (w
->orig_total_lines
))
4571 case SAVE_ORIG_SIZES
:
4572 w
->orig_top_line
= w
->top_line
;
4573 w
->orig_total_lines
= w
->total_lines
;
4574 XSETFASTINT (w
->last_modified
, 0);
4575 XSETFASTINT (w
->last_overlay_modified
, 0);
4578 case RESTORE_ORIG_SIZES
:
4579 xassert (INTEGERP (w
->orig_top_line
) && INTEGERP (w
->orig_total_lines
));
4580 w
->top_line
= w
->orig_top_line
;
4581 w
->total_lines
= w
->orig_total_lines
;
4582 w
->orig_total_lines
= w
->orig_top_line
= Qnil
;
4583 XSETFASTINT (w
->last_modified
, 0);
4584 XSETFASTINT (w
->last_overlay_modified
, 0);
4591 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
4598 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4599 without deleting other windows. */
4602 grow_mini_window (struct window
*w
, int delta
)
4604 struct frame
*f
= XFRAME (w
->frame
);
4605 struct window
*root
;
4607 xassert (MINI_WINDOW_P (w
));
4608 /* Commenting out the following assertion goes against the stated interface
4609 of the function, but it currently does not seem to do anything useful.
4610 See discussion of this issue in the thread for bug#4534.
4611 xassert (delta >= 0); */
4613 /* Compute how much we can enlarge the mini-window without deleting
4615 root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4618 int min_height
= window_min_size (root
, 0, 0, 0, 0);
4619 if (XFASTINT (root
->total_lines
) - delta
< min_height
)
4620 /* Note that the root window may already be smaller than
4622 delta
= max (0, XFASTINT (root
->total_lines
) - min_height
);
4627 /* Save original window sizes and positions, if not already done. */
4628 if (!save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
4629 save_restore_orig_size (root
, SAVE_ORIG_SIZES
);
4631 /* Shrink other windows. */
4632 shrink_window_lowest_first (root
, XFASTINT (root
->total_lines
) - delta
);
4634 /* Grow the mini-window. */
4635 w
->top_line
= make_number (XFASTINT (root
->top_line
) + XFASTINT (root
->total_lines
));
4636 w
->total_lines
= make_number (XFASTINT (w
->total_lines
) + delta
);
4637 XSETFASTINT (w
->last_modified
, 0);
4638 XSETFASTINT (w
->last_overlay_modified
, 0);
4645 /* Shrink mini-window W. If there is recorded info about window sizes
4646 before a call to grow_mini_window, restore recorded window sizes.
4647 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4651 shrink_mini_window (struct window
*w
)
4653 struct frame
*f
= XFRAME (w
->frame
);
4654 struct window
*root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4656 if (save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
4658 save_restore_orig_size (root
, RESTORE_ORIG_SIZES
);
4660 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
4661 windows_or_buffers_changed
= 1;
4663 else if (XFASTINT (w
->total_lines
) > 1)
4665 /* Distribute the additional lines of the mini-window
4666 among the other windows. */
4668 XSETWINDOW (window
, w
);
4669 enlarge_window (window
, 1 - XFASTINT (w
->total_lines
), 0);
4675 /* Mark window cursors off for all windows in the window tree rooted
4676 at W by setting their phys_cursor_on_p flag to zero. Called from
4677 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4678 the frame are cleared. */
4681 mark_window_cursors_off (struct window
*w
)
4685 if (!NILP (w
->hchild
))
4686 mark_window_cursors_off (XWINDOW (w
->hchild
));
4687 else if (!NILP (w
->vchild
))
4688 mark_window_cursors_off (XWINDOW (w
->vchild
));
4690 w
->phys_cursor_on_p
= 0;
4692 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
4697 /* Return number of lines of text (not counting mode lines) in W. */
4700 window_internal_height (struct window
*w
)
4702 int ht
= XFASTINT (w
->total_lines
);
4704 if (!MINI_WINDOW_P (w
))
4706 if (!NILP (w
->parent
)
4707 || !NILP (w
->vchild
)
4708 || !NILP (w
->hchild
)
4711 || WINDOW_WANTS_MODELINE_P (w
))
4714 if (WINDOW_WANTS_HEADER_LINE_P (w
))
4722 /* Return the number of columns in W.
4723 Don't count columns occupied by scroll bars or the vertical bar
4724 separating W from the sibling to its right. */
4727 window_box_text_cols (struct window
*w
)
4729 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4730 int width
= XINT (w
->total_cols
);
4732 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w
))
4733 /* Scroll bars occupy a few columns. */
4734 width
-= WINDOW_CONFIG_SCROLL_BAR_COLS (w
);
4735 else if (!FRAME_WINDOW_P (f
)
4736 && !WINDOW_RIGHTMOST_P (w
) && !WINDOW_FULL_WIDTH_P (w
))
4737 /* The column of `|' characters separating side-by-side windows
4738 occupies one column only. */
4741 if (FRAME_WINDOW_P (f
))
4742 /* On window-systems, fringes and display margins cannot be
4743 used for normal text. */
4744 width
-= (WINDOW_FRINGE_COLS (w
)
4745 + WINDOW_LEFT_MARGIN_COLS (w
)
4746 + WINDOW_RIGHT_MARGIN_COLS (w
));
4752 /************************************************************************
4754 ***********************************************************************/
4756 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4757 N screen-fulls, which is defined as the height of the window minus
4758 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4759 instead. Negative values of N mean scroll down. NOERROR non-zero
4760 means don't signal an error if we try to move over BEGV or ZV,
4764 window_scroll (Lisp_Object window
, int n
, int whole
, int noerror
)
4768 /* If we must, use the pixel-based version which is much slower than
4769 the line-based one but can handle varying line heights. */
4770 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window
)->frame
)))
4771 window_scroll_pixel_based (window
, n
, whole
, noerror
);
4773 window_scroll_line_based (window
, n
, whole
, noerror
);
4779 /* Implementation of window_scroll that works based on pixel line
4780 heights. See the comment of window_scroll for parameter
4784 window_scroll_pixel_based (Lisp_Object window
, int n
, int whole
, int noerror
)
4787 struct window
*w
= XWINDOW (window
);
4788 struct text_pos start
;
4789 int this_scroll_margin
;
4790 /* True if we fiddled the window vscroll field without really scrolling. */
4792 int x
, y
, rtop
, rbot
, rowh
, vpos
;
4794 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
4796 /* If PT is not visible in WINDOW, move back one half of
4797 the screen. Allow PT to be partially visible, otherwise
4798 something like (scroll-down 1) with PT in the line before
4799 the partially visible one would recenter. */
4801 if (!pos_visible_p (w
, PT
, &x
, &y
, &rtop
, &rbot
, &rowh
, &vpos
))
4803 /* Move backward half the height of the window. Performance note:
4804 vmotion used here is about 10% faster, but would give wrong
4805 results for variable height lines. */
4806 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4807 it
.current_y
= it
.last_visible_y
;
4808 move_it_vertically_backward (&it
, window_box_height (w
) / 2);
4810 /* The function move_iterator_vertically may move over more than
4811 the specified y-distance. If it->w is small, e.g. a
4812 mini-buffer window, we may end up in front of the window's
4813 display area. This is the case when Start displaying at the
4814 start of the line containing PT in this case. */
4815 if (it
.current_y
<= 0)
4817 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4818 move_it_vertically_backward (&it
, 0);
4822 start
= it
.current
.pos
;
4824 else if (auto_window_vscroll_p
)
4826 if (rtop
|| rbot
) /* partially visible */
4829 int dy
= WINDOW_FRAME_LINE_HEIGHT (w
);
4831 dy
= max ((window_box_height (w
)
4832 - next_screen_context_lines
* dy
),
4838 /* Only vscroll backwards if already vscrolled forwards. */
4839 if (w
->vscroll
< 0 && rtop
> 0)
4841 px
= max (0, -w
->vscroll
- min (rtop
, -dy
));
4842 Fset_window_vscroll (window
, make_number (px
), Qt
);
4848 /* Do vscroll if already vscrolled or only display line. */
4849 if (rbot
> 0 && (w
->vscroll
< 0 || vpos
== 0))
4851 px
= max (0, -w
->vscroll
+ min (rbot
, dy
));
4852 Fset_window_vscroll (window
, make_number (px
), Qt
);
4856 /* Maybe modify window start instead of scrolling. */
4857 if (rbot
> 0 || w
->vscroll
< 0)
4861 Fset_window_vscroll (window
, make_number (0), Qt
);
4862 /* If there are other text lines above the current row,
4863 move window start to current row. Else to next row. */
4865 spos
= XINT (Fline_beginning_position (Qnil
));
4867 spos
= min (XINT (Fline_end_position (Qnil
)) + 1, ZV
);
4868 set_marker_restricted (w
->start
, make_number (spos
),
4870 w
->start_at_line_beg
= Qt
;
4871 w
->update_mode_line
= Qt
;
4872 XSETFASTINT (w
->last_modified
, 0);
4873 XSETFASTINT (w
->last_overlay_modified
, 0);
4874 /* Set force_start so that redisplay_window will run the
4875 window-scroll-functions. */
4876 w
->force_start
= Qt
;
4881 /* Cancel previous vscroll. */
4882 Fset_window_vscroll (window
, make_number (0), Qt
);
4885 /* If scroll_preserve_screen_position is non-nil, we try to set
4886 point in the same window line as it is now, so get that line. */
4887 if (!NILP (Vscroll_preserve_screen_position
))
4889 /* We preserve the goal pixel coordinate across consecutive
4890 calls to scroll-up, scroll-down and other commands that
4891 have the `scroll-command' property. This avoids the
4892 possibility of point becoming "stuck" on a tall line when
4893 scrolling by one line. */
4894 if (window_scroll_pixel_based_preserve_y
< 0
4895 || !SYMBOLP (current_kboard
->Vlast_command
)
4896 || NILP (Fget (current_kboard
->Vlast_command
, Qscroll_command
)))
4898 start_display (&it
, w
, start
);
4899 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
4900 window_scroll_pixel_based_preserve_y
= it
.current_y
;
4901 window_scroll_pixel_based_preserve_x
= it
.current_x
;
4905 window_scroll_pixel_based_preserve_y
4906 = window_scroll_pixel_based_preserve_x
= -1;
4908 /* Move iterator it from start the specified distance forward or
4909 backward. The result is the new window start. */
4910 start_display (&it
, w
, start
);
4913 int start_pos
= IT_CHARPOS (it
);
4914 int dy
= WINDOW_FRAME_LINE_HEIGHT (w
);
4915 dy
= max ((window_box_height (w
)
4916 - next_screen_context_lines
* dy
),
4919 /* Note that move_it_vertically always moves the iterator to the
4920 start of a line. So, if the last line doesn't have a newline,
4921 we would end up at the start of the line ending at ZV. */
4924 move_it_vertically_backward (&it
, -dy
);
4925 /* Ensure we actually do move, e.g. in case we are currently
4926 looking at an image that is taller that the window height. */
4927 while (start_pos
== IT_CHARPOS (it
)
4928 && start_pos
> BEGV
)
4929 move_it_by_lines (&it
, -1, 1);
4933 move_it_to (&it
, ZV
, -1, it
.current_y
+ dy
, -1,
4934 MOVE_TO_POS
| MOVE_TO_Y
);
4935 /* Ensure we actually do move, e.g. in case we are currently
4936 looking at an image that is taller that the window height. */
4937 while (start_pos
== IT_CHARPOS (it
)
4939 move_it_by_lines (&it
, 1, 1);
4943 move_it_by_lines (&it
, n
, 1);
4945 /* We failed if we find ZV is already on the screen (scrolling up,
4946 means there's nothing past the end), or if we can't start any
4947 earlier (scrolling down, means there's nothing past the top). */
4948 if ((n
> 0 && IT_CHARPOS (it
) == ZV
)
4949 || (n
< 0 && IT_CHARPOS (it
) == CHARPOS (start
)))
4951 if (IT_CHARPOS (it
) == ZV
)
4953 if (it
.current_y
< it
.last_visible_y
4954 && (it
.current_y
+ it
.max_ascent
+ it
.max_descent
4955 > it
.last_visible_y
))
4957 /* The last line was only partially visible, make it fully
4959 w
->vscroll
= (it
.last_visible_y
4960 - it
.current_y
+ it
.max_ascent
+ it
.max_descent
);
4961 adjust_glyphs (it
.f
);
4965 else if (n
< 0) /* could happen with empty buffers */
4966 xsignal0 (Qbeginning_of_buffer
);
4968 xsignal0 (Qend_of_buffer
);
4972 if (w
->vscroll
!= 0)
4973 /* The first line was only partially visible, make it fully
4979 xsignal0 (Qbeginning_of_buffer
);
4982 /* If control gets here, then we vscrolled. */
4984 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
4986 /* Don't try to change the window start below. */
4992 int pos
= IT_CHARPOS (it
);
4995 /* If in the middle of a multi-glyph character move forward to
4996 the next character. */
4997 if (in_display_vector_p (&it
))
5000 move_it_to (&it
, pos
, -1, -1, -1, MOVE_TO_POS
);
5003 /* Set the window start, and set up the window for redisplay. */
5004 set_marker_restricted (w
->start
, make_number (pos
),
5006 bytepos
= XMARKER (w
->start
)->bytepos
;
5007 w
->start_at_line_beg
= ((pos
== BEGV
|| FETCH_BYTE (bytepos
- 1) == '\n')
5009 w
->update_mode_line
= Qt
;
5010 XSETFASTINT (w
->last_modified
, 0);
5011 XSETFASTINT (w
->last_overlay_modified
, 0);
5012 /* Set force_start so that redisplay_window will run the
5013 window-scroll-functions. */
5014 w
->force_start
= Qt
;
5017 /* The rest of this function uses current_y in a nonstandard way,
5018 not including the height of the header line if any. */
5019 it
.current_y
= it
.vpos
= 0;
5021 /* Move PT out of scroll margins.
5022 This code wants current_y to be zero at the window start position
5023 even if there is a header line. */
5024 this_scroll_margin
= max (0, scroll_margin
);
5025 this_scroll_margin
= min (this_scroll_margin
, XFASTINT (w
->total_lines
) / 4);
5026 this_scroll_margin
*= FRAME_LINE_HEIGHT (it
.f
);
5030 /* We moved the window start towards ZV, so PT may be now
5031 in the scroll margin at the top. */
5032 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
5033 if (IT_CHARPOS (it
) == PT
&& it
.current_y
>= this_scroll_margin
5034 && (NILP (Vscroll_preserve_screen_position
)
5035 || EQ (Vscroll_preserve_screen_position
, Qt
)))
5036 /* We found PT at a legitimate height. Leave it alone. */
5038 else if (window_scroll_pixel_based_preserve_y
>= 0)
5040 /* If we have a header line, take account of it.
5041 This is necessary because we set it.current_y to 0, above. */
5042 move_it_to (&it
, -1,
5043 window_scroll_pixel_based_preserve_x
,
5044 window_scroll_pixel_based_preserve_y
5045 - (WINDOW_WANTS_HEADER_LINE_P (w
) ? 1 : 0 ),
5046 -1, MOVE_TO_Y
| MOVE_TO_X
);
5047 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5051 while (it
.current_y
< this_scroll_margin
)
5053 int prev
= it
.current_y
;
5054 move_it_by_lines (&it
, 1, 1);
5055 if (prev
== it
.current_y
)
5058 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5063 int charpos
, bytepos
;
5066 /* Save our position, for the
5067 window_scroll_pixel_based_preserve_y case. */
5068 charpos
= IT_CHARPOS (it
);
5069 bytepos
= IT_BYTEPOS (it
);
5071 /* We moved the window start towards BEGV, so PT may be now
5072 in the scroll margin at the bottom. */
5073 move_it_to (&it
, PT
, -1,
5074 (it
.last_visible_y
- CURRENT_HEADER_LINE_HEIGHT (w
)
5075 - this_scroll_margin
- 1),
5077 MOVE_TO_POS
| MOVE_TO_Y
);
5079 /* Save our position, in case it's correct. */
5080 charpos
= IT_CHARPOS (it
);
5081 bytepos
= IT_BYTEPOS (it
);
5083 /* See if point is on a partially visible line at the end. */
5084 if (it
.what
== IT_EOB
)
5085 partial_p
= it
.current_y
+ it
.ascent
+ it
.descent
> it
.last_visible_y
;
5088 move_it_by_lines (&it
, 1, 1);
5089 partial_p
= it
.current_y
> it
.last_visible_y
;
5092 if (charpos
== PT
&& !partial_p
5093 && (NILP (Vscroll_preserve_screen_position
)
5094 || EQ (Vscroll_preserve_screen_position
, Qt
)))
5095 /* We found PT before we found the display margin, so PT is ok. */
5097 else if (window_scroll_pixel_based_preserve_y
>= 0)
5099 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
5100 start_display (&it
, w
, start
);
5101 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5102 here because we called start_display again and did not
5103 alter it.current_y this time. */
5104 move_it_to (&it
, -1, window_scroll_pixel_based_preserve_x
,
5105 window_scroll_pixel_based_preserve_y
, -1,
5106 MOVE_TO_Y
| MOVE_TO_X
);
5107 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5112 /* The last line was only partially visible, so back up two
5113 lines to make sure we're on a fully visible line. */
5115 move_it_by_lines (&it
, -2, 0);
5116 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5119 /* No, the position we saved is OK, so use it. */
5120 SET_PT_BOTH (charpos
, bytepos
);
5126 /* Implementation of window_scroll that works based on screen lines.
5127 See the comment of window_scroll for parameter descriptions. */
5130 window_scroll_line_based (Lisp_Object window
, int n
, int whole
, int noerror
)
5132 register struct window
*w
= XWINDOW (window
);
5133 register int opoint
= PT
, opoint_byte
= PT_BYTE
;
5134 register int pos
, pos_byte
;
5135 register int ht
= window_internal_height (w
);
5136 register Lisp_Object tem
;
5140 Lisp_Object original_pos
= Qnil
;
5142 /* If scrolling screen-fulls, compute the number of lines to
5143 scroll from the window's height. */
5145 n
*= max (1, ht
- next_screen_context_lines
);
5147 startpos
= marker_position (w
->start
);
5149 if (!NILP (Vscroll_preserve_screen_position
))
5151 if (window_scroll_preserve_vpos
<= 0
5152 || !SYMBOLP (current_kboard
->Vlast_command
)
5153 || NILP (Fget (current_kboard
->Vlast_command
, Qscroll_command
)))
5155 struct position posit
5156 = *compute_motion (startpos
, 0, 0, 0,
5158 -1, XINT (w
->hscroll
),
5160 window_scroll_preserve_vpos
= posit
.vpos
;
5161 window_scroll_preserve_hpos
= posit
.hpos
+ XINT (w
->hscroll
);
5164 original_pos
= Fcons (make_number (window_scroll_preserve_hpos
),
5165 make_number (window_scroll_preserve_vpos
));
5168 XSETFASTINT (tem
, PT
);
5169 tem
= Fpos_visible_in_window_p (tem
, window
, Qnil
);
5173 Fvertical_motion (make_number (- (ht
/ 2)), window
);
5178 lose
= n
< 0 && PT
== BEGV
;
5179 Fvertical_motion (make_number (n
), window
);
5183 SET_PT_BOTH (opoint
, opoint_byte
);
5190 xsignal0 (Qbeginning_of_buffer
);
5195 int this_scroll_margin
= scroll_margin
;
5197 /* Don't use a scroll margin that is negative or too large. */
5198 if (this_scroll_margin
< 0)
5199 this_scroll_margin
= 0;
5201 if (XINT (w
->total_lines
) < 4 * scroll_margin
)
5202 this_scroll_margin
= XINT (w
->total_lines
) / 4;
5204 set_marker_restricted_both (w
->start
, w
->buffer
, pos
, pos_byte
);
5205 w
->start_at_line_beg
= bolp
;
5206 w
->update_mode_line
= Qt
;
5207 XSETFASTINT (w
->last_modified
, 0);
5208 XSETFASTINT (w
->last_overlay_modified
, 0);
5209 /* Set force_start so that redisplay_window will run
5210 the window-scroll-functions. */
5211 w
->force_start
= Qt
;
5213 if (!NILP (Vscroll_preserve_screen_position
)
5214 && (whole
|| !EQ (Vscroll_preserve_screen_position
, Qt
)))
5216 SET_PT_BOTH (pos
, pos_byte
);
5217 Fvertical_motion (original_pos
, window
);
5219 /* If we scrolled forward, put point enough lines down
5220 that it is outside the scroll margin. */
5225 if (this_scroll_margin
> 0)
5227 SET_PT_BOTH (pos
, pos_byte
);
5228 Fvertical_motion (make_number (this_scroll_margin
), window
);
5234 if (top_margin
<= opoint
)
5235 SET_PT_BOTH (opoint
, opoint_byte
);
5236 else if (!NILP (Vscroll_preserve_screen_position
))
5238 SET_PT_BOTH (pos
, pos_byte
);
5239 Fvertical_motion (original_pos
, window
);
5242 SET_PT (top_margin
);
5248 /* If we scrolled backward, put point near the end of the window
5249 but not within the scroll margin. */
5250 SET_PT_BOTH (pos
, pos_byte
);
5251 tem
= Fvertical_motion (make_number (ht
- this_scroll_margin
), window
);
5252 if (XFASTINT (tem
) == ht
- this_scroll_margin
)
5255 bottom_margin
= PT
+ 1;
5257 if (bottom_margin
> opoint
)
5258 SET_PT_BOTH (opoint
, opoint_byte
);
5261 if (!NILP (Vscroll_preserve_screen_position
))
5263 SET_PT_BOTH (pos
, pos_byte
);
5264 Fvertical_motion (original_pos
, window
);
5267 Fvertical_motion (make_number (-1), window
);
5276 xsignal0 (Qend_of_buffer
);
5281 /* Scroll selected_window up or down. If N is nil, scroll a
5282 screen-full which is defined as the height of the window minus
5283 next_screen_context_lines. If N is the symbol `-', scroll.
5284 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5285 up. This is the guts of Fscroll_up and Fscroll_down. */
5288 scroll_command (Lisp_Object n
, int direction
)
5290 int count
= SPECPDL_INDEX ();
5292 xassert (eabs (direction
) == 1);
5294 /* If selected window's buffer isn't current, make it current for
5295 the moment. But don't screw up if window_scroll gets an error. */
5296 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
5298 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
5299 Fset_buffer (XWINDOW (selected_window
)->buffer
);
5301 /* Make redisplay consider other windows than just selected_window. */
5302 ++windows_or_buffers_changed
;
5306 window_scroll (selected_window
, direction
, 1, 0);
5307 else if (EQ (n
, Qminus
))
5308 window_scroll (selected_window
, -direction
, 1, 0);
5311 n
= Fprefix_numeric_value (n
);
5312 window_scroll (selected_window
, XINT (n
) * direction
, 0, 0);
5315 unbind_to (count
, Qnil
);
5318 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "^P",
5319 doc
: /* Scroll text of selected window upward ARG lines.
5320 If ARG is omitted or nil, scroll upward by a near full screen.
5321 A near full screen is `next-screen-context-lines' less than a full screen.
5322 Negative ARG means scroll downward.
5323 If ARG is the atom `-', scroll downward by nearly full screen.
5324 When calling from a program, supply as argument a number, nil, or `-'. */)
5327 scroll_command (arg
, 1);
5331 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "^P",
5332 doc
: /* Scroll text of selected window down ARG lines.
5333 If ARG is omitted or nil, scroll down by a near full screen.
5334 A near full screen is `next-screen-context-lines' less than a full screen.
5335 Negative ARG means scroll upward.
5336 If ARG is the atom `-', scroll upward by nearly full screen.
5337 When calling from a program, supply as argument a number, nil, or `-'. */)
5340 scroll_command (arg
, -1);
5344 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling
, Sother_window_for_scrolling
, 0, 0, 0,
5345 doc
: /* Return the other window for \"other window scroll\" commands.
5346 If `other-window-scroll-buffer' is non-nil, a window
5347 showing that buffer is used.
5348 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5349 specifies the window. This takes precedence over
5350 `other-window-scroll-buffer'. */)
5355 if (MINI_WINDOW_P (XWINDOW (selected_window
))
5356 && !NILP (Vminibuf_scroll_window
))
5357 window
= Vminibuf_scroll_window
;
5358 /* If buffer is specified, scroll that buffer. */
5359 else if (!NILP (Vother_window_scroll_buffer
))
5361 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
5363 window
= display_buffer (Vother_window_scroll_buffer
, Qt
, Qnil
);
5367 /* Nothing specified; look for a neighboring window on the same
5369 window
= Fnext_window (selected_window
, Qnil
, Qnil
);
5371 if (EQ (window
, selected_window
))
5372 /* That didn't get us anywhere; look for a window on another
5375 window
= Fnext_window (window
, Qnil
, Qt
);
5376 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window
))))
5377 && ! EQ (window
, selected_window
));
5380 CHECK_LIVE_WINDOW (window
);
5382 if (EQ (window
, selected_window
))
5383 error ("There is no other window");
5388 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
5389 doc
: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5390 A near full screen is `next-screen-context-lines' less than a full screen.
5391 The next window is the one below the current one; or the one at the top
5392 if the current one is at the bottom. Negative ARG means scroll downward.
5393 If ARG is the atom `-', scroll downward by nearly full screen.
5394 When calling from a program, supply as argument a number, nil, or `-'.
5396 If `other-window-scroll-buffer' is non-nil, scroll the window
5397 showing that buffer, popping the buffer up if necessary.
5398 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5399 specifies the window to scroll. This takes precedence over
5400 `other-window-scroll-buffer'. */)
5405 int count
= SPECPDL_INDEX ();
5407 window
= Fother_window_for_scrolling ();
5408 w
= XWINDOW (window
);
5410 /* Don't screw up if window_scroll gets an error. */
5411 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
5412 ++windows_or_buffers_changed
;
5414 Fset_buffer (w
->buffer
);
5415 SET_PT (marker_position (w
->pointm
));
5418 window_scroll (window
, 1, 1, 1);
5419 else if (EQ (arg
, Qminus
))
5420 window_scroll (window
, -1, 1, 1);
5426 window_scroll (window
, XINT (arg
), 0, 1);
5429 set_marker_both (w
->pointm
, Qnil
, PT
, PT_BYTE
);
5430 unbind_to (count
, Qnil
);
5435 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 0, 2, "^P\np",
5436 doc
: /* Scroll selected window display ARG columns left.
5437 Default for ARG is window width minus 2.
5438 Value is the total amount of leftward horizontal scrolling in
5439 effect after the change.
5440 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5441 lower bound for automatic scrolling, i.e. automatic scrolling
5442 will not scroll a window to a column less than the value returned
5443 by this function. This happens in an interactive call. */)
5444 (register Lisp_Object arg
, Lisp_Object set_minimum
)
5448 struct window
*w
= XWINDOW (selected_window
);
5451 XSETFASTINT (arg
, window_box_text_cols (w
) - 2);
5453 arg
= Fprefix_numeric_value (arg
);
5455 hscroll
= XINT (w
->hscroll
) + XINT (arg
);
5456 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
5458 if (!NILP (set_minimum
))
5459 w
->min_hscroll
= w
->hscroll
;
5464 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 0, 2, "^P\np",
5465 doc
: /* Scroll selected window display ARG columns right.
5466 Default for ARG is window width minus 2.
5467 Value is the total amount of leftward horizontal scrolling in
5468 effect after the change.
5469 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5470 lower bound for automatic scrolling, i.e. automatic scrolling
5471 will not scroll a window to a column less than the value returned
5472 by this function. This happens in an interactive call. */)
5473 (register Lisp_Object arg
, Lisp_Object set_minimum
)
5477 struct window
*w
= XWINDOW (selected_window
);
5480 XSETFASTINT (arg
, window_box_text_cols (w
) - 2);
5482 arg
= Fprefix_numeric_value (arg
);
5484 hscroll
= XINT (w
->hscroll
) - XINT (arg
);
5485 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
5487 if (!NILP (set_minimum
))
5488 w
->min_hscroll
= w
->hscroll
;
5493 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window
, Sminibuffer_selected_window
, 0, 0, 0,
5494 doc
: /* Return the window which was selected when entering the minibuffer.
5495 Returns nil, if selected window is not a minibuffer window. */)
5498 if (minibuf_level
> 0
5499 && MINI_WINDOW_P (XWINDOW (selected_window
))
5500 && WINDOW_LIVE_P (minibuf_selected_window
))
5501 return minibuf_selected_window
;
5506 /* Value is the number of lines actually displayed in window W,
5507 as opposed to its height. */
5510 displayed_window_lines (struct window
*w
)
5513 struct text_pos start
;
5514 int height
= window_box_height (w
);
5515 struct buffer
*old_buffer
;
5518 if (XBUFFER (w
->buffer
) != current_buffer
)
5520 old_buffer
= current_buffer
;
5521 set_buffer_internal (XBUFFER (w
->buffer
));
5526 /* In case W->start is out of the accessible range, do something
5527 reasonable. This happens in Info mode when Info-scroll-down
5528 calls (recenter -1) while W->start is 1. */
5529 if (XMARKER (w
->start
)->charpos
< BEGV
)
5530 SET_TEXT_POS (start
, BEGV
, BEGV_BYTE
);
5531 else if (XMARKER (w
->start
)->charpos
> ZV
)
5532 SET_TEXT_POS (start
, ZV
, ZV_BYTE
);
5534 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
5536 start_display (&it
, w
, start
);
5537 move_it_vertically (&it
, height
);
5538 bottom_y
= line_bottom_y (&it
);
5540 /* rms: On a non-window display,
5541 the value of it.vpos at the bottom of the screen
5542 seems to be 1 larger than window_box_height (w).
5543 This kludge fixes a bug whereby (move-to-window-line -1)
5544 when ZV is on the last screen line
5545 moves to the previous screen line instead of the last one. */
5546 if (! FRAME_WINDOW_P (XFRAME (w
->frame
)))
5549 /* Add in empty lines at the bottom of the window. */
5550 if (bottom_y
< height
)
5552 int uy
= FRAME_LINE_HEIGHT (it
.f
);
5553 it
.vpos
+= (height
- bottom_y
+ uy
- 1) / uy
;
5557 set_buffer_internal (old_buffer
);
5563 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
5564 doc
: /* Center point in selected window and maybe redisplay frame.
5565 With prefix argument ARG, recenter putting point on screen line ARG
5566 relative to the selected window. If ARG is negative, it counts up from the
5567 bottom of the window. (ARG should be less than the height of the window.)
5569 If ARG is omitted or nil, then recenter with point on the middle line of
5570 the selected window; if the variable `recenter-redisplay' is non-nil,
5571 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5572 is set to `grow-only', this resets the tool-bar's height to the minimum
5573 height needed); if `recenter-redisplay' has the special value `tty',
5574 then only tty frame are redrawn.
5576 Just C-u as prefix means put point in the center of the window
5577 and redisplay normally--don't erase and redraw the frame. */)
5578 (register Lisp_Object arg
)
5580 struct window
*w
= XWINDOW (selected_window
);
5581 struct buffer
*buf
= XBUFFER (w
->buffer
);
5582 struct buffer
*obuf
= current_buffer
;
5584 int charpos
, bytepos
;
5586 int this_scroll_margin
;
5588 /* If redisplay is suppressed due to an error, try again. */
5589 obuf
->display_error_modiff
= 0;
5593 if (!NILP (Vrecenter_redisplay
)
5594 && (!EQ (Vrecenter_redisplay
, Qtty
)
5595 || !NILP (Ftty_type (selected_frame
))))
5599 /* Invalidate pixel data calculated for all compositions. */
5600 for (i
= 0; i
< n_compositions
; i
++)
5601 composition_table
[i
]->font
= NULL
;
5603 WINDOW_XFRAME (w
)->minimize_tool_bar_window_p
= 1;
5605 Fredraw_frame (WINDOW_FRAME (w
));
5606 SET_FRAME_GARBAGED (WINDOW_XFRAME (w
));
5611 else if (CONSP (arg
)) /* Just C-u. */
5615 arg
= Fprefix_numeric_value (arg
);
5620 set_buffer_internal (buf
);
5622 /* Do this after making BUF current
5623 in case scroll_margin is buffer-local. */
5624 this_scroll_margin
= max (0, scroll_margin
);
5625 this_scroll_margin
= min (this_scroll_margin
,
5626 XFASTINT (w
->total_lines
) / 4);
5628 /* Handle centering on a graphical frame specially. Such frames can
5629 have variable-height lines and centering point on the basis of
5630 line counts would lead to strange effects. */
5631 if (FRAME_WINDOW_P (XFRAME (w
->frame
)))
5638 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
5639 start_display (&it
, w
, pt
);
5640 move_it_vertically_backward (&it
, window_box_height (w
) / 2);
5641 charpos
= IT_CHARPOS (it
);
5642 bytepos
= IT_BYTEPOS (it
);
5649 int extra_line_spacing
;
5650 int h
= window_box_height (w
);
5652 iarg
= - max (-iarg
, this_scroll_margin
);
5654 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
5655 start_display (&it
, w
, pt
);
5657 /* Be sure we have the exact height of the full line containing PT. */
5658 move_it_by_lines (&it
, 0, 1);
5660 /* The amount of pixels we have to move back is the window
5661 height minus what's displayed in the line containing PT,
5662 and the lines below. */
5665 move_it_by_lines (&it
, nlines
, 1);
5667 if (it
.vpos
== nlines
)
5671 /* Last line has no newline */
5672 h
-= line_bottom_y (&it
);
5676 /* Don't reserve space for extra line spacing of last line. */
5677 extra_line_spacing
= it
.max_extra_line_spacing
;
5679 /* If we can't move down NLINES lines because we hit
5680 the end of the buffer, count in some empty lines. */
5681 if (it
.vpos
< nlines
)
5684 extra_line_spacing
= it
.extra_line_spacing
;
5685 h
-= nlines
* (FRAME_LINE_HEIGHT (it
.f
) + extra_line_spacing
);
5690 /* Now find the new top line (starting position) of the window. */
5691 start_display (&it
, w
, pt
);
5693 move_it_vertically_backward (&it
, h
);
5695 /* If extra line spacing is present, we may move too far
5696 back. This causes the last line to be only partially
5697 visible (which triggers redisplay to recenter that line
5698 in the middle), so move forward.
5699 But ignore extra line spacing on last line, as it is not
5700 considered to be part of the visible height of the line.
5702 h
+= extra_line_spacing
;
5703 while (-it
.current_y
> h
)
5704 move_it_by_lines (&it
, 1, 1);
5706 charpos
= IT_CHARPOS (it
);
5707 bytepos
= IT_BYTEPOS (it
);
5711 struct position pos
;
5713 iarg
= max (iarg
, this_scroll_margin
);
5715 pos
= *vmotion (PT
, -iarg
, w
);
5716 charpos
= pos
.bufpos
;
5717 bytepos
= pos
.bytepos
;
5722 struct position pos
;
5723 int ht
= window_internal_height (w
);
5730 /* Don't let it get into the margin at either top or bottom. */
5731 iarg
= max (iarg
, this_scroll_margin
);
5732 iarg
= min (iarg
, ht
- this_scroll_margin
- 1);
5734 pos
= *vmotion (PT
, - iarg
, w
);
5735 charpos
= pos
.bufpos
;
5736 bytepos
= pos
.bytepos
;
5739 /* Set the new window start. */
5740 set_marker_both (w
->start
, w
->buffer
, charpos
, bytepos
);
5741 w
->window_end_valid
= Qnil
;
5743 w
->optional_new_start
= Qt
;
5745 if (bytepos
== BEGV_BYTE
|| FETCH_BYTE (bytepos
- 1) == '\n')
5746 w
->start_at_line_beg
= Qt
;
5748 w
->start_at_line_beg
= Qnil
;
5750 set_buffer_internal (obuf
);
5755 DEFUN ("window-text-height", Fwindow_text_height
, Swindow_text_height
,
5757 doc
: /* Return the height in lines of the text display area of WINDOW.
5758 WINDOW defaults to the selected window.
5760 The return value does not include the mode line, any header line, nor
5761 any partial-height lines in the text display area. */)
5762 (Lisp_Object window
)
5764 struct window
*w
= decode_window (window
);
5765 int pixel_height
= window_box_height (w
);
5766 int line_height
= pixel_height
/ FRAME_LINE_HEIGHT (XFRAME (w
->frame
));
5767 return make_number (line_height
);
5772 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
5774 doc
: /* Position point relative to window.
5775 With no argument, position point at center of window.
5776 An argument specifies vertical position within the window;
5777 zero means top of window, negative means relative to bottom of window. */)
5780 struct window
*w
= XWINDOW (selected_window
);
5784 int this_scroll_margin
;
5787 window
= selected_window
;
5788 start
= marker_position (w
->start
);
5789 if (start
< BEGV
|| start
> ZV
)
5791 int height
= window_internal_height (w
);
5792 Fvertical_motion (make_number (- (height
/ 2)), window
);
5793 set_marker_both (w
->start
, w
->buffer
, PT
, PT_BYTE
);
5794 w
->start_at_line_beg
= Fbolp ();
5795 w
->force_start
= Qt
;
5798 Fgoto_char (w
->start
);
5800 lines
= displayed_window_lines (w
);
5803 this_scroll_margin
= max (0, scroll_margin
);
5804 this_scroll_margin
= min (this_scroll_margin
, lines
/ 4);
5808 XSETFASTINT (arg
, lines
/ 2);
5811 int iarg
= XINT (Fprefix_numeric_value (arg
));
5814 iarg
= iarg
+ lines
;
5816 #if 0 /* This code would prevent move-to-window-line from moving point
5817 to a place inside the scroll margins (which would cause the
5818 next redisplay to scroll). I wrote this code, but then concluded
5819 it is probably better not to install it. However, it is here
5820 inside #if 0 so as not to lose it. -- rms. */
5822 /* Don't let it get into the margin at either top or bottom. */
5823 iarg
= max (iarg
, this_scroll_margin
);
5824 iarg
= min (iarg
, lines
- this_scroll_margin
- 1);
5827 arg
= make_number (iarg
);
5830 /* Skip past a partially visible first line. */
5832 XSETINT (arg
, XINT (arg
) + 1);
5834 return Fvertical_motion (arg
, window
);
5839 /***********************************************************************
5840 Window Configuration
5841 ***********************************************************************/
5843 struct save_window_data
5846 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
5847 Lisp_Object selected_frame
;
5848 Lisp_Object current_window
;
5849 Lisp_Object current_buffer
;
5850 Lisp_Object minibuf_scroll_window
;
5851 Lisp_Object minibuf_selected_window
;
5852 Lisp_Object root_window
;
5853 Lisp_Object focus_frame
;
5854 /* A vector, each of whose elements is a struct saved_window
5856 Lisp_Object saved_windows
;
5858 /* All fields above are traced by the GC.
5859 From `fame-cols' down, the fields are ignored by the GC. */
5861 int frame_cols
, frame_lines
, frame_menu_bar_lines
;
5862 int frame_tool_bar_lines
;
5865 /* This is saved as a Lisp_Vector */
5868 /* these first two must agree with struct Lisp_Vector in lisp.h */
5870 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
5873 Lisp_Object buffer
, start
, pointm
, mark
;
5874 Lisp_Object left_col
, top_line
, total_cols
, total_lines
;
5875 Lisp_Object hscroll
, min_hscroll
;
5876 Lisp_Object parent
, prev
;
5877 Lisp_Object start_at_line_beg
;
5878 Lisp_Object display_table
;
5879 Lisp_Object orig_top_line
, orig_total_lines
;
5880 Lisp_Object left_margin_cols
, right_margin_cols
;
5881 Lisp_Object left_fringe_width
, right_fringe_width
, fringes_outside_margins
;
5882 Lisp_Object scroll_bar_width
, vertical_scroll_bar_type
;
5883 Lisp_Object dedicated
, resize_proportionally
;
5886 #define SAVED_WINDOW_N(swv,n) \
5887 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5889 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
5890 doc
: /* Return t if OBJECT is a window-configuration object. */)
5891 (Lisp_Object object
)
5893 return WINDOW_CONFIGURATIONP (object
) ? Qt
: Qnil
;
5896 DEFUN ("window-configuration-frame", Fwindow_configuration_frame
, Swindow_configuration_frame
, 1, 1, 0,
5897 doc
: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5898 (Lisp_Object config
)
5900 register struct save_window_data
*data
;
5901 struct Lisp_Vector
*saved_windows
;
5903 CHECK_WINDOW_CONFIGURATION (config
);
5905 data
= (struct save_window_data
*) XVECTOR (config
);
5906 saved_windows
= XVECTOR (data
->saved_windows
);
5907 return XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
5910 DEFUN ("set-window-configuration", Fset_window_configuration
,
5911 Sset_window_configuration
, 1, 1, 0,
5912 doc
: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5913 CONFIGURATION must be a value previously returned
5914 by `current-window-configuration' (which see).
5915 If CONFIGURATION was made from a frame that is now deleted,
5916 only frame-independent values can be restored. In this case,
5917 the return value is nil. Otherwise the value is t. */)
5918 (Lisp_Object configuration
)
5920 register struct save_window_data
*data
;
5921 struct Lisp_Vector
*saved_windows
;
5922 Lisp_Object new_current_buffer
;
5927 CHECK_WINDOW_CONFIGURATION (configuration
);
5929 data
= (struct save_window_data
*) XVECTOR (configuration
);
5930 saved_windows
= XVECTOR (data
->saved_windows
);
5932 new_current_buffer
= data
->current_buffer
;
5933 if (NILP (XBUFFER (new_current_buffer
)->name
))
5934 new_current_buffer
= Qnil
;
5937 if (XBUFFER (new_current_buffer
) == current_buffer
)
5938 /* The code further down "preserves point" by saving here PT in
5939 old_point and then setting it later back into PT. When the
5940 current-selected-window and the final-selected-window both show
5941 the current buffer, this suffers from the problem that the
5942 current PT is the window-point of the current-selected-window,
5943 while the final PT is the point of the final-selected-window, so
5944 this copy from one PT to the other would end up moving the
5945 window-point of the final-selected-window to the window-point of
5946 the current-selected-window. So we have to be careful which
5947 point of the current-buffer we copy into old_point. */
5948 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
)
5949 && WINDOWP (selected_window
)
5950 && EQ (XWINDOW (selected_window
)->buffer
, new_current_buffer
)
5951 && !EQ (selected_window
, data
->current_window
))
5952 old_point
= XMARKER (XWINDOW (data
->current_window
)->pointm
)->charpos
;
5956 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5957 point in new_current_buffer as of the last time this buffer was
5958 used. This can be non-deterministic since it can be changed by
5959 things like jit-lock by mere temporary selection of some random
5960 window that happens to show this buffer.
5961 So if possible we want this arbitrary choice of "which point" to
5962 be the one from the to-be-selected-window so as to prevent this
5963 window's cursor from being copied from another window. */
5964 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
)
5965 /* If current_window = selected_window, its point is in BUF_PT. */
5966 && !EQ (selected_window
, data
->current_window
))
5967 old_point
= XMARKER (XWINDOW (data
->current_window
)->pointm
)->charpos
;
5969 old_point
= BUF_PT (XBUFFER (new_current_buffer
));
5972 frame
= XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
5975 /* If f is a dead frame, don't bother rebuilding its window tree.
5976 However, there is other stuff we should still try to do below. */
5977 if (FRAME_LIVE_P (f
))
5979 register struct window
*w
;
5980 register struct saved_window
*p
;
5981 struct window
*root_window
;
5982 struct window
**leaf_windows
;
5986 /* If the frame has been resized since this window configuration was
5987 made, we change the frame to the size specified in the
5988 configuration, restore the configuration, and then resize it
5989 back. We keep track of the prevailing height in these variables. */
5990 int previous_frame_lines
= FRAME_LINES (f
);
5991 int previous_frame_cols
= FRAME_COLS (f
);
5992 int previous_frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
5993 int previous_frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
5995 /* The mouse highlighting code could get screwed up
5996 if it runs during this. */
5999 if (data
->frame_lines
!= previous_frame_lines
6000 || data
->frame_cols
!= previous_frame_cols
)
6001 change_frame_size (f
, data
->frame_lines
,
6002 data
->frame_cols
, 0, 0, 0);
6003 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6004 if (data
->frame_menu_bar_lines
6005 != previous_frame_menu_bar_lines
)
6006 x_set_menu_bar_lines (f
, make_number (data
->frame_menu_bar_lines
),
6008 #ifdef HAVE_WINDOW_SYSTEM
6009 if (data
->frame_tool_bar_lines
6010 != previous_frame_tool_bar_lines
)
6011 x_set_tool_bar_lines (f
, make_number (data
->frame_tool_bar_lines
),
6016 /* "Swap out" point from the selected window's buffer
6017 into the window itself. (Normally the pointm of the selected
6018 window holds garbage.) We do this now, before
6019 restoring the window contents, and prevent it from
6020 being done later on when we select a new window. */
6021 if (! NILP (XWINDOW (selected_window
)->buffer
))
6023 w
= XWINDOW (selected_window
);
6024 set_marker_both (w
->pointm
,
6026 BUF_PT (XBUFFER (w
->buffer
)),
6027 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6030 windows_or_buffers_changed
++;
6031 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
6033 /* Problem: Freeing all matrices and later allocating them again
6034 is a serious redisplay flickering problem. What we would
6035 really like to do is to free only those matrices not reused
6037 root_window
= XWINDOW (FRAME_ROOT_WINDOW (f
));
6039 = (struct window
**) alloca (count_windows (root_window
)
6040 * sizeof (struct window
*));
6041 n_leaf_windows
= get_leaf_windows (root_window
, leaf_windows
, 0);
6044 Mark all windows now on frame as "deleted".
6045 Restoring the new configuration "undeletes" any that are in it.
6047 Save their current buffers in their height fields, since we may
6048 need it later, if a buffer saved in the configuration is now
6050 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6052 for (k
= 0; k
< saved_windows
->size
; k
++)
6054 p
= SAVED_WINDOW_N (saved_windows
, k
);
6055 w
= XWINDOW (p
->window
);
6058 if (!NILP (p
->parent
))
6059 w
->parent
= SAVED_WINDOW_N (saved_windows
,
6060 XFASTINT (p
->parent
))->window
;
6064 if (!NILP (p
->prev
))
6066 w
->prev
= SAVED_WINDOW_N (saved_windows
,
6067 XFASTINT (p
->prev
))->window
;
6068 XWINDOW (w
->prev
)->next
= p
->window
;
6073 if (!NILP (w
->parent
))
6075 if (EQ (p
->total_cols
, XWINDOW (w
->parent
)->total_cols
))
6077 XWINDOW (w
->parent
)->vchild
= p
->window
;
6078 XWINDOW (w
->parent
)->hchild
= Qnil
;
6082 XWINDOW (w
->parent
)->hchild
= p
->window
;
6083 XWINDOW (w
->parent
)->vchild
= Qnil
;
6088 /* If we squirreled away the buffer in the window's height,
6090 if (BUFFERP (w
->total_lines
))
6091 w
->buffer
= w
->total_lines
;
6092 w
->left_col
= p
->left_col
;
6093 w
->top_line
= p
->top_line
;
6094 w
->total_cols
= p
->total_cols
;
6095 w
->total_lines
= p
->total_lines
;
6096 w
->hscroll
= p
->hscroll
;
6097 w
->min_hscroll
= p
->min_hscroll
;
6098 w
->display_table
= p
->display_table
;
6099 w
->orig_top_line
= p
->orig_top_line
;
6100 w
->orig_total_lines
= p
->orig_total_lines
;
6101 w
->left_margin_cols
= p
->left_margin_cols
;
6102 w
->right_margin_cols
= p
->right_margin_cols
;
6103 w
->left_fringe_width
= p
->left_fringe_width
;
6104 w
->right_fringe_width
= p
->right_fringe_width
;
6105 w
->fringes_outside_margins
= p
->fringes_outside_margins
;
6106 w
->scroll_bar_width
= p
->scroll_bar_width
;
6107 w
->vertical_scroll_bar_type
= p
->vertical_scroll_bar_type
;
6108 w
->dedicated
= p
->dedicated
;
6109 w
->resize_proportionally
= p
->resize_proportionally
;
6110 XSETFASTINT (w
->last_modified
, 0);
6111 XSETFASTINT (w
->last_overlay_modified
, 0);
6113 /* Reinstall the saved buffer and pointers into it. */
6114 if (NILP (p
->buffer
))
6115 w
->buffer
= p
->buffer
;
6118 if (!NILP (XBUFFER (p
->buffer
)->name
))
6119 /* If saved buffer is alive, install it. */
6121 w
->buffer
= p
->buffer
;
6122 w
->start_at_line_beg
= p
->start_at_line_beg
;
6123 set_marker_restricted (w
->start
, p
->start
, w
->buffer
);
6124 set_marker_restricted (w
->pointm
, p
->pointm
, w
->buffer
);
6125 Fset_marker (XBUFFER (w
->buffer
)->mark
,
6126 p
->mark
, w
->buffer
);
6128 /* As documented in Fcurrent_window_configuration, don't
6129 restore the location of point in the buffer which was
6130 current when the window configuration was recorded. */
6131 if (!EQ (p
->buffer
, new_current_buffer
)
6132 && XBUFFER (p
->buffer
) == current_buffer
)
6133 Fgoto_char (w
->pointm
);
6135 else if (NILP (w
->buffer
) || NILP (XBUFFER (w
->buffer
)->name
))
6136 /* Else unless window has a live buffer, get one. */
6138 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
6139 /* This will set the markers to beginning of visible
6141 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
6142 set_marker_restricted (w
->pointm
, make_number (0),w
->buffer
);
6143 w
->start_at_line_beg
= Qt
;
6146 /* Keeping window's old buffer; make sure the markers
6149 /* Set window markers at start of visible range. */
6150 if (XMARKER (w
->start
)->buffer
== 0)
6151 set_marker_restricted (w
->start
, make_number (0),
6153 if (XMARKER (w
->pointm
)->buffer
== 0)
6154 set_marker_restricted_both (w
->pointm
, w
->buffer
,
6155 BUF_PT (XBUFFER (w
->buffer
)),
6156 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6157 w
->start_at_line_beg
= Qt
;
6162 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
6163 /* Prevent "swapping out point" in the old selected window
6164 using the buffer that has been restored into it.
6165 We already swapped out point that from that window's old buffer. */
6166 selected_window
= Qnil
;
6168 /* Arrange *not* to restore point in the buffer that was
6169 current when the window configuration was saved. */
6170 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
))
6171 set_marker_restricted (XWINDOW (data
->current_window
)->pointm
,
6172 make_number (old_point
),
6173 XWINDOW (data
->current_window
)->buffer
);
6175 Fselect_window (data
->current_window
, Qnil
);
6176 XBUFFER (XWINDOW (selected_window
)->buffer
)->last_selected_window
6179 if (NILP (data
->focus_frame
)
6180 || (FRAMEP (data
->focus_frame
)
6181 && FRAME_LIVE_P (XFRAME (data
->focus_frame
))))
6182 Fredirect_frame_focus (frame
, data
->focus_frame
);
6184 #if 0 /* I don't understand why this is needed, and it causes problems
6185 when the frame's old selected window has been deleted. */
6186 if (f
!= selected_frame
&& FRAME_WINDOW_P (f
))
6187 do_switch_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)),
6191 /* Set the screen height to the value it had before this function. */
6192 if (previous_frame_lines
!= FRAME_LINES (f
)
6193 || previous_frame_cols
!= FRAME_COLS (f
))
6194 change_frame_size (f
, previous_frame_lines
, previous_frame_cols
,
6196 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6197 if (previous_frame_menu_bar_lines
!= FRAME_MENU_BAR_LINES (f
))
6198 x_set_menu_bar_lines (f
, make_number (previous_frame_menu_bar_lines
),
6200 #ifdef HAVE_WINDOW_SYSTEM
6201 if (previous_frame_tool_bar_lines
!= FRAME_TOOL_BAR_LINES (f
))
6202 x_set_tool_bar_lines (f
, make_number (previous_frame_tool_bar_lines
),
6207 /* Now, free glyph matrices in windows that were not reused. */
6208 for (i
= n
= 0; i
< n_leaf_windows
; ++i
)
6210 if (NILP (leaf_windows
[i
]->buffer
))
6212 /* Assert it's not reused as a combination. */
6213 xassert (NILP (leaf_windows
[i
]->hchild
)
6214 && NILP (leaf_windows
[i
]->vchild
));
6215 free_window_matrices (leaf_windows
[i
]);
6217 else if (EQ (leaf_windows
[i
]->buffer
, new_current_buffer
))
6225 /* Fselect_window will have made f the selected frame, so we
6226 reselect the proper frame here. Fhandle_switch_frame will change the
6227 selected window too, but that doesn't make the call to
6228 Fselect_window above totally superfluous; it still sets f's
6230 if (FRAME_LIVE_P (XFRAME (data
->selected_frame
)))
6231 do_switch_frame (data
->selected_frame
, 0, 0, Qnil
);
6233 run_window_configuration_change_hook (f
);
6236 if (!NILP (new_current_buffer
))
6237 Fset_buffer (new_current_buffer
);
6239 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
6240 minibuf_selected_window
= data
->minibuf_selected_window
;
6242 return (FRAME_LIVE_P (f
) ? Qt
: Qnil
);
6245 /* Mark all windows now on frame as deleted
6246 by setting their buffers to nil. */
6249 delete_all_subwindows (register struct window
*w
)
6251 if (!NILP (w
->next
))
6252 delete_all_subwindows (XWINDOW (w
->next
));
6253 if (!NILP (w
->vchild
))
6254 delete_all_subwindows (XWINDOW (w
->vchild
));
6255 if (!NILP (w
->hchild
))
6256 delete_all_subwindows (XWINDOW (w
->hchild
));
6258 w
->total_lines
= w
->buffer
; /* See Fset_window_configuration for excuse. */
6260 if (!NILP (w
->buffer
))
6263 /* We set all three of these fields to nil, to make sure that we can
6264 distinguish this dead window from any live window. Live leaf
6265 windows will have buffer set, and combination windows will have
6266 vchild or hchild set. */
6271 Vwindow_list
= Qnil
;
6275 count_windows (register struct window
*window
)
6277 register int count
= 1;
6278 if (!NILP (window
->next
))
6279 count
+= count_windows (XWINDOW (window
->next
));
6280 if (!NILP (window
->vchild
))
6281 count
+= count_windows (XWINDOW (window
->vchild
));
6282 if (!NILP (window
->hchild
))
6283 count
+= count_windows (XWINDOW (window
->hchild
));
6288 /* Fill vector FLAT with leaf windows under W, starting at index I.
6289 Value is last index + 1. */
6292 get_leaf_windows (struct window
*w
, struct window
**flat
, int i
)
6296 if (!NILP (w
->hchild
))
6297 i
= get_leaf_windows (XWINDOW (w
->hchild
), flat
, i
);
6298 else if (!NILP (w
->vchild
))
6299 i
= get_leaf_windows (XWINDOW (w
->vchild
), flat
, i
);
6303 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6310 /* Return a pointer to the glyph W's physical cursor is on. Value is
6311 null if W's current matrix is invalid, so that no meaningfull glyph
6315 get_phys_cursor_glyph (struct window
*w
)
6317 struct glyph_row
*row
;
6318 struct glyph
*glyph
;
6320 if (w
->phys_cursor
.vpos
>= 0
6321 && w
->phys_cursor
.vpos
< w
->current_matrix
->nrows
6322 && (row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
),
6324 && row
->used
[TEXT_AREA
] > w
->phys_cursor
.hpos
)
6325 glyph
= row
->glyphs
[TEXT_AREA
] + w
->phys_cursor
.hpos
;
6334 save_window_save (Lisp_Object window
, struct Lisp_Vector
*vector
, int i
)
6336 register struct saved_window
*p
;
6337 register struct window
*w
;
6338 register Lisp_Object tem
;
6340 for (;!NILP (window
); window
= w
->next
)
6342 p
= SAVED_WINDOW_N (vector
, i
);
6343 w
= XWINDOW (window
);
6345 XSETFASTINT (w
->temslot
, i
); i
++;
6347 p
->buffer
= w
->buffer
;
6348 p
->left_col
= w
->left_col
;
6349 p
->top_line
= w
->top_line
;
6350 p
->total_cols
= w
->total_cols
;
6351 p
->total_lines
= w
->total_lines
;
6352 p
->hscroll
= w
->hscroll
;
6353 p
->min_hscroll
= w
->min_hscroll
;
6354 p
->display_table
= w
->display_table
;
6355 p
->orig_top_line
= w
->orig_top_line
;
6356 p
->orig_total_lines
= w
->orig_total_lines
;
6357 p
->left_margin_cols
= w
->left_margin_cols
;
6358 p
->right_margin_cols
= w
->right_margin_cols
;
6359 p
->left_fringe_width
= w
->left_fringe_width
;
6360 p
->right_fringe_width
= w
->right_fringe_width
;
6361 p
->fringes_outside_margins
= w
->fringes_outside_margins
;
6362 p
->scroll_bar_width
= w
->scroll_bar_width
;
6363 p
->vertical_scroll_bar_type
= w
->vertical_scroll_bar_type
;
6364 p
->dedicated
= w
->dedicated
;
6365 p
->resize_proportionally
= w
->resize_proportionally
;
6366 if (!NILP (w
->buffer
))
6368 /* Save w's value of point in the window configuration.
6369 If w is the selected window, then get the value of point
6370 from the buffer; pointm is garbage in the selected window. */
6371 if (EQ (window
, selected_window
))
6373 p
->pointm
= Fmake_marker ();
6374 set_marker_both (p
->pointm
, w
->buffer
,
6375 BUF_PT (XBUFFER (w
->buffer
)),
6376 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6379 p
->pointm
= Fcopy_marker (w
->pointm
, Qnil
);
6381 p
->start
= Fcopy_marker (w
->start
, Qnil
);
6382 p
->start_at_line_beg
= w
->start_at_line_beg
;
6384 tem
= XBUFFER (w
->buffer
)->mark
;
6385 p
->mark
= Fcopy_marker (tem
, Qnil
);
6392 p
->start_at_line_beg
= Qnil
;
6395 if (NILP (w
->parent
))
6398 p
->parent
= XWINDOW (w
->parent
)->temslot
;
6403 p
->prev
= XWINDOW (w
->prev
)->temslot
;
6405 if (!NILP (w
->vchild
))
6406 i
= save_window_save (w
->vchild
, vector
, i
);
6407 if (!NILP (w
->hchild
))
6408 i
= save_window_save (w
->hchild
, vector
, i
);
6414 DEFUN ("current-window-configuration", Fcurrent_window_configuration
,
6415 Scurrent_window_configuration
, 0, 1, 0,
6416 doc
: /* Return an object representing the current window configuration of FRAME.
6417 If FRAME is nil or omitted, use the selected frame.
6418 This describes the number of windows, their sizes and current buffers,
6419 and for each displayed buffer, where display starts, and the positions of
6420 point and mark. An exception is made for point in the current buffer:
6421 its value is -not- saved.
6422 This also records the currently selected frame, and FRAME's focus
6423 redirection (see `redirect-frame-focus'). */)
6426 register Lisp_Object tem
;
6427 register int n_windows
;
6428 register struct save_window_data
*data
;
6433 frame
= selected_frame
;
6434 CHECK_LIVE_FRAME (frame
);
6437 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6438 data
= ALLOCATE_PSEUDOVECTOR (struct save_window_data
, frame_cols
,
6439 PVEC_WINDOW_CONFIGURATION
);
6441 data
->frame_cols
= FRAME_COLS (f
);
6442 data
->frame_lines
= FRAME_LINES (f
);
6443 data
->frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
6444 data
->frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
6445 data
->selected_frame
= selected_frame
;
6446 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
6447 XSETBUFFER (data
->current_buffer
, current_buffer
);
6448 data
->minibuf_scroll_window
= minibuf_level
> 0 ? Vminibuf_scroll_window
: Qnil
;
6449 data
->minibuf_selected_window
= minibuf_level
> 0 ? minibuf_selected_window
: Qnil
;
6450 data
->root_window
= FRAME_ROOT_WINDOW (f
);
6451 data
->focus_frame
= FRAME_FOCUS_FRAME (f
);
6452 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
6453 data
->saved_windows
= tem
;
6454 for (i
= 0; i
< n_windows
; i
++)
6455 XVECTOR (tem
)->contents
[i
]
6456 = Fmake_vector (make_number (VECSIZE (struct saved_window
)), Qnil
);
6457 save_window_save (FRAME_ROOT_WINDOW (f
), XVECTOR (tem
), 0);
6458 XSETWINDOW_CONFIGURATION (tem
, data
);
6462 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
6464 doc
: /* Execute BODY, preserving window sizes and contents.
6465 Return the value of the last form in BODY.
6466 Restore which buffer appears in which window, where display starts,
6467 and the value of point and mark for each window.
6468 Also restore the choice of selected window.
6469 Also restore which buffer is current.
6470 Does not restore the value of point in current buffer.
6471 usage: (save-window-excursion BODY...) */)
6474 register Lisp_Object val
;
6475 register int count
= SPECPDL_INDEX ();
6477 record_unwind_protect (Fset_window_configuration
,
6478 Fcurrent_window_configuration (Qnil
));
6479 val
= Fprogn (args
);
6480 return unbind_to (count
, val
);
6485 /***********************************************************************
6487 ***********************************************************************/
6490 window_tree (struct window
*w
)
6492 Lisp_Object tail
= Qnil
;
6493 Lisp_Object result
= Qnil
;
6500 if (!NILP (w
->hchild
))
6501 wn
= Fcons (Qnil
, Fcons (Fwindow_edges (wn
),
6502 window_tree (XWINDOW (w
->hchild
))));
6503 else if (!NILP (w
->vchild
))
6504 wn
= Fcons (Qt
, Fcons (Fwindow_edges (wn
),
6505 window_tree (XWINDOW (w
->vchild
))));
6509 result
= tail
= Fcons (wn
, Qnil
);
6513 XSETCDR (tail
, Fcons (wn
, Qnil
));
6517 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6525 DEFUN ("window-tree", Fwindow_tree
, Swindow_tree
,
6527 doc
: /* Return the window tree for frame FRAME.
6529 The return value is a list of the form (ROOT MINI), where ROOT
6530 represents the window tree of the frame's root window, and MINI
6531 is the frame's minibuffer window.
6533 If the root window is not split, ROOT is the root window itself.
6534 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6535 horizontal split, and t for a vertical split, EDGES gives the combined
6536 size and position of the subwindows in the split, and the rest of the
6537 elements are the subwindows in the split. Each of the subwindows may
6538 again be a window or a list representing a window split, and so on.
6539 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6541 If FRAME is nil or omitted, return information on the currently
6548 frame
= selected_frame
;
6550 CHECK_FRAME (frame
);
6553 if (!FRAME_LIVE_P (f
))
6556 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6560 /***********************************************************************
6562 ***********************************************************************/
6564 DEFUN ("set-window-margins", Fset_window_margins
, Sset_window_margins
,
6566 doc
: /* Set width of marginal areas of window WINDOW.
6567 If WINDOW is nil, set margins of the currently selected window.
6568 Second arg LEFT-WIDTH specifies the number of character cells to
6569 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6570 does the same for the right marginal area. A nil width parameter
6571 means no margin. */)
6572 (Lisp_Object window
, Lisp_Object left_width
, Lisp_Object right_width
)
6574 struct window
*w
= decode_window (window
);
6576 /* Translate negative or zero widths to nil.
6577 Margins that are too wide have to be checked elsewhere. */
6579 if (!NILP (left_width
))
6581 CHECK_NUMBER (left_width
);
6582 if (XINT (left_width
) <= 0)
6586 if (!NILP (right_width
))
6588 CHECK_NUMBER (right_width
);
6589 if (XINT (right_width
) <= 0)
6593 if (!EQ (w
->left_margin_cols
, left_width
)
6594 || !EQ (w
->right_margin_cols
, right_width
))
6596 w
->left_margin_cols
= left_width
;
6597 w
->right_margin_cols
= right_width
;
6599 adjust_window_margins (w
);
6601 ++windows_or_buffers_changed
;
6602 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6609 DEFUN ("window-margins", Fwindow_margins
, Swindow_margins
,
6611 doc
: /* Get width of marginal areas of window WINDOW.
6612 If WINDOW is omitted or nil, use the currently selected window.
6613 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6614 If a marginal area does not exist, its width will be returned
6616 (Lisp_Object window
)
6618 struct window
*w
= decode_window (window
);
6619 return Fcons (w
->left_margin_cols
, w
->right_margin_cols
);
6624 /***********************************************************************
6626 ***********************************************************************/
6628 DEFUN ("set-window-fringes", Fset_window_fringes
, Sset_window_fringes
,
6630 doc
: /* Set the fringe widths of window WINDOW.
6631 If WINDOW is nil, set the fringe widths of the currently selected
6633 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6634 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6635 fringe width. If a fringe width arg is nil, that means to use the
6636 frame's default fringe width. Default fringe widths can be set with
6637 the command `set-fringe-style'.
6638 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6639 outside of the display margins. By default, fringes are drawn between
6640 display marginal areas and the text area. */)
6641 (Lisp_Object window
, Lisp_Object left_width
, Lisp_Object right_width
, Lisp_Object outside_margins
)
6643 struct window
*w
= decode_window (window
);
6645 if (!NILP (left_width
))
6646 CHECK_NATNUM (left_width
);
6647 if (!NILP (right_width
))
6648 CHECK_NATNUM (right_width
);
6650 /* Do nothing on a tty. */
6651 if (FRAME_WINDOW_P (WINDOW_XFRAME (w
))
6652 && (!EQ (w
->left_fringe_width
, left_width
)
6653 || !EQ (w
->right_fringe_width
, right_width
)
6654 || !EQ (w
->fringes_outside_margins
, outside_margins
)))
6656 w
->left_fringe_width
= left_width
;
6657 w
->right_fringe_width
= right_width
;
6658 w
->fringes_outside_margins
= outside_margins
;
6660 adjust_window_margins (w
);
6662 clear_glyph_matrix (w
->current_matrix
);
6663 w
->window_end_valid
= Qnil
;
6665 ++windows_or_buffers_changed
;
6666 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6673 DEFUN ("window-fringes", Fwindow_fringes
, Swindow_fringes
,
6675 doc
: /* Get width of fringes of window WINDOW.
6676 If WINDOW is omitted or nil, use the currently selected window.
6677 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6678 (Lisp_Object window
)
6680 struct window
*w
= decode_window (window
);
6682 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w
)),
6683 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w
)),
6684 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
6685 ? Qt
: Qnil
), Qnil
)));
6690 /***********************************************************************
6692 ***********************************************************************/
6694 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars
, Sset_window_scroll_bars
,
6696 doc
: /* Set width and type of scroll bars of window WINDOW.
6697 If window is nil, set scroll bars of the currently selected window.
6698 Second parameter WIDTH specifies the pixel width for the scroll bar;
6699 this is automatically adjusted to a multiple of the frame column width.
6700 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6701 bar: left, right, or nil.
6702 If WIDTH is nil, use the frame's scroll-bar width.
6703 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6704 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6705 (Lisp_Object window
, Lisp_Object width
, Lisp_Object vertical_type
, Lisp_Object horizontal_type
)
6707 struct window
*w
= decode_window (window
);
6711 CHECK_NATNUM (width
);
6713 if (XINT (width
) == 0)
6714 vertical_type
= Qnil
;
6717 if (!(NILP (vertical_type
)
6718 || EQ (vertical_type
, Qleft
)
6719 || EQ (vertical_type
, Qright
)
6720 || EQ (vertical_type
, Qt
)))
6721 error ("Invalid type of vertical scroll bar");
6723 if (!EQ (w
->scroll_bar_width
, width
)
6724 || !EQ (w
->vertical_scroll_bar_type
, vertical_type
))
6726 w
->scroll_bar_width
= width
;
6727 w
->vertical_scroll_bar_type
= vertical_type
;
6729 adjust_window_margins (w
);
6731 clear_glyph_matrix (w
->current_matrix
);
6732 w
->window_end_valid
= Qnil
;
6734 ++windows_or_buffers_changed
;
6735 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6742 DEFUN ("window-scroll-bars", Fwindow_scroll_bars
, Swindow_scroll_bars
,
6744 doc
: /* Get width and type of scroll bars of window WINDOW.
6745 If WINDOW is omitted or nil, use the currently selected window.
6746 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6747 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6749 (Lisp_Object window
)
6751 struct window
*w
= decode_window (window
);
6752 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
)
6753 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
)
6754 : WINDOW_SCROLL_BAR_AREA_WIDTH (w
))),
6755 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w
)),
6756 Fcons (w
->vertical_scroll_bar_type
,
6757 Fcons (Qnil
, Qnil
))));
6762 /***********************************************************************
6764 ***********************************************************************/
6766 DEFUN ("window-vscroll", Fwindow_vscroll
, Swindow_vscroll
, 0, 2, 0,
6767 doc
: /* Return the amount by which WINDOW is scrolled vertically.
6768 Use the selected window if WINDOW is nil or omitted.
6769 Normally, value is a multiple of the canonical character height of WINDOW;
6770 optional second arg PIXELS-P means value is measured in pixels. */)
6771 (Lisp_Object window
, Lisp_Object pixels_p
)
6778 window
= selected_window
;
6780 CHECK_WINDOW (window
);
6781 w
= XWINDOW (window
);
6782 f
= XFRAME (w
->frame
);
6784 if (FRAME_WINDOW_P (f
))
6785 result
= (NILP (pixels_p
)
6786 ? FRAME_CANON_Y_FROM_PIXEL_Y (f
, -w
->vscroll
)
6787 : make_number (-w
->vscroll
));
6789 result
= make_number (0);
6794 DEFUN ("set-window-vscroll", Fset_window_vscroll
, Sset_window_vscroll
,
6796 doc
: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6797 WINDOW nil means use the selected window. Normally, VSCROLL is a
6798 non-negative multiple of the canonical character height of WINDOW;
6799 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6800 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6801 corresponds to an integral number of pixels. The return value is the
6802 result of this rounding.
6803 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6804 (Lisp_Object window
, Lisp_Object vscroll
, Lisp_Object pixels_p
)
6810 window
= selected_window
;
6812 CHECK_WINDOW (window
);
6813 CHECK_NUMBER_OR_FLOAT (vscroll
);
6815 w
= XWINDOW (window
);
6816 f
= XFRAME (w
->frame
);
6818 if (FRAME_WINDOW_P (f
))
6820 int old_dy
= w
->vscroll
;
6822 w
->vscroll
= - (NILP (pixels_p
)
6823 ? FRAME_LINE_HEIGHT (f
) * XFLOATINT (vscroll
)
6824 : XFLOATINT (vscroll
));
6825 w
->vscroll
= min (w
->vscroll
, 0);
6827 if (w
->vscroll
!= old_dy
)
6829 /* Adjust glyph matrix of the frame if the virtual display
6830 area becomes larger than before. */
6831 if (w
->vscroll
< 0 && w
->vscroll
< old_dy
)
6834 /* Prevent redisplay shortcuts. */
6835 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
6839 return Fwindow_vscroll (window
, pixels_p
);
6843 /* Call FN for all leaf windows on frame F. FN is called with the
6844 first argument being a pointer to the leaf window, and with
6845 additional argument USER_DATA. Stops when FN returns 0. */
6848 foreach_window (struct frame
*f
, int (*fn
) (struct window
*, void *), void *user_data
)
6850 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6851 if (WINDOWP (FRAME_ROOT_WINDOW (f
)))
6852 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f
)), fn
, user_data
);
6856 /* Helper function for foreach_window. Call FN for all leaf windows
6857 reachable from W. FN is called with the first argument being a
6858 pointer to the leaf window, and with additional argument USER_DATA.
6859 Stop when FN returns 0. Value is 0 if stopped by FN. */
6862 foreach_window_1 (struct window
*w
, int (*fn
) (struct window
*, void *), void *user_data
)
6866 for (cont
= 1; w
&& cont
;)
6868 if (!NILP (w
->hchild
))
6869 cont
= foreach_window_1 (XWINDOW (w
->hchild
), fn
, user_data
);
6870 else if (!NILP (w
->vchild
))
6871 cont
= foreach_window_1 (XWINDOW (w
->vchild
), fn
, user_data
);
6873 cont
= fn (w
, user_data
);
6875 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6882 /* Freeze or unfreeze the window start of W unless it is a
6883 mini-window or the selected window. FREEZE_P non-null means freeze
6884 the window start. */
6887 freeze_window_start (struct window
*w
, void *freeze_p
)
6889 if (MINI_WINDOW_P (w
)
6890 || (WINDOWP (selected_window
) /* Can be nil in corner cases. */
6891 && (w
== XWINDOW (selected_window
)
6892 || (MINI_WINDOW_P (XWINDOW (selected_window
))
6893 && ! NILP (Vminibuf_scroll_window
)
6894 && w
== XWINDOW (Vminibuf_scroll_window
)))))
6897 w
->frozen_window_start_p
= freeze_p
!= NULL
;
6902 /* Freeze or unfreeze the window starts of all leaf windows on frame
6903 F, except the selected window and a mini-window. FREEZE_P non-zero
6904 means freeze the window start. */
6907 freeze_window_starts (struct frame
*f
, int freeze_p
)
6909 foreach_window (f
, freeze_window_start
, (void *) (freeze_p
? f
: 0));
6913 /***********************************************************************
6915 ***********************************************************************/
6917 /* Return 1 if window configurations C1 and C2
6918 describe the same state of affairs. This is used by Fequal. */
6921 compare_window_configurations (Lisp_Object c1
, Lisp_Object c2
, int ignore_positions
)
6923 register struct save_window_data
*d1
, *d2
;
6924 struct Lisp_Vector
*sw1
, *sw2
;
6927 CHECK_WINDOW_CONFIGURATION (c1
);
6928 CHECK_WINDOW_CONFIGURATION (c2
);
6930 d1
= (struct save_window_data
*) XVECTOR (c1
);
6931 d2
= (struct save_window_data
*) XVECTOR (c2
);
6932 sw1
= XVECTOR (d1
->saved_windows
);
6933 sw2
= XVECTOR (d2
->saved_windows
);
6935 if (d1
->frame_cols
!= d2
->frame_cols
)
6937 if (d1
->frame_lines
!= d2
->frame_lines
)
6939 if (d1
->frame_menu_bar_lines
!= d2
->frame_menu_bar_lines
)
6941 if (! EQ (d1
->selected_frame
, d2
->selected_frame
))
6943 /* Don't compare the current_window field directly.
6944 Instead see w1_is_current and w2_is_current, below. */
6945 if (! EQ (d1
->current_buffer
, d2
->current_buffer
))
6947 if (! ignore_positions
)
6949 if (! EQ (d1
->minibuf_scroll_window
, d2
->minibuf_scroll_window
))
6951 if (! EQ (d1
->minibuf_selected_window
, d2
->minibuf_selected_window
))
6954 /* Don't compare the root_window field.
6955 We don't require the two configurations
6956 to use the same window object,
6957 and the two root windows must be equivalent
6958 if everything else compares equal. */
6959 if (! EQ (d1
->focus_frame
, d2
->focus_frame
))
6962 /* Verify that the two confis have the same number of windows. */
6963 if (sw1
->size
!= sw2
->size
)
6966 for (i
= 0; i
< sw1
->size
; i
++)
6968 struct saved_window
*p1
, *p2
;
6969 int w1_is_current
, w2_is_current
;
6971 p1
= SAVED_WINDOW_N (sw1
, i
);
6972 p2
= SAVED_WINDOW_N (sw2
, i
);
6974 /* Verify that the current windows in the two
6975 configurations correspond to each other. */
6976 w1_is_current
= EQ (d1
->current_window
, p1
->window
);
6977 w2_is_current
= EQ (d2
->current_window
, p2
->window
);
6979 if (w1_is_current
!= w2_is_current
)
6982 /* Verify that the corresponding windows do match. */
6983 if (! EQ (p1
->buffer
, p2
->buffer
))
6985 if (! EQ (p1
->left_col
, p2
->left_col
))
6987 if (! EQ (p1
->top_line
, p2
->top_line
))
6989 if (! EQ (p1
->total_cols
, p2
->total_cols
))
6991 if (! EQ (p1
->total_lines
, p2
->total_lines
))
6993 if (! EQ (p1
->display_table
, p2
->display_table
))
6995 if (! EQ (p1
->parent
, p2
->parent
))
6997 if (! EQ (p1
->prev
, p2
->prev
))
6999 if (! ignore_positions
)
7001 if (! EQ (p1
->hscroll
, p2
->hscroll
))
7003 if (!EQ (p1
->min_hscroll
, p2
->min_hscroll
))
7005 if (! EQ (p1
->start_at_line_beg
, p2
->start_at_line_beg
))
7007 if (NILP (Fequal (p1
->start
, p2
->start
)))
7009 if (NILP (Fequal (p1
->pointm
, p2
->pointm
)))
7011 if (NILP (Fequal (p1
->mark
, p2
->mark
)))
7014 if (! EQ (p1
->left_margin_cols
, p2
->left_margin_cols
))
7016 if (! EQ (p1
->right_margin_cols
, p2
->right_margin_cols
))
7018 if (! EQ (p1
->left_fringe_width
, p2
->left_fringe_width
))
7020 if (! EQ (p1
->right_fringe_width
, p2
->right_fringe_width
))
7022 if (! EQ (p1
->fringes_outside_margins
, p2
->fringes_outside_margins
))
7024 if (! EQ (p1
->scroll_bar_width
, p2
->scroll_bar_width
))
7026 if (! EQ (p1
->vertical_scroll_bar_type
, p2
->vertical_scroll_bar_type
))
7033 DEFUN ("compare-window-configurations", Fcompare_window_configurations
,
7034 Scompare_window_configurations
, 2, 2, 0,
7035 doc
: /* Compare two window configurations as regards the structure of windows.
7036 This function ignores details such as the values of point and mark
7037 and scrolling positions. */)
7038 (Lisp_Object x
, Lisp_Object y
)
7040 if (compare_window_configurations (x
, y
, 1))
7046 init_window_once (void)
7048 struct frame
*f
= make_initial_frame ();
7049 XSETFRAME (selected_frame
, f
);
7050 Vterminal_frame
= selected_frame
;
7051 minibuf_window
= f
->minibuffer_window
;
7052 selected_window
= f
->selected_window
;
7053 last_nonminibuf_frame
= f
;
7055 window_initialized
= 1;
7061 Vwindow_list
= Qnil
;
7065 syms_of_window (void)
7067 Qscroll_up
= intern_c_string ("scroll-up");
7068 staticpro (&Qscroll_up
);
7070 Qscroll_down
= intern_c_string ("scroll-down");
7071 staticpro (&Qscroll_down
);
7073 Qscroll_command
= intern_c_string ("scroll-command");
7074 staticpro (&Qscroll_command
);
7076 Fput (Qscroll_up
, Qscroll_command
, Qt
);
7077 Fput (Qscroll_down
, Qscroll_command
, Qt
);
7079 Qwindow_size_fixed
= intern_c_string ("window-size-fixed");
7080 staticpro (&Qwindow_size_fixed
);
7081 Fset (Qwindow_size_fixed
, Qnil
);
7083 staticpro (&Qwindow_configuration_change_hook
);
7084 Qwindow_configuration_change_hook
7085 = intern_c_string ("window-configuration-change-hook");
7087 Qwindowp
= intern_c_string ("windowp");
7088 staticpro (&Qwindowp
);
7090 Qwindow_configuration_p
= intern_c_string ("window-configuration-p");
7091 staticpro (&Qwindow_configuration_p
);
7093 Qwindow_live_p
= intern_c_string ("window-live-p");
7094 staticpro (&Qwindow_live_p
);
7096 Qdisplay_buffer
= intern_c_string ("display-buffer");
7097 staticpro (&Qdisplay_buffer
);
7099 Qtemp_buffer_show_hook
= intern_c_string ("temp-buffer-show-hook");
7100 staticpro (&Qtemp_buffer_show_hook
);
7102 staticpro (&Vwindow_list
);
7104 minibuf_selected_window
= Qnil
;
7105 staticpro (&minibuf_selected_window
);
7107 window_scroll_pixel_based_preserve_x
= -1;
7108 window_scroll_pixel_based_preserve_y
= -1;
7109 window_scroll_preserve_hpos
= -1;
7110 window_scroll_preserve_vpos
= -1;
7112 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
7113 doc
: /* Non-nil means call as function to display a help buffer.
7114 The function is called with one argument, the buffer to be displayed.
7115 Used by `with-output-to-temp-buffer'.
7116 If this function is used, then it must do the entire job of showing
7117 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7118 Vtemp_buffer_show_function
= Qnil
;
7120 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
7121 doc
: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7122 Vminibuf_scroll_window
= Qnil
;
7124 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows
,
7125 doc
: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7126 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7127 is displayed in the `mode-line' face. */);
7128 mode_line_in_non_selected_windows
= 1;
7130 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
7131 doc
: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7132 Vother_window_scroll_buffer
= Qnil
;
7134 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p
,
7135 doc
: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7136 auto_window_vscroll_p
= 1;
7138 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
7139 doc
: /* *Number of lines of continuity when scrolling by screenfuls. */);
7140 next_screen_context_lines
= 2;
7142 DEFVAR_INT ("window-min-height", &window_min_height
,
7143 doc
: /* Allow deleting windows less than this tall.
7144 The value is measured in line units. If a window wants a modeline it
7145 is counted as one line.
7147 Emacs honors settings of this variable when enlarging or shrinking
7148 windows vertically. A value less than 1 is invalid. */);
7149 window_min_height
= 4;
7151 DEFVAR_INT ("window-min-width", &window_min_width
,
7152 doc
: /* Allow deleting windows less than this wide.
7153 The value is measured in characters and includes any fringes or
7156 Emacs honors settings of this variable when enlarging or shrinking
7157 windows horizontally. A value less than 2 is invalid. */);
7158 window_min_width
= 10;
7160 DEFVAR_LISP ("scroll-preserve-screen-position",
7161 &Vscroll_preserve_screen_position
,
7162 doc
: /* *Controls if scroll commands move point to keep its screen position unchanged.
7163 A value of nil means point does not keep its screen position except
7164 at the scroll margin or window boundary respectively.
7165 A value of t means point keeps its screen position if the scroll
7166 command moved it vertically out of the window, e.g. when scrolling
7168 Any other value means point always keeps its screen position.
7169 Scroll commands should have the `scroll-command' property
7170 on their symbols to be controlled by this variable. */);
7171 Vscroll_preserve_screen_position
= Qnil
;
7173 DEFVAR_LISP ("window-point-insertion-type", &Vwindow_point_insertion_type
,
7174 doc
: /* Type of marker to use for `window-point'. */);
7175 Vwindow_point_insertion_type
= Qnil
;
7177 DEFVAR_LISP ("window-configuration-change-hook",
7178 &Vwindow_configuration_change_hook
,
7179 doc
: /* Functions to call when window configuration changes.
7180 The buffer-local part is run once per window, with the relevant window
7181 selected; while the global part is run only once for the modified frame,
7182 with the relevant frame selected. */);
7183 Vwindow_configuration_change_hook
= Qnil
;
7185 DEFVAR_LISP ("recenter-redisplay", &Vrecenter_redisplay
,
7186 doc
: /* If non-nil, then the `recenter' command with a nil argument
7187 will redraw the entire frame; the special value `tty' causes the
7188 frame to be redrawn only if it is a tty frame. */);
7189 Vrecenter_redisplay
= Qtty
;
7192 defsubr (&Sselected_window
);
7193 defsubr (&Sminibuffer_window
);
7194 defsubr (&Swindow_minibuffer_p
);
7195 defsubr (&Swindowp
);
7196 defsubr (&Swindow_live_p
);
7197 defsubr (&Spos_visible_in_window_p
);
7198 defsubr (&Swindow_line_height
);
7199 defsubr (&Swindow_buffer
);
7200 defsubr (&Swindow_height
);
7201 defsubr (&Swindow_width
);
7202 defsubr (&Swindow_full_width_p
);
7203 defsubr (&Swindow_hscroll
);
7204 defsubr (&Sset_window_hscroll
);
7205 defsubr (&Swindow_redisplay_end_trigger
);
7206 defsubr (&Sset_window_redisplay_end_trigger
);
7207 defsubr (&Swindow_edges
);
7208 defsubr (&Swindow_pixel_edges
);
7209 defsubr (&Swindow_absolute_pixel_edges
);
7210 defsubr (&Swindow_inside_edges
);
7211 defsubr (&Swindow_inside_pixel_edges
);
7212 defsubr (&Swindow_inside_absolute_pixel_edges
);
7213 defsubr (&Scoordinates_in_window_p
);
7214 defsubr (&Swindow_at
);
7215 defsubr (&Swindow_point
);
7216 defsubr (&Swindow_start
);
7217 defsubr (&Swindow_end
);
7218 defsubr (&Sset_window_point
);
7219 defsubr (&Sset_window_start
);
7220 defsubr (&Swindow_dedicated_p
);
7221 defsubr (&Sset_window_dedicated_p
);
7222 defsubr (&Swindow_display_table
);
7223 defsubr (&Sset_window_display_table
);
7224 defsubr (&Snext_window
);
7225 defsubr (&Sprevious_window
);
7226 defsubr (&Sother_window
);
7227 defsubr (&Sget_lru_window
);
7228 defsubr (&Sget_largest_window
);
7229 defsubr (&Sget_buffer_window
);
7230 defsubr (&Sdelete_other_windows
);
7231 defsubr (&Sdelete_windows_on
);
7232 defsubr (&Sreplace_buffer_in_windows
);
7233 defsubr (&Sdelete_window
);
7234 defsubr (&Sset_window_buffer
);
7235 defsubr (&Sselect_window
);
7236 defsubr (&Sforce_window_update
);
7237 defsubr (&Ssplit_window
);
7238 defsubr (&Senlarge_window
);
7239 defsubr (&Sshrink_window
);
7240 defsubr (&Sadjust_window_trailing_edge
);
7241 defsubr (&Sscroll_up
);
7242 defsubr (&Sscroll_down
);
7243 defsubr (&Sscroll_left
);
7244 defsubr (&Sscroll_right
);
7245 defsubr (&Sother_window_for_scrolling
);
7246 defsubr (&Sscroll_other_window
);
7247 defsubr (&Sminibuffer_selected_window
);
7248 defsubr (&Srecenter
);
7249 defsubr (&Swindow_text_height
);
7250 defsubr (&Smove_to_window_line
);
7251 defsubr (&Swindow_configuration_p
);
7252 defsubr (&Swindow_configuration_frame
);
7253 defsubr (&Sset_window_configuration
);
7254 defsubr (&Scurrent_window_configuration
);
7255 defsubr (&Ssave_window_excursion
);
7256 defsubr (&Swindow_tree
);
7257 defsubr (&Sset_window_margins
);
7258 defsubr (&Swindow_margins
);
7259 defsubr (&Sset_window_fringes
);
7260 defsubr (&Swindow_fringes
);
7261 defsubr (&Sset_window_scroll_bars
);
7262 defsubr (&Swindow_scroll_bars
);
7263 defsubr (&Swindow_vscroll
);
7264 defsubr (&Sset_window_vscroll
);
7265 defsubr (&Scompare_window_configurations
);
7266 defsubr (&Swindow_list
);
7267 defsubr (&Swindow_parameters
);
7268 defsubr (&Swindow_parameter
);
7269 defsubr (&Sset_window_parameter
);
7274 keys_of_window (void)
7276 initial_define_key (control_x_map
, '1', "delete-other-windows");
7277 initial_define_key (control_x_map
, '2', "split-window");
7278 initial_define_key (control_x_map
, '0', "delete-window");
7279 initial_define_key (control_x_map
, 'o', "other-window");
7280 initial_define_key (control_x_map
, '^', "enlarge-window");
7281 initial_define_key (control_x_map
, '<', "scroll-left");
7282 initial_define_key (control_x_map
, '>', "scroll-right");
7284 initial_define_key (global_map
, Ctl ('V'), "scroll-up-command");
7285 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
7286 initial_define_key (meta_map
, 'v', "scroll-down-command");
7289 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7290 (do not change this comment) */