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, 2011
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 /* Set in `set-window-configuration' to prevent "swapping out point"
162 in the old selected window. */
164 static int inhibit_point_swap
;
166 /* Hook to run when window config changes. */
168 static Lisp_Object Qwindow_configuration_change_hook
;
169 static Lisp_Object Vwindow_configuration_change_hook
;
171 /* Non-nil means scroll commands try to put point
172 at the same screen height as previously. */
174 Lisp_Object Vscroll_preserve_screen_position
;
176 /* Non-nil means that text is inserted before window's markers. */
178 Lisp_Object Vwindow_point_insertion_type
;
180 /* Incremented by 1 whenever a window is deleted. */
182 int window_deletion_count
;
184 /* Used by the function window_scroll_pixel_based */
186 static int window_scroll_pixel_based_preserve_x
;
187 static int window_scroll_pixel_based_preserve_y
;
189 /* Same for window_scroll_line_based. */
191 static int window_scroll_preserve_hpos
;
192 static int window_scroll_preserve_vpos
;
194 #if 0 /* This isn't used anywhere. */
195 /* Nonzero means we can split a frame even if it is "unsplittable". */
196 static int inhibit_frame_unsplittable
;
199 extern EMACS_INT scroll_margin
;
201 extern Lisp_Object Qwindow_scroll_functions
, Vwindow_scroll_functions
;
203 /* If non-nil, then the `recenter' command with a nil argument
204 the entire frame to be redrawn; the special value `tty' causes the
205 frame to be redrawn only if it is a tty frame. */
207 static Lisp_Object Vrecenter_redisplay
;
210 DEFUN ("windowp", Fwindowp
, Swindowp
, 1, 1, 0,
211 doc
: /* Return t if OBJECT is a window. */)
214 return WINDOWP (object
) ? Qt
: Qnil
;
217 DEFUN ("window-live-p", Fwindow_live_p
, Swindow_live_p
, 1, 1, 0,
218 doc
: /* Return t if OBJECT is a window which is currently visible. */)
221 return WINDOW_LIVE_P (object
) ? Qt
: Qnil
;
228 register struct window
*p
;
230 p
= allocate_window ();
232 XSETFASTINT (p
->sequence_number
, sequence_number
);
233 XSETFASTINT (p
->left_col
, 0);
234 XSETFASTINT (p
->top_line
, 0);
235 XSETFASTINT (p
->total_lines
, 0);
236 XSETFASTINT (p
->total_cols
, 0);
237 XSETFASTINT (p
->hscroll
, 0);
238 XSETFASTINT (p
->min_hscroll
, 0);
239 p
->orig_top_line
= p
->orig_total_lines
= Qnil
;
240 p
->start
= Fmake_marker ();
241 p
->pointm
= Fmake_marker ();
242 XSETFASTINT (p
->use_time
, 0);
244 p
->display_table
= Qnil
;
246 p
->window_parameters
= Qnil
;
247 p
->pseudo_window_p
= 0;
248 memset (&p
->cursor
, 0, sizeof (p
->cursor
));
249 memset (&p
->last_cursor
, 0, sizeof (p
->last_cursor
));
250 memset (&p
->phys_cursor
, 0, sizeof (p
->phys_cursor
));
251 p
->desired_matrix
= p
->current_matrix
= 0;
252 p
->nrows_scale_factor
= p
->ncols_scale_factor
= 1;
253 p
->phys_cursor_type
= -1;
254 p
->phys_cursor_width
= -1;
255 p
->must_be_updated_p
= 0;
256 XSETFASTINT (p
->window_end_vpos
, 0);
257 XSETFASTINT (p
->window_end_pos
, 0);
258 p
->window_end_valid
= Qnil
;
261 XSETFASTINT (p
->last_point
, 0);
262 p
->frozen_window_start_p
= 0;
263 p
->last_cursor_off_p
= p
->cursor_off_p
= 0;
264 p
->left_margin_cols
= Qnil
;
265 p
->right_margin_cols
= Qnil
;
266 p
->left_fringe_width
= Qnil
;
267 p
->right_fringe_width
= Qnil
;
268 p
->fringes_outside_margins
= Qnil
;
269 p
->scroll_bar_width
= Qnil
;
270 p
->vertical_scroll_bar_type
= Qt
;
271 p
->resize_proportionally
= Qnil
;
277 DEFUN ("selected-window", Fselected_window
, Sselected_window
, 0, 0, 0,
278 doc
: /* Return the window that the cursor now appears in and commands apply to. */)
281 return selected_window
;
284 DEFUN ("minibuffer-window", Fminibuffer_window
, Sminibuffer_window
, 0, 1, 0,
285 doc
: /* Return the window used now for minibuffers.
286 If the optional argument FRAME is specified, return the minibuffer window
287 used by that frame. */)
291 frame
= selected_frame
;
292 CHECK_LIVE_FRAME (frame
);
293 return FRAME_MINIBUF_WINDOW (XFRAME (frame
));
296 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p
, Swindow_minibuffer_p
, 0, 1, 0,
297 doc
: /* Return non-nil if WINDOW is a minibuffer window.
298 WINDOW defaults to the selected window. */)
301 struct window
*w
= decode_window (window
);
302 return MINI_WINDOW_P (w
) ? Qt
: Qnil
;
306 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p
,
307 Spos_visible_in_window_p
, 0, 3, 0,
308 doc
: /* Return non-nil if position POS is currently on the frame in WINDOW.
309 Return nil if that position is scrolled vertically out of view.
310 If a character is only partially visible, nil is returned, unless the
311 optional argument PARTIALLY is non-nil.
312 If POS is only out of view because of horizontal scrolling, return non-nil.
313 If POS is t, it specifies the position of the last visible glyph in WINDOW.
314 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
316 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
317 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
318 where X and Y are the pixel coordinates relative to the top left corner
319 of the window. The remaining elements are omitted if the character after
320 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
321 off-window at the top and bottom of the row, ROWH is the height of the
322 display row, and VPOS is the row number (0-based) containing POS. */)
323 (Lisp_Object pos
, Lisp_Object window
, Lisp_Object partially
)
325 register struct window
*w
;
326 register EMACS_INT posint
;
327 register struct buffer
*buf
;
329 Lisp_Object in_window
= Qnil
;
330 int rtop
, rbot
, rowh
, vpos
, fully_p
= 1;
333 w
= decode_window (window
);
334 buf
= XBUFFER (w
->buffer
);
335 SET_TEXT_POS_FROM_MARKER (top
, w
->start
);
339 else if (!NILP (pos
))
341 CHECK_NUMBER_COERCE_MARKER (pos
);
344 else if (w
== XWINDOW (selected_window
))
347 posint
= XMARKER (w
->pointm
)->charpos
;
349 /* If position is above window start or outside buffer boundaries,
350 or if window start is out of range, position is not visible. */
352 || (posint
>= CHARPOS (top
) && posint
<= BUF_ZV (buf
)))
353 && CHARPOS (top
) >= BUF_BEGV (buf
)
354 && CHARPOS (top
) <= BUF_ZV (buf
)
355 && pos_visible_p (w
, posint
, &x
, &y
, &rtop
, &rbot
, &rowh
, &vpos
)
356 && (fully_p
= !rtop
&& !rbot
, (!NILP (partially
) || fully_p
)))
359 if (!NILP (in_window
) && !NILP (partially
))
361 Lisp_Object part
= Qnil
;
363 part
= list4 (make_number (rtop
), make_number (rbot
),
364 make_number (rowh
), make_number (vpos
));
365 in_window
= Fcons (make_number (x
),
366 Fcons (make_number (y
), part
));
372 DEFUN ("window-line-height", Fwindow_line_height
,
373 Swindow_line_height
, 0, 2, 0,
374 doc
: /* Return height in pixels of text line LINE in window WINDOW.
375 If WINDOW is nil or omitted, use selected window.
377 Return height of current line if LINE is omitted or nil. Return height of
378 header or mode line if LINE is `header-line' and `mode-line'.
379 Otherwise, LINE is a text line number starting from 0. A negative number
380 counts from the end of the window.
382 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
383 in pixels of the visible part of the line, VPOS and YPOS are the
384 vertical position in lines and pixels of the line, relative to the top
385 of the first text line, and OFFBOT is the number of off-window pixels at
386 the bottom of the text line. If there are off-window pixels at the top
387 of the (first) text line, YPOS is negative.
389 Return nil if window display is not up-to-date. In that case, use
390 `pos-visible-in-window-p' to obtain the information. */)
391 (Lisp_Object line
, Lisp_Object window
)
393 register struct window
*w
;
394 register struct buffer
*b
;
395 struct glyph_row
*row
, *end_row
;
396 int max_y
, crop
, i
, n
;
398 w
= decode_window (window
);
401 || w
->pseudo_window_p
)
404 CHECK_BUFFER (w
->buffer
);
405 b
= XBUFFER (w
->buffer
);
407 /* Fail if current matrix is not up-to-date. */
408 if (NILP (w
->window_end_valid
)
409 || current_buffer
->clip_changed
410 || current_buffer
->prevent_redisplay_optimizations_p
411 || XFASTINT (w
->last_modified
) < BUF_MODIFF (b
)
412 || XFASTINT (w
->last_overlay_modified
) < BUF_OVERLAY_MODIFF (b
))
418 if (i
< 0 || i
>= w
->current_matrix
->nrows
419 || (row
= MATRIX_ROW (w
->current_matrix
, i
), !row
->enabled_p
))
421 max_y
= window_text_bottom_y (w
);
425 if (EQ (line
, Qheader_line
))
427 if (!WINDOW_WANTS_HEADER_LINE_P (w
))
429 row
= MATRIX_HEADER_LINE_ROW (w
->current_matrix
);
432 return list4 (make_number (row
->height
),
433 make_number (0), make_number (0),
437 if (EQ (line
, Qmode_line
))
439 row
= MATRIX_MODE_LINE_ROW (w
->current_matrix
);
442 return list4 (make_number (row
->height
),
443 make_number (0), /* not accurate */
444 make_number (WINDOW_HEADER_LINE_HEIGHT (w
)
445 + window_text_bottom_y (w
)),
452 row
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
453 end_row
= MATRIX_BOTTOM_TEXT_ROW (w
->current_matrix
, w
);
454 max_y
= window_text_bottom_y (w
);
457 while ((n
< 0 || i
< n
)
458 && row
<= end_row
&& row
->enabled_p
459 && row
->y
+ row
->height
< max_y
)
462 if (row
> end_row
|| !row
->enabled_p
)
474 crop
= max (0, (row
->y
+ row
->height
) - max_y
);
475 return list4 (make_number (row
->height
+ min (0, row
->y
) - crop
),
477 make_number (row
->y
),
483 static struct window
*
484 decode_window (register Lisp_Object window
)
487 return XWINDOW (selected_window
);
489 CHECK_LIVE_WINDOW (window
);
490 return XWINDOW (window
);
493 static struct window
*
494 decode_any_window (register Lisp_Object window
)
497 return XWINDOW (selected_window
);
499 CHECK_WINDOW (window
);
500 return XWINDOW (window
);
503 DEFUN ("window-buffer", Fwindow_buffer
, Swindow_buffer
, 0, 1, 0,
504 doc
: /* Return the buffer that WINDOW is displaying.
505 WINDOW defaults to the selected window. */)
508 return decode_window (window
)->buffer
;
511 DEFUN ("window-height", Fwindow_height
, Swindow_height
, 0, 1, 0,
512 doc
: /* Return the number of lines in WINDOW.
513 WINDOW defaults to the selected window.
515 The return value includes WINDOW's mode line and header line, if any.
517 Note: The function does not take into account the value of `line-spacing'
518 when calculating the number of lines in WINDOW. */)
521 return decode_any_window (window
)->total_lines
;
524 DEFUN ("window-width", Fwindow_width
, Swindow_width
, 0, 1, 0,
525 doc
: /* Return the number of display columns in WINDOW.
526 WINDOW defaults to the selected window.
528 Note: The return value is the number of columns available for text in
529 WINDOW. If you want to find out how many columns WINDOW takes up, use
530 (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
533 return make_number (window_box_text_cols (decode_any_window (window
)));
536 DEFUN ("window-full-width-p", Fwindow_full_width_p
, Swindow_full_width_p
, 0, 1, 0,
537 doc
: /* Return t if WINDOW is as wide as its frame.
538 WINDOW defaults to the selected window. */)
541 return WINDOW_FULL_WIDTH_P (decode_any_window (window
)) ? Qt
: Qnil
;
544 DEFUN ("window-hscroll", Fwindow_hscroll
, Swindow_hscroll
, 0, 1, 0,
545 doc
: /* Return the number of columns by which WINDOW is scrolled from left margin.
546 WINDOW defaults to the selected window. */)
549 return decode_window (window
)->hscroll
;
552 DEFUN ("set-window-hscroll", Fset_window_hscroll
, Sset_window_hscroll
, 2, 2, 0,
553 doc
: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
554 Return NCOL. NCOL should be zero or positive.
556 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
557 window so that the location of point moves off-window. */)
558 (Lisp_Object window
, Lisp_Object ncol
)
560 struct window
*w
= decode_window (window
);
564 hscroll
= max (0, XINT (ncol
));
566 /* Prevent redisplay shortcuts when changing the hscroll. */
567 if (XINT (w
->hscroll
) != hscroll
)
568 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
570 w
->hscroll
= make_number (hscroll
);
574 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger
,
575 Swindow_redisplay_end_trigger
, 0, 1, 0,
576 doc
: /* Return WINDOW's redisplay end trigger value.
577 WINDOW defaults to the selected window.
578 See `set-window-redisplay-end-trigger' for more information. */)
581 return decode_window (window
)->redisplay_end_trigger
;
584 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger
,
585 Sset_window_redisplay_end_trigger
, 2, 2, 0,
586 doc
: /* Set WINDOW's redisplay end trigger value to VALUE.
587 VALUE should be a buffer position (typically a marker) or nil.
588 If it is a buffer position, then if redisplay in WINDOW reaches a position
589 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
590 with two arguments: WINDOW, and the end trigger value.
591 Afterwards the end-trigger value is reset to nil. */)
592 (register Lisp_Object window
, Lisp_Object value
)
594 register struct window
*w
;
596 w
= decode_window (window
);
597 w
->redisplay_end_trigger
= value
;
601 DEFUN ("window-edges", Fwindow_edges
, Swindow_edges
, 0, 1, 0,
602 doc
: /* Return a list of the edge coordinates of WINDOW.
603 The list has the form (LEFT TOP RIGHT BOTTOM).
604 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
605 all relative to 0, 0 at top left corner of frame.
607 RIGHT is one more than the rightmost column occupied by WINDOW.
608 BOTTOM is one more than the bottommost row occupied by WINDOW.
609 The edges include the space used by WINDOW's scroll bar, display
610 margins, fringes, header line, and/or mode line. For the edges of
611 just the text area, use `window-inside-edges'. */)
614 register struct window
*w
= decode_any_window (window
);
616 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w
)),
617 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w
)),
618 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w
)),
619 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w
)),
623 DEFUN ("window-pixel-edges", Fwindow_pixel_edges
, Swindow_pixel_edges
, 0, 1, 0,
624 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
625 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
626 the top left corner of the frame.
628 RIGHT is one more than the rightmost x position occupied by WINDOW.
629 BOTTOM is one more than the bottommost y position occupied by WINDOW.
630 The pixel edges include the space used by WINDOW's scroll bar, display
631 margins, fringes, header line, and/or mode line. For the pixel edges
632 of just the text area, use `window-inside-pixel-edges'. */)
635 register struct window
*w
= decode_any_window (window
);
637 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w
)),
638 Fcons (make_number (WINDOW_TOP_EDGE_Y (w
)),
639 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w
)),
640 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w
)),
645 calc_absolute_offset(struct window
*w
, int *add_x
, int *add_y
)
647 struct frame
*f
= XFRAME (w
->frame
);
649 #ifdef FRAME_MENUBAR_HEIGHT
650 *add_y
+= FRAME_MENUBAR_HEIGHT (f
);
652 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
653 *add_y
+= FRAME_TOOLBAR_TOP_HEIGHT (f
);
654 #elif FRAME_TOOLBAR_HEIGHT
655 *add_y
+= FRAME_TOOLBAR_HEIGHT (f
);
657 #ifdef FRAME_NS_TITLEBAR_HEIGHT
658 *add_y
+= FRAME_NS_TITLEBAR_HEIGHT (f
);
660 *add_x
= f
->left_pos
;
661 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
662 *add_x
+= FRAME_TOOLBAR_LEFT_WIDTH (f
);
666 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges
,
667 Swindow_absolute_pixel_edges
, 0, 1, 0,
668 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
669 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
670 the top left corner of the display.
672 RIGHT is one more than the rightmost x position occupied by WINDOW.
673 BOTTOM is one more than the bottommost y position occupied by WINDOW.
674 The pixel edges include the space used by WINDOW's scroll bar, display
675 margins, fringes, header line, and/or mode line. For the pixel edges
676 of just the text area, use `window-inside-absolute-pixel-edges'. */)
679 register struct window
*w
= decode_any_window (window
);
681 calc_absolute_offset (w
, &add_x
, &add_y
);
683 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w
) + add_x
),
684 Fcons (make_number (WINDOW_TOP_EDGE_Y (w
) + add_y
),
685 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w
) + add_x
),
686 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w
) + add_y
),
690 DEFUN ("window-inside-edges", Fwindow_inside_edges
, Swindow_inside_edges
, 0, 1, 0,
691 doc
: /* Return a list of the edge coordinates of WINDOW.
692 The list has the form (LEFT TOP RIGHT BOTTOM).
693 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
694 all relative to 0, 0 at top left corner of frame.
696 RIGHT is one more than the rightmost column of WINDOW's text area.
697 BOTTOM is one more than the bottommost row of WINDOW's text area.
698 The inside edges do not include the space used by the WINDOW's scroll
699 bar, display margins, fringes, header line, and/or mode line. */)
702 register struct window
*w
= decode_any_window (window
);
704 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w
)
705 + WINDOW_LEFT_MARGIN_COLS (w
)
706 + WINDOW_LEFT_FRINGE_COLS (w
)),
707 make_number (WINDOW_TOP_EDGE_LINE (w
)
708 + WINDOW_HEADER_LINE_LINES (w
)),
709 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w
)
710 - WINDOW_RIGHT_MARGIN_COLS (w
)
711 - WINDOW_RIGHT_FRINGE_COLS (w
)),
712 make_number (WINDOW_BOTTOM_EDGE_LINE (w
)
713 - WINDOW_MODE_LINE_LINES (w
)));
716 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges
, Swindow_inside_pixel_edges
, 0, 1, 0,
717 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
718 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
719 the top left corner of the frame.
721 RIGHT is one more than the rightmost x position of WINDOW's text area.
722 BOTTOM is one more than the bottommost y position of WINDOW's text area.
723 The inside edges do not include the space used by WINDOW's scroll bar,
724 display margins, fringes, header line, and/or mode line. */)
727 register struct window
*w
= decode_any_window (window
);
729 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w
)
730 + WINDOW_LEFT_MARGIN_WIDTH (w
)
731 + WINDOW_LEFT_FRINGE_WIDTH (w
)),
732 make_number (WINDOW_TOP_EDGE_Y (w
)
733 + WINDOW_HEADER_LINE_HEIGHT (w
)),
734 make_number (WINDOW_BOX_RIGHT_EDGE_X (w
)
735 - WINDOW_RIGHT_MARGIN_WIDTH (w
)
736 - WINDOW_RIGHT_FRINGE_WIDTH (w
)),
737 make_number (WINDOW_BOTTOM_EDGE_Y (w
)
738 - WINDOW_MODE_LINE_HEIGHT (w
)));
741 DEFUN ("window-inside-absolute-pixel-edges",
742 Fwindow_inside_absolute_pixel_edges
,
743 Swindow_inside_absolute_pixel_edges
, 0, 1, 0,
744 doc
: /* Return a list of the edge pixel coordinates of WINDOW.
745 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
746 the top left corner of the display.
748 RIGHT is one more than the rightmost x position of WINDOW's text area.
749 BOTTOM is one more than the bottommost y position of WINDOW's text area.
750 The inside edges do not include the space used by WINDOW's scroll bar,
751 display margins, fringes, header line, and/or mode line. */)
754 register struct window
*w
= decode_any_window (window
);
756 calc_absolute_offset (w
, &add_x
, &add_y
);
758 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w
)
759 + WINDOW_LEFT_MARGIN_WIDTH (w
)
760 + WINDOW_LEFT_FRINGE_WIDTH (w
) + add_x
),
761 make_number (WINDOW_TOP_EDGE_Y (w
)
762 + WINDOW_HEADER_LINE_HEIGHT (w
) + add_y
),
763 make_number (WINDOW_BOX_RIGHT_EDGE_X (w
)
764 - WINDOW_RIGHT_MARGIN_WIDTH (w
)
765 - WINDOW_RIGHT_FRINGE_WIDTH (w
) + add_x
),
766 make_number (WINDOW_BOTTOM_EDGE_Y (w
)
767 - WINDOW_MODE_LINE_HEIGHT (w
) + add_y
));
770 /* Test if the character at column X, row Y is within window W.
771 If it is not, return ON_NOTHING;
772 if it is in the window's text area, return ON_TEXT;
773 if it is on the window's modeline, return ON_MODE_LINE;
774 if it is on the border between the window and its right sibling,
775 return ON_VERTICAL_BORDER.
776 if it is on a scroll bar, return ON_SCROLL_BAR.
777 if it is on the window's top line, return ON_HEADER_LINE;
778 if it is in left or right fringe of the window,
779 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
780 if it is in the marginal area to the left/right of the window,
781 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
783 X and Y are frame relative pixel coordinates. */
785 static enum window_part
786 coordinates_in_window (register struct window
*w
, int x
, int y
)
788 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
790 enum window_part part
;
791 int ux
= FRAME_COLUMN_WIDTH (f
);
792 int x0
= WINDOW_LEFT_EDGE_X (w
);
793 int x1
= WINDOW_RIGHT_EDGE_X (w
);
794 /* The width of the area where the vertical line can be dragged.
795 (Between mode lines for instance. */
796 int grabbable_width
= ux
;
797 int lmargin_width
, rmargin_width
, text_left
, text_right
;
798 int top_y
= WINDOW_TOP_EDGE_Y (w
);
799 int bottom_y
= WINDOW_BOTTOM_EDGE_Y (w
);
801 /* Outside any interesting row? */
802 if (y
< top_y
|| y
>= bottom_y
)
805 /* In what's below, we subtract 1 when computing right_x because we
806 want the rightmost pixel, which is given by left_pixel+width-1. */
807 if (w
->pseudo_window_p
)
810 right_x
= WINDOW_TOTAL_WIDTH (w
) - 1;
814 left_x
= WINDOW_BOX_LEFT_EDGE_X (w
);
815 right_x
= WINDOW_BOX_RIGHT_EDGE_X (w
) - 1;
818 /* On the mode line or header line? If it's near the start of
819 the mode or header line of window that's has a horizontal
820 sibling, say it's on the vertical line. That's to be able
821 to resize windows horizontally in case we're using toolkit
824 if (WINDOW_WANTS_MODELINE_P (w
)
825 && y
>= bottom_y
- CURRENT_MODE_LINE_HEIGHT (w
))
829 header_vertical_border_check
:
830 /* We're somewhere on the mode line. We consider the place
831 between mode lines of horizontally adjacent mode lines
832 as the vertical border. If scroll bars on the left,
833 return the right window. */
834 if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w
)
835 || WINDOW_RIGHTMOST_P (w
))
836 && !WINDOW_LEFTMOST_P (w
)
837 && eabs (x
- x0
) < grabbable_width
)
838 return ON_VERTICAL_BORDER
;
840 /* Make sure we're not at the rightmost position of a
841 mode-/header-line and there's yet another window on the
843 else if ((WINDOW_RIGHTMOST_P (w
) || x
< x1
)
844 && eabs (x
- x1
) < grabbable_width
)
845 return ON_VERTICAL_BORDER
;
847 if (x
< x0
|| x
>= x1
)
853 if (WINDOW_WANTS_HEADER_LINE_P (w
)
854 && y
< top_y
+ CURRENT_HEADER_LINE_HEIGHT (w
))
856 part
= ON_HEADER_LINE
;
857 goto header_vertical_border_check
;
860 if (x
< x0
|| x
>= x1
) return ON_NOTHING
;
862 /* Outside any interesting column? */
863 if (x
< left_x
|| x
> right_x
)
864 return ON_SCROLL_BAR
;
866 lmargin_width
= window_box_width (w
, LEFT_MARGIN_AREA
);
867 rmargin_width
= window_box_width (w
, RIGHT_MARGIN_AREA
);
869 text_left
= window_box_left (w
, TEXT_AREA
);
870 text_right
= text_left
+ window_box_width (w
, TEXT_AREA
);
872 if (FRAME_WINDOW_P (f
))
874 if (!w
->pseudo_window_p
875 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w
)
876 && !WINDOW_RIGHTMOST_P (w
)
877 && (eabs (x
- right_x
) < grabbable_width
))
878 return ON_VERTICAL_BORDER
;
880 /* Need to say "x > right_x" rather than >=, since on character
881 terminals, the vertical line's x coordinate is right_x. */
882 else if (!w
->pseudo_window_p
883 && !WINDOW_RIGHTMOST_P (w
)
885 return ON_VERTICAL_BORDER
;
889 if (lmargin_width
> 0
890 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
891 ? (x
>= left_x
+ WINDOW_LEFT_FRINGE_WIDTH (w
))
892 : (x
< left_x
+ lmargin_width
)))
893 return ON_LEFT_MARGIN
;
895 return ON_LEFT_FRINGE
;
900 if (rmargin_width
> 0
901 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
902 ? (x
< right_x
- WINDOW_RIGHT_FRINGE_WIDTH (w
))
903 : (x
>= right_x
- rmargin_width
)))
904 return ON_RIGHT_MARGIN
;
906 return ON_RIGHT_FRINGE
;
909 /* Everything special ruled out - must be on text area */
913 /* Take X is the frame-relative pixel x-coordinate, and return the
914 x-coordinate relative to part PART of window W. */
916 window_relative_x_coord (struct window
*w
, enum window_part part
, int x
)
918 int left_x
= (w
->pseudo_window_p
) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w
);
923 return x
- window_box_left (w
, TEXT_AREA
);
928 case ON_RIGHT_FRINGE
:
929 return x
- left_x
- WINDOW_LEFT_FRINGE_WIDTH (w
);
933 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
))
934 ? WINDOW_LEFT_FRINGE_WIDTH (w
) : 0));
936 case ON_RIGHT_MARGIN
:
938 - ((w
->pseudo_window_p
)
939 ? WINDOW_TOTAL_WIDTH (w
)
940 : WINDOW_BOX_RIGHT_EDGE_X (w
))
941 + window_box_width (w
, RIGHT_MARGIN_AREA
)
942 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
))
943 ? WINDOW_RIGHT_FRINGE_WIDTH (w
) : 0));
946 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
951 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p
,
952 Scoordinates_in_window_p
, 2, 2, 0,
953 doc
: /* Return non-nil if COORDINATES are in WINDOW.
954 COORDINATES is a cons of the form (X . Y), X and Y being distances
955 measured in characters from the upper-left corner of the frame.
956 \(0 . 0) denotes the character in the upper left corner of the
958 If COORDINATES are in the text portion of WINDOW,
959 the coordinates relative to the window are returned.
960 If they are in the mode line of WINDOW, `mode-line' is returned.
961 If they are in the top mode line of WINDOW, `header-line' is returned.
962 If they are in the left fringe of WINDOW, `left-fringe' is returned.
963 If they are in the right fringe of WINDOW, `right-fringe' is returned.
964 If they are on the border between WINDOW and its right sibling,
965 `vertical-line' is returned.
966 If they are in the windows's left or right marginal areas, `left-margin'\n\
967 or `right-margin' is returned. */)
968 (register Lisp_Object coordinates
, Lisp_Object window
)
975 CHECK_WINDOW (window
);
976 w
= XWINDOW (window
);
977 f
= XFRAME (w
->frame
);
978 CHECK_CONS (coordinates
);
979 lx
= Fcar (coordinates
);
980 ly
= Fcdr (coordinates
);
981 CHECK_NUMBER_OR_FLOAT (lx
);
982 CHECK_NUMBER_OR_FLOAT (ly
);
983 x
= FRAME_PIXEL_X_FROM_CANON_X (f
, lx
) + FRAME_INTERNAL_BORDER_WIDTH (f
);
984 y
= FRAME_PIXEL_Y_FROM_CANON_Y (f
, ly
) + FRAME_INTERNAL_BORDER_WIDTH (f
);
986 switch (coordinates_in_window (w
, x
, y
))
992 /* Convert X and Y to window relative pixel coordinates, and
993 return the canonical char units. */
994 x
-= window_box_left (w
, TEXT_AREA
);
995 y
-= WINDOW_TOP_EDGE_Y (w
);
996 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f
, x
),
997 FRAME_CANON_Y_FROM_PIXEL_Y (f
, y
));
1002 case ON_VERTICAL_BORDER
:
1003 return Qvertical_line
;
1005 case ON_HEADER_LINE
:
1006 return Qheader_line
;
1008 case ON_LEFT_FRINGE
:
1009 return Qleft_fringe
;
1011 case ON_RIGHT_FRINGE
:
1012 return Qright_fringe
;
1014 case ON_LEFT_MARGIN
:
1015 return Qleft_margin
;
1017 case ON_RIGHT_MARGIN
:
1018 return Qright_margin
;
1021 /* Historically we are supposed to return nil in this case. */
1030 /* Callback for foreach_window, used in window_from_coordinates.
1031 Check if window W contains coordinates specified by USER_DATA which
1032 is actually a pointer to a struct check_window_data CW.
1034 Check if window W contains coordinates *CW->x and *CW->y. If it
1035 does, return W in *CW->window, as Lisp_Object, and return in
1036 *CW->part the part of the window under coordinates *X,*Y. Return
1037 zero from this function to stop iterating over windows. */
1039 struct check_window_data
1041 Lisp_Object
*window
;
1043 enum window_part
*part
;
1047 check_window_containing (struct window
*w
, void *user_data
)
1049 struct check_window_data
*cw
= (struct check_window_data
*) user_data
;
1050 enum window_part found
;
1053 found
= coordinates_in_window (w
, cw
->x
, cw
->y
);
1054 if (found
!= ON_NOTHING
)
1057 XSETWINDOW (*cw
->window
, w
);
1065 /* Find the window containing frame-relative pixel position X/Y and
1066 return it as a Lisp_Object.
1068 If X, Y is on one of the window's special `window_part' elements,
1069 set *PART to the id of that element.
1071 If there is no window under X, Y return nil and leave *PART
1072 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1074 This function was previously implemented with a loop cycling over
1075 windows with Fnext_window, and starting with the frame's selected
1076 window. It turned out that this doesn't work with an
1077 implementation of next_window using Vwindow_list, because
1078 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1079 tree of F when this function is called asynchronously from
1080 note_mouse_highlight. The original loop didn't terminate in this
1084 window_from_coordinates (struct frame
*f
, int x
, int y
,
1085 enum window_part
*part
, int tool_bar_p
)
1088 struct check_window_data cw
;
1089 enum window_part dummy
;
1095 cw
.window
= &window
, cw
.x
= x
, cw
.y
= y
; cw
.part
= part
;
1096 foreach_window (f
, check_window_containing
, &cw
);
1098 /* If not found above, see if it's in the tool bar window, if a tool
1102 && WINDOWP (f
->tool_bar_window
)
1103 && WINDOW_TOTAL_LINES (XWINDOW (f
->tool_bar_window
)) > 0
1104 && (coordinates_in_window (XWINDOW (f
->tool_bar_window
), x
, y
)
1108 window
= f
->tool_bar_window
;
1114 DEFUN ("window-at", Fwindow_at
, Swindow_at
, 2, 3, 0,
1115 doc
: /* Return window containing coordinates X and Y on FRAME.
1116 If omitted, FRAME defaults to the currently selected frame.
1117 The top left corner of the frame is considered to be row 0,
1119 (Lisp_Object x
, Lisp_Object y
, Lisp_Object frame
)
1124 frame
= selected_frame
;
1125 CHECK_LIVE_FRAME (frame
);
1128 /* Check that arguments are integers or floats. */
1129 CHECK_NUMBER_OR_FLOAT (x
);
1130 CHECK_NUMBER_OR_FLOAT (y
);
1132 return window_from_coordinates (f
,
1133 (FRAME_PIXEL_X_FROM_CANON_X (f
, x
)
1134 + FRAME_INTERNAL_BORDER_WIDTH (f
)),
1135 (FRAME_PIXEL_Y_FROM_CANON_Y (f
, y
)
1136 + FRAME_INTERNAL_BORDER_WIDTH (f
)),
1140 DEFUN ("window-point", Fwindow_point
, Swindow_point
, 0, 1, 0,
1141 doc
: /* Return current value of point in WINDOW.
1142 WINDOW defaults to the selected window.
1144 For a nonselected window, this is the value point would have
1145 if that window were selected.
1147 Note that, when WINDOW is the selected window and its buffer
1148 is also currently selected, the value returned is the same as (point).
1149 It would be more strictly correct to return the `top-level' value
1150 of point, outside of any save-excursion forms.
1151 But that is hard to define. */)
1152 (Lisp_Object window
)
1154 register struct window
*w
= decode_window (window
);
1156 if (w
== XWINDOW (selected_window
)
1157 && current_buffer
== XBUFFER (w
->buffer
))
1159 return Fmarker_position (w
->pointm
);
1162 DEFUN ("window-start", Fwindow_start
, Swindow_start
, 0, 1, 0,
1163 doc
: /* Return position at which display currently starts in WINDOW.
1164 WINDOW defaults to the selected window.
1165 This is updated by redisplay or by calling `set-window-start'. */)
1166 (Lisp_Object window
)
1168 return Fmarker_position (decode_window (window
)->start
);
1171 /* This is text temporarily removed from the doc string below.
1173 This function returns nil if the position is not currently known.
1174 That happens when redisplay is preempted and doesn't finish.
1175 If in that case you want to compute where the end of the window would
1176 have been if redisplay had finished, do this:
1178 (goto-char (window-start window))
1179 (vertical-motion (1- (window-height window)) window)
1182 DEFUN ("window-end", Fwindow_end
, Swindow_end
, 0, 2, 0,
1183 doc
: /* Return position at which display currently ends in WINDOW.
1184 WINDOW defaults to the selected window.
1185 This is updated by redisplay, when it runs to completion.
1186 Simply changing the buffer text or setting `window-start'
1187 does not update this value.
1188 Return nil if there is no recorded value. \(This can happen if the
1189 last redisplay of WINDOW was preempted, and did not finish.)
1190 If UPDATE is non-nil, compute the up-to-date position
1191 if it isn't already recorded. */)
1192 (Lisp_Object window
, Lisp_Object update
)
1195 struct window
*w
= decode_window (window
);
1203 #if 0 /* This change broke some things. We should make it later. */
1204 /* If we don't know the end position, return nil.
1205 The user can compute it with vertical-motion if he wants to.
1206 It would be nicer to do it automatically,
1207 but that's so slow that it would probably bother people. */
1208 if (NILP (w
->window_end_valid
))
1213 && ! (! NILP (w
->window_end_valid
)
1214 && XFASTINT (w
->last_modified
) >= BUF_MODIFF (b
)
1215 && XFASTINT (w
->last_overlay_modified
) >= BUF_OVERLAY_MODIFF (b
))
1218 struct text_pos startp
;
1220 struct buffer
*old_buffer
= NULL
;
1222 /* Cannot use Fvertical_motion because that function doesn't
1223 cope with variable-height lines. */
1224 if (b
!= current_buffer
)
1226 old_buffer
= current_buffer
;
1227 set_buffer_internal (b
);
1230 /* In case W->start is out of the range, use something
1231 reasonable. This situation occurred when loading a file with
1232 `-l' containing a call to `rmail' with subsequent other
1233 commands. At the end, W->start happened to be BEG, while
1234 rmail had already narrowed the buffer. */
1235 if (XMARKER (w
->start
)->charpos
< BEGV
)
1236 SET_TEXT_POS (startp
, BEGV
, BEGV_BYTE
);
1237 else if (XMARKER (w
->start
)->charpos
> ZV
)
1238 SET_TEXT_POS (startp
, ZV
, ZV_BYTE
);
1240 SET_TEXT_POS_FROM_MARKER (startp
, w
->start
);
1242 start_display (&it
, w
, startp
);
1243 move_it_vertically (&it
, window_box_height (w
));
1244 if (it
.current_y
< it
.last_visible_y
)
1245 move_it_past_eol (&it
);
1246 value
= make_number (IT_CHARPOS (it
));
1249 set_buffer_internal (old_buffer
);
1252 XSETINT (value
, BUF_Z (b
) - XFASTINT (w
->window_end_pos
));
1257 DEFUN ("set-window-point", Fset_window_point
, Sset_window_point
, 2, 2, 0,
1258 doc
: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1260 (Lisp_Object window
, Lisp_Object pos
)
1262 register struct window
*w
= decode_window (window
);
1264 CHECK_NUMBER_COERCE_MARKER (pos
);
1265 if (w
== XWINDOW (selected_window
)
1266 && XBUFFER (w
->buffer
) == current_buffer
)
1269 set_marker_restricted (w
->pointm
, pos
, w
->buffer
);
1271 /* We have to make sure that redisplay updates the window to show
1272 the new value of point. */
1273 if (!EQ (window
, selected_window
))
1274 ++windows_or_buffers_changed
;
1279 DEFUN ("set-window-start", Fset_window_start
, Sset_window_start
, 2, 3, 0,
1280 doc
: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1281 WINDOW defaults to the selected window. Return POS.
1282 Optional third arg NOFORCE non-nil inhibits next redisplay from
1283 overriding motion of point in order to display at this exact start. */)
1284 (Lisp_Object window
, Lisp_Object pos
, Lisp_Object noforce
)
1286 register struct window
*w
= decode_window (window
);
1288 CHECK_NUMBER_COERCE_MARKER (pos
);
1289 set_marker_restricted (w
->start
, pos
, w
->buffer
);
1290 /* this is not right, but much easier than doing what is right. */
1291 w
->start_at_line_beg
= Qnil
;
1293 w
->force_start
= Qt
;
1294 w
->update_mode_line
= Qt
;
1295 XSETFASTINT (w
->last_modified
, 0);
1296 XSETFASTINT (w
->last_overlay_modified
, 0);
1297 if (!EQ (window
, selected_window
))
1298 windows_or_buffers_changed
++;
1304 DEFUN ("window-dedicated-p", Fwindow_dedicated_p
, Swindow_dedicated_p
,
1306 doc
: /* Return non-nil when WINDOW is dedicated to its buffer.
1307 More precisely, return the value assigned by the last call of
1308 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1309 never called with WINDOW as its argument, or the value set by that
1310 function was internally reset since its last call. WINDOW defaults to
1311 the selected window.
1313 When a window is dedicated to its buffer, `display-buffer' will refrain
1314 from displaying another buffer in it. `get-lru-window' and
1315 `get-largest-window' treat dedicated windows specially.
1316 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1317 `kill-buffer' can delete a dedicated window and the containing frame.
1319 Functions like `set-window-buffer' may change the buffer displayed by a
1320 window, unless that window is "strongly" dedicated to its buffer, that
1321 is the value returned by `window-dedicated-p' is t. */)
1322 (Lisp_Object window
)
1324 return decode_window (window
)->dedicated
;
1327 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p
,
1328 Sset_window_dedicated_p
, 2, 2, 0,
1329 doc
: /* Mark WINDOW as dedicated according to FLAG.
1330 WINDOW defaults to the selected window. FLAG non-nil means mark WINDOW
1331 as dedicated to its buffer. FLAG nil means mark WINDOW as non-dedicated.
1334 When a window is dedicated to its buffer, `display-buffer' will refrain
1335 from displaying another buffer in it. `get-lru-window' and
1336 `get-largest-window' treat dedicated windows specially.
1337 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1338 `kill-buffer' can delete a dedicated window and the containing
1341 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1342 its buffer. Functions like `set-window-buffer' may change the buffer
1343 displayed by a window, unless that window is strongly dedicated to its
1344 buffer. If and when `set-window-buffer' displays another buffer in a
1345 window, it also makes sure that the window is not marked as dedicated. */)
1346 (Lisp_Object window
, Lisp_Object flag
)
1348 register struct window
*w
= decode_window (window
);
1350 w
->dedicated
= flag
;
1351 return w
->dedicated
;
1355 DEFUN ("window-parameters", Fwindow_parameters
, Swindow_parameters
,
1357 doc
: /* Return the parameters of WINDOW and their values.
1358 WINDOW defaults to the selected window. The return value is a list of
1359 elements of the form (PARAMETER . VALUE). */)
1360 (Lisp_Object window
)
1362 return Fcopy_alist (decode_window (window
)->window_parameters
);
1365 DEFUN ("window-parameter", Fwindow_parameter
, Swindow_parameter
,
1367 doc
: /* Return WINDOW's value for PARAMETER.
1368 WINDOW defaults to the selected window. */)
1369 (Lisp_Object window
, Lisp_Object parameter
)
1373 result
= Fassq (parameter
, decode_window (window
)->window_parameters
);
1374 return CDR_SAFE (result
);
1377 DEFUN ("set-window-parameter", Fset_window_parameter
,
1378 Sset_window_parameter
, 3, 3, 0,
1379 doc
: /* Set WINDOW's value of PARAMETER to VALUE.
1380 WINDOW defaults to the selected window. Return VALUE. */)
1381 (Lisp_Object window
, Lisp_Object parameter
, Lisp_Object value
)
1383 register struct window
*w
= decode_window (window
);
1384 Lisp_Object old_alist_elt
;
1386 old_alist_elt
= Fassq (parameter
, w
->window_parameters
);
1387 if (NILP (old_alist_elt
))
1388 w
->window_parameters
= Fcons (Fcons (parameter
, value
), w
->window_parameters
);
1390 Fsetcdr (old_alist_elt
, value
);
1395 DEFUN ("window-display-table", Fwindow_display_table
, Swindow_display_table
,
1397 doc
: /* Return the display-table that WINDOW is using.
1398 WINDOW defaults to the selected window. */)
1399 (Lisp_Object window
)
1401 return decode_window (window
)->display_table
;
1404 /* Get the display table for use on window W. This is either W's
1405 display table or W's buffer's display table. Ignore the specified
1406 tables if they are not valid; if no valid table is specified,
1409 struct Lisp_Char_Table
*
1410 window_display_table (struct window
*w
)
1412 struct Lisp_Char_Table
*dp
= NULL
;
1414 if (DISP_TABLE_P (w
->display_table
))
1415 dp
= XCHAR_TABLE (w
->display_table
);
1416 else if (BUFFERP (w
->buffer
))
1418 struct buffer
*b
= XBUFFER (w
->buffer
);
1420 if (DISP_TABLE_P (b
->display_table
))
1421 dp
= XCHAR_TABLE (b
->display_table
);
1422 else if (DISP_TABLE_P (Vstandard_display_table
))
1423 dp
= XCHAR_TABLE (Vstandard_display_table
);
1429 DEFUN ("set-window-display-table", Fset_window_display_table
, Sset_window_display_table
, 2, 2, 0,
1430 doc
: /* Set WINDOW's display-table to TABLE. */)
1431 (register Lisp_Object window
, Lisp_Object table
)
1433 register struct window
*w
;
1435 w
= decode_window (window
);
1436 w
->display_table
= table
;
1440 static void delete_window (Lisp_Object
);
1442 /* Record info on buffer window w is displaying
1443 when it is about to cease to display that buffer. */
1445 unshow_buffer (register struct window
*w
)
1452 if (b
!= XMARKER (w
->pointm
)->buffer
)
1456 if (w
== XWINDOW (selected_window
)
1457 || ! EQ (buf
, XWINDOW (selected_window
)->buffer
))
1458 /* Do this except when the selected window's buffer
1459 is being removed from some other window. */
1461 /* last_window_start records the start position that this buffer
1462 had in the last window to be disconnected from it.
1463 Now that this statement is unconditional,
1464 it is possible for the buffer to be displayed in the
1465 selected window, while last_window_start reflects another
1466 window which was recently showing the same buffer.
1467 Some people might say that might be a good thing. Let's see. */
1468 b
->last_window_start
= marker_position (w
->start
);
1470 /* Point in the selected window's buffer
1471 is actually stored in that buffer, and the window's pointm isn't used.
1472 So don't clobber point in that buffer. */
1473 if (! EQ (buf
, XWINDOW (selected_window
)->buffer
)
1474 /* This line helps to fix Horsley's testbug.el bug. */
1475 && !(WINDOWP (b
->last_selected_window
)
1476 && w
!= XWINDOW (b
->last_selected_window
)
1477 && EQ (buf
, XWINDOW (b
->last_selected_window
)->buffer
)))
1478 temp_set_point_both (b
,
1479 clip_to_bounds (BUF_BEGV (b
),
1480 XMARKER (w
->pointm
)->charpos
,
1482 clip_to_bounds (BUF_BEGV_BYTE (b
),
1483 marker_byte_position (w
->pointm
),
1486 if (WINDOWP (b
->last_selected_window
)
1487 && w
== XWINDOW (b
->last_selected_window
))
1488 b
->last_selected_window
= Qnil
;
1491 /* Put replacement into the window structure in place of old. */
1493 replace_window (Lisp_Object old
, Lisp_Object replacement
)
1495 register Lisp_Object tem
;
1496 register struct window
*o
= XWINDOW (old
), *p
= XWINDOW (replacement
);
1498 /* If OLD is its frame's root_window, then replacement is the new
1499 root_window for that frame. */
1501 if (EQ (old
, FRAME_ROOT_WINDOW (XFRAME (o
->frame
))))
1502 FRAME_ROOT_WINDOW (XFRAME (o
->frame
)) = replacement
;
1504 p
->left_col
= o
->left_col
;
1505 p
->top_line
= o
->top_line
;
1506 p
->total_cols
= o
->total_cols
;
1507 p
->total_lines
= o
->total_lines
;
1508 p
->desired_matrix
= p
->current_matrix
= 0;
1510 memset (&p
->cursor
, 0, sizeof (p
->cursor
));
1511 memset (&p
->last_cursor
, 0, sizeof (p
->last_cursor
));
1512 memset (&p
->phys_cursor
, 0, sizeof (p
->phys_cursor
));
1513 p
->phys_cursor_type
= -1;
1514 p
->phys_cursor_width
= -1;
1515 p
->must_be_updated_p
= 0;
1516 p
->pseudo_window_p
= 0;
1517 XSETFASTINT (p
->window_end_vpos
, 0);
1518 XSETFASTINT (p
->window_end_pos
, 0);
1519 p
->window_end_valid
= Qnil
;
1520 p
->frozen_window_start_p
= 0;
1521 p
->orig_top_line
= p
->orig_total_lines
= Qnil
;
1523 p
->next
= tem
= o
->next
;
1525 XWINDOW (tem
)->prev
= replacement
;
1527 p
->prev
= tem
= o
->prev
;
1529 XWINDOW (tem
)->next
= replacement
;
1531 p
->parent
= tem
= o
->parent
;
1534 if (EQ (XWINDOW (tem
)->vchild
, old
))
1535 XWINDOW (tem
)->vchild
= replacement
;
1536 if (EQ (XWINDOW (tem
)->hchild
, old
))
1537 XWINDOW (tem
)->hchild
= replacement
;
1540 /*** Here, if replacement is a vertical combination
1541 and so is its new parent, we should make replacement's
1542 children be children of that parent instead. ***/
1545 DEFUN ("delete-window", Fdelete_window
, Sdelete_window
, 0, 1, "",
1546 doc
: /* Remove WINDOW from its frame.
1547 WINDOW defaults to the selected window. Return nil.
1548 Signal an error when WINDOW is the only window on its frame. */)
1549 (register Lisp_Object window
)
1553 window
= selected_window
;
1555 CHECK_LIVE_WINDOW (window
);
1557 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
1558 delete_window (window
);
1560 run_window_configuration_change_hook (f
);
1566 delete_window (register Lisp_Object window
)
1568 register Lisp_Object tem
, parent
, sib
;
1569 register struct window
*p
;
1570 register struct window
*par
;
1573 /* Because this function is called by other C code on non-leaf
1574 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1575 so we can't decode_window here. */
1576 CHECK_WINDOW (window
);
1577 p
= XWINDOW (window
);
1579 /* It's a no-op to delete an already-deleted window. */
1580 if (NILP (p
->buffer
)
1582 && NILP (p
->vchild
))
1587 error ("Attempt to delete minibuffer or sole ordinary window");
1588 par
= XWINDOW (parent
);
1590 windows_or_buffers_changed
++;
1591 Vwindow_list
= Qnil
;
1592 f
= XFRAME (WINDOW_FRAME (p
));
1593 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
1595 /* Are we trying to delete any frame's selected window? */
1597 Lisp_Object swindow
, pwindow
;
1599 /* See if the frame's selected window is either WINDOW
1600 or any subwindow of it, by finding all that window's parents
1601 and comparing each one with WINDOW. */
1602 swindow
= FRAME_SELECTED_WINDOW (f
);
1607 while (!NILP (pwindow
))
1609 if (EQ (window
, pwindow
))
1611 pwindow
= XWINDOW (pwindow
)->parent
;
1614 /* If the window being deleted is not a parent of SWINDOW,
1615 then SWINDOW is ok as the new selected window. */
1616 if (!EQ (window
, pwindow
))
1618 /* Otherwise, try another window for SWINDOW. */
1619 swindow
= Fnext_window (swindow
, Qlambda
, Qnil
);
1621 /* If we get back to the frame's selected window,
1622 it means there was no acceptable alternative,
1623 so we cannot delete. */
1624 if (EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1625 error ("Cannot delete window");
1628 /* If we need to change SWINDOW, do it. */
1629 if (! EQ (swindow
, FRAME_SELECTED_WINDOW (f
)))
1631 /* If we're about to delete the selected window on the
1632 selected frame, then we should use Fselect_window to select
1633 the new window. On the other hand, if we're about to
1634 delete the selected window on any other frame, we shouldn't do
1635 anything but set the frame's selected_window slot. */
1636 if (EQ (FRAME_SELECTED_WINDOW (f
), selected_window
))
1637 Fselect_window (swindow
, Qnil
);
1639 FRAME_SELECTED_WINDOW (f
) = swindow
;
1643 /* Now we know we can delete this one. */
1644 window_deletion_count
++;
1647 /* tem is null for dummy parent windows
1648 (which have inferiors but not any contents themselves) */
1652 unchain_marker (XMARKER (p
->pointm
));
1653 unchain_marker (XMARKER (p
->start
));
1656 /* Free window glyph matrices. It is sure that they are allocated
1657 again when ADJUST_GLYPHS is called. Block input so that expose
1658 events and other events that access glyph matrices are not
1659 processed while we are changing them. */
1661 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f
)));
1665 XWINDOW (tem
)->prev
= p
->prev
;
1669 XWINDOW (tem
)->next
= p
->next
;
1671 if (EQ (window
, par
->hchild
))
1672 par
->hchild
= p
->next
;
1673 if (EQ (window
, par
->vchild
))
1674 par
->vchild
= p
->next
;
1676 /* Find one of our siblings to give our space to. */
1680 /* If p gives its space to its next sibling, that sibling needs
1681 to have its top/left side pulled back to where p's is.
1682 set_window_{height,width} will re-position the sibling's
1685 XWINDOW (sib
)->top_line
= p
->top_line
;
1686 XWINDOW (sib
)->left_col
= p
->left_col
;
1689 /* Stretch that sibling. */
1690 if (!NILP (par
->vchild
))
1691 set_window_height (sib
,
1692 XFASTINT (XWINDOW (sib
)->total_lines
) + XFASTINT (p
->total_lines
),
1694 if (!NILP (par
->hchild
))
1695 set_window_width (sib
,
1696 XFASTINT (XWINDOW (sib
)->total_cols
) + XFASTINT (p
->total_cols
),
1699 /* If parent now has only one child,
1700 put the child into the parent's place. */
1704 if (NILP (XWINDOW (tem
)->next
)) {
1705 replace_window (parent
, tem
);
1706 par
= XWINDOW (tem
);
1709 /* Since we may be deleting combination windows, we must make sure that
1710 not only p but all its children have been marked as deleted. */
1711 if (! NILP (p
->hchild
))
1712 delete_all_subwindows (XWINDOW (p
->hchild
));
1713 else if (! NILP (p
->vchild
))
1714 delete_all_subwindows (XWINDOW (p
->vchild
));
1716 /* Mark this window as deleted. */
1717 p
->buffer
= p
->hchild
= p
->vchild
= Qnil
;
1719 if (! NILP (par
->parent
))
1720 par
= XWINDOW (par
->parent
);
1722 /* Check if we have a v/hchild with a v/hchild. In that case remove
1725 if (! NILP (par
->vchild
) && ! NILP (XWINDOW (par
->vchild
)->vchild
))
1727 p
= XWINDOW (par
->vchild
);
1728 par
->vchild
= p
->vchild
;
1731 else if (! NILP (par
->hchild
) && ! NILP (XWINDOW (par
->hchild
)->hchild
))
1733 p
= XWINDOW (par
->hchild
);
1734 par
->hchild
= p
->hchild
;
1742 while (! NILP (tem
)) {
1743 XWINDOW (tem
)->parent
= p
->parent
;
1744 if (NILP (XWINDOW (tem
)->next
))
1746 tem
= XWINDOW (tem
)->next
;
1749 /* The next of the v/hchild we are removing is now the next of the
1750 last child for the v/hchild:
1751 Before v/hchild -> v/hchild -> next1 -> next2
1754 After: v/hchild -> next1 -> next2 -> next3
1756 XWINDOW (tem
)->next
= p
->next
;
1757 if (! NILP (p
->next
))
1758 XWINDOW (p
->next
)->prev
= tem
;
1760 p
->next
= p
->prev
= p
->vchild
= p
->hchild
= p
->buffer
= Qnil
;
1764 /* Adjust glyph matrices. */
1771 /***********************************************************************
1773 ***********************************************************************/
1775 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1776 pointer. This is a callback function for foreach_window, used in
1777 function window_list. */
1780 add_window_to_list (struct window
*w
, void *user_data
)
1782 Lisp_Object
*list
= (Lisp_Object
*) user_data
;
1784 XSETWINDOW (window
, w
);
1785 *list
= Fcons (window
, *list
);
1790 /* Return a list of all windows, for use by next_window. If
1791 Vwindow_list is a list, return that list. Otherwise, build a new
1792 list, cache it in Vwindow_list, and return that. */
1797 if (!CONSP (Vwindow_list
))
1801 Vwindow_list
= Qnil
;
1802 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
1804 Lisp_Object args
[2];
1806 /* We are visiting windows in canonical order, and add
1807 new windows at the front of args[1], which means we
1808 have to reverse this list at the end. */
1810 foreach_window (XFRAME (XCAR (tail
)), add_window_to_list
, &args
[1]);
1811 args
[0] = Vwindow_list
;
1812 args
[1] = Fnreverse (args
[1]);
1813 Vwindow_list
= Fnconc (2, args
);
1817 return Vwindow_list
;
1821 /* Value is non-zero if WINDOW satisfies the constraints given by
1822 OWINDOW, MINIBUF and ALL_FRAMES.
1824 MINIBUF t means WINDOW may be minibuffer windows.
1825 `lambda' means WINDOW may not be a minibuffer window.
1826 a window means a specific minibuffer window
1828 ALL_FRAMES t means search all frames,
1829 nil means search just current frame,
1830 `visible' means search just visible frames,
1831 0 means search visible and iconified frames,
1832 a window means search the frame that window belongs to,
1833 a frame means consider windows on that frame, only. */
1836 candidate_window_p (Lisp_Object window
, Lisp_Object owindow
, Lisp_Object minibuf
, Lisp_Object all_frames
)
1838 struct window
*w
= XWINDOW (window
);
1839 struct frame
*f
= XFRAME (w
->frame
);
1840 int candidate_p
= 1;
1842 if (!BUFFERP (w
->buffer
))
1844 else if (MINI_WINDOW_P (w
)
1845 && (EQ (minibuf
, Qlambda
)
1846 || (WINDOWP (minibuf
) && !EQ (minibuf
, window
))))
1848 /* If MINIBUF is `lambda' don't consider any mini-windows.
1849 If it is a window, consider only that one. */
1852 else if (EQ (all_frames
, Qt
))
1854 else if (NILP (all_frames
))
1856 xassert (WINDOWP (owindow
));
1857 candidate_p
= EQ (w
->frame
, XWINDOW (owindow
)->frame
);
1859 else if (EQ (all_frames
, Qvisible
))
1861 FRAME_SAMPLE_VISIBILITY (f
);
1862 candidate_p
= FRAME_VISIBLE_P (f
)
1863 && (FRAME_TERMINAL (XFRAME (w
->frame
))
1864 == FRAME_TERMINAL (XFRAME (selected_frame
)));
1867 else if (INTEGERP (all_frames
) && XINT (all_frames
) == 0)
1869 FRAME_SAMPLE_VISIBILITY (f
);
1870 candidate_p
= (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
)
1871 #ifdef HAVE_X_WINDOWS
1872 /* Yuck!! If we've just created the frame and the
1873 window-manager requested the user to place it
1874 manually, the window may still not be considered
1875 `visible'. I'd argue it should be at least
1876 something like `iconified', but don't know how to do
1878 || (FRAME_X_P (f
) && f
->output_data
.x
->asked_for_visible
1879 && !f
->output_data
.x
->has_been_visible
)
1882 && (FRAME_TERMINAL (XFRAME (w
->frame
))
1883 == FRAME_TERMINAL (XFRAME (selected_frame
)));
1885 else if (WINDOWP (all_frames
))
1886 candidate_p
= (EQ (FRAME_MINIBUF_WINDOW (f
), all_frames
)
1887 || EQ (XWINDOW (all_frames
)->frame
, w
->frame
)
1888 || EQ (XWINDOW (all_frames
)->frame
, FRAME_FOCUS_FRAME (f
)));
1889 else if (FRAMEP (all_frames
))
1890 candidate_p
= EQ (all_frames
, w
->frame
);
1896 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1897 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1901 decode_next_window_args (Lisp_Object
*window
, Lisp_Object
*minibuf
, Lisp_Object
*all_frames
)
1904 *window
= selected_window
;
1906 CHECK_LIVE_WINDOW (*window
);
1908 /* MINIBUF nil may or may not include minibuffers. Decide if it
1910 if (NILP (*minibuf
))
1911 *minibuf
= minibuf_level
? minibuf_window
: Qlambda
;
1912 else if (!EQ (*minibuf
, Qt
))
1915 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1916 => count none of them, or a specific minibuffer window (the
1917 active one) to count. */
1919 /* ALL_FRAMES nil doesn't specify which frames to include. */
1920 if (NILP (*all_frames
))
1921 *all_frames
= (!EQ (*minibuf
, Qlambda
)
1922 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window
)->frame
))
1924 else if (EQ (*all_frames
, Qvisible
))
1926 else if (EQ (*all_frames
, make_number (0)))
1928 else if (FRAMEP (*all_frames
))
1930 else if (!EQ (*all_frames
, Qt
))
1933 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1934 search just current frame, `visible' meaning search just visible
1935 frames, 0 meaning search visible and iconified frames, or a
1936 window, meaning search the frame that window belongs to, or a
1937 frame, meaning consider windows on that frame, only. */
1941 /* Return the next or previous window of WINDOW in cyclic ordering
1942 of windows. NEXT_P non-zero means return the next window. See the
1943 documentation string of next-window for the meaning of MINIBUF and
1947 next_window (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
, int next_p
)
1949 decode_next_window_args (&window
, &minibuf
, &all_frames
);
1951 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1952 return the first window on the frame. */
1953 if (FRAMEP (all_frames
)
1954 && !EQ (all_frames
, XWINDOW (window
)->frame
))
1955 return Fframe_first_window (all_frames
);
1961 /* Find WINDOW in the list of all windows. */
1962 list
= Fmemq (window
, window_list ());
1964 /* Scan forward from WINDOW to the end of the window list. */
1966 for (list
= XCDR (list
); CONSP (list
); list
= XCDR (list
))
1967 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1970 /* Scan from the start of the window list up to WINDOW. */
1972 for (list
= Vwindow_list
;
1973 CONSP (list
) && !EQ (XCAR (list
), window
);
1975 if (candidate_window_p (XCAR (list
), window
, minibuf
, all_frames
))
1979 window
= XCAR (list
);
1983 Lisp_Object candidate
, list
;
1985 /* Scan through the list of windows for candidates. If there are
1986 candidate windows in front of WINDOW, the last one of these
1987 is the one we want. If there are candidates following WINDOW
1988 in the list, again the last one of these is the one we want. */
1990 for (list
= window_list (); CONSP (list
); list
= XCDR (list
))
1992 if (EQ (XCAR (list
), window
))
1994 if (WINDOWP (candidate
))
1997 else if (candidate_window_p (XCAR (list
), window
, minibuf
,
1999 candidate
= XCAR (list
);
2002 if (WINDOWP (candidate
))
2010 DEFUN ("next-window", Fnext_window
, Snext_window
, 0, 3, 0,
2011 doc
: /* Return window following WINDOW in cyclic ordering of windows.
2012 WINDOW defaults to the selected window. The optional arguments
2013 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2015 MINIBUF t means consider the minibuffer window even if the
2016 minibuffer is not active. MINIBUF nil or omitted means consider
2017 the minibuffer window only if the minibuffer is active. Any
2018 other value means do not consider the minibuffer window even if
2019 the minibuffer is active.
2021 Several frames may share a single minibuffer; if the minibuffer
2022 is active, all windows on all frames that share that minibuffer
2023 are considered too. Therefore, if you are using a separate
2024 minibuffer frame and the minibuffer is active and MINIBUF says it
2025 counts, `next-window' considers the windows in the frame from
2026 which you entered the minibuffer, as well as the minibuffer
2029 ALL-FRAMES nil or omitted means consider all windows on WINDOW's
2030 frame, plus the minibuffer window if specified by the MINIBUF
2031 argument, see above. If the minibuffer counts, consider all
2032 windows on all frames that share that minibuffer too.
2033 ALL-FRAMES t means consider all windows on all existing frames.
2034 ALL-FRAMES `visible' means consider all windows on all visible
2036 ALL-FRAMES 0 means consider all windows on all visible and
2038 ALL-FRAMES a frame means consider all windows on that frame only.
2039 Anything else means consider all windows on WINDOW's frame and no
2042 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2043 `next-window' to iterate through the entire cycle of acceptable
2044 windows, eventually ending up back at the window you started with.
2045 `previous-window' traverses the same cycle, in the reverse order. */)
2046 (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
)
2048 return next_window (window
, minibuf
, all_frames
, 1);
2052 DEFUN ("previous-window", Fprevious_window
, Sprevious_window
, 0, 3, 0,
2053 doc
: /* Return window preceding WINDOW in cyclic ordering of windows.
2054 WINDOW defaults to the selected window. The optional arguments
2055 MINIBUF and ALL-FRAMES specify the set of windows to consider.
2056 For the precise meaning of these arguments see `next-window'.
2058 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2059 use `previous-window' to iterate through the entire cycle of
2060 acceptable windows, eventually ending up back at the window you
2061 started with. `next-window' traverses the same cycle, in the
2063 (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
)
2065 return next_window (window
, minibuf
, all_frames
, 0);
2069 DEFUN ("other-window", Fother_window
, Sother_window
, 1, 2, "p",
2070 doc
: /* Select another window in cyclic ordering of windows.
2071 COUNT specifies the number of windows to skip, starting with the
2072 selected window, before making the selection. If COUNT is
2073 positive, skip COUNT windows forwards. If COUNT is negative,
2074 skip -COUNT windows backwards. COUNT zero means do not skip any
2075 window, so select the selected window. In an interactive call,
2076 COUNT is the numeric prefix argument. Return nil.
2078 This function uses `next-window' for finding the window to select.
2079 The argument ALL-FRAMES has the same meaning as in `next-window',
2080 but the MINIBUF argument of `next-window' is always effectively
2082 (Lisp_Object count
, Lisp_Object all_frames
)
2087 CHECK_NUMBER (count
);
2088 window
= selected_window
;
2090 for (i
= XINT (count
); i
> 0; --i
)
2091 window
= Fnext_window (window
, Qnil
, all_frames
);
2093 window
= Fprevious_window (window
, Qnil
, all_frames
);
2095 Fselect_window (window
, Qnil
);
2100 DEFUN ("window-list", Fwindow_list
, Swindow_list
, 0, 3, 0,
2101 doc
: /* Return a list of windows on FRAME, starting with WINDOW.
2102 FRAME nil or omitted means use the selected frame.
2103 WINDOW nil or omitted means use the selected window.
2104 MINIBUF t means include the minibuffer window, even if it isn't active.
2105 MINIBUF nil or omitted means include the minibuffer window only
2107 MINIBUF neither nil nor t means never include the minibuffer window. */)
2108 (Lisp_Object frame
, Lisp_Object minibuf
, Lisp_Object window
)
2111 window
= FRAMEP (frame
) ? XFRAME (frame
)->selected_window
: selected_window
;
2112 CHECK_WINDOW (window
);
2114 frame
= selected_frame
;
2116 if (!EQ (frame
, XWINDOW (window
)->frame
))
2117 error ("Window is on a different frame");
2119 return window_list_1 (window
, minibuf
, frame
);
2123 /* Return a list of windows in cyclic ordering. Arguments are like
2124 for `next-window'. */
2127 window_list_1 (Lisp_Object window
, Lisp_Object minibuf
, Lisp_Object all_frames
)
2129 Lisp_Object tail
, list
, rest
;
2131 decode_next_window_args (&window
, &minibuf
, &all_frames
);
2134 for (tail
= window_list (); CONSP (tail
); tail
= XCDR (tail
))
2135 if (candidate_window_p (XCAR (tail
), window
, minibuf
, all_frames
))
2136 list
= Fcons (XCAR (tail
), list
);
2138 /* Rotate the list to start with WINDOW. */
2139 list
= Fnreverse (list
);
2140 rest
= Fmemq (window
, list
);
2141 if (!NILP (rest
) && !EQ (rest
, list
))
2143 for (tail
= list
; !EQ (XCDR (tail
), rest
); tail
= XCDR (tail
))
2145 XSETCDR (tail
, Qnil
);
2146 list
= nconc2 (rest
, list
);
2153 /* Look at all windows, performing an operation specified by TYPE
2155 If FRAMES is Qt, look at all frames;
2156 Qnil, look at just the selected frame;
2157 Qvisible, look at visible frames;
2158 a frame, just look at windows on that frame.
2159 If MINI is non-zero, perform the operation on minibuffer windows too. */
2164 GET_BUFFER_WINDOW
, /* Arg is buffer */
2165 GET_LRU_WINDOW
, /* Arg is t for full-width windows only */
2166 DELETE_OTHER_WINDOWS
, /* Arg is window not to delete */
2167 DELETE_BUFFER_WINDOWS
, /* Arg is buffer */
2169 UNSHOW_BUFFER
, /* Arg is buffer */
2170 REDISPLAY_BUFFER_WINDOWS
, /* Arg is buffer */
2175 window_loop (enum window_loop type
, Lisp_Object obj
, int mini
, Lisp_Object frames
)
2177 Lisp_Object window
, windows
, best_window
, frame_arg
;
2179 struct gcpro gcpro1
;
2181 /* If we're only looping through windows on a particular frame,
2182 frame points to that frame. If we're looping through windows
2183 on all frames, frame is 0. */
2184 if (FRAMEP (frames
))
2185 f
= XFRAME (frames
);
2186 else if (NILP (frames
))
2187 f
= SELECTED_FRAME ();
2192 frame_arg
= Qlambda
;
2193 else if (EQ (frames
, make_number (0)))
2195 else if (EQ (frames
, Qvisible
))
2200 /* frame_arg is Qlambda to stick to one frame,
2201 Qvisible to consider all visible frames,
2204 /* Pick a window to start with. */
2208 window
= FRAME_SELECTED_WINDOW (f
);
2210 window
= FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2212 windows
= window_list_1 (window
, mini
? Qt
: Qnil
, frame_arg
);
2216 for (; CONSP (windows
); windows
= XCDR (windows
))
2220 window
= XCAR (windows
);
2221 w
= XWINDOW (window
);
2223 /* Note that we do not pay attention here to whether the frame
2224 is visible, since Fwindow_list skips non-visible frames if
2225 that is desired, under the control of frame_arg. */
2226 if (!MINI_WINDOW_P (w
)
2227 /* For UNSHOW_BUFFER, we must always consider all windows. */
2228 || type
== UNSHOW_BUFFER
2229 || (mini
&& minibuf_level
> 0))
2232 case GET_BUFFER_WINDOW
:
2233 if (EQ (w
->buffer
, obj
)
2234 /* Don't find any minibuffer window
2235 except the one that is currently in use. */
2236 && (MINI_WINDOW_P (w
)
2237 ? EQ (window
, minibuf_window
)
2240 if (NILP (best_window
))
2241 best_window
= window
;
2242 else if (EQ (window
, selected_window
))
2243 /* Prefer to return selected-window. */
2244 RETURN_UNGCPRO (window
);
2245 else if (EQ (Fwindow_frame (window
), selected_frame
))
2246 /* Prefer windows on the current frame. */
2247 best_window
= window
;
2251 case GET_LRU_WINDOW
:
2252 /* `obj' is an integer encoding a bitvector.
2253 `obj & 1' means consider only full-width windows.
2254 `obj & 2' means consider also dedicated windows. */
2255 if (((XINT (obj
) & 1) && !WINDOW_FULL_WIDTH_P (w
))
2256 || (!(XINT (obj
) & 2) && !NILP (w
->dedicated
))
2257 /* Minibuffer windows are always ignored. */
2258 || MINI_WINDOW_P (w
))
2260 if (NILP (best_window
)
2261 || (XFASTINT (XWINDOW (best_window
)->use_time
)
2262 > XFASTINT (w
->use_time
)))
2263 best_window
= window
;
2266 case DELETE_OTHER_WINDOWS
:
2267 if (!EQ (window
, obj
))
2268 Fdelete_window (window
);
2271 case DELETE_BUFFER_WINDOWS
:
2272 if (EQ (w
->buffer
, obj
))
2274 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
2276 /* If this window is dedicated, and in a frame of its own,
2278 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
2279 && !NILP (w
->dedicated
)
2280 && other_visible_frames (f
))
2282 /* Skip the other windows on this frame.
2283 There might be one, the minibuffer! */
2284 while (CONSP (XCDR (windows
))
2285 && EQ (XWINDOW (XCAR (windows
))->frame
,
2286 XWINDOW (XCAR (XCDR (windows
)))->frame
))
2287 windows
= XCDR (windows
);
2289 /* Now we can safely delete the frame. */
2290 delete_frame (w
->frame
, Qnil
);
2292 else if (NILP (w
->parent
))
2294 /* If we're deleting the buffer displayed in the
2295 only window on the frame, find a new buffer to
2298 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
2299 /* Reset dedicated state of window. */
2300 w
->dedicated
= Qnil
;
2301 Fset_window_buffer (window
, buffer
, Qnil
);
2302 if (EQ (window
, selected_window
))
2303 Fset_buffer (w
->buffer
);
2306 Fdelete_window (window
);
2310 case GET_LARGEST_WINDOW
:
2311 { /* nil `obj' means to ignore dedicated windows. */
2312 /* Ignore dedicated windows and minibuffers. */
2313 if (MINI_WINDOW_P (w
) || (NILP (obj
) && !NILP (w
->dedicated
)))
2316 if (NILP (best_window
))
2317 best_window
= window
;
2320 struct window
*b
= XWINDOW (best_window
);
2321 if (XFASTINT (w
->total_lines
) * XFASTINT (w
->total_cols
)
2322 > XFASTINT (b
->total_lines
) * XFASTINT (b
->total_cols
))
2323 best_window
= window
;
2329 if (EQ (w
->buffer
, obj
))
2332 struct frame
*f
= XFRAME (w
->frame
);
2334 /* Find another buffer to show in this window. */
2335 buffer
= Fother_buffer (obj
, Qnil
, w
->frame
);
2337 /* If this window is dedicated, and in a frame of its own,
2339 if (EQ (window
, FRAME_ROOT_WINDOW (f
))
2340 && !NILP (w
->dedicated
)
2341 && other_visible_frames (f
))
2343 /* Skip the other windows on this frame.
2344 There might be one, the minibuffer! */
2345 while (CONSP (XCDR (windows
))
2346 && EQ (XWINDOW (XCAR (windows
))->frame
,
2347 XWINDOW (XCAR (XCDR (windows
)))->frame
))
2348 windows
= XCDR (windows
);
2350 /* Now we can safely delete the frame. */
2351 delete_frame (w
->frame
, Qnil
);
2353 else if (!NILP (w
->dedicated
) && !NILP (w
->parent
))
2356 XSETWINDOW (window
, w
);
2357 /* If this window is dedicated and not the only window
2358 in its frame, then kill it. */
2359 Fdelete_window (window
);
2363 /* Otherwise show a different buffer in the window. */
2364 w
->dedicated
= Qnil
;
2365 Fset_window_buffer (window
, buffer
, Qnil
);
2366 if (EQ (window
, selected_window
))
2367 Fset_buffer (w
->buffer
);
2372 case REDISPLAY_BUFFER_WINDOWS
:
2373 if (EQ (w
->buffer
, obj
))
2375 mark_window_display_accurate (window
, 0);
2376 w
->update_mode_line
= Qt
;
2377 XBUFFER (obj
)->prevent_redisplay_optimizations_p
= 1;
2378 ++update_mode_lines
;
2379 best_window
= window
;
2383 /* Check for a window that has a killed buffer. */
2384 case CHECK_ALL_WINDOWS
:
2385 if (! NILP (w
->buffer
)
2386 && NILP (XBUFFER (w
->buffer
)->name
))
2390 case WINDOW_LOOP_UNUSED
:
2399 /* Used for debugging. Abort if any window has a dead buffer. */
2402 check_all_windows (void)
2404 window_loop (CHECK_ALL_WINDOWS
, Qnil
, 1, Qt
);
2407 DEFUN ("window-use-time", Fwindow_use_time
, Swindow_use_time
, 0, 1, 0,
2408 doc
: /* Return WINDOW's use time.
2409 WINDOW defaults to the selected window. The window with the highest use
2410 time is the most recently selected one. The window with the lowest use
2411 time is the least recently selected one. */)
2412 (Lisp_Object window
)
2414 return decode_window (window
)->use_time
;
2417 DEFUN ("get-lru-window", Fget_lru_window
, Sget_lru_window
, 0, 2, 0,
2418 doc
: /* Return the window least recently selected or used for display.
2419 \(LRU means Least Recently Used.)
2421 Return a full-width window if possible.
2422 A minibuffer window is never a candidate.
2423 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2424 so if all windows are dedicated, the value is nil.
2425 If optional argument FRAME is `visible', search all visible frames.
2426 If FRAME is 0, search all visible and iconified frames.
2427 If FRAME is t, search all frames.
2428 If FRAME is nil, search only the selected frame.
2429 If FRAME is a frame, search only that frame. */)
2430 (Lisp_Object frame
, Lisp_Object dedicated
)
2432 register Lisp_Object w
;
2433 /* First try for a window that is full-width */
2434 w
= window_loop (GET_LRU_WINDOW
,
2435 NILP (dedicated
) ? make_number (1) : make_number (3),
2437 if (!NILP (w
) && !EQ (w
, selected_window
))
2439 /* If none of them, try the rest */
2440 return window_loop (GET_LRU_WINDOW
,
2441 NILP (dedicated
) ? make_number (0) : make_number (2),
2445 DEFUN ("get-largest-window", Fget_largest_window
, Sget_largest_window
, 0, 2, 0,
2446 doc
: /* Return the largest window in area.
2447 A minibuffer window is never a candidate.
2448 A dedicated window is never a candidate unless DEDICATED is non-nil,
2449 so if all windows are dedicated, the value is nil.
2450 If optional argument FRAME is `visible', search all visible frames.
2451 If FRAME is 0, search all visible and iconified frames.
2452 If FRAME is t, search all frames.
2453 If FRAME is nil, search only the selected frame.
2454 If FRAME is a frame, search only that frame. */)
2455 (Lisp_Object frame
, Lisp_Object dedicated
)
2457 return window_loop (GET_LARGEST_WINDOW
, dedicated
, 0,
2461 DEFUN ("get-buffer-window", Fget_buffer_window
, Sget_buffer_window
, 0, 2, 0,
2462 doc
: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2463 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to the
2465 If optional argument FRAME is `visible', search all visible frames.
2466 If optional argument FRAME is 0, search all visible and iconified frames.
2467 If FRAME is t, search all frames.
2468 If FRAME is nil, search only the selected frame.
2469 If FRAME is a frame, search only that frame. */)
2470 (Lisp_Object buffer_or_name
, Lisp_Object frame
)
2474 if (NILP (buffer_or_name
))
2475 buffer
= Fcurrent_buffer ();
2477 buffer
= Fget_buffer (buffer_or_name
);
2479 if (BUFFERP (buffer
))
2480 return window_loop (GET_BUFFER_WINDOW
, buffer
, 1, frame
);
2485 DEFUN ("delete-other-windows", Fdelete_other_windows
, Sdelete_other_windows
,
2487 doc
: /* Make WINDOW (or the selected window) fill its frame.
2488 Only the frame WINDOW is on is affected.
2489 This function tries to reduce display jumps by keeping the text
2490 previously visible in WINDOW in the same place on the frame. Doing this
2491 depends on the value of (window-start WINDOW), so if calling this
2492 function in a program gives strange scrolling, make sure the
2493 window-start value is reasonable when this function is called. */)
2494 (Lisp_Object window
)
2501 window
= selected_window
;
2503 CHECK_LIVE_WINDOW (window
);
2504 w
= XWINDOW (window
);
2506 startpos
= marker_position (w
->start
);
2507 top
= WINDOW_TOP_EDGE_LINE (w
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2509 if (MINI_WINDOW_P (w
) && top
> 0)
2510 error ("Can't expand minibuffer to full frame");
2512 window_loop (DELETE_OTHER_WINDOWS
, window
, 0, WINDOW_FRAME (w
));
2514 /* Try to minimize scrolling, by setting the window start to the point
2515 will cause the text at the old window start to be at the same place
2516 on the frame. But don't try to do this if the window start is
2517 outside the visible portion (as might happen when the display is
2518 not current, due to typeahead). */
2519 new_top
= WINDOW_TOP_EDGE_LINE (w
) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w
)));
2521 && startpos
>= BUF_BEGV (XBUFFER (w
->buffer
))
2522 && startpos
<= BUF_ZV (XBUFFER (w
->buffer
)))
2524 struct position pos
;
2525 struct buffer
*obuf
= current_buffer
;
2527 Fset_buffer (w
->buffer
);
2528 /* This computation used to temporarily move point, but that can
2529 have unwanted side effects due to text properties. */
2530 pos
= *vmotion (startpos
, -top
, w
);
2532 set_marker_both (w
->start
, w
->buffer
, pos
.bufpos
, pos
.bytepos
);
2533 w
->window_end_valid
= Qnil
;
2534 w
->start_at_line_beg
= ((pos
.bytepos
== BEGV_BYTE
2535 || FETCH_BYTE (pos
.bytepos
- 1) == '\n') ? Qt
2537 /* We need to do this, so that the window-scroll-functions
2539 w
->optional_new_start
= Qt
;
2541 set_buffer_internal (obuf
);
2547 DEFUN ("delete-windows-on", Fdelete_windows_on
, Sdelete_windows_on
,
2548 0, 2, "bDelete windows on (buffer): ",
2549 doc
: /* Delete all windows showing BUFFER-OR-NAME.
2550 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2551 defaults to the current buffer.
2553 Optional second argument FRAME controls which frames are affected.
2554 If optional argument FRAME is `visible', search all visible frames.
2555 If FRAME is 0, search all visible and iconified frames.
2556 If FRAME is nil, search all frames.
2557 If FRAME is t, search only the selected frame.
2558 If FRAME is a frame, search only that frame.
2559 When a window showing BUFFER-OR-NAME is dedicated and the only window of
2560 its frame, that frame is deleted when there are other frames left. */)
2561 (Lisp_Object buffer_or_name
, Lisp_Object frame
)
2565 /* FRAME uses t and nil to mean the opposite of what window_loop
2569 else if (EQ (frame
, Qt
))
2572 if (NILP (buffer_or_name
))
2573 buffer
= Fcurrent_buffer ();
2576 buffer
= Fget_buffer (buffer_or_name
);
2577 CHECK_BUFFER (buffer
);
2580 window_loop (DELETE_BUFFER_WINDOWS
, buffer
, 0, frame
);
2585 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows
,
2586 Sreplace_buffer_in_windows
,
2587 0, 1, "bReplace buffer in windows: ",
2588 doc
: /* Replace BUFFER-OR-NAME with some other buffer in all windows showing it.
2589 BUFFER-OR-NAME may be a buffer or the name of an existing buffer and
2590 defaults to the current buffer.
2592 When a window showing BUFFER-OR-NAME is dedicated that window is
2593 deleted. If that window is the only window on its frame, that frame is
2594 deleted too when there are other frames left. If there are no other
2595 frames left, some other buffer is displayed in that window. */)
2596 (Lisp_Object buffer_or_name
)
2600 if (NILP (buffer_or_name
))
2601 buffer
= Fcurrent_buffer ();
2604 buffer
= Fget_buffer (buffer_or_name
);
2605 CHECK_BUFFER (buffer
);
2608 window_loop (UNSHOW_BUFFER
, buffer
, 0, Qt
);
2613 /* Replace BUFFER with some other buffer in all windows
2614 of all frames, even those on other keyboards. */
2617 replace_buffer_in_all_windows (Lisp_Object buffer
)
2619 Lisp_Object tail
, frame
;
2621 /* A single call to window_loop won't do the job
2622 because it only considers frames on the current keyboard.
2623 So loop manually over frames, and handle each one. */
2624 FOR_EACH_FRAME (tail
, frame
)
2625 window_loop (UNSHOW_BUFFER
, buffer
, 1, frame
);
2628 /* Set the height of WINDOW and all its inferiors. */
2630 /* The smallest acceptable dimensions for a window. Anything smaller
2631 might crash Emacs. */
2633 #define MIN_SAFE_WINDOW_WIDTH (2)
2634 #define MIN_SAFE_WINDOW_HEIGHT (1)
2636 /* For wp non-zero the total number of columns of window w. Otherwise
2637 the total number of lines of w. */
2639 #define WINDOW_TOTAL_SIZE(w, wp) \
2640 (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
2642 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2643 minimum allowable size. */
2646 check_frame_size (FRAME_PTR frame
, int *rows
, int *cols
)
2648 /* For height, we have to see:
2649 how many windows the frame has at minimum (one or two),
2650 and whether it has a menu bar or other special stuff at the top. */
2652 = ((FRAME_MINIBUF_ONLY_P (frame
) || ! FRAME_HAS_MINIBUF_P (frame
))
2653 ? MIN_SAFE_WINDOW_HEIGHT
2654 : 2 * MIN_SAFE_WINDOW_HEIGHT
);
2656 if (FRAME_TOP_MARGIN (frame
) > 0)
2657 min_height
+= FRAME_TOP_MARGIN (frame
);
2659 if (*rows
< min_height
)
2661 if (*cols
< MIN_SAFE_WINDOW_WIDTH
)
2662 *cols
= MIN_SAFE_WINDOW_WIDTH
;
2665 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2666 check if W's width can be changed, otherwise check W's height.
2667 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2668 siblings, too. If none of the siblings is resizable, WINDOW isn't
2672 window_fixed_size_p (struct window
*w
, int width_p
, int check_siblings_p
)
2677 if (!NILP (w
->hchild
))
2679 c
= XWINDOW (w
->hchild
);
2683 /* A horizontal combination is fixed-width if all of if its
2685 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2686 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2687 fixed_p
= c
== NULL
;
2691 /* A horizontal combination is fixed-height if one of if its
2693 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2694 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2695 fixed_p
= c
!= NULL
;
2698 else if (!NILP (w
->vchild
))
2700 c
= XWINDOW (w
->vchild
);
2704 /* A vertical combination is fixed-width if one of if its
2706 while (c
&& !window_fixed_size_p (c
, width_p
, 0))
2707 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2708 fixed_p
= c
!= NULL
;
2712 /* A vertical combination is fixed-height if all of if its
2714 while (c
&& window_fixed_size_p (c
, width_p
, 0))
2715 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2716 fixed_p
= c
== NULL
;
2719 else if (BUFFERP (w
->buffer
))
2721 struct buffer
*old
= current_buffer
;
2724 current_buffer
= XBUFFER (w
->buffer
);
2725 val
= find_symbol_value (Qwindow_size_fixed
);
2726 current_buffer
= old
;
2729 if (!EQ (val
, Qunbound
))
2731 fixed_p
= !NILP (val
);
2734 && ((EQ (val
, Qheight
) && width_p
)
2735 || (EQ (val
, Qwidth
) && !width_p
)))
2739 /* Can't tell if this one is resizable without looking at
2740 siblings. If all siblings are fixed-size this one is too. */
2741 if (!fixed_p
&& check_siblings_p
&& WINDOWP (w
->parent
))
2745 for (child
= w
->prev
; WINDOWP (child
); child
= XWINDOW (child
)->prev
)
2746 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2750 for (child
= w
->next
; WINDOWP (child
); child
= XWINDOW (child
)->next
)
2751 if (!window_fixed_size_p (XWINDOW (child
), width_p
, 0))
2764 /* Return minimum size of leaf window W. WIDTH_P non-zero means return
2765 the minimum width of W, WIDTH_P zero means return the minimum height
2766 of W. SAFE_P non-zero means ignore window-min-height|width but just
2767 return values that won't crash Emacs and don't hide components like
2768 fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the
2769 minibuffer window, always return 1. */
2772 window_min_size_2 (struct window
*w
, int width_p
, int safe_p
)
2774 /* We should consider buffer-local values of window_min_height and
2775 window_min_width here. */
2778 int safe_size
= (MIN_SAFE_WINDOW_WIDTH
2779 + WINDOW_FRINGE_COLS (w
)
2780 + WINDOW_SCROLL_BAR_COLS (w
));
2782 return safe_p
? safe_size
: max (window_min_width
, safe_size
);
2784 else if (MINI_WINDOW_P (w
))
2788 int safe_size
= (MIN_SAFE_WINDOW_HEIGHT
2789 + ((BUFFERP (w
->buffer
)
2790 && !NILP (XBUFFER (w
->buffer
)->mode_line_format
))
2793 return safe_p
? safe_size
: max (window_min_height
, safe_size
);
2797 /* Return minimum size of window W, not taking fixed-width windows into
2798 account. WIDTH_P non-zero means return the minimum width, otherwise
2799 return the minimum height. SAFE_P non-zero means ignore
2800 window-min-height|width but just return values that won't crash Emacs
2801 and don't hide components like fringes, scrollbars, or modelines. If
2802 W is a combination window, compute the minimum size from the minimum
2803 sizes of W's children. */
2806 window_min_size_1 (struct window
*w
, int width_p
, int safe_p
)
2811 if (!NILP (w
->hchild
))
2813 /* W is a horizontal combination. */
2814 c
= XWINDOW (w
->hchild
);
2819 /* The minimum width of a horizontal combination is the sum of
2820 the minimum widths of its children. */
2823 size
+= window_min_size_1 (c
, 1, safe_p
);
2824 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2829 /* The minimum height of a horizontal combination is the
2830 maximum of the minimum heights of its children. */
2833 size
= max (window_min_size_1 (c
, 0, safe_p
), size
);
2834 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2838 else if (!NILP (w
->vchild
))
2840 /* W is a vertical combination. */
2841 c
= XWINDOW (w
->vchild
);
2846 /* The minimum width of a vertical combination is the maximum
2847 of the minimum widths of its children. */
2850 size
= max (window_min_size_1 (c
, 1, safe_p
), size
);
2851 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2856 /* The minimum height of a vertical combination is the sum of
2857 the minimum height of its children. */
2860 size
+= window_min_size_1 (c
, 0, safe_p
);
2861 c
= WINDOWP (c
->next
) ? XWINDOW (c
->next
) : NULL
;
2866 /* W is a leaf window. */
2867 size
= window_min_size_2 (w
, width_p
, safe_p
);
2872 /* Return the minimum size of window W, taking fixed-size windows into
2873 account. WIDTH_P non-zero means return the minimum width, otherwise
2874 return the minimum height. SAFE_P non-zero means ignore
2875 window-min-height|width but just return values that won't crash Emacs
2876 and don't hide components like fringes, scrollbars, or modelines.
2877 IGNORE_FIXED_P non-zero means ignore if W is fixed-size. Set *FIXED
2878 to 1 if W is fixed-size unless FIXED is null. */
2881 window_min_size (struct window
*w
, int width_p
, int safe_p
, int ignore_fixed_p
, int *fixed
)
2888 fixed_p
= window_fixed_size_p (w
, width_p
, 1);
2894 size
= WINDOW_TOTAL_SIZE (w
, width_p
);
2896 size
= window_min_size_1 (w
, width_p
, safe_p
);
2902 /* Adjust the margins of window W if text area is too small.
2903 Return 1 if window width is ok after adjustment; 0 if window
2904 is still too narrow. */
2907 adjust_window_margins (struct window
*w
)
2909 int box_cols
= (WINDOW_TOTAL_COLS (w
)
2910 - WINDOW_FRINGE_COLS (w
)
2911 - WINDOW_SCROLL_BAR_COLS (w
));
2912 int margin_cols
= (WINDOW_LEFT_MARGIN_COLS (w
)
2913 + WINDOW_RIGHT_MARGIN_COLS (w
));
2915 if (box_cols
- margin_cols
>= MIN_SAFE_WINDOW_WIDTH
)
2918 if (margin_cols
< 0 || box_cols
< MIN_SAFE_WINDOW_WIDTH
)
2921 /* Window's text area is too narrow, but reducing the window
2922 margins will fix that. */
2923 margin_cols
= box_cols
- MIN_SAFE_WINDOW_WIDTH
;
2924 if (WINDOW_RIGHT_MARGIN_COLS (w
) > 0)
2926 if (WINDOW_LEFT_MARGIN_COLS (w
) > 0)
2927 w
->left_margin_cols
= w
->right_margin_cols
2928 = make_number (margin_cols
/2);
2930 w
->right_margin_cols
= make_number (margin_cols
);
2933 w
->left_margin_cols
= make_number (margin_cols
);
2937 /* Calculate new sizes for windows in the list FORWARD when their
2938 compound size goes from TOTAL to SIZE. TOTAL must be greater than
2939 SIZE. The number of windows in FORWARD is NCHILDREN, and the number
2940 that can shrink is SHRINKABLE. Fixed-size windows may be shrunk if
2941 and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means
2942 shrink columns, otherwise shrink lines.
2944 SAFE_P zero means windows may be sized down to window-min-height
2945 lines (window-min-window columns for WIDTH_P non-zero). SAFE_P
2946 non-zero means windows may be sized down to their minimum safe sizes
2947 taking into account the space needed to display modelines, fringes,
2950 This function returns an allocated array of new sizes that the caller
2951 must free. A size -1 means the window is fixed and RESIZE_FIXED_P is
2952 zero. A size zero means the window shall be deleted. Array index 0
2953 refers to the first window in FORWARD, 1 to the second, and so on.
2955 This function resizes windows proportionally to their size. It also
2956 tries to preserve smaller windows by resizing larger windows before
2957 resizing any window to zero. If resize_proportionally is non-nil for
2958 a specific window, it will attempt to strictly resize that window
2959 proportionally, even at the expense of deleting smaller windows. */
2961 shrink_windows (int total
, int size
, int nchildren
, int shrinkable
,
2962 int resize_fixed_p
, Lisp_Object forward
, int width_p
, int safe_p
)
2964 int available_resize
= 0;
2965 int *new_sizes
, *min_sizes
;
2968 int smallest
= total
;
2969 int total_removed
= 0;
2970 int total_shrink
= total
- size
;
2973 new_sizes
= xmalloc (sizeof (*new_sizes
) * nchildren
);
2974 min_sizes
= xmalloc (sizeof (*min_sizes
) * nchildren
);
2976 for (i
= 0, child
= forward
; !NILP (child
); child
= c
->next
, ++i
)
2980 c
= XWINDOW (child
);
2981 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
2983 if (!resize_fixed_p
&& window_fixed_size_p (c
, width_p
, 0))
2987 new_sizes
[i
] = child_size
;
2988 min_sizes
[i
] = window_min_size_1 (c
, width_p
, safe_p
);
2989 if (child_size
> min_sizes
[i
]
2990 && NILP (c
->resize_proportionally
))
2991 available_resize
+= child_size
- min_sizes
[i
];
2994 /* We might need to shrink some windows to zero. Find the smallest
2995 windows and set them to 0 until we can fulfil the new size. */
2997 while (shrinkable
> 1 && size
+ available_resize
< total
)
2999 for (i
= 0; i
< nchildren
; ++i
)
3000 if (new_sizes
[i
] > 0 && smallest
> new_sizes
[i
])
3001 smallest
= new_sizes
[i
];
3003 for (i
= 0; i
< nchildren
; ++i
)
3004 if (new_sizes
[i
] == smallest
)
3006 /* Resize this window down to zero. */
3008 if (smallest
> min_sizes
[i
])
3009 available_resize
-= smallest
- min_sizes
[i
];
3010 available_resize
+= smallest
;
3012 total_removed
+= smallest
;
3014 /* We don't know what the smallest is now. */
3017 /* Out of for, just remove one window at the time and
3018 check again if we have enough space. */
3023 /* Now, calculate the new sizes. Try to shrink each window
3024 proportional to its size. */
3025 for (i
= 0; i
< nchildren
; ++i
)
3027 if (new_sizes
[i
] > min_sizes
[i
])
3029 int to_shrink
= total_shrink
* new_sizes
[i
] / total
;
3031 if (new_sizes
[i
] - to_shrink
< min_sizes
[i
])
3032 to_shrink
= new_sizes
[i
] - min_sizes
[i
];
3033 new_sizes
[i
] -= to_shrink
;
3034 total_removed
+= to_shrink
;
3038 /* Any reminder due to rounding, we just subtract from windows
3039 that are left and still can be shrunk. */
3040 while (total_shrink
> total_removed
)
3042 int nonzero_sizes
= 0;
3043 int nonzero_idx
= -1;
3045 for (i
= 0; i
< nchildren
; ++i
)
3046 if (new_sizes
[i
] > 0)
3052 for (i
= 0; i
< nchildren
; ++i
)
3053 if (new_sizes
[i
] > min_sizes
[i
])
3058 /* Out of for, just shrink one window at the time and
3059 check again if we have enough space. */
3063 /* Special case, only one window left. */
3064 if (nonzero_sizes
== 1)
3068 /* Any surplus due to rounding, we add to windows that are left. */
3069 while (total_shrink
< total_removed
)
3071 for (i
= 0; i
< nchildren
; ++i
)
3073 if (new_sizes
[i
] != 0 && total_shrink
< total_removed
)
3087 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
3088 WINDOW's width. Resize WINDOW's children, if any, so that they keep
3089 their proportionate size relative to WINDOW.
3091 If FIRST_ONLY is 1, change only the first of WINDOW's children when
3092 they are in series. If LAST_ONLY is 1, change only the last of
3093 WINDOW's children when they are in series.
3095 Propagate WINDOW's top or left edge position to children. Delete
3096 windows that become too small unless NODELETE_P is 1. When
3097 NODELETE_P equals 2 do not honor settings for window-min-height and
3098 window-min-width when resizing windows but use safe defaults instead.
3099 This should give better behavior when resizing frames. */
3102 size_window (Lisp_Object window
, int size
, int width_p
, int nodelete_p
, int first_only
, int last_only
)
3104 struct window
*w
= XWINDOW (window
);
3106 Lisp_Object child
, *forward
, *sideward
;
3107 int old_size
= WINDOW_TOTAL_SIZE (w
, width_p
);
3109 size
= max (0, size
);
3111 /* Delete WINDOW if it's too small. */
3112 if (nodelete_p
!= 1 && !NILP (w
->parent
)
3113 && size
< window_min_size_1 (w
, width_p
, nodelete_p
== 2))
3115 delete_window (window
);
3119 /* Set redisplay hints. */
3120 w
->last_modified
= make_number (0);
3121 w
->last_overlay_modified
= make_number (0);
3122 windows_or_buffers_changed
++;
3123 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w
->frame
)) = 1;
3127 sideward
= &w
->vchild
;
3128 forward
= &w
->hchild
;
3129 w
->total_cols
= make_number (size
);
3130 adjust_window_margins (w
);
3134 sideward
= &w
->hchild
;
3135 forward
= &w
->vchild
;
3136 w
->total_lines
= make_number (size
);
3137 w
->orig_total_lines
= Qnil
;
3140 if (!NILP (*sideward
))
3142 /* We have a chain of parallel siblings whose size should all change. */
3143 for (child
= *sideward
; !NILP (child
); child
= c
->next
)
3145 c
= XWINDOW (child
);
3147 c
->left_col
= w
->left_col
;
3149 c
->top_line
= w
->top_line
;
3150 size_window (child
, size
, width_p
, nodelete_p
,
3151 first_only
, last_only
);
3154 else if (!NILP (*forward
) && last_only
)
3156 /* Change the last in a series of siblings. */
3157 Lisp_Object last_child
;
3160 for (child
= *forward
; !NILP (child
); child
= c
->next
)
3162 c
= XWINDOW (child
);
3166 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3167 size_window (last_child
, size
- old_size
+ child_size
,
3168 width_p
, nodelete_p
, first_only
, last_only
);
3170 else if (!NILP (*forward
) && first_only
)
3172 /* Change the first in a series of siblings. */
3176 c
= XWINDOW (child
);
3179 c
->left_col
= w
->left_col
;
3181 c
->top_line
= w
->top_line
;
3183 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3184 size_window (child
, size
- old_size
+ child_size
,
3185 width_p
, nodelete_p
, first_only
, last_only
);
3187 else if (!NILP (*forward
))
3189 int fixed_size
, each
, extra
, n
;
3190 int resize_fixed_p
, nfixed
;
3191 int last_pos
, first_pos
, nchildren
, total
;
3192 int *new_sizes
= NULL
;
3194 /* Determine the fixed-size portion of this window, and the
3195 number of child windows. */
3196 fixed_size
= nchildren
= nfixed
= total
= 0;
3197 for (child
= *forward
; !NILP (child
); child
= c
->next
, ++nchildren
)
3201 c
= XWINDOW (child
);
3202 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3203 total
+= child_size
;
3205 if (window_fixed_size_p (c
, width_p
, 0))
3207 fixed_size
+= child_size
;
3212 /* If the new size is smaller than fixed_size, or if there
3213 aren't any resizable windows, allow resizing fixed-size
3215 resize_fixed_p
= nfixed
== nchildren
|| size
< fixed_size
;
3217 /* Compute how many lines/columns to add/remove to each child. The
3218 value of extra takes care of rounding errors. */
3219 n
= resize_fixed_p
? nchildren
: nchildren
- nfixed
;
3220 if (size
< total
&& n
> 1)
3221 new_sizes
= shrink_windows (total
, size
, nchildren
, n
,
3222 resize_fixed_p
, *forward
, width_p
,
3226 each
= (size
- total
) / n
;
3227 extra
= (size
- total
) - n
* each
;
3230 /* Compute new children heights and edge positions. */
3231 first_pos
= width_p
? XINT (w
->left_col
) : XINT (w
->top_line
);
3232 last_pos
= first_pos
;
3233 for (n
= 0, child
= *forward
; !NILP (child
); child
= c
->next
, ++n
)
3235 int new_size
, old_size
;
3237 c
= XWINDOW (child
);
3238 old_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3239 new_size
= old_size
;
3241 /* The top or left edge position of this child equals the
3242 bottom or right edge of its predecessor. */
3244 c
->left_col
= make_number (last_pos
);
3246 c
->top_line
= make_number (last_pos
);
3248 /* If this child can be resized, do it. */
3249 if (resize_fixed_p
|| !window_fixed_size_p (c
, width_p
, 0))
3251 new_size
= new_sizes
? new_sizes
[n
] : old_size
+ each
+ extra
;
3255 /* Set new size. Note that size_window also propagates
3256 edge positions to children, so it's not a no-op if we
3257 didn't change the child's size. */
3258 size_window (child
, new_size
, width_p
, 1, first_only
, last_only
);
3260 /* Remember the bottom/right edge position of this child; it
3261 will be used to set the top/left edge of the next child. */
3262 last_pos
+= new_size
;
3267 /* We should have covered the parent exactly with child windows. */
3268 xassert (size
== last_pos
- first_pos
);
3270 /* Now delete any children that became too small. */
3271 if (nodelete_p
!= 1)
3272 for (child
= *forward
; !NILP (child
); child
= c
->next
)
3276 c
= XWINDOW (child
);
3277 child_size
= WINDOW_TOTAL_SIZE (c
, width_p
);
3278 size_window (child
, child_size
, width_p
, nodelete_p
,
3279 first_only
, last_only
);
3284 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3285 WINDOW's children. NODELETE zero means windows that have become
3286 smaller than window-min-height in the process may be deleted.
3287 NODELETE 1 means never delete windows that become too small in the
3288 process. (The caller should check later and do so if appropriate.)
3289 NODELETE 2 means delete only windows that have become too small to be
3290 displayed correctly. */
3293 set_window_height (Lisp_Object window
, int height
, int nodelete
)
3295 size_window (window
, height
, 0, nodelete
, 0, 0);
3298 /* Set WINDOW's width to WIDTH, and recursively change the width of
3299 WINDOW's children. NODELETE zero means windows that have become
3300 smaller than window-min-width in the process may be deleted.
3301 NODELETE 1 means never delete windows that become too small in the
3302 process. (The caller should check later and do so if appropriate.)
3303 NODELETE 2 means delete only windows that have become too small to be
3304 displayed correctly. */
3307 set_window_width (Lisp_Object window
, int width
, int nodelete
)
3309 size_window (window
, width
, 1, nodelete
, 0, 0);
3312 /* Change window heights in windows rooted in WINDOW by N lines. */
3315 change_window_heights (Lisp_Object window
, int n
)
3317 struct window
*w
= XWINDOW (window
);
3319 XSETFASTINT (w
->top_line
, XFASTINT (w
->top_line
) + n
);
3320 XSETFASTINT (w
->total_lines
, XFASTINT (w
->total_lines
) - n
);
3322 if (INTEGERP (w
->orig_top_line
))
3323 XSETFASTINT (w
->orig_top_line
, XFASTINT (w
->orig_top_line
) + n
);
3324 if (INTEGERP (w
->orig_total_lines
))
3325 XSETFASTINT (w
->orig_total_lines
, XFASTINT (w
->orig_total_lines
) - n
);
3327 /* Handle just the top child in a vertical split. */
3328 if (!NILP (w
->vchild
))
3329 change_window_heights (w
->vchild
, n
);
3331 /* Adjust all children in a horizontal split. */
3332 for (window
= w
->hchild
; !NILP (window
); window
= w
->next
)
3334 w
= XWINDOW (window
);
3335 change_window_heights (window
, n
);
3340 int window_select_count
;
3342 EXFUN (Fset_window_fringes
, 4);
3343 EXFUN (Fset_window_scroll_bars
, 4);
3346 run_funs (Lisp_Object funs
)
3348 for (; CONSP (funs
); funs
= XCDR (funs
))
3349 if (!EQ (XCAR (funs
), Qt
))
3350 call0 (XCAR (funs
));
3353 static Lisp_Object
select_window_norecord (Lisp_Object window
);
3354 static Lisp_Object
select_frame_norecord (Lisp_Object frame
);
3357 run_window_configuration_change_hook (struct frame
*f
)
3359 int count
= SPECPDL_INDEX ();
3360 Lisp_Object frame
, global_wcch
3361 = Fdefault_value (Qwindow_configuration_change_hook
);
3362 XSETFRAME (frame
, f
);
3364 if (NILP (Vrun_hooks
))
3367 if (SELECTED_FRAME () != f
)
3369 record_unwind_protect (select_frame_norecord
, Fselected_frame ());
3370 Fselect_frame (frame
, Qt
);
3373 /* Use the right buffer. Matters when running the local hooks. */
3374 if (current_buffer
!= XBUFFER (Fwindow_buffer (Qnil
)))
3376 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
3377 Fset_buffer (Fwindow_buffer (Qnil
));
3380 /* Look for buffer-local values. */
3382 Lisp_Object windows
= Fwindow_list (frame
, Qlambda
, Qnil
);
3383 for (; CONSP (windows
); windows
= XCDR (windows
))
3385 Lisp_Object window
= XCAR (windows
);
3386 Lisp_Object buffer
= Fwindow_buffer (window
);
3387 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook
,
3390 int count
= SPECPDL_INDEX ();
3391 record_unwind_protect (select_window_norecord
, Fselected_window ());
3392 select_window_norecord (window
);
3393 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook
,
3395 unbind_to (count
, Qnil
);
3400 run_funs (global_wcch
);
3401 unbind_to (count
, Qnil
);
3404 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3405 means it's allowed to run hooks. See make_frame for a case where
3406 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3407 margins, fringes, and scroll-bar settings of the window are not
3408 reset from the buffer's local settings. */
3411 set_window_buffer (Lisp_Object window
, Lisp_Object buffer
, int run_hooks_p
, int keep_margins_p
)
3413 struct window
*w
= XWINDOW (window
);
3414 struct buffer
*b
= XBUFFER (buffer
);
3415 int count
= SPECPDL_INDEX ();
3416 int samebuf
= EQ (buffer
, w
->buffer
);
3420 if (EQ (window
, selected_window
))
3421 b
->last_selected_window
= window
;
3423 /* Let redisplay errors through. */
3424 b
->display_error_modiff
= 0;
3426 /* Update time stamps of buffer display. */
3427 if (INTEGERP (b
->display_count
))
3428 XSETINT (b
->display_count
, XINT (b
->display_count
) + 1);
3429 b
->display_time
= Fcurrent_time ();
3431 XSETFASTINT (w
->window_end_pos
, 0);
3432 XSETFASTINT (w
->window_end_vpos
, 0);
3433 memset (&w
->last_cursor
, 0, sizeof w
->last_cursor
);
3434 w
->window_end_valid
= Qnil
;
3435 if (!(keep_margins_p
&& samebuf
))
3436 { /* If we're not actually changing the buffer, don't reset hscroll and
3437 vscroll. This case happens for example when called from
3438 change_frame_size_1, where we use a dummy call to
3439 Fset_window_buffer on the frame's selected window (and no other)
3440 just in order to run window-configuration-change-hook.
3441 Resetting hscroll and vscroll here is problematic for things like
3442 image-mode and doc-view-mode since it resets the image's position
3443 whenever we resize the frame. */
3444 w
->hscroll
= w
->min_hscroll
= make_number (0);
3446 set_marker_both (w
->pointm
, buffer
, BUF_PT (b
), BUF_PT_BYTE (b
));
3447 set_marker_restricted (w
->start
,
3448 make_number (b
->last_window_start
),
3450 w
->start_at_line_beg
= Qnil
;
3451 w
->force_start
= Qnil
;
3452 XSETFASTINT (w
->last_modified
, 0);
3453 XSETFASTINT (w
->last_overlay_modified
, 0);
3455 /* Maybe we could move this into the `if' but it's not obviously safe and
3456 I doubt it's worth the trouble. */
3457 windows_or_buffers_changed
++;
3459 /* We must select BUFFER for running the window-scroll-functions. */
3460 /* We can't check ! NILP (Vwindow_scroll_functions) here
3461 because that might itself be a local variable. */
3462 if (window_initialized
)
3464 record_unwind_protect (Fset_buffer
, Fcurrent_buffer ());
3465 Fset_buffer (buffer
);
3468 XMARKER (w
->pointm
)->insertion_type
= !NILP (Vwindow_point_insertion_type
);
3470 if (!keep_margins_p
)
3472 /* Set left and right marginal area width etc. from buffer. */
3474 /* This may call adjust_window_margins three times, so
3475 temporarily disable window margins. */
3476 Lisp_Object save_left
= w
->left_margin_cols
;
3477 Lisp_Object save_right
= w
->right_margin_cols
;
3479 w
->left_margin_cols
= w
->right_margin_cols
= Qnil
;
3481 Fset_window_fringes (window
,
3482 b
->left_fringe_width
, b
->right_fringe_width
,
3483 b
->fringes_outside_margins
);
3485 Fset_window_scroll_bars (window
,
3486 b
->scroll_bar_width
,
3487 b
->vertical_scroll_bar_type
, Qnil
);
3489 w
->left_margin_cols
= save_left
;
3490 w
->right_margin_cols
= save_right
;
3492 Fset_window_margins (window
,
3493 b
->left_margin_cols
, b
->right_margin_cols
);
3498 if (! NILP (Vwindow_scroll_functions
))
3499 run_hook_with_args_2 (Qwindow_scroll_functions
, window
,
3500 Fmarker_position (w
->start
));
3501 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w
)));
3504 unbind_to (count
, Qnil
);
3508 DEFUN ("set-window-buffer", Fset_window_buffer
, Sset_window_buffer
, 2, 3, 0,
3509 doc
: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3510 WINDOW defaults to the selected window. BUFFER-OR-NAME must be a buffer
3511 or the name of an existing buffer. Optional third argument KEEP-MARGINS
3512 non-nil means that WINDOW's current display margins, fringe widths, and
3513 scroll bar settings are preserved; the default is to reset these from
3514 the local settings for BUFFER-OR-NAME or the frame defaults. Return nil.
3516 This function throws an error when WINDOW is strongly dedicated to its
3517 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3518 already display BUFFER-OR-NAME.
3520 This function runs `window-scroll-functions' before running
3521 `window-configuration-change-hook'. */)
3522 (register Lisp_Object window
, Lisp_Object buffer_or_name
, Lisp_Object keep_margins
)
3524 register Lisp_Object tem
, buffer
;
3525 register struct window
*w
= decode_window (window
);
3527 XSETWINDOW (window
, w
);
3528 buffer
= Fget_buffer (buffer_or_name
);
3529 CHECK_BUFFER (buffer
);
3530 if (NILP (XBUFFER (buffer
)->name
))
3531 error ("Attempt to display deleted buffer");
3535 error ("Window is deleted");
3536 else if (!EQ (tem
, Qt
))
3537 /* w->buffer is t when the window is first being set up. */
3539 if (EQ (tem
, buffer
))
3541 else if (EQ (w
->dedicated
, Qt
))
3542 error ("Window is dedicated to `%s'", SDATA (XBUFFER (tem
)->name
));
3544 w
->dedicated
= Qnil
;
3549 set_window_buffer (window
, buffer
, 1, !NILP (keep_margins
));
3553 /* Note that selected_window can be nil when this is called from
3554 Fset_window_configuration. */
3556 DEFUN ("select-window", Fselect_window
, Sselect_window
, 1, 2, 0,
3557 doc
: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3558 If WINDOW is not already selected, make WINDOW's buffer current
3559 and make WINDOW the frame's selected window. Return WINDOW.
3560 Optional second arg NORECORD non-nil means do not put this buffer
3561 at the front of the list of recently selected ones and do not
3562 make this window the most recently selected one.
3564 Note that the main editor command loop selects the buffer of the
3565 selected window before each command. */)
3566 (register Lisp_Object window
, Lisp_Object norecord
)
3568 register struct window
*w
;
3569 register struct window
*ow
;
3572 CHECK_LIVE_WINDOW (window
);
3574 w
= XWINDOW (window
);
3575 w
->frozen_window_start_p
= 0;
3577 if (NILP (norecord
))
3579 ++window_select_count
;
3580 XSETFASTINT (w
->use_time
, window_select_count
);
3581 record_buffer (w
->buffer
);
3584 if (EQ (window
, selected_window
))
3587 sf
= SELECTED_FRAME ();
3588 if (XFRAME (WINDOW_FRAME (w
)) != sf
)
3590 XFRAME (WINDOW_FRAME (w
))->selected_window
= window
;
3591 /* Use this rather than Fhandle_switch_frame
3592 so that FRAME_FOCUS_FRAME is moved appropriately as we
3593 move around in the state where a minibuffer in a separate
3595 Fselect_frame (WINDOW_FRAME (w
), norecord
);
3596 /* Fselect_frame called us back so we've done all the work already. */
3597 eassert (EQ (window
, selected_window
));
3601 sf
->selected_window
= window
;
3603 /* Store the current buffer's actual point into the
3604 old selected window. It belongs to that window,
3605 and when the window is not selected, must be in the window. */
3606 if (inhibit_point_swap
)
3607 inhibit_point_swap
= 0;
3610 ow
= XWINDOW (selected_window
);
3611 if (! NILP (ow
->buffer
))
3612 set_marker_both (ow
->pointm
, ow
->buffer
,
3613 BUF_PT (XBUFFER (ow
->buffer
)),
3614 BUF_PT_BYTE (XBUFFER (ow
->buffer
)));
3617 selected_window
= window
;
3619 Fset_buffer (w
->buffer
);
3621 XBUFFER (w
->buffer
)->last_selected_window
= window
;
3623 /* Go to the point recorded in the window.
3624 This is important when the buffer is in more
3625 than one window. It also matters when
3626 redisplay_window has altered point after scrolling,
3627 because it makes the change only in the window. */
3629 register EMACS_INT new_point
= marker_position (w
->pointm
);
3630 if (new_point
< BEGV
)
3632 else if (new_point
> ZV
)
3638 windows_or_buffers_changed
++;
3643 select_window_norecord (Lisp_Object window
)
3645 return WINDOW_LIVE_P (window
)
3646 ? Fselect_window (window
, Qt
) : selected_window
;
3650 select_frame_norecord (Lisp_Object frame
)
3652 return FRAME_LIVE_P (XFRAME (frame
))
3653 ? Fselect_frame (frame
, Qt
) : selected_frame
;
3657 display_buffer (Lisp_Object buffer
, Lisp_Object not_this_window_p
, Lisp_Object override_frame
)
3659 return call3 (Qdisplay_buffer
, buffer
, not_this_window_p
, override_frame
);
3662 DEFUN ("force-window-update", Fforce_window_update
, Sforce_window_update
,
3664 doc
: /* Force all windows to be updated on next redisplay.
3665 If optional arg OBJECT is a window, force redisplay of that window only.
3666 If OBJECT is a buffer or buffer name, force redisplay of all windows
3667 displaying that buffer. */)
3668 (Lisp_Object object
)
3672 windows_or_buffers_changed
++;
3673 update_mode_lines
++;
3677 if (WINDOWP (object
))
3679 struct window
*w
= XWINDOW (object
);
3680 mark_window_display_accurate (object
, 0);
3681 w
->update_mode_line
= Qt
;
3682 if (BUFFERP (w
->buffer
))
3683 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
3684 ++update_mode_lines
;
3688 if (STRINGP (object
))
3689 object
= Fget_buffer (object
);
3690 if (BUFFERP (object
) && !NILP (XBUFFER (object
)->name
))
3692 /* Walk all windows looking for buffer, and force update
3693 of each of those windows. */
3695 object
= window_loop (REDISPLAY_BUFFER_WINDOWS
, object
, 0, Qvisible
);
3696 return NILP (object
) ? Qnil
: Qt
;
3699 /* If nothing suitable was found, just return.
3700 We could signal an error, but this feature will typically be used
3701 asynchronously in timers or process sentinels, so we don't. */
3707 temp_output_buffer_show (register Lisp_Object buf
)
3709 register struct buffer
*old
= current_buffer
;
3710 register Lisp_Object window
;
3711 register struct window
*w
;
3713 XBUFFER (buf
)->directory
= current_buffer
->directory
;
3716 BUF_SAVE_MODIFF (XBUFFER (buf
)) = MODIFF
;
3720 #if 0 /* rms: there should be no reason for this. */
3721 XBUFFER (buf
)->prevent_redisplay_optimizations_p
= 1;
3723 set_buffer_internal (old
);
3725 if (!NILP (Vtemp_buffer_show_function
))
3726 call1 (Vtemp_buffer_show_function
, buf
);
3729 window
= display_buffer (buf
, Qnil
, Qnil
);
3731 if (!EQ (XWINDOW (window
)->frame
, selected_frame
))
3732 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window
)));
3733 Vminibuf_scroll_window
= window
;
3734 w
= XWINDOW (window
);
3735 XSETFASTINT (w
->hscroll
, 0);
3736 XSETFASTINT (w
->min_hscroll
, 0);
3737 set_marker_restricted_both (w
->start
, buf
, BEG
, BEG
);
3738 set_marker_restricted_both (w
->pointm
, buf
, BEG
, BEG
);
3740 /* Run temp-buffer-show-hook, with the chosen window selected
3741 and its buffer current. */
3743 if (!NILP (Vrun_hooks
)
3744 && !NILP (Fboundp (Qtemp_buffer_show_hook
))
3745 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook
)))
3747 int count
= SPECPDL_INDEX ();
3748 Lisp_Object prev_window
, prev_buffer
;
3749 prev_window
= selected_window
;
3750 XSETBUFFER (prev_buffer
, old
);
3752 /* Select the window that was chosen, for running the hook.
3753 Note: Both Fselect_window and select_window_norecord may
3754 set-buffer to the buffer displayed in the window,
3755 so we need to save the current buffer. --stef */
3756 record_unwind_protect (Fset_buffer
, prev_buffer
);
3757 record_unwind_protect (select_window_norecord
, prev_window
);
3758 Fselect_window (window
, Qt
);
3759 Fset_buffer (w
->buffer
);
3760 call1 (Vrun_hooks
, Qtemp_buffer_show_hook
);
3761 unbind_to (count
, Qnil
);
3767 make_dummy_parent (Lisp_Object window
)
3770 register struct window
*o
, *p
;
3773 o
= XWINDOW (window
);
3774 p
= allocate_window ();
3775 for (i
= 0; i
< VECSIZE (struct window
); ++i
)
3776 ((struct Lisp_Vector
*) p
)->contents
[i
]
3777 = ((struct Lisp_Vector
*)o
)->contents
[i
];
3778 XSETWINDOW (new, p
);
3781 XSETFASTINT (p
->sequence_number
, sequence_number
);
3783 /* Put new into window structure in place of window */
3784 replace_window (window
, new);
3797 DEFUN ("split-window", Fsplit_window
, Ssplit_window
, 0, 3, "",
3798 doc
: /* Split WINDOW, putting SIZE lines in the first of the pair.
3799 WINDOW defaults to selected one and SIZE to half its size.
3800 If optional third arg HORIZONTAL is non-nil, split side by side and put
3801 SIZE columns in the first of the pair. In that case, SIZE includes that
3802 window's scroll bar, or the divider column to its right.
3803 Interactively, all arguments are nil.
3804 Returns the newly created window (which is the lower or rightmost one).
3805 The upper or leftmost window is the original one, and remains selected
3806 if it was selected before.
3808 See Info node `(elisp)Splitting Windows' for more details and examples. */)
3809 (Lisp_Object window
, Lisp_Object size
, Lisp_Object horizontal
)
3811 register Lisp_Object
new;
3812 register struct window
*o
, *p
;
3814 register int size_int
;
3817 window
= selected_window
;
3819 CHECK_LIVE_WINDOW (window
);
3821 o
= XWINDOW (window
);
3822 fo
= XFRAME (WINDOW_FRAME (o
));
3826 if (!NILP (horizontal
))
3827 /* Calculate the size of the left-hand window, by dividing
3828 the usable space in columns by two.
3829 We round up, since the left-hand window may include
3830 a dividing line, while the right-hand may not. */
3831 size_int
= (XFASTINT (o
->total_cols
) + 1) >> 1;
3833 size_int
= XFASTINT (o
->total_lines
) >> 1;
3837 CHECK_NUMBER (size
);
3838 size_int
= XINT (size
);
3841 if (MINI_WINDOW_P (o
))
3842 error ("Attempt to split minibuffer window");
3843 else if (window_fixed_size_p (o
, !NILP (horizontal
), 0))
3844 error ("Attempt to split fixed-size window");
3846 if (NILP (horizontal
))
3848 int window_safe_height
= window_min_size_2 (o
, 0, 0);
3850 if (size_int
< window_safe_height
)
3851 error ("Window height %d too small (after splitting)", size_int
);
3852 if (size_int
+ window_safe_height
> XFASTINT (o
->total_lines
))
3853 error ("Window height %d too small (after splitting)",
3854 XFASTINT (o
->total_lines
) - size_int
);
3855 if (NILP (o
->parent
)
3856 || NILP (XWINDOW (o
->parent
)->vchild
))
3858 make_dummy_parent (window
);
3860 XWINDOW (new)->vchild
= window
;
3865 int window_safe_width
= window_min_size_2 (o
, 1, 0);
3867 if (size_int
< window_safe_width
)
3868 error ("Window width %d too small (after splitting)", size_int
);
3869 if (size_int
+ window_safe_width
> XFASTINT (o
->total_cols
))
3870 error ("Window width %d too small (after splitting)",
3871 XFASTINT (o
->total_cols
) - size_int
);
3872 if (NILP (o
->parent
)
3873 || NILP (XWINDOW (o
->parent
)->hchild
))
3875 make_dummy_parent (window
);
3877 XWINDOW (new)->hchild
= window
;
3881 /* Now we know that window's parent is a vertical combination
3882 if we are dividing vertically, or a horizontal combination
3883 if we are making side-by-side windows */
3885 windows_or_buffers_changed
++;
3886 FRAME_WINDOW_SIZES_CHANGED (fo
) = 1;
3887 new = make_window ();
3890 p
->frame
= o
->frame
;
3892 if (!NILP (p
->next
))
3893 XWINDOW (p
->next
)->prev
= new;
3896 p
->parent
= o
->parent
;
3898 p
->window_end_valid
= Qnil
;
3899 memset (&p
->last_cursor
, 0, sizeof p
->last_cursor
);
3901 /* Duplicate special geometry settings. */
3903 p
->left_margin_cols
= o
->left_margin_cols
;
3904 p
->right_margin_cols
= o
->right_margin_cols
;
3905 p
->left_fringe_width
= o
->left_fringe_width
;
3906 p
->right_fringe_width
= o
->right_fringe_width
;
3907 p
->fringes_outside_margins
= o
->fringes_outside_margins
;
3908 p
->scroll_bar_width
= o
->scroll_bar_width
;
3909 p
->vertical_scroll_bar_type
= o
->vertical_scroll_bar_type
;
3911 /* Apportion the available frame space among the two new windows */
3913 if (!NILP (horizontal
))
3915 p
->total_lines
= o
->total_lines
;
3916 p
->top_line
= o
->top_line
;
3917 XSETFASTINT (p
->total_cols
, XFASTINT (o
->total_cols
) - size_int
);
3918 XSETFASTINT (o
->total_cols
, size_int
);
3919 XSETFASTINT (p
->left_col
, XFASTINT (o
->left_col
) + size_int
);
3920 adjust_window_margins (p
);
3921 adjust_window_margins (o
);
3925 p
->left_col
= o
->left_col
;
3926 p
->total_cols
= o
->total_cols
;
3927 XSETFASTINT (p
->total_lines
, XFASTINT (o
->total_lines
) - size_int
);
3928 XSETFASTINT (o
->total_lines
, size_int
);
3929 XSETFASTINT (p
->top_line
, XFASTINT (o
->top_line
) + size_int
);
3932 /* Adjust glyph matrices. */
3935 Fset_window_buffer (new, o
->buffer
, Qt
);
3939 DEFUN ("enlarge-window", Fenlarge_window
, Senlarge_window
, 1, 2, "p",
3940 doc
: /* Make selected window SIZE lines taller.
3941 Interactively, if no argument is given, make the selected window one
3942 line taller. If optional argument HORIZONTAL is non-nil, make selected
3943 window wider by SIZE columns. If SIZE is negative, shrink the window by
3944 -SIZE lines or columns. Return nil.
3946 This function can delete windows if they get too small. The size of
3947 fixed size windows is not altered by this function. */)
3948 (Lisp_Object size
, Lisp_Object horizontal
)
3950 CHECK_NUMBER (size
);
3951 enlarge_window (selected_window
, XINT (size
), !NILP (horizontal
));
3953 run_window_configuration_change_hook (SELECTED_FRAME ());
3958 DEFUN ("shrink-window", Fshrink_window
, Sshrink_window
, 1, 2, "p",
3959 doc
: /* Make selected window SIZE lines smaller.
3960 Interactively, if no argument is given, make the selected window one
3961 line smaller. If optional argument HORIZONTAL is non-nil, make the
3962 window narrower by SIZE columns. If SIZE is negative, enlarge selected
3963 window by -SIZE lines or columns. Return nil.
3965 This function can delete windows if they get too small. The size of
3966 fixed size windows is not altered by this function. */)
3967 (Lisp_Object size
, Lisp_Object horizontal
)
3969 CHECK_NUMBER (size
);
3970 enlarge_window (selected_window
, -XINT (size
), !NILP (horizontal
));
3972 run_window_configuration_change_hook (SELECTED_FRAME ());
3978 window_height (Lisp_Object window
)
3980 register struct window
*p
= XWINDOW (window
);
3981 return WINDOW_TOTAL_LINES (p
);
3985 window_width (Lisp_Object window
)
3987 register struct window
*p
= XWINDOW (window
);
3988 return WINDOW_TOTAL_COLS (p
);
3993 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
3995 #define CURSIZE(w) \
3996 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
3999 /* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it
4000 horizontally; zero means do it vertically.
4002 Siblings of the selected window are resized to fulfill the size
4003 request. If they become too small in the process, they may be
4007 enlarge_window (Lisp_Object window
, int delta
, int horiz_flag
)
4009 Lisp_Object parent
, next
, prev
;
4013 int (*sizefun
) (Lisp_Object
)
4014 = horiz_flag
? window_width
: window_height
;
4015 void (*setsizefun
) (Lisp_Object
, int, int)
4016 = (horiz_flag
? set_window_width
: set_window_height
);
4018 /* Give up if this window cannot be resized. */
4019 if (window_fixed_size_p (XWINDOW (window
), horiz_flag
, 1))
4020 error ("Window is not resizable");
4022 /* Find the parent of the selected window. */
4025 p
= XWINDOW (window
);
4031 error ("No other window to side of this one");
4036 ? !NILP (XWINDOW (parent
)->hchild
)
4037 : !NILP (XWINDOW (parent
)->vchild
))
4043 sizep
= &CURSIZE (window
);
4046 register int maxdelta
;
4048 /* Compute the maximum size increment this window can have. */
4050 maxdelta
= (!NILP (parent
) ? (*sizefun
) (parent
) - XINT (*sizep
)
4051 /* This is a main window followed by a minibuffer. */
4052 : !NILP (p
->next
) ? ((*sizefun
) (p
->next
)
4053 - window_min_size (XWINDOW (p
->next
),
4054 horiz_flag
, 0, 0, 0))
4055 /* This is a minibuffer following a main window. */
4056 : !NILP (p
->prev
) ? ((*sizefun
) (p
->prev
)
4057 - window_min_size (XWINDOW (p
->prev
),
4058 horiz_flag
, 0, 0, 0))
4059 /* This is a frame with only one window, a minibuffer-only
4060 or a minibufferless frame. */
4063 if (delta
> maxdelta
)
4064 /* This case traps trying to make the minibuffer
4065 the full frame, or make the only window aside from the
4066 minibuffer the full frame. */
4070 if (XINT (*sizep
) + delta
< window_min_size (XWINDOW (window
),
4071 horiz_flag
, 0, 0, 0))
4073 delete_window (window
);
4080 /* Find the total we can get from other siblings without deleting them. */
4082 for (next
= p
->next
; WINDOWP (next
); next
= XWINDOW (next
)->next
)
4083 maximum
+= (*sizefun
) (next
) - window_min_size (XWINDOW (next
),
4084 horiz_flag
, 0, 0, 0);
4085 for (prev
= p
->prev
; WINDOWP (prev
); prev
= XWINDOW (prev
)->prev
)
4086 maximum
+= (*sizefun
) (prev
) - window_min_size (XWINDOW (prev
),
4087 horiz_flag
, 0, 0, 0);
4089 /* If we can get it all from them without deleting them, do so. */
4090 if (delta
<= maximum
)
4092 Lisp_Object first_unaffected
;
4093 Lisp_Object first_affected
;
4098 first_affected
= window
;
4099 /* Look at one sibling at a time,
4100 moving away from this window in both directions alternately,
4101 and take as much as we can get without deleting that sibling. */
4103 && (!NILP (next
) || !NILP (prev
)))
4107 int this_one
= ((*sizefun
) (next
)
4108 - window_min_size (XWINDOW (next
), horiz_flag
,
4112 if (this_one
> delta
)
4115 (*setsizefun
) (next
, (*sizefun
) (next
) - this_one
, 0);
4116 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
4121 next
= XWINDOW (next
)->next
;
4129 int this_one
= ((*sizefun
) (prev
)
4130 - window_min_size (XWINDOW (prev
), horiz_flag
,
4134 if (this_one
> delta
)
4137 first_affected
= prev
;
4139 (*setsizefun
) (prev
, (*sizefun
) (prev
) - this_one
, 0);
4140 (*setsizefun
) (window
, XINT (*sizep
) + this_one
, 0);
4145 prev
= XWINDOW (prev
)->prev
;
4149 xassert (delta
== 0);
4151 /* Now recalculate the edge positions of all the windows affected,
4152 based on the new sizes. */
4153 first_unaffected
= next
;
4154 prev
= first_affected
;
4155 for (next
= XWINDOW (prev
)->next
; ! EQ (next
, first_unaffected
);
4156 prev
= next
, next
= XWINDOW (next
)->next
)
4158 XSETINT (CURBEG (next
), XINT (CURBEG (prev
)) + (*sizefun
) (prev
));
4159 /* This does not change size of NEXT,
4160 but it propagates the new top edge to its children */
4161 (*setsizefun
) (next
, (*sizefun
) (next
), 0);
4166 register int delta1
;
4167 register int opht
= (*sizefun
) (parent
);
4169 if (opht
<= XINT (*sizep
) + delta
)
4171 /* If trying to grow this window to or beyond size of the parent,
4172 just delete all the sibling windows. */
4173 Lisp_Object start
, tem
, next
;
4175 start
= XWINDOW (parent
)->vchild
;
4177 start
= XWINDOW (parent
)->hchild
;
4179 /* Delete any siblings that come after WINDOW. */
4180 tem
= XWINDOW (window
)->next
;
4181 while (! NILP (tem
))
4183 next
= XWINDOW (tem
)->next
;
4184 delete_window (tem
);
4188 /* Delete any siblings that come after WINDOW.
4189 Note that if START is not WINDOW, then WINDOW still
4190 has siblings, so WINDOW has not yet replaced its parent. */
4192 while (! EQ (tem
, window
))
4194 next
= XWINDOW (tem
)->next
;
4195 delete_window (tem
);
4201 /* Otherwise, make delta1 just right so that if we add
4202 delta1 lines to this window and to the parent, and then
4203 shrink the parent back to its original size, the new
4204 proportional size of this window will increase by delta.
4206 The function size_window will compute the new height h'
4207 of the window from delta1 as:
4210 x = delta1 - delta1/n * n for the 1st resizable child
4213 where n is the number of children that can be resized.
4214 We can ignore x by choosing a delta1 that is a multiple of
4215 n. We want the height of this window to come out as
4225 The number of children n equals the number of resizable
4226 children of this window + 1 because we know window itself
4227 is resizable (otherwise we would have signaled an error).
4229 This reasoning is not correct when other windows become too
4230 small and shrink_windows refuses to delete them. Below we
4231 use resize_proportionally to work around this problem. */
4233 struct window
*w
= XWINDOW (window
);
4237 for (s
= w
->next
; WINDOWP (s
); s
= XWINDOW (s
)->next
)
4238 if (!window_fixed_size_p (XWINDOW (s
), horiz_flag
, 0))
4240 for (s
= w
->prev
; WINDOWP (s
); s
= XWINDOW (s
)->prev
)
4241 if (!window_fixed_size_p (XWINDOW (s
), horiz_flag
, 0))
4246 /* Add delta1 lines or columns to this window, and to the parent,
4247 keeping things consistent while not affecting siblings. */
4248 XSETINT (CURSIZE (parent
), opht
+ delta1
);
4249 (*setsizefun
) (window
, XINT (*sizep
) + delta1
, 0);
4251 /* Squeeze out delta1 lines or columns from our parent,
4252 shrinking this window and siblings proportionately. This
4253 brings parent back to correct size. Delta1 was calculated
4254 so this makes this window the desired size, taking it all
4255 out of the siblings.
4257 Temporarily set resize_proportionally to Qt to assure that,
4258 if necessary, shrink_windows deletes smaller windows rather
4259 than shrink this window. */
4260 w
->resize_proportionally
= Qt
;
4261 (*setsizefun
) (parent
, opht
, 0);
4262 w
->resize_proportionally
= Qnil
;
4266 XSETFASTINT (p
->last_modified
, 0);
4267 XSETFASTINT (p
->last_overlay_modified
, 0);
4269 /* Adjust glyph matrices. */
4270 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4274 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4275 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4276 zero means adjust the height, moving the bottom edge.
4278 Following siblings of the selected window are resized to fulfill
4279 the size request. If they become too small in the process, they
4280 are not deleted; instead, we signal an error. */
4283 adjust_window_trailing_edge (Lisp_Object window
, int delta
, int horiz_flag
)
4285 Lisp_Object parent
, child
;
4287 Lisp_Object old_config
= Fcurrent_window_configuration (Qnil
);
4288 int delcount
= window_deletion_count
;
4290 CHECK_WINDOW (window
);
4292 /* Give up if this window cannot be resized. */
4293 if (window_fixed_size_p (XWINDOW (window
), horiz_flag
, 1))
4294 error ("Window is not resizable");
4298 Lisp_Object first_parallel
= Qnil
;
4302 /* This happens if WINDOW on the previous iteration was
4303 at top level of the window tree. */
4304 Fset_window_configuration (old_config
);
4305 error ("Specified window edge is fixed");
4308 p
= XWINDOW (window
);
4311 /* See if this level has windows in parallel in the specified
4312 direction. If so, set FIRST_PARALLEL to the first one. */
4315 if (! NILP (parent
) && !NILP (XWINDOW (parent
)->vchild
))
4316 first_parallel
= XWINDOW (parent
)->vchild
;
4317 else if (NILP (parent
) && !NILP (p
->next
))
4319 /* Handle the vertical chain of main window and minibuffer
4320 which has no parent. */
4321 first_parallel
= window
;
4322 while (! NILP (XWINDOW (first_parallel
)->prev
))
4323 first_parallel
= XWINDOW (first_parallel
)->prev
;
4328 if (! NILP (parent
) && !NILP (XWINDOW (parent
)->hchild
))
4329 first_parallel
= XWINDOW (parent
)->hchild
;
4332 /* If this level's succession is in the desired dimension,
4333 and this window is the last one, and there is no higher level,
4334 its trailing edge is fixed. */
4335 if (NILP (XWINDOW (window
)->next
) && NILP (first_parallel
)
4338 Fset_window_configuration (old_config
);
4339 error ("Specified window edge is fixed");
4342 /* Don't make this window too small. */
4343 if (XINT (CURSIZE (window
)) + delta
4344 < window_min_size_2 (XWINDOW (window
), horiz_flag
, 0))
4346 Fset_window_configuration (old_config
);
4347 error ("Cannot adjust window size as specified");
4350 /* Clear out some redisplay caches. */
4351 XSETFASTINT (p
->last_modified
, 0);
4352 XSETFASTINT (p
->last_overlay_modified
, 0);
4354 /* Adjust this window's edge. */
4355 XSETINT (CURSIZE (window
),
4356 XINT (CURSIZE (window
)) + delta
);
4358 /* If this window has following siblings in the desired dimension,
4359 make them smaller, and exit the loop.
4361 (If we reach the top of the tree and can never do this,
4362 we will fail and report an error, above.) */
4363 if (NILP (first_parallel
))
4365 if (!NILP (p
->next
))
4367 /* This may happen for the minibuffer. In that case
4368 the window_deletion_count check below does not work. */
4369 if (XINT (CURSIZE (p
->next
)) - delta
<= 0)
4371 Fset_window_configuration (old_config
);
4372 error ("Cannot adjust window size as specified");
4375 XSETINT (CURBEG (p
->next
),
4376 XINT (CURBEG (p
->next
)) + delta
);
4377 size_window (p
->next
, XINT (CURSIZE (p
->next
)) - delta
,
4378 horiz_flag
, 0, 1, 0);
4383 /* Here we have a chain of parallel siblings, in the other dimension.
4384 Change the size of the other siblings. */
4385 for (child
= first_parallel
;
4387 child
= XWINDOW (child
)->next
)
4388 if (! EQ (child
, window
))
4389 size_window (child
, XINT (CURSIZE (child
)) + delta
,
4390 horiz_flag
, 0, 0, 1);
4395 /* If we made a window so small it got deleted,
4396 we failed. Report failure. */
4397 if (delcount
!= window_deletion_count
)
4399 Fset_window_configuration (old_config
);
4400 error ("Cannot adjust window size as specified");
4403 /* Adjust glyph matrices. */
4404 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4410 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge
,
4411 Sadjust_window_trailing_edge
, 3, 3, 0,
4412 doc
: /* Adjust the bottom or right edge of WINDOW by DELTA.
4413 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4414 Otherwise, adjust the height, moving the bottom edge.
4416 Following siblings of the selected window are resized to fulfill
4417 the size request. If they become too small in the process, they
4418 are not deleted; instead, we signal an error. */)
4419 (Lisp_Object window
, Lisp_Object delta
, Lisp_Object horizontal
)
4421 CHECK_NUMBER (delta
);
4423 window
= selected_window
;
4424 adjust_window_trailing_edge (window
, XINT (delta
), !NILP (horizontal
));
4426 run_window_configuration_change_hook
4427 (XFRAME (WINDOW_FRAME (XWINDOW (window
))));
4434 /***********************************************************************
4435 Resizing Mini-Windows
4436 ***********************************************************************/
4438 static void shrink_window_lowest_first (struct window
*, int);
4440 enum save_restore_action
4447 static int save_restore_orig_size (struct window
*,
4448 enum save_restore_action
);
4450 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4451 from lowest windows first. */
4454 shrink_window_lowest_first (struct window
*w
, int height
)
4460 xassert (!MINI_WINDOW_P (w
));
4462 /* Set redisplay hints. */
4463 XSETFASTINT (w
->last_modified
, 0);
4464 XSETFASTINT (w
->last_overlay_modified
, 0);
4465 windows_or_buffers_changed
++;
4466 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w
))) = 1;
4468 old_height
= XFASTINT (w
->total_lines
);
4469 XSETFASTINT (w
->total_lines
, height
);
4471 if (!NILP (w
->hchild
))
4473 for (child
= w
->hchild
; !NILP (child
); child
= c
->next
)
4475 c
= XWINDOW (child
);
4476 c
->top_line
= w
->top_line
;
4477 shrink_window_lowest_first (c
, height
);
4480 else if (!NILP (w
->vchild
))
4482 Lisp_Object last_child
;
4483 int delta
= old_height
- height
;
4488 /* Find the last child. We are taking space from lowest windows
4489 first, so we iterate over children from the last child
4491 for (child
= w
->vchild
; WINDOWP (child
); child
= XWINDOW (child
)->next
)
4494 /* Size children down to their safe heights. */
4495 for (child
= last_child
; delta
&& !NILP (child
); child
= c
->prev
)
4499 c
= XWINDOW (child
);
4500 this_one
= XFASTINT (c
->total_lines
) - window_min_size_1 (c
, 0, 1);
4502 if (this_one
> delta
)
4505 shrink_window_lowest_first (c
, XFASTINT (c
->total_lines
) - this_one
);
4509 /* Compute new positions. */
4510 last_top
= XINT (w
->top_line
);
4511 for (child
= w
->vchild
; !NILP (child
); child
= c
->next
)
4513 c
= XWINDOW (child
);
4514 c
->top_line
= make_number (last_top
);
4515 shrink_window_lowest_first (c
, XFASTINT (c
->total_lines
));
4516 last_top
+= XFASTINT (c
->total_lines
);
4522 /* Save, restore, or check positions and sizes in the window tree
4523 rooted at W. ACTION says what to do.
4525 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4526 orig_total_lines members are valid for all windows in the window
4527 tree. Value is non-zero if they are valid.
4529 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4530 orig_top_line and orig_total_lines for all windows in the tree.
4532 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4533 stored in orig_top_line and orig_total_lines for all windows. */
4536 save_restore_orig_size (struct window
*w
, enum save_restore_action action
)
4542 if (!NILP (w
->hchild
))
4544 if (!save_restore_orig_size (XWINDOW (w
->hchild
), action
))
4547 else if (!NILP (w
->vchild
))
4549 if (!save_restore_orig_size (XWINDOW (w
->vchild
), action
))
4555 case CHECK_ORIG_SIZES
:
4556 if (!INTEGERP (w
->orig_top_line
) || !INTEGERP (w
->orig_total_lines
))
4560 case SAVE_ORIG_SIZES
:
4561 w
->orig_top_line
= w
->top_line
;
4562 w
->orig_total_lines
= w
->total_lines
;
4563 XSETFASTINT (w
->last_modified
, 0);
4564 XSETFASTINT (w
->last_overlay_modified
, 0);
4567 case RESTORE_ORIG_SIZES
:
4568 xassert (INTEGERP (w
->orig_top_line
) && INTEGERP (w
->orig_total_lines
));
4569 w
->top_line
= w
->orig_top_line
;
4570 w
->total_lines
= w
->orig_total_lines
;
4571 w
->orig_total_lines
= w
->orig_top_line
= Qnil
;
4572 XSETFASTINT (w
->last_modified
, 0);
4573 XSETFASTINT (w
->last_overlay_modified
, 0);
4580 w
= NILP (w
->next
) ? NULL
: XWINDOW (w
->next
);
4587 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4588 without deleting other windows. */
4591 grow_mini_window (struct window
*w
, int delta
)
4593 struct frame
*f
= XFRAME (w
->frame
);
4594 struct window
*root
;
4596 xassert (MINI_WINDOW_P (w
));
4597 /* Commenting out the following assertion goes against the stated interface
4598 of the function, but it currently does not seem to do anything useful.
4599 See discussion of this issue in the thread for bug#4534.
4600 xassert (delta >= 0); */
4602 /* Compute how much we can enlarge the mini-window without deleting
4604 root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4607 int min_height
= window_min_size (root
, 0, 0, 0, 0);
4608 if (XFASTINT (root
->total_lines
) - delta
< min_height
)
4609 /* Note that the root window may already be smaller than
4611 delta
= max (0, XFASTINT (root
->total_lines
) - min_height
);
4616 /* Save original window sizes and positions, if not already done. */
4617 if (!save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
4618 save_restore_orig_size (root
, SAVE_ORIG_SIZES
);
4620 /* Shrink other windows. */
4621 shrink_window_lowest_first (root
, XFASTINT (root
->total_lines
) - delta
);
4623 /* Grow the mini-window. */
4624 w
->top_line
= make_number (XFASTINT (root
->top_line
) + XFASTINT (root
->total_lines
));
4625 w
->total_lines
= make_number (XFASTINT (w
->total_lines
) + delta
);
4626 XSETFASTINT (w
->last_modified
, 0);
4627 XSETFASTINT (w
->last_overlay_modified
, 0);
4634 /* Shrink mini-window W. If there is recorded info about window sizes
4635 before a call to grow_mini_window, restore recorded window sizes.
4636 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4640 shrink_mini_window (struct window
*w
)
4642 struct frame
*f
= XFRAME (w
->frame
);
4643 struct window
*root
= XWINDOW (FRAME_ROOT_WINDOW (f
));
4645 if (save_restore_orig_size (root
, CHECK_ORIG_SIZES
))
4647 save_restore_orig_size (root
, RESTORE_ORIG_SIZES
);
4649 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
4650 windows_or_buffers_changed
= 1;
4652 else if (XFASTINT (w
->total_lines
) > 1)
4654 /* Distribute the additional lines of the mini-window
4655 among the other windows. */
4657 XSETWINDOW (window
, w
);
4658 enlarge_window (window
, 1 - XFASTINT (w
->total_lines
), 0);
4664 /* Mark window cursors off for all windows in the window tree rooted
4665 at W by setting their phys_cursor_on_p flag to zero. Called from
4666 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4667 the frame are cleared. */
4670 mark_window_cursors_off (struct window
*w
)
4674 if (!NILP (w
->hchild
))
4675 mark_window_cursors_off (XWINDOW (w
->hchild
));
4676 else if (!NILP (w
->vchild
))
4677 mark_window_cursors_off (XWINDOW (w
->vchild
));
4679 w
->phys_cursor_on_p
= 0;
4681 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
4686 /* Return number of lines of text (not counting mode lines) in W. */
4689 window_internal_height (struct window
*w
)
4691 int ht
= XFASTINT (w
->total_lines
);
4693 if (!MINI_WINDOW_P (w
))
4695 if (!NILP (w
->parent
)
4696 || !NILP (w
->vchild
)
4697 || !NILP (w
->hchild
)
4700 || WINDOW_WANTS_MODELINE_P (w
))
4703 if (WINDOW_WANTS_HEADER_LINE_P (w
))
4711 /* Return the number of columns in W.
4712 Don't count columns occupied by scroll bars or the vertical bar
4713 separating W from the sibling to its right. */
4716 window_box_text_cols (struct window
*w
)
4718 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4719 int width
= XINT (w
->total_cols
);
4721 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w
))
4722 /* Scroll bars occupy a few columns. */
4723 width
-= WINDOW_CONFIG_SCROLL_BAR_COLS (w
);
4724 else if (!FRAME_WINDOW_P (f
)
4725 && !WINDOW_RIGHTMOST_P (w
) && !WINDOW_FULL_WIDTH_P (w
))
4726 /* The column of `|' characters separating side-by-side windows
4727 occupies one column only. */
4730 if (FRAME_WINDOW_P (f
))
4731 /* On window-systems, fringes and display margins cannot be
4732 used for normal text. */
4733 width
-= (WINDOW_FRINGE_COLS (w
)
4734 + WINDOW_LEFT_MARGIN_COLS (w
)
4735 + WINDOW_RIGHT_MARGIN_COLS (w
));
4741 /************************************************************************
4743 ***********************************************************************/
4745 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4746 N screen-fulls, which is defined as the height of the window minus
4747 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4748 instead. Negative values of N mean scroll down. NOERROR non-zero
4749 means don't signal an error if we try to move over BEGV or ZV,
4753 window_scroll (Lisp_Object window
, int n
, int whole
, int noerror
)
4757 /* If we must, use the pixel-based version which is much slower than
4758 the line-based one but can handle varying line heights. */
4759 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window
)->frame
)))
4760 window_scroll_pixel_based (window
, n
, whole
, noerror
);
4762 window_scroll_line_based (window
, n
, whole
, noerror
);
4768 /* Implementation of window_scroll that works based on pixel line
4769 heights. See the comment of window_scroll for parameter
4773 window_scroll_pixel_based (Lisp_Object window
, int n
, int whole
, int noerror
)
4776 struct window
*w
= XWINDOW (window
);
4777 struct text_pos start
;
4778 int this_scroll_margin
;
4779 /* True if we fiddled the window vscroll field without really scrolling. */
4781 int x
, y
, rtop
, rbot
, rowh
, vpos
;
4783 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
4785 /* If PT is not visible in WINDOW, move back one half of
4786 the screen. Allow PT to be partially visible, otherwise
4787 something like (scroll-down 1) with PT in the line before
4788 the partially visible one would recenter. */
4790 if (!pos_visible_p (w
, PT
, &x
, &y
, &rtop
, &rbot
, &rowh
, &vpos
))
4792 /* Move backward half the height of the window. Performance note:
4793 vmotion used here is about 10% faster, but would give wrong
4794 results for variable height lines. */
4795 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4796 it
.current_y
= it
.last_visible_y
;
4797 move_it_vertically_backward (&it
, window_box_height (w
) / 2);
4799 /* The function move_iterator_vertically may move over more than
4800 the specified y-distance. If it->w is small, e.g. a
4801 mini-buffer window, we may end up in front of the window's
4802 display area. This is the case when Start displaying at the
4803 start of the line containing PT in this case. */
4804 if (it
.current_y
<= 0)
4806 init_iterator (&it
, w
, PT
, PT_BYTE
, NULL
, DEFAULT_FACE_ID
);
4807 move_it_vertically_backward (&it
, 0);
4811 start
= it
.current
.pos
;
4813 else if (auto_window_vscroll_p
)
4815 if (rtop
|| rbot
) /* partially visible */
4818 int dy
= WINDOW_FRAME_LINE_HEIGHT (w
);
4820 dy
= max ((window_box_height (w
)
4821 - next_screen_context_lines
* dy
),
4827 /* Only vscroll backwards if already vscrolled forwards. */
4828 if (w
->vscroll
< 0 && rtop
> 0)
4830 px
= max (0, -w
->vscroll
- min (rtop
, -dy
));
4831 Fset_window_vscroll (window
, make_number (px
), Qt
);
4837 /* Do vscroll if already vscrolled or only display line. */
4838 if (rbot
> 0 && (w
->vscroll
< 0 || vpos
== 0))
4840 px
= max (0, -w
->vscroll
+ min (rbot
, dy
));
4841 Fset_window_vscroll (window
, make_number (px
), Qt
);
4845 /* Maybe modify window start instead of scrolling. */
4846 if (rbot
> 0 || w
->vscroll
< 0)
4850 Fset_window_vscroll (window
, make_number (0), Qt
);
4851 /* If there are other text lines above the current row,
4852 move window start to current row. Else to next row. */
4854 spos
= XINT (Fline_beginning_position (Qnil
));
4856 spos
= min (XINT (Fline_end_position (Qnil
)) + 1, ZV
);
4857 set_marker_restricted (w
->start
, make_number (spos
),
4859 w
->start_at_line_beg
= Qt
;
4860 w
->update_mode_line
= Qt
;
4861 XSETFASTINT (w
->last_modified
, 0);
4862 XSETFASTINT (w
->last_overlay_modified
, 0);
4863 /* Set force_start so that redisplay_window will run the
4864 window-scroll-functions. */
4865 w
->force_start
= Qt
;
4870 /* Cancel previous vscroll. */
4871 Fset_window_vscroll (window
, make_number (0), Qt
);
4874 /* If scroll_preserve_screen_position is non-nil, we try to set
4875 point in the same window line as it is now, so get that line. */
4876 if (!NILP (Vscroll_preserve_screen_position
))
4878 /* We preserve the goal pixel coordinate across consecutive
4879 calls to scroll-up, scroll-down and other commands that
4880 have the `scroll-command' property. This avoids the
4881 possibility of point becoming "stuck" on a tall line when
4882 scrolling by one line. */
4883 if (window_scroll_pixel_based_preserve_y
< 0
4884 || !SYMBOLP (current_kboard
->Vlast_command
)
4885 || NILP (Fget (current_kboard
->Vlast_command
, Qscroll_command
)))
4887 start_display (&it
, w
, start
);
4888 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
4889 window_scroll_pixel_based_preserve_y
= it
.current_y
;
4890 window_scroll_pixel_based_preserve_x
= it
.current_x
;
4894 window_scroll_pixel_based_preserve_y
4895 = window_scroll_pixel_based_preserve_x
= -1;
4897 /* Move iterator it from start the specified distance forward or
4898 backward. The result is the new window start. */
4899 start_display (&it
, w
, start
);
4902 EMACS_INT start_pos
= IT_CHARPOS (it
);
4903 int dy
= WINDOW_FRAME_LINE_HEIGHT (w
);
4904 dy
= max ((window_box_height (w
)
4905 - next_screen_context_lines
* dy
),
4908 /* Note that move_it_vertically always moves the iterator to the
4909 start of a line. So, if the last line doesn't have a newline,
4910 we would end up at the start of the line ending at ZV. */
4913 move_it_vertically_backward (&it
, -dy
);
4914 /* Ensure we actually do move, e.g. in case we are currently
4915 looking at an image that is taller that the window height. */
4916 while (start_pos
== IT_CHARPOS (it
)
4917 && start_pos
> BEGV
)
4918 move_it_by_lines (&it
, -1, 1);
4922 move_it_to (&it
, ZV
, -1, it
.current_y
+ dy
, -1,
4923 MOVE_TO_POS
| MOVE_TO_Y
);
4924 /* Ensure we actually do move, e.g. in case we are currently
4925 looking at an image that is taller that the window height. */
4926 while (start_pos
== IT_CHARPOS (it
)
4928 move_it_by_lines (&it
, 1, 1);
4932 move_it_by_lines (&it
, n
, 1);
4934 /* We failed if we find ZV is already on the screen (scrolling up,
4935 means there's nothing past the end), or if we can't start any
4936 earlier (scrolling down, means there's nothing past the top). */
4937 if ((n
> 0 && IT_CHARPOS (it
) == ZV
)
4938 || (n
< 0 && IT_CHARPOS (it
) == CHARPOS (start
)))
4940 if (IT_CHARPOS (it
) == ZV
)
4942 if (it
.current_y
< it
.last_visible_y
4943 && (it
.current_y
+ it
.max_ascent
+ it
.max_descent
4944 > it
.last_visible_y
))
4946 /* The last line was only partially visible, make it fully
4948 w
->vscroll
= (it
.last_visible_y
4949 - it
.current_y
+ it
.max_ascent
+ it
.max_descent
);
4950 adjust_glyphs (it
.f
);
4954 else if (n
< 0) /* could happen with empty buffers */
4955 xsignal0 (Qbeginning_of_buffer
);
4957 xsignal0 (Qend_of_buffer
);
4961 if (w
->vscroll
!= 0)
4962 /* The first line was only partially visible, make it fully
4968 xsignal0 (Qbeginning_of_buffer
);
4971 /* If control gets here, then we vscrolled. */
4973 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
4975 /* Don't try to change the window start below. */
4981 EMACS_INT pos
= IT_CHARPOS (it
);
4984 /* If in the middle of a multi-glyph character move forward to
4985 the next character. */
4986 if (in_display_vector_p (&it
))
4989 move_it_to (&it
, pos
, -1, -1, -1, MOVE_TO_POS
);
4992 /* Set the window start, and set up the window for redisplay. */
4993 set_marker_restricted (w
->start
, make_number (pos
),
4995 bytepos
= XMARKER (w
->start
)->bytepos
;
4996 w
->start_at_line_beg
= ((pos
== BEGV
|| FETCH_BYTE (bytepos
- 1) == '\n')
4998 w
->update_mode_line
= Qt
;
4999 XSETFASTINT (w
->last_modified
, 0);
5000 XSETFASTINT (w
->last_overlay_modified
, 0);
5001 /* Set force_start so that redisplay_window will run the
5002 window-scroll-functions. */
5003 w
->force_start
= Qt
;
5006 /* The rest of this function uses current_y in a nonstandard way,
5007 not including the height of the header line if any. */
5008 it
.current_y
= it
.vpos
= 0;
5010 /* Move PT out of scroll margins.
5011 This code wants current_y to be zero at the window start position
5012 even if there is a header line. */
5013 this_scroll_margin
= max (0, scroll_margin
);
5014 this_scroll_margin
= min (this_scroll_margin
, XFASTINT (w
->total_lines
) / 4);
5015 this_scroll_margin
*= FRAME_LINE_HEIGHT (it
.f
);
5019 /* We moved the window start towards ZV, so PT may be now
5020 in the scroll margin at the top. */
5021 move_it_to (&it
, PT
, -1, -1, -1, MOVE_TO_POS
);
5022 if (IT_CHARPOS (it
) == PT
&& it
.current_y
>= this_scroll_margin
5023 && (NILP (Vscroll_preserve_screen_position
)
5024 || EQ (Vscroll_preserve_screen_position
, Qt
)))
5025 /* We found PT at a legitimate height. Leave it alone. */
5027 else if (window_scroll_pixel_based_preserve_y
>= 0)
5029 /* If we have a header line, take account of it.
5030 This is necessary because we set it.current_y to 0, above. */
5031 move_it_to (&it
, -1,
5032 window_scroll_pixel_based_preserve_x
,
5033 window_scroll_pixel_based_preserve_y
5034 - (WINDOW_WANTS_HEADER_LINE_P (w
) ? 1 : 0 ),
5035 -1, MOVE_TO_Y
| MOVE_TO_X
);
5036 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5040 while (it
.current_y
< this_scroll_margin
)
5042 int prev
= it
.current_y
;
5043 move_it_by_lines (&it
, 1, 1);
5044 if (prev
== it
.current_y
)
5047 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5052 EMACS_INT charpos
, bytepos
;
5055 /* Save our position, for the
5056 window_scroll_pixel_based_preserve_y case. */
5057 charpos
= IT_CHARPOS (it
);
5058 bytepos
= IT_BYTEPOS (it
);
5060 /* We moved the window start towards BEGV, so PT may be now
5061 in the scroll margin at the bottom. */
5062 move_it_to (&it
, PT
, -1,
5063 (it
.last_visible_y
- CURRENT_HEADER_LINE_HEIGHT (w
)
5064 - this_scroll_margin
- 1),
5066 MOVE_TO_POS
| MOVE_TO_Y
);
5068 /* Save our position, in case it's correct. */
5069 charpos
= IT_CHARPOS (it
);
5070 bytepos
= IT_BYTEPOS (it
);
5072 /* See if point is on a partially visible line at the end. */
5073 if (it
.what
== IT_EOB
)
5074 partial_p
= it
.current_y
+ it
.ascent
+ it
.descent
> it
.last_visible_y
;
5077 move_it_by_lines (&it
, 1, 1);
5078 partial_p
= it
.current_y
> it
.last_visible_y
;
5081 if (charpos
== PT
&& !partial_p
5082 && (NILP (Vscroll_preserve_screen_position
)
5083 || EQ (Vscroll_preserve_screen_position
, Qt
)))
5084 /* We found PT before we found the display margin, so PT is ok. */
5086 else if (window_scroll_pixel_based_preserve_y
>= 0)
5088 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
5089 start_display (&it
, w
, start
);
5090 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5091 here because we called start_display again and did not
5092 alter it.current_y this time. */
5093 move_it_to (&it
, -1, window_scroll_pixel_based_preserve_x
,
5094 window_scroll_pixel_based_preserve_y
, -1,
5095 MOVE_TO_Y
| MOVE_TO_X
);
5096 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5101 /* The last line was only partially visible, so back up two
5102 lines to make sure we're on a fully visible line. */
5104 move_it_by_lines (&it
, -2, 0);
5105 SET_PT_BOTH (IT_CHARPOS (it
), IT_BYTEPOS (it
));
5108 /* No, the position we saved is OK, so use it. */
5109 SET_PT_BOTH (charpos
, bytepos
);
5115 /* Implementation of window_scroll that works based on screen lines.
5116 See the comment of window_scroll for parameter descriptions. */
5119 window_scroll_line_based (Lisp_Object window
, int n
, int whole
, int noerror
)
5121 register struct window
*w
= XWINDOW (window
);
5122 register EMACS_INT opoint
= PT
, opoint_byte
= PT_BYTE
;
5123 register EMACS_INT pos
, pos_byte
;
5124 register int ht
= window_internal_height (w
);
5125 register Lisp_Object tem
;
5129 Lisp_Object original_pos
= Qnil
;
5131 /* If scrolling screen-fulls, compute the number of lines to
5132 scroll from the window's height. */
5134 n
*= max (1, ht
- next_screen_context_lines
);
5136 startpos
= marker_position (w
->start
);
5138 if (!NILP (Vscroll_preserve_screen_position
))
5140 if (window_scroll_preserve_vpos
<= 0
5141 || !SYMBOLP (current_kboard
->Vlast_command
)
5142 || NILP (Fget (current_kboard
->Vlast_command
, Qscroll_command
)))
5144 struct position posit
5145 = *compute_motion (startpos
, 0, 0, 0,
5147 -1, XINT (w
->hscroll
),
5149 window_scroll_preserve_vpos
= posit
.vpos
;
5150 window_scroll_preserve_hpos
= posit
.hpos
+ XINT (w
->hscroll
);
5153 original_pos
= Fcons (make_number (window_scroll_preserve_hpos
),
5154 make_number (window_scroll_preserve_vpos
));
5157 XSETFASTINT (tem
, PT
);
5158 tem
= Fpos_visible_in_window_p (tem
, window
, Qnil
);
5162 Fvertical_motion (make_number (- (ht
/ 2)), window
);
5167 lose
= n
< 0 && PT
== BEGV
;
5168 Fvertical_motion (make_number (n
), window
);
5172 SET_PT_BOTH (opoint
, opoint_byte
);
5179 xsignal0 (Qbeginning_of_buffer
);
5184 int this_scroll_margin
= scroll_margin
;
5186 /* Don't use a scroll margin that is negative or too large. */
5187 if (this_scroll_margin
< 0)
5188 this_scroll_margin
= 0;
5190 if (XINT (w
->total_lines
) < 4 * scroll_margin
)
5191 this_scroll_margin
= XINT (w
->total_lines
) / 4;
5193 set_marker_restricted_both (w
->start
, w
->buffer
, pos
, pos_byte
);
5194 w
->start_at_line_beg
= bolp
;
5195 w
->update_mode_line
= Qt
;
5196 XSETFASTINT (w
->last_modified
, 0);
5197 XSETFASTINT (w
->last_overlay_modified
, 0);
5198 /* Set force_start so that redisplay_window will run
5199 the window-scroll-functions. */
5200 w
->force_start
= Qt
;
5202 if (!NILP (Vscroll_preserve_screen_position
)
5203 && (whole
|| !EQ (Vscroll_preserve_screen_position
, Qt
)))
5205 SET_PT_BOTH (pos
, pos_byte
);
5206 Fvertical_motion (original_pos
, window
);
5208 /* If we scrolled forward, put point enough lines down
5209 that it is outside the scroll margin. */
5214 if (this_scroll_margin
> 0)
5216 SET_PT_BOTH (pos
, pos_byte
);
5217 Fvertical_motion (make_number (this_scroll_margin
), window
);
5223 if (top_margin
<= opoint
)
5224 SET_PT_BOTH (opoint
, opoint_byte
);
5225 else if (!NILP (Vscroll_preserve_screen_position
))
5227 SET_PT_BOTH (pos
, pos_byte
);
5228 Fvertical_motion (original_pos
, window
);
5231 SET_PT (top_margin
);
5237 /* If we scrolled backward, put point near the end of the window
5238 but not within the scroll margin. */
5239 SET_PT_BOTH (pos
, pos_byte
);
5240 tem
= Fvertical_motion (make_number (ht
- this_scroll_margin
), window
);
5241 if (XFASTINT (tem
) == ht
- this_scroll_margin
)
5244 bottom_margin
= PT
+ 1;
5246 if (bottom_margin
> opoint
)
5247 SET_PT_BOTH (opoint
, opoint_byte
);
5250 if (!NILP (Vscroll_preserve_screen_position
))
5252 SET_PT_BOTH (pos
, pos_byte
);
5253 Fvertical_motion (original_pos
, window
);
5256 Fvertical_motion (make_number (-1), window
);
5265 xsignal0 (Qend_of_buffer
);
5270 /* Scroll selected_window up or down. If N is nil, scroll a
5271 screen-full which is defined as the height of the window minus
5272 next_screen_context_lines. If N is the symbol `-', scroll.
5273 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5274 up. This is the guts of Fscroll_up and Fscroll_down. */
5277 scroll_command (Lisp_Object n
, int direction
)
5279 int count
= SPECPDL_INDEX ();
5281 xassert (eabs (direction
) == 1);
5283 /* If selected window's buffer isn't current, make it current for
5284 the moment. But don't screw up if window_scroll gets an error. */
5285 if (XBUFFER (XWINDOW (selected_window
)->buffer
) != current_buffer
)
5287 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
5288 Fset_buffer (XWINDOW (selected_window
)->buffer
);
5290 /* Make redisplay consider other windows than just selected_window. */
5291 ++windows_or_buffers_changed
;
5295 window_scroll (selected_window
, direction
, 1, 0);
5296 else if (EQ (n
, Qminus
))
5297 window_scroll (selected_window
, -direction
, 1, 0);
5300 n
= Fprefix_numeric_value (n
);
5301 window_scroll (selected_window
, XINT (n
) * direction
, 0, 0);
5304 unbind_to (count
, Qnil
);
5307 DEFUN ("scroll-up", Fscroll_up
, Sscroll_up
, 0, 1, "^P",
5308 doc
: /* Scroll text of selected window upward ARG lines.
5309 If ARG is omitted or nil, scroll upward by a near full screen.
5310 A near full screen is `next-screen-context-lines' less than a full screen.
5311 Negative ARG means scroll downward.
5312 If ARG is the atom `-', scroll downward by nearly full screen.
5313 When calling from a program, supply as argument a number, nil, or `-'. */)
5316 scroll_command (arg
, 1);
5320 DEFUN ("scroll-down", Fscroll_down
, Sscroll_down
, 0, 1, "^P",
5321 doc
: /* Scroll text of selected window down ARG lines.
5322 If ARG is omitted or nil, scroll down by a near full screen.
5323 A near full screen is `next-screen-context-lines' less than a full screen.
5324 Negative ARG means scroll upward.
5325 If ARG is the atom `-', scroll upward by nearly full screen.
5326 When calling from a program, supply as argument a number, nil, or `-'. */)
5329 scroll_command (arg
, -1);
5333 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling
, Sother_window_for_scrolling
, 0, 0, 0,
5334 doc
: /* Return the other window for \"other window scroll\" commands.
5335 If `other-window-scroll-buffer' is non-nil, a window
5336 showing that buffer is used.
5337 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5338 specifies the window. This takes precedence over
5339 `other-window-scroll-buffer'. */)
5344 if (MINI_WINDOW_P (XWINDOW (selected_window
))
5345 && !NILP (Vminibuf_scroll_window
))
5346 window
= Vminibuf_scroll_window
;
5347 /* If buffer is specified, scroll that buffer. */
5348 else if (!NILP (Vother_window_scroll_buffer
))
5350 window
= Fget_buffer_window (Vother_window_scroll_buffer
, Qnil
);
5352 window
= display_buffer (Vother_window_scroll_buffer
, Qt
, Qnil
);
5356 /* Nothing specified; look for a neighboring window on the same
5358 window
= Fnext_window (selected_window
, Qnil
, Qnil
);
5360 if (EQ (window
, selected_window
))
5361 /* That didn't get us anywhere; look for a window on another
5364 window
= Fnext_window (window
, Qnil
, Qt
);
5365 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window
))))
5366 && ! EQ (window
, selected_window
));
5369 CHECK_LIVE_WINDOW (window
);
5371 if (EQ (window
, selected_window
))
5372 error ("There is no other window");
5377 DEFUN ("scroll-other-window", Fscroll_other_window
, Sscroll_other_window
, 0, 1, "P",
5378 doc
: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5379 A near full screen is `next-screen-context-lines' less than a full screen.
5380 The next window is the one below the current one; or the one at the top
5381 if the current one is at the bottom. Negative ARG means scroll downward.
5382 If ARG is the atom `-', scroll downward by nearly full screen.
5383 When calling from a program, supply as argument a number, nil, or `-'.
5385 If `other-window-scroll-buffer' is non-nil, scroll the window
5386 showing that buffer, popping the buffer up if necessary.
5387 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5388 specifies the window to scroll. This takes precedence over
5389 `other-window-scroll-buffer'. */)
5394 int count
= SPECPDL_INDEX ();
5396 window
= Fother_window_for_scrolling ();
5397 w
= XWINDOW (window
);
5399 /* Don't screw up if window_scroll gets an error. */
5400 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
5401 ++windows_or_buffers_changed
;
5403 Fset_buffer (w
->buffer
);
5404 SET_PT (marker_position (w
->pointm
));
5407 window_scroll (window
, 1, 1, 1);
5408 else if (EQ (arg
, Qminus
))
5409 window_scroll (window
, -1, 1, 1);
5415 window_scroll (window
, XINT (arg
), 0, 1);
5418 set_marker_both (w
->pointm
, Qnil
, PT
, PT_BYTE
);
5419 unbind_to (count
, Qnil
);
5424 DEFUN ("scroll-left", Fscroll_left
, Sscroll_left
, 0, 2, "^P\np",
5425 doc
: /* Scroll selected window display ARG columns left.
5426 Default for ARG is window width minus 2.
5427 Value is the total amount of leftward horizontal scrolling in
5428 effect after the change.
5429 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5430 lower bound for automatic scrolling, i.e. automatic scrolling
5431 will not scroll a window to a column less than the value returned
5432 by this function. This happens in an interactive call. */)
5433 (register Lisp_Object arg
, Lisp_Object set_minimum
)
5437 struct window
*w
= XWINDOW (selected_window
);
5440 XSETFASTINT (arg
, window_box_text_cols (w
) - 2);
5442 arg
= Fprefix_numeric_value (arg
);
5444 hscroll
= XINT (w
->hscroll
) + XINT (arg
);
5445 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
5447 if (!NILP (set_minimum
))
5448 w
->min_hscroll
= w
->hscroll
;
5453 DEFUN ("scroll-right", Fscroll_right
, Sscroll_right
, 0, 2, "^P\np",
5454 doc
: /* Scroll selected window display ARG columns right.
5455 Default for ARG is window width minus 2.
5456 Value is the total amount of leftward horizontal scrolling in
5457 effect after the change.
5458 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5459 lower bound for automatic scrolling, i.e. automatic scrolling
5460 will not scroll a window to a column less than the value returned
5461 by this function. This happens in an interactive call. */)
5462 (register Lisp_Object arg
, Lisp_Object set_minimum
)
5466 struct window
*w
= XWINDOW (selected_window
);
5469 XSETFASTINT (arg
, window_box_text_cols (w
) - 2);
5471 arg
= Fprefix_numeric_value (arg
);
5473 hscroll
= XINT (w
->hscroll
) - XINT (arg
);
5474 result
= Fset_window_hscroll (selected_window
, make_number (hscroll
));
5476 if (!NILP (set_minimum
))
5477 w
->min_hscroll
= w
->hscroll
;
5482 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window
, Sminibuffer_selected_window
, 0, 0, 0,
5483 doc
: /* Return the window which was selected when entering the minibuffer.
5484 Returns nil, if selected window is not a minibuffer window. */)
5487 if (minibuf_level
> 0
5488 && MINI_WINDOW_P (XWINDOW (selected_window
))
5489 && WINDOW_LIVE_P (minibuf_selected_window
))
5490 return minibuf_selected_window
;
5495 /* Value is the number of lines actually displayed in window W,
5496 as opposed to its height. */
5499 displayed_window_lines (struct window
*w
)
5502 struct text_pos start
;
5503 int height
= window_box_height (w
);
5504 struct buffer
*old_buffer
;
5507 if (XBUFFER (w
->buffer
) != current_buffer
)
5509 old_buffer
= current_buffer
;
5510 set_buffer_internal (XBUFFER (w
->buffer
));
5515 /* In case W->start is out of the accessible range, do something
5516 reasonable. This happens in Info mode when Info-scroll-down
5517 calls (recenter -1) while W->start is 1. */
5518 if (XMARKER (w
->start
)->charpos
< BEGV
)
5519 SET_TEXT_POS (start
, BEGV
, BEGV_BYTE
);
5520 else if (XMARKER (w
->start
)->charpos
> ZV
)
5521 SET_TEXT_POS (start
, ZV
, ZV_BYTE
);
5523 SET_TEXT_POS_FROM_MARKER (start
, w
->start
);
5525 start_display (&it
, w
, start
);
5526 move_it_vertically (&it
, height
);
5527 bottom_y
= line_bottom_y (&it
);
5529 /* rms: On a non-window display,
5530 the value of it.vpos at the bottom of the screen
5531 seems to be 1 larger than window_box_height (w).
5532 This kludge fixes a bug whereby (move-to-window-line -1)
5533 when ZV is on the last screen line
5534 moves to the previous screen line instead of the last one. */
5535 if (! FRAME_WINDOW_P (XFRAME (w
->frame
)))
5538 /* Add in empty lines at the bottom of the window. */
5539 if (bottom_y
< height
)
5541 int uy
= FRAME_LINE_HEIGHT (it
.f
);
5542 it
.vpos
+= (height
- bottom_y
+ uy
- 1) / uy
;
5546 set_buffer_internal (old_buffer
);
5552 DEFUN ("recenter", Frecenter
, Srecenter
, 0, 1, "P",
5553 doc
: /* Center point in selected window and maybe redisplay frame.
5554 With prefix argument ARG, recenter putting point on screen line ARG
5555 relative to the selected window. If ARG is negative, it counts up from the
5556 bottom of the window. (ARG should be less than the height of the window.)
5558 If ARG is omitted or nil, then recenter with point on the middle line of
5559 the selected window; if the variable `recenter-redisplay' is non-nil,
5560 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5561 is set to `grow-only', this resets the tool-bar's height to the minimum
5562 height needed); if `recenter-redisplay' has the special value `tty',
5563 then only tty frame are redrawn.
5565 Just C-u as prefix means put point in the center of the window
5566 and redisplay normally--don't erase and redraw the frame. */)
5567 (register Lisp_Object arg
)
5569 struct window
*w
= XWINDOW (selected_window
);
5570 struct buffer
*buf
= XBUFFER (w
->buffer
);
5571 struct buffer
*obuf
= current_buffer
;
5573 EMACS_INT charpos
, bytepos
;
5575 int this_scroll_margin
;
5577 /* If redisplay is suppressed due to an error, try again. */
5578 obuf
->display_error_modiff
= 0;
5582 if (!NILP (Vrecenter_redisplay
)
5583 && (!EQ (Vrecenter_redisplay
, Qtty
)
5584 || !NILP (Ftty_type (selected_frame
))))
5588 /* Invalidate pixel data calculated for all compositions. */
5589 for (i
= 0; i
< n_compositions
; i
++)
5590 composition_table
[i
]->font
= NULL
;
5592 WINDOW_XFRAME (w
)->minimize_tool_bar_window_p
= 1;
5594 Fredraw_frame (WINDOW_FRAME (w
));
5595 SET_FRAME_GARBAGED (WINDOW_XFRAME (w
));
5600 else if (CONSP (arg
)) /* Just C-u. */
5604 arg
= Fprefix_numeric_value (arg
);
5609 set_buffer_internal (buf
);
5611 /* Do this after making BUF current
5612 in case scroll_margin is buffer-local. */
5613 this_scroll_margin
= max (0, scroll_margin
);
5614 this_scroll_margin
= min (this_scroll_margin
,
5615 XFASTINT (w
->total_lines
) / 4);
5617 /* Handle centering on a graphical frame specially. Such frames can
5618 have variable-height lines and centering point on the basis of
5619 line counts would lead to strange effects. */
5620 if (FRAME_WINDOW_P (XFRAME (w
->frame
)))
5627 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
5628 start_display (&it
, w
, pt
);
5629 move_it_vertically_backward (&it
, window_box_height (w
) / 2);
5630 charpos
= IT_CHARPOS (it
);
5631 bytepos
= IT_BYTEPOS (it
);
5638 int extra_line_spacing
;
5639 int h
= window_box_height (w
);
5641 iarg
= - max (-iarg
, this_scroll_margin
);
5643 SET_TEXT_POS (pt
, PT
, PT_BYTE
);
5644 start_display (&it
, w
, pt
);
5646 /* Be sure we have the exact height of the full line containing PT. */
5647 move_it_by_lines (&it
, 0, 1);
5649 /* The amount of pixels we have to move back is the window
5650 height minus what's displayed in the line containing PT,
5651 and the lines below. */
5654 move_it_by_lines (&it
, nlines
, 1);
5656 if (it
.vpos
== nlines
)
5660 /* Last line has no newline */
5661 h
-= line_bottom_y (&it
);
5665 /* Don't reserve space for extra line spacing of last line. */
5666 extra_line_spacing
= it
.max_extra_line_spacing
;
5668 /* If we can't move down NLINES lines because we hit
5669 the end of the buffer, count in some empty lines. */
5670 if (it
.vpos
< nlines
)
5673 extra_line_spacing
= it
.extra_line_spacing
;
5674 h
-= nlines
* (FRAME_LINE_HEIGHT (it
.f
) + extra_line_spacing
);
5679 /* Now find the new top line (starting position) of the window. */
5680 start_display (&it
, w
, pt
);
5682 move_it_vertically_backward (&it
, h
);
5684 /* If extra line spacing is present, we may move too far
5685 back. This causes the last line to be only partially
5686 visible (which triggers redisplay to recenter that line
5687 in the middle), so move forward.
5688 But ignore extra line spacing on last line, as it is not
5689 considered to be part of the visible height of the line.
5691 h
+= extra_line_spacing
;
5692 while (-it
.current_y
> h
)
5693 move_it_by_lines (&it
, 1, 1);
5695 charpos
= IT_CHARPOS (it
);
5696 bytepos
= IT_BYTEPOS (it
);
5700 struct position pos
;
5702 iarg
= max (iarg
, this_scroll_margin
);
5704 pos
= *vmotion (PT
, -iarg
, w
);
5705 charpos
= pos
.bufpos
;
5706 bytepos
= pos
.bytepos
;
5711 struct position pos
;
5712 int ht
= window_internal_height (w
);
5719 /* Don't let it get into the margin at either top or bottom. */
5720 iarg
= max (iarg
, this_scroll_margin
);
5721 iarg
= min (iarg
, ht
- this_scroll_margin
- 1);
5723 pos
= *vmotion (PT
, - iarg
, w
);
5724 charpos
= pos
.bufpos
;
5725 bytepos
= pos
.bytepos
;
5728 /* Set the new window start. */
5729 set_marker_both (w
->start
, w
->buffer
, charpos
, bytepos
);
5730 w
->window_end_valid
= Qnil
;
5732 w
->optional_new_start
= Qt
;
5734 if (bytepos
== BEGV_BYTE
|| FETCH_BYTE (bytepos
- 1) == '\n')
5735 w
->start_at_line_beg
= Qt
;
5737 w
->start_at_line_beg
= Qnil
;
5739 set_buffer_internal (obuf
);
5744 DEFUN ("window-text-height", Fwindow_text_height
, Swindow_text_height
,
5746 doc
: /* Return the height in lines of the text display area of WINDOW.
5747 WINDOW defaults to the selected window.
5749 The return value does not include the mode line, any header line, nor
5750 any partial-height lines in the text display area. */)
5751 (Lisp_Object window
)
5753 struct window
*w
= decode_window (window
);
5754 int pixel_height
= window_box_height (w
);
5755 int line_height
= pixel_height
/ FRAME_LINE_HEIGHT (XFRAME (w
->frame
));
5756 return make_number (line_height
);
5761 DEFUN ("move-to-window-line", Fmove_to_window_line
, Smove_to_window_line
,
5763 doc
: /* Position point relative to window.
5764 With no argument, position point at center of window.
5765 An argument specifies vertical position within the window;
5766 zero means top of window, negative means relative to bottom of window. */)
5769 struct window
*w
= XWINDOW (selected_window
);
5773 int this_scroll_margin
;
5776 if (!(BUFFERP (w
->buffer
)
5777 && XBUFFER (w
->buffer
) == current_buffer
))
5778 /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
5779 when passed below to set_marker_both. */
5780 error ("move-to-window-line called from unrelated buffer");
5782 window
= selected_window
;
5783 start
= marker_position (w
->start
);
5784 if (start
< BEGV
|| start
> ZV
)
5786 int height
= window_internal_height (w
);
5787 Fvertical_motion (make_number (- (height
/ 2)), window
);
5788 set_marker_both (w
->start
, w
->buffer
, PT
, PT_BYTE
);
5789 w
->start_at_line_beg
= Fbolp ();
5790 w
->force_start
= Qt
;
5793 Fgoto_char (w
->start
);
5795 lines
= displayed_window_lines (w
);
5798 this_scroll_margin
= max (0, scroll_margin
);
5799 this_scroll_margin
= min (this_scroll_margin
, lines
/ 4);
5803 XSETFASTINT (arg
, lines
/ 2);
5806 int iarg
= XINT (Fprefix_numeric_value (arg
));
5809 iarg
= iarg
+ lines
;
5811 #if 0 /* This code would prevent move-to-window-line from moving point
5812 to a place inside the scroll margins (which would cause the
5813 next redisplay to scroll). I wrote this code, but then concluded
5814 it is probably better not to install it. However, it is here
5815 inside #if 0 so as not to lose it. -- rms. */
5817 /* Don't let it get into the margin at either top or bottom. */
5818 iarg
= max (iarg
, this_scroll_margin
);
5819 iarg
= min (iarg
, lines
- this_scroll_margin
- 1);
5822 arg
= make_number (iarg
);
5825 /* Skip past a partially visible first line. */
5827 XSETINT (arg
, XINT (arg
) + 1);
5829 return Fvertical_motion (arg
, window
);
5834 /***********************************************************************
5835 Window Configuration
5836 ***********************************************************************/
5838 struct save_window_data
5841 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
5842 Lisp_Object selected_frame
;
5843 Lisp_Object current_window
;
5844 Lisp_Object current_buffer
;
5845 Lisp_Object minibuf_scroll_window
;
5846 Lisp_Object minibuf_selected_window
;
5847 Lisp_Object root_window
;
5848 Lisp_Object focus_frame
;
5849 /* A vector, each of whose elements is a struct saved_window
5851 Lisp_Object saved_windows
;
5853 /* All fields above are traced by the GC.
5854 From `fame-cols' down, the fields are ignored by the GC. */
5856 int frame_cols
, frame_lines
, frame_menu_bar_lines
;
5857 int frame_tool_bar_lines
;
5860 /* This is saved as a Lisp_Vector */
5863 /* these first two must agree with struct Lisp_Vector in lisp.h */
5865 struct Lisp_Vector
*next_from_Lisp_Vector_struct
;
5868 Lisp_Object buffer
, start
, pointm
, mark
;
5869 Lisp_Object left_col
, top_line
, total_cols
, total_lines
;
5870 Lisp_Object hscroll
, min_hscroll
;
5871 Lisp_Object parent
, prev
;
5872 Lisp_Object start_at_line_beg
;
5873 Lisp_Object display_table
;
5874 Lisp_Object orig_top_line
, orig_total_lines
;
5875 Lisp_Object left_margin_cols
, right_margin_cols
;
5876 Lisp_Object left_fringe_width
, right_fringe_width
, fringes_outside_margins
;
5877 Lisp_Object scroll_bar_width
, vertical_scroll_bar_type
;
5878 Lisp_Object dedicated
, resize_proportionally
;
5881 #define SAVED_WINDOW_N(swv,n) \
5882 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5884 DEFUN ("window-configuration-p", Fwindow_configuration_p
, Swindow_configuration_p
, 1, 1, 0,
5885 doc
: /* Return t if OBJECT is a window-configuration object. */)
5886 (Lisp_Object object
)
5888 return WINDOW_CONFIGURATIONP (object
) ? Qt
: Qnil
;
5891 DEFUN ("window-configuration-frame", Fwindow_configuration_frame
, Swindow_configuration_frame
, 1, 1, 0,
5892 doc
: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5893 (Lisp_Object config
)
5895 register struct save_window_data
*data
;
5896 struct Lisp_Vector
*saved_windows
;
5898 CHECK_WINDOW_CONFIGURATION (config
);
5900 data
= (struct save_window_data
*) XVECTOR (config
);
5901 saved_windows
= XVECTOR (data
->saved_windows
);
5902 return XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
5905 DEFUN ("set-window-configuration", Fset_window_configuration
,
5906 Sset_window_configuration
, 1, 1, 0,
5907 doc
: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5908 CONFIGURATION must be a value previously returned
5909 by `current-window-configuration' (which see).
5910 If CONFIGURATION was made from a frame that is now deleted,
5911 only frame-independent values can be restored. In this case,
5912 the return value is nil. Otherwise the value is t. */)
5913 (Lisp_Object configuration
)
5915 register struct save_window_data
*data
;
5916 struct Lisp_Vector
*saved_windows
;
5917 Lisp_Object new_current_buffer
;
5920 EMACS_INT old_point
= -1;
5922 CHECK_WINDOW_CONFIGURATION (configuration
);
5924 data
= (struct save_window_data
*) XVECTOR (configuration
);
5925 saved_windows
= XVECTOR (data
->saved_windows
);
5927 new_current_buffer
= data
->current_buffer
;
5928 if (NILP (XBUFFER (new_current_buffer
)->name
))
5929 new_current_buffer
= Qnil
;
5932 if (XBUFFER (new_current_buffer
) == current_buffer
)
5933 /* The code further down "preserves point" by saving here PT in
5934 old_point and then setting it later back into PT. When the
5935 current-selected-window and the final-selected-window both show
5936 the current buffer, this suffers from the problem that the
5937 current PT is the window-point of the current-selected-window,
5938 while the final PT is the point of the final-selected-window, so
5939 this copy from one PT to the other would end up moving the
5940 window-point of the final-selected-window to the window-point of
5941 the current-selected-window. So we have to be careful which
5942 point of the current-buffer we copy into old_point. */
5943 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
)
5944 && WINDOWP (selected_window
)
5945 && EQ (XWINDOW (selected_window
)->buffer
, new_current_buffer
)
5946 && !EQ (selected_window
, data
->current_window
))
5947 old_point
= XMARKER (XWINDOW (data
->current_window
)->pointm
)->charpos
;
5951 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5952 point in new_current_buffer as of the last time this buffer was
5953 used. This can be non-deterministic since it can be changed by
5954 things like jit-lock by mere temporary selection of some random
5955 window that happens to show this buffer.
5956 So if possible we want this arbitrary choice of "which point" to
5957 be the one from the to-be-selected-window so as to prevent this
5958 window's cursor from being copied from another window. */
5959 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
)
5960 /* If current_window = selected_window, its point is in BUF_PT. */
5961 && !EQ (selected_window
, data
->current_window
))
5962 old_point
= XMARKER (XWINDOW (data
->current_window
)->pointm
)->charpos
;
5964 old_point
= BUF_PT (XBUFFER (new_current_buffer
));
5967 frame
= XWINDOW (SAVED_WINDOW_N (saved_windows
, 0)->window
)->frame
;
5970 /* If f is a dead frame, don't bother rebuilding its window tree.
5971 However, there is other stuff we should still try to do below. */
5972 if (FRAME_LIVE_P (f
))
5974 register struct window
*w
;
5975 register struct saved_window
*p
;
5976 struct window
*root_window
;
5977 struct window
**leaf_windows
;
5981 /* If the frame has been resized since this window configuration was
5982 made, we change the frame to the size specified in the
5983 configuration, restore the configuration, and then resize it
5984 back. We keep track of the prevailing height in these variables. */
5985 int previous_frame_lines
= FRAME_LINES (f
);
5986 int previous_frame_cols
= FRAME_COLS (f
);
5987 int previous_frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
5988 int previous_frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
5990 /* The mouse highlighting code could get screwed up
5991 if it runs during this. */
5994 if (data
->frame_lines
!= previous_frame_lines
5995 || data
->frame_cols
!= previous_frame_cols
)
5996 change_frame_size (f
, data
->frame_lines
,
5997 data
->frame_cols
, 0, 0, 0);
5998 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5999 if (data
->frame_menu_bar_lines
6000 != previous_frame_menu_bar_lines
)
6001 x_set_menu_bar_lines (f
, make_number (data
->frame_menu_bar_lines
),
6003 #ifdef HAVE_WINDOW_SYSTEM
6004 if (data
->frame_tool_bar_lines
6005 != previous_frame_tool_bar_lines
)
6006 x_set_tool_bar_lines (f
, make_number (data
->frame_tool_bar_lines
),
6011 /* "Swap out" point from the selected window's buffer
6012 into the window itself. (Normally the pointm of the selected
6013 window holds garbage.) We do this now, before
6014 restoring the window contents, and prevent it from
6015 being done later on when we select a new window. */
6016 if (! NILP (XWINDOW (selected_window
)->buffer
))
6018 w
= XWINDOW (selected_window
);
6019 set_marker_both (w
->pointm
,
6021 BUF_PT (XBUFFER (w
->buffer
)),
6022 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6025 windows_or_buffers_changed
++;
6026 FRAME_WINDOW_SIZES_CHANGED (f
) = 1;
6028 /* Problem: Freeing all matrices and later allocating them again
6029 is a serious redisplay flickering problem. What we would
6030 really like to do is to free only those matrices not reused
6032 root_window
= XWINDOW (FRAME_ROOT_WINDOW (f
));
6034 = (struct window
**) alloca (count_windows (root_window
)
6035 * sizeof (struct window
*));
6036 n_leaf_windows
= get_leaf_windows (root_window
, leaf_windows
, 0);
6039 Mark all windows now on frame as "deleted".
6040 Restoring the new configuration "undeletes" any that are in it.
6042 Save their current buffers in their height fields, since we may
6043 need it later, if a buffer saved in the configuration is now
6045 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6047 for (k
= 0; k
< saved_windows
->size
; k
++)
6049 p
= SAVED_WINDOW_N (saved_windows
, k
);
6050 w
= XWINDOW (p
->window
);
6053 if (!NILP (p
->parent
))
6054 w
->parent
= SAVED_WINDOW_N (saved_windows
,
6055 XFASTINT (p
->parent
))->window
;
6059 if (!NILP (p
->prev
))
6061 w
->prev
= SAVED_WINDOW_N (saved_windows
,
6062 XFASTINT (p
->prev
))->window
;
6063 XWINDOW (w
->prev
)->next
= p
->window
;
6068 if (!NILP (w
->parent
))
6070 if (EQ (p
->total_cols
, XWINDOW (w
->parent
)->total_cols
))
6072 XWINDOW (w
->parent
)->vchild
= p
->window
;
6073 XWINDOW (w
->parent
)->hchild
= Qnil
;
6077 XWINDOW (w
->parent
)->hchild
= p
->window
;
6078 XWINDOW (w
->parent
)->vchild
= Qnil
;
6083 /* If we squirreled away the buffer in the window's height,
6085 if (BUFFERP (w
->total_lines
))
6086 w
->buffer
= w
->total_lines
;
6087 w
->left_col
= p
->left_col
;
6088 w
->top_line
= p
->top_line
;
6089 w
->total_cols
= p
->total_cols
;
6090 w
->total_lines
= p
->total_lines
;
6091 w
->hscroll
= p
->hscroll
;
6092 w
->min_hscroll
= p
->min_hscroll
;
6093 w
->display_table
= p
->display_table
;
6094 w
->orig_top_line
= p
->orig_top_line
;
6095 w
->orig_total_lines
= p
->orig_total_lines
;
6096 w
->left_margin_cols
= p
->left_margin_cols
;
6097 w
->right_margin_cols
= p
->right_margin_cols
;
6098 w
->left_fringe_width
= p
->left_fringe_width
;
6099 w
->right_fringe_width
= p
->right_fringe_width
;
6100 w
->fringes_outside_margins
= p
->fringes_outside_margins
;
6101 w
->scroll_bar_width
= p
->scroll_bar_width
;
6102 w
->vertical_scroll_bar_type
= p
->vertical_scroll_bar_type
;
6103 w
->dedicated
= p
->dedicated
;
6104 w
->resize_proportionally
= p
->resize_proportionally
;
6105 XSETFASTINT (w
->last_modified
, 0);
6106 XSETFASTINT (w
->last_overlay_modified
, 0);
6108 /* Reinstall the saved buffer and pointers into it. */
6109 if (NILP (p
->buffer
))
6110 w
->buffer
= p
->buffer
;
6113 if (!NILP (XBUFFER (p
->buffer
)->name
))
6114 /* If saved buffer is alive, install it. */
6116 w
->buffer
= p
->buffer
;
6117 w
->start_at_line_beg
= p
->start_at_line_beg
;
6118 set_marker_restricted (w
->start
, p
->start
, w
->buffer
);
6119 set_marker_restricted (w
->pointm
, p
->pointm
, w
->buffer
);
6120 Fset_marker (XBUFFER (w
->buffer
)->mark
,
6121 p
->mark
, w
->buffer
);
6123 /* As documented in Fcurrent_window_configuration, don't
6124 restore the location of point in the buffer which was
6125 current when the window configuration was recorded. */
6126 if (!EQ (p
->buffer
, new_current_buffer
)
6127 && XBUFFER (p
->buffer
) == current_buffer
)
6128 Fgoto_char (w
->pointm
);
6130 else if (NILP (w
->buffer
) || NILP (XBUFFER (w
->buffer
)->name
))
6131 /* Else unless window has a live buffer, get one. */
6133 w
->buffer
= Fcdr (Fcar (Vbuffer_alist
));
6134 /* This will set the markers to beginning of visible
6136 set_marker_restricted (w
->start
, make_number (0), w
->buffer
);
6137 set_marker_restricted (w
->pointm
, make_number (0),w
->buffer
);
6138 w
->start_at_line_beg
= Qt
;
6141 /* Keeping window's old buffer; make sure the markers
6144 /* Set window markers at start of visible range. */
6145 if (XMARKER (w
->start
)->buffer
== 0)
6146 set_marker_restricted (w
->start
, make_number (0),
6148 if (XMARKER (w
->pointm
)->buffer
== 0)
6149 set_marker_restricted_both (w
->pointm
, w
->buffer
,
6150 BUF_PT (XBUFFER (w
->buffer
)),
6151 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6152 w
->start_at_line_beg
= Qt
;
6157 FRAME_ROOT_WINDOW (f
) = data
->root_window
;
6159 /* Arrange *not* to restore point in the buffer that was
6160 current when the window configuration was saved. */
6161 if (EQ (XWINDOW (data
->current_window
)->buffer
, new_current_buffer
))
6162 set_marker_restricted (XWINDOW (data
->current_window
)->pointm
,
6163 make_number (old_point
),
6164 XWINDOW (data
->current_window
)->buffer
);
6166 /* In the following call to `select-window, prevent "swapping
6167 out point" in the old selected window using the buffer that
6168 has been restored into it. We already swapped out that point
6169 from that window's old buffer. */
6170 inhibit_point_swap
= 1;
6171 Fselect_window (data
->current_window
, Qnil
);
6172 XBUFFER (XWINDOW (selected_window
)->buffer
)->last_selected_window
6175 if (NILP (data
->focus_frame
)
6176 || (FRAMEP (data
->focus_frame
)
6177 && FRAME_LIVE_P (XFRAME (data
->focus_frame
))))
6178 Fredirect_frame_focus (frame
, data
->focus_frame
);
6180 /* Set the screen height to the value it had before this function. */
6181 if (previous_frame_lines
!= FRAME_LINES (f
)
6182 || previous_frame_cols
!= FRAME_COLS (f
))
6183 change_frame_size (f
, previous_frame_lines
, previous_frame_cols
,
6185 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6186 if (previous_frame_menu_bar_lines
!= FRAME_MENU_BAR_LINES (f
))
6187 x_set_menu_bar_lines (f
, make_number (previous_frame_menu_bar_lines
),
6189 #ifdef HAVE_WINDOW_SYSTEM
6190 if (previous_frame_tool_bar_lines
!= FRAME_TOOL_BAR_LINES (f
))
6191 x_set_tool_bar_lines (f
, make_number (previous_frame_tool_bar_lines
),
6196 /* Now, free glyph matrices in windows that were not reused. */
6197 for (i
= n
= 0; i
< n_leaf_windows
; ++i
)
6199 if (NILP (leaf_windows
[i
]->buffer
))
6201 /* Assert it's not reused as a combination. */
6202 xassert (NILP (leaf_windows
[i
]->hchild
)
6203 && NILP (leaf_windows
[i
]->vchild
));
6204 free_window_matrices (leaf_windows
[i
]);
6206 else if (EQ (leaf_windows
[i
]->buffer
, new_current_buffer
))
6214 /* Fselect_window will have made f the selected frame, so we
6215 reselect the proper frame here. Fhandle_switch_frame will change the
6216 selected window too, but that doesn't make the call to
6217 Fselect_window above totally superfluous; it still sets f's
6219 if (FRAME_LIVE_P (XFRAME (data
->selected_frame
)))
6220 do_switch_frame (data
->selected_frame
, 0, 0, Qnil
);
6222 run_window_configuration_change_hook (f
);
6225 if (!NILP (new_current_buffer
))
6226 Fset_buffer (new_current_buffer
);
6228 Vminibuf_scroll_window
= data
->minibuf_scroll_window
;
6229 minibuf_selected_window
= data
->minibuf_selected_window
;
6231 return (FRAME_LIVE_P (f
) ? Qt
: Qnil
);
6234 /* Mark all windows now on frame as deleted
6235 by setting their buffers to nil. */
6238 delete_all_subwindows (register struct window
*w
)
6240 if (!NILP (w
->next
))
6241 delete_all_subwindows (XWINDOW (w
->next
));
6242 if (!NILP (w
->vchild
))
6243 delete_all_subwindows (XWINDOW (w
->vchild
));
6244 if (!NILP (w
->hchild
))
6245 delete_all_subwindows (XWINDOW (w
->hchild
));
6247 w
->total_lines
= w
->buffer
; /* See Fset_window_configuration for excuse. */
6249 if (!NILP (w
->buffer
))
6252 /* We set all three of these fields to nil, to make sure that we can
6253 distinguish this dead window from any live window. Live leaf
6254 windows will have buffer set, and combination windows will have
6255 vchild or hchild set. */
6260 Vwindow_list
= Qnil
;
6264 count_windows (register struct window
*window
)
6266 register int count
= 1;
6267 if (!NILP (window
->next
))
6268 count
+= count_windows (XWINDOW (window
->next
));
6269 if (!NILP (window
->vchild
))
6270 count
+= count_windows (XWINDOW (window
->vchild
));
6271 if (!NILP (window
->hchild
))
6272 count
+= count_windows (XWINDOW (window
->hchild
));
6277 /* Fill vector FLAT with leaf windows under W, starting at index I.
6278 Value is last index + 1. */
6281 get_leaf_windows (struct window
*w
, struct window
**flat
, int i
)
6285 if (!NILP (w
->hchild
))
6286 i
= get_leaf_windows (XWINDOW (w
->hchild
), flat
, i
);
6287 else if (!NILP (w
->vchild
))
6288 i
= get_leaf_windows (XWINDOW (w
->vchild
), flat
, i
);
6292 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6299 /* Return a pointer to the glyph W's physical cursor is on. Value is
6300 null if W's current matrix is invalid, so that no meaningfull glyph
6304 get_phys_cursor_glyph (struct window
*w
)
6306 struct glyph_row
*row
;
6307 struct glyph
*glyph
;
6309 if (w
->phys_cursor
.vpos
>= 0
6310 && w
->phys_cursor
.vpos
< w
->current_matrix
->nrows
6311 && (row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
),
6313 && row
->used
[TEXT_AREA
] > w
->phys_cursor
.hpos
)
6314 glyph
= row
->glyphs
[TEXT_AREA
] + w
->phys_cursor
.hpos
;
6323 save_window_save (Lisp_Object window
, struct Lisp_Vector
*vector
, int i
)
6325 register struct saved_window
*p
;
6326 register struct window
*w
;
6327 register Lisp_Object tem
;
6329 for (;!NILP (window
); window
= w
->next
)
6331 p
= SAVED_WINDOW_N (vector
, i
);
6332 w
= XWINDOW (window
);
6334 XSETFASTINT (w
->temslot
, i
); i
++;
6336 p
->buffer
= w
->buffer
;
6337 p
->left_col
= w
->left_col
;
6338 p
->top_line
= w
->top_line
;
6339 p
->total_cols
= w
->total_cols
;
6340 p
->total_lines
= w
->total_lines
;
6341 p
->hscroll
= w
->hscroll
;
6342 p
->min_hscroll
= w
->min_hscroll
;
6343 p
->display_table
= w
->display_table
;
6344 p
->orig_top_line
= w
->orig_top_line
;
6345 p
->orig_total_lines
= w
->orig_total_lines
;
6346 p
->left_margin_cols
= w
->left_margin_cols
;
6347 p
->right_margin_cols
= w
->right_margin_cols
;
6348 p
->left_fringe_width
= w
->left_fringe_width
;
6349 p
->right_fringe_width
= w
->right_fringe_width
;
6350 p
->fringes_outside_margins
= w
->fringes_outside_margins
;
6351 p
->scroll_bar_width
= w
->scroll_bar_width
;
6352 p
->vertical_scroll_bar_type
= w
->vertical_scroll_bar_type
;
6353 p
->dedicated
= w
->dedicated
;
6354 p
->resize_proportionally
= w
->resize_proportionally
;
6355 if (!NILP (w
->buffer
))
6357 /* Save w's value of point in the window configuration.
6358 If w is the selected window, then get the value of point
6359 from the buffer; pointm is garbage in the selected window. */
6360 if (EQ (window
, selected_window
))
6362 p
->pointm
= Fmake_marker ();
6363 set_marker_both (p
->pointm
, w
->buffer
,
6364 BUF_PT (XBUFFER (w
->buffer
)),
6365 BUF_PT_BYTE (XBUFFER (w
->buffer
)));
6368 p
->pointm
= Fcopy_marker (w
->pointm
, Qnil
);
6370 p
->start
= Fcopy_marker (w
->start
, Qnil
);
6371 p
->start_at_line_beg
= w
->start_at_line_beg
;
6373 tem
= XBUFFER (w
->buffer
)->mark
;
6374 p
->mark
= Fcopy_marker (tem
, Qnil
);
6381 p
->start_at_line_beg
= Qnil
;
6384 if (NILP (w
->parent
))
6387 p
->parent
= XWINDOW (w
->parent
)->temslot
;
6392 p
->prev
= XWINDOW (w
->prev
)->temslot
;
6394 if (!NILP (w
->vchild
))
6395 i
= save_window_save (w
->vchild
, vector
, i
);
6396 if (!NILP (w
->hchild
))
6397 i
= save_window_save (w
->hchild
, vector
, i
);
6403 DEFUN ("current-window-configuration", Fcurrent_window_configuration
,
6404 Scurrent_window_configuration
, 0, 1, 0,
6405 doc
: /* Return an object representing the current window configuration of FRAME.
6406 If FRAME is nil or omitted, use the selected frame.
6407 This describes the number of windows, their sizes and current buffers,
6408 and for each displayed buffer, where display starts, and the positions of
6409 point and mark. An exception is made for point in the current buffer:
6410 its value is -not- saved.
6411 This also records the currently selected frame, and FRAME's focus
6412 redirection (see `redirect-frame-focus'). */)
6415 register Lisp_Object tem
;
6416 register int n_windows
;
6417 register struct save_window_data
*data
;
6422 frame
= selected_frame
;
6423 CHECK_LIVE_FRAME (frame
);
6426 n_windows
= count_windows (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6427 data
= ALLOCATE_PSEUDOVECTOR (struct save_window_data
, frame_cols
,
6428 PVEC_WINDOW_CONFIGURATION
);
6430 data
->frame_cols
= FRAME_COLS (f
);
6431 data
->frame_lines
= FRAME_LINES (f
);
6432 data
->frame_menu_bar_lines
= FRAME_MENU_BAR_LINES (f
);
6433 data
->frame_tool_bar_lines
= FRAME_TOOL_BAR_LINES (f
);
6434 data
->selected_frame
= selected_frame
;
6435 data
->current_window
= FRAME_SELECTED_WINDOW (f
);
6436 XSETBUFFER (data
->current_buffer
, current_buffer
);
6437 data
->minibuf_scroll_window
= minibuf_level
> 0 ? Vminibuf_scroll_window
: Qnil
;
6438 data
->minibuf_selected_window
= minibuf_level
> 0 ? minibuf_selected_window
: Qnil
;
6439 data
->root_window
= FRAME_ROOT_WINDOW (f
);
6440 data
->focus_frame
= FRAME_FOCUS_FRAME (f
);
6441 tem
= Fmake_vector (make_number (n_windows
), Qnil
);
6442 data
->saved_windows
= tem
;
6443 for (i
= 0; i
< n_windows
; i
++)
6444 XVECTOR (tem
)->contents
[i
]
6445 = Fmake_vector (make_number (VECSIZE (struct saved_window
)), Qnil
);
6446 save_window_save (FRAME_ROOT_WINDOW (f
), XVECTOR (tem
), 0);
6447 XSETWINDOW_CONFIGURATION (tem
, data
);
6451 DEFUN ("save-window-excursion", Fsave_window_excursion
, Ssave_window_excursion
,
6453 doc
: /* Execute BODY, preserving window sizes and contents.
6454 Return the value of the last form in BODY.
6455 Restore which buffer appears in which window, where display starts,
6456 and the value of point and mark for each window.
6457 Also restore the choice of selected window.
6458 Also restore which buffer is current.
6459 Does not restore the value of point in current buffer.
6460 usage: (save-window-excursion BODY...) */)
6463 register Lisp_Object val
;
6464 register int count
= SPECPDL_INDEX ();
6466 record_unwind_protect (Fset_window_configuration
,
6467 Fcurrent_window_configuration (Qnil
));
6468 val
= Fprogn (args
);
6469 return unbind_to (count
, val
);
6474 /***********************************************************************
6476 ***********************************************************************/
6479 window_tree (struct window
*w
)
6481 Lisp_Object tail
= Qnil
;
6482 Lisp_Object result
= Qnil
;
6489 if (!NILP (w
->hchild
))
6490 wn
= Fcons (Qnil
, Fcons (Fwindow_edges (wn
),
6491 window_tree (XWINDOW (w
->hchild
))));
6492 else if (!NILP (w
->vchild
))
6493 wn
= Fcons (Qt
, Fcons (Fwindow_edges (wn
),
6494 window_tree (XWINDOW (w
->vchild
))));
6498 result
= tail
= Fcons (wn
, Qnil
);
6502 XSETCDR (tail
, Fcons (wn
, Qnil
));
6506 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6514 DEFUN ("window-tree", Fwindow_tree
, Swindow_tree
,
6516 doc
: /* Return the window tree for frame FRAME.
6518 The return value is a list of the form (ROOT MINI), where ROOT
6519 represents the window tree of the frame's root window, and MINI
6520 is the frame's minibuffer window.
6522 If the root window is not split, ROOT is the root window itself.
6523 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6524 horizontal split, and t for a vertical split, EDGES gives the combined
6525 size and position of the subwindows in the split, and the rest of the
6526 elements are the subwindows in the split. Each of the subwindows may
6527 again be a window or a list representing a window split, and so on.
6528 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6530 If FRAME is nil or omitted, return information on the currently
6537 frame
= selected_frame
;
6539 CHECK_FRAME (frame
);
6542 if (!FRAME_LIVE_P (f
))
6545 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f
)));
6549 /***********************************************************************
6551 ***********************************************************************/
6553 DEFUN ("set-window-margins", Fset_window_margins
, Sset_window_margins
,
6555 doc
: /* Set width of marginal areas of window WINDOW.
6556 If WINDOW is nil, set margins of the currently selected window.
6557 Second arg LEFT-WIDTH specifies the number of character cells to
6558 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6559 does the same for the right marginal area. A nil width parameter
6560 means no margin. */)
6561 (Lisp_Object window
, Lisp_Object left_width
, Lisp_Object right_width
)
6563 struct window
*w
= decode_window (window
);
6565 /* Translate negative or zero widths to nil.
6566 Margins that are too wide have to be checked elsewhere. */
6568 if (!NILP (left_width
))
6570 CHECK_NUMBER (left_width
);
6571 if (XINT (left_width
) <= 0)
6575 if (!NILP (right_width
))
6577 CHECK_NUMBER (right_width
);
6578 if (XINT (right_width
) <= 0)
6582 if (!EQ (w
->left_margin_cols
, left_width
)
6583 || !EQ (w
->right_margin_cols
, right_width
))
6585 w
->left_margin_cols
= left_width
;
6586 w
->right_margin_cols
= right_width
;
6588 adjust_window_margins (w
);
6590 ++windows_or_buffers_changed
;
6591 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6598 DEFUN ("window-margins", Fwindow_margins
, Swindow_margins
,
6600 doc
: /* Get width of marginal areas of window WINDOW.
6601 If WINDOW is omitted or nil, use the currently selected window.
6602 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6603 If a marginal area does not exist, its width will be returned
6605 (Lisp_Object window
)
6607 struct window
*w
= decode_window (window
);
6608 return Fcons (w
->left_margin_cols
, w
->right_margin_cols
);
6613 /***********************************************************************
6615 ***********************************************************************/
6617 DEFUN ("set-window-fringes", Fset_window_fringes
, Sset_window_fringes
,
6619 doc
: /* Set the fringe widths of window WINDOW.
6620 If WINDOW is nil, set the fringe widths of the currently selected
6622 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6623 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6624 fringe width. If a fringe width arg is nil, that means to use the
6625 frame's default fringe width. Default fringe widths can be set with
6626 the command `set-fringe-style'.
6627 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6628 outside of the display margins. By default, fringes are drawn between
6629 display marginal areas and the text area. */)
6630 (Lisp_Object window
, Lisp_Object left_width
, Lisp_Object right_width
, Lisp_Object outside_margins
)
6632 struct window
*w
= decode_window (window
);
6634 if (!NILP (left_width
))
6635 CHECK_NATNUM (left_width
);
6636 if (!NILP (right_width
))
6637 CHECK_NATNUM (right_width
);
6639 /* Do nothing on a tty. */
6640 if (FRAME_WINDOW_P (WINDOW_XFRAME (w
))
6641 && (!EQ (w
->left_fringe_width
, left_width
)
6642 || !EQ (w
->right_fringe_width
, right_width
)
6643 || !EQ (w
->fringes_outside_margins
, outside_margins
)))
6645 w
->left_fringe_width
= left_width
;
6646 w
->right_fringe_width
= right_width
;
6647 w
->fringes_outside_margins
= outside_margins
;
6649 adjust_window_margins (w
);
6651 clear_glyph_matrix (w
->current_matrix
);
6652 w
->window_end_valid
= Qnil
;
6654 ++windows_or_buffers_changed
;
6655 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6662 DEFUN ("window-fringes", Fwindow_fringes
, Swindow_fringes
,
6664 doc
: /* Get width of fringes of window WINDOW.
6665 If WINDOW is omitted or nil, use the currently selected window.
6666 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6667 (Lisp_Object window
)
6669 struct window
*w
= decode_window (window
);
6671 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w
)),
6672 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w
)),
6673 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w
)
6674 ? Qt
: Qnil
), Qnil
)));
6679 /***********************************************************************
6681 ***********************************************************************/
6683 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars
, Sset_window_scroll_bars
,
6685 doc
: /* Set width and type of scroll bars of window WINDOW.
6686 If window is nil, set scroll bars of the currently selected window.
6687 Second parameter WIDTH specifies the pixel width for the scroll bar;
6688 this is automatically adjusted to a multiple of the frame column width.
6689 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6690 bar: left, right, or nil.
6691 If WIDTH is nil, use the frame's scroll-bar width.
6692 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6693 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6694 (Lisp_Object window
, Lisp_Object width
, Lisp_Object vertical_type
, Lisp_Object horizontal_type
)
6696 struct window
*w
= decode_window (window
);
6700 CHECK_NATNUM (width
);
6702 if (XINT (width
) == 0)
6703 vertical_type
= Qnil
;
6706 if (!(NILP (vertical_type
)
6707 || EQ (vertical_type
, Qleft
)
6708 || EQ (vertical_type
, Qright
)
6709 || EQ (vertical_type
, Qt
)))
6710 error ("Invalid type of vertical scroll bar");
6712 if (!EQ (w
->scroll_bar_width
, width
)
6713 || !EQ (w
->vertical_scroll_bar_type
, vertical_type
))
6715 w
->scroll_bar_width
= width
;
6716 w
->vertical_scroll_bar_type
= vertical_type
;
6718 adjust_window_margins (w
);
6720 clear_glyph_matrix (w
->current_matrix
);
6721 w
->window_end_valid
= Qnil
;
6723 ++windows_or_buffers_changed
;
6724 adjust_glyphs (XFRAME (WINDOW_FRAME (w
)));
6731 DEFUN ("window-scroll-bars", Fwindow_scroll_bars
, Swindow_scroll_bars
,
6733 doc
: /* Get width and type of scroll bars of window WINDOW.
6734 If WINDOW is omitted or nil, use the currently selected window.
6735 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6736 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6738 (Lisp_Object window
)
6740 struct window
*w
= decode_window (window
);
6741 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
)
6742 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
)
6743 : WINDOW_SCROLL_BAR_AREA_WIDTH (w
))),
6744 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w
)),
6745 Fcons (w
->vertical_scroll_bar_type
,
6746 Fcons (Qnil
, Qnil
))));
6751 /***********************************************************************
6753 ***********************************************************************/
6755 DEFUN ("window-vscroll", Fwindow_vscroll
, Swindow_vscroll
, 0, 2, 0,
6756 doc
: /* Return the amount by which WINDOW is scrolled vertically.
6757 Use the selected window if WINDOW is nil or omitted.
6758 Normally, value is a multiple of the canonical character height of WINDOW;
6759 optional second arg PIXELS-P means value is measured in pixels. */)
6760 (Lisp_Object window
, Lisp_Object pixels_p
)
6767 window
= selected_window
;
6769 CHECK_WINDOW (window
);
6770 w
= XWINDOW (window
);
6771 f
= XFRAME (w
->frame
);
6773 if (FRAME_WINDOW_P (f
))
6774 result
= (NILP (pixels_p
)
6775 ? FRAME_CANON_Y_FROM_PIXEL_Y (f
, -w
->vscroll
)
6776 : make_number (-w
->vscroll
));
6778 result
= make_number (0);
6783 DEFUN ("set-window-vscroll", Fset_window_vscroll
, Sset_window_vscroll
,
6785 doc
: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6786 WINDOW nil means use the selected window. Normally, VSCROLL is a
6787 non-negative multiple of the canonical character height of WINDOW;
6788 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6789 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6790 corresponds to an integral number of pixels. The return value is the
6791 result of this rounding.
6792 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6793 (Lisp_Object window
, Lisp_Object vscroll
, Lisp_Object pixels_p
)
6799 window
= selected_window
;
6801 CHECK_WINDOW (window
);
6802 CHECK_NUMBER_OR_FLOAT (vscroll
);
6804 w
= XWINDOW (window
);
6805 f
= XFRAME (w
->frame
);
6807 if (FRAME_WINDOW_P (f
))
6809 int old_dy
= w
->vscroll
;
6811 w
->vscroll
= - (NILP (pixels_p
)
6812 ? FRAME_LINE_HEIGHT (f
) * XFLOATINT (vscroll
)
6813 : XFLOATINT (vscroll
));
6814 w
->vscroll
= min (w
->vscroll
, 0);
6816 if (w
->vscroll
!= old_dy
)
6818 /* Adjust glyph matrix of the frame if the virtual display
6819 area becomes larger than before. */
6820 if (w
->vscroll
< 0 && w
->vscroll
< old_dy
)
6823 /* Prevent redisplay shortcuts. */
6824 XBUFFER (w
->buffer
)->prevent_redisplay_optimizations_p
= 1;
6828 return Fwindow_vscroll (window
, pixels_p
);
6832 /* Call FN for all leaf windows on frame F. FN is called with the
6833 first argument being a pointer to the leaf window, and with
6834 additional argument USER_DATA. Stops when FN returns 0. */
6837 foreach_window (struct frame
*f
, int (*fn
) (struct window
*, void *),
6840 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6841 if (WINDOWP (FRAME_ROOT_WINDOW (f
)))
6842 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f
)), fn
, user_data
);
6846 /* Helper function for foreach_window. Call FN for all leaf windows
6847 reachable from W. FN is called with the first argument being a
6848 pointer to the leaf window, and with additional argument USER_DATA.
6849 Stop when FN returns 0. Value is 0 if stopped by FN. */
6852 foreach_window_1 (struct window
*w
, int (*fn
) (struct window
*, void *), void *user_data
)
6856 for (cont
= 1; w
&& cont
;)
6858 if (!NILP (w
->hchild
))
6859 cont
= foreach_window_1 (XWINDOW (w
->hchild
), fn
, user_data
);
6860 else if (!NILP (w
->vchild
))
6861 cont
= foreach_window_1 (XWINDOW (w
->vchild
), fn
, user_data
);
6863 cont
= fn (w
, user_data
);
6865 w
= NILP (w
->next
) ? 0 : XWINDOW (w
->next
);
6872 /* Freeze or unfreeze the window start of W unless it is a
6873 mini-window or the selected window. FREEZE_P non-null means freeze
6874 the window start. */
6877 freeze_window_start (struct window
*w
, void *freeze_p
)
6879 if (MINI_WINDOW_P (w
)
6880 || (WINDOWP (selected_window
) /* Can be nil in corner cases. */
6881 && (w
== XWINDOW (selected_window
)
6882 || (MINI_WINDOW_P (XWINDOW (selected_window
))
6883 && ! NILP (Vminibuf_scroll_window
)
6884 && w
== XWINDOW (Vminibuf_scroll_window
)))))
6887 w
->frozen_window_start_p
= freeze_p
!= NULL
;
6892 /* Freeze or unfreeze the window starts of all leaf windows on frame
6893 F, except the selected window and a mini-window. FREEZE_P non-zero
6894 means freeze the window start. */
6897 freeze_window_starts (struct frame
*f
, int freeze_p
)
6899 foreach_window (f
, freeze_window_start
, (void *) (freeze_p
? f
: 0));
6903 /***********************************************************************
6905 ***********************************************************************/
6907 /* Return 1 if window configurations C1 and C2
6908 describe the same state of affairs. This is used by Fequal. */
6911 compare_window_configurations (Lisp_Object c1
, Lisp_Object c2
, int ignore_positions
)
6913 register struct save_window_data
*d1
, *d2
;
6914 struct Lisp_Vector
*sw1
, *sw2
;
6917 CHECK_WINDOW_CONFIGURATION (c1
);
6918 CHECK_WINDOW_CONFIGURATION (c2
);
6920 d1
= (struct save_window_data
*) XVECTOR (c1
);
6921 d2
= (struct save_window_data
*) XVECTOR (c2
);
6922 sw1
= XVECTOR (d1
->saved_windows
);
6923 sw2
= XVECTOR (d2
->saved_windows
);
6925 if (d1
->frame_cols
!= d2
->frame_cols
)
6927 if (d1
->frame_lines
!= d2
->frame_lines
)
6929 if (d1
->frame_menu_bar_lines
!= d2
->frame_menu_bar_lines
)
6931 if (! EQ (d1
->selected_frame
, d2
->selected_frame
))
6933 /* Don't compare the current_window field directly.
6934 Instead see w1_is_current and w2_is_current, below. */
6935 if (! EQ (d1
->current_buffer
, d2
->current_buffer
))
6937 if (! ignore_positions
)
6939 if (! EQ (d1
->minibuf_scroll_window
, d2
->minibuf_scroll_window
))
6941 if (! EQ (d1
->minibuf_selected_window
, d2
->minibuf_selected_window
))
6944 /* Don't compare the root_window field.
6945 We don't require the two configurations
6946 to use the same window object,
6947 and the two root windows must be equivalent
6948 if everything else compares equal. */
6949 if (! EQ (d1
->focus_frame
, d2
->focus_frame
))
6952 /* Verify that the two confis have the same number of windows. */
6953 if (sw1
->size
!= sw2
->size
)
6956 for (i
= 0; i
< sw1
->size
; i
++)
6958 struct saved_window
*p1
, *p2
;
6959 int w1_is_current
, w2_is_current
;
6961 p1
= SAVED_WINDOW_N (sw1
, i
);
6962 p2
= SAVED_WINDOW_N (sw2
, i
);
6964 /* Verify that the current windows in the two
6965 configurations correspond to each other. */
6966 w1_is_current
= EQ (d1
->current_window
, p1
->window
);
6967 w2_is_current
= EQ (d2
->current_window
, p2
->window
);
6969 if (w1_is_current
!= w2_is_current
)
6972 /* Verify that the corresponding windows do match. */
6973 if (! EQ (p1
->buffer
, p2
->buffer
))
6975 if (! EQ (p1
->left_col
, p2
->left_col
))
6977 if (! EQ (p1
->top_line
, p2
->top_line
))
6979 if (! EQ (p1
->total_cols
, p2
->total_cols
))
6981 if (! EQ (p1
->total_lines
, p2
->total_lines
))
6983 if (! EQ (p1
->display_table
, p2
->display_table
))
6985 if (! EQ (p1
->parent
, p2
->parent
))
6987 if (! EQ (p1
->prev
, p2
->prev
))
6989 if (! ignore_positions
)
6991 if (! EQ (p1
->hscroll
, p2
->hscroll
))
6993 if (!EQ (p1
->min_hscroll
, p2
->min_hscroll
))
6995 if (! EQ (p1
->start_at_line_beg
, p2
->start_at_line_beg
))
6997 if (NILP (Fequal (p1
->start
, p2
->start
)))
6999 if (NILP (Fequal (p1
->pointm
, p2
->pointm
)))
7001 if (NILP (Fequal (p1
->mark
, p2
->mark
)))
7004 if (! EQ (p1
->left_margin_cols
, p2
->left_margin_cols
))
7006 if (! EQ (p1
->right_margin_cols
, p2
->right_margin_cols
))
7008 if (! EQ (p1
->left_fringe_width
, p2
->left_fringe_width
))
7010 if (! EQ (p1
->right_fringe_width
, p2
->right_fringe_width
))
7012 if (! EQ (p1
->fringes_outside_margins
, p2
->fringes_outside_margins
))
7014 if (! EQ (p1
->scroll_bar_width
, p2
->scroll_bar_width
))
7016 if (! EQ (p1
->vertical_scroll_bar_type
, p2
->vertical_scroll_bar_type
))
7023 DEFUN ("compare-window-configurations", Fcompare_window_configurations
,
7024 Scompare_window_configurations
, 2, 2, 0,
7025 doc
: /* Compare two window configurations as regards the structure of windows.
7026 This function ignores details such as the values of point and mark
7027 and scrolling positions. */)
7028 (Lisp_Object x
, Lisp_Object y
)
7030 if (compare_window_configurations (x
, y
, 1))
7036 init_window_once (void)
7038 struct frame
*f
= make_initial_frame ();
7039 XSETFRAME (selected_frame
, f
);
7040 Vterminal_frame
= selected_frame
;
7041 minibuf_window
= f
->minibuffer_window
;
7042 selected_window
= f
->selected_window
;
7043 last_nonminibuf_frame
= f
;
7045 window_initialized
= 1;
7051 Vwindow_list
= Qnil
;
7055 syms_of_window (void)
7057 Qscroll_up
= intern_c_string ("scroll-up");
7058 staticpro (&Qscroll_up
);
7060 Qscroll_down
= intern_c_string ("scroll-down");
7061 staticpro (&Qscroll_down
);
7063 Qscroll_command
= intern_c_string ("scroll-command");
7064 staticpro (&Qscroll_command
);
7066 Fput (Qscroll_up
, Qscroll_command
, Qt
);
7067 Fput (Qscroll_down
, Qscroll_command
, Qt
);
7069 Qwindow_size_fixed
= intern_c_string ("window-size-fixed");
7070 staticpro (&Qwindow_size_fixed
);
7071 Fset (Qwindow_size_fixed
, Qnil
);
7073 staticpro (&Qwindow_configuration_change_hook
);
7074 Qwindow_configuration_change_hook
7075 = intern_c_string ("window-configuration-change-hook");
7077 Qwindowp
= intern_c_string ("windowp");
7078 staticpro (&Qwindowp
);
7080 Qwindow_configuration_p
= intern_c_string ("window-configuration-p");
7081 staticpro (&Qwindow_configuration_p
);
7083 Qwindow_live_p
= intern_c_string ("window-live-p");
7084 staticpro (&Qwindow_live_p
);
7086 Qdisplay_buffer
= intern_c_string ("display-buffer");
7087 staticpro (&Qdisplay_buffer
);
7089 Qtemp_buffer_show_hook
= intern_c_string ("temp-buffer-show-hook");
7090 staticpro (&Qtemp_buffer_show_hook
);
7092 staticpro (&Vwindow_list
);
7094 minibuf_selected_window
= Qnil
;
7095 staticpro (&minibuf_selected_window
);
7097 window_scroll_pixel_based_preserve_x
= -1;
7098 window_scroll_pixel_based_preserve_y
= -1;
7099 window_scroll_preserve_hpos
= -1;
7100 window_scroll_preserve_vpos
= -1;
7102 inhibit_point_swap
= 0;
7104 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function
,
7105 doc
: /* Non-nil means call as function to display a help buffer.
7106 The function is called with one argument, the buffer to be displayed.
7107 Used by `with-output-to-temp-buffer'.
7108 If this function is used, then it must do the entire job of showing
7109 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7110 Vtemp_buffer_show_function
= Qnil
;
7112 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window
,
7113 doc
: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7114 Vminibuf_scroll_window
= Qnil
;
7116 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows
,
7117 doc
: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7118 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7119 is displayed in the `mode-line' face. */);
7120 mode_line_in_non_selected_windows
= 1;
7122 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer
,
7123 doc
: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7124 Vother_window_scroll_buffer
= Qnil
;
7126 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p
,
7127 doc
: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7128 auto_window_vscroll_p
= 1;
7130 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines
,
7131 doc
: /* *Number of lines of continuity when scrolling by screenfuls. */);
7132 next_screen_context_lines
= 2;
7134 DEFVAR_INT ("window-min-height", &window_min_height
,
7135 doc
: /* Allow deleting windows less than this tall.
7136 The value is measured in line units. If a window wants a modeline it
7137 is counted as one line.
7139 Emacs honors settings of this variable when enlarging or shrinking
7140 windows vertically. A value less than 1 is invalid. */);
7141 window_min_height
= 4;
7143 DEFVAR_INT ("window-min-width", &window_min_width
,
7144 doc
: /* Allow deleting windows less than this wide.
7145 The value is measured in characters and includes any fringes or
7148 Emacs honors settings of this variable when enlarging or shrinking
7149 windows horizontally. A value less than 2 is invalid. */);
7150 window_min_width
= 10;
7152 DEFVAR_LISP ("scroll-preserve-screen-position",
7153 &Vscroll_preserve_screen_position
,
7154 doc
: /* *Controls if scroll commands move point to keep its screen position unchanged.
7155 A value of nil means point does not keep its screen position except
7156 at the scroll margin or window boundary respectively.
7157 A value of t means point keeps its screen position if the scroll
7158 command moved it vertically out of the window, e.g. when scrolling
7160 Any other value means point always keeps its screen position.
7161 Scroll commands should have the `scroll-command' property
7162 on their symbols to be controlled by this variable. */);
7163 Vscroll_preserve_screen_position
= Qnil
;
7165 DEFVAR_LISP ("window-point-insertion-type", &Vwindow_point_insertion_type
,
7166 doc
: /* Type of marker to use for `window-point'. */);
7167 Vwindow_point_insertion_type
= Qnil
;
7169 DEFVAR_LISP ("window-configuration-change-hook",
7170 &Vwindow_configuration_change_hook
,
7171 doc
: /* Functions to call when window configuration changes.
7172 The buffer-local part is run once per window, with the relevant window
7173 selected; while the global part is run only once for the modified frame,
7174 with the relevant frame selected. */);
7175 Vwindow_configuration_change_hook
= Qnil
;
7177 DEFVAR_LISP ("recenter-redisplay", &Vrecenter_redisplay
,
7178 doc
: /* If non-nil, then the `recenter' command with a nil argument
7179 will redraw the entire frame; the special value `tty' causes the
7180 frame to be redrawn only if it is a tty frame. */);
7181 Vrecenter_redisplay
= Qtty
;
7184 defsubr (&Sselected_window
);
7185 defsubr (&Sminibuffer_window
);
7186 defsubr (&Swindow_minibuffer_p
);
7187 defsubr (&Swindowp
);
7188 defsubr (&Swindow_live_p
);
7189 defsubr (&Spos_visible_in_window_p
);
7190 defsubr (&Swindow_line_height
);
7191 defsubr (&Swindow_buffer
);
7192 defsubr (&Swindow_height
);
7193 defsubr (&Swindow_width
);
7194 defsubr (&Swindow_full_width_p
);
7195 defsubr (&Swindow_hscroll
);
7196 defsubr (&Sset_window_hscroll
);
7197 defsubr (&Swindow_redisplay_end_trigger
);
7198 defsubr (&Sset_window_redisplay_end_trigger
);
7199 defsubr (&Swindow_edges
);
7200 defsubr (&Swindow_pixel_edges
);
7201 defsubr (&Swindow_absolute_pixel_edges
);
7202 defsubr (&Swindow_inside_edges
);
7203 defsubr (&Swindow_inside_pixel_edges
);
7204 defsubr (&Swindow_inside_absolute_pixel_edges
);
7205 defsubr (&Scoordinates_in_window_p
);
7206 defsubr (&Swindow_at
);
7207 defsubr (&Swindow_point
);
7208 defsubr (&Swindow_start
);
7209 defsubr (&Swindow_end
);
7210 defsubr (&Sset_window_point
);
7211 defsubr (&Sset_window_start
);
7212 defsubr (&Swindow_dedicated_p
);
7213 defsubr (&Sset_window_dedicated_p
);
7214 defsubr (&Swindow_display_table
);
7215 defsubr (&Sset_window_display_table
);
7216 defsubr (&Snext_window
);
7217 defsubr (&Sprevious_window
);
7218 defsubr (&Sother_window
);
7219 defsubr (&Sget_lru_window
);
7220 defsubr (&Swindow_use_time
);
7221 defsubr (&Sget_largest_window
);
7222 defsubr (&Sget_buffer_window
);
7223 defsubr (&Sdelete_other_windows
);
7224 defsubr (&Sdelete_windows_on
);
7225 defsubr (&Sreplace_buffer_in_windows
);
7226 defsubr (&Sdelete_window
);
7227 defsubr (&Sset_window_buffer
);
7228 defsubr (&Sselect_window
);
7229 defsubr (&Sforce_window_update
);
7230 defsubr (&Ssplit_window
);
7231 defsubr (&Senlarge_window
);
7232 defsubr (&Sshrink_window
);
7233 defsubr (&Sadjust_window_trailing_edge
);
7234 defsubr (&Sscroll_up
);
7235 defsubr (&Sscroll_down
);
7236 defsubr (&Sscroll_left
);
7237 defsubr (&Sscroll_right
);
7238 defsubr (&Sother_window_for_scrolling
);
7239 defsubr (&Sscroll_other_window
);
7240 defsubr (&Sminibuffer_selected_window
);
7241 defsubr (&Srecenter
);
7242 defsubr (&Swindow_text_height
);
7243 defsubr (&Smove_to_window_line
);
7244 defsubr (&Swindow_configuration_p
);
7245 defsubr (&Swindow_configuration_frame
);
7246 defsubr (&Sset_window_configuration
);
7247 defsubr (&Scurrent_window_configuration
);
7248 defsubr (&Ssave_window_excursion
);
7249 defsubr (&Swindow_tree
);
7250 defsubr (&Sset_window_margins
);
7251 defsubr (&Swindow_margins
);
7252 defsubr (&Sset_window_fringes
);
7253 defsubr (&Swindow_fringes
);
7254 defsubr (&Sset_window_scroll_bars
);
7255 defsubr (&Swindow_scroll_bars
);
7256 defsubr (&Swindow_vscroll
);
7257 defsubr (&Sset_window_vscroll
);
7258 defsubr (&Scompare_window_configurations
);
7259 defsubr (&Swindow_list
);
7260 defsubr (&Swindow_parameters
);
7261 defsubr (&Swindow_parameter
);
7262 defsubr (&Sset_window_parameter
);
7267 keys_of_window (void)
7269 initial_define_key (control_x_map
, '1', "delete-other-windows");
7270 initial_define_key (control_x_map
, '2', "split-window");
7271 initial_define_key (control_x_map
, '0', "delete-window");
7272 initial_define_key (control_x_map
, 'o', "other-window");
7273 initial_define_key (control_x_map
, '^', "enlarge-window");
7274 initial_define_key (control_x_map
, '<', "scroll-left");
7275 initial_define_key (control_x_map
, '>', "scroll-right");
7277 initial_define_key (global_map
, Ctl ('V'), "scroll-up-command");
7278 initial_define_key (meta_map
, Ctl ('V'), "scroll-other-window");
7279 initial_define_key (meta_map
, 'v', "scroll-down-command");