Correct typo.
[emacs.git] / src / window.c
blob6fe78166ba12e56a190733ae214a031c09470214
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 "lisp.h"
25 #include "buffer.h"
26 #include "keyboard.h"
27 #include "keymap.h"
28 #include "frame.h"
29 #include "window.h"
30 #include "commands.h"
31 #include "indent.h"
32 #include "termchar.h"
33 #include "disptab.h"
34 #include "dispextern.h"
35 #include "blockinput.h"
36 #include "intervals.h"
38 #ifdef HAVE_X_WINDOWS
39 #include "xterm.h"
40 #endif /* HAVE_X_WINDOWS */
41 #ifdef WINDOWSNT
42 #include "w32term.h"
43 #endif
44 #ifdef MSDOS
45 #include "msdos.h"
46 #endif
47 #ifdef MAC_OS
48 #include "macterm.h"
49 #endif
52 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
53 Lisp_Object Qscroll_up, Qscroll_down;
54 Lisp_Object Qwindow_size_fixed;
55 extern Lisp_Object Qleft_margin, Qright_margin;
57 static int displayed_window_lines P_ ((struct window *));
58 static struct window *decode_window P_ ((Lisp_Object));
59 static int count_windows P_ ((struct window *));
60 static int get_leaf_windows P_ ((struct window *, struct window **, int));
61 static void window_scroll P_ ((Lisp_Object, int, int, int));
62 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
63 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
64 static int window_min_size_1 P_ ((struct window *, int));
65 static int window_min_size_2 P_ ((struct window *, int));
66 static int window_min_size P_ ((struct window *, int, int, int *));
67 static void size_window P_ ((Lisp_Object, int, int, int, int, int));
68 static int freeze_window_start P_ ((struct window *, void *));
69 static int window_fixed_size_p P_ ((struct window *, int, int));
70 static void enlarge_window P_ ((Lisp_Object, int, int));
71 static Lisp_Object window_list P_ ((void));
72 static int add_window_to_list P_ ((struct window *, void *));
73 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
74 Lisp_Object));
75 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
76 Lisp_Object, int));
77 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
78 Lisp_Object *));
79 static int foreach_window_1 P_ ((struct window *,
80 int (* fn) (struct window *, void *),
81 void *));
82 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
84 /* This is the window in which the terminal's cursor should
85 be left when nothing is being done with it. This must
86 always be a leaf window, and its buffer is selected by
87 the top level editing loop at the end of each command.
89 This value is always the same as
90 FRAME_SELECTED_WINDOW (selected_frame). */
92 Lisp_Object selected_window;
94 /* A list of all windows for use by next_window and Fwindow_list.
95 Functions creating or deleting windows should invalidate this cache
96 by setting it to nil. */
98 Lisp_Object Vwindow_list;
100 /* The mini-buffer window of the selected frame.
101 Note that you cannot test for mini-bufferness of an arbitrary window
102 by comparing against this; but you can test for mini-bufferness of
103 the selected window. */
105 Lisp_Object minibuf_window;
107 /* Non-nil means it is the window whose mode line should be
108 shown as the selected window when the minibuffer is selected. */
110 Lisp_Object minibuf_selected_window;
112 /* Non-nil means it is the window for C-M-v to scroll
113 when the mini-buffer is selected. */
115 Lisp_Object Vminibuf_scroll_window;
117 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
119 Lisp_Object Vother_window_scroll_buffer;
121 /* Non-nil means it's function to call to display temp buffers. */
123 Lisp_Object Vtemp_buffer_show_function;
125 /* Non-zero means line and page scrolling on tall lines (with images)
126 does partial scrolling by modifying window-vscroll. */
128 int auto_window_vscroll_p;
130 /* Non-zero means to use mode-line-inactive face in all windows but the
131 selected-window and the minibuffer-scroll-window when the
132 minibuffer is active. */
133 int mode_line_in_non_selected_windows;
135 /* If a window gets smaller than either of these, it is removed. */
137 EMACS_INT window_min_height;
138 EMACS_INT window_min_width;
140 /* Nonzero implies Fdisplay_buffer should create windows. */
142 int pop_up_windows;
144 /* Nonzero implies make new frames for Fdisplay_buffer. */
146 int pop_up_frames;
148 /* Nonzero means reuse existing frames for displaying buffers. */
150 int display_buffer_reuse_frames;
152 /* Non-nil means use this function instead of default */
154 Lisp_Object Vpop_up_frame_function;
156 /* Function to call to handle Fdisplay_buffer. */
158 Lisp_Object Vdisplay_buffer_function;
160 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
162 Lisp_Object Veven_window_heights;
164 /* List of buffer *names* for buffers that should have their own frames. */
166 Lisp_Object Vspecial_display_buffer_names;
168 /* List of regexps for buffer names that should have their own frames. */
170 Lisp_Object Vspecial_display_regexps;
172 /* Function to pop up a special frame. */
174 Lisp_Object Vspecial_display_function;
176 /* List of buffer *names* for buffers to appear in selected window. */
178 Lisp_Object Vsame_window_buffer_names;
180 /* List of regexps for buffer names to appear in selected window. */
182 Lisp_Object Vsame_window_regexps;
184 /* Hook run at end of temp_output_buffer_show. */
186 Lisp_Object Qtemp_buffer_show_hook;
188 /* Fdisplay_buffer always splits the largest window
189 if that window is more than this high. */
191 EMACS_INT split_height_threshold;
193 /* Number of lines of continuity in scrolling by screenfuls. */
195 EMACS_INT next_screen_context_lines;
197 /* Incremented for each window created. */
199 static int sequence_number;
201 /* Nonzero after init_window_once has finished. */
203 static int window_initialized;
205 /* Hook to run when window config changes. */
207 Lisp_Object Qwindow_configuration_change_hook;
208 Lisp_Object Vwindow_configuration_change_hook;
210 /* Non-nil means scroll commands try to put point
211 at the same screen height as previously. */
213 Lisp_Object Vscroll_preserve_screen_position;
215 /* Incremented by 1 whenever a window is deleted. */
217 int window_deletion_count;
219 /* Used by the function window_scroll_pixel_based */
221 static int window_scroll_pixel_based_preserve_y;
223 #if 0 /* This isn't used anywhere. */
224 /* Nonzero means we can split a frame even if it is "unsplittable". */
225 static int inhibit_frame_unsplittable;
226 #endif /* 0 */
228 extern EMACS_INT scroll_margin;
230 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
232 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
233 doc: /* Returns t if OBJECT is a window. */)
234 (object)
235 Lisp_Object object;
237 return WINDOWP (object) ? Qt : Qnil;
240 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
241 doc: /* Returns t if OBJECT is a window which is currently visible. */)
242 (object)
243 Lisp_Object object;
245 return WINDOW_LIVE_P (object) ? Qt : Qnil;
248 Lisp_Object
249 make_window ()
251 Lisp_Object val;
252 register struct window *p;
254 p = allocate_window ();
255 ++sequence_number;
256 XSETFASTINT (p->sequence_number, sequence_number);
257 XSETFASTINT (p->left_col, 0);
258 XSETFASTINT (p->top_line, 0);
259 XSETFASTINT (p->total_lines, 0);
260 XSETFASTINT (p->total_cols, 0);
261 XSETFASTINT (p->hscroll, 0);
262 XSETFASTINT (p->min_hscroll, 0);
263 p->orig_top_line = p->orig_total_lines = Qnil;
264 p->start = Fmake_marker ();
265 p->pointm = Fmake_marker ();
266 XSETFASTINT (p->use_time, 0);
267 p->frame = Qnil;
268 p->display_table = Qnil;
269 p->dedicated = Qnil;
270 p->pseudo_window_p = 0;
271 bzero (&p->cursor, sizeof (p->cursor));
272 bzero (&p->last_cursor, sizeof (p->last_cursor));
273 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
274 p->desired_matrix = p->current_matrix = 0;
275 p->nrows_scale_factor = p->ncols_scale_factor = 1;
276 p->phys_cursor_type = -1;
277 p->phys_cursor_width = -1;
278 p->must_be_updated_p = 0;
279 XSETFASTINT (p->window_end_vpos, 0);
280 XSETFASTINT (p->window_end_pos, 0);
281 p->window_end_valid = Qnil;
282 p->vscroll = 0;
283 XSETWINDOW (val, p);
284 XSETFASTINT (p->last_point, 0);
285 p->frozen_window_start_p = 0;
286 p->last_cursor_off_p = p->cursor_off_p = 0;
287 p->left_margin_cols = Qnil;
288 p->right_margin_cols = Qnil;
289 p->left_fringe_width = Qnil;
290 p->right_fringe_width = Qnil;
291 p->fringes_outside_margins = Qnil;
292 p->scroll_bar_width = Qnil;
293 p->vertical_scroll_bar_type = Qt;
295 Vwindow_list = Qnil;
296 return val;
299 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
300 doc: /* Return the window that the cursor now appears in and commands apply to. */)
303 return selected_window;
306 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
307 doc: /* Return the window used now for minibuffers.
308 If the optional argument FRAME is specified, return the minibuffer window
309 used by that frame. */)
310 (frame)
311 Lisp_Object frame;
313 if (NILP (frame))
314 frame = selected_frame;
315 CHECK_LIVE_FRAME (frame);
316 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
319 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
320 doc: /* Returns non-nil if WINDOW is a minibuffer window.
321 WINDOW defaults to the selected window. */)
322 (window)
323 Lisp_Object window;
325 struct window *w = decode_window (window);
326 return MINI_WINDOW_P (w) ? Qt : Qnil;
330 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
331 Spos_visible_in_window_p, 0, 3, 0,
332 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
333 Return nil if that position is scrolled vertically out of view.
334 If a character is only partially visible, nil is returned, unless the
335 optional argument PARTIALLY is non-nil.
336 If POS is only out of view because of horizontal scrolling, return non-nil.
337 If POS is t, it specifies the position of the last visible glyph in WINDOW.
338 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
340 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
341 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
342 where X and Y are the pixel coordinates relative to the top left corner
343 of the window. The remaining elements are omitted if the character after
344 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
345 off-window at the top and bottom of the row, ROWH is the height of the
346 display row, and VPOS is the row number (0-based) containing POS. */)
347 (pos, window, partially)
348 Lisp_Object pos, window, partially;
350 register struct window *w;
351 register int posint;
352 register struct buffer *buf;
353 struct text_pos top;
354 Lisp_Object in_window = Qnil;
355 int rtop, rbot, rowh, vpos, fully_p = 1;
356 int x, y;
358 w = decode_window (window);
359 buf = XBUFFER (w->buffer);
360 SET_TEXT_POS_FROM_MARKER (top, w->start);
362 if (EQ (pos, Qt))
363 posint = -1;
364 else if (!NILP (pos))
366 CHECK_NUMBER_COERCE_MARKER (pos);
367 posint = XINT (pos);
369 else if (w == XWINDOW (selected_window))
370 posint = PT;
371 else
372 posint = XMARKER (w->pointm)->charpos;
374 /* If position is above window start or outside buffer boundaries,
375 or if window start is out of range, position is not visible. */
376 if ((EQ (pos, Qt)
377 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
378 && CHARPOS (top) >= BUF_BEGV (buf)
379 && CHARPOS (top) <= BUF_ZV (buf)
380 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
381 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
382 in_window = Qt;
384 if (!NILP (in_window) && !NILP (partially))
386 Lisp_Object part = Qnil;
387 if (!fully_p)
388 part = list4 (make_number (rtop), make_number (rbot),
389 make_number (rowh), make_number (vpos));
390 in_window = Fcons (make_number (x),
391 Fcons (make_number (y), part));
394 return in_window;
397 DEFUN ("window-line-height", Fwindow_line_height,
398 Swindow_line_height, 0, 2, 0,
399 doc: /* Return height in pixels of text line LINE in window WINDOW.
400 If WINDOW is nil or omitted, use selected window.
402 Return height of current line if LINE is omitted or nil. Return height of
403 header or mode line if LINE is `header-line' and `mode-line'.
404 Otherwise, LINE is a text line number starting from 0. A negative number
405 counts from the end of the window.
407 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
408 in pixels of the visible part of the line, VPOS and YPOS are the
409 vertical position in lines and pixels of the line, relative to the top
410 of the first text line, and OFFBOT is the number of off-window pixels at
411 the bottom of the text line. If there are off-window pixels at the top
412 of the (first) text line, YPOS is negative.
414 Return nil if window display is not up-to-date. In that case, use
415 `pos-visible-in-window-p' to obtain the information. */)
416 (line, window)
417 Lisp_Object line, window;
419 register struct window *w;
420 register struct buffer *b;
421 struct glyph_row *row, *end_row;
422 int max_y, crop, i, n;
424 w = decode_window (window);
426 if (noninteractive
427 || w->pseudo_window_p)
428 return Qnil;
430 CHECK_BUFFER (w->buffer);
431 b = XBUFFER (w->buffer);
433 /* Fail if current matrix is not up-to-date. */
434 if (NILP (w->window_end_valid)
435 || current_buffer->clip_changed
436 || current_buffer->prevent_redisplay_optimizations_p
437 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
438 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
439 return Qnil;
441 if (NILP (line))
443 i = w->cursor.vpos;
444 if (i < 0 || i >= w->current_matrix->nrows
445 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
446 return Qnil;
447 max_y = window_text_bottom_y (w);
448 goto found_row;
451 if (EQ (line, Qheader_line))
453 if (!WINDOW_WANTS_HEADER_LINE_P (w))
454 return Qnil;
455 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
456 if (!row->enabled_p)
457 return Qnil;
458 return list4 (make_number (row->height),
459 make_number (0), make_number (0),
460 make_number (0));
463 if (EQ (line, Qmode_line))
465 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
466 if (!row->enabled_p)
467 return Qnil;
468 return list4 (make_number (row->height),
469 make_number (0), /* not accurate */
470 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
471 + window_text_bottom_y (w)),
472 make_number (0));
475 CHECK_NUMBER (line);
476 n = XINT (line);
478 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
479 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
480 max_y = window_text_bottom_y (w);
481 i = 0;
483 while ((n < 0 || i < n)
484 && row <= end_row && row->enabled_p
485 && row->y + row->height < max_y)
486 row++, i++;
488 if (row > end_row || !row->enabled_p)
489 return Qnil;
491 if (++n < 0)
493 if (-n > i)
494 return Qnil;
495 row += n;
496 i += n;
499 found_row:
500 crop = max (0, (row->y + row->height) - max_y);
501 return list4 (make_number (row->height + min (0, row->y) - crop),
502 make_number (i),
503 make_number (row->y),
504 make_number (crop));
509 static struct window *
510 decode_window (window)
511 register Lisp_Object window;
513 if (NILP (window))
514 return XWINDOW (selected_window);
516 CHECK_LIVE_WINDOW (window);
517 return XWINDOW (window);
520 static struct window *
521 decode_any_window (window)
522 register Lisp_Object window;
524 if (NILP (window))
525 return XWINDOW (selected_window);
527 CHECK_WINDOW (window);
528 return XWINDOW (window);
531 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
532 doc: /* Return the buffer that WINDOW is displaying.
533 WINDOW defaults to the selected window. */)
534 (window)
535 Lisp_Object window;
537 return decode_window (window)->buffer;
540 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
541 doc: /* Return the number of lines in WINDOW (including its mode line).
542 WINDOW defaults to the selected window. */)
543 (window)
544 Lisp_Object window;
546 return decode_any_window (window)->total_lines;
549 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
550 doc: /* Return the number of display columns in WINDOW.
551 This is the width that is usable columns available for text in WINDOW.
552 If you want to find out how many columns WINDOW takes up,
553 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
554 (window)
555 Lisp_Object window;
557 return make_number (window_box_text_cols (decode_any_window (window)));
560 DEFUN ("window-full-width-p", Fwindow_full_width_p, Swindow_full_width_p, 0, 1, 0,
561 doc: /* Return t if WINDOW is as wide as its frame.
562 WINDOW defaults to the selected window. */)
563 (window)
564 Lisp_Object window;
566 return WINDOW_FULL_WIDTH_P (decode_any_window (window)) ? Qt : Qnil;
569 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
570 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
571 WINDOW defaults to the selected window. */)
572 (window)
573 Lisp_Object window;
575 return decode_window (window)->hscroll;
578 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
579 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
580 Return NCOL. NCOL should be zero or positive.
582 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
583 window so that the location of point moves off-window. */)
584 (window, ncol)
585 Lisp_Object window, ncol;
587 struct window *w = decode_window (window);
588 int hscroll;
590 CHECK_NUMBER (ncol);
591 hscroll = max (0, XINT (ncol));
593 /* Prevent redisplay shortcuts when changing the hscroll. */
594 if (XINT (w->hscroll) != hscroll)
595 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
597 w->hscroll = make_number (hscroll);
598 return ncol;
601 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
602 Swindow_redisplay_end_trigger, 0, 1, 0,
603 doc: /* Return WINDOW's redisplay end trigger value.
604 WINDOW defaults to the selected window.
605 See `set-window-redisplay-end-trigger' for more information. */)
606 (window)
607 Lisp_Object window;
609 return decode_window (window)->redisplay_end_trigger;
612 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
613 Sset_window_redisplay_end_trigger, 2, 2, 0,
614 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
615 VALUE should be a buffer position (typically a marker) or nil.
616 If it is a buffer position, then if redisplay in WINDOW reaches a position
617 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
618 with two arguments: WINDOW, and the end trigger value.
619 Afterwards the end-trigger value is reset to nil. */)
620 (window, value)
621 register Lisp_Object window, value;
623 register struct window *w;
625 w = decode_window (window);
626 w->redisplay_end_trigger = value;
627 return value;
630 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
631 doc: /* Return a list of the edge coordinates of WINDOW.
632 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
633 RIGHT is one more than the rightmost column occupied by WINDOW,
634 and BOTTOM is one more than the bottommost row occupied by WINDOW.
635 The edges include the space used by the window's scroll bar,
636 display margins, fringes, header line, and mode line, if it has them.
637 To get the edges of the actual text area, use `window-inside-edges'. */)
638 (window)
639 Lisp_Object window;
641 register struct window *w = decode_any_window (window);
643 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
644 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
645 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
646 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
647 Qnil))));
650 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
651 doc: /* Return a list of the edge pixel coordinates of WINDOW.
652 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
653 RIGHT is one more than the rightmost x position occupied by WINDOW,
654 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
655 The pixel edges include the space used by the window's scroll bar,
656 display margins, fringes, header line, and mode line, if it has them.
657 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
658 (window)
659 Lisp_Object window;
661 register struct window *w = decode_any_window (window);
663 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
664 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
665 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
666 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
667 Qnil))));
670 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
671 doc: /* Return a list of the edge coordinates of WINDOW.
672 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
673 RIGHT is one more than the rightmost column used by text in WINDOW,
674 and BOTTOM is one more than the bottommost row used by text in WINDOW.
675 The inside edges do not include the space used by the window's scroll bar,
676 display margins, fringes, header line, and/or mode line. */)
677 (window)
678 Lisp_Object window;
680 register struct window *w = decode_any_window (window);
682 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
683 + WINDOW_LEFT_MARGIN_COLS (w)
684 + WINDOW_LEFT_FRINGE_COLS (w)),
685 make_number (WINDOW_TOP_EDGE_LINE (w)
686 + WINDOW_HEADER_LINE_LINES (w)),
687 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
688 - WINDOW_RIGHT_MARGIN_COLS (w)
689 - WINDOW_RIGHT_FRINGE_COLS (w)),
690 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
691 - WINDOW_MODE_LINE_LINES (w)));
694 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
695 doc: /* Return a list of the edge pixel coordinates of WINDOW.
696 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
697 RIGHT is one more than the rightmost x position used by text in WINDOW,
698 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
699 The inside edges do not include the space used by the window's scroll bar,
700 display margins, fringes, header line, and/or mode line. */)
701 (window)
702 Lisp_Object window;
704 register struct window *w = decode_any_window (window);
706 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
707 + WINDOW_LEFT_MARGIN_WIDTH (w)
708 + WINDOW_LEFT_FRINGE_WIDTH (w)),
709 make_number (WINDOW_TOP_EDGE_Y (w)
710 + WINDOW_HEADER_LINE_HEIGHT (w)),
711 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
712 - WINDOW_RIGHT_MARGIN_WIDTH (w)
713 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
714 make_number (WINDOW_BOTTOM_EDGE_Y (w)
715 - WINDOW_MODE_LINE_HEIGHT (w)));
718 /* Test if the character at column *X, row *Y is within window W.
719 If it is not, return ON_NOTHING;
720 if it is in the window's text area,
721 set *x and *y to its location relative to the upper left corner
722 of the window, and
723 return ON_TEXT;
724 if it is on the window's modeline, return ON_MODE_LINE;
725 if it is on the border between the window and its right sibling,
726 return ON_VERTICAL_BORDER.
727 if it is on a scroll bar,
728 return ON_SCROLL_BAR.
729 if it is on the window's top line, return ON_HEADER_LINE;
730 if it is in left or right fringe of the window,
731 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
732 to window-relative coordinates;
733 if it is in the marginal area to the left/right of the window,
734 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
735 to window-relative coordinates.
737 X and Y are frame relative pixel coordinates. */
739 static enum window_part
740 coordinates_in_window (w, x, y)
741 register struct window *w;
742 register int *x, *y;
744 struct frame *f = XFRAME (WINDOW_FRAME (w));
745 int left_x, right_x, top_y, bottom_y;
746 enum window_part part;
747 int ux = FRAME_COLUMN_WIDTH (f);
748 int x0 = WINDOW_LEFT_EDGE_X (w);
749 int x1 = WINDOW_RIGHT_EDGE_X (w);
750 /* The width of the area where the vertical line can be dragged.
751 (Between mode lines for instance. */
752 int grabbable_width = ux;
753 int lmargin_width, rmargin_width, text_left, text_right;
755 /* In what's below, we subtract 1 when computing right_x because we
756 want the rightmost pixel, which is given by left_pixel+width-1. */
757 if (w->pseudo_window_p)
759 left_x = 0;
760 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
761 top_y = WINDOW_TOP_EDGE_Y (w);
762 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
764 else
766 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
767 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
768 top_y = WINDOW_TOP_EDGE_Y (w);
769 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
772 /* Outside any interesting row? */
773 if (*y < top_y || *y >= bottom_y)
774 return ON_NOTHING;
776 /* On the mode line or header line? If it's near the start of
777 the mode or header line of window that's has a horizontal
778 sibling, say it's on the vertical line. That's to be able
779 to resize windows horizontally in case we're using toolkit
780 scroll bars. */
782 if (WINDOW_WANTS_MODELINE_P (w)
783 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
785 part = ON_MODE_LINE;
787 header_vertical_border_check:
788 /* We're somewhere on the mode line. We consider the place
789 between mode lines of horizontally adjacent mode lines
790 as the vertical border. If scroll bars on the left,
791 return the right window. */
792 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
793 || WINDOW_RIGHTMOST_P (w))
795 if (!WINDOW_LEFTMOST_P (w) && abs (*x - x0) < grabbable_width)
797 /* Convert X and Y to window relative coordinates.
798 Vertical border is at the left edge of window. */
799 *x = max (0, *x - x0);
800 *y -= top_y;
801 return ON_VERTICAL_BORDER;
804 else
806 if (abs (*x - x1) < grabbable_width)
808 /* Convert X and Y to window relative coordinates.
809 Vertical border is at the right edge of window. */
810 *x = min (x1, *x) - x0;
811 *y -= top_y;
812 return ON_VERTICAL_BORDER;
816 if (*x < x0 || *x >= x1)
817 return ON_NOTHING;
819 /* Convert X and Y to window relative coordinates.
820 Mode line starts at left edge of window. */
821 *x -= x0;
822 *y -= top_y;
823 return part;
826 if (WINDOW_WANTS_HEADER_LINE_P (w)
827 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
829 part = ON_HEADER_LINE;
830 goto header_vertical_border_check;
833 if (*x < x0 || *x >= x1)
834 return ON_NOTHING;
836 /* Outside any interesting column? */
837 if (*x < left_x || *x > right_x)
839 *y -= top_y;
840 return ON_SCROLL_BAR;
843 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
844 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
846 text_left = window_box_left (w, TEXT_AREA);
847 text_right = text_left + window_box_width (w, TEXT_AREA);
849 if (FRAME_WINDOW_P (f))
851 if (!w->pseudo_window_p
852 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
853 && !WINDOW_RIGHTMOST_P (w)
854 && (abs (*x - right_x) < grabbable_width))
856 /* Convert X and Y to window relative coordinates.
857 Vertical border is at the right edge of window. */
858 *x = min (right_x, *x) - left_x;
859 *y -= top_y;
860 return ON_VERTICAL_BORDER;
863 else
865 /* Need to say "*x > right_x" rather than >=, since on character
866 terminals, the vertical line's x coordinate is right_x. */
867 if (!w->pseudo_window_p
868 && !WINDOW_RIGHTMOST_P (w)
869 && *x > right_x - ux)
871 /* On the border on the right side of the window? Assume that
872 this area begins at RIGHT_X minus a canonical char width. */
873 *x = min (right_x, *x) - left_x;
874 *y -= top_y;
875 return ON_VERTICAL_BORDER;
879 if (*x < text_left)
881 if (lmargin_width > 0
882 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
883 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
884 : (*x < left_x + lmargin_width)))
886 *x -= left_x;
887 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
888 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
889 *y -= top_y;
890 return ON_LEFT_MARGIN;
893 /* Convert X and Y to window-relative pixel coordinates. */
894 *x -= left_x;
895 *y -= top_y;
896 return ON_LEFT_FRINGE;
899 if (*x >= text_right)
901 if (rmargin_width > 0
902 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
903 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
904 : (*x >= right_x - rmargin_width)))
906 *x -= right_x - rmargin_width;
907 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
908 *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
909 *y -= top_y;
910 return ON_RIGHT_MARGIN;
913 /* Convert X and Y to window-relative pixel coordinates. */
914 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
915 *y -= top_y;
916 return ON_RIGHT_FRINGE;
919 /* Everything special ruled out - must be on text area */
920 *x -= text_left;
921 *y -= top_y;
922 return ON_TEXT;
926 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
927 Scoordinates_in_window_p, 2, 2, 0,
928 doc: /* Return non-nil if COORDINATES are in WINDOW.
929 COORDINATES is a cons of the form (X . Y), X and Y being distances
930 measured in characters from the upper-left corner of the frame.
931 \(0 . 0) denotes the character in the upper left corner of the
932 frame.
933 If COORDINATES are in the text portion of WINDOW,
934 the coordinates relative to the window are returned.
935 If they are in the mode line of WINDOW, `mode-line' is returned.
936 If they are in the top mode line of WINDOW, `header-line' is returned.
937 If they are in the left fringe of WINDOW, `left-fringe' is returned.
938 If they are in the right fringe of WINDOW, `right-fringe' is returned.
939 If they are on the border between WINDOW and its right sibling,
940 `vertical-line' is returned.
941 If they are in the windows's left or right marginal areas, `left-margin'\n\
942 or `right-margin' is returned. */)
943 (coordinates, window)
944 register Lisp_Object coordinates, window;
946 struct window *w;
947 struct frame *f;
948 int x, y;
949 Lisp_Object lx, ly;
951 CHECK_WINDOW (window);
952 w = XWINDOW (window);
953 f = XFRAME (w->frame);
954 CHECK_CONS (coordinates);
955 lx = Fcar (coordinates);
956 ly = Fcdr (coordinates);
957 CHECK_NUMBER_OR_FLOAT (lx);
958 CHECK_NUMBER_OR_FLOAT (ly);
959 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
960 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
962 switch (coordinates_in_window (w, &x, &y))
964 case ON_NOTHING:
965 return Qnil;
967 case ON_TEXT:
968 /* X and Y are now window relative pixel coordinates. Convert
969 them to canonical char units before returning them. */
970 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
971 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
973 case ON_MODE_LINE:
974 return Qmode_line;
976 case ON_VERTICAL_BORDER:
977 return Qvertical_line;
979 case ON_HEADER_LINE:
980 return Qheader_line;
982 case ON_LEFT_FRINGE:
983 return Qleft_fringe;
985 case ON_RIGHT_FRINGE:
986 return Qright_fringe;
988 case ON_LEFT_MARGIN:
989 return Qleft_margin;
991 case ON_RIGHT_MARGIN:
992 return Qright_margin;
994 case ON_SCROLL_BAR:
995 /* Historically we are supposed to return nil in this case. */
996 return Qnil;
998 default:
999 abort ();
1004 /* Callback for foreach_window, used in window_from_coordinates.
1005 Check if window W contains coordinates specified by USER_DATA which
1006 is actually a pointer to a struct check_window_data CW.
1008 Check if window W contains coordinates *CW->x and *CW->y. If it
1009 does, return W in *CW->window, as Lisp_Object, and return in
1010 *CW->part the part of the window under coordinates *X,*Y. Return
1011 zero from this function to stop iterating over windows. */
1013 struct check_window_data
1015 Lisp_Object *window;
1016 int *x, *y;
1017 enum window_part *part;
1020 static int
1021 check_window_containing (w, user_data)
1022 struct window *w;
1023 void *user_data;
1025 struct check_window_data *cw = (struct check_window_data *) user_data;
1026 enum window_part found;
1027 int continue_p = 1;
1029 found = coordinates_in_window (w, cw->x, cw->y);
1030 if (found != ON_NOTHING)
1032 *cw->part = found;
1033 XSETWINDOW (*cw->window, w);
1034 continue_p = 0;
1037 return continue_p;
1041 /* Find the window containing frame-relative pixel position X/Y and
1042 return it as a Lisp_Object.
1044 If X, Y is on one of the window's special `window_part' elements,
1045 set *PART to the id of that element, and return X and Y converted
1046 to window relative coordinates in WX and WY.
1048 If there is no window under X, Y return nil and leave *PART
1049 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1051 This function was previously implemented with a loop cycling over
1052 windows with Fnext_window, and starting with the frame's selected
1053 window. It turned out that this doesn't work with an
1054 implementation of next_window using Vwindow_list, because
1055 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1056 tree of F when this function is called asynchronously from
1057 note_mouse_highlight. The original loop didn't terminate in this
1058 case. */
1060 Lisp_Object
1061 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
1062 struct frame *f;
1063 int x, y;
1064 enum window_part *part;
1065 int *wx, *wy;
1066 int tool_bar_p;
1068 Lisp_Object window;
1069 struct check_window_data cw;
1070 enum window_part dummy;
1072 if (part == 0)
1073 part = &dummy;
1075 window = Qnil;
1076 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
1077 foreach_window (f, check_window_containing, &cw);
1079 /* If not found above, see if it's in the tool bar window, if a tool
1080 bar exists. */
1081 if (NILP (window)
1082 && tool_bar_p
1083 && WINDOWP (f->tool_bar_window)
1084 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1085 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
1086 != ON_NOTHING))
1088 *part = ON_TEXT;
1089 window = f->tool_bar_window;
1092 if (wx) *wx = x;
1093 if (wy) *wy = y;
1095 return window;
1098 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1099 doc: /* Return window containing coordinates X and Y on FRAME.
1100 If omitted, FRAME defaults to the currently selected frame.
1101 The top left corner of the frame is considered to be row 0,
1102 column 0. */)
1103 (x, y, frame)
1104 Lisp_Object x, y, frame;
1106 struct frame *f;
1108 if (NILP (frame))
1109 frame = selected_frame;
1110 CHECK_LIVE_FRAME (frame);
1111 f = XFRAME (frame);
1113 /* Check that arguments are integers or floats. */
1114 CHECK_NUMBER_OR_FLOAT (x);
1115 CHECK_NUMBER_OR_FLOAT (y);
1117 return window_from_coordinates (f,
1118 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1119 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1120 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1121 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1122 0, 0, 0, 0);
1125 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1126 doc: /* Return current value of point in WINDOW.
1127 WINDOW defaults to the selected window.
1129 For a nonselected window, this is the value point would have
1130 if that window were selected.
1132 Note that, when WINDOW is the selected window and its buffer
1133 is also currently selected, the value returned is the same as (point).
1134 It would be more strictly correct to return the `top-level' value
1135 of point, outside of any save-excursion forms.
1136 But that is hard to define. */)
1137 (window)
1138 Lisp_Object window;
1140 register struct window *w = decode_window (window);
1142 if (w == XWINDOW (selected_window)
1143 && current_buffer == XBUFFER (w->buffer))
1144 return Fpoint ();
1145 return Fmarker_position (w->pointm);
1148 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1149 doc: /* Return position at which display currently starts in WINDOW.
1150 WINDOW defaults to the selected window.
1151 This is updated by redisplay or by calling `set-window-start'. */)
1152 (window)
1153 Lisp_Object window;
1155 return Fmarker_position (decode_window (window)->start);
1158 /* This is text temporarily removed from the doc string below.
1160 This function returns nil if the position is not currently known.
1161 That happens when redisplay is preempted and doesn't finish.
1162 If in that case you want to compute where the end of the window would
1163 have been if redisplay had finished, do this:
1164 (save-excursion
1165 (goto-char (window-start window))
1166 (vertical-motion (1- (window-height window)) window)
1167 (point))") */
1169 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1170 doc: /* Return position at which display currently ends in WINDOW.
1171 WINDOW defaults to the selected window.
1172 This is updated by redisplay, when it runs to completion.
1173 Simply changing the buffer text or setting `window-start'
1174 does not update this value.
1175 Return nil if there is no recorded value. \(This can happen if the
1176 last redisplay of WINDOW was preempted, and did not finish.)
1177 If UPDATE is non-nil, compute the up-to-date position
1178 if it isn't already recorded. */)
1179 (window, update)
1180 Lisp_Object window, update;
1182 Lisp_Object value;
1183 struct window *w = decode_window (window);
1184 Lisp_Object buf;
1185 struct buffer *b;
1187 buf = w->buffer;
1188 CHECK_BUFFER (buf);
1189 b = XBUFFER (buf);
1191 #if 0 /* This change broke some things. We should make it later. */
1192 /* If we don't know the end position, return nil.
1193 The user can compute it with vertical-motion if he wants to.
1194 It would be nicer to do it automatically,
1195 but that's so slow that it would probably bother people. */
1196 if (NILP (w->window_end_valid))
1197 return Qnil;
1198 #endif
1200 if (! NILP (update)
1201 && ! (! NILP (w->window_end_valid)
1202 && XFASTINT (w->last_modified) >= BUF_MODIFF (b)
1203 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
1204 && !noninteractive)
1206 struct text_pos startp;
1207 struct it it;
1208 struct buffer *old_buffer = NULL;
1210 /* Cannot use Fvertical_motion because that function doesn't
1211 cope with variable-height lines. */
1212 if (b != current_buffer)
1214 old_buffer = current_buffer;
1215 set_buffer_internal (b);
1218 /* In case W->start is out of the range, use something
1219 reasonable. This situation occurred when loading a file with
1220 `-l' containing a call to `rmail' with subsequent other
1221 commands. At the end, W->start happened to be BEG, while
1222 rmail had already narrowed the buffer. */
1223 if (XMARKER (w->start)->charpos < BEGV)
1224 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1225 else if (XMARKER (w->start)->charpos > ZV)
1226 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1227 else
1228 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1230 start_display (&it, w, startp);
1231 move_it_vertically (&it, window_box_height (w));
1232 if (it.current_y < it.last_visible_y)
1233 move_it_past_eol (&it);
1234 value = make_number (IT_CHARPOS (it));
1236 if (old_buffer)
1237 set_buffer_internal (old_buffer);
1239 else
1240 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1242 return value;
1245 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1246 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1247 Return POS. */)
1248 (window, pos)
1249 Lisp_Object window, pos;
1251 register struct window *w = decode_window (window);
1253 CHECK_NUMBER_COERCE_MARKER (pos);
1254 if (w == XWINDOW (selected_window)
1255 && XBUFFER (w->buffer) == current_buffer)
1256 Fgoto_char (pos);
1257 else
1258 set_marker_restricted (w->pointm, pos, w->buffer);
1260 /* We have to make sure that redisplay updates the window to show
1261 the new value of point. */
1262 if (!EQ (window, selected_window))
1263 ++windows_or_buffers_changed;
1265 return pos;
1268 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1269 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1270 Return POS.
1271 Optional third arg NOFORCE non-nil inhibits next redisplay
1272 from overriding motion of point in order to display at this exact start. */)
1273 (window, pos, noforce)
1274 Lisp_Object window, pos, noforce;
1276 register struct window *w = decode_window (window);
1278 CHECK_NUMBER_COERCE_MARKER (pos);
1279 set_marker_restricted (w->start, pos, w->buffer);
1280 /* this is not right, but much easier than doing what is right. */
1281 w->start_at_line_beg = Qnil;
1282 if (NILP (noforce))
1283 w->force_start = Qt;
1284 w->update_mode_line = Qt;
1285 XSETFASTINT (w->last_modified, 0);
1286 XSETFASTINT (w->last_overlay_modified, 0);
1287 if (!EQ (window, selected_window))
1288 windows_or_buffers_changed++;
1290 return pos;
1293 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1294 1, 1, 0,
1295 doc: /* Return WINDOW's dedicated object, usually t or nil.
1296 See also `set-window-dedicated-p'. */)
1297 (window)
1298 Lisp_Object window;
1300 return decode_window (window)->dedicated;
1303 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1304 Sset_window_dedicated_p, 2, 2, 0,
1305 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1306 If it is dedicated, Emacs will not automatically change
1307 which buffer appears in it.
1308 The second argument is the new value for the dedication flag;
1309 non-nil means yes. */)
1310 (window, arg)
1311 Lisp_Object window, arg;
1313 register struct window *w = decode_window (window);
1315 w->dedicated = arg;
1317 return w->dedicated;
1320 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1321 0, 1, 0,
1322 doc: /* Return the display-table that WINDOW is using.
1323 WINDOW defaults to the selected window. */)
1324 (window)
1325 Lisp_Object window;
1327 return decode_window (window)->display_table;
1330 /* Get the display table for use on window W. This is either W's
1331 display table or W's buffer's display table. Ignore the specified
1332 tables if they are not valid; if no valid table is specified,
1333 return 0. */
1335 struct Lisp_Char_Table *
1336 window_display_table (w)
1337 struct window *w;
1339 struct Lisp_Char_Table *dp = NULL;
1341 if (DISP_TABLE_P (w->display_table))
1342 dp = XCHAR_TABLE (w->display_table);
1343 else if (BUFFERP (w->buffer))
1345 struct buffer *b = XBUFFER (w->buffer);
1347 if (DISP_TABLE_P (b->display_table))
1348 dp = XCHAR_TABLE (b->display_table);
1349 else if (DISP_TABLE_P (Vstandard_display_table))
1350 dp = XCHAR_TABLE (Vstandard_display_table);
1353 return dp;
1356 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1357 doc: /* Set WINDOW's display-table to TABLE. */)
1358 (window, table)
1359 register Lisp_Object window, table;
1361 register struct window *w;
1363 w = decode_window (window);
1364 w->display_table = table;
1365 return table;
1368 /* Record info on buffer window w is displaying
1369 when it is about to cease to display that buffer. */
1370 static void
1371 unshow_buffer (w)
1372 register struct window *w;
1374 Lisp_Object buf;
1375 struct buffer *b;
1377 buf = w->buffer;
1378 b = XBUFFER (buf);
1379 if (b != XMARKER (w->pointm)->buffer)
1380 abort ();
1382 #if 0
1383 if (w == XWINDOW (selected_window)
1384 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1385 /* Do this except when the selected window's buffer
1386 is being removed from some other window. */
1387 #endif
1388 /* last_window_start records the start position that this buffer
1389 had in the last window to be disconnected from it.
1390 Now that this statement is unconditional,
1391 it is possible for the buffer to be displayed in the
1392 selected window, while last_window_start reflects another
1393 window which was recently showing the same buffer.
1394 Some people might say that might be a good thing. Let's see. */
1395 b->last_window_start = marker_position (w->start);
1397 /* Point in the selected window's buffer
1398 is actually stored in that buffer, and the window's pointm isn't used.
1399 So don't clobber point in that buffer. */
1400 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1401 /* This line helps to fix Horsley's testbug.el bug. */
1402 && !(WINDOWP (b->last_selected_window)
1403 && w != XWINDOW (b->last_selected_window)
1404 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1405 temp_set_point_both (b,
1406 clip_to_bounds (BUF_BEGV (b),
1407 XMARKER (w->pointm)->charpos,
1408 BUF_ZV (b)),
1409 clip_to_bounds (BUF_BEGV_BYTE (b),
1410 marker_byte_position (w->pointm),
1411 BUF_ZV_BYTE (b)));
1413 if (WINDOWP (b->last_selected_window)
1414 && w == XWINDOW (b->last_selected_window))
1415 b->last_selected_window = Qnil;
1418 /* Put replacement into the window structure in place of old. */
1419 static void
1420 replace_window (old, replacement)
1421 Lisp_Object old, replacement;
1423 register Lisp_Object tem;
1424 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1426 /* If OLD is its frame's root_window, then replacement is the new
1427 root_window for that frame. */
1429 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1430 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1432 p->left_col = o->left_col;
1433 p->top_line = o->top_line;
1434 p->total_cols = o->total_cols;
1435 p->total_lines = o->total_lines;
1436 p->desired_matrix = p->current_matrix = 0;
1437 p->vscroll = 0;
1438 bzero (&p->cursor, sizeof (p->cursor));
1439 bzero (&p->last_cursor, sizeof (p->last_cursor));
1440 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1441 p->phys_cursor_type = -1;
1442 p->phys_cursor_width = -1;
1443 p->must_be_updated_p = 0;
1444 p->pseudo_window_p = 0;
1445 XSETFASTINT (p->window_end_vpos, 0);
1446 XSETFASTINT (p->window_end_pos, 0);
1447 p->window_end_valid = Qnil;
1448 p->frozen_window_start_p = 0;
1449 p->orig_top_line = p->orig_total_lines = Qnil;
1451 p->next = tem = o->next;
1452 if (!NILP (tem))
1453 XWINDOW (tem)->prev = replacement;
1455 p->prev = tem = o->prev;
1456 if (!NILP (tem))
1457 XWINDOW (tem)->next = replacement;
1459 p->parent = tem = o->parent;
1460 if (!NILP (tem))
1462 if (EQ (XWINDOW (tem)->vchild, old))
1463 XWINDOW (tem)->vchild = replacement;
1464 if (EQ (XWINDOW (tem)->hchild, old))
1465 XWINDOW (tem)->hchild = replacement;
1468 /*** Here, if replacement is a vertical combination
1469 and so is its new parent, we should make replacement's
1470 children be children of that parent instead. ***/
1473 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1474 doc: /* Remove WINDOW from the display. Default is selected window. */)
1475 (window)
1476 register Lisp_Object window;
1478 delete_window (window);
1480 if (! NILP (Vwindow_configuration_change_hook)
1481 && ! NILP (Vrun_hooks))
1482 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1484 return Qnil;
1487 void
1488 delete_window (window)
1489 register Lisp_Object window;
1491 register Lisp_Object tem, parent, sib;
1492 register struct window *p;
1493 register struct window *par;
1494 struct frame *f;
1496 /* Because this function is called by other C code on non-leaf
1497 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1498 so we can't decode_window here. */
1499 if (NILP (window))
1500 window = selected_window;
1501 else
1502 CHECK_WINDOW (window);
1503 p = XWINDOW (window);
1505 /* It's a no-op to delete an already-deleted window. */
1506 if (NILP (p->buffer)
1507 && NILP (p->hchild)
1508 && NILP (p->vchild))
1509 return;
1511 parent = p->parent;
1512 if (NILP (parent))
1513 error ("Attempt to delete minibuffer or sole ordinary window");
1514 par = XWINDOW (parent);
1516 windows_or_buffers_changed++;
1517 Vwindow_list = Qnil;
1518 f = XFRAME (WINDOW_FRAME (p));
1519 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1521 /* Are we trying to delete any frame's selected window? */
1523 Lisp_Object swindow, pwindow;
1525 /* See if the frame's selected window is either WINDOW
1526 or any subwindow of it, by finding all that window's parents
1527 and comparing each one with WINDOW. */
1528 swindow = FRAME_SELECTED_WINDOW (f);
1530 while (1)
1532 pwindow = swindow;
1533 while (!NILP (pwindow))
1535 if (EQ (window, pwindow))
1536 break;
1537 pwindow = XWINDOW (pwindow)->parent;
1540 /* If the window being deleted is not a parent of SWINDOW,
1541 then SWINDOW is ok as the new selected window. */
1542 if (!EQ (window, pwindow))
1543 break;
1544 /* Otherwise, try another window for SWINDOW. */
1545 swindow = Fnext_window (swindow, Qlambda, Qnil);
1547 /* If we get back to the frame's selected window,
1548 it means there was no acceptable alternative,
1549 so we cannot delete. */
1550 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1551 error ("Cannot delete window");
1554 /* If we need to change SWINDOW, do it. */
1555 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1557 /* If we're about to delete the selected window on the
1558 selected frame, then we should use Fselect_window to select
1559 the new window. On the other hand, if we're about to
1560 delete the selected window on any other frame, we shouldn't do
1561 anything but set the frame's selected_window slot. */
1562 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1563 Fselect_window (swindow, Qnil);
1564 else
1565 FRAME_SELECTED_WINDOW (f) = swindow;
1569 /* Now we know we can delete this one. */
1570 window_deletion_count++;
1572 tem = p->buffer;
1573 /* tem is null for dummy parent windows
1574 (which have inferiors but not any contents themselves) */
1575 if (!NILP (tem))
1577 unshow_buffer (p);
1578 unchain_marker (XMARKER (p->pointm));
1579 unchain_marker (XMARKER (p->start));
1582 /* Free window glyph matrices. It is sure that they are allocated
1583 again when ADJUST_GLYPHS is called. Block input so that expose
1584 events and other events that access glyph matrices are not
1585 processed while we are changing them. */
1586 BLOCK_INPUT;
1587 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1589 tem = p->next;
1590 if (!NILP (tem))
1591 XWINDOW (tem)->prev = p->prev;
1593 tem = p->prev;
1594 if (!NILP (tem))
1595 XWINDOW (tem)->next = p->next;
1597 if (EQ (window, par->hchild))
1598 par->hchild = p->next;
1599 if (EQ (window, par->vchild))
1600 par->vchild = p->next;
1602 /* Find one of our siblings to give our space to. */
1603 sib = p->prev;
1604 if (NILP (sib))
1606 /* If p gives its space to its next sibling, that sibling needs
1607 to have its top/left side pulled back to where p's is.
1608 set_window_{height,width} will re-position the sibling's
1609 children. */
1610 sib = p->next;
1611 XWINDOW (sib)->top_line = p->top_line;
1612 XWINDOW (sib)->left_col = p->left_col;
1615 /* Stretch that sibling. */
1616 if (!NILP (par->vchild))
1617 set_window_height (sib,
1618 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1620 if (!NILP (par->hchild))
1621 set_window_width (sib,
1622 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1625 /* If parent now has only one child,
1626 put the child into the parent's place. */
1627 tem = par->hchild;
1628 if (NILP (tem))
1629 tem = par->vchild;
1630 if (NILP (XWINDOW (tem)->next)) {
1631 replace_window (parent, tem);
1632 par = XWINDOW (tem);
1635 /* Since we may be deleting combination windows, we must make sure that
1636 not only p but all its children have been marked as deleted. */
1637 if (! NILP (p->hchild))
1638 delete_all_subwindows (XWINDOW (p->hchild));
1639 else if (! NILP (p->vchild))
1640 delete_all_subwindows (XWINDOW (p->vchild));
1642 /* Mark this window as deleted. */
1643 p->buffer = p->hchild = p->vchild = Qnil;
1645 if (! NILP (par->parent))
1646 par = XWINDOW (par->parent);
1648 /* Check if we have a v/hchild with a v/hchild. In that case remove
1649 one of them. */
1651 if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
1653 p = XWINDOW (par->vchild);
1654 par->vchild = p->vchild;
1655 tem = p->vchild;
1657 else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
1659 p = XWINDOW (par->hchild);
1660 par->hchild = p->hchild;
1661 tem = p->hchild;
1663 else
1664 p = 0;
1666 if (p)
1668 while (! NILP (tem)) {
1669 XWINDOW (tem)->parent = p->parent;
1670 if (NILP (XWINDOW (tem)->next))
1671 break;
1672 tem = XWINDOW (tem)->next;
1674 if (! NILP (tem)) {
1675 /* The next of the v/hchild we are removing is now the next of the
1676 last child for the v/hchild:
1677 Before v/hchild -> v/hchild -> next1 -> next2
1679 -> next3
1680 After: v/hchild -> next1 -> next2 -> next3
1682 XWINDOW (tem)->next = p->next;
1683 if (! NILP (p->next))
1684 XWINDOW (p->next)->prev = tem;
1686 p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
1690 /* Adjust glyph matrices. */
1691 adjust_glyphs (f);
1692 UNBLOCK_INPUT;
1697 /***********************************************************************
1698 Window List
1699 ***********************************************************************/
1701 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1702 pointer. This is a callback function for foreach_window, used in
1703 function window_list. */
1705 static int
1706 add_window_to_list (w, user_data)
1707 struct window *w;
1708 void *user_data;
1710 Lisp_Object *list = (Lisp_Object *) user_data;
1711 Lisp_Object window;
1712 XSETWINDOW (window, w);
1713 *list = Fcons (window, *list);
1714 return 1;
1718 /* Return a list of all windows, for use by next_window. If
1719 Vwindow_list is a list, return that list. Otherwise, build a new
1720 list, cache it in Vwindow_list, and return that. */
1722 static Lisp_Object
1723 window_list ()
1725 if (!CONSP (Vwindow_list))
1727 Lisp_Object tail;
1729 Vwindow_list = Qnil;
1730 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1732 Lisp_Object args[2];
1734 /* We are visiting windows in canonical order, and add
1735 new windows at the front of args[1], which means we
1736 have to reverse this list at the end. */
1737 args[1] = Qnil;
1738 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1739 args[0] = Vwindow_list;
1740 args[1] = Fnreverse (args[1]);
1741 Vwindow_list = Fnconc (2, args);
1745 return Vwindow_list;
1749 /* Value is non-zero if WINDOW satisfies the constraints given by
1750 OWINDOW, MINIBUF and ALL_FRAMES.
1752 MINIBUF t means WINDOW may be minibuffer windows.
1753 `lambda' means WINDOW may not be a minibuffer window.
1754 a window means a specific minibuffer window
1756 ALL_FRAMES t means search all frames,
1757 nil means search just current frame,
1758 `visible' means search just visible frames,
1759 0 means search visible and iconified frames,
1760 a window means search the frame that window belongs to,
1761 a frame means consider windows on that frame, only. */
1763 static int
1764 candidate_window_p (window, owindow, minibuf, all_frames)
1765 Lisp_Object window, owindow, minibuf, all_frames;
1767 struct window *w = XWINDOW (window);
1768 struct frame *f = XFRAME (w->frame);
1769 int candidate_p = 1;
1771 if (!BUFFERP (w->buffer))
1772 candidate_p = 0;
1773 else if (MINI_WINDOW_P (w)
1774 && (EQ (minibuf, Qlambda)
1775 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1777 /* If MINIBUF is `lambda' don't consider any mini-windows.
1778 If it is a window, consider only that one. */
1779 candidate_p = 0;
1781 else if (EQ (all_frames, Qt))
1782 candidate_p = 1;
1783 else if (NILP (all_frames))
1785 xassert (WINDOWP (owindow));
1786 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1788 else if (EQ (all_frames, Qvisible))
1790 FRAME_SAMPLE_VISIBILITY (f);
1791 candidate_p = FRAME_VISIBLE_P (f);
1793 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1795 FRAME_SAMPLE_VISIBILITY (f);
1796 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1798 else if (WINDOWP (all_frames))
1799 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1800 || EQ (XWINDOW (all_frames)->frame, w->frame)
1801 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1802 else if (FRAMEP (all_frames))
1803 candidate_p = EQ (all_frames, w->frame);
1805 return candidate_p;
1809 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1810 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1811 ALL_FRAMES. */
1813 static void
1814 decode_next_window_args (window, minibuf, all_frames)
1815 Lisp_Object *window, *minibuf, *all_frames;
1817 if (NILP (*window))
1818 *window = selected_window;
1819 else
1820 CHECK_LIVE_WINDOW (*window);
1822 /* MINIBUF nil may or may not include minibuffers. Decide if it
1823 does. */
1824 if (NILP (*minibuf))
1825 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1826 else if (!EQ (*minibuf, Qt))
1827 *minibuf = Qlambda;
1829 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1830 => count none of them, or a specific minibuffer window (the
1831 active one) to count. */
1833 /* ALL_FRAMES nil doesn't specify which frames to include. */
1834 if (NILP (*all_frames))
1835 *all_frames = (!EQ (*minibuf, Qlambda)
1836 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1837 : Qnil);
1838 else if (EQ (*all_frames, Qvisible))
1840 else if (EQ (*all_frames, make_number (0)))
1842 else if (FRAMEP (*all_frames))
1844 else if (!EQ (*all_frames, Qt))
1845 *all_frames = Qnil;
1847 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1848 search just current frame, `visible' meaning search just visible
1849 frames, 0 meaning search visible and iconified frames, or a
1850 window, meaning search the frame that window belongs to, or a
1851 frame, meaning consider windows on that frame, only. */
1855 /* Return the next or previous window of WINDOW in canonical ordering
1856 of windows. NEXT_P non-zero means return the next window. See the
1857 documentation string of next-window for the meaning of MINIBUF and
1858 ALL_FRAMES. */
1860 static Lisp_Object
1861 next_window (window, minibuf, all_frames, next_p)
1862 Lisp_Object window, minibuf, all_frames;
1863 int next_p;
1865 decode_next_window_args (&window, &minibuf, &all_frames);
1867 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1868 return the first window on the frame. */
1869 if (FRAMEP (all_frames)
1870 && !EQ (all_frames, XWINDOW (window)->frame))
1871 return Fframe_first_window (all_frames);
1873 if (next_p)
1875 Lisp_Object list;
1877 /* Find WINDOW in the list of all windows. */
1878 list = Fmemq (window, window_list ());
1880 /* Scan forward from WINDOW to the end of the window list. */
1881 if (CONSP (list))
1882 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1883 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1884 break;
1886 /* Scan from the start of the window list up to WINDOW. */
1887 if (!CONSP (list))
1888 for (list = Vwindow_list;
1889 CONSP (list) && !EQ (XCAR (list), window);
1890 list = XCDR (list))
1891 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1892 break;
1894 if (CONSP (list))
1895 window = XCAR (list);
1897 else
1899 Lisp_Object candidate, list;
1901 /* Scan through the list of windows for candidates. If there are
1902 candidate windows in front of WINDOW, the last one of these
1903 is the one we want. If there are candidates following WINDOW
1904 in the list, again the last one of these is the one we want. */
1905 candidate = Qnil;
1906 for (list = window_list (); CONSP (list); list = XCDR (list))
1908 if (EQ (XCAR (list), window))
1910 if (WINDOWP (candidate))
1911 break;
1913 else if (candidate_window_p (XCAR (list), window, minibuf,
1914 all_frames))
1915 candidate = XCAR (list);
1918 if (WINDOWP (candidate))
1919 window = candidate;
1922 return window;
1926 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1927 doc: /* Return next window after WINDOW in canonical ordering of windows.
1928 If omitted, WINDOW defaults to the selected window.
1930 Optional second arg MINIBUF t means count the minibuffer window even
1931 if not active. MINIBUF nil or omitted means count the minibuffer iff
1932 it is active. MINIBUF neither t nor nil means not to count the
1933 minibuffer even if it is active.
1935 Several frames may share a single minibuffer; if the minibuffer
1936 counts, all windows on all frames that share that minibuffer count
1937 too. Therefore, `next-window' can be used to iterate through the
1938 set of windows even when the minibuffer is on another frame. If the
1939 minibuffer does not count, only windows from WINDOW's frame count.
1941 Optional third arg ALL-FRAMES t means include windows on all frames.
1942 ALL-FRAMES nil or omitted means cycle within the frames as specified
1943 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1944 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1945 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1946 Anything else means restrict to WINDOW's frame.
1948 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1949 `next-window' to iterate through the entire cycle of acceptable
1950 windows, eventually ending up back at the window you started with.
1951 `previous-window' traverses the same cycle, in the reverse order. */)
1952 (window, minibuf, all_frames)
1953 Lisp_Object window, minibuf, all_frames;
1955 return next_window (window, minibuf, all_frames, 1);
1959 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1960 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1961 If omitted, WINDOW defaults to the selected window.
1963 Optional second arg MINIBUF t means count the minibuffer window even
1964 if not active. MINIBUF nil or omitted means count the minibuffer iff
1965 it is active. MINIBUF neither t nor nil means not to count the
1966 minibuffer even if it is active.
1968 Several frames may share a single minibuffer; if the minibuffer
1969 counts, all windows on all frames that share that minibuffer count
1970 too. Therefore, `previous-window' can be used to iterate through
1971 the set of windows even when the minibuffer is on another frame. If
1972 the minibuffer does not count, only windows from WINDOW's frame count
1974 Optional third arg ALL-FRAMES t means include windows on all frames.
1975 ALL-FRAMES nil or omitted means cycle within the frames as specified
1976 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1977 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1978 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1979 Anything else means restrict to WINDOW's frame.
1981 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1982 `previous-window' to iterate through the entire cycle of acceptable
1983 windows, eventually ending up back at the window you started with.
1984 `next-window' traverses the same cycle, in the reverse order. */)
1985 (window, minibuf, all_frames)
1986 Lisp_Object window, minibuf, all_frames;
1988 return next_window (window, minibuf, all_frames, 0);
1992 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1993 doc: /* Select the ARG'th different window on this frame.
1994 All windows on current frame are arranged in a cyclic order.
1995 This command selects the window ARG steps away in that order.
1996 A negative ARG moves in the opposite order. The optional second
1997 argument ALL-FRAMES has the same meaning as in `next-window', which see. */)
1998 (arg, all_frames)
1999 Lisp_Object arg, all_frames;
2001 Lisp_Object window;
2002 int i;
2004 CHECK_NUMBER (arg);
2005 window = selected_window;
2007 for (i = XINT (arg); i > 0; --i)
2008 window = Fnext_window (window, Qnil, all_frames);
2009 for (; i < 0; ++i)
2010 window = Fprevious_window (window, Qnil, all_frames);
2012 Fselect_window (window, Qnil);
2013 return Qnil;
2017 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2018 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2019 FRAME nil or omitted means use the selected frame.
2020 WINDOW nil or omitted means use the selected window.
2021 MINIBUF t means include the minibuffer window, even if it isn't active.
2022 MINIBUF nil or omitted means include the minibuffer window only
2023 if it's active.
2024 MINIBUF neither nil nor t means never include the minibuffer window. */)
2025 (frame, minibuf, window)
2026 Lisp_Object frame, minibuf, window;
2028 if (NILP (window))
2029 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2030 CHECK_WINDOW (window);
2031 if (NILP (frame))
2032 frame = selected_frame;
2034 if (!EQ (frame, XWINDOW (window)->frame))
2035 error ("Window is on a different frame");
2037 return window_list_1 (window, minibuf, frame);
2041 /* Return a list of windows in canonical ordering. Arguments are like
2042 for `next-window'. */
2044 static Lisp_Object
2045 window_list_1 (window, minibuf, all_frames)
2046 Lisp_Object window, minibuf, all_frames;
2048 Lisp_Object tail, list, rest;
2050 decode_next_window_args (&window, &minibuf, &all_frames);
2051 list = Qnil;
2053 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2054 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2055 list = Fcons (XCAR (tail), list);
2057 /* Rotate the list to start with WINDOW. */
2058 list = Fnreverse (list);
2059 rest = Fmemq (window, list);
2060 if (!NILP (rest) && !EQ (rest, list))
2062 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2064 XSETCDR (tail, Qnil);
2065 list = nconc2 (rest, list);
2067 return list;
2072 /* Look at all windows, performing an operation specified by TYPE
2073 with argument OBJ.
2074 If FRAMES is Qt, look at all frames;
2075 Qnil, look at just the selected frame;
2076 Qvisible, look at visible frames;
2077 a frame, just look at windows on that frame.
2078 If MINI is non-zero, perform the operation on minibuffer windows too. */
2080 enum window_loop
2082 WINDOW_LOOP_UNUSED,
2083 GET_BUFFER_WINDOW, /* Arg is buffer */
2084 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2085 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2086 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2087 GET_LARGEST_WINDOW,
2088 UNSHOW_BUFFER, /* Arg is buffer */
2089 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2090 CHECK_ALL_WINDOWS
2093 static Lisp_Object
2094 window_loop (type, obj, mini, frames)
2095 enum window_loop type;
2096 Lisp_Object obj, frames;
2097 int mini;
2099 Lisp_Object window, windows, best_window, frame_arg;
2100 struct frame *f;
2101 struct gcpro gcpro1;
2103 /* If we're only looping through windows on a particular frame,
2104 frame points to that frame. If we're looping through windows
2105 on all frames, frame is 0. */
2106 if (FRAMEP (frames))
2107 f = XFRAME (frames);
2108 else if (NILP (frames))
2109 f = SELECTED_FRAME ();
2110 else
2111 f = NULL;
2113 if (f)
2114 frame_arg = Qlambda;
2115 else if (EQ (frames, make_number (0)))
2116 frame_arg = frames;
2117 else if (EQ (frames, Qvisible))
2118 frame_arg = frames;
2119 else
2120 frame_arg = Qt;
2122 /* frame_arg is Qlambda to stick to one frame,
2123 Qvisible to consider all visible frames,
2124 or Qt otherwise. */
2126 /* Pick a window to start with. */
2127 if (WINDOWP (obj))
2128 window = obj;
2129 else if (f)
2130 window = FRAME_SELECTED_WINDOW (f);
2131 else
2132 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2134 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2135 GCPRO1 (windows);
2136 best_window = Qnil;
2138 for (; CONSP (windows); windows = XCDR (windows))
2140 struct window *w;
2142 window = XCAR (windows);
2143 w = XWINDOW (window);
2145 /* Note that we do not pay attention here to whether the frame
2146 is visible, since Fwindow_list skips non-visible frames if
2147 that is desired, under the control of frame_arg. */
2148 if (!MINI_WINDOW_P (w)
2149 /* For UNSHOW_BUFFER, we must always consider all windows. */
2150 || type == UNSHOW_BUFFER
2151 || (mini && minibuf_level > 0))
2152 switch (type)
2154 case GET_BUFFER_WINDOW:
2155 if (EQ (w->buffer, obj)
2156 /* Don't find any minibuffer window
2157 except the one that is currently in use. */
2158 && (MINI_WINDOW_P (w)
2159 ? EQ (window, minibuf_window)
2160 : 1))
2162 if (NILP (best_window))
2163 best_window = window;
2164 else if (EQ (window, selected_window))
2165 /* For compatibility with 20.x, prefer to return
2166 selected-window. */
2167 best_window = window;
2169 break;
2171 case GET_LRU_WINDOW:
2172 /* `obj' is an integer encoding a bitvector.
2173 `obj & 1' means consider only full-width windows.
2174 `obj & 2' means consider also dedicated windows. */
2175 if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
2176 || (!(XINT (obj) & 2) && !NILP (w->dedicated))
2177 /* Minibuffer windows are always ignored. */
2178 || MINI_WINDOW_P (w))
2179 break;
2180 if (NILP (best_window)
2181 || (XFASTINT (XWINDOW (best_window)->use_time)
2182 > XFASTINT (w->use_time)))
2183 best_window = window;
2184 break;
2186 case DELETE_OTHER_WINDOWS:
2187 if (!EQ (window, obj))
2188 Fdelete_window (window);
2189 break;
2191 case DELETE_BUFFER_WINDOWS:
2192 if (EQ (w->buffer, obj))
2194 struct frame *f = XFRAME (WINDOW_FRAME (w));
2196 /* If this window is dedicated, and in a frame of its own,
2197 kill the frame. */
2198 if (EQ (window, FRAME_ROOT_WINDOW (f))
2199 && !NILP (w->dedicated)
2200 && other_visible_frames (f))
2202 /* Skip the other windows on this frame.
2203 There might be one, the minibuffer! */
2204 while (CONSP (XCDR (windows))
2205 && EQ (XWINDOW (XCAR (windows))->frame,
2206 XWINDOW (XCAR (XCDR (windows)))->frame))
2207 windows = XCDR (windows);
2209 /* Now we can safely delete the frame. */
2210 Fdelete_frame (w->frame, Qnil);
2212 else if (NILP (w->parent))
2214 /* If we're deleting the buffer displayed in the
2215 only window on the frame, find a new buffer to
2216 display there. */
2217 Lisp_Object buffer;
2218 buffer = Fother_buffer (obj, Qnil, w->frame);
2219 Fset_window_buffer (window, buffer, Qnil);
2220 if (EQ (window, selected_window))
2221 Fset_buffer (w->buffer);
2223 else
2224 Fdelete_window (window);
2226 break;
2228 case GET_LARGEST_WINDOW:
2229 { /* nil `obj' means to ignore dedicated windows. */
2230 /* Ignore dedicated windows and minibuffers. */
2231 if (MINI_WINDOW_P (w) || (NILP (obj) && !NILP (w->dedicated)))
2232 break;
2234 if (NILP (best_window))
2235 best_window = window;
2236 else
2238 struct window *b = XWINDOW (best_window);
2239 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2240 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2241 best_window = window;
2244 break;
2246 case UNSHOW_BUFFER:
2247 if (EQ (w->buffer, obj))
2249 Lisp_Object buffer;
2250 struct frame *f = XFRAME (w->frame);
2252 /* Find another buffer to show in this window. */
2253 buffer = Fother_buffer (obj, Qnil, w->frame);
2255 /* If this window is dedicated, and in a frame of its own,
2256 kill the frame. */
2257 if (EQ (window, FRAME_ROOT_WINDOW (f))
2258 && !NILP (w->dedicated)
2259 && other_visible_frames (f))
2261 /* Skip the other windows on this frame.
2262 There might be one, the minibuffer! */
2263 while (CONSP (XCDR (windows))
2264 && EQ (XWINDOW (XCAR (windows))->frame,
2265 XWINDOW (XCAR (XCDR (windows)))->frame))
2266 windows = XCDR (windows);
2268 /* Now we can safely delete the frame. */
2269 Fdelete_frame (w->frame, Qnil);
2271 else if (!NILP (w->dedicated) && !NILP (w->parent))
2273 Lisp_Object window;
2274 XSETWINDOW (window, w);
2275 /* If this window is dedicated and not the only window
2276 in its frame, then kill it. */
2277 Fdelete_window (window);
2279 else
2281 /* Otherwise show a different buffer in the window. */
2282 w->dedicated = Qnil;
2283 Fset_window_buffer (window, buffer, Qnil);
2284 if (EQ (window, selected_window))
2285 Fset_buffer (w->buffer);
2288 break;
2290 case REDISPLAY_BUFFER_WINDOWS:
2291 if (EQ (w->buffer, obj))
2293 mark_window_display_accurate (window, 0);
2294 w->update_mode_line = Qt;
2295 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2296 ++update_mode_lines;
2297 best_window = window;
2299 break;
2301 /* Check for a window that has a killed buffer. */
2302 case CHECK_ALL_WINDOWS:
2303 if (! NILP (w->buffer)
2304 && NILP (XBUFFER (w->buffer)->name))
2305 abort ();
2306 break;
2308 case WINDOW_LOOP_UNUSED:
2309 break;
2313 UNGCPRO;
2314 return best_window;
2317 /* Used for debugging. Abort if any window has a dead buffer. */
2319 void
2320 check_all_windows ()
2322 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2325 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
2326 doc: /* Return the window least recently selected or used for display.
2327 \(LRU means Least Recently Used.)
2329 Return a full-width window if possible.
2330 A minibuffer window is never a candidate.
2331 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2332 so if all windows are dedicated, the value is nil.
2333 If optional argument FRAME is `visible', search all visible frames.
2334 If FRAME is 0, search all visible and iconified frames.
2335 If FRAME is t, search all frames.
2336 If FRAME is nil, search only the selected frame.
2337 If FRAME is a frame, search only that frame. */)
2338 (frame, dedicated)
2339 Lisp_Object frame, dedicated;
2341 register Lisp_Object w;
2342 /* First try for a window that is full-width */
2343 w = window_loop (GET_LRU_WINDOW,
2344 NILP (dedicated) ? make_number (1) : make_number (3),
2345 0, frame);
2346 if (!NILP (w) && !EQ (w, selected_window))
2347 return w;
2348 /* If none of them, try the rest */
2349 return window_loop (GET_LRU_WINDOW,
2350 NILP (dedicated) ? make_number (0) : make_number (2),
2351 0, frame);
2354 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
2355 doc: /* Return the largest window in area.
2356 A minibuffer window is never a candidate.
2357 A dedicated window is never a candidate unless DEDICATED is non-nil,
2358 so if all windows are dedicated, the value is nil.
2359 If optional argument FRAME is `visible', search all visible frames.
2360 If FRAME is 0, search all visible and iconified frames.
2361 If FRAME is t, search all frames.
2362 If FRAME is nil, search only the selected frame.
2363 If FRAME is a frame, search only that frame. */)
2364 (frame, dedicated)
2365 Lisp_Object frame, dedicated;
2367 return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
2368 frame);
2371 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2372 doc: /* Return a window currently displaying BUFFER, or nil if none.
2373 BUFFER can be a buffer or a buffer name.
2374 If optional argument FRAME is `visible', search all visible frames.
2375 If optional argument FRAME is 0, search all visible and iconified frames.
2376 If FRAME is t, search all frames.
2377 If FRAME is nil, search only the selected frame.
2378 If FRAME is a frame, search only that frame. */)
2379 (buffer, frame)
2380 Lisp_Object buffer, frame;
2382 buffer = Fget_buffer (buffer);
2383 if (BUFFERP (buffer))
2384 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2385 else
2386 return Qnil;
2389 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2390 0, 1, "",
2391 doc: /* Make WINDOW (or the selected window) fill its frame.
2392 Only the frame WINDOW is on is affected.
2393 This function tries to reduce display jumps
2394 by keeping the text previously visible in WINDOW
2395 in the same place on the frame. Doing this depends on
2396 the value of (window-start WINDOW), so if calling this function
2397 in a program gives strange scrolling, make sure the window-start
2398 value is reasonable when this function is called. */)
2399 (window)
2400 Lisp_Object window;
2402 struct window *w;
2403 int startpos;
2404 int top, new_top;
2406 if (NILP (window))
2407 window = selected_window;
2408 else
2409 CHECK_LIVE_WINDOW (window);
2410 w = XWINDOW (window);
2412 startpos = marker_position (w->start);
2413 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2415 if (MINI_WINDOW_P (w) && top > 0)
2416 error ("Can't expand minibuffer to full frame");
2418 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2420 /* Try to minimize scrolling, by setting the window start to the point
2421 will cause the text at the old window start to be at the same place
2422 on the frame. But don't try to do this if the window start is
2423 outside the visible portion (as might happen when the display is
2424 not current, due to typeahead). */
2425 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2426 if (new_top != top
2427 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2428 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2430 struct position pos;
2431 struct buffer *obuf = current_buffer;
2433 Fset_buffer (w->buffer);
2434 /* This computation used to temporarily move point, but that can
2435 have unwanted side effects due to text properties. */
2436 pos = *vmotion (startpos, -top, w);
2438 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2439 w->window_end_valid = Qnil;
2440 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2441 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2442 : Qnil);
2443 /* We need to do this, so that the window-scroll-functions
2444 get called. */
2445 w->optional_new_start = Qt;
2447 set_buffer_internal (obuf);
2450 return Qnil;
2453 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2454 1, 2, "bDelete windows on (buffer): ",
2455 doc: /* Delete all windows showing BUFFER.
2456 BUFFER must be a buffer or the name of an existing buffer.
2457 Optional second argument FRAME controls which frames are affected.
2458 If optional argument FRAME is `visible', search all visible frames.
2459 If FRAME is 0, search all visible and iconified frames.
2460 If FRAME is nil, search all frames.
2461 If FRAME is t, search only the selected frame.
2462 If FRAME is a frame, search only that frame. */)
2463 (buffer, frame)
2464 Lisp_Object buffer, frame;
2466 /* FRAME uses t and nil to mean the opposite of what window_loop
2467 expects. */
2468 if (NILP (frame))
2469 frame = Qt;
2470 else if (EQ (frame, Qt))
2471 frame = Qnil;
2473 if (!NILP (buffer))
2475 buffer = Fget_buffer (buffer);
2476 CHECK_BUFFER (buffer);
2477 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2480 return Qnil;
2483 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2484 Sreplace_buffer_in_windows,
2485 1, 1, "bReplace buffer in windows: ",
2486 doc: /* Replace BUFFER with some other buffer in all windows showing it.
2487 BUFFER may be a buffer or the name of an existing buffer. */)
2488 (buffer)
2489 Lisp_Object buffer;
2491 if (!NILP (buffer))
2493 buffer = Fget_buffer (buffer);
2494 CHECK_BUFFER (buffer);
2495 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2497 return Qnil;
2500 /* Replace BUFFER with some other buffer in all windows
2501 of all frames, even those on other keyboards. */
2503 void
2504 replace_buffer_in_all_windows (buffer)
2505 Lisp_Object buffer;
2507 #ifdef MULTI_KBOARD
2508 Lisp_Object tail, frame;
2510 /* A single call to window_loop won't do the job
2511 because it only considers frames on the current keyboard.
2512 So loop manually over frames, and handle each one. */
2513 FOR_EACH_FRAME (tail, frame)
2514 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2515 #else
2516 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2517 #endif
2520 /* Set the height of WINDOW and all its inferiors. */
2522 /* The smallest acceptable dimensions for a window. Anything smaller
2523 might crash Emacs. */
2525 #define MIN_SAFE_WINDOW_WIDTH (2)
2526 #define MIN_SAFE_WINDOW_HEIGHT (1)
2528 /* Make sure that window_min_height and window_min_width are
2529 not too small; if they are, set them to safe minima. */
2531 static void
2532 check_min_window_sizes ()
2534 /* Smaller values might permit a crash. */
2535 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2536 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2537 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2538 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2541 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2542 minimum allowable size. */
2544 void
2545 check_frame_size (frame, rows, cols)
2546 FRAME_PTR frame;
2547 int *rows, *cols;
2549 /* For height, we have to see:
2550 how many windows the frame has at minimum (one or two),
2551 and whether it has a menu bar or other special stuff at the top. */
2552 int min_height
2553 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2554 ? MIN_SAFE_WINDOW_HEIGHT
2555 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2557 if (FRAME_TOP_MARGIN (frame) > 0)
2558 min_height += FRAME_TOP_MARGIN (frame);
2560 if (*rows < min_height)
2561 *rows = min_height;
2562 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2563 *cols = MIN_SAFE_WINDOW_WIDTH;
2566 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2567 check if W's width can be changed, otherwise check W's height.
2568 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2569 siblings, too. If none of the siblings is resizable, WINDOW isn't
2570 either. */
2572 static int
2573 window_fixed_size_p (w, width_p, check_siblings_p)
2574 struct window *w;
2575 int width_p, check_siblings_p;
2577 int fixed_p;
2578 struct window *c;
2580 if (!NILP (w->hchild))
2582 c = XWINDOW (w->hchild);
2584 if (width_p)
2586 /* A horiz. combination is fixed-width if all of if its
2587 children are. */
2588 while (c && window_fixed_size_p (c, width_p, 0))
2589 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2590 fixed_p = c == NULL;
2592 else
2594 /* A horiz. combination is fixed-height if one of if its
2595 children is. */
2596 while (c && !window_fixed_size_p (c, width_p, 0))
2597 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2598 fixed_p = c != NULL;
2601 else if (!NILP (w->vchild))
2603 c = XWINDOW (w->vchild);
2605 if (width_p)
2607 /* A vert. combination is fixed-width 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;
2613 else
2615 /* A vert. combination is fixed-height if all of if its
2616 children are. */
2617 while (c && window_fixed_size_p (c, width_p, 0))
2618 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2619 fixed_p = c == NULL;
2622 else if (BUFFERP (w->buffer))
2624 struct buffer *old = current_buffer;
2625 Lisp_Object val;
2627 current_buffer = XBUFFER (w->buffer);
2628 val = find_symbol_value (Qwindow_size_fixed);
2629 current_buffer = old;
2631 fixed_p = 0;
2632 if (!EQ (val, Qunbound))
2634 fixed_p = !NILP (val);
2636 if (fixed_p
2637 && ((EQ (val, Qheight) && width_p)
2638 || (EQ (val, Qwidth) && !width_p)))
2639 fixed_p = 0;
2642 /* Can't tell if this one is resizable without looking at
2643 siblings. If all siblings are fixed-size this one is too. */
2644 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2646 Lisp_Object child;
2648 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2649 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2650 break;
2652 if (NILP (child))
2653 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2654 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2655 break;
2657 if (NILP (child))
2658 fixed_p = 1;
2661 else
2662 fixed_p = 1;
2664 return fixed_p;
2667 /* Return the minimum size for leaf window W. WIDTH_P non-zero means
2668 take into account fringes and the scrollbar of W. WIDTH_P zero
2669 means take into account mode-line and header-line of W. Return 1
2670 for the minibuffer. */
2672 static int
2673 window_min_size_2 (w, width_p)
2674 struct window *w;
2675 int width_p;
2677 int size;
2679 if (width_p)
2680 size = max (window_min_width,
2681 (MIN_SAFE_WINDOW_WIDTH
2682 + WINDOW_FRINGE_COLS (w)
2683 + WINDOW_SCROLL_BAR_COLS (w)));
2684 else if (MINI_WINDOW_P (w))
2685 size = 1;
2686 else
2687 size = max (window_min_height,
2688 (MIN_SAFE_WINDOW_HEIGHT
2689 + (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)
2690 + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 )));
2692 return size;
2695 /* Return the minimum size of window W, not taking fixed-width windows
2696 into account. WIDTH_P non-zero means return the minimum width,
2697 otherwise return the minimum height. If W is a combination window,
2698 compute the minimum size from the minimum sizes of W's children. */
2700 static int
2701 window_min_size_1 (w, width_p)
2702 struct window *w;
2703 int width_p;
2705 struct window *c;
2706 int size;
2708 if (!NILP (w->hchild))
2710 c = XWINDOW (w->hchild);
2711 size = 0;
2713 if (width_p)
2715 /* The min width of a horizontal combination is
2716 the sum of the min widths of its children. */
2717 while (c)
2719 size += window_min_size_1 (c, width_p);
2720 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2723 else
2725 /* The min height a horizontal combination equals
2726 the maximum of all min height of its children. */
2727 while (c)
2729 int min_size = window_min_size_1 (c, width_p);
2730 size = max (min_size, size);
2731 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2735 else if (!NILP (w->vchild))
2737 c = XWINDOW (w->vchild);
2738 size = 0;
2740 if (width_p)
2742 /* The min width of a vertical combination is
2743 the maximum of the min widths of its children. */
2744 while (c)
2746 int min_size = window_min_size_1 (c, width_p);
2747 size = max (min_size, size);
2748 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2751 else
2753 /* The min height of a vertical combination equals
2754 the sum of the min height of its children. */
2755 while (c)
2757 size += window_min_size_1 (c, width_p);
2758 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2762 else
2763 size = window_min_size_2 (w, width_p);
2765 return size;
2769 /* Return the minimum size of window W, taking fixed-size windows into
2770 account. WIDTH_P non-zero means return the minimum width,
2771 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2772 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2773 unless FIXED is null. */
2775 static int
2776 window_min_size (w, width_p, ignore_fixed_p, fixed)
2777 struct window *w;
2778 int width_p, ignore_fixed_p, *fixed;
2780 int size, fixed_p;
2782 if (ignore_fixed_p)
2783 fixed_p = 0;
2784 else
2785 fixed_p = window_fixed_size_p (w, width_p, 1);
2787 if (fixed)
2788 *fixed = fixed_p;
2790 if (fixed_p)
2791 size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines);
2792 else
2793 size = window_min_size_1 (w, width_p);
2795 return size;
2799 /* Adjust the margins of window W if text area is too small.
2800 Return 1 if window width is ok after adjustment; 0 if window
2801 is still too narrow. */
2803 static int
2804 adjust_window_margins (w)
2805 struct window *w;
2807 int box_cols = (WINDOW_TOTAL_COLS (w)
2808 - WINDOW_FRINGE_COLS (w)
2809 - WINDOW_SCROLL_BAR_COLS (w));
2810 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2811 + WINDOW_RIGHT_MARGIN_COLS (w));
2813 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2814 return 1;
2816 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2817 return 0;
2819 /* Window's text area is too narrow, but reducing the window
2820 margins will fix that. */
2821 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2822 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2824 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2825 w->left_margin_cols = w->right_margin_cols
2826 = make_number (margin_cols/2);
2827 else
2828 w->right_margin_cols = make_number (margin_cols);
2830 else
2831 w->left_margin_cols = make_number (margin_cols);
2832 return 1;
2835 /* Calculate new sizes for windows in the list FORWARD when the window size
2836 goes from TOTAL to SIZE. TOTAL must be greater than SIZE.
2837 The number of windows in FORWARD is NCHILDREN, and the number that
2838 can shrink is SHRINKABLE.
2839 The minimum size a window can have is MIN_SIZE.
2840 If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
2841 If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
2842 shrinking rows.
2844 This function returns an allocated array of new sizes that the caller
2845 must free. The size -1 means the window is fixed and RESIZE_FIXED_P
2846 is zero. Array index 0 refers to the first window in FORWARD, 1 to
2847 the second, and so on.
2849 This function tries to keep windows at least at the minimum size
2850 and resize other windows before it resizes any window to zero (i.e.
2851 delete that window).
2853 Windows are resized proportional to their size, so bigger windows
2854 shrink more than smaller windows. */
2855 static int *
2856 shrink_windows (total, size, nchildren, shrinkable,
2857 min_size, resize_fixed_p, forward, width_p)
2858 int total, size, nchildren, shrinkable, min_size;
2859 int resize_fixed_p, width_p;
2860 Lisp_Object forward;
2862 int available_resize = 0;
2863 int *new_sizes;
2864 struct window *c;
2865 Lisp_Object child;
2866 int smallest = total;
2867 int total_removed = 0;
2868 int total_shrink = total - size;
2869 int i;
2871 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2873 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2875 int child_size;
2877 c = XWINDOW (child);
2878 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2880 if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2881 new_sizes[i] = -1;
2882 else
2884 new_sizes[i] = child_size;
2885 if (child_size > min_size)
2886 available_resize += child_size - min_size;
2889 /* We might need to shrink some windows to zero. Find the smallest
2890 windows and set them to 0 until we can fulfil the new size. */
2892 while (shrinkable > 1 && size + available_resize < total)
2894 for (i = 0; i < nchildren; ++i)
2895 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2896 smallest = new_sizes[i];
2898 for (i = 0; i < nchildren; ++i)
2899 if (new_sizes[i] == smallest)
2901 /* Resize this window down to zero. */
2902 new_sizes[i] = 0;
2903 if (smallest > min_size)
2904 available_resize -= smallest - min_size;
2905 available_resize += smallest;
2906 --shrinkable;
2907 total_removed += smallest;
2909 /* We don't know what the smallest is now. */
2910 smallest = total;
2912 /* Out of for, just remove one window at the time and
2913 check again if we have enough space. */
2914 break;
2918 /* Now, calculate the new sizes. Try to shrink each window
2919 proportional to its size. */
2920 for (i = 0; i < nchildren; ++i)
2922 if (new_sizes[i] > min_size)
2924 int to_shrink = total_shrink*new_sizes[i]/total;
2925 if (new_sizes[i] - to_shrink < min_size)
2926 to_shrink = new_sizes[i] - min_size;
2927 new_sizes[i] -= to_shrink;
2928 total_removed += to_shrink;
2932 /* Any reminder due to rounding, we just subtract from windows
2933 that are left and still can be shrunk. */
2934 while (total_shrink > total_removed)
2936 int nonzero_sizes = 0;
2937 int nonzero_idx = -1;
2939 for (i = 0; i < nchildren; ++i)
2940 if (new_sizes[i] > 0)
2942 ++nonzero_sizes;
2943 nonzero_idx = i;
2946 for (i = 0; i < nchildren; ++i)
2947 if (new_sizes[i] > min_size)
2949 --new_sizes[i];
2950 ++total_removed;
2952 /* Out of for, just shrink one window at the time and
2953 check again if we have enough space. */
2954 break;
2958 /* Special case, only one window left. */
2959 if (nonzero_sizes == 1)
2960 break;
2963 /* Any surplus due to rounding, we add to windows that are left. */
2964 while (total_shrink < total_removed)
2966 for (i = 0; i < nchildren; ++i)
2968 if (new_sizes[i] != 0 && total_shrink < total_removed)
2970 ++new_sizes[i];
2971 --total_removed;
2972 break;
2977 return new_sizes;
2980 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2981 WINDOW's width. Resize WINDOW's children, if any, so that they
2982 keep their proportionate size relative to WINDOW.
2984 If FIRST_ONLY is 1, change only the first of WINDOW's children when
2985 they are in series. If LAST_ONLY is 1, change only the last of
2986 WINDOW's children when they are in series.
2988 Propagate WINDOW's top or left edge position to children. Delete
2989 windows that become too small unless NODELETE_P is non-zero.
2991 If NODELETE_P is 2, that means we do delete windows that are
2992 too small, even if they were too small before! */
2994 static void
2995 size_window (window, size, width_p, nodelete_p, first_only, last_only)
2996 Lisp_Object window;
2997 int size, width_p, nodelete_p;
2998 int first_only, last_only;
3000 struct window *w = XWINDOW (window);
3001 struct window *c;
3002 Lisp_Object child, *forward, *sideward;
3003 int old_size, min_size, safe_min_size;
3005 check_min_window_sizes ();
3006 size = max (0, size);
3008 /* If the window has been "too small" at one point,
3009 don't delete it for being "too small" in the future.
3010 Preserve it as long as that is at all possible. */
3011 if (width_p)
3013 old_size = WINDOW_TOTAL_COLS (w);
3014 min_size = window_min_width;
3015 safe_min_size = window_min_size_2 (w, 1);
3017 else
3019 old_size = XINT (w->total_lines);
3020 min_size = window_min_height;
3021 safe_min_size = window_min_size_2 (w, 0);
3024 if (old_size < min_size && nodelete_p != 2)
3025 w->too_small_ok = Qt;
3027 /* Move the following test here since otherwise the
3028 preceding test doesn't make sense. martin. */
3029 if (nodelete_p == 2)
3030 nodelete_p = 0;
3032 /* Maybe delete WINDOW if it's too small. */
3033 if (nodelete_p != 1 && !NILP (w->parent))
3035 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
3036 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
3037 if (min_size < safe_min_size)
3038 min_size = safe_min_size;
3039 if (size < min_size)
3041 delete_window (window);
3042 return;
3046 /* Set redisplay hints. */
3047 w->last_modified = make_number (0);
3048 w->last_overlay_modified = make_number (0);
3049 windows_or_buffers_changed++;
3050 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
3052 if (width_p)
3054 sideward = &w->vchild;
3055 forward = &w->hchild;
3056 w->total_cols = make_number (size);
3057 adjust_window_margins (w);
3059 else
3061 sideward = &w->hchild;
3062 forward = &w->vchild;
3063 w->total_lines = make_number (size);
3064 w->orig_total_lines = Qnil;
3067 if (!NILP (*sideward))
3069 /* We have a chain of parallel siblings whose size should all change. */
3070 for (child = *sideward; !NILP (child); child = c->next)
3072 c = XWINDOW (child);
3073 if (width_p)
3074 c->left_col = w->left_col;
3075 else
3076 c->top_line = w->top_line;
3077 size_window (child, size, width_p, nodelete_p,
3078 first_only, last_only);
3081 else if (!NILP (*forward) && last_only)
3083 /* Change the last in a series of siblings. */
3084 Lisp_Object last_child;
3085 int child_size;
3087 for (child = *forward; !NILP (child); child = c->next)
3089 c = XWINDOW (child);
3090 last_child = child;
3093 child_size = XINT (width_p ? c->total_cols : c->total_lines);
3094 size_window (last_child,
3095 size - old_size + child_size,
3096 width_p, nodelete_p, first_only, last_only);
3098 else if (!NILP (*forward) && first_only)
3100 /* Change the first in a series of siblings. */
3101 int child_size;
3103 child = *forward;
3104 c = XWINDOW (child);
3106 if (width_p)
3107 c->left_col = w->left_col;
3108 else
3109 c->top_line = w->top_line;
3111 child_size = XINT (width_p ? c->total_cols : c->total_lines);
3112 size_window (child,
3113 size - old_size + child_size,
3114 width_p, nodelete_p, first_only, last_only);
3116 else if (!NILP (*forward))
3118 int fixed_size, each, extra, n;
3119 int resize_fixed_p, nfixed;
3120 int last_pos, first_pos, nchildren, total;
3121 int *new_sizes = NULL;
3123 /* Determine the fixed-size portion of this window, and the
3124 number of child windows. */
3125 fixed_size = nchildren = nfixed = total = 0;
3126 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
3128 int child_size;
3130 c = XWINDOW (child);
3131 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
3132 total += child_size;
3134 if (window_fixed_size_p (c, width_p, 0))
3136 fixed_size += child_size;
3137 ++nfixed;
3141 /* If the new size is smaller than fixed_size, or if there
3142 aren't any resizable windows, allow resizing fixed-size
3143 windows. */
3144 resize_fixed_p = nfixed == nchildren || size < fixed_size;
3146 /* Compute how many lines/columns to add/remove to each child. The
3147 value of extra takes care of rounding errors. */
3148 n = resize_fixed_p ? nchildren : nchildren - nfixed;
3149 if (size < total && n > 1)
3150 new_sizes = shrink_windows (total, size, nchildren, n, min_size,
3151 resize_fixed_p, *forward, width_p);
3152 else
3154 each = (size - total) / n;
3155 extra = (size - total) - n * each;
3158 /* Compute new children heights and edge positions. */
3159 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
3160 last_pos = first_pos;
3161 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
3163 int new_size, old_size;
3165 c = XWINDOW (child);
3166 old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines);
3167 new_size = old_size;
3169 /* The top or left edge position of this child equals the
3170 bottom or right edge of its predecessor. */
3171 if (width_p)
3172 c->left_col = make_number (last_pos);
3173 else
3174 c->top_line = make_number (last_pos);
3176 /* If this child can be resized, do it. */
3177 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
3179 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
3180 extra = 0;
3183 /* Set new height. Note that size_window also propagates
3184 edge positions to children, so it's not a no-op if we
3185 didn't change the child's size. */
3186 size_window (child, new_size, width_p, 1, first_only, last_only);
3188 /* Remember the bottom/right edge position of this child; it
3189 will be used to set the top/left edge of the next child. */
3190 last_pos += new_size;
3193 if (new_sizes) xfree (new_sizes);
3195 /* We should have covered the parent exactly with child windows. */
3196 xassert (size == last_pos - first_pos);
3198 /* Now delete any children that became too small. */
3199 if (!nodelete_p)
3200 for (child = *forward; !NILP (child); child = c->next)
3202 int child_size;
3203 c = XWINDOW (child);
3204 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
3205 size_window (child, child_size, width_p, 2, first_only, last_only);
3210 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3211 WINDOW's children. NODELETE non-zero means don't delete windows
3212 that become too small in the process. (The caller should check
3213 later and do so if appropriate.) */
3215 void
3216 set_window_height (window, height, nodelete)
3217 Lisp_Object window;
3218 int height;
3219 int nodelete;
3221 size_window (window, height, 0, nodelete, 0, 0);
3225 /* Set WINDOW's width to WIDTH, and recursively change the width of
3226 WINDOW's children. NODELETE non-zero means don't delete windows
3227 that become too small in the process. (The caller should check
3228 later and do so if appropriate.) */
3230 void
3231 set_window_width (window, width, nodelete)
3232 Lisp_Object window;
3233 int width;
3234 int nodelete;
3236 size_window (window, width, 1, nodelete, 0, 0);
3239 /* Change window heights in windows rooted in WINDOW by N lines. */
3241 void
3242 change_window_heights (window, n)
3243 Lisp_Object window;
3244 int n;
3246 struct window *w = XWINDOW (window);
3248 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
3249 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
3251 if (INTEGERP (w->orig_top_line))
3252 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
3253 if (INTEGERP (w->orig_total_lines))
3254 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
3256 /* Handle just the top child in a vertical split. */
3257 if (!NILP (w->vchild))
3258 change_window_heights (w->vchild, n);
3260 /* Adjust all children in a horizontal split. */
3261 for (window = w->hchild; !NILP (window); window = w->next)
3263 w = XWINDOW (window);
3264 change_window_heights (window, n);
3269 int window_select_count;
3271 Lisp_Object
3272 Fset_window_buffer_unwind (obuf)
3273 Lisp_Object obuf;
3275 Fset_buffer (obuf);
3276 return Qnil;
3279 EXFUN (Fset_window_fringes, 4);
3280 EXFUN (Fset_window_scroll_bars, 4);
3282 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3283 means it's allowed to run hooks. See make_frame for a case where
3284 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3285 margins, fringes, and scroll-bar settings of the window are not
3286 reset from the buffer's local settings. */
3288 void
3289 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
3290 Lisp_Object window, buffer;
3291 int run_hooks_p, keep_margins_p;
3293 struct window *w = XWINDOW (window);
3294 struct buffer *b = XBUFFER (buffer);
3295 int count = SPECPDL_INDEX ();
3297 w->buffer = buffer;
3299 if (EQ (window, selected_window))
3300 b->last_selected_window = window;
3302 /* Let redisplay errors through. */
3303 b->display_error_modiff = 0;
3305 /* Update time stamps of buffer display. */
3306 if (INTEGERP (b->display_count))
3307 XSETINT (b->display_count, XINT (b->display_count) + 1);
3308 b->display_time = Fcurrent_time ();
3310 XSETFASTINT (w->window_end_pos, 0);
3311 XSETFASTINT (w->window_end_vpos, 0);
3312 bzero (&w->last_cursor, sizeof w->last_cursor);
3313 w->window_end_valid = Qnil;
3314 w->hscroll = w->min_hscroll = make_number (0);
3315 w->vscroll = 0;
3316 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3317 set_marker_restricted (w->start,
3318 make_number (b->last_window_start),
3319 buffer);
3320 w->start_at_line_beg = Qnil;
3321 w->force_start = Qnil;
3322 XSETFASTINT (w->last_modified, 0);
3323 XSETFASTINT (w->last_overlay_modified, 0);
3324 windows_or_buffers_changed++;
3326 /* We must select BUFFER for running the window-scroll-functions.
3327 If WINDOW is selected, switch permanently.
3328 Otherwise, switch but go back to the ambient buffer afterward. */
3329 if (EQ (window, selected_window))
3330 Fset_buffer (buffer);
3331 /* We can't check ! NILP (Vwindow_scroll_functions) here
3332 because that might itself be a local variable. */
3333 else if (window_initialized)
3335 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
3336 Fset_buffer (buffer);
3339 if (!keep_margins_p)
3341 /* Set left and right marginal area width etc. from buffer. */
3343 /* This may call adjust_window_margins three times, so
3344 temporarily disable window margins. */
3345 Lisp_Object save_left = w->left_margin_cols;
3346 Lisp_Object save_right = w->right_margin_cols;
3348 w->left_margin_cols = w->right_margin_cols = Qnil;
3350 Fset_window_fringes (window,
3351 b->left_fringe_width, b->right_fringe_width,
3352 b->fringes_outside_margins);
3354 Fset_window_scroll_bars (window,
3355 b->scroll_bar_width,
3356 b->vertical_scroll_bar_type, Qnil);
3358 w->left_margin_cols = save_left;
3359 w->right_margin_cols = save_right;
3361 Fset_window_margins (window,
3362 b->left_margin_cols, b->right_margin_cols);
3365 if (run_hooks_p)
3367 if (! NILP (Vwindow_scroll_functions))
3368 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3369 Fmarker_position (w->start));
3371 if (! NILP (Vwindow_configuration_change_hook)
3372 && ! NILP (Vrun_hooks))
3373 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3376 unbind_to (count, Qnil);
3380 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3381 doc: /* Make WINDOW display BUFFER as its contents.
3382 BUFFER can be a buffer or the name of an existing buffer.
3383 Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
3384 display margins, fringe widths, and scroll bar settings are maintained;
3385 the default is to reset these from BUFFER's local settings or the frame
3386 defaults.
3388 This function runs the hook `window-scroll-functions'. */)
3389 (window, buffer, keep_margins)
3390 register Lisp_Object window, buffer, keep_margins;
3392 register Lisp_Object tem;
3393 register struct window *w = decode_window (window);
3395 XSETWINDOW (window, w);
3396 buffer = Fget_buffer (buffer);
3397 CHECK_BUFFER (buffer);
3399 if (NILP (XBUFFER (buffer)->name))
3400 error ("Attempt to display deleted buffer");
3402 tem = w->buffer;
3403 if (NILP (tem))
3404 error ("Window is deleted");
3405 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3406 is first being set up. */
3408 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3409 error ("Window is dedicated to `%s'",
3410 SDATA (XBUFFER (tem)->name));
3412 unshow_buffer (w);
3415 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3416 return Qnil;
3419 /* Note that selected_window can be nil
3420 when this is called from Fset_window_configuration. */
3422 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3423 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3424 If WINDOW is not already selected, make WINDOW's buffer current
3425 and make WINDOW the frame's selected window. Return WINDOW.
3426 Optional second arg NORECORD non-nil means
3427 do not put this buffer at the front of the list of recently selected ones.
3429 Note that the main editor command loop
3430 selects the buffer of the selected window before each command. */)
3431 (window, norecord)
3432 register Lisp_Object window, norecord;
3434 register struct window *w;
3435 register struct window *ow;
3436 struct frame *sf;
3438 CHECK_LIVE_WINDOW (window);
3440 w = XWINDOW (window);
3441 w->frozen_window_start_p = 0;
3443 ++window_select_count;
3444 XSETFASTINT (w->use_time, window_select_count);
3445 if (EQ (window, selected_window))
3446 return window;
3448 /* Store the current buffer's actual point into the
3449 old selected window. It belongs to that window,
3450 and when the window is not selected, must be in the window. */
3451 if (!NILP (selected_window))
3453 ow = XWINDOW (selected_window);
3454 if (! NILP (ow->buffer))
3455 set_marker_both (ow->pointm, ow->buffer,
3456 BUF_PT (XBUFFER (ow->buffer)),
3457 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3460 selected_window = window;
3461 sf = SELECTED_FRAME ();
3462 if (XFRAME (WINDOW_FRAME (w)) != sf)
3464 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3465 /* Use this rather than Fhandle_switch_frame
3466 so that FRAME_FOCUS_FRAME is moved appropriately as we
3467 move around in the state where a minibuffer in a separate
3468 frame is active. */
3469 Fselect_frame (WINDOW_FRAME (w));
3471 else
3472 sf->selected_window = window;
3474 if (NILP (norecord))
3475 record_buffer (w->buffer);
3476 Fset_buffer (w->buffer);
3478 XBUFFER (w->buffer)->last_selected_window = window;
3480 /* Go to the point recorded in the window.
3481 This is important when the buffer is in more
3482 than one window. It also matters when
3483 redisplay_window has altered point after scrolling,
3484 because it makes the change only in the window. */
3486 register int new_point = marker_position (w->pointm);
3487 if (new_point < BEGV)
3488 SET_PT (BEGV);
3489 else if (new_point > ZV)
3490 SET_PT (ZV);
3491 else
3492 SET_PT (new_point);
3495 windows_or_buffers_changed++;
3496 return window;
3499 static Lisp_Object
3500 select_window_norecord (window)
3501 Lisp_Object window;
3503 return Fselect_window (window, Qt);
3506 /* Deiconify the frame containing the window WINDOW,
3507 unless it is the selected frame;
3508 then return WINDOW.
3510 The reason for the exception for the selected frame
3511 is that it seems better not to change the selected frames visibility
3512 merely because of displaying a different buffer in it.
3513 The deiconification is useful when a buffer gets shown in
3514 another frame that you were not using lately. */
3516 static Lisp_Object
3517 display_buffer_1 (window)
3518 Lisp_Object window;
3520 Lisp_Object frame = XWINDOW (window)->frame;
3521 FRAME_PTR f = XFRAME (frame);
3523 FRAME_SAMPLE_VISIBILITY (f);
3525 if (EQ (frame, selected_frame))
3526 ; /* Assume the selected frame is already visible enough. */
3527 else if (minibuf_level > 0
3528 && MINI_WINDOW_P (XWINDOW (selected_window))
3529 && WINDOW_LIVE_P (minibuf_selected_window)
3530 && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
3531 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3532 else
3534 if (FRAME_ICONIFIED_P (f))
3535 Fmake_frame_visible (frame);
3536 else if (FRAME_VISIBLE_P (f))
3537 Fraise_frame (frame);
3540 return window;
3543 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
3544 doc: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
3545 If the value is t, `display-buffer' or `pop-to-buffer' would create a
3546 special frame for that buffer using the default frame parameters.
3548 If the value is a list, it is a list of frame parameters that would be used
3549 to make a frame for that buffer.
3550 The variables `special-display-buffer-names'
3551 and `special-display-regexps' control this. */)
3552 (buffer_name)
3553 Lisp_Object buffer_name;
3555 Lisp_Object tem;
3557 CHECK_STRING (buffer_name);
3559 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
3560 if (!NILP (tem))
3561 return Qt;
3563 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
3564 if (!NILP (tem))
3565 return XCDR (tem);
3567 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
3569 Lisp_Object car = XCAR (tem);
3570 if (STRINGP (car)
3571 && fast_string_match (car, buffer_name) >= 0)
3572 return Qt;
3573 else if (CONSP (car)
3574 && STRINGP (XCAR (car))
3575 && fast_string_match (XCAR (car), buffer_name) >= 0)
3576 return XCDR (car);
3578 return Qnil;
3581 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
3582 doc: /* Returns non-nil if a buffer named BUFFER-NAME would use the same window.
3583 More precisely, if `display-buffer' or `pop-to-buffer' would display
3584 that buffer in the selected window rather than (as usual) in some other window.
3585 See `same-window-buffer-names' and `same-window-regexps'. */)
3586 (buffer_name)
3587 Lisp_Object buffer_name;
3589 Lisp_Object tem;
3591 CHECK_STRING (buffer_name);
3593 tem = Fmember (buffer_name, Vsame_window_buffer_names);
3594 if (!NILP (tem))
3595 return Qt;
3597 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
3598 if (!NILP (tem))
3599 return Qt;
3601 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3603 Lisp_Object car = XCAR (tem);
3604 if (STRINGP (car)
3605 && fast_string_match (car, buffer_name) >= 0)
3606 return Qt;
3607 else if (CONSP (car)
3608 && STRINGP (XCAR (car))
3609 && fast_string_match (XCAR (car), buffer_name) >= 0)
3610 return Qt;
3612 return Qnil;
3615 /* Use B so the default is (other-buffer). */
3616 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
3617 "BDisplay buffer: \nP",
3618 doc: /* Make BUFFER appear in some window but don't select it.
3619 BUFFER must be the name of an existing buffer, or, when called from Lisp,
3620 a buffer.
3621 If BUFFER is shown already in some window, just use that one,
3622 unless the window is the selected window and the optional second
3623 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3624 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3625 Returns the window displaying BUFFER.
3626 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3627 displaying BUFFER, then simply raise that frame.
3629 The variables `special-display-buffer-names',
3630 `special-display-regexps', `same-window-buffer-names', and
3631 `same-window-regexps' customize how certain buffer names are handled.
3632 The latter two take effect only if NOT-THIS-WINDOW is nil.
3634 If optional argument FRAME is `visible', check all visible frames
3635 for a window to use.
3636 If FRAME is 0, check all visible and iconified frames.
3637 If FRAME is t, check all frames.
3638 If FRAME is a frame, check only that frame.
3639 If FRAME is nil, check only the selected frame
3640 (actually the last nonminibuffer frame),
3641 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3642 which means search visible and iconified frames.
3644 If a full-width window on a splittable frame is available to display
3645 the buffer, it may be split, subject to the value of the variable
3646 `split-height-threshold'.
3648 If `even-window-heights' is non-nil, window heights will be evened out
3649 if displaying the buffer causes two vertically adjacent windows to be
3650 displayed. */)
3651 (buffer, not_this_window, frame)
3652 register Lisp_Object buffer, not_this_window, frame;
3654 register Lisp_Object window, tem, swp;
3655 struct frame *f;
3657 swp = Qnil;
3658 buffer = Fget_buffer (buffer);
3659 CHECK_BUFFER (buffer);
3661 if (!NILP (Vdisplay_buffer_function))
3662 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3664 if (NILP (not_this_window)
3665 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3666 return display_buffer_1 (selected_window);
3668 /* See if the user has specified this buffer should appear
3669 in the selected window. */
3670 if (NILP (not_this_window))
3672 swp = Fsame_window_p (XBUFFER (buffer)->name);
3673 if (!NILP (swp) && !no_switch_window (selected_window))
3675 Fswitch_to_buffer (buffer, Qnil);
3676 return display_buffer_1 (selected_window);
3680 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3681 look for a window showing BUFFER on any visible or iconified frame.
3682 Otherwise search only the current frame. */
3683 if (! NILP (frame))
3684 tem = frame;
3685 else if (pop_up_frames
3686 || display_buffer_reuse_frames
3687 || last_nonminibuf_frame == 0)
3688 XSETFASTINT (tem, 0);
3689 else
3690 XSETFRAME (tem, last_nonminibuf_frame);
3692 window = Fget_buffer_window (buffer, tem);
3693 if (!NILP (window)
3694 && (NILP (not_this_window) || !EQ (window, selected_window)))
3695 return display_buffer_1 (window);
3697 /* Certain buffer names get special handling. */
3698 if (!NILP (Vspecial_display_function) && NILP (swp))
3700 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3701 if (EQ (tem, Qt))
3702 return call1 (Vspecial_display_function, buffer);
3703 if (CONSP (tem))
3704 return call2 (Vspecial_display_function, buffer, tem);
3707 /* If there are no frames open that have more than a minibuffer,
3708 we need to create a new frame. */
3709 if (pop_up_frames || last_nonminibuf_frame == 0)
3711 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3712 Fset_window_buffer (window, buffer, Qnil);
3713 return display_buffer_1 (window);
3716 f = SELECTED_FRAME ();
3717 if (pop_up_windows
3718 || FRAME_MINIBUF_ONLY_P (f)
3719 /* If the current frame is a special display frame,
3720 don't try to reuse its windows. */
3721 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3723 Lisp_Object frames;
3725 frames = Qnil;
3726 if (FRAME_MINIBUF_ONLY_P (f))
3727 XSETFRAME (frames, last_nonminibuf_frame);
3729 /* Note that both Fget_largest_window and Fget_lru_window
3730 ignore minibuffers and dedicated windows.
3731 This means they can return nil. */
3733 /* If the frame we would try to split cannot be split,
3734 try other frames. */
3735 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3737 /* Try visible frames first. */
3738 window = Fget_largest_window (Qvisible, Qt);
3739 /* If that didn't work, try iconified frames. */
3740 if (NILP (window))
3741 window = Fget_largest_window (make_number (0), Qt);
3742 #if 0 /* Don't try windows on other displays. */
3743 if (NILP (window))
3744 window = Fget_largest_window (Qt, Qt);
3745 #endif
3747 else
3748 window = Fget_largest_window (frames, Qt);
3750 /* If the largest window is tall enough, full-width, and either eligible
3751 for splitting or the only window, split it. */
3752 if (!NILP (window)
3753 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3754 && WINDOW_FULL_WIDTH_P (XWINDOW (window))
3755 && (window_height (window) >= split_height_threshold
3756 || (NILP (XWINDOW (window)->parent)))
3757 && (window_height (window)
3758 >= (2 * window_min_size_2 (XWINDOW (window), 0))))
3759 window = Fsplit_window (window, Qnil, Qnil);
3760 else
3762 Lisp_Object upper, lower, other;
3764 window = Fget_lru_window (frames, Qt);
3765 /* If the LRU window is tall enough, and either eligible for splitting
3766 and selected or the only window, split it. */
3767 if (!NILP (window)
3768 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3769 && ((EQ (window, selected_window)
3770 && window_height (window) >= split_height_threshold)
3771 || (NILP (XWINDOW (window)->parent)))
3772 && (window_height (window)
3773 >= (2 * window_min_size_2 (XWINDOW (window), 0))))
3774 window = Fsplit_window (window, Qnil, Qnil);
3775 else
3776 window = Fget_lru_window (frames, Qnil);
3777 /* If Fget_lru_window returned nil, try other approaches. */
3779 /* Try visible frames first. */
3780 if (NILP (window))
3781 window = Fget_buffer_window (buffer, Qvisible);
3782 if (NILP (window))
3783 window = Fget_largest_window (Qvisible, Qnil);
3784 /* If that didn't work, try iconified frames. */
3785 if (NILP (window))
3786 window = Fget_buffer_window (buffer, make_number (0));
3787 if (NILP (window))
3788 window = Fget_largest_window (make_number (0), Qnil);
3790 #if 0 /* Don't try frames on other displays. */
3791 if (NILP (window))
3792 window = Fget_buffer_window (buffer, Qt);
3793 if (NILP (window))
3794 window = Fget_largest_window (Qt, Qnil);
3795 #endif
3796 /* As a last resort, make a new frame. */
3797 if (NILP (window))
3798 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3799 /* If window appears above or below another,
3800 even out their heights. */
3801 other = upper = lower = Qnil;
3802 if (!NILP (XWINDOW (window)->prev))
3803 other = upper = XWINDOW (window)->prev, lower = window;
3804 if (!NILP (XWINDOW (window)->next))
3805 other = lower = XWINDOW (window)->next, upper = window;
3806 if (!NILP (other)
3807 && !NILP (Veven_window_heights)
3808 /* Check that OTHER and WINDOW are vertically arrayed. */
3809 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3810 && (XFASTINT (XWINDOW (other)->total_lines)
3811 > XFASTINT (XWINDOW (window)->total_lines)))
3813 int total = (XFASTINT (XWINDOW (other)->total_lines)
3814 + XFASTINT (XWINDOW (window)->total_lines));
3815 enlarge_window (upper,
3816 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
3821 else
3822 window = Fget_lru_window (Qnil, Qnil);
3824 Fset_window_buffer (window, buffer, Qnil);
3825 return display_buffer_1 (window);
3829 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3830 0, 1, 0,
3831 doc: /* Force all windows to be updated on next redisplay.
3832 If optional arg OBJECT is a window, force redisplay of that window only.
3833 If OBJECT is a buffer or buffer name, force redisplay of all windows
3834 displaying that buffer. */)
3835 (object)
3836 Lisp_Object object;
3838 if (NILP (object))
3840 windows_or_buffers_changed++;
3841 update_mode_lines++;
3842 return Qt;
3845 if (WINDOWP (object))
3847 struct window *w = XWINDOW (object);
3848 mark_window_display_accurate (object, 0);
3849 w->update_mode_line = Qt;
3850 if (BUFFERP (w->buffer))
3851 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3852 ++update_mode_lines;
3853 return Qt;
3856 if (STRINGP (object))
3857 object = Fget_buffer (object);
3858 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3860 /* Walk all windows looking for buffer, and force update
3861 of each of those windows. */
3863 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3864 return NILP (object) ? Qnil : Qt;
3867 /* If nothing suitable was found, just return.
3868 We could signal an error, but this feature will typically be used
3869 asynchronously in timers or process sentinels, so we don't. */
3870 return Qnil;
3874 void
3875 temp_output_buffer_show (buf)
3876 register Lisp_Object buf;
3878 register struct buffer *old = current_buffer;
3879 register Lisp_Object window;
3880 register struct window *w;
3882 XBUFFER (buf)->directory = current_buffer->directory;
3884 Fset_buffer (buf);
3885 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3886 BEGV = BEG;
3887 ZV = Z;
3888 SET_PT (BEG);
3889 #if 0 /* rms: there should be no reason for this. */
3890 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3891 #endif
3892 set_buffer_internal (old);
3894 if (!NILP (Vtemp_buffer_show_function))
3895 call1 (Vtemp_buffer_show_function, buf);
3896 else
3898 window = Fdisplay_buffer (buf, Qnil, Qnil);
3900 if (!EQ (XWINDOW (window)->frame, selected_frame))
3901 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3902 Vminibuf_scroll_window = window;
3903 w = XWINDOW (window);
3904 XSETFASTINT (w->hscroll, 0);
3905 XSETFASTINT (w->min_hscroll, 0);
3906 set_marker_restricted_both (w->start, buf, BEG, BEG);
3907 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3909 /* Run temp-buffer-show-hook, with the chosen window selected
3910 and its buffer current. */
3912 if (!NILP (Vrun_hooks)
3913 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3914 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3916 int count = SPECPDL_INDEX ();
3917 Lisp_Object prev_window, prev_buffer;
3918 prev_window = selected_window;
3919 XSETBUFFER (prev_buffer, old);
3921 /* Select the window that was chosen, for running the hook.
3922 Note: Both Fselect_window and select_window_norecord may
3923 set-buffer to the buffer displayed in the window,
3924 so we need to save the current buffer. --stef */
3925 record_unwind_protect (Fset_buffer, prev_buffer);
3926 record_unwind_protect (select_window_norecord, prev_window);
3927 Fselect_window (window, Qt);
3928 Fset_buffer (w->buffer);
3929 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3930 unbind_to (count, Qnil);
3935 static void
3936 make_dummy_parent (window)
3937 Lisp_Object window;
3939 Lisp_Object new;
3940 register struct window *o, *p;
3941 int i;
3943 o = XWINDOW (window);
3944 p = allocate_window ();
3945 for (i = 0; i < VECSIZE (struct window); ++i)
3946 ((struct Lisp_Vector *) p)->contents[i]
3947 = ((struct Lisp_Vector *)o)->contents[i];
3948 XSETWINDOW (new, p);
3950 ++sequence_number;
3951 XSETFASTINT (p->sequence_number, sequence_number);
3953 /* Put new into window structure in place of window */
3954 replace_window (window, new);
3956 o->next = Qnil;
3957 o->prev = Qnil;
3958 o->vchild = Qnil;
3959 o->hchild = Qnil;
3960 o->parent = new;
3962 p->start = Qnil;
3963 p->pointm = Qnil;
3964 p->buffer = Qnil;
3967 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3968 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3969 WINDOW defaults to selected one and SIZE to half its size.
3970 If optional third arg HORFLAG is non-nil, split side by side
3971 and put SIZE columns in the first of the pair. In that case,
3972 SIZE includes that window's scroll bar, or the divider column to its right.
3973 Interactively, all arguments are nil.
3975 Returns the newly created window (which is the lower or rightmost one).
3976 The upper or leftmost window is the original one, and remains selected
3977 if it was selected before.
3979 See Info node `(elisp)Splitting Windows' for more details and examples.*/)
3980 (window, size, horflag)
3981 Lisp_Object window, size, horflag;
3983 register Lisp_Object new;
3984 register struct window *o, *p;
3985 FRAME_PTR fo;
3986 register int size_int;
3988 if (NILP (window))
3989 window = selected_window;
3990 else
3991 CHECK_LIVE_WINDOW (window);
3993 o = XWINDOW (window);
3994 fo = XFRAME (WINDOW_FRAME (o));
3996 if (NILP (size))
3998 if (!NILP (horflag))
3999 /* Calculate the size of the left-hand window, by dividing
4000 the usable space in columns by two.
4001 We round up, since the left-hand window may include
4002 a dividing line, while the right-hand may not. */
4003 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
4004 else
4005 size_int = XFASTINT (o->total_lines) >> 1;
4007 else
4009 CHECK_NUMBER (size);
4010 size_int = XINT (size);
4013 if (MINI_WINDOW_P (o))
4014 error ("Attempt to split minibuffer window");
4015 else if (window_fixed_size_p (o, !NILP (horflag), 0))
4016 error ("Attempt to split fixed-size window");
4018 check_min_window_sizes ();
4020 if (NILP (horflag))
4022 int window_safe_height = window_min_size_2 (o, 0);
4024 if (size_int < window_safe_height)
4025 error ("Window height %d too small (after splitting)", size_int);
4026 if (size_int + window_safe_height > XFASTINT (o->total_lines))
4027 error ("Window height %d too small (after splitting)",
4028 XFASTINT (o->total_lines) - size_int);
4029 if (NILP (o->parent)
4030 || NILP (XWINDOW (o->parent)->vchild))
4032 make_dummy_parent (window);
4033 new = o->parent;
4034 XWINDOW (new)->vchild = window;
4037 else
4039 int window_safe_width = window_min_size_2 (o, 1);
4041 if (size_int < window_safe_width)
4042 error ("Window width %d too small (after splitting)", size_int);
4043 if (size_int + window_safe_width > XFASTINT (o->total_cols))
4044 error ("Window width %d too small (after splitting)",
4045 XFASTINT (o->total_cols) - size_int);
4046 if (NILP (o->parent)
4047 || NILP (XWINDOW (o->parent)->hchild))
4049 make_dummy_parent (window);
4050 new = o->parent;
4051 XWINDOW (new)->hchild = window;
4055 /* Now we know that window's parent is a vertical combination
4056 if we are dividing vertically, or a horizontal combination
4057 if we are making side-by-side windows */
4059 windows_or_buffers_changed++;
4060 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
4061 new = make_window ();
4062 p = XWINDOW (new);
4064 p->frame = o->frame;
4065 p->next = o->next;
4066 if (!NILP (p->next))
4067 XWINDOW (p->next)->prev = new;
4068 p->prev = window;
4069 o->next = new;
4070 p->parent = o->parent;
4071 p->buffer = Qt;
4072 p->window_end_valid = Qnil;
4073 bzero (&p->last_cursor, sizeof p->last_cursor);
4075 /* Duplicate special geometry settings. */
4077 p->left_margin_cols = o->left_margin_cols;
4078 p->right_margin_cols = o->right_margin_cols;
4079 p->left_fringe_width = o->left_fringe_width;
4080 p->right_fringe_width = o->right_fringe_width;
4081 p->fringes_outside_margins = o->fringes_outside_margins;
4082 p->scroll_bar_width = o->scroll_bar_width;
4083 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
4085 /* Apportion the available frame space among the two new windows */
4087 if (!NILP (horflag))
4089 p->total_lines = o->total_lines;
4090 p->top_line = o->top_line;
4091 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
4092 XSETFASTINT (o->total_cols, size_int);
4093 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
4094 adjust_window_margins (p);
4095 adjust_window_margins (o);
4097 else
4099 p->left_col = o->left_col;
4100 p->total_cols = o->total_cols;
4101 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
4102 XSETFASTINT (o->total_lines, size_int);
4103 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
4106 /* Adjust glyph matrices. */
4107 adjust_glyphs (fo);
4109 Fset_window_buffer (new, o->buffer, Qt);
4110 return new;
4113 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
4114 doc: /* Make current window ARG lines bigger.
4115 From program, optional second arg non-nil means grow sideways ARG columns.
4116 Interactively, if an argument is not given, make the window one line bigger.
4117 If HORIZONTAL is non-nil, enlarge horizontally instead of vertically.
4118 This function can delete windows, even the second window, if they get
4119 too small. */)
4120 (arg, horizontal)
4121 Lisp_Object arg, horizontal;
4123 CHECK_NUMBER (arg);
4124 enlarge_window (selected_window, XINT (arg), !NILP (horizontal));
4126 if (! NILP (Vwindow_configuration_change_hook))
4127 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4129 return Qnil;
4132 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
4133 doc: /* Make current window ARG lines smaller.
4134 From program, optional second arg non-nil means shrink sideways arg columns.
4135 Interactively, if an argument is not given, make the window one line smaller.
4136 Only siblings to the right or below are changed. */)
4137 (arg, side)
4138 Lisp_Object arg, side;
4140 CHECK_NUMBER (arg);
4141 enlarge_window (selected_window, -XINT (arg), !NILP (side));
4143 if (! NILP (Vwindow_configuration_change_hook))
4144 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4146 return Qnil;
4150 window_height (window)
4151 Lisp_Object window;
4153 register struct window *p = XWINDOW (window);
4154 return WINDOW_TOTAL_LINES (p);
4158 window_width (window)
4159 Lisp_Object window;
4161 register struct window *p = XWINDOW (window);
4162 return WINDOW_TOTAL_COLS (p);
4166 #define CURBEG(w) \
4167 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
4169 #define CURSIZE(w) \
4170 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
4173 /* Enlarge WINDOW by DELTA.
4174 HORIZ_FLAG nonzero means enlarge it horizontally;
4175 zero means do it vertically.
4177 Siblings of the selected window are resized to fulfill the size
4178 request. If they become too small in the process, they will be
4179 deleted. */
4181 static void
4182 enlarge_window (window, delta, horiz_flag)
4183 Lisp_Object window;
4184 int delta, horiz_flag;
4186 Lisp_Object parent, next, prev;
4187 struct window *p;
4188 Lisp_Object *sizep;
4189 int maximum;
4190 int (*sizefun) P_ ((Lisp_Object))
4191 = horiz_flag ? window_width : window_height;
4192 void (*setsizefun) P_ ((Lisp_Object, int, int))
4193 = (horiz_flag ? set_window_width : set_window_height);
4195 /* Check values of window_min_width and window_min_height for
4196 validity. */
4197 check_min_window_sizes ();
4199 /* Give up if this window cannot be resized. */
4200 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4201 error ("Window is not resizable");
4203 /* Find the parent of the selected window. */
4204 while (1)
4206 p = XWINDOW (window);
4207 parent = p->parent;
4209 if (NILP (parent))
4211 if (horiz_flag)
4212 error ("No other window to side of this one");
4213 break;
4216 if (horiz_flag
4217 ? !NILP (XWINDOW (parent)->hchild)
4218 : !NILP (XWINDOW (parent)->vchild))
4219 break;
4221 window = parent;
4224 sizep = &CURSIZE (window);
4227 register int maxdelta;
4229 /* Compute the maximum size increment this window can have. */
4231 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
4232 /* This is a main window followed by a minibuffer. */
4233 : !NILP (p->next) ? ((*sizefun) (p->next)
4234 - window_min_size (XWINDOW (p->next),
4235 horiz_flag, 0, 0))
4236 /* This is a minibuffer following a main window. */
4237 : !NILP (p->prev) ? ((*sizefun) (p->prev)
4238 - window_min_size (XWINDOW (p->prev),
4239 horiz_flag, 0, 0))
4240 /* This is a frame with only one window, a minibuffer-only
4241 or a minibufferless frame. */
4242 : (delta = 0));
4244 if (delta > maxdelta)
4245 /* This case traps trying to make the minibuffer
4246 the full frame, or make the only window aside from the
4247 minibuffer the full frame. */
4248 delta = maxdelta;
4251 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), horiz_flag, 0, 0))
4253 delete_window (window);
4254 return;
4257 if (delta == 0)
4258 return;
4260 /* Find the total we can get from other siblings without deleting them. */
4261 maximum = 0;
4262 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
4263 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
4264 horiz_flag, 0, 0);
4265 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
4266 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
4267 horiz_flag, 0, 0);
4269 /* If we can get it all from them without deleting them, do so. */
4270 if (delta <= maximum)
4272 Lisp_Object first_unaffected;
4273 Lisp_Object first_affected;
4274 int fixed_p;
4276 next = p->next;
4277 prev = p->prev;
4278 first_affected = window;
4279 /* Look at one sibling at a time,
4280 moving away from this window in both directions alternately,
4281 and take as much as we can get without deleting that sibling. */
4282 while (delta != 0
4283 && (!NILP (next) || !NILP (prev)))
4285 if (! NILP (next))
4287 int this_one = ((*sizefun) (next)
4288 - window_min_size (XWINDOW (next),
4289 horiz_flag, 0, &fixed_p));
4290 if (!fixed_p)
4292 if (this_one > delta)
4293 this_one = delta;
4295 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
4296 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4298 delta -= this_one;
4301 next = XWINDOW (next)->next;
4304 if (delta == 0)
4305 break;
4307 if (! NILP (prev))
4309 int this_one = ((*sizefun) (prev)
4310 - window_min_size (XWINDOW (prev),
4311 horiz_flag, 0, &fixed_p));
4312 if (!fixed_p)
4314 if (this_one > delta)
4315 this_one = delta;
4317 first_affected = prev;
4319 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
4320 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4322 delta -= this_one;
4325 prev = XWINDOW (prev)->prev;
4329 xassert (delta == 0);
4331 /* Now recalculate the edge positions of all the windows affected,
4332 based on the new sizes. */
4333 first_unaffected = next;
4334 prev = first_affected;
4335 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4336 prev = next, next = XWINDOW (next)->next)
4338 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4339 /* This does not change size of NEXT,
4340 but it propagates the new top edge to its children */
4341 (*setsizefun) (next, (*sizefun) (next), 0);
4344 else
4346 register int delta1;
4347 register int opht = (*sizefun) (parent);
4349 if (opht <= XINT (*sizep) + delta)
4351 /* If trying to grow this window to or beyond size of the parent,
4352 just delete all the sibling windows. */
4353 Lisp_Object start, tem, next;
4355 start = XWINDOW (parent)->vchild;
4356 if (NILP (start))
4357 start = XWINDOW (parent)->hchild;
4359 /* Delete any siblings that come after WINDOW. */
4360 tem = XWINDOW (window)->next;
4361 while (! NILP (tem))
4363 next = XWINDOW (tem)->next;
4364 delete_window (tem);
4365 tem = next;
4368 /* Delete any siblings that come after WINDOW.
4369 Note that if START is not WINDOW, then WINDOW still
4370 Fhas siblings, so WINDOW has not yet replaced its parent. */
4371 tem = start;
4372 while (! EQ (tem, window))
4374 next = XWINDOW (tem)->next;
4375 delete_window (tem);
4376 tem = next;
4379 else
4381 /* Otherwise, make delta1 just right so that if we add
4382 delta1 lines to this window and to the parent, and then
4383 shrink the parent back to its original size, the new
4384 proportional size of this window will increase by delta.
4386 The function size_window will compute the new height h'
4387 of the window from delta1 as:
4389 e = delta1/n
4390 x = delta1 - delta1/n * n for the 1st resizable child
4391 h' = h + e + x
4393 where n is the number of children that can be resized.
4394 We can ignore x by choosing a delta1 that is a multiple of
4395 n. We want the height of this window to come out as
4397 h' = h + delta
4399 So, delta1 must be
4401 h + e = h + delta
4402 delta1/n = delta
4403 delta1 = n * delta.
4405 The number of children n equals the number of resizable
4406 children of this window + 1 because we know window itself
4407 is resizable (otherwise we would have signalled an error). */
4409 struct window *w = XWINDOW (window);
4410 Lisp_Object s;
4411 int n = 1;
4413 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
4414 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4415 ++n;
4416 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
4417 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4418 ++n;
4420 delta1 = n * delta;
4422 /* Add delta1 lines or columns to this window, and to the parent,
4423 keeping things consistent while not affecting siblings. */
4424 XSETINT (CURSIZE (parent), opht + delta1);
4425 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4427 /* Squeeze out delta1 lines or columns from our parent,
4428 shriking this window and siblings proportionately.
4429 This brings parent back to correct size.
4430 Delta1 was calculated so this makes this window the desired size,
4431 taking it all out of the siblings. */
4432 (*setsizefun) (parent, opht, 0);
4437 XSETFASTINT (p->last_modified, 0);
4438 XSETFASTINT (p->last_overlay_modified, 0);
4440 /* Adjust glyph matrices. */
4441 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4445 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4446 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4447 zero means adjust the height, moving the bottom edge.
4449 Following siblings of the selected window are resized to fulfill
4450 the size request. If they become too small in the process, they
4451 are not deleted; instead, we signal an error. */
4453 static void
4454 adjust_window_trailing_edge (window, delta, horiz_flag)
4455 Lisp_Object window;
4456 int delta, horiz_flag;
4458 Lisp_Object parent, child;
4459 struct window *p;
4460 Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
4461 int delcount = window_deletion_count;
4463 /* Check values of window_min_width and window_min_height for
4464 validity. */
4465 check_min_window_sizes ();
4467 if (NILP (window))
4468 window = Fselected_window ();
4470 CHECK_WINDOW (window);
4472 /* Give up if this window cannot be resized. */
4473 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4474 error ("Window is not resizable");
4476 while (1)
4478 Lisp_Object first_parallel = Qnil;
4480 if (NILP (window))
4482 /* This happens if WINDOW on the previous iteration was
4483 at top level of the window tree. */
4484 Fset_window_configuration (old_config);
4485 error ("Specified window edge is fixed");
4488 p = XWINDOW (window);
4489 parent = p->parent;
4491 /* See if this level has windows in parallel in the specified
4492 direction. If so, set FIRST_PARALLEL to the first one. */
4493 if (horiz_flag)
4495 if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
4496 first_parallel = XWINDOW (parent)->vchild;
4497 else if (NILP (parent) && !NILP (p->next))
4499 /* Handle the vertical chain of main window and minibuffer
4500 which has no parent. */
4501 first_parallel = window;
4502 while (! NILP (XWINDOW (first_parallel)->prev))
4503 first_parallel = XWINDOW (first_parallel)->prev;
4506 else
4508 if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
4509 first_parallel = XWINDOW (parent)->hchild;
4512 /* If this level's succession is in the desired dimension,
4513 and this window is the last one, and there is no higher level,
4514 its trailing edge is fixed. */
4515 if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
4516 && NILP (parent))
4518 Fset_window_configuration (old_config);
4519 error ("Specified window edge is fixed");
4522 /* Don't make this window too small. */
4523 if (XINT (CURSIZE (window)) + delta
4524 < window_min_size_2 (XWINDOW (window), horiz_flag))
4526 Fset_window_configuration (old_config);
4527 error ("Cannot adjust window size as specified");
4530 /* Clear out some redisplay caches. */
4531 XSETFASTINT (p->last_modified, 0);
4532 XSETFASTINT (p->last_overlay_modified, 0);
4534 /* Adjust this window's edge. */
4535 XSETINT (CURSIZE (window),
4536 XINT (CURSIZE (window)) + delta);
4538 /* If this window has following siblings in the desired dimension,
4539 make them smaller, and exit the loop.
4541 (If we reach the top of the tree and can never do this,
4542 we will fail and report an error, above.) */
4543 if (NILP (first_parallel))
4545 if (!NILP (p->next))
4547 /* This may happen for the minibuffer. In that case
4548 the window_deletion_count check below does not work. */
4549 if (XINT (CURSIZE (p->next)) - delta <= 0)
4551 Fset_window_configuration (old_config);
4552 error ("Cannot adjust window size as specified");
4555 XSETINT (CURBEG (p->next),
4556 XINT (CURBEG (p->next)) + delta);
4557 size_window (p->next, XINT (CURSIZE (p->next)) - delta,
4558 horiz_flag, 0, 1, 0);
4559 break;
4562 else
4563 /* Here we have a chain of parallel siblings, in the other dimension.
4564 Change the size of the other siblings. */
4565 for (child = first_parallel;
4566 ! NILP (child);
4567 child = XWINDOW (child)->next)
4568 if (! EQ (child, window))
4569 size_window (child, XINT (CURSIZE (child)) + delta,
4570 horiz_flag, 0, 0, 1);
4572 window = parent;
4575 /* If we made a window so small it got deleted,
4576 we failed. Report failure. */
4577 if (delcount != window_deletion_count)
4579 Fset_window_configuration (old_config);
4580 error ("Cannot adjust window size as specified");
4583 /* Adjust glyph matrices. */
4584 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4587 #undef CURBEG
4588 #undef CURSIZE
4590 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
4591 Sadjust_window_trailing_edge, 3, 3, 0,
4592 doc: /* Adjust the bottom or right edge of WINDOW by DELTA.
4593 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4594 Otherwise, adjust the height, moving the bottom edge.
4596 Following siblings of the selected window are resized to fulfill
4597 the size request. If they become too small in the process, they
4598 are not deleted; instead, we signal an error. */)
4599 (window, delta, horizontal)
4600 Lisp_Object window, delta, horizontal;
4602 CHECK_NUMBER (delta);
4603 adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
4605 if (! NILP (Vwindow_configuration_change_hook))
4606 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4608 return Qnil;
4613 /***********************************************************************
4614 Resizing Mini-Windows
4615 ***********************************************************************/
4617 static void shrink_window_lowest_first P_ ((struct window *, int));
4619 enum save_restore_action
4621 CHECK_ORIG_SIZES,
4622 SAVE_ORIG_SIZES,
4623 RESTORE_ORIG_SIZES
4626 static int save_restore_orig_size P_ ((struct window *,
4627 enum save_restore_action));
4629 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4630 from lowest windows first. */
4632 static void
4633 shrink_window_lowest_first (w, height)
4634 struct window *w;
4635 int height;
4637 struct window *c;
4638 Lisp_Object child;
4639 int old_height;
4641 xassert (!MINI_WINDOW_P (w));
4643 /* Set redisplay hints. */
4644 XSETFASTINT (w->last_modified, 0);
4645 XSETFASTINT (w->last_overlay_modified, 0);
4646 windows_or_buffers_changed++;
4647 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4649 old_height = XFASTINT (w->total_lines);
4650 XSETFASTINT (w->total_lines, height);
4652 if (!NILP (w->hchild))
4654 for (child = w->hchild; !NILP (child); child = c->next)
4656 c = XWINDOW (child);
4657 c->top_line = w->top_line;
4658 shrink_window_lowest_first (c, height);
4661 else if (!NILP (w->vchild))
4663 Lisp_Object last_child;
4664 int delta = old_height - height;
4665 int last_top;
4667 last_child = Qnil;
4669 /* Find the last child. We are taking space from lowest windows
4670 first, so we iterate over children from the last child
4671 backwards. */
4672 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
4673 last_child = child;
4675 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
4676 for (child = last_child; delta && !NILP (child); child = c->prev)
4678 int this_one;
4680 c = XWINDOW (child);
4681 this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
4683 if (this_one > delta)
4684 this_one = delta;
4686 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4687 delta -= this_one;
4690 /* Compute new positions. */
4691 last_top = XINT (w->top_line);
4692 for (child = w->vchild; !NILP (child); child = c->next)
4694 c = XWINDOW (child);
4695 c->top_line = make_number (last_top);
4696 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4697 last_top += XFASTINT (c->total_lines);
4703 /* Save, restore, or check positions and sizes in the window tree
4704 rooted at W. ACTION says what to do.
4706 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4707 orig_total_lines members are valid for all windows in the window
4708 tree. Value is non-zero if they are valid.
4710 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4711 orig_top_line and orig_total_lines for all windows in the tree.
4713 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4714 stored in orig_top_line and orig_total_lines for all windows. */
4716 static int
4717 save_restore_orig_size (w, action)
4718 struct window *w;
4719 enum save_restore_action action;
4721 int success_p = 1;
4723 while (w)
4725 if (!NILP (w->hchild))
4727 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4728 success_p = 0;
4730 else if (!NILP (w->vchild))
4732 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4733 success_p = 0;
4736 switch (action)
4738 case CHECK_ORIG_SIZES:
4739 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4740 return 0;
4741 break;
4743 case SAVE_ORIG_SIZES:
4744 w->orig_top_line = w->top_line;
4745 w->orig_total_lines = w->total_lines;
4746 XSETFASTINT (w->last_modified, 0);
4747 XSETFASTINT (w->last_overlay_modified, 0);
4748 break;
4750 case RESTORE_ORIG_SIZES:
4751 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4752 w->top_line = w->orig_top_line;
4753 w->total_lines = w->orig_total_lines;
4754 w->orig_total_lines = w->orig_top_line = Qnil;
4755 XSETFASTINT (w->last_modified, 0);
4756 XSETFASTINT (w->last_overlay_modified, 0);
4757 break;
4759 default:
4760 abort ();
4763 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4766 return success_p;
4770 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4771 without deleting other windows. */
4773 void
4774 grow_mini_window (w, delta)
4775 struct window *w;
4776 int delta;
4778 struct frame *f = XFRAME (w->frame);
4779 struct window *root;
4781 xassert (MINI_WINDOW_P (w));
4782 xassert (delta >= 0);
4784 /* Check values of window_min_width and window_min_height for
4785 validity. */
4786 check_min_window_sizes ();
4788 /* Compute how much we can enlarge the mini-window without deleting
4789 other windows. */
4790 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4791 if (delta)
4793 int min_height = window_min_size (root, 0, 0, 0);
4794 if (XFASTINT (root->total_lines) - delta < min_height)
4795 /* Note that the root window may already be smaller than
4796 min_height. */
4797 delta = max (0, XFASTINT (root->total_lines) - min_height);
4800 if (delta)
4802 /* Save original window sizes and positions, if not already done. */
4803 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4804 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4806 /* Shrink other windows. */
4807 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4809 /* Grow the mini-window. */
4810 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4811 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4812 XSETFASTINT (w->last_modified, 0);
4813 XSETFASTINT (w->last_overlay_modified, 0);
4815 adjust_glyphs (f);
4820 /* Shrink mini-window W. If there is recorded info about window sizes
4821 before a call to grow_mini_window, restore recorded window sizes.
4822 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4823 line. */
4825 void
4826 shrink_mini_window (w)
4827 struct window *w;
4829 struct frame *f = XFRAME (w->frame);
4830 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4832 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4834 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4835 adjust_glyphs (f);
4836 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4837 windows_or_buffers_changed = 1;
4839 else if (XFASTINT (w->total_lines) > 1)
4841 /* Distribute the additional lines of the mini-window
4842 among the other windows. */
4843 Lisp_Object window;
4844 XSETWINDOW (window, w);
4845 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
4851 /* Mark window cursors off for all windows in the window tree rooted
4852 at W by setting their phys_cursor_on_p flag to zero. Called from
4853 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4854 the frame are cleared. */
4856 void
4857 mark_window_cursors_off (w)
4858 struct window *w;
4860 while (w)
4862 if (!NILP (w->hchild))
4863 mark_window_cursors_off (XWINDOW (w->hchild));
4864 else if (!NILP (w->vchild))
4865 mark_window_cursors_off (XWINDOW (w->vchild));
4866 else
4867 w->phys_cursor_on_p = 0;
4869 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4874 /* Return number of lines of text (not counting mode lines) in W. */
4877 window_internal_height (w)
4878 struct window *w;
4880 int ht = XFASTINT (w->total_lines);
4882 if (!MINI_WINDOW_P (w))
4884 if (!NILP (w->parent)
4885 || !NILP (w->vchild)
4886 || !NILP (w->hchild)
4887 || !NILP (w->next)
4888 || !NILP (w->prev)
4889 || WINDOW_WANTS_MODELINE_P (w))
4890 --ht;
4892 if (WINDOW_WANTS_HEADER_LINE_P (w))
4893 --ht;
4896 return ht;
4900 /* Return the number of columns in W.
4901 Don't count columns occupied by scroll bars or the vertical bar
4902 separating W from the sibling to its right. */
4905 window_box_text_cols (w)
4906 struct window *w;
4908 struct frame *f = XFRAME (WINDOW_FRAME (w));
4909 int width = XINT (w->total_cols);
4911 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4912 /* Scroll bars occupy a few columns. */
4913 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4914 else if (!FRAME_WINDOW_P (f)
4915 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4916 /* The column of `|' characters separating side-by-side windows
4917 occupies one column only. */
4918 width -= 1;
4920 if (FRAME_WINDOW_P (f))
4921 /* On window-systems, fringes and display margins cannot be
4922 used for normal text. */
4923 width -= (WINDOW_FRINGE_COLS (w)
4924 + WINDOW_LEFT_MARGIN_COLS (w)
4925 + WINDOW_RIGHT_MARGIN_COLS (w));
4927 return width;
4931 /************************************************************************
4932 Window Scrolling
4933 ***********************************************************************/
4935 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4936 N screen-fulls, which is defined as the height of the window minus
4937 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4938 instead. Negative values of N mean scroll down. NOERROR non-zero
4939 means don't signal an error if we try to move over BEGV or ZV,
4940 respectively. */
4942 static void
4943 window_scroll (window, n, whole, noerror)
4944 Lisp_Object window;
4945 int n;
4946 int whole;
4947 int noerror;
4949 immediate_quit = 1;
4951 /* If we must, use the pixel-based version which is much slower than
4952 the line-based one but can handle varying line heights. */
4953 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4954 window_scroll_pixel_based (window, n, whole, noerror);
4955 else
4956 window_scroll_line_based (window, n, whole, noerror);
4958 immediate_quit = 0;
4962 /* Implementation of window_scroll that works based on pixel line
4963 heights. See the comment of window_scroll for parameter
4964 descriptions. */
4966 static void
4967 window_scroll_pixel_based (window, n, whole, noerror)
4968 Lisp_Object window;
4969 int n;
4970 int whole;
4971 int noerror;
4973 struct it it;
4974 struct window *w = XWINDOW (window);
4975 struct text_pos start;
4976 int this_scroll_margin;
4977 /* True if we fiddled the window vscroll field without really scrolling. */
4978 int vscrolled = 0;
4979 int x, y, rtop, rbot, rowh, vpos;
4981 SET_TEXT_POS_FROM_MARKER (start, w->start);
4983 /* If PT is not visible in WINDOW, move back one half of
4984 the screen. Allow PT to be partially visible, otherwise
4985 something like (scroll-down 1) with PT in the line before
4986 the partially visible one would recenter. */
4988 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4990 /* Move backward half the height of the window. Performance note:
4991 vmotion used here is about 10% faster, but would give wrong
4992 results for variable height lines. */
4993 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4994 it.current_y = it.last_visible_y;
4995 move_it_vertically_backward (&it, window_box_height (w) / 2);
4997 /* The function move_iterator_vertically may move over more than
4998 the specified y-distance. If it->w is small, e.g. a
4999 mini-buffer window, we may end up in front of the window's
5000 display area. This is the case when Start displaying at the
5001 start of the line containing PT in this case. */
5002 if (it.current_y <= 0)
5004 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5005 move_it_vertically_backward (&it, 0);
5006 it.current_y = 0;
5009 start = it.current.pos;
5011 else if (auto_window_vscroll_p)
5013 if (rtop || rbot) /* partially visible */
5015 int px;
5016 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
5017 if (whole)
5018 dy = max ((window_box_height (w)
5019 - next_screen_context_lines * dy),
5020 dy);
5021 dy *= n;
5023 if (n < 0)
5025 /* Only vscroll backwards if already vscrolled forwards. */
5026 if (w->vscroll < 0 && rtop > 0)
5028 px = max (0, -w->vscroll - min (rtop, -dy));
5029 Fset_window_vscroll (window, make_number (px), Qt);
5030 return;
5033 if (n > 0)
5035 /* Do vscroll if already vscrolled or only display line. */
5036 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
5038 px = max (0, -w->vscroll + min (rbot, dy));
5039 Fset_window_vscroll (window, make_number (px), Qt);
5040 return;
5043 /* Maybe modify window start instead of scrolling. */
5044 if (rbot > 0 || w->vscroll < 0)
5046 int spos;
5048 Fset_window_vscroll (window, make_number (0), Qt);
5049 /* If there are other text lines above the current row,
5050 move window start to current row. Else to next row. */
5051 if (rbot > 0)
5052 spos = XINT (Fline_beginning_position (Qnil));
5053 else
5054 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
5055 set_marker_restricted (w->start, make_number (spos),
5056 w->buffer);
5057 w->start_at_line_beg = Qt;
5058 w->update_mode_line = Qt;
5059 XSETFASTINT (w->last_modified, 0);
5060 XSETFASTINT (w->last_overlay_modified, 0);
5061 /* Set force_start so that redisplay_window will run the
5062 window-scroll-functions. */
5063 w->force_start = Qt;
5064 return;
5068 /* Cancel previous vscroll. */
5069 Fset_window_vscroll (window, make_number (0), Qt);
5072 /* If scroll_preserve_screen_position is non-nil, we try to set
5073 point in the same window line as it is now, so get that line. */
5074 if (!NILP (Vscroll_preserve_screen_position))
5076 /* We preserve the goal pixel coordinate across consecutive
5077 calls to scroll-up or scroll-down. This avoids the
5078 possibility of point becoming "stuck" on a tall line when
5079 scrolling by one line. */
5080 if (window_scroll_pixel_based_preserve_y < 0
5081 || (!EQ (current_kboard->Vlast_command, Qscroll_up)
5082 && !EQ (current_kboard->Vlast_command, Qscroll_down)))
5084 start_display (&it, w, start);
5085 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5086 window_scroll_pixel_based_preserve_y = it.current_y;
5089 else
5090 window_scroll_pixel_based_preserve_y = -1;
5092 /* Move iterator it from start the specified distance forward or
5093 backward. The result is the new window start. */
5094 start_display (&it, w, start);
5095 if (whole)
5097 int start_pos = IT_CHARPOS (it);
5098 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
5099 dy = max ((window_box_height (w)
5100 - next_screen_context_lines * dy),
5101 dy) * n;
5103 /* Note that move_it_vertically always moves the iterator to the
5104 start of a line. So, if the last line doesn't have a newline,
5105 we would end up at the start of the line ending at ZV. */
5106 if (dy <= 0)
5108 move_it_vertically_backward (&it, -dy);
5109 /* Ensure we actually do move, e.g. in case we are currently
5110 looking at an image that is taller that the window height. */
5111 while (start_pos == IT_CHARPOS (it)
5112 && start_pos > BEGV)
5113 move_it_by_lines (&it, -1, 1);
5115 else if (dy > 0)
5117 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
5118 MOVE_TO_POS | MOVE_TO_Y);
5119 /* Ensure we actually do move, e.g. in case we are currently
5120 looking at an image that is taller that the window height. */
5121 while (start_pos == IT_CHARPOS (it)
5122 && start_pos < ZV)
5123 move_it_by_lines (&it, 1, 1);
5126 else
5127 move_it_by_lines (&it, n, 1);
5129 /* We failed if we find ZV is already on the screen (scrolling up,
5130 means there's nothing past the end), or if we can't start any
5131 earlier (scrolling down, means there's nothing past the top). */
5132 if ((n > 0 && IT_CHARPOS (it) == ZV)
5133 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
5135 if (IT_CHARPOS (it) == ZV)
5137 if (it.current_y < it.last_visible_y
5138 && (it.current_y + it.max_ascent + it.max_descent
5139 > it.last_visible_y))
5141 /* The last line was only partially visible, make it fully
5142 visible. */
5143 w->vscroll = (it.last_visible_y
5144 - it.current_y + it.max_ascent + it.max_descent);
5145 adjust_glyphs (it.f);
5147 else if (noerror)
5148 return;
5149 else if (n < 0) /* could happen with empty buffers */
5150 xsignal0 (Qbeginning_of_buffer);
5151 else
5152 xsignal0 (Qend_of_buffer);
5154 else
5156 if (w->vscroll != 0)
5157 /* The first line was only partially visible, make it fully
5158 visible. */
5159 w->vscroll = 0;
5160 else if (noerror)
5161 return;
5162 else
5163 xsignal0 (Qbeginning_of_buffer);
5166 /* If control gets here, then we vscrolled. */
5168 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5170 /* Don't try to change the window start below. */
5171 vscrolled = 1;
5174 if (! vscrolled)
5176 int pos = IT_CHARPOS (it);
5177 int bytepos;
5179 /* If in the middle of a multi-glyph character move forward to
5180 the next character. */
5181 if (in_display_vector_p (&it))
5183 ++pos;
5184 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
5187 /* Set the window start, and set up the window for redisplay. */
5188 set_marker_restricted (w->start, make_number (pos),
5189 w->buffer);
5190 bytepos = XMARKER (w->start)->bytepos;
5191 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
5192 ? Qt : Qnil);
5193 w->update_mode_line = Qt;
5194 XSETFASTINT (w->last_modified, 0);
5195 XSETFASTINT (w->last_overlay_modified, 0);
5196 /* Set force_start so that redisplay_window will run the
5197 window-scroll-functions. */
5198 w->force_start = Qt;
5201 /* The rest of this function uses current_y in a nonstandard way,
5202 not including the height of the header line if any. */
5203 it.current_y = it.vpos = 0;
5205 /* Move PT out of scroll margins.
5206 This code wants current_y to be zero at the window start position
5207 even if there is a header line. */
5208 this_scroll_margin = max (0, scroll_margin);
5209 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
5210 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5212 if (n > 0)
5214 /* We moved the window start towards ZV, so PT may be now
5215 in the scroll margin at the top. */
5216 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5217 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5218 && (NILP (Vscroll_preserve_screen_position)
5219 || EQ (Vscroll_preserve_screen_position, Qt)))
5220 /* We found PT at a legitimate height. Leave it alone. */
5222 else if (window_scroll_pixel_based_preserve_y >= 0)
5224 /* If we have a header line, take account of it.
5225 This is necessary because we set it.current_y to 0, above. */
5226 move_it_to (&it, -1, -1,
5227 window_scroll_pixel_based_preserve_y
5228 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
5229 -1, MOVE_TO_Y);
5230 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5232 else
5234 while (it.current_y < this_scroll_margin)
5236 int prev = it.current_y;
5237 move_it_by_lines (&it, 1, 1);
5238 if (prev == it.current_y)
5239 break;
5241 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5244 else if (n < 0)
5246 int charpos, bytepos;
5247 int partial_p;
5249 /* Save our position, for the
5250 window_scroll_pixel_based_preserve_y case. */
5251 charpos = IT_CHARPOS (it);
5252 bytepos = IT_BYTEPOS (it);
5254 /* We moved the window start towards BEGV, so PT may be now
5255 in the scroll margin at the bottom. */
5256 move_it_to (&it, PT, -1,
5257 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5258 - this_scroll_margin - 1),
5260 MOVE_TO_POS | MOVE_TO_Y);
5262 /* Save our position, in case it's correct. */
5263 charpos = IT_CHARPOS (it);
5264 bytepos = IT_BYTEPOS (it);
5266 /* See if point is on a partially visible line at the end. */
5267 if (it.what == IT_EOB)
5268 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5269 else
5271 move_it_by_lines (&it, 1, 1);
5272 partial_p = it.current_y > it.last_visible_y;
5275 if (charpos == PT && !partial_p
5276 && (NILP (Vscroll_preserve_screen_position)
5277 || EQ (Vscroll_preserve_screen_position, Qt)))
5278 /* We found PT before we found the display margin, so PT is ok. */
5280 else if (window_scroll_pixel_based_preserve_y >= 0)
5282 SET_TEXT_POS_FROM_MARKER (start, w->start);
5283 start_display (&it, w, start);
5284 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5285 here because we called start_display again and did not
5286 alter it.current_y this time. */
5287 move_it_to (&it, -1, -1, window_scroll_pixel_based_preserve_y, -1,
5288 MOVE_TO_Y);
5289 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5291 else
5293 if (partial_p)
5294 /* The last line was only partially visible, so back up two
5295 lines to make sure we're on a fully visible line. */
5297 move_it_by_lines (&it, -2, 0);
5298 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5300 else
5301 /* No, the position we saved is OK, so use it. */
5302 SET_PT_BOTH (charpos, bytepos);
5308 /* Implementation of window_scroll that works based on screen lines.
5309 See the comment of window_scroll for parameter descriptions. */
5311 static void
5312 window_scroll_line_based (window, n, whole, noerror)
5313 Lisp_Object window;
5314 int n;
5315 int whole;
5316 int noerror;
5318 register struct window *w = XWINDOW (window);
5319 register int opoint = PT, opoint_byte = PT_BYTE;
5320 register int pos, pos_byte;
5321 register int ht = window_internal_height (w);
5322 register Lisp_Object tem;
5323 int lose;
5324 Lisp_Object bolp;
5325 int startpos;
5326 struct position posit;
5327 int original_vpos;
5329 /* If scrolling screen-fulls, compute the number of lines to
5330 scroll from the window's height. */
5331 if (whole)
5332 n *= max (1, ht - next_screen_context_lines);
5334 startpos = marker_position (w->start);
5336 posit = *compute_motion (startpos, 0, 0, 0,
5337 PT, ht, 0,
5338 -1, XINT (w->hscroll),
5339 0, w);
5340 original_vpos = posit.vpos;
5342 XSETFASTINT (tem, PT);
5343 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5345 if (NILP (tem))
5347 Fvertical_motion (make_number (- (ht / 2)), window);
5348 startpos = PT;
5351 SET_PT (startpos);
5352 lose = n < 0 && PT == BEGV;
5353 Fvertical_motion (make_number (n), window);
5354 pos = PT;
5355 pos_byte = PT_BYTE;
5356 bolp = Fbolp ();
5357 SET_PT_BOTH (opoint, opoint_byte);
5359 if (lose)
5361 if (noerror)
5362 return;
5363 else
5364 xsignal0 (Qbeginning_of_buffer);
5367 if (pos < ZV)
5369 int this_scroll_margin = scroll_margin;
5371 /* Don't use a scroll margin that is negative or too large. */
5372 if (this_scroll_margin < 0)
5373 this_scroll_margin = 0;
5375 if (XINT (w->total_lines) < 4 * scroll_margin)
5376 this_scroll_margin = XINT (w->total_lines) / 4;
5378 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
5379 w->start_at_line_beg = bolp;
5380 w->update_mode_line = Qt;
5381 XSETFASTINT (w->last_modified, 0);
5382 XSETFASTINT (w->last_overlay_modified, 0);
5383 /* Set force_start so that redisplay_window will run
5384 the window-scroll-functions. */
5385 w->force_start = Qt;
5387 if (!NILP (Vscroll_preserve_screen_position)
5388 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5390 SET_PT_BOTH (pos, pos_byte);
5391 Fvertical_motion (make_number (original_vpos), window);
5393 /* If we scrolled forward, put point enough lines down
5394 that it is outside the scroll margin. */
5395 else if (n > 0)
5397 int top_margin;
5399 if (this_scroll_margin > 0)
5401 SET_PT_BOTH (pos, pos_byte);
5402 Fvertical_motion (make_number (this_scroll_margin), window);
5403 top_margin = PT;
5405 else
5406 top_margin = pos;
5408 if (top_margin <= opoint)
5409 SET_PT_BOTH (opoint, opoint_byte);
5410 else if (!NILP (Vscroll_preserve_screen_position))
5412 SET_PT_BOTH (pos, pos_byte);
5413 Fvertical_motion (make_number (original_vpos), window);
5415 else
5416 SET_PT (top_margin);
5418 else if (n < 0)
5420 int bottom_margin;
5422 /* If we scrolled backward, put point near the end of the window
5423 but not within the scroll margin. */
5424 SET_PT_BOTH (pos, pos_byte);
5425 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
5426 if (XFASTINT (tem) == ht - this_scroll_margin)
5427 bottom_margin = PT;
5428 else
5429 bottom_margin = PT + 1;
5431 if (bottom_margin > opoint)
5432 SET_PT_BOTH (opoint, opoint_byte);
5433 else
5435 if (!NILP (Vscroll_preserve_screen_position))
5437 SET_PT_BOTH (pos, pos_byte);
5438 Fvertical_motion (make_number (original_vpos), window);
5440 else
5441 Fvertical_motion (make_number (-1), window);
5445 else
5447 if (noerror)
5448 return;
5449 else
5450 xsignal0 (Qend_of_buffer);
5455 /* Scroll selected_window up or down. If N is nil, scroll a
5456 screen-full which is defined as the height of the window minus
5457 next_screen_context_lines. If N is the symbol `-', scroll.
5458 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5459 up. This is the guts of Fscroll_up and Fscroll_down. */
5461 static void
5462 scroll_command (n, direction)
5463 Lisp_Object n;
5464 int direction;
5466 int count = SPECPDL_INDEX ();
5468 xassert (abs (direction) == 1);
5470 /* If selected window's buffer isn't current, make it current for
5471 the moment. But don't screw up if window_scroll gets an error. */
5472 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
5474 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5475 Fset_buffer (XWINDOW (selected_window)->buffer);
5477 /* Make redisplay consider other windows than just selected_window. */
5478 ++windows_or_buffers_changed;
5481 if (NILP (n))
5482 window_scroll (selected_window, direction, 1, 0);
5483 else if (EQ (n, Qminus))
5484 window_scroll (selected_window, -direction, 1, 0);
5485 else
5487 n = Fprefix_numeric_value (n);
5488 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5491 unbind_to (count, Qnil);
5494 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
5495 doc: /* Scroll text of current window upward ARG lines.
5496 If ARG is omitted or nil, scroll upward by a near full screen.
5497 A near full screen is `next-screen-context-lines' less than a full screen.
5498 Negative ARG means scroll downward.
5499 If ARG is the atom `-', scroll downward by nearly full screen.
5500 When calling from a program, supply as argument a number, nil, or `-'. */)
5501 (arg)
5502 Lisp_Object arg;
5504 scroll_command (arg, 1);
5505 return Qnil;
5508 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
5509 doc: /* Scroll text of current window down ARG lines.
5510 If ARG is omitted or nil, scroll down by a near full screen.
5511 A near full screen is `next-screen-context-lines' less than a full screen.
5512 Negative ARG means scroll upward.
5513 If ARG is the atom `-', scroll upward by nearly full screen.
5514 When calling from a program, supply as argument a number, nil, or `-'. */)
5515 (arg)
5516 Lisp_Object arg;
5518 scroll_command (arg, -1);
5519 return Qnil;
5522 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5523 doc: /* Return the other window for \"other window scroll\" commands.
5524 If `other-window-scroll-buffer' is non-nil, a window
5525 showing that buffer is used.
5526 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5527 specifies the window. This takes precedence over
5528 `other-window-scroll-buffer'. */)
5531 Lisp_Object window;
5533 if (MINI_WINDOW_P (XWINDOW (selected_window))
5534 && !NILP (Vminibuf_scroll_window))
5535 window = Vminibuf_scroll_window;
5536 /* If buffer is specified, scroll that buffer. */
5537 else if (!NILP (Vother_window_scroll_buffer))
5539 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5540 if (NILP (window))
5541 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5543 else
5545 /* Nothing specified; look for a neighboring window on the same
5546 frame. */
5547 window = Fnext_window (selected_window, Qnil, Qnil);
5549 if (EQ (window, selected_window))
5550 /* That didn't get us anywhere; look for a window on another
5551 visible frame. */
5553 window = Fnext_window (window, Qnil, Qt);
5554 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5555 && ! EQ (window, selected_window));
5558 CHECK_LIVE_WINDOW (window);
5560 if (EQ (window, selected_window))
5561 error ("There is no other window");
5563 return window;
5566 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5567 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5568 A near full screen is `next-screen-context-lines' less than a full screen.
5569 The next window is the one below the current one; or the one at the top
5570 if the current one is at the bottom. Negative ARG means scroll downward.
5571 If ARG is the atom `-', scroll downward by nearly full screen.
5572 When calling from a program, supply as argument a number, nil, or `-'.
5574 If `other-window-scroll-buffer' is non-nil, scroll the window
5575 showing that buffer, popping the buffer up if necessary.
5576 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5577 specifies the window to scroll. This takes precedence over
5578 `other-window-scroll-buffer'. */)
5579 (arg)
5580 Lisp_Object arg;
5582 Lisp_Object window;
5583 struct window *w;
5584 int count = SPECPDL_INDEX ();
5586 window = Fother_window_for_scrolling ();
5587 w = XWINDOW (window);
5589 /* Don't screw up if window_scroll gets an error. */
5590 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5591 ++windows_or_buffers_changed;
5593 Fset_buffer (w->buffer);
5594 SET_PT (marker_position (w->pointm));
5596 if (NILP (arg))
5597 window_scroll (window, 1, 1, 1);
5598 else if (EQ (arg, Qminus))
5599 window_scroll (window, -1, 1, 1);
5600 else
5602 if (CONSP (arg))
5603 arg = Fcar (arg);
5604 CHECK_NUMBER (arg);
5605 window_scroll (window, XINT (arg), 0, 1);
5608 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5609 unbind_to (count, Qnil);
5611 return Qnil;
5614 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "P\np",
5615 doc: /* Scroll selected window display ARG columns left.
5616 Default for ARG is window width minus 2.
5617 Value is the total amount of leftward horizontal scrolling in
5618 effect after the change.
5619 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5620 lower bound for automatic scrolling, i.e. automatic scrolling
5621 will not scroll a window to a column less than the value returned
5622 by this function. This happens in an interactive call. */)
5623 (arg, set_minimum)
5624 register Lisp_Object arg, set_minimum;
5626 Lisp_Object result;
5627 int hscroll;
5628 struct window *w = XWINDOW (selected_window);
5630 if (NILP (arg))
5631 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5632 else
5633 arg = Fprefix_numeric_value (arg);
5635 hscroll = XINT (w->hscroll) + XINT (arg);
5636 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5638 if (!NILP (set_minimum))
5639 w->min_hscroll = w->hscroll;
5641 return result;
5644 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "P\np",
5645 doc: /* Scroll selected window display ARG columns right.
5646 Default for ARG is window width minus 2.
5647 Value is the total amount of leftward horizontal scrolling in
5648 effect after the change.
5649 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5650 lower bound for automatic scrolling, i.e. automatic scrolling
5651 will not scroll a window to a column less than the value returned
5652 by this function. This happens in an interactive call. */)
5653 (arg, set_minimum)
5654 register Lisp_Object arg, set_minimum;
5656 Lisp_Object result;
5657 int hscroll;
5658 struct window *w = XWINDOW (selected_window);
5660 if (NILP (arg))
5661 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5662 else
5663 arg = Fprefix_numeric_value (arg);
5665 hscroll = XINT (w->hscroll) - XINT (arg);
5666 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5668 if (!NILP (set_minimum))
5669 w->min_hscroll = w->hscroll;
5671 return result;
5674 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5675 doc: /* Return the window which was selected when entering the minibuffer.
5676 Returns nil, if current window is not a minibuffer window. */)
5679 if (minibuf_level > 0
5680 && MINI_WINDOW_P (XWINDOW (selected_window))
5681 && WINDOW_LIVE_P (minibuf_selected_window))
5682 return minibuf_selected_window;
5684 return Qnil;
5687 /* Value is the number of lines actually displayed in window W,
5688 as opposed to its height. */
5690 static int
5691 displayed_window_lines (w)
5692 struct window *w;
5694 struct it it;
5695 struct text_pos start;
5696 int height = window_box_height (w);
5697 struct buffer *old_buffer;
5698 int bottom_y;
5700 if (XBUFFER (w->buffer) != current_buffer)
5702 old_buffer = current_buffer;
5703 set_buffer_internal (XBUFFER (w->buffer));
5705 else
5706 old_buffer = NULL;
5708 /* In case W->start is out of the accessible range, do something
5709 reasonable. This happens in Info mode when Info-scroll-down
5710 calls (recenter -1) while W->start is 1. */
5711 if (XMARKER (w->start)->charpos < BEGV)
5712 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5713 else if (XMARKER (w->start)->charpos > ZV)
5714 SET_TEXT_POS (start, ZV, ZV_BYTE);
5715 else
5716 SET_TEXT_POS_FROM_MARKER (start, w->start);
5718 start_display (&it, w, start);
5719 move_it_vertically (&it, height);
5720 bottom_y = line_bottom_y (&it);
5722 /* rms: On a non-window display,
5723 the value of it.vpos at the bottom of the screen
5724 seems to be 1 larger than window_box_height (w).
5725 This kludge fixes a bug whereby (move-to-window-line -1)
5726 when ZV is on the last screen line
5727 moves to the previous screen line instead of the last one. */
5728 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5729 height++;
5731 /* Add in empty lines at the bottom of the window. */
5732 if (bottom_y < height)
5734 int uy = FRAME_LINE_HEIGHT (it.f);
5735 it.vpos += (height - bottom_y + uy - 1) / uy;
5738 if (old_buffer)
5739 set_buffer_internal (old_buffer);
5741 return it.vpos;
5745 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5746 doc: /* Center point in window and redisplay frame.
5747 With prefix argument ARG, recenter putting point on screen line ARG
5748 relative to the current window. If ARG is negative, it counts up from the
5749 bottom of the window. (ARG should be less than the height of the window.)
5751 If ARG is omitted or nil, erase the entire frame and then redraw with point
5752 in the center of the current window. If `auto-resize-tool-bars' is set to
5753 `grow-only', this resets the tool-bar's height to the minimum height needed.
5755 Just C-u as prefix means put point in the center of the window
5756 and redisplay normally--don't erase and redraw the frame. */)
5757 (arg)
5758 register Lisp_Object arg;
5760 struct window *w = XWINDOW (selected_window);
5761 struct buffer *buf = XBUFFER (w->buffer);
5762 struct buffer *obuf = current_buffer;
5763 int center_p = 0;
5764 int charpos, bytepos;
5765 int iarg;
5766 int this_scroll_margin;
5768 /* If redisplay is suppressed due to an error, try again. */
5769 obuf->display_error_modiff = 0;
5771 if (NILP (arg))
5773 int i;
5775 /* Invalidate pixel data calculated for all compositions. */
5776 for (i = 0; i < n_compositions; i++)
5777 composition_table[i]->font = NULL;
5779 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5781 Fredraw_frame (WINDOW_FRAME (w));
5782 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5783 center_p = 1;
5785 else if (CONSP (arg)) /* Just C-u. */
5786 center_p = 1;
5787 else
5789 arg = Fprefix_numeric_value (arg);
5790 CHECK_NUMBER (arg);
5791 iarg = XINT (arg);
5794 set_buffer_internal (buf);
5796 /* Do this after making BUF current
5797 in case scroll_margin is buffer-local. */
5798 this_scroll_margin = max (0, scroll_margin);
5799 this_scroll_margin = min (this_scroll_margin,
5800 XFASTINT (w->total_lines) / 4);
5802 /* Handle centering on a graphical frame specially. Such frames can
5803 have variable-height lines and centering point on the basis of
5804 line counts would lead to strange effects. */
5805 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5807 if (center_p)
5809 struct it it;
5810 struct text_pos pt;
5812 SET_TEXT_POS (pt, PT, PT_BYTE);
5813 start_display (&it, w, pt);
5814 move_it_vertically_backward (&it, window_box_height (w) / 2);
5815 charpos = IT_CHARPOS (it);
5816 bytepos = IT_BYTEPOS (it);
5818 else if (iarg < 0)
5820 struct it it;
5821 struct text_pos pt;
5822 int nlines = -iarg;
5823 int extra_line_spacing;
5824 int h = window_box_height (w);
5826 iarg = - max (-iarg, this_scroll_margin);
5828 SET_TEXT_POS (pt, PT, PT_BYTE);
5829 start_display (&it, w, pt);
5831 /* Be sure we have the exact height of the full line containing PT. */
5832 move_it_by_lines (&it, 0, 1);
5834 /* The amount of pixels we have to move back is the window
5835 height minus what's displayed in the line containing PT,
5836 and the lines below. */
5837 it.current_y = 0;
5838 it.vpos = 0;
5839 move_it_by_lines (&it, nlines, 1);
5841 if (it.vpos == nlines)
5842 h -= it.current_y;
5843 else
5845 /* Last line has no newline */
5846 h -= line_bottom_y (&it);
5847 it.vpos++;
5850 /* Don't reserve space for extra line spacing of last line. */
5851 extra_line_spacing = it.max_extra_line_spacing;
5853 /* If we can't move down NLINES lines because we hit
5854 the end of the buffer, count in some empty lines. */
5855 if (it.vpos < nlines)
5857 nlines -= it.vpos;
5858 extra_line_spacing = it.extra_line_spacing;
5859 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5861 if (h <= 0)
5862 return Qnil;
5864 /* Now find the new top line (starting position) of the window. */
5865 start_display (&it, w, pt);
5866 it.current_y = 0;
5867 move_it_vertically_backward (&it, h);
5869 /* If extra line spacing is present, we may move too far
5870 back. This causes the last line to be only partially
5871 visible (which triggers redisplay to recenter that line
5872 in the middle), so move forward.
5873 But ignore extra line spacing on last line, as it is not
5874 considered to be part of the visible height of the line.
5876 h += extra_line_spacing;
5877 while (-it.current_y > h)
5878 move_it_by_lines (&it, 1, 1);
5880 charpos = IT_CHARPOS (it);
5881 bytepos = IT_BYTEPOS (it);
5883 else
5885 struct position pos;
5887 iarg = max (iarg, this_scroll_margin);
5889 pos = *vmotion (PT, -iarg, w);
5890 charpos = pos.bufpos;
5891 bytepos = pos.bytepos;
5894 else
5896 struct position pos;
5897 int ht = window_internal_height (w);
5899 if (center_p)
5900 iarg = ht / 2;
5901 else if (iarg < 0)
5902 iarg += ht;
5904 /* Don't let it get into the margin at either top or bottom. */
5905 iarg = max (iarg, this_scroll_margin);
5906 iarg = min (iarg, ht - this_scroll_margin - 1);
5908 pos = *vmotion (PT, - iarg, w);
5909 charpos = pos.bufpos;
5910 bytepos = pos.bytepos;
5913 /* Set the new window start. */
5914 set_marker_both (w->start, w->buffer, charpos, bytepos);
5915 w->window_end_valid = Qnil;
5917 w->optional_new_start = Qt;
5919 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5920 w->start_at_line_beg = Qt;
5921 else
5922 w->start_at_line_beg = Qnil;
5924 set_buffer_internal (obuf);
5925 return Qnil;
5929 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5930 0, 1, 0,
5931 doc: /* Return the height in lines of the text display area of WINDOW.
5932 WINDOW defaults to the selected window.
5933 This doesn't include the mode-line (or header-line if any) or any
5934 partial-height lines in the text display area. */)
5935 (window)
5936 Lisp_Object window;
5938 struct window *w = decode_window (window);
5939 int pixel_height = window_box_height (w);
5940 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5941 return make_number (line_height);
5946 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5947 1, 1, "P",
5948 doc: /* Position point relative to window.
5949 With no argument, position point at center of window.
5950 An argument specifies vertical position within the window;
5951 zero means top of window, negative means relative to bottom of window. */)
5952 (arg)
5953 Lisp_Object arg;
5955 struct window *w = XWINDOW (selected_window);
5956 int lines, start;
5957 Lisp_Object window;
5958 #if 0
5959 int this_scroll_margin;
5960 #endif
5962 window = selected_window;
5963 start = marker_position (w->start);
5964 if (start < BEGV || start > ZV)
5966 int height = window_internal_height (w);
5967 Fvertical_motion (make_number (- (height / 2)), window);
5968 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5969 w->start_at_line_beg = Fbolp ();
5970 w->force_start = Qt;
5972 else
5973 Fgoto_char (w->start);
5975 lines = displayed_window_lines (w);
5977 #if 0
5978 this_scroll_margin = max (0, scroll_margin);
5979 this_scroll_margin = min (this_scroll_margin, lines / 4);
5980 #endif
5982 if (NILP (arg))
5983 XSETFASTINT (arg, lines / 2);
5984 else
5986 int iarg = XINT (Fprefix_numeric_value (arg));
5988 if (iarg < 0)
5989 iarg = iarg + lines;
5991 #if 0 /* This code would prevent move-to-window-line from moving point
5992 to a place inside the scroll margins (which would cause the
5993 next redisplay to scroll). I wrote this code, but then concluded
5994 it is probably better not to install it. However, it is here
5995 inside #if 0 so as not to lose it. -- rms. */
5997 /* Don't let it get into the margin at either top or bottom. */
5998 iarg = max (iarg, this_scroll_margin);
5999 iarg = min (iarg, lines - this_scroll_margin - 1);
6000 #endif
6002 arg = make_number (iarg);
6005 /* Skip past a partially visible first line. */
6006 if (w->vscroll)
6007 XSETINT (arg, XINT (arg) + 1);
6009 return Fvertical_motion (arg, window);
6014 /***********************************************************************
6015 Window Configuration
6016 ***********************************************************************/
6018 struct save_window_data
6020 EMACS_INT size_from_Lisp_Vector_struct;
6021 struct Lisp_Vector *next_from_Lisp_Vector_struct;
6022 Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
6023 Lisp_Object frame_tool_bar_lines;
6024 Lisp_Object selected_frame;
6025 Lisp_Object current_window;
6026 Lisp_Object current_buffer;
6027 Lisp_Object minibuf_scroll_window;
6028 Lisp_Object minibuf_selected_window;
6029 Lisp_Object root_window;
6030 Lisp_Object focus_frame;
6031 /* Record the values of window-min-width and window-min-height
6032 so that window sizes remain consistent with them. */
6033 Lisp_Object min_width, min_height;
6034 /* A vector, each of whose elements is a struct saved_window
6035 for one window. */
6036 Lisp_Object saved_windows;
6039 /* This is saved as a Lisp_Vector */
6040 struct saved_window
6042 /* these first two must agree with struct Lisp_Vector in lisp.h */
6043 EMACS_INT size_from_Lisp_Vector_struct;
6044 struct Lisp_Vector *next_from_Lisp_Vector_struct;
6046 Lisp_Object window;
6047 Lisp_Object buffer, start, pointm, mark;
6048 Lisp_Object left_col, top_line, total_cols, total_lines;
6049 Lisp_Object hscroll, min_hscroll;
6050 Lisp_Object parent, prev;
6051 Lisp_Object start_at_line_beg;
6052 Lisp_Object display_table;
6053 Lisp_Object orig_top_line, orig_total_lines;
6054 Lisp_Object left_margin_cols, right_margin_cols;
6055 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
6056 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
6057 Lisp_Object dedicated;
6060 #define SAVED_WINDOW_N(swv,n) \
6061 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
6063 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
6064 doc: /* Return t if OBJECT is a window-configuration object. */)
6065 (object)
6066 Lisp_Object object;
6068 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
6071 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
6072 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
6073 (config)
6074 Lisp_Object config;
6076 register struct save_window_data *data;
6077 struct Lisp_Vector *saved_windows;
6079 CHECK_WINDOW_CONFIGURATION (config);
6081 data = (struct save_window_data *) XVECTOR (config);
6082 saved_windows = XVECTOR (data->saved_windows);
6083 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6086 DEFUN ("set-window-configuration", Fset_window_configuration,
6087 Sset_window_configuration, 1, 1, 0,
6088 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
6089 CONFIGURATION must be a value previously returned
6090 by `current-window-configuration' (which see).
6091 If CONFIGURATION was made from a frame that is now deleted,
6092 only frame-independent values can be restored. In this case,
6093 the return value is nil. Otherwise the value is t. */)
6094 (configuration)
6095 Lisp_Object configuration;
6097 register struct save_window_data *data;
6098 struct Lisp_Vector *saved_windows;
6099 Lisp_Object new_current_buffer;
6100 Lisp_Object frame;
6101 FRAME_PTR f;
6102 int old_point = -1;
6104 CHECK_WINDOW_CONFIGURATION (configuration);
6106 data = (struct save_window_data *) XVECTOR (configuration);
6107 saved_windows = XVECTOR (data->saved_windows);
6109 new_current_buffer = data->current_buffer;
6110 if (NILP (XBUFFER (new_current_buffer)->name))
6111 new_current_buffer = Qnil;
6112 else
6114 if (XBUFFER (new_current_buffer) == current_buffer)
6115 /* The code further down "preserves point" by saving here PT in
6116 old_point and then setting it later back into PT. When the
6117 current-selected-window and the final-selected-window both show
6118 the current buffer, this suffers from the problem that the
6119 current PT is the window-point of the current-selected-window,
6120 while the final PT is the point of the final-selected-window, so
6121 this copy from one PT to the other would end up moving the
6122 window-point of the final-selected-window to the window-point of
6123 the current-selected-window. So we have to be careful which
6124 point of the current-buffer we copy into old_point. */
6125 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6126 && WINDOWP (selected_window)
6127 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
6128 && !EQ (selected_window, data->current_window))
6129 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6130 else
6131 old_point = PT;
6132 else
6133 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6134 point in new_current_buffer as of the last time this buffer was
6135 used. This can be non-deterministic since it can be changed by
6136 things like jit-lock by mere temporary selection of some random
6137 window that happens to show this buffer.
6138 So if possible we want this arbitrary choice of "which point" to
6139 be the one from the to-be-selected-window so as to prevent this
6140 window's cursor from being copied from another window. */
6141 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6142 /* If current_window = selected_window, its point is in BUF_PT. */
6143 && !EQ (selected_window, data->current_window))
6144 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6145 else
6146 old_point = BUF_PT (XBUFFER (new_current_buffer));
6149 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6150 f = XFRAME (frame);
6152 /* If f is a dead frame, don't bother rebuilding its window tree.
6153 However, there is other stuff we should still try to do below. */
6154 if (FRAME_LIVE_P (f))
6156 register struct window *w;
6157 register struct saved_window *p;
6158 struct window *root_window;
6159 struct window **leaf_windows;
6160 int n_leaf_windows;
6161 int k, i, n;
6163 /* If the frame has been resized since this window configuration was
6164 made, we change the frame to the size specified in the
6165 configuration, restore the configuration, and then resize it
6166 back. We keep track of the prevailing height in these variables. */
6167 int previous_frame_lines = FRAME_LINES (f);
6168 int previous_frame_cols = FRAME_COLS (f);
6169 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6170 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6172 /* The mouse highlighting code could get screwed up
6173 if it runs during this. */
6174 BLOCK_INPUT;
6176 if (XFASTINT (data->frame_lines) != previous_frame_lines
6177 || XFASTINT (data->frame_cols) != previous_frame_cols)
6178 change_frame_size (f, XFASTINT (data->frame_lines),
6179 XFASTINT (data->frame_cols), 0, 0, 0);
6180 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6181 if (XFASTINT (data->frame_menu_bar_lines)
6182 != previous_frame_menu_bar_lines)
6183 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
6184 #ifdef HAVE_WINDOW_SYSTEM
6185 if (XFASTINT (data->frame_tool_bar_lines)
6186 != previous_frame_tool_bar_lines)
6187 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
6188 #endif
6189 #endif
6191 /* "Swap out" point from the selected window's buffer
6192 into the window itself. (Normally the pointm of the selected
6193 window holds garbage.) We do this now, before
6194 restoring the window contents, and prevent it from
6195 being done later on when we select a new window. */
6196 if (! NILP (XWINDOW (selected_window)->buffer))
6198 w = XWINDOW (selected_window);
6199 set_marker_both (w->pointm,
6200 w->buffer,
6201 BUF_PT (XBUFFER (w->buffer)),
6202 BUF_PT_BYTE (XBUFFER (w->buffer)));
6205 windows_or_buffers_changed++;
6206 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
6208 /* Problem: Freeing all matrices and later allocating them again
6209 is a serious redisplay flickering problem. What we would
6210 really like to do is to free only those matrices not reused
6211 below. */
6212 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6213 leaf_windows
6214 = (struct window **) alloca (count_windows (root_window)
6215 * sizeof (struct window *));
6216 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6218 /* Temporarily avoid any problems with windows that are smaller
6219 than they are supposed to be. */
6220 window_min_height = 1;
6221 window_min_width = 1;
6223 /* Kludge Alert!
6224 Mark all windows now on frame as "deleted".
6225 Restoring the new configuration "undeletes" any that are in it.
6227 Save their current buffers in their height fields, since we may
6228 need it later, if a buffer saved in the configuration is now
6229 dead. */
6230 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6232 for (k = 0; k < saved_windows->size; k++)
6234 p = SAVED_WINDOW_N (saved_windows, k);
6235 w = XWINDOW (p->window);
6236 w->next = Qnil;
6238 if (!NILP (p->parent))
6239 w->parent = SAVED_WINDOW_N (saved_windows,
6240 XFASTINT (p->parent))->window;
6241 else
6242 w->parent = Qnil;
6244 if (!NILP (p->prev))
6246 w->prev = SAVED_WINDOW_N (saved_windows,
6247 XFASTINT (p->prev))->window;
6248 XWINDOW (w->prev)->next = p->window;
6250 else
6252 w->prev = Qnil;
6253 if (!NILP (w->parent))
6255 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
6257 XWINDOW (w->parent)->vchild = p->window;
6258 XWINDOW (w->parent)->hchild = Qnil;
6260 else
6262 XWINDOW (w->parent)->hchild = p->window;
6263 XWINDOW (w->parent)->vchild = Qnil;
6268 /* If we squirreled away the buffer in the window's height,
6269 restore it now. */
6270 if (BUFFERP (w->total_lines))
6271 w->buffer = w->total_lines;
6272 w->left_col = p->left_col;
6273 w->top_line = p->top_line;
6274 w->total_cols = p->total_cols;
6275 w->total_lines = p->total_lines;
6276 w->hscroll = p->hscroll;
6277 w->min_hscroll = p->min_hscroll;
6278 w->display_table = p->display_table;
6279 w->orig_top_line = p->orig_top_line;
6280 w->orig_total_lines = p->orig_total_lines;
6281 w->left_margin_cols = p->left_margin_cols;
6282 w->right_margin_cols = p->right_margin_cols;
6283 w->left_fringe_width = p->left_fringe_width;
6284 w->right_fringe_width = p->right_fringe_width;
6285 w->fringes_outside_margins = p->fringes_outside_margins;
6286 w->scroll_bar_width = p->scroll_bar_width;
6287 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
6288 w->dedicated = p->dedicated;
6289 XSETFASTINT (w->last_modified, 0);
6290 XSETFASTINT (w->last_overlay_modified, 0);
6292 /* Reinstall the saved buffer and pointers into it. */
6293 if (NILP (p->buffer))
6294 w->buffer = p->buffer;
6295 else
6297 if (!NILP (XBUFFER (p->buffer)->name))
6298 /* If saved buffer is alive, install it. */
6300 w->buffer = p->buffer;
6301 w->start_at_line_beg = p->start_at_line_beg;
6302 set_marker_restricted (w->start, p->start, w->buffer);
6303 set_marker_restricted (w->pointm, p->pointm, w->buffer);
6304 Fset_marker (XBUFFER (w->buffer)->mark,
6305 p->mark, w->buffer);
6307 /* As documented in Fcurrent_window_configuration, don't
6308 restore the location of point in the buffer which was
6309 current when the window configuration was recorded. */
6310 if (!EQ (p->buffer, new_current_buffer)
6311 && XBUFFER (p->buffer) == current_buffer)
6312 Fgoto_char (w->pointm);
6314 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
6315 /* Else unless window has a live buffer, get one. */
6317 w->buffer = Fcdr (Fcar (Vbuffer_alist));
6318 /* This will set the markers to beginning of visible
6319 range. */
6320 set_marker_restricted (w->start, make_number (0), w->buffer);
6321 set_marker_restricted (w->pointm, make_number (0),w->buffer);
6322 w->start_at_line_beg = Qt;
6324 else
6325 /* Keeping window's old buffer; make sure the markers
6326 are real. */
6328 /* Set window markers at start of visible range. */
6329 if (XMARKER (w->start)->buffer == 0)
6330 set_marker_restricted (w->start, make_number (0),
6331 w->buffer);
6332 if (XMARKER (w->pointm)->buffer == 0)
6333 set_marker_restricted_both (w->pointm, w->buffer,
6334 BUF_PT (XBUFFER (w->buffer)),
6335 BUF_PT_BYTE (XBUFFER (w->buffer)));
6336 w->start_at_line_beg = Qt;
6341 FRAME_ROOT_WINDOW (f) = data->root_window;
6342 /* Prevent "swapping out point" in the old selected window
6343 using the buffer that has been restored into it.
6344 We already swapped out point that from that window's old buffer. */
6345 selected_window = Qnil;
6347 /* Arrange *not* to restore point in the buffer that was
6348 current when the window configuration was saved. */
6349 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
6350 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6351 make_number (old_point),
6352 XWINDOW (data->current_window)->buffer);
6354 Fselect_window (data->current_window, Qnil);
6355 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
6356 = selected_window;
6358 if (NILP (data->focus_frame)
6359 || (FRAMEP (data->focus_frame)
6360 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6361 Fredirect_frame_focus (frame, data->focus_frame);
6363 #if 0 /* I don't understand why this is needed, and it causes problems
6364 when the frame's old selected window has been deleted. */
6365 if (f != selected_frame && FRAME_WINDOW_P (f))
6366 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
6367 0, 0);
6368 #endif
6370 /* Set the screen height to the value it had before this function. */
6371 if (previous_frame_lines != FRAME_LINES (f)
6372 || previous_frame_cols != FRAME_COLS (f))
6373 change_frame_size (f, previous_frame_lines, previous_frame_cols,
6374 0, 0, 0);
6375 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6376 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
6377 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
6378 make_number (0));
6379 #ifdef HAVE_WINDOW_SYSTEM
6380 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
6381 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
6382 make_number (0));
6383 #endif
6384 #endif
6386 /* Now, free glyph matrices in windows that were not reused. */
6387 for (i = n = 0; i < n_leaf_windows; ++i)
6389 if (NILP (leaf_windows[i]->buffer))
6391 /* Assert it's not reused as a combination. */
6392 xassert (NILP (leaf_windows[i]->hchild)
6393 && NILP (leaf_windows[i]->vchild));
6394 free_window_matrices (leaf_windows[i]);
6396 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
6397 ++n;
6400 adjust_glyphs (f);
6402 UNBLOCK_INPUT;
6404 /* Fselect_window will have made f the selected frame, so we
6405 reselect the proper frame here. Fhandle_switch_frame will change the
6406 selected window too, but that doesn't make the call to
6407 Fselect_window above totally superfluous; it still sets f's
6408 selected window. */
6409 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6410 do_switch_frame (data->selected_frame, 0, 0);
6412 if (! NILP (Vwindow_configuration_change_hook)
6413 && ! NILP (Vrun_hooks))
6414 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
6417 if (!NILP (new_current_buffer))
6418 Fset_buffer (new_current_buffer);
6420 /* Restore the minimum heights recorded in the configuration. */
6421 window_min_height = XINT (data->min_height);
6422 window_min_width = XINT (data->min_width);
6424 Vminibuf_scroll_window = data->minibuf_scroll_window;
6425 minibuf_selected_window = data->minibuf_selected_window;
6427 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6430 /* Mark all windows now on frame as deleted
6431 by setting their buffers to nil. */
6433 void
6434 delete_all_subwindows (w)
6435 register struct window *w;
6437 if (!NILP (w->next))
6438 delete_all_subwindows (XWINDOW (w->next));
6439 if (!NILP (w->vchild))
6440 delete_all_subwindows (XWINDOW (w->vchild));
6441 if (!NILP (w->hchild))
6442 delete_all_subwindows (XWINDOW (w->hchild));
6444 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
6446 if (!NILP (w->buffer))
6447 unshow_buffer (w);
6449 /* We set all three of these fields to nil, to make sure that we can
6450 distinguish this dead window from any live window. Live leaf
6451 windows will have buffer set, and combination windows will have
6452 vchild or hchild set. */
6453 w->buffer = Qnil;
6454 w->vchild = Qnil;
6455 w->hchild = Qnil;
6457 Vwindow_list = Qnil;
6460 static int
6461 count_windows (window)
6462 register struct window *window;
6464 register int count = 1;
6465 if (!NILP (window->next))
6466 count += count_windows (XWINDOW (window->next));
6467 if (!NILP (window->vchild))
6468 count += count_windows (XWINDOW (window->vchild));
6469 if (!NILP (window->hchild))
6470 count += count_windows (XWINDOW (window->hchild));
6471 return count;
6475 /* Fill vector FLAT with leaf windows under W, starting at index I.
6476 Value is last index + 1. */
6478 static int
6479 get_leaf_windows (w, flat, i)
6480 struct window *w;
6481 struct window **flat;
6482 int i;
6484 while (w)
6486 if (!NILP (w->hchild))
6487 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
6488 else if (!NILP (w->vchild))
6489 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
6490 else
6491 flat[i++] = w;
6493 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6496 return i;
6500 /* Return a pointer to the glyph W's physical cursor is on. Value is
6501 null if W's current matrix is invalid, so that no meaningfull glyph
6502 can be returned. */
6504 struct glyph *
6505 get_phys_cursor_glyph (w)
6506 struct window *w;
6508 struct glyph_row *row;
6509 struct glyph *glyph;
6511 if (w->phys_cursor.vpos >= 0
6512 && w->phys_cursor.vpos < w->current_matrix->nrows
6513 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
6514 row->enabled_p)
6515 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
6516 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
6517 else
6518 glyph = NULL;
6520 return glyph;
6524 static int
6525 save_window_save (window, vector, i)
6526 Lisp_Object window;
6527 struct Lisp_Vector *vector;
6528 int i;
6530 register struct saved_window *p;
6531 register struct window *w;
6532 register Lisp_Object tem;
6534 for (;!NILP (window); window = w->next)
6536 p = SAVED_WINDOW_N (vector, i);
6537 w = XWINDOW (window);
6539 XSETFASTINT (w->temslot, i); i++;
6540 p->window = window;
6541 p->buffer = w->buffer;
6542 p->left_col = w->left_col;
6543 p->top_line = w->top_line;
6544 p->total_cols = w->total_cols;
6545 p->total_lines = w->total_lines;
6546 p->hscroll = w->hscroll;
6547 p->min_hscroll = w->min_hscroll;
6548 p->display_table = w->display_table;
6549 p->orig_top_line = w->orig_top_line;
6550 p->orig_total_lines = w->orig_total_lines;
6551 p->left_margin_cols = w->left_margin_cols;
6552 p->right_margin_cols = w->right_margin_cols;
6553 p->left_fringe_width = w->left_fringe_width;
6554 p->right_fringe_width = w->right_fringe_width;
6555 p->fringes_outside_margins = w->fringes_outside_margins;
6556 p->scroll_bar_width = w->scroll_bar_width;
6557 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6558 p->dedicated = w->dedicated;
6559 if (!NILP (w->buffer))
6561 /* Save w's value of point in the window configuration.
6562 If w is the selected window, then get the value of point
6563 from the buffer; pointm is garbage in the selected window. */
6564 if (EQ (window, selected_window))
6566 p->pointm = Fmake_marker ();
6567 set_marker_both (p->pointm, w->buffer,
6568 BUF_PT (XBUFFER (w->buffer)),
6569 BUF_PT_BYTE (XBUFFER (w->buffer)));
6571 else
6572 p->pointm = Fcopy_marker (w->pointm, Qnil);
6574 p->start = Fcopy_marker (w->start, Qnil);
6575 p->start_at_line_beg = w->start_at_line_beg;
6577 tem = XBUFFER (w->buffer)->mark;
6578 p->mark = Fcopy_marker (tem, Qnil);
6580 else
6582 p->pointm = Qnil;
6583 p->start = Qnil;
6584 p->mark = Qnil;
6585 p->start_at_line_beg = Qnil;
6588 if (NILP (w->parent))
6589 p->parent = Qnil;
6590 else
6591 p->parent = XWINDOW (w->parent)->temslot;
6593 if (NILP (w->prev))
6594 p->prev = Qnil;
6595 else
6596 p->prev = XWINDOW (w->prev)->temslot;
6598 if (!NILP (w->vchild))
6599 i = save_window_save (w->vchild, vector, i);
6600 if (!NILP (w->hchild))
6601 i = save_window_save (w->hchild, vector, i);
6604 return i;
6607 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6608 Scurrent_window_configuration, 0, 1, 0,
6609 doc: /* Return an object representing the current window configuration of FRAME.
6610 If FRAME is nil or omitted, use the selected frame.
6611 This describes the number of windows, their sizes and current buffers,
6612 and for each displayed buffer, where display starts, and the positions of
6613 point and mark. An exception is made for point in the current buffer:
6614 its value is -not- saved.
6615 This also records the currently selected frame, and FRAME's focus
6616 redirection (see `redirect-frame-focus'). */)
6617 (frame)
6618 Lisp_Object frame;
6620 register Lisp_Object tem;
6621 register int n_windows;
6622 register struct save_window_data *data;
6623 register struct Lisp_Vector *vec;
6624 register int i;
6625 FRAME_PTR f;
6627 if (NILP (frame))
6628 frame = selected_frame;
6629 CHECK_LIVE_FRAME (frame);
6630 f = XFRAME (frame);
6632 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6633 vec = allocate_other_vector (VECSIZE (struct save_window_data));
6634 data = (struct save_window_data *)vec;
6636 XSETFASTINT (data->frame_cols, FRAME_COLS (f));
6637 XSETFASTINT (data->frame_lines, FRAME_LINES (f));
6638 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
6639 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
6640 data->selected_frame = selected_frame;
6641 data->current_window = FRAME_SELECTED_WINDOW (f);
6642 XSETBUFFER (data->current_buffer, current_buffer);
6643 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6644 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6645 data->root_window = FRAME_ROOT_WINDOW (f);
6646 data->focus_frame = FRAME_FOCUS_FRAME (f);
6647 XSETINT (data->min_height, window_min_height);
6648 XSETINT (data->min_width, window_min_width);
6649 tem = Fmake_vector (make_number (n_windows), Qnil);
6650 data->saved_windows = tem;
6651 for (i = 0; i < n_windows; i++)
6652 XVECTOR (tem)->contents[i]
6653 = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
6654 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6655 XSETWINDOW_CONFIGURATION (tem, data);
6656 return (tem);
6659 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
6660 0, UNEVALLED, 0,
6661 doc: /* Execute BODY, preserving window sizes and contents.
6662 Return the value of the last form in BODY.
6663 Restore which buffer appears in which window, where display starts,
6664 and the value of point and mark for each window.
6665 Also restore the choice of selected window.
6666 Also restore which buffer is current.
6667 Does not restore the value of point in current buffer.
6668 usage: (save-window-excursion BODY...) */)
6669 (args)
6670 Lisp_Object args;
6672 register Lisp_Object val;
6673 register int count = SPECPDL_INDEX ();
6675 record_unwind_protect (Fset_window_configuration,
6676 Fcurrent_window_configuration (Qnil));
6677 val = Fprogn (args);
6678 return unbind_to (count, val);
6683 /***********************************************************************
6684 Window Split Tree
6685 ***********************************************************************/
6687 static Lisp_Object
6688 window_tree (w)
6689 struct window *w;
6691 Lisp_Object tail = Qnil;
6692 Lisp_Object result = Qnil;
6694 while (w)
6696 Lisp_Object wn;
6698 XSETWINDOW (wn, w);
6699 if (!NILP (w->hchild))
6700 wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
6701 window_tree (XWINDOW (w->hchild))));
6702 else if (!NILP (w->vchild))
6703 wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
6704 window_tree (XWINDOW (w->vchild))));
6706 if (NILP (result))
6708 result = tail = Fcons (wn, Qnil);
6710 else
6712 XSETCDR (tail, Fcons (wn, Qnil));
6713 tail = XCDR (tail);
6716 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6719 return result;
6724 DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
6725 0, 1, 0,
6726 doc: /* Return the window tree for frame FRAME.
6728 The return value is a list of the form (ROOT MINI), where ROOT
6729 represents the window tree of the frame's root window, and MINI
6730 is the frame's minibuffer window.
6732 If the root window is not split, ROOT is the root window itself.
6733 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6734 horizontal split, and t for a vertical split, EDGES gives the combined
6735 size and position of the subwindows in the split, and the rest of the
6736 elements are the subwindows in the split. Each of the subwindows may
6737 again be a window or a list representing a window split, and so on.
6738 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6740 If FRAME is nil or omitted, return information on the currently
6741 selected frame. */)
6742 (frame)
6743 Lisp_Object frame;
6745 FRAME_PTR f;
6747 if (NILP (frame))
6748 frame = selected_frame;
6750 CHECK_FRAME (frame);
6751 f = XFRAME (frame);
6753 if (!FRAME_LIVE_P (f))
6754 return Qnil;
6756 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
6760 /***********************************************************************
6761 Marginal Areas
6762 ***********************************************************************/
6764 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6765 2, 3, 0,
6766 doc: /* Set width of marginal areas of window WINDOW.
6767 If WINDOW is nil, set margins of the currently selected window.
6768 Second arg LEFT-WIDTH specifies the number of character cells to
6769 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6770 does the same for the right marginal area. A nil width parameter
6771 means no margin. */)
6772 (window, left_width, right_width)
6773 Lisp_Object window, left_width, right_width;
6775 struct window *w = decode_window (window);
6777 /* Translate negative or zero widths to nil.
6778 Margins that are too wide have to be checked elsewhere. */
6780 if (!NILP (left_width))
6782 CHECK_NUMBER (left_width);
6783 if (XINT (left_width) <= 0)
6784 left_width = Qnil;
6787 if (!NILP (right_width))
6789 CHECK_NUMBER (right_width);
6790 if (XINT (right_width) <= 0)
6791 right_width = Qnil;
6794 if (!EQ (w->left_margin_cols, left_width)
6795 || !EQ (w->right_margin_cols, right_width))
6797 w->left_margin_cols = left_width;
6798 w->right_margin_cols = right_width;
6800 adjust_window_margins (w);
6802 ++windows_or_buffers_changed;
6803 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6806 return Qnil;
6810 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6811 0, 1, 0,
6812 doc: /* Get width of marginal areas of window WINDOW.
6813 If WINDOW is omitted or nil, use the currently selected window.
6814 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6815 If a marginal area does not exist, its width will be returned
6816 as nil. */)
6817 (window)
6818 Lisp_Object window;
6820 struct window *w = decode_window (window);
6821 return Fcons (w->left_margin_cols, w->right_margin_cols);
6826 /***********************************************************************
6827 Fringes
6828 ***********************************************************************/
6830 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6831 2, 4, 0,
6832 doc: /* Set the fringe widths of window WINDOW.
6833 If WINDOW is nil, set the fringe widths of the currently selected
6834 window.
6835 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6836 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6837 fringe width. If a fringe width arg is nil, that means to use the
6838 frame's default fringe width. Default fringe widths can be set with
6839 the command `set-fringe-style'.
6840 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6841 outside of the display margins. By default, fringes are drawn between
6842 display marginal areas and the text area. */)
6843 (window, left_width, right_width, outside_margins)
6844 Lisp_Object window, left_width, right_width, outside_margins;
6846 struct window *w = decode_window (window);
6848 if (!NILP (left_width))
6849 CHECK_NATNUM (left_width);
6850 if (!NILP (right_width))
6851 CHECK_NATNUM (right_width);
6853 /* Do nothing on a tty. */
6854 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6855 && (!EQ (w->left_fringe_width, left_width)
6856 || !EQ (w->right_fringe_width, right_width)
6857 || !EQ (w->fringes_outside_margins, outside_margins)))
6859 w->left_fringe_width = left_width;
6860 w->right_fringe_width = right_width;
6861 w->fringes_outside_margins = outside_margins;
6863 adjust_window_margins (w);
6865 clear_glyph_matrix (w->current_matrix);
6866 w->window_end_valid = Qnil;
6868 ++windows_or_buffers_changed;
6869 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6872 return Qnil;
6876 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6877 0, 1, 0,
6878 doc: /* Get width of fringes of window WINDOW.
6879 If WINDOW is omitted or nil, use the currently selected window.
6880 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6881 (window)
6882 Lisp_Object window;
6884 struct window *w = decode_window (window);
6886 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6887 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6888 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6889 ? Qt : Qnil), Qnil)));
6894 /***********************************************************************
6895 Scroll bars
6896 ***********************************************************************/
6898 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6899 2, 4, 0,
6900 doc: /* Set width and type of scroll bars of window WINDOW.
6901 If window is nil, set scroll bars of the currently selected window.
6902 Second parameter WIDTH specifies the pixel width for the scroll bar;
6903 this is automatically adjusted to a multiple of the frame column width.
6904 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6905 bar: left, right, or nil.
6906 If WIDTH is nil, use the frame's scroll-bar width.
6907 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6908 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6909 (window, width, vertical_type, horizontal_type)
6910 Lisp_Object window, width, vertical_type, horizontal_type;
6912 struct window *w = decode_window (window);
6914 if (!NILP (width))
6916 CHECK_NATNUM (width);
6918 if (XINT (width) == 0)
6919 vertical_type = Qnil;
6922 if (!(NILP (vertical_type)
6923 || EQ (vertical_type, Qleft)
6924 || EQ (vertical_type, Qright)
6925 || EQ (vertical_type, Qt)))
6926 error ("Invalid type of vertical scroll bar");
6928 if (!EQ (w->scroll_bar_width, width)
6929 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6931 w->scroll_bar_width = width;
6932 w->vertical_scroll_bar_type = vertical_type;
6934 adjust_window_margins (w);
6936 clear_glyph_matrix (w->current_matrix);
6937 w->window_end_valid = Qnil;
6939 ++windows_or_buffers_changed;
6940 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6943 return Qnil;
6947 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6948 0, 1, 0,
6949 doc: /* Get width and type of scroll bars of window WINDOW.
6950 If WINDOW is omitted or nil, use the currently selected window.
6951 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6952 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6953 value. */)
6954 (window)
6955 Lisp_Object window;
6957 struct window *w = decode_window (window);
6958 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6959 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6960 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6961 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6962 Fcons (w->vertical_scroll_bar_type,
6963 Fcons (Qnil, Qnil))));
6968 /***********************************************************************
6969 Smooth scrolling
6970 ***********************************************************************/
6972 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6973 doc: /* Return the amount by which WINDOW is scrolled vertically.
6974 Use the selected window if WINDOW is nil or omitted.
6975 Normally, value is a multiple of the canonical character height of WINDOW;
6976 optional second arg PIXELS-P means value is measured in pixels. */)
6977 (window, pixels_p)
6978 Lisp_Object window, pixels_p;
6980 Lisp_Object result;
6981 struct frame *f;
6982 struct window *w;
6984 if (NILP (window))
6985 window = selected_window;
6986 else
6987 CHECK_WINDOW (window);
6988 w = XWINDOW (window);
6989 f = XFRAME (w->frame);
6991 if (FRAME_WINDOW_P (f))
6992 result = (NILP (pixels_p)
6993 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6994 : make_number (-w->vscroll));
6995 else
6996 result = make_number (0);
6997 return result;
7001 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
7002 2, 3, 0,
7003 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
7004 WINDOW nil means use the selected window. Normally, VSCROLL is a
7005 non-negative multiple of the canonical character height of WINDOW;
7006 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
7007 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
7008 corresponds to an integral number of pixels. The return value is the
7009 result of this rounding.
7010 If PIXELS-P is non-nil, the return value is VSCROLL. */)
7011 (window, vscroll, pixels_p)
7012 Lisp_Object window, vscroll, pixels_p;
7014 struct window *w;
7015 struct frame *f;
7017 if (NILP (window))
7018 window = selected_window;
7019 else
7020 CHECK_WINDOW (window);
7021 CHECK_NUMBER_OR_FLOAT (vscroll);
7023 w = XWINDOW (window);
7024 f = XFRAME (w->frame);
7026 if (FRAME_WINDOW_P (f))
7028 int old_dy = w->vscroll;
7030 w->vscroll = - (NILP (pixels_p)
7031 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
7032 : XFLOATINT (vscroll));
7033 w->vscroll = min (w->vscroll, 0);
7035 if (w->vscroll != old_dy)
7037 /* Adjust glyph matrix of the frame if the virtual display
7038 area becomes larger than before. */
7039 if (w->vscroll < 0 && w->vscroll < old_dy)
7040 adjust_glyphs (f);
7042 /* Prevent redisplay shortcuts. */
7043 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
7047 return Fwindow_vscroll (window, pixels_p);
7051 /* Call FN for all leaf windows on frame F. FN is called with the
7052 first argument being a pointer to the leaf window, and with
7053 additional argument USER_DATA. Stops when FN returns 0. */
7055 void
7056 foreach_window (f, fn, user_data)
7057 struct frame *f;
7058 int (* fn) P_ ((struct window *, void *));
7059 void *user_data;
7061 /* Fdelete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
7062 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
7063 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
7067 /* Helper function for foreach_window. Call FN for all leaf windows
7068 reachable from W. FN is called with the first argument being a
7069 pointer to the leaf window, and with additional argument USER_DATA.
7070 Stop when FN returns 0. Value is 0 if stopped by FN. */
7072 static int
7073 foreach_window_1 (w, fn, user_data)
7074 struct window *w;
7075 int (* fn) P_ ((struct window *, void *));
7076 void *user_data;
7078 int cont;
7080 for (cont = 1; w && cont;)
7082 if (!NILP (w->hchild))
7083 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
7084 else if (!NILP (w->vchild))
7085 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
7086 else
7087 cont = fn (w, user_data);
7089 w = NILP (w->next) ? 0 : XWINDOW (w->next);
7092 return cont;
7096 /* Freeze or unfreeze the window start of W unless it is a
7097 mini-window or the selected window. FREEZE_P non-null means freeze
7098 the window start. */
7100 static int
7101 freeze_window_start (w, freeze_p)
7102 struct window *w;
7103 void *freeze_p;
7105 if (w == XWINDOW (selected_window)
7106 || MINI_WINDOW_P (w)
7107 || (MINI_WINDOW_P (XWINDOW (selected_window))
7108 && ! NILP (Vminibuf_scroll_window)
7109 && w == XWINDOW (Vminibuf_scroll_window)))
7110 freeze_p = NULL;
7112 w->frozen_window_start_p = freeze_p != NULL;
7113 return 1;
7117 /* Freeze or unfreeze the window starts of all leaf windows on frame
7118 F, except the selected window and a mini-window. FREEZE_P non-zero
7119 means freeze the window start. */
7121 void
7122 freeze_window_starts (f, freeze_p)
7123 struct frame *f;
7124 int freeze_p;
7126 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
7130 /***********************************************************************
7131 Initialization
7132 ***********************************************************************/
7134 /* Return 1 if window configurations C1 and C2
7135 describe the same state of affairs. This is used by Fequal. */
7138 compare_window_configurations (c1, c2, ignore_positions)
7139 Lisp_Object c1, c2;
7140 int ignore_positions;
7142 register struct save_window_data *d1, *d2;
7143 struct Lisp_Vector *sw1, *sw2;
7144 int i;
7146 CHECK_WINDOW_CONFIGURATION (c1);
7147 CHECK_WINDOW_CONFIGURATION (c2);
7149 d1 = (struct save_window_data *) XVECTOR (c1);
7150 d2 = (struct save_window_data *) XVECTOR (c2);
7151 sw1 = XVECTOR (d1->saved_windows);
7152 sw2 = XVECTOR (d2->saved_windows);
7154 if (! EQ (d1->frame_cols, d2->frame_cols))
7155 return 0;
7156 if (! EQ (d1->frame_lines, d2->frame_lines))
7157 return 0;
7158 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
7159 return 0;
7160 if (! EQ (d1->selected_frame, d2->selected_frame))
7161 return 0;
7162 /* Don't compare the current_window field directly.
7163 Instead see w1_is_current and w2_is_current, below. */
7164 if (! EQ (d1->current_buffer, d2->current_buffer))
7165 return 0;
7166 if (! ignore_positions)
7168 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
7169 return 0;
7170 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
7171 return 0;
7173 /* Don't compare the root_window field.
7174 We don't require the two configurations
7175 to use the same window object,
7176 and the two root windows must be equivalent
7177 if everything else compares equal. */
7178 if (! EQ (d1->focus_frame, d2->focus_frame))
7179 return 0;
7180 if (! EQ (d1->min_width, d2->min_width))
7181 return 0;
7182 if (! EQ (d1->min_height, d2->min_height))
7183 return 0;
7185 /* Verify that the two confis have the same number of windows. */
7186 if (sw1->size != sw2->size)
7187 return 0;
7189 for (i = 0; i < sw1->size; i++)
7191 struct saved_window *p1, *p2;
7192 int w1_is_current, w2_is_current;
7194 p1 = SAVED_WINDOW_N (sw1, i);
7195 p2 = SAVED_WINDOW_N (sw2, i);
7197 /* Verify that the current windows in the two
7198 configurations correspond to each other. */
7199 w1_is_current = EQ (d1->current_window, p1->window);
7200 w2_is_current = EQ (d2->current_window, p2->window);
7202 if (w1_is_current != w2_is_current)
7203 return 0;
7205 /* Verify that the corresponding windows do match. */
7206 if (! EQ (p1->buffer, p2->buffer))
7207 return 0;
7208 if (! EQ (p1->left_col, p2->left_col))
7209 return 0;
7210 if (! EQ (p1->top_line, p2->top_line))
7211 return 0;
7212 if (! EQ (p1->total_cols, p2->total_cols))
7213 return 0;
7214 if (! EQ (p1->total_lines, p2->total_lines))
7215 return 0;
7216 if (! EQ (p1->display_table, p2->display_table))
7217 return 0;
7218 if (! EQ (p1->parent, p2->parent))
7219 return 0;
7220 if (! EQ (p1->prev, p2->prev))
7221 return 0;
7222 if (! ignore_positions)
7224 if (! EQ (p1->hscroll, p2->hscroll))
7225 return 0;
7226 if (!EQ (p1->min_hscroll, p2->min_hscroll))
7227 return 0;
7228 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
7229 return 0;
7230 if (NILP (Fequal (p1->start, p2->start)))
7231 return 0;
7232 if (NILP (Fequal (p1->pointm, p2->pointm)))
7233 return 0;
7234 if (NILP (Fequal (p1->mark, p2->mark)))
7235 return 0;
7237 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
7238 return 0;
7239 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
7240 return 0;
7241 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
7242 return 0;
7243 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
7244 return 0;
7245 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
7246 return 0;
7247 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
7248 return 0;
7249 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
7250 return 0;
7253 return 1;
7256 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7257 Scompare_window_configurations, 2, 2, 0,
7258 doc: /* Compare two window configurations as regards the structure of windows.
7259 This function ignores details such as the values of point and mark
7260 and scrolling positions. */)
7261 (x, y)
7262 Lisp_Object x, y;
7264 if (compare_window_configurations (x, y, 1))
7265 return Qt;
7266 return Qnil;
7269 void
7270 init_window_once ()
7272 struct frame *f = make_terminal_frame ();
7273 XSETFRAME (selected_frame, f);
7274 Vterminal_frame = selected_frame;
7275 minibuf_window = f->minibuffer_window;
7276 selected_window = f->selected_window;
7277 last_nonminibuf_frame = f;
7279 window_initialized = 1;
7282 void
7283 init_window ()
7285 Vwindow_list = Qnil;
7288 void
7289 syms_of_window ()
7291 Qscroll_up = intern ("scroll-up");
7292 staticpro (&Qscroll_up);
7294 Qscroll_down = intern ("scroll-down");
7295 staticpro (&Qscroll_down);
7297 Qwindow_size_fixed = intern ("window-size-fixed");
7298 staticpro (&Qwindow_size_fixed);
7299 Fset (Qwindow_size_fixed, Qnil);
7301 staticpro (&Qwindow_configuration_change_hook);
7302 Qwindow_configuration_change_hook
7303 = intern ("window-configuration-change-hook");
7305 Qwindowp = intern ("windowp");
7306 staticpro (&Qwindowp);
7308 Qwindow_configuration_p = intern ("window-configuration-p");
7309 staticpro (&Qwindow_configuration_p);
7311 Qwindow_live_p = intern ("window-live-p");
7312 staticpro (&Qwindow_live_p);
7314 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
7315 staticpro (&Qtemp_buffer_show_hook);
7317 staticpro (&Vwindow_list);
7319 minibuf_selected_window = Qnil;
7320 staticpro (&minibuf_selected_window);
7322 window_scroll_pixel_based_preserve_y = -1;
7324 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
7325 doc: /* Non-nil means call as function to display a help buffer.
7326 The function is called with one argument, the buffer to be displayed.
7327 Used by `with-output-to-temp-buffer'.
7328 If this function is used, then it must do the entire job of showing
7329 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7330 Vtemp_buffer_show_function = Qnil;
7332 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
7333 doc: /* If non-nil, function to call to handle `display-buffer'.
7334 It will receive two args, the buffer and a flag which if non-nil means
7335 that the currently selected window is not acceptable.
7336 It should choose or create a window, display the specified buffer in it,
7337 and return the window.
7338 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
7339 work using this function. */);
7340 Vdisplay_buffer_function = Qnil;
7342 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
7343 doc: /* *If non-nil, `display-buffer' should even the window heights.
7344 If nil, `display-buffer' will leave the window configuration alone. */);
7345 Veven_window_heights = Qt;
7347 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
7348 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7349 Vminibuf_scroll_window = Qnil;
7351 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
7352 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7353 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7354 is displayed in the `mode-line' face. */);
7355 mode_line_in_non_selected_windows = 1;
7357 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
7358 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7359 Vother_window_scroll_buffer = Qnil;
7361 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
7362 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
7363 pop_up_frames = 0;
7365 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
7366 doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7367 auto_window_vscroll_p = 1;
7369 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
7370 doc: /* *Non-nil means `display-buffer' should reuse frames.
7371 If the buffer in question is already displayed in a frame, raise that frame. */);
7372 display_buffer_reuse_frames = 0;
7374 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
7375 doc: /* Function to call to handle automatic new frame creation.
7376 It is called with no arguments and should return a newly created frame.
7378 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
7379 where `pop-up-frame-alist' would hold the default frame parameters. */);
7380 Vpop_up_frame_function = Qnil;
7382 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
7383 doc: /* *List of buffer names that should have their own special frames.
7384 Displaying a buffer with `display-buffer' or `pop-to-buffer',
7385 if its name is in this list, makes a special frame for it
7386 using `special-display-function'. See also `special-display-regexps'.
7388 An element of the list can be a list instead of just a string.
7389 There are two ways to use a list as an element:
7390 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
7391 In the first case, the FRAME-PARAMETERS are pairs of the form
7392 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7393 In the second case, FUNCTION is called with BUFFER as the first argument,
7394 followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
7395 All this is done by the function found in `special-display-function'.
7397 If the specified frame parameters include (same-buffer . t), the
7398 buffer is displayed in the currently selected window. Otherwise, if
7399 they include (same-frame . t), the buffer is displayed in a new window
7400 in the currently selected frame.
7402 If this variable appears \"not to work\", because you add a name to it
7403 but that buffer still appears in the selected window, look at the
7404 values of `same-window-buffer-names' and `same-window-regexps'.
7405 Those variables take precedence over this one. */);
7406 Vspecial_display_buffer_names = Qnil;
7408 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
7409 doc: /* *List of regexps saying which buffers should have their own special frames.
7410 When displaying a buffer with `display-buffer' or `pop-to-buffer',
7411 if any regexp in this list matches the buffer name, it makes a
7412 special frame for the buffer by calling `special-display-function'.
7414 An element of the list can be a list instead of just a string.
7415 There are two ways to use a list as an element:
7416 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
7417 In the first case, the FRAME-PARAMETERS are pairs of the form
7418 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7419 In the second case, FUNCTION is called with BUFFER as the first argument,
7420 followed by the OTHER-ARGS--it can display the buffer in any way it likes.
7421 All this is done by the function found in `special-display-function'.
7423 If the specified frame parameters include (same-buffer . t), the
7424 buffer is displayed in the currently selected window. Otherwise, if
7425 they include (same-frame . t), the buffer is displayed in a new window
7426 in the currently selected frame.
7428 If this variable appears \"not to work\", because you add a regexp to it
7429 but the matching buffers still appear in the selected window, look at the
7430 values of `same-window-buffer-names' and `same-window-regexps'.
7431 Those variables take precedence over this one. */);
7432 Vspecial_display_regexps = Qnil;
7434 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
7435 doc: /* Function to call to make a new frame for a special buffer.
7436 It is called with two arguments, the buffer and optional buffer specific
7437 data, and should return a window displaying that buffer.
7438 The default value normally makes a separate frame for the buffer,
7439 using `special-display-frame-alist' to specify the frame parameters.
7440 But if the buffer specific data includes (same-buffer . t) then the
7441 buffer is displayed in the current selected window.
7442 Otherwise if it includes (same-frame . t) then the buffer is displayed in
7443 a new window in the currently selected frame.
7445 A buffer is special if it is listed in `special-display-buffer-names'
7446 or matches a regexp in `special-display-regexps'. */);
7447 Vspecial_display_function = Qnil;
7449 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
7450 doc: /* *List of buffer names that should appear in the selected window.
7451 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
7452 switches to it in the selected window, rather than making it appear
7453 in some other window.
7455 An element of the list can be a cons cell instead of just a string.
7456 Then the car must be a string, which specifies the buffer name.
7457 This is for compatibility with `special-display-buffer-names';
7458 the cdr of the cons cell is ignored.
7460 See also `same-window-regexps'. */);
7461 Vsame_window_buffer_names = Qnil;
7463 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
7464 doc: /* *List of regexps saying which buffers should appear in the selected window.
7465 If a buffer name matches one of these regexps, then displaying it
7466 using `display-buffer' or `pop-to-buffer' switches to it
7467 in the selected window, rather than making it appear in some other window.
7469 An element of the list can be a cons cell instead of just a string.
7470 Then the car must be a string, which specifies the buffer name.
7471 This is for compatibility with `special-display-buffer-names';
7472 the cdr of the cons cell is ignored.
7474 See also `same-window-buffer-names'. */);
7475 Vsame_window_regexps = Qnil;
7477 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
7478 doc: /* *Non-nil means display-buffer should make new windows. */);
7479 pop_up_windows = 1;
7481 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
7482 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
7483 next_screen_context_lines = 2;
7485 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
7486 doc: /* *A window must be at least this tall to be eligible for splitting
7487 by `display-buffer'. The value is in line units.
7488 If there is only one window, it is split regardless of this value. */);
7489 split_height_threshold = 500;
7491 DEFVAR_INT ("window-min-height", &window_min_height,
7492 doc: /* *Delete any window less than this tall (including its mode line).
7493 The value is in line units. */);
7494 window_min_height = 4;
7496 DEFVAR_INT ("window-min-width", &window_min_width,
7497 doc: /* *Delete any window less than this wide (measured in characters). */);
7498 window_min_width = 10;
7500 DEFVAR_LISP ("scroll-preserve-screen-position",
7501 &Vscroll_preserve_screen_position,
7502 doc: /* *Controls if scroll commands move point to keep its screen line unchanged.
7503 A value of nil means point does not keep its screen position except
7504 at the scroll margin or window boundary respectively.
7505 A value of t means point keeps its screen position if the scroll
7506 command moved it vertically out of the window, e.g. when scrolling
7507 by full screens.
7508 Any other value means point always keeps its screen position. */);
7509 Vscroll_preserve_screen_position = Qnil;
7511 DEFVAR_LISP ("window-configuration-change-hook",
7512 &Vwindow_configuration_change_hook,
7513 doc: /* Functions to call when window configuration changes.
7514 The selected frame is the one whose configuration has changed. */);
7515 Vwindow_configuration_change_hook = Qnil;
7517 defsubr (&Sselected_window);
7518 defsubr (&Sminibuffer_window);
7519 defsubr (&Swindow_minibuffer_p);
7520 defsubr (&Swindowp);
7521 defsubr (&Swindow_live_p);
7522 defsubr (&Spos_visible_in_window_p);
7523 defsubr (&Swindow_line_height);
7524 defsubr (&Swindow_buffer);
7525 defsubr (&Swindow_height);
7526 defsubr (&Swindow_width);
7527 defsubr (&Swindow_full_width_p);
7528 defsubr (&Swindow_hscroll);
7529 defsubr (&Sset_window_hscroll);
7530 defsubr (&Swindow_redisplay_end_trigger);
7531 defsubr (&Sset_window_redisplay_end_trigger);
7532 defsubr (&Swindow_edges);
7533 defsubr (&Swindow_pixel_edges);
7534 defsubr (&Swindow_inside_edges);
7535 defsubr (&Swindow_inside_pixel_edges);
7536 defsubr (&Scoordinates_in_window_p);
7537 defsubr (&Swindow_at);
7538 defsubr (&Swindow_point);
7539 defsubr (&Swindow_start);
7540 defsubr (&Swindow_end);
7541 defsubr (&Sset_window_point);
7542 defsubr (&Sset_window_start);
7543 defsubr (&Swindow_dedicated_p);
7544 defsubr (&Sset_window_dedicated_p);
7545 defsubr (&Swindow_display_table);
7546 defsubr (&Sset_window_display_table);
7547 defsubr (&Snext_window);
7548 defsubr (&Sprevious_window);
7549 defsubr (&Sother_window);
7550 defsubr (&Sget_lru_window);
7551 defsubr (&Sget_largest_window);
7552 defsubr (&Sget_buffer_window);
7553 defsubr (&Sdelete_other_windows);
7554 defsubr (&Sdelete_windows_on);
7555 defsubr (&Sreplace_buffer_in_windows);
7556 defsubr (&Sdelete_window);
7557 defsubr (&Sset_window_buffer);
7558 defsubr (&Sselect_window);
7559 defsubr (&Sspecial_display_p);
7560 defsubr (&Ssame_window_p);
7561 defsubr (&Sdisplay_buffer);
7562 defsubr (&Sforce_window_update);
7563 defsubr (&Ssplit_window);
7564 defsubr (&Senlarge_window);
7565 defsubr (&Sshrink_window);
7566 defsubr (&Sadjust_window_trailing_edge);
7567 defsubr (&Sscroll_up);
7568 defsubr (&Sscroll_down);
7569 defsubr (&Sscroll_left);
7570 defsubr (&Sscroll_right);
7571 defsubr (&Sother_window_for_scrolling);
7572 defsubr (&Sscroll_other_window);
7573 defsubr (&Sminibuffer_selected_window);
7574 defsubr (&Srecenter);
7575 defsubr (&Swindow_text_height);
7576 defsubr (&Smove_to_window_line);
7577 defsubr (&Swindow_configuration_p);
7578 defsubr (&Swindow_configuration_frame);
7579 defsubr (&Sset_window_configuration);
7580 defsubr (&Scurrent_window_configuration);
7581 defsubr (&Ssave_window_excursion);
7582 defsubr (&Swindow_tree);
7583 defsubr (&Sset_window_margins);
7584 defsubr (&Swindow_margins);
7585 defsubr (&Sset_window_fringes);
7586 defsubr (&Swindow_fringes);
7587 defsubr (&Sset_window_scroll_bars);
7588 defsubr (&Swindow_scroll_bars);
7589 defsubr (&Swindow_vscroll);
7590 defsubr (&Sset_window_vscroll);
7591 defsubr (&Scompare_window_configurations);
7592 defsubr (&Swindow_list);
7595 void
7596 keys_of_window ()
7598 initial_define_key (control_x_map, '1', "delete-other-windows");
7599 initial_define_key (control_x_map, '2', "split-window");
7600 initial_define_key (control_x_map, '0', "delete-window");
7601 initial_define_key (control_x_map, 'o', "other-window");
7602 initial_define_key (control_x_map, '^', "enlarge-window");
7603 initial_define_key (control_x_map, '<', "scroll-left");
7604 initial_define_key (control_x_map, '>', "scroll-right");
7606 initial_define_key (global_map, Ctl ('V'), "scroll-up");
7607 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7608 initial_define_key (meta_map, 'v', "scroll-down");
7610 initial_define_key (global_map, Ctl('L'), "recenter");
7611 initial_define_key (meta_map, 'r', "move-to-window-line");
7614 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7615 (do not change this comment) */