(doc-view-mode-map): Bind `q' to quit-window, as is the custom.
[emacs.git] / src / window.c
blobc5e8b56084b34ab058bd9c0131aef1bd7fde9c9d
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
4 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 Free Software Foundation, Inc.
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 #include <config.h>
23 #include <stdio.h>
25 #include "lisp.h"
26 #include "buffer.h"
27 #include "keyboard.h"
28 #include "keymap.h"
29 #include "frame.h"
30 #include "window.h"
31 #include "commands.h"
32 #include "indent.h"
33 #include "termchar.h"
34 #include "disptab.h"
35 #include "dispextern.h"
36 #include "blockinput.h"
37 #include "intervals.h"
38 #include "termhooks.h" /* For FRAME_TERMINAL. */
40 #ifdef HAVE_X_WINDOWS
41 #include "xterm.h"
42 #endif /* HAVE_X_WINDOWS */
43 #ifdef WINDOWSNT
44 #include "w32term.h"
45 #endif
46 #ifdef MSDOS
47 #include "msdos.h"
48 #endif
49 #ifdef MAC_OS
50 #include "macterm.h"
51 #endif
54 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
55 Lisp_Object Qscroll_up, Qscroll_down;
56 Lisp_Object Qwindow_size_fixed;
57 extern Lisp_Object Qleft_margin, Qright_margin;
59 static int displayed_window_lines P_ ((struct window *));
60 static struct window *decode_window P_ ((Lisp_Object));
61 static int count_windows P_ ((struct window *));
62 static int get_leaf_windows P_ ((struct window *, struct window **, int));
63 static void window_scroll P_ ((Lisp_Object, int, int, int));
64 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
65 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
66 static int window_min_size_1 P_ ((struct window *, int, int));
67 static int window_min_size_2 P_ ((struct window *, int, int));
68 static int window_min_size P_ ((struct window *, int, int, int, int *));
69 static void size_window P_ ((Lisp_Object, int, int, int, int, int));
70 static int freeze_window_start P_ ((struct window *, void *));
71 static int window_fixed_size_p P_ ((struct window *, int, int));
72 static void enlarge_window P_ ((Lisp_Object, int, int));
73 static Lisp_Object window_list P_ ((void));
74 static int add_window_to_list P_ ((struct window *, void *));
75 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
76 Lisp_Object));
77 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
78 Lisp_Object, int));
79 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
80 Lisp_Object *));
81 static int foreach_window_1 P_ ((struct window *,
82 int (* fn) (struct window *, void *),
83 void *));
84 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
86 /* This is the window in which the terminal's cursor should
87 be left when nothing is being done with it. This must
88 always be a leaf window, and its buffer is selected by
89 the top level editing loop at the end of each command.
91 This value is always the same as
92 FRAME_SELECTED_WINDOW (selected_frame). */
94 Lisp_Object selected_window;
96 /* A list of all windows for use by next_window and Fwindow_list.
97 Functions creating or deleting windows should invalidate this cache
98 by setting it to nil. */
100 Lisp_Object Vwindow_list;
102 /* The mini-buffer window of the selected frame.
103 Note that you cannot test for mini-bufferness of an arbitrary window
104 by comparing against this; but you can test for mini-bufferness of
105 the selected window. */
107 Lisp_Object minibuf_window;
109 /* Non-nil means it is the window whose mode line should be
110 shown as the selected window when the minibuffer is selected. */
112 Lisp_Object minibuf_selected_window;
114 /* Non-nil means it is the window for C-M-v to scroll
115 when the mini-buffer is selected. */
117 Lisp_Object Vminibuf_scroll_window;
119 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
121 Lisp_Object Vother_window_scroll_buffer;
123 /* Non-nil means it's function to call to display temp buffers. */
125 Lisp_Object Vtemp_buffer_show_function;
127 /* Non-zero means line and page scrolling on tall lines (with images)
128 does partial scrolling by modifying window-vscroll. */
130 int auto_window_vscroll_p;
132 /* Non-zero means to use mode-line-inactive face in all windows but the
133 selected-window and the minibuffer-scroll-window when the
134 minibuffer is active. */
135 int mode_line_in_non_selected_windows;
137 /* If a window gets smaller than either of these, it is removed. */
139 EMACS_INT window_min_height;
140 EMACS_INT window_min_width;
142 /* Nonzero implies Fdisplay_buffer should create windows. */
144 int pop_up_windows;
146 /* Nonzero implies make new frames for Fdisplay_buffer. */
148 int pop_up_frames;
150 /* Nonzero means reuse existing frames for displaying buffers. */
152 int display_buffer_reuse_frames;
154 /* Non-nil means use this function instead of default */
156 Lisp_Object Vpop_up_frame_function;
158 /* Function to call to handle Fdisplay_buffer. */
160 Lisp_Object Vdisplay_buffer_function;
162 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
164 Lisp_Object Veven_window_heights;
166 /* List of buffer *names* for buffers that should have their own frames. */
168 Lisp_Object Vspecial_display_buffer_names;
170 /* List of regexps for buffer names that should have their own frames. */
172 Lisp_Object Vspecial_display_regexps;
174 /* Function to pop up a special frame. */
176 Lisp_Object Vspecial_display_function;
178 /* List of buffer *names* for buffers to appear in selected window. */
180 Lisp_Object Vsame_window_buffer_names;
182 /* List of regexps for buffer names to appear in selected window. */
184 Lisp_Object Vsame_window_regexps;
186 /* Hook run at end of temp_output_buffer_show. */
188 Lisp_Object Qtemp_buffer_show_hook;
190 /* Fdisplay_buffer always splits the largest window
191 if that window is more than this high. */
193 EMACS_INT split_height_threshold;
195 /* How to split windows (horizontally/vertically/hybrid). */
197 Lisp_Object Vsplit_window_preferred_function;
199 /* Number of lines of continuity in scrolling by screenfuls. */
201 EMACS_INT next_screen_context_lines;
203 /* Incremented for each window created. */
205 static int sequence_number;
207 /* Nonzero after init_window_once has finished. */
209 static int window_initialized;
211 /* Hook to run when window config changes. */
213 static Lisp_Object Qwindow_configuration_change_hook;
214 static Lisp_Object Vwindow_configuration_change_hook;
216 /* Non-nil means scroll commands try to put point
217 at the same screen height as previously. */
219 Lisp_Object Vscroll_preserve_screen_position;
221 /* Incremented by 1 whenever a window is deleted. */
223 int window_deletion_count;
225 /* Used by the function window_scroll_pixel_based */
227 static int window_scroll_pixel_based_preserve_y;
229 #if 0 /* This isn't used anywhere. */
230 /* Nonzero means we can split a frame even if it is "unsplittable". */
231 static int inhibit_frame_unsplittable;
232 #endif /* 0 */
234 extern EMACS_INT scroll_margin;
236 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
238 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
239 doc: /* Returns t if OBJECT is a window. */)
240 (object)
241 Lisp_Object object;
243 return WINDOWP (object) ? Qt : Qnil;
246 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
247 doc: /* Returns t if OBJECT is a window which is currently visible. */)
248 (object)
249 Lisp_Object object;
251 return WINDOW_LIVE_P (object) ? Qt : Qnil;
254 Lisp_Object
255 make_window ()
257 Lisp_Object val;
258 register struct window *p;
260 p = allocate_window ();
261 ++sequence_number;
262 XSETFASTINT (p->sequence_number, sequence_number);
263 XSETFASTINT (p->left_col, 0);
264 XSETFASTINT (p->top_line, 0);
265 XSETFASTINT (p->total_lines, 0);
266 XSETFASTINT (p->total_cols, 0);
267 XSETFASTINT (p->hscroll, 0);
268 XSETFASTINT (p->min_hscroll, 0);
269 p->orig_top_line = p->orig_total_lines = Qnil;
270 p->start = Fmake_marker ();
271 p->pointm = Fmake_marker ();
272 XSETFASTINT (p->use_time, 0);
273 p->frame = Qnil;
274 p->display_table = Qnil;
275 p->dedicated = Qnil;
276 p->pseudo_window_p = 0;
277 bzero (&p->cursor, sizeof (p->cursor));
278 bzero (&p->last_cursor, sizeof (p->last_cursor));
279 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
280 p->desired_matrix = p->current_matrix = 0;
281 p->nrows_scale_factor = p->ncols_scale_factor = 1;
282 p->phys_cursor_type = -1;
283 p->phys_cursor_width = -1;
284 p->must_be_updated_p = 0;
285 XSETFASTINT (p->window_end_vpos, 0);
286 XSETFASTINT (p->window_end_pos, 0);
287 p->window_end_valid = Qnil;
288 p->vscroll = 0;
289 XSETWINDOW (val, p);
290 XSETFASTINT (p->last_point, 0);
291 p->frozen_window_start_p = 0;
292 p->last_cursor_off_p = p->cursor_off_p = 0;
293 p->left_margin_cols = Qnil;
294 p->right_margin_cols = Qnil;
295 p->left_fringe_width = Qnil;
296 p->right_fringe_width = Qnil;
297 p->fringes_outside_margins = Qnil;
298 p->scroll_bar_width = Qnil;
299 p->vertical_scroll_bar_type = Qt;
300 p->resize_proportionally = Qnil;
302 Vwindow_list = Qnil;
303 return val;
306 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
307 doc: /* Return the window that the cursor now appears in and commands apply to. */)
310 return selected_window;
313 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
314 doc: /* Return the window used now for minibuffers.
315 If the optional argument FRAME is specified, return the minibuffer window
316 used by that frame. */)
317 (frame)
318 Lisp_Object frame;
320 if (NILP (frame))
321 frame = selected_frame;
322 CHECK_LIVE_FRAME (frame);
323 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
326 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
327 doc: /* Returns non-nil if WINDOW is a minibuffer window.
328 WINDOW defaults to the selected window. */)
329 (window)
330 Lisp_Object window;
332 struct window *w = decode_window (window);
333 return MINI_WINDOW_P (w) ? Qt : Qnil;
337 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
338 Spos_visible_in_window_p, 0, 3, 0,
339 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
340 Return nil if that position is scrolled vertically out of view.
341 If a character is only partially visible, nil is returned, unless the
342 optional argument PARTIALLY is non-nil.
343 If POS is only out of view because of horizontal scrolling, return non-nil.
344 If POS is t, it specifies the position of the last visible glyph in WINDOW.
345 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
347 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
348 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
349 where X and Y are the pixel coordinates relative to the top left corner
350 of the window. The remaining elements are omitted if the character after
351 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
352 off-window at the top and bottom of the row, ROWH is the height of the
353 display row, and VPOS is the row number (0-based) containing POS. */)
354 (pos, window, partially)
355 Lisp_Object pos, window, partially;
357 register struct window *w;
358 register int posint;
359 register struct buffer *buf;
360 struct text_pos top;
361 Lisp_Object in_window = Qnil;
362 int rtop, rbot, rowh, vpos, fully_p = 1;
363 int x, y;
365 w = decode_window (window);
366 buf = XBUFFER (w->buffer);
367 SET_TEXT_POS_FROM_MARKER (top, w->start);
369 if (EQ (pos, Qt))
370 posint = -1;
371 else if (!NILP (pos))
373 CHECK_NUMBER_COERCE_MARKER (pos);
374 posint = XINT (pos);
376 else if (w == XWINDOW (selected_window))
377 posint = PT;
378 else
379 posint = XMARKER (w->pointm)->charpos;
381 /* If position is above window start or outside buffer boundaries,
382 or if window start is out of range, position is not visible. */
383 if ((EQ (pos, Qt)
384 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
385 && CHARPOS (top) >= BUF_BEGV (buf)
386 && CHARPOS (top) <= BUF_ZV (buf)
387 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
388 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
389 in_window = Qt;
391 if (!NILP (in_window) && !NILP (partially))
393 Lisp_Object part = Qnil;
394 if (!fully_p)
395 part = list4 (make_number (rtop), make_number (rbot),
396 make_number (rowh), make_number (vpos));
397 in_window = Fcons (make_number (x),
398 Fcons (make_number (y), part));
401 return in_window;
404 DEFUN ("window-line-height", Fwindow_line_height,
405 Swindow_line_height, 0, 2, 0,
406 doc: /* Return height in pixels of text line LINE in window WINDOW.
407 If WINDOW is nil or omitted, use selected window.
409 Return height of current line if LINE is omitted or nil. Return height of
410 header or mode line if LINE is `header-line' and `mode-line'.
411 Otherwise, LINE is a text line number starting from 0. A negative number
412 counts from the end of the window.
414 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
415 in pixels of the visible part of the line, VPOS and YPOS are the
416 vertical position in lines and pixels of the line, relative to the top
417 of the first text line, and OFFBOT is the number of off-window pixels at
418 the bottom of the text line. If there are off-window pixels at the top
419 of the (first) text line, YPOS is negative.
421 Return nil if window display is not up-to-date. In that case, use
422 `pos-visible-in-window-p' to obtain the information. */)
423 (line, window)
424 Lisp_Object line, window;
426 register struct window *w;
427 register struct buffer *b;
428 struct glyph_row *row, *end_row;
429 int max_y, crop, i, n;
431 w = decode_window (window);
433 if (noninteractive
434 || w->pseudo_window_p)
435 return Qnil;
437 CHECK_BUFFER (w->buffer);
438 b = XBUFFER (w->buffer);
440 /* Fail if current matrix is not up-to-date. */
441 if (NILP (w->window_end_valid)
442 || current_buffer->clip_changed
443 || current_buffer->prevent_redisplay_optimizations_p
444 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
445 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
446 return Qnil;
448 if (NILP (line))
450 i = w->cursor.vpos;
451 if (i < 0 || i >= w->current_matrix->nrows
452 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
453 return Qnil;
454 max_y = window_text_bottom_y (w);
455 goto found_row;
458 if (EQ (line, Qheader_line))
460 if (!WINDOW_WANTS_HEADER_LINE_P (w))
461 return Qnil;
462 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
463 if (!row->enabled_p)
464 return Qnil;
465 return list4 (make_number (row->height),
466 make_number (0), make_number (0),
467 make_number (0));
470 if (EQ (line, Qmode_line))
472 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
473 if (!row->enabled_p)
474 return Qnil;
475 return list4 (make_number (row->height),
476 make_number (0), /* not accurate */
477 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
478 + window_text_bottom_y (w)),
479 make_number (0));
482 CHECK_NUMBER (line);
483 n = XINT (line);
485 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
486 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
487 max_y = window_text_bottom_y (w);
488 i = 0;
490 while ((n < 0 || i < n)
491 && row <= end_row && row->enabled_p
492 && row->y + row->height < max_y)
493 row++, i++;
495 if (row > end_row || !row->enabled_p)
496 return Qnil;
498 if (++n < 0)
500 if (-n > i)
501 return Qnil;
502 row += n;
503 i += n;
506 found_row:
507 crop = max (0, (row->y + row->height) - max_y);
508 return list4 (make_number (row->height + min (0, row->y) - crop),
509 make_number (i),
510 make_number (row->y),
511 make_number (crop));
516 static struct window *
517 decode_window (window)
518 register Lisp_Object window;
520 if (NILP (window))
521 return XWINDOW (selected_window);
523 CHECK_LIVE_WINDOW (window);
524 return XWINDOW (window);
527 static struct window *
528 decode_any_window (window)
529 register Lisp_Object window;
531 if (NILP (window))
532 return XWINDOW (selected_window);
534 CHECK_WINDOW (window);
535 return XWINDOW (window);
538 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
539 doc: /* Return the buffer that WINDOW is displaying.
540 WINDOW defaults to the selected window. */)
541 (window)
542 Lisp_Object window;
544 return decode_window (window)->buffer;
547 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
548 doc: /* Return the number of lines in WINDOW (including its mode line).
549 WINDOW defaults to the selected window. */)
550 (window)
551 Lisp_Object window;
553 return decode_any_window (window)->total_lines;
556 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
557 doc: /* Return the number of display columns in WINDOW.
558 This is the width that is usable columns available for text in WINDOW.
559 If you want to find out how many columns WINDOW takes up,
560 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
561 (window)
562 Lisp_Object window;
564 return make_number (window_box_text_cols (decode_any_window (window)));
567 DEFUN ("window-full-width-p", Fwindow_full_width_p, Swindow_full_width_p, 0, 1, 0,
568 doc: /* Return t if WINDOW is as wide as its frame.
569 WINDOW defaults to the selected window. */)
570 (window)
571 Lisp_Object window;
573 return WINDOW_FULL_WIDTH_P (decode_any_window (window)) ? Qt : Qnil;
576 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
577 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
578 WINDOW defaults to the selected window. */)
579 (window)
580 Lisp_Object window;
582 return decode_window (window)->hscroll;
585 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
586 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
587 Return NCOL. NCOL should be zero or positive.
589 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
590 window so that the location of point moves off-window. */)
591 (window, ncol)
592 Lisp_Object window, ncol;
594 struct window *w = decode_window (window);
595 int hscroll;
597 CHECK_NUMBER (ncol);
598 hscroll = max (0, XINT (ncol));
600 /* Prevent redisplay shortcuts when changing the hscroll. */
601 if (XINT (w->hscroll) != hscroll)
602 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
604 w->hscroll = make_number (hscroll);
605 return ncol;
608 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
609 Swindow_redisplay_end_trigger, 0, 1, 0,
610 doc: /* Return WINDOW's redisplay end trigger value.
611 WINDOW defaults to the selected window.
612 See `set-window-redisplay-end-trigger' for more information. */)
613 (window)
614 Lisp_Object window;
616 return decode_window (window)->redisplay_end_trigger;
619 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
620 Sset_window_redisplay_end_trigger, 2, 2, 0,
621 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
622 VALUE should be a buffer position (typically a marker) or nil.
623 If it is a buffer position, then if redisplay in WINDOW reaches a position
624 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
625 with two arguments: WINDOW, and the end trigger value.
626 Afterwards the end-trigger value is reset to nil. */)
627 (window, value)
628 register Lisp_Object window, value;
630 register struct window *w;
632 w = decode_window (window);
633 w->redisplay_end_trigger = value;
634 return value;
637 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
638 doc: /* Return a list of the edge coordinates of WINDOW.
639 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
640 RIGHT is one more than the rightmost column occupied by WINDOW,
641 and BOTTOM is one more than the bottommost row occupied by WINDOW.
642 The edges include the space used by the window's scroll bar,
643 display margins, fringes, header line, and mode line, if it has them.
644 To get the edges of the actual text area, use `window-inside-edges'. */)
645 (window)
646 Lisp_Object window;
648 register struct window *w = decode_any_window (window);
650 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
651 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
652 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
653 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
654 Qnil))));
657 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
658 doc: /* Return a list of the edge pixel coordinates of WINDOW.
659 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
660 RIGHT is one more than the rightmost x position occupied by WINDOW,
661 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
662 The pixel edges include the space used by the window's scroll bar,
663 display margins, fringes, header line, and mode line, if it has them.
664 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
665 (window)
666 Lisp_Object window;
668 register struct window *w = decode_any_window (window);
670 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
671 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
672 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
673 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
674 Qnil))));
677 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
678 doc: /* Return a list of the edge coordinates of WINDOW.
679 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
680 RIGHT is one more than the rightmost column used by text in WINDOW,
681 and BOTTOM is one more than the bottommost row used by text in WINDOW.
682 The inside edges do not include the space used by the window's scroll bar,
683 display margins, fringes, header line, and/or mode line. */)
684 (window)
685 Lisp_Object window;
687 register struct window *w = decode_any_window (window);
689 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
690 + WINDOW_LEFT_MARGIN_COLS (w)
691 + WINDOW_LEFT_FRINGE_COLS (w)),
692 make_number (WINDOW_TOP_EDGE_LINE (w)
693 + WINDOW_HEADER_LINE_LINES (w)),
694 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
695 - WINDOW_RIGHT_MARGIN_COLS (w)
696 - WINDOW_RIGHT_FRINGE_COLS (w)),
697 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
698 - WINDOW_MODE_LINE_LINES (w)));
701 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
702 doc: /* Return a list of the edge pixel coordinates of WINDOW.
703 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
704 RIGHT is one more than the rightmost x position used by text in WINDOW,
705 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
706 The inside edges do not include the space used by the window's scroll bar,
707 display margins, fringes, header line, and/or mode line. */)
708 (window)
709 Lisp_Object window;
711 register struct window *w = decode_any_window (window);
713 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
714 + WINDOW_LEFT_MARGIN_WIDTH (w)
715 + WINDOW_LEFT_FRINGE_WIDTH (w)),
716 make_number (WINDOW_TOP_EDGE_Y (w)
717 + WINDOW_HEADER_LINE_HEIGHT (w)),
718 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
719 - WINDOW_RIGHT_MARGIN_WIDTH (w)
720 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
721 make_number (WINDOW_BOTTOM_EDGE_Y (w)
722 - WINDOW_MODE_LINE_HEIGHT (w)));
725 /* Test if the character at column *X, row *Y is within window W.
726 If it is not, return ON_NOTHING;
727 if it is in the window's text area,
728 set *x and *y to its location relative to the upper left corner
729 of the window, and
730 return ON_TEXT;
731 if it is on the window's modeline, return ON_MODE_LINE;
732 if it is on the border between the window and its right sibling,
733 return ON_VERTICAL_BORDER.
734 if it is on a scroll bar,
735 return ON_SCROLL_BAR.
736 if it is on the window's top line, return ON_HEADER_LINE;
737 if it is in left or right fringe of the window,
738 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
739 to window-relative coordinates;
740 if it is in the marginal area to the left/right of the window,
741 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
742 to window-relative coordinates.
744 X and Y are frame relative pixel coordinates. */
746 static enum window_part
747 coordinates_in_window (w, x, y)
748 register struct window *w;
749 register int *x, *y;
751 struct frame *f = XFRAME (WINDOW_FRAME (w));
752 int left_x, right_x, top_y, bottom_y;
753 enum window_part part;
754 int ux = FRAME_COLUMN_WIDTH (f);
755 int x0 = WINDOW_LEFT_EDGE_X (w);
756 int x1 = WINDOW_RIGHT_EDGE_X (w);
757 /* The width of the area where the vertical line can be dragged.
758 (Between mode lines for instance. */
759 int grabbable_width = ux;
760 int lmargin_width, rmargin_width, text_left, text_right;
762 /* In what's below, we subtract 1 when computing right_x because we
763 want the rightmost pixel, which is given by left_pixel+width-1. */
764 if (w->pseudo_window_p)
766 left_x = 0;
767 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
768 top_y = WINDOW_TOP_EDGE_Y (w);
769 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
771 else
773 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
774 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
775 top_y = WINDOW_TOP_EDGE_Y (w);
776 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
779 /* Outside any interesting row? */
780 if (*y < top_y || *y >= bottom_y)
781 return ON_NOTHING;
783 /* On the mode line or header line? If it's near the start of
784 the mode or header line of window that's has a horizontal
785 sibling, say it's on the vertical line. That's to be able
786 to resize windows horizontally in case we're using toolkit
787 scroll bars. */
789 if (WINDOW_WANTS_MODELINE_P (w)
790 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
792 part = ON_MODE_LINE;
794 header_vertical_border_check:
795 /* We're somewhere on the mode line. We consider the place
796 between mode lines of horizontally adjacent mode lines
797 as the vertical border. If scroll bars on the left,
798 return the right window. */
799 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
800 || WINDOW_RIGHTMOST_P (w))
802 if (!WINDOW_LEFTMOST_P (w) && eabs (*x - x0) < grabbable_width)
804 /* Convert X and Y to window relative coordinates.
805 Vertical border is at the left edge of window. */
806 *x = max (0, *x - x0);
807 *y -= top_y;
808 return ON_VERTICAL_BORDER;
811 else
813 if (eabs (*x - x1) < grabbable_width)
815 /* Convert X and Y to window relative coordinates.
816 Vertical border is at the right edge of window. */
817 *x = min (x1, *x) - x0;
818 *y -= top_y;
819 return ON_VERTICAL_BORDER;
823 if (*x < x0 || *x >= x1)
824 return ON_NOTHING;
826 /* Convert X and Y to window relative coordinates.
827 Mode line starts at left edge of window. */
828 *x -= x0;
829 *y -= top_y;
830 return part;
833 if (WINDOW_WANTS_HEADER_LINE_P (w)
834 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
836 part = ON_HEADER_LINE;
837 goto header_vertical_border_check;
840 if (*x < x0 || *x >= x1)
841 return ON_NOTHING;
843 /* Outside any interesting column? */
844 if (*x < left_x || *x > right_x)
846 *y -= top_y;
847 return ON_SCROLL_BAR;
850 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
851 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
853 text_left = window_box_left (w, TEXT_AREA);
854 text_right = text_left + window_box_width (w, TEXT_AREA);
856 if (FRAME_WINDOW_P (f))
858 if (!w->pseudo_window_p
859 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
860 && !WINDOW_RIGHTMOST_P (w)
861 && (eabs (*x - right_x) < grabbable_width))
863 /* Convert X and Y to window relative coordinates.
864 Vertical border is at the right edge of window. */
865 *x = min (right_x, *x) - left_x;
866 *y -= top_y;
867 return ON_VERTICAL_BORDER;
870 else
872 /* Need to say "*x > right_x" rather than >=, since on character
873 terminals, the vertical line's x coordinate is right_x. */
874 if (!w->pseudo_window_p
875 && !WINDOW_RIGHTMOST_P (w)
876 && *x > right_x - ux)
878 /* On the border on the right side of the window? Assume that
879 this area begins at RIGHT_X minus a canonical char width. */
880 *x = min (right_x, *x) - left_x;
881 *y -= top_y;
882 return ON_VERTICAL_BORDER;
886 if (*x < text_left)
888 if (lmargin_width > 0
889 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
890 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
891 : (*x < left_x + lmargin_width)))
893 *x -= left_x;
894 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
895 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
896 *y -= top_y;
897 return ON_LEFT_MARGIN;
900 /* Convert X and Y to window-relative pixel coordinates. */
901 *x -= left_x;
902 *y -= top_y;
903 return ON_LEFT_FRINGE;
906 if (*x >= text_right)
908 if (rmargin_width > 0
909 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
910 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
911 : (*x >= right_x - rmargin_width)))
913 *x -= right_x - rmargin_width;
914 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
915 *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
916 *y -= top_y;
917 return ON_RIGHT_MARGIN;
920 /* Convert X and Y to window-relative pixel coordinates. */
921 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
922 *y -= top_y;
923 return ON_RIGHT_FRINGE;
926 /* Everything special ruled out - must be on text area */
927 *x -= text_left;
928 *y -= top_y;
929 return ON_TEXT;
933 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
934 Scoordinates_in_window_p, 2, 2, 0,
935 doc: /* Return non-nil if COORDINATES are in WINDOW.
936 COORDINATES is a cons of the form (X . Y), X and Y being distances
937 measured in characters from the upper-left corner of the frame.
938 \(0 . 0) denotes the character in the upper left corner of the
939 frame.
940 If COORDINATES are in the text portion of WINDOW,
941 the coordinates relative to the window are returned.
942 If they are in the mode line of WINDOW, `mode-line' is returned.
943 If they are in the top mode line of WINDOW, `header-line' is returned.
944 If they are in the left fringe of WINDOW, `left-fringe' is returned.
945 If they are in the right fringe of WINDOW, `right-fringe' is returned.
946 If they are on the border between WINDOW and its right sibling,
947 `vertical-line' is returned.
948 If they are in the windows's left or right marginal areas, `left-margin'\n\
949 or `right-margin' is returned. */)
950 (coordinates, window)
951 register Lisp_Object coordinates, window;
953 struct window *w;
954 struct frame *f;
955 int x, y;
956 Lisp_Object lx, ly;
958 CHECK_WINDOW (window);
959 w = XWINDOW (window);
960 f = XFRAME (w->frame);
961 CHECK_CONS (coordinates);
962 lx = Fcar (coordinates);
963 ly = Fcdr (coordinates);
964 CHECK_NUMBER_OR_FLOAT (lx);
965 CHECK_NUMBER_OR_FLOAT (ly);
966 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
967 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
969 switch (coordinates_in_window (w, &x, &y))
971 case ON_NOTHING:
972 return Qnil;
974 case ON_TEXT:
975 /* X and Y are now window relative pixel coordinates. Convert
976 them to canonical char units before returning them. */
977 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
978 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
980 case ON_MODE_LINE:
981 return Qmode_line;
983 case ON_VERTICAL_BORDER:
984 return Qvertical_line;
986 case ON_HEADER_LINE:
987 return Qheader_line;
989 case ON_LEFT_FRINGE:
990 return Qleft_fringe;
992 case ON_RIGHT_FRINGE:
993 return Qright_fringe;
995 case ON_LEFT_MARGIN:
996 return Qleft_margin;
998 case ON_RIGHT_MARGIN:
999 return Qright_margin;
1001 case ON_SCROLL_BAR:
1002 /* Historically we are supposed to return nil in this case. */
1003 return Qnil;
1005 default:
1006 abort ();
1011 /* Callback for foreach_window, used in window_from_coordinates.
1012 Check if window W contains coordinates specified by USER_DATA which
1013 is actually a pointer to a struct check_window_data CW.
1015 Check if window W contains coordinates *CW->x and *CW->y. If it
1016 does, return W in *CW->window, as Lisp_Object, and return in
1017 *CW->part the part of the window under coordinates *X,*Y. Return
1018 zero from this function to stop iterating over windows. */
1020 struct check_window_data
1022 Lisp_Object *window;
1023 int *x, *y;
1024 enum window_part *part;
1027 static int
1028 check_window_containing (w, user_data)
1029 struct window *w;
1030 void *user_data;
1032 struct check_window_data *cw = (struct check_window_data *) user_data;
1033 enum window_part found;
1034 int continue_p = 1;
1036 found = coordinates_in_window (w, cw->x, cw->y);
1037 if (found != ON_NOTHING)
1039 *cw->part = found;
1040 XSETWINDOW (*cw->window, w);
1041 continue_p = 0;
1044 return continue_p;
1048 /* Find the window containing frame-relative pixel position X/Y and
1049 return it as a Lisp_Object.
1051 If X, Y is on one of the window's special `window_part' elements,
1052 set *PART to the id of that element, and return X and Y converted
1053 to window relative coordinates in WX and WY.
1055 If there is no window under X, Y return nil and leave *PART
1056 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1058 This function was previously implemented with a loop cycling over
1059 windows with Fnext_window, and starting with the frame's selected
1060 window. It turned out that this doesn't work with an
1061 implementation of next_window using Vwindow_list, because
1062 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1063 tree of F when this function is called asynchronously from
1064 note_mouse_highlight. The original loop didn't terminate in this
1065 case. */
1067 Lisp_Object
1068 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
1069 struct frame *f;
1070 int x, y;
1071 enum window_part *part;
1072 int *wx, *wy;
1073 int tool_bar_p;
1075 Lisp_Object window;
1076 struct check_window_data cw;
1077 enum window_part dummy;
1079 if (part == 0)
1080 part = &dummy;
1082 window = Qnil;
1083 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
1084 foreach_window (f, check_window_containing, &cw);
1086 /* If not found above, see if it's in the tool bar window, if a tool
1087 bar exists. */
1088 if (NILP (window)
1089 && tool_bar_p
1090 && WINDOWP (f->tool_bar_window)
1091 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1092 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
1093 != ON_NOTHING))
1095 *part = ON_TEXT;
1096 window = f->tool_bar_window;
1099 if (wx) *wx = x;
1100 if (wy) *wy = y;
1102 return window;
1105 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1106 doc: /* Return window containing coordinates X and Y on FRAME.
1107 If omitted, FRAME defaults to the currently selected frame.
1108 The top left corner of the frame is considered to be row 0,
1109 column 0. */)
1110 (x, y, frame)
1111 Lisp_Object x, y, frame;
1113 struct frame *f;
1115 if (NILP (frame))
1116 frame = selected_frame;
1117 CHECK_LIVE_FRAME (frame);
1118 f = XFRAME (frame);
1120 /* Check that arguments are integers or floats. */
1121 CHECK_NUMBER_OR_FLOAT (x);
1122 CHECK_NUMBER_OR_FLOAT (y);
1124 return window_from_coordinates (f,
1125 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1126 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1127 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1128 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1129 0, 0, 0, 0);
1132 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1133 doc: /* Return current value of point in WINDOW.
1134 WINDOW defaults to the selected window.
1136 For a nonselected window, this is the value point would have
1137 if that window were selected.
1139 Note that, when WINDOW is the selected window and its buffer
1140 is also currently selected, the value returned is the same as (point).
1141 It would be more strictly correct to return the `top-level' value
1142 of point, outside of any save-excursion forms.
1143 But that is hard to define. */)
1144 (window)
1145 Lisp_Object window;
1147 register struct window *w = decode_window (window);
1149 if (w == XWINDOW (selected_window)
1150 && current_buffer == XBUFFER (w->buffer))
1151 return Fpoint ();
1152 return Fmarker_position (w->pointm);
1155 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1156 doc: /* Return position at which display currently starts in WINDOW.
1157 WINDOW defaults to the selected window.
1158 This is updated by redisplay or by calling `set-window-start'. */)
1159 (window)
1160 Lisp_Object window;
1162 return Fmarker_position (decode_window (window)->start);
1165 /* This is text temporarily removed from the doc string below.
1167 This function returns nil if the position is not currently known.
1168 That happens when redisplay is preempted and doesn't finish.
1169 If in that case you want to compute where the end of the window would
1170 have been if redisplay had finished, do this:
1171 (save-excursion
1172 (goto-char (window-start window))
1173 (vertical-motion (1- (window-height window)) window)
1174 (point))") */
1176 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1177 doc: /* Return position at which display currently ends in WINDOW.
1178 WINDOW defaults to the selected window.
1179 This is updated by redisplay, when it runs to completion.
1180 Simply changing the buffer text or setting `window-start'
1181 does not update this value.
1182 Return nil if there is no recorded value. \(This can happen if the
1183 last redisplay of WINDOW was preempted, and did not finish.)
1184 If UPDATE is non-nil, compute the up-to-date position
1185 if it isn't already recorded. */)
1186 (window, update)
1187 Lisp_Object window, update;
1189 Lisp_Object value;
1190 struct window *w = decode_window (window);
1191 Lisp_Object buf;
1192 struct buffer *b;
1194 buf = w->buffer;
1195 CHECK_BUFFER (buf);
1196 b = XBUFFER (buf);
1198 #if 0 /* This change broke some things. We should make it later. */
1199 /* If we don't know the end position, return nil.
1200 The user can compute it with vertical-motion if he wants to.
1201 It would be nicer to do it automatically,
1202 but that's so slow that it would probably bother people. */
1203 if (NILP (w->window_end_valid))
1204 return Qnil;
1205 #endif
1207 if (! NILP (update)
1208 && ! (! NILP (w->window_end_valid)
1209 && XFASTINT (w->last_modified) >= BUF_MODIFF (b)
1210 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
1211 && !noninteractive)
1213 struct text_pos startp;
1214 struct it it;
1215 struct buffer *old_buffer = NULL;
1217 /* Cannot use Fvertical_motion because that function doesn't
1218 cope with variable-height lines. */
1219 if (b != current_buffer)
1221 old_buffer = current_buffer;
1222 set_buffer_internal (b);
1225 /* In case W->start is out of the range, use something
1226 reasonable. This situation occurred when loading a file with
1227 `-l' containing a call to `rmail' with subsequent other
1228 commands. At the end, W->start happened to be BEG, while
1229 rmail had already narrowed the buffer. */
1230 if (XMARKER (w->start)->charpos < BEGV)
1231 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1232 else if (XMARKER (w->start)->charpos > ZV)
1233 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1234 else
1235 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1237 start_display (&it, w, startp);
1238 move_it_vertically (&it, window_box_height (w));
1239 if (it.current_y < it.last_visible_y)
1240 move_it_past_eol (&it);
1241 value = make_number (IT_CHARPOS (it));
1243 if (old_buffer)
1244 set_buffer_internal (old_buffer);
1246 else
1247 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1249 return value;
1252 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1253 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1254 Return POS. */)
1255 (window, pos)
1256 Lisp_Object window, pos;
1258 register struct window *w = decode_window (window);
1260 CHECK_NUMBER_COERCE_MARKER (pos);
1261 if (w == XWINDOW (selected_window)
1262 && XBUFFER (w->buffer) == current_buffer)
1263 Fgoto_char (pos);
1264 else
1265 set_marker_restricted (w->pointm, pos, w->buffer);
1267 /* We have to make sure that redisplay updates the window to show
1268 the new value of point. */
1269 if (!EQ (window, selected_window))
1270 ++windows_or_buffers_changed;
1272 return pos;
1275 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1276 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1277 Return POS.
1278 Optional third arg NOFORCE non-nil inhibits next redisplay
1279 from overriding motion of point in order to display at this exact start. */)
1280 (window, pos, noforce)
1281 Lisp_Object window, pos, noforce;
1283 register struct window *w = decode_window (window);
1285 CHECK_NUMBER_COERCE_MARKER (pos);
1286 set_marker_restricted (w->start, pos, w->buffer);
1287 /* this is not right, but much easier than doing what is right. */
1288 w->start_at_line_beg = Qnil;
1289 if (NILP (noforce))
1290 w->force_start = Qt;
1291 w->update_mode_line = Qt;
1292 XSETFASTINT (w->last_modified, 0);
1293 XSETFASTINT (w->last_overlay_modified, 0);
1294 if (!EQ (window, selected_window))
1295 windows_or_buffers_changed++;
1297 return pos;
1300 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1301 1, 1, 0,
1302 doc: /* Return WINDOW's dedicated object, usually t or nil.
1303 See also `set-window-dedicated-p'. */)
1304 (window)
1305 Lisp_Object window;
1307 return decode_window (window)->dedicated;
1310 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1311 Sset_window_dedicated_p, 2, 2, 0,
1312 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1313 If it is dedicated, Emacs will not automatically change
1314 which buffer appears in it.
1315 The second argument is the new value for the dedication flag;
1316 non-nil means yes. */)
1317 (window, arg)
1318 Lisp_Object window, arg;
1320 register struct window *w = decode_window (window);
1322 w->dedicated = arg;
1324 return w->dedicated;
1327 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1328 0, 1, 0,
1329 doc: /* Return the display-table that WINDOW is using.
1330 WINDOW defaults to the selected window. */)
1331 (window)
1332 Lisp_Object window;
1334 return decode_window (window)->display_table;
1337 /* Get the display table for use on window W. This is either W's
1338 display table or W's buffer's display table. Ignore the specified
1339 tables if they are not valid; if no valid table is specified,
1340 return 0. */
1342 struct Lisp_Char_Table *
1343 window_display_table (w)
1344 struct window *w;
1346 struct Lisp_Char_Table *dp = NULL;
1348 if (DISP_TABLE_P (w->display_table))
1349 dp = XCHAR_TABLE (w->display_table);
1350 else if (BUFFERP (w->buffer))
1352 struct buffer *b = XBUFFER (w->buffer);
1354 if (DISP_TABLE_P (b->display_table))
1355 dp = XCHAR_TABLE (b->display_table);
1356 else if (DISP_TABLE_P (Vstandard_display_table))
1357 dp = XCHAR_TABLE (Vstandard_display_table);
1360 return dp;
1363 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1364 doc: /* Set WINDOW's display-table to TABLE. */)
1365 (window, table)
1366 register Lisp_Object window, table;
1368 register struct window *w;
1370 w = decode_window (window);
1371 w->display_table = table;
1372 return table;
1375 /* Record info on buffer window w is displaying
1376 when it is about to cease to display that buffer. */
1377 static void
1378 unshow_buffer (w)
1379 register struct window *w;
1381 Lisp_Object buf;
1382 struct buffer *b;
1384 buf = w->buffer;
1385 b = XBUFFER (buf);
1386 if (b != XMARKER (w->pointm)->buffer)
1387 abort ();
1389 #if 0
1390 if (w == XWINDOW (selected_window)
1391 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1392 /* Do this except when the selected window's buffer
1393 is being removed from some other window. */
1394 #endif
1395 /* last_window_start records the start position that this buffer
1396 had in the last window to be disconnected from it.
1397 Now that this statement is unconditional,
1398 it is possible for the buffer to be displayed in the
1399 selected window, while last_window_start reflects another
1400 window which was recently showing the same buffer.
1401 Some people might say that might be a good thing. Let's see. */
1402 b->last_window_start = marker_position (w->start);
1404 /* Point in the selected window's buffer
1405 is actually stored in that buffer, and the window's pointm isn't used.
1406 So don't clobber point in that buffer. */
1407 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1408 /* This line helps to fix Horsley's testbug.el bug. */
1409 && !(WINDOWP (b->last_selected_window)
1410 && w != XWINDOW (b->last_selected_window)
1411 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1412 temp_set_point_both (b,
1413 clip_to_bounds (BUF_BEGV (b),
1414 XMARKER (w->pointm)->charpos,
1415 BUF_ZV (b)),
1416 clip_to_bounds (BUF_BEGV_BYTE (b),
1417 marker_byte_position (w->pointm),
1418 BUF_ZV_BYTE (b)));
1420 if (WINDOWP (b->last_selected_window)
1421 && w == XWINDOW (b->last_selected_window))
1422 b->last_selected_window = Qnil;
1425 /* Put replacement into the window structure in place of old. */
1426 static void
1427 replace_window (old, replacement)
1428 Lisp_Object old, replacement;
1430 register Lisp_Object tem;
1431 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1433 /* If OLD is its frame's root_window, then replacement is the new
1434 root_window for that frame. */
1436 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1437 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1439 p->left_col = o->left_col;
1440 p->top_line = o->top_line;
1441 p->total_cols = o->total_cols;
1442 p->total_lines = o->total_lines;
1443 p->desired_matrix = p->current_matrix = 0;
1444 p->vscroll = 0;
1445 bzero (&p->cursor, sizeof (p->cursor));
1446 bzero (&p->last_cursor, sizeof (p->last_cursor));
1447 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1448 p->phys_cursor_type = -1;
1449 p->phys_cursor_width = -1;
1450 p->must_be_updated_p = 0;
1451 p->pseudo_window_p = 0;
1452 XSETFASTINT (p->window_end_vpos, 0);
1453 XSETFASTINT (p->window_end_pos, 0);
1454 p->window_end_valid = Qnil;
1455 p->frozen_window_start_p = 0;
1456 p->orig_top_line = p->orig_total_lines = Qnil;
1458 p->next = tem = o->next;
1459 if (!NILP (tem))
1460 XWINDOW (tem)->prev = replacement;
1462 p->prev = tem = o->prev;
1463 if (!NILP (tem))
1464 XWINDOW (tem)->next = replacement;
1466 p->parent = tem = o->parent;
1467 if (!NILP (tem))
1469 if (EQ (XWINDOW (tem)->vchild, old))
1470 XWINDOW (tem)->vchild = replacement;
1471 if (EQ (XWINDOW (tem)->hchild, old))
1472 XWINDOW (tem)->hchild = replacement;
1475 /*** Here, if replacement is a vertical combination
1476 and so is its new parent, we should make replacement's
1477 children be children of that parent instead. ***/
1480 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1481 doc: /* Remove WINDOW from the display. Default is selected window. */)
1482 (window)
1483 register Lisp_Object window;
1485 struct frame *f;
1486 if (NILP (window))
1487 window = selected_window;
1488 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1489 delete_window (window);
1491 run_window_configuration_change_hook (f);
1493 return Qnil;
1496 void
1497 delete_window (window)
1498 register Lisp_Object window;
1500 register Lisp_Object tem, parent, sib;
1501 register struct window *p;
1502 register struct window *par;
1503 struct frame *f;
1505 /* Because this function is called by other C code on non-leaf
1506 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1507 so we can't decode_window here. */
1508 CHECK_WINDOW (window);
1509 p = XWINDOW (window);
1511 /* It's a no-op to delete an already-deleted window. */
1512 if (NILP (p->buffer)
1513 && NILP (p->hchild)
1514 && NILP (p->vchild))
1515 return;
1517 parent = p->parent;
1518 if (NILP (parent))
1519 error ("Attempt to delete minibuffer or sole ordinary window");
1520 par = XWINDOW (parent);
1522 windows_or_buffers_changed++;
1523 Vwindow_list = Qnil;
1524 f = XFRAME (WINDOW_FRAME (p));
1525 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1527 /* Are we trying to delete any frame's selected window? */
1529 Lisp_Object swindow, pwindow;
1531 /* See if the frame's selected window is either WINDOW
1532 or any subwindow of it, by finding all that window's parents
1533 and comparing each one with WINDOW. */
1534 swindow = FRAME_SELECTED_WINDOW (f);
1536 while (1)
1538 pwindow = swindow;
1539 while (!NILP (pwindow))
1541 if (EQ (window, pwindow))
1542 break;
1543 pwindow = XWINDOW (pwindow)->parent;
1546 /* If the window being deleted is not a parent of SWINDOW,
1547 then SWINDOW is ok as the new selected window. */
1548 if (!EQ (window, pwindow))
1549 break;
1550 /* Otherwise, try another window for SWINDOW. */
1551 swindow = Fnext_window (swindow, Qlambda, Qnil);
1553 /* If we get back to the frame's selected window,
1554 it means there was no acceptable alternative,
1555 so we cannot delete. */
1556 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1557 error ("Cannot delete window");
1560 /* If we need to change SWINDOW, do it. */
1561 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1563 /* If we're about to delete the selected window on the
1564 selected frame, then we should use Fselect_window to select
1565 the new window. On the other hand, if we're about to
1566 delete the selected window on any other frame, we shouldn't do
1567 anything but set the frame's selected_window slot. */
1568 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1569 Fselect_window (swindow, Qnil);
1570 else
1571 FRAME_SELECTED_WINDOW (f) = swindow;
1575 /* Now we know we can delete this one. */
1576 window_deletion_count++;
1578 tem = p->buffer;
1579 /* tem is null for dummy parent windows
1580 (which have inferiors but not any contents themselves) */
1581 if (!NILP (tem))
1583 unshow_buffer (p);
1584 unchain_marker (XMARKER (p->pointm));
1585 unchain_marker (XMARKER (p->start));
1588 /* Free window glyph matrices. It is sure that they are allocated
1589 again when ADJUST_GLYPHS is called. Block input so that expose
1590 events and other events that access glyph matrices are not
1591 processed while we are changing them. */
1592 BLOCK_INPUT;
1593 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1595 tem = p->next;
1596 if (!NILP (tem))
1597 XWINDOW (tem)->prev = p->prev;
1599 tem = p->prev;
1600 if (!NILP (tem))
1601 XWINDOW (tem)->next = p->next;
1603 if (EQ (window, par->hchild))
1604 par->hchild = p->next;
1605 if (EQ (window, par->vchild))
1606 par->vchild = p->next;
1608 /* Find one of our siblings to give our space to. */
1609 sib = p->prev;
1610 if (NILP (sib))
1612 /* If p gives its space to its next sibling, that sibling needs
1613 to have its top/left side pulled back to where p's is.
1614 set_window_{height,width} will re-position the sibling's
1615 children. */
1616 sib = p->next;
1617 XWINDOW (sib)->top_line = p->top_line;
1618 XWINDOW (sib)->left_col = p->left_col;
1621 /* Stretch that sibling. */
1622 if (!NILP (par->vchild))
1623 set_window_height (sib,
1624 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1626 if (!NILP (par->hchild))
1627 set_window_width (sib,
1628 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1631 /* If parent now has only one child,
1632 put the child into the parent's place. */
1633 tem = par->hchild;
1634 if (NILP (tem))
1635 tem = par->vchild;
1636 if (NILP (XWINDOW (tem)->next)) {
1637 replace_window (parent, tem);
1638 par = XWINDOW (tem);
1641 /* Since we may be deleting combination windows, we must make sure that
1642 not only p but all its children have been marked as deleted. */
1643 if (! NILP (p->hchild))
1644 delete_all_subwindows (XWINDOW (p->hchild));
1645 else if (! NILP (p->vchild))
1646 delete_all_subwindows (XWINDOW (p->vchild));
1648 /* Mark this window as deleted. */
1649 p->buffer = p->hchild = p->vchild = Qnil;
1651 if (! NILP (par->parent))
1652 par = XWINDOW (par->parent);
1654 /* Check if we have a v/hchild with a v/hchild. In that case remove
1655 one of them. */
1657 if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
1659 p = XWINDOW (par->vchild);
1660 par->vchild = p->vchild;
1661 tem = p->vchild;
1663 else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
1665 p = XWINDOW (par->hchild);
1666 par->hchild = p->hchild;
1667 tem = p->hchild;
1669 else
1670 p = 0;
1672 if (p)
1674 while (! NILP (tem)) {
1675 XWINDOW (tem)->parent = p->parent;
1676 if (NILP (XWINDOW (tem)->next))
1677 break;
1678 tem = XWINDOW (tem)->next;
1680 if (! NILP (tem)) {
1681 /* The next of the v/hchild we are removing is now the next of the
1682 last child for the v/hchild:
1683 Before v/hchild -> v/hchild -> next1 -> next2
1685 -> next3
1686 After: v/hchild -> next1 -> next2 -> next3
1688 XWINDOW (tem)->next = p->next;
1689 if (! NILP (p->next))
1690 XWINDOW (p->next)->prev = tem;
1692 p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
1696 /* Adjust glyph matrices. */
1697 adjust_glyphs (f);
1698 UNBLOCK_INPUT;
1703 /***********************************************************************
1704 Window List
1705 ***********************************************************************/
1707 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1708 pointer. This is a callback function for foreach_window, used in
1709 function window_list. */
1711 static int
1712 add_window_to_list (w, user_data)
1713 struct window *w;
1714 void *user_data;
1716 Lisp_Object *list = (Lisp_Object *) user_data;
1717 Lisp_Object window;
1718 XSETWINDOW (window, w);
1719 *list = Fcons (window, *list);
1720 return 1;
1724 /* Return a list of all windows, for use by next_window. If
1725 Vwindow_list is a list, return that list. Otherwise, build a new
1726 list, cache it in Vwindow_list, and return that. */
1728 static Lisp_Object
1729 window_list ()
1731 if (!CONSP (Vwindow_list))
1733 Lisp_Object tail;
1735 Vwindow_list = Qnil;
1736 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1738 Lisp_Object args[2];
1740 /* We are visiting windows in canonical order, and add
1741 new windows at the front of args[1], which means we
1742 have to reverse this list at the end. */
1743 args[1] = Qnil;
1744 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1745 args[0] = Vwindow_list;
1746 args[1] = Fnreverse (args[1]);
1747 Vwindow_list = Fnconc (2, args);
1751 return Vwindow_list;
1755 /* Value is non-zero if WINDOW satisfies the constraints given by
1756 OWINDOW, MINIBUF and ALL_FRAMES.
1758 MINIBUF t means WINDOW may be minibuffer windows.
1759 `lambda' means WINDOW may not be a minibuffer window.
1760 a window means a specific minibuffer window
1762 ALL_FRAMES t means search all frames,
1763 nil means search just current frame,
1764 `visible' means search just visible frames,
1765 0 means search visible and iconified frames,
1766 a window means search the frame that window belongs to,
1767 a frame means consider windows on that frame, only. */
1769 static int
1770 candidate_window_p (window, owindow, minibuf, all_frames)
1771 Lisp_Object window, owindow, minibuf, all_frames;
1773 struct window *w = XWINDOW (window);
1774 struct frame *f = XFRAME (w->frame);
1775 int candidate_p = 1;
1777 if (!BUFFERP (w->buffer))
1778 candidate_p = 0;
1779 else if (MINI_WINDOW_P (w)
1780 && (EQ (minibuf, Qlambda)
1781 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1783 /* If MINIBUF is `lambda' don't consider any mini-windows.
1784 If it is a window, consider only that one. */
1785 candidate_p = 0;
1787 else if (EQ (all_frames, Qt))
1788 candidate_p = 1;
1789 else if (NILP (all_frames))
1791 xassert (WINDOWP (owindow));
1792 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1794 else if (EQ (all_frames, Qvisible))
1796 FRAME_SAMPLE_VISIBILITY (f);
1797 candidate_p = FRAME_VISIBLE_P (f)
1798 && (FRAME_TERMINAL (XFRAME (w->frame))
1799 == FRAME_TERMINAL (XFRAME (selected_frame)));
1802 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1804 FRAME_SAMPLE_VISIBILITY (f);
1805 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
1806 #ifdef HAVE_X_WINDOWS
1807 /* Yuck!! If we've just created the frame and the
1808 window-manager requested the user to place it
1809 manually, the window may still not be considered
1810 `visible'. I'd argue it should be at least
1811 something like `iconified', but don't know how to do
1812 that yet. --Stef */
1813 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
1814 && !f->output_data.x->has_been_visible)
1815 #endif
1817 && (FRAME_TERMINAL (XFRAME (w->frame))
1818 == FRAME_TERMINAL (XFRAME (selected_frame)));
1820 else if (WINDOWP (all_frames))
1821 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1822 || EQ (XWINDOW (all_frames)->frame, w->frame)
1823 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1824 else if (FRAMEP (all_frames))
1825 candidate_p = EQ (all_frames, w->frame);
1827 return candidate_p;
1831 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1832 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1833 ALL_FRAMES. */
1835 static void
1836 decode_next_window_args (window, minibuf, all_frames)
1837 Lisp_Object *window, *minibuf, *all_frames;
1839 if (NILP (*window))
1840 *window = selected_window;
1841 else
1842 CHECK_LIVE_WINDOW (*window);
1844 /* MINIBUF nil may or may not include minibuffers. Decide if it
1845 does. */
1846 if (NILP (*minibuf))
1847 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1848 else if (!EQ (*minibuf, Qt))
1849 *minibuf = Qlambda;
1851 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1852 => count none of them, or a specific minibuffer window (the
1853 active one) to count. */
1855 /* ALL_FRAMES nil doesn't specify which frames to include. */
1856 if (NILP (*all_frames))
1857 *all_frames = (!EQ (*minibuf, Qlambda)
1858 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1859 : Qnil);
1860 else if (EQ (*all_frames, Qvisible))
1862 else if (EQ (*all_frames, make_number (0)))
1864 else if (FRAMEP (*all_frames))
1866 else if (!EQ (*all_frames, Qt))
1867 *all_frames = Qnil;
1869 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1870 search just current frame, `visible' meaning search just visible
1871 frames, 0 meaning search visible and iconified frames, or a
1872 window, meaning search the frame that window belongs to, or a
1873 frame, meaning consider windows on that frame, only. */
1877 /* Return the next or previous window of WINDOW in canonical ordering
1878 of windows. NEXT_P non-zero means return the next window. See the
1879 documentation string of next-window for the meaning of MINIBUF and
1880 ALL_FRAMES. */
1882 static Lisp_Object
1883 next_window (window, minibuf, all_frames, next_p)
1884 Lisp_Object window, minibuf, all_frames;
1885 int next_p;
1887 decode_next_window_args (&window, &minibuf, &all_frames);
1889 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1890 return the first window on the frame. */
1891 if (FRAMEP (all_frames)
1892 && !EQ (all_frames, XWINDOW (window)->frame))
1893 return Fframe_first_window (all_frames);
1895 if (next_p)
1897 Lisp_Object list;
1899 /* Find WINDOW in the list of all windows. */
1900 list = Fmemq (window, window_list ());
1902 /* Scan forward from WINDOW to the end of the window list. */
1903 if (CONSP (list))
1904 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1905 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1906 break;
1908 /* Scan from the start of the window list up to WINDOW. */
1909 if (!CONSP (list))
1910 for (list = Vwindow_list;
1911 CONSP (list) && !EQ (XCAR (list), window);
1912 list = XCDR (list))
1913 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1914 break;
1916 if (CONSP (list))
1917 window = XCAR (list);
1919 else
1921 Lisp_Object candidate, list;
1923 /* Scan through the list of windows for candidates. If there are
1924 candidate windows in front of WINDOW, the last one of these
1925 is the one we want. If there are candidates following WINDOW
1926 in the list, again the last one of these is the one we want. */
1927 candidate = Qnil;
1928 for (list = window_list (); CONSP (list); list = XCDR (list))
1930 if (EQ (XCAR (list), window))
1932 if (WINDOWP (candidate))
1933 break;
1935 else if (candidate_window_p (XCAR (list), window, minibuf,
1936 all_frames))
1937 candidate = XCAR (list);
1940 if (WINDOWP (candidate))
1941 window = candidate;
1944 return window;
1948 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1949 doc: /* Return next window after WINDOW in canonical ordering of windows.
1950 If omitted, WINDOW defaults to the selected window.
1952 Optional second arg MINIBUF t means count the minibuffer window even
1953 if not active. MINIBUF nil or omitted means count the minibuffer iff
1954 it is active. MINIBUF neither t nor nil means not to count the
1955 minibuffer even if it is active.
1957 Several frames may share a single minibuffer; if the minibuffer
1958 counts, all windows on all frames that share that minibuffer count
1959 too. Therefore, `next-window' can be used to iterate through the
1960 set of windows even when the minibuffer is on another frame. If the
1961 minibuffer does not count, only windows from WINDOW's frame count.
1963 Optional third arg ALL-FRAMES t means include windows on all frames.
1964 ALL-FRAMES nil or omitted means cycle within the frames as specified
1965 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1966 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1967 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1968 Anything else means restrict to WINDOW's frame.
1970 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1971 `next-window' to iterate through the entire cycle of acceptable
1972 windows, eventually ending up back at the window you started with.
1973 `previous-window' traverses the same cycle, in the reverse order. */)
1974 (window, minibuf, all_frames)
1975 Lisp_Object window, minibuf, all_frames;
1977 return next_window (window, minibuf, all_frames, 1);
1981 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1982 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1983 If omitted, WINDOW defaults to the selected window.
1985 Optional second arg MINIBUF t means count the minibuffer window even
1986 if not active. MINIBUF nil or omitted means count the minibuffer iff
1987 it is active. MINIBUF neither t nor nil means not to count the
1988 minibuffer even if it is active.
1990 Several frames may share a single minibuffer; if the minibuffer
1991 counts, all windows on all frames that share that minibuffer count
1992 too. Therefore, `previous-window' can be used to iterate through
1993 the set of windows even when the minibuffer is on another frame. If
1994 the minibuffer does not count, only windows from WINDOW's frame count
1996 Optional third arg ALL-FRAMES t means include windows on all frames.
1997 ALL-FRAMES nil or omitted means cycle within the frames as specified
1998 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1999 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
2000 If ALL-FRAMES is a frame, restrict search to windows on that frame.
2001 Anything else means restrict to WINDOW's frame.
2003 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2004 `previous-window' to iterate through the entire cycle of acceptable
2005 windows, eventually ending up back at the window you started with.
2006 `next-window' traverses the same cycle, in the reverse order. */)
2007 (window, minibuf, all_frames)
2008 Lisp_Object window, minibuf, all_frames;
2010 return next_window (window, minibuf, all_frames, 0);
2014 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
2015 doc: /* Select the ARG'th different window on this frame.
2016 All windows on current frame are arranged in a cyclic order.
2017 This command selects the window ARG steps away in that order.
2018 A negative ARG moves in the opposite order. The optional second
2019 argument ALL-FRAMES has the same meaning as in `next-window', which see. */)
2020 (arg, all_frames)
2021 Lisp_Object arg, all_frames;
2023 Lisp_Object window;
2024 int i;
2026 CHECK_NUMBER (arg);
2027 window = selected_window;
2029 for (i = XINT (arg); i > 0; --i)
2030 window = Fnext_window (window, Qnil, all_frames);
2031 for (; i < 0; ++i)
2032 window = Fprevious_window (window, Qnil, all_frames);
2034 Fselect_window (window, Qnil);
2035 return Qnil;
2039 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2040 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2041 FRAME nil or omitted means use the selected frame.
2042 WINDOW nil or omitted means use the selected window.
2043 MINIBUF t means include the minibuffer window, even if it isn't active.
2044 MINIBUF nil or omitted means include the minibuffer window only
2045 if it's active.
2046 MINIBUF neither nil nor t means never include the minibuffer window. */)
2047 (frame, minibuf, window)
2048 Lisp_Object frame, minibuf, window;
2050 if (NILP (window))
2051 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2052 CHECK_WINDOW (window);
2053 if (NILP (frame))
2054 frame = selected_frame;
2056 if (!EQ (frame, XWINDOW (window)->frame))
2057 error ("Window is on a different frame");
2059 return window_list_1 (window, minibuf, frame);
2063 /* Return a list of windows in canonical ordering. Arguments are like
2064 for `next-window'. */
2066 static Lisp_Object
2067 window_list_1 (window, minibuf, all_frames)
2068 Lisp_Object window, minibuf, all_frames;
2070 Lisp_Object tail, list, rest;
2072 decode_next_window_args (&window, &minibuf, &all_frames);
2073 list = Qnil;
2075 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2076 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2077 list = Fcons (XCAR (tail), list);
2079 /* Rotate the list to start with WINDOW. */
2080 list = Fnreverse (list);
2081 rest = Fmemq (window, list);
2082 if (!NILP (rest) && !EQ (rest, list))
2084 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2086 XSETCDR (tail, Qnil);
2087 list = nconc2 (rest, list);
2089 return list;
2094 /* Look at all windows, performing an operation specified by TYPE
2095 with argument OBJ.
2096 If FRAMES is Qt, look at all frames;
2097 Qnil, look at just the selected frame;
2098 Qvisible, look at visible frames;
2099 a frame, just look at windows on that frame.
2100 If MINI is non-zero, perform the operation on minibuffer windows too. */
2102 enum window_loop
2104 WINDOW_LOOP_UNUSED,
2105 GET_BUFFER_WINDOW, /* Arg is buffer */
2106 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2107 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2108 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2109 GET_LARGEST_WINDOW,
2110 UNSHOW_BUFFER, /* Arg is buffer */
2111 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2112 CHECK_ALL_WINDOWS
2115 static Lisp_Object
2116 window_loop (type, obj, mini, frames)
2117 enum window_loop type;
2118 Lisp_Object obj, frames;
2119 int mini;
2121 Lisp_Object window, windows, best_window, frame_arg;
2122 struct frame *f;
2123 struct gcpro gcpro1;
2125 /* If we're only looping through windows on a particular frame,
2126 frame points to that frame. If we're looping through windows
2127 on all frames, frame is 0. */
2128 if (FRAMEP (frames))
2129 f = XFRAME (frames);
2130 else if (NILP (frames))
2131 f = SELECTED_FRAME ();
2132 else
2133 f = NULL;
2135 if (f)
2136 frame_arg = Qlambda;
2137 else if (EQ (frames, make_number (0)))
2138 frame_arg = frames;
2139 else if (EQ (frames, Qvisible))
2140 frame_arg = frames;
2141 else
2142 frame_arg = Qt;
2144 /* frame_arg is Qlambda to stick to one frame,
2145 Qvisible to consider all visible frames,
2146 or Qt otherwise. */
2148 /* Pick a window to start with. */
2149 if (WINDOWP (obj))
2150 window = obj;
2151 else if (f)
2152 window = FRAME_SELECTED_WINDOW (f);
2153 else
2154 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2156 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2157 GCPRO1 (windows);
2158 best_window = Qnil;
2160 for (; CONSP (windows); windows = XCDR (windows))
2162 struct window *w;
2164 window = XCAR (windows);
2165 w = XWINDOW (window);
2167 /* Note that we do not pay attention here to whether the frame
2168 is visible, since Fwindow_list skips non-visible frames if
2169 that is desired, under the control of frame_arg. */
2170 if (!MINI_WINDOW_P (w)
2171 /* For UNSHOW_BUFFER, we must always consider all windows. */
2172 || type == UNSHOW_BUFFER
2173 || (mini && minibuf_level > 0))
2174 switch (type)
2176 case GET_BUFFER_WINDOW:
2177 if (EQ (w->buffer, obj)
2178 /* Don't find any minibuffer window
2179 except the one that is currently in use. */
2180 && (MINI_WINDOW_P (w)
2181 ? EQ (window, minibuf_window)
2182 : 1))
2184 if (NILP (best_window))
2185 best_window = window;
2186 else if (EQ (window, selected_window))
2187 /* Prefer to return selected-window. */
2188 RETURN_UNGCPRO (window);
2189 else if (EQ (Fwindow_frame (window), selected_frame))
2190 /* Prefer windows on the current frame. */
2191 best_window = window;
2193 break;
2195 case GET_LRU_WINDOW:
2196 /* `obj' is an integer encoding a bitvector.
2197 `obj & 1' means consider only full-width windows.
2198 `obj & 2' means consider also dedicated windows. */
2199 if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
2200 || (!(XINT (obj) & 2) && !NILP (w->dedicated))
2201 /* Minibuffer windows are always ignored. */
2202 || MINI_WINDOW_P (w))
2203 break;
2204 if (NILP (best_window)
2205 || (XFASTINT (XWINDOW (best_window)->use_time)
2206 > XFASTINT (w->use_time)))
2207 best_window = window;
2208 break;
2210 case DELETE_OTHER_WINDOWS:
2211 if (!EQ (window, obj))
2212 Fdelete_window (window);
2213 break;
2215 case DELETE_BUFFER_WINDOWS:
2216 if (EQ (w->buffer, obj))
2218 struct frame *f = XFRAME (WINDOW_FRAME (w));
2220 /* If this window is dedicated, and in a frame of its own,
2221 kill the frame. */
2222 if (EQ (window, FRAME_ROOT_WINDOW (f))
2223 && !NILP (w->dedicated)
2224 && other_visible_frames (f))
2226 /* Skip the other windows on this frame.
2227 There might be one, the minibuffer! */
2228 while (CONSP (XCDR (windows))
2229 && EQ (XWINDOW (XCAR (windows))->frame,
2230 XWINDOW (XCAR (XCDR (windows)))->frame))
2231 windows = XCDR (windows);
2233 /* Now we can safely delete the frame. */
2234 Fdelete_frame (w->frame, Qnil);
2236 else if (NILP (w->parent))
2238 /* If we're deleting the buffer displayed in the
2239 only window on the frame, find a new buffer to
2240 display there. */
2241 Lisp_Object buffer;
2242 buffer = Fother_buffer (obj, Qnil, w->frame);
2243 Fset_window_buffer (window, buffer, Qnil);
2244 if (EQ (window, selected_window))
2245 Fset_buffer (w->buffer);
2247 else
2248 Fdelete_window (window);
2250 break;
2252 case GET_LARGEST_WINDOW:
2253 { /* nil `obj' means to ignore dedicated windows. */
2254 /* Ignore dedicated windows and minibuffers. */
2255 if (MINI_WINDOW_P (w) || (NILP (obj) && !NILP (w->dedicated)))
2256 break;
2258 if (NILP (best_window))
2259 best_window = window;
2260 else
2262 struct window *b = XWINDOW (best_window);
2263 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2264 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2265 best_window = window;
2268 break;
2270 case UNSHOW_BUFFER:
2271 if (EQ (w->buffer, obj))
2273 Lisp_Object buffer;
2274 struct frame *f = XFRAME (w->frame);
2276 /* Find another buffer to show in this window. */
2277 buffer = Fother_buffer (obj, Qnil, w->frame);
2279 /* If this window is dedicated, and in a frame of its own,
2280 kill the frame. */
2281 if (EQ (window, FRAME_ROOT_WINDOW (f))
2282 && !NILP (w->dedicated)
2283 && other_visible_frames (f))
2285 /* Skip the other windows on this frame.
2286 There might be one, the minibuffer! */
2287 while (CONSP (XCDR (windows))
2288 && EQ (XWINDOW (XCAR (windows))->frame,
2289 XWINDOW (XCAR (XCDR (windows)))->frame))
2290 windows = XCDR (windows);
2292 /* Now we can safely delete the frame. */
2293 Fdelete_frame (w->frame, Qnil);
2295 else if (!NILP (w->dedicated) && !NILP (w->parent))
2297 Lisp_Object window;
2298 XSETWINDOW (window, w);
2299 /* If this window is dedicated and not the only window
2300 in its frame, then kill it. */
2301 Fdelete_window (window);
2303 else
2305 /* Otherwise show a different buffer in the window. */
2306 w->dedicated = Qnil;
2307 Fset_window_buffer (window, buffer, Qnil);
2308 if (EQ (window, selected_window))
2309 Fset_buffer (w->buffer);
2312 break;
2314 case REDISPLAY_BUFFER_WINDOWS:
2315 if (EQ (w->buffer, obj))
2317 mark_window_display_accurate (window, 0);
2318 w->update_mode_line = Qt;
2319 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2320 ++update_mode_lines;
2321 best_window = window;
2323 break;
2325 /* Check for a window that has a killed buffer. */
2326 case CHECK_ALL_WINDOWS:
2327 if (! NILP (w->buffer)
2328 && NILP (XBUFFER (w->buffer)->name))
2329 abort ();
2330 break;
2332 case WINDOW_LOOP_UNUSED:
2333 break;
2337 UNGCPRO;
2338 return best_window;
2341 /* Used for debugging. Abort if any window has a dead buffer. */
2343 void
2344 check_all_windows ()
2346 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2349 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
2350 doc: /* Return the window least recently selected or used for display.
2351 \(LRU means Least Recently Used.)
2353 Return a full-width window if possible.
2354 A minibuffer window is never a candidate.
2355 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2356 so if all windows are dedicated, the value is nil.
2357 If optional argument FRAME is `visible', search all visible frames.
2358 If FRAME is 0, search all visible and iconified frames.
2359 If FRAME is t, search all frames.
2360 If FRAME is nil, search only the selected frame.
2361 If FRAME is a frame, search only that frame. */)
2362 (frame, dedicated)
2363 Lisp_Object frame, dedicated;
2365 register Lisp_Object w;
2366 /* First try for a window that is full-width */
2367 w = window_loop (GET_LRU_WINDOW,
2368 NILP (dedicated) ? make_number (1) : make_number (3),
2369 0, frame);
2370 if (!NILP (w) && !EQ (w, selected_window))
2371 return w;
2372 /* If none of them, try the rest */
2373 return window_loop (GET_LRU_WINDOW,
2374 NILP (dedicated) ? make_number (0) : make_number (2),
2375 0, frame);
2378 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
2379 doc: /* Return the largest window in area.
2380 A minibuffer window is never a candidate.
2381 A dedicated window is never a candidate unless DEDICATED is non-nil,
2382 so if all windows are dedicated, the value is nil.
2383 If optional argument FRAME is `visible', search all visible frames.
2384 If FRAME is 0, search all visible and iconified frames.
2385 If FRAME is t, search all frames.
2386 If FRAME is nil, search only the selected frame.
2387 If FRAME is a frame, search only that frame. */)
2388 (frame, dedicated)
2389 Lisp_Object frame, dedicated;
2391 return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
2392 frame);
2395 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2396 doc: /* Return a window currently displaying BUFFER, or nil if none.
2397 BUFFER can be a buffer or a buffer name.
2398 If optional argument FRAME is `visible', search all visible frames.
2399 If optional argument FRAME is 0, search all visible and iconified frames.
2400 If FRAME is t, search all frames.
2401 If FRAME is nil, search only the selected frame.
2402 If FRAME is a frame, search only that frame. */)
2403 (buffer, frame)
2404 Lisp_Object buffer, frame;
2406 buffer = Fget_buffer (buffer);
2407 if (BUFFERP (buffer))
2408 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2409 else
2410 return Qnil;
2413 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2414 0, 1, "",
2415 doc: /* Make WINDOW (or the selected window) fill its frame.
2416 Only the frame WINDOW is on is affected.
2417 This function tries to reduce display jumps
2418 by keeping the text previously visible in WINDOW
2419 in the same place on the frame. Doing this depends on
2420 the value of (window-start WINDOW), so if calling this function
2421 in a program gives strange scrolling, make sure the window-start
2422 value is reasonable when this function is called. */)
2423 (window)
2424 Lisp_Object window;
2426 struct window *w;
2427 int startpos;
2428 int top, new_top;
2430 if (NILP (window))
2431 window = selected_window;
2432 else
2433 CHECK_LIVE_WINDOW (window);
2434 w = XWINDOW (window);
2436 startpos = marker_position (w->start);
2437 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2439 if (MINI_WINDOW_P (w) && top > 0)
2440 error ("Can't expand minibuffer to full frame");
2442 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2444 /* Try to minimize scrolling, by setting the window start to the point
2445 will cause the text at the old window start to be at the same place
2446 on the frame. But don't try to do this if the window start is
2447 outside the visible portion (as might happen when the display is
2448 not current, due to typeahead). */
2449 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2450 if (new_top != top
2451 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2452 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2454 struct position pos;
2455 struct buffer *obuf = current_buffer;
2457 Fset_buffer (w->buffer);
2458 /* This computation used to temporarily move point, but that can
2459 have unwanted side effects due to text properties. */
2460 pos = *vmotion (startpos, -top, w);
2462 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2463 w->window_end_valid = Qnil;
2464 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2465 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2466 : Qnil);
2467 /* We need to do this, so that the window-scroll-functions
2468 get called. */
2469 w->optional_new_start = Qt;
2471 set_buffer_internal (obuf);
2474 return Qnil;
2477 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2478 1, 2, "bDelete windows on (buffer): ",
2479 doc: /* Delete all windows showing BUFFER.
2480 BUFFER must be a buffer or the name of an existing buffer.
2481 Optional second argument FRAME controls which frames are affected.
2482 If optional argument FRAME is `visible', search all visible frames.
2483 If FRAME is 0, search all visible and iconified frames.
2484 If FRAME is nil, search all frames.
2485 If FRAME is t, search only the selected frame.
2486 If FRAME is a frame, search only that frame. */)
2487 (buffer, frame)
2488 Lisp_Object buffer, frame;
2490 /* FRAME uses t and nil to mean the opposite of what window_loop
2491 expects. */
2492 if (NILP (frame))
2493 frame = Qt;
2494 else if (EQ (frame, Qt))
2495 frame = Qnil;
2497 if (!NILP (buffer))
2499 buffer = Fget_buffer (buffer);
2500 CHECK_BUFFER (buffer);
2501 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2504 return Qnil;
2507 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2508 Sreplace_buffer_in_windows,
2509 1, 1, "bReplace buffer in windows: ",
2510 doc: /* Replace BUFFER with some other buffer in all windows showing it.
2511 BUFFER may be a buffer or the name of an existing buffer. */)
2512 (buffer)
2513 Lisp_Object buffer;
2515 if (!NILP (buffer))
2517 buffer = Fget_buffer (buffer);
2518 CHECK_BUFFER (buffer);
2519 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2521 return Qnil;
2524 /* Replace BUFFER with some other buffer in all windows
2525 of all frames, even those on other keyboards. */
2527 void
2528 replace_buffer_in_all_windows (buffer)
2529 Lisp_Object buffer;
2531 #ifdef MULTI_KBOARD
2532 Lisp_Object tail, frame;
2534 /* A single call to window_loop won't do the job
2535 because it only considers frames on the current keyboard.
2536 So loop manually over frames, and handle each one. */
2537 FOR_EACH_FRAME (tail, frame)
2538 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2539 #else
2540 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2541 #endif
2544 /* Set the height of WINDOW and all its inferiors. */
2546 /* The smallest acceptable dimensions for a window. Anything smaller
2547 might crash Emacs. */
2549 #define MIN_SAFE_WINDOW_WIDTH (2)
2550 #define MIN_SAFE_WINDOW_HEIGHT (1)
2552 /* For wp non-zero the total number of columns of window w. Otherwise
2553 the total number of lines of w. */
2555 #define WINDOW_TOTAL_SIZE(w, wp) \
2556 (wp ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
2558 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2559 minimum allowable size. */
2561 void
2562 check_frame_size (frame, rows, cols)
2563 FRAME_PTR frame;
2564 int *rows, *cols;
2566 /* For height, we have to see:
2567 how many windows the frame has at minimum (one or two),
2568 and whether it has a menu bar or other special stuff at the top. */
2569 int min_height
2570 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2571 ? MIN_SAFE_WINDOW_HEIGHT
2572 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2574 if (FRAME_TOP_MARGIN (frame) > 0)
2575 min_height += FRAME_TOP_MARGIN (frame);
2577 if (*rows < min_height)
2578 *rows = min_height;
2579 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2580 *cols = MIN_SAFE_WINDOW_WIDTH;
2583 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2584 check if W's width can be changed, otherwise check W's height.
2585 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2586 siblings, too. If none of the siblings is resizable, WINDOW isn't
2587 either. */
2589 static int
2590 window_fixed_size_p (w, width_p, check_siblings_p)
2591 struct window *w;
2592 int width_p, check_siblings_p;
2594 int fixed_p;
2595 struct window *c;
2597 if (!NILP (w->hchild))
2599 c = XWINDOW (w->hchild);
2601 if (width_p)
2603 /* A horizontal combination is fixed-width if all of if its
2604 children are. */
2605 while (c && window_fixed_size_p (c, width_p, 0))
2606 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2607 fixed_p = c == NULL;
2609 else
2611 /* A horizontal combination is fixed-height if one of if its
2612 children is. */
2613 while (c && !window_fixed_size_p (c, width_p, 0))
2614 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2615 fixed_p = c != NULL;
2618 else if (!NILP (w->vchild))
2620 c = XWINDOW (w->vchild);
2622 if (width_p)
2624 /* A vertical combination is fixed-width if one of if its
2625 children is. */
2626 while (c && !window_fixed_size_p (c, width_p, 0))
2627 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2628 fixed_p = c != NULL;
2630 else
2632 /* A vertical combination is fixed-height if all of if its
2633 children are. */
2634 while (c && window_fixed_size_p (c, width_p, 0))
2635 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2636 fixed_p = c == NULL;
2639 else if (BUFFERP (w->buffer))
2641 struct buffer *old = current_buffer;
2642 Lisp_Object val;
2644 current_buffer = XBUFFER (w->buffer);
2645 val = find_symbol_value (Qwindow_size_fixed);
2646 current_buffer = old;
2648 fixed_p = 0;
2649 if (!EQ (val, Qunbound))
2651 fixed_p = !NILP (val);
2653 if (fixed_p
2654 && ((EQ (val, Qheight) && width_p)
2655 || (EQ (val, Qwidth) && !width_p)))
2656 fixed_p = 0;
2659 /* Can't tell if this one is resizable without looking at
2660 siblings. If all siblings are fixed-size this one is too. */
2661 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2663 Lisp_Object child;
2665 for (child = w->prev; WINDOWP (child); child = XWINDOW (child)->prev)
2666 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2667 break;
2669 if (NILP (child))
2670 for (child = w->next; WINDOWP (child); child = XWINDOW (child)->next)
2671 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2672 break;
2674 if (NILP (child))
2675 fixed_p = 1;
2678 else
2679 fixed_p = 1;
2681 return fixed_p;
2684 /* Return minimum size of leaf window W. WIDTH_P non-zero means return
2685 the minimum width of W, WIDTH_P zero means return the minimum height
2686 of W. SAFE_P non-zero means ignore window-min-height|width but just
2687 return values that won't crash Emacs and don't hide components like
2688 fringes, scrollbars, or modelines. If WIDTH_P is zero and W is the
2689 minibuffer window, always return 1. */
2691 static int
2692 window_min_size_2 (w, width_p, safe_p)
2693 struct window *w;
2694 int width_p, safe_p;
2696 /* We should consider buffer-local values of window_min_height and
2697 window_min_width here. */
2698 if (width_p)
2700 int safe_size = (MIN_SAFE_WINDOW_WIDTH
2701 + WINDOW_FRINGE_COLS (w)
2702 + WINDOW_SCROLL_BAR_COLS (w));
2704 return safe_p ? safe_size : max (window_min_width, safe_size);
2706 else if (MINI_WINDOW_P (w))
2707 return 1;
2708 else
2710 int safe_size = (MIN_SAFE_WINDOW_HEIGHT
2711 + ((BUFFERP (w->buffer)
2712 && !NILP (XBUFFER (w->buffer)->mode_line_format))
2713 ? 1 : 0));
2715 return safe_p ? safe_size : max (window_min_height, safe_size);
2719 /* Return minimum size of window W, not taking fixed-width windows into
2720 account. WIDTH_P non-zero means return the minimum width, otherwise
2721 return the minimum height. SAFE_P non-zero means ignore
2722 window-min-height|width but just return values that won't crash Emacs
2723 and don't hide components like fringes, scrollbars, or modelines. If
2724 W is a combination window, compute the minimum size from the minimum
2725 sizes of W's children. */
2727 static int
2728 window_min_size_1 (w, width_p, safe_p)
2729 struct window *w;
2730 int width_p, safe_p;
2732 struct window *c;
2733 int size;
2735 if (!NILP (w->hchild))
2737 /* W is a horizontal combination. */
2738 c = XWINDOW (w->hchild);
2739 size = 0;
2741 if (width_p)
2743 /* The minimum width of a horizontal combination is the sum of
2744 the minimum widths of its children. */
2745 while (c)
2747 size += window_min_size_1 (c, 1, safe_p);
2748 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2751 else
2753 /* The minimum height of a horizontal combination is the
2754 maximum of the minimum heights of its children. */
2755 while (c)
2757 size = max (window_min_size_1 (c, 0, safe_p), size);
2758 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2762 else if (!NILP (w->vchild))
2764 /* W is a vertical combination. */
2765 c = XWINDOW (w->vchild);
2766 size = 0;
2768 if (width_p)
2770 /* The minimum width of a vertical combination is the maximum
2771 of the minimum widths of its children. */
2772 while (c)
2774 size = max (window_min_size_1 (c, 1, safe_p), size);
2775 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2778 else
2780 /* The minimum height of a vertical combination is the sum of
2781 the minimum height of its children. */
2782 while (c)
2784 size += window_min_size_1 (c, 0, safe_p);
2785 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2789 else
2790 /* W is a leaf window. */
2791 size = window_min_size_2 (w, width_p, safe_p);
2793 return size;
2796 /* Return the minimum size of window W, taking fixed-size windows into
2797 account. WIDTH_P non-zero means return the minimum width, otherwise
2798 return the minimum height. SAFE_P non-zero means ignore
2799 window-min-height|width but just return values that won't crash Emacs
2800 and don't hide components like fringes, scrollbars, or modelines.
2801 IGNORE_FIXED_P non-zero means ignore if W is fixed-size. Set *FIXED
2802 to 1 if W is fixed-size unless FIXED is null. */
2804 static int
2805 window_min_size (w, width_p, safe_p, ignore_fixed_p, fixed)
2806 struct window *w;
2807 int width_p, safe_p, ignore_fixed_p, *fixed;
2809 int size, fixed_p;
2811 if (ignore_fixed_p)
2812 fixed_p = 0;
2813 else
2814 fixed_p = window_fixed_size_p (w, width_p, 1);
2816 if (fixed)
2817 *fixed = fixed_p;
2819 if (fixed_p)
2820 size = WINDOW_TOTAL_SIZE (w, width_p);
2821 else
2822 size = window_min_size_1 (w, width_p, safe_p);
2824 return size;
2828 /* Adjust the margins of window W if text area is too small.
2829 Return 1 if window width is ok after adjustment; 0 if window
2830 is still too narrow. */
2832 static int
2833 adjust_window_margins (w)
2834 struct window *w;
2836 int box_cols = (WINDOW_TOTAL_COLS (w)
2837 - WINDOW_FRINGE_COLS (w)
2838 - WINDOW_SCROLL_BAR_COLS (w));
2839 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2840 + WINDOW_RIGHT_MARGIN_COLS (w));
2842 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2843 return 1;
2845 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2846 return 0;
2848 /* Window's text area is too narrow, but reducing the window
2849 margins will fix that. */
2850 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2851 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2853 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2854 w->left_margin_cols = w->right_margin_cols
2855 = make_number (margin_cols/2);
2856 else
2857 w->right_margin_cols = make_number (margin_cols);
2859 else
2860 w->left_margin_cols = make_number (margin_cols);
2861 return 1;
2864 /* Calculate new sizes for windows in the list FORWARD when their
2865 compound size goes from TOTAL to SIZE. TOTAL must be greater than
2866 SIZE. The number of windows in FORWARD is NCHILDREN, and the number
2867 that can shrink is SHRINKABLE. Fixed-size windows may be shrunk if
2868 and only if RESIZE_FIXED_P is non-zero. WIDTH_P non-zero means
2869 shrink columns, otherwise shrink lines.
2871 SAFE_P zero means windows may be sized down to window-min-height
2872 lines (window-min-window columns for WIDTH_P non-zero). SAFE_P
2873 non-zero means windows may be sized down to their minimum safe sizes
2874 taking into account the space needed to display modelines, fringes,
2875 and scrollbars.
2877 This function returns an allocated array of new sizes that the caller
2878 must free. A size -1 means the window is fixed and RESIZE_FIXED_P is
2879 zero. A size zero means the window shall be deleted. Array index 0
2880 refers to the first window in FORWARD, 1 to the second, and so on.
2882 This function resizes windows proportionally to their size. It also
2883 tries to preserve smaller windows by resizing larger windows before
2884 resizing any window to zero. If resize_proportionally is non-nil for
2885 a specific window, it will attempt to strictly resize that window
2886 proportionally, even at the expense of deleting smaller windows. */
2887 static int *
2888 shrink_windows (total, size, nchildren, shrinkable, resize_fixed_p,
2889 forward, width_p, safe_p)
2890 int total, size, nchildren, shrinkable;
2891 int resize_fixed_p, width_p, safe_p;
2892 Lisp_Object forward;
2894 int available_resize = 0;
2895 int *new_sizes, *min_sizes;
2896 struct window *c;
2897 Lisp_Object child;
2898 int smallest = total;
2899 int total_removed = 0;
2900 int total_shrink = total - size;
2901 int i;
2903 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2904 min_sizes = xmalloc (sizeof (*min_sizes) * nchildren);
2906 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2908 int child_size;
2910 c = XWINDOW (child);
2911 child_size = WINDOW_TOTAL_SIZE (c, width_p);
2913 if (!resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2914 new_sizes[i] = -1;
2915 else
2917 new_sizes[i] = child_size;
2918 min_sizes[i] = window_min_size_1 (c, width_p, safe_p);
2919 if (child_size > min_sizes[i]
2920 && NILP (c->resize_proportionally))
2921 available_resize += child_size - min_sizes[i];
2924 /* We might need to shrink some windows to zero. Find the smallest
2925 windows and set them to 0 until we can fulfil the new size. */
2927 while (shrinkable > 1 && size + available_resize < total)
2929 for (i = 0; i < nchildren; ++i)
2930 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2931 smallest = new_sizes[i];
2933 for (i = 0; i < nchildren; ++i)
2934 if (new_sizes[i] == smallest)
2936 /* Resize this window down to zero. */
2937 new_sizes[i] = 0;
2938 if (smallest > min_sizes[i])
2939 available_resize -= smallest - min_sizes[i];
2940 available_resize += smallest;
2941 --shrinkable;
2942 total_removed += smallest;
2944 /* We don't know what the smallest is now. */
2945 smallest = total;
2947 /* Out of for, just remove one window at the time and
2948 check again if we have enough space. */
2949 break;
2953 /* Now, calculate the new sizes. Try to shrink each window
2954 proportional to its size. */
2955 for (i = 0; i < nchildren; ++i)
2957 if (new_sizes[i] > min_sizes[i])
2959 int to_shrink = total_shrink * new_sizes[i] / total;
2961 if (new_sizes[i] - to_shrink < min_sizes[i])
2962 to_shrink = new_sizes[i] - min_sizes[i];
2963 new_sizes[i] -= to_shrink;
2964 total_removed += to_shrink;
2968 /* Any reminder due to rounding, we just subtract from windows
2969 that are left and still can be shrunk. */
2970 while (total_shrink > total_removed)
2972 int nonzero_sizes = 0;
2973 int nonzero_idx = -1;
2975 for (i = 0; i < nchildren; ++i)
2976 if (new_sizes[i] > 0)
2978 ++nonzero_sizes;
2979 nonzero_idx = i;
2982 for (i = 0; i < nchildren; ++i)
2983 if (new_sizes[i] > min_sizes[i])
2985 --new_sizes[i];
2986 ++total_removed;
2988 /* Out of for, just shrink one window at the time and
2989 check again if we have enough space. */
2990 break;
2993 /* Special case, only one window left. */
2994 if (nonzero_sizes == 1)
2995 break;
2998 /* Any surplus due to rounding, we add to windows that are left. */
2999 while (total_shrink < total_removed)
3001 for (i = 0; i < nchildren; ++i)
3003 if (new_sizes[i] != 0 && total_shrink < total_removed)
3005 ++new_sizes[i];
3006 --total_removed;
3007 break;
3012 xfree (min_sizes);
3014 return new_sizes;
3017 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
3018 WINDOW's width. Resize WINDOW's children, if any, so that they keep
3019 their proportionate size relative to WINDOW.
3021 If FIRST_ONLY is 1, change only the first of WINDOW's children when
3022 they are in series. If LAST_ONLY is 1, change only the last of
3023 WINDOW's children when they are in series.
3025 Propagate WINDOW's top or left edge position to children. Delete
3026 windows that become too small unless NODELETE_P is 1. When
3027 NODELETE_P equals 2 do not honor settings for window-min-height and
3028 window-min-width when resizing windows but use safe defaults instead.
3029 This should give better behavior when resizing frames. */
3031 static void
3032 size_window (window, size, width_p, nodelete_p, first_only, last_only)
3033 Lisp_Object window;
3034 int size, width_p, nodelete_p;
3035 int first_only, last_only;
3037 struct window *w = XWINDOW (window);
3038 struct window *c;
3039 Lisp_Object child, *forward, *sideward;
3040 int old_size = WINDOW_TOTAL_SIZE (w, width_p);
3042 size = max (0, size);
3044 /* Delete WINDOW if it's too small. */
3045 if (nodelete_p != 1 && !NILP (w->parent)
3046 && size < window_min_size_1 (w, width_p, nodelete_p == 2))
3048 delete_window (window);
3049 return;
3052 /* Set redisplay hints. */
3053 w->last_modified = make_number (0);
3054 w->last_overlay_modified = make_number (0);
3055 windows_or_buffers_changed++;
3056 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
3058 if (width_p)
3060 sideward = &w->vchild;
3061 forward = &w->hchild;
3062 w->total_cols = make_number (size);
3063 adjust_window_margins (w);
3065 else
3067 sideward = &w->hchild;
3068 forward = &w->vchild;
3069 w->total_lines = make_number (size);
3070 w->orig_total_lines = Qnil;
3073 if (!NILP (*sideward))
3075 /* We have a chain of parallel siblings whose size should all change. */
3076 for (child = *sideward; !NILP (child); child = c->next)
3078 c = XWINDOW (child);
3079 if (width_p)
3080 c->left_col = w->left_col;
3081 else
3082 c->top_line = w->top_line;
3083 size_window (child, size, width_p, nodelete_p,
3084 first_only, last_only);
3087 else if (!NILP (*forward) && last_only)
3089 /* Change the last in a series of siblings. */
3090 Lisp_Object last_child;
3091 int child_size;
3093 for (child = *forward; !NILP (child); child = c->next)
3095 c = XWINDOW (child);
3096 last_child = child;
3099 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3100 size_window (last_child, size - old_size + child_size,
3101 width_p, nodelete_p, first_only, last_only);
3103 else if (!NILP (*forward) && first_only)
3105 /* Change the first in a series of siblings. */
3106 int child_size;
3108 child = *forward;
3109 c = XWINDOW (child);
3111 if (width_p)
3112 c->left_col = w->left_col;
3113 else
3114 c->top_line = w->top_line;
3116 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3117 size_window (child, size - old_size + child_size,
3118 width_p, nodelete_p, first_only, last_only);
3120 else if (!NILP (*forward))
3122 int fixed_size, each, extra, n;
3123 int resize_fixed_p, nfixed;
3124 int last_pos, first_pos, nchildren, total;
3125 int *new_sizes = NULL;
3127 /* Determine the fixed-size portion of this window, and the
3128 number of child windows. */
3129 fixed_size = nchildren = nfixed = total = 0;
3130 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
3132 int child_size;
3134 c = XWINDOW (child);
3135 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3136 total += child_size;
3138 if (window_fixed_size_p (c, width_p, 0))
3140 fixed_size += child_size;
3141 ++nfixed;
3145 /* If the new size is smaller than fixed_size, or if there
3146 aren't any resizable windows, allow resizing fixed-size
3147 windows. */
3148 resize_fixed_p = nfixed == nchildren || size < fixed_size;
3150 /* Compute how many lines/columns to add/remove to each child. The
3151 value of extra takes care of rounding errors. */
3152 n = resize_fixed_p ? nchildren : nchildren - nfixed;
3153 if (size < total && n > 1)
3154 new_sizes = shrink_windows (total, size, nchildren, n,
3155 resize_fixed_p, *forward, width_p,
3156 nodelete_p == 2);
3157 else
3159 each = (size - total) / n;
3160 extra = (size - total) - n * each;
3163 /* Compute new children heights and edge positions. */
3164 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
3165 last_pos = first_pos;
3166 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
3168 int new_size, old_size;
3170 c = XWINDOW (child);
3171 old_size = WINDOW_TOTAL_SIZE (c, width_p);
3172 new_size = old_size;
3174 /* The top or left edge position of this child equals the
3175 bottom or right edge of its predecessor. */
3176 if (width_p)
3177 c->left_col = make_number (last_pos);
3178 else
3179 c->top_line = make_number (last_pos);
3181 /* If this child can be resized, do it. */
3182 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
3184 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
3185 extra = 0;
3188 /* Set new size. Note that size_window also propagates
3189 edge positions to children, so it's not a no-op if we
3190 didn't change the child's size. */
3191 size_window (child, new_size, width_p, 1, first_only, last_only);
3193 /* Remember the bottom/right edge position of this child; it
3194 will be used to set the top/left edge of the next child. */
3195 last_pos += new_size;
3198 if (new_sizes) xfree (new_sizes);
3200 /* We should have covered the parent exactly with child windows. */
3201 xassert (size == last_pos - first_pos);
3203 /* Now delete any children that became too small. */
3204 if (nodelete_p != 1)
3205 for (child = *forward; !NILP (child); child = c->next)
3207 int child_size;
3209 c = XWINDOW (child);
3210 child_size = WINDOW_TOTAL_SIZE (c, width_p);
3211 size_window (child, child_size, width_p, nodelete_p,
3212 first_only, last_only);
3217 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3218 WINDOW's children. NODELETE zero means windows that have become
3219 smaller than window-min-height in the process may be deleted.
3220 NODELETE 1 means never delete windows that become too small in the
3221 process. (The caller should check later and do so if appropriate.)
3222 NODELETE 2 means delete only windows that have become too small to be
3223 displayed correctly. */
3225 void
3226 set_window_height (window, height, nodelete)
3227 Lisp_Object window;
3228 int height;
3229 int nodelete;
3231 size_window (window, height, 0, nodelete, 0, 0);
3234 /* Set WINDOW's width to WIDTH, and recursively change the width of
3235 WINDOW's children. NODELETE zero means windows that have become
3236 smaller than window-min-width in the process may be deleted.
3237 NODELETE 1 means never delete windows that become too small in the
3238 process. (The caller should check later and do so if appropriate.)
3239 NODELETE 2 means delete only windows that have become too small to be
3240 displayed correctly. */
3242 void
3243 set_window_width (window, width, nodelete)
3244 Lisp_Object window;
3245 int width;
3246 int nodelete;
3248 size_window (window, width, 1, nodelete, 0, 0);
3251 /* Change window heights in windows rooted in WINDOW by N lines. */
3253 void
3254 change_window_heights (window, n)
3255 Lisp_Object window;
3256 int n;
3258 struct window *w = XWINDOW (window);
3260 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
3261 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
3263 if (INTEGERP (w->orig_top_line))
3264 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
3265 if (INTEGERP (w->orig_total_lines))
3266 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
3268 /* Handle just the top child in a vertical split. */
3269 if (!NILP (w->vchild))
3270 change_window_heights (w->vchild, n);
3272 /* Adjust all children in a horizontal split. */
3273 for (window = w->hchild; !NILP (window); window = w->next)
3275 w = XWINDOW (window);
3276 change_window_heights (window, n);
3281 int window_select_count;
3283 Lisp_Object
3284 Fset_window_buffer_unwind (obuf)
3285 Lisp_Object obuf;
3287 Fset_buffer (obuf);
3288 return Qnil;
3291 EXFUN (Fset_window_fringes, 4);
3292 EXFUN (Fset_window_scroll_bars, 4);
3294 static void
3295 run_funs (Lisp_Object funs)
3297 for (; CONSP (funs); funs = XCDR (funs))
3298 if (!EQ (XCAR (funs), Qt))
3299 call0 (XCAR (funs));
3302 static Lisp_Object select_window_norecord (Lisp_Object window);
3304 void
3305 run_window_configuration_change_hook (struct frame *f)
3307 int count = SPECPDL_INDEX ();
3308 Lisp_Object frame, global_wcch
3309 = Fdefault_value (Qwindow_configuration_change_hook);
3310 XSETFRAME (frame, f);
3312 if (NILP (Vrun_hooks))
3313 return;
3315 if (SELECTED_FRAME () != f)
3317 record_unwind_protect (Fselect_frame, Fselected_frame ());
3318 Fselect_frame (frame);
3321 /* Use the right buffer. Matters when running the local hooks. */
3322 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3324 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
3325 Fset_buffer (Fwindow_buffer (Qnil));
3328 /* Look for buffer-local values. */
3330 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3331 for (; CONSP (windows); windows = XCDR (windows))
3333 Lisp_Object window = XCAR (windows);
3334 Lisp_Object buffer = Fwindow_buffer (window);
3335 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3336 buffer)))
3338 int count = SPECPDL_INDEX ();
3339 record_unwind_protect (select_window_norecord, Fselected_window ());
3340 select_window_norecord (window);
3341 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3342 buffer));
3343 unbind_to (count, Qnil);
3348 run_funs (global_wcch);
3349 unbind_to (count, Qnil);
3352 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3353 means it's allowed to run hooks. See make_frame for a case where
3354 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3355 margins, fringes, and scroll-bar settings of the window are not
3356 reset from the buffer's local settings. */
3358 void
3359 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
3360 Lisp_Object window, buffer;
3361 int run_hooks_p, keep_margins_p;
3363 struct window *w = XWINDOW (window);
3364 struct buffer *b = XBUFFER (buffer);
3365 int count = SPECPDL_INDEX ();
3366 int samebuf = EQ (buffer, w->buffer);
3368 w->buffer = buffer;
3370 if (EQ (window, selected_window))
3371 b->last_selected_window = window;
3373 /* Let redisplay errors through. */
3374 b->display_error_modiff = 0;
3376 /* Update time stamps of buffer display. */
3377 if (INTEGERP (b->display_count))
3378 XSETINT (b->display_count, XINT (b->display_count) + 1);
3379 b->display_time = Fcurrent_time ();
3381 XSETFASTINT (w->window_end_pos, 0);
3382 XSETFASTINT (w->window_end_vpos, 0);
3383 bzero (&w->last_cursor, sizeof w->last_cursor);
3384 w->window_end_valid = Qnil;
3385 if (!(keep_margins_p && samebuf))
3386 { /* If we're not actually changing the buffer, Don't reset hscroll and
3387 vscroll. This case happens for example when called from
3388 change_frame_size_1, where we use a dummy call to
3389 Fset_window_buffer on the frame's selected window (and no other)
3390 just in order to run window-configuration-change-hook.
3391 Resetting hscroll and vscroll here is problematic for things like
3392 image-mode and doc-view-mode since it resets the image's position
3393 whenever we resize the frame. */
3394 w->hscroll = w->min_hscroll = make_number (0);
3395 w->vscroll = 0;
3396 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3397 set_marker_restricted (w->start,
3398 make_number (b->last_window_start),
3399 buffer);
3400 w->start_at_line_beg = Qnil;
3401 w->force_start = Qnil;
3402 XSETFASTINT (w->last_modified, 0);
3403 XSETFASTINT (w->last_overlay_modified, 0);
3405 /* Maybe we could move this into the `if' but it's not obviously safe and
3406 I doubt it's worth the trouble. */
3407 windows_or_buffers_changed++;
3409 /* We must select BUFFER for running the window-scroll-functions.
3410 If WINDOW is selected, switch permanently.
3411 Otherwise, switch but go back to the ambient buffer afterward. */
3412 if (EQ (window, selected_window))
3413 Fset_buffer (buffer);
3414 /* We can't check ! NILP (Vwindow_scroll_functions) here
3415 because that might itself be a local variable. */
3416 else if (window_initialized)
3418 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
3419 Fset_buffer (buffer);
3422 if (!keep_margins_p)
3424 /* Set left and right marginal area width etc. from buffer. */
3426 /* This may call adjust_window_margins three times, so
3427 temporarily disable window margins. */
3428 Lisp_Object save_left = w->left_margin_cols;
3429 Lisp_Object save_right = w->right_margin_cols;
3431 w->left_margin_cols = w->right_margin_cols = Qnil;
3433 Fset_window_fringes (window,
3434 b->left_fringe_width, b->right_fringe_width,
3435 b->fringes_outside_margins);
3437 Fset_window_scroll_bars (window,
3438 b->scroll_bar_width,
3439 b->vertical_scroll_bar_type, Qnil);
3441 w->left_margin_cols = save_left;
3442 w->right_margin_cols = save_right;
3444 Fset_window_margins (window,
3445 b->left_margin_cols, b->right_margin_cols);
3448 if (run_hooks_p)
3450 if (! NILP (Vwindow_scroll_functions))
3451 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3452 Fmarker_position (w->start));
3453 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3456 unbind_to (count, Qnil);
3460 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3461 doc: /* Make WINDOW display BUFFER as its contents.
3462 BUFFER can be a buffer or the name of an existing buffer.
3463 Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
3464 display margins, fringe widths, and scroll bar settings are maintained;
3465 the default is to reset these from BUFFER's local settings or the frame
3466 defaults.
3468 This function runs the hook `window-scroll-functions'. */)
3469 (window, buffer, keep_margins)
3470 register Lisp_Object window, buffer, keep_margins;
3472 register Lisp_Object tem;
3473 register struct window *w = decode_window (window);
3475 XSETWINDOW (window, w);
3476 buffer = Fget_buffer (buffer);
3477 CHECK_BUFFER (buffer);
3479 if (NILP (XBUFFER (buffer)->name))
3480 error ("Attempt to display deleted buffer");
3482 tem = w->buffer;
3483 if (NILP (tem))
3484 error ("Window is deleted");
3485 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3486 is first being set up. */
3488 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3489 error ("Window is dedicated to `%s'",
3490 SDATA (XBUFFER (tem)->name));
3492 unshow_buffer (w);
3495 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3496 return Qnil;
3499 /* Note that selected_window can be nil
3500 when this is called from Fset_window_configuration. */
3502 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3503 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3504 If WINDOW is not already selected, make WINDOW's buffer current
3505 and make WINDOW the frame's selected window. Return WINDOW.
3506 Optional second arg NORECORD non-nil means
3507 do not put this buffer at the front of the list of recently selected ones.
3509 Note that the main editor command loop
3510 selects the buffer of the selected window before each command. */)
3511 (window, norecord)
3512 register Lisp_Object window, norecord;
3514 register struct window *w;
3515 register struct window *ow;
3516 struct frame *sf;
3518 CHECK_LIVE_WINDOW (window);
3520 w = XWINDOW (window);
3521 w->frozen_window_start_p = 0;
3523 ++window_select_count;
3524 XSETFASTINT (w->use_time, window_select_count);
3525 if (EQ (window, selected_window))
3526 return window;
3528 sf = SELECTED_FRAME ();
3529 if (XFRAME (WINDOW_FRAME (w)) != sf)
3531 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3532 /* Use this rather than Fhandle_switch_frame
3533 so that FRAME_FOCUS_FRAME is moved appropriately as we
3534 move around in the state where a minibuffer in a separate
3535 frame is active. */
3536 Fselect_frame (WINDOW_FRAME (w));
3537 /* Fselect_frame called us back so we've done all the work already. */
3538 eassert (EQ (window, selected_window));
3539 return window;
3541 else
3542 sf->selected_window = window;
3544 /* Store the current buffer's actual point into the
3545 old selected window. It belongs to that window,
3546 and when the window is not selected, must be in the window. */
3547 if (!NILP (selected_window))
3549 ow = XWINDOW (selected_window);
3550 if (! NILP (ow->buffer))
3551 set_marker_both (ow->pointm, ow->buffer,
3552 BUF_PT (XBUFFER (ow->buffer)),
3553 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3556 selected_window = window;
3558 if (NILP (norecord))
3559 record_buffer (w->buffer);
3560 Fset_buffer (w->buffer);
3562 XBUFFER (w->buffer)->last_selected_window = window;
3564 /* Go to the point recorded in the window.
3565 This is important when the buffer is in more
3566 than one window. It also matters when
3567 redisplay_window has altered point after scrolling,
3568 because it makes the change only in the window. */
3570 register int new_point = marker_position (w->pointm);
3571 if (new_point < BEGV)
3572 SET_PT (BEGV);
3573 else if (new_point > ZV)
3574 SET_PT (ZV);
3575 else
3576 SET_PT (new_point);
3579 windows_or_buffers_changed++;
3580 return window;
3583 static Lisp_Object
3584 select_window_norecord (window)
3585 Lisp_Object window;
3587 return Fselect_window (window, Qt);
3590 /* Deiconify the frame containing the window WINDOW,
3591 unless it is the selected frame;
3592 then return WINDOW.
3594 The reason for the exception for the selected frame
3595 is that it seems better not to change the selected frames visibility
3596 merely because of displaying a different buffer in it.
3597 The deiconification is useful when a buffer gets shown in
3598 another frame that you were not using lately. */
3600 static Lisp_Object
3601 display_buffer_1 (window)
3602 Lisp_Object window;
3604 Lisp_Object frame = XWINDOW (window)->frame;
3605 FRAME_PTR f = XFRAME (frame);
3607 FRAME_SAMPLE_VISIBILITY (f);
3609 if (EQ (frame, selected_frame))
3610 ; /* Assume the selected frame is already visible enough. */
3611 else if (minibuf_level > 0
3612 && MINI_WINDOW_P (XWINDOW (selected_window))
3613 && WINDOW_LIVE_P (minibuf_selected_window)
3614 && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
3615 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3616 else
3618 if (FRAME_ICONIFIED_P (f))
3619 Fmake_frame_visible (frame);
3620 else if (FRAME_VISIBLE_P (f))
3621 Fraise_frame (frame);
3624 return window;
3627 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
3628 doc: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
3629 If the value is t, `display-buffer' or `pop-to-buffer' would create a
3630 special frame for that buffer using the default frame parameters.
3632 If the value is a list, it is a list of frame parameters that would be used
3633 to make a frame for that buffer.
3634 The variables `special-display-buffer-names'
3635 and `special-display-regexps' control this. */)
3636 (buffer_name)
3637 Lisp_Object buffer_name;
3639 Lisp_Object tem;
3641 CHECK_STRING (buffer_name);
3643 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
3644 if (!NILP (tem))
3645 return Qt;
3647 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
3648 if (!NILP (tem))
3649 return XCDR (tem);
3651 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
3653 Lisp_Object car = XCAR (tem);
3654 if (STRINGP (car)
3655 && fast_string_match (car, buffer_name) >= 0)
3656 return Qt;
3657 else if (CONSP (car)
3658 && STRINGP (XCAR (car))
3659 && fast_string_match (XCAR (car), buffer_name) >= 0)
3660 return XCDR (car);
3662 return Qnil;
3665 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
3666 doc: /* Returns non-nil if a buffer named BUFFER-NAME would use the same window.
3667 More precisely, if `display-buffer' or `pop-to-buffer' would display
3668 that buffer in the selected window rather than (as usual) in some other window.
3669 See `same-window-buffer-names' and `same-window-regexps'. */)
3670 (buffer_name)
3671 Lisp_Object buffer_name;
3673 Lisp_Object tem;
3675 CHECK_STRING (buffer_name);
3677 tem = Fmember (buffer_name, Vsame_window_buffer_names);
3678 if (!NILP (tem))
3679 return Qt;
3681 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
3682 if (!NILP (tem))
3683 return Qt;
3685 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3687 Lisp_Object car = XCAR (tem);
3688 if (STRINGP (car)
3689 && fast_string_match (car, buffer_name) >= 0)
3690 return Qt;
3691 else if (CONSP (car)
3692 && STRINGP (XCAR (car))
3693 && fast_string_match (XCAR (car), buffer_name) >= 0)
3694 return Qt;
3696 return Qnil;
3699 /* Use B so the default is (other-buffer). */
3700 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
3701 "BDisplay buffer: \nP",
3702 doc: /* Make BUFFER appear in some window but don't select it.
3703 BUFFER must be the name of an existing buffer, or, when called from Lisp,
3704 a buffer.
3705 If BUFFER is shown already in some window, just use that one,
3706 unless the window is the selected window and the optional second
3707 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3708 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3709 Returns the window displaying BUFFER.
3710 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3711 displaying BUFFER, then simply raise that frame.
3713 The variables `special-display-buffer-names',
3714 `special-display-regexps', `same-window-buffer-names', and
3715 `same-window-regexps' customize how certain buffer names are handled.
3716 The latter two take effect only if NOT-THIS-WINDOW is nil.
3718 If optional argument FRAME is `visible', check all visible frames
3719 for a window to use.
3720 If FRAME is 0, check all visible and iconified frames.
3721 If FRAME is t, check all frames.
3722 If FRAME is a frame, check only that frame.
3723 If FRAME is nil, check only the selected frame
3724 (actually the last nonminibuffer frame),
3725 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3726 which means search visible and iconified frames.
3728 If a full-width window on a splittable frame is available to display
3729 the buffer, it may be split, subject to the value of the variable
3730 `split-height-threshold'.
3732 If `even-window-heights' is non-nil, window heights will be evened out
3733 if displaying the buffer causes two vertically adjacent windows to be
3734 displayed. */)
3735 (buffer, not_this_window, frame)
3736 Lisp_Object buffer, not_this_window, frame;
3738 register Lisp_Object window, tem, swp;
3739 struct frame *f;
3741 swp = Qnil;
3742 buffer = Fget_buffer (buffer);
3743 CHECK_BUFFER (buffer);
3745 if (!NILP (Vdisplay_buffer_function))
3746 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3748 if (NILP (not_this_window)
3749 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3750 return display_buffer_1 (selected_window);
3752 /* See if the user has specified this buffer should appear
3753 in the selected window. */
3754 if (NILP (not_this_window))
3756 swp = Fsame_window_p (XBUFFER (buffer)->name);
3757 if (!NILP (swp) && !no_switch_window (selected_window))
3759 Fswitch_to_buffer (buffer, Qnil);
3760 return display_buffer_1 (selected_window);
3764 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3765 look for a window showing BUFFER on any visible or iconified frame.
3766 Otherwise search only the current frame. */
3767 if (! NILP (frame))
3768 tem = frame;
3769 else if (pop_up_frames
3770 || display_buffer_reuse_frames
3771 || last_nonminibuf_frame == 0)
3772 XSETFASTINT (tem, 0);
3773 else
3774 XSETFRAME (tem, last_nonminibuf_frame);
3776 window = Fget_buffer_window (buffer, tem);
3777 if (!NILP (window)
3778 && (NILP (not_this_window) || !EQ (window, selected_window)))
3779 return display_buffer_1 (window);
3781 /* Certain buffer names get special handling. */
3782 if (!NILP (Vspecial_display_function) && NILP (swp))
3784 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3785 if (EQ (tem, Qt))
3786 return call1 (Vspecial_display_function, buffer);
3787 if (CONSP (tem))
3788 return call2 (Vspecial_display_function, buffer, tem);
3791 /* If there are no frames open that have more than a minibuffer,
3792 we need to create a new frame. */
3793 if (pop_up_frames || last_nonminibuf_frame == 0)
3795 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3796 Fset_window_buffer (window, buffer, Qnil);
3797 return display_buffer_1 (window);
3800 f = SELECTED_FRAME ();
3801 if (pop_up_windows
3802 || FRAME_MINIBUF_ONLY_P (f)
3803 /* If the current frame is a special display frame,
3804 don't try to reuse its windows. */
3805 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3807 Lisp_Object frames;
3808 struct gcpro gcpro1;
3809 GCPRO1 (buffer);
3811 frames = Qnil;
3812 if (FRAME_MINIBUF_ONLY_P (f))
3813 XSETFRAME (frames, last_nonminibuf_frame);
3815 /* Note that both Fget_largest_window and Fget_lru_window
3816 ignore minibuffers and dedicated windows.
3817 This means they can return nil. */
3819 /* If the frame we would try to split cannot be split,
3820 try other frames. */
3821 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3823 /* Try visible frames first. */
3824 window = Fget_largest_window (Qvisible, Qt);
3825 /* If that didn't work, try iconified frames. */
3826 if (NILP (window))
3827 window = Fget_largest_window (make_number (0), Qt);
3828 #if 0 /* Don't try windows on other displays. */
3829 if (NILP (window))
3830 window = Fget_largest_window (Qt, Qt);
3831 #endif
3833 else
3834 window = Fget_largest_window (frames, Qt);
3836 tem = Qnil;
3837 if (!NILP (Vsplit_window_preferred_function))
3838 tem = call1 (Vsplit_window_preferred_function, window);
3840 if (!NILP (tem))
3841 window = tem;
3842 else
3843 /* If the largest window is tall enough, full-width, and either eligible
3844 for splitting or the only window, split it. */
3845 if (!NILP (window)
3846 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3847 && WINDOW_FULL_WIDTH_P (XWINDOW (window))
3848 && (window_height (window) >= split_height_threshold
3849 || (NILP (XWINDOW (window)->parent)))
3850 && (window_height (window)
3851 >= (2 * window_min_size_2 (XWINDOW (window), 0, 0))))
3852 window = Fsplit_window (window, Qnil, Qnil);
3853 else
3855 Lisp_Object upper, other;
3857 window = Fget_lru_window (frames, Qt);
3858 /* If the LRU window is tall enough, and either eligible for
3859 splitting and selected or the only window, split it. */
3860 if (!NILP (window)
3861 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3862 && ((EQ (window, selected_window)
3863 && window_height (window) >= split_height_threshold)
3864 || (NILP (XWINDOW (window)->parent)))
3865 && (window_height (window)
3866 >= (2 * window_min_size_2 (XWINDOW (window), 0, 0))))
3867 window = Fsplit_window (window, Qnil, Qnil);
3868 else
3869 window = Fget_lru_window (frames, Qnil);
3870 /* If Fget_lru_window returned nil, try other approaches. */
3872 /* Try visible frames first. */
3873 if (NILP (window))
3874 window = Fget_buffer_window (buffer, Qvisible);
3875 if (NILP (window))
3876 window = Fget_largest_window (Qvisible, Qnil);
3877 /* If that didn't work, try iconified frames. */
3878 if (NILP (window))
3879 window = Fget_buffer_window (buffer, make_number (0));
3880 if (NILP (window))
3881 window = Fget_largest_window (make_number (0), Qnil);
3883 #if 0 /* Don't try frames on other displays. */
3884 if (NILP (window))
3885 window = Fget_buffer_window (buffer, Qt);
3886 if (NILP (window))
3887 window = Fget_largest_window (Qt, Qnil);
3888 #endif
3889 /* As a last resort, make a new frame. */
3890 if (NILP (window))
3891 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3892 /* If window appears above or below another,
3893 even out their heights. */
3894 other = upper = Qnil;
3895 if (!NILP (XWINDOW (window)->prev))
3896 other = upper = XWINDOW (window)->prev;
3897 if (!NILP (XWINDOW (window)->next))
3898 other = XWINDOW (window)->next, upper = window;
3899 if (!NILP (other)
3900 && !NILP (Veven_window_heights)
3901 /* Check that OTHER and WINDOW are vertically arrayed. */
3902 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3903 && (XFASTINT (XWINDOW (other)->total_lines)
3904 > XFASTINT (XWINDOW (window)->total_lines)))
3906 int total = (XFASTINT (XWINDOW (other)->total_lines)
3907 + XFASTINT (XWINDOW (window)->total_lines));
3908 enlarge_window (upper,
3909 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
3913 UNGCPRO;
3915 else
3916 window = Fget_lru_window (Qnil, Qnil);
3918 Fset_window_buffer (window, buffer, Qnil);
3919 return display_buffer_1 (window);
3923 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3924 0, 1, 0,
3925 doc: /* Force all windows to be updated on next redisplay.
3926 If optional arg OBJECT is a window, force redisplay of that window only.
3927 If OBJECT is a buffer or buffer name, force redisplay of all windows
3928 displaying that buffer. */)
3929 (object)
3930 Lisp_Object object;
3932 if (NILP (object))
3934 windows_or_buffers_changed++;
3935 update_mode_lines++;
3936 return Qt;
3939 if (WINDOWP (object))
3941 struct window *w = XWINDOW (object);
3942 mark_window_display_accurate (object, 0);
3943 w->update_mode_line = Qt;
3944 if (BUFFERP (w->buffer))
3945 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3946 ++update_mode_lines;
3947 return Qt;
3950 if (STRINGP (object))
3951 object = Fget_buffer (object);
3952 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3954 /* Walk all windows looking for buffer, and force update
3955 of each of those windows. */
3957 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3958 return NILP (object) ? Qnil : Qt;
3961 /* If nothing suitable was found, just return.
3962 We could signal an error, but this feature will typically be used
3963 asynchronously in timers or process sentinels, so we don't. */
3964 return Qnil;
3968 void
3969 temp_output_buffer_show (buf)
3970 register Lisp_Object buf;
3972 register struct buffer *old = current_buffer;
3973 register Lisp_Object window;
3974 register struct window *w;
3976 XBUFFER (buf)->directory = current_buffer->directory;
3978 Fset_buffer (buf);
3979 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3980 BEGV = BEG;
3981 ZV = Z;
3982 SET_PT (BEG);
3983 #if 0 /* rms: there should be no reason for this. */
3984 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3985 #endif
3986 set_buffer_internal (old);
3988 if (!NILP (Vtemp_buffer_show_function))
3989 call1 (Vtemp_buffer_show_function, buf);
3990 else
3992 window = Fdisplay_buffer (buf, Qnil, Qnil);
3994 if (!EQ (XWINDOW (window)->frame, selected_frame))
3995 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3996 Vminibuf_scroll_window = window;
3997 w = XWINDOW (window);
3998 XSETFASTINT (w->hscroll, 0);
3999 XSETFASTINT (w->min_hscroll, 0);
4000 set_marker_restricted_both (w->start, buf, BEG, BEG);
4001 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
4003 /* Run temp-buffer-show-hook, with the chosen window selected
4004 and its buffer current. */
4006 if (!NILP (Vrun_hooks)
4007 && !NILP (Fboundp (Qtemp_buffer_show_hook))
4008 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
4010 int count = SPECPDL_INDEX ();
4011 Lisp_Object prev_window, prev_buffer;
4012 prev_window = selected_window;
4013 XSETBUFFER (prev_buffer, old);
4015 /* Select the window that was chosen, for running the hook.
4016 Note: Both Fselect_window and select_window_norecord may
4017 set-buffer to the buffer displayed in the window,
4018 so we need to save the current buffer. --stef */
4019 record_unwind_protect (Fset_buffer, prev_buffer);
4020 record_unwind_protect (select_window_norecord, prev_window);
4021 Fselect_window (window, Qt);
4022 Fset_buffer (w->buffer);
4023 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
4024 unbind_to (count, Qnil);
4029 static void
4030 make_dummy_parent (window)
4031 Lisp_Object window;
4033 Lisp_Object new;
4034 register struct window *o, *p;
4035 int i;
4037 o = XWINDOW (window);
4038 p = allocate_window ();
4039 for (i = 0; i < VECSIZE (struct window); ++i)
4040 ((struct Lisp_Vector *) p)->contents[i]
4041 = ((struct Lisp_Vector *)o)->contents[i];
4042 XSETWINDOW (new, p);
4044 ++sequence_number;
4045 XSETFASTINT (p->sequence_number, sequence_number);
4047 /* Put new into window structure in place of window */
4048 replace_window (window, new);
4050 o->next = Qnil;
4051 o->prev = Qnil;
4052 o->vchild = Qnil;
4053 o->hchild = Qnil;
4054 o->parent = new;
4056 p->start = Qnil;
4057 p->pointm = Qnil;
4058 p->buffer = Qnil;
4061 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
4062 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
4063 WINDOW defaults to selected one and SIZE to half its size.
4064 If optional third arg HORFLAG is non-nil, split side by side
4065 and put SIZE columns in the first of the pair. In that case,
4066 SIZE includes that window's scroll bar, or the divider column to its right.
4067 Interactively, all arguments are nil.
4069 Returns the newly created window (which is the lower or rightmost one).
4070 The upper or leftmost window is the original one, and remains selected
4071 if it was selected before.
4073 See Info node `(elisp)Splitting Windows' for more details and examples.*/)
4074 (window, size, horflag)
4075 Lisp_Object window, size, horflag;
4077 register Lisp_Object new;
4078 register struct window *o, *p;
4079 FRAME_PTR fo;
4080 register int size_int;
4082 if (NILP (window))
4083 window = selected_window;
4084 else
4085 CHECK_LIVE_WINDOW (window);
4087 o = XWINDOW (window);
4088 fo = XFRAME (WINDOW_FRAME (o));
4090 if (NILP (size))
4092 if (!NILP (horflag))
4093 /* Calculate the size of the left-hand window, by dividing
4094 the usable space in columns by two.
4095 We round up, since the left-hand window may include
4096 a dividing line, while the right-hand may not. */
4097 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
4098 else
4099 size_int = XFASTINT (o->total_lines) >> 1;
4101 else
4103 CHECK_NUMBER (size);
4104 size_int = XINT (size);
4107 if (MINI_WINDOW_P (o))
4108 error ("Attempt to split minibuffer window");
4109 else if (window_fixed_size_p (o, !NILP (horflag), 0))
4110 error ("Attempt to split fixed-size window");
4112 if (NILP (horflag))
4114 int window_safe_height = window_min_size_2 (o, 0, 0);
4116 if (size_int < window_safe_height)
4117 error ("Window height %d too small (after splitting)", size_int);
4118 if (size_int + window_safe_height > XFASTINT (o->total_lines))
4119 error ("Window height %d too small (after splitting)",
4120 XFASTINT (o->total_lines) - size_int);
4121 if (NILP (o->parent)
4122 || NILP (XWINDOW (o->parent)->vchild))
4124 make_dummy_parent (window);
4125 new = o->parent;
4126 XWINDOW (new)->vchild = window;
4129 else
4131 int window_safe_width = window_min_size_2 (o, 1, 0);
4133 if (size_int < window_safe_width)
4134 error ("Window width %d too small (after splitting)", size_int);
4135 if (size_int + window_safe_width > XFASTINT (o->total_cols))
4136 error ("Window width %d too small (after splitting)",
4137 XFASTINT (o->total_cols) - size_int);
4138 if (NILP (o->parent)
4139 || NILP (XWINDOW (o->parent)->hchild))
4141 make_dummy_parent (window);
4142 new = o->parent;
4143 XWINDOW (new)->hchild = window;
4147 /* Now we know that window's parent is a vertical combination
4148 if we are dividing vertically, or a horizontal combination
4149 if we are making side-by-side windows */
4151 windows_or_buffers_changed++;
4152 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
4153 new = make_window ();
4154 p = XWINDOW (new);
4156 p->frame = o->frame;
4157 p->next = o->next;
4158 if (!NILP (p->next))
4159 XWINDOW (p->next)->prev = new;
4160 p->prev = window;
4161 o->next = new;
4162 p->parent = o->parent;
4163 p->buffer = Qt;
4164 p->window_end_valid = Qnil;
4165 bzero (&p->last_cursor, sizeof p->last_cursor);
4167 /* Duplicate special geometry settings. */
4169 p->left_margin_cols = o->left_margin_cols;
4170 p->right_margin_cols = o->right_margin_cols;
4171 p->left_fringe_width = o->left_fringe_width;
4172 p->right_fringe_width = o->right_fringe_width;
4173 p->fringes_outside_margins = o->fringes_outside_margins;
4174 p->scroll_bar_width = o->scroll_bar_width;
4175 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
4177 /* Apportion the available frame space among the two new windows */
4179 if (!NILP (horflag))
4181 p->total_lines = o->total_lines;
4182 p->top_line = o->top_line;
4183 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
4184 XSETFASTINT (o->total_cols, size_int);
4185 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
4186 adjust_window_margins (p);
4187 adjust_window_margins (o);
4189 else
4191 p->left_col = o->left_col;
4192 p->total_cols = o->total_cols;
4193 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
4194 XSETFASTINT (o->total_lines, size_int);
4195 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
4198 /* Adjust glyph matrices. */
4199 adjust_glyphs (fo);
4201 Fset_window_buffer (new, o->buffer, Qt);
4202 return new;
4205 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
4206 doc: /* Make current window ARG lines bigger.
4207 From program, optional second arg non-nil means grow sideways ARG columns.
4208 Interactively, if an argument is not given, make the window one line bigger.
4209 If HORIZONTAL is non-nil, enlarge horizontally instead of vertically.
4210 This function can delete windows, even the second window, if they get
4211 too small. */)
4212 (arg, horizontal)
4213 Lisp_Object arg, horizontal;
4215 CHECK_NUMBER (arg);
4216 enlarge_window (selected_window, XINT (arg), !NILP (horizontal));
4218 run_window_configuration_change_hook (SELECTED_FRAME ());
4220 return Qnil;
4223 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
4224 doc: /* Make current window ARG lines smaller.
4225 From program, optional second arg non-nil means shrink sideways arg columns.
4226 Interactively, if an argument is not given, make the window one line smaller.
4227 Only siblings to the right or below are changed. */)
4228 (arg, side)
4229 Lisp_Object arg, side;
4231 CHECK_NUMBER (arg);
4232 enlarge_window (selected_window, -XINT (arg), !NILP (side));
4234 run_window_configuration_change_hook (SELECTED_FRAME ());
4236 return Qnil;
4240 window_height (window)
4241 Lisp_Object window;
4243 register struct window *p = XWINDOW (window);
4244 return WINDOW_TOTAL_LINES (p);
4248 window_width (window)
4249 Lisp_Object window;
4251 register struct window *p = XWINDOW (window);
4252 return WINDOW_TOTAL_COLS (p);
4256 #define CURBEG(w) \
4257 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
4259 #define CURSIZE(w) \
4260 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
4263 /* Enlarge WINDOW by DELTA. HORIZ_FLAG nonzero means enlarge it
4264 horizontally; zero means do it vertically.
4266 Siblings of the selected window are resized to fulfill the size
4267 request. If they become too small in the process, they may be
4268 deleted. */
4270 static void
4271 enlarge_window (window, delta, horiz_flag)
4272 Lisp_Object window;
4273 int delta, horiz_flag;
4275 Lisp_Object parent, next, prev;
4276 struct window *p;
4277 Lisp_Object *sizep;
4278 int maximum;
4279 int (*sizefun) P_ ((Lisp_Object))
4280 = horiz_flag ? window_width : window_height;
4281 void (*setsizefun) P_ ((Lisp_Object, int, int))
4282 = (horiz_flag ? set_window_width : set_window_height);
4284 /* Give up if this window cannot be resized. */
4285 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4286 error ("Window is not resizable");
4288 /* Find the parent of the selected window. */
4289 while (1)
4291 p = XWINDOW (window);
4292 parent = p->parent;
4294 if (NILP (parent))
4296 if (horiz_flag)
4297 error ("No other window to side of this one");
4298 break;
4301 if (horiz_flag
4302 ? !NILP (XWINDOW (parent)->hchild)
4303 : !NILP (XWINDOW (parent)->vchild))
4304 break;
4306 window = parent;
4309 sizep = &CURSIZE (window);
4312 register int maxdelta;
4314 /* Compute the maximum size increment this window can have. */
4316 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
4317 /* This is a main window followed by a minibuffer. */
4318 : !NILP (p->next) ? ((*sizefun) (p->next)
4319 - window_min_size (XWINDOW (p->next),
4320 horiz_flag, 0, 0, 0))
4321 /* This is a minibuffer following a main window. */
4322 : !NILP (p->prev) ? ((*sizefun) (p->prev)
4323 - window_min_size (XWINDOW (p->prev),
4324 horiz_flag, 0, 0, 0))
4325 /* This is a frame with only one window, a minibuffer-only
4326 or a minibufferless frame. */
4327 : (delta = 0));
4329 if (delta > maxdelta)
4330 /* This case traps trying to make the minibuffer
4331 the full frame, or make the only window aside from the
4332 minibuffer the full frame. */
4333 delta = maxdelta;
4336 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window),
4337 horiz_flag, 0, 0, 0))
4339 delete_window (window);
4340 return;
4343 if (delta == 0)
4344 return;
4346 /* Find the total we can get from other siblings without deleting them. */
4347 maximum = 0;
4348 for (next = p->next; WINDOWP (next); next = XWINDOW (next)->next)
4349 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
4350 horiz_flag, 0, 0, 0);
4351 for (prev = p->prev; WINDOWP (prev); prev = XWINDOW (prev)->prev)
4352 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
4353 horiz_flag, 0, 0, 0);
4355 /* If we can get it all from them without deleting them, do so. */
4356 if (delta <= maximum)
4358 Lisp_Object first_unaffected;
4359 Lisp_Object first_affected;
4360 int fixed_p;
4362 next = p->next;
4363 prev = p->prev;
4364 first_affected = window;
4365 /* Look at one sibling at a time,
4366 moving away from this window in both directions alternately,
4367 and take as much as we can get without deleting that sibling. */
4368 while (delta != 0
4369 && (!NILP (next) || !NILP (prev)))
4371 if (! NILP (next))
4373 int this_one = ((*sizefun) (next)
4374 - window_min_size (XWINDOW (next), horiz_flag,
4375 0, 0, &fixed_p));
4376 if (!fixed_p)
4378 if (this_one > delta)
4379 this_one = delta;
4381 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
4382 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4384 delta -= this_one;
4387 next = XWINDOW (next)->next;
4390 if (delta == 0)
4391 break;
4393 if (! NILP (prev))
4395 int this_one = ((*sizefun) (prev)
4396 - window_min_size (XWINDOW (prev), horiz_flag,
4397 0, 0, &fixed_p));
4398 if (!fixed_p)
4400 if (this_one > delta)
4401 this_one = delta;
4403 first_affected = prev;
4405 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
4406 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4408 delta -= this_one;
4411 prev = XWINDOW (prev)->prev;
4415 xassert (delta == 0);
4417 /* Now recalculate the edge positions of all the windows affected,
4418 based on the new sizes. */
4419 first_unaffected = next;
4420 prev = first_affected;
4421 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4422 prev = next, next = XWINDOW (next)->next)
4424 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4425 /* This does not change size of NEXT,
4426 but it propagates the new top edge to its children */
4427 (*setsizefun) (next, (*sizefun) (next), 0);
4430 else
4432 register int delta1;
4433 register int opht = (*sizefun) (parent);
4435 if (opht <= XINT (*sizep) + delta)
4437 /* If trying to grow this window to or beyond size of the parent,
4438 just delete all the sibling windows. */
4439 Lisp_Object start, tem, next;
4441 start = XWINDOW (parent)->vchild;
4442 if (NILP (start))
4443 start = XWINDOW (parent)->hchild;
4445 /* Delete any siblings that come after WINDOW. */
4446 tem = XWINDOW (window)->next;
4447 while (! NILP (tem))
4449 next = XWINDOW (tem)->next;
4450 delete_window (tem);
4451 tem = next;
4454 /* Delete any siblings that come after WINDOW.
4455 Note that if START is not WINDOW, then WINDOW still
4456 has siblings, so WINDOW has not yet replaced its parent. */
4457 tem = start;
4458 while (! EQ (tem, window))
4460 next = XWINDOW (tem)->next;
4461 delete_window (tem);
4462 tem = next;
4465 else
4467 /* Otherwise, make delta1 just right so that if we add
4468 delta1 lines to this window and to the parent, and then
4469 shrink the parent back to its original size, the new
4470 proportional size of this window will increase by delta.
4472 The function size_window will compute the new height h'
4473 of the window from delta1 as:
4475 e = delta1/n
4476 x = delta1 - delta1/n * n for the 1st resizable child
4477 h' = h + e + x
4479 where n is the number of children that can be resized.
4480 We can ignore x by choosing a delta1 that is a multiple of
4481 n. We want the height of this window to come out as
4483 h' = h + delta
4485 So, delta1 must be
4487 h + e = h + delta
4488 delta1/n = delta
4489 delta1 = n * delta.
4491 The number of children n equals the number of resizable
4492 children of this window + 1 because we know window itself
4493 is resizable (otherwise we would have signalled an error).
4495 This reasoning is not correct when other windows become too
4496 small and shrink_windows refuses to delete them. Below we
4497 use resize_proportionally to work around this problem. */
4499 struct window *w = XWINDOW (window);
4500 Lisp_Object s;
4501 int n = 1;
4503 for (s = w->next; WINDOWP (s); s = XWINDOW (s)->next)
4504 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4505 ++n;
4506 for (s = w->prev; WINDOWP (s); s = XWINDOW (s)->prev)
4507 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4508 ++n;
4510 delta1 = n * delta;
4512 /* Add delta1 lines or columns to this window, and to the parent,
4513 keeping things consistent while not affecting siblings. */
4514 XSETINT (CURSIZE (parent), opht + delta1);
4515 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4517 /* Squeeze out delta1 lines or columns from our parent,
4518 shrinking this window and siblings proportionately. This
4519 brings parent back to correct size. Delta1 was calculated
4520 so this makes this window the desired size, taking it all
4521 out of the siblings.
4523 Temporarily set resize_proportionally to Qt to assure that,
4524 if necessary, shrink_windows deletes smaller windows rather
4525 than shrink this window. */
4526 w->resize_proportionally = Qt;
4527 (*setsizefun) (parent, opht, 0);
4528 w->resize_proportionally = Qnil;
4532 XSETFASTINT (p->last_modified, 0);
4533 XSETFASTINT (p->last_overlay_modified, 0);
4535 /* Adjust glyph matrices. */
4536 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4540 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4541 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4542 zero means adjust the height, moving the bottom edge.
4544 Following siblings of the selected window are resized to fulfill
4545 the size request. If they become too small in the process, they
4546 are not deleted; instead, we signal an error. */
4548 static void
4549 adjust_window_trailing_edge (window, delta, horiz_flag)
4550 Lisp_Object window;
4551 int delta, horiz_flag;
4553 Lisp_Object parent, child;
4554 struct window *p;
4555 Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
4556 int delcount = window_deletion_count;
4558 CHECK_WINDOW (window);
4560 /* Give up if this window cannot be resized. */
4561 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4562 error ("Window is not resizable");
4564 while (1)
4566 Lisp_Object first_parallel = Qnil;
4568 if (NILP (window))
4570 /* This happens if WINDOW on the previous iteration was
4571 at top level of the window tree. */
4572 Fset_window_configuration (old_config);
4573 error ("Specified window edge is fixed");
4576 p = XWINDOW (window);
4577 parent = p->parent;
4579 /* See if this level has windows in parallel in the specified
4580 direction. If so, set FIRST_PARALLEL to the first one. */
4581 if (horiz_flag)
4583 if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
4584 first_parallel = XWINDOW (parent)->vchild;
4585 else if (NILP (parent) && !NILP (p->next))
4587 /* Handle the vertical chain of main window and minibuffer
4588 which has no parent. */
4589 first_parallel = window;
4590 while (! NILP (XWINDOW (first_parallel)->prev))
4591 first_parallel = XWINDOW (first_parallel)->prev;
4594 else
4596 if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
4597 first_parallel = XWINDOW (parent)->hchild;
4600 /* If this level's succession is in the desired dimension,
4601 and this window is the last one, and there is no higher level,
4602 its trailing edge is fixed. */
4603 if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
4604 && NILP (parent))
4606 Fset_window_configuration (old_config);
4607 error ("Specified window edge is fixed");
4610 /* Don't make this window too small. */
4611 if (XINT (CURSIZE (window)) + delta
4612 < window_min_size_2 (XWINDOW (window), horiz_flag, 0))
4614 Fset_window_configuration (old_config);
4615 error ("Cannot adjust window size as specified");
4618 /* Clear out some redisplay caches. */
4619 XSETFASTINT (p->last_modified, 0);
4620 XSETFASTINT (p->last_overlay_modified, 0);
4622 /* Adjust this window's edge. */
4623 XSETINT (CURSIZE (window),
4624 XINT (CURSIZE (window)) + delta);
4626 /* If this window has following siblings in the desired dimension,
4627 make them smaller, and exit the loop.
4629 (If we reach the top of the tree and can never do this,
4630 we will fail and report an error, above.) */
4631 if (NILP (first_parallel))
4633 if (!NILP (p->next))
4635 /* This may happen for the minibuffer. In that case
4636 the window_deletion_count check below does not work. */
4637 if (XINT (CURSIZE (p->next)) - delta <= 0)
4639 Fset_window_configuration (old_config);
4640 error ("Cannot adjust window size as specified");
4643 XSETINT (CURBEG (p->next),
4644 XINT (CURBEG (p->next)) + delta);
4645 size_window (p->next, XINT (CURSIZE (p->next)) - delta,
4646 horiz_flag, 0, 1, 0);
4647 break;
4650 else
4651 /* Here we have a chain of parallel siblings, in the other dimension.
4652 Change the size of the other siblings. */
4653 for (child = first_parallel;
4654 ! NILP (child);
4655 child = XWINDOW (child)->next)
4656 if (! EQ (child, window))
4657 size_window (child, XINT (CURSIZE (child)) + delta,
4658 horiz_flag, 0, 0, 1);
4660 window = parent;
4663 /* If we made a window so small it got deleted,
4664 we failed. Report failure. */
4665 if (delcount != window_deletion_count)
4667 Fset_window_configuration (old_config);
4668 error ("Cannot adjust window size as specified");
4671 /* Adjust glyph matrices. */
4672 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4675 #undef CURBEG
4676 #undef CURSIZE
4678 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
4679 Sadjust_window_trailing_edge, 3, 3, 0,
4680 doc: /* Adjust the bottom or right edge of WINDOW by DELTA.
4681 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4682 Otherwise, adjust the height, moving the bottom edge.
4684 Following siblings of the selected window are resized to fulfill
4685 the size request. If they become too small in the process, they
4686 are not deleted; instead, we signal an error. */)
4687 (window, delta, horizontal)
4688 Lisp_Object window, delta, horizontal;
4690 CHECK_NUMBER (delta);
4691 if (NILP (window))
4692 window = selected_window;
4693 adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
4695 run_window_configuration_change_hook
4696 (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4698 return Qnil;
4703 /***********************************************************************
4704 Resizing Mini-Windows
4705 ***********************************************************************/
4707 static void shrink_window_lowest_first P_ ((struct window *, int));
4709 enum save_restore_action
4711 CHECK_ORIG_SIZES,
4712 SAVE_ORIG_SIZES,
4713 RESTORE_ORIG_SIZES
4716 static int save_restore_orig_size P_ ((struct window *,
4717 enum save_restore_action));
4719 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4720 from lowest windows first. */
4722 static void
4723 shrink_window_lowest_first (w, height)
4724 struct window *w;
4725 int height;
4727 struct window *c;
4728 Lisp_Object child;
4729 int old_height;
4731 xassert (!MINI_WINDOW_P (w));
4733 /* Set redisplay hints. */
4734 XSETFASTINT (w->last_modified, 0);
4735 XSETFASTINT (w->last_overlay_modified, 0);
4736 windows_or_buffers_changed++;
4737 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4739 old_height = XFASTINT (w->total_lines);
4740 XSETFASTINT (w->total_lines, height);
4742 if (!NILP (w->hchild))
4744 for (child = w->hchild; !NILP (child); child = c->next)
4746 c = XWINDOW (child);
4747 c->top_line = w->top_line;
4748 shrink_window_lowest_first (c, height);
4751 else if (!NILP (w->vchild))
4753 Lisp_Object last_child;
4754 int delta = old_height - height;
4755 int last_top;
4757 last_child = Qnil;
4759 /* Find the last child. We are taking space from lowest windows
4760 first, so we iterate over children from the last child
4761 backwards. */
4762 for (child = w->vchild; WINDOWP (child); child = XWINDOW (child)->next)
4763 last_child = child;
4765 /* Size children down to their safe heights. */
4766 for (child = last_child; delta && !NILP (child); child = c->prev)
4768 int this_one;
4770 c = XWINDOW (child);
4771 this_one = XFASTINT (c->total_lines) - window_min_size_1 (c, 0, 1);
4773 if (this_one > delta)
4774 this_one = delta;
4776 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4777 delta -= this_one;
4780 /* Compute new positions. */
4781 last_top = XINT (w->top_line);
4782 for (child = w->vchild; !NILP (child); child = c->next)
4784 c = XWINDOW (child);
4785 c->top_line = make_number (last_top);
4786 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4787 last_top += XFASTINT (c->total_lines);
4793 /* Save, restore, or check positions and sizes in the window tree
4794 rooted at W. ACTION says what to do.
4796 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4797 orig_total_lines members are valid for all windows in the window
4798 tree. Value is non-zero if they are valid.
4800 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4801 orig_top_line and orig_total_lines for all windows in the tree.
4803 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4804 stored in orig_top_line and orig_total_lines for all windows. */
4806 static int
4807 save_restore_orig_size (w, action)
4808 struct window *w;
4809 enum save_restore_action action;
4811 int success_p = 1;
4813 while (w)
4815 if (!NILP (w->hchild))
4817 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4818 success_p = 0;
4820 else if (!NILP (w->vchild))
4822 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4823 success_p = 0;
4826 switch (action)
4828 case CHECK_ORIG_SIZES:
4829 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4830 return 0;
4831 break;
4833 case SAVE_ORIG_SIZES:
4834 w->orig_top_line = w->top_line;
4835 w->orig_total_lines = w->total_lines;
4836 XSETFASTINT (w->last_modified, 0);
4837 XSETFASTINT (w->last_overlay_modified, 0);
4838 break;
4840 case RESTORE_ORIG_SIZES:
4841 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4842 w->top_line = w->orig_top_line;
4843 w->total_lines = w->orig_total_lines;
4844 w->orig_total_lines = w->orig_top_line = Qnil;
4845 XSETFASTINT (w->last_modified, 0);
4846 XSETFASTINT (w->last_overlay_modified, 0);
4847 break;
4849 default:
4850 abort ();
4853 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4856 return success_p;
4860 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4861 without deleting other windows. */
4863 void
4864 grow_mini_window (w, delta)
4865 struct window *w;
4866 int delta;
4868 struct frame *f = XFRAME (w->frame);
4869 struct window *root;
4871 xassert (MINI_WINDOW_P (w));
4872 xassert (delta >= 0);
4874 /* Compute how much we can enlarge the mini-window without deleting
4875 other windows. */
4876 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4877 if (delta)
4879 int min_height = window_min_size (root, 0, 0, 0, 0);
4880 if (XFASTINT (root->total_lines) - delta < min_height)
4881 /* Note that the root window may already be smaller than
4882 min_height. */
4883 delta = max (0, XFASTINT (root->total_lines) - min_height);
4886 if (delta)
4888 /* Save original window sizes and positions, if not already done. */
4889 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4890 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4892 /* Shrink other windows. */
4893 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4895 /* Grow the mini-window. */
4896 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4897 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4898 XSETFASTINT (w->last_modified, 0);
4899 XSETFASTINT (w->last_overlay_modified, 0);
4901 adjust_glyphs (f);
4906 /* Shrink mini-window W. If there is recorded info about window sizes
4907 before a call to grow_mini_window, restore recorded window sizes.
4908 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4909 line. */
4911 void
4912 shrink_mini_window (w)
4913 struct window *w;
4915 struct frame *f = XFRAME (w->frame);
4916 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4918 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4920 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4921 adjust_glyphs (f);
4922 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4923 windows_or_buffers_changed = 1;
4925 else if (XFASTINT (w->total_lines) > 1)
4927 /* Distribute the additional lines of the mini-window
4928 among the other windows. */
4929 Lisp_Object window;
4930 XSETWINDOW (window, w);
4931 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
4937 /* Mark window cursors off for all windows in the window tree rooted
4938 at W by setting their phys_cursor_on_p flag to zero. Called from
4939 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4940 the frame are cleared. */
4942 void
4943 mark_window_cursors_off (w)
4944 struct window *w;
4946 while (w)
4948 if (!NILP (w->hchild))
4949 mark_window_cursors_off (XWINDOW (w->hchild));
4950 else if (!NILP (w->vchild))
4951 mark_window_cursors_off (XWINDOW (w->vchild));
4952 else
4953 w->phys_cursor_on_p = 0;
4955 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4960 /* Return number of lines of text (not counting mode lines) in W. */
4963 window_internal_height (w)
4964 struct window *w;
4966 int ht = XFASTINT (w->total_lines);
4968 if (!MINI_WINDOW_P (w))
4970 if (!NILP (w->parent)
4971 || !NILP (w->vchild)
4972 || !NILP (w->hchild)
4973 || !NILP (w->next)
4974 || !NILP (w->prev)
4975 || WINDOW_WANTS_MODELINE_P (w))
4976 --ht;
4978 if (WINDOW_WANTS_HEADER_LINE_P (w))
4979 --ht;
4982 return ht;
4986 /* Return the number of columns in W.
4987 Don't count columns occupied by scroll bars or the vertical bar
4988 separating W from the sibling to its right. */
4991 window_box_text_cols (w)
4992 struct window *w;
4994 struct frame *f = XFRAME (WINDOW_FRAME (w));
4995 int width = XINT (w->total_cols);
4997 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4998 /* Scroll bars occupy a few columns. */
4999 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
5000 else if (!FRAME_WINDOW_P (f)
5001 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
5002 /* The column of `|' characters separating side-by-side windows
5003 occupies one column only. */
5004 width -= 1;
5006 if (FRAME_WINDOW_P (f))
5007 /* On window-systems, fringes and display margins cannot be
5008 used for normal text. */
5009 width -= (WINDOW_FRINGE_COLS (w)
5010 + WINDOW_LEFT_MARGIN_COLS (w)
5011 + WINDOW_RIGHT_MARGIN_COLS (w));
5013 return width;
5017 /************************************************************************
5018 Window Scrolling
5019 ***********************************************************************/
5021 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
5022 N screen-fulls, which is defined as the height of the window minus
5023 next_screen_context_lines. If WHOLE is zero, scroll up N lines
5024 instead. Negative values of N mean scroll down. NOERROR non-zero
5025 means don't signal an error if we try to move over BEGV or ZV,
5026 respectively. */
5028 static void
5029 window_scroll (window, n, whole, noerror)
5030 Lisp_Object window;
5031 int n;
5032 int whole;
5033 int noerror;
5035 immediate_quit = 1;
5037 /* If we must, use the pixel-based version which is much slower than
5038 the line-based one but can handle varying line heights. */
5039 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
5040 window_scroll_pixel_based (window, n, whole, noerror);
5041 else
5042 window_scroll_line_based (window, n, whole, noerror);
5044 immediate_quit = 0;
5048 /* Implementation of window_scroll that works based on pixel line
5049 heights. See the comment of window_scroll for parameter
5050 descriptions. */
5052 static void
5053 window_scroll_pixel_based (window, n, whole, noerror)
5054 Lisp_Object window;
5055 int n;
5056 int whole;
5057 int noerror;
5059 struct it it;
5060 struct window *w = XWINDOW (window);
5061 struct text_pos start;
5062 int this_scroll_margin;
5063 /* True if we fiddled the window vscroll field without really scrolling. */
5064 int vscrolled = 0;
5065 int x, y, rtop, rbot, rowh, vpos;
5067 SET_TEXT_POS_FROM_MARKER (start, w->start);
5069 /* If PT is not visible in WINDOW, move back one half of
5070 the screen. Allow PT to be partially visible, otherwise
5071 something like (scroll-down 1) with PT in the line before
5072 the partially visible one would recenter. */
5074 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
5076 /* Move backward half the height of the window. Performance note:
5077 vmotion used here is about 10% faster, but would give wrong
5078 results for variable height lines. */
5079 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5080 it.current_y = it.last_visible_y;
5081 move_it_vertically_backward (&it, window_box_height (w) / 2);
5083 /* The function move_iterator_vertically may move over more than
5084 the specified y-distance. If it->w is small, e.g. a
5085 mini-buffer window, we may end up in front of the window's
5086 display area. This is the case when Start displaying at the
5087 start of the line containing PT in this case. */
5088 if (it.current_y <= 0)
5090 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5091 move_it_vertically_backward (&it, 0);
5092 it.current_y = 0;
5095 start = it.current.pos;
5097 else if (auto_window_vscroll_p)
5099 if (rtop || rbot) /* partially visible */
5101 int px;
5102 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
5103 if (whole)
5104 dy = max ((window_box_height (w)
5105 - next_screen_context_lines * dy),
5106 dy);
5107 dy *= n;
5109 if (n < 0)
5111 /* Only vscroll backwards if already vscrolled forwards. */
5112 if (w->vscroll < 0 && rtop > 0)
5114 px = max (0, -w->vscroll - min (rtop, -dy));
5115 Fset_window_vscroll (window, make_number (px), Qt);
5116 return;
5119 if (n > 0)
5121 /* Do vscroll if already vscrolled or only display line. */
5122 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
5124 px = max (0, -w->vscroll + min (rbot, dy));
5125 Fset_window_vscroll (window, make_number (px), Qt);
5126 return;
5129 /* Maybe modify window start instead of scrolling. */
5130 if (rbot > 0 || w->vscroll < 0)
5132 int spos;
5134 Fset_window_vscroll (window, make_number (0), Qt);
5135 /* If there are other text lines above the current row,
5136 move window start to current row. Else to next row. */
5137 if (rbot > 0)
5138 spos = XINT (Fline_beginning_position (Qnil));
5139 else
5140 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
5141 set_marker_restricted (w->start, make_number (spos),
5142 w->buffer);
5143 w->start_at_line_beg = Qt;
5144 w->update_mode_line = Qt;
5145 XSETFASTINT (w->last_modified, 0);
5146 XSETFASTINT (w->last_overlay_modified, 0);
5147 /* Set force_start so that redisplay_window will run the
5148 window-scroll-functions. */
5149 w->force_start = Qt;
5150 return;
5154 /* Cancel previous vscroll. */
5155 Fset_window_vscroll (window, make_number (0), Qt);
5158 /* If scroll_preserve_screen_position is non-nil, we try to set
5159 point in the same window line as it is now, so get that line. */
5160 if (!NILP (Vscroll_preserve_screen_position))
5162 /* We preserve the goal pixel coordinate across consecutive
5163 calls to scroll-up or scroll-down. This avoids the
5164 possibility of point becoming "stuck" on a tall line when
5165 scrolling by one line. */
5166 if (window_scroll_pixel_based_preserve_y < 0
5167 || (!EQ (current_kboard->Vlast_command, Qscroll_up)
5168 && !EQ (current_kboard->Vlast_command, Qscroll_down)))
5170 start_display (&it, w, start);
5171 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5172 window_scroll_pixel_based_preserve_y = it.current_y;
5175 else
5176 window_scroll_pixel_based_preserve_y = -1;
5178 /* Move iterator it from start the specified distance forward or
5179 backward. The result is the new window start. */
5180 start_display (&it, w, start);
5181 if (whole)
5183 int start_pos = IT_CHARPOS (it);
5184 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
5185 dy = max ((window_box_height (w)
5186 - next_screen_context_lines * dy),
5187 dy) * n;
5189 /* Note that move_it_vertically always moves the iterator to the
5190 start of a line. So, if the last line doesn't have a newline,
5191 we would end up at the start of the line ending at ZV. */
5192 if (dy <= 0)
5194 move_it_vertically_backward (&it, -dy);
5195 /* Ensure we actually do move, e.g. in case we are currently
5196 looking at an image that is taller that the window height. */
5197 while (start_pos == IT_CHARPOS (it)
5198 && start_pos > BEGV)
5199 move_it_by_lines (&it, -1, 1);
5201 else if (dy > 0)
5203 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
5204 MOVE_TO_POS | MOVE_TO_Y);
5205 /* Ensure we actually do move, e.g. in case we are currently
5206 looking at an image that is taller that the window height. */
5207 while (start_pos == IT_CHARPOS (it)
5208 && start_pos < ZV)
5209 move_it_by_lines (&it, 1, 1);
5212 else
5213 move_it_by_lines (&it, n, 1);
5215 /* We failed if we find ZV is already on the screen (scrolling up,
5216 means there's nothing past the end), or if we can't start any
5217 earlier (scrolling down, means there's nothing past the top). */
5218 if ((n > 0 && IT_CHARPOS (it) == ZV)
5219 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
5221 if (IT_CHARPOS (it) == ZV)
5223 if (it.current_y < it.last_visible_y
5224 && (it.current_y + it.max_ascent + it.max_descent
5225 > it.last_visible_y))
5227 /* The last line was only partially visible, make it fully
5228 visible. */
5229 w->vscroll = (it.last_visible_y
5230 - it.current_y + it.max_ascent + it.max_descent);
5231 adjust_glyphs (it.f);
5233 else if (noerror)
5234 return;
5235 else if (n < 0) /* could happen with empty buffers */
5236 xsignal0 (Qbeginning_of_buffer);
5237 else
5238 xsignal0 (Qend_of_buffer);
5240 else
5242 if (w->vscroll != 0)
5243 /* The first line was only partially visible, make it fully
5244 visible. */
5245 w->vscroll = 0;
5246 else if (noerror)
5247 return;
5248 else
5249 xsignal0 (Qbeginning_of_buffer);
5252 /* If control gets here, then we vscrolled. */
5254 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5256 /* Don't try to change the window start below. */
5257 vscrolled = 1;
5260 if (! vscrolled)
5262 int pos = IT_CHARPOS (it);
5263 int bytepos;
5265 /* If in the middle of a multi-glyph character move forward to
5266 the next character. */
5267 if (in_display_vector_p (&it))
5269 ++pos;
5270 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
5273 /* Set the window start, and set up the window for redisplay. */
5274 set_marker_restricted (w->start, make_number (pos),
5275 w->buffer);
5276 bytepos = XMARKER (w->start)->bytepos;
5277 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
5278 ? Qt : Qnil);
5279 w->update_mode_line = Qt;
5280 XSETFASTINT (w->last_modified, 0);
5281 XSETFASTINT (w->last_overlay_modified, 0);
5282 /* Set force_start so that redisplay_window will run the
5283 window-scroll-functions. */
5284 w->force_start = Qt;
5287 /* The rest of this function uses current_y in a nonstandard way,
5288 not including the height of the header line if any. */
5289 it.current_y = it.vpos = 0;
5291 /* Move PT out of scroll margins.
5292 This code wants current_y to be zero at the window start position
5293 even if there is a header line. */
5294 this_scroll_margin = max (0, scroll_margin);
5295 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
5296 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5298 if (n > 0)
5300 /* We moved the window start towards ZV, so PT may be now
5301 in the scroll margin at the top. */
5302 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5303 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5304 && (NILP (Vscroll_preserve_screen_position)
5305 || EQ (Vscroll_preserve_screen_position, Qt)))
5306 /* We found PT at a legitimate height. Leave it alone. */
5308 else if (window_scroll_pixel_based_preserve_y >= 0)
5310 /* If we have a header line, take account of it.
5311 This is necessary because we set it.current_y to 0, above. */
5312 move_it_to (&it, -1, -1,
5313 window_scroll_pixel_based_preserve_y
5314 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
5315 -1, MOVE_TO_Y);
5316 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5318 else
5320 while (it.current_y < this_scroll_margin)
5322 int prev = it.current_y;
5323 move_it_by_lines (&it, 1, 1);
5324 if (prev == it.current_y)
5325 break;
5327 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5330 else if (n < 0)
5332 int charpos, bytepos;
5333 int partial_p;
5335 /* Save our position, for the
5336 window_scroll_pixel_based_preserve_y case. */
5337 charpos = IT_CHARPOS (it);
5338 bytepos = IT_BYTEPOS (it);
5340 /* We moved the window start towards BEGV, so PT may be now
5341 in the scroll margin at the bottom. */
5342 move_it_to (&it, PT, -1,
5343 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5344 - this_scroll_margin - 1),
5346 MOVE_TO_POS | MOVE_TO_Y);
5348 /* Save our position, in case it's correct. */
5349 charpos = IT_CHARPOS (it);
5350 bytepos = IT_BYTEPOS (it);
5352 /* See if point is on a partially visible line at the end. */
5353 if (it.what == IT_EOB)
5354 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5355 else
5357 move_it_by_lines (&it, 1, 1);
5358 partial_p = it.current_y > it.last_visible_y;
5361 if (charpos == PT && !partial_p
5362 && (NILP (Vscroll_preserve_screen_position)
5363 || EQ (Vscroll_preserve_screen_position, Qt)))
5364 /* We found PT before we found the display margin, so PT is ok. */
5366 else if (window_scroll_pixel_based_preserve_y >= 0)
5368 SET_TEXT_POS_FROM_MARKER (start, w->start);
5369 start_display (&it, w, start);
5370 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5371 here because we called start_display again and did not
5372 alter it.current_y this time. */
5373 move_it_to (&it, -1, -1, window_scroll_pixel_based_preserve_y, -1,
5374 MOVE_TO_Y);
5375 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5377 else
5379 if (partial_p)
5380 /* The last line was only partially visible, so back up two
5381 lines to make sure we're on a fully visible line. */
5383 move_it_by_lines (&it, -2, 0);
5384 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5386 else
5387 /* No, the position we saved is OK, so use it. */
5388 SET_PT_BOTH (charpos, bytepos);
5394 /* Implementation of window_scroll that works based on screen lines.
5395 See the comment of window_scroll for parameter descriptions. */
5397 static void
5398 window_scroll_line_based (window, n, whole, noerror)
5399 Lisp_Object window;
5400 int n;
5401 int whole;
5402 int noerror;
5404 register struct window *w = XWINDOW (window);
5405 register int opoint = PT, opoint_byte = PT_BYTE;
5406 register int pos, pos_byte;
5407 register int ht = window_internal_height (w);
5408 register Lisp_Object tem;
5409 int lose;
5410 Lisp_Object bolp;
5411 int startpos;
5412 struct position posit;
5413 int original_vpos;
5415 /* If scrolling screen-fulls, compute the number of lines to
5416 scroll from the window's height. */
5417 if (whole)
5418 n *= max (1, ht - next_screen_context_lines);
5420 startpos = marker_position (w->start);
5422 posit = *compute_motion (startpos, 0, 0, 0,
5423 PT, ht, 0,
5424 -1, XINT (w->hscroll),
5425 0, w);
5426 original_vpos = posit.vpos;
5428 XSETFASTINT (tem, PT);
5429 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5431 if (NILP (tem))
5433 Fvertical_motion (make_number (- (ht / 2)), window);
5434 startpos = PT;
5437 SET_PT (startpos);
5438 lose = n < 0 && PT == BEGV;
5439 Fvertical_motion (make_number (n), window);
5440 pos = PT;
5441 pos_byte = PT_BYTE;
5442 bolp = Fbolp ();
5443 SET_PT_BOTH (opoint, opoint_byte);
5445 if (lose)
5447 if (noerror)
5448 return;
5449 else
5450 xsignal0 (Qbeginning_of_buffer);
5453 if (pos < ZV)
5455 int this_scroll_margin = scroll_margin;
5457 /* Don't use a scroll margin that is negative or too large. */
5458 if (this_scroll_margin < 0)
5459 this_scroll_margin = 0;
5461 if (XINT (w->total_lines) < 4 * scroll_margin)
5462 this_scroll_margin = XINT (w->total_lines) / 4;
5464 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
5465 w->start_at_line_beg = bolp;
5466 w->update_mode_line = Qt;
5467 XSETFASTINT (w->last_modified, 0);
5468 XSETFASTINT (w->last_overlay_modified, 0);
5469 /* Set force_start so that redisplay_window will run
5470 the window-scroll-functions. */
5471 w->force_start = Qt;
5473 if (!NILP (Vscroll_preserve_screen_position)
5474 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5476 SET_PT_BOTH (pos, pos_byte);
5477 Fvertical_motion (make_number (original_vpos), window);
5479 /* If we scrolled forward, put point enough lines down
5480 that it is outside the scroll margin. */
5481 else if (n > 0)
5483 int top_margin;
5485 if (this_scroll_margin > 0)
5487 SET_PT_BOTH (pos, pos_byte);
5488 Fvertical_motion (make_number (this_scroll_margin), window);
5489 top_margin = PT;
5491 else
5492 top_margin = pos;
5494 if (top_margin <= opoint)
5495 SET_PT_BOTH (opoint, opoint_byte);
5496 else if (!NILP (Vscroll_preserve_screen_position))
5498 SET_PT_BOTH (pos, pos_byte);
5499 Fvertical_motion (make_number (original_vpos), window);
5501 else
5502 SET_PT (top_margin);
5504 else if (n < 0)
5506 int bottom_margin;
5508 /* If we scrolled backward, put point near the end of the window
5509 but not within the scroll margin. */
5510 SET_PT_BOTH (pos, pos_byte);
5511 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
5512 if (XFASTINT (tem) == ht - this_scroll_margin)
5513 bottom_margin = PT;
5514 else
5515 bottom_margin = PT + 1;
5517 if (bottom_margin > opoint)
5518 SET_PT_BOTH (opoint, opoint_byte);
5519 else
5521 if (!NILP (Vscroll_preserve_screen_position))
5523 SET_PT_BOTH (pos, pos_byte);
5524 Fvertical_motion (make_number (original_vpos), window);
5526 else
5527 Fvertical_motion (make_number (-1), window);
5531 else
5533 if (noerror)
5534 return;
5535 else
5536 xsignal0 (Qend_of_buffer);
5541 /* Scroll selected_window up or down. If N is nil, scroll a
5542 screen-full which is defined as the height of the window minus
5543 next_screen_context_lines. If N is the symbol `-', scroll.
5544 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5545 up. This is the guts of Fscroll_up and Fscroll_down. */
5547 static void
5548 scroll_command (n, direction)
5549 Lisp_Object n;
5550 int direction;
5552 int count = SPECPDL_INDEX ();
5554 xassert (eabs (direction) == 1);
5556 /* If selected window's buffer isn't current, make it current for
5557 the moment. But don't screw up if window_scroll gets an error. */
5558 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
5560 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5561 Fset_buffer (XWINDOW (selected_window)->buffer);
5563 /* Make redisplay consider other windows than just selected_window. */
5564 ++windows_or_buffers_changed;
5567 if (NILP (n))
5568 window_scroll (selected_window, direction, 1, 0);
5569 else if (EQ (n, Qminus))
5570 window_scroll (selected_window, -direction, 1, 0);
5571 else
5573 n = Fprefix_numeric_value (n);
5574 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5577 unbind_to (count, Qnil);
5580 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
5581 doc: /* Scroll text of current window upward ARG lines.
5582 If ARG is omitted or nil, scroll upward by a near full screen.
5583 A near full screen is `next-screen-context-lines' less than a full screen.
5584 Negative ARG means scroll downward.
5585 If ARG is the atom `-', scroll downward by nearly full screen.
5586 When calling from a program, supply as argument a number, nil, or `-'. */)
5587 (arg)
5588 Lisp_Object arg;
5590 scroll_command (arg, 1);
5591 return Qnil;
5594 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
5595 doc: /* Scroll text of current window down ARG lines.
5596 If ARG is omitted or nil, scroll down by a near full screen.
5597 A near full screen is `next-screen-context-lines' less than a full screen.
5598 Negative ARG means scroll upward.
5599 If ARG is the atom `-', scroll upward by nearly full screen.
5600 When calling from a program, supply as argument a number, nil, or `-'. */)
5601 (arg)
5602 Lisp_Object arg;
5604 scroll_command (arg, -1);
5605 return Qnil;
5608 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5609 doc: /* Return the other window for \"other window scroll\" commands.
5610 If `other-window-scroll-buffer' is non-nil, a window
5611 showing that buffer is used.
5612 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5613 specifies the window. This takes precedence over
5614 `other-window-scroll-buffer'. */)
5617 Lisp_Object window;
5619 if (MINI_WINDOW_P (XWINDOW (selected_window))
5620 && !NILP (Vminibuf_scroll_window))
5621 window = Vminibuf_scroll_window;
5622 /* If buffer is specified, scroll that buffer. */
5623 else if (!NILP (Vother_window_scroll_buffer))
5625 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5626 if (NILP (window))
5627 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5629 else
5631 /* Nothing specified; look for a neighboring window on the same
5632 frame. */
5633 window = Fnext_window (selected_window, Qnil, Qnil);
5635 if (EQ (window, selected_window))
5636 /* That didn't get us anywhere; look for a window on another
5637 visible frame. */
5639 window = Fnext_window (window, Qnil, Qt);
5640 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5641 && ! EQ (window, selected_window));
5644 CHECK_LIVE_WINDOW (window);
5646 if (EQ (window, selected_window))
5647 error ("There is no other window");
5649 return window;
5652 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5653 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5654 A near full screen is `next-screen-context-lines' less than a full screen.
5655 The next window is the one below the current one; or the one at the top
5656 if the current one is at the bottom. Negative ARG means scroll downward.
5657 If ARG is the atom `-', scroll downward by nearly full screen.
5658 When calling from a program, supply as argument a number, nil, or `-'.
5660 If `other-window-scroll-buffer' is non-nil, scroll the window
5661 showing that buffer, popping the buffer up if necessary.
5662 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5663 specifies the window to scroll. This takes precedence over
5664 `other-window-scroll-buffer'. */)
5665 (arg)
5666 Lisp_Object arg;
5668 Lisp_Object window;
5669 struct window *w;
5670 int count = SPECPDL_INDEX ();
5672 window = Fother_window_for_scrolling ();
5673 w = XWINDOW (window);
5675 /* Don't screw up if window_scroll gets an error. */
5676 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5677 ++windows_or_buffers_changed;
5679 Fset_buffer (w->buffer);
5680 SET_PT (marker_position (w->pointm));
5682 if (NILP (arg))
5683 window_scroll (window, 1, 1, 1);
5684 else if (EQ (arg, Qminus))
5685 window_scroll (window, -1, 1, 1);
5686 else
5688 if (CONSP (arg))
5689 arg = Fcar (arg);
5690 CHECK_NUMBER (arg);
5691 window_scroll (window, XINT (arg), 0, 1);
5694 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5695 unbind_to (count, Qnil);
5697 return Qnil;
5700 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5701 doc: /* Scroll selected window display ARG columns left.
5702 Default for ARG is window width minus 2.
5703 Value is the total amount of leftward horizontal scrolling in
5704 effect after the change.
5705 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5706 lower bound for automatic scrolling, i.e. automatic scrolling
5707 will not scroll a window to a column less than the value returned
5708 by this function. This happens in an interactive call. */)
5709 (arg, set_minimum)
5710 register Lisp_Object arg, set_minimum;
5712 Lisp_Object result;
5713 int hscroll;
5714 struct window *w = XWINDOW (selected_window);
5716 if (NILP (arg))
5717 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5718 else
5719 arg = Fprefix_numeric_value (arg);
5721 hscroll = XINT (w->hscroll) + XINT (arg);
5722 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5724 if (!NILP (set_minimum))
5725 w->min_hscroll = w->hscroll;
5727 return result;
5730 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5731 doc: /* Scroll selected window display ARG columns right.
5732 Default for ARG is window width minus 2.
5733 Value is the total amount of leftward horizontal scrolling in
5734 effect after the change.
5735 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5736 lower bound for automatic scrolling, i.e. automatic scrolling
5737 will not scroll a window to a column less than the value returned
5738 by this function. This happens in an interactive call. */)
5739 (arg, set_minimum)
5740 register Lisp_Object arg, set_minimum;
5742 Lisp_Object result;
5743 int hscroll;
5744 struct window *w = XWINDOW (selected_window);
5746 if (NILP (arg))
5747 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5748 else
5749 arg = Fprefix_numeric_value (arg);
5751 hscroll = XINT (w->hscroll) - XINT (arg);
5752 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5754 if (!NILP (set_minimum))
5755 w->min_hscroll = w->hscroll;
5757 return result;
5760 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5761 doc: /* Return the window which was selected when entering the minibuffer.
5762 Returns nil, if current window is not a minibuffer window. */)
5765 if (minibuf_level > 0
5766 && MINI_WINDOW_P (XWINDOW (selected_window))
5767 && WINDOW_LIVE_P (minibuf_selected_window))
5768 return minibuf_selected_window;
5770 return Qnil;
5773 /* Value is the number of lines actually displayed in window W,
5774 as opposed to its height. */
5776 static int
5777 displayed_window_lines (w)
5778 struct window *w;
5780 struct it it;
5781 struct text_pos start;
5782 int height = window_box_height (w);
5783 struct buffer *old_buffer;
5784 int bottom_y;
5786 if (XBUFFER (w->buffer) != current_buffer)
5788 old_buffer = current_buffer;
5789 set_buffer_internal (XBUFFER (w->buffer));
5791 else
5792 old_buffer = NULL;
5794 /* In case W->start is out of the accessible range, do something
5795 reasonable. This happens in Info mode when Info-scroll-down
5796 calls (recenter -1) while W->start is 1. */
5797 if (XMARKER (w->start)->charpos < BEGV)
5798 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5799 else if (XMARKER (w->start)->charpos > ZV)
5800 SET_TEXT_POS (start, ZV, ZV_BYTE);
5801 else
5802 SET_TEXT_POS_FROM_MARKER (start, w->start);
5804 start_display (&it, w, start);
5805 move_it_vertically (&it, height);
5806 bottom_y = line_bottom_y (&it);
5808 /* rms: On a non-window display,
5809 the value of it.vpos at the bottom of the screen
5810 seems to be 1 larger than window_box_height (w).
5811 This kludge fixes a bug whereby (move-to-window-line -1)
5812 when ZV is on the last screen line
5813 moves to the previous screen line instead of the last one. */
5814 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5815 height++;
5817 /* Add in empty lines at the bottom of the window. */
5818 if (bottom_y < height)
5820 int uy = FRAME_LINE_HEIGHT (it.f);
5821 it.vpos += (height - bottom_y + uy - 1) / uy;
5824 if (old_buffer)
5825 set_buffer_internal (old_buffer);
5827 return it.vpos;
5831 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5832 doc: /* Center point in window and redisplay frame.
5833 With prefix argument ARG, recenter putting point on screen line ARG
5834 relative to the current window. If ARG is negative, it counts up from the
5835 bottom of the window. (ARG should be less than the height of the window.)
5837 If ARG is omitted or nil, erase the entire frame and then redraw with point
5838 in the center of the current window. If `auto-resize-tool-bars' is set to
5839 `grow-only', this resets the tool-bar's height to the minimum height needed.
5841 Just C-u as prefix means put point in the center of the window
5842 and redisplay normally--don't erase and redraw the frame. */)
5843 (arg)
5844 register Lisp_Object arg;
5846 struct window *w = XWINDOW (selected_window);
5847 struct buffer *buf = XBUFFER (w->buffer);
5848 struct buffer *obuf = current_buffer;
5849 int center_p = 0;
5850 int charpos, bytepos;
5851 int iarg;
5852 int this_scroll_margin;
5854 /* If redisplay is suppressed due to an error, try again. */
5855 obuf->display_error_modiff = 0;
5857 if (NILP (arg))
5859 int i;
5861 /* Invalidate pixel data calculated for all compositions. */
5862 for (i = 0; i < n_compositions; i++)
5863 composition_table[i]->font = NULL;
5865 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5867 Fredraw_frame (WINDOW_FRAME (w));
5868 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5869 center_p = 1;
5871 else if (CONSP (arg)) /* Just C-u. */
5872 center_p = 1;
5873 else
5875 arg = Fprefix_numeric_value (arg);
5876 CHECK_NUMBER (arg);
5877 iarg = XINT (arg);
5880 set_buffer_internal (buf);
5882 /* Do this after making BUF current
5883 in case scroll_margin is buffer-local. */
5884 this_scroll_margin = max (0, scroll_margin);
5885 this_scroll_margin = min (this_scroll_margin,
5886 XFASTINT (w->total_lines) / 4);
5888 /* Handle centering on a graphical frame specially. Such frames can
5889 have variable-height lines and centering point on the basis of
5890 line counts would lead to strange effects. */
5891 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5893 if (center_p)
5895 struct it it;
5896 struct text_pos pt;
5898 SET_TEXT_POS (pt, PT, PT_BYTE);
5899 start_display (&it, w, pt);
5900 move_it_vertically_backward (&it, window_box_height (w) / 2);
5901 charpos = IT_CHARPOS (it);
5902 bytepos = IT_BYTEPOS (it);
5904 else if (iarg < 0)
5906 struct it it;
5907 struct text_pos pt;
5908 int nlines = -iarg;
5909 int extra_line_spacing;
5910 int h = window_box_height (w);
5912 iarg = - max (-iarg, this_scroll_margin);
5914 SET_TEXT_POS (pt, PT, PT_BYTE);
5915 start_display (&it, w, pt);
5917 /* Be sure we have the exact height of the full line containing PT. */
5918 move_it_by_lines (&it, 0, 1);
5920 /* The amount of pixels we have to move back is the window
5921 height minus what's displayed in the line containing PT,
5922 and the lines below. */
5923 it.current_y = 0;
5924 it.vpos = 0;
5925 move_it_by_lines (&it, nlines, 1);
5927 if (it.vpos == nlines)
5928 h -= it.current_y;
5929 else
5931 /* Last line has no newline */
5932 h -= line_bottom_y (&it);
5933 it.vpos++;
5936 /* Don't reserve space for extra line spacing of last line. */
5937 extra_line_spacing = it.max_extra_line_spacing;
5939 /* If we can't move down NLINES lines because we hit
5940 the end of the buffer, count in some empty lines. */
5941 if (it.vpos < nlines)
5943 nlines -= it.vpos;
5944 extra_line_spacing = it.extra_line_spacing;
5945 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5947 if (h <= 0)
5948 return Qnil;
5950 /* Now find the new top line (starting position) of the window. */
5951 start_display (&it, w, pt);
5952 it.current_y = 0;
5953 move_it_vertically_backward (&it, h);
5955 /* If extra line spacing is present, we may move too far
5956 back. This causes the last line to be only partially
5957 visible (which triggers redisplay to recenter that line
5958 in the middle), so move forward.
5959 But ignore extra line spacing on last line, as it is not
5960 considered to be part of the visible height of the line.
5962 h += extra_line_spacing;
5963 while (-it.current_y > h)
5964 move_it_by_lines (&it, 1, 1);
5966 charpos = IT_CHARPOS (it);
5967 bytepos = IT_BYTEPOS (it);
5969 else
5971 struct position pos;
5973 iarg = max (iarg, this_scroll_margin);
5975 pos = *vmotion (PT, -iarg, w);
5976 charpos = pos.bufpos;
5977 bytepos = pos.bytepos;
5980 else
5982 struct position pos;
5983 int ht = window_internal_height (w);
5985 if (center_p)
5986 iarg = ht / 2;
5987 else if (iarg < 0)
5988 iarg += ht;
5990 /* Don't let it get into the margin at either top or bottom. */
5991 iarg = max (iarg, this_scroll_margin);
5992 iarg = min (iarg, ht - this_scroll_margin - 1);
5994 pos = *vmotion (PT, - iarg, w);
5995 charpos = pos.bufpos;
5996 bytepos = pos.bytepos;
5999 /* Set the new window start. */
6000 set_marker_both (w->start, w->buffer, charpos, bytepos);
6001 w->window_end_valid = Qnil;
6003 w->optional_new_start = Qt;
6005 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
6006 w->start_at_line_beg = Qt;
6007 else
6008 w->start_at_line_beg = Qnil;
6010 set_buffer_internal (obuf);
6011 return Qnil;
6015 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
6016 0, 1, 0,
6017 doc: /* Return the height in lines of the text display area of WINDOW.
6018 WINDOW defaults to the selected window.
6019 This doesn't include the mode-line (or header-line if any) or any
6020 partial-height lines in the text display area. */)
6021 (window)
6022 Lisp_Object window;
6024 struct window *w = decode_window (window);
6025 int pixel_height = window_box_height (w);
6026 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
6027 return make_number (line_height);
6032 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
6033 1, 1, "P",
6034 doc: /* Position point relative to window.
6035 With no argument, position point at center of window.
6036 An argument specifies vertical position within the window;
6037 zero means top of window, negative means relative to bottom of window. */)
6038 (arg)
6039 Lisp_Object arg;
6041 struct window *w = XWINDOW (selected_window);
6042 int lines, start;
6043 Lisp_Object window;
6044 #if 0
6045 int this_scroll_margin;
6046 #endif
6048 window = selected_window;
6049 start = marker_position (w->start);
6050 if (start < BEGV || start > ZV)
6052 int height = window_internal_height (w);
6053 Fvertical_motion (make_number (- (height / 2)), window);
6054 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
6055 w->start_at_line_beg = Fbolp ();
6056 w->force_start = Qt;
6058 else
6059 Fgoto_char (w->start);
6061 lines = displayed_window_lines (w);
6063 #if 0
6064 this_scroll_margin = max (0, scroll_margin);
6065 this_scroll_margin = min (this_scroll_margin, lines / 4);
6066 #endif
6068 if (NILP (arg))
6069 XSETFASTINT (arg, lines / 2);
6070 else
6072 int iarg = XINT (Fprefix_numeric_value (arg));
6074 if (iarg < 0)
6075 iarg = iarg + lines;
6077 #if 0 /* This code would prevent move-to-window-line from moving point
6078 to a place inside the scroll margins (which would cause the
6079 next redisplay to scroll). I wrote this code, but then concluded
6080 it is probably better not to install it. However, it is here
6081 inside #if 0 so as not to lose it. -- rms. */
6083 /* Don't let it get into the margin at either top or bottom. */
6084 iarg = max (iarg, this_scroll_margin);
6085 iarg = min (iarg, lines - this_scroll_margin - 1);
6086 #endif
6088 arg = make_number (iarg);
6091 /* Skip past a partially visible first line. */
6092 if (w->vscroll)
6093 XSETINT (arg, XINT (arg) + 1);
6095 return Fvertical_motion (arg, window);
6100 /***********************************************************************
6101 Window Configuration
6102 ***********************************************************************/
6104 struct save_window_data
6106 EMACS_UINT size;
6107 struct Lisp_Vector *next_from_Lisp_Vector_struct;
6108 Lisp_Object selected_frame;
6109 Lisp_Object current_window;
6110 Lisp_Object current_buffer;
6111 Lisp_Object minibuf_scroll_window;
6112 Lisp_Object minibuf_selected_window;
6113 Lisp_Object root_window;
6114 Lisp_Object focus_frame;
6115 /* A vector, each of whose elements is a struct saved_window
6116 for one window. */
6117 Lisp_Object saved_windows;
6119 /* All fields above are traced by the GC.
6120 From `fame-cols' down, the fields are ignored by the GC. */
6122 int frame_cols, frame_lines, frame_menu_bar_lines;
6123 int frame_tool_bar_lines;
6126 /* This is saved as a Lisp_Vector */
6127 struct saved_window
6129 /* these first two must agree with struct Lisp_Vector in lisp.h */
6130 EMACS_UINT size;
6131 struct Lisp_Vector *next_from_Lisp_Vector_struct;
6133 Lisp_Object window;
6134 Lisp_Object buffer, start, pointm, mark;
6135 Lisp_Object left_col, top_line, total_cols, total_lines;
6136 Lisp_Object hscroll, min_hscroll;
6137 Lisp_Object parent, prev;
6138 Lisp_Object start_at_line_beg;
6139 Lisp_Object display_table;
6140 Lisp_Object orig_top_line, orig_total_lines;
6141 Lisp_Object left_margin_cols, right_margin_cols;
6142 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
6143 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
6144 Lisp_Object dedicated, resize_proportionally;
6147 #define SAVED_WINDOW_N(swv,n) \
6148 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
6150 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
6151 doc: /* Return t if OBJECT is a window-configuration object. */)
6152 (object)
6153 Lisp_Object object;
6155 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
6158 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
6159 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
6160 (config)
6161 Lisp_Object config;
6163 register struct save_window_data *data;
6164 struct Lisp_Vector *saved_windows;
6166 CHECK_WINDOW_CONFIGURATION (config);
6168 data = (struct save_window_data *) XVECTOR (config);
6169 saved_windows = XVECTOR (data->saved_windows);
6170 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6173 DEFUN ("set-window-configuration", Fset_window_configuration,
6174 Sset_window_configuration, 1, 1, 0,
6175 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
6176 CONFIGURATION must be a value previously returned
6177 by `current-window-configuration' (which see).
6178 If CONFIGURATION was made from a frame that is now deleted,
6179 only frame-independent values can be restored. In this case,
6180 the return value is nil. Otherwise the value is t. */)
6181 (configuration)
6182 Lisp_Object configuration;
6184 register struct save_window_data *data;
6185 struct Lisp_Vector *saved_windows;
6186 Lisp_Object new_current_buffer;
6187 Lisp_Object frame;
6188 FRAME_PTR f;
6189 int old_point = -1;
6191 CHECK_WINDOW_CONFIGURATION (configuration);
6193 data = (struct save_window_data *) XVECTOR (configuration);
6194 saved_windows = XVECTOR (data->saved_windows);
6196 new_current_buffer = data->current_buffer;
6197 if (NILP (XBUFFER (new_current_buffer)->name))
6198 new_current_buffer = Qnil;
6199 else
6201 if (XBUFFER (new_current_buffer) == current_buffer)
6202 /* The code further down "preserves point" by saving here PT in
6203 old_point and then setting it later back into PT. When the
6204 current-selected-window and the final-selected-window both show
6205 the current buffer, this suffers from the problem that the
6206 current PT is the window-point of the current-selected-window,
6207 while the final PT is the point of the final-selected-window, so
6208 this copy from one PT to the other would end up moving the
6209 window-point of the final-selected-window to the window-point of
6210 the current-selected-window. So we have to be careful which
6211 point of the current-buffer we copy into old_point. */
6212 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6213 && WINDOWP (selected_window)
6214 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
6215 && !EQ (selected_window, data->current_window))
6216 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6217 else
6218 old_point = PT;
6219 else
6220 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6221 point in new_current_buffer as of the last time this buffer was
6222 used. This can be non-deterministic since it can be changed by
6223 things like jit-lock by mere temporary selection of some random
6224 window that happens to show this buffer.
6225 So if possible we want this arbitrary choice of "which point" to
6226 be the one from the to-be-selected-window so as to prevent this
6227 window's cursor from being copied from another window. */
6228 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6229 /* If current_window = selected_window, its point is in BUF_PT. */
6230 && !EQ (selected_window, data->current_window))
6231 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6232 else
6233 old_point = BUF_PT (XBUFFER (new_current_buffer));
6236 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6237 f = XFRAME (frame);
6239 /* If f is a dead frame, don't bother rebuilding its window tree.
6240 However, there is other stuff we should still try to do below. */
6241 if (FRAME_LIVE_P (f))
6243 register struct window *w;
6244 register struct saved_window *p;
6245 struct window *root_window;
6246 struct window **leaf_windows;
6247 int n_leaf_windows;
6248 int k, i, n;
6250 /* If the frame has been resized since this window configuration was
6251 made, we change the frame to the size specified in the
6252 configuration, restore the configuration, and then resize it
6253 back. We keep track of the prevailing height in these variables. */
6254 int previous_frame_lines = FRAME_LINES (f);
6255 int previous_frame_cols = FRAME_COLS (f);
6256 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6257 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6259 /* The mouse highlighting code could get screwed up
6260 if it runs during this. */
6261 BLOCK_INPUT;
6263 if (data->frame_lines != previous_frame_lines
6264 || data->frame_cols != previous_frame_cols)
6265 change_frame_size (f, data->frame_lines,
6266 data->frame_cols, 0, 0, 0);
6267 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6268 if (data->frame_menu_bar_lines
6269 != previous_frame_menu_bar_lines)
6270 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
6271 make_number (0));
6272 #ifdef HAVE_WINDOW_SYSTEM
6273 if (data->frame_tool_bar_lines
6274 != previous_frame_tool_bar_lines)
6275 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
6276 make_number (0));
6277 #endif
6278 #endif
6280 /* "Swap out" point from the selected window's buffer
6281 into the window itself. (Normally the pointm of the selected
6282 window holds garbage.) We do this now, before
6283 restoring the window contents, and prevent it from
6284 being done later on when we select a new window. */
6285 if (! NILP (XWINDOW (selected_window)->buffer))
6287 w = XWINDOW (selected_window);
6288 set_marker_both (w->pointm,
6289 w->buffer,
6290 BUF_PT (XBUFFER (w->buffer)),
6291 BUF_PT_BYTE (XBUFFER (w->buffer)));
6294 windows_or_buffers_changed++;
6295 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
6297 /* Problem: Freeing all matrices and later allocating them again
6298 is a serious redisplay flickering problem. What we would
6299 really like to do is to free only those matrices not reused
6300 below. */
6301 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6302 leaf_windows
6303 = (struct window **) alloca (count_windows (root_window)
6304 * sizeof (struct window *));
6305 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6307 /* Kludge Alert!
6308 Mark all windows now on frame as "deleted".
6309 Restoring the new configuration "undeletes" any that are in it.
6311 Save their current buffers in their height fields, since we may
6312 need it later, if a buffer saved in the configuration is now
6313 dead. */
6314 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6316 for (k = 0; k < saved_windows->size; k++)
6318 p = SAVED_WINDOW_N (saved_windows, k);
6319 w = XWINDOW (p->window);
6320 w->next = Qnil;
6322 if (!NILP (p->parent))
6323 w->parent = SAVED_WINDOW_N (saved_windows,
6324 XFASTINT (p->parent))->window;
6325 else
6326 w->parent = Qnil;
6328 if (!NILP (p->prev))
6330 w->prev = SAVED_WINDOW_N (saved_windows,
6331 XFASTINT (p->prev))->window;
6332 XWINDOW (w->prev)->next = p->window;
6334 else
6336 w->prev = Qnil;
6337 if (!NILP (w->parent))
6339 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
6341 XWINDOW (w->parent)->vchild = p->window;
6342 XWINDOW (w->parent)->hchild = Qnil;
6344 else
6346 XWINDOW (w->parent)->hchild = p->window;
6347 XWINDOW (w->parent)->vchild = Qnil;
6352 /* If we squirreled away the buffer in the window's height,
6353 restore it now. */
6354 if (BUFFERP (w->total_lines))
6355 w->buffer = w->total_lines;
6356 w->left_col = p->left_col;
6357 w->top_line = p->top_line;
6358 w->total_cols = p->total_cols;
6359 w->total_lines = p->total_lines;
6360 w->hscroll = p->hscroll;
6361 w->min_hscroll = p->min_hscroll;
6362 w->display_table = p->display_table;
6363 w->orig_top_line = p->orig_top_line;
6364 w->orig_total_lines = p->orig_total_lines;
6365 w->left_margin_cols = p->left_margin_cols;
6366 w->right_margin_cols = p->right_margin_cols;
6367 w->left_fringe_width = p->left_fringe_width;
6368 w->right_fringe_width = p->right_fringe_width;
6369 w->fringes_outside_margins = p->fringes_outside_margins;
6370 w->scroll_bar_width = p->scroll_bar_width;
6371 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
6372 w->dedicated = p->dedicated;
6373 w->resize_proportionally = p->resize_proportionally;
6374 XSETFASTINT (w->last_modified, 0);
6375 XSETFASTINT (w->last_overlay_modified, 0);
6377 /* Reinstall the saved buffer and pointers into it. */
6378 if (NILP (p->buffer))
6379 w->buffer = p->buffer;
6380 else
6382 if (!NILP (XBUFFER (p->buffer)->name))
6383 /* If saved buffer is alive, install it. */
6385 w->buffer = p->buffer;
6386 w->start_at_line_beg = p->start_at_line_beg;
6387 set_marker_restricted (w->start, p->start, w->buffer);
6388 set_marker_restricted (w->pointm, p->pointm, w->buffer);
6389 Fset_marker (XBUFFER (w->buffer)->mark,
6390 p->mark, w->buffer);
6392 /* As documented in Fcurrent_window_configuration, don't
6393 restore the location of point in the buffer which was
6394 current when the window configuration was recorded. */
6395 if (!EQ (p->buffer, new_current_buffer)
6396 && XBUFFER (p->buffer) == current_buffer)
6397 Fgoto_char (w->pointm);
6399 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
6400 /* Else unless window has a live buffer, get one. */
6402 w->buffer = Fcdr (Fcar (Vbuffer_alist));
6403 /* This will set the markers to beginning of visible
6404 range. */
6405 set_marker_restricted (w->start, make_number (0), w->buffer);
6406 set_marker_restricted (w->pointm, make_number (0),w->buffer);
6407 w->start_at_line_beg = Qt;
6409 else
6410 /* Keeping window's old buffer; make sure the markers
6411 are real. */
6413 /* Set window markers at start of visible range. */
6414 if (XMARKER (w->start)->buffer == 0)
6415 set_marker_restricted (w->start, make_number (0),
6416 w->buffer);
6417 if (XMARKER (w->pointm)->buffer == 0)
6418 set_marker_restricted_both (w->pointm, w->buffer,
6419 BUF_PT (XBUFFER (w->buffer)),
6420 BUF_PT_BYTE (XBUFFER (w->buffer)));
6421 w->start_at_line_beg = Qt;
6426 FRAME_ROOT_WINDOW (f) = data->root_window;
6427 /* Prevent "swapping out point" in the old selected window
6428 using the buffer that has been restored into it.
6429 We already swapped out point that from that window's old buffer. */
6430 selected_window = Qnil;
6432 /* Arrange *not* to restore point in the buffer that was
6433 current when the window configuration was saved. */
6434 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
6435 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6436 make_number (old_point),
6437 XWINDOW (data->current_window)->buffer);
6439 Fselect_window (data->current_window, Qnil);
6440 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
6441 = selected_window;
6443 if (NILP (data->focus_frame)
6444 || (FRAMEP (data->focus_frame)
6445 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6446 Fredirect_frame_focus (frame, data->focus_frame);
6448 #if 0 /* I don't understand why this is needed, and it causes problems
6449 when the frame's old selected window has been deleted. */
6450 if (f != selected_frame && FRAME_WINDOW_P (f))
6451 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
6452 0, 0);
6453 #endif
6455 /* Set the screen height to the value it had before this function. */
6456 if (previous_frame_lines != FRAME_LINES (f)
6457 || previous_frame_cols != FRAME_COLS (f))
6458 change_frame_size (f, previous_frame_lines, previous_frame_cols,
6459 0, 0, 0);
6460 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6461 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
6462 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
6463 make_number (0));
6464 #ifdef HAVE_WINDOW_SYSTEM
6465 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
6466 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
6467 make_number (0));
6468 #endif
6469 #endif
6471 /* Now, free glyph matrices in windows that were not reused. */
6472 for (i = n = 0; i < n_leaf_windows; ++i)
6474 if (NILP (leaf_windows[i]->buffer))
6476 /* Assert it's not reused as a combination. */
6477 xassert (NILP (leaf_windows[i]->hchild)
6478 && NILP (leaf_windows[i]->vchild));
6479 free_window_matrices (leaf_windows[i]);
6481 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
6482 ++n;
6485 adjust_glyphs (f);
6487 UNBLOCK_INPUT;
6489 /* Fselect_window will have made f the selected frame, so we
6490 reselect the proper frame here. Fhandle_switch_frame will change the
6491 selected window too, but that doesn't make the call to
6492 Fselect_window above totally superfluous; it still sets f's
6493 selected window. */
6494 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6495 do_switch_frame (data->selected_frame, 0, 0);
6497 run_window_configuration_change_hook (f);
6500 if (!NILP (new_current_buffer))
6501 Fset_buffer (new_current_buffer);
6503 Vminibuf_scroll_window = data->minibuf_scroll_window;
6504 minibuf_selected_window = data->minibuf_selected_window;
6506 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6509 /* Mark all windows now on frame as deleted
6510 by setting their buffers to nil. */
6512 void
6513 delete_all_subwindows (w)
6514 register struct window *w;
6516 if (!NILP (w->next))
6517 delete_all_subwindows (XWINDOW (w->next));
6518 if (!NILP (w->vchild))
6519 delete_all_subwindows (XWINDOW (w->vchild));
6520 if (!NILP (w->hchild))
6521 delete_all_subwindows (XWINDOW (w->hchild));
6523 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
6525 if (!NILP (w->buffer))
6526 unshow_buffer (w);
6528 /* We set all three of these fields to nil, to make sure that we can
6529 distinguish this dead window from any live window. Live leaf
6530 windows will have buffer set, and combination windows will have
6531 vchild or hchild set. */
6532 w->buffer = Qnil;
6533 w->vchild = Qnil;
6534 w->hchild = Qnil;
6536 Vwindow_list = Qnil;
6539 static int
6540 count_windows (window)
6541 register struct window *window;
6543 register int count = 1;
6544 if (!NILP (window->next))
6545 count += count_windows (XWINDOW (window->next));
6546 if (!NILP (window->vchild))
6547 count += count_windows (XWINDOW (window->vchild));
6548 if (!NILP (window->hchild))
6549 count += count_windows (XWINDOW (window->hchild));
6550 return count;
6554 /* Fill vector FLAT with leaf windows under W, starting at index I.
6555 Value is last index + 1. */
6557 static int
6558 get_leaf_windows (w, flat, i)
6559 struct window *w;
6560 struct window **flat;
6561 int i;
6563 while (w)
6565 if (!NILP (w->hchild))
6566 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
6567 else if (!NILP (w->vchild))
6568 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
6569 else
6570 flat[i++] = w;
6572 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6575 return i;
6579 /* Return a pointer to the glyph W's physical cursor is on. Value is
6580 null if W's current matrix is invalid, so that no meaningfull glyph
6581 can be returned. */
6583 struct glyph *
6584 get_phys_cursor_glyph (w)
6585 struct window *w;
6587 struct glyph_row *row;
6588 struct glyph *glyph;
6590 if (w->phys_cursor.vpos >= 0
6591 && w->phys_cursor.vpos < w->current_matrix->nrows
6592 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
6593 row->enabled_p)
6594 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
6595 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
6596 else
6597 glyph = NULL;
6599 return glyph;
6603 static int
6604 save_window_save (window, vector, i)
6605 Lisp_Object window;
6606 struct Lisp_Vector *vector;
6607 int i;
6609 register struct saved_window *p;
6610 register struct window *w;
6611 register Lisp_Object tem;
6613 for (;!NILP (window); window = w->next)
6615 p = SAVED_WINDOW_N (vector, i);
6616 w = XWINDOW (window);
6618 XSETFASTINT (w->temslot, i); i++;
6619 p->window = window;
6620 p->buffer = w->buffer;
6621 p->left_col = w->left_col;
6622 p->top_line = w->top_line;
6623 p->total_cols = w->total_cols;
6624 p->total_lines = w->total_lines;
6625 p->hscroll = w->hscroll;
6626 p->min_hscroll = w->min_hscroll;
6627 p->display_table = w->display_table;
6628 p->orig_top_line = w->orig_top_line;
6629 p->orig_total_lines = w->orig_total_lines;
6630 p->left_margin_cols = w->left_margin_cols;
6631 p->right_margin_cols = w->right_margin_cols;
6632 p->left_fringe_width = w->left_fringe_width;
6633 p->right_fringe_width = w->right_fringe_width;
6634 p->fringes_outside_margins = w->fringes_outside_margins;
6635 p->scroll_bar_width = w->scroll_bar_width;
6636 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6637 p->dedicated = w->dedicated;
6638 p->resize_proportionally = w->resize_proportionally;
6639 if (!NILP (w->buffer))
6641 /* Save w's value of point in the window configuration.
6642 If w is the selected window, then get the value of point
6643 from the buffer; pointm is garbage in the selected window. */
6644 if (EQ (window, selected_window))
6646 p->pointm = Fmake_marker ();
6647 set_marker_both (p->pointm, w->buffer,
6648 BUF_PT (XBUFFER (w->buffer)),
6649 BUF_PT_BYTE (XBUFFER (w->buffer)));
6651 else
6652 p->pointm = Fcopy_marker (w->pointm, Qnil);
6654 p->start = Fcopy_marker (w->start, Qnil);
6655 p->start_at_line_beg = w->start_at_line_beg;
6657 tem = XBUFFER (w->buffer)->mark;
6658 p->mark = Fcopy_marker (tem, Qnil);
6660 else
6662 p->pointm = Qnil;
6663 p->start = Qnil;
6664 p->mark = Qnil;
6665 p->start_at_line_beg = Qnil;
6668 if (NILP (w->parent))
6669 p->parent = Qnil;
6670 else
6671 p->parent = XWINDOW (w->parent)->temslot;
6673 if (NILP (w->prev))
6674 p->prev = Qnil;
6675 else
6676 p->prev = XWINDOW (w->prev)->temslot;
6678 if (!NILP (w->vchild))
6679 i = save_window_save (w->vchild, vector, i);
6680 if (!NILP (w->hchild))
6681 i = save_window_save (w->hchild, vector, i);
6684 return i;
6687 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6688 Scurrent_window_configuration, 0, 1, 0,
6689 doc: /* Return an object representing the current window configuration of FRAME.
6690 If FRAME is nil or omitted, use the selected frame.
6691 This describes the number of windows, their sizes and current buffers,
6692 and for each displayed buffer, where display starts, and the positions of
6693 point and mark. An exception is made for point in the current buffer:
6694 its value is -not- saved.
6695 This also records the currently selected frame, and FRAME's focus
6696 redirection (see `redirect-frame-focus'). */)
6697 (frame)
6698 Lisp_Object frame;
6700 register Lisp_Object tem;
6701 register int n_windows;
6702 register struct save_window_data *data;
6703 register int i;
6704 FRAME_PTR f;
6706 if (NILP (frame))
6707 frame = selected_frame;
6708 CHECK_LIVE_FRAME (frame);
6709 f = XFRAME (frame);
6711 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6712 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6713 PVEC_WINDOW_CONFIGURATION);
6715 data->frame_cols = FRAME_COLS (f);
6716 data->frame_lines = FRAME_LINES (f);
6717 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6718 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6719 data->selected_frame = selected_frame;
6720 data->current_window = FRAME_SELECTED_WINDOW (f);
6721 XSETBUFFER (data->current_buffer, current_buffer);
6722 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6723 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6724 data->root_window = FRAME_ROOT_WINDOW (f);
6725 data->focus_frame = FRAME_FOCUS_FRAME (f);
6726 tem = Fmake_vector (make_number (n_windows), Qnil);
6727 data->saved_windows = tem;
6728 for (i = 0; i < n_windows; i++)
6729 XVECTOR (tem)->contents[i]
6730 = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
6731 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6732 XSETWINDOW_CONFIGURATION (tem, data);
6733 return (tem);
6736 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
6737 0, UNEVALLED, 0,
6738 doc: /* Execute BODY, preserving window sizes and contents.
6739 Return the value of the last form in BODY.
6740 Restore which buffer appears in which window, where display starts,
6741 and the value of point and mark for each window.
6742 Also restore the choice of selected window.
6743 Also restore which buffer is current.
6744 Does not restore the value of point in current buffer.
6745 usage: (save-window-excursion BODY...) */)
6746 (args)
6747 Lisp_Object args;
6749 register Lisp_Object val;
6750 register int count = SPECPDL_INDEX ();
6752 record_unwind_protect (Fset_window_configuration,
6753 Fcurrent_window_configuration (Qnil));
6754 val = Fprogn (args);
6755 return unbind_to (count, val);
6760 /***********************************************************************
6761 Window Split Tree
6762 ***********************************************************************/
6764 static Lisp_Object
6765 window_tree (w)
6766 struct window *w;
6768 Lisp_Object tail = Qnil;
6769 Lisp_Object result = Qnil;
6771 while (w)
6773 Lisp_Object wn;
6775 XSETWINDOW (wn, w);
6776 if (!NILP (w->hchild))
6777 wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
6778 window_tree (XWINDOW (w->hchild))));
6779 else if (!NILP (w->vchild))
6780 wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
6781 window_tree (XWINDOW (w->vchild))));
6783 if (NILP (result))
6785 result = tail = Fcons (wn, Qnil);
6787 else
6789 XSETCDR (tail, Fcons (wn, Qnil));
6790 tail = XCDR (tail);
6793 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6796 return result;
6801 DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
6802 0, 1, 0,
6803 doc: /* Return the window tree for frame FRAME.
6805 The return value is a list of the form (ROOT MINI), where ROOT
6806 represents the window tree of the frame's root window, and MINI
6807 is the frame's minibuffer window.
6809 If the root window is not split, ROOT is the root window itself.
6810 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6811 horizontal split, and t for a vertical split, EDGES gives the combined
6812 size and position of the subwindows in the split, and the rest of the
6813 elements are the subwindows in the split. Each of the subwindows may
6814 again be a window or a list representing a window split, and so on.
6815 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6817 If FRAME is nil or omitted, return information on the currently
6818 selected frame. */)
6819 (frame)
6820 Lisp_Object frame;
6822 FRAME_PTR f;
6824 if (NILP (frame))
6825 frame = selected_frame;
6827 CHECK_FRAME (frame);
6828 f = XFRAME (frame);
6830 if (!FRAME_LIVE_P (f))
6831 return Qnil;
6833 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
6837 /***********************************************************************
6838 Marginal Areas
6839 ***********************************************************************/
6841 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6842 2, 3, 0,
6843 doc: /* Set width of marginal areas of window WINDOW.
6844 If WINDOW is nil, set margins of the currently selected window.
6845 Second arg LEFT-WIDTH specifies the number of character cells to
6846 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6847 does the same for the right marginal area. A nil width parameter
6848 means no margin. */)
6849 (window, left_width, right_width)
6850 Lisp_Object window, left_width, right_width;
6852 struct window *w = decode_window (window);
6854 /* Translate negative or zero widths to nil.
6855 Margins that are too wide have to be checked elsewhere. */
6857 if (!NILP (left_width))
6859 CHECK_NUMBER (left_width);
6860 if (XINT (left_width) <= 0)
6861 left_width = Qnil;
6864 if (!NILP (right_width))
6866 CHECK_NUMBER (right_width);
6867 if (XINT (right_width) <= 0)
6868 right_width = Qnil;
6871 if (!EQ (w->left_margin_cols, left_width)
6872 || !EQ (w->right_margin_cols, right_width))
6874 w->left_margin_cols = left_width;
6875 w->right_margin_cols = right_width;
6877 adjust_window_margins (w);
6879 ++windows_or_buffers_changed;
6880 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6883 return Qnil;
6887 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6888 0, 1, 0,
6889 doc: /* Get width of marginal areas of window WINDOW.
6890 If WINDOW is omitted or nil, use the currently selected window.
6891 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6892 If a marginal area does not exist, its width will be returned
6893 as nil. */)
6894 (window)
6895 Lisp_Object window;
6897 struct window *w = decode_window (window);
6898 return Fcons (w->left_margin_cols, w->right_margin_cols);
6903 /***********************************************************************
6904 Fringes
6905 ***********************************************************************/
6907 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6908 2, 4, 0,
6909 doc: /* Set the fringe widths of window WINDOW.
6910 If WINDOW is nil, set the fringe widths of the currently selected
6911 window.
6912 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6913 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6914 fringe width. If a fringe width arg is nil, that means to use the
6915 frame's default fringe width. Default fringe widths can be set with
6916 the command `set-fringe-style'.
6917 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6918 outside of the display margins. By default, fringes are drawn between
6919 display marginal areas and the text area. */)
6920 (window, left_width, right_width, outside_margins)
6921 Lisp_Object window, left_width, right_width, outside_margins;
6923 struct window *w = decode_window (window);
6925 if (!NILP (left_width))
6926 CHECK_NATNUM (left_width);
6927 if (!NILP (right_width))
6928 CHECK_NATNUM (right_width);
6930 /* Do nothing on a tty. */
6931 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6932 && (!EQ (w->left_fringe_width, left_width)
6933 || !EQ (w->right_fringe_width, right_width)
6934 || !EQ (w->fringes_outside_margins, outside_margins)))
6936 w->left_fringe_width = left_width;
6937 w->right_fringe_width = right_width;
6938 w->fringes_outside_margins = outside_margins;
6940 adjust_window_margins (w);
6942 clear_glyph_matrix (w->current_matrix);
6943 w->window_end_valid = Qnil;
6945 ++windows_or_buffers_changed;
6946 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6949 return Qnil;
6953 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6954 0, 1, 0,
6955 doc: /* Get width of fringes of window WINDOW.
6956 If WINDOW is omitted or nil, use the currently selected window.
6957 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6958 (window)
6959 Lisp_Object window;
6961 struct window *w = decode_window (window);
6963 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6964 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6965 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6966 ? Qt : Qnil), Qnil)));
6971 /***********************************************************************
6972 Scroll bars
6973 ***********************************************************************/
6975 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6976 2, 4, 0,
6977 doc: /* Set width and type of scroll bars of window WINDOW.
6978 If window is nil, set scroll bars of the currently selected window.
6979 Second parameter WIDTH specifies the pixel width for the scroll bar;
6980 this is automatically adjusted to a multiple of the frame column width.
6981 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6982 bar: left, right, or nil.
6983 If WIDTH is nil, use the frame's scroll-bar width.
6984 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6985 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6986 (window, width, vertical_type, horizontal_type)
6987 Lisp_Object window, width, vertical_type, horizontal_type;
6989 struct window *w = decode_window (window);
6991 if (!NILP (width))
6993 CHECK_NATNUM (width);
6995 if (XINT (width) == 0)
6996 vertical_type = Qnil;
6999 if (!(NILP (vertical_type)
7000 || EQ (vertical_type, Qleft)
7001 || EQ (vertical_type, Qright)
7002 || EQ (vertical_type, Qt)))
7003 error ("Invalid type of vertical scroll bar");
7005 if (!EQ (w->scroll_bar_width, width)
7006 || !EQ (w->vertical_scroll_bar_type, vertical_type))
7008 w->scroll_bar_width = width;
7009 w->vertical_scroll_bar_type = vertical_type;
7011 adjust_window_margins (w);
7013 clear_glyph_matrix (w->current_matrix);
7014 w->window_end_valid = Qnil;
7016 ++windows_or_buffers_changed;
7017 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
7020 return Qnil;
7024 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
7025 0, 1, 0,
7026 doc: /* Get width and type of scroll bars of window WINDOW.
7027 If WINDOW is omitted or nil, use the currently selected window.
7028 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
7029 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
7030 value. */)
7031 (window)
7032 Lisp_Object window;
7034 struct window *w = decode_window (window);
7035 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
7036 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
7037 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
7038 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
7039 Fcons (w->vertical_scroll_bar_type,
7040 Fcons (Qnil, Qnil))));
7045 /***********************************************************************
7046 Smooth scrolling
7047 ***********************************************************************/
7049 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
7050 doc: /* Return the amount by which WINDOW is scrolled vertically.
7051 Use the selected window if WINDOW is nil or omitted.
7052 Normally, value is a multiple of the canonical character height of WINDOW;
7053 optional second arg PIXELS-P means value is measured in pixels. */)
7054 (window, pixels_p)
7055 Lisp_Object window, pixels_p;
7057 Lisp_Object result;
7058 struct frame *f;
7059 struct window *w;
7061 if (NILP (window))
7062 window = selected_window;
7063 else
7064 CHECK_WINDOW (window);
7065 w = XWINDOW (window);
7066 f = XFRAME (w->frame);
7068 if (FRAME_WINDOW_P (f))
7069 result = (NILP (pixels_p)
7070 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
7071 : make_number (-w->vscroll));
7072 else
7073 result = make_number (0);
7074 return result;
7078 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
7079 2, 3, 0,
7080 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
7081 WINDOW nil means use the selected window. Normally, VSCROLL is a
7082 non-negative multiple of the canonical character height of WINDOW;
7083 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
7084 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
7085 corresponds to an integral number of pixels. The return value is the
7086 result of this rounding.
7087 If PIXELS-P is non-nil, the return value is VSCROLL. */)
7088 (window, vscroll, pixels_p)
7089 Lisp_Object window, vscroll, pixels_p;
7091 struct window *w;
7092 struct frame *f;
7094 if (NILP (window))
7095 window = selected_window;
7096 else
7097 CHECK_WINDOW (window);
7098 CHECK_NUMBER_OR_FLOAT (vscroll);
7100 w = XWINDOW (window);
7101 f = XFRAME (w->frame);
7103 if (FRAME_WINDOW_P (f))
7105 int old_dy = w->vscroll;
7107 w->vscroll = - (NILP (pixels_p)
7108 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
7109 : XFLOATINT (vscroll));
7110 w->vscroll = min (w->vscroll, 0);
7112 if (w->vscroll != old_dy)
7114 /* Adjust glyph matrix of the frame if the virtual display
7115 area becomes larger than before. */
7116 if (w->vscroll < 0 && w->vscroll < old_dy)
7117 adjust_glyphs (f);
7119 /* Prevent redisplay shortcuts. */
7120 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
7124 return Fwindow_vscroll (window, pixels_p);
7128 /* Call FN for all leaf windows on frame F. FN is called with the
7129 first argument being a pointer to the leaf window, and with
7130 additional argument USER_DATA. Stops when FN returns 0. */
7132 void
7133 foreach_window (f, fn, user_data)
7134 struct frame *f;
7135 int (* fn) P_ ((struct window *, void *));
7136 void *user_data;
7138 /* Fdelete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
7139 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
7140 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
7144 /* Helper function for foreach_window. Call FN for all leaf windows
7145 reachable from W. FN is called with the first argument being a
7146 pointer to the leaf window, and with additional argument USER_DATA.
7147 Stop when FN returns 0. Value is 0 if stopped by FN. */
7149 static int
7150 foreach_window_1 (w, fn, user_data)
7151 struct window *w;
7152 int (* fn) P_ ((struct window *, void *));
7153 void *user_data;
7155 int cont;
7157 for (cont = 1; w && cont;)
7159 if (!NILP (w->hchild))
7160 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
7161 else if (!NILP (w->vchild))
7162 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
7163 else
7164 cont = fn (w, user_data);
7166 w = NILP (w->next) ? 0 : XWINDOW (w->next);
7169 return cont;
7173 /* Freeze or unfreeze the window start of W unless it is a
7174 mini-window or the selected window. FREEZE_P non-null means freeze
7175 the window start. */
7177 static int
7178 freeze_window_start (w, freeze_p)
7179 struct window *w;
7180 void *freeze_p;
7182 if (MINI_WINDOW_P (w)
7183 || (WINDOWP (selected_window) /* Can be nil in corner cases. */
7184 && (w == XWINDOW (selected_window)
7185 || (MINI_WINDOW_P (XWINDOW (selected_window))
7186 && ! NILP (Vminibuf_scroll_window)
7187 && w == XWINDOW (Vminibuf_scroll_window)))))
7188 freeze_p = NULL;
7190 w->frozen_window_start_p = freeze_p != NULL;
7191 return 1;
7195 /* Freeze or unfreeze the window starts of all leaf windows on frame
7196 F, except the selected window and a mini-window. FREEZE_P non-zero
7197 means freeze the window start. */
7199 void
7200 freeze_window_starts (f, freeze_p)
7201 struct frame *f;
7202 int freeze_p;
7204 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
7208 /***********************************************************************
7209 Initialization
7210 ***********************************************************************/
7212 /* Return 1 if window configurations C1 and C2
7213 describe the same state of affairs. This is used by Fequal. */
7216 compare_window_configurations (c1, c2, ignore_positions)
7217 Lisp_Object c1, c2;
7218 int ignore_positions;
7220 register struct save_window_data *d1, *d2;
7221 struct Lisp_Vector *sw1, *sw2;
7222 int i;
7224 CHECK_WINDOW_CONFIGURATION (c1);
7225 CHECK_WINDOW_CONFIGURATION (c2);
7227 d1 = (struct save_window_data *) XVECTOR (c1);
7228 d2 = (struct save_window_data *) XVECTOR (c2);
7229 sw1 = XVECTOR (d1->saved_windows);
7230 sw2 = XVECTOR (d2->saved_windows);
7232 if (d1->frame_cols != d2->frame_cols)
7233 return 0;
7234 if (d1->frame_lines != d2->frame_lines)
7235 return 0;
7236 if (d1->frame_menu_bar_lines != d2->frame_menu_bar_lines)
7237 return 0;
7238 if (! EQ (d1->selected_frame, d2->selected_frame))
7239 return 0;
7240 /* Don't compare the current_window field directly.
7241 Instead see w1_is_current and w2_is_current, below. */
7242 if (! EQ (d1->current_buffer, d2->current_buffer))
7243 return 0;
7244 if (! ignore_positions)
7246 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
7247 return 0;
7248 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
7249 return 0;
7251 /* Don't compare the root_window field.
7252 We don't require the two configurations
7253 to use the same window object,
7254 and the two root windows must be equivalent
7255 if everything else compares equal. */
7256 if (! EQ (d1->focus_frame, d2->focus_frame))
7257 return 0;
7259 /* Verify that the two confis have the same number of windows. */
7260 if (sw1->size != sw2->size)
7261 return 0;
7263 for (i = 0; i < sw1->size; i++)
7265 struct saved_window *p1, *p2;
7266 int w1_is_current, w2_is_current;
7268 p1 = SAVED_WINDOW_N (sw1, i);
7269 p2 = SAVED_WINDOW_N (sw2, i);
7271 /* Verify that the current windows in the two
7272 configurations correspond to each other. */
7273 w1_is_current = EQ (d1->current_window, p1->window);
7274 w2_is_current = EQ (d2->current_window, p2->window);
7276 if (w1_is_current != w2_is_current)
7277 return 0;
7279 /* Verify that the corresponding windows do match. */
7280 if (! EQ (p1->buffer, p2->buffer))
7281 return 0;
7282 if (! EQ (p1->left_col, p2->left_col))
7283 return 0;
7284 if (! EQ (p1->top_line, p2->top_line))
7285 return 0;
7286 if (! EQ (p1->total_cols, p2->total_cols))
7287 return 0;
7288 if (! EQ (p1->total_lines, p2->total_lines))
7289 return 0;
7290 if (! EQ (p1->display_table, p2->display_table))
7291 return 0;
7292 if (! EQ (p1->parent, p2->parent))
7293 return 0;
7294 if (! EQ (p1->prev, p2->prev))
7295 return 0;
7296 if (! ignore_positions)
7298 if (! EQ (p1->hscroll, p2->hscroll))
7299 return 0;
7300 if (!EQ (p1->min_hscroll, p2->min_hscroll))
7301 return 0;
7302 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
7303 return 0;
7304 if (NILP (Fequal (p1->start, p2->start)))
7305 return 0;
7306 if (NILP (Fequal (p1->pointm, p2->pointm)))
7307 return 0;
7308 if (NILP (Fequal (p1->mark, p2->mark)))
7309 return 0;
7311 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
7312 return 0;
7313 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
7314 return 0;
7315 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
7316 return 0;
7317 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
7318 return 0;
7319 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
7320 return 0;
7321 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
7322 return 0;
7323 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
7324 return 0;
7327 return 1;
7330 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7331 Scompare_window_configurations, 2, 2, 0,
7332 doc: /* Compare two window configurations as regards the structure of windows.
7333 This function ignores details such as the values of point and mark
7334 and scrolling positions. */)
7335 (x, y)
7336 Lisp_Object x, y;
7338 if (compare_window_configurations (x, y, 1))
7339 return Qt;
7340 return Qnil;
7343 void
7344 init_window_once ()
7346 struct frame *f = make_initial_frame ();
7347 XSETFRAME (selected_frame, f);
7348 Vterminal_frame = selected_frame;
7349 minibuf_window = f->minibuffer_window;
7350 selected_window = f->selected_window;
7351 last_nonminibuf_frame = f;
7353 window_initialized = 1;
7356 void
7357 init_window ()
7359 Vwindow_list = Qnil;
7362 void
7363 syms_of_window ()
7365 Qscroll_up = intern ("scroll-up");
7366 staticpro (&Qscroll_up);
7368 Qscroll_down = intern ("scroll-down");
7369 staticpro (&Qscroll_down);
7371 Qwindow_size_fixed = intern ("window-size-fixed");
7372 staticpro (&Qwindow_size_fixed);
7373 Fset (Qwindow_size_fixed, Qnil);
7375 staticpro (&Qwindow_configuration_change_hook);
7376 Qwindow_configuration_change_hook
7377 = intern ("window-configuration-change-hook");
7379 Qwindowp = intern ("windowp");
7380 staticpro (&Qwindowp);
7382 Qwindow_configuration_p = intern ("window-configuration-p");
7383 staticpro (&Qwindow_configuration_p);
7385 Qwindow_live_p = intern ("window-live-p");
7386 staticpro (&Qwindow_live_p);
7388 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
7389 staticpro (&Qtemp_buffer_show_hook);
7391 staticpro (&Vwindow_list);
7393 minibuf_selected_window = Qnil;
7394 staticpro (&minibuf_selected_window);
7396 window_scroll_pixel_based_preserve_y = -1;
7398 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
7399 doc: /* Non-nil means call as function to display a help buffer.
7400 The function is called with one argument, the buffer to be displayed.
7401 Used by `with-output-to-temp-buffer'.
7402 If this function is used, then it must do the entire job of showing
7403 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7404 Vtemp_buffer_show_function = Qnil;
7406 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
7407 doc: /* If non-nil, function to call to handle `display-buffer'.
7408 It will receive two args, the buffer and a flag which if non-nil means
7409 that the currently selected window is not acceptable.
7410 It should choose or create a window, display the specified buffer in it,
7411 and return the window.
7412 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
7413 work using this function. */);
7414 Vdisplay_buffer_function = Qnil;
7416 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
7417 doc: /* *If non-nil, `display-buffer' should even the window heights.
7418 If nil, `display-buffer' will leave the window configuration alone. */);
7419 Veven_window_heights = Qt;
7421 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
7422 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7423 Vminibuf_scroll_window = Qnil;
7425 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
7426 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7427 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7428 is displayed in the `mode-line' face. */);
7429 mode_line_in_non_selected_windows = 1;
7431 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
7432 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7433 Vother_window_scroll_buffer = Qnil;
7435 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
7436 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
7437 pop_up_frames = 0;
7439 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
7440 doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7441 auto_window_vscroll_p = 1;
7443 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
7444 doc: /* *Non-nil means `display-buffer' should reuse frames.
7445 If the buffer in question is already displayed in a frame, raise that frame. */);
7446 display_buffer_reuse_frames = 0;
7448 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
7449 doc: /* Function to call to handle automatic new frame creation.
7450 It is called with no arguments and should return a newly created frame.
7452 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
7453 where `pop-up-frame-alist' would hold the default frame parameters. */);
7454 Vpop_up_frame_function = Qnil;
7456 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
7457 doc: /* *List of buffer names that should have their own special frames.
7458 Displaying a buffer with `display-buffer' or `pop-to-buffer',
7459 if its name is in this list, makes a special frame for it
7460 using `special-display-function'. See also `special-display-regexps'.
7462 An element of the list can be a list instead of just a string.
7463 There are two ways to use a list as an element:
7464 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
7465 In the first case, the FRAME-PARAMETERS are pairs of the form
7466 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7467 In the second case, FUNCTION is called with BUFFER as the first argument,
7468 followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
7469 All this is done by the function found in `special-display-function'.
7471 If the specified frame parameters include (same-buffer . t), the
7472 buffer is displayed in the currently selected window. Otherwise, if
7473 they include (same-frame . t), the buffer is displayed in a new window
7474 in the currently selected frame.
7476 If this variable appears \"not to work\", because you add a name to it
7477 but that buffer still appears in the selected window, look at the
7478 values of `same-window-buffer-names' and `same-window-regexps'.
7479 Those variables take precedence over this one. */);
7480 Vspecial_display_buffer_names = Qnil;
7482 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
7483 doc: /* *List of regexps saying which buffers should have their own special frames.
7484 When displaying a buffer with `display-buffer' or `pop-to-buffer',
7485 if any regexp in this list matches the buffer name, it makes a
7486 special frame for the buffer by calling `special-display-function'.
7488 An element of the list can be a list instead of just a string.
7489 There are two ways to use a list as an element:
7490 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
7491 In the first case, the FRAME-PARAMETERS are pairs of the form
7492 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7493 In the second case, FUNCTION is called with BUFFER as the first argument,
7494 followed by the OTHER-ARGS--it can display the buffer in any way it likes.
7495 All this is done by the function found in `special-display-function'.
7497 If the specified frame parameters include (same-buffer . t), the
7498 buffer is displayed in the currently selected window. Otherwise, if
7499 they include (same-frame . t), the buffer is displayed in a new window
7500 in the currently selected frame.
7502 If this variable appears \"not to work\", because you add a regexp to it
7503 but the matching buffers still appear in the selected window, look at the
7504 values of `same-window-buffer-names' and `same-window-regexps'.
7505 Those variables take precedence over this one. */);
7506 Vspecial_display_regexps = Qnil;
7508 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
7509 doc: /* Function to call to make a new frame for a special buffer.
7510 It is called with two arguments, the buffer and optional buffer specific
7511 data, and should return a window displaying that buffer.
7512 The default value normally makes a separate frame for the buffer,
7513 using `special-display-frame-alist' to specify the frame parameters.
7514 But if the buffer specific data includes (same-buffer . t) then the
7515 buffer is displayed in the current selected window.
7516 Otherwise if it includes (same-frame . t) then the buffer is displayed in
7517 a new window in the currently selected frame.
7519 A buffer is special if it is listed in `special-display-buffer-names'
7520 or matches a regexp in `special-display-regexps'. */);
7521 Vspecial_display_function = Qnil;
7523 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
7524 doc: /* *List of buffer names that should appear in the selected window.
7525 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
7526 switches to it in the selected window, rather than making it appear
7527 in some other window.
7529 An element of the list can be a cons cell instead of just a string.
7530 Then the car must be a string, which specifies the buffer name.
7531 This is for compatibility with `special-display-buffer-names';
7532 the cdr of the cons cell is ignored.
7534 See also `same-window-regexps'. */);
7535 Vsame_window_buffer_names = Qnil;
7537 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
7538 doc: /* *List of regexps saying which buffers should appear in the selected window.
7539 If a buffer name matches one of these regexps, then displaying it
7540 using `display-buffer' or `pop-to-buffer' switches to it
7541 in the selected window, rather than making it appear in some other window.
7543 An element of the list can be a cons cell instead of just a string.
7544 Then the car must be a string, which specifies the buffer name.
7545 This is for compatibility with `special-display-buffer-names';
7546 the cdr of the cons cell is ignored.
7548 See also `same-window-buffer-names'. */);
7549 Vsame_window_regexps = Qnil;
7551 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
7552 doc: /* *Non-nil means display-buffer should make new windows. */);
7553 pop_up_windows = 1;
7555 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
7556 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
7557 next_screen_context_lines = 2;
7559 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
7560 doc: /* *A window must be at least this tall to be eligible for splitting
7561 by `display-buffer'. The value is in line units.
7562 If there is only one window, it is split regardless of this value. */);
7563 split_height_threshold = 500;
7565 DEFVAR_LISP ("split-window-preferred-function",
7566 &Vsplit_window_preferred_function,
7567 doc: /* Function to use to split a window.
7568 This is used by `display-buffer' to allow the user to choose whether
7569 to split windows horizontally or vertically or some mix of the two.
7570 When this variable is nil, `display-buffer' splits windows vertically.
7571 Otherwise, `display-buffer' calls this function to split a window.
7572 It is called with a window as single argument and should split it in two
7573 and return the new window, or return an appropriate existing window
7574 if splitting is not eligible. */);
7575 Vsplit_window_preferred_function = Qnil;
7577 DEFVAR_INT ("window-min-height", &window_min_height,
7578 doc: /* Allow deleting windows less than this tall.
7579 The value is measured in line units. If a window wants a modeline it
7580 is counted as one line.
7582 Emacs honors settings of this variable when enlarging or shrinking
7583 windows vertically. A value less than 1 is invalid. */);
7584 window_min_height = 4;
7586 DEFVAR_INT ("window-min-width", &window_min_width,
7587 doc: /* Allow deleting windows less than this wide.
7588 The value is measured in characters and includes any fringes or
7589 the scrollbar.
7591 Emacs honors settings of this variable when enlarging or shrinking
7592 windows horizontally. A value less than 2 is invalid. */);
7593 window_min_width = 10;
7595 DEFVAR_LISP ("scroll-preserve-screen-position",
7596 &Vscroll_preserve_screen_position,
7597 doc: /* *Controls if scroll commands move point to keep its screen line unchanged.
7598 A value of nil means point does not keep its screen position except
7599 at the scroll margin or window boundary respectively.
7600 A value of t means point keeps its screen position if the scroll
7601 command moved it vertically out of the window, e.g. when scrolling
7602 by full screens.
7603 Any other value means point always keeps its screen position. */);
7604 Vscroll_preserve_screen_position = Qnil;
7606 DEFVAR_LISP ("window-configuration-change-hook",
7607 &Vwindow_configuration_change_hook,
7608 doc: /* Functions to call when window configuration changes.
7609 The buffer-local part is run once per window, with the relevant window
7610 selected; while the global part is run only once for the modified frame,
7611 with the relevant frame selected. */);
7612 Vwindow_configuration_change_hook = Qnil;
7614 defsubr (&Sselected_window);
7615 defsubr (&Sminibuffer_window);
7616 defsubr (&Swindow_minibuffer_p);
7617 defsubr (&Swindowp);
7618 defsubr (&Swindow_live_p);
7619 defsubr (&Spos_visible_in_window_p);
7620 defsubr (&Swindow_line_height);
7621 defsubr (&Swindow_buffer);
7622 defsubr (&Swindow_height);
7623 defsubr (&Swindow_width);
7624 defsubr (&Swindow_full_width_p);
7625 defsubr (&Swindow_hscroll);
7626 defsubr (&Sset_window_hscroll);
7627 defsubr (&Swindow_redisplay_end_trigger);
7628 defsubr (&Sset_window_redisplay_end_trigger);
7629 defsubr (&Swindow_edges);
7630 defsubr (&Swindow_pixel_edges);
7631 defsubr (&Swindow_inside_edges);
7632 defsubr (&Swindow_inside_pixel_edges);
7633 defsubr (&Scoordinates_in_window_p);
7634 defsubr (&Swindow_at);
7635 defsubr (&Swindow_point);
7636 defsubr (&Swindow_start);
7637 defsubr (&Swindow_end);
7638 defsubr (&Sset_window_point);
7639 defsubr (&Sset_window_start);
7640 defsubr (&Swindow_dedicated_p);
7641 defsubr (&Sset_window_dedicated_p);
7642 defsubr (&Swindow_display_table);
7643 defsubr (&Sset_window_display_table);
7644 defsubr (&Snext_window);
7645 defsubr (&Sprevious_window);
7646 defsubr (&Sother_window);
7647 defsubr (&Sget_lru_window);
7648 defsubr (&Sget_largest_window);
7649 defsubr (&Sget_buffer_window);
7650 defsubr (&Sdelete_other_windows);
7651 defsubr (&Sdelete_windows_on);
7652 defsubr (&Sreplace_buffer_in_windows);
7653 defsubr (&Sdelete_window);
7654 defsubr (&Sset_window_buffer);
7655 defsubr (&Sselect_window);
7656 defsubr (&Sspecial_display_p);
7657 defsubr (&Ssame_window_p);
7658 defsubr (&Sdisplay_buffer);
7659 defsubr (&Sforce_window_update);
7660 defsubr (&Ssplit_window);
7661 defsubr (&Senlarge_window);
7662 defsubr (&Sshrink_window);
7663 defsubr (&Sadjust_window_trailing_edge);
7664 defsubr (&Sscroll_up);
7665 defsubr (&Sscroll_down);
7666 defsubr (&Sscroll_left);
7667 defsubr (&Sscroll_right);
7668 defsubr (&Sother_window_for_scrolling);
7669 defsubr (&Sscroll_other_window);
7670 defsubr (&Sminibuffer_selected_window);
7671 defsubr (&Srecenter);
7672 defsubr (&Swindow_text_height);
7673 defsubr (&Smove_to_window_line);
7674 defsubr (&Swindow_configuration_p);
7675 defsubr (&Swindow_configuration_frame);
7676 defsubr (&Sset_window_configuration);
7677 defsubr (&Scurrent_window_configuration);
7678 defsubr (&Ssave_window_excursion);
7679 defsubr (&Swindow_tree);
7680 defsubr (&Sset_window_margins);
7681 defsubr (&Swindow_margins);
7682 defsubr (&Sset_window_fringes);
7683 defsubr (&Swindow_fringes);
7684 defsubr (&Sset_window_scroll_bars);
7685 defsubr (&Swindow_scroll_bars);
7686 defsubr (&Swindow_vscroll);
7687 defsubr (&Sset_window_vscroll);
7688 defsubr (&Scompare_window_configurations);
7689 defsubr (&Swindow_list);
7692 void
7693 keys_of_window ()
7695 initial_define_key (control_x_map, '1', "delete-other-windows");
7696 initial_define_key (control_x_map, '2', "split-window");
7697 initial_define_key (control_x_map, '0', "delete-window");
7698 initial_define_key (control_x_map, 'o', "other-window");
7699 initial_define_key (control_x_map, '^', "enlarge-window");
7700 initial_define_key (control_x_map, '<', "scroll-left");
7701 initial_define_key (control_x_map, '>', "scroll-right");
7703 initial_define_key (global_map, Ctl ('V'), "scroll-up");
7704 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7705 initial_define_key (meta_map, 'v', "scroll-down");
7707 initial_define_key (global_map, Ctl('L'), "recenter");
7708 initial_define_key (meta_map, 'r', "move-to-window-line");
7711 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7712 (do not change this comment) */