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 */
54 Lisp_Object Qwindowp
, Qwindow_live_p
, Qwindow_configuration_p
;
55 Lisp_Object Qdisplay_buffer
;
56 Lisp_Object Qscroll_up
, Qscroll_down
, Qscroll_command
;
57 Lisp_Object Qwindow_size_fixed
;
59 static int displayed_window_lines (struct window
*);
60 static struct window
*decode_window (Lisp_Object
);
61 static int count_windows (struct window
*);
62 static int get_leaf_windows (struct window
*, struct window
**, int);
63 static void window_scroll (Lisp_Object
, int, int, int);
64 static void window_scroll_pixel_based (Lisp_Object
, int, int, int);
65 static void window_scroll_line_based (Lisp_Object
, int, int, int);
66 static int window_min_size_1 (struct window
*, int, int);
67 static int window_min_size_2 (struct window
*, int, int);
68 static int window_min_size (struct window
*, int, int, int, int *);
69 static void size_window (Lisp_Object
, int, int, int, int, int);
70 static int freeze_window_start (struct window
*, void *);
71 static int window_fixed_size_p (struct window
*, int, int);
72 static void enlarge_window (Lisp_Object
, int, int);
73 static Lisp_Object
window_list (void);
74 static int add_window_to_list (struct window
*, void *);
75 static int candidate_window_p (Lisp_Object
, Lisp_Object
, Lisp_Object
,
77 static Lisp_Object
next_window (Lisp_Object
, Lisp_Object
,
79 static void decode_next_window_args (Lisp_Object
*, Lisp_Object
*,
81 static void foreach_window (struct frame
*,
82 int (* fn
) (struct window
*, void *),
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 /* If non-nil, then the `recenter' command with a nil argument
195 the entire frame to be redrawn; the special value `tty' causes the
196 frame to be redrawn only if it is a tty frame. */
198 static Lisp_Object Vrecenter_redisplay
;
201 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
202 doc
: /* Return t if OBJECT is a window. */)
205 return WINDOWP (object
) ? Qt
: Qnil
;
208 DEFUN ("window-live-p", Fwindow_live_p
, Swindow_live_p
, 1, 1, 0,
209 doc
: /* Return t if OBJECT is a window which is currently visible. */)
212 return WINDOW_LIVE_P (object
) ? Qt
: Qnil
;
219 register struct window
*p
;
221 p
= allocate_window ();
223 XSETFASTINT (p
->sequence_number
, sequence_number
);
224 XSETFASTINT (p
->left_col
, 0);
225 XSETFASTINT (p
->top_line
, 0);
226 XSETFASTINT (p
->total_lines
, 0);
227 XSETFASTINT (p
->total_cols
, 0);
228 XSETFASTINT (p
->hscroll
, 0);
229 XSETFASTINT (p
->min_hscroll
, 0);
230 p
->orig_top_line
= p
->orig_total_lines
= Qnil
;
231 p
->start
= Fmake_marker ();
232 p
->pointm
= Fmake_marker ();
233 XSETFASTINT (p
->use_time
, 0);
235 p
->display_table
= Qnil
;
237 p
->window_parameters
= Qnil
;
238 p
->pseudo_window_p
= 0;
239 memset (&p
->cursor
, 0, sizeof (p
->cursor
));
240 memset (&p
->last_cursor
, 0, sizeof (p
->last_cursor
));
241 memset (&p
->phys_cursor
, 0, sizeof (p
->phys_cursor
));
242 p
->desired_matrix
= p
->current_matrix
= 0;
243 p
->nrows_scale_factor
= p
->ncols_scale_factor
= 1;
244 p
->phys_cursor_type
= -1;
245 p
->phys_cursor_width
= -1;
246 p
->must_be_updated_p
= 0;
247 XSETFASTINT (p
->window_end_vpos
, 0);
248 XSETFASTINT (p
->window_end_pos
, 0);
249 p
->window_end_valid
= Qnil
;
252 XSETFASTINT (p
->last_point
, 0);
253 p
->frozen_window_start_p
= 0;
254 p
->last_cursor_off_p
= p
->cursor_off_p
= 0;
255 p
->left_margin_cols
= Qnil
;
256 p
->right_margin_cols
= Qnil
;
257 p
->left_fringe_width
= Qnil
;
258 p
->right_fringe_width
= Qnil
;
259 p
->fringes_outside_margins
= Qnil
;
260 p
->scroll_bar_width
= Qnil
;
261 p
->vertical_scroll_bar_type
= Qt
;
262 p
->resize_proportionally
= Qnil
;
268 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
269 doc
: /* Return the window that the cursor now appears in and commands apply to. */)
272 return selected_window
;
275 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 1, 0,
276 doc
: /* Return the window used now for minibuffers.
277 If the optional argument FRAME is specified, return the minibuffer window
278 used by that frame. */)
282 frame
= selected_frame
;
283 CHECK_LIVE_FRAME (frame
);
284 return FRAME_MINIBUF_WINDOW (XFRAME (frame
));
287 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 0, 1, 0,
288 doc
: /* Return non-nil if WINDOW is a minibuffer window.
289 WINDOW defaults to the selected window. */)
292 struct window
*w
= decode_window (window
);
293 return MINI_WINDOW_P (w
) ? Qt
: Qnil
;
297 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
298 Spos_visible_in_window_p
, 0, 3, 0,
299 doc
: /* Return non-nil if position POS is currently on the frame in WINDOW.
300 Return nil if that position is scrolled vertically out of view.
301 If a character is only partially visible, nil is returned, unless the
302 optional argument PARTIALLY is non-nil.
303 If POS is only out of view because of horizontal scrolling, return non-nil.
304 If POS is t, it specifies the position of the last visible glyph in WINDOW.
305 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
307 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
308 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
309 where X and Y are the pixel coordinates relative to the top left corner
310 of the window. The remaining elements are omitted if the character after
311 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
312 off-window at the top and bottom of the row, ROWH is the height of the
313 display row, and VPOS is the row number (0-based) containing POS. */)
314 (Lisp_Object pos
, Lisp_Object window
, Lisp_Object partially
)
316 register struct window
*w
;
317 register EMACS_INT posint
;
318 register struct buffer
*buf
;
320 Lisp_Object in_window
= Qnil
;
321 int rtop
, rbot
, rowh
, vpos
, fully_p
= 1;
324 w
= decode_window (window
);
325 buf
= XBUFFER (w
->buffer
);
326 SET_TEXT_POS_FROM_MARKER (top
, w
->start
);
330 else if (!NILP (pos
))
332 CHECK_NUMBER_COERCE_MARKER (pos
);
335 else if (w
== XWINDOW (selected_window
))
338 posint
= XMARKER (w
->pointm
)->charpos
;
340 /* If position is above window start or outside buffer boundaries,
341 or if window start is out of range, position is not visible. */
343 || (posint
>= CHARPOS (top
) && posint
<= BUF_ZV (buf
)))
344 && CHARPOS (top
) >= BUF_BEGV (buf
)
345 && CHARPOS (top
) <= BUF_ZV (buf
)
346 && pos_visible_p (w
, posint
, &x
, &y
, &rtop
, &rbot
, &rowh
, &vpos
)
347 && (fully_p
= !rtop
&& !rbot
, (!NILP (partially
) || fully_p
)))
350 if (!NILP (in_window
) && !NILP (partially
))
352 Lisp_Object part
= Qnil
;
354 part
= list4 (make_number (rtop
), make_number (rbot
),
355 make_number (rowh
), make_number (vpos
));
356 in_window
= Fcons (make_number (x
),
357 Fcons (make_number (y
), part
));
363 DEFUN ("window-line-height", Fwindow_line_height
,
364 Swindow_line_height
, 0, 2, 0,
365 doc
: /* Return height in pixels of text line LINE in window WINDOW.
366 If WINDOW is nil or omitted, use selected window.
368 Return height of current line if LINE is omitted or nil. Return height of
369 header or mode line if LINE is `header-line' and `mode-line'.
370 Otherwise, LINE is a text line number starting from 0. A negative number
371 counts from the end of the window.
373 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
374 in pixels of the visible part of the line, VPOS and YPOS are the
375 vertical position in lines and pixels of the line, relative to the top
376 of the first text line, and OFFBOT is the number of off-window pixels at
377 the bottom of the text line. If there are off-window pixels at the top
378 of the (first) text line, YPOS is negative.
380 Return nil if window display is not up-to-date. In that case, use
381 `pos-visible-in-window-p' to obtain the information. */)
382 (Lisp_Object line
, Lisp_Object window
)
384 register struct window
*w
;
385 register struct buffer
*b
;
386 struct glyph_row
*row
, *end_row
;
387 int max_y
, crop
, i
, n
;
389 w
= decode_window (window
);
392 || w
->pseudo_window_p
)
395 CHECK_BUFFER (w
->buffer
);
396 b
= XBUFFER (w
->buffer
);
398 /* Fail if current matrix is not up-to-date. */
399 if (NILP (w
->window_end_valid
)
400 || current_buffer
->clip_changed
401 || current_buffer
->prevent_redisplay_optimizations_p
402 || XFASTINT (w
->last_modified
) < BUF_MODIFF (b
)
403 || XFASTINT (w
->last_overlay_modified
) < BUF_OVERLAY_MODIFF (b
))
409 if (i
< 0 || i
>= w
->current_matrix
->nrows
410 || (row
= MATRIX_ROW (w
->current_matrix
, i
), !row
->enabled_p
))
412 max_y
= window_text_bottom_y (w
);
416 if (EQ (line
, Qheader_line
))
418 if (!WINDOW_WANTS_HEADER_LINE_P (w
))
420 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
423 return list4 (make_number (row
->height
),
424 make_number (0), make_number (0),
428 if (EQ (line
, Qmode_line
))
430 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
433 return list4 (make_number (row
->height
),
434 make_number (0), /* not accurate */
435 make_number (WINDOW_HEADER_LINE_HEIGHT (w
)
436 + window_text_bottom_y (w
)),
443 row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
444 end_row
= MATRIX_BOTTOM_TEXT_ROW (w
->current_matrix
, w
);
445 max_y
= window_text_bottom_y (w
);
448 while ((n
< 0 || i
< n
)
449 && row
<= end_row
&& row
->enabled_p
450 && row
->y
+ row
->height
< max_y
)
453 if (row
> end_row
|| !row
->enabled_p
)
465 crop
= max (0, (row
->y
+ row
->height
) - max_y
);
466 return list4 (make_number (row
->height
+ min (0, row
->y
) - crop
),
468 make_number (row
->y
),
474 static struct window
*
475 decode_window (register Lisp_Object window
)
478 return XWINDOW (selected_window
);
480 CHECK_LIVE_WINDOW (window
);
481 return XWINDOW (window
);
484 static struct window
*
485 decode_any_window (register Lisp_Object window
)
488 return XWINDOW (selected_window
);
490 CHECK_WINDOW (window
);
491 return XWINDOW (window
);
494 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
495 doc
: /* Return the buffer that WINDOW is displaying.
496 WINDOW defaults to the selected window. */)
499 return decode_window (window
)->buffer
;
502 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
503 doc
: /* Return the number of lines in WINDOW.
504 WINDOW defaults to the selected window.
506 The return value includes WINDOW's mode line and header line, if any.
508 Note: The function does not take into account the value of `line-spacing'
509 when calculating the number of lines in WINDOW. */)
512 return decode_any_window (window
)->total_lines
;
515 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
516 doc
: /* Return the number of display columns in WINDOW.
517 WINDOW defaults to the selected window.
519 Note: The return value is the number of columns available for text in
520 WINDOW. If you want to find out how many columns WINDOW takes up, use
521 (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
524 return make_number (window_box_text_cols (decode_any_window (window
)));
527 DEFUN ("window-full-width-p", Fwindow_full_width_p
, Swindow_full_width_p
, 0, 1, 0,
528 doc
: /* Return t if WINDOW is as wide as its frame.
529 WINDOW defaults to the selected window. */)
532 return WINDOW_FULL_WIDTH_P (decode_any_window (window
)) ? Qt
: Qnil
;
535 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
536 doc
: /* Return the number of columns by which WINDOW is scrolled from left margin.
537 WINDOW defaults to the selected window. */)
540 return decode_window (window
)->hscroll
;
543 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
544 doc
: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
545 Return NCOL. NCOL should be zero or positive.
547 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
548 window so that the location of point moves off-window. */)
549 (Lisp_Object window
, Lisp_Object ncol
)
551 struct window
*w
= decode_window (window
);
555 hscroll
= max (0, XINT (ncol
));
557 /* Prevent redisplay shortcuts when changing the hscroll. */
558 if (XINT (w
->hscroll
) != hscroll
)
559 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
561 w
->hscroll
= make_number (hscroll
);
565 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger
,
566 Swindow_redisplay_end_trigger
, 0, 1, 0,
567 doc
: /* Return WINDOW's redisplay end trigger value.
568 WINDOW defaults to the selected window.
569 See `set-window-redisplay-end-trigger' for more information. */)
572 return decode_window (window
)->redisplay_end_trigger
;
575 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger
,
576 Sset_window_redisplay_end_trigger
, 2, 2, 0,
577 doc
: /* Set WINDOW's redisplay end trigger value to VALUE.
578 VALUE should be a buffer position (typically a marker) or nil.
579 If it is a buffer position, then if redisplay in WINDOW reaches a position
580 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
581 with two arguments: WINDOW, and the end trigger value.
582 Afterwards the end-trigger value is reset to nil. */)
583 (register Lisp_Object window
, Lisp_Object value
)
585 register struct window
*w
;
587 w
= decode_window (window
);
588 w
->redisplay_end_trigger
= value
;
592 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
593 doc
: /* Return a list of the edge coordinates of WINDOW.
594 The list has the form (LEFT TOP RIGHT BOTTOM).
595 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
596 all relative to 0, 0 at top left corner of frame.
598 RIGHT is one more than the rightmost column occupied by WINDOW.
599 BOTTOM is one more than the bottommost row occupied by WINDOW.
600 The edges include the space used by WINDOW's scroll bar, display
601 margins, fringes, header line, and/or mode line. For the edges of
602 just the text area, use `window-inside-edges'. */)
605 register struct window
*w
= decode_any_window (window
);
607 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w
)),
608 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w
)),
609 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w
)),
610 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w
)),
614 DEFUN ("window-pixel-edges", Fwindow_pixel_edges
, Swindow_pixel_edges
, 0, 1, 0,
615 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
616 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
617 the top left corner of the frame.
619 RIGHT is one more than the rightmost x position occupied by WINDOW.
620 BOTTOM is one more than the bottommost y position occupied by WINDOW.
621 The pixel edges include the space used by WINDOW's scroll bar, display
622 margins, fringes, header line, and/or mode line. For the pixel edges
623 of just the text area, use `window-inside-pixel-edges'. */)
626 register struct window
*w
= decode_any_window (window
);
628 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w
)),
629 Fcons (make_number (WINDOW_TOP_EDGE_Y (w
)),
630 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w
)),
631 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w
)),
636 calc_absolute_offset(struct window
*w
, int *add_x
, int *add_y
)
638 struct frame
*f
= XFRAME (w
->frame
);
640 #ifdef FRAME_MENUBAR_HEIGHT
641 *add_y
+= FRAME_MENUBAR_HEIGHT (f
);
643 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
644 *add_y
+= FRAME_TOOLBAR_TOP_HEIGHT (f
);
645 #elif FRAME_TOOLBAR_HEIGHT
646 *add_y
+= FRAME_TOOLBAR_HEIGHT (f
);
648 #ifdef FRAME_NS_TITLEBAR_HEIGHT
649 *add_y
+= FRAME_NS_TITLEBAR_HEIGHT (f
);
651 *add_x
= f
->left_pos
;
652 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
653 *add_x
+= FRAME_TOOLBAR_LEFT_WIDTH (f
);
657 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges
,
658 Swindow_absolute_pixel_edges
, 0, 1, 0,
659 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
660 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
661 the top left corner of the display.
663 RIGHT is one more than the rightmost x position occupied by WINDOW.
664 BOTTOM is one more than the bottommost y position occupied by WINDOW.
665 The pixel edges include the space used by WINDOW's scroll bar, display
666 margins, fringes, header line, and/or mode line. For the pixel edges
667 of just the text area, use `window-inside-absolute-pixel-edges'. */)
670 register struct window
*w
= decode_any_window (window
);
672 calc_absolute_offset (w
, &add_x
, &add_y
);
674 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w
) + add_x
),
675 Fcons (make_number (WINDOW_TOP_EDGE_Y (w
) + add_y
),
676 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w
) + add_x
),
677 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w
) + add_y
),
681 DEFUN ("window-inside-edges", Fwindow_inside_edges
, Swindow_inside_edges
, 0, 1, 0,
682 doc
: /* Return a list of the edge coordinates of WINDOW.
683 The list has the form (LEFT TOP RIGHT BOTTOM).
684 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
685 all relative to 0, 0 at top left corner of frame.
687 RIGHT is one more than the rightmost column of WINDOW's text area.
688 BOTTOM is one more than the bottommost row of WINDOW's text area.
689 The inside edges do not include the space used by the WINDOW's scroll
690 bar, display margins, fringes, header line, and/or mode line. */)
693 register struct window
*w
= decode_any_window (window
);
695 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w
)
696 + WINDOW_LEFT_MARGIN_COLS (w
)
697 + WINDOW_LEFT_FRINGE_COLS (w
)),
698 make_number (WINDOW_TOP_EDGE_LINE (w
)
699 + WINDOW_HEADER_LINE_LINES (w
)),
700 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w
)
701 - WINDOW_RIGHT_MARGIN_COLS (w
)
702 - WINDOW_RIGHT_FRINGE_COLS (w
)),
703 make_number (WINDOW_BOTTOM_EDGE_LINE (w
)
704 - WINDOW_MODE_LINE_LINES (w
)));
707 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges
, Swindow_inside_pixel_edges
, 0, 1, 0,
708 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
709 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
710 the top left corner of the frame.
712 RIGHT is one more than the rightmost x position of WINDOW's text area.
713 BOTTOM is one more than the bottommost y position of WINDOW's text area.
714 The inside edges do not include the space used by WINDOW's scroll bar,
715 display margins, fringes, header line, and/or mode line. */)
718 register struct window
*w
= decode_any_window (window
);
720 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w
)
721 + WINDOW_LEFT_MARGIN_WIDTH (w
)
722 + WINDOW_LEFT_FRINGE_WIDTH (w
)),
723 make_number (WINDOW_TOP_EDGE_Y (w
)
724 + WINDOW_HEADER_LINE_HEIGHT (w
)),
725 make_number (WINDOW_BOX_RIGHT_EDGE_X (w
)
726 - WINDOW_RIGHT_MARGIN_WIDTH (w
)
727 - WINDOW_RIGHT_FRINGE_WIDTH (w
)),
728 make_number (WINDOW_BOTTOM_EDGE_Y (w
)
729 - WINDOW_MODE_LINE_HEIGHT (w
)));
732 DEFUN ("window-inside-absolute-pixel-edges",
733 Fwindow_inside_absolute_pixel_edges
,
734 Swindow_inside_absolute_pixel_edges
, 0, 1, 0,
735 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
736 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
737 the top left corner of the display.
739 RIGHT is one more than the rightmost x position of WINDOW's text area.
740 BOTTOM is one more than the bottommost y position of WINDOW's text area.
741 The inside edges do not include the space used by WINDOW's scroll bar,
742 display margins, fringes, header line, and/or mode line. */)
745 register struct window
*w
= decode_any_window (window
);
747 calc_absolute_offset (w
, &add_x
, &add_y
);
749 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w
)
750 + WINDOW_LEFT_MARGIN_WIDTH (w
)
751 + WINDOW_LEFT_FRINGE_WIDTH (w
) + add_x
),
752 make_number (WINDOW_TOP_EDGE_Y (w
)
753 + WINDOW_HEADER_LINE_HEIGHT (w
) + add_y
),
754 make_number (WINDOW_BOX_RIGHT_EDGE_X (w
)
755 - WINDOW_RIGHT_MARGIN_WIDTH (w
)
756 - WINDOW_RIGHT_FRINGE_WIDTH (w
) + add_x
),
757 make_number (WINDOW_BOTTOM_EDGE_Y (w
)
758 - WINDOW_MODE_LINE_HEIGHT (w
) + add_y
));
761 /* Test if the character at column X, row Y is within window W.
762 If it is not, return ON_NOTHING;
763 if it is in the window's text area, return ON_TEXT;
764 if it is on the window's modeline, return ON_MODE_LINE;
765 if it is on the border between the window and its right sibling,
766 return ON_VERTICAL_BORDER.
767 if it is on a scroll bar, return ON_SCROLL_BAR.
768 if it is on the window's top line, return ON_HEADER_LINE;
769 if it is in left or right fringe of the window,
770 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
771 if it is in the marginal area to the left/right of the window,
772 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
774 X and Y are frame relative pixel coordinates. */
776 static enum window_part
777 coordinates_in_window (register struct window
*w
, int x
, int y
)
779 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
781 enum window_part part
;
782 int ux
= FRAME_COLUMN_WIDTH (f
);
783 int x0
= WINDOW_LEFT_EDGE_X (w
);
784 int x1
= WINDOW_RIGHT_EDGE_X (w
);
785 /* The width of the area where the vertical line can be dragged.
786 (Between mode lines for instance. */
787 int grabbable_width
= ux
;
788 int lmargin_width
, rmargin_width
, text_left
, text_right
;
789 int top_y
= WINDOW_TOP_EDGE_Y (w
);
790 int bottom_y
= WINDOW_BOTTOM_EDGE_Y (w
);
792 /* Outside any interesting row? */
793 if (y
< top_y
|| y
>= bottom_y
)
796 /* In what's below, we subtract 1 when computing right_x because we
797 want the rightmost pixel, which is given by left_pixel+width-1. */
798 if (w
->pseudo_window_p
)
801 right_x
= WINDOW_TOTAL_WIDTH (w
) - 1;
805 left_x
= WINDOW_BOX_LEFT_EDGE_X (w
);
806 right_x
= WINDOW_BOX_RIGHT_EDGE_X (w
) - 1;
809 /* On the mode line or header line? If it's near the start of
810 the mode or header line of window that's has a horizontal
811 sibling, say it's on the vertical line. That's to be able
812 to resize windows horizontally in case we're using toolkit
815 if (WINDOW_WANTS_MODELINE_P (w
)
816 && y
>= bottom_y
- CURRENT_MODE_LINE_HEIGHT (w
))
820 header_vertical_border_check
:
821 /* We're somewhere on the mode line. We consider the place
822 between mode lines of horizontally adjacent mode lines
823 as the vertical border. If scroll bars on the left,
824 return the right window. */
825 if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
)
826 || WINDOW_RIGHTMOST_P (w
))
827 && !WINDOW_LEFTMOST_P (w
)
828 && eabs (x
- x0
) < grabbable_width
)
829 return ON_VERTICAL_BORDER
;
831 /* Make sure we're not at the rightmost position of a
832 mode-/header-line and there's yet another window on the
834 else if ((WINDOW_RIGHTMOST_P (w
) || x
< x1
)
835 && eabs (x
- x1
) < grabbable_width
)
836 return ON_VERTICAL_BORDER
;
838 if (x
< x0
|| x
>= x1
)
844 if (WINDOW_WANTS_HEADER_LINE_P (w
)
845 && y
< top_y
+ CURRENT_HEADER_LINE_HEIGHT (w
))
847 part
= ON_HEADER_LINE
;
848 goto header_vertical_border_check
;
851 if (x
< x0
|| x
>= x1
) return ON_NOTHING
;
853 /* Outside any interesting column? */
854 if (x
< left_x
|| x
> right_x
)
855 return ON_SCROLL_BAR
;
857 lmargin_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
858 rmargin_width
= window_box_width (w
, RIGHT_MARGIN_AREA
);
860 text_left
= window_box_left (w
, TEXT_AREA
);
861 text_right
= text_left
+ window_box_width (w
, TEXT_AREA
);
863 if (FRAME_WINDOW_P (f
))
865 if (!w
->pseudo_window_p
866 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w
)
867 && !WINDOW_RIGHTMOST_P (w
)
868 && (eabs (x
- right_x
) < grabbable_width
))
869 return ON_VERTICAL_BORDER
;
871 /* Need to say "x > right_x" rather than >=, since on character
872 terminals, the vertical line's x coordinate is right_x. */
873 else if (!w
->pseudo_window_p
874 && !WINDOW_RIGHTMOST_P (w
)
876 return ON_VERTICAL_BORDER
;
880 if (lmargin_width
> 0
881 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
882 ? (x
>= left_x
+ WINDOW_LEFT_FRINGE_WIDTH (w
))
883 : (x
< left_x
+ lmargin_width
)))
884 return ON_LEFT_MARGIN
;
886 return ON_LEFT_FRINGE
;
891 if (rmargin_width
> 0
892 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
893 ? (x
< right_x
- WINDOW_RIGHT_FRINGE_WIDTH (w
))
894 : (x
>= right_x
- rmargin_width
)))
895 return ON_RIGHT_MARGIN
;
897 return ON_RIGHT_FRINGE
;
900 /* Everything special ruled out - must be on text area */
904 /* Take X is the frame-relative pixel x-coordinate, and return the
905 x-coordinate relative to part PART of window W. */
907 window_relative_x_coord (struct window
*w
, enum window_part part
, int x
)
909 int left_x
= (w
->pseudo_window_p
) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w
);
914 return x
- window_box_left (w
, TEXT_AREA
);
919 case ON_RIGHT_FRINGE
:
920 return x
- left_x
- WINDOW_LEFT_FRINGE_WIDTH (w
);
924 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
))
925 ? WINDOW_LEFT_FRINGE_WIDTH (w
) : 0));
927 case ON_RIGHT_MARGIN
:
929 - ((w
->pseudo_window_p
)
930 ? WINDOW_TOTAL_WIDTH (w
)
931 : WINDOW_BOX_RIGHT_EDGE_X (w
))
932 + window_box_width (w
, RIGHT_MARGIN_AREA
)
933 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
))
934 ? WINDOW_RIGHT_FRINGE_WIDTH (w
) : 0));
937 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
942 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
943 Scoordinates_in_window_p
, 2, 2, 0,
944 doc
: /* Return non-nil if COORDINATES are in WINDOW.
945 COORDINATES is a cons of the form (X . Y), X and Y being distances
946 measured in characters from the upper-left corner of the frame.
947 \(0 . 0) denotes the character in the upper left corner of the
949 If COORDINATES are in the text portion of WINDOW,
950 the coordinates relative to the window are returned.
951 If they are in the mode line of WINDOW, `mode-line' is returned.
952 If they are in the top mode line of WINDOW, `header-line' is returned.
953 If they are in the left fringe of WINDOW, `left-fringe' is returned.
954 If they are in the right fringe of WINDOW, `right-fringe' is returned.
955 If they are on the border between WINDOW and its right sibling,
956 `vertical-line' is returned.
957 If they are in the windows's left or right marginal areas, `left-margin'\n\
958 or `right-margin' is returned. */)
959 (register Lisp_Object coordinates
, Lisp_Object window
)
966 CHECK_WINDOW (window
);
967 w
= XWINDOW (window
);
968 f
= XFRAME (w
->frame
);
969 CHECK_CONS (coordinates
);
970 lx
= Fcar (coordinates
);
971 ly
= Fcdr (coordinates
);
972 CHECK_NUMBER_OR_FLOAT (lx
);
973 CHECK_NUMBER_OR_FLOAT (ly
);
974 x
= FRAME_PIXEL_X_FROM_CANON_X (f
, lx
) + FRAME_INTERNAL_BORDER_WIDTH (f
);
975 y
= FRAME_PIXEL_Y_FROM_CANON_Y (f
, ly
) + FRAME_INTERNAL_BORDER_WIDTH (f
);
977 switch (coordinates_in_window (w
, x
, y
))
983 /* Convert X and Y to window relative pixel coordinates, and
984 return the canonical char units. */
985 x
-= window_box_left (w
, TEXT_AREA
);
986 y
-= WINDOW_TOP_EDGE_Y (w
);
987 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f
, x
),
988 FRAME_CANON_Y_FROM_PIXEL_Y (f
, y
));
993 case ON_VERTICAL_BORDER
:
994 return Qvertical_line
;
1000 return Qleft_fringe
;
1002 case ON_RIGHT_FRINGE
:
1003 return Qright_fringe
;
1005 case ON_LEFT_MARGIN
:
1006 return Qleft_margin
;
1008 case ON_RIGHT_MARGIN
:
1009 return Qright_margin
;
1012 /* Historically we are supposed to return nil in this case. */
1021 /* Callback for foreach_window, used in window_from_coordinates.
1022 Check if window W contains coordinates specified by USER_DATA which
1023 is actually a pointer to a struct check_window_data CW.
1025 Check if window W contains coordinates *CW->x and *CW->y. If it
1026 does, return W in *CW->window, as Lisp_Object, and return in
1027 *CW->part the part of the window under coordinates *X,*Y. Return
1028 zero from this function to stop iterating over windows. */
1030 struct check_window_data
1032 Lisp_Object
*window
;
1034 enum window_part
*part
;
1038 check_window_containing (struct window
*w
, void *user_data
)
1040 struct check_window_data
*cw
= (struct check_window_data
*) user_data
;
1041 enum window_part found
;
1044 found
= coordinates_in_window (w
, cw
->x
, cw
->y
);
1045 if (found
!= ON_NOTHING
)
1048 XSETWINDOW (*cw
->window
, w
);
1056 /* Find the window containing frame-relative pixel position X/Y and
1057 return it as a Lisp_Object.
1059 If X, Y is on one of the window's special `window_part' elements,
1060 set *PART to the id of that element.
1062 If there is no window under X, Y return nil and leave *PART
1063 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1065 This function was previously implemented with a loop cycling over
1066 windows with Fnext_window, and starting with the frame's selected
1067 window. It turned out that this doesn't work with an
1068 implementation of next_window using Vwindow_list, because
1069 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1070 tree of F when this function is called asynchronously from
1071 note_mouse_highlight. The original loop didn't terminate in this
1075 window_from_coordinates (struct frame
*f
, int x
, int y
,
1076 enum window_part
*part
, int tool_bar_p
)
1079 struct check_window_data cw
;
1080 enum window_part dummy
;
1086 cw
.window
= &window
, cw
.x
= x
, cw
.y
= y
; cw
.part
= part
;
1087 foreach_window (f
, check_window_containing
, &cw
);
1089 /* If not found above, see if it's in the tool bar window, if a tool
1093 && WINDOWP (f
->tool_bar_window
)
1094 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)) > 0
1095 && (coordinates_in_window (XWINDOW (f
->tool_bar_window
), x
, y
)
1099 window
= f
->tool_bar_window
;
1105 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
1106 doc
: /* Return window containing coordinates X and Y on FRAME.
1107 If omitted, FRAME defaults to the currently selected frame.
1108 The top left corner of the frame is considered to be row 0,
1110 (Lisp_Object x
, Lisp_Object y
, Lisp_Object frame
)
1115 frame
= selected_frame
;
1116 CHECK_LIVE_FRAME (frame
);
1119 /* Check that arguments are integers or floats. */
1120 CHECK_NUMBER_OR_FLOAT (x
);
1121 CHECK_NUMBER_OR_FLOAT (y
);
1123 return window_from_coordinates (f
,
1124 (FRAME_PIXEL_X_FROM_CANON_X (f
, x
)
1125 + FRAME_INTERNAL_BORDER_WIDTH (f
)),
1126 (FRAME_PIXEL_Y_FROM_CANON_Y (f
, y
)
1127 + FRAME_INTERNAL_BORDER_WIDTH (f
)),
1131 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
1132 doc
: /* Return current value of point in WINDOW.
1133 WINDOW defaults to the selected window.
1135 For a nonselected window, this is the value point would have
1136 if that window were selected.
1138 Note that, when WINDOW is the selected window and its buffer
1139 is also currently selected, the value returned is the same as (point).
1140 It would be more strictly correct to return the `top-level' value
1141 of point, outside of any save-excursion forms.
1142 But that is hard to define. */)
1143 (Lisp_Object window
)
1145 register struct window
*w
= decode_window (window
);
1147 if (w
== XWINDOW (selected_window
)
1148 && current_buffer
== XBUFFER (w
->buffer
))
1150 return Fmarker_position (w
->pointm
);
1153 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
1154 doc
: /* Return position at which display currently starts in WINDOW.
1155 WINDOW defaults to the selected window.
1156 This is updated by redisplay or by calling `set-window-start'. */)
1157 (Lisp_Object window
)
1159 return Fmarker_position (decode_window (window
)->start
);
1162 /* This is text temporarily removed from the doc string below.
1164 This function returns nil if the position is not currently known.
1165 That happens when redisplay is preempted and doesn't finish.
1166 If in that case you want to compute where the end of the window would
1167 have been if redisplay had finished, do this:
1169 (goto-char (window-start window))
1170 (vertical-motion (1- (window-height window)) window)
1173 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 2, 0,
1174 doc
: /* Return position at which display currently ends in WINDOW.
1175 WINDOW defaults to the selected window.
1176 This is updated by redisplay, when it runs to completion.
1177 Simply changing the buffer text or setting `window-start'
1178 does not update this value.
1179 Return nil if there is no recorded value. \(This can happen if the
1180 last redisplay of WINDOW was preempted, and did not finish.)
1181 If UPDATE is non-nil, compute the up-to-date position
1182 if it isn't already recorded. */)
1183 (Lisp_Object window
, Lisp_Object update
)
1186 struct window
*w
= decode_window (window
);
1194 #if 0 /* This change broke some things. We should make it later. */
1195 /* If we don't know the end position, return nil.
1196 The user can compute it with vertical-motion if he wants to.
1197 It would be nicer to do it automatically,
1198 but that's so slow that it would probably bother people. */
1199 if (NILP (w
->window_end_valid
))
1204 && ! (! NILP (w
->window_end_valid
)
1205 && XFASTINT (w
->last_modified
) >= BUF_MODIFF (b
)
1206 && XFASTINT (w
->last_overlay_modified
) >= BUF_OVERLAY_MODIFF (b
))
1209 struct text_pos startp
;
1211 struct buffer
*old_buffer
= NULL
;
1213 /* Cannot use Fvertical_motion because that function doesn't
1214 cope with variable-height lines. */
1215 if (b
!= current_buffer
)
1217 old_buffer
= current_buffer
;
1218 set_buffer_internal (b
);
1221 /* In case W->start is out of the range, use something
1222 reasonable. This situation occurred when loading a file with
1223 `-l' containing a call to `rmail' with subsequent other
1224 commands. At the end, W->start happened to be BEG, while
1225 rmail had already narrowed the buffer. */
1226 if (XMARKER (w
->start
)->charpos
< BEGV
)
1227 SET_TEXT_POS (startp
, BEGV
, BEGV_BYTE
);
1228 else if (XMARKER (w
->start
)->charpos
> ZV
)
1229 SET_TEXT_POS (startp
, ZV
, ZV_BYTE
);
1231 SET_TEXT_POS_FROM_MARKER (startp
, w
->start
);
1233 start_display (&it
, w
, startp
);
1234 move_it_vertically (&it
, window_box_height (w
));
1235 if (it
.current_y
< it
.last_visible_y
)
1236 move_it_past_eol (&it
);
1237 value
= make_number (IT_CHARPOS (it
));
1240 set_buffer_internal (old_buffer
);
1243 XSETINT (value
, BUF_Z (b
) - XFASTINT (w
->window_end_pos
));
1248 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
1249 doc
: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1251 (Lisp_Object window
, Lisp_Object pos
)
1253 register struct window
*w
= decode_window (window
);
1255 CHECK_NUMBER_COERCE_MARKER (pos
);
1256 if (w
== XWINDOW (selected_window
)
1257 && XBUFFER (w
->buffer
) == current_buffer
)
1260 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
1262 /* We have to make sure that redisplay updates the window to show
1263 the new value of point. */
1264 if (!EQ (window
, selected_window
))
1265 ++windows_or_buffers_changed
;
1270 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
1271 doc
: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1272 WINDOW defaults to the selected window. Return POS.
1273 Optional third arg NOFORCE non-nil inhibits next redisplay from
1274 overriding motion of point in order to display at this exact start. */)
1275 (Lisp_Object window
, Lisp_Object pos
, Lisp_Object noforce
)
1277 register struct window
*w
= decode_window (window
);
1279 CHECK_NUMBER_COERCE_MARKER (pos
);
1280 set_marker_restricted (w
->start
, pos
, w
->buffer
);
1281 /* this is not right, but much easier than doing what is right. */
1282 w
->start_at_line_beg
= Qnil
;
1284 w
->force_start
= Qt
;
1285 w
->update_mode_line
= Qt
;
1286 XSETFASTINT (w
->last_modified
, 0);
1287 XSETFASTINT (w
->last_overlay_modified
, 0);
1288 if (!EQ (window
, selected_window
))
1289 windows_or_buffers_changed
++;
1295 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
1297 doc
: /* Return non-nil when WINDOW is dedicated to its buffer.
1298 More precisely, return the value assigned by the last call of
1299 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1300 never called with WINDOW as its argument, or the value set by that
1301 function was internally reset since its last call. WINDOW defaults to
1302 the selected window.
1304 When a window is dedicated to its buffer, `display-buffer' will refrain
1305 from displaying another buffer in it. `get-lru-window' and
1306 `get-largest-window' treat dedicated windows specially.
1307 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1308 `kill-buffer' can delete a dedicated window and the containing frame.
1310 Functions like `set-window-buffer' may change the buffer displayed by a
1311 window, unless that window is "strongly" dedicated to its buffer, that
1312 is the value returned by `window-dedicated-p' is t. */)
1313 (Lisp_Object window
)
1315 return decode_window (window
)->dedicated
;
1318 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
1319 Sset_window_dedicated_p
, 2, 2, 0,
1320 doc
: /* Mark WINDOW as dedicated according to FLAG.
1321 WINDOW defaults to the selected window. FLAG non-nil means mark WINDOW
1322 as dedicated to its buffer. FLAG nil means mark WINDOW as non-dedicated.
1325 When a window is dedicated to its buffer, `display-buffer' will refrain
1326 from displaying another buffer in it. `get-lru-window' and
1327 `get-largest-window' treat dedicated windows specially.
1328 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1329 `kill-buffer' can delete a dedicated window and the containing
1332 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1333 its buffer. Functions like `set-window-buffer' may change the buffer
1334 displayed by a window, unless that window is strongly dedicated to its
1335 buffer. If and when `set-window-buffer' displays another buffer in a
1336 window, it also makes sure that the window is not marked as dedicated. */)
1337 (Lisp_Object window
, Lisp_Object flag
)
1339 register struct window
*w
= decode_window (window
);
1341 w
->dedicated
= flag
;
1342 return w
->dedicated
;
1346 DEFUN ("window-parameters", Fwindow_parameters
, Swindow_parameters
,
1348 doc
: /* Return the parameters of WINDOW and their values.
1349 WINDOW defaults to the selected window. The return value is a list of
1350 elements of the form (PARAMETER . VALUE). */)
1351 (Lisp_Object window
)
1353 return Fcopy_alist (decode_window (window
)->window_parameters
);
1356 DEFUN ("window-parameter", Fwindow_parameter
, Swindow_parameter
,
1358 doc
: /* Return WINDOW's value for PARAMETER.
1359 WINDOW defaults to the selected window. */)
1360 (Lisp_Object window
, Lisp_Object parameter
)
1364 result
= Fassq (parameter
, decode_window (window
)->window_parameters
);
1365 return CDR_SAFE (result
);
1368 DEFUN ("set-window-parameter", Fset_window_parameter
,
1369 Sset_window_parameter
, 3, 3, 0,
1370 doc
: /* Set WINDOW's value of PARAMETER to VALUE.
1371 WINDOW defaults to the selected window. Return VALUE. */)
1372 (Lisp_Object window
, Lisp_Object parameter
, Lisp_Object value
)
1374 register struct window
*w
= decode_window (window
);
1375 Lisp_Object old_alist_elt
;
1377 old_alist_elt
= Fassq (parameter
, w
->window_parameters
);
1378 if (NILP (old_alist_elt
))
1379 w
->window_parameters
= Fcons (Fcons (parameter
, value
), w
->window_parameters
);
1381 Fsetcdr (old_alist_elt
, value
);
1386 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
1388 doc
: /* Return the display-table that WINDOW is using.
1389 WINDOW defaults to the selected window. */)
1390 (Lisp_Object window
)
1392 return decode_window (window
)->display_table
;
1395 /* Get the display table for use on window W. This is either W's
1396 display table or W's buffer's display table. Ignore the specified
1397 tables if they are not valid; if no valid table is specified,
1400 struct Lisp_Char_Table
*
1401 window_display_table (struct window
*w
)
1403 struct Lisp_Char_Table
*dp
= NULL
;
1405 if (DISP_TABLE_P (w
->display_table
))
1406 dp
= XCHAR_TABLE (w
->display_table
);
1407 else if (BUFFERP (w
->buffer
))
1409 struct buffer
*b
= XBUFFER (w
->buffer
);
1411 if (DISP_TABLE_P (b
->display_table
))
1412 dp
= XCHAR_TABLE (b
->display_table
);
1413 else if (DISP_TABLE_P (Vstandard_display_table
))
1414 dp
= XCHAR_TABLE (Vstandard_display_table
);
1420 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
1421 doc
: /* Set WINDOW's display-table to TABLE. */)
1422 (register Lisp_Object window
, Lisp_Object table
)
1424 register struct window
*w
;
1426 w
= decode_window (window
);
1427 w
->display_table
= table
;
1431 static void delete_window (Lisp_Object
);
1433 /* Record info on buffer window w is displaying
1434 when it is about to cease to display that buffer. */
1436 unshow_buffer (register struct window
*w
)
1443 if (b
!= XMARKER (w
->pointm
)->buffer
)
1447 if (w
== XWINDOW (selected_window
)
1448 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
1449 /* Do this except when the selected window's buffer
1450 is being removed from some other window. */
1452 /* last_window_start records the start position that this buffer
1453 had in the last window to be disconnected from it.
1454 Now that this statement is unconditional,
1455 it is possible for the buffer to be displayed in the
1456 selected window, while last_window_start reflects another
1457 window which was recently showing the same buffer.
1458 Some people might say that might be a good thing. Let's see. */
1459 b
->last_window_start
= marker_position (w
->start
);
1461 /* Point in the selected window's buffer
1462 is actually stored in that buffer, and the window's pointm isn't used.
1463 So don't clobber point in that buffer. */
1464 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
)
1465 /* This line helps to fix Horsley's testbug.el bug. */
1466 && !(WINDOWP (b
->last_selected_window
)
1467 && w
!= XWINDOW (b
->last_selected_window
)
1468 && EQ (buf
, XWINDOW (b
->last_selected_window
)->buffer
)))
1469 temp_set_point_both (b
,
1470 clip_to_bounds (BUF_BEGV (b
),
1471 XMARKER (w
->pointm
)->charpos
,
1473 clip_to_bounds (BUF_BEGV_BYTE (b
),
1474 marker_byte_position (w
->pointm
),
1477 if (WINDOWP (b
->last_selected_window
)
1478 && w
== XWINDOW (b
->last_selected_window
))
1479 b
->last_selected_window
= Qnil
;
1482 /* Put replacement into the window structure in place of old. */
1484 replace_window (Lisp_Object old
, Lisp_Object replacement
)
1486 register Lisp_Object tem
;
1487 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
1489 /* If OLD is its frame's root_window, then replacement is the new
1490 root_window for that frame. */
1492 if (EQ (old
, FRAME_ROOT_WINDOW (XFRAME (o
->frame
))))
1493 FRAME_ROOT_WINDOW (XFRAME (o
->frame
)) = replacement
;
1495 p
->left_col
= o
->left_col
;
1496 p
->top_line
= o
->top_line
;
1497 p
->total_cols
= o
->total_cols
;
1498 p
->total_lines
= o
->total_lines
;
1499 p
->desired_matrix
= p
->current_matrix
= 0;
1501 memset (&p
->cursor
, 0, sizeof (p
->cursor
));
1502 memset (&p
->last_cursor
, 0, sizeof (p
->last_cursor
));
1503 memset (&p
->phys_cursor
, 0, sizeof (p
->phys_cursor
));
1504 p
->phys_cursor_type
= -1;
1505 p
->phys_cursor_width
= -1;
1506 p
->must_be_updated_p
= 0;
1507 p
->pseudo_window_p
= 0;
1508 XSETFASTINT (p
->window_end_vpos
, 0);
1509 XSETFASTINT (p
->window_end_pos
, 0);
1510 p
->window_end_valid
= Qnil
;
1511 p
->frozen_window_start_p
= 0;
1512 p
->orig_top_line
= p
->orig_total_lines
= Qnil
;
1514 p
->next
= tem
= o
->next
;
1516 XWINDOW (tem
)->prev
= replacement
;
1518 p
->prev
= tem
= o
->prev
;
1520 XWINDOW (tem
)->next
= replacement
;
1522 p
->parent
= tem
= o
->parent
;
1525 if (EQ (XWINDOW (tem
)->vchild
, old
))
1526 XWINDOW (tem
)->vchild
= replacement
;
1527 if (EQ (XWINDOW (tem
)->hchild
, old
))
1528 XWINDOW (tem
)->hchild
= replacement
;
1531 /*** Here, if replacement is a vertical combination
1532 and so is its new parent, we should make replacement's
1533 children be children of that parent instead. ***/
1536 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
1537 doc
: /* Remove WINDOW from its frame.
1538 WINDOW defaults to the selected window. Return nil.
1539 Signal an error when WINDOW is the only window on its frame. */)
1540 (register Lisp_Object window
)
1544 window
= selected_window
;
1546 CHECK_LIVE_WINDOW (window
);
1548 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
1549 delete_window (window
);
1551 run_window_configuration_change_hook (f
);
1557 delete_window (register Lisp_Object window
)
1559 register Lisp_Object tem
, parent
, sib
;
1560 register struct window
*p
;
1561 register struct window
*par
;
1564 /* Because this function is called by other C code on non-leaf
1565 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1566 so we can't decode_window here. */
1567 CHECK_WINDOW (window
);
1568 p
= XWINDOW (window
);
1570 /* It's a no-op to delete an already-deleted window. */
1571 if (NILP (p
->buffer
)
1573 && NILP (p
->vchild
))
1578 error ("Attempt to delete minibuffer or sole ordinary window");
1579 par
= XWINDOW (parent
);
1581 windows_or_buffers_changed
++;
1582 Vwindow_list
= Qnil
;
1583 f
= XFRAME (WINDOW_FRAME (p
));
1584 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
1586 /* Are we trying to delete any frame's selected window? */
1588 Lisp_Object swindow
, pwindow
;
1590 /* See if the frame's selected window is either WINDOW
1591 or any subwindow of it, by finding all that window's parents
1592 and comparing each one with WINDOW. */
1593 swindow
= FRAME_SELECTED_WINDOW (f
);
1598 while (!NILP (pwindow
))
1600 if (EQ (window
, pwindow
))
1602 pwindow
= XWINDOW (pwindow
)->parent
;
1605 /* If the window being deleted is not a parent of SWINDOW,
1606 then SWINDOW is ok as the new selected window. */
1607 if (!EQ (window
, pwindow
))
1609 /* Otherwise, try another window for SWINDOW. */
1610 swindow
= Fnext_window (swindow
, Qlambda
, Qnil
);
1612 /* If we get back to the frame's selected window,
1613 it means there was no acceptable alternative,
1614 so we cannot delete. */
1615 if (EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1616 error ("Cannot delete window");
1619 /* If we need to change SWINDOW, do it. */
1620 if (! EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1622 /* If we're about to delete the selected window on the
1623 selected frame, then we should use Fselect_window to select
1624 the new window. On the other hand, if we're about to
1625 delete the selected window on any other frame, we shouldn't do
1626 anything but set the frame's selected_window slot. */
1627 if (EQ (FRAME_SELECTED_WINDOW (f
), selected_window
))
1628 Fselect_window (swindow
, Qnil
);
1630 FRAME_SELECTED_WINDOW (f
) = swindow
;
1634 /* Now we know we can delete this one. */
1635 window_deletion_count
++;
1638 /* tem is null for dummy parent windows
1639 (which have inferiors but not any contents themselves) */
1643 unchain_marker (XMARKER (p
->pointm
));
1644 unchain_marker (XMARKER (p
->start
));
1647 /* Free window glyph matrices. It is sure that they are allocated
1648 again when ADJUST_GLYPHS is called. Block input so that expose
1649 events and other events that access glyph matrices are not
1650 processed while we are changing them. */
1652 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f
)));
1656 XWINDOW (tem
)->prev
= p
->prev
;
1660 XWINDOW (tem
)->next
= p
->next
;
1662 if (EQ (window
, par
->hchild
))
1663 par
->hchild
= p
->next
;
1664 if (EQ (window
, par
->vchild
))
1665 par
->vchild
= p
->next
;
1667 /* Find one of our siblings to give our space to. */
1671 /* If p gives its space to its next sibling, that sibling needs
1672 to have its top/left side pulled back to where p's is.
1673 set_window_{height,width} will re-position the sibling's
1676 XWINDOW (sib
)->top_line
= p
->top_line
;
1677 XWINDOW (sib
)->left_col
= p
->left_col
;
1680 /* Stretch that sibling. */
1681 if (!NILP (par
->vchild
))
1682 set_window_height (sib
,
1683 XFASTINT (XWINDOW (sib
)->total_lines
) + XFASTINT (p
->total_lines
),
1685 if (!NILP (par
->hchild
))
1686 set_window_width (sib
,
1687 XFASTINT (XWINDOW (sib
)->total_cols
) + XFASTINT (p
->total_cols
),
1690 /* If parent now has only one child,
1691 put the child into the parent's place. */
1695 if (NILP (XWINDOW (tem
)->next
)) {
1696 replace_window (parent
, tem
);
1697 par
= XWINDOW (tem
);
1700 /* Since we may be deleting combination windows, we must make sure that
1701 not only p but all its children have been marked as deleted. */
1702 if (! NILP (p
->hchild
))
1703 delete_all_subwindows (XWINDOW (p
->hchild
));
1704 else if (! NILP (p
->vchild
))
1705 delete_all_subwindows (XWINDOW (p
->vchild
));
1707 /* Mark this window as deleted. */
1708 p
->buffer
= p
->hchild
= p
->vchild
= Qnil
;
1710 if (! NILP (par
->parent
))
1711 par
= XWINDOW (par
->parent
);
1713 /* Check if we have a v/hchild with a v/hchild. In that case remove
1716 if (! NILP (par
->vchild
) && ! NILP (XWINDOW (par
->vchild
)->vchild
))
1718 p
= XWINDOW (par
->vchild
);
1719 par
->vchild
= p
->vchild
;
1722 else if (! NILP (par
->hchild
) && ! NILP (XWINDOW (par
->hchild
)->hchild
))
1724 p
= XWINDOW (par
->hchild
);
1725 par
->hchild
= p
->hchild
;
1733 while (! NILP (tem
)) {
1734 XWINDOW (tem
)->parent
= p
->parent
;
1735 if (NILP (XWINDOW (tem
)->next
))
1737 tem
= XWINDOW (tem
)->next
;
1740 /* The next of the v/hchild we are removing is now the next of the
1741 last child for the v/hchild:
1742 Before v/hchild -> v/hchild -> next1 -> next2
1745 After: v/hchild -> next1 -> next2 -> next3
1747 XWINDOW (tem
)->next
= p
->next
;
1748 if (! NILP (p
->next
))
1749 XWINDOW (p
->next
)->prev
= tem
;
1751 p
->next
= p
->prev
= p
->vchild
= p
->hchild
= p
->buffer
= Qnil
;
1755 /* Adjust glyph matrices. */
1762 /***********************************************************************
1764 ***********************************************************************/
1766 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1767 pointer. This is a callback function for foreach_window, used in
1768 function window_list. */
1771 add_window_to_list (struct window
*w
, void *user_data
)
1773 Lisp_Object
*list
= (Lisp_Object
*) user_data
;
1775 XSETWINDOW (window
, w
);
1776 *list
= Fcons (window
, *list
);
1781 /* Return a list of all windows, for use by next_window. If
1782 Vwindow_list is a list, return that list. Otherwise, build a new
1783 list, cache it in Vwindow_list, and return that. */
1788 if (!CONSP (Vwindow_list
))
1792 Vwindow_list
= Qnil
;
1793 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
1795 Lisp_Object args
[2];
1797 /* We are visiting windows in canonical order, and add
1798 new windows at the front of args[1], which means we
1799 have to reverse this list at the end. */
1801 foreach_window (XFRAME (XCAR (tail
)), add_window_to_list
, &args
[1]);
1802 args
[0] = Vwindow_list
;
1803 args
[1] = Fnreverse (args
[1]);
1804 Vwindow_list
= Fnconc (2, args
);
1808 return Vwindow_list
;
1812 /* Value is non-zero if WINDOW satisfies the constraints given by
1813 OWINDOW, MINIBUF and ALL_FRAMES.
1815 MINIBUF t means WINDOW may be minibuffer windows.
1816 `lambda' means WINDOW may not be a minibuffer window.
1817 a window means a specific minibuffer window
1819 ALL_FRAMES t means search all frames,
1820 nil means search just current frame,
1821 `visible' means search just visible frames,
1822 0 means search visible and iconified frames,
1823 a window means search the frame that window belongs to,
1824 a frame means consider windows on that frame, only. */
1827 candidate_window_p (Lisp_Object window
, Lisp_Object owindow
, Lisp_Object minibuf
, Lisp_Object all_frames
)
1829 struct window
*w
= XWINDOW (window
);
1830 struct frame
*f
= XFRAME (w
->frame
);
1831 int candidate_p
= 1;
1833 if (!BUFFERP (w
->buffer
))
1835 else if (MINI_WINDOW_P (w
)
1836 && (EQ (minibuf
, Qlambda
)
1837 || (WINDOWP (minibuf
) && !EQ (minibuf
, window
))))
1839 /* If MINIBUF is `lambda' don't consider any mini-windows.
1840 If it is a window, consider only that one. */
1843 else if (EQ (all_frames
, Qt
))
1845 else if (NILP (all_frames
))
1847 xassert (WINDOWP (owindow
));
1848 candidate_p
= EQ (w
->frame
, XWINDOW (owindow
)->frame
);
1850 else if (EQ (all_frames
, Qvisible
))
1852 FRAME_SAMPLE_VISIBILITY (f
);
1853 candidate_p
= FRAME_VISIBLE_P (f
)
1854 && (FRAME_TERMINAL (XFRAME (w
->frame
))
1855 == FRAME_TERMINAL (XFRAME (selected_frame
)));
1858 else if (INTEGERP (all_frames
) && XINT (all_frames
) == 0)
1860 FRAME_SAMPLE_VISIBILITY (f
);
1861 candidate_p
= (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
)
1862 #ifdef HAVE_X_WINDOWS
1863 /* Yuck!! If we've just created the frame and the
1864 window-manager requested the user to place it
1865 manually, the window may still not be considered
1866 `visible'. I'd argue it should be at least
1867 something like `iconified', but don't know how to do
1869 || (FRAME_X_P (f
) && f
->output_data
.x
->asked_for_visible
1870 && !f
->output_data
.x
->has_been_visible
)
1873 && (FRAME_TERMINAL (XFRAME (w
->frame
))
1874 == FRAME_TERMINAL (XFRAME (selected_frame
)));
1876 else if (WINDOWP (all_frames
))
1877 candidate_p
= (EQ (FRAME_MINIBUF_WINDOW (f
), all_frames
)
1878 || EQ (XWINDOW (all_frames
)->frame
, w
->frame
)
1879 || EQ (XWINDOW (all_frames
)->frame
, FRAME_FOCUS_FRAME (f
)));
1880 else if (FRAMEP (all_frames
))
1881 candidate_p
= EQ (all_frames
, w
->frame
);
1887 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1888 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1892 decode_next_window_args (Lisp_Object
*window
, Lisp_Object
*minibuf
, Lisp_Object
*all_frames
)
1895 *window
= selected_window
;
1897 CHECK_LIVE_WINDOW (*window
);
1899 /* MINIBUF nil may or may not include minibuffers. Decide if it
1901 if (NILP (*minibuf
))
1902 *minibuf
= minibuf_level
? minibuf_window
: Qlambda
;
1903 else if (!EQ (*minibuf
, Qt
))
1906 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1907 => count none of them, or a specific minibuffer window (the
1908 active one) to count. */
1910 /* ALL_FRAMES nil doesn't specify which frames to include. */
1911 if (NILP (*all_frames
))
1912 *all_frames
= (!EQ (*minibuf
, Qlambda
)
1913 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window
)->frame
))
1915 else if (EQ (*all_frames
, Qvisible
))
1917 else if (EQ (*all_frames
, make_number (0)))
1919 else if (FRAMEP (*all_frames
))
1921 else if (!EQ (*all_frames
, Qt
))
1924 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1925 search just current frame, `visible' meaning search just visible
1926 frames, 0 meaning search visible and iconified frames, or a
1927 window, meaning search the frame that window belongs to, or a
1928 frame, meaning consider windows on that frame, only. */
1932 /* Return the next or previous window of WINDOW in cyclic ordering
1933 of windows. NEXT_P non-zero means return the next window. See the
1934 documentation string of next-window for the meaning of MINIBUF and
1938 next_window (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
, int next_p
)
1940 decode_next_window_args (&window
, &minibuf
, &all_frames
);
1942 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1943 return the first window on the frame. */
1944 if (FRAMEP (all_frames
)
1945 && !EQ (all_frames
, XWINDOW (window
)->frame
))
1946 return Fframe_first_window (all_frames
);
1952 /* Find WINDOW in the list of all windows. */
1953 list
= Fmemq (window
, window_list ());
1955 /* Scan forward from WINDOW to the end of the window list. */
1957 for (list
= XCDR (list
); CONSP (list
); list
= XCDR (list
))
1958 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1961 /* Scan from the start of the window list up to WINDOW. */
1963 for (list
= Vwindow_list
;
1964 CONSP (list
) && !EQ (XCAR (list
), window
);
1966 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1970 window
= XCAR (list
);
1974 Lisp_Object candidate
, list
;
1976 /* Scan through the list of windows for candidates. If there are
1977 candidate windows in front of WINDOW, the last one of these
1978 is the one we want. If there are candidates following WINDOW
1979 in the list, again the last one of these is the one we want. */
1981 for (list
= window_list (); CONSP (list
); list
= XCDR (list
))
1983 if (EQ (XCAR (list
), window
))
1985 if (WINDOWP (candidate
))
1988 else if (candidate_window_p (XCAR (list
), window
, minibuf
,
1990 candidate
= XCAR (list
);
1993 if (WINDOWP (candidate
))
2001 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
2002 doc
: /* Return window following WINDOW in cyclic ordering of windows.
2003 WINDOW defaults to the selected window. The optional arguments
2004 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2006 MINIBUF t means consider the minibuffer window even if the
2007 minibuffer is not active. MINIBUF nil or omitted means consider
2008 the minibuffer window only if the minibuffer is active. Any
2009 other value means do not consider the minibuffer window even if
2010 the minibuffer is active.
2012 Several frames may share a single minibuffer; if the minibuffer
2013 is active, all windows on all frames that share that minibuffer
2014 are considered too. Therefore, if you are using a separate
2015 minibuffer frame and the minibuffer is active and MINIBUF says it
2016 counts, `next-window' considers the windows in the frame from
2017 which you entered the minibuffer, as well as the minibuffer
2020 ALL-FRAMES nil or omitted means consider all windows on WINDOW's
2021 frame, plus the minibuffer window if specified by the MINIBUF
2022 argument, see above. If the minibuffer counts, consider all
2023 windows on all frames that share that minibuffer too.
2024 ALL-FRAMES t means consider all windows on all existing frames.
2025 ALL-FRAMES `visible' means consider all windows on all visible
2027 ALL-FRAMES 0 means consider all windows on all visible and
2029 ALL-FRAMES a frame means consider all windows on that frame only.
2030 Anything else means consider all windows on WINDOW's frame and no
2033 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2034 `next-window' to iterate through the entire cycle of acceptable
2035 windows, eventually ending up back at the window you started with.
2036 `previous-window' traverses the same cycle, in the reverse order. */)
2037 (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
)
2039 return next_window (window
, minibuf
, all_frames
, 1);
2043 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
2044 doc
: /* Return window preceding WINDOW in cyclic ordering of windows.
2045 WINDOW defaults to the selected window. The optional arguments
2046 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2047 For the precise meaning of these arguments see `next-window'.
2049 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2050 use `previous-window' to iterate through the entire cycle of
2051 acceptable windows, eventually ending up back at the window you
2052 started with. `next-window' traverses the same cycle, in the
2054 (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
)
2056 return next_window (window
, minibuf
, all_frames
, 0);
2060 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
2061 doc
: /* Select another window in cyclic ordering of windows.
2062 COUNT specifies the number of windows to skip, starting with the
2063 selected window, before making the selection. If COUNT is
2064 positive, skip COUNT windows forwards. If COUNT is negative,
2065 skip -COUNT windows backwards. COUNT zero means do not skip any
2066 window, so select the selected window. In an interactive call,
2067 COUNT is the numeric prefix argument. Return nil.
2069 This function uses `next-window' for finding the window to select.
2070 The argument ALL-FRAMES has the same meaning as in `next-window',
2071 but the MINIBUF argument of `next-window' is always effectively
2073 (Lisp_Object count
, Lisp_Object all_frames
)
2078 CHECK_NUMBER (count
);
2079 window
= selected_window
;
2081 for (i
= XINT (count
); i
> 0; --i
)
2082 window
= Fnext_window (window
, Qnil
, all_frames
);
2084 window
= Fprevious_window (window
, Qnil
, all_frames
);
2086 Fselect_window (window
, Qnil
);
2091 DEFUN ("window-list", Fwindow_list
, Swindow_list
, 0, 3, 0,
2092 doc
: /* Return a list of windows on FRAME, starting with WINDOW.
2093 FRAME nil or omitted means use the selected frame.
2094 WINDOW nil or omitted means use the selected window.
2095 MINIBUF t means include the minibuffer window, even if it isn't active.
2096 MINIBUF nil or omitted means include the minibuffer window only
2098 MINIBUF neither nil nor t means never include the minibuffer window. */)
2099 (Lisp_Object frame
, Lisp_Object minibuf
, Lisp_Object window
)
2102 window
= FRAMEP (frame
) ? XFRAME (frame
)->selected_window
: selected_window
;
2103 CHECK_WINDOW (window
);
2105 frame
= selected_frame
;
2107 if (!EQ (frame
, XWINDOW (window
)->frame
))
2108 error ("Window is on a different frame");
2110 return window_list_1 (window
, minibuf
, frame
);
2114 /* Return a list of windows in cyclic ordering. Arguments are like
2115 for `next-window'. */
2118 window_list_1 (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
)
2120 Lisp_Object tail
, list
, rest
;
2122 decode_next_window_args (&window
, &minibuf
, &all_frames
);
2125 for (tail
= window_list (); CONSP (tail
); tail
= XCDR (tail
))
2126 if (candidate_window_p (XCAR (tail
), window
, minibuf
, all_frames
))
2127 list
= Fcons (XCAR (tail
), list
);
2129 /* Rotate the list to start with WINDOW. */
2130 list
= Fnreverse (list
);
2131 rest
= Fmemq (window
, list
);
2132 if (!NILP (rest
) && !EQ (rest
, list
))
2134 for (tail
= list
; !EQ (XCDR (tail
), rest
); tail
= XCDR (tail
))
2136 XSETCDR (tail
, Qnil
);
2137 list
= nconc2 (rest
, list
);
2144 /* Look at all windows, performing an operation specified by TYPE
2146 If FRAMES is Qt, look at all frames;
2147 Qnil, look at just the selected frame;
2148 Qvisible, look at visible frames;
2149 a frame, just look at windows on that frame.
2150 If MINI is non-zero, perform the operation on minibuffer windows too. */
2155 GET_BUFFER_WINDOW
, /* Arg is buffer */
2156 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
2157 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
2158 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
2160 UNSHOW_BUFFER
, /* Arg is buffer */
2161 REDISPLAY_BUFFER_WINDOWS
, /* Arg is buffer */
2166 window_loop (enum window_loop type
, Lisp_Object obj
, int mini
, Lisp_Object frames
)
2168 Lisp_Object window
, windows
, best_window
, frame_arg
;
2170 struct gcpro gcpro1
;
2172 /* If we're only looping through windows on a particular frame,
2173 frame points to that frame. If we're looping through windows
2174 on all frames, frame is 0. */
2175 if (FRAMEP (frames
))
2176 f
= XFRAME (frames
);
2177 else if (NILP (frames
))
2178 f
= SELECTED_FRAME ();
2183 frame_arg
= Qlambda
;
2184 else if (EQ (frames
, make_number (0)))
2186 else if (EQ (frames
, Qvisible
))
2191 /* frame_arg is Qlambda to stick to one frame,
2192 Qvisible to consider all visible frames,
2195 /* Pick a window to start with. */
2199 window
= FRAME_SELECTED_WINDOW (f
);
2201 window
= FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2203 windows
= window_list_1 (window
, mini
? Qt
: Qnil
, frame_arg
);
2207 for (; CONSP (windows
); windows
= XCDR (windows
))
2211 window
= XCAR (windows
);
2212 w
= XWINDOW (window
);
2214 /* Note that we do not pay attention here to whether the frame
2215 is visible, since Fwindow_list skips non-visible frames if
2216 that is desired, under the control of frame_arg. */
2217 if (!MINI_WINDOW_P (w
)
2218 /* For UNSHOW_BUFFER, we must always consider all windows. */
2219 || type
== UNSHOW_BUFFER
2220 || (mini
&& minibuf_level
> 0))
2223 case GET_BUFFER_WINDOW
:
2224 if (EQ (w
->buffer
, obj
)
2225 /* Don't find any minibuffer window
2226 except the one that is currently in use. */
2227 && (MINI_WINDOW_P (w
)
2228 ? EQ (window
, minibuf_window
)
2231 if (NILP (best_window
))
2232 best_window
= window
;
2233 else if (EQ (window
, selected_window
))
2234 /* Prefer to return selected-window. */
2235 RETURN_UNGCPRO (window
);
2236 else if (EQ (Fwindow_frame (window
), selected_frame
))
2237 /* Prefer windows on the current frame. */
2238 best_window
= window
;
2242 case GET_LRU_WINDOW
:
2243 /* `obj' is an integer encoding a bitvector.
2244 `obj & 1' means consider only full-width windows.
2245 `obj & 2' means consider also dedicated windows. */
2246 if (((XINT (obj
) & 1) && !WINDOW_FULL_WIDTH_P (w
))
2247 || (!(XINT (obj
) & 2) && !NILP (w
->dedicated
))
2248 /* Minibuffer windows are always ignored. */
2249 || MINI_WINDOW_P (w
))
2251 if (NILP (best_window
)
2252 || (XFASTINT (XWINDOW (best_window
)->use_time
)
2253 > XFASTINT (w
->use_time
)))
2254 best_window
= window
;
2257 case DELETE_OTHER_WINDOWS
:
2258 if (!EQ (window
, obj
))
2259 Fdelete_window (window
);
2262 case DELETE_BUFFER_WINDOWS
:
2263 if (EQ (w
->buffer
, obj
))
2265 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2267 /* If this window is dedicated, and in a frame of its own,
2269 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
2270 && !NILP (w
->dedicated
)
2271 && other_visible_frames (f
))
2273 /* Skip the other windows on this frame.
2274 There might be one, the minibuffer! */
2275 while (CONSP (XCDR (windows
))
2276 && EQ (XWINDOW (XCAR (windows
))->frame
,
2277 XWINDOW (XCAR (XCDR (windows
)))->frame
))
2278 windows
= XCDR (windows
);
2280 /* Now we can safely delete the frame. */
2281 delete_frame (w
->frame
, Qnil
);
2283 else if (NILP (w
->parent
))
2285 /* If we're deleting the buffer displayed in the
2286 only window on the frame, find a new buffer to
2289 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
2290 /* Reset dedicated state of window. */
2291 w
->dedicated
= Qnil
;
2292 Fset_window_buffer (window
, buffer
, Qnil
);
2293 if (EQ (window
, selected_window
))
2294 Fset_buffer (w
->buffer
);
2297 Fdelete_window (window
);
2301 case GET_LARGEST_WINDOW
:
2302 { /* nil `obj' means to ignore dedicated windows. */
2303 /* Ignore dedicated windows and minibuffers. */
2304 if (MINI_WINDOW_P (w
) || (NILP (obj
) && !NILP (w
->dedicated
)))
2307 if (NILP (best_window
))
2308 best_window
= window
;
2311 struct window
*b
= XWINDOW (best_window
);
2312 if (XFASTINT (w
->total_lines
) * XFASTINT (w
->total_cols
)
2313 > XFASTINT (b
->total_lines
) * XFASTINT (b
->total_cols
))
2314 best_window
= window
;
2320 if (EQ (w
->buffer
, obj
))
2323 struct frame
*f
= XFRAME (w
->frame
);
2325 /* Find another buffer to show in this window. */
2326 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
2328 /* If this window is dedicated, and in a frame of its own,
2330 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
2331 && !NILP (w
->dedicated
)
2332 && other_visible_frames (f
))
2334 /* Skip the other windows on this frame.
2335 There might be one, the minibuffer! */
2336 while (CONSP (XCDR (windows
))
2337 && EQ (XWINDOW (XCAR (windows
))->frame
,
2338 XWINDOW (XCAR (XCDR (windows
)))->frame
))
2339 windows
= XCDR (windows
);
2341 /* Now we can safely delete the frame. */
2342 delete_frame (w
->frame
, Qnil
);
2344 else if (!NILP (w
->dedicated
) && !NILP (w
->parent
))
2347 XSETWINDOW (window
, w
);
2348 /* If this window is dedicated and not the only window
2349 in its frame, then kill it. */
2350 Fdelete_window (window
);
2354 /* Otherwise show a different buffer in the window. */
2355 w
->dedicated
= Qnil
;
2356 Fset_window_buffer (window
, buffer
, Qnil
);
2357 if (EQ (window
, selected_window
))
2358 Fset_buffer (w
->buffer
);
2363 case REDISPLAY_BUFFER_WINDOWS
:
2364 if (EQ (w
->buffer
, obj
))
2366 mark_window_display_accurate (window
, 0);
2367 w
->update_mode_line
= Qt
;
2368 XBUFFER (obj
)->prevent_redisplay_optimizations_p
= 1;
2369 ++update_mode_lines
;
2370 best_window
= window
;
2374 /* Check for a window that has a killed buffer. */
2375 case CHECK_ALL_WINDOWS
:
2376 if (! NILP (w
->buffer
)
2377 && NILP (XBUFFER (w
->buffer
)->name
))
2381 case WINDOW_LOOP_UNUSED
:
2390 /* Used for debugging. Abort if any window has a dead buffer. */
2393 check_all_windows (void)
2395 window_loop (CHECK_ALL_WINDOWS
, Qnil
, 1, Qt
);
2398 DEFUN ("window-use-time", Fwindow_use_time
, Swindow_use_time
, 0, 1, 0,
2399 doc
: /* Return WINDOW's use time.
2400 WINDOW defaults to the selected window. The window with the highest use
2401 time is the most recently selected one. The window with the lowest use
2402 time is the least recently selected one. */)
2403 (Lisp_Object window
)
2405 return decode_window (window
)->use_time
;
2408 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 2, 0,
2409 doc
: /* Return the window least recently selected or used for display.
2410 \(LRU means Least Recently Used.)
2412 Return a full-width window if possible.
2413 A minibuffer window is never a candidate.
2414 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2415 so if all windows are dedicated, the value is nil.
2416 If optional argument FRAME is `visible', search all visible frames.
2417 If FRAME is 0, search all visible and iconified frames.
2418 If FRAME is t, search all frames.
2419 If FRAME is nil, search only the selected frame.
2420 If FRAME is a frame, search only that frame. */)
2421 (Lisp_Object frame
, Lisp_Object dedicated
)
2423 register Lisp_Object w
;
2424 /* First try for a window that is full-width */
2425 w
= window_loop (GET_LRU_WINDOW
,
2426 NILP (dedicated
) ? make_number (1) : make_number (3),
2428 if (!NILP (w
) && !EQ (w
, selected_window
))
2430 /* If none of them, try the rest */
2431 return window_loop (GET_LRU_WINDOW
,
2432 NILP (dedicated
) ? make_number (0) : make_number (2),
2436 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 2, 0,
2437 doc
: /* Return the largest window in area.
2438 A minibuffer window is never a candidate.
2439 A dedicated window is never a candidate unless DEDICATED is non-nil,
2440 so if all windows are dedicated, the value is nil.
2441 If optional argument FRAME is `visible', search all visible frames.
2442 If FRAME is 0, search all visible and iconified frames.
2443 If FRAME is t, search all frames.
2444 If FRAME is nil, search only the selected frame.
2445 If FRAME is a frame, search only that frame. */)
2446 (Lisp_Object frame
, Lisp_Object dedicated
)
2448 return window_loop (GET_LARGEST_WINDOW
, dedicated
, 0,
2452 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 0, 2, 0,
2453 doc
: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2454 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to the
2456 If optional argument FRAME is `visible', search all visible frames.
2457 If optional argument FRAME is 0, search all visible and iconified frames.
2458 If FRAME is t, search all frames.
2459 If FRAME is nil, search only the selected frame.
2460 If FRAME is a frame, search only that frame. */)
2461 (Lisp_Object buffer_or_name
, Lisp_Object frame
)
2465 if (NILP (buffer_or_name
))
2466 buffer
= Fcurrent_buffer ();
2468 buffer
= Fget_buffer (buffer_or_name
);
2470 if (BUFFERP (buffer
))
2471 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
2476 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
2478 doc
: /* Make WINDOW (or the selected window) fill its frame.
2479 Only the frame WINDOW is on is affected.
2480 This function tries to reduce display jumps by keeping the text
2481 previously visible in WINDOW in the same place on the frame. Doing this
2482 depends on the value of (window-start WINDOW), so if calling this
2483 function in a program gives strange scrolling, make sure the
2484 window-start value is reasonable when this function is called. */)
2485 (Lisp_Object window
)
2492 window
= selected_window
;
2494 CHECK_LIVE_WINDOW (window
);
2495 w
= XWINDOW (window
);
2497 startpos
= marker_position (w
->start
);
2498 top
= WINDOW_TOP_EDGE_LINE (w
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2500 if (MINI_WINDOW_P (w
) && top
> 0)
2501 error ("Can't expand minibuffer to full frame");
2503 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_FRAME (w
));
2505 /* Try to minimize scrolling, by setting the window start to the point
2506 will cause the text at the old window start to be at the same place
2507 on the frame. But don't try to do this if the window start is
2508 outside the visible portion (as might happen when the display is
2509 not current, due to typeahead). */
2510 new_top
= WINDOW_TOP_EDGE_LINE (w
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2512 && startpos
>= BUF_BEGV (XBUFFER (w
->buffer
))
2513 && startpos
<= BUF_ZV (XBUFFER (w
->buffer
)))
2515 struct position pos
;
2516 struct buffer
*obuf
= current_buffer
;
2518 Fset_buffer (w
->buffer
);
2519 /* This computation used to temporarily move point, but that can
2520 have unwanted side effects due to text properties. */
2521 pos
= *vmotion (startpos
, -top
, w
);
2523 set_marker_both (w
->start
, w
->buffer
, pos
.bufpos
, pos
.bytepos
);
2524 w
->window_end_valid
= Qnil
;
2525 w
->start_at_line_beg
= ((pos
.bytepos
== BEGV_BYTE
2526 || FETCH_BYTE (pos
.bytepos
- 1) == '\n') ? Qt
2528 /* We need to do this, so that the window-scroll-functions
2530 w
->optional_new_start
= Qt
;
2532 set_buffer_internal (obuf
);
2538 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
2539 0, 2, "bDelete windows on (buffer): ",
2540 doc
: /* Delete all windows showing BUFFER-OR-NAME.
2541 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2542 defaults to the current buffer.
2544 Optional second argument FRAME controls which frames are affected.
2545 If optional argument FRAME is `visible', search all visible frames.
2546 If FRAME is 0, search all visible and iconified frames.
2547 If FRAME is nil, search all frames.
2548 If FRAME is t, search only the selected frame.
2549 If FRAME is a frame, search only that frame.
2550 When a window showing BUFFER-OR-NAME is dedicated and the only window of
2551 its frame, that frame is deleted when there are other frames left. */)
2552 (Lisp_Object buffer_or_name
, Lisp_Object frame
)
2556 /* FRAME uses t and nil to mean the opposite of what window_loop
2560 else if (EQ (frame
, Qt
))
2563 if (NILP (buffer_or_name
))
2564 buffer
= Fcurrent_buffer ();
2567 buffer
= Fget_buffer (buffer_or_name
);
2568 CHECK_BUFFER (buffer
);
2571 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, frame
);
2576 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
2577 Sreplace_buffer_in_windows
,
2578 0, 1, "bReplace buffer in windows: ",
2579 doc
: /* Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
2580 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2581 defaults to the current buffer.
2583 When a window showing BUFFER-OR-NAME is dedicated that window is
2584 deleted. If that window is the only window on its frame, that frame is
2585 deleted too when there are other frames left. If there are no other
2586 frames left, some other buffer is displayed in that window. */)
2587 (Lisp_Object buffer_or_name
)
2591 if (NILP (buffer_or_name
))
2592 buffer
= Fcurrent_buffer ();
2595 buffer
= Fget_buffer (buffer_or_name
);
2596 CHECK_BUFFER (buffer
);
2599 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
2604 /* Replace BUFFER with some other buffer in all windows
2605 of all frames, even those on other keyboards. */
2608 replace_buffer_in_all_windows (Lisp_Object buffer
)
2610 Lisp_Object tail
, frame
;
2612 /* A single call to window_loop won't do the job
2613 because it only considers frames on the current keyboard.
2614 So loop manually over frames, and handle each one. */
2615 FOR_EACH_FRAME (tail
, frame
)
2616 window_loop (UNSHOW_BUFFER
, buffer
, 1, frame
);
2619 /* Set the height of WINDOW and all its inferiors. */
2621 /* The smallest acceptable dimensions for a window. Anything smaller
2622 might crash Emacs. */
2624 #define MIN_SAFE_WINDOW_WIDTH (2)
2625 #define MIN_SAFE_WINDOW_HEIGHT (1)
2627 /* For wp non-zero the total number of columns of window w. Otherwise
2628 the total number of lines of w. */
2630 #define WINDOW_TOTAL_SIZE(w, wp) \
2631 (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
2633 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2634 minimum allowable size. */
2637 check_frame_size (FRAME_PTR frame
, int *rows
, int *cols
)
2639 /* For height, we have to see:
2640 how many windows the frame has at minimum (one or two),
2641 and whether it has a menu bar or other special stuff at the top. */
2643 = ((FRAME_MINIBUF_ONLY_P (frame
) || ! FRAME_HAS_MINIBUF_P (frame
))
2644 ? MIN_SAFE_WINDOW_HEIGHT
2645 : 2 * MIN_SAFE_WINDOW_HEIGHT
);
2647 if (FRAME_TOP_MARGIN (frame
) > 0)
2648 min_height
+= FRAME_TOP_MARGIN (frame
);
2650 if (*rows
< min_height
)
2652 if (*cols
< MIN_SAFE_WINDOW_WIDTH
)
2653 *cols
= MIN_SAFE_WINDOW_WIDTH
;
2656 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2657 check if W's width can be changed, otherwise check W's height.
2658 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2659 siblings, too. If none of the siblings is resizable, WINDOW isn't
2663 window_fixed_size_p (struct window
*w
, int width_p
, int check_siblings_p
)
2668 if (!NILP (w
->hchild
))
2670 c
= XWINDOW (w
->hchild
);
2674 /* A horizontal combination is fixed-width if all of if its
2676 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2677 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2678 fixed_p
= c
== NULL
;
2682 /* A horizontal combination is fixed-height if one of if its
2684 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2685 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2686 fixed_p
= c
!= NULL
;
2689 else if (!NILP (w
->vchild
))
2691 c
= XWINDOW (w
->vchild
);
2695 /* A vertical combination is fixed-width if one of if its
2697 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2698 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2699 fixed_p
= c
!= NULL
;
2703 /* A vertical combination is fixed-height if all of if its
2705 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2706 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2707 fixed_p
= c
== NULL
;
2710 else if (BUFFERP (w
->buffer
))
2712 struct buffer
*old
= current_buffer
;
2715 current_buffer
= XBUFFER (w
->buffer
);
2716 val
= find_symbol_value (Qwindow_size_fixed
);
2717 current_buffer
= old
;
2720 if (!EQ (val
, Qunbound
))
2722 fixed_p
= !NILP (val
);
2725 && ((EQ (val
, Qheight
) && width_p
)
2726 || (EQ (val
, Qwidth
) && !width_p
)))
2730 /* Can't tell if this one is resizable without looking at
2731 siblings. If all siblings are fixed-size this one is too. */
2732 if (!fixed_p
&& check_siblings_p
&& WINDOWP (w
->parent
))
2736 for (child
= w
->prev
; WINDOWP (child
); child
= XWINDOW (child
)->prev
)
2737 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2741 for (child
= w
->next
; WINDOWP (child
); child
= XWINDOW (child
)->next
)
2742 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2755 /* Return minimum size of leaf window W. WIDTH_P non-zero means return
2756 the minimum width of W, WIDTH_P zero means return the minimum height
2757 of W. SAFE_P non-zero means ignore window-min-height|width but just
2758 return values that won't crash Emacs and don't hide components like
2759 fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the
2760 minibuffer window, always return 1. */
2763 window_min_size_2 (struct window
*w
, int width_p
, int safe_p
)
2765 /* We should consider buffer-local values of window_min_height and
2766 window_min_width here. */
2769 int safe_size
= (MIN_SAFE_WINDOW_WIDTH
2770 + WINDOW_FRINGE_COLS (w
)
2771 + WINDOW_SCROLL_BAR_COLS (w
));
2773 return safe_p
? safe_size
: max (window_min_width
, safe_size
);
2775 else if (MINI_WINDOW_P (w
))
2779 int safe_size
= (MIN_SAFE_WINDOW_HEIGHT
2780 + ((BUFFERP (w
->buffer
)
2781 && !NILP (XBUFFER (w
->buffer
)->mode_line_format
))
2784 return safe_p
? safe_size
: max (window_min_height
, safe_size
);
2788 /* Return minimum size of window W, not taking fixed-width windows into
2789 account. WIDTH_P non-zero means return the minimum width, otherwise
2790 return the minimum height. SAFE_P non-zero means ignore
2791 window-min-height|width but just return values that won't crash Emacs
2792 and don't hide components like fringes, scrollbars, or modelines. If
2793 W is a combination window, compute the minimum size from the minimum
2794 sizes of W's children. */
2797 window_min_size_1 (struct window
*w
, int width_p
, int safe_p
)
2802 if (!NILP (w
->hchild
))
2804 /* W is a horizontal combination. */
2805 c
= XWINDOW (w
->hchild
);
2810 /* The minimum width of a horizontal combination is the sum of
2811 the minimum widths of its children. */
2814 size
+= window_min_size_1 (c
, 1, safe_p
);
2815 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2820 /* The minimum height of a horizontal combination is the
2821 maximum of the minimum heights of its children. */
2824 size
= max (window_min_size_1 (c
, 0, safe_p
), size
);
2825 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2829 else if (!NILP (w
->vchild
))
2831 /* W is a vertical combination. */
2832 c
= XWINDOW (w
->vchild
);
2837 /* The minimum width of a vertical combination is the maximum
2838 of the minimum widths of its children. */
2841 size
= max (window_min_size_1 (c
, 1, safe_p
), size
);
2842 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2847 /* The minimum height of a vertical combination is the sum of
2848 the minimum height of its children. */
2851 size
+= window_min_size_1 (c
, 0, safe_p
);
2852 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2857 /* W is a leaf window. */
2858 size
= window_min_size_2 (w
, width_p
, safe_p
);
2863 /* Return the minimum size of window W, taking fixed-size windows into
2864 account. WIDTH_P non-zero means return the minimum width, otherwise
2865 return the minimum height. SAFE_P non-zero means ignore
2866 window-min-height|width but just return values that won't crash Emacs
2867 and don't hide components like fringes, scrollbars, or modelines.
2868 IGNORE_FIXED_P non-zero means ignore if W is fixed-size. Set *FIXED
2869 to 1 if W is fixed-size unless FIXED is null. */
2872 window_min_size (struct window
*w
, int width_p
, int safe_p
, int ignore_fixed_p
, int *fixed
)
2879 fixed_p
= window_fixed_size_p (w
, width_p
, 1);
2885 size
= WINDOW_TOTAL_SIZE (w
, width_p
);
2887 size
= window_min_size_1 (w
, width_p
, safe_p
);
2893 /* Adjust the margins of window W if text area is too small.
2894 Return 1 if window width is ok after adjustment; 0 if window
2895 is still too narrow. */
2898 adjust_window_margins (struct window
*w
)
2900 int box_cols
= (WINDOW_TOTAL_COLS (w
)
2901 - WINDOW_FRINGE_COLS (w
)
2902 - WINDOW_SCROLL_BAR_COLS (w
));
2903 int margin_cols
= (WINDOW_LEFT_MARGIN_COLS (w
)
2904 + WINDOW_RIGHT_MARGIN_COLS (w
));
2906 if (box_cols
- margin_cols
>= MIN_SAFE_WINDOW_WIDTH
)
2909 if (margin_cols
< 0 || box_cols
< MIN_SAFE_WINDOW_WIDTH
)
2912 /* Window's text area is too narrow, but reducing the window
2913 margins will fix that. */
2914 margin_cols
= box_cols
- MIN_SAFE_WINDOW_WIDTH
;
2915 if (WINDOW_RIGHT_MARGIN_COLS (w
) > 0)
2917 if (WINDOW_LEFT_MARGIN_COLS (w
) > 0)
2918 w
->left_margin_cols
= w
->right_margin_cols
2919 = make_number (margin_cols
/2);
2921 w
->right_margin_cols
= make_number (margin_cols
);
2924 w
->left_margin_cols
= make_number (margin_cols
);
2928 /* Calculate new sizes for windows in the list FORWARD when their
2929 compound size goes from TOTAL to SIZE. TOTAL must be greater than
2930 SIZE. The number of windows in FORWARD is NCHILDREN, and the number
2931 that can shrink is SHRINKABLE. Fixed-size windows may be shrunk if
2932 and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means
2933 shrink columns, otherwise shrink lines.
2935 SAFE_P zero means windows may be sized down to window-min-height
2936 lines (window-min-window columns for WIDTH_P non-zero). SAFE_P
2937 non-zero means windows may be sized down to their minimum safe sizes
2938 taking into account the space needed to display modelines, fringes,
2941 This function returns an allocated array of new sizes that the caller
2942 must free. A size -1 means the window is fixed and RESIZE_FIXED_P is
2943 zero. A size zero means the window shall be deleted. Array index 0
2944 refers to the first window in FORWARD, 1 to the second, and so on.
2946 This function resizes windows proportionally to their size. It also
2947 tries to preserve smaller windows by resizing larger windows before
2948 resizing any window to zero. If resize_proportionally is non-nil for
2949 a specific window, it will attempt to strictly resize that window
2950 proportionally, even at the expense of deleting smaller windows. */
2952 shrink_windows (int total
, int size
, int nchildren
, int shrinkable
,
2953 int resize_fixed_p
, Lisp_Object forward
, int width_p
, int safe_p
)
2955 int available_resize
= 0;
2956 int *new_sizes
, *min_sizes
;
2959 int smallest
= total
;
2960 int total_removed
= 0;
2961 int total_shrink
= total
- size
;
2964 new_sizes
= xmalloc (sizeof (*new_sizes
) * nchildren
);
2965 min_sizes
= xmalloc (sizeof (*min_sizes
) * nchildren
);
2967 for (i
= 0, child
= forward
; !NILP (child
); child
= c
->next
, ++i
)
2971 c
= XWINDOW (child
);
2972 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
2974 if (!resize_fixed_p
&& window_fixed_size_p (c
, width_p
, 0))
2978 new_sizes
[i
] = child_size
;
2979 min_sizes
[i
] = window_min_size_1 (c
, width_p
, safe_p
);
2980 if (child_size
> min_sizes
[i
]
2981 && NILP (c
->resize_proportionally
))
2982 available_resize
+= child_size
- min_sizes
[i
];
2985 /* We might need to shrink some windows to zero. Find the smallest
2986 windows and set them to 0 until we can fulfil the new size. */
2988 while (shrinkable
> 1 && size
+ available_resize
< total
)
2990 for (i
= 0; i
< nchildren
; ++i
)
2991 if (new_sizes
[i
] > 0 && smallest
> new_sizes
[i
])
2992 smallest
= new_sizes
[i
];
2994 for (i
= 0; i
< nchildren
; ++i
)
2995 if (new_sizes
[i
] == smallest
)
2997 /* Resize this window down to zero. */
2999 if (smallest
> min_sizes
[i
])
3000 available_resize
-= smallest
- min_sizes
[i
];
3001 available_resize
+= smallest
;
3003 total_removed
+= smallest
;
3005 /* We don't know what the smallest is now. */
3008 /* Out of for, just remove one window at the time and
3009 check again if we have enough space. */
3014 /* Now, calculate the new sizes. Try to shrink each window
3015 proportional to its size. */
3016 for (i
= 0; i
< nchildren
; ++i
)
3018 if (new_sizes
[i
] > min_sizes
[i
])
3020 int to_shrink
= total_shrink
* new_sizes
[i
] / total
;
3022 if (new_sizes
[i
] - to_shrink
< min_sizes
[i
])
3023 to_shrink
= new_sizes
[i
] - min_sizes
[i
];
3024 new_sizes
[i
] -= to_shrink
;
3025 total_removed
+= to_shrink
;
3029 /* Any reminder due to rounding, we just subtract from windows
3030 that are left and still can be shrunk. */
3031 while (total_shrink
> total_removed
)
3033 int nonzero_sizes
= 0;
3034 int nonzero_idx
= -1;
3036 for (i
= 0; i
< nchildren
; ++i
)
3037 if (new_sizes
[i
] > 0)
3043 for (i
= 0; i
< nchildren
; ++i
)
3044 if (new_sizes
[i
] > min_sizes
[i
])
3049 /* Out of for, just shrink one window at the time and
3050 check again if we have enough space. */
3054 /* Special case, only one window left. */
3055 if (nonzero_sizes
== 1)
3059 /* Any surplus due to rounding, we add to windows that are left. */
3060 while (total_shrink
< total_removed
)
3062 for (i
= 0; i
< nchildren
; ++i
)
3064 if (new_sizes
[i
] != 0 && total_shrink
< total_removed
)
3078 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
3079 WINDOW's width. Resize WINDOW's children, if any, so that they keep
3080 their proportionate size relative to WINDOW.
3082 If FIRST_ONLY is 1, change only the first of WINDOW's children when
3083 they are in series. If LAST_ONLY is 1, change only the last of
3084 WINDOW's children when they are in series.
3086 Propagate WINDOW's top or left edge position to children. Delete
3087 windows that become too small unless NODELETE_P is 1. When
3088 NODELETE_P equals 2 do not honor settings for window-min-height and
3089 window-min-width when resizing windows but use safe defaults instead.
3090 This should give better behavior when resizing frames. */
3093 size_window (Lisp_Object window
, int size
, int width_p
, int nodelete_p
, int first_only
, int last_only
)
3095 struct window
*w
= XWINDOW (window
);
3097 Lisp_Object child
, *forward
, *sideward
;
3098 int old_size
= WINDOW_TOTAL_SIZE (w
, width_p
);
3100 size
= max (0, size
);
3102 /* Delete WINDOW if it's too small. */
3103 if (nodelete_p
!= 1 && !NILP (w
->parent
)
3104 && size
< window_min_size_1 (w
, width_p
, nodelete_p
== 2))
3106 delete_window (window
);
3110 /* Set redisplay hints. */
3111 w
->last_modified
= make_number (0);
3112 w
->last_overlay_modified
= make_number (0);
3113 windows_or_buffers_changed
++;
3114 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w
->frame
)) = 1;
3118 sideward
= &w
->vchild
;
3119 forward
= &w
->hchild
;
3120 w
->total_cols
= make_number (size
);
3121 adjust_window_margins (w
);
3125 sideward
= &w
->hchild
;
3126 forward
= &w
->vchild
;
3127 w
->total_lines
= make_number (size
);
3128 w
->orig_total_lines
= Qnil
;
3131 if (!NILP (*sideward
))
3133 /* We have a chain of parallel siblings whose size should all change. */
3134 for (child
= *sideward
; !NILP (child
); child
= c
->next
)
3136 c
= XWINDOW (child
);
3138 c
->left_col
= w
->left_col
;
3140 c
->top_line
= w
->top_line
;
3141 size_window (child
, size
, width_p
, nodelete_p
,
3142 first_only
, last_only
);
3145 else if (!NILP (*forward
) && last_only
)
3147 /* Change the last in a series of siblings. */
3148 Lisp_Object last_child
;
3151 for (child
= *forward
; !NILP (child
); child
= c
->next
)
3153 c
= XWINDOW (child
);
3157 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3158 size_window (last_child
, size
- old_size
+ child_size
,
3159 width_p
, nodelete_p
, first_only
, last_only
);
3161 else if (!NILP (*forward
) && first_only
)
3163 /* Change the first in a series of siblings. */
3167 c
= XWINDOW (child
);
3170 c
->left_col
= w
->left_col
;
3172 c
->top_line
= w
->top_line
;
3174 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3175 size_window (child
, size
- old_size
+ child_size
,
3176 width_p
, nodelete_p
, first_only
, last_only
);
3178 else if (!NILP (*forward
))
3180 int fixed_size
, each
, extra
, n
;
3181 int resize_fixed_p
, nfixed
;
3182 int last_pos
, first_pos
, nchildren
, total
;
3183 int *new_sizes
= NULL
;
3185 /* Determine the fixed-size portion of this window, and the
3186 number of child windows. */
3187 fixed_size
= nchildren
= nfixed
= total
= 0;
3188 for (child
= *forward
; !NILP (child
); child
= c
->next
, ++nchildren
)
3192 c
= XWINDOW (child
);
3193 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3194 total
+= child_size
;
3196 if (window_fixed_size_p (c
, width_p
, 0))
3198 fixed_size
+= child_size
;
3203 /* If the new size is smaller than fixed_size, or if there
3204 aren't any resizable windows, allow resizing fixed-size
3206 resize_fixed_p
= nfixed
== nchildren
|| size
< fixed_size
;
3208 /* Compute how many lines/columns to add/remove to each child. The
3209 value of extra takes care of rounding errors. */
3210 n
= resize_fixed_p
? nchildren
: nchildren
- nfixed
;
3211 if (size
< total
&& n
> 1)
3212 new_sizes
= shrink_windows (total
, size
, nchildren
, n
,
3213 resize_fixed_p
, *forward
, width_p
,
3217 each
= (size
- total
) / n
;
3218 extra
= (size
- total
) - n
* each
;
3221 /* Compute new children heights and edge positions. */
3222 first_pos
= width_p
? XINT (w
->left_col
) : XINT (w
->top_line
);
3223 last_pos
= first_pos
;
3224 for (n
= 0, child
= *forward
; !NILP (child
); child
= c
->next
, ++n
)
3226 int new_size
, old_size
;
3228 c
= XWINDOW (child
);
3229 old_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3230 new_size
= old_size
;
3232 /* The top or left edge position of this child equals the
3233 bottom or right edge of its predecessor. */
3235 c
->left_col
= make_number (last_pos
);
3237 c
->top_line
= make_number (last_pos
);
3239 /* If this child can be resized, do it. */
3240 if (resize_fixed_p
|| !window_fixed_size_p (c
, width_p
, 0))
3242 new_size
= new_sizes
? new_sizes
[n
] : old_size
+ each
+ extra
;
3246 /* Set new size. Note that size_window also propagates
3247 edge positions to children, so it's not a no-op if we
3248 didn't change the child's size. */
3249 size_window (child
, new_size
, width_p
, 1, first_only
, last_only
);
3251 /* Remember the bottom/right edge position of this child; it
3252 will be used to set the top/left edge of the next child. */
3253 last_pos
+= new_size
;
3258 /* We should have covered the parent exactly with child windows. */
3259 xassert (size
== last_pos
- first_pos
);
3261 /* Now delete any children that became too small. */
3262 if (nodelete_p
!= 1)
3263 for (child
= *forward
; !NILP (child
); child
= c
->next
)
3267 c
= XWINDOW (child
);
3268 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3269 size_window (child
, child_size
, width_p
, nodelete_p
,
3270 first_only
, last_only
);
3275 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3276 WINDOW's children. NODELETE zero means windows that have become
3277 smaller than window-min-height in the process may be deleted.
3278 NODELETE 1 means never delete windows that become too small in the
3279 process. (The caller should check later and do so if appropriate.)
3280 NODELETE 2 means delete only windows that have become too small to be
3281 displayed correctly. */
3284 set_window_height (Lisp_Object window
, int height
, int nodelete
)
3286 size_window (window
, height
, 0, nodelete
, 0, 0);
3289 /* Set WINDOW's width to WIDTH, and recursively change the width of
3290 WINDOW's children. NODELETE zero means windows that have become
3291 smaller than window-min-width in the process may be deleted.
3292 NODELETE 1 means never delete windows that become too small in the
3293 process. (The caller should check later and do so if appropriate.)
3294 NODELETE 2 means delete only windows that have become too small to be
3295 displayed correctly. */
3298 set_window_width (Lisp_Object window
, int width
, int nodelete
)
3300 size_window (window
, width
, 1, nodelete
, 0, 0);
3303 /* Change window heights in windows rooted in WINDOW by N lines. */
3306 change_window_heights (Lisp_Object window
, int n
)
3308 struct window
*w
= XWINDOW (window
);
3310 XSETFASTINT (w
->top_line
, XFASTINT (w
->top_line
) + n
);
3311 XSETFASTINT (w
->total_lines
, XFASTINT (w
->total_lines
) - n
);
3313 if (INTEGERP (w
->orig_top_line
))
3314 XSETFASTINT (w
->orig_top_line
, XFASTINT (w
->orig_top_line
) + n
);
3315 if (INTEGERP (w
->orig_total_lines
))
3316 XSETFASTINT (w
->orig_total_lines
, XFASTINT (w
->orig_total_lines
) - n
);
3318 /* Handle just the top child in a vertical split. */
3319 if (!NILP (w
->vchild
))
3320 change_window_heights (w
->vchild
, n
);
3322 /* Adjust all children in a horizontal split. */
3323 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
3325 w
= XWINDOW (window
);
3326 change_window_heights (window
, n
);
3331 int window_select_count
;
3333 EXFUN (Fset_window_fringes
, 4);
3334 EXFUN (Fset_window_scroll_bars
, 4);
3337 run_funs (Lisp_Object funs
)
3339 for (; CONSP (funs
); funs
= XCDR (funs
))
3340 if (!EQ (XCAR (funs
), Qt
))
3341 call0 (XCAR (funs
));
3344 static Lisp_Object
select_window_norecord (Lisp_Object window
);
3345 static Lisp_Object
select_frame_norecord (Lisp_Object frame
);
3348 run_window_configuration_change_hook (struct frame
*f
)
3350 int count
= SPECPDL_INDEX ();
3351 Lisp_Object frame
, global_wcch
3352 = Fdefault_value (Qwindow_configuration_change_hook
);
3353 XSETFRAME (frame
, f
);
3355 if (NILP (Vrun_hooks
))
3358 if (SELECTED_FRAME () != f
)
3360 record_unwind_protect (select_frame_norecord
, Fselected_frame ());
3361 Fselect_frame (frame
, Qt
);
3364 /* Use the right buffer. Matters when running the local hooks. */
3365 if (current_buffer
!= XBUFFER (Fwindow_buffer (Qnil
)))
3367 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
3368 Fset_buffer (Fwindow_buffer (Qnil
));
3371 /* Look for buffer-local values. */
3373 Lisp_Object windows
= Fwindow_list (frame
, Qlambda
, Qnil
);
3374 for (; CONSP (windows
); windows
= XCDR (windows
))
3376 Lisp_Object window
= XCAR (windows
);
3377 Lisp_Object buffer
= Fwindow_buffer (window
);
3378 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook
,
3381 int count
= SPECPDL_INDEX ();
3382 record_unwind_protect (select_window_norecord
, Fselected_window ());
3383 select_window_norecord (window
);
3384 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook
,
3386 unbind_to (count
, Qnil
);
3391 run_funs (global_wcch
);
3392 unbind_to (count
, Qnil
);
3395 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3396 means it's allowed to run hooks. See make_frame for a case where
3397 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3398 margins, fringes, and scroll-bar settings of the window are not
3399 reset from the buffer's local settings. */
3402 set_window_buffer (Lisp_Object window
, Lisp_Object buffer
, int run_hooks_p
, int keep_margins_p
)
3404 struct window
*w
= XWINDOW (window
);
3405 struct buffer
*b
= XBUFFER (buffer
);
3406 int count
= SPECPDL_INDEX ();
3407 int samebuf
= EQ (buffer
, w
->buffer
);
3411 if (EQ (window
, selected_window
))
3412 b
->last_selected_window
= window
;
3414 /* Let redisplay errors through. */
3415 b
->display_error_modiff
= 0;
3417 /* Update time stamps of buffer display. */
3418 if (INTEGERP (b
->display_count
))
3419 XSETINT (b
->display_count
, XINT (b
->display_count
) + 1);
3420 b
->display_time
= Fcurrent_time ();
3422 XSETFASTINT (w
->window_end_pos
, 0);
3423 XSETFASTINT (w
->window_end_vpos
, 0);
3424 memset (&w
->last_cursor
, 0, sizeof w
->last_cursor
);
3425 w
->window_end_valid
= Qnil
;
3426 if (!(keep_margins_p
&& samebuf
))
3427 { /* If we're not actually changing the buffer, don't reset hscroll and
3428 vscroll. This case happens for example when called from
3429 change_frame_size_1, where we use a dummy call to
3430 Fset_window_buffer on the frame's selected window (and no other)
3431 just in order to run window-configuration-change-hook.
3432 Resetting hscroll and vscroll here is problematic for things like
3433 image-mode and doc-view-mode since it resets the image's position
3434 whenever we resize the frame. */
3435 w
->hscroll
= w
->min_hscroll
= make_number (0);
3437 set_marker_both (w
->pointm
, buffer
, BUF_PT (b
), BUF_PT_BYTE (b
));
3438 set_marker_restricted (w
->start
,
3439 make_number (b
->last_window_start
),
3441 w
->start_at_line_beg
= Qnil
;
3442 w
->force_start
= Qnil
;
3443 XSETFASTINT (w
->last_modified
, 0);
3444 XSETFASTINT (w
->last_overlay_modified
, 0);
3446 /* Maybe we could move this into the `if' but it's not obviously safe and
3447 I doubt it's worth the trouble. */
3448 windows_or_buffers_changed
++;
3450 /* We must select BUFFER for running the window-scroll-functions. */
3451 /* We can't check ! NILP (Vwindow_scroll_functions) here
3452 because that might itself be a local variable. */
3453 if (window_initialized
)
3455 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
3456 Fset_buffer (buffer
);
3459 XMARKER (w
->pointm
)->insertion_type
= !NILP (Vwindow_point_insertion_type
);
3461 if (!keep_margins_p
)
3463 /* Set left and right marginal area width etc. from buffer. */
3465 /* This may call adjust_window_margins three times, so
3466 temporarily disable window margins. */
3467 Lisp_Object save_left
= w
->left_margin_cols
;
3468 Lisp_Object save_right
= w
->right_margin_cols
;
3470 w
->left_margin_cols
= w
->right_margin_cols
= Qnil
;
3472 Fset_window_fringes (window
,
3473 b
->left_fringe_width
, b
->right_fringe_width
,
3474 b
->fringes_outside_margins
);
3476 Fset_window_scroll_bars (window
,
3477 b
->scroll_bar_width
,
3478 b
->vertical_scroll_bar_type
, Qnil
);
3480 w
->left_margin_cols
= save_left
;
3481 w
->right_margin_cols
= save_right
;
3483 Fset_window_margins (window
,
3484 b
->left_margin_cols
, b
->right_margin_cols
);
3489 if (! NILP (Vwindow_scroll_functions
))
3490 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
3491 Fmarker_position (w
->start
));
3492 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w
)));
3495 unbind_to (count
, Qnil
);
3499 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 3, 0,
3500 doc
: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3501 WINDOW defaults to the selected window. BUFFER-OR-NAME must be a buffer
3502 or the name of an existing buffer. Optional third argument KEEP-MARGINS
3503 non-nil means that WINDOW's current display margins, fringe widths, and
3504 scroll bar settings are preserved; the default is to reset these from
3505 the local settings for BUFFER-OR-NAME or the frame defaults. Return nil.
3507 This function throws an error when WINDOW is strongly dedicated to its
3508 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3509 already display BUFFER-OR-NAME.
3511 This function runs `window-scroll-functions' before running
3512 `window-configuration-change-hook'. */)
3513 (register Lisp_Object window
, Lisp_Object buffer_or_name
, Lisp_Object keep_margins
)
3515 register Lisp_Object tem
, buffer
;
3516 register struct window
*w
= decode_window (window
);
3518 XSETWINDOW (window
, w
);
3519 buffer
= Fget_buffer (buffer_or_name
);
3520 CHECK_BUFFER (buffer
);
3521 if (NILP (XBUFFER (buffer
)->name
))
3522 error ("Attempt to display deleted buffer");
3526 error ("Window is deleted");
3527 else if (!EQ (tem
, Qt
))
3528 /* w->buffer is t when the window is first being set up. */
3530 if (EQ (tem
, buffer
))
3532 else if (EQ (w
->dedicated
, Qt
))
3533 error ("Window is dedicated to `%s'", SDATA (XBUFFER (tem
)->name
));
3535 w
->dedicated
= Qnil
;
3540 set_window_buffer (window
, buffer
, 1, !NILP (keep_margins
));
3544 /* Note that selected_window can be nil when this is called from
3545 Fset_window_configuration. */
3547 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 2, 0,
3548 doc
: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3549 If WINDOW is not already selected, make WINDOW's buffer current
3550 and make WINDOW the frame's selected window. Return WINDOW.
3551 Optional second arg NORECORD non-nil means do not put this buffer
3552 at the front of the list of recently selected ones and do not
3553 make this window the most recently selected one.
3555 Note that the main editor command loop selects the buffer of the
3556 selected window before each command. */)
3557 (register Lisp_Object window
, Lisp_Object norecord
)
3559 register struct window
*w
;
3560 register struct window
*ow
;
3563 CHECK_LIVE_WINDOW (window
);
3565 w
= XWINDOW (window
);
3566 w
->frozen_window_start_p
= 0;
3568 if (NILP (norecord
))
3570 ++window_select_count
;
3571 XSETFASTINT (w
->use_time
, window_select_count
);
3572 record_buffer (w
->buffer
);
3575 if (EQ (window
, selected_window
))
3578 sf
= SELECTED_FRAME ();
3579 if (XFRAME (WINDOW_FRAME (w
)) != sf
)
3581 XFRAME (WINDOW_FRAME (w
))->selected_window
= window
;
3582 /* Use this rather than Fhandle_switch_frame
3583 so that FRAME_FOCUS_FRAME is moved appropriately as we
3584 move around in the state where a minibuffer in a separate
3586 Fselect_frame (WINDOW_FRAME (w
), norecord
);
3587 /* Fselect_frame called us back so we've done all the work already. */
3588 eassert (EQ (window
, selected_window
));
3592 sf
->selected_window
= window
;
3594 /* Store the current buffer's actual point into the
3595 old selected window. It belongs to that window,
3596 and when the window is not selected, must be in the window. */
3597 if (!NILP (selected_window
))
3599 ow
= XWINDOW (selected_window
);
3600 if (! NILP (ow
->buffer
))
3601 set_marker_both (ow
->pointm
, ow
->buffer
,
3602 BUF_PT (XBUFFER (ow
->buffer
)),
3603 BUF_PT_BYTE (XBUFFER (ow
->buffer
)));
3606 selected_window
= window
;
3608 Fset_buffer (w
->buffer
);
3610 XBUFFER (w
->buffer
)->last_selected_window
= window
;
3612 /* Go to the point recorded in the window.
3613 This is important when the buffer is in more
3614 than one window. It also matters when
3615 redisplay_window has altered point after scrolling,
3616 because it makes the change only in the window. */
3618 register EMACS_INT new_point
= marker_position (w
->pointm
);
3619 if (new_point
< BEGV
)
3621 else if (new_point
> ZV
)
3627 windows_or_buffers_changed
++;
3632 select_window_norecord (Lisp_Object window
)
3634 return WINDOW_LIVE_P (window
)
3635 ? Fselect_window (window
, Qt
) : selected_window
;
3639 select_frame_norecord (Lisp_Object frame
)
3641 return FRAME_LIVE_P (XFRAME (frame
))
3642 ? Fselect_frame (frame
, Qt
) : selected_frame
;
3646 display_buffer (Lisp_Object buffer
, Lisp_Object not_this_window_p
, Lisp_Object override_frame
)
3648 return call3 (Qdisplay_buffer
, buffer
, not_this_window_p
, override_frame
);
3651 DEFUN ("force-window-update", Fforce_window_update
, Sforce_window_update
,
3653 doc
: /* Force all windows to be updated on next redisplay.
3654 If optional arg OBJECT is a window, force redisplay of that window only.
3655 If OBJECT is a buffer or buffer name, force redisplay of all windows
3656 displaying that buffer. */)
3657 (Lisp_Object object
)
3661 windows_or_buffers_changed
++;
3662 update_mode_lines
++;
3666 if (WINDOWP (object
))
3668 struct window
*w
= XWINDOW (object
);
3669 mark_window_display_accurate (object
, 0);
3670 w
->update_mode_line
= Qt
;
3671 if (BUFFERP (w
->buffer
))
3672 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
3673 ++update_mode_lines
;
3677 if (STRINGP (object
))
3678 object
= Fget_buffer (object
);
3679 if (BUFFERP (object
) && !NILP (XBUFFER (object
)->name
))
3681 /* Walk all windows looking for buffer, and force update
3682 of each of those windows. */
3684 object
= window_loop (REDISPLAY_BUFFER_WINDOWS
, object
, 0, Qvisible
);
3685 return NILP (object
) ? Qnil
: Qt
;
3688 /* If nothing suitable was found, just return.
3689 We could signal an error, but this feature will typically be used
3690 asynchronously in timers or process sentinels, so we don't. */
3696 temp_output_buffer_show (register Lisp_Object buf
)
3698 register struct buffer
*old
= current_buffer
;
3699 register Lisp_Object window
;
3700 register struct window
*w
;
3702 XBUFFER (buf
)->directory
= current_buffer
->directory
;
3705 BUF_SAVE_MODIFF (XBUFFER (buf
)) = MODIFF
;
3709 #if 0 /* rms: there should be no reason for this. */
3710 XBUFFER (buf
)->prevent_redisplay_optimizations_p
= 1;
3712 set_buffer_internal (old
);
3714 if (!NILP (Vtemp_buffer_show_function
))
3715 call1 (Vtemp_buffer_show_function
, buf
);
3718 window
= display_buffer (buf
, Qnil
, Qnil
);
3720 if (!EQ (XWINDOW (window
)->frame
, selected_frame
))
3721 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
3722 Vminibuf_scroll_window
= window
;
3723 w
= XWINDOW (window
);
3724 XSETFASTINT (w
->hscroll
, 0);
3725 XSETFASTINT (w
->min_hscroll
, 0);
3726 set_marker_restricted_both (w
->start
, buf
, BEG
, BEG
);
3727 set_marker_restricted_both (w
->pointm
, buf
, BEG
, BEG
);
3729 /* Run temp-buffer-show-hook, with the chosen window selected
3730 and its buffer current. */
3732 if (!NILP (Vrun_hooks
)
3733 && !NILP (Fboundp (Qtemp_buffer_show_hook
))
3734 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook
)))
3736 int count
= SPECPDL_INDEX ();
3737 Lisp_Object prev_window
, prev_buffer
;
3738 prev_window
= selected_window
;
3739 XSETBUFFER (prev_buffer
, old
);
3741 /* Select the window that was chosen, for running the hook.
3742 Note: Both Fselect_window and select_window_norecord may
3743 set-buffer to the buffer displayed in the window,
3744 so we need to save the current buffer. --stef */
3745 record_unwind_protect (Fset_buffer
, prev_buffer
);
3746 record_unwind_protect (select_window_norecord
, prev_window
);
3747 Fselect_window (window
, Qt
);
3748 Fset_buffer (w
->buffer
);
3749 call1 (Vrun_hooks
, Qtemp_buffer_show_hook
);
3750 unbind_to (count
, Qnil
);
3756 make_dummy_parent (Lisp_Object window
)
3759 register struct window
*o
, *p
;
3762 o
= XWINDOW (window
);
3763 p
= allocate_window ();
3764 for (i
= 0; i
< VECSIZE (struct window
); ++i
)
3765 ((struct Lisp_Vector
*) p
)->contents
[i
]
3766 = ((struct Lisp_Vector
*)o
)->contents
[i
];
3767 XSETWINDOW (new, p
);
3770 XSETFASTINT (p
->sequence_number
, sequence_number
);
3772 /* Put new into window structure in place of window */
3773 replace_window (window
, new);
3786 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
3787 doc
: /* Split WINDOW, putting SIZE lines in the first of the pair.
3788 WINDOW defaults to selected one and SIZE to half its size.
3789 If optional third arg HORIZONTAL is non-nil, split side by side and put
3790 SIZE columns in the first of the pair. In that case, SIZE includes that
3791 window's scroll bar, or the divider column to its right.
3792 Interactively, all arguments are nil.
3793 Returns the newly created window (which is the lower or rightmost one).
3794 The upper or leftmost window is the original one, and remains selected
3795 if it was selected before.
3797 See Info node `(elisp)Splitting Windows' for more details and examples. */)
3798 (Lisp_Object window
, Lisp_Object size
, Lisp_Object horizontal
)
3800 register Lisp_Object
new;
3801 register struct window
*o
, *p
;
3803 register int size_int
;
3806 window
= selected_window
;
3808 CHECK_LIVE_WINDOW (window
);
3810 o
= XWINDOW (window
);
3811 fo
= XFRAME (WINDOW_FRAME (o
));
3815 if (!NILP (horizontal
))
3816 /* Calculate the size of the left-hand window, by dividing
3817 the usable space in columns by two.
3818 We round up, since the left-hand window may include
3819 a dividing line, while the right-hand may not. */
3820 size_int
= (XFASTINT (o
->total_cols
) + 1) >> 1;
3822 size_int
= XFASTINT (o
->total_lines
) >> 1;
3826 CHECK_NUMBER (size
);
3827 size_int
= XINT (size
);
3830 if (MINI_WINDOW_P (o
))
3831 error ("Attempt to split minibuffer window");
3832 else if (window_fixed_size_p (o
, !NILP (horizontal
), 0))
3833 error ("Attempt to split fixed-size window");
3835 if (NILP (horizontal
))
3837 int window_safe_height
= window_min_size_2 (o
, 0, 0);
3839 if (size_int
< window_safe_height
)
3840 error ("Window height %d too small (after splitting)", size_int
);
3841 if (size_int
+ window_safe_height
> XFASTINT (o
->total_lines
))
3842 error ("Window height %d too small (after splitting)",
3843 XFASTINT (o
->total_lines
) - size_int
);
3844 if (NILP (o
->parent
)
3845 || NILP (XWINDOW (o
->parent
)->vchild
))
3847 make_dummy_parent (window
);
3849 XWINDOW (new)->vchild
= window
;
3854 int window_safe_width
= window_min_size_2 (o
, 1, 0);
3856 if (size_int
< window_safe_width
)
3857 error ("Window width %d too small (after splitting)", size_int
);
3858 if (size_int
+ window_safe_width
> XFASTINT (o
->total_cols
))
3859 error ("Window width %d too small (after splitting)",
3860 XFASTINT (o
->total_cols
) - size_int
);
3861 if (NILP (o
->parent
)
3862 || NILP (XWINDOW (o
->parent
)->hchild
))
3864 make_dummy_parent (window
);
3866 XWINDOW (new)->hchild
= window
;
3870 /* Now we know that window's parent is a vertical combination
3871 if we are dividing vertically, or a horizontal combination
3872 if we are making side-by-side windows */
3874 windows_or_buffers_changed
++;
3875 FRAME_WINDOW_SIZES_CHANGED (fo
) = 1;
3876 new = make_window ();
3879 p
->frame
= o
->frame
;
3881 if (!NILP (p
->next
))
3882 XWINDOW (p
->next
)->prev
= new;
3885 p
->parent
= o
->parent
;
3887 p
->window_end_valid
= Qnil
;
3888 memset (&p
->last_cursor
, 0, sizeof p
->last_cursor
);
3890 /* Duplicate special geometry settings. */
3892 p
->left_margin_cols
= o
->left_margin_cols
;
3893 p
->right_margin_cols
= o
->right_margin_cols
;
3894 p
->left_fringe_width
= o
->left_fringe_width
;
3895 p
->right_fringe_width
= o
->right_fringe_width
;
3896 p
->fringes_outside_margins
= o
->fringes_outside_margins
;
3897 p
->scroll_bar_width
= o
->scroll_bar_width
;
3898 p
->vertical_scroll_bar_type
= o
->vertical_scroll_bar_type
;
3900 /* Apportion the available frame space among the two new windows */
3902 if (!NILP (horizontal
))
3904 p
->total_lines
= o
->total_lines
;
3905 p
->top_line
= o
->top_line
;
3906 XSETFASTINT (p
->total_cols
, XFASTINT (o
->total_cols
) - size_int
);
3907 XSETFASTINT (o
->total_cols
, size_int
);
3908 XSETFASTINT (p
->left_col
, XFASTINT (o
->left_col
) + size_int
);
3909 adjust_window_margins (p
);
3910 adjust_window_margins (o
);
3914 p
->left_col
= o
->left_col
;
3915 p
->total_cols
= o
->total_cols
;
3916 XSETFASTINT (p
->total_lines
, XFASTINT (o
->total_lines
) - size_int
);
3917 XSETFASTINT (o
->total_lines
, size_int
);
3918 XSETFASTINT (p
->top_line
, XFASTINT (o
->top_line
) + size_int
);
3921 /* Adjust glyph matrices. */
3924 Fset_window_buffer (new, o
->buffer
, Qt
);
3928 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
3929 doc
: /* Make selected window SIZE lines taller.
3930 Interactively, if no argument is given, make the selected window one
3931 line taller. If optional argument HORIZONTAL is non-nil, make selected
3932 window wider by SIZE columns. If SIZE is negative, shrink the window by
3933 -SIZE lines or columns. Return nil.
3935 This function can delete windows if they get too small. The size of
3936 fixed size windows is not altered by this function. */)
3937 (Lisp_Object size
, Lisp_Object horizontal
)
3939 CHECK_NUMBER (size
);
3940 enlarge_window (selected_window
, XINT (size
), !NILP (horizontal
));
3942 run_window_configuration_change_hook (SELECTED_FRAME ());
3947 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
3948 doc
: /* Make selected window SIZE lines smaller.
3949 Interactively, if no argument is given, make the selected window one
3950 line smaller. If optional argument HORIZONTAL is non-nil, make the
3951 window narrower by SIZE columns. If SIZE is negative, enlarge selected
3952 window by -SIZE lines or columns. Return nil.
3954 This function can delete windows if they get too small. The size of
3955 fixed size windows is not altered by this function. */)
3956 (Lisp_Object size
, Lisp_Object horizontal
)
3958 CHECK_NUMBER (size
);
3959 enlarge_window (selected_window
, -XINT (size
), !NILP (horizontal
));
3961 run_window_configuration_change_hook (SELECTED_FRAME ());
3967 window_height (Lisp_Object window
)
3969 register struct window
*p
= XWINDOW (window
);
3970 return WINDOW_TOTAL_LINES (p
);
3974 window_width (Lisp_Object window
)
3976 register struct window
*p
= XWINDOW (window
);
3977 return WINDOW_TOTAL_COLS (p
);
3982 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
3984 #define CURSIZE(w) \
3985 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
3988 /* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it
3989 horizontally; zero means do it vertically.
3991 Siblings of the selected window are resized to fulfill the size
3992 request. If they become too small in the process, they may be
3996 enlarge_window (Lisp_Object window
, int delta
, int horiz_flag
)
3998 Lisp_Object parent
, next
, prev
;
4002 int (*sizefun
) (Lisp_Object
)
4003 = horiz_flag
? window_width
: window_height
;
4004 void (*setsizefun
) (Lisp_Object
, int, int)
4005 = (horiz_flag
? set_window_width
: set_window_height
);
4007 /* Give up if this window cannot be resized. */
4008 if (window_fixed_size_p (XWINDOW (window
), horiz_flag
, 1))
4009 error ("Window is not resizable");
4011 /* Find the parent of the selected window. */
4014 p
= XWINDOW (window
);
4020 error ("No other window to side of this one");
4025 ? !NILP (XWINDOW (parent
)->hchild
)
4026 : !NILP (XWINDOW (parent
)->vchild
))
4032 sizep
= &CURSIZE (window
);
4035 register int maxdelta
;
4037 /* Compute the maximum size increment this window can have. */
4039 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - XINT (*sizep
)
4040 /* This is a main window followed by a minibuffer. */
4041 : !NILP (p
->next
) ? ((*sizefun
) (p
->next
)
4042 - window_min_size (XWINDOW (p
->next
),
4043 horiz_flag
, 0, 0, 0))
4044 /* This is a minibuffer following a main window. */
4045 : !NILP (p
->prev
) ? ((*sizefun
) (p
->prev
)
4046 - window_min_size (XWINDOW (p
->prev
),
4047 horiz_flag
, 0, 0, 0))
4048 /* This is a frame with only one window, a minibuffer-only
4049 or a minibufferless frame. */
4052 if (delta
> maxdelta
)
4053 /* This case traps trying to make the minibuffer
4054 the full frame, or make the only window aside from the
4055 minibuffer the full frame. */
4059 if (XINT (*sizep
) + delta
< window_min_size (XWINDOW (window
),
4060 horiz_flag
, 0, 0, 0))
4062 delete_window (window
);
4069 /* Find the total we can get from other siblings without deleting them. */
4071 for (next
= p
->next
; WINDOWP (next
); next
= XWINDOW (next
)->next
)
4072 maximum
+= (*sizefun
) (next
) - window_min_size (XWINDOW (next
),
4073 horiz_flag
, 0, 0, 0);
4074 for (prev
= p
->prev
; WINDOWP (prev
); prev
= XWINDOW (prev
)->prev
)
4075 maximum
+= (*sizefun
) (prev
) - window_min_size (XWINDOW (prev
),
4076 horiz_flag
, 0, 0, 0);
4078 /* If we can get it all from them without deleting them, do so. */
4079 if (delta
<= maximum
)
4081 Lisp_Object first_unaffected
;
4082 Lisp_Object first_affected
;
4087 first_affected
= window
;
4088 /* Look at one sibling at a time,
4089 moving away from this window in both directions alternately,
4090 and take as much as we can get without deleting that sibling. */
4092 && (!NILP (next
) || !NILP (prev
)))
4096 int this_one
= ((*sizefun
) (next
)
4097 - window_min_size (XWINDOW (next
), horiz_flag
,
4101 if (this_one
> delta
)
4104 (*setsizefun
) (next
, (*sizefun
) (next
) - this_one
, 0);
4105 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
4110 next
= XWINDOW (next
)->next
;
4118 int this_one
= ((*sizefun
) (prev
)
4119 - window_min_size (XWINDOW (prev
), horiz_flag
,
4123 if (this_one
> delta
)
4126 first_affected
= prev
;
4128 (*setsizefun
) (prev
, (*sizefun
) (prev
) - this_one
, 0);
4129 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
4134 prev
= XWINDOW (prev
)->prev
;
4138 xassert (delta
== 0);
4140 /* Now recalculate the edge positions of all the windows affected,
4141 based on the new sizes. */
4142 first_unaffected
= next
;
4143 prev
= first_affected
;
4144 for (next
= XWINDOW (prev
)->next
; ! EQ (next
, first_unaffected
);
4145 prev
= next
, next
= XWINDOW (next
)->next
)
4147 XSETINT (CURBEG (next
), XINT (CURBEG (prev
)) + (*sizefun
) (prev
));
4148 /* This does not change size of NEXT,
4149 but it propagates the new top edge to its children */
4150 (*setsizefun
) (next
, (*sizefun
) (next
), 0);
4155 register int delta1
;
4156 register int opht
= (*sizefun
) (parent
);
4158 if (opht
<= XINT (*sizep
) + delta
)
4160 /* If trying to grow this window to or beyond size of the parent,
4161 just delete all the sibling windows. */
4162 Lisp_Object start
, tem
, next
;
4164 start
= XWINDOW (parent
)->vchild
;
4166 start
= XWINDOW (parent
)->hchild
;
4168 /* Delete any siblings that come after WINDOW. */
4169 tem
= XWINDOW (window
)->next
;
4170 while (! NILP (tem
))
4172 next
= XWINDOW (tem
)->next
;
4173 delete_window (tem
);
4177 /* Delete any siblings that come after WINDOW.
4178 Note that if START is not WINDOW, then WINDOW still
4179 has siblings, so WINDOW has not yet replaced its parent. */
4181 while (! EQ (tem
, window
))
4183 next
= XWINDOW (tem
)->next
;
4184 delete_window (tem
);
4190 /* Otherwise, make delta1 just right so that if we add
4191 delta1 lines to this window and to the parent, and then
4192 shrink the parent back to its original size, the new
4193 proportional size of this window will increase by delta.
4195 The function size_window will compute the new height h'
4196 of the window from delta1 as:
4199 x = delta1 - delta1/n * n for the 1st resizable child
4202 where n is the number of children that can be resized.
4203 We can ignore x by choosing a delta1 that is a multiple of
4204 n. We want the height of this window to come out as
4214 The number of children n equals the number of resizable
4215 children of this window + 1 because we know window itself
4216 is resizable (otherwise we would have signaled an error).
4218 This reasoning is not correct when other windows become too
4219 small and shrink_windows refuses to delete them. Below we
4220 use resize_proportionally to work around this problem. */
4222 struct window
*w
= XWINDOW (window
);
4226 for (s
= w
->next
; WINDOWP (s
); s
= XWINDOW (s
)->next
)
4227 if (!window_fixed_size_p (XWINDOW (s
), horiz_flag
, 0))
4229 for (s
= w
->prev
; WINDOWP (s
); s
= XWINDOW (s
)->prev
)
4230 if (!window_fixed_size_p (XWINDOW (s
), horiz_flag
, 0))
4235 /* Add delta1 lines or columns to this window, and to the parent,
4236 keeping things consistent while not affecting siblings. */
4237 XSETINT (CURSIZE (parent
), opht
+ delta1
);
4238 (*setsizefun
) (window
, XINT (*sizep
) + delta1
, 0);
4240 /* Squeeze out delta1 lines or columns from our parent,
4241 shrinking this window and siblings proportionately. This
4242 brings parent back to correct size. Delta1 was calculated
4243 so this makes this window the desired size, taking it all
4244 out of the siblings.
4246 Temporarily set resize_proportionally to Qt to assure that,
4247 if necessary, shrink_windows deletes smaller windows rather
4248 than shrink this window. */
4249 w
->resize_proportionally
= Qt
;
4250 (*setsizefun
) (parent
, opht
, 0);
4251 w
->resize_proportionally
= Qnil
;
4255 XSETFASTINT (p
->last_modified
, 0);
4256 XSETFASTINT (p
->last_overlay_modified
, 0);
4258 /* Adjust glyph matrices. */
4259 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4263 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4264 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4265 zero means adjust the height, moving the bottom edge.
4267 Following siblings of the selected window are resized to fulfill
4268 the size request. If they become too small in the process, they
4269 are not deleted; instead, we signal an error. */
4272 adjust_window_trailing_edge (Lisp_Object window
, int delta
, int horiz_flag
)
4274 Lisp_Object parent
, child
;
4276 Lisp_Object old_config
= Fcurrent_window_configuration (Qnil
);
4277 int delcount
= window_deletion_count
;
4279 CHECK_WINDOW (window
);
4281 /* Give up if this window cannot be resized. */
4282 if (window_fixed_size_p (XWINDOW (window
), horiz_flag
, 1))
4283 error ("Window is not resizable");
4287 Lisp_Object first_parallel
= Qnil
;
4291 /* This happens if WINDOW on the previous iteration was
4292 at top level of the window tree. */
4293 Fset_window_configuration (old_config
);
4294 error ("Specified window edge is fixed");
4297 p
= XWINDOW (window
);
4300 /* See if this level has windows in parallel in the specified
4301 direction. If so, set FIRST_PARALLEL to the first one. */
4304 if (! NILP (parent
) && !NILP (XWINDOW (parent
)->vchild
))
4305 first_parallel
= XWINDOW (parent
)->vchild
;
4306 else if (NILP (parent
) && !NILP (p
->next
))
4308 /* Handle the vertical chain of main window and minibuffer
4309 which has no parent. */
4310 first_parallel
= window
;
4311 while (! NILP (XWINDOW (first_parallel
)->prev
))
4312 first_parallel
= XWINDOW (first_parallel
)->prev
;
4317 if (! NILP (parent
) && !NILP (XWINDOW (parent
)->hchild
))
4318 first_parallel
= XWINDOW (parent
)->hchild
;
4321 /* If this level's succession is in the desired dimension,
4322 and this window is the last one, and there is no higher level,
4323 its trailing edge is fixed. */
4324 if (NILP (XWINDOW (window
)->next
) && NILP (first_parallel
)
4327 Fset_window_configuration (old_config
);
4328 error ("Specified window edge is fixed");
4331 /* Don't make this window too small. */
4332 if (XINT (CURSIZE (window
)) + delta
4333 < window_min_size_2 (XWINDOW (window
), horiz_flag
, 0))
4335 Fset_window_configuration (old_config
);
4336 error ("Cannot adjust window size as specified");
4339 /* Clear out some redisplay caches. */
4340 XSETFASTINT (p
->last_modified
, 0);
4341 XSETFASTINT (p
->last_overlay_modified
, 0);
4343 /* Adjust this window's edge. */
4344 XSETINT (CURSIZE (window
),
4345 XINT (CURSIZE (window
)) + delta
);
4347 /* If this window has following siblings in the desired dimension,
4348 make them smaller, and exit the loop.
4350 (If we reach the top of the tree and can never do this,
4351 we will fail and report an error, above.) */
4352 if (NILP (first_parallel
))
4354 if (!NILP (p
->next
))
4356 /* This may happen for the minibuffer. In that case
4357 the window_deletion_count check below does not work. */
4358 if (XINT (CURSIZE (p
->next
)) - delta
<= 0)
4360 Fset_window_configuration (old_config
);
4361 error ("Cannot adjust window size as specified");
4364 XSETINT (CURBEG (p
->next
),
4365 XINT (CURBEG (p
->next
)) + delta
);
4366 size_window (p
->next
, XINT (CURSIZE (p
->next
)) - delta
,
4367 horiz_flag
, 0, 1, 0);
4372 /* Here we have a chain of parallel siblings, in the other dimension.
4373 Change the size of the other siblings. */
4374 for (child
= first_parallel
;
4376 child
= XWINDOW (child
)->next
)
4377 if (! EQ (child
, window
))
4378 size_window (child
, XINT (CURSIZE (child
)) + delta
,
4379 horiz_flag
, 0, 0, 1);
4384 /* If we made a window so small it got deleted,
4385 we failed. Report failure. */
4386 if (delcount
!= window_deletion_count
)
4388 Fset_window_configuration (old_config
);
4389 error ("Cannot adjust window size as specified");
4392 /* Adjust glyph matrices. */
4393 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4399 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge
,
4400 Sadjust_window_trailing_edge
, 3, 3, 0,
4401 doc
: /* Adjust the bottom or right edge of WINDOW by DELTA.
4402 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4403 Otherwise, adjust the height, moving the bottom edge.
4405 Following siblings of the selected window are resized to fulfill
4406 the size request. If they become too small in the process, they
4407 are not deleted; instead, we signal an error. */)
4408 (Lisp_Object window
, Lisp_Object delta
, Lisp_Object horizontal
)
4410 CHECK_NUMBER (delta
);
4412 window
= selected_window
;
4413 adjust_window_trailing_edge (window
, XINT (delta
), !NILP (horizontal
));
4415 run_window_configuration_change_hook
4416 (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4423 /***********************************************************************
4424 Resizing Mini-Windows
4425 ***********************************************************************/
4427 static void shrink_window_lowest_first (struct window
*, int);
4429 enum save_restore_action
4436 static int save_restore_orig_size (struct window
*,
4437 enum save_restore_action
);
4439 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4440 from lowest windows first. */
4443 shrink_window_lowest_first (struct window
*w
, int height
)
4449 xassert (!MINI_WINDOW_P (w
));
4451 /* Set redisplay hints. */
4452 XSETFASTINT (w
->last_modified
, 0);
4453 XSETFASTINT (w
->last_overlay_modified
, 0);
4454 windows_or_buffers_changed
++;
4455 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w
))) = 1;
4457 old_height
= XFASTINT (w
->total_lines
);
4458 XSETFASTINT (w
->total_lines
, height
);
4460 if (!NILP (w
->hchild
))
4462 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
4464 c
= XWINDOW (child
);
4465 c
->top_line
= w
->top_line
;
4466 shrink_window_lowest_first (c
, height
);
4469 else if (!NILP (w
->vchild
))
4471 Lisp_Object last_child
;
4472 int delta
= old_height
- height
;
4477 /* Find the last child. We are taking space from lowest windows
4478 first, so we iterate over children from the last child
4480 for (child
= w
->vchild
; WINDOWP (child
); child
= XWINDOW (child
)->next
)
4483 /* Size children down to their safe heights. */
4484 for (child
= last_child
; delta
&& !NILP (child
); child
= c
->prev
)
4488 c
= XWINDOW (child
);
4489 this_one
= XFASTINT (c
->total_lines
) - window_min_size_1 (c
, 0, 1);
4491 if (this_one
> delta
)
4494 shrink_window_lowest_first (c
, XFASTINT (c
->total_lines
) - this_one
);
4498 /* Compute new positions. */
4499 last_top
= XINT (w
->top_line
);
4500 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
4502 c
= XWINDOW (child
);
4503 c
->top_line
= make_number (last_top
);
4504 shrink_window_lowest_first (c
, XFASTINT (c
->total_lines
));
4505 last_top
+= XFASTINT (c
->total_lines
);
4511 /* Save, restore, or check positions and sizes in the window tree
4512 rooted at W. ACTION says what to do.
4514 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4515 orig_total_lines members are valid for all windows in the window
4516 tree. Value is non-zero if they are valid.
4518 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4519 orig_top_line and orig_total_lines for all windows in the tree.
4521 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4522 stored in orig_top_line and orig_total_lines for all windows. */
4525 save_restore_orig_size (struct window
*w
, enum save_restore_action action
)
4531 if (!NILP (w
->hchild
))
4533 if (!save_restore_orig_size (XWINDOW (w
->hchild
), action
))
4536 else if (!NILP (w
->vchild
))
4538 if (!save_restore_orig_size (XWINDOW (w
->vchild
), action
))
4544 case CHECK_ORIG_SIZES
:
4545 if (!INTEGERP (w
->orig_top_line
) || !INTEGERP (w
->orig_total_lines
))
4549 case SAVE_ORIG_SIZES
:
4550 w
->orig_top_line
= w
->top_line
;
4551 w
->orig_total_lines
= w
->total_lines
;
4552 XSETFASTINT (w
->last_modified
, 0);
4553 XSETFASTINT (w
->last_overlay_modified
, 0);
4556 case RESTORE_ORIG_SIZES
:
4557 xassert (INTEGERP (w
->orig_top_line
) && INTEGERP (w
->orig_total_lines
));
4558 w
->top_line
= w
->orig_top_line
;
4559 w
->total_lines
= w
->orig_total_lines
;
4560 w
->orig_total_lines
= w
->orig_top_line
= Qnil
;
4561 XSETFASTINT (w
->last_modified
, 0);
4562 XSETFASTINT (w
->last_overlay_modified
, 0);
4569 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
4576 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4577 without deleting other windows. */
4580 grow_mini_window (struct window
*w
, int delta
)
4582 struct frame
*f
= XFRAME (w
->frame
);
4583 struct window
*root
;
4585 xassert (MINI_WINDOW_P (w
));
4586 /* Commenting out the following assertion goes against the stated interface
4587 of the function, but it currently does not seem to do anything useful.
4588 See discussion of this issue in the thread for bug#4534.
4589 xassert (delta >= 0); */
4591 /* Compute how much we can enlarge the mini-window without deleting
4593 root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4596 int min_height
= window_min_size (root
, 0, 0, 0, 0);
4597 if (XFASTINT (root
->total_lines
) - delta
< min_height
)
4598 /* Note that the root window may already be smaller than
4600 delta
= max (0, XFASTINT (root
->total_lines
) - min_height
);
4605 /* Save original window sizes and positions, if not already done. */
4606 if (!save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
4607 save_restore_orig_size (root
, SAVE_ORIG_SIZES
);
4609 /* Shrink other windows. */
4610 shrink_window_lowest_first (root
, XFASTINT (root
->total_lines
) - delta
);
4612 /* Grow the mini-window. */
4613 w
->top_line
= make_number (XFASTINT (root
->top_line
) + XFASTINT (root
->total_lines
));
4614 w
->total_lines
= make_number (XFASTINT (w
->total_lines
) + delta
);
4615 XSETFASTINT (w
->last_modified
, 0);
4616 XSETFASTINT (w
->last_overlay_modified
, 0);
4623 /* Shrink mini-window W. If there is recorded info about window sizes
4624 before a call to grow_mini_window, restore recorded window sizes.
4625 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4629 shrink_mini_window (struct window
*w
)
4631 struct frame
*f
= XFRAME (w
->frame
);
4632 struct window
*root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4634 if (save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
4636 save_restore_orig_size (root
, RESTORE_ORIG_SIZES
);
4638 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
4639 windows_or_buffers_changed
= 1;
4641 else if (XFASTINT (w
->total_lines
) > 1)
4643 /* Distribute the additional lines of the mini-window
4644 among the other windows. */
4646 XSETWINDOW (window
, w
);
4647 enlarge_window (window
, 1 - XFASTINT (w
->total_lines
), 0);
4653 /* Mark window cursors off for all windows in the window tree rooted
4654 at W by setting their phys_cursor_on_p flag to zero. Called from
4655 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4656 the frame are cleared. */
4659 mark_window_cursors_off (struct window
*w
)
4663 if (!NILP (w
->hchild
))
4664 mark_window_cursors_off (XWINDOW (w
->hchild
));
4665 else if (!NILP (w
->vchild
))
4666 mark_window_cursors_off (XWINDOW (w
->vchild
));
4668 w
->phys_cursor_on_p
= 0;
4670 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
4675 /* Return number of lines of text (not counting mode lines) in W. */
4678 window_internal_height (struct window
*w
)
4680 int ht
= XFASTINT (w
->total_lines
);
4682 if (!MINI_WINDOW_P (w
))
4684 if (!NILP (w
->parent
)
4685 || !NILP (w
->vchild
)
4686 || !NILP (w
->hchild
)
4689 || WINDOW_WANTS_MODELINE_P (w
))
4692 if (WINDOW_WANTS_HEADER_LINE_P (w
))
4700 /* Return the number of columns in W.
4701 Don't count columns occupied by scroll bars or the vertical bar
4702 separating W from the sibling to its right. */
4705 window_box_text_cols (struct window
*w
)
4707 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4708 int width
= XINT (w
->total_cols
);
4710 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w
))
4711 /* Scroll bars occupy a few columns. */
4712 width
-= WINDOW_CONFIG_SCROLL_BAR_COLS (w
);
4713 else if (!FRAME_WINDOW_P (f
)
4714 && !WINDOW_RIGHTMOST_P (w
) && !WINDOW_FULL_WIDTH_P (w
))
4715 /* The column of `|' characters separating side-by-side windows
4716 occupies one column only. */
4719 if (FRAME_WINDOW_P (f
))
4720 /* On window-systems, fringes and display margins cannot be
4721 used for normal text. */
4722 width
-= (WINDOW_FRINGE_COLS (w
)
4723 + WINDOW_LEFT_MARGIN_COLS (w
)
4724 + WINDOW_RIGHT_MARGIN_COLS (w
));
4730 /************************************************************************
4732 ***********************************************************************/
4734 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4735 N screen-fulls, which is defined as the height of the window minus
4736 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4737 instead. Negative values of N mean scroll down. NOERROR non-zero
4738 means don't signal an error if we try to move over BEGV or ZV,
4742 window_scroll (Lisp_Object window
, int n
, int whole
, int noerror
)
4746 /* If we must, use the pixel-based version which is much slower than
4747 the line-based one but can handle varying line heights. */
4748 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window
)->frame
)))
4749 window_scroll_pixel_based (window
, n
, whole
, noerror
);
4751 window_scroll_line_based (window
, n
, whole
, noerror
);
4757 /* Implementation of window_scroll that works based on pixel line
4758 heights. See the comment of window_scroll for parameter
4762 window_scroll_pixel_based (Lisp_Object window
, int n
, int whole
, int noerror
)
4765 struct window
*w
= XWINDOW (window
);
4766 struct text_pos start
;
4767 int this_scroll_margin
;
4768 /* True if we fiddled the window vscroll field without really scrolling. */
4770 int x
, y
, rtop
, rbot
, rowh
, vpos
;
4772 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
4774 /* If PT is not visible in WINDOW, move back one half of
4775 the screen. Allow PT to be partially visible, otherwise
4776 something like (scroll-down 1) with PT in the line before
4777 the partially visible one would recenter. */
4779 if (!pos_visible_p (w
, PT
, &x
, &y
, &rtop
, &rbot
, &rowh
, &vpos
))
4781 /* Move backward half the height of the window. Performance note:
4782 vmotion used here is about 10% faster, but would give wrong
4783 results for variable height lines. */
4784 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4785 it
.current_y
= it
.last_visible_y
;
4786 move_it_vertically_backward (&it
, window_box_height (w
) / 2);
4788 /* The function move_iterator_vertically may move over more than
4789 the specified y-distance. If it->w is small, e.g. a
4790 mini-buffer window, we may end up in front of the window's
4791 display area. This is the case when Start displaying at the
4792 start of the line containing PT in this case. */
4793 if (it
.current_y
<= 0)
4795 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4796 move_it_vertically_backward (&it
, 0);
4800 start
= it
.current
.pos
;
4802 else if (auto_window_vscroll_p
)
4804 if (rtop
|| rbot
) /* partially visible */
4807 int dy
= WINDOW_FRAME_LINE_HEIGHT (w
);
4809 dy
= max ((window_box_height (w
)
4810 - next_screen_context_lines
* dy
),
4816 /* Only vscroll backwards if already vscrolled forwards. */
4817 if (w
->vscroll
< 0 && rtop
> 0)
4819 px
= max (0, -w
->vscroll
- min (rtop
, -dy
));
4820 Fset_window_vscroll (window
, make_number (px
), Qt
);
4826 /* Do vscroll if already vscrolled or only display line. */
4827 if (rbot
> 0 && (w
->vscroll
< 0 || vpos
== 0))
4829 px
= max (0, -w
->vscroll
+ min (rbot
, dy
));
4830 Fset_window_vscroll (window
, make_number (px
), Qt
);
4834 /* Maybe modify window start instead of scrolling. */
4835 if (rbot
> 0 || w
->vscroll
< 0)
4839 Fset_window_vscroll (window
, make_number (0), Qt
);
4840 /* If there are other text lines above the current row,
4841 move window start to current row. Else to next row. */
4843 spos
= XINT (Fline_beginning_position (Qnil
));
4845 spos
= min (XINT (Fline_end_position (Qnil
)) + 1, ZV
);
4846 set_marker_restricted (w
->start
, make_number (spos
),
4848 w
->start_at_line_beg
= Qt
;
4849 w
->update_mode_line
= Qt
;
4850 XSETFASTINT (w
->last_modified
, 0);
4851 XSETFASTINT (w
->last_overlay_modified
, 0);
4852 /* Set force_start so that redisplay_window will run the
4853 window-scroll-functions. */
4854 w
->force_start
= Qt
;
4859 /* Cancel previous vscroll. */
4860 Fset_window_vscroll (window
, make_number (0), Qt
);
4863 /* If scroll_preserve_screen_position is non-nil, we try to set
4864 point in the same window line as it is now, so get that line. */
4865 if (!NILP (Vscroll_preserve_screen_position
))
4867 /* We preserve the goal pixel coordinate across consecutive
4868 calls to scroll-up, scroll-down and other commands that
4869 have the `scroll-command' property. This avoids the
4870 possibility of point becoming "stuck" on a tall line when
4871 scrolling by one line. */
4872 if (window_scroll_pixel_based_preserve_y
< 0
4873 || !SYMBOLP (current_kboard
->Vlast_command
)
4874 || NILP (Fget (current_kboard
->Vlast_command
, Qscroll_command
)))
4876 start_display (&it
, w
, start
);
4877 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
4878 window_scroll_pixel_based_preserve_y
= it
.current_y
;
4879 window_scroll_pixel_based_preserve_x
= it
.current_x
;
4883 window_scroll_pixel_based_preserve_y
4884 = window_scroll_pixel_based_preserve_x
= -1;
4886 /* Move iterator it from start the specified distance forward or
4887 backward. The result is the new window start. */
4888 start_display (&it
, w
, start
);
4891 EMACS_INT start_pos
= IT_CHARPOS (it
);
4892 int dy
= WINDOW_FRAME_LINE_HEIGHT (w
);
4893 dy
= max ((window_box_height (w
)
4894 - next_screen_context_lines
* dy
),
4897 /* Note that move_it_vertically always moves the iterator to the
4898 start of a line. So, if the last line doesn't have a newline,
4899 we would end up at the start of the line ending at ZV. */
4902 move_it_vertically_backward (&it
, -dy
);
4903 /* Ensure we actually do move, e.g. in case we are currently
4904 looking at an image that is taller that the window height. */
4905 while (start_pos
== IT_CHARPOS (it
)
4906 && start_pos
> BEGV
)
4907 move_it_by_lines (&it
, -1, 1);
4911 move_it_to (&it
, ZV
, -1, it
.current_y
+ dy
, -1,
4912 MOVE_TO_POS
| MOVE_TO_Y
);
4913 /* Ensure we actually do move, e.g. in case we are currently
4914 looking at an image that is taller that the window height. */
4915 while (start_pos
== IT_CHARPOS (it
)
4917 move_it_by_lines (&it
, 1, 1);
4921 move_it_by_lines (&it
, n
, 1);
4923 /* We failed if we find ZV is already on the screen (scrolling up,
4924 means there's nothing past the end), or if we can't start any
4925 earlier (scrolling down, means there's nothing past the top). */
4926 if ((n
> 0 && IT_CHARPOS (it
) == ZV
)
4927 || (n
< 0 && IT_CHARPOS (it
) == CHARPOS (start
)))
4929 if (IT_CHARPOS (it
) == ZV
)
4931 if (it
.current_y
< it
.last_visible_y
4932 && (it
.current_y
+ it
.max_ascent
+ it
.max_descent
4933 > it
.last_visible_y
))
4935 /* The last line was only partially visible, make it fully
4937 w
->vscroll
= (it
.last_visible_y
4938 - it
.current_y
+ it
.max_ascent
+ it
.max_descent
);
4939 adjust_glyphs (it
.f
);
4943 else if (n
< 0) /* could happen with empty buffers */
4944 xsignal0 (Qbeginning_of_buffer
);
4946 xsignal0 (Qend_of_buffer
);
4950 if (w
->vscroll
!= 0)
4951 /* The first line was only partially visible, make it fully
4957 xsignal0 (Qbeginning_of_buffer
);
4960 /* If control gets here, then we vscrolled. */
4962 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
4964 /* Don't try to change the window start below. */
4970 EMACS_INT pos
= IT_CHARPOS (it
);
4973 /* If in the middle of a multi-glyph character move forward to
4974 the next character. */
4975 if (in_display_vector_p (&it
))
4978 move_it_to (&it
, pos
, -1, -1, -1, MOVE_TO_POS
);
4981 /* Set the window start, and set up the window for redisplay. */
4982 set_marker_restricted (w
->start
, make_number (pos
),
4984 bytepos
= XMARKER (w
->start
)->bytepos
;
4985 w
->start_at_line_beg
= ((pos
== BEGV
|| FETCH_BYTE (bytepos
- 1) == '\n')
4987 w
->update_mode_line
= Qt
;
4988 XSETFASTINT (w
->last_modified
, 0);
4989 XSETFASTINT (w
->last_overlay_modified
, 0);
4990 /* Set force_start so that redisplay_window will run the
4991 window-scroll-functions. */
4992 w
->force_start
= Qt
;
4995 /* The rest of this function uses current_y in a nonstandard way,
4996 not including the height of the header line if any. */
4997 it
.current_y
= it
.vpos
= 0;
4999 /* Move PT out of scroll margins.
5000 This code wants current_y to be zero at the window start position
5001 even if there is a header line. */
5002 this_scroll_margin
= max (0, scroll_margin
);
5003 this_scroll_margin
= min (this_scroll_margin
, XFASTINT (w
->total_lines
) / 4);
5004 this_scroll_margin
*= FRAME_LINE_HEIGHT (it
.f
);
5008 /* We moved the window start towards ZV, so PT may be now
5009 in the scroll margin at the top. */
5010 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
5011 if (IT_CHARPOS (it
) == PT
&& it
.current_y
>= this_scroll_margin
5012 && (NILP (Vscroll_preserve_screen_position
)
5013 || EQ (Vscroll_preserve_screen_position
, Qt
)))
5014 /* We found PT at a legitimate height. Leave it alone. */
5016 else if (window_scroll_pixel_based_preserve_y
>= 0)
5018 /* If we have a header line, take account of it.
5019 This is necessary because we set it.current_y to 0, above. */
5020 move_it_to (&it
, -1,
5021 window_scroll_pixel_based_preserve_x
,
5022 window_scroll_pixel_based_preserve_y
5023 - (WINDOW_WANTS_HEADER_LINE_P (w
) ? 1 : 0 ),
5024 -1, MOVE_TO_Y
| MOVE_TO_X
);
5025 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5029 while (it
.current_y
< this_scroll_margin
)
5031 int prev
= it
.current_y
;
5032 move_it_by_lines (&it
, 1, 1);
5033 if (prev
== it
.current_y
)
5036 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5041 EMACS_INT charpos
, bytepos
;
5044 /* Save our position, for the
5045 window_scroll_pixel_based_preserve_y case. */
5046 charpos
= IT_CHARPOS (it
);
5047 bytepos
= IT_BYTEPOS (it
);
5049 /* We moved the window start towards BEGV, so PT may be now
5050 in the scroll margin at the bottom. */
5051 move_it_to (&it
, PT
, -1,
5052 (it
.last_visible_y
- CURRENT_HEADER_LINE_HEIGHT (w
)
5053 - this_scroll_margin
- 1),
5055 MOVE_TO_POS
| MOVE_TO_Y
);
5057 /* Save our position, in case it's correct. */
5058 charpos
= IT_CHARPOS (it
);
5059 bytepos
= IT_BYTEPOS (it
);
5061 /* See if point is on a partially visible line at the end. */
5062 if (it
.what
== IT_EOB
)
5063 partial_p
= it
.current_y
+ it
.ascent
+ it
.descent
> it
.last_visible_y
;
5066 move_it_by_lines (&it
, 1, 1);
5067 partial_p
= it
.current_y
> it
.last_visible_y
;
5070 if (charpos
== PT
&& !partial_p
5071 && (NILP (Vscroll_preserve_screen_position
)
5072 || EQ (Vscroll_preserve_screen_position
, Qt
)))
5073 /* We found PT before we found the display margin, so PT is ok. */
5075 else if (window_scroll_pixel_based_preserve_y
>= 0)
5077 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
5078 start_display (&it
, w
, start
);
5079 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5080 here because we called start_display again and did not
5081 alter it.current_y this time. */
5082 move_it_to (&it
, -1, window_scroll_pixel_based_preserve_x
,
5083 window_scroll_pixel_based_preserve_y
, -1,
5084 MOVE_TO_Y
| MOVE_TO_X
);
5085 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5090 /* The last line was only partially visible, so back up two
5091 lines to make sure we're on a fully visible line. */
5093 move_it_by_lines (&it
, -2, 0);
5094 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5097 /* No, the position we saved is OK, so use it. */
5098 SET_PT_BOTH (charpos
, bytepos
);
5104 /* Implementation of window_scroll that works based on screen lines.
5105 See the comment of window_scroll for parameter descriptions. */
5108 window_scroll_line_based (Lisp_Object window
, int n
, int whole
, int noerror
)
5110 register struct window
*w
= XWINDOW (window
);
5111 register EMACS_INT opoint
= PT
, opoint_byte
= PT_BYTE
;
5112 register EMACS_INT pos
, pos_byte
;
5113 register int ht
= window_internal_height (w
);
5114 register Lisp_Object tem
;
5118 Lisp_Object original_pos
= Qnil
;
5120 /* If scrolling screen-fulls, compute the number of lines to
5121 scroll from the window's height. */
5123 n
*= max (1, ht
- next_screen_context_lines
);
5125 startpos
= marker_position (w
->start
);
5127 if (!NILP (Vscroll_preserve_screen_position
))
5129 if (window_scroll_preserve_vpos
<= 0
5130 || !SYMBOLP (current_kboard
->Vlast_command
)
5131 || NILP (Fget (current_kboard
->Vlast_command
, Qscroll_command
)))
5133 struct position posit
5134 = *compute_motion (startpos
, 0, 0, 0,
5136 -1, XINT (w
->hscroll
),
5138 window_scroll_preserve_vpos
= posit
.vpos
;
5139 window_scroll_preserve_hpos
= posit
.hpos
+ XINT (w
->hscroll
);
5142 original_pos
= Fcons (make_number (window_scroll_preserve_hpos
),
5143 make_number (window_scroll_preserve_vpos
));
5146 XSETFASTINT (tem
, PT
);
5147 tem
= Fpos_visible_in_window_p (tem
, window
, Qnil
);
5151 Fvertical_motion (make_number (- (ht
/ 2)), window
);
5156 lose
= n
< 0 && PT
== BEGV
;
5157 Fvertical_motion (make_number (n
), window
);
5161 SET_PT_BOTH (opoint
, opoint_byte
);
5168 xsignal0 (Qbeginning_of_buffer
);
5173 int this_scroll_margin
= scroll_margin
;
5175 /* Don't use a scroll margin that is negative or too large. */
5176 if (this_scroll_margin
< 0)
5177 this_scroll_margin
= 0;
5179 if (XINT (w
->total_lines
) < 4 * scroll_margin
)
5180 this_scroll_margin
= XINT (w
->total_lines
) / 4;
5182 set_marker_restricted_both (w
->start
, w
->buffer
, pos
, pos_byte
);
5183 w
->start_at_line_beg
= bolp
;
5184 w
->update_mode_line
= Qt
;
5185 XSETFASTINT (w
->last_modified
, 0);
5186 XSETFASTINT (w
->last_overlay_modified
, 0);
5187 /* Set force_start so that redisplay_window will run
5188 the window-scroll-functions. */
5189 w
->force_start
= Qt
;
5191 if (!NILP (Vscroll_preserve_screen_position
)
5192 && (whole
|| !EQ (Vscroll_preserve_screen_position
, Qt
)))
5194 SET_PT_BOTH (pos
, pos_byte
);
5195 Fvertical_motion (original_pos
, window
);
5197 /* If we scrolled forward, put point enough lines down
5198 that it is outside the scroll margin. */
5203 if (this_scroll_margin
> 0)
5205 SET_PT_BOTH (pos
, pos_byte
);
5206 Fvertical_motion (make_number (this_scroll_margin
), window
);
5212 if (top_margin
<= opoint
)
5213 SET_PT_BOTH (opoint
, opoint_byte
);
5214 else if (!NILP (Vscroll_preserve_screen_position
))
5216 SET_PT_BOTH (pos
, pos_byte
);
5217 Fvertical_motion (original_pos
, window
);
5220 SET_PT (top_margin
);
5226 /* If we scrolled backward, put point near the end of the window
5227 but not within the scroll margin. */
5228 SET_PT_BOTH (pos
, pos_byte
);
5229 tem
= Fvertical_motion (make_number (ht
- this_scroll_margin
), window
);
5230 if (XFASTINT (tem
) == ht
- this_scroll_margin
)
5233 bottom_margin
= PT
+ 1;
5235 if (bottom_margin
> opoint
)
5236 SET_PT_BOTH (opoint
, opoint_byte
);
5239 if (!NILP (Vscroll_preserve_screen_position
))
5241 SET_PT_BOTH (pos
, pos_byte
);
5242 Fvertical_motion (original_pos
, window
);
5245 Fvertical_motion (make_number (-1), window
);
5254 xsignal0 (Qend_of_buffer
);
5259 /* Scroll selected_window up or down. If N is nil, scroll a
5260 screen-full which is defined as the height of the window minus
5261 next_screen_context_lines. If N is the symbol `-', scroll.
5262 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5263 up. This is the guts of Fscroll_up and Fscroll_down. */
5266 scroll_command (Lisp_Object n
, int direction
)
5268 int count
= SPECPDL_INDEX ();
5270 xassert (eabs (direction
) == 1);
5272 /* If selected window's buffer isn't current, make it current for
5273 the moment. But don't screw up if window_scroll gets an error. */
5274 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
5276 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
5277 Fset_buffer (XWINDOW (selected_window
)->buffer
);
5279 /* Make redisplay consider other windows than just selected_window. */
5280 ++windows_or_buffers_changed
;
5284 window_scroll (selected_window
, direction
, 1, 0);
5285 else if (EQ (n
, Qminus
))
5286 window_scroll (selected_window
, -direction
, 1, 0);
5289 n
= Fprefix_numeric_value (n
);
5290 window_scroll (selected_window
, XINT (n
) * direction
, 0, 0);
5293 unbind_to (count
, Qnil
);
5296 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "^P",
5297 doc
: /* Scroll text of selected window upward ARG lines.
5298 If ARG is omitted or nil, scroll upward by a near full screen.
5299 A near full screen is `next-screen-context-lines' less than a full screen.
5300 Negative ARG means scroll downward.
5301 If ARG is the atom `-', scroll downward by nearly full screen.
5302 When calling from a program, supply as argument a number, nil, or `-'. */)
5305 scroll_command (arg
, 1);
5309 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "^P",
5310 doc
: /* Scroll text of selected window down ARG lines.
5311 If ARG is omitted or nil, scroll down by a near full screen.
5312 A near full screen is `next-screen-context-lines' less than a full screen.
5313 Negative ARG means scroll upward.
5314 If ARG is the atom `-', scroll upward by nearly full screen.
5315 When calling from a program, supply as argument a number, nil, or `-'. */)
5318 scroll_command (arg
, -1);
5322 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling
, Sother_window_for_scrolling
, 0, 0, 0,
5323 doc
: /* Return the other window for \"other window scroll\" commands.
5324 If `other-window-scroll-buffer' is non-nil, a window
5325 showing that buffer is used.
5326 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5327 specifies the window. This takes precedence over
5328 `other-window-scroll-buffer'. */)
5333 if (MINI_WINDOW_P (XWINDOW (selected_window
))
5334 && !NILP (Vminibuf_scroll_window
))
5335 window
= Vminibuf_scroll_window
;
5336 /* If buffer is specified, scroll that buffer. */
5337 else if (!NILP (Vother_window_scroll_buffer
))
5339 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
5341 window
= display_buffer (Vother_window_scroll_buffer
, Qt
, Qnil
);
5345 /* Nothing specified; look for a neighboring window on the same
5347 window
= Fnext_window (selected_window
, Qnil
, Qnil
);
5349 if (EQ (window
, selected_window
))
5350 /* That didn't get us anywhere; look for a window on another
5353 window
= Fnext_window (window
, Qnil
, Qt
);
5354 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window
))))
5355 && ! EQ (window
, selected_window
));
5358 CHECK_LIVE_WINDOW (window
);
5360 if (EQ (window
, selected_window
))
5361 error ("There is no other window");
5366 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
5367 doc
: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5368 A near full screen is `next-screen-context-lines' less than a full screen.
5369 The next window is the one below the current one; or the one at the top
5370 if the current one is at the bottom. Negative ARG means scroll downward.
5371 If ARG is the atom `-', scroll downward by nearly full screen.
5372 When calling from a program, supply as argument a number, nil, or `-'.
5374 If `other-window-scroll-buffer' is non-nil, scroll the window
5375 showing that buffer, popping the buffer up if necessary.
5376 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5377 specifies the window to scroll. This takes precedence over
5378 `other-window-scroll-buffer'. */)
5383 int count
= SPECPDL_INDEX ();
5385 window
= Fother_window_for_scrolling ();
5386 w
= XWINDOW (window
);
5388 /* Don't screw up if window_scroll gets an error. */
5389 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
5390 ++windows_or_buffers_changed
;
5392 Fset_buffer (w
->buffer
);
5393 SET_PT (marker_position (w
->pointm
));
5396 window_scroll (window
, 1, 1, 1);
5397 else if (EQ (arg
, Qminus
))
5398 window_scroll (window
, -1, 1, 1);
5404 window_scroll (window
, XINT (arg
), 0, 1);
5407 set_marker_both (w
->pointm
, Qnil
, PT
, PT_BYTE
);
5408 unbind_to (count
, Qnil
);
5413 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 0, 2, "^P\np",
5414 doc
: /* Scroll selected window display ARG columns left.
5415 Default for ARG is window width minus 2.
5416 Value is the total amount of leftward horizontal scrolling in
5417 effect after the change.
5418 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5419 lower bound for automatic scrolling, i.e. automatic scrolling
5420 will not scroll a window to a column less than the value returned
5421 by this function. This happens in an interactive call. */)
5422 (register Lisp_Object arg
, Lisp_Object set_minimum
)
5426 struct window
*w
= XWINDOW (selected_window
);
5429 XSETFASTINT (arg
, window_box_text_cols (w
) - 2);
5431 arg
= Fprefix_numeric_value (arg
);
5433 hscroll
= XINT (w
->hscroll
) + XINT (arg
);
5434 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
5436 if (!NILP (set_minimum
))
5437 w
->min_hscroll
= w
->hscroll
;
5442 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 0, 2, "^P\np",
5443 doc
: /* Scroll selected window display ARG columns right.
5444 Default for ARG is window width minus 2.
5445 Value is the total amount of leftward horizontal scrolling in
5446 effect after the change.
5447 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5448 lower bound for automatic scrolling, i.e. automatic scrolling
5449 will not scroll a window to a column less than the value returned
5450 by this function. This happens in an interactive call. */)
5451 (register Lisp_Object arg
, Lisp_Object set_minimum
)
5455 struct window
*w
= XWINDOW (selected_window
);
5458 XSETFASTINT (arg
, window_box_text_cols (w
) - 2);
5460 arg
= Fprefix_numeric_value (arg
);
5462 hscroll
= XINT (w
->hscroll
) - XINT (arg
);
5463 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
5465 if (!NILP (set_minimum
))
5466 w
->min_hscroll
= w
->hscroll
;
5471 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window
, Sminibuffer_selected_window
, 0, 0, 0,
5472 doc
: /* Return the window which was selected when entering the minibuffer.
5473 Returns nil, if selected window is not a minibuffer window. */)
5476 if (minibuf_level
> 0
5477 && MINI_WINDOW_P (XWINDOW (selected_window
))
5478 && WINDOW_LIVE_P (minibuf_selected_window
))
5479 return minibuf_selected_window
;
5484 /* Value is the number of lines actually displayed in window W,
5485 as opposed to its height. */
5488 displayed_window_lines (struct window
*w
)
5491 struct text_pos start
;
5492 int height
= window_box_height (w
);
5493 struct buffer
*old_buffer
;
5496 if (XBUFFER (w
->buffer
) != current_buffer
)
5498 old_buffer
= current_buffer
;
5499 set_buffer_internal (XBUFFER (w
->buffer
));
5504 /* In case W->start is out of the accessible range, do something
5505 reasonable. This happens in Info mode when Info-scroll-down
5506 calls (recenter -1) while W->start is 1. */
5507 if (XMARKER (w
->start
)->charpos
< BEGV
)
5508 SET_TEXT_POS (start
, BEGV
, BEGV_BYTE
);
5509 else if (XMARKER (w
->start
)->charpos
> ZV
)
5510 SET_TEXT_POS (start
, ZV
, ZV_BYTE
);
5512 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
5514 start_display (&it
, w
, start
);
5515 move_it_vertically (&it
, height
);
5516 bottom_y
= line_bottom_y (&it
);
5518 /* rms: On a non-window display,
5519 the value of it.vpos at the bottom of the screen
5520 seems to be 1 larger than window_box_height (w).
5521 This kludge fixes a bug whereby (move-to-window-line -1)
5522 when ZV is on the last screen line
5523 moves to the previous screen line instead of the last one. */
5524 if (! FRAME_WINDOW_P (XFRAME (w
->frame
)))
5527 /* Add in empty lines at the bottom of the window. */
5528 if (bottom_y
< height
)
5530 int uy
= FRAME_LINE_HEIGHT (it
.f
);
5531 it
.vpos
+= (height
- bottom_y
+ uy
- 1) / uy
;
5535 set_buffer_internal (old_buffer
);
5541 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
5542 doc
: /* Center point in selected window and maybe redisplay frame.
5543 With prefix argument ARG, recenter putting point on screen line ARG
5544 relative to the selected window. If ARG is negative, it counts up from the
5545 bottom of the window. (ARG should be less than the height of the window.)
5547 If ARG is omitted or nil, then recenter with point on the middle line of
5548 the selected window; if the variable `recenter-redisplay' is non-nil,
5549 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5550 is set to `grow-only', this resets the tool-bar's height to the minimum
5551 height needed); if `recenter-redisplay' has the special value `tty',
5552 then only tty frame are redrawn.
5554 Just C-u as prefix means put point in the center of the window
5555 and redisplay normally--don't erase and redraw the frame. */)
5556 (register Lisp_Object arg
)
5558 struct window
*w
= XWINDOW (selected_window
);
5559 struct buffer
*buf
= XBUFFER (w
->buffer
);
5560 struct buffer
*obuf
= current_buffer
;
5562 EMACS_INT charpos
, bytepos
;
5564 int this_scroll_margin
;
5566 /* If redisplay is suppressed due to an error, try again. */
5567 obuf
->display_error_modiff
= 0;
5571 if (!NILP (Vrecenter_redisplay
)
5572 && (!EQ (Vrecenter_redisplay
, Qtty
)
5573 || !NILP (Ftty_type (selected_frame
))))
5577 /* Invalidate pixel data calculated for all compositions. */
5578 for (i
= 0; i
< n_compositions
; i
++)
5579 composition_table
[i
]->font
= NULL
;
5581 WINDOW_XFRAME (w
)->minimize_tool_bar_window_p
= 1;
5583 Fredraw_frame (WINDOW_FRAME (w
));
5584 SET_FRAME_GARBAGED (WINDOW_XFRAME (w
));
5589 else if (CONSP (arg
)) /* Just C-u. */
5593 arg
= Fprefix_numeric_value (arg
);
5598 set_buffer_internal (buf
);
5600 /* Do this after making BUF current
5601 in case scroll_margin is buffer-local. */
5602 this_scroll_margin
= max (0, scroll_margin
);
5603 this_scroll_margin
= min (this_scroll_margin
,
5604 XFASTINT (w
->total_lines
) / 4);
5606 /* Handle centering on a graphical frame specially. Such frames can
5607 have variable-height lines and centering point on the basis of
5608 line counts would lead to strange effects. */
5609 if (FRAME_WINDOW_P (XFRAME (w
->frame
)))
5616 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
5617 start_display (&it
, w
, pt
);
5618 move_it_vertically_backward (&it
, window_box_height (w
) / 2);
5619 charpos
= IT_CHARPOS (it
);
5620 bytepos
= IT_BYTEPOS (it
);
5627 int extra_line_spacing
;
5628 int h
= window_box_height (w
);
5630 iarg
= - max (-iarg
, this_scroll_margin
);
5632 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
5633 start_display (&it
, w
, pt
);
5635 /* Be sure we have the exact height of the full line containing PT. */
5636 move_it_by_lines (&it
, 0, 1);
5638 /* The amount of pixels we have to move back is the window
5639 height minus what's displayed in the line containing PT,
5640 and the lines below. */
5643 move_it_by_lines (&it
, nlines
, 1);
5645 if (it
.vpos
== nlines
)
5649 /* Last line has no newline */
5650 h
-= line_bottom_y (&it
);
5654 /* Don't reserve space for extra line spacing of last line. */
5655 extra_line_spacing
= it
.max_extra_line_spacing
;
5657 /* If we can't move down NLINES lines because we hit
5658 the end of the buffer, count in some empty lines. */
5659 if (it
.vpos
< nlines
)
5662 extra_line_spacing
= it
.extra_line_spacing
;
5663 h
-= nlines
* (FRAME_LINE_HEIGHT (it
.f
) + extra_line_spacing
);
5668 /* Now find the new top line (starting position) of the window. */
5669 start_display (&it
, w
, pt
);
5671 move_it_vertically_backward (&it
, h
);
5673 /* If extra line spacing is present, we may move too far
5674 back. This causes the last line to be only partially
5675 visible (which triggers redisplay to recenter that line
5676 in the middle), so move forward.
5677 But ignore extra line spacing on last line, as it is not
5678 considered to be part of the visible height of the line.
5680 h
+= extra_line_spacing
;
5681 while (-it
.current_y
> h
)
5682 move_it_by_lines (&it
, 1, 1);
5684 charpos
= IT_CHARPOS (it
);
5685 bytepos
= IT_BYTEPOS (it
);
5689 struct position pos
;
5691 iarg
= max (iarg
, this_scroll_margin
);
5693 pos
= *vmotion (PT
, -iarg
, w
);
5694 charpos
= pos
.bufpos
;
5695 bytepos
= pos
.bytepos
;
5700 struct position pos
;
5701 int ht
= window_internal_height (w
);
5708 /* Don't let it get into the margin at either top or bottom. */
5709 iarg
= max (iarg
, this_scroll_margin
);
5710 iarg
= min (iarg
, ht
- this_scroll_margin
- 1);
5712 pos
= *vmotion (PT
, - iarg
, w
);
5713 charpos
= pos
.bufpos
;
5714 bytepos
= pos
.bytepos
;
5717 /* Set the new window start. */
5718 set_marker_both (w
->start
, w
->buffer
, charpos
, bytepos
);
5719 w
->window_end_valid
= Qnil
;
5721 w
->optional_new_start
= Qt
;
5723 if (bytepos
== BEGV_BYTE
|| FETCH_BYTE (bytepos
- 1) == '\n')
5724 w
->start_at_line_beg
= Qt
;
5726 w
->start_at_line_beg
= Qnil
;
5728 set_buffer_internal (obuf
);
5733 DEFUN ("window-text-height", Fwindow_text_height
, Swindow_text_height
,
5735 doc
: /* Return the height in lines of the text display area of WINDOW.
5736 WINDOW defaults to the selected window.
5738 The return value does not include the mode line, any header line, nor
5739 any partial-height lines in the text display area. */)
5740 (Lisp_Object window
)
5742 struct window
*w
= decode_window (window
);
5743 int pixel_height
= window_box_height (w
);
5744 int line_height
= pixel_height
/ FRAME_LINE_HEIGHT (XFRAME (w
->frame
));
5745 return make_number (line_height
);
5750 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
5752 doc
: /* Position point relative to window.
5753 With no argument, position point at center of window.
5754 An argument specifies vertical position within the window;
5755 zero means top of window, negative means relative to bottom of window. */)
5758 struct window
*w
= XWINDOW (selected_window
);
5762 int this_scroll_margin
;
5765 if (!(BUFFERP (w
->buffer
)
5766 && XBUFFER (w
->buffer
) == current_buffer
))
5767 /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
5768 when passed below to set_marker_both. */
5769 error ("move-to-window-line called from unrelated buffer");
5771 window
= selected_window
;
5772 start
= marker_position (w
->start
);
5773 if (start
< BEGV
|| start
> ZV
)
5775 int height
= window_internal_height (w
);
5776 Fvertical_motion (make_number (- (height
/ 2)), window
);
5777 set_marker_both (w
->start
, w
->buffer
, PT
, PT_BYTE
);
5778 w
->start_at_line_beg
= Fbolp ();
5779 w
->force_start
= Qt
;
5782 Fgoto_char (w
->start
);
5784 lines
= displayed_window_lines (w
);
5787 this_scroll_margin
= max (0, scroll_margin
);
5788 this_scroll_margin
= min (this_scroll_margin
, lines
/ 4);
5792 XSETFASTINT (arg
, lines
/ 2);
5795 int iarg
= XINT (Fprefix_numeric_value (arg
));
5798 iarg
= iarg
+ lines
;
5800 #if 0 /* This code would prevent move-to-window-line from moving point
5801 to a place inside the scroll margins (which would cause the
5802 next redisplay to scroll). I wrote this code, but then concluded
5803 it is probably better not to install it. However, it is here
5804 inside #if 0 so as not to lose it. -- rms. */
5806 /* Don't let it get into the margin at either top or bottom. */
5807 iarg
= max (iarg
, this_scroll_margin
);
5808 iarg
= min (iarg
, lines
- this_scroll_margin
- 1);
5811 arg
= make_number (iarg
);
5814 /* Skip past a partially visible first line. */
5816 XSETINT (arg
, XINT (arg
) + 1);
5818 return Fvertical_motion (arg
, window
);
5823 /***********************************************************************
5824 Window Configuration
5825 ***********************************************************************/
5827 struct save_window_data
5830 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
5831 Lisp_Object selected_frame
;
5832 Lisp_Object current_window
;
5833 Lisp_Object current_buffer
;
5834 Lisp_Object minibuf_scroll_window
;
5835 Lisp_Object minibuf_selected_window
;
5836 Lisp_Object root_window
;
5837 Lisp_Object focus_frame
;
5838 /* A vector, each of whose elements is a struct saved_window
5840 Lisp_Object saved_windows
;
5842 /* All fields above are traced by the GC.
5843 From `fame-cols' down, the fields are ignored by the GC. */
5845 int frame_cols
, frame_lines
, frame_menu_bar_lines
;
5846 int frame_tool_bar_lines
;
5849 /* This is saved as a Lisp_Vector */
5852 /* these first two must agree with struct Lisp_Vector in lisp.h */
5854 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
5857 Lisp_Object buffer
, start
, pointm
, mark
;
5858 Lisp_Object left_col
, top_line
, total_cols
, total_lines
;
5859 Lisp_Object hscroll
, min_hscroll
;
5860 Lisp_Object parent
, prev
;
5861 Lisp_Object start_at_line_beg
;
5862 Lisp_Object display_table
;
5863 Lisp_Object orig_top_line
, orig_total_lines
;
5864 Lisp_Object left_margin_cols
, right_margin_cols
;
5865 Lisp_Object left_fringe_width
, right_fringe_width
, fringes_outside_margins
;
5866 Lisp_Object scroll_bar_width
, vertical_scroll_bar_type
;
5867 Lisp_Object dedicated
, resize_proportionally
;
5870 #define SAVED_WINDOW_N(swv,n) \
5871 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5873 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
5874 doc
: /* Return t if OBJECT is a window-configuration object. */)
5875 (Lisp_Object object
)
5877 return WINDOW_CONFIGURATIONP (object
) ? Qt
: Qnil
;
5880 DEFUN ("window-configuration-frame", Fwindow_configuration_frame
, Swindow_configuration_frame
, 1, 1, 0,
5881 doc
: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5882 (Lisp_Object config
)
5884 register struct save_window_data
*data
;
5885 struct Lisp_Vector
*saved_windows
;
5887 CHECK_WINDOW_CONFIGURATION (config
);
5889 data
= (struct save_window_data
*) XVECTOR (config
);
5890 saved_windows
= XVECTOR (data
->saved_windows
);
5891 return XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
5894 DEFUN ("set-window-configuration", Fset_window_configuration
,
5895 Sset_window_configuration
, 1, 1, 0,
5896 doc
: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5897 CONFIGURATION must be a value previously returned
5898 by `current-window-configuration' (which see).
5899 If CONFIGURATION was made from a frame that is now deleted,
5900 only frame-independent values can be restored. In this case,
5901 the return value is nil. Otherwise the value is t. */)
5902 (Lisp_Object configuration
)
5904 register struct save_window_data
*data
;
5905 struct Lisp_Vector
*saved_windows
;
5906 Lisp_Object new_current_buffer
;
5909 EMACS_INT old_point
= -1;
5911 CHECK_WINDOW_CONFIGURATION (configuration
);
5913 data
= (struct save_window_data
*) XVECTOR (configuration
);
5914 saved_windows
= XVECTOR (data
->saved_windows
);
5916 new_current_buffer
= data
->current_buffer
;
5917 if (NILP (XBUFFER (new_current_buffer
)->name
))
5918 new_current_buffer
= Qnil
;
5921 if (XBUFFER (new_current_buffer
) == current_buffer
)
5922 /* The code further down "preserves point" by saving here PT in
5923 old_point and then setting it later back into PT. When the
5924 current-selected-window and the final-selected-window both show
5925 the current buffer, this suffers from the problem that the
5926 current PT is the window-point of the current-selected-window,
5927 while the final PT is the point of the final-selected-window, so
5928 this copy from one PT to the other would end up moving the
5929 window-point of the final-selected-window to the window-point of
5930 the current-selected-window. So we have to be careful which
5931 point of the current-buffer we copy into old_point. */
5932 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
)
5933 && WINDOWP (selected_window
)
5934 && EQ (XWINDOW (selected_window
)->buffer
, new_current_buffer
)
5935 && !EQ (selected_window
, data
->current_window
))
5936 old_point
= XMARKER (XWINDOW (data
->current_window
)->pointm
)->charpos
;
5940 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5941 point in new_current_buffer as of the last time this buffer was
5942 used. This can be non-deterministic since it can be changed by
5943 things like jit-lock by mere temporary selection of some random
5944 window that happens to show this buffer.
5945 So if possible we want this arbitrary choice of "which point" to
5946 be the one from the to-be-selected-window so as to prevent this
5947 window's cursor from being copied from another window. */
5948 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
)
5949 /* If current_window = selected_window, its point is in BUF_PT. */
5950 && !EQ (selected_window
, data
->current_window
))
5951 old_point
= XMARKER (XWINDOW (data
->current_window
)->pointm
)->charpos
;
5953 old_point
= BUF_PT (XBUFFER (new_current_buffer
));
5956 frame
= XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
5959 /* If f is a dead frame, don't bother rebuilding its window tree.
5960 However, there is other stuff we should still try to do below. */
5961 if (FRAME_LIVE_P (f
))
5963 register struct window
*w
;
5964 register struct saved_window
*p
;
5965 struct window
*root_window
;
5966 struct window
**leaf_windows
;
5970 /* If the frame has been resized since this window configuration was
5971 made, we change the frame to the size specified in the
5972 configuration, restore the configuration, and then resize it
5973 back. We keep track of the prevailing height in these variables. */
5974 int previous_frame_lines
= FRAME_LINES (f
);
5975 int previous_frame_cols
= FRAME_COLS (f
);
5976 int previous_frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
5977 int previous_frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
5979 /* The mouse highlighting code could get screwed up
5980 if it runs during this. */
5983 if (data
->frame_lines
!= previous_frame_lines
5984 || data
->frame_cols
!= previous_frame_cols
)
5985 change_frame_size (f
, data
->frame_lines
,
5986 data
->frame_cols
, 0, 0, 0);
5987 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5988 if (data
->frame_menu_bar_lines
5989 != previous_frame_menu_bar_lines
)
5990 x_set_menu_bar_lines (f
, make_number (data
->frame_menu_bar_lines
),
5992 #ifdef HAVE_WINDOW_SYSTEM
5993 if (data
->frame_tool_bar_lines
5994 != previous_frame_tool_bar_lines
)
5995 x_set_tool_bar_lines (f
, make_number (data
->frame_tool_bar_lines
),
6000 /* "Swap out" point from the selected window's buffer
6001 into the window itself. (Normally the pointm of the selected
6002 window holds garbage.) We do this now, before
6003 restoring the window contents, and prevent it from
6004 being done later on when we select a new window. */
6005 if (! NILP (XWINDOW (selected_window
)->buffer
))
6007 w
= XWINDOW (selected_window
);
6008 set_marker_both (w
->pointm
,
6010 BUF_PT (XBUFFER (w
->buffer
)),
6011 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6014 windows_or_buffers_changed
++;
6015 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
6017 /* Problem: Freeing all matrices and later allocating them again
6018 is a serious redisplay flickering problem. What we would
6019 really like to do is to free only those matrices not reused
6021 root_window
= XWINDOW (FRAME_ROOT_WINDOW (f
));
6023 = (struct window
**) alloca (count_windows (root_window
)
6024 * sizeof (struct window
*));
6025 n_leaf_windows
= get_leaf_windows (root_window
, leaf_windows
, 0);
6028 Mark all windows now on frame as "deleted".
6029 Restoring the new configuration "undeletes" any that are in it.
6031 Save their current buffers in their height fields, since we may
6032 need it later, if a buffer saved in the configuration is now
6034 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6036 for (k
= 0; k
< saved_windows
->size
; k
++)
6038 p
= SAVED_WINDOW_N (saved_windows
, k
);
6039 w
= XWINDOW (p
->window
);
6042 if (!NILP (p
->parent
))
6043 w
->parent
= SAVED_WINDOW_N (saved_windows
,
6044 XFASTINT (p
->parent
))->window
;
6048 if (!NILP (p
->prev
))
6050 w
->prev
= SAVED_WINDOW_N (saved_windows
,
6051 XFASTINT (p
->prev
))->window
;
6052 XWINDOW (w
->prev
)->next
= p
->window
;
6057 if (!NILP (w
->parent
))
6059 if (EQ (p
->total_cols
, XWINDOW (w
->parent
)->total_cols
))
6061 XWINDOW (w
->parent
)->vchild
= p
->window
;
6062 XWINDOW (w
->parent
)->hchild
= Qnil
;
6066 XWINDOW (w
->parent
)->hchild
= p
->window
;
6067 XWINDOW (w
->parent
)->vchild
= Qnil
;
6072 /* If we squirreled away the buffer in the window's height,
6074 if (BUFFERP (w
->total_lines
))
6075 w
->buffer
= w
->total_lines
;
6076 w
->left_col
= p
->left_col
;
6077 w
->top_line
= p
->top_line
;
6078 w
->total_cols
= p
->total_cols
;
6079 w
->total_lines
= p
->total_lines
;
6080 w
->hscroll
= p
->hscroll
;
6081 w
->min_hscroll
= p
->min_hscroll
;
6082 w
->display_table
= p
->display_table
;
6083 w
->orig_top_line
= p
->orig_top_line
;
6084 w
->orig_total_lines
= p
->orig_total_lines
;
6085 w
->left_margin_cols
= p
->left_margin_cols
;
6086 w
->right_margin_cols
= p
->right_margin_cols
;
6087 w
->left_fringe_width
= p
->left_fringe_width
;
6088 w
->right_fringe_width
= p
->right_fringe_width
;
6089 w
->fringes_outside_margins
= p
->fringes_outside_margins
;
6090 w
->scroll_bar_width
= p
->scroll_bar_width
;
6091 w
->vertical_scroll_bar_type
= p
->vertical_scroll_bar_type
;
6092 w
->dedicated
= p
->dedicated
;
6093 w
->resize_proportionally
= p
->resize_proportionally
;
6094 XSETFASTINT (w
->last_modified
, 0);
6095 XSETFASTINT (w
->last_overlay_modified
, 0);
6097 /* Reinstall the saved buffer and pointers into it. */
6098 if (NILP (p
->buffer
))
6099 w
->buffer
= p
->buffer
;
6102 if (!NILP (XBUFFER (p
->buffer
)->name
))
6103 /* If saved buffer is alive, install it. */
6105 w
->buffer
= p
->buffer
;
6106 w
->start_at_line_beg
= p
->start_at_line_beg
;
6107 set_marker_restricted (w
->start
, p
->start
, w
->buffer
);
6108 set_marker_restricted (w
->pointm
, p
->pointm
, w
->buffer
);
6109 Fset_marker (XBUFFER (w
->buffer
)->mark
,
6110 p
->mark
, w
->buffer
);
6112 /* As documented in Fcurrent_window_configuration, don't
6113 restore the location of point in the buffer which was
6114 current when the window configuration was recorded. */
6115 if (!EQ (p
->buffer
, new_current_buffer
)
6116 && XBUFFER (p
->buffer
) == current_buffer
)
6117 Fgoto_char (w
->pointm
);
6119 else if (NILP (w
->buffer
) || NILP (XBUFFER (w
->buffer
)->name
))
6120 /* Else unless window has a live buffer, get one. */
6122 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
6123 /* This will set the markers to beginning of visible
6125 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
6126 set_marker_restricted (w
->pointm
, make_number (0),w
->buffer
);
6127 w
->start_at_line_beg
= Qt
;
6130 /* Keeping window's old buffer; make sure the markers
6133 /* Set window markers at start of visible range. */
6134 if (XMARKER (w
->start
)->buffer
== 0)
6135 set_marker_restricted (w
->start
, make_number (0),
6137 if (XMARKER (w
->pointm
)->buffer
== 0)
6138 set_marker_restricted_both (w
->pointm
, w
->buffer
,
6139 BUF_PT (XBUFFER (w
->buffer
)),
6140 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6141 w
->start_at_line_beg
= Qt
;
6146 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
6147 /* Prevent "swapping out point" in the old selected window
6148 using the buffer that has been restored into it.
6149 We already swapped out point that from that window's old buffer. */
6150 selected_window
= Qnil
;
6152 /* Arrange *not* to restore point in the buffer that was
6153 current when the window configuration was saved. */
6154 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
))
6155 set_marker_restricted (XWINDOW (data
->current_window
)->pointm
,
6156 make_number (old_point
),
6157 XWINDOW (data
->current_window
)->buffer
);
6159 Fselect_window (data
->current_window
, Qnil
);
6160 XBUFFER (XWINDOW (selected_window
)->buffer
)->last_selected_window
6163 if (NILP (data
->focus_frame
)
6164 || (FRAMEP (data
->focus_frame
)
6165 && FRAME_LIVE_P (XFRAME (data
->focus_frame
))))
6166 Fredirect_frame_focus (frame
, data
->focus_frame
);
6168 #if 0 /* I don't understand why this is needed, and it causes problems
6169 when the frame's old selected window has been deleted. */
6170 if (f
!= selected_frame
&& FRAME_WINDOW_P (f
))
6171 do_switch_frame (WINDOW_FRAME (XWINDOW (data
->root_window
)),
6175 /* Set the screen height to the value it had before this function. */
6176 if (previous_frame_lines
!= FRAME_LINES (f
)
6177 || previous_frame_cols
!= FRAME_COLS (f
))
6178 change_frame_size (f
, previous_frame_lines
, previous_frame_cols
,
6180 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6181 if (previous_frame_menu_bar_lines
!= FRAME_MENU_BAR_LINES (f
))
6182 x_set_menu_bar_lines (f
, make_number (previous_frame_menu_bar_lines
),
6184 #ifdef HAVE_WINDOW_SYSTEM
6185 if (previous_frame_tool_bar_lines
!= FRAME_TOOL_BAR_LINES (f
))
6186 x_set_tool_bar_lines (f
, make_number (previous_frame_tool_bar_lines
),
6191 /* Now, free glyph matrices in windows that were not reused. */
6192 for (i
= n
= 0; i
< n_leaf_windows
; ++i
)
6194 if (NILP (leaf_windows
[i
]->buffer
))
6196 /* Assert it's not reused as a combination. */
6197 xassert (NILP (leaf_windows
[i
]->hchild
)
6198 && NILP (leaf_windows
[i
]->vchild
));
6199 free_window_matrices (leaf_windows
[i
]);
6201 else if (EQ (leaf_windows
[i
]->buffer
, new_current_buffer
))
6209 /* Fselect_window will have made f the selected frame, so we
6210 reselect the proper frame here. Fhandle_switch_frame will change the
6211 selected window too, but that doesn't make the call to
6212 Fselect_window above totally superfluous; it still sets f's
6214 if (FRAME_LIVE_P (XFRAME (data
->selected_frame
)))
6215 do_switch_frame (data
->selected_frame
, 0, 0, Qnil
);
6217 run_window_configuration_change_hook (f
);
6220 if (!NILP (new_current_buffer
))
6221 Fset_buffer (new_current_buffer
);
6223 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
6224 minibuf_selected_window
= data
->minibuf_selected_window
;
6226 return (FRAME_LIVE_P (f
) ? Qt
: Qnil
);
6229 /* Mark all windows now on frame as deleted
6230 by setting their buffers to nil. */
6233 delete_all_subwindows (register struct window
*w
)
6235 if (!NILP (w
->next
))
6236 delete_all_subwindows (XWINDOW (w
->next
));
6237 if (!NILP (w
->vchild
))
6238 delete_all_subwindows (XWINDOW (w
->vchild
));
6239 if (!NILP (w
->hchild
))
6240 delete_all_subwindows (XWINDOW (w
->hchild
));
6242 w
->total_lines
= w
->buffer
; /* See Fset_window_configuration for excuse. */
6244 if (!NILP (w
->buffer
))
6247 /* We set all three of these fields to nil, to make sure that we can
6248 distinguish this dead window from any live window. Live leaf
6249 windows will have buffer set, and combination windows will have
6250 vchild or hchild set. */
6255 Vwindow_list
= Qnil
;
6259 count_windows (register struct window
*window
)
6261 register int count
= 1;
6262 if (!NILP (window
->next
))
6263 count
+= count_windows (XWINDOW (window
->next
));
6264 if (!NILP (window
->vchild
))
6265 count
+= count_windows (XWINDOW (window
->vchild
));
6266 if (!NILP (window
->hchild
))
6267 count
+= count_windows (XWINDOW (window
->hchild
));
6272 /* Fill vector FLAT with leaf windows under W, starting at index I.
6273 Value is last index + 1. */
6276 get_leaf_windows (struct window
*w
, struct window
**flat
, int i
)
6280 if (!NILP (w
->hchild
))
6281 i
= get_leaf_windows (XWINDOW (w
->hchild
), flat
, i
);
6282 else if (!NILP (w
->vchild
))
6283 i
= get_leaf_windows (XWINDOW (w
->vchild
), flat
, i
);
6287 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6294 /* Return a pointer to the glyph W's physical cursor is on. Value is
6295 null if W's current matrix is invalid, so that no meaningfull glyph
6299 get_phys_cursor_glyph (struct window
*w
)
6301 struct glyph_row
*row
;
6302 struct glyph
*glyph
;
6304 if (w
->phys_cursor
.vpos
>= 0
6305 && w
->phys_cursor
.vpos
< w
->current_matrix
->nrows
6306 && (row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
),
6308 && row
->used
[TEXT_AREA
] > w
->phys_cursor
.hpos
)
6309 glyph
= row
->glyphs
[TEXT_AREA
] + w
->phys_cursor
.hpos
;
6318 save_window_save (Lisp_Object window
, struct Lisp_Vector
*vector
, int i
)
6320 register struct saved_window
*p
;
6321 register struct window
*w
;
6322 register Lisp_Object tem
;
6324 for (;!NILP (window
); window
= w
->next
)
6326 p
= SAVED_WINDOW_N (vector
, i
);
6327 w
= XWINDOW (window
);
6329 XSETFASTINT (w
->temslot
, i
); i
++;
6331 p
->buffer
= w
->buffer
;
6332 p
->left_col
= w
->left_col
;
6333 p
->top_line
= w
->top_line
;
6334 p
->total_cols
= w
->total_cols
;
6335 p
->total_lines
= w
->total_lines
;
6336 p
->hscroll
= w
->hscroll
;
6337 p
->min_hscroll
= w
->min_hscroll
;
6338 p
->display_table
= w
->display_table
;
6339 p
->orig_top_line
= w
->orig_top_line
;
6340 p
->orig_total_lines
= w
->orig_total_lines
;
6341 p
->left_margin_cols
= w
->left_margin_cols
;
6342 p
->right_margin_cols
= w
->right_margin_cols
;
6343 p
->left_fringe_width
= w
->left_fringe_width
;
6344 p
->right_fringe_width
= w
->right_fringe_width
;
6345 p
->fringes_outside_margins
= w
->fringes_outside_margins
;
6346 p
->scroll_bar_width
= w
->scroll_bar_width
;
6347 p
->vertical_scroll_bar_type
= w
->vertical_scroll_bar_type
;
6348 p
->dedicated
= w
->dedicated
;
6349 p
->resize_proportionally
= w
->resize_proportionally
;
6350 if (!NILP (w
->buffer
))
6352 /* Save w's value of point in the window configuration.
6353 If w is the selected window, then get the value of point
6354 from the buffer; pointm is garbage in the selected window. */
6355 if (EQ (window
, selected_window
))
6357 p
->pointm
= Fmake_marker ();
6358 set_marker_both (p
->pointm
, w
->buffer
,
6359 BUF_PT (XBUFFER (w
->buffer
)),
6360 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6363 p
->pointm
= Fcopy_marker (w
->pointm
, Qnil
);
6365 p
->start
= Fcopy_marker (w
->start
, Qnil
);
6366 p
->start_at_line_beg
= w
->start_at_line_beg
;
6368 tem
= XBUFFER (w
->buffer
)->mark
;
6369 p
->mark
= Fcopy_marker (tem
, Qnil
);
6376 p
->start_at_line_beg
= Qnil
;
6379 if (NILP (w
->parent
))
6382 p
->parent
= XWINDOW (w
->parent
)->temslot
;
6387 p
->prev
= XWINDOW (w
->prev
)->temslot
;
6389 if (!NILP (w
->vchild
))
6390 i
= save_window_save (w
->vchild
, vector
, i
);
6391 if (!NILP (w
->hchild
))
6392 i
= save_window_save (w
->hchild
, vector
, i
);
6398 DEFUN ("current-window-configuration", Fcurrent_window_configuration
,
6399 Scurrent_window_configuration
, 0, 1, 0,
6400 doc
: /* Return an object representing the current window configuration of FRAME.
6401 If FRAME is nil or omitted, use the selected frame.
6402 This describes the number of windows, their sizes and current buffers,
6403 and for each displayed buffer, where display starts, and the positions of
6404 point and mark. An exception is made for point in the current buffer:
6405 its value is -not- saved.
6406 This also records the currently selected frame, and FRAME's focus
6407 redirection (see `redirect-frame-focus'). */)
6410 register Lisp_Object tem
;
6411 register int n_windows
;
6412 register struct save_window_data
*data
;
6417 frame
= selected_frame
;
6418 CHECK_LIVE_FRAME (frame
);
6421 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6422 data
= ALLOCATE_PSEUDOVECTOR (struct save_window_data
, frame_cols
,
6423 PVEC_WINDOW_CONFIGURATION
);
6425 data
->frame_cols
= FRAME_COLS (f
);
6426 data
->frame_lines
= FRAME_LINES (f
);
6427 data
->frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
6428 data
->frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
6429 data
->selected_frame
= selected_frame
;
6430 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
6431 XSETBUFFER (data
->current_buffer
, current_buffer
);
6432 data
->minibuf_scroll_window
= minibuf_level
> 0 ? Vminibuf_scroll_window
: Qnil
;
6433 data
->minibuf_selected_window
= minibuf_level
> 0 ? minibuf_selected_window
: Qnil
;
6434 data
->root_window
= FRAME_ROOT_WINDOW (f
);
6435 data
->focus_frame
= FRAME_FOCUS_FRAME (f
);
6436 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
6437 data
->saved_windows
= tem
;
6438 for (i
= 0; i
< n_windows
; i
++)
6439 XVECTOR (tem
)->contents
[i
]
6440 = Fmake_vector (make_number (VECSIZE (struct saved_window
)), Qnil
);
6441 save_window_save (FRAME_ROOT_WINDOW (f
), XVECTOR (tem
), 0);
6442 XSETWINDOW_CONFIGURATION (tem
, data
);
6446 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
6448 doc
: /* Execute BODY, preserving window sizes and contents.
6449 Return the value of the last form in BODY.
6450 Restore which buffer appears in which window, where display starts,
6451 and the value of point and mark for each window.
6452 Also restore the choice of selected window.
6453 Also restore which buffer is current.
6454 Does not restore the value of point in current buffer.
6455 usage: (save-window-excursion BODY...) */)
6458 register Lisp_Object val
;
6459 register int count
= SPECPDL_INDEX ();
6461 record_unwind_protect (Fset_window_configuration
,
6462 Fcurrent_window_configuration (Qnil
));
6463 val
= Fprogn (args
);
6464 return unbind_to (count
, val
);
6469 /***********************************************************************
6471 ***********************************************************************/
6474 window_tree (struct window
*w
)
6476 Lisp_Object tail
= Qnil
;
6477 Lisp_Object result
= Qnil
;
6484 if (!NILP (w
->hchild
))
6485 wn
= Fcons (Qnil
, Fcons (Fwindow_edges (wn
),
6486 window_tree (XWINDOW (w
->hchild
))));
6487 else if (!NILP (w
->vchild
))
6488 wn
= Fcons (Qt
, Fcons (Fwindow_edges (wn
),
6489 window_tree (XWINDOW (w
->vchild
))));
6493 result
= tail
= Fcons (wn
, Qnil
);
6497 XSETCDR (tail
, Fcons (wn
, Qnil
));
6501 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6509 DEFUN ("window-tree", Fwindow_tree
, Swindow_tree
,
6511 doc
: /* Return the window tree for frame FRAME.
6513 The return value is a list of the form (ROOT MINI), where ROOT
6514 represents the window tree of the frame's root window, and MINI
6515 is the frame's minibuffer window.
6517 If the root window is not split, ROOT is the root window itself.
6518 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6519 horizontal split, and t for a vertical split, EDGES gives the combined
6520 size and position of the subwindows in the split, and the rest of the
6521 elements are the subwindows in the split. Each of the subwindows may
6522 again be a window or a list representing a window split, and so on.
6523 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6525 If FRAME is nil or omitted, return information on the currently
6532 frame
= selected_frame
;
6534 CHECK_FRAME (frame
);
6537 if (!FRAME_LIVE_P (f
))
6540 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6544 /***********************************************************************
6546 ***********************************************************************/
6548 DEFUN ("set-window-margins", Fset_window_margins
, Sset_window_margins
,
6550 doc
: /* Set width of marginal areas of window WINDOW.
6551 If WINDOW is nil, set margins of the currently selected window.
6552 Second arg LEFT-WIDTH specifies the number of character cells to
6553 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6554 does the same for the right marginal area. A nil width parameter
6555 means no margin. */)
6556 (Lisp_Object window
, Lisp_Object left_width
, Lisp_Object right_width
)
6558 struct window
*w
= decode_window (window
);
6560 /* Translate negative or zero widths to nil.
6561 Margins that are too wide have to be checked elsewhere. */
6563 if (!NILP (left_width
))
6565 CHECK_NUMBER (left_width
);
6566 if (XINT (left_width
) <= 0)
6570 if (!NILP (right_width
))
6572 CHECK_NUMBER (right_width
);
6573 if (XINT (right_width
) <= 0)
6577 if (!EQ (w
->left_margin_cols
, left_width
)
6578 || !EQ (w
->right_margin_cols
, right_width
))
6580 w
->left_margin_cols
= left_width
;
6581 w
->right_margin_cols
= right_width
;
6583 adjust_window_margins (w
);
6585 ++windows_or_buffers_changed
;
6586 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6593 DEFUN ("window-margins", Fwindow_margins
, Swindow_margins
,
6595 doc
: /* Get width of marginal areas of window WINDOW.
6596 If WINDOW is omitted or nil, use the currently selected window.
6597 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6598 If a marginal area does not exist, its width will be returned
6600 (Lisp_Object window
)
6602 struct window
*w
= decode_window (window
);
6603 return Fcons (w
->left_margin_cols
, w
->right_margin_cols
);
6608 /***********************************************************************
6610 ***********************************************************************/
6612 DEFUN ("set-window-fringes", Fset_window_fringes
, Sset_window_fringes
,
6614 doc
: /* Set the fringe widths of window WINDOW.
6615 If WINDOW is nil, set the fringe widths of the currently selected
6617 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6618 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6619 fringe width. If a fringe width arg is nil, that means to use the
6620 frame's default fringe width. Default fringe widths can be set with
6621 the command `set-fringe-style'.
6622 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6623 outside of the display margins. By default, fringes are drawn between
6624 display marginal areas and the text area. */)
6625 (Lisp_Object window
, Lisp_Object left_width
, Lisp_Object right_width
, Lisp_Object outside_margins
)
6627 struct window
*w
= decode_window (window
);
6629 if (!NILP (left_width
))
6630 CHECK_NATNUM (left_width
);
6631 if (!NILP (right_width
))
6632 CHECK_NATNUM (right_width
);
6634 /* Do nothing on a tty. */
6635 if (FRAME_WINDOW_P (WINDOW_XFRAME (w
))
6636 && (!EQ (w
->left_fringe_width
, left_width
)
6637 || !EQ (w
->right_fringe_width
, right_width
)
6638 || !EQ (w
->fringes_outside_margins
, outside_margins
)))
6640 w
->left_fringe_width
= left_width
;
6641 w
->right_fringe_width
= right_width
;
6642 w
->fringes_outside_margins
= outside_margins
;
6644 adjust_window_margins (w
);
6646 clear_glyph_matrix (w
->current_matrix
);
6647 w
->window_end_valid
= Qnil
;
6649 ++windows_or_buffers_changed
;
6650 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6657 DEFUN ("window-fringes", Fwindow_fringes
, Swindow_fringes
,
6659 doc
: /* Get width of fringes of window WINDOW.
6660 If WINDOW is omitted or nil, use the currently selected window.
6661 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6662 (Lisp_Object window
)
6664 struct window
*w
= decode_window (window
);
6666 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w
)),
6667 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w
)),
6668 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
6669 ? Qt
: Qnil
), Qnil
)));
6674 /***********************************************************************
6676 ***********************************************************************/
6678 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars
, Sset_window_scroll_bars
,
6680 doc
: /* Set width and type of scroll bars of window WINDOW.
6681 If window is nil, set scroll bars of the currently selected window.
6682 Second parameter WIDTH specifies the pixel width for the scroll bar;
6683 this is automatically adjusted to a multiple of the frame column width.
6684 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6685 bar: left, right, or nil.
6686 If WIDTH is nil, use the frame's scroll-bar width.
6687 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6688 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6689 (Lisp_Object window
, Lisp_Object width
, Lisp_Object vertical_type
, Lisp_Object horizontal_type
)
6691 struct window
*w
= decode_window (window
);
6695 CHECK_NATNUM (width
);
6697 if (XINT (width
) == 0)
6698 vertical_type
= Qnil
;
6701 if (!(NILP (vertical_type
)
6702 || EQ (vertical_type
, Qleft
)
6703 || EQ (vertical_type
, Qright
)
6704 || EQ (vertical_type
, Qt
)))
6705 error ("Invalid type of vertical scroll bar");
6707 if (!EQ (w
->scroll_bar_width
, width
)
6708 || !EQ (w
->vertical_scroll_bar_type
, vertical_type
))
6710 w
->scroll_bar_width
= width
;
6711 w
->vertical_scroll_bar_type
= vertical_type
;
6713 adjust_window_margins (w
);
6715 clear_glyph_matrix (w
->current_matrix
);
6716 w
->window_end_valid
= Qnil
;
6718 ++windows_or_buffers_changed
;
6719 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6726 DEFUN ("window-scroll-bars", Fwindow_scroll_bars
, Swindow_scroll_bars
,
6728 doc
: /* Get width and type of scroll bars of window WINDOW.
6729 If WINDOW is omitted or nil, use the currently selected window.
6730 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6731 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6733 (Lisp_Object window
)
6735 struct window
*w
= decode_window (window
);
6736 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
)
6737 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
)
6738 : WINDOW_SCROLL_BAR_AREA_WIDTH (w
))),
6739 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w
)),
6740 Fcons (w
->vertical_scroll_bar_type
,
6741 Fcons (Qnil
, Qnil
))));
6746 /***********************************************************************
6748 ***********************************************************************/
6750 DEFUN ("window-vscroll", Fwindow_vscroll
, Swindow_vscroll
, 0, 2, 0,
6751 doc
: /* Return the amount by which WINDOW is scrolled vertically.
6752 Use the selected window if WINDOW is nil or omitted.
6753 Normally, value is a multiple of the canonical character height of WINDOW;
6754 optional second arg PIXELS-P means value is measured in pixels. */)
6755 (Lisp_Object window
, Lisp_Object pixels_p
)
6762 window
= selected_window
;
6764 CHECK_WINDOW (window
);
6765 w
= XWINDOW (window
);
6766 f
= XFRAME (w
->frame
);
6768 if (FRAME_WINDOW_P (f
))
6769 result
= (NILP (pixels_p
)
6770 ? FRAME_CANON_Y_FROM_PIXEL_Y (f
, -w
->vscroll
)
6771 : make_number (-w
->vscroll
));
6773 result
= make_number (0);
6778 DEFUN ("set-window-vscroll", Fset_window_vscroll
, Sset_window_vscroll
,
6780 doc
: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6781 WINDOW nil means use the selected window. Normally, VSCROLL is a
6782 non-negative multiple of the canonical character height of WINDOW;
6783 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6784 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6785 corresponds to an integral number of pixels. The return value is the
6786 result of this rounding.
6787 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6788 (Lisp_Object window
, Lisp_Object vscroll
, Lisp_Object pixels_p
)
6794 window
= selected_window
;
6796 CHECK_WINDOW (window
);
6797 CHECK_NUMBER_OR_FLOAT (vscroll
);
6799 w
= XWINDOW (window
);
6800 f
= XFRAME (w
->frame
);
6802 if (FRAME_WINDOW_P (f
))
6804 int old_dy
= w
->vscroll
;
6806 w
->vscroll
= - (NILP (pixels_p
)
6807 ? FRAME_LINE_HEIGHT (f
) * XFLOATINT (vscroll
)
6808 : XFLOATINT (vscroll
));
6809 w
->vscroll
= min (w
->vscroll
, 0);
6811 if (w
->vscroll
!= old_dy
)
6813 /* Adjust glyph matrix of the frame if the virtual display
6814 area becomes larger than before. */
6815 if (w
->vscroll
< 0 && w
->vscroll
< old_dy
)
6818 /* Prevent redisplay shortcuts. */
6819 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
6823 return Fwindow_vscroll (window
, pixels_p
);
6827 /* Call FN for all leaf windows on frame F. FN is called with the
6828 first argument being a pointer to the leaf window, and with
6829 additional argument USER_DATA. Stops when FN returns 0. */
6832 foreach_window (struct frame
*f
, int (*fn
) (struct window
*, void *),
6835 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6836 if (WINDOWP (FRAME_ROOT_WINDOW (f
)))
6837 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f
)), fn
, user_data
);
6841 /* Helper function for foreach_window. Call FN for all leaf windows
6842 reachable from W. FN is called with the first argument being a
6843 pointer to the leaf window, and with additional argument USER_DATA.
6844 Stop when FN returns 0. Value is 0 if stopped by FN. */
6847 foreach_window_1 (struct window
*w
, int (*fn
) (struct window
*, void *), void *user_data
)
6851 for (cont
= 1; w
&& cont
;)
6853 if (!NILP (w
->hchild
))
6854 cont
= foreach_window_1 (XWINDOW (w
->hchild
), fn
, user_data
);
6855 else if (!NILP (w
->vchild
))
6856 cont
= foreach_window_1 (XWINDOW (w
->vchild
), fn
, user_data
);
6858 cont
= fn (w
, user_data
);
6860 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6867 /* Freeze or unfreeze the window start of W unless it is a
6868 mini-window or the selected window. FREEZE_P non-null means freeze
6869 the window start. */
6872 freeze_window_start (struct window
*w
, void *freeze_p
)
6874 if (MINI_WINDOW_P (w
)
6875 || (WINDOWP (selected_window
) /* Can be nil in corner cases. */
6876 && (w
== XWINDOW (selected_window
)
6877 || (MINI_WINDOW_P (XWINDOW (selected_window
))
6878 && ! NILP (Vminibuf_scroll_window
)
6879 && w
== XWINDOW (Vminibuf_scroll_window
)))))
6882 w
->frozen_window_start_p
= freeze_p
!= NULL
;
6887 /* Freeze or unfreeze the window starts of all leaf windows on frame
6888 F, except the selected window and a mini-window. FREEZE_P non-zero
6889 means freeze the window start. */
6892 freeze_window_starts (struct frame
*f
, int freeze_p
)
6894 foreach_window (f
, freeze_window_start
, (void *) (freeze_p
? f
: 0));
6898 /***********************************************************************
6900 ***********************************************************************/
6902 /* Return 1 if window configurations C1 and C2
6903 describe the same state of affairs. This is used by Fequal. */
6906 compare_window_configurations (Lisp_Object c1
, Lisp_Object c2
, int ignore_positions
)
6908 register struct save_window_data
*d1
, *d2
;
6909 struct Lisp_Vector
*sw1
, *sw2
;
6912 CHECK_WINDOW_CONFIGURATION (c1
);
6913 CHECK_WINDOW_CONFIGURATION (c2
);
6915 d1
= (struct save_window_data
*) XVECTOR (c1
);
6916 d2
= (struct save_window_data
*) XVECTOR (c2
);
6917 sw1
= XVECTOR (d1
->saved_windows
);
6918 sw2
= XVECTOR (d2
->saved_windows
);
6920 if (d1
->frame_cols
!= d2
->frame_cols
)
6922 if (d1
->frame_lines
!= d2
->frame_lines
)
6924 if (d1
->frame_menu_bar_lines
!= d2
->frame_menu_bar_lines
)
6926 if (! EQ (d1
->selected_frame
, d2
->selected_frame
))
6928 /* Don't compare the current_window field directly.
6929 Instead see w1_is_current and w2_is_current, below. */
6930 if (! EQ (d1
->current_buffer
, d2
->current_buffer
))
6932 if (! ignore_positions
)
6934 if (! EQ (d1
->minibuf_scroll_window
, d2
->minibuf_scroll_window
))
6936 if (! EQ (d1
->minibuf_selected_window
, d2
->minibuf_selected_window
))
6939 /* Don't compare the root_window field.
6940 We don't require the two configurations
6941 to use the same window object,
6942 and the two root windows must be equivalent
6943 if everything else compares equal. */
6944 if (! EQ (d1
->focus_frame
, d2
->focus_frame
))
6947 /* Verify that the two confis have the same number of windows. */
6948 if (sw1
->size
!= sw2
->size
)
6951 for (i
= 0; i
< sw1
->size
; i
++)
6953 struct saved_window
*p1
, *p2
;
6954 int w1_is_current
, w2_is_current
;
6956 p1
= SAVED_WINDOW_N (sw1
, i
);
6957 p2
= SAVED_WINDOW_N (sw2
, i
);
6959 /* Verify that the current windows in the two
6960 configurations correspond to each other. */
6961 w1_is_current
= EQ (d1
->current_window
, p1
->window
);
6962 w2_is_current
= EQ (d2
->current_window
, p2
->window
);
6964 if (w1_is_current
!= w2_is_current
)
6967 /* Verify that the corresponding windows do match. */
6968 if (! EQ (p1
->buffer
, p2
->buffer
))
6970 if (! EQ (p1
->left_col
, p2
->left_col
))
6972 if (! EQ (p1
->top_line
, p2
->top_line
))
6974 if (! EQ (p1
->total_cols
, p2
->total_cols
))
6976 if (! EQ (p1
->total_lines
, p2
->total_lines
))
6978 if (! EQ (p1
->display_table
, p2
->display_table
))
6980 if (! EQ (p1
->parent
, p2
->parent
))
6982 if (! EQ (p1
->prev
, p2
->prev
))
6984 if (! ignore_positions
)
6986 if (! EQ (p1
->hscroll
, p2
->hscroll
))
6988 if (!EQ (p1
->min_hscroll
, p2
->min_hscroll
))
6990 if (! EQ (p1
->start_at_line_beg
, p2
->start_at_line_beg
))
6992 if (NILP (Fequal (p1
->start
, p2
->start
)))
6994 if (NILP (Fequal (p1
->pointm
, p2
->pointm
)))
6996 if (NILP (Fequal (p1
->mark
, p2
->mark
)))
6999 if (! EQ (p1
->left_margin_cols
, p2
->left_margin_cols
))
7001 if (! EQ (p1
->right_margin_cols
, p2
->right_margin_cols
))
7003 if (! EQ (p1
->left_fringe_width
, p2
->left_fringe_width
))
7005 if (! EQ (p1
->right_fringe_width
, p2
->right_fringe_width
))
7007 if (! EQ (p1
->fringes_outside_margins
, p2
->fringes_outside_margins
))
7009 if (! EQ (p1
->scroll_bar_width
, p2
->scroll_bar_width
))
7011 if (! EQ (p1
->vertical_scroll_bar_type
, p2
->vertical_scroll_bar_type
))
7018 DEFUN ("compare-window-configurations", Fcompare_window_configurations
,
7019 Scompare_window_configurations
, 2, 2, 0,
7020 doc
: /* Compare two window configurations as regards the structure of windows.
7021 This function ignores details such as the values of point and mark
7022 and scrolling positions. */)
7023 (Lisp_Object x
, Lisp_Object y
)
7025 if (compare_window_configurations (x
, y
, 1))
7031 init_window_once (void)
7033 struct frame
*f
= make_initial_frame ();
7034 XSETFRAME (selected_frame
, f
);
7035 Vterminal_frame
= selected_frame
;
7036 minibuf_window
= f
->minibuffer_window
;
7037 selected_window
= f
->selected_window
;
7038 last_nonminibuf_frame
= f
;
7040 window_initialized
= 1;
7046 Vwindow_list
= Qnil
;
7050 syms_of_window (void)
7052 Qscroll_up
= intern_c_string ("scroll-up");
7053 staticpro (&Qscroll_up
);
7055 Qscroll_down
= intern_c_string ("scroll-down");
7056 staticpro (&Qscroll_down
);
7058 Qscroll_command
= intern_c_string ("scroll-command");
7059 staticpro (&Qscroll_command
);
7061 Fput (Qscroll_up
, Qscroll_command
, Qt
);
7062 Fput (Qscroll_down
, Qscroll_command
, Qt
);
7064 Qwindow_size_fixed
= intern_c_string ("window-size-fixed");
7065 staticpro (&Qwindow_size_fixed
);
7066 Fset (Qwindow_size_fixed
, Qnil
);
7068 staticpro (&Qwindow_configuration_change_hook
);
7069 Qwindow_configuration_change_hook
7070 = intern_c_string ("window-configuration-change-hook");
7072 Qwindowp
= intern_c_string ("windowp");
7073 staticpro (&Qwindowp
);
7075 Qwindow_configuration_p
= intern_c_string ("window-configuration-p");
7076 staticpro (&Qwindow_configuration_p
);
7078 Qwindow_live_p
= intern_c_string ("window-live-p");
7079 staticpro (&Qwindow_live_p
);
7081 Qdisplay_buffer
= intern_c_string ("display-buffer");
7082 staticpro (&Qdisplay_buffer
);
7084 Qtemp_buffer_show_hook
= intern_c_string ("temp-buffer-show-hook");
7085 staticpro (&Qtemp_buffer_show_hook
);
7087 staticpro (&Vwindow_list
);
7089 minibuf_selected_window
= Qnil
;
7090 staticpro (&minibuf_selected_window
);
7092 window_scroll_pixel_based_preserve_x
= -1;
7093 window_scroll_pixel_based_preserve_y
= -1;
7094 window_scroll_preserve_hpos
= -1;
7095 window_scroll_preserve_vpos
= -1;
7097 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
7098 doc
: /* Non-nil means call as function to display a help buffer.
7099 The function is called with one argument, the buffer to be displayed.
7100 Used by `with-output-to-temp-buffer'.
7101 If this function is used, then it must do the entire job of showing
7102 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7103 Vtemp_buffer_show_function
= Qnil
;
7105 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
7106 doc
: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7107 Vminibuf_scroll_window
= Qnil
;
7109 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows
,
7110 doc
: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7111 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7112 is displayed in the `mode-line' face. */);
7113 mode_line_in_non_selected_windows
= 1;
7115 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
7116 doc
: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7117 Vother_window_scroll_buffer
= Qnil
;
7119 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p
,
7120 doc
: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7121 auto_window_vscroll_p
= 1;
7123 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
7124 doc
: /* *Number of lines of continuity when scrolling by screenfuls. */);
7125 next_screen_context_lines
= 2;
7127 DEFVAR_INT ("window-min-height", &window_min_height
,
7128 doc
: /* Allow deleting windows less than this tall.
7129 The value is measured in line units. If a window wants a modeline it
7130 is counted as one line.
7132 Emacs honors settings of this variable when enlarging or shrinking
7133 windows vertically. A value less than 1 is invalid. */);
7134 window_min_height
= 4;
7136 DEFVAR_INT ("window-min-width", &window_min_width
,
7137 doc
: /* Allow deleting windows less than this wide.
7138 The value is measured in characters and includes any fringes or
7141 Emacs honors settings of this variable when enlarging or shrinking
7142 windows horizontally. A value less than 2 is invalid. */);
7143 window_min_width
= 10;
7145 DEFVAR_LISP ("scroll-preserve-screen-position",
7146 &Vscroll_preserve_screen_position
,
7147 doc
: /* *Controls if scroll commands move point to keep its screen position unchanged.
7148 A value of nil means point does not keep its screen position except
7149 at the scroll margin or window boundary respectively.
7150 A value of t means point keeps its screen position if the scroll
7151 command moved it vertically out of the window, e.g. when scrolling
7153 Any other value means point always keeps its screen position.
7154 Scroll commands should have the `scroll-command' property
7155 on their symbols to be controlled by this variable. */);
7156 Vscroll_preserve_screen_position
= Qnil
;
7158 DEFVAR_LISP ("window-point-insertion-type", &Vwindow_point_insertion_type
,
7159 doc
: /* Type of marker to use for `window-point'. */);
7160 Vwindow_point_insertion_type
= Qnil
;
7162 DEFVAR_LISP ("window-configuration-change-hook",
7163 &Vwindow_configuration_change_hook
,
7164 doc
: /* Functions to call when window configuration changes.
7165 The buffer-local part is run once per window, with the relevant window
7166 selected; while the global part is run only once for the modified frame,
7167 with the relevant frame selected. */);
7168 Vwindow_configuration_change_hook
= Qnil
;
7170 DEFVAR_LISP ("recenter-redisplay", &Vrecenter_redisplay
,
7171 doc
: /* If non-nil, then the `recenter' command with a nil argument
7172 will redraw the entire frame; the special value `tty' causes the
7173 frame to be redrawn only if it is a tty frame. */);
7174 Vrecenter_redisplay
= Qtty
;
7177 defsubr (&Sselected_window
);
7178 defsubr (&Sminibuffer_window
);
7179 defsubr (&Swindow_minibuffer_p
);
7180 defsubr (&Swindowp
);
7181 defsubr (&Swindow_live_p
);
7182 defsubr (&Spos_visible_in_window_p
);
7183 defsubr (&Swindow_line_height
);
7184 defsubr (&Swindow_buffer
);
7185 defsubr (&Swindow_height
);
7186 defsubr (&Swindow_width
);
7187 defsubr (&Swindow_full_width_p
);
7188 defsubr (&Swindow_hscroll
);
7189 defsubr (&Sset_window_hscroll
);
7190 defsubr (&Swindow_redisplay_end_trigger
);
7191 defsubr (&Sset_window_redisplay_end_trigger
);
7192 defsubr (&Swindow_edges
);
7193 defsubr (&Swindow_pixel_edges
);
7194 defsubr (&Swindow_absolute_pixel_edges
);
7195 defsubr (&Swindow_inside_edges
);
7196 defsubr (&Swindow_inside_pixel_edges
);
7197 defsubr (&Swindow_inside_absolute_pixel_edges
);
7198 defsubr (&Scoordinates_in_window_p
);
7199 defsubr (&Swindow_at
);
7200 defsubr (&Swindow_point
);
7201 defsubr (&Swindow_start
);
7202 defsubr (&Swindow_end
);
7203 defsubr (&Sset_window_point
);
7204 defsubr (&Sset_window_start
);
7205 defsubr (&Swindow_dedicated_p
);
7206 defsubr (&Sset_window_dedicated_p
);
7207 defsubr (&Swindow_display_table
);
7208 defsubr (&Sset_window_display_table
);
7209 defsubr (&Snext_window
);
7210 defsubr (&Sprevious_window
);
7211 defsubr (&Sother_window
);
7212 defsubr (&Sget_lru_window
);
7213 defsubr (&Swindow_use_time
);
7214 defsubr (&Sget_largest_window
);
7215 defsubr (&Sget_buffer_window
);
7216 defsubr (&Sdelete_other_windows
);
7217 defsubr (&Sdelete_windows_on
);
7218 defsubr (&Sreplace_buffer_in_windows
);
7219 defsubr (&Sdelete_window
);
7220 defsubr (&Sset_window_buffer
);
7221 defsubr (&Sselect_window
);
7222 defsubr (&Sforce_window_update
);
7223 defsubr (&Ssplit_window
);
7224 defsubr (&Senlarge_window
);
7225 defsubr (&Sshrink_window
);
7226 defsubr (&Sadjust_window_trailing_edge
);
7227 defsubr (&Sscroll_up
);
7228 defsubr (&Sscroll_down
);
7229 defsubr (&Sscroll_left
);
7230 defsubr (&Sscroll_right
);
7231 defsubr (&Sother_window_for_scrolling
);
7232 defsubr (&Sscroll_other_window
);
7233 defsubr (&Sminibuffer_selected_window
);
7234 defsubr (&Srecenter
);
7235 defsubr (&Swindow_text_height
);
7236 defsubr (&Smove_to_window_line
);
7237 defsubr (&Swindow_configuration_p
);
7238 defsubr (&Swindow_configuration_frame
);
7239 defsubr (&Sset_window_configuration
);
7240 defsubr (&Scurrent_window_configuration
);
7241 defsubr (&Ssave_window_excursion
);
7242 defsubr (&Swindow_tree
);
7243 defsubr (&Sset_window_margins
);
7244 defsubr (&Swindow_margins
);
7245 defsubr (&Sset_window_fringes
);
7246 defsubr (&Swindow_fringes
);
7247 defsubr (&Sset_window_scroll_bars
);
7248 defsubr (&Swindow_scroll_bars
);
7249 defsubr (&Swindow_vscroll
);
7250 defsubr (&Sset_window_vscroll
);
7251 defsubr (&Scompare_window_configurations
);
7252 defsubr (&Swindow_list
);
7253 defsubr (&Swindow_parameters
);
7254 defsubr (&Swindow_parameter
);
7255 defsubr (&Sset_window_parameter
);
7260 keys_of_window (void)
7262 initial_define_key (control_x_map
, '1', "delete-other-windows");
7263 initial_define_key (control_x_map
, '2', "split-window");
7264 initial_define_key (control_x_map
, '0', "delete-window");
7265 initial_define_key (control_x_map
, 'o', "other-window");
7266 initial_define_key (control_x_map
, '^', "enlarge-window");
7267 initial_define_key (control_x_map
, '<', "scroll-left");
7268 initial_define_key (control_x_map
, '>', "scroll-right");
7270 initial_define_key (global_map
, Ctl ('V'), "scroll-up-command");
7271 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
7272 initial_define_key (meta_map
, 'v', "scroll-down-command");
7275 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7276 (do not change this comment) */