Mention doc-view.el.
[emacs.git] / src / window.c
bloba34c4200b7f4a0d23daa69c0f10dbe481f43c007
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 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
23 #include <config.h>
24 #include <stdio.h>
26 #include "lisp.h"
27 #include "buffer.h"
28 #include "keyboard.h"
29 #include "keymap.h"
30 #include "frame.h"
31 #include "window.h"
32 #include "commands.h"
33 #include "indent.h"
34 #include "termchar.h"
35 #include "disptab.h"
36 #include "dispextern.h"
37 #include "blockinput.h"
38 #include "intervals.h"
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));
67 static int window_min_size_2 P_ ((struct window *, int));
68 static int window_min_size P_ ((struct window *, 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 /* Non-nil means that windows are split horizontally, i.e. side-by-side,
167 instead of vertically by `display-buffer'. An integer value means that
168 windows may only be split horizontally if the newly created window is at
169 least as wide as that value. */
171 Lisp_Object Vprefer_window_split_horizontally;
173 /* List of buffer *names* for buffers that should have their own frames. */
175 Lisp_Object Vspecial_display_buffer_names;
177 /* List of regexps for buffer names that should have their own frames. */
179 Lisp_Object Vspecial_display_regexps;
181 /* Function to pop up a special frame. */
183 Lisp_Object Vspecial_display_function;
185 /* List of buffer *names* for buffers to appear in selected window. */
187 Lisp_Object Vsame_window_buffer_names;
189 /* List of regexps for buffer names to appear in selected window. */
191 Lisp_Object Vsame_window_regexps;
193 /* Hook run at end of temp_output_buffer_show. */
195 Lisp_Object Qtemp_buffer_show_hook;
197 /* Fdisplay_buffer always splits the largest window
198 if that window is more than this high. */
200 EMACS_INT split_height_threshold;
202 /* How to split windows (horizontally/vertically/hybrid). */
204 Lisp_Object Vsplit_window_preferred_function;
206 /* Number of lines of continuity in scrolling by screenfuls. */
208 EMACS_INT next_screen_context_lines;
210 /* Incremented for each window created. */
212 static int sequence_number;
214 /* Nonzero after init_window_once has finished. */
216 static int window_initialized;
218 /* Hook to run when window config changes. */
220 Lisp_Object Qwindow_configuration_change_hook;
221 Lisp_Object Vwindow_configuration_change_hook;
223 /* Non-nil means scroll commands try to put point
224 at the same screen height as previously. */
226 Lisp_Object Vscroll_preserve_screen_position;
228 /* Incremented by 1 whenever a window is deleted. */
230 int window_deletion_count;
232 /* Used by the function window_scroll_pixel_based */
234 static int window_scroll_pixel_based_preserve_y;
236 #if 0 /* This isn't used anywhere. */
237 /* Nonzero means we can split a frame even if it is "unsplittable". */
238 static int inhibit_frame_unsplittable;
239 #endif /* 0 */
241 extern EMACS_INT scroll_margin;
243 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
245 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
246 doc: /* Returns t if OBJECT is a window. */)
247 (object)
248 Lisp_Object object;
250 return WINDOWP (object) ? Qt : Qnil;
253 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
254 doc: /* Returns t if OBJECT is a window which is currently visible. */)
255 (object)
256 Lisp_Object object;
258 return WINDOW_LIVE_P (object) ? Qt : Qnil;
261 Lisp_Object
262 make_window ()
264 Lisp_Object val;
265 register struct window *p;
267 p = allocate_window ();
268 ++sequence_number;
269 XSETFASTINT (p->sequence_number, sequence_number);
270 XSETFASTINT (p->left_col, 0);
271 XSETFASTINT (p->top_line, 0);
272 XSETFASTINT (p->total_lines, 0);
273 XSETFASTINT (p->total_cols, 0);
274 XSETFASTINT (p->hscroll, 0);
275 XSETFASTINT (p->min_hscroll, 0);
276 p->orig_top_line = p->orig_total_lines = Qnil;
277 p->start = Fmake_marker ();
278 p->pointm = Fmake_marker ();
279 XSETFASTINT (p->use_time, 0);
280 p->frame = Qnil;
281 p->display_table = Qnil;
282 p->dedicated = Qnil;
283 p->pseudo_window_p = 0;
284 bzero (&p->cursor, sizeof (p->cursor));
285 bzero (&p->last_cursor, sizeof (p->last_cursor));
286 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
287 p->desired_matrix = p->current_matrix = 0;
288 p->nrows_scale_factor = p->ncols_scale_factor = 1;
289 p->phys_cursor_type = -1;
290 p->phys_cursor_width = -1;
291 p->must_be_updated_p = 0;
292 XSETFASTINT (p->window_end_vpos, 0);
293 XSETFASTINT (p->window_end_pos, 0);
294 p->window_end_valid = Qnil;
295 p->vscroll = 0;
296 XSETWINDOW (val, p);
297 XSETFASTINT (p->last_point, 0);
298 p->frozen_window_start_p = 0;
299 p->last_cursor_off_p = p->cursor_off_p = 0;
300 p->left_margin_cols = Qnil;
301 p->right_margin_cols = Qnil;
302 p->left_fringe_width = Qnil;
303 p->right_fringe_width = Qnil;
304 p->fringes_outside_margins = Qnil;
305 p->scroll_bar_width = Qnil;
306 p->vertical_scroll_bar_type = Qt;
308 Vwindow_list = Qnil;
309 return val;
312 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
313 doc: /* Return the window that the cursor now appears in and commands apply to. */)
316 return selected_window;
319 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
320 doc: /* Return the window used now for minibuffers.
321 If the optional argument FRAME is specified, return the minibuffer window
322 used by that frame. */)
323 (frame)
324 Lisp_Object frame;
326 if (NILP (frame))
327 frame = selected_frame;
328 CHECK_LIVE_FRAME (frame);
329 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
332 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
333 doc: /* Returns non-nil if WINDOW is a minibuffer window.
334 WINDOW defaults to the selected window. */)
335 (window)
336 Lisp_Object window;
338 struct window *w = decode_window (window);
339 return MINI_WINDOW_P (w) ? Qt : Qnil;
343 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
344 Spos_visible_in_window_p, 0, 3, 0,
345 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
346 Return nil if that position is scrolled vertically out of view.
347 If a character is only partially visible, nil is returned, unless the
348 optional argument PARTIALLY is non-nil.
349 If POS is only out of view because of horizontal scrolling, return non-nil.
350 If POS is t, it specifies the position of the last visible glyph in WINDOW.
351 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
353 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
354 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
355 where X and Y are the pixel coordinates relative to the top left corner
356 of the window. The remaining elements are omitted if the character after
357 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
358 off-window at the top and bottom of the row, ROWH is the height of the
359 display row, and VPOS is the row number (0-based) containing POS. */)
360 (pos, window, partially)
361 Lisp_Object pos, window, partially;
363 register struct window *w;
364 register int posint;
365 register struct buffer *buf;
366 struct text_pos top;
367 Lisp_Object in_window = Qnil;
368 int rtop, rbot, rowh, vpos, fully_p = 1;
369 int x, y;
371 w = decode_window (window);
372 buf = XBUFFER (w->buffer);
373 SET_TEXT_POS_FROM_MARKER (top, w->start);
375 if (EQ (pos, Qt))
376 posint = -1;
377 else if (!NILP (pos))
379 CHECK_NUMBER_COERCE_MARKER (pos);
380 posint = XINT (pos);
382 else if (w == XWINDOW (selected_window))
383 posint = PT;
384 else
385 posint = XMARKER (w->pointm)->charpos;
387 /* If position is above window start or outside buffer boundaries,
388 or if window start is out of range, position is not visible. */
389 if ((EQ (pos, Qt)
390 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
391 && CHARPOS (top) >= BUF_BEGV (buf)
392 && CHARPOS (top) <= BUF_ZV (buf)
393 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
394 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
395 in_window = Qt;
397 if (!NILP (in_window) && !NILP (partially))
399 Lisp_Object part = Qnil;
400 if (!fully_p)
401 part = list4 (make_number (rtop), make_number (rbot),
402 make_number (rowh), make_number (vpos));
403 in_window = Fcons (make_number (x),
404 Fcons (make_number (y), part));
407 return in_window;
410 DEFUN ("window-line-height", Fwindow_line_height,
411 Swindow_line_height, 0, 2, 0,
412 doc: /* Return height in pixels of text line LINE in window WINDOW.
413 If WINDOW is nil or omitted, use selected window.
415 Return height of current line if LINE is omitted or nil. Return height of
416 header or mode line if LINE is `header-line' and `mode-line'.
417 Otherwise, LINE is a text line number starting from 0. A negative number
418 counts from the end of the window.
420 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
421 in pixels of the visible part of the line, VPOS and YPOS are the
422 vertical position in lines and pixels of the line, relative to the top
423 of the first text line, and OFFBOT is the number of off-window pixels at
424 the bottom of the text line. If there are off-window pixels at the top
425 of the (first) text line, YPOS is negative.
427 Return nil if window display is not up-to-date. In that case, use
428 `pos-visible-in-window-p' to obtain the information. */)
429 (line, window)
430 Lisp_Object line, window;
432 register struct window *w;
433 register struct buffer *b;
434 struct glyph_row *row, *end_row;
435 int max_y, crop, i, n;
437 w = decode_window (window);
439 if (noninteractive
440 || w->pseudo_window_p)
441 return Qnil;
443 CHECK_BUFFER (w->buffer);
444 b = XBUFFER (w->buffer);
446 /* Fail if current matrix is not up-to-date. */
447 if (NILP (w->window_end_valid)
448 || current_buffer->clip_changed
449 || current_buffer->prevent_redisplay_optimizations_p
450 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
451 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
452 return Qnil;
454 if (NILP (line))
456 i = w->cursor.vpos;
457 if (i < 0 || i >= w->current_matrix->nrows
458 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
459 return Qnil;
460 max_y = window_text_bottom_y (w);
461 goto found_row;
464 if (EQ (line, Qheader_line))
466 if (!WINDOW_WANTS_HEADER_LINE_P (w))
467 return Qnil;
468 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
469 if (!row->enabled_p)
470 return Qnil;
471 return list4 (make_number (row->height),
472 make_number (0), make_number (0),
473 make_number (0));
476 if (EQ (line, Qmode_line))
478 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
479 if (!row->enabled_p)
480 return Qnil;
481 return list4 (make_number (row->height),
482 make_number (0), /* not accurate */
483 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
484 + window_text_bottom_y (w)),
485 make_number (0));
488 CHECK_NUMBER (line);
489 n = XINT (line);
491 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
492 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
493 max_y = window_text_bottom_y (w);
494 i = 0;
496 while ((n < 0 || i < n)
497 && row <= end_row && row->enabled_p
498 && row->y + row->height < max_y)
499 row++, i++;
501 if (row > end_row || !row->enabled_p)
502 return Qnil;
504 if (++n < 0)
506 if (-n > i)
507 return Qnil;
508 row += n;
509 i += n;
512 found_row:
513 crop = max (0, (row->y + row->height) - max_y);
514 return list4 (make_number (row->height + min (0, row->y) - crop),
515 make_number (i),
516 make_number (row->y),
517 make_number (crop));
522 static struct window *
523 decode_window (window)
524 register Lisp_Object window;
526 if (NILP (window))
527 return XWINDOW (selected_window);
529 CHECK_LIVE_WINDOW (window);
530 return XWINDOW (window);
533 static struct window *
534 decode_any_window (window)
535 register Lisp_Object window;
537 if (NILP (window))
538 return XWINDOW (selected_window);
540 CHECK_WINDOW (window);
541 return XWINDOW (window);
544 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
545 doc: /* Return the buffer that WINDOW is displaying.
546 WINDOW defaults to the selected window. */)
547 (window)
548 Lisp_Object window;
550 return decode_window (window)->buffer;
553 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
554 doc: /* Return the number of lines in WINDOW (including its mode line).
555 WINDOW defaults to the selected window. */)
556 (window)
557 Lisp_Object window;
559 return decode_any_window (window)->total_lines;
562 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
563 doc: /* Return the number of display columns in WINDOW.
564 This is the width that is usable columns available for text in WINDOW.
565 If you want to find out how many columns WINDOW takes up,
566 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
567 (window)
568 Lisp_Object window;
570 return make_number (window_box_text_cols (decode_any_window (window)));
573 DEFUN ("window-full-width-p", Fwindow_full_width_p, Swindow_full_width_p, 0, 1, 0,
574 doc: /* Return t if WINDOW is as wide as its frame.
575 WINDOW defaults to the selected window. */)
576 (window)
577 Lisp_Object window;
579 return WINDOW_FULL_WIDTH_P (decode_any_window (window)) ? Qt : Qnil;
582 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
583 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
584 WINDOW defaults to the selected window. */)
585 (window)
586 Lisp_Object window;
588 return decode_window (window)->hscroll;
591 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
592 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
593 Return NCOL. NCOL should be zero or positive.
595 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
596 window so that the location of point moves off-window. */)
597 (window, ncol)
598 Lisp_Object window, ncol;
600 struct window *w = decode_window (window);
601 int hscroll;
603 CHECK_NUMBER (ncol);
604 hscroll = max (0, XINT (ncol));
606 /* Prevent redisplay shortcuts when changing the hscroll. */
607 if (XINT (w->hscroll) != hscroll)
608 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
610 w->hscroll = make_number (hscroll);
611 return ncol;
614 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
615 Swindow_redisplay_end_trigger, 0, 1, 0,
616 doc: /* Return WINDOW's redisplay end trigger value.
617 WINDOW defaults to the selected window.
618 See `set-window-redisplay-end-trigger' for more information. */)
619 (window)
620 Lisp_Object window;
622 return decode_window (window)->redisplay_end_trigger;
625 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
626 Sset_window_redisplay_end_trigger, 2, 2, 0,
627 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
628 VALUE should be a buffer position (typically a marker) or nil.
629 If it is a buffer position, then if redisplay in WINDOW reaches a position
630 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
631 with two arguments: WINDOW, and the end trigger value.
632 Afterwards the end-trigger value is reset to nil. */)
633 (window, value)
634 register Lisp_Object window, value;
636 register struct window *w;
638 w = decode_window (window);
639 w->redisplay_end_trigger = value;
640 return value;
643 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
644 doc: /* Return a list of the edge coordinates of WINDOW.
645 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
646 RIGHT is one more than the rightmost column occupied by WINDOW,
647 and BOTTOM is one more than the bottommost row occupied by WINDOW.
648 The edges include the space used by the window's scroll bar,
649 display margins, fringes, header line, and mode line, if it has them.
650 To get the edges of the actual text area, use `window-inside-edges'. */)
651 (window)
652 Lisp_Object window;
654 register struct window *w = decode_any_window (window);
656 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
657 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
658 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
659 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
660 Qnil))));
663 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
664 doc: /* Return a list of the edge pixel coordinates of WINDOW.
665 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
666 RIGHT is one more than the rightmost x position occupied by WINDOW,
667 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
668 The pixel edges include the space used by the window's scroll bar,
669 display margins, fringes, header line, and mode line, if it has them.
670 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
671 (window)
672 Lisp_Object window;
674 register struct window *w = decode_any_window (window);
676 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
677 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
678 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
679 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
680 Qnil))));
683 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
684 doc: /* Return a list of the edge coordinates of WINDOW.
685 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
686 RIGHT is one more than the rightmost column used by text in WINDOW,
687 and BOTTOM is one more than the bottommost row used by text in WINDOW.
688 The inside edges do not include the space used by the window's scroll bar,
689 display margins, fringes, header line, and/or mode line. */)
690 (window)
691 Lisp_Object window;
693 register struct window *w = decode_any_window (window);
695 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
696 + WINDOW_LEFT_MARGIN_COLS (w)
697 + WINDOW_LEFT_FRINGE_COLS (w)),
698 make_number (WINDOW_TOP_EDGE_LINE (w)
699 + WINDOW_HEADER_LINE_LINES (w)),
700 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
701 - WINDOW_RIGHT_MARGIN_COLS (w)
702 - WINDOW_RIGHT_FRINGE_COLS (w)),
703 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
704 - WINDOW_MODE_LINE_LINES (w)));
707 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
708 doc: /* Return a list of the edge pixel coordinates of WINDOW.
709 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
710 RIGHT is one more than the rightmost x position used by text in WINDOW,
711 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
712 The inside edges do not include the space used by the window's scroll bar,
713 display margins, fringes, header line, and/or mode line. */)
714 (window)
715 Lisp_Object window;
717 register struct window *w = decode_any_window (window);
719 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
720 + WINDOW_LEFT_MARGIN_WIDTH (w)
721 + WINDOW_LEFT_FRINGE_WIDTH (w)),
722 make_number (WINDOW_TOP_EDGE_Y (w)
723 + WINDOW_HEADER_LINE_HEIGHT (w)),
724 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
725 - WINDOW_RIGHT_MARGIN_WIDTH (w)
726 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
727 make_number (WINDOW_BOTTOM_EDGE_Y (w)
728 - WINDOW_MODE_LINE_HEIGHT (w)));
731 /* Test if the character at column *X, row *Y is within window W.
732 If it is not, return ON_NOTHING;
733 if it is in the window's text area,
734 set *x and *y to its location relative to the upper left corner
735 of the window, and
736 return ON_TEXT;
737 if it is on the window's modeline, return ON_MODE_LINE;
738 if it is on the border between the window and its right sibling,
739 return ON_VERTICAL_BORDER.
740 if it is on a scroll bar,
741 return ON_SCROLL_BAR.
742 if it is on the window's top line, return ON_HEADER_LINE;
743 if it is in left or right fringe of the window,
744 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
745 to window-relative coordinates;
746 if it is in the marginal area to the left/right of the window,
747 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
748 to window-relative coordinates.
750 X and Y are frame relative pixel coordinates. */
752 static enum window_part
753 coordinates_in_window (w, x, y)
754 register struct window *w;
755 register int *x, *y;
757 struct frame *f = XFRAME (WINDOW_FRAME (w));
758 int left_x, right_x, top_y, bottom_y;
759 enum window_part part;
760 int ux = FRAME_COLUMN_WIDTH (f);
761 int x0 = WINDOW_LEFT_EDGE_X (w);
762 int x1 = WINDOW_RIGHT_EDGE_X (w);
763 /* The width of the area where the vertical line can be dragged.
764 (Between mode lines for instance. */
765 int grabbable_width = ux;
766 int lmargin_width, rmargin_width, text_left, text_right;
768 /* In what's below, we subtract 1 when computing right_x because we
769 want the rightmost pixel, which is given by left_pixel+width-1. */
770 if (w->pseudo_window_p)
772 left_x = 0;
773 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
774 top_y = WINDOW_TOP_EDGE_Y (w);
775 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
777 else
779 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
780 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
781 top_y = WINDOW_TOP_EDGE_Y (w);
782 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
785 /* Outside any interesting row? */
786 if (*y < top_y || *y >= bottom_y)
787 return ON_NOTHING;
789 /* On the mode line or header line? If it's near the start of
790 the mode or header line of window that's has a horizontal
791 sibling, say it's on the vertical line. That's to be able
792 to resize windows horizontally in case we're using toolkit
793 scroll bars. */
795 if (WINDOW_WANTS_MODELINE_P (w)
796 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
798 part = ON_MODE_LINE;
800 header_vertical_border_check:
801 /* We're somewhere on the mode line. We consider the place
802 between mode lines of horizontally adjacent mode lines
803 as the vertical border. If scroll bars on the left,
804 return the right window. */
805 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
806 || WINDOW_RIGHTMOST_P (w))
808 if (!WINDOW_LEFTMOST_P (w) && abs (*x - x0) < grabbable_width)
810 /* Convert X and Y to window relative coordinates.
811 Vertical border is at the left edge of window. */
812 *x = max (0, *x - x0);
813 *y -= top_y;
814 return ON_VERTICAL_BORDER;
817 else
819 if (abs (*x - x1) < grabbable_width)
821 /* Convert X and Y to window relative coordinates.
822 Vertical border is at the right edge of window. */
823 *x = min (x1, *x) - x0;
824 *y -= top_y;
825 return ON_VERTICAL_BORDER;
829 if (*x < x0 || *x >= x1)
830 return ON_NOTHING;
832 /* Convert X and Y to window relative coordinates.
833 Mode line starts at left edge of window. */
834 *x -= x0;
835 *y -= top_y;
836 return part;
839 if (WINDOW_WANTS_HEADER_LINE_P (w)
840 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
842 part = ON_HEADER_LINE;
843 goto header_vertical_border_check;
846 if (*x < x0 || *x >= x1)
847 return ON_NOTHING;
849 /* Outside any interesting column? */
850 if (*x < left_x || *x > right_x)
852 *y -= top_y;
853 return ON_SCROLL_BAR;
856 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
857 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
859 text_left = window_box_left (w, TEXT_AREA);
860 text_right = text_left + window_box_width (w, TEXT_AREA);
862 if (FRAME_WINDOW_P (f))
864 if (!w->pseudo_window_p
865 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
866 && !WINDOW_RIGHTMOST_P (w)
867 && (abs (*x - right_x) < grabbable_width))
869 /* Convert X and Y to window relative coordinates.
870 Vertical border is at the right edge of window. */
871 *x = min (right_x, *x) - left_x;
872 *y -= top_y;
873 return ON_VERTICAL_BORDER;
876 else
878 /* Need to say "*x > right_x" rather than >=, since on character
879 terminals, the vertical line's x coordinate is right_x. */
880 if (!w->pseudo_window_p
881 && !WINDOW_RIGHTMOST_P (w)
882 && *x > right_x - ux)
884 /* On the border on the right side of the window? Assume that
885 this area begins at RIGHT_X minus a canonical char width. */
886 *x = min (right_x, *x) - left_x;
887 *y -= top_y;
888 return ON_VERTICAL_BORDER;
892 if (*x < text_left)
894 if (lmargin_width > 0
895 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
896 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
897 : (*x < left_x + lmargin_width)))
899 *x -= left_x;
900 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
901 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
902 *y -= top_y;
903 return ON_LEFT_MARGIN;
906 /* Convert X and Y to window-relative pixel coordinates. */
907 *x -= left_x;
908 *y -= top_y;
909 return ON_LEFT_FRINGE;
912 if (*x >= text_right)
914 if (rmargin_width > 0
915 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
916 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
917 : (*x >= right_x - rmargin_width)))
919 *x -= right_x - rmargin_width;
920 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
921 *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
922 *y -= top_y;
923 return ON_RIGHT_MARGIN;
926 /* Convert X and Y to window-relative pixel coordinates. */
927 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
928 *y -= top_y;
929 return ON_RIGHT_FRINGE;
932 /* Everything special ruled out - must be on text area */
933 *x -= text_left;
934 *y -= top_y;
935 return ON_TEXT;
939 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
940 Scoordinates_in_window_p, 2, 2, 0,
941 doc: /* Return non-nil if COORDINATES are in WINDOW.
942 COORDINATES is a cons of the form (X . Y), X and Y being distances
943 measured in characters from the upper-left corner of the frame.
944 \(0 . 0) denotes the character in the upper left corner of the
945 frame.
946 If COORDINATES are in the text portion of WINDOW,
947 the coordinates relative to the window are returned.
948 If they are in the mode line of WINDOW, `mode-line' is returned.
949 If they are in the top mode line of WINDOW, `header-line' is returned.
950 If they are in the left fringe of WINDOW, `left-fringe' is returned.
951 If they are in the right fringe of WINDOW, `right-fringe' is returned.
952 If they are on the border between WINDOW and its right sibling,
953 `vertical-line' is returned.
954 If they are in the windows's left or right marginal areas, `left-margin'\n\
955 or `right-margin' is returned. */)
956 (coordinates, window)
957 register Lisp_Object coordinates, window;
959 struct window *w;
960 struct frame *f;
961 int x, y;
962 Lisp_Object lx, ly;
964 CHECK_WINDOW (window);
965 w = XWINDOW (window);
966 f = XFRAME (w->frame);
967 CHECK_CONS (coordinates);
968 lx = Fcar (coordinates);
969 ly = Fcdr (coordinates);
970 CHECK_NUMBER_OR_FLOAT (lx);
971 CHECK_NUMBER_OR_FLOAT (ly);
972 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
973 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
975 switch (coordinates_in_window (w, &x, &y))
977 case ON_NOTHING:
978 return Qnil;
980 case ON_TEXT:
981 /* X and Y are now window relative pixel coordinates. Convert
982 them to canonical char units before returning them. */
983 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
984 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
986 case ON_MODE_LINE:
987 return Qmode_line;
989 case ON_VERTICAL_BORDER:
990 return Qvertical_line;
992 case ON_HEADER_LINE:
993 return Qheader_line;
995 case ON_LEFT_FRINGE:
996 return Qleft_fringe;
998 case ON_RIGHT_FRINGE:
999 return Qright_fringe;
1001 case ON_LEFT_MARGIN:
1002 return Qleft_margin;
1004 case ON_RIGHT_MARGIN:
1005 return Qright_margin;
1007 case ON_SCROLL_BAR:
1008 /* Historically we are supposed to return nil in this case. */
1009 return Qnil;
1011 default:
1012 abort ();
1017 /* Callback for foreach_window, used in window_from_coordinates.
1018 Check if window W contains coordinates specified by USER_DATA which
1019 is actually a pointer to a struct check_window_data CW.
1021 Check if window W contains coordinates *CW->x and *CW->y. If it
1022 does, return W in *CW->window, as Lisp_Object, and return in
1023 *CW->part the part of the window under coordinates *X,*Y. Return
1024 zero from this function to stop iterating over windows. */
1026 struct check_window_data
1028 Lisp_Object *window;
1029 int *x, *y;
1030 enum window_part *part;
1033 static int
1034 check_window_containing (w, user_data)
1035 struct window *w;
1036 void *user_data;
1038 struct check_window_data *cw = (struct check_window_data *) user_data;
1039 enum window_part found;
1040 int continue_p = 1;
1042 found = coordinates_in_window (w, cw->x, cw->y);
1043 if (found != ON_NOTHING)
1045 *cw->part = found;
1046 XSETWINDOW (*cw->window, w);
1047 continue_p = 0;
1050 return continue_p;
1054 /* Find the window containing frame-relative pixel position X/Y and
1055 return it as a Lisp_Object.
1057 If X, Y is on one of the window's special `window_part' elements,
1058 set *PART to the id of that element, and return X and Y converted
1059 to window relative coordinates in WX and WY.
1061 If there is no window under X, Y return nil and leave *PART
1062 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1064 This function was previously implemented with a loop cycling over
1065 windows with Fnext_window, and starting with the frame's selected
1066 window. It turned out that this doesn't work with an
1067 implementation of next_window using Vwindow_list, because
1068 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1069 tree of F when this function is called asynchronously from
1070 note_mouse_highlight. The original loop didn't terminate in this
1071 case. */
1073 Lisp_Object
1074 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
1075 struct frame *f;
1076 int x, y;
1077 enum window_part *part;
1078 int *wx, *wy;
1079 int tool_bar_p;
1081 Lisp_Object window;
1082 struct check_window_data cw;
1083 enum window_part dummy;
1085 if (part == 0)
1086 part = &dummy;
1088 window = Qnil;
1089 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
1090 foreach_window (f, check_window_containing, &cw);
1092 /* If not found above, see if it's in the tool bar window, if a tool
1093 bar exists. */
1094 if (NILP (window)
1095 && tool_bar_p
1096 && WINDOWP (f->tool_bar_window)
1097 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1098 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
1099 != ON_NOTHING))
1101 *part = ON_TEXT;
1102 window = f->tool_bar_window;
1105 if (wx) *wx = x;
1106 if (wy) *wy = y;
1108 return window;
1111 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1112 doc: /* Return window containing coordinates X and Y on FRAME.
1113 If omitted, FRAME defaults to the currently selected frame.
1114 The top left corner of the frame is considered to be row 0,
1115 column 0. */)
1116 (x, y, frame)
1117 Lisp_Object x, y, frame;
1119 struct frame *f;
1121 if (NILP (frame))
1122 frame = selected_frame;
1123 CHECK_LIVE_FRAME (frame);
1124 f = XFRAME (frame);
1126 /* Check that arguments are integers or floats. */
1127 CHECK_NUMBER_OR_FLOAT (x);
1128 CHECK_NUMBER_OR_FLOAT (y);
1130 return window_from_coordinates (f,
1131 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1132 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1133 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1134 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1135 0, 0, 0, 0);
1138 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1139 doc: /* Return current value of point in WINDOW.
1140 WINDOW defaults to the selected window.
1142 For a nonselected window, this is the value point would have
1143 if that window were selected.
1145 Note that, when WINDOW is the selected window and its buffer
1146 is also currently selected, the value returned is the same as (point).
1147 It would be more strictly correct to return the `top-level' value
1148 of point, outside of any save-excursion forms.
1149 But that is hard to define. */)
1150 (window)
1151 Lisp_Object window;
1153 register struct window *w = decode_window (window);
1155 if (w == XWINDOW (selected_window)
1156 && current_buffer == XBUFFER (w->buffer))
1157 return Fpoint ();
1158 return Fmarker_position (w->pointm);
1161 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1162 doc: /* Return position at which display currently starts in WINDOW.
1163 WINDOW defaults to the selected window.
1164 This is updated by redisplay or by calling `set-window-start'. */)
1165 (window)
1166 Lisp_Object window;
1168 return Fmarker_position (decode_window (window)->start);
1171 /* This is text temporarily removed from the doc string below.
1173 This function returns nil if the position is not currently known.
1174 That happens when redisplay is preempted and doesn't finish.
1175 If in that case you want to compute where the end of the window would
1176 have been if redisplay had finished, do this:
1177 (save-excursion
1178 (goto-char (window-start window))
1179 (vertical-motion (1- (window-height window)) window)
1180 (point))") */
1182 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1183 doc: /* Return position at which display currently ends in WINDOW.
1184 WINDOW defaults to the selected window.
1185 This is updated by redisplay, when it runs to completion.
1186 Simply changing the buffer text or setting `window-start'
1187 does not update this value.
1188 Return nil if there is no recorded value. \(This can happen if the
1189 last redisplay of WINDOW was preempted, and did not finish.)
1190 If UPDATE is non-nil, compute the up-to-date position
1191 if it isn't already recorded. */)
1192 (window, update)
1193 Lisp_Object window, update;
1195 Lisp_Object value;
1196 struct window *w = decode_window (window);
1197 Lisp_Object buf;
1198 struct buffer *b;
1200 buf = w->buffer;
1201 CHECK_BUFFER (buf);
1202 b = XBUFFER (buf);
1204 #if 0 /* This change broke some things. We should make it later. */
1205 /* If we don't know the end position, return nil.
1206 The user can compute it with vertical-motion if he wants to.
1207 It would be nicer to do it automatically,
1208 but that's so slow that it would probably bother people. */
1209 if (NILP (w->window_end_valid))
1210 return Qnil;
1211 #endif
1213 if (! NILP (update)
1214 && ! (! NILP (w->window_end_valid)
1215 && XFASTINT (w->last_modified) >= BUF_MODIFF (b)
1216 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
1217 && !noninteractive)
1219 struct text_pos startp;
1220 struct it it;
1221 struct buffer *old_buffer = NULL;
1223 /* Cannot use Fvertical_motion because that function doesn't
1224 cope with variable-height lines. */
1225 if (b != current_buffer)
1227 old_buffer = current_buffer;
1228 set_buffer_internal (b);
1231 /* In case W->start is out of the range, use something
1232 reasonable. This situation occurred when loading a file with
1233 `-l' containing a call to `rmail' with subsequent other
1234 commands. At the end, W->start happened to be BEG, while
1235 rmail had already narrowed the buffer. */
1236 if (XMARKER (w->start)->charpos < BEGV)
1237 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1238 else if (XMARKER (w->start)->charpos > ZV)
1239 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1240 else
1241 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1243 start_display (&it, w, startp);
1244 move_it_vertically (&it, window_box_height (w));
1245 if (it.current_y < it.last_visible_y)
1246 move_it_past_eol (&it);
1247 value = make_number (IT_CHARPOS (it));
1249 if (old_buffer)
1250 set_buffer_internal (old_buffer);
1252 else
1253 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1255 return value;
1258 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1259 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1260 Return POS. */)
1261 (window, pos)
1262 Lisp_Object window, pos;
1264 register struct window *w = decode_window (window);
1266 CHECK_NUMBER_COERCE_MARKER (pos);
1267 if (w == XWINDOW (selected_window)
1268 && XBUFFER (w->buffer) == current_buffer)
1269 Fgoto_char (pos);
1270 else
1271 set_marker_restricted (w->pointm, pos, w->buffer);
1273 /* We have to make sure that redisplay updates the window to show
1274 the new value of point. */
1275 if (!EQ (window, selected_window))
1276 ++windows_or_buffers_changed;
1278 return pos;
1281 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1282 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1283 Return POS.
1284 Optional third arg NOFORCE non-nil inhibits next redisplay
1285 from overriding motion of point in order to display at this exact start. */)
1286 (window, pos, noforce)
1287 Lisp_Object window, pos, noforce;
1289 register struct window *w = decode_window (window);
1291 CHECK_NUMBER_COERCE_MARKER (pos);
1292 set_marker_restricted (w->start, pos, w->buffer);
1293 /* this is not right, but much easier than doing what is right. */
1294 w->start_at_line_beg = Qnil;
1295 if (NILP (noforce))
1296 w->force_start = Qt;
1297 w->update_mode_line = Qt;
1298 XSETFASTINT (w->last_modified, 0);
1299 XSETFASTINT (w->last_overlay_modified, 0);
1300 if (!EQ (window, selected_window))
1301 windows_or_buffers_changed++;
1303 return pos;
1306 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1307 1, 1, 0,
1308 doc: /* Return WINDOW's dedicated object, usually t or nil.
1309 See also `set-window-dedicated-p'. */)
1310 (window)
1311 Lisp_Object window;
1313 return decode_window (window)->dedicated;
1316 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1317 Sset_window_dedicated_p, 2, 2, 0,
1318 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1319 If it is dedicated, Emacs will not automatically change
1320 which buffer appears in it.
1321 The second argument is the new value for the dedication flag;
1322 non-nil means yes. */)
1323 (window, arg)
1324 Lisp_Object window, arg;
1326 register struct window *w = decode_window (window);
1328 w->dedicated = arg;
1330 return w->dedicated;
1333 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1334 0, 1, 0,
1335 doc: /* Return the display-table that WINDOW is using.
1336 WINDOW defaults to the selected window. */)
1337 (window)
1338 Lisp_Object window;
1340 return decode_window (window)->display_table;
1343 /* Get the display table for use on window W. This is either W's
1344 display table or W's buffer's display table. Ignore the specified
1345 tables if they are not valid; if no valid table is specified,
1346 return 0. */
1348 struct Lisp_Char_Table *
1349 window_display_table (w)
1350 struct window *w;
1352 struct Lisp_Char_Table *dp = NULL;
1354 if (DISP_TABLE_P (w->display_table))
1355 dp = XCHAR_TABLE (w->display_table);
1356 else if (BUFFERP (w->buffer))
1358 struct buffer *b = XBUFFER (w->buffer);
1360 if (DISP_TABLE_P (b->display_table))
1361 dp = XCHAR_TABLE (b->display_table);
1362 else if (DISP_TABLE_P (Vstandard_display_table))
1363 dp = XCHAR_TABLE (Vstandard_display_table);
1366 return dp;
1369 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1370 doc: /* Set WINDOW's display-table to TABLE. */)
1371 (window, table)
1372 register Lisp_Object window, table;
1374 register struct window *w;
1376 w = decode_window (window);
1377 w->display_table = table;
1378 return table;
1381 /* Record info on buffer window w is displaying
1382 when it is about to cease to display that buffer. */
1383 static void
1384 unshow_buffer (w)
1385 register struct window *w;
1387 Lisp_Object buf;
1388 struct buffer *b;
1390 buf = w->buffer;
1391 b = XBUFFER (buf);
1392 if (b != XMARKER (w->pointm)->buffer)
1393 abort ();
1395 #if 0
1396 if (w == XWINDOW (selected_window)
1397 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1398 /* Do this except when the selected window's buffer
1399 is being removed from some other window. */
1400 #endif
1401 /* last_window_start records the start position that this buffer
1402 had in the last window to be disconnected from it.
1403 Now that this statement is unconditional,
1404 it is possible for the buffer to be displayed in the
1405 selected window, while last_window_start reflects another
1406 window which was recently showing the same buffer.
1407 Some people might say that might be a good thing. Let's see. */
1408 b->last_window_start = marker_position (w->start);
1410 /* Point in the selected window's buffer
1411 is actually stored in that buffer, and the window's pointm isn't used.
1412 So don't clobber point in that buffer. */
1413 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1414 /* This line helps to fix Horsley's testbug.el bug. */
1415 && !(WINDOWP (b->last_selected_window)
1416 && w != XWINDOW (b->last_selected_window)
1417 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1418 temp_set_point_both (b,
1419 clip_to_bounds (BUF_BEGV (b),
1420 XMARKER (w->pointm)->charpos,
1421 BUF_ZV (b)),
1422 clip_to_bounds (BUF_BEGV_BYTE (b),
1423 marker_byte_position (w->pointm),
1424 BUF_ZV_BYTE (b)));
1426 if (WINDOWP (b->last_selected_window)
1427 && w == XWINDOW (b->last_selected_window))
1428 b->last_selected_window = Qnil;
1431 /* Put replacement into the window structure in place of old. */
1432 static void
1433 replace_window (old, replacement)
1434 Lisp_Object old, replacement;
1436 register Lisp_Object tem;
1437 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1439 /* If OLD is its frame's root_window, then replacement is the new
1440 root_window for that frame. */
1442 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1443 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1445 p->left_col = o->left_col;
1446 p->top_line = o->top_line;
1447 p->total_cols = o->total_cols;
1448 p->total_lines = o->total_lines;
1449 p->desired_matrix = p->current_matrix = 0;
1450 p->vscroll = 0;
1451 bzero (&p->cursor, sizeof (p->cursor));
1452 bzero (&p->last_cursor, sizeof (p->last_cursor));
1453 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1454 p->phys_cursor_type = -1;
1455 p->phys_cursor_width = -1;
1456 p->must_be_updated_p = 0;
1457 p->pseudo_window_p = 0;
1458 XSETFASTINT (p->window_end_vpos, 0);
1459 XSETFASTINT (p->window_end_pos, 0);
1460 p->window_end_valid = Qnil;
1461 p->frozen_window_start_p = 0;
1462 p->orig_top_line = p->orig_total_lines = Qnil;
1464 p->next = tem = o->next;
1465 if (!NILP (tem))
1466 XWINDOW (tem)->prev = replacement;
1468 p->prev = tem = o->prev;
1469 if (!NILP (tem))
1470 XWINDOW (tem)->next = replacement;
1472 p->parent = tem = o->parent;
1473 if (!NILP (tem))
1475 if (EQ (XWINDOW (tem)->vchild, old))
1476 XWINDOW (tem)->vchild = replacement;
1477 if (EQ (XWINDOW (tem)->hchild, old))
1478 XWINDOW (tem)->hchild = replacement;
1481 /*** Here, if replacement is a vertical combination
1482 and so is its new parent, we should make replacement's
1483 children be children of that parent instead. ***/
1486 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1487 doc: /* Remove WINDOW from the display. Default is selected window. */)
1488 (window)
1489 register Lisp_Object window;
1491 delete_window (window);
1493 if (! NILP (Vwindow_configuration_change_hook)
1494 && ! NILP (Vrun_hooks))
1495 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1497 return Qnil;
1500 void
1501 delete_window (window)
1502 register Lisp_Object window;
1504 register Lisp_Object tem, parent, sib;
1505 register struct window *p;
1506 register struct window *par;
1507 struct frame *f;
1509 /* Because this function is called by other C code on non-leaf
1510 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1511 so we can't decode_window here. */
1512 if (NILP (window))
1513 window = selected_window;
1514 else
1515 CHECK_WINDOW (window);
1516 p = XWINDOW (window);
1518 /* It's a no-op to delete an already-deleted window. */
1519 if (NILP (p->buffer)
1520 && NILP (p->hchild)
1521 && NILP (p->vchild))
1522 return;
1524 parent = p->parent;
1525 if (NILP (parent))
1526 error ("Attempt to delete minibuffer or sole ordinary window");
1527 par = XWINDOW (parent);
1529 windows_or_buffers_changed++;
1530 Vwindow_list = Qnil;
1531 f = XFRAME (WINDOW_FRAME (p));
1532 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1534 /* Are we trying to delete any frame's selected window? */
1536 Lisp_Object swindow, pwindow;
1538 /* See if the frame's selected window is either WINDOW
1539 or any subwindow of it, by finding all that window's parents
1540 and comparing each one with WINDOW. */
1541 swindow = FRAME_SELECTED_WINDOW (f);
1543 while (1)
1545 pwindow = swindow;
1546 while (!NILP (pwindow))
1548 if (EQ (window, pwindow))
1549 break;
1550 pwindow = XWINDOW (pwindow)->parent;
1553 /* If the window being deleted is not a parent of SWINDOW,
1554 then SWINDOW is ok as the new selected window. */
1555 if (!EQ (window, pwindow))
1556 break;
1557 /* Otherwise, try another window for SWINDOW. */
1558 swindow = Fnext_window (swindow, Qlambda, Qnil);
1560 /* If we get back to the frame's selected window,
1561 it means there was no acceptable alternative,
1562 so we cannot delete. */
1563 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1564 error ("Cannot delete window");
1567 /* If we need to change SWINDOW, do it. */
1568 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1570 /* If we're about to delete the selected window on the
1571 selected frame, then we should use Fselect_window to select
1572 the new window. On the other hand, if we're about to
1573 delete the selected window on any other frame, we shouldn't do
1574 anything but set the frame's selected_window slot. */
1575 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1576 Fselect_window (swindow, Qnil);
1577 else
1578 FRAME_SELECTED_WINDOW (f) = swindow;
1582 /* Now we know we can delete this one. */
1583 window_deletion_count++;
1585 tem = p->buffer;
1586 /* tem is null for dummy parent windows
1587 (which have inferiors but not any contents themselves) */
1588 if (!NILP (tem))
1590 unshow_buffer (p);
1591 unchain_marker (XMARKER (p->pointm));
1592 unchain_marker (XMARKER (p->start));
1595 /* Free window glyph matrices. It is sure that they are allocated
1596 again when ADJUST_GLYPHS is called. Block input so that expose
1597 events and other events that access glyph matrices are not
1598 processed while we are changing them. */
1599 BLOCK_INPUT;
1600 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1602 tem = p->next;
1603 if (!NILP (tem))
1604 XWINDOW (tem)->prev = p->prev;
1606 tem = p->prev;
1607 if (!NILP (tem))
1608 XWINDOW (tem)->next = p->next;
1610 if (EQ (window, par->hchild))
1611 par->hchild = p->next;
1612 if (EQ (window, par->vchild))
1613 par->vchild = p->next;
1615 /* Find one of our siblings to give our space to. */
1616 sib = p->prev;
1617 if (NILP (sib))
1619 /* If p gives its space to its next sibling, that sibling needs
1620 to have its top/left side pulled back to where p's is.
1621 set_window_{height,width} will re-position the sibling's
1622 children. */
1623 sib = p->next;
1624 XWINDOW (sib)->top_line = p->top_line;
1625 XWINDOW (sib)->left_col = p->left_col;
1628 /* Stretch that sibling. */
1629 if (!NILP (par->vchild))
1630 set_window_height (sib,
1631 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1633 if (!NILP (par->hchild))
1634 set_window_width (sib,
1635 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1638 /* If parent now has only one child,
1639 put the child into the parent's place. */
1640 tem = par->hchild;
1641 if (NILP (tem))
1642 tem = par->vchild;
1643 if (NILP (XWINDOW (tem)->next)) {
1644 replace_window (parent, tem);
1645 par = XWINDOW (tem);
1648 /* Since we may be deleting combination windows, we must make sure that
1649 not only p but all its children have been marked as deleted. */
1650 if (! NILP (p->hchild))
1651 delete_all_subwindows (XWINDOW (p->hchild));
1652 else if (! NILP (p->vchild))
1653 delete_all_subwindows (XWINDOW (p->vchild));
1655 /* Mark this window as deleted. */
1656 p->buffer = p->hchild = p->vchild = Qnil;
1658 if (! NILP (par->parent))
1659 par = XWINDOW (par->parent);
1661 /* Check if we have a v/hchild with a v/hchild. In that case remove
1662 one of them. */
1664 if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
1666 p = XWINDOW (par->vchild);
1667 par->vchild = p->vchild;
1668 tem = p->vchild;
1670 else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
1672 p = XWINDOW (par->hchild);
1673 par->hchild = p->hchild;
1674 tem = p->hchild;
1676 else
1677 p = 0;
1679 if (p)
1681 while (! NILP (tem)) {
1682 XWINDOW (tem)->parent = p->parent;
1683 if (NILP (XWINDOW (tem)->next))
1684 break;
1685 tem = XWINDOW (tem)->next;
1687 if (! NILP (tem)) {
1688 /* The next of the v/hchild we are removing is now the next of the
1689 last child for the v/hchild:
1690 Before v/hchild -> v/hchild -> next1 -> next2
1692 -> next3
1693 After: v/hchild -> next1 -> next2 -> next3
1695 XWINDOW (tem)->next = p->next;
1696 if (! NILP (p->next))
1697 XWINDOW (p->next)->prev = tem;
1699 p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
1703 /* Adjust glyph matrices. */
1704 adjust_glyphs (f);
1705 UNBLOCK_INPUT;
1710 /***********************************************************************
1711 Window List
1712 ***********************************************************************/
1714 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1715 pointer. This is a callback function for foreach_window, used in
1716 function window_list. */
1718 static int
1719 add_window_to_list (w, user_data)
1720 struct window *w;
1721 void *user_data;
1723 Lisp_Object *list = (Lisp_Object *) user_data;
1724 Lisp_Object window;
1725 XSETWINDOW (window, w);
1726 *list = Fcons (window, *list);
1727 return 1;
1731 /* Return a list of all windows, for use by next_window. If
1732 Vwindow_list is a list, return that list. Otherwise, build a new
1733 list, cache it in Vwindow_list, and return that. */
1735 static Lisp_Object
1736 window_list ()
1738 if (!CONSP (Vwindow_list))
1740 Lisp_Object tail;
1742 Vwindow_list = Qnil;
1743 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1745 Lisp_Object args[2];
1747 /* We are visiting windows in canonical order, and add
1748 new windows at the front of args[1], which means we
1749 have to reverse this list at the end. */
1750 args[1] = Qnil;
1751 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1752 args[0] = Vwindow_list;
1753 args[1] = Fnreverse (args[1]);
1754 Vwindow_list = Fnconc (2, args);
1758 return Vwindow_list;
1762 /* Value is non-zero if WINDOW satisfies the constraints given by
1763 OWINDOW, MINIBUF and ALL_FRAMES.
1765 MINIBUF t means WINDOW may be minibuffer windows.
1766 `lambda' means WINDOW may not be a minibuffer window.
1767 a window means a specific minibuffer window
1769 ALL_FRAMES t means search all frames,
1770 nil means search just current frame,
1771 `visible' means search just visible frames,
1772 0 means search visible and iconified frames,
1773 a window means search the frame that window belongs to,
1774 a frame means consider windows on that frame, only. */
1776 static int
1777 candidate_window_p (window, owindow, minibuf, all_frames)
1778 Lisp_Object window, owindow, minibuf, all_frames;
1780 struct window *w = XWINDOW (window);
1781 struct frame *f = XFRAME (w->frame);
1782 int candidate_p = 1;
1784 if (!BUFFERP (w->buffer))
1785 candidate_p = 0;
1786 else if (MINI_WINDOW_P (w)
1787 && (EQ (minibuf, Qlambda)
1788 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1790 /* If MINIBUF is `lambda' don't consider any mini-windows.
1791 If it is a window, consider only that one. */
1792 candidate_p = 0;
1794 else if (EQ (all_frames, Qt))
1795 candidate_p = 1;
1796 else if (NILP (all_frames))
1798 xassert (WINDOWP (owindow));
1799 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1801 else if (EQ (all_frames, Qvisible))
1803 FRAME_SAMPLE_VISIBILITY (f);
1804 candidate_p = FRAME_VISIBLE_P (f);
1806 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1808 FRAME_SAMPLE_VISIBILITY (f);
1809 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1811 else if (WINDOWP (all_frames))
1812 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1813 || EQ (XWINDOW (all_frames)->frame, w->frame)
1814 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1815 else if (FRAMEP (all_frames))
1816 candidate_p = EQ (all_frames, w->frame);
1818 return candidate_p;
1822 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1823 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1824 ALL_FRAMES. */
1826 static void
1827 decode_next_window_args (window, minibuf, all_frames)
1828 Lisp_Object *window, *minibuf, *all_frames;
1830 if (NILP (*window))
1831 *window = selected_window;
1832 else
1833 CHECK_LIVE_WINDOW (*window);
1835 /* MINIBUF nil may or may not include minibuffers. Decide if it
1836 does. */
1837 if (NILP (*minibuf))
1838 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1839 else if (!EQ (*minibuf, Qt))
1840 *minibuf = Qlambda;
1842 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1843 => count none of them, or a specific minibuffer window (the
1844 active one) to count. */
1846 /* ALL_FRAMES nil doesn't specify which frames to include. */
1847 if (NILP (*all_frames))
1848 *all_frames = (!EQ (*minibuf, Qlambda)
1849 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1850 : Qnil);
1851 else if (EQ (*all_frames, Qvisible))
1853 else if (EQ (*all_frames, make_number (0)))
1855 else if (FRAMEP (*all_frames))
1857 else if (!EQ (*all_frames, Qt))
1858 *all_frames = Qnil;
1860 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1861 search just current frame, `visible' meaning search just visible
1862 frames, 0 meaning search visible and iconified frames, or a
1863 window, meaning search the frame that window belongs to, or a
1864 frame, meaning consider windows on that frame, only. */
1868 /* Return the next or previous window of WINDOW in canonical ordering
1869 of windows. NEXT_P non-zero means return the next window. See the
1870 documentation string of next-window for the meaning of MINIBUF and
1871 ALL_FRAMES. */
1873 static Lisp_Object
1874 next_window (window, minibuf, all_frames, next_p)
1875 Lisp_Object window, minibuf, all_frames;
1876 int next_p;
1878 decode_next_window_args (&window, &minibuf, &all_frames);
1880 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1881 return the first window on the frame. */
1882 if (FRAMEP (all_frames)
1883 && !EQ (all_frames, XWINDOW (window)->frame))
1884 return Fframe_first_window (all_frames);
1886 if (next_p)
1888 Lisp_Object list;
1890 /* Find WINDOW in the list of all windows. */
1891 list = Fmemq (window, window_list ());
1893 /* Scan forward from WINDOW to the end of the window list. */
1894 if (CONSP (list))
1895 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1896 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1897 break;
1899 /* Scan from the start of the window list up to WINDOW. */
1900 if (!CONSP (list))
1901 for (list = Vwindow_list;
1902 CONSP (list) && !EQ (XCAR (list), window);
1903 list = XCDR (list))
1904 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1905 break;
1907 if (CONSP (list))
1908 window = XCAR (list);
1910 else
1912 Lisp_Object candidate, list;
1914 /* Scan through the list of windows for candidates. If there are
1915 candidate windows in front of WINDOW, the last one of these
1916 is the one we want. If there are candidates following WINDOW
1917 in the list, again the last one of these is the one we want. */
1918 candidate = Qnil;
1919 for (list = window_list (); CONSP (list); list = XCDR (list))
1921 if (EQ (XCAR (list), window))
1923 if (WINDOWP (candidate))
1924 break;
1926 else if (candidate_window_p (XCAR (list), window, minibuf,
1927 all_frames))
1928 candidate = XCAR (list);
1931 if (WINDOWP (candidate))
1932 window = candidate;
1935 return window;
1939 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1940 doc: /* Return next window after WINDOW in canonical ordering of windows.
1941 If omitted, WINDOW defaults to the selected window.
1943 Optional second arg MINIBUF t means count the minibuffer window even
1944 if not active. MINIBUF nil or omitted means count the minibuffer iff
1945 it is active. MINIBUF neither t nor nil means not to count the
1946 minibuffer even if it is active.
1948 Several frames may share a single minibuffer; if the minibuffer
1949 counts, all windows on all frames that share that minibuffer count
1950 too. Therefore, `next-window' can be used to iterate through the
1951 set of windows even when the minibuffer is on another frame. If the
1952 minibuffer does not count, only windows from WINDOW's frame count.
1954 Optional third arg ALL-FRAMES t means include windows on all frames.
1955 ALL-FRAMES nil or omitted means cycle within the frames as specified
1956 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1957 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1958 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1959 Anything else means restrict to WINDOW's frame.
1961 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1962 `next-window' to iterate through the entire cycle of acceptable
1963 windows, eventually ending up back at the window you started with.
1964 `previous-window' traverses the same cycle, in the reverse order. */)
1965 (window, minibuf, all_frames)
1966 Lisp_Object window, minibuf, all_frames;
1968 return next_window (window, minibuf, all_frames, 1);
1972 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1973 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1974 If omitted, WINDOW defaults to the selected window.
1976 Optional second arg MINIBUF t means count the minibuffer window even
1977 if not active. MINIBUF nil or omitted means count the minibuffer iff
1978 it is active. MINIBUF neither t nor nil means not to count the
1979 minibuffer even if it is active.
1981 Several frames may share a single minibuffer; if the minibuffer
1982 counts, all windows on all frames that share that minibuffer count
1983 too. Therefore, `previous-window' can be used to iterate through
1984 the set of windows even when the minibuffer is on another frame. If
1985 the minibuffer does not count, only windows from WINDOW's frame count
1987 Optional third arg ALL-FRAMES t means include windows on all frames.
1988 ALL-FRAMES nil or omitted means cycle within the frames as specified
1989 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1990 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1991 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1992 Anything else means restrict to WINDOW's frame.
1994 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1995 `previous-window' to iterate through the entire cycle of acceptable
1996 windows, eventually ending up back at the window you started with.
1997 `next-window' traverses the same cycle, in the reverse order. */)
1998 (window, minibuf, all_frames)
1999 Lisp_Object window, minibuf, all_frames;
2001 return next_window (window, minibuf, all_frames, 0);
2005 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
2006 doc: /* Select the ARG'th different window on this frame.
2007 All windows on current frame are arranged in a cyclic order.
2008 This command selects the window ARG steps away in that order.
2009 A negative ARG moves in the opposite order. The optional second
2010 argument ALL-FRAMES has the same meaning as in `next-window', which see. */)
2011 (arg, all_frames)
2012 Lisp_Object arg, all_frames;
2014 Lisp_Object window;
2015 int i;
2017 CHECK_NUMBER (arg);
2018 window = selected_window;
2020 for (i = XINT (arg); i > 0; --i)
2021 window = Fnext_window (window, Qnil, all_frames);
2022 for (; i < 0; ++i)
2023 window = Fprevious_window (window, Qnil, all_frames);
2025 Fselect_window (window, Qnil);
2026 return Qnil;
2030 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2031 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2032 FRAME nil or omitted means use the selected frame.
2033 WINDOW nil or omitted means use the selected window.
2034 MINIBUF t means include the minibuffer window, even if it isn't active.
2035 MINIBUF nil or omitted means include the minibuffer window only
2036 if it's active.
2037 MINIBUF neither nil nor t means never include the minibuffer window. */)
2038 (frame, minibuf, window)
2039 Lisp_Object frame, minibuf, window;
2041 if (NILP (window))
2042 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2043 CHECK_WINDOW (window);
2044 if (NILP (frame))
2045 frame = selected_frame;
2047 if (!EQ (frame, XWINDOW (window)->frame))
2048 error ("Window is on a different frame");
2050 return window_list_1 (window, minibuf, frame);
2054 /* Return a list of windows in canonical ordering. Arguments are like
2055 for `next-window'. */
2057 static Lisp_Object
2058 window_list_1 (window, minibuf, all_frames)
2059 Lisp_Object window, minibuf, all_frames;
2061 Lisp_Object tail, list, rest;
2063 decode_next_window_args (&window, &minibuf, &all_frames);
2064 list = Qnil;
2066 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2067 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2068 list = Fcons (XCAR (tail), list);
2070 /* Rotate the list to start with WINDOW. */
2071 list = Fnreverse (list);
2072 rest = Fmemq (window, list);
2073 if (!NILP (rest) && !EQ (rest, list))
2075 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2077 XSETCDR (tail, Qnil);
2078 list = nconc2 (rest, list);
2080 return list;
2085 /* Look at all windows, performing an operation specified by TYPE
2086 with argument OBJ.
2087 If FRAMES is Qt, look at all frames;
2088 Qnil, look at just the selected frame;
2089 Qvisible, look at visible frames;
2090 a frame, just look at windows on that frame.
2091 If MINI is non-zero, perform the operation on minibuffer windows too. */
2093 enum window_loop
2095 WINDOW_LOOP_UNUSED,
2096 GET_BUFFER_WINDOW, /* Arg is buffer */
2097 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2098 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2099 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2100 GET_LARGEST_WINDOW,
2101 UNSHOW_BUFFER, /* Arg is buffer */
2102 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2103 CHECK_ALL_WINDOWS
2106 static Lisp_Object
2107 window_loop (type, obj, mini, frames)
2108 enum window_loop type;
2109 Lisp_Object obj, frames;
2110 int mini;
2112 Lisp_Object window, windows, best_window, frame_arg;
2113 struct frame *f;
2114 struct gcpro gcpro1;
2116 /* If we're only looping through windows on a particular frame,
2117 frame points to that frame. If we're looping through windows
2118 on all frames, frame is 0. */
2119 if (FRAMEP (frames))
2120 f = XFRAME (frames);
2121 else if (NILP (frames))
2122 f = SELECTED_FRAME ();
2123 else
2124 f = NULL;
2126 if (f)
2127 frame_arg = Qlambda;
2128 else if (EQ (frames, make_number (0)))
2129 frame_arg = frames;
2130 else if (EQ (frames, Qvisible))
2131 frame_arg = frames;
2132 else
2133 frame_arg = Qt;
2135 /* frame_arg is Qlambda to stick to one frame,
2136 Qvisible to consider all visible frames,
2137 or Qt otherwise. */
2139 /* Pick a window to start with. */
2140 if (WINDOWP (obj))
2141 window = obj;
2142 else if (f)
2143 window = FRAME_SELECTED_WINDOW (f);
2144 else
2145 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2147 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2148 GCPRO1 (windows);
2149 best_window = Qnil;
2151 for (; CONSP (windows); windows = XCDR (windows))
2153 struct window *w;
2155 window = XCAR (windows);
2156 w = XWINDOW (window);
2158 /* Note that we do not pay attention here to whether the frame
2159 is visible, since Fwindow_list skips non-visible frames if
2160 that is desired, under the control of frame_arg. */
2161 if (!MINI_WINDOW_P (w)
2162 /* For UNSHOW_BUFFER, we must always consider all windows. */
2163 || type == UNSHOW_BUFFER
2164 || (mini && minibuf_level > 0))
2165 switch (type)
2167 case GET_BUFFER_WINDOW:
2168 if (EQ (w->buffer, obj)
2169 /* Don't find any minibuffer window
2170 except the one that is currently in use. */
2171 && (MINI_WINDOW_P (w)
2172 ? EQ (window, minibuf_window)
2173 : 1))
2175 if (NILP (best_window))
2176 best_window = window;
2177 else if (EQ (window, selected_window))
2178 /* For compatibility with 20.x, prefer to return
2179 selected-window. */
2180 best_window = window;
2182 break;
2184 case GET_LRU_WINDOW:
2185 /* `obj' is an integer encoding a bitvector.
2186 `obj & 1' means consider only full-width windows.
2187 `obj & 2' means consider also dedicated windows. */
2188 if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
2189 || (!(XINT (obj) & 2) && !NILP (w->dedicated))
2190 /* Minibuffer windows are always ignored. */
2191 || MINI_WINDOW_P (w))
2192 break;
2193 if (NILP (best_window)
2194 || (XFASTINT (XWINDOW (best_window)->use_time)
2195 > XFASTINT (w->use_time)))
2196 best_window = window;
2197 break;
2199 case DELETE_OTHER_WINDOWS:
2200 if (!EQ (window, obj))
2201 Fdelete_window (window);
2202 break;
2204 case DELETE_BUFFER_WINDOWS:
2205 if (EQ (w->buffer, obj))
2207 struct frame *f = XFRAME (WINDOW_FRAME (w));
2209 /* If this window is dedicated, and in a frame of its own,
2210 kill the frame. */
2211 if (EQ (window, FRAME_ROOT_WINDOW (f))
2212 && !NILP (w->dedicated)
2213 && other_visible_frames (f))
2215 /* Skip the other windows on this frame.
2216 There might be one, the minibuffer! */
2217 while (CONSP (XCDR (windows))
2218 && EQ (XWINDOW (XCAR (windows))->frame,
2219 XWINDOW (XCAR (XCDR (windows)))->frame))
2220 windows = XCDR (windows);
2222 /* Now we can safely delete the frame. */
2223 Fdelete_frame (w->frame, Qnil);
2225 else if (NILP (w->parent))
2227 /* If we're deleting the buffer displayed in the
2228 only window on the frame, find a new buffer to
2229 display there. */
2230 Lisp_Object buffer;
2231 buffer = Fother_buffer (obj, Qnil, w->frame);
2232 Fset_window_buffer (window, buffer, Qnil);
2233 if (EQ (window, selected_window))
2234 Fset_buffer (w->buffer);
2236 else
2237 Fdelete_window (window);
2239 break;
2241 case GET_LARGEST_WINDOW:
2242 { /* nil `obj' means to ignore dedicated windows. */
2243 /* Ignore dedicated windows and minibuffers. */
2244 if (MINI_WINDOW_P (w) || (NILP (obj) && !NILP (w->dedicated)))
2245 break;
2247 if (NILP (best_window))
2248 best_window = window;
2249 else
2251 struct window *b = XWINDOW (best_window);
2252 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2253 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2254 best_window = window;
2257 break;
2259 case UNSHOW_BUFFER:
2260 if (EQ (w->buffer, obj))
2262 Lisp_Object buffer;
2263 struct frame *f = XFRAME (w->frame);
2265 /* Find another buffer to show in this window. */
2266 buffer = Fother_buffer (obj, Qnil, w->frame);
2268 /* If this window is dedicated, and in a frame of its own,
2269 kill the frame. */
2270 if (EQ (window, FRAME_ROOT_WINDOW (f))
2271 && !NILP (w->dedicated)
2272 && other_visible_frames (f))
2274 /* Skip the other windows on this frame.
2275 There might be one, the minibuffer! */
2276 while (CONSP (XCDR (windows))
2277 && EQ (XWINDOW (XCAR (windows))->frame,
2278 XWINDOW (XCAR (XCDR (windows)))->frame))
2279 windows = XCDR (windows);
2281 /* Now we can safely delete the frame. */
2282 Fdelete_frame (w->frame, Qnil);
2284 else if (!NILP (w->dedicated) && !NILP (w->parent))
2286 Lisp_Object window;
2287 XSETWINDOW (window, w);
2288 /* If this window is dedicated and not the only window
2289 in its frame, then kill it. */
2290 Fdelete_window (window);
2292 else
2294 /* Otherwise show a different buffer in the window. */
2295 w->dedicated = Qnil;
2296 Fset_window_buffer (window, buffer, Qnil);
2297 if (EQ (window, selected_window))
2298 Fset_buffer (w->buffer);
2301 break;
2303 case REDISPLAY_BUFFER_WINDOWS:
2304 if (EQ (w->buffer, obj))
2306 mark_window_display_accurate (window, 0);
2307 w->update_mode_line = Qt;
2308 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2309 ++update_mode_lines;
2310 best_window = window;
2312 break;
2314 /* Check for a window that has a killed buffer. */
2315 case CHECK_ALL_WINDOWS:
2316 if (! NILP (w->buffer)
2317 && NILP (XBUFFER (w->buffer)->name))
2318 abort ();
2319 break;
2321 case WINDOW_LOOP_UNUSED:
2322 break;
2326 UNGCPRO;
2327 return best_window;
2330 /* Used for debugging. Abort if any window has a dead buffer. */
2332 void
2333 check_all_windows ()
2335 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2338 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
2339 doc: /* Return the window least recently selected or used for display.
2340 \(LRU means Least Recently Used.)
2342 Return a full-width window if possible.
2343 A minibuffer window is never a candidate.
2344 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2345 so if all windows are dedicated, the value is nil.
2346 If optional argument FRAME is `visible', search all visible frames.
2347 If FRAME is 0, search all visible and iconified frames.
2348 If FRAME is t, search all frames.
2349 If FRAME is nil, search only the selected frame.
2350 If FRAME is a frame, search only that frame. */)
2351 (frame, dedicated)
2352 Lisp_Object frame, dedicated;
2354 register Lisp_Object w;
2355 /* First try for a window that is full-width */
2356 w = window_loop (GET_LRU_WINDOW,
2357 NILP (dedicated) ? make_number (1) : make_number (3),
2358 0, frame);
2359 if (!NILP (w) && !EQ (w, selected_window))
2360 return w;
2361 /* If none of them, try the rest */
2362 return window_loop (GET_LRU_WINDOW,
2363 NILP (dedicated) ? make_number (0) : make_number (2),
2364 0, frame);
2367 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
2368 doc: /* Return the largest window in area.
2369 A minibuffer window is never a candidate.
2370 A dedicated window is never a candidate unless DEDICATED is non-nil,
2371 so if all windows are dedicated, the value is nil.
2372 If optional argument FRAME is `visible', search all visible frames.
2373 If FRAME is 0, search all visible and iconified frames.
2374 If FRAME is t, search all frames.
2375 If FRAME is nil, search only the selected frame.
2376 If FRAME is a frame, search only that frame. */)
2377 (frame, dedicated)
2378 Lisp_Object frame, dedicated;
2380 return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
2381 frame);
2384 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2385 doc: /* Return a window currently displaying BUFFER, or nil if none.
2386 BUFFER can be a buffer or a buffer name.
2387 If optional argument FRAME is `visible', search all visible frames.
2388 If optional argument FRAME is 0, search all visible and iconified frames.
2389 If FRAME is t, search all frames.
2390 If FRAME is nil, search only the selected frame.
2391 If FRAME is a frame, search only that frame. */)
2392 (buffer, frame)
2393 Lisp_Object buffer, frame;
2395 buffer = Fget_buffer (buffer);
2396 if (BUFFERP (buffer))
2397 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2398 else
2399 return Qnil;
2402 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2403 0, 1, "",
2404 doc: /* Make WINDOW (or the selected window) fill its frame.
2405 Only the frame WINDOW is on is affected.
2406 This function tries to reduce display jumps
2407 by keeping the text previously visible in WINDOW
2408 in the same place on the frame. Doing this depends on
2409 the value of (window-start WINDOW), so if calling this function
2410 in a program gives strange scrolling, make sure the window-start
2411 value is reasonable when this function is called. */)
2412 (window)
2413 Lisp_Object window;
2415 struct window *w;
2416 int startpos;
2417 int top, new_top;
2419 if (NILP (window))
2420 window = selected_window;
2421 else
2422 CHECK_LIVE_WINDOW (window);
2423 w = XWINDOW (window);
2425 startpos = marker_position (w->start);
2426 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2428 if (MINI_WINDOW_P (w) && top > 0)
2429 error ("Can't expand minibuffer to full frame");
2431 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2433 /* Try to minimize scrolling, by setting the window start to the point
2434 will cause the text at the old window start to be at the same place
2435 on the frame. But don't try to do this if the window start is
2436 outside the visible portion (as might happen when the display is
2437 not current, due to typeahead). */
2438 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2439 if (new_top != top
2440 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2441 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2443 struct position pos;
2444 struct buffer *obuf = current_buffer;
2446 Fset_buffer (w->buffer);
2447 /* This computation used to temporarily move point, but that can
2448 have unwanted side effects due to text properties. */
2449 pos = *vmotion (startpos, -top, w);
2451 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2452 w->window_end_valid = Qnil;
2453 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2454 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2455 : Qnil);
2456 /* We need to do this, so that the window-scroll-functions
2457 get called. */
2458 w->optional_new_start = Qt;
2460 set_buffer_internal (obuf);
2463 return Qnil;
2466 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2467 1, 2, "bDelete windows on (buffer): ",
2468 doc: /* Delete all windows showing BUFFER.
2469 BUFFER must be a buffer or the name of an existing buffer.
2470 Optional second argument FRAME controls which frames are affected.
2471 If optional argument FRAME is `visible', search all visible frames.
2472 If FRAME is 0, search all visible and iconified frames.
2473 If FRAME is nil, search all frames.
2474 If FRAME is t, search only the selected frame.
2475 If FRAME is a frame, search only that frame. */)
2476 (buffer, frame)
2477 Lisp_Object buffer, frame;
2479 /* FRAME uses t and nil to mean the opposite of what window_loop
2480 expects. */
2481 if (NILP (frame))
2482 frame = Qt;
2483 else if (EQ (frame, Qt))
2484 frame = Qnil;
2486 if (!NILP (buffer))
2488 buffer = Fget_buffer (buffer);
2489 CHECK_BUFFER (buffer);
2490 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2493 return Qnil;
2496 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2497 Sreplace_buffer_in_windows,
2498 1, 1, "bReplace buffer in windows: ",
2499 doc: /* Replace BUFFER with some other buffer in all windows showing it.
2500 BUFFER may be a buffer or the name of an existing buffer. */)
2501 (buffer)
2502 Lisp_Object buffer;
2504 if (!NILP (buffer))
2506 buffer = Fget_buffer (buffer);
2507 CHECK_BUFFER (buffer);
2508 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2510 return Qnil;
2513 /* Replace BUFFER with some other buffer in all windows
2514 of all frames, even those on other keyboards. */
2516 void
2517 replace_buffer_in_all_windows (buffer)
2518 Lisp_Object buffer;
2520 #ifdef MULTI_KBOARD
2521 Lisp_Object tail, frame;
2523 /* A single call to window_loop won't do the job
2524 because it only considers frames on the current keyboard.
2525 So loop manually over frames, and handle each one. */
2526 FOR_EACH_FRAME (tail, frame)
2527 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2528 #else
2529 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2530 #endif
2533 /* Set the height of WINDOW and all its inferiors. */
2535 /* The smallest acceptable dimensions for a window. Anything smaller
2536 might crash Emacs. */
2538 #define MIN_SAFE_WINDOW_WIDTH (2)
2539 #define MIN_SAFE_WINDOW_HEIGHT (1)
2541 /* Make sure that window_min_height and window_min_width are
2542 not too small; if they are, set them to safe minima. */
2544 static void
2545 check_min_window_sizes ()
2547 /* Smaller values might permit a crash. */
2548 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2549 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2550 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2551 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2554 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2555 minimum allowable size. */
2557 void
2558 check_frame_size (frame, rows, cols)
2559 FRAME_PTR frame;
2560 int *rows, *cols;
2562 /* For height, we have to see:
2563 how many windows the frame has at minimum (one or two),
2564 and whether it has a menu bar or other special stuff at the top. */
2565 int min_height
2566 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2567 ? MIN_SAFE_WINDOW_HEIGHT
2568 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2570 if (FRAME_TOP_MARGIN (frame) > 0)
2571 min_height += FRAME_TOP_MARGIN (frame);
2573 if (*rows < min_height)
2574 *rows = min_height;
2575 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2576 *cols = MIN_SAFE_WINDOW_WIDTH;
2579 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2580 check if W's width can be changed, otherwise check W's height.
2581 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2582 siblings, too. If none of the siblings is resizable, WINDOW isn't
2583 either. */
2585 static int
2586 window_fixed_size_p (w, width_p, check_siblings_p)
2587 struct window *w;
2588 int width_p, check_siblings_p;
2590 int fixed_p;
2591 struct window *c;
2593 if (!NILP (w->hchild))
2595 c = XWINDOW (w->hchild);
2597 if (width_p)
2599 /* A horiz. combination is fixed-width if all of if its
2600 children are. */
2601 while (c && window_fixed_size_p (c, width_p, 0))
2602 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2603 fixed_p = c == NULL;
2605 else
2607 /* A horiz. combination is fixed-height if one of if its
2608 children is. */
2609 while (c && !window_fixed_size_p (c, width_p, 0))
2610 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2611 fixed_p = c != NULL;
2614 else if (!NILP (w->vchild))
2616 c = XWINDOW (w->vchild);
2618 if (width_p)
2620 /* A vert. combination is fixed-width if one of if its
2621 children is. */
2622 while (c && !window_fixed_size_p (c, width_p, 0))
2623 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2624 fixed_p = c != NULL;
2626 else
2628 /* A vert. combination is fixed-height if all of if its
2629 children are. */
2630 while (c && window_fixed_size_p (c, width_p, 0))
2631 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2632 fixed_p = c == NULL;
2635 else if (BUFFERP (w->buffer))
2637 struct buffer *old = current_buffer;
2638 Lisp_Object val;
2640 current_buffer = XBUFFER (w->buffer);
2641 val = find_symbol_value (Qwindow_size_fixed);
2642 current_buffer = old;
2644 fixed_p = 0;
2645 if (!EQ (val, Qunbound))
2647 fixed_p = !NILP (val);
2649 if (fixed_p
2650 && ((EQ (val, Qheight) && width_p)
2651 || (EQ (val, Qwidth) && !width_p)))
2652 fixed_p = 0;
2655 /* Can't tell if this one is resizable without looking at
2656 siblings. If all siblings are fixed-size this one is too. */
2657 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2659 Lisp_Object child;
2661 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2662 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2663 break;
2665 if (NILP (child))
2666 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2667 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2668 break;
2670 if (NILP (child))
2671 fixed_p = 1;
2674 else
2675 fixed_p = 1;
2677 return fixed_p;
2680 /* Return the minimum size for leaf window W. WIDTH_P non-zero means
2681 take into account fringes and the scrollbar of W. WIDTH_P zero
2682 means take into account mode-line and header-line of W. Return 1
2683 for the minibuffer. */
2685 static int
2686 window_min_size_2 (w, width_p)
2687 struct window *w;
2688 int width_p;
2690 int size;
2692 if (width_p)
2693 size = max (window_min_width,
2694 (MIN_SAFE_WINDOW_WIDTH
2695 + WINDOW_FRINGE_COLS (w)
2696 + WINDOW_SCROLL_BAR_COLS (w)));
2697 else if (MINI_WINDOW_P (w))
2698 size = 1;
2699 else
2700 size = max (window_min_height,
2701 (MIN_SAFE_WINDOW_HEIGHT
2702 + (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)
2703 + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 )));
2705 return size;
2708 /* Return the minimum size of window W, not taking fixed-width windows
2709 into account. WIDTH_P non-zero means return the minimum width,
2710 otherwise return the minimum height. If W is a combination window,
2711 compute the minimum size from the minimum sizes of W's children. */
2713 static int
2714 window_min_size_1 (w, width_p)
2715 struct window *w;
2716 int width_p;
2718 struct window *c;
2719 int size;
2721 if (!NILP (w->hchild))
2723 c = XWINDOW (w->hchild);
2724 size = 0;
2726 if (width_p)
2728 /* The min width of a horizontal combination is
2729 the sum of the min widths of its children. */
2730 while (c)
2732 size += window_min_size_1 (c, width_p);
2733 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2736 else
2738 /* The min height a horizontal combination equals
2739 the maximum of all min height of its children. */
2740 while (c)
2742 int min_size = window_min_size_1 (c, width_p);
2743 size = max (min_size, size);
2744 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2748 else if (!NILP (w->vchild))
2750 c = XWINDOW (w->vchild);
2751 size = 0;
2753 if (width_p)
2755 /* The min width of a vertical combination is
2756 the maximum of the min widths of its children. */
2757 while (c)
2759 int min_size = window_min_size_1 (c, width_p);
2760 size = max (min_size, size);
2761 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2764 else
2766 /* The min height of a vertical combination equals
2767 the sum of the min height of its children. */
2768 while (c)
2770 size += window_min_size_1 (c, width_p);
2771 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2775 else
2776 size = window_min_size_2 (w, width_p);
2778 return size;
2782 /* Return the minimum size of window W, taking fixed-size windows into
2783 account. WIDTH_P non-zero means return the minimum width,
2784 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2785 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2786 unless FIXED is null. */
2788 static int
2789 window_min_size (w, width_p, ignore_fixed_p, fixed)
2790 struct window *w;
2791 int width_p, ignore_fixed_p, *fixed;
2793 int size, fixed_p;
2795 if (ignore_fixed_p)
2796 fixed_p = 0;
2797 else
2798 fixed_p = window_fixed_size_p (w, width_p, 1);
2800 if (fixed)
2801 *fixed = fixed_p;
2803 if (fixed_p)
2804 size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines);
2805 else
2806 size = window_min_size_1 (w, width_p);
2808 return size;
2812 /* Adjust the margins of window W if text area is too small.
2813 Return 1 if window width is ok after adjustment; 0 if window
2814 is still too narrow. */
2816 static int
2817 adjust_window_margins (w)
2818 struct window *w;
2820 int box_cols = (WINDOW_TOTAL_COLS (w)
2821 - WINDOW_FRINGE_COLS (w)
2822 - WINDOW_SCROLL_BAR_COLS (w));
2823 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2824 + WINDOW_RIGHT_MARGIN_COLS (w));
2826 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2827 return 1;
2829 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2830 return 0;
2832 /* Window's text area is too narrow, but reducing the window
2833 margins will fix that. */
2834 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2835 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2837 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2838 w->left_margin_cols = w->right_margin_cols
2839 = make_number (margin_cols/2);
2840 else
2841 w->right_margin_cols = make_number (margin_cols);
2843 else
2844 w->left_margin_cols = make_number (margin_cols);
2845 return 1;
2848 /* Calculate new sizes for windows in the list FORWARD when the window size
2849 goes from TOTAL to SIZE. TOTAL must be greater than SIZE.
2850 The number of windows in FORWARD is NCHILDREN, and the number that
2851 can shrink is SHRINKABLE.
2852 The minimum size a window can have is MIN_SIZE.
2853 If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
2854 If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
2855 shrinking rows.
2857 This function returns an allocated array of new sizes that the caller
2858 must free. The size -1 means the window is fixed and RESIZE_FIXED_P
2859 is zero. Array index 0 refers to the first window in FORWARD, 1 to
2860 the second, and so on.
2862 This function tries to keep windows at least at the minimum size
2863 and resize other windows before it resizes any window to zero (i.e.
2864 delete that window).
2866 Windows are resized proportional to their size, so bigger windows
2867 shrink more than smaller windows. */
2868 static int *
2869 shrink_windows (total, size, nchildren, shrinkable,
2870 min_size, resize_fixed_p, forward, width_p)
2871 int total, size, nchildren, shrinkable, min_size;
2872 int resize_fixed_p, width_p;
2873 Lisp_Object forward;
2875 int available_resize = 0;
2876 int *new_sizes;
2877 struct window *c;
2878 Lisp_Object child;
2879 int smallest = total;
2880 int total_removed = 0;
2881 int total_shrink = total - size;
2882 int i;
2884 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2886 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2888 int child_size;
2890 c = XWINDOW (child);
2891 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2893 if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2894 new_sizes[i] = -1;
2895 else
2897 new_sizes[i] = child_size;
2898 if (child_size > min_size)
2899 available_resize += child_size - min_size;
2902 /* We might need to shrink some windows to zero. Find the smallest
2903 windows and set them to 0 until we can fulfil the new size. */
2905 while (shrinkable > 1 && size + available_resize < total)
2907 for (i = 0; i < nchildren; ++i)
2908 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2909 smallest = new_sizes[i];
2911 for (i = 0; i < nchildren; ++i)
2912 if (new_sizes[i] == smallest)
2914 /* Resize this window down to zero. */
2915 new_sizes[i] = 0;
2916 if (smallest > min_size)
2917 available_resize -= smallest - min_size;
2918 available_resize += smallest;
2919 --shrinkable;
2920 total_removed += smallest;
2922 /* We don't know what the smallest is now. */
2923 smallest = total;
2925 /* Out of for, just remove one window at the time and
2926 check again if we have enough space. */
2927 break;
2931 /* Now, calculate the new sizes. Try to shrink each window
2932 proportional to its size. */
2933 for (i = 0; i < nchildren; ++i)
2935 if (new_sizes[i] > min_size)
2937 int to_shrink = total_shrink*new_sizes[i]/total;
2938 if (new_sizes[i] - to_shrink < min_size)
2939 to_shrink = new_sizes[i] - min_size;
2940 new_sizes[i] -= to_shrink;
2941 total_removed += to_shrink;
2945 /* Any reminder due to rounding, we just subtract from windows
2946 that are left and still can be shrunk. */
2947 while (total_shrink > total_removed)
2949 int nonzero_sizes = 0;
2950 int nonzero_idx = -1;
2952 for (i = 0; i < nchildren; ++i)
2953 if (new_sizes[i] > 0)
2955 ++nonzero_sizes;
2956 nonzero_idx = i;
2959 for (i = 0; i < nchildren; ++i)
2960 if (new_sizes[i] > min_size)
2962 --new_sizes[i];
2963 ++total_removed;
2965 /* Out of for, just shrink one window at the time and
2966 check again if we have enough space. */
2967 break;
2971 /* Special case, only one window left. */
2972 if (nonzero_sizes == 1)
2973 break;
2976 /* Any surplus due to rounding, we add to windows that are left. */
2977 while (total_shrink < total_removed)
2979 for (i = 0; i < nchildren; ++i)
2981 if (new_sizes[i] != 0 && total_shrink < total_removed)
2983 ++new_sizes[i];
2984 --total_removed;
2985 break;
2990 return new_sizes;
2993 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2994 WINDOW's width. Resize WINDOW's children, if any, so that they
2995 keep their proportionate size relative to WINDOW.
2997 If FIRST_ONLY is 1, change only the first of WINDOW's children when
2998 they are in series. If LAST_ONLY is 1, change only the last of
2999 WINDOW's children when they are in series.
3001 Propagate WINDOW's top or left edge position to children. Delete
3002 windows that become too small unless NODELETE_P is non-zero.
3004 If NODELETE_P is 2, that means we do delete windows that are
3005 too small, even if they were too small before! */
3007 static void
3008 size_window (window, size, width_p, nodelete_p, first_only, last_only)
3009 Lisp_Object window;
3010 int size, width_p, nodelete_p;
3011 int first_only, last_only;
3013 struct window *w = XWINDOW (window);
3014 struct window *c;
3015 Lisp_Object child, *forward, *sideward;
3016 int old_size, min_size, safe_min_size;
3018 check_min_window_sizes ();
3019 size = max (0, size);
3021 /* If the window has been "too small" at one point,
3022 don't delete it for being "too small" in the future.
3023 Preserve it as long as that is at all possible. */
3024 if (width_p)
3026 old_size = WINDOW_TOTAL_COLS (w);
3027 min_size = window_min_width;
3028 safe_min_size = window_min_size_2 (w, 1);
3030 else
3032 old_size = XINT (w->total_lines);
3033 min_size = window_min_height;
3034 safe_min_size = window_min_size_2 (w, 0);
3037 if (old_size < min_size && nodelete_p != 2)
3038 w->too_small_ok = Qt;
3040 /* Move the following test here since otherwise the
3041 preceding test doesn't make sense. martin. */
3042 if (nodelete_p == 2)
3043 nodelete_p = 0;
3045 /* Maybe delete WINDOW if it's too small. */
3046 if (nodelete_p != 1 && !NILP (w->parent))
3048 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
3049 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
3050 if (min_size < safe_min_size)
3051 min_size = safe_min_size;
3052 if (size < min_size)
3054 delete_window (window);
3055 return;
3059 /* Set redisplay hints. */
3060 w->last_modified = make_number (0);
3061 w->last_overlay_modified = make_number (0);
3062 windows_or_buffers_changed++;
3063 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
3065 if (width_p)
3067 sideward = &w->vchild;
3068 forward = &w->hchild;
3069 w->total_cols = make_number (size);
3070 adjust_window_margins (w);
3072 else
3074 sideward = &w->hchild;
3075 forward = &w->vchild;
3076 w->total_lines = make_number (size);
3077 w->orig_total_lines = Qnil;
3080 if (!NILP (*sideward))
3082 /* We have a chain of parallel siblings whose size should all change. */
3083 for (child = *sideward; !NILP (child); child = c->next)
3085 c = XWINDOW (child);
3086 if (width_p)
3087 c->left_col = w->left_col;
3088 else
3089 c->top_line = w->top_line;
3090 size_window (child, size, width_p, nodelete_p,
3091 first_only, last_only);
3094 else if (!NILP (*forward) && last_only)
3096 /* Change the last in a series of siblings. */
3097 Lisp_Object last_child;
3098 int child_size;
3100 for (child = *forward; !NILP (child); child = c->next)
3102 c = XWINDOW (child);
3103 last_child = child;
3106 child_size = XINT (width_p ? c->total_cols : c->total_lines);
3107 size_window (last_child,
3108 size - old_size + child_size,
3109 width_p, nodelete_p, first_only, last_only);
3111 else if (!NILP (*forward) && first_only)
3113 /* Change the first in a series of siblings. */
3114 int child_size;
3116 child = *forward;
3117 c = XWINDOW (child);
3119 if (width_p)
3120 c->left_col = w->left_col;
3121 else
3122 c->top_line = w->top_line;
3124 child_size = XINT (width_p ? c->total_cols : c->total_lines);
3125 size_window (child,
3126 size - old_size + child_size,
3127 width_p, nodelete_p, first_only, last_only);
3129 else if (!NILP (*forward))
3131 int fixed_size, each, extra, n;
3132 int resize_fixed_p, nfixed;
3133 int last_pos, first_pos, nchildren, total;
3134 int *new_sizes = NULL;
3136 /* Determine the fixed-size portion of this window, and the
3137 number of child windows. */
3138 fixed_size = nchildren = nfixed = total = 0;
3139 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
3141 int child_size;
3143 c = XWINDOW (child);
3144 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
3145 total += child_size;
3147 if (window_fixed_size_p (c, width_p, 0))
3149 fixed_size += child_size;
3150 ++nfixed;
3154 /* If the new size is smaller than fixed_size, or if there
3155 aren't any resizable windows, allow resizing fixed-size
3156 windows. */
3157 resize_fixed_p = nfixed == nchildren || size < fixed_size;
3159 /* Compute how many lines/columns to add/remove to each child. The
3160 value of extra takes care of rounding errors. */
3161 n = resize_fixed_p ? nchildren : nchildren - nfixed;
3162 if (size < total && n > 1)
3163 new_sizes = shrink_windows (total, size, nchildren, n, min_size,
3164 resize_fixed_p, *forward, width_p);
3165 else
3167 each = (size - total) / n;
3168 extra = (size - total) - n * each;
3171 /* Compute new children heights and edge positions. */
3172 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
3173 last_pos = first_pos;
3174 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
3176 int new_size, old_size;
3178 c = XWINDOW (child);
3179 old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines);
3180 new_size = old_size;
3182 /* The top or left edge position of this child equals the
3183 bottom or right edge of its predecessor. */
3184 if (width_p)
3185 c->left_col = make_number (last_pos);
3186 else
3187 c->top_line = make_number (last_pos);
3189 /* If this child can be resized, do it. */
3190 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
3192 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
3193 extra = 0;
3196 /* Set new height. Note that size_window also propagates
3197 edge positions to children, so it's not a no-op if we
3198 didn't change the child's size. */
3199 size_window (child, new_size, width_p, 1, first_only, last_only);
3201 /* Remember the bottom/right edge position of this child; it
3202 will be used to set the top/left edge of the next child. */
3203 last_pos += new_size;
3206 if (new_sizes) xfree (new_sizes);
3208 /* We should have covered the parent exactly with child windows. */
3209 xassert (size == last_pos - first_pos);
3211 /* Now delete any children that became too small. */
3212 if (!nodelete_p)
3213 for (child = *forward; !NILP (child); child = c->next)
3215 int child_size;
3216 c = XWINDOW (child);
3217 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
3218 size_window (child, child_size, width_p, 2, first_only, last_only);
3223 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3224 WINDOW's children. NODELETE non-zero means don't delete windows
3225 that become too small in the process. (The caller should check
3226 later and do so if appropriate.) */
3228 void
3229 set_window_height (window, height, nodelete)
3230 Lisp_Object window;
3231 int height;
3232 int nodelete;
3234 size_window (window, height, 0, nodelete, 0, 0);
3238 /* Set WINDOW's width to WIDTH, and recursively change the width of
3239 WINDOW's children. NODELETE non-zero means don't delete windows
3240 that become too small in the process. (The caller should check
3241 later and do so if appropriate.) */
3243 void
3244 set_window_width (window, width, nodelete)
3245 Lisp_Object window;
3246 int width;
3247 int nodelete;
3249 size_window (window, width, 1, nodelete, 0, 0);
3252 /* Change window heights in windows rooted in WINDOW by N lines. */
3254 void
3255 change_window_heights (window, n)
3256 Lisp_Object window;
3257 int n;
3259 struct window *w = XWINDOW (window);
3261 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
3262 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
3264 if (INTEGERP (w->orig_top_line))
3265 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
3266 if (INTEGERP (w->orig_total_lines))
3267 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
3269 /* Handle just the top child in a vertical split. */
3270 if (!NILP (w->vchild))
3271 change_window_heights (w->vchild, n);
3273 /* Adjust all children in a horizontal split. */
3274 for (window = w->hchild; !NILP (window); window = w->next)
3276 w = XWINDOW (window);
3277 change_window_heights (window, n);
3282 int window_select_count;
3284 Lisp_Object
3285 Fset_window_buffer_unwind (obuf)
3286 Lisp_Object obuf;
3288 Fset_buffer (obuf);
3289 return Qnil;
3292 EXFUN (Fset_window_fringes, 4);
3293 EXFUN (Fset_window_scroll_bars, 4);
3295 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3296 means it's allowed to run hooks. See make_frame for a case where
3297 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3298 margins, fringes, and scroll-bar settings of the window are not
3299 reset from the buffer's local settings. */
3301 void
3302 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
3303 Lisp_Object window, buffer;
3304 int run_hooks_p, keep_margins_p;
3306 struct window *w = XWINDOW (window);
3307 struct buffer *b = XBUFFER (buffer);
3308 int count = SPECPDL_INDEX ();
3310 w->buffer = buffer;
3312 if (EQ (window, selected_window))
3313 b->last_selected_window = window;
3315 /* Let redisplay errors through. */
3316 b->display_error_modiff = 0;
3318 /* Update time stamps of buffer display. */
3319 if (INTEGERP (b->display_count))
3320 XSETINT (b->display_count, XINT (b->display_count) + 1);
3321 b->display_time = Fcurrent_time ();
3323 XSETFASTINT (w->window_end_pos, 0);
3324 XSETFASTINT (w->window_end_vpos, 0);
3325 bzero (&w->last_cursor, sizeof w->last_cursor);
3326 w->window_end_valid = Qnil;
3327 w->hscroll = w->min_hscroll = make_number (0);
3328 w->vscroll = 0;
3329 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3330 set_marker_restricted (w->start,
3331 make_number (b->last_window_start),
3332 buffer);
3333 w->start_at_line_beg = Qnil;
3334 w->force_start = Qnil;
3335 XSETFASTINT (w->last_modified, 0);
3336 XSETFASTINT (w->last_overlay_modified, 0);
3337 windows_or_buffers_changed++;
3339 /* We must select BUFFER for running the window-scroll-functions.
3340 If WINDOW is selected, switch permanently.
3341 Otherwise, switch but go back to the ambient buffer afterward. */
3342 if (EQ (window, selected_window))
3343 Fset_buffer (buffer);
3344 /* We can't check ! NILP (Vwindow_scroll_functions) here
3345 because that might itself be a local variable. */
3346 else if (window_initialized)
3348 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
3349 Fset_buffer (buffer);
3352 if (!keep_margins_p)
3354 /* Set left and right marginal area width etc. from buffer. */
3356 /* This may call adjust_window_margins three times, so
3357 temporarily disable window margins. */
3358 Lisp_Object save_left = w->left_margin_cols;
3359 Lisp_Object save_right = w->right_margin_cols;
3361 w->left_margin_cols = w->right_margin_cols = Qnil;
3363 Fset_window_fringes (window,
3364 b->left_fringe_width, b->right_fringe_width,
3365 b->fringes_outside_margins);
3367 Fset_window_scroll_bars (window,
3368 b->scroll_bar_width,
3369 b->vertical_scroll_bar_type, Qnil);
3371 w->left_margin_cols = save_left;
3372 w->right_margin_cols = save_right;
3374 Fset_window_margins (window,
3375 b->left_margin_cols, b->right_margin_cols);
3378 if (run_hooks_p)
3380 if (! NILP (Vwindow_scroll_functions))
3381 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3382 Fmarker_position (w->start));
3384 if (! NILP (Vwindow_configuration_change_hook)
3385 && ! NILP (Vrun_hooks))
3386 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3389 unbind_to (count, Qnil);
3393 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3394 doc: /* Make WINDOW display BUFFER as its contents.
3395 BUFFER can be a buffer or the name of an existing buffer.
3396 Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
3397 display margins, fringe widths, and scroll bar settings are maintained;
3398 the default is to reset these from BUFFER's local settings or the frame
3399 defaults.
3401 This function runs the hook `window-scroll-functions'. */)
3402 (window, buffer, keep_margins)
3403 register Lisp_Object window, buffer, keep_margins;
3405 register Lisp_Object tem;
3406 register struct window *w = decode_window (window);
3408 XSETWINDOW (window, w);
3409 buffer = Fget_buffer (buffer);
3410 CHECK_BUFFER (buffer);
3412 if (NILP (XBUFFER (buffer)->name))
3413 error ("Attempt to display deleted buffer");
3415 tem = w->buffer;
3416 if (NILP (tem))
3417 error ("Window is deleted");
3418 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3419 is first being set up. */
3421 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3422 error ("Window is dedicated to `%s'",
3423 SDATA (XBUFFER (tem)->name));
3425 unshow_buffer (w);
3428 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3429 return Qnil;
3432 /* Note that selected_window can be nil
3433 when this is called from Fset_window_configuration. */
3435 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3436 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3437 If WINDOW is not already selected, make WINDOW's buffer current
3438 and make WINDOW the frame's selected window. Return WINDOW.
3439 Optional second arg NORECORD non-nil means
3440 do not put this buffer at the front of the list of recently selected ones.
3442 Note that the main editor command loop
3443 selects the buffer of the selected window before each command. */)
3444 (window, norecord)
3445 register Lisp_Object window, norecord;
3447 register struct window *w;
3448 register struct window *ow;
3449 struct frame *sf;
3451 CHECK_LIVE_WINDOW (window);
3453 w = XWINDOW (window);
3454 w->frozen_window_start_p = 0;
3456 ++window_select_count;
3457 XSETFASTINT (w->use_time, window_select_count);
3458 if (EQ (window, selected_window))
3459 return window;
3461 /* Store the current buffer's actual point into the
3462 old selected window. It belongs to that window,
3463 and when the window is not selected, must be in the window. */
3464 if (!NILP (selected_window))
3466 ow = XWINDOW (selected_window);
3467 if (! NILP (ow->buffer))
3468 set_marker_both (ow->pointm, ow->buffer,
3469 BUF_PT (XBUFFER (ow->buffer)),
3470 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3473 selected_window = window;
3474 sf = SELECTED_FRAME ();
3475 if (XFRAME (WINDOW_FRAME (w)) != sf)
3477 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3478 /* Use this rather than Fhandle_switch_frame
3479 so that FRAME_FOCUS_FRAME is moved appropriately as we
3480 move around in the state where a minibuffer in a separate
3481 frame is active. */
3482 Fselect_frame (WINDOW_FRAME (w));
3484 else
3485 sf->selected_window = window;
3487 if (NILP (norecord))
3488 record_buffer (w->buffer);
3489 Fset_buffer (w->buffer);
3491 XBUFFER (w->buffer)->last_selected_window = window;
3493 /* Go to the point recorded in the window.
3494 This is important when the buffer is in more
3495 than one window. It also matters when
3496 redisplay_window has altered point after scrolling,
3497 because it makes the change only in the window. */
3499 register int new_point = marker_position (w->pointm);
3500 if (new_point < BEGV)
3501 SET_PT (BEGV);
3502 else if (new_point > ZV)
3503 SET_PT (ZV);
3504 else
3505 SET_PT (new_point);
3508 windows_or_buffers_changed++;
3509 return window;
3512 static Lisp_Object
3513 select_window_norecord (window)
3514 Lisp_Object window;
3516 return Fselect_window (window, Qt);
3519 /* Deiconify the frame containing the window WINDOW,
3520 unless it is the selected frame;
3521 then return WINDOW.
3523 The reason for the exception for the selected frame
3524 is that it seems better not to change the selected frames visibility
3525 merely because of displaying a different buffer in it.
3526 The deiconification is useful when a buffer gets shown in
3527 another frame that you were not using lately. */
3529 static Lisp_Object
3530 display_buffer_1 (window)
3531 Lisp_Object window;
3533 Lisp_Object frame = XWINDOW (window)->frame;
3534 FRAME_PTR f = XFRAME (frame);
3536 FRAME_SAMPLE_VISIBILITY (f);
3538 if (EQ (frame, selected_frame))
3539 ; /* Assume the selected frame is already visible enough. */
3540 else if (minibuf_level > 0
3541 && MINI_WINDOW_P (XWINDOW (selected_window))
3542 && WINDOW_LIVE_P (minibuf_selected_window)
3543 && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
3544 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3545 else
3547 if (FRAME_ICONIFIED_P (f))
3548 Fmake_frame_visible (frame);
3549 else if (FRAME_VISIBLE_P (f))
3550 Fraise_frame (frame);
3553 return window;
3556 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
3557 doc: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
3558 If the value is t, `display-buffer' or `pop-to-buffer' would create a
3559 special frame for that buffer using the default frame parameters.
3561 If the value is a list, it is a list of frame parameters that would be used
3562 to make a frame for that buffer.
3563 The variables `special-display-buffer-names'
3564 and `special-display-regexps' control this. */)
3565 (buffer_name)
3566 Lisp_Object buffer_name;
3568 Lisp_Object tem;
3570 CHECK_STRING (buffer_name);
3572 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
3573 if (!NILP (tem))
3574 return Qt;
3576 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
3577 if (!NILP (tem))
3578 return XCDR (tem);
3580 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
3582 Lisp_Object car = XCAR (tem);
3583 if (STRINGP (car)
3584 && fast_string_match (car, buffer_name) >= 0)
3585 return Qt;
3586 else if (CONSP (car)
3587 && STRINGP (XCAR (car))
3588 && fast_string_match (XCAR (car), buffer_name) >= 0)
3589 return XCDR (car);
3591 return Qnil;
3594 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
3595 doc: /* Returns non-nil if a buffer named BUFFER-NAME would use the same window.
3596 More precisely, if `display-buffer' or `pop-to-buffer' would display
3597 that buffer in the selected window rather than (as usual) in some other window.
3598 See `same-window-buffer-names' and `same-window-regexps'. */)
3599 (buffer_name)
3600 Lisp_Object buffer_name;
3602 Lisp_Object tem;
3604 CHECK_STRING (buffer_name);
3606 tem = Fmember (buffer_name, Vsame_window_buffer_names);
3607 if (!NILP (tem))
3608 return Qt;
3610 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
3611 if (!NILP (tem))
3612 return Qt;
3614 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3616 Lisp_Object car = XCAR (tem);
3617 if (STRINGP (car)
3618 && fast_string_match (car, buffer_name) >= 0)
3619 return Qt;
3620 else if (CONSP (car)
3621 && STRINGP (XCAR (car))
3622 && fast_string_match (XCAR (car), buffer_name) >= 0)
3623 return Qt;
3625 return Qnil;
3628 /* Use B so the default is (other-buffer). */
3629 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
3630 "BDisplay buffer: \nP",
3631 doc: /* Make BUFFER appear in some window but don't select it.
3632 BUFFER must be the name of an existing buffer, or, when called from Lisp,
3633 a buffer.
3634 If BUFFER is shown already in some window, just use that one,
3635 unless the window is the selected window and the optional second
3636 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3637 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3638 Returns the window displaying BUFFER.
3639 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3640 displaying BUFFER, then simply raise that frame.
3642 The variables `special-display-buffer-names',
3643 `special-display-regexps', `same-window-buffer-names', and
3644 `same-window-regexps' customize how certain buffer names are handled.
3645 The latter two take effect only if NOT-THIS-WINDOW is nil.
3647 If optional argument FRAME is `visible', check all visible frames
3648 for a window to use.
3649 If FRAME is 0, check all visible and iconified frames.
3650 If FRAME is t, check all frames.
3651 If FRAME is a frame, check only that frame.
3652 If FRAME is nil, check only the selected frame
3653 (actually the last nonminibuffer frame),
3654 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3655 which means search visible and iconified frames.
3657 If a full-width window on a splittable frame is available to display
3658 the buffer, it may be split, subject to the value of the variable
3659 `split-height-threshold'.
3661 If `even-window-heights' is non-nil, window heights will be evened out
3662 if displaying the buffer causes two vertically adjacent windows to be
3663 displayed.
3665 If `prefer-window-split-horizontally' is non-nil, windows are split
3666 horizontally, i.e. side-by-side, instead of vertically if possible. If the
3667 variable has an integer value, windows may only be split horizontally if the
3668 newly created window is at least as wide as that value. */)
3669 (buffer, not_this_window, frame)
3670 Lisp_Object buffer, not_this_window, frame;
3672 register Lisp_Object window, tem, swp;
3673 struct frame *f;
3675 swp = Qnil;
3676 buffer = Fget_buffer (buffer);
3677 CHECK_BUFFER (buffer);
3679 if (!NILP (Vdisplay_buffer_function))
3680 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3682 if (NILP (not_this_window)
3683 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3684 return display_buffer_1 (selected_window);
3686 /* See if the user has specified this buffer should appear
3687 in the selected window. */
3688 if (NILP (not_this_window))
3690 swp = Fsame_window_p (XBUFFER (buffer)->name);
3691 if (!NILP (swp) && !no_switch_window (selected_window))
3693 Fswitch_to_buffer (buffer, Qnil);
3694 return display_buffer_1 (selected_window);
3698 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3699 look for a window showing BUFFER on any visible or iconified frame.
3700 Otherwise search only the current frame. */
3701 if (! NILP (frame))
3702 tem = frame;
3703 else if (pop_up_frames
3704 || display_buffer_reuse_frames
3705 || last_nonminibuf_frame == 0)
3706 XSETFASTINT (tem, 0);
3707 else
3708 XSETFRAME (tem, last_nonminibuf_frame);
3710 window = Fget_buffer_window (buffer, tem);
3711 if (!NILP (window)
3712 && (NILP (not_this_window) || !EQ (window, selected_window)))
3713 return display_buffer_1 (window);
3715 /* Certain buffer names get special handling. */
3716 if (!NILP (Vspecial_display_function) && NILP (swp))
3718 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3719 if (EQ (tem, Qt))
3720 return call1 (Vspecial_display_function, buffer);
3721 if (CONSP (tem))
3722 return call2 (Vspecial_display_function, buffer, tem);
3725 /* If there are no frames open that have more than a minibuffer,
3726 we need to create a new frame. */
3727 if (pop_up_frames || last_nonminibuf_frame == 0)
3729 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3730 Fset_window_buffer (window, buffer, Qnil);
3731 return display_buffer_1 (window);
3734 f = SELECTED_FRAME ();
3735 if (pop_up_windows
3736 || FRAME_MINIBUF_ONLY_P (f)
3737 /* If the current frame is a special display frame,
3738 don't try to reuse its windows. */
3739 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3741 Lisp_Object frames;
3742 struct gcpro gcpro1;
3743 GCPRO1 (buffer);
3745 frames = Qnil;
3746 if (FRAME_MINIBUF_ONLY_P (f))
3747 XSETFRAME (frames, last_nonminibuf_frame);
3749 /* Note that both Fget_largest_window and Fget_lru_window
3750 ignore minibuffers and dedicated windows.
3751 This means they can return nil. */
3753 /* If the frame we would try to split cannot be split,
3754 try other frames. */
3755 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3757 /* Try visible frames first. */
3758 window = Fget_largest_window (Qvisible, Qt);
3759 /* If that didn't work, try iconified frames. */
3760 if (NILP (window))
3761 window = Fget_largest_window (make_number (0), Qt);
3762 #if 0 /* Don't try windows on other displays. */
3763 if (NILP (window))
3764 window = Fget_largest_window (Qt, Qt);
3765 #endif
3767 else
3768 window = Fget_largest_window (frames, Qt);
3770 /* If we prefer to split horizontally and the window is wide
3771 enough, split it horizontally. */
3772 if (!NILP (window)
3773 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3774 && WINDOW_FULL_WIDTH_P (XWINDOW (window))
3775 && !NILP (Vprefer_window_split_horizontally)
3776 && (!NUMBERP (Vprefer_window_split_horizontally) ||
3777 (window_width(window) >=
3778 2 * XINT (Vprefer_window_split_horizontally)))
3779 && (window_width(window)) >= (2 * window_min_width))
3781 window = Fsplit_window (window, Qnil, Qt);
3783 /* Else, if the largest window is tall enough, full-width, and either
3784 eligible for splitting or the only window, split it. */
3785 else if (!NILP (window)
3786 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3787 && WINDOW_FULL_WIDTH_P (XWINDOW (window))
3788 && (window_height (window) >= split_height_threshold
3789 || (NILP (XWINDOW (window)->parent)))
3790 && (window_height (window)
3791 >= (2 * window_min_size_2 (XWINDOW (window), 0))))
3792 window = call1 (Vsplit_window_preferred_function, window);
3793 else
3795 Lisp_Object upper, lower, other;
3797 window = Fget_lru_window (frames, Qt);
3798 /* If we prefer to split horizontally and the LRU window is
3799 wide enough, split it horizontally. */
3800 if (!NILP (window)
3801 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3802 && !NILP (Vprefer_window_split_horizontally)
3803 && window_width(window) >= (2 * window_min_width)
3804 && (!NUMBERP (Vprefer_window_split_horizontally) ||
3805 window_width(window) >=
3806 (2 * XINT (Vprefer_window_split_horizontally))))
3807 window = Fsplit_window (window, Qnil, Qt);
3808 /* Else if the LRU window is tall enough, and either
3809 eligible for splitting and selected, or the only window,
3810 split it. */
3811 else if (!NILP (window)
3812 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3813 && ((EQ (window, selected_window)
3814 && window_height (window) >= split_height_threshold)
3815 || (NILP (XWINDOW (window)->parent)))
3816 && (window_height (window)
3817 >= (2 * window_min_size_2 (XWINDOW (window), 0))))
3818 window = Fsplit_window (window, Qnil, Qnil);
3819 else
3820 window = Fget_lru_window (frames, Qnil);
3821 /* If Fget_lru_window returned nil, try other approaches. */
3823 /* Try visible frames first. */
3824 if (NILP (window))
3825 window = Fget_buffer_window (buffer, Qvisible);
3826 if (NILP (window))
3827 window = Fget_largest_window (Qvisible, Qnil);
3828 /* If that didn't work, try iconified frames. */
3829 if (NILP (window))
3830 window = Fget_buffer_window (buffer, make_number (0));
3831 if (NILP (window))
3832 window = Fget_largest_window (make_number (0), Qnil);
3834 #if 0 /* Don't try frames on other displays. */
3835 if (NILP (window))
3836 window = Fget_buffer_window (buffer, Qt);
3837 if (NILP (window))
3838 window = Fget_largest_window (Qt, Qnil);
3839 #endif
3840 /* As a last resort, make a new frame. */
3841 if (NILP (window))
3842 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3843 /* If window appears above or below another,
3844 even out their heights. */
3845 other = upper = lower = Qnil;
3846 if (!NILP (XWINDOW (window)->prev))
3847 other = upper = XWINDOW (window)->prev, lower = window;
3848 if (!NILP (XWINDOW (window)->next))
3849 other = lower = XWINDOW (window)->next, upper = window;
3850 if (!NILP (other)
3851 && !NILP (Veven_window_heights)
3852 /* Check that OTHER and WINDOW are vertically arrayed. */
3853 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3854 && (XFASTINT (XWINDOW (other)->total_lines)
3855 > XFASTINT (XWINDOW (window)->total_lines)))
3857 int total = (XFASTINT (XWINDOW (other)->total_lines)
3858 + XFASTINT (XWINDOW (window)->total_lines));
3859 enlarge_window (upper,
3860 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
3864 UNGCPRO;
3866 else
3867 window = Fget_lru_window (Qnil, Qnil);
3869 Fset_window_buffer (window, buffer, Qnil);
3870 return display_buffer_1 (window);
3874 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3875 0, 1, 0,
3876 doc: /* Force all windows to be updated on next redisplay.
3877 If optional arg OBJECT is a window, force redisplay of that window only.
3878 If OBJECT is a buffer or buffer name, force redisplay of all windows
3879 displaying that buffer. */)
3880 (object)
3881 Lisp_Object object;
3883 if (NILP (object))
3885 windows_or_buffers_changed++;
3886 update_mode_lines++;
3887 return Qt;
3890 if (WINDOWP (object))
3892 struct window *w = XWINDOW (object);
3893 mark_window_display_accurate (object, 0);
3894 w->update_mode_line = Qt;
3895 if (BUFFERP (w->buffer))
3896 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3897 ++update_mode_lines;
3898 return Qt;
3901 if (STRINGP (object))
3902 object = Fget_buffer (object);
3903 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3905 /* Walk all windows looking for buffer, and force update
3906 of each of those windows. */
3908 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3909 return NILP (object) ? Qnil : Qt;
3912 /* If nothing suitable was found, just return.
3913 We could signal an error, but this feature will typically be used
3914 asynchronously in timers or process sentinels, so we don't. */
3915 return Qnil;
3919 void
3920 temp_output_buffer_show (buf)
3921 register Lisp_Object buf;
3923 register struct buffer *old = current_buffer;
3924 register Lisp_Object window;
3925 register struct window *w;
3927 XBUFFER (buf)->directory = current_buffer->directory;
3929 Fset_buffer (buf);
3930 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3931 BEGV = BEG;
3932 ZV = Z;
3933 SET_PT (BEG);
3934 #if 0 /* rms: there should be no reason for this. */
3935 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3936 #endif
3937 set_buffer_internal (old);
3939 if (!NILP (Vtemp_buffer_show_function))
3940 call1 (Vtemp_buffer_show_function, buf);
3941 else
3943 window = Fdisplay_buffer (buf, Qnil, Qnil);
3945 if (!EQ (XWINDOW (window)->frame, selected_frame))
3946 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3947 Vminibuf_scroll_window = window;
3948 w = XWINDOW (window);
3949 XSETFASTINT (w->hscroll, 0);
3950 XSETFASTINT (w->min_hscroll, 0);
3951 set_marker_restricted_both (w->start, buf, BEG, BEG);
3952 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3954 /* Run temp-buffer-show-hook, with the chosen window selected
3955 and its buffer current. */
3957 if (!NILP (Vrun_hooks)
3958 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3959 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3961 int count = SPECPDL_INDEX ();
3962 Lisp_Object prev_window, prev_buffer;
3963 prev_window = selected_window;
3964 XSETBUFFER (prev_buffer, old);
3966 /* Select the window that was chosen, for running the hook.
3967 Note: Both Fselect_window and select_window_norecord may
3968 set-buffer to the buffer displayed in the window,
3969 so we need to save the current buffer. --stef */
3970 record_unwind_protect (Fset_buffer, prev_buffer);
3971 record_unwind_protect (select_window_norecord, prev_window);
3972 Fselect_window (window, Qt);
3973 Fset_buffer (w->buffer);
3974 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3975 unbind_to (count, Qnil);
3980 static void
3981 make_dummy_parent (window)
3982 Lisp_Object window;
3984 Lisp_Object new;
3985 register struct window *o, *p;
3986 int i;
3988 o = XWINDOW (window);
3989 p = allocate_window ();
3990 for (i = 0; i < VECSIZE (struct window); ++i)
3991 ((struct Lisp_Vector *) p)->contents[i]
3992 = ((struct Lisp_Vector *)o)->contents[i];
3993 XSETWINDOW (new, p);
3995 ++sequence_number;
3996 XSETFASTINT (p->sequence_number, sequence_number);
3998 /* Put new into window structure in place of window */
3999 replace_window (window, new);
4001 o->next = Qnil;
4002 o->prev = Qnil;
4003 o->vchild = Qnil;
4004 o->hchild = Qnil;
4005 o->parent = new;
4007 p->start = Qnil;
4008 p->pointm = Qnil;
4009 p->buffer = Qnil;
4012 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
4013 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
4014 WINDOW defaults to selected one and SIZE to half its size.
4015 If optional third arg HORFLAG is non-nil, split side by side
4016 and put SIZE columns in the first of the pair. In that case,
4017 SIZE includes that window's scroll bar, or the divider column to its right.
4018 Interactively, all arguments are nil.
4020 Returns the newly created window (which is the lower or rightmost one).
4021 The upper or leftmost window is the original one, and remains selected
4022 if it was selected before.
4024 See Info node `(elisp)Splitting Windows' for more details and examples.*/)
4025 (window, size, horflag)
4026 Lisp_Object window, size, horflag;
4028 register Lisp_Object new;
4029 register struct window *o, *p;
4030 FRAME_PTR fo;
4031 register int size_int;
4033 if (NILP (window))
4034 window = selected_window;
4035 else
4036 CHECK_LIVE_WINDOW (window);
4038 o = XWINDOW (window);
4039 fo = XFRAME (WINDOW_FRAME (o));
4041 if (NILP (size))
4043 if (!NILP (horflag))
4044 /* Calculate the size of the left-hand window, by dividing
4045 the usable space in columns by two.
4046 We round up, since the left-hand window may include
4047 a dividing line, while the right-hand may not. */
4048 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
4049 else
4050 size_int = XFASTINT (o->total_lines) >> 1;
4052 else
4054 CHECK_NUMBER (size);
4055 size_int = XINT (size);
4058 if (MINI_WINDOW_P (o))
4059 error ("Attempt to split minibuffer window");
4060 else if (window_fixed_size_p (o, !NILP (horflag), 0))
4061 error ("Attempt to split fixed-size window");
4063 check_min_window_sizes ();
4065 if (NILP (horflag))
4067 int window_safe_height = window_min_size_2 (o, 0);
4069 if (size_int < window_safe_height)
4070 error ("Window height %d too small (after splitting)", size_int);
4071 if (size_int + window_safe_height > XFASTINT (o->total_lines))
4072 error ("Window height %d too small (after splitting)",
4073 XFASTINT (o->total_lines) - size_int);
4074 if (NILP (o->parent)
4075 || NILP (XWINDOW (o->parent)->vchild))
4077 make_dummy_parent (window);
4078 new = o->parent;
4079 XWINDOW (new)->vchild = window;
4082 else
4084 int window_safe_width = window_min_size_2 (o, 1);
4086 if (size_int < window_safe_width)
4087 error ("Window width %d too small (after splitting)", size_int);
4088 if (size_int + window_safe_width > XFASTINT (o->total_cols))
4089 error ("Window width %d too small (after splitting)",
4090 XFASTINT (o->total_cols) - size_int);
4091 if (NILP (o->parent)
4092 || NILP (XWINDOW (o->parent)->hchild))
4094 make_dummy_parent (window);
4095 new = o->parent;
4096 XWINDOW (new)->hchild = window;
4100 /* Now we know that window's parent is a vertical combination
4101 if we are dividing vertically, or a horizontal combination
4102 if we are making side-by-side windows */
4104 windows_or_buffers_changed++;
4105 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
4106 new = make_window ();
4107 p = XWINDOW (new);
4109 p->frame = o->frame;
4110 p->next = o->next;
4111 if (!NILP (p->next))
4112 XWINDOW (p->next)->prev = new;
4113 p->prev = window;
4114 o->next = new;
4115 p->parent = o->parent;
4116 p->buffer = Qt;
4117 p->window_end_valid = Qnil;
4118 bzero (&p->last_cursor, sizeof p->last_cursor);
4120 /* Duplicate special geometry settings. */
4122 p->left_margin_cols = o->left_margin_cols;
4123 p->right_margin_cols = o->right_margin_cols;
4124 p->left_fringe_width = o->left_fringe_width;
4125 p->right_fringe_width = o->right_fringe_width;
4126 p->fringes_outside_margins = o->fringes_outside_margins;
4127 p->scroll_bar_width = o->scroll_bar_width;
4128 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
4130 /* Apportion the available frame space among the two new windows */
4132 if (!NILP (horflag))
4134 p->total_lines = o->total_lines;
4135 p->top_line = o->top_line;
4136 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
4137 XSETFASTINT (o->total_cols, size_int);
4138 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
4139 adjust_window_margins (p);
4140 adjust_window_margins (o);
4142 else
4144 p->left_col = o->left_col;
4145 p->total_cols = o->total_cols;
4146 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
4147 XSETFASTINT (o->total_lines, size_int);
4148 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
4151 /* Adjust glyph matrices. */
4152 adjust_glyphs (fo);
4154 Fset_window_buffer (new, o->buffer, Qt);
4155 return new;
4158 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
4159 doc: /* Make current window ARG lines bigger.
4160 From program, optional second arg non-nil means grow sideways ARG columns.
4161 Interactively, if an argument is not given, make the window one line bigger.
4162 If HORIZONTAL is non-nil, enlarge horizontally instead of vertically.
4163 This function can delete windows, even the second window, if they get
4164 too small. */)
4165 (arg, horizontal)
4166 Lisp_Object arg, horizontal;
4168 CHECK_NUMBER (arg);
4169 enlarge_window (selected_window, XINT (arg), !NILP (horizontal));
4171 if (! NILP (Vwindow_configuration_change_hook))
4172 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4174 return Qnil;
4177 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
4178 doc: /* Make current window ARG lines smaller.
4179 From program, optional second arg non-nil means shrink sideways arg columns.
4180 Interactively, if an argument is not given, make the window one line smaller.
4181 Only siblings to the right or below are changed. */)
4182 (arg, side)
4183 Lisp_Object arg, side;
4185 CHECK_NUMBER (arg);
4186 enlarge_window (selected_window, -XINT (arg), !NILP (side));
4188 if (! NILP (Vwindow_configuration_change_hook))
4189 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4191 return Qnil;
4195 window_height (window)
4196 Lisp_Object window;
4198 register struct window *p = XWINDOW (window);
4199 return WINDOW_TOTAL_LINES (p);
4203 window_width (window)
4204 Lisp_Object window;
4206 register struct window *p = XWINDOW (window);
4207 return WINDOW_TOTAL_COLS (p);
4211 #define CURBEG(w) \
4212 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
4214 #define CURSIZE(w) \
4215 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
4218 /* Enlarge WINDOW by DELTA.
4219 HORIZ_FLAG nonzero means enlarge it horizontally;
4220 zero means do it vertically.
4222 Siblings of the selected window are resized to fulfill the size
4223 request. If they become too small in the process, they will be
4224 deleted. */
4226 static void
4227 enlarge_window (window, delta, horiz_flag)
4228 Lisp_Object window;
4229 int delta, horiz_flag;
4231 Lisp_Object parent, next, prev;
4232 struct window *p;
4233 Lisp_Object *sizep;
4234 int maximum;
4235 int (*sizefun) P_ ((Lisp_Object))
4236 = horiz_flag ? window_width : window_height;
4237 void (*setsizefun) P_ ((Lisp_Object, int, int))
4238 = (horiz_flag ? set_window_width : set_window_height);
4240 /* Check values of window_min_width and window_min_height for
4241 validity. */
4242 check_min_window_sizes ();
4244 /* Give up if this window cannot be resized. */
4245 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4246 error ("Window is not resizable");
4248 /* Find the parent of the selected window. */
4249 while (1)
4251 p = XWINDOW (window);
4252 parent = p->parent;
4254 if (NILP (parent))
4256 if (horiz_flag)
4257 error ("No other window to side of this one");
4258 break;
4261 if (horiz_flag
4262 ? !NILP (XWINDOW (parent)->hchild)
4263 : !NILP (XWINDOW (parent)->vchild))
4264 break;
4266 window = parent;
4269 sizep = &CURSIZE (window);
4272 register int maxdelta;
4274 /* Compute the maximum size increment this window can have. */
4276 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
4277 /* This is a main window followed by a minibuffer. */
4278 : !NILP (p->next) ? ((*sizefun) (p->next)
4279 - window_min_size (XWINDOW (p->next),
4280 horiz_flag, 0, 0))
4281 /* This is a minibuffer following a main window. */
4282 : !NILP (p->prev) ? ((*sizefun) (p->prev)
4283 - window_min_size (XWINDOW (p->prev),
4284 horiz_flag, 0, 0))
4285 /* This is a frame with only one window, a minibuffer-only
4286 or a minibufferless frame. */
4287 : (delta = 0));
4289 if (delta > maxdelta)
4290 /* This case traps trying to make the minibuffer
4291 the full frame, or make the only window aside from the
4292 minibuffer the full frame. */
4293 delta = maxdelta;
4296 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), horiz_flag, 0, 0))
4298 delete_window (window);
4299 return;
4302 if (delta == 0)
4303 return;
4305 /* Find the total we can get from other siblings without deleting them. */
4306 maximum = 0;
4307 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
4308 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
4309 horiz_flag, 0, 0);
4310 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
4311 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
4312 horiz_flag, 0, 0);
4314 /* If we can get it all from them without deleting them, do so. */
4315 if (delta <= maximum)
4317 Lisp_Object first_unaffected;
4318 Lisp_Object first_affected;
4319 int fixed_p;
4321 next = p->next;
4322 prev = p->prev;
4323 first_affected = window;
4324 /* Look at one sibling at a time,
4325 moving away from this window in both directions alternately,
4326 and take as much as we can get without deleting that sibling. */
4327 while (delta != 0
4328 && (!NILP (next) || !NILP (prev)))
4330 if (! NILP (next))
4332 int this_one = ((*sizefun) (next)
4333 - window_min_size (XWINDOW (next),
4334 horiz_flag, 0, &fixed_p));
4335 if (!fixed_p)
4337 if (this_one > delta)
4338 this_one = delta;
4340 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
4341 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4343 delta -= this_one;
4346 next = XWINDOW (next)->next;
4349 if (delta == 0)
4350 break;
4352 if (! NILP (prev))
4354 int this_one = ((*sizefun) (prev)
4355 - window_min_size (XWINDOW (prev),
4356 horiz_flag, 0, &fixed_p));
4357 if (!fixed_p)
4359 if (this_one > delta)
4360 this_one = delta;
4362 first_affected = prev;
4364 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
4365 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4367 delta -= this_one;
4370 prev = XWINDOW (prev)->prev;
4374 xassert (delta == 0);
4376 /* Now recalculate the edge positions of all the windows affected,
4377 based on the new sizes. */
4378 first_unaffected = next;
4379 prev = first_affected;
4380 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4381 prev = next, next = XWINDOW (next)->next)
4383 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4384 /* This does not change size of NEXT,
4385 but it propagates the new top edge to its children */
4386 (*setsizefun) (next, (*sizefun) (next), 0);
4389 else
4391 register int delta1;
4392 register int opht = (*sizefun) (parent);
4394 if (opht <= XINT (*sizep) + delta)
4396 /* If trying to grow this window to or beyond size of the parent,
4397 just delete all the sibling windows. */
4398 Lisp_Object start, tem, next;
4400 start = XWINDOW (parent)->vchild;
4401 if (NILP (start))
4402 start = XWINDOW (parent)->hchild;
4404 /* Delete any siblings that come after WINDOW. */
4405 tem = XWINDOW (window)->next;
4406 while (! NILP (tem))
4408 next = XWINDOW (tem)->next;
4409 delete_window (tem);
4410 tem = next;
4413 /* Delete any siblings that come after WINDOW.
4414 Note that if START is not WINDOW, then WINDOW still
4415 Fhas siblings, so WINDOW has not yet replaced its parent. */
4416 tem = start;
4417 while (! EQ (tem, window))
4419 next = XWINDOW (tem)->next;
4420 delete_window (tem);
4421 tem = next;
4424 else
4426 /* Otherwise, make delta1 just right so that if we add
4427 delta1 lines to this window and to the parent, and then
4428 shrink the parent back to its original size, the new
4429 proportional size of this window will increase by delta.
4431 The function size_window will compute the new height h'
4432 of the window from delta1 as:
4434 e = delta1/n
4435 x = delta1 - delta1/n * n for the 1st resizable child
4436 h' = h + e + x
4438 where n is the number of children that can be resized.
4439 We can ignore x by choosing a delta1 that is a multiple of
4440 n. We want the height of this window to come out as
4442 h' = h + delta
4444 So, delta1 must be
4446 h + e = h + delta
4447 delta1/n = delta
4448 delta1 = n * delta.
4450 The number of children n equals the number of resizable
4451 children of this window + 1 because we know window itself
4452 is resizable (otherwise we would have signalled an error). */
4454 struct window *w = XWINDOW (window);
4455 Lisp_Object s;
4456 int n = 1;
4458 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
4459 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4460 ++n;
4461 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
4462 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4463 ++n;
4465 delta1 = n * delta;
4467 /* Add delta1 lines or columns to this window, and to the parent,
4468 keeping things consistent while not affecting siblings. */
4469 XSETINT (CURSIZE (parent), opht + delta1);
4470 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4472 /* Squeeze out delta1 lines or columns from our parent,
4473 shriking this window and siblings proportionately.
4474 This brings parent back to correct size.
4475 Delta1 was calculated so this makes this window the desired size,
4476 taking it all out of the siblings. */
4477 (*setsizefun) (parent, opht, 0);
4482 XSETFASTINT (p->last_modified, 0);
4483 XSETFASTINT (p->last_overlay_modified, 0);
4485 /* Adjust glyph matrices. */
4486 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4490 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4491 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4492 zero means adjust the height, moving the bottom edge.
4494 Following siblings of the selected window are resized to fulfill
4495 the size request. If they become too small in the process, they
4496 are not deleted; instead, we signal an error. */
4498 static void
4499 adjust_window_trailing_edge (window, delta, horiz_flag)
4500 Lisp_Object window;
4501 int delta, horiz_flag;
4503 Lisp_Object parent, child;
4504 struct window *p;
4505 Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
4506 int delcount = window_deletion_count;
4508 /* Check values of window_min_width and window_min_height for
4509 validity. */
4510 check_min_window_sizes ();
4512 if (NILP (window))
4513 window = Fselected_window ();
4515 CHECK_WINDOW (window);
4517 /* Give up if this window cannot be resized. */
4518 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4519 error ("Window is not resizable");
4521 while (1)
4523 Lisp_Object first_parallel = Qnil;
4525 if (NILP (window))
4527 /* This happens if WINDOW on the previous iteration was
4528 at top level of the window tree. */
4529 Fset_window_configuration (old_config);
4530 error ("Specified window edge is fixed");
4533 p = XWINDOW (window);
4534 parent = p->parent;
4536 /* See if this level has windows in parallel in the specified
4537 direction. If so, set FIRST_PARALLEL to the first one. */
4538 if (horiz_flag)
4540 if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
4541 first_parallel = XWINDOW (parent)->vchild;
4542 else if (NILP (parent) && !NILP (p->next))
4544 /* Handle the vertical chain of main window and minibuffer
4545 which has no parent. */
4546 first_parallel = window;
4547 while (! NILP (XWINDOW (first_parallel)->prev))
4548 first_parallel = XWINDOW (first_parallel)->prev;
4551 else
4553 if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
4554 first_parallel = XWINDOW (parent)->hchild;
4557 /* If this level's succession is in the desired dimension,
4558 and this window is the last one, and there is no higher level,
4559 its trailing edge is fixed. */
4560 if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
4561 && NILP (parent))
4563 Fset_window_configuration (old_config);
4564 error ("Specified window edge is fixed");
4567 /* Don't make this window too small. */
4568 if (XINT (CURSIZE (window)) + delta
4569 < window_min_size_2 (XWINDOW (window), horiz_flag))
4571 Fset_window_configuration (old_config);
4572 error ("Cannot adjust window size as specified");
4575 /* Clear out some redisplay caches. */
4576 XSETFASTINT (p->last_modified, 0);
4577 XSETFASTINT (p->last_overlay_modified, 0);
4579 /* Adjust this window's edge. */
4580 XSETINT (CURSIZE (window),
4581 XINT (CURSIZE (window)) + delta);
4583 /* If this window has following siblings in the desired dimension,
4584 make them smaller, and exit the loop.
4586 (If we reach the top of the tree and can never do this,
4587 we will fail and report an error, above.) */
4588 if (NILP (first_parallel))
4590 if (!NILP (p->next))
4592 /* This may happen for the minibuffer. In that case
4593 the window_deletion_count check below does not work. */
4594 if (XINT (CURSIZE (p->next)) - delta <= 0)
4596 Fset_window_configuration (old_config);
4597 error ("Cannot adjust window size as specified");
4600 XSETINT (CURBEG (p->next),
4601 XINT (CURBEG (p->next)) + delta);
4602 size_window (p->next, XINT (CURSIZE (p->next)) - delta,
4603 horiz_flag, 0, 1, 0);
4604 break;
4607 else
4608 /* Here we have a chain of parallel siblings, in the other dimension.
4609 Change the size of the other siblings. */
4610 for (child = first_parallel;
4611 ! NILP (child);
4612 child = XWINDOW (child)->next)
4613 if (! EQ (child, window))
4614 size_window (child, XINT (CURSIZE (child)) + delta,
4615 horiz_flag, 0, 0, 1);
4617 window = parent;
4620 /* If we made a window so small it got deleted,
4621 we failed. Report failure. */
4622 if (delcount != window_deletion_count)
4624 Fset_window_configuration (old_config);
4625 error ("Cannot adjust window size as specified");
4628 /* Adjust glyph matrices. */
4629 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4632 #undef CURBEG
4633 #undef CURSIZE
4635 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
4636 Sadjust_window_trailing_edge, 3, 3, 0,
4637 doc: /* Adjust the bottom or right edge of WINDOW by DELTA.
4638 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4639 Otherwise, adjust the height, moving the bottom edge.
4641 Following siblings of the selected window are resized to fulfill
4642 the size request. If they become too small in the process, they
4643 are not deleted; instead, we signal an error. */)
4644 (window, delta, horizontal)
4645 Lisp_Object window, delta, horizontal;
4647 CHECK_NUMBER (delta);
4648 adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
4650 if (! NILP (Vwindow_configuration_change_hook))
4651 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4653 return Qnil;
4658 /***********************************************************************
4659 Resizing Mini-Windows
4660 ***********************************************************************/
4662 static void shrink_window_lowest_first P_ ((struct window *, int));
4664 enum save_restore_action
4666 CHECK_ORIG_SIZES,
4667 SAVE_ORIG_SIZES,
4668 RESTORE_ORIG_SIZES
4671 static int save_restore_orig_size P_ ((struct window *,
4672 enum save_restore_action));
4674 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4675 from lowest windows first. */
4677 static void
4678 shrink_window_lowest_first (w, height)
4679 struct window *w;
4680 int height;
4682 struct window *c;
4683 Lisp_Object child;
4684 int old_height;
4686 xassert (!MINI_WINDOW_P (w));
4688 /* Set redisplay hints. */
4689 XSETFASTINT (w->last_modified, 0);
4690 XSETFASTINT (w->last_overlay_modified, 0);
4691 windows_or_buffers_changed++;
4692 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4694 old_height = XFASTINT (w->total_lines);
4695 XSETFASTINT (w->total_lines, height);
4697 if (!NILP (w->hchild))
4699 for (child = w->hchild; !NILP (child); child = c->next)
4701 c = XWINDOW (child);
4702 c->top_line = w->top_line;
4703 shrink_window_lowest_first (c, height);
4706 else if (!NILP (w->vchild))
4708 Lisp_Object last_child;
4709 int delta = old_height - height;
4710 int last_top;
4712 last_child = Qnil;
4714 /* Find the last child. We are taking space from lowest windows
4715 first, so we iterate over children from the last child
4716 backwards. */
4717 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
4718 last_child = child;
4720 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
4721 for (child = last_child; delta && !NILP (child); child = c->prev)
4723 int this_one;
4725 c = XWINDOW (child);
4726 this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
4728 if (this_one > delta)
4729 this_one = delta;
4731 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4732 delta -= this_one;
4735 /* Compute new positions. */
4736 last_top = XINT (w->top_line);
4737 for (child = w->vchild; !NILP (child); child = c->next)
4739 c = XWINDOW (child);
4740 c->top_line = make_number (last_top);
4741 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4742 last_top += XFASTINT (c->total_lines);
4748 /* Save, restore, or check positions and sizes in the window tree
4749 rooted at W. ACTION says what to do.
4751 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4752 orig_total_lines members are valid for all windows in the window
4753 tree. Value is non-zero if they are valid.
4755 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4756 orig_top_line and orig_total_lines for all windows in the tree.
4758 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4759 stored in orig_top_line and orig_total_lines for all windows. */
4761 static int
4762 save_restore_orig_size (w, action)
4763 struct window *w;
4764 enum save_restore_action action;
4766 int success_p = 1;
4768 while (w)
4770 if (!NILP (w->hchild))
4772 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4773 success_p = 0;
4775 else if (!NILP (w->vchild))
4777 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4778 success_p = 0;
4781 switch (action)
4783 case CHECK_ORIG_SIZES:
4784 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4785 return 0;
4786 break;
4788 case SAVE_ORIG_SIZES:
4789 w->orig_top_line = w->top_line;
4790 w->orig_total_lines = w->total_lines;
4791 XSETFASTINT (w->last_modified, 0);
4792 XSETFASTINT (w->last_overlay_modified, 0);
4793 break;
4795 case RESTORE_ORIG_SIZES:
4796 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4797 w->top_line = w->orig_top_line;
4798 w->total_lines = w->orig_total_lines;
4799 w->orig_total_lines = w->orig_top_line = Qnil;
4800 XSETFASTINT (w->last_modified, 0);
4801 XSETFASTINT (w->last_overlay_modified, 0);
4802 break;
4804 default:
4805 abort ();
4808 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4811 return success_p;
4815 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4816 without deleting other windows. */
4818 void
4819 grow_mini_window (w, delta)
4820 struct window *w;
4821 int delta;
4823 struct frame *f = XFRAME (w->frame);
4824 struct window *root;
4826 xassert (MINI_WINDOW_P (w));
4827 xassert (delta >= 0);
4829 /* Check values of window_min_width and window_min_height for
4830 validity. */
4831 check_min_window_sizes ();
4833 /* Compute how much we can enlarge the mini-window without deleting
4834 other windows. */
4835 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4836 if (delta)
4838 int min_height = window_min_size (root, 0, 0, 0);
4839 if (XFASTINT (root->total_lines) - delta < min_height)
4840 /* Note that the root window may already be smaller than
4841 min_height. */
4842 delta = max (0, XFASTINT (root->total_lines) - min_height);
4845 if (delta)
4847 /* Save original window sizes and positions, if not already done. */
4848 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4849 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4851 /* Shrink other windows. */
4852 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4854 /* Grow the mini-window. */
4855 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4856 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4857 XSETFASTINT (w->last_modified, 0);
4858 XSETFASTINT (w->last_overlay_modified, 0);
4860 adjust_glyphs (f);
4865 /* Shrink mini-window W. If there is recorded info about window sizes
4866 before a call to grow_mini_window, restore recorded window sizes.
4867 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4868 line. */
4870 void
4871 shrink_mini_window (w)
4872 struct window *w;
4874 struct frame *f = XFRAME (w->frame);
4875 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4877 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4879 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4880 adjust_glyphs (f);
4881 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4882 windows_or_buffers_changed = 1;
4884 else if (XFASTINT (w->total_lines) > 1)
4886 /* Distribute the additional lines of the mini-window
4887 among the other windows. */
4888 Lisp_Object window;
4889 XSETWINDOW (window, w);
4890 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
4896 /* Mark window cursors off for all windows in the window tree rooted
4897 at W by setting their phys_cursor_on_p flag to zero. Called from
4898 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4899 the frame are cleared. */
4901 void
4902 mark_window_cursors_off (w)
4903 struct window *w;
4905 while (w)
4907 if (!NILP (w->hchild))
4908 mark_window_cursors_off (XWINDOW (w->hchild));
4909 else if (!NILP (w->vchild))
4910 mark_window_cursors_off (XWINDOW (w->vchild));
4911 else
4912 w->phys_cursor_on_p = 0;
4914 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4919 /* Return number of lines of text (not counting mode lines) in W. */
4922 window_internal_height (w)
4923 struct window *w;
4925 int ht = XFASTINT (w->total_lines);
4927 if (!MINI_WINDOW_P (w))
4929 if (!NILP (w->parent)
4930 || !NILP (w->vchild)
4931 || !NILP (w->hchild)
4932 || !NILP (w->next)
4933 || !NILP (w->prev)
4934 || WINDOW_WANTS_MODELINE_P (w))
4935 --ht;
4937 if (WINDOW_WANTS_HEADER_LINE_P (w))
4938 --ht;
4941 return ht;
4945 /* Return the number of columns in W.
4946 Don't count columns occupied by scroll bars or the vertical bar
4947 separating W from the sibling to its right. */
4950 window_box_text_cols (w)
4951 struct window *w;
4953 struct frame *f = XFRAME (WINDOW_FRAME (w));
4954 int width = XINT (w->total_cols);
4956 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4957 /* Scroll bars occupy a few columns. */
4958 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4959 else if (!FRAME_WINDOW_P (f)
4960 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4961 /* The column of `|' characters separating side-by-side windows
4962 occupies one column only. */
4963 width -= 1;
4965 if (FRAME_WINDOW_P (f))
4966 /* On window-systems, fringes and display margins cannot be
4967 used for normal text. */
4968 width -= (WINDOW_FRINGE_COLS (w)
4969 + WINDOW_LEFT_MARGIN_COLS (w)
4970 + WINDOW_RIGHT_MARGIN_COLS (w));
4972 return width;
4976 /************************************************************************
4977 Window Scrolling
4978 ***********************************************************************/
4980 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4981 N screen-fulls, which is defined as the height of the window minus
4982 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4983 instead. Negative values of N mean scroll down. NOERROR non-zero
4984 means don't signal an error if we try to move over BEGV or ZV,
4985 respectively. */
4987 static void
4988 window_scroll (window, n, whole, noerror)
4989 Lisp_Object window;
4990 int n;
4991 int whole;
4992 int noerror;
4994 immediate_quit = 1;
4996 /* If we must, use the pixel-based version which is much slower than
4997 the line-based one but can handle varying line heights. */
4998 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4999 window_scroll_pixel_based (window, n, whole, noerror);
5000 else
5001 window_scroll_line_based (window, n, whole, noerror);
5003 immediate_quit = 0;
5007 /* Implementation of window_scroll that works based on pixel line
5008 heights. See the comment of window_scroll for parameter
5009 descriptions. */
5011 static void
5012 window_scroll_pixel_based (window, n, whole, noerror)
5013 Lisp_Object window;
5014 int n;
5015 int whole;
5016 int noerror;
5018 struct it it;
5019 struct window *w = XWINDOW (window);
5020 struct text_pos start;
5021 int this_scroll_margin;
5022 /* True if we fiddled the window vscroll field without really scrolling. */
5023 int vscrolled = 0;
5024 int x, y, rtop, rbot, rowh, vpos;
5026 SET_TEXT_POS_FROM_MARKER (start, w->start);
5028 /* If PT is not visible in WINDOW, move back one half of
5029 the screen. Allow PT to be partially visible, otherwise
5030 something like (scroll-down 1) with PT in the line before
5031 the partially visible one would recenter. */
5033 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
5035 /* Move backward half the height of the window. Performance note:
5036 vmotion used here is about 10% faster, but would give wrong
5037 results for variable height lines. */
5038 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5039 it.current_y = it.last_visible_y;
5040 move_it_vertically_backward (&it, window_box_height (w) / 2);
5042 /* The function move_iterator_vertically may move over more than
5043 the specified y-distance. If it->w is small, e.g. a
5044 mini-buffer window, we may end up in front of the window's
5045 display area. This is the case when Start displaying at the
5046 start of the line containing PT in this case. */
5047 if (it.current_y <= 0)
5049 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5050 move_it_vertically_backward (&it, 0);
5051 it.current_y = 0;
5054 start = it.current.pos;
5056 else if (auto_window_vscroll_p)
5058 if (rtop || rbot) /* partially visible */
5060 int px;
5061 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
5062 if (whole)
5063 dy = max ((window_box_height (w)
5064 - next_screen_context_lines * dy),
5065 dy);
5066 dy *= n;
5068 if (n < 0)
5070 /* Only vscroll backwards if already vscrolled forwards. */
5071 if (w->vscroll < 0 && rtop > 0)
5073 px = max (0, -w->vscroll - min (rtop, -dy));
5074 Fset_window_vscroll (window, make_number (px), Qt);
5075 return;
5078 if (n > 0)
5080 /* Do vscroll if already vscrolled or only display line. */
5081 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
5083 px = max (0, -w->vscroll + min (rbot, dy));
5084 Fset_window_vscroll (window, make_number (px), Qt);
5085 return;
5088 /* Maybe modify window start instead of scrolling. */
5089 if (rbot > 0 || w->vscroll < 0)
5091 int spos;
5093 Fset_window_vscroll (window, make_number (0), Qt);
5094 /* If there are other text lines above the current row,
5095 move window start to current row. Else to next row. */
5096 if (rbot > 0)
5097 spos = XINT (Fline_beginning_position (Qnil));
5098 else
5099 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
5100 set_marker_restricted (w->start, make_number (spos),
5101 w->buffer);
5102 w->start_at_line_beg = Qt;
5103 w->update_mode_line = Qt;
5104 XSETFASTINT (w->last_modified, 0);
5105 XSETFASTINT (w->last_overlay_modified, 0);
5106 /* Set force_start so that redisplay_window will run the
5107 window-scroll-functions. */
5108 w->force_start = Qt;
5109 return;
5113 /* Cancel previous vscroll. */
5114 Fset_window_vscroll (window, make_number (0), Qt);
5117 /* If scroll_preserve_screen_position is non-nil, we try to set
5118 point in the same window line as it is now, so get that line. */
5119 if (!NILP (Vscroll_preserve_screen_position))
5121 /* We preserve the goal pixel coordinate across consecutive
5122 calls to scroll-up or scroll-down. This avoids the
5123 possibility of point becoming "stuck" on a tall line when
5124 scrolling by one line. */
5125 if (window_scroll_pixel_based_preserve_y < 0
5126 || (!EQ (current_kboard->Vlast_command, Qscroll_up)
5127 && !EQ (current_kboard->Vlast_command, Qscroll_down)))
5129 start_display (&it, w, start);
5130 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5131 window_scroll_pixel_based_preserve_y = it.current_y;
5134 else
5135 window_scroll_pixel_based_preserve_y = -1;
5137 /* Move iterator it from start the specified distance forward or
5138 backward. The result is the new window start. */
5139 start_display (&it, w, start);
5140 if (whole)
5142 int start_pos = IT_CHARPOS (it);
5143 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
5144 dy = max ((window_box_height (w)
5145 - next_screen_context_lines * dy),
5146 dy) * n;
5148 /* Note that move_it_vertically always moves the iterator to the
5149 start of a line. So, if the last line doesn't have a newline,
5150 we would end up at the start of the line ending at ZV. */
5151 if (dy <= 0)
5153 move_it_vertically_backward (&it, -dy);
5154 /* Ensure we actually do move, e.g. in case we are currently
5155 looking at an image that is taller that the window height. */
5156 while (start_pos == IT_CHARPOS (it)
5157 && start_pos > BEGV)
5158 move_it_by_lines (&it, -1, 1);
5160 else if (dy > 0)
5162 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
5163 MOVE_TO_POS | MOVE_TO_Y);
5164 /* Ensure we actually do move, e.g. in case we are currently
5165 looking at an image that is taller that the window height. */
5166 while (start_pos == IT_CHARPOS (it)
5167 && start_pos < ZV)
5168 move_it_by_lines (&it, 1, 1);
5171 else
5172 move_it_by_lines (&it, n, 1);
5174 /* We failed if we find ZV is already on the screen (scrolling up,
5175 means there's nothing past the end), or if we can't start any
5176 earlier (scrolling down, means there's nothing past the top). */
5177 if ((n > 0 && IT_CHARPOS (it) == ZV)
5178 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
5180 if (IT_CHARPOS (it) == ZV)
5182 if (it.current_y < it.last_visible_y
5183 && (it.current_y + it.max_ascent + it.max_descent
5184 > it.last_visible_y))
5186 /* The last line was only partially visible, make it fully
5187 visible. */
5188 w->vscroll = (it.last_visible_y
5189 - it.current_y + it.max_ascent + it.max_descent);
5190 adjust_glyphs (it.f);
5192 else if (noerror)
5193 return;
5194 else if (n < 0) /* could happen with empty buffers */
5195 xsignal0 (Qbeginning_of_buffer);
5196 else
5197 xsignal0 (Qend_of_buffer);
5199 else
5201 if (w->vscroll != 0)
5202 /* The first line was only partially visible, make it fully
5203 visible. */
5204 w->vscroll = 0;
5205 else if (noerror)
5206 return;
5207 else
5208 xsignal0 (Qbeginning_of_buffer);
5211 /* If control gets here, then we vscrolled. */
5213 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5215 /* Don't try to change the window start below. */
5216 vscrolled = 1;
5219 if (! vscrolled)
5221 int pos = IT_CHARPOS (it);
5222 int bytepos;
5224 /* If in the middle of a multi-glyph character move forward to
5225 the next character. */
5226 if (in_display_vector_p (&it))
5228 ++pos;
5229 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
5232 /* Set the window start, and set up the window for redisplay. */
5233 set_marker_restricted (w->start, make_number (pos),
5234 w->buffer);
5235 bytepos = XMARKER (w->start)->bytepos;
5236 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
5237 ? Qt : Qnil);
5238 w->update_mode_line = Qt;
5239 XSETFASTINT (w->last_modified, 0);
5240 XSETFASTINT (w->last_overlay_modified, 0);
5241 /* Set force_start so that redisplay_window will run the
5242 window-scroll-functions. */
5243 w->force_start = Qt;
5246 /* The rest of this function uses current_y in a nonstandard way,
5247 not including the height of the header line if any. */
5248 it.current_y = it.vpos = 0;
5250 /* Move PT out of scroll margins.
5251 This code wants current_y to be zero at the window start position
5252 even if there is a header line. */
5253 this_scroll_margin = max (0, scroll_margin);
5254 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
5255 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5257 if (n > 0)
5259 /* We moved the window start towards ZV, so PT may be now
5260 in the scroll margin at the top. */
5261 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5262 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5263 && (NILP (Vscroll_preserve_screen_position)
5264 || EQ (Vscroll_preserve_screen_position, Qt)))
5265 /* We found PT at a legitimate height. Leave it alone. */
5267 else if (window_scroll_pixel_based_preserve_y >= 0)
5269 /* If we have a header line, take account of it.
5270 This is necessary because we set it.current_y to 0, above. */
5271 move_it_to (&it, -1, -1,
5272 window_scroll_pixel_based_preserve_y
5273 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
5274 -1, MOVE_TO_Y);
5275 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5277 else
5279 while (it.current_y < this_scroll_margin)
5281 int prev = it.current_y;
5282 move_it_by_lines (&it, 1, 1);
5283 if (prev == it.current_y)
5284 break;
5286 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5289 else if (n < 0)
5291 int charpos, bytepos;
5292 int partial_p;
5294 /* Save our position, for the
5295 window_scroll_pixel_based_preserve_y case. */
5296 charpos = IT_CHARPOS (it);
5297 bytepos = IT_BYTEPOS (it);
5299 /* We moved the window start towards BEGV, so PT may be now
5300 in the scroll margin at the bottom. */
5301 move_it_to (&it, PT, -1,
5302 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5303 - this_scroll_margin - 1),
5305 MOVE_TO_POS | MOVE_TO_Y);
5307 /* Save our position, in case it's correct. */
5308 charpos = IT_CHARPOS (it);
5309 bytepos = IT_BYTEPOS (it);
5311 /* See if point is on a partially visible line at the end. */
5312 if (it.what == IT_EOB)
5313 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5314 else
5316 move_it_by_lines (&it, 1, 1);
5317 partial_p = it.current_y > it.last_visible_y;
5320 if (charpos == PT && !partial_p
5321 && (NILP (Vscroll_preserve_screen_position)
5322 || EQ (Vscroll_preserve_screen_position, Qt)))
5323 /* We found PT before we found the display margin, so PT is ok. */
5325 else if (window_scroll_pixel_based_preserve_y >= 0)
5327 SET_TEXT_POS_FROM_MARKER (start, w->start);
5328 start_display (&it, w, start);
5329 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5330 here because we called start_display again and did not
5331 alter it.current_y this time. */
5332 move_it_to (&it, -1, -1, window_scroll_pixel_based_preserve_y, -1,
5333 MOVE_TO_Y);
5334 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5336 else
5338 if (partial_p)
5339 /* The last line was only partially visible, so back up two
5340 lines to make sure we're on a fully visible line. */
5342 move_it_by_lines (&it, -2, 0);
5343 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5345 else
5346 /* No, the position we saved is OK, so use it. */
5347 SET_PT_BOTH (charpos, bytepos);
5353 /* Implementation of window_scroll that works based on screen lines.
5354 See the comment of window_scroll for parameter descriptions. */
5356 static void
5357 window_scroll_line_based (window, n, whole, noerror)
5358 Lisp_Object window;
5359 int n;
5360 int whole;
5361 int noerror;
5363 register struct window *w = XWINDOW (window);
5364 register int opoint = PT, opoint_byte = PT_BYTE;
5365 register int pos, pos_byte;
5366 register int ht = window_internal_height (w);
5367 register Lisp_Object tem;
5368 int lose;
5369 Lisp_Object bolp;
5370 int startpos;
5371 struct position posit;
5372 int original_vpos;
5374 /* If scrolling screen-fulls, compute the number of lines to
5375 scroll from the window's height. */
5376 if (whole)
5377 n *= max (1, ht - next_screen_context_lines);
5379 startpos = marker_position (w->start);
5381 posit = *compute_motion (startpos, 0, 0, 0,
5382 PT, ht, 0,
5383 -1, XINT (w->hscroll),
5384 0, w);
5385 original_vpos = posit.vpos;
5387 XSETFASTINT (tem, PT);
5388 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5390 if (NILP (tem))
5392 Fvertical_motion (make_number (- (ht / 2)), window);
5393 startpos = PT;
5396 SET_PT (startpos);
5397 lose = n < 0 && PT == BEGV;
5398 Fvertical_motion (make_number (n), window);
5399 pos = PT;
5400 pos_byte = PT_BYTE;
5401 bolp = Fbolp ();
5402 SET_PT_BOTH (opoint, opoint_byte);
5404 if (lose)
5406 if (noerror)
5407 return;
5408 else
5409 xsignal0 (Qbeginning_of_buffer);
5412 if (pos < ZV)
5414 int this_scroll_margin = scroll_margin;
5416 /* Don't use a scroll margin that is negative or too large. */
5417 if (this_scroll_margin < 0)
5418 this_scroll_margin = 0;
5420 if (XINT (w->total_lines) < 4 * scroll_margin)
5421 this_scroll_margin = XINT (w->total_lines) / 4;
5423 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
5424 w->start_at_line_beg = bolp;
5425 w->update_mode_line = Qt;
5426 XSETFASTINT (w->last_modified, 0);
5427 XSETFASTINT (w->last_overlay_modified, 0);
5428 /* Set force_start so that redisplay_window will run
5429 the window-scroll-functions. */
5430 w->force_start = Qt;
5432 if (!NILP (Vscroll_preserve_screen_position)
5433 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5435 SET_PT_BOTH (pos, pos_byte);
5436 Fvertical_motion (make_number (original_vpos), window);
5438 /* If we scrolled forward, put point enough lines down
5439 that it is outside the scroll margin. */
5440 else if (n > 0)
5442 int top_margin;
5444 if (this_scroll_margin > 0)
5446 SET_PT_BOTH (pos, pos_byte);
5447 Fvertical_motion (make_number (this_scroll_margin), window);
5448 top_margin = PT;
5450 else
5451 top_margin = pos;
5453 if (top_margin <= opoint)
5454 SET_PT_BOTH (opoint, opoint_byte);
5455 else if (!NILP (Vscroll_preserve_screen_position))
5457 SET_PT_BOTH (pos, pos_byte);
5458 Fvertical_motion (make_number (original_vpos), window);
5460 else
5461 SET_PT (top_margin);
5463 else if (n < 0)
5465 int bottom_margin;
5467 /* If we scrolled backward, put point near the end of the window
5468 but not within the scroll margin. */
5469 SET_PT_BOTH (pos, pos_byte);
5470 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
5471 if (XFASTINT (tem) == ht - this_scroll_margin)
5472 bottom_margin = PT;
5473 else
5474 bottom_margin = PT + 1;
5476 if (bottom_margin > opoint)
5477 SET_PT_BOTH (opoint, opoint_byte);
5478 else
5480 if (!NILP (Vscroll_preserve_screen_position))
5482 SET_PT_BOTH (pos, pos_byte);
5483 Fvertical_motion (make_number (original_vpos), window);
5485 else
5486 Fvertical_motion (make_number (-1), window);
5490 else
5492 if (noerror)
5493 return;
5494 else
5495 xsignal0 (Qend_of_buffer);
5500 /* Scroll selected_window up or down. If N is nil, scroll a
5501 screen-full which is defined as the height of the window minus
5502 next_screen_context_lines. If N is the symbol `-', scroll.
5503 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5504 up. This is the guts of Fscroll_up and Fscroll_down. */
5506 static void
5507 scroll_command (n, direction)
5508 Lisp_Object n;
5509 int direction;
5511 int count = SPECPDL_INDEX ();
5513 xassert (abs (direction) == 1);
5515 /* If selected window's buffer isn't current, make it current for
5516 the moment. But don't screw up if window_scroll gets an error. */
5517 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
5519 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5520 Fset_buffer (XWINDOW (selected_window)->buffer);
5522 /* Make redisplay consider other windows than just selected_window. */
5523 ++windows_or_buffers_changed;
5526 if (NILP (n))
5527 window_scroll (selected_window, direction, 1, 0);
5528 else if (EQ (n, Qminus))
5529 window_scroll (selected_window, -direction, 1, 0);
5530 else
5532 n = Fprefix_numeric_value (n);
5533 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5536 unbind_to (count, Qnil);
5539 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
5540 doc: /* Scroll text of current window upward ARG lines.
5541 If ARG is omitted or nil, scroll upward by a near full screen.
5542 A near full screen is `next-screen-context-lines' less than a full screen.
5543 Negative ARG means scroll downward.
5544 If ARG is the atom `-', scroll downward by nearly full screen.
5545 When calling from a program, supply as argument a number, nil, or `-'. */)
5546 (arg)
5547 Lisp_Object arg;
5549 scroll_command (arg, 1);
5550 return Qnil;
5553 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
5554 doc: /* Scroll text of current window down ARG lines.
5555 If ARG is omitted or nil, scroll down by a near full screen.
5556 A near full screen is `next-screen-context-lines' less than a full screen.
5557 Negative ARG means scroll upward.
5558 If ARG is the atom `-', scroll upward by nearly full screen.
5559 When calling from a program, supply as argument a number, nil, or `-'. */)
5560 (arg)
5561 Lisp_Object arg;
5563 scroll_command (arg, -1);
5564 return Qnil;
5567 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5568 doc: /* Return the other window for \"other window scroll\" commands.
5569 If `other-window-scroll-buffer' is non-nil, a window
5570 showing that buffer is used.
5571 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5572 specifies the window. This takes precedence over
5573 `other-window-scroll-buffer'. */)
5576 Lisp_Object window;
5578 if (MINI_WINDOW_P (XWINDOW (selected_window))
5579 && !NILP (Vminibuf_scroll_window))
5580 window = Vminibuf_scroll_window;
5581 /* If buffer is specified, scroll that buffer. */
5582 else if (!NILP (Vother_window_scroll_buffer))
5584 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5585 if (NILP (window))
5586 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5588 else
5590 /* Nothing specified; look for a neighboring window on the same
5591 frame. */
5592 window = Fnext_window (selected_window, Qnil, Qnil);
5594 if (EQ (window, selected_window))
5595 /* That didn't get us anywhere; look for a window on another
5596 visible frame. */
5598 window = Fnext_window (window, Qnil, Qt);
5599 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5600 && ! EQ (window, selected_window));
5603 CHECK_LIVE_WINDOW (window);
5605 if (EQ (window, selected_window))
5606 error ("There is no other window");
5608 return window;
5611 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5612 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5613 A near full screen is `next-screen-context-lines' less than a full screen.
5614 The next window is the one below the current one; or the one at the top
5615 if the current one is at the bottom. Negative ARG means scroll downward.
5616 If ARG is the atom `-', scroll downward by nearly full screen.
5617 When calling from a program, supply as argument a number, nil, or `-'.
5619 If `other-window-scroll-buffer' is non-nil, scroll the window
5620 showing that buffer, popping the buffer up if necessary.
5621 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5622 specifies the window to scroll. This takes precedence over
5623 `other-window-scroll-buffer'. */)
5624 (arg)
5625 Lisp_Object arg;
5627 Lisp_Object window;
5628 struct window *w;
5629 int count = SPECPDL_INDEX ();
5631 window = Fother_window_for_scrolling ();
5632 w = XWINDOW (window);
5634 /* Don't screw up if window_scroll gets an error. */
5635 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5636 ++windows_or_buffers_changed;
5638 Fset_buffer (w->buffer);
5639 SET_PT (marker_position (w->pointm));
5641 if (NILP (arg))
5642 window_scroll (window, 1, 1, 1);
5643 else if (EQ (arg, Qminus))
5644 window_scroll (window, -1, 1, 1);
5645 else
5647 if (CONSP (arg))
5648 arg = Fcar (arg);
5649 CHECK_NUMBER (arg);
5650 window_scroll (window, XINT (arg), 0, 1);
5653 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5654 unbind_to (count, Qnil);
5656 return Qnil;
5659 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "P\np",
5660 doc: /* Scroll selected window display ARG columns left.
5661 Default for ARG is window width minus 2.
5662 Value is the total amount of leftward horizontal scrolling in
5663 effect after the change.
5664 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5665 lower bound for automatic scrolling, i.e. automatic scrolling
5666 will not scroll a window to a column less than the value returned
5667 by this function. This happens in an interactive call. */)
5668 (arg, set_minimum)
5669 register Lisp_Object arg, set_minimum;
5671 Lisp_Object result;
5672 int hscroll;
5673 struct window *w = XWINDOW (selected_window);
5675 if (NILP (arg))
5676 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5677 else
5678 arg = Fprefix_numeric_value (arg);
5680 hscroll = XINT (w->hscroll) + XINT (arg);
5681 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5683 if (!NILP (set_minimum))
5684 w->min_hscroll = w->hscroll;
5686 return result;
5689 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "P\np",
5690 doc: /* Scroll selected window display ARG columns right.
5691 Default for ARG is window width minus 2.
5692 Value is the total amount of leftward horizontal scrolling in
5693 effect after the change.
5694 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5695 lower bound for automatic scrolling, i.e. automatic scrolling
5696 will not scroll a window to a column less than the value returned
5697 by this function. This happens in an interactive call. */)
5698 (arg, set_minimum)
5699 register Lisp_Object arg, set_minimum;
5701 Lisp_Object result;
5702 int hscroll;
5703 struct window *w = XWINDOW (selected_window);
5705 if (NILP (arg))
5706 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5707 else
5708 arg = Fprefix_numeric_value (arg);
5710 hscroll = XINT (w->hscroll) - XINT (arg);
5711 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5713 if (!NILP (set_minimum))
5714 w->min_hscroll = w->hscroll;
5716 return result;
5719 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5720 doc: /* Return the window which was selected when entering the minibuffer.
5721 Returns nil, if current window is not a minibuffer window. */)
5724 if (minibuf_level > 0
5725 && MINI_WINDOW_P (XWINDOW (selected_window))
5726 && WINDOW_LIVE_P (minibuf_selected_window))
5727 return minibuf_selected_window;
5729 return Qnil;
5732 /* Value is the number of lines actually displayed in window W,
5733 as opposed to its height. */
5735 static int
5736 displayed_window_lines (w)
5737 struct window *w;
5739 struct it it;
5740 struct text_pos start;
5741 int height = window_box_height (w);
5742 struct buffer *old_buffer;
5743 int bottom_y;
5745 if (XBUFFER (w->buffer) != current_buffer)
5747 old_buffer = current_buffer;
5748 set_buffer_internal (XBUFFER (w->buffer));
5750 else
5751 old_buffer = NULL;
5753 /* In case W->start is out of the accessible range, do something
5754 reasonable. This happens in Info mode when Info-scroll-down
5755 calls (recenter -1) while W->start is 1. */
5756 if (XMARKER (w->start)->charpos < BEGV)
5757 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5758 else if (XMARKER (w->start)->charpos > ZV)
5759 SET_TEXT_POS (start, ZV, ZV_BYTE);
5760 else
5761 SET_TEXT_POS_FROM_MARKER (start, w->start);
5763 start_display (&it, w, start);
5764 move_it_vertically (&it, height);
5765 bottom_y = line_bottom_y (&it);
5767 /* rms: On a non-window display,
5768 the value of it.vpos at the bottom of the screen
5769 seems to be 1 larger than window_box_height (w).
5770 This kludge fixes a bug whereby (move-to-window-line -1)
5771 when ZV is on the last screen line
5772 moves to the previous screen line instead of the last one. */
5773 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5774 height++;
5776 /* Add in empty lines at the bottom of the window. */
5777 if (bottom_y < height)
5779 int uy = FRAME_LINE_HEIGHT (it.f);
5780 it.vpos += (height - bottom_y + uy - 1) / uy;
5783 if (old_buffer)
5784 set_buffer_internal (old_buffer);
5786 return it.vpos;
5790 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5791 doc: /* Center point in window and redisplay frame.
5792 With prefix argument ARG, recenter putting point on screen line ARG
5793 relative to the current window. If ARG is negative, it counts up from the
5794 bottom of the window. (ARG should be less than the height of the window.)
5796 If ARG is omitted or nil, erase the entire frame and then redraw with point
5797 in the center of the current window. If `auto-resize-tool-bars' is set to
5798 `grow-only', this resets the tool-bar's height to the minimum height needed.
5800 Just C-u as prefix means put point in the center of the window
5801 and redisplay normally--don't erase and redraw the frame. */)
5802 (arg)
5803 register Lisp_Object arg;
5805 struct window *w = XWINDOW (selected_window);
5806 struct buffer *buf = XBUFFER (w->buffer);
5807 struct buffer *obuf = current_buffer;
5808 int center_p = 0;
5809 int charpos, bytepos;
5810 int iarg;
5811 int this_scroll_margin;
5813 /* If redisplay is suppressed due to an error, try again. */
5814 obuf->display_error_modiff = 0;
5816 if (NILP (arg))
5818 int i;
5820 /* Invalidate pixel data calculated for all compositions. */
5821 for (i = 0; i < n_compositions; i++)
5822 composition_table[i]->font = NULL;
5824 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5826 Fredraw_frame (WINDOW_FRAME (w));
5827 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5828 center_p = 1;
5830 else if (CONSP (arg)) /* Just C-u. */
5831 center_p = 1;
5832 else
5834 arg = Fprefix_numeric_value (arg);
5835 CHECK_NUMBER (arg);
5836 iarg = XINT (arg);
5839 set_buffer_internal (buf);
5841 /* Do this after making BUF current
5842 in case scroll_margin is buffer-local. */
5843 this_scroll_margin = max (0, scroll_margin);
5844 this_scroll_margin = min (this_scroll_margin,
5845 XFASTINT (w->total_lines) / 4);
5847 /* Handle centering on a graphical frame specially. Such frames can
5848 have variable-height lines and centering point on the basis of
5849 line counts would lead to strange effects. */
5850 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5852 if (center_p)
5854 struct it it;
5855 struct text_pos pt;
5857 SET_TEXT_POS (pt, PT, PT_BYTE);
5858 start_display (&it, w, pt);
5859 move_it_vertically_backward (&it, window_box_height (w) / 2);
5860 charpos = IT_CHARPOS (it);
5861 bytepos = IT_BYTEPOS (it);
5863 else if (iarg < 0)
5865 struct it it;
5866 struct text_pos pt;
5867 int nlines = -iarg;
5868 int extra_line_spacing;
5869 int h = window_box_height (w);
5871 iarg = - max (-iarg, this_scroll_margin);
5873 SET_TEXT_POS (pt, PT, PT_BYTE);
5874 start_display (&it, w, pt);
5876 /* Be sure we have the exact height of the full line containing PT. */
5877 move_it_by_lines (&it, 0, 1);
5879 /* The amount of pixels we have to move back is the window
5880 height minus what's displayed in the line containing PT,
5881 and the lines below. */
5882 it.current_y = 0;
5883 it.vpos = 0;
5884 move_it_by_lines (&it, nlines, 1);
5886 if (it.vpos == nlines)
5887 h -= it.current_y;
5888 else
5890 /* Last line has no newline */
5891 h -= line_bottom_y (&it);
5892 it.vpos++;
5895 /* Don't reserve space for extra line spacing of last line. */
5896 extra_line_spacing = it.max_extra_line_spacing;
5898 /* If we can't move down NLINES lines because we hit
5899 the end of the buffer, count in some empty lines. */
5900 if (it.vpos < nlines)
5902 nlines -= it.vpos;
5903 extra_line_spacing = it.extra_line_spacing;
5904 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5906 if (h <= 0)
5907 return Qnil;
5909 /* Now find the new top line (starting position) of the window. */
5910 start_display (&it, w, pt);
5911 it.current_y = 0;
5912 move_it_vertically_backward (&it, h);
5914 /* If extra line spacing is present, we may move too far
5915 back. This causes the last line to be only partially
5916 visible (which triggers redisplay to recenter that line
5917 in the middle), so move forward.
5918 But ignore extra line spacing on last line, as it is not
5919 considered to be part of the visible height of the line.
5921 h += extra_line_spacing;
5922 while (-it.current_y > h)
5923 move_it_by_lines (&it, 1, 1);
5925 charpos = IT_CHARPOS (it);
5926 bytepos = IT_BYTEPOS (it);
5928 else
5930 struct position pos;
5932 iarg = max (iarg, this_scroll_margin);
5934 pos = *vmotion (PT, -iarg, w);
5935 charpos = pos.bufpos;
5936 bytepos = pos.bytepos;
5939 else
5941 struct position pos;
5942 int ht = window_internal_height (w);
5944 if (center_p)
5945 iarg = ht / 2;
5946 else if (iarg < 0)
5947 iarg += ht;
5949 /* Don't let it get into the margin at either top or bottom. */
5950 iarg = max (iarg, this_scroll_margin);
5951 iarg = min (iarg, ht - this_scroll_margin - 1);
5953 pos = *vmotion (PT, - iarg, w);
5954 charpos = pos.bufpos;
5955 bytepos = pos.bytepos;
5958 /* Set the new window start. */
5959 set_marker_both (w->start, w->buffer, charpos, bytepos);
5960 w->window_end_valid = Qnil;
5962 w->optional_new_start = Qt;
5964 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5965 w->start_at_line_beg = Qt;
5966 else
5967 w->start_at_line_beg = Qnil;
5969 set_buffer_internal (obuf);
5970 return Qnil;
5974 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5975 0, 1, 0,
5976 doc: /* Return the height in lines of the text display area of WINDOW.
5977 WINDOW defaults to the selected window.
5978 This doesn't include the mode-line (or header-line if any) or any
5979 partial-height lines in the text display area. */)
5980 (window)
5981 Lisp_Object window;
5983 struct window *w = decode_window (window);
5984 int pixel_height = window_box_height (w);
5985 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5986 return make_number (line_height);
5991 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5992 1, 1, "P",
5993 doc: /* Position point relative to window.
5994 With no argument, position point at center of window.
5995 An argument specifies vertical position within the window;
5996 zero means top of window, negative means relative to bottom of window. */)
5997 (arg)
5998 Lisp_Object arg;
6000 struct window *w = XWINDOW (selected_window);
6001 int lines, start;
6002 Lisp_Object window;
6003 #if 0
6004 int this_scroll_margin;
6005 #endif
6007 window = selected_window;
6008 start = marker_position (w->start);
6009 if (start < BEGV || start > ZV)
6011 int height = window_internal_height (w);
6012 Fvertical_motion (make_number (- (height / 2)), window);
6013 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
6014 w->start_at_line_beg = Fbolp ();
6015 w->force_start = Qt;
6017 else
6018 Fgoto_char (w->start);
6020 lines = displayed_window_lines (w);
6022 #if 0
6023 this_scroll_margin = max (0, scroll_margin);
6024 this_scroll_margin = min (this_scroll_margin, lines / 4);
6025 #endif
6027 if (NILP (arg))
6028 XSETFASTINT (arg, lines / 2);
6029 else
6031 int iarg = XINT (Fprefix_numeric_value (arg));
6033 if (iarg < 0)
6034 iarg = iarg + lines;
6036 #if 0 /* This code would prevent move-to-window-line from moving point
6037 to a place inside the scroll margins (which would cause the
6038 next redisplay to scroll). I wrote this code, but then concluded
6039 it is probably better not to install it. However, it is here
6040 inside #if 0 so as not to lose it. -- rms. */
6042 /* Don't let it get into the margin at either top or bottom. */
6043 iarg = max (iarg, this_scroll_margin);
6044 iarg = min (iarg, lines - this_scroll_margin - 1);
6045 #endif
6047 arg = make_number (iarg);
6050 /* Skip past a partially visible first line. */
6051 if (w->vscroll)
6052 XSETINT (arg, XINT (arg) + 1);
6054 return Fvertical_motion (arg, window);
6059 /***********************************************************************
6060 Window Configuration
6061 ***********************************************************************/
6063 struct save_window_data
6065 EMACS_INT size_from_Lisp_Vector_struct;
6066 struct Lisp_Vector *next_from_Lisp_Vector_struct;
6067 Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
6068 Lisp_Object frame_tool_bar_lines;
6069 Lisp_Object selected_frame;
6070 Lisp_Object current_window;
6071 Lisp_Object current_buffer;
6072 Lisp_Object minibuf_scroll_window;
6073 Lisp_Object minibuf_selected_window;
6074 Lisp_Object root_window;
6075 Lisp_Object focus_frame;
6076 /* Record the values of window-min-width and window-min-height
6077 so that window sizes remain consistent with them. */
6078 Lisp_Object min_width, min_height;
6079 /* A vector, each of whose elements is a struct saved_window
6080 for one window. */
6081 Lisp_Object saved_windows;
6084 /* This is saved as a Lisp_Vector */
6085 struct saved_window
6087 /* these first two must agree with struct Lisp_Vector in lisp.h */
6088 EMACS_INT size_from_Lisp_Vector_struct;
6089 struct Lisp_Vector *next_from_Lisp_Vector_struct;
6091 Lisp_Object window;
6092 Lisp_Object buffer, start, pointm, mark;
6093 Lisp_Object left_col, top_line, total_cols, total_lines;
6094 Lisp_Object hscroll, min_hscroll;
6095 Lisp_Object parent, prev;
6096 Lisp_Object start_at_line_beg;
6097 Lisp_Object display_table;
6098 Lisp_Object orig_top_line, orig_total_lines;
6099 Lisp_Object left_margin_cols, right_margin_cols;
6100 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
6101 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
6102 Lisp_Object dedicated;
6105 #define SAVED_WINDOW_N(swv,n) \
6106 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
6108 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
6109 doc: /* Return t if OBJECT is a window-configuration object. */)
6110 (object)
6111 Lisp_Object object;
6113 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
6116 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
6117 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
6118 (config)
6119 Lisp_Object config;
6121 register struct save_window_data *data;
6122 struct Lisp_Vector *saved_windows;
6124 CHECK_WINDOW_CONFIGURATION (config);
6126 data = (struct save_window_data *) XVECTOR (config);
6127 saved_windows = XVECTOR (data->saved_windows);
6128 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6131 DEFUN ("set-window-configuration", Fset_window_configuration,
6132 Sset_window_configuration, 1, 1, 0,
6133 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
6134 CONFIGURATION must be a value previously returned
6135 by `current-window-configuration' (which see).
6136 If CONFIGURATION was made from a frame that is now deleted,
6137 only frame-independent values can be restored. In this case,
6138 the return value is nil. Otherwise the value is t. */)
6139 (configuration)
6140 Lisp_Object configuration;
6142 register struct save_window_data *data;
6143 struct Lisp_Vector *saved_windows;
6144 Lisp_Object new_current_buffer;
6145 Lisp_Object frame;
6146 FRAME_PTR f;
6147 int old_point = -1;
6149 CHECK_WINDOW_CONFIGURATION (configuration);
6151 data = (struct save_window_data *) XVECTOR (configuration);
6152 saved_windows = XVECTOR (data->saved_windows);
6154 new_current_buffer = data->current_buffer;
6155 if (NILP (XBUFFER (new_current_buffer)->name))
6156 new_current_buffer = Qnil;
6157 else
6159 if (XBUFFER (new_current_buffer) == current_buffer)
6160 /* The code further down "preserves point" by saving here PT in
6161 old_point and then setting it later back into PT. When the
6162 current-selected-window and the final-selected-window both show
6163 the current buffer, this suffers from the problem that the
6164 current PT is the window-point of the current-selected-window,
6165 while the final PT is the point of the final-selected-window, so
6166 this copy from one PT to the other would end up moving the
6167 window-point of the final-selected-window to the window-point of
6168 the current-selected-window. So we have to be careful which
6169 point of the current-buffer we copy into old_point. */
6170 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6171 && WINDOWP (selected_window)
6172 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
6173 && !EQ (selected_window, data->current_window))
6174 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6175 else
6176 old_point = PT;
6177 else
6178 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6179 point in new_current_buffer as of the last time this buffer was
6180 used. This can be non-deterministic since it can be changed by
6181 things like jit-lock by mere temporary selection of some random
6182 window that happens to show this buffer.
6183 So if possible we want this arbitrary choice of "which point" to
6184 be the one from the to-be-selected-window so as to prevent this
6185 window's cursor from being copied from another window. */
6186 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6187 /* If current_window = selected_window, its point is in BUF_PT. */
6188 && !EQ (selected_window, data->current_window))
6189 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6190 else
6191 old_point = BUF_PT (XBUFFER (new_current_buffer));
6194 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6195 f = XFRAME (frame);
6197 /* If f is a dead frame, don't bother rebuilding its window tree.
6198 However, there is other stuff we should still try to do below. */
6199 if (FRAME_LIVE_P (f))
6201 register struct window *w;
6202 register struct saved_window *p;
6203 struct window *root_window;
6204 struct window **leaf_windows;
6205 int n_leaf_windows;
6206 int k, i, n;
6208 /* If the frame has been resized since this window configuration was
6209 made, we change the frame to the size specified in the
6210 configuration, restore the configuration, and then resize it
6211 back. We keep track of the prevailing height in these variables. */
6212 int previous_frame_lines = FRAME_LINES (f);
6213 int previous_frame_cols = FRAME_COLS (f);
6214 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6215 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6217 /* The mouse highlighting code could get screwed up
6218 if it runs during this. */
6219 BLOCK_INPUT;
6221 if (XFASTINT (data->frame_lines) != previous_frame_lines
6222 || XFASTINT (data->frame_cols) != previous_frame_cols)
6223 change_frame_size (f, XFASTINT (data->frame_lines),
6224 XFASTINT (data->frame_cols), 0, 0, 0);
6225 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6226 if (XFASTINT (data->frame_menu_bar_lines)
6227 != previous_frame_menu_bar_lines)
6228 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
6229 #ifdef HAVE_WINDOW_SYSTEM
6230 if (XFASTINT (data->frame_tool_bar_lines)
6231 != previous_frame_tool_bar_lines)
6232 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
6233 #endif
6234 #endif
6236 /* "Swap out" point from the selected window's buffer
6237 into the window itself. (Normally the pointm of the selected
6238 window holds garbage.) We do this now, before
6239 restoring the window contents, and prevent it from
6240 being done later on when we select a new window. */
6241 if (! NILP (XWINDOW (selected_window)->buffer))
6243 w = XWINDOW (selected_window);
6244 set_marker_both (w->pointm,
6245 w->buffer,
6246 BUF_PT (XBUFFER (w->buffer)),
6247 BUF_PT_BYTE (XBUFFER (w->buffer)));
6250 windows_or_buffers_changed++;
6251 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
6253 /* Problem: Freeing all matrices and later allocating them again
6254 is a serious redisplay flickering problem. What we would
6255 really like to do is to free only those matrices not reused
6256 below. */
6257 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6258 leaf_windows
6259 = (struct window **) alloca (count_windows (root_window)
6260 * sizeof (struct window *));
6261 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6263 /* Temporarily avoid any problems with windows that are smaller
6264 than they are supposed to be. */
6265 window_min_height = 1;
6266 window_min_width = 1;
6268 /* Kludge Alert!
6269 Mark all windows now on frame as "deleted".
6270 Restoring the new configuration "undeletes" any that are in it.
6272 Save their current buffers in their height fields, since we may
6273 need it later, if a buffer saved in the configuration is now
6274 dead. */
6275 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6277 for (k = 0; k < saved_windows->size; k++)
6279 p = SAVED_WINDOW_N (saved_windows, k);
6280 w = XWINDOW (p->window);
6281 w->next = Qnil;
6283 if (!NILP (p->parent))
6284 w->parent = SAVED_WINDOW_N (saved_windows,
6285 XFASTINT (p->parent))->window;
6286 else
6287 w->parent = Qnil;
6289 if (!NILP (p->prev))
6291 w->prev = SAVED_WINDOW_N (saved_windows,
6292 XFASTINT (p->prev))->window;
6293 XWINDOW (w->prev)->next = p->window;
6295 else
6297 w->prev = Qnil;
6298 if (!NILP (w->parent))
6300 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
6302 XWINDOW (w->parent)->vchild = p->window;
6303 XWINDOW (w->parent)->hchild = Qnil;
6305 else
6307 XWINDOW (w->parent)->hchild = p->window;
6308 XWINDOW (w->parent)->vchild = Qnil;
6313 /* If we squirreled away the buffer in the window's height,
6314 restore it now. */
6315 if (BUFFERP (w->total_lines))
6316 w->buffer = w->total_lines;
6317 w->left_col = p->left_col;
6318 w->top_line = p->top_line;
6319 w->total_cols = p->total_cols;
6320 w->total_lines = p->total_lines;
6321 w->hscroll = p->hscroll;
6322 w->min_hscroll = p->min_hscroll;
6323 w->display_table = p->display_table;
6324 w->orig_top_line = p->orig_top_line;
6325 w->orig_total_lines = p->orig_total_lines;
6326 w->left_margin_cols = p->left_margin_cols;
6327 w->right_margin_cols = p->right_margin_cols;
6328 w->left_fringe_width = p->left_fringe_width;
6329 w->right_fringe_width = p->right_fringe_width;
6330 w->fringes_outside_margins = p->fringes_outside_margins;
6331 w->scroll_bar_width = p->scroll_bar_width;
6332 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
6333 w->dedicated = p->dedicated;
6334 XSETFASTINT (w->last_modified, 0);
6335 XSETFASTINT (w->last_overlay_modified, 0);
6337 /* Reinstall the saved buffer and pointers into it. */
6338 if (NILP (p->buffer))
6339 w->buffer = p->buffer;
6340 else
6342 if (!NILP (XBUFFER (p->buffer)->name))
6343 /* If saved buffer is alive, install it. */
6345 w->buffer = p->buffer;
6346 w->start_at_line_beg = p->start_at_line_beg;
6347 set_marker_restricted (w->start, p->start, w->buffer);
6348 set_marker_restricted (w->pointm, p->pointm, w->buffer);
6349 Fset_marker (XBUFFER (w->buffer)->mark,
6350 p->mark, w->buffer);
6352 /* As documented in Fcurrent_window_configuration, don't
6353 restore the location of point in the buffer which was
6354 current when the window configuration was recorded. */
6355 if (!EQ (p->buffer, new_current_buffer)
6356 && XBUFFER (p->buffer) == current_buffer)
6357 Fgoto_char (w->pointm);
6359 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
6360 /* Else unless window has a live buffer, get one. */
6362 w->buffer = Fcdr (Fcar (Vbuffer_alist));
6363 /* This will set the markers to beginning of visible
6364 range. */
6365 set_marker_restricted (w->start, make_number (0), w->buffer);
6366 set_marker_restricted (w->pointm, make_number (0),w->buffer);
6367 w->start_at_line_beg = Qt;
6369 else
6370 /* Keeping window's old buffer; make sure the markers
6371 are real. */
6373 /* Set window markers at start of visible range. */
6374 if (XMARKER (w->start)->buffer == 0)
6375 set_marker_restricted (w->start, make_number (0),
6376 w->buffer);
6377 if (XMARKER (w->pointm)->buffer == 0)
6378 set_marker_restricted_both (w->pointm, w->buffer,
6379 BUF_PT (XBUFFER (w->buffer)),
6380 BUF_PT_BYTE (XBUFFER (w->buffer)));
6381 w->start_at_line_beg = Qt;
6386 FRAME_ROOT_WINDOW (f) = data->root_window;
6387 /* Prevent "swapping out point" in the old selected window
6388 using the buffer that has been restored into it.
6389 We already swapped out point that from that window's old buffer. */
6390 selected_window = Qnil;
6392 /* Arrange *not* to restore point in the buffer that was
6393 current when the window configuration was saved. */
6394 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
6395 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6396 make_number (old_point),
6397 XWINDOW (data->current_window)->buffer);
6399 Fselect_window (data->current_window, Qnil);
6400 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
6401 = selected_window;
6403 if (NILP (data->focus_frame)
6404 || (FRAMEP (data->focus_frame)
6405 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6406 Fredirect_frame_focus (frame, data->focus_frame);
6408 #if 0 /* I don't understand why this is needed, and it causes problems
6409 when the frame's old selected window has been deleted. */
6410 if (f != selected_frame && FRAME_WINDOW_P (f))
6411 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
6412 0, 0);
6413 #endif
6415 /* Set the screen height to the value it had before this function. */
6416 if (previous_frame_lines != FRAME_LINES (f)
6417 || previous_frame_cols != FRAME_COLS (f))
6418 change_frame_size (f, previous_frame_lines, previous_frame_cols,
6419 0, 0, 0);
6420 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6421 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
6422 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
6423 make_number (0));
6424 #ifdef HAVE_WINDOW_SYSTEM
6425 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
6426 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
6427 make_number (0));
6428 #endif
6429 #endif
6431 /* Now, free glyph matrices in windows that were not reused. */
6432 for (i = n = 0; i < n_leaf_windows; ++i)
6434 if (NILP (leaf_windows[i]->buffer))
6436 /* Assert it's not reused as a combination. */
6437 xassert (NILP (leaf_windows[i]->hchild)
6438 && NILP (leaf_windows[i]->vchild));
6439 free_window_matrices (leaf_windows[i]);
6441 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
6442 ++n;
6445 adjust_glyphs (f);
6447 UNBLOCK_INPUT;
6449 /* Fselect_window will have made f the selected frame, so we
6450 reselect the proper frame here. Fhandle_switch_frame will change the
6451 selected window too, but that doesn't make the call to
6452 Fselect_window above totally superfluous; it still sets f's
6453 selected window. */
6454 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6455 do_switch_frame (data->selected_frame, 0, 0);
6457 if (! NILP (Vwindow_configuration_change_hook)
6458 && ! NILP (Vrun_hooks))
6459 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
6462 if (!NILP (new_current_buffer))
6463 Fset_buffer (new_current_buffer);
6465 /* Restore the minimum heights recorded in the configuration. */
6466 window_min_height = XINT (data->min_height);
6467 window_min_width = XINT (data->min_width);
6469 Vminibuf_scroll_window = data->minibuf_scroll_window;
6470 minibuf_selected_window = data->minibuf_selected_window;
6472 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6475 /* Mark all windows now on frame as deleted
6476 by setting their buffers to nil. */
6478 void
6479 delete_all_subwindows (w)
6480 register struct window *w;
6482 if (!NILP (w->next))
6483 delete_all_subwindows (XWINDOW (w->next));
6484 if (!NILP (w->vchild))
6485 delete_all_subwindows (XWINDOW (w->vchild));
6486 if (!NILP (w->hchild))
6487 delete_all_subwindows (XWINDOW (w->hchild));
6489 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
6491 if (!NILP (w->buffer))
6492 unshow_buffer (w);
6494 /* We set all three of these fields to nil, to make sure that we can
6495 distinguish this dead window from any live window. Live leaf
6496 windows will have buffer set, and combination windows will have
6497 vchild or hchild set. */
6498 w->buffer = Qnil;
6499 w->vchild = Qnil;
6500 w->hchild = Qnil;
6502 Vwindow_list = Qnil;
6505 static int
6506 count_windows (window)
6507 register struct window *window;
6509 register int count = 1;
6510 if (!NILP (window->next))
6511 count += count_windows (XWINDOW (window->next));
6512 if (!NILP (window->vchild))
6513 count += count_windows (XWINDOW (window->vchild));
6514 if (!NILP (window->hchild))
6515 count += count_windows (XWINDOW (window->hchild));
6516 return count;
6520 /* Fill vector FLAT with leaf windows under W, starting at index I.
6521 Value is last index + 1. */
6523 static int
6524 get_leaf_windows (w, flat, i)
6525 struct window *w;
6526 struct window **flat;
6527 int i;
6529 while (w)
6531 if (!NILP (w->hchild))
6532 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
6533 else if (!NILP (w->vchild))
6534 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
6535 else
6536 flat[i++] = w;
6538 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6541 return i;
6545 /* Return a pointer to the glyph W's physical cursor is on. Value is
6546 null if W's current matrix is invalid, so that no meaningfull glyph
6547 can be returned. */
6549 struct glyph *
6550 get_phys_cursor_glyph (w)
6551 struct window *w;
6553 struct glyph_row *row;
6554 struct glyph *glyph;
6556 if (w->phys_cursor.vpos >= 0
6557 && w->phys_cursor.vpos < w->current_matrix->nrows
6558 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
6559 row->enabled_p)
6560 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
6561 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
6562 else
6563 glyph = NULL;
6565 return glyph;
6569 static int
6570 save_window_save (window, vector, i)
6571 Lisp_Object window;
6572 struct Lisp_Vector *vector;
6573 int i;
6575 register struct saved_window *p;
6576 register struct window *w;
6577 register Lisp_Object tem;
6579 for (;!NILP (window); window = w->next)
6581 p = SAVED_WINDOW_N (vector, i);
6582 w = XWINDOW (window);
6584 XSETFASTINT (w->temslot, i); i++;
6585 p->window = window;
6586 p->buffer = w->buffer;
6587 p->left_col = w->left_col;
6588 p->top_line = w->top_line;
6589 p->total_cols = w->total_cols;
6590 p->total_lines = w->total_lines;
6591 p->hscroll = w->hscroll;
6592 p->min_hscroll = w->min_hscroll;
6593 p->display_table = w->display_table;
6594 p->orig_top_line = w->orig_top_line;
6595 p->orig_total_lines = w->orig_total_lines;
6596 p->left_margin_cols = w->left_margin_cols;
6597 p->right_margin_cols = w->right_margin_cols;
6598 p->left_fringe_width = w->left_fringe_width;
6599 p->right_fringe_width = w->right_fringe_width;
6600 p->fringes_outside_margins = w->fringes_outside_margins;
6601 p->scroll_bar_width = w->scroll_bar_width;
6602 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6603 p->dedicated = w->dedicated;
6604 if (!NILP (w->buffer))
6606 /* Save w's value of point in the window configuration.
6607 If w is the selected window, then get the value of point
6608 from the buffer; pointm is garbage in the selected window. */
6609 if (EQ (window, selected_window))
6611 p->pointm = Fmake_marker ();
6612 set_marker_both (p->pointm, w->buffer,
6613 BUF_PT (XBUFFER (w->buffer)),
6614 BUF_PT_BYTE (XBUFFER (w->buffer)));
6616 else
6617 p->pointm = Fcopy_marker (w->pointm, Qnil);
6619 p->start = Fcopy_marker (w->start, Qnil);
6620 p->start_at_line_beg = w->start_at_line_beg;
6622 tem = XBUFFER (w->buffer)->mark;
6623 p->mark = Fcopy_marker (tem, Qnil);
6625 else
6627 p->pointm = Qnil;
6628 p->start = Qnil;
6629 p->mark = Qnil;
6630 p->start_at_line_beg = Qnil;
6633 if (NILP (w->parent))
6634 p->parent = Qnil;
6635 else
6636 p->parent = XWINDOW (w->parent)->temslot;
6638 if (NILP (w->prev))
6639 p->prev = Qnil;
6640 else
6641 p->prev = XWINDOW (w->prev)->temslot;
6643 if (!NILP (w->vchild))
6644 i = save_window_save (w->vchild, vector, i);
6645 if (!NILP (w->hchild))
6646 i = save_window_save (w->hchild, vector, i);
6649 return i;
6652 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6653 Scurrent_window_configuration, 0, 1, 0,
6654 doc: /* Return an object representing the current window configuration of FRAME.
6655 If FRAME is nil or omitted, use the selected frame.
6656 This describes the number of windows, their sizes and current buffers,
6657 and for each displayed buffer, where display starts, and the positions of
6658 point and mark. An exception is made for point in the current buffer:
6659 its value is -not- saved.
6660 This also records the currently selected frame, and FRAME's focus
6661 redirection (see `redirect-frame-focus'). */)
6662 (frame)
6663 Lisp_Object frame;
6665 register Lisp_Object tem;
6666 register int n_windows;
6667 register struct save_window_data *data;
6668 register struct Lisp_Vector *vec;
6669 register int i;
6670 FRAME_PTR f;
6672 if (NILP (frame))
6673 frame = selected_frame;
6674 CHECK_LIVE_FRAME (frame);
6675 f = XFRAME (frame);
6677 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6678 vec = allocate_other_vector (VECSIZE (struct save_window_data));
6679 data = (struct save_window_data *)vec;
6681 XSETFASTINT (data->frame_cols, FRAME_COLS (f));
6682 XSETFASTINT (data->frame_lines, FRAME_LINES (f));
6683 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
6684 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
6685 data->selected_frame = selected_frame;
6686 data->current_window = FRAME_SELECTED_WINDOW (f);
6687 XSETBUFFER (data->current_buffer, current_buffer);
6688 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6689 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6690 data->root_window = FRAME_ROOT_WINDOW (f);
6691 data->focus_frame = FRAME_FOCUS_FRAME (f);
6692 XSETINT (data->min_height, window_min_height);
6693 XSETINT (data->min_width, window_min_width);
6694 tem = Fmake_vector (make_number (n_windows), Qnil);
6695 data->saved_windows = tem;
6696 for (i = 0; i < n_windows; i++)
6697 XVECTOR (tem)->contents[i]
6698 = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
6699 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6700 XSETWINDOW_CONFIGURATION (tem, data);
6701 return (tem);
6704 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
6705 0, UNEVALLED, 0,
6706 doc: /* Execute BODY, preserving window sizes and contents.
6707 Return the value of the last form in BODY.
6708 Restore which buffer appears in which window, where display starts,
6709 and the value of point and mark for each window.
6710 Also restore the choice of selected window.
6711 Also restore which buffer is current.
6712 Does not restore the value of point in current buffer.
6713 usage: (save-window-excursion BODY...) */)
6714 (args)
6715 Lisp_Object args;
6717 register Lisp_Object val;
6718 register int count = SPECPDL_INDEX ();
6720 record_unwind_protect (Fset_window_configuration,
6721 Fcurrent_window_configuration (Qnil));
6722 val = Fprogn (args);
6723 return unbind_to (count, val);
6728 /***********************************************************************
6729 Window Split Tree
6730 ***********************************************************************/
6732 static Lisp_Object
6733 window_tree (w)
6734 struct window *w;
6736 Lisp_Object tail = Qnil;
6737 Lisp_Object result = Qnil;
6739 while (w)
6741 Lisp_Object wn;
6743 XSETWINDOW (wn, w);
6744 if (!NILP (w->hchild))
6745 wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
6746 window_tree (XWINDOW (w->hchild))));
6747 else if (!NILP (w->vchild))
6748 wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
6749 window_tree (XWINDOW (w->vchild))));
6751 if (NILP (result))
6753 result = tail = Fcons (wn, Qnil);
6755 else
6757 XSETCDR (tail, Fcons (wn, Qnil));
6758 tail = XCDR (tail);
6761 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6764 return result;
6769 DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
6770 0, 1, 0,
6771 doc: /* Return the window tree for frame FRAME.
6773 The return value is a list of the form (ROOT MINI), where ROOT
6774 represents the window tree of the frame's root window, and MINI
6775 is the frame's minibuffer window.
6777 If the root window is not split, ROOT is the root window itself.
6778 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6779 horizontal split, and t for a vertical split, EDGES gives the combined
6780 size and position of the subwindows in the split, and the rest of the
6781 elements are the subwindows in the split. Each of the subwindows may
6782 again be a window or a list representing a window split, and so on.
6783 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6785 If FRAME is nil or omitted, return information on the currently
6786 selected frame. */)
6787 (frame)
6788 Lisp_Object frame;
6790 FRAME_PTR f;
6792 if (NILP (frame))
6793 frame = selected_frame;
6795 CHECK_FRAME (frame);
6796 f = XFRAME (frame);
6798 if (!FRAME_LIVE_P (f))
6799 return Qnil;
6801 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
6805 /***********************************************************************
6806 Marginal Areas
6807 ***********************************************************************/
6809 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6810 2, 3, 0,
6811 doc: /* Set width of marginal areas of window WINDOW.
6812 If WINDOW is nil, set margins of the currently selected window.
6813 Second arg LEFT-WIDTH specifies the number of character cells to
6814 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6815 does the same for the right marginal area. A nil width parameter
6816 means no margin. */)
6817 (window, left_width, right_width)
6818 Lisp_Object window, left_width, right_width;
6820 struct window *w = decode_window (window);
6822 /* Translate negative or zero widths to nil.
6823 Margins that are too wide have to be checked elsewhere. */
6825 if (!NILP (left_width))
6827 CHECK_NUMBER (left_width);
6828 if (XINT (left_width) <= 0)
6829 left_width = Qnil;
6832 if (!NILP (right_width))
6834 CHECK_NUMBER (right_width);
6835 if (XINT (right_width) <= 0)
6836 right_width = Qnil;
6839 if (!EQ (w->left_margin_cols, left_width)
6840 || !EQ (w->right_margin_cols, right_width))
6842 w->left_margin_cols = left_width;
6843 w->right_margin_cols = right_width;
6845 adjust_window_margins (w);
6847 ++windows_or_buffers_changed;
6848 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6851 return Qnil;
6855 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6856 0, 1, 0,
6857 doc: /* Get width of marginal areas of window WINDOW.
6858 If WINDOW is omitted or nil, use the currently selected window.
6859 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6860 If a marginal area does not exist, its width will be returned
6861 as nil. */)
6862 (window)
6863 Lisp_Object window;
6865 struct window *w = decode_window (window);
6866 return Fcons (w->left_margin_cols, w->right_margin_cols);
6871 /***********************************************************************
6872 Fringes
6873 ***********************************************************************/
6875 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6876 2, 4, 0,
6877 doc: /* Set the fringe widths of window WINDOW.
6878 If WINDOW is nil, set the fringe widths of the currently selected
6879 window.
6880 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6881 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6882 fringe width. If a fringe width arg is nil, that means to use the
6883 frame's default fringe width. Default fringe widths can be set with
6884 the command `set-fringe-style'.
6885 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6886 outside of the display margins. By default, fringes are drawn between
6887 display marginal areas and the text area. */)
6888 (window, left_width, right_width, outside_margins)
6889 Lisp_Object window, left_width, right_width, outside_margins;
6891 struct window *w = decode_window (window);
6893 if (!NILP (left_width))
6894 CHECK_NATNUM (left_width);
6895 if (!NILP (right_width))
6896 CHECK_NATNUM (right_width);
6898 /* Do nothing on a tty. */
6899 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6900 && (!EQ (w->left_fringe_width, left_width)
6901 || !EQ (w->right_fringe_width, right_width)
6902 || !EQ (w->fringes_outside_margins, outside_margins)))
6904 w->left_fringe_width = left_width;
6905 w->right_fringe_width = right_width;
6906 w->fringes_outside_margins = outside_margins;
6908 adjust_window_margins (w);
6910 clear_glyph_matrix (w->current_matrix);
6911 w->window_end_valid = Qnil;
6913 ++windows_or_buffers_changed;
6914 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6917 return Qnil;
6921 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6922 0, 1, 0,
6923 doc: /* Get width of fringes of window WINDOW.
6924 If WINDOW is omitted or nil, use the currently selected window.
6925 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6926 (window)
6927 Lisp_Object window;
6929 struct window *w = decode_window (window);
6931 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6932 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6933 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6934 ? Qt : Qnil), Qnil)));
6939 /***********************************************************************
6940 Scroll bars
6941 ***********************************************************************/
6943 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6944 2, 4, 0,
6945 doc: /* Set width and type of scroll bars of window WINDOW.
6946 If window is nil, set scroll bars of the currently selected window.
6947 Second parameter WIDTH specifies the pixel width for the scroll bar;
6948 this is automatically adjusted to a multiple of the frame column width.
6949 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6950 bar: left, right, or nil.
6951 If WIDTH is nil, use the frame's scroll-bar width.
6952 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6953 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6954 (window, width, vertical_type, horizontal_type)
6955 Lisp_Object window, width, vertical_type, horizontal_type;
6957 struct window *w = decode_window (window);
6959 if (!NILP (width))
6961 CHECK_NATNUM (width);
6963 if (XINT (width) == 0)
6964 vertical_type = Qnil;
6967 if (!(NILP (vertical_type)
6968 || EQ (vertical_type, Qleft)
6969 || EQ (vertical_type, Qright)
6970 || EQ (vertical_type, Qt)))
6971 error ("Invalid type of vertical scroll bar");
6973 if (!EQ (w->scroll_bar_width, width)
6974 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6976 w->scroll_bar_width = width;
6977 w->vertical_scroll_bar_type = vertical_type;
6979 adjust_window_margins (w);
6981 clear_glyph_matrix (w->current_matrix);
6982 w->window_end_valid = Qnil;
6984 ++windows_or_buffers_changed;
6985 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6988 return Qnil;
6992 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6993 0, 1, 0,
6994 doc: /* Get width and type of scroll bars of window WINDOW.
6995 If WINDOW is omitted or nil, use the currently selected window.
6996 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6997 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6998 value. */)
6999 (window)
7000 Lisp_Object window;
7002 struct window *w = decode_window (window);
7003 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
7004 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
7005 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
7006 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
7007 Fcons (w->vertical_scroll_bar_type,
7008 Fcons (Qnil, Qnil))));
7013 /***********************************************************************
7014 Smooth scrolling
7015 ***********************************************************************/
7017 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
7018 doc: /* Return the amount by which WINDOW is scrolled vertically.
7019 Use the selected window if WINDOW is nil or omitted.
7020 Normally, value is a multiple of the canonical character height of WINDOW;
7021 optional second arg PIXELS-P means value is measured in pixels. */)
7022 (window, pixels_p)
7023 Lisp_Object window, pixels_p;
7025 Lisp_Object result;
7026 struct frame *f;
7027 struct window *w;
7029 if (NILP (window))
7030 window = selected_window;
7031 else
7032 CHECK_WINDOW (window);
7033 w = XWINDOW (window);
7034 f = XFRAME (w->frame);
7036 if (FRAME_WINDOW_P (f))
7037 result = (NILP (pixels_p)
7038 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
7039 : make_number (-w->vscroll));
7040 else
7041 result = make_number (0);
7042 return result;
7046 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
7047 2, 3, 0,
7048 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
7049 WINDOW nil means use the selected window. Normally, VSCROLL is a
7050 non-negative multiple of the canonical character height of WINDOW;
7051 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
7052 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
7053 corresponds to an integral number of pixels. The return value is the
7054 result of this rounding.
7055 If PIXELS-P is non-nil, the return value is VSCROLL. */)
7056 (window, vscroll, pixels_p)
7057 Lisp_Object window, vscroll, pixels_p;
7059 struct window *w;
7060 struct frame *f;
7062 if (NILP (window))
7063 window = selected_window;
7064 else
7065 CHECK_WINDOW (window);
7066 CHECK_NUMBER_OR_FLOAT (vscroll);
7068 w = XWINDOW (window);
7069 f = XFRAME (w->frame);
7071 if (FRAME_WINDOW_P (f))
7073 int old_dy = w->vscroll;
7075 w->vscroll = - (NILP (pixels_p)
7076 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
7077 : XFLOATINT (vscroll));
7078 w->vscroll = min (w->vscroll, 0);
7080 if (w->vscroll != old_dy)
7082 /* Adjust glyph matrix of the frame if the virtual display
7083 area becomes larger than before. */
7084 if (w->vscroll < 0 && w->vscroll < old_dy)
7085 adjust_glyphs (f);
7087 /* Prevent redisplay shortcuts. */
7088 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
7092 return Fwindow_vscroll (window, pixels_p);
7096 /* Call FN for all leaf windows on frame F. FN is called with the
7097 first argument being a pointer to the leaf window, and with
7098 additional argument USER_DATA. Stops when FN returns 0. */
7100 void
7101 foreach_window (f, fn, user_data)
7102 struct frame *f;
7103 int (* fn) P_ ((struct window *, void *));
7104 void *user_data;
7106 /* Fdelete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
7107 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
7108 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
7112 /* Helper function for foreach_window. Call FN for all leaf windows
7113 reachable from W. FN is called with the first argument being a
7114 pointer to the leaf window, and with additional argument USER_DATA.
7115 Stop when FN returns 0. Value is 0 if stopped by FN. */
7117 static int
7118 foreach_window_1 (w, fn, user_data)
7119 struct window *w;
7120 int (* fn) P_ ((struct window *, void *));
7121 void *user_data;
7123 int cont;
7125 for (cont = 1; w && cont;)
7127 if (!NILP (w->hchild))
7128 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
7129 else if (!NILP (w->vchild))
7130 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
7131 else
7132 cont = fn (w, user_data);
7134 w = NILP (w->next) ? 0 : XWINDOW (w->next);
7137 return cont;
7141 /* Freeze or unfreeze the window start of W unless it is a
7142 mini-window or the selected window. FREEZE_P non-null means freeze
7143 the window start. */
7145 static int
7146 freeze_window_start (w, freeze_p)
7147 struct window *w;
7148 void *freeze_p;
7150 if (MINI_WINDOW_P (w)
7151 || (WINDOWP (selected_window) /* Can be nil in corner cases. */
7152 && (w == XWINDOW (selected_window)
7153 || (MINI_WINDOW_P (XWINDOW (selected_window))
7154 && ! NILP (Vminibuf_scroll_window)
7155 && w == XWINDOW (Vminibuf_scroll_window)))))
7156 freeze_p = NULL;
7158 w->frozen_window_start_p = freeze_p != NULL;
7159 return 1;
7163 /* Freeze or unfreeze the window starts of all leaf windows on frame
7164 F, except the selected window and a mini-window. FREEZE_P non-zero
7165 means freeze the window start. */
7167 void
7168 freeze_window_starts (f, freeze_p)
7169 struct frame *f;
7170 int freeze_p;
7172 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
7176 /***********************************************************************
7177 Initialization
7178 ***********************************************************************/
7180 /* Return 1 if window configurations C1 and C2
7181 describe the same state of affairs. This is used by Fequal. */
7184 compare_window_configurations (c1, c2, ignore_positions)
7185 Lisp_Object c1, c2;
7186 int ignore_positions;
7188 register struct save_window_data *d1, *d2;
7189 struct Lisp_Vector *sw1, *sw2;
7190 int i;
7192 CHECK_WINDOW_CONFIGURATION (c1);
7193 CHECK_WINDOW_CONFIGURATION (c2);
7195 d1 = (struct save_window_data *) XVECTOR (c1);
7196 d2 = (struct save_window_data *) XVECTOR (c2);
7197 sw1 = XVECTOR (d1->saved_windows);
7198 sw2 = XVECTOR (d2->saved_windows);
7200 if (! EQ (d1->frame_cols, d2->frame_cols))
7201 return 0;
7202 if (! EQ (d1->frame_lines, d2->frame_lines))
7203 return 0;
7204 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
7205 return 0;
7206 if (! EQ (d1->selected_frame, d2->selected_frame))
7207 return 0;
7208 /* Don't compare the current_window field directly.
7209 Instead see w1_is_current and w2_is_current, below. */
7210 if (! EQ (d1->current_buffer, d2->current_buffer))
7211 return 0;
7212 if (! ignore_positions)
7214 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
7215 return 0;
7216 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
7217 return 0;
7219 /* Don't compare the root_window field.
7220 We don't require the two configurations
7221 to use the same window object,
7222 and the two root windows must be equivalent
7223 if everything else compares equal. */
7224 if (! EQ (d1->focus_frame, d2->focus_frame))
7225 return 0;
7226 if (! EQ (d1->min_width, d2->min_width))
7227 return 0;
7228 if (! EQ (d1->min_height, d2->min_height))
7229 return 0;
7231 /* Verify that the two confis have the same number of windows. */
7232 if (sw1->size != sw2->size)
7233 return 0;
7235 for (i = 0; i < sw1->size; i++)
7237 struct saved_window *p1, *p2;
7238 int w1_is_current, w2_is_current;
7240 p1 = SAVED_WINDOW_N (sw1, i);
7241 p2 = SAVED_WINDOW_N (sw2, i);
7243 /* Verify that the current windows in the two
7244 configurations correspond to each other. */
7245 w1_is_current = EQ (d1->current_window, p1->window);
7246 w2_is_current = EQ (d2->current_window, p2->window);
7248 if (w1_is_current != w2_is_current)
7249 return 0;
7251 /* Verify that the corresponding windows do match. */
7252 if (! EQ (p1->buffer, p2->buffer))
7253 return 0;
7254 if (! EQ (p1->left_col, p2->left_col))
7255 return 0;
7256 if (! EQ (p1->top_line, p2->top_line))
7257 return 0;
7258 if (! EQ (p1->total_cols, p2->total_cols))
7259 return 0;
7260 if (! EQ (p1->total_lines, p2->total_lines))
7261 return 0;
7262 if (! EQ (p1->display_table, p2->display_table))
7263 return 0;
7264 if (! EQ (p1->parent, p2->parent))
7265 return 0;
7266 if (! EQ (p1->prev, p2->prev))
7267 return 0;
7268 if (! ignore_positions)
7270 if (! EQ (p1->hscroll, p2->hscroll))
7271 return 0;
7272 if (!EQ (p1->min_hscroll, p2->min_hscroll))
7273 return 0;
7274 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
7275 return 0;
7276 if (NILP (Fequal (p1->start, p2->start)))
7277 return 0;
7278 if (NILP (Fequal (p1->pointm, p2->pointm)))
7279 return 0;
7280 if (NILP (Fequal (p1->mark, p2->mark)))
7281 return 0;
7283 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
7284 return 0;
7285 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
7286 return 0;
7287 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
7288 return 0;
7289 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
7290 return 0;
7291 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
7292 return 0;
7293 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
7294 return 0;
7295 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
7296 return 0;
7299 return 1;
7302 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7303 Scompare_window_configurations, 2, 2, 0,
7304 doc: /* Compare two window configurations as regards the structure of windows.
7305 This function ignores details such as the values of point and mark
7306 and scrolling positions. */)
7307 (x, y)
7308 Lisp_Object x, y;
7310 if (compare_window_configurations (x, y, 1))
7311 return Qt;
7312 return Qnil;
7315 void
7316 init_window_once ()
7318 struct frame *f = make_initial_frame ();
7319 XSETFRAME (selected_frame, f);
7320 Vterminal_frame = selected_frame;
7321 minibuf_window = f->minibuffer_window;
7322 selected_window = f->selected_window;
7323 last_nonminibuf_frame = f;
7325 window_initialized = 1;
7328 void
7329 init_window ()
7331 Vwindow_list = Qnil;
7334 void
7335 syms_of_window ()
7337 Qscroll_up = intern ("scroll-up");
7338 staticpro (&Qscroll_up);
7340 Qscroll_down = intern ("scroll-down");
7341 staticpro (&Qscroll_down);
7343 Qwindow_size_fixed = intern ("window-size-fixed");
7344 staticpro (&Qwindow_size_fixed);
7345 Fset (Qwindow_size_fixed, Qnil);
7347 staticpro (&Qwindow_configuration_change_hook);
7348 Qwindow_configuration_change_hook
7349 = intern ("window-configuration-change-hook");
7351 Qwindowp = intern ("windowp");
7352 staticpro (&Qwindowp);
7354 Qwindow_configuration_p = intern ("window-configuration-p");
7355 staticpro (&Qwindow_configuration_p);
7357 Qwindow_live_p = intern ("window-live-p");
7358 staticpro (&Qwindow_live_p);
7360 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
7361 staticpro (&Qtemp_buffer_show_hook);
7363 staticpro (&Vwindow_list);
7365 minibuf_selected_window = Qnil;
7366 staticpro (&minibuf_selected_window);
7368 window_scroll_pixel_based_preserve_y = -1;
7370 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
7371 doc: /* Non-nil means call as function to display a help buffer.
7372 The function is called with one argument, the buffer to be displayed.
7373 Used by `with-output-to-temp-buffer'.
7374 If this function is used, then it must do the entire job of showing
7375 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7376 Vtemp_buffer_show_function = Qnil;
7378 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
7379 doc: /* If non-nil, function to call to handle `display-buffer'.
7380 It will receive two args, the buffer and a flag which if non-nil means
7381 that the currently selected window is not acceptable.
7382 It should choose or create a window, display the specified buffer in it,
7383 and return the window.
7384 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
7385 work using this function. */);
7386 Vdisplay_buffer_function = Qnil;
7388 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
7389 doc: /* *If non-nil, `display-buffer' should even the window heights.
7390 If nil, `display-buffer' will leave the window configuration alone. */);
7391 Veven_window_heights = Qt;
7393 DEFVAR_LISP ("prefer-window-split-horizontally", &Vprefer_window_split_horizontally,
7394 doc: /* *Non-nil means that windows are split horizontally, i.e.
7395 side-by-side, instead
7396 of vertically by `display-buffer'.
7397 An integer value means that windows may only be split horizontally if the newly
7398 created window is at least as wide as that value. */);
7399 Vprefer_window_split_horizontally = Qnil;
7401 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
7402 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7403 Vminibuf_scroll_window = Qnil;
7405 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
7406 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7407 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7408 is displayed in the `mode-line' face. */);
7409 mode_line_in_non_selected_windows = 1;
7411 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
7412 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7413 Vother_window_scroll_buffer = Qnil;
7415 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
7416 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
7417 pop_up_frames = 0;
7419 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
7420 doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7421 auto_window_vscroll_p = 1;
7423 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
7424 doc: /* *Non-nil means `display-buffer' should reuse frames.
7425 If the buffer in question is already displayed in a frame, raise that frame. */);
7426 display_buffer_reuse_frames = 0;
7428 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
7429 doc: /* Function to call to handle automatic new frame creation.
7430 It is called with no arguments and should return a newly created frame.
7432 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
7433 where `pop-up-frame-alist' would hold the default frame parameters. */);
7434 Vpop_up_frame_function = Qnil;
7436 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
7437 doc: /* *List of buffer names that should have their own special frames.
7438 Displaying a buffer with `display-buffer' or `pop-to-buffer',
7439 if its name is in this list, makes a special frame for it
7440 using `special-display-function'. See also `special-display-regexps'.
7442 An element of the list can be a list instead of just a string.
7443 There are two ways to use a list as an element:
7444 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
7445 In the first case, the FRAME-PARAMETERS are pairs of the form
7446 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7447 In the second case, FUNCTION is called with BUFFER as the first argument,
7448 followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
7449 All this is done by the function found in `special-display-function'.
7451 If the specified frame parameters include (same-buffer . t), the
7452 buffer is displayed in the currently selected window. Otherwise, if
7453 they include (same-frame . t), the buffer is displayed in a new window
7454 in the currently selected frame.
7456 If this variable appears \"not to work\", because you add a name to it
7457 but that buffer still appears in the selected window, look at the
7458 values of `same-window-buffer-names' and `same-window-regexps'.
7459 Those variables take precedence over this one. */);
7460 Vspecial_display_buffer_names = Qnil;
7462 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
7463 doc: /* *List of regexps saying which buffers should have their own special frames.
7464 When displaying a buffer with `display-buffer' or `pop-to-buffer',
7465 if any regexp in this list matches the buffer name, it makes a
7466 special frame for the buffer by calling `special-display-function'.
7468 An element of the list can be a list instead of just a string.
7469 There are two ways to use a list as an element:
7470 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
7471 In the first case, the FRAME-PARAMETERS are pairs of the form
7472 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7473 In the second case, FUNCTION is called with BUFFER as the first argument,
7474 followed by the OTHER-ARGS--it can display the buffer in any way it likes.
7475 All this is done by the function found in `special-display-function'.
7477 If the specified frame parameters include (same-buffer . t), the
7478 buffer is displayed in the currently selected window. Otherwise, if
7479 they include (same-frame . t), the buffer is displayed in a new window
7480 in the currently selected frame.
7482 If this variable appears \"not to work\", because you add a regexp to it
7483 but the matching buffers still appear in the selected window, look at the
7484 values of `same-window-buffer-names' and `same-window-regexps'.
7485 Those variables take precedence over this one. */);
7486 Vspecial_display_regexps = Qnil;
7488 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
7489 doc: /* Function to call to make a new frame for a special buffer.
7490 It is called with two arguments, the buffer and optional buffer specific
7491 data, and should return a window displaying that buffer.
7492 The default value normally makes a separate frame for the buffer,
7493 using `special-display-frame-alist' to specify the frame parameters.
7494 But if the buffer specific data includes (same-buffer . t) then the
7495 buffer is displayed in the current selected window.
7496 Otherwise if it includes (same-frame . t) then the buffer is displayed in
7497 a new window in the currently selected frame.
7499 A buffer is special if it is listed in `special-display-buffer-names'
7500 or matches a regexp in `special-display-regexps'. */);
7501 Vspecial_display_function = Qnil;
7503 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
7504 doc: /* *List of buffer names that should appear in the selected window.
7505 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
7506 switches to it in the selected window, rather than making it appear
7507 in some other window.
7509 An element of the list can be a cons cell instead of just a string.
7510 Then the car must be a string, which specifies the buffer name.
7511 This is for compatibility with `special-display-buffer-names';
7512 the cdr of the cons cell is ignored.
7514 See also `same-window-regexps'. */);
7515 Vsame_window_buffer_names = Qnil;
7517 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
7518 doc: /* *List of regexps saying which buffers should appear in the selected window.
7519 If a buffer name matches one of these regexps, then displaying it
7520 using `display-buffer' or `pop-to-buffer' switches to it
7521 in the selected window, rather than making it appear in some other window.
7523 An element of the list can be a cons cell instead of just a string.
7524 Then the car must be a string, which specifies the buffer name.
7525 This is for compatibility with `special-display-buffer-names';
7526 the cdr of the cons cell is ignored.
7528 See also `same-window-buffer-names'. */);
7529 Vsame_window_regexps = Qnil;
7531 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
7532 doc: /* *Non-nil means display-buffer should make new windows. */);
7533 pop_up_windows = 1;
7535 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
7536 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
7537 next_screen_context_lines = 2;
7539 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
7540 doc: /* *A window must be at least this tall to be eligible for splitting
7541 by `display-buffer'. The value is in line units.
7542 If there is only one window, it is split regardless of this value. */);
7543 split_height_threshold = 500;
7545 DEFVAR_LISP ("split-window-preferred-function",
7546 &Vsplit_window_preferred_function,
7547 doc: /* Function to use to split a window.
7548 This is used by `display-buffer' to allow the user to choose whether
7549 to split windows horizontally or vertically or some mix of the two.
7550 It is called with a window as single argument and should split it in two
7551 and return the new window. */);
7552 Vsplit_window_preferred_function = intern ("split-window");
7554 DEFVAR_INT ("window-min-height", &window_min_height,
7555 doc: /* *Delete any window less than this tall (including its mode line).
7556 The value is in line units. */);
7557 window_min_height = 4;
7559 DEFVAR_INT ("window-min-width", &window_min_width,
7560 doc: /* *Delete any window less than this wide (measured in characters). */);
7561 window_min_width = 10;
7563 DEFVAR_LISP ("scroll-preserve-screen-position",
7564 &Vscroll_preserve_screen_position,
7565 doc: /* *Controls if scroll commands move point to keep its screen line unchanged.
7566 A value of nil means point does not keep its screen position except
7567 at the scroll margin or window boundary respectively.
7568 A value of t means point keeps its screen position if the scroll
7569 command moved it vertically out of the window, e.g. when scrolling
7570 by full screens.
7571 Any other value means point always keeps its screen position. */);
7572 Vscroll_preserve_screen_position = Qnil;
7574 DEFVAR_LISP ("window-configuration-change-hook",
7575 &Vwindow_configuration_change_hook,
7576 doc: /* Functions to call when window configuration changes.
7577 The selected frame is the one whose configuration has changed. */);
7578 Vwindow_configuration_change_hook = Qnil;
7580 defsubr (&Sselected_window);
7581 defsubr (&Sminibuffer_window);
7582 defsubr (&Swindow_minibuffer_p);
7583 defsubr (&Swindowp);
7584 defsubr (&Swindow_live_p);
7585 defsubr (&Spos_visible_in_window_p);
7586 defsubr (&Swindow_line_height);
7587 defsubr (&Swindow_buffer);
7588 defsubr (&Swindow_height);
7589 defsubr (&Swindow_width);
7590 defsubr (&Swindow_full_width_p);
7591 defsubr (&Swindow_hscroll);
7592 defsubr (&Sset_window_hscroll);
7593 defsubr (&Swindow_redisplay_end_trigger);
7594 defsubr (&Sset_window_redisplay_end_trigger);
7595 defsubr (&Swindow_edges);
7596 defsubr (&Swindow_pixel_edges);
7597 defsubr (&Swindow_inside_edges);
7598 defsubr (&Swindow_inside_pixel_edges);
7599 defsubr (&Scoordinates_in_window_p);
7600 defsubr (&Swindow_at);
7601 defsubr (&Swindow_point);
7602 defsubr (&Swindow_start);
7603 defsubr (&Swindow_end);
7604 defsubr (&Sset_window_point);
7605 defsubr (&Sset_window_start);
7606 defsubr (&Swindow_dedicated_p);
7607 defsubr (&Sset_window_dedicated_p);
7608 defsubr (&Swindow_display_table);
7609 defsubr (&Sset_window_display_table);
7610 defsubr (&Snext_window);
7611 defsubr (&Sprevious_window);
7612 defsubr (&Sother_window);
7613 defsubr (&Sget_lru_window);
7614 defsubr (&Sget_largest_window);
7615 defsubr (&Sget_buffer_window);
7616 defsubr (&Sdelete_other_windows);
7617 defsubr (&Sdelete_windows_on);
7618 defsubr (&Sreplace_buffer_in_windows);
7619 defsubr (&Sdelete_window);
7620 defsubr (&Sset_window_buffer);
7621 defsubr (&Sselect_window);
7622 defsubr (&Sspecial_display_p);
7623 defsubr (&Ssame_window_p);
7624 defsubr (&Sdisplay_buffer);
7625 defsubr (&Sforce_window_update);
7626 defsubr (&Ssplit_window);
7627 defsubr (&Senlarge_window);
7628 defsubr (&Sshrink_window);
7629 defsubr (&Sadjust_window_trailing_edge);
7630 defsubr (&Sscroll_up);
7631 defsubr (&Sscroll_down);
7632 defsubr (&Sscroll_left);
7633 defsubr (&Sscroll_right);
7634 defsubr (&Sother_window_for_scrolling);
7635 defsubr (&Sscroll_other_window);
7636 defsubr (&Sminibuffer_selected_window);
7637 defsubr (&Srecenter);
7638 defsubr (&Swindow_text_height);
7639 defsubr (&Smove_to_window_line);
7640 defsubr (&Swindow_configuration_p);
7641 defsubr (&Swindow_configuration_frame);
7642 defsubr (&Sset_window_configuration);
7643 defsubr (&Scurrent_window_configuration);
7644 defsubr (&Ssave_window_excursion);
7645 defsubr (&Swindow_tree);
7646 defsubr (&Sset_window_margins);
7647 defsubr (&Swindow_margins);
7648 defsubr (&Sset_window_fringes);
7649 defsubr (&Swindow_fringes);
7650 defsubr (&Sset_window_scroll_bars);
7651 defsubr (&Swindow_scroll_bars);
7652 defsubr (&Swindow_vscroll);
7653 defsubr (&Sset_window_vscroll);
7654 defsubr (&Scompare_window_configurations);
7655 defsubr (&Swindow_list);
7658 void
7659 keys_of_window ()
7661 initial_define_key (control_x_map, '1', "delete-other-windows");
7662 initial_define_key (control_x_map, '2', "split-window");
7663 initial_define_key (control_x_map, '0', "delete-window");
7664 initial_define_key (control_x_map, 'o', "other-window");
7665 initial_define_key (control_x_map, '^', "enlarge-window");
7666 initial_define_key (control_x_map, '<', "scroll-left");
7667 initial_define_key (control_x_map, '>', "scroll-right");
7669 initial_define_key (global_map, Ctl ('V'), "scroll-up");
7670 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7671 initial_define_key (meta_map, 'v', "scroll-down");
7673 initial_define_key (global_map, Ctl('L'), "recenter");
7674 initial_define_key (meta_map, 'r', "move-to-window-line");
7677 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7678 (do not change this comment) */