* quail/cyrillic.el ("cyrillic-translit"): Add g' for Ukrainian G with upturn.
[emacs.git] / src / window.c
blob57452b313e963dcca04d5758fe9fb665ca369a27
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
4 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 Free Software Foundation, Inc.
7 This file is part of GNU Emacs.
9 GNU Emacs is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
24 #include <config.h>
25 #include "lisp.h"
26 #include "buffer.h"
27 #include "keyboard.h"
28 #include "keymap.h"
29 #include "frame.h"
30 #include "window.h"
31 #include "commands.h"
32 #include "indent.h"
33 #include "termchar.h"
34 #include "disptab.h"
35 #include "dispextern.h"
36 #include "blockinput.h"
37 #include "intervals.h"
39 #ifdef HAVE_X_WINDOWS
40 #include "xterm.h"
41 #endif /* HAVE_X_WINDOWS */
42 #ifdef WINDOWSNT
43 #include "w32term.h"
44 #endif
45 #ifdef MSDOS
46 #include "msdos.h"
47 #endif
48 #ifdef MAC_OS
49 #include "macterm.h"
50 #endif
53 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
54 Lisp_Object Qscroll_up, Qscroll_down;
55 Lisp_Object Qwindow_size_fixed;
56 extern Lisp_Object Qleft_margin, Qright_margin;
58 static int displayed_window_lines P_ ((struct window *));
59 static struct window *decode_window P_ ((Lisp_Object));
60 static int count_windows P_ ((struct window *));
61 static int get_leaf_windows P_ ((struct window *, struct window **, int));
62 static void window_scroll P_ ((Lisp_Object, int, int, int));
63 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
64 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
65 static int window_min_size_1 P_ ((struct window *, int));
66 static int window_min_size_2 P_ ((struct window *, int));
67 static int window_min_size P_ ((struct window *, int, int, int *));
68 static void size_window P_ ((Lisp_Object, int, int, int, int, int));
69 static int freeze_window_start P_ ((struct window *, void *));
70 static int window_fixed_size_p P_ ((struct window *, int, int));
71 static void enlarge_window P_ ((Lisp_Object, int, int));
72 static Lisp_Object window_list P_ ((void));
73 static int add_window_to_list P_ ((struct window *, void *));
74 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
75 Lisp_Object));
76 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
77 Lisp_Object, int));
78 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
79 Lisp_Object *));
80 static int foreach_window_1 P_ ((struct window *,
81 int (* fn) (struct window *, void *),
82 void *));
83 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
85 /* This is the window in which the terminal's cursor should
86 be left when nothing is being done with it. This must
87 always be a leaf window, and its buffer is selected by
88 the top level editing loop at the end of each command.
90 This value is always the same as
91 FRAME_SELECTED_WINDOW (selected_frame). */
93 Lisp_Object selected_window;
95 /* A list of all windows for use by next_window and Fwindow_list.
96 Functions creating or deleting windows should invalidate this cache
97 by setting it to nil. */
99 Lisp_Object Vwindow_list;
101 /* The mini-buffer window of the selected frame.
102 Note that you cannot test for mini-bufferness of an arbitrary window
103 by comparing against this; but you can test for mini-bufferness of
104 the selected window. */
106 Lisp_Object minibuf_window;
108 /* Non-nil means it is the window whose mode line should be
109 shown as the selected window when the minibuffer is selected. */
111 Lisp_Object minibuf_selected_window;
113 /* Non-nil means it is the window for C-M-v to scroll
114 when the mini-buffer is selected. */
116 Lisp_Object Vminibuf_scroll_window;
118 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
120 Lisp_Object Vother_window_scroll_buffer;
122 /* Non-nil means it's function to call to display temp buffers. */
124 Lisp_Object Vtemp_buffer_show_function;
126 /* Non-zero means line and page scrolling on tall lines (with images)
127 does partial scrolling by modifying window-vscroll. */
129 int auto_window_vscroll_p;
131 /* Non-zero means to use mode-line-inactive face in all windows but the
132 selected-window and the minibuffer-scroll-window when the
133 minibuffer is active. */
134 int mode_line_in_non_selected_windows;
136 /* If a window gets smaller than either of these, it is removed. */
138 EMACS_INT window_min_height;
139 EMACS_INT window_min_width;
141 /* Nonzero implies Fdisplay_buffer should create windows. */
143 int pop_up_windows;
145 /* Nonzero implies make new frames for Fdisplay_buffer. */
147 int pop_up_frames;
149 /* Nonzero means reuse existing frames for displaying buffers. */
151 int display_buffer_reuse_frames;
153 /* Non-nil means use this function instead of default */
155 Lisp_Object Vpop_up_frame_function;
157 /* Function to call to handle Fdisplay_buffer. */
159 Lisp_Object Vdisplay_buffer_function;
161 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
163 Lisp_Object Veven_window_heights;
165 /* List of buffer *names* for buffers that should have their own frames. */
167 Lisp_Object Vspecial_display_buffer_names;
169 /* List of regexps for buffer names that should have their own frames. */
171 Lisp_Object Vspecial_display_regexps;
173 /* Function to pop up a special frame. */
175 Lisp_Object Vspecial_display_function;
177 /* List of buffer *names* for buffers to appear in selected window. */
179 Lisp_Object Vsame_window_buffer_names;
181 /* List of regexps for buffer names to appear in selected window. */
183 Lisp_Object Vsame_window_regexps;
185 /* Hook run at end of temp_output_buffer_show. */
187 Lisp_Object Qtemp_buffer_show_hook;
189 /* Fdisplay_buffer always splits the largest window
190 if that window is more than this high. */
192 EMACS_INT split_height_threshold;
194 /* Number of lines of continuity in scrolling by screenfuls. */
196 EMACS_INT next_screen_context_lines;
198 /* Incremented for each window created. */
200 static int sequence_number;
202 /* Nonzero after init_window_once has finished. */
204 static int window_initialized;
206 /* Hook to run when window config changes. */
208 Lisp_Object Qwindow_configuration_change_hook;
209 Lisp_Object Vwindow_configuration_change_hook;
211 /* Non-nil means scroll commands try to put point
212 at the same screen height as previously. */
214 Lisp_Object Vscroll_preserve_screen_position;
216 /* Incremented by 1 whenever a window is deleted. */
218 int window_deletion_count;
220 /* Used by the function window_scroll_pixel_based */
222 static int window_scroll_pixel_based_preserve_y;
224 #if 0 /* This isn't used anywhere. */
225 /* Nonzero means we can split a frame even if it is "unsplittable". */
226 static int inhibit_frame_unsplittable;
227 #endif /* 0 */
229 extern EMACS_INT scroll_margin;
231 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
233 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
234 doc: /* Returns t if OBJECT is a window. */)
235 (object)
236 Lisp_Object object;
238 return WINDOWP (object) ? Qt : Qnil;
241 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
242 doc: /* Returns t if OBJECT is a window which is currently visible. */)
243 (object)
244 Lisp_Object object;
246 return WINDOW_LIVE_P (object) ? Qt : Qnil;
249 Lisp_Object
250 make_window ()
252 Lisp_Object val;
253 register struct window *p;
255 p = allocate_window ();
256 ++sequence_number;
257 XSETFASTINT (p->sequence_number, sequence_number);
258 XSETFASTINT (p->left_col, 0);
259 XSETFASTINT (p->top_line, 0);
260 XSETFASTINT (p->total_lines, 0);
261 XSETFASTINT (p->total_cols, 0);
262 XSETFASTINT (p->hscroll, 0);
263 XSETFASTINT (p->min_hscroll, 0);
264 p->orig_top_line = p->orig_total_lines = Qnil;
265 p->start = Fmake_marker ();
266 p->pointm = Fmake_marker ();
267 XSETFASTINT (p->use_time, 0);
268 p->frame = Qnil;
269 p->display_table = Qnil;
270 p->dedicated = Qnil;
271 p->pseudo_window_p = 0;
272 bzero (&p->cursor, sizeof (p->cursor));
273 bzero (&p->last_cursor, sizeof (p->last_cursor));
274 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
275 p->desired_matrix = p->current_matrix = 0;
276 p->nrows_scale_factor = p->ncols_scale_factor = 1;
277 p->phys_cursor_type = -1;
278 p->phys_cursor_width = -1;
279 p->must_be_updated_p = 0;
280 XSETFASTINT (p->window_end_vpos, 0);
281 XSETFASTINT (p->window_end_pos, 0);
282 p->window_end_valid = Qnil;
283 p->vscroll = 0;
284 XSETWINDOW (val, p);
285 XSETFASTINT (p->last_point, 0);
286 p->frozen_window_start_p = 0;
287 p->last_cursor_off_p = p->cursor_off_p = 0;
288 p->left_margin_cols = Qnil;
289 p->right_margin_cols = Qnil;
290 p->left_fringe_width = Qnil;
291 p->right_fringe_width = Qnil;
292 p->fringes_outside_margins = Qnil;
293 p->scroll_bar_width = Qnil;
294 p->vertical_scroll_bar_type = Qt;
296 Vwindow_list = Qnil;
297 return val;
300 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
301 doc: /* Return the window that the cursor now appears in and commands apply to. */)
304 return selected_window;
307 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
308 doc: /* Return the window used now for minibuffers.
309 If the optional argument FRAME is specified, return the minibuffer window
310 used by that frame. */)
311 (frame)
312 Lisp_Object frame;
314 if (NILP (frame))
315 frame = selected_frame;
316 CHECK_LIVE_FRAME (frame);
317 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
320 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
321 doc: /* Returns non-nil if WINDOW is a minibuffer window.
322 WINDOW defaults to the selected window. */)
323 (window)
324 Lisp_Object window;
326 struct window *w = decode_window (window);
327 return MINI_WINDOW_P (w) ? Qt : Qnil;
331 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
332 Spos_visible_in_window_p, 0, 3, 0,
333 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
334 Return nil if that position is scrolled vertically out of view.
335 If a character is only partially visible, nil is returned, unless the
336 optional argument PARTIALLY is non-nil.
337 If POS is only out of view because of horizontal scrolling, return non-nil.
338 If POS is t, it specifies the position of the last visible glyph in WINDOW.
339 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
341 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
342 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
343 where X and Y are the pixel coordinates relative to the top left corner
344 of the window. The remaining elements are omitted if the character after
345 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
346 off-window at the top and bottom of the row, ROWH is the height of the
347 display row, and VPOS is the row number (0-based) containing POS. */)
348 (pos, window, partially)
349 Lisp_Object pos, window, partially;
351 register struct window *w;
352 register int posint;
353 register struct buffer *buf;
354 struct text_pos top;
355 Lisp_Object in_window = Qnil;
356 int rtop, rbot, rowh, vpos, fully_p = 1;
357 int x, y;
359 w = decode_window (window);
360 buf = XBUFFER (w->buffer);
361 SET_TEXT_POS_FROM_MARKER (top, w->start);
363 if (EQ (pos, Qt))
364 posint = -1;
365 else if (!NILP (pos))
367 CHECK_NUMBER_COERCE_MARKER (pos);
368 posint = XINT (pos);
370 else if (w == XWINDOW (selected_window))
371 posint = PT;
372 else
373 posint = XMARKER (w->pointm)->charpos;
375 /* If position is above window start or outside buffer boundaries,
376 or if window start is out of range, position is not visible. */
377 if ((EQ (pos, Qt)
378 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
379 && CHARPOS (top) >= BUF_BEGV (buf)
380 && CHARPOS (top) <= BUF_ZV (buf)
381 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
382 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
383 in_window = Qt;
385 if (!NILP (in_window) && !NILP (partially))
387 Lisp_Object part = Qnil;
388 if (!fully_p)
389 part = list4 (make_number (rtop), make_number (rbot),
390 make_number (rowh), make_number (vpos));
391 in_window = Fcons (make_number (x),
392 Fcons (make_number (y), part));
395 return in_window;
398 DEFUN ("window-line-height", Fwindow_line_height,
399 Swindow_line_height, 0, 2, 0,
400 doc: /* Return height in pixels of text line LINE in window WINDOW.
401 If WINDOW is nil or omitted, use selected window.
403 Return height of current line if LINE is omitted or nil. Return height of
404 header or mode line if LINE is `header-line' and `mode-line'.
405 Otherwise, LINE is a text line number starting from 0. A negative number
406 counts from the end of the window.
408 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
409 in pixels of the visible part of the line, VPOS and YPOS are the
410 vertical position in lines and pixels of the line, relative to the top
411 of the first text line, and OFFBOT is the number of off-window pixels at
412 the bottom of the text line. If there are off-window pixels at the top
413 of the (first) text line, YPOS is negative.
415 Return nil if window display is not up-to-date. In that case, use
416 `pos-visible-in-window-p' to obtain the information. */)
417 (line, window)
418 Lisp_Object line, window;
420 register struct window *w;
421 register struct buffer *b;
422 struct glyph_row *row, *end_row;
423 int max_y, crop, i, n;
425 w = decode_window (window);
427 if (noninteractive
428 || w->pseudo_window_p)
429 return Qnil;
431 CHECK_BUFFER (w->buffer);
432 b = XBUFFER (w->buffer);
434 /* Fail if current matrix is not up-to-date. */
435 if (NILP (w->window_end_valid)
436 || current_buffer->clip_changed
437 || current_buffer->prevent_redisplay_optimizations_p
438 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
439 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
440 return Qnil;
442 if (NILP (line))
444 i = w->cursor.vpos;
445 if (i < 0 || i >= w->current_matrix->nrows
446 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
447 return Qnil;
448 max_y = window_text_bottom_y (w);
449 goto found_row;
452 if (EQ (line, Qheader_line))
454 if (!WINDOW_WANTS_HEADER_LINE_P (w))
455 return Qnil;
456 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
457 if (!row->enabled_p)
458 return Qnil;
459 return list4 (make_number (row->height),
460 make_number (0), make_number (0),
461 make_number (0));
464 if (EQ (line, Qmode_line))
466 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
467 if (!row->enabled_p)
468 return Qnil;
469 return list4 (make_number (row->height),
470 make_number (0), /* not accurate */
471 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
472 + window_text_bottom_y (w)),
473 make_number (0));
476 CHECK_NUMBER (line);
477 n = XINT (line);
479 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
480 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
481 max_y = window_text_bottom_y (w);
482 i = 0;
484 while ((n < 0 || i < n)
485 && row <= end_row && row->enabled_p
486 && row->y + row->height < max_y)
487 row++, i++;
489 if (row > end_row || !row->enabled_p)
490 return Qnil;
492 if (++n < 0)
494 if (-n > i)
495 return Qnil;
496 row += n;
497 i += n;
500 found_row:
501 crop = max (0, (row->y + row->height) - max_y);
502 return list4 (make_number (row->height + min (0, row->y) - crop),
503 make_number (i),
504 make_number (row->y),
505 make_number (crop));
510 static struct window *
511 decode_window (window)
512 register Lisp_Object window;
514 if (NILP (window))
515 return XWINDOW (selected_window);
517 CHECK_LIVE_WINDOW (window);
518 return XWINDOW (window);
521 static struct window *
522 decode_any_window (window)
523 register Lisp_Object window;
525 if (NILP (window))
526 return XWINDOW (selected_window);
528 CHECK_WINDOW (window);
529 return XWINDOW (window);
532 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
533 doc: /* Return the buffer that WINDOW is displaying.
534 WINDOW defaults to the selected window. */)
535 (window)
536 Lisp_Object window;
538 return decode_window (window)->buffer;
541 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
542 doc: /* Return the number of lines in WINDOW (including its mode line).
543 WINDOW defaults to the selected window. */)
544 (window)
545 Lisp_Object window;
547 return decode_any_window (window)->total_lines;
550 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
551 doc: /* Return the number of display columns in WINDOW.
552 This is the width that is usable columns available for text in WINDOW.
553 If you want to find out how many columns WINDOW takes up,
554 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
555 (window)
556 Lisp_Object window;
558 return make_number (window_box_text_cols (decode_any_window (window)));
561 DEFUN ("window-full-width-p", Fwindow_full_width_p, Swindow_full_width_p, 0, 1, 0,
562 doc: /* Return t if WINDOW is as wide as its frame.
563 WINDOW defaults to the selected window. */)
564 (window)
565 Lisp_Object window;
567 return WINDOW_FULL_WIDTH_P (decode_any_window (window)) ? Qt : Qnil;
570 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
571 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
572 WINDOW defaults to the selected window. */)
573 (window)
574 Lisp_Object window;
576 return decode_window (window)->hscroll;
579 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
580 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
581 Return NCOL. NCOL should be zero or positive.
583 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
584 window so that the location of point moves off-window. */)
585 (window, ncol)
586 Lisp_Object window, ncol;
588 struct window *w = decode_window (window);
589 int hscroll;
591 CHECK_NUMBER (ncol);
592 hscroll = max (0, XINT (ncol));
594 /* Prevent redisplay shortcuts when changing the hscroll. */
595 if (XINT (w->hscroll) != hscroll)
596 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
598 w->hscroll = make_number (hscroll);
599 return ncol;
602 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
603 Swindow_redisplay_end_trigger, 0, 1, 0,
604 doc: /* Return WINDOW's redisplay end trigger value.
605 WINDOW defaults to the selected window.
606 See `set-window-redisplay-end-trigger' for more information. */)
607 (window)
608 Lisp_Object window;
610 return decode_window (window)->redisplay_end_trigger;
613 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
614 Sset_window_redisplay_end_trigger, 2, 2, 0,
615 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
616 VALUE should be a buffer position (typically a marker) or nil.
617 If it is a buffer position, then if redisplay in WINDOW reaches a position
618 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
619 with two arguments: WINDOW, and the end trigger value.
620 Afterwards the end-trigger value is reset to nil. */)
621 (window, value)
622 register Lisp_Object window, value;
624 register struct window *w;
626 w = decode_window (window);
627 w->redisplay_end_trigger = value;
628 return value;
631 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
632 doc: /* Return a list of the edge coordinates of WINDOW.
633 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
634 RIGHT is one more than the rightmost column occupied by WINDOW,
635 and BOTTOM is one more than the bottommost row occupied by WINDOW.
636 The edges include the space used by the window's scroll bar,
637 display margins, fringes, header line, and mode line, if it has them.
638 To get the edges of the actual text area, use `window-inside-edges'. */)
639 (window)
640 Lisp_Object window;
642 register struct window *w = decode_any_window (window);
644 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
645 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
646 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
647 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
648 Qnil))));
651 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
652 doc: /* Return a list of the edge pixel coordinates of WINDOW.
653 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
654 RIGHT is one more than the rightmost x position occupied by WINDOW,
655 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
656 The pixel edges include the space used by the window's scroll bar,
657 display margins, fringes, header line, and mode line, if it has them.
658 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
659 (window)
660 Lisp_Object window;
662 register struct window *w = decode_any_window (window);
664 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
665 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
666 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
667 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
668 Qnil))));
671 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
672 doc: /* Return a list of the edge coordinates of WINDOW.
673 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
674 RIGHT is one more than the rightmost column used by text in WINDOW,
675 and BOTTOM is one more than the bottommost row used by text in WINDOW.
676 The inside edges do not include the space used by the window's scroll bar,
677 display margins, fringes, header line, and/or mode line. */)
678 (window)
679 Lisp_Object window;
681 register struct window *w = decode_any_window (window);
683 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
684 + WINDOW_LEFT_MARGIN_COLS (w)
685 + WINDOW_LEFT_FRINGE_COLS (w)),
686 make_number (WINDOW_TOP_EDGE_LINE (w)
687 + WINDOW_HEADER_LINE_LINES (w)),
688 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
689 - WINDOW_RIGHT_MARGIN_COLS (w)
690 - WINDOW_RIGHT_FRINGE_COLS (w)),
691 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
692 - WINDOW_MODE_LINE_LINES (w)));
695 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
696 doc: /* Return a list of the edge pixel coordinates of WINDOW.
697 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
698 RIGHT is one more than the rightmost x position used by text in WINDOW,
699 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
700 The inside edges do not include the space used by the window's scroll bar,
701 display margins, fringes, header line, and/or mode line. */)
702 (window)
703 Lisp_Object window;
705 register struct window *w = decode_any_window (window);
707 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
708 + WINDOW_LEFT_MARGIN_WIDTH (w)
709 + WINDOW_LEFT_FRINGE_WIDTH (w)),
710 make_number (WINDOW_TOP_EDGE_Y (w)
711 + WINDOW_HEADER_LINE_HEIGHT (w)),
712 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
713 - WINDOW_RIGHT_MARGIN_WIDTH (w)
714 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
715 make_number (WINDOW_BOTTOM_EDGE_Y (w)
716 - WINDOW_MODE_LINE_HEIGHT (w)));
719 /* Test if the character at column *X, row *Y is within window W.
720 If it is not, return ON_NOTHING;
721 if it is in the window's text area,
722 set *x and *y to its location relative to the upper left corner
723 of the window, and
724 return ON_TEXT;
725 if it is on the window's modeline, return ON_MODE_LINE;
726 if it is on the border between the window and its right sibling,
727 return ON_VERTICAL_BORDER.
728 if it is on a scroll bar,
729 return ON_SCROLL_BAR.
730 if it is on the window's top line, return ON_HEADER_LINE;
731 if it is in left or right fringe of the window,
732 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
733 to window-relative coordinates;
734 if it is in the marginal area to the left/right of the window,
735 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
736 to window-relative coordinates.
738 X and Y are frame relative pixel coordinates. */
740 static enum window_part
741 coordinates_in_window (w, x, y)
742 register struct window *w;
743 register int *x, *y;
745 struct frame *f = XFRAME (WINDOW_FRAME (w));
746 int left_x, right_x, top_y, bottom_y;
747 enum window_part part;
748 int ux = FRAME_COLUMN_WIDTH (f);
749 int x0 = WINDOW_LEFT_EDGE_X (w);
750 int x1 = WINDOW_RIGHT_EDGE_X (w);
751 /* The width of the area where the vertical line can be dragged.
752 (Between mode lines for instance. */
753 int grabbable_width = ux;
754 int lmargin_width, rmargin_width, text_left, text_right;
756 /* In what's below, we subtract 1 when computing right_x because we
757 want the rightmost pixel, which is given by left_pixel+width-1. */
758 if (w->pseudo_window_p)
760 left_x = 0;
761 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
762 top_y = WINDOW_TOP_EDGE_Y (w);
763 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
765 else
767 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
768 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
769 top_y = WINDOW_TOP_EDGE_Y (w);
770 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
773 /* Outside any interesting row? */
774 if (*y < top_y || *y >= bottom_y)
775 return ON_NOTHING;
777 /* On the mode line or header line? If it's near the start of
778 the mode or header line of window that's has a horizontal
779 sibling, say it's on the vertical line. That's to be able
780 to resize windows horizontally in case we're using toolkit
781 scroll bars. */
783 if (WINDOW_WANTS_MODELINE_P (w)
784 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
786 part = ON_MODE_LINE;
788 header_vertical_border_check:
789 /* We're somewhere on the mode line. We consider the place
790 between mode lines of horizontally adjacent mode lines
791 as the vertical border. If scroll bars on the left,
792 return the right window. */
793 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
794 || WINDOW_RIGHTMOST_P (w))
796 if (!WINDOW_LEFTMOST_P (w) && abs (*x - x0) < grabbable_width)
798 /* Convert X and Y to window relative coordinates.
799 Vertical border is at the left edge of window. */
800 *x = max (0, *x - x0);
801 *y -= top_y;
802 return ON_VERTICAL_BORDER;
805 else
807 if (abs (*x - x1) < grabbable_width)
809 /* Convert X and Y to window relative coordinates.
810 Vertical border is at the right edge of window. */
811 *x = min (x1, *x) - x0;
812 *y -= top_y;
813 return ON_VERTICAL_BORDER;
817 if (*x < x0 || *x >= x1)
818 return ON_NOTHING;
820 /* Convert X and Y to window relative coordinates.
821 Mode line starts at left edge of window. */
822 *x -= x0;
823 *y -= top_y;
824 return part;
827 if (WINDOW_WANTS_HEADER_LINE_P (w)
828 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
830 part = ON_HEADER_LINE;
831 goto header_vertical_border_check;
834 if (*x < x0 || *x >= x1)
835 return ON_NOTHING;
837 /* Outside any interesting column? */
838 if (*x < left_x || *x > right_x)
840 *y -= top_y;
841 return ON_SCROLL_BAR;
844 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
845 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
847 text_left = window_box_left (w, TEXT_AREA);
848 text_right = text_left + window_box_width (w, TEXT_AREA);
850 if (FRAME_WINDOW_P (f))
852 if (!w->pseudo_window_p
853 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
854 && !WINDOW_RIGHTMOST_P (w)
855 && (abs (*x - right_x) < grabbable_width))
857 /* Convert X and Y to window relative coordinates.
858 Vertical border is at the right edge of window. */
859 *x = min (right_x, *x) - left_x;
860 *y -= top_y;
861 return ON_VERTICAL_BORDER;
864 else
866 /* Need to say "*x > right_x" rather than >=, since on character
867 terminals, the vertical line's x coordinate is right_x. */
868 if (!w->pseudo_window_p
869 && !WINDOW_RIGHTMOST_P (w)
870 && *x > right_x - ux)
872 /* On the border on the right side of the window? Assume that
873 this area begins at RIGHT_X minus a canonical char width. */
874 *x = min (right_x, *x) - left_x;
875 *y -= top_y;
876 return ON_VERTICAL_BORDER;
880 if (*x < text_left)
882 if (lmargin_width > 0
883 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
884 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
885 : (*x < left_x + lmargin_width)))
887 *x -= left_x;
888 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
889 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
890 *y -= top_y;
891 return ON_LEFT_MARGIN;
894 /* Convert X and Y to window-relative pixel coordinates. */
895 *x -= left_x;
896 *y -= top_y;
897 return ON_LEFT_FRINGE;
900 if (*x >= text_right)
902 if (rmargin_width > 0
903 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
904 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
905 : (*x >= right_x - rmargin_width)))
907 *x -= right_x - rmargin_width;
908 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
909 *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
910 *y -= top_y;
911 return ON_RIGHT_MARGIN;
914 /* Convert X and Y to window-relative pixel coordinates. */
915 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
916 *y -= top_y;
917 return ON_RIGHT_FRINGE;
920 /* Everything special ruled out - must be on text area */
921 *x -= text_left;
922 *y -= top_y;
923 return ON_TEXT;
927 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
928 Scoordinates_in_window_p, 2, 2, 0,
929 doc: /* Return non-nil if COORDINATES are in WINDOW.
930 COORDINATES is a cons of the form (X . Y), X and Y being distances
931 measured in characters from the upper-left corner of the frame.
932 \(0 . 0) denotes the character in the upper left corner of the
933 frame.
934 If COORDINATES are in the text portion of WINDOW,
935 the coordinates relative to the window are returned.
936 If they are in the mode line of WINDOW, `mode-line' is returned.
937 If they are in the top mode line of WINDOW, `header-line' is returned.
938 If they are in the left fringe of WINDOW, `left-fringe' is returned.
939 If they are in the right fringe of WINDOW, `right-fringe' is returned.
940 If they are on the border between WINDOW and its right sibling,
941 `vertical-line' is returned.
942 If they are in the windows's left or right marginal areas, `left-margin'\n\
943 or `right-margin' is returned. */)
944 (coordinates, window)
945 register Lisp_Object coordinates, window;
947 struct window *w;
948 struct frame *f;
949 int x, y;
950 Lisp_Object lx, ly;
952 CHECK_WINDOW (window);
953 w = XWINDOW (window);
954 f = XFRAME (w->frame);
955 CHECK_CONS (coordinates);
956 lx = Fcar (coordinates);
957 ly = Fcdr (coordinates);
958 CHECK_NUMBER_OR_FLOAT (lx);
959 CHECK_NUMBER_OR_FLOAT (ly);
960 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
961 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
963 switch (coordinates_in_window (w, &x, &y))
965 case ON_NOTHING:
966 return Qnil;
968 case ON_TEXT:
969 /* X and Y are now window relative pixel coordinates. Convert
970 them to canonical char units before returning them. */
971 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
972 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
974 case ON_MODE_LINE:
975 return Qmode_line;
977 case ON_VERTICAL_BORDER:
978 return Qvertical_line;
980 case ON_HEADER_LINE:
981 return Qheader_line;
983 case ON_LEFT_FRINGE:
984 return Qleft_fringe;
986 case ON_RIGHT_FRINGE:
987 return Qright_fringe;
989 case ON_LEFT_MARGIN:
990 return Qleft_margin;
992 case ON_RIGHT_MARGIN:
993 return Qright_margin;
995 case ON_SCROLL_BAR:
996 /* Historically we are supposed to return nil in this case. */
997 return Qnil;
999 default:
1000 abort ();
1005 /* Callback for foreach_window, used in window_from_coordinates.
1006 Check if window W contains coordinates specified by USER_DATA which
1007 is actually a pointer to a struct check_window_data CW.
1009 Check if window W contains coordinates *CW->x and *CW->y. If it
1010 does, return W in *CW->window, as Lisp_Object, and return in
1011 *CW->part the part of the window under coordinates *X,*Y. Return
1012 zero from this function to stop iterating over windows. */
1014 struct check_window_data
1016 Lisp_Object *window;
1017 int *x, *y;
1018 enum window_part *part;
1021 static int
1022 check_window_containing (w, user_data)
1023 struct window *w;
1024 void *user_data;
1026 struct check_window_data *cw = (struct check_window_data *) user_data;
1027 enum window_part found;
1028 int continue_p = 1;
1030 found = coordinates_in_window (w, cw->x, cw->y);
1031 if (found != ON_NOTHING)
1033 *cw->part = found;
1034 XSETWINDOW (*cw->window, w);
1035 continue_p = 0;
1038 return continue_p;
1042 /* Find the window containing frame-relative pixel position X/Y and
1043 return it as a Lisp_Object.
1045 If X, Y is on one of the window's special `window_part' elements,
1046 set *PART to the id of that element, and return X and Y converted
1047 to window relative coordinates in WX and WY.
1049 If there is no window under X, Y return nil and leave *PART
1050 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1052 This function was previously implemented with a loop cycling over
1053 windows with Fnext_window, and starting with the frame's selected
1054 window. It turned out that this doesn't work with an
1055 implementation of next_window using Vwindow_list, because
1056 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1057 tree of F when this function is called asynchronously from
1058 note_mouse_highlight. The original loop didn't terminate in this
1059 case. */
1061 Lisp_Object
1062 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
1063 struct frame *f;
1064 int x, y;
1065 enum window_part *part;
1066 int *wx, *wy;
1067 int tool_bar_p;
1069 Lisp_Object window;
1070 struct check_window_data cw;
1071 enum window_part dummy;
1073 if (part == 0)
1074 part = &dummy;
1076 window = Qnil;
1077 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
1078 foreach_window (f, check_window_containing, &cw);
1080 /* If not found above, see if it's in the tool bar window, if a tool
1081 bar exists. */
1082 if (NILP (window)
1083 && tool_bar_p
1084 && WINDOWP (f->tool_bar_window)
1085 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1086 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
1087 != ON_NOTHING))
1089 *part = ON_TEXT;
1090 window = f->tool_bar_window;
1093 if (wx) *wx = x;
1094 if (wy) *wy = y;
1096 return window;
1099 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1100 doc: /* Return window containing coordinates X and Y on FRAME.
1101 If omitted, FRAME defaults to the currently selected frame.
1102 The top left corner of the frame is considered to be row 0,
1103 column 0. */)
1104 (x, y, frame)
1105 Lisp_Object x, y, frame;
1107 struct frame *f;
1109 if (NILP (frame))
1110 frame = selected_frame;
1111 CHECK_LIVE_FRAME (frame);
1112 f = XFRAME (frame);
1114 /* Check that arguments are integers or floats. */
1115 CHECK_NUMBER_OR_FLOAT (x);
1116 CHECK_NUMBER_OR_FLOAT (y);
1118 return window_from_coordinates (f,
1119 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1120 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1121 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1122 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1123 0, 0, 0, 0);
1126 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1127 doc: /* Return current value of point in WINDOW.
1128 WINDOW defaults to the selected window.
1130 For a nonselected window, this is the value point would have
1131 if that window were selected.
1133 Note that, when WINDOW is the selected window and its buffer
1134 is also currently selected, the value returned is the same as (point).
1135 It would be more strictly correct to return the `top-level' value
1136 of point, outside of any save-excursion forms.
1137 But that is hard to define. */)
1138 (window)
1139 Lisp_Object window;
1141 register struct window *w = decode_window (window);
1143 if (w == XWINDOW (selected_window)
1144 && current_buffer == XBUFFER (w->buffer))
1145 return Fpoint ();
1146 return Fmarker_position (w->pointm);
1149 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1150 doc: /* Return position at which display currently starts in WINDOW.
1151 WINDOW defaults to the selected window.
1152 This is updated by redisplay or by calling `set-window-start'. */)
1153 (window)
1154 Lisp_Object window;
1156 return Fmarker_position (decode_window (window)->start);
1159 /* This is text temporarily removed from the doc string below.
1161 This function returns nil if the position is not currently known.
1162 That happens when redisplay is preempted and doesn't finish.
1163 If in that case you want to compute where the end of the window would
1164 have been if redisplay had finished, do this:
1165 (save-excursion
1166 (goto-char (window-start window))
1167 (vertical-motion (1- (window-height window)) window)
1168 (point))") */
1170 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1171 doc: /* Return position at which display currently ends in WINDOW.
1172 WINDOW defaults to the selected window.
1173 This is updated by redisplay, when it runs to completion.
1174 Simply changing the buffer text or setting `window-start'
1175 does not update this value.
1176 Return nil if there is no recorded value. \(This can happen if the
1177 last redisplay of WINDOW was preempted, and did not finish.)
1178 If UPDATE is non-nil, compute the up-to-date position
1179 if it isn't already recorded. */)
1180 (window, update)
1181 Lisp_Object window, update;
1183 Lisp_Object value;
1184 struct window *w = decode_window (window);
1185 Lisp_Object buf;
1186 struct buffer *b;
1188 buf = w->buffer;
1189 CHECK_BUFFER (buf);
1190 b = XBUFFER (buf);
1192 #if 0 /* This change broke some things. We should make it later. */
1193 /* If we don't know the end position, return nil.
1194 The user can compute it with vertical-motion if he wants to.
1195 It would be nicer to do it automatically,
1196 but that's so slow that it would probably bother people. */
1197 if (NILP (w->window_end_valid))
1198 return Qnil;
1199 #endif
1201 if (! NILP (update)
1202 && ! (! NILP (w->window_end_valid)
1203 && XFASTINT (w->last_modified) >= BUF_MODIFF (b)
1204 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
1205 && !noninteractive)
1207 struct text_pos startp;
1208 struct it it;
1209 struct buffer *old_buffer = NULL;
1211 /* Cannot use Fvertical_motion because that function doesn't
1212 cope with variable-height lines. */
1213 if (b != current_buffer)
1215 old_buffer = current_buffer;
1216 set_buffer_internal (b);
1219 /* In case W->start is out of the range, use something
1220 reasonable. This situation occurred when loading a file with
1221 `-l' containing a call to `rmail' with subsequent other
1222 commands. At the end, W->start happened to be BEG, while
1223 rmail had already narrowed the buffer. */
1224 if (XMARKER (w->start)->charpos < BEGV)
1225 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1226 else if (XMARKER (w->start)->charpos > ZV)
1227 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1228 else
1229 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1231 start_display (&it, w, startp);
1232 move_it_vertically (&it, window_box_height (w));
1233 if (it.current_y < it.last_visible_y)
1234 move_it_past_eol (&it);
1235 value = make_number (IT_CHARPOS (it));
1237 if (old_buffer)
1238 set_buffer_internal (old_buffer);
1240 else
1241 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1243 return value;
1246 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1247 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1248 Return POS. */)
1249 (window, pos)
1250 Lisp_Object window, pos;
1252 register struct window *w = decode_window (window);
1254 CHECK_NUMBER_COERCE_MARKER (pos);
1255 if (w == XWINDOW (selected_window)
1256 && XBUFFER (w->buffer) == current_buffer)
1257 Fgoto_char (pos);
1258 else
1259 set_marker_restricted (w->pointm, pos, w->buffer);
1261 /* We have to make sure that redisplay updates the window to show
1262 the new value of point. */
1263 if (!EQ (window, selected_window))
1264 ++windows_or_buffers_changed;
1266 return pos;
1269 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1270 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1271 Return POS.
1272 Optional third arg NOFORCE non-nil inhibits next redisplay
1273 from overriding motion of point in order to display at this exact start. */)
1274 (window, pos, noforce)
1275 Lisp_Object window, pos, noforce;
1277 register struct window *w = decode_window (window);
1279 CHECK_NUMBER_COERCE_MARKER (pos);
1280 set_marker_restricted (w->start, pos, w->buffer);
1281 /* this is not right, but much easier than doing what is right. */
1282 w->start_at_line_beg = Qnil;
1283 if (NILP (noforce))
1284 w->force_start = Qt;
1285 w->update_mode_line = Qt;
1286 XSETFASTINT (w->last_modified, 0);
1287 XSETFASTINT (w->last_overlay_modified, 0);
1288 if (!EQ (window, selected_window))
1289 windows_or_buffers_changed++;
1291 return pos;
1294 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1295 1, 1, 0,
1296 doc: /* Return WINDOW's dedicated object, usually t or nil.
1297 See also `set-window-dedicated-p'. */)
1298 (window)
1299 Lisp_Object window;
1301 return decode_window (window)->dedicated;
1304 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1305 Sset_window_dedicated_p, 2, 2, 0,
1306 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1307 If it is dedicated, Emacs will not automatically change
1308 which buffer appears in it.
1309 The second argument is the new value for the dedication flag;
1310 non-nil means yes. */)
1311 (window, arg)
1312 Lisp_Object window, arg;
1314 register struct window *w = decode_window (window);
1316 w->dedicated = arg;
1318 return w->dedicated;
1321 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1322 0, 1, 0,
1323 doc: /* Return the display-table that WINDOW is using.
1324 WINDOW defaults to the selected window. */)
1325 (window)
1326 Lisp_Object window;
1328 return decode_window (window)->display_table;
1331 /* Get the display table for use on window W. This is either W's
1332 display table or W's buffer's display table. Ignore the specified
1333 tables if they are not valid; if no valid table is specified,
1334 return 0. */
1336 struct Lisp_Char_Table *
1337 window_display_table (w)
1338 struct window *w;
1340 struct Lisp_Char_Table *dp = NULL;
1342 if (DISP_TABLE_P (w->display_table))
1343 dp = XCHAR_TABLE (w->display_table);
1344 else if (BUFFERP (w->buffer))
1346 struct buffer *b = XBUFFER (w->buffer);
1348 if (DISP_TABLE_P (b->display_table))
1349 dp = XCHAR_TABLE (b->display_table);
1350 else if (DISP_TABLE_P (Vstandard_display_table))
1351 dp = XCHAR_TABLE (Vstandard_display_table);
1354 return dp;
1357 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1358 doc: /* Set WINDOW's display-table to TABLE. */)
1359 (window, table)
1360 register Lisp_Object window, table;
1362 register struct window *w;
1364 w = decode_window (window);
1365 w->display_table = table;
1366 return table;
1369 /* Record info on buffer window w is displaying
1370 when it is about to cease to display that buffer. */
1371 static void
1372 unshow_buffer (w)
1373 register struct window *w;
1375 Lisp_Object buf;
1376 struct buffer *b;
1378 buf = w->buffer;
1379 b = XBUFFER (buf);
1380 if (b != XMARKER (w->pointm)->buffer)
1381 abort ();
1383 #if 0
1384 if (w == XWINDOW (selected_window)
1385 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1386 /* Do this except when the selected window's buffer
1387 is being removed from some other window. */
1388 #endif
1389 /* last_window_start records the start position that this buffer
1390 had in the last window to be disconnected from it.
1391 Now that this statement is unconditional,
1392 it is possible for the buffer to be displayed in the
1393 selected window, while last_window_start reflects another
1394 window which was recently showing the same buffer.
1395 Some people might say that might be a good thing. Let's see. */
1396 b->last_window_start = marker_position (w->start);
1398 /* Point in the selected window's buffer
1399 is actually stored in that buffer, and the window's pointm isn't used.
1400 So don't clobber point in that buffer. */
1401 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1402 /* This line helps to fix Horsley's testbug.el bug. */
1403 && !(WINDOWP (b->last_selected_window)
1404 && w != XWINDOW (b->last_selected_window)
1405 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1406 temp_set_point_both (b,
1407 clip_to_bounds (BUF_BEGV (b),
1408 XMARKER (w->pointm)->charpos,
1409 BUF_ZV (b)),
1410 clip_to_bounds (BUF_BEGV_BYTE (b),
1411 marker_byte_position (w->pointm),
1412 BUF_ZV_BYTE (b)));
1414 if (WINDOWP (b->last_selected_window)
1415 && w == XWINDOW (b->last_selected_window))
1416 b->last_selected_window = Qnil;
1419 /* Put replacement into the window structure in place of old. */
1420 static void
1421 replace_window (old, replacement)
1422 Lisp_Object old, replacement;
1424 register Lisp_Object tem;
1425 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1427 /* If OLD is its frame's root_window, then replacement is the new
1428 root_window for that frame. */
1430 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1431 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1433 p->left_col = o->left_col;
1434 p->top_line = o->top_line;
1435 p->total_cols = o->total_cols;
1436 p->total_lines = o->total_lines;
1437 p->desired_matrix = p->current_matrix = 0;
1438 p->vscroll = 0;
1439 bzero (&p->cursor, sizeof (p->cursor));
1440 bzero (&p->last_cursor, sizeof (p->last_cursor));
1441 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1442 p->phys_cursor_type = -1;
1443 p->phys_cursor_width = -1;
1444 p->must_be_updated_p = 0;
1445 p->pseudo_window_p = 0;
1446 XSETFASTINT (p->window_end_vpos, 0);
1447 XSETFASTINT (p->window_end_pos, 0);
1448 p->window_end_valid = Qnil;
1449 p->frozen_window_start_p = 0;
1450 p->orig_top_line = p->orig_total_lines = Qnil;
1452 p->next = tem = o->next;
1453 if (!NILP (tem))
1454 XWINDOW (tem)->prev = replacement;
1456 p->prev = tem = o->prev;
1457 if (!NILP (tem))
1458 XWINDOW (tem)->next = replacement;
1460 p->parent = tem = o->parent;
1461 if (!NILP (tem))
1463 if (EQ (XWINDOW (tem)->vchild, old))
1464 XWINDOW (tem)->vchild = replacement;
1465 if (EQ (XWINDOW (tem)->hchild, old))
1466 XWINDOW (tem)->hchild = replacement;
1469 /*** Here, if replacement is a vertical combination
1470 and so is its new parent, we should make replacement's
1471 children be children of that parent instead. ***/
1474 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1475 doc: /* Remove WINDOW from the display. Default is selected window. */)
1476 (window)
1477 register Lisp_Object window;
1479 delete_window (window);
1481 if (! NILP (Vwindow_configuration_change_hook)
1482 && ! NILP (Vrun_hooks))
1483 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1485 return Qnil;
1488 void
1489 delete_window (window)
1490 register Lisp_Object window;
1492 register Lisp_Object tem, parent, sib;
1493 register struct window *p;
1494 register struct window *par;
1495 struct frame *f;
1497 /* Because this function is called by other C code on non-leaf
1498 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1499 so we can't decode_window here. */
1500 if (NILP (window))
1501 window = selected_window;
1502 else
1503 CHECK_WINDOW (window);
1504 p = XWINDOW (window);
1506 /* It's a no-op to delete an already-deleted window. */
1507 if (NILP (p->buffer)
1508 && NILP (p->hchild)
1509 && NILP (p->vchild))
1510 return;
1512 parent = p->parent;
1513 if (NILP (parent))
1514 error ("Attempt to delete minibuffer or sole ordinary window");
1515 par = XWINDOW (parent);
1517 windows_or_buffers_changed++;
1518 Vwindow_list = Qnil;
1519 f = XFRAME (WINDOW_FRAME (p));
1520 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1522 /* Are we trying to delete any frame's selected window? */
1524 Lisp_Object swindow, pwindow;
1526 /* See if the frame's selected window is either WINDOW
1527 or any subwindow of it, by finding all that window's parents
1528 and comparing each one with WINDOW. */
1529 swindow = FRAME_SELECTED_WINDOW (f);
1531 while (1)
1533 pwindow = swindow;
1534 while (!NILP (pwindow))
1536 if (EQ (window, pwindow))
1537 break;
1538 pwindow = XWINDOW (pwindow)->parent;
1541 /* If the window being deleted is not a parent of SWINDOW,
1542 then SWINDOW is ok as the new selected window. */
1543 if (!EQ (window, pwindow))
1544 break;
1545 /* Otherwise, try another window for SWINDOW. */
1546 swindow = Fnext_window (swindow, Qlambda, Qnil);
1548 /* If we get back to the frame's selected window,
1549 it means there was no acceptable alternative,
1550 so we cannot delete. */
1551 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1552 error ("Cannot delete window");
1555 /* If we need to change SWINDOW, do it. */
1556 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1558 /* If we're about to delete the selected window on the
1559 selected frame, then we should use Fselect_window to select
1560 the new window. On the other hand, if we're about to
1561 delete the selected window on any other frame, we shouldn't do
1562 anything but set the frame's selected_window slot. */
1563 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1564 Fselect_window (swindow, Qnil);
1565 else
1566 FRAME_SELECTED_WINDOW (f) = swindow;
1570 /* Now we know we can delete this one. */
1571 window_deletion_count++;
1573 tem = p->buffer;
1574 /* tem is null for dummy parent windows
1575 (which have inferiors but not any contents themselves) */
1576 if (!NILP (tem))
1578 unshow_buffer (p);
1579 unchain_marker (XMARKER (p->pointm));
1580 unchain_marker (XMARKER (p->start));
1583 /* Free window glyph matrices. It is sure that they are allocated
1584 again when ADJUST_GLYPHS is called. Block input so that expose
1585 events and other events that access glyph matrices are not
1586 processed while we are changing them. */
1587 BLOCK_INPUT;
1588 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1590 tem = p->next;
1591 if (!NILP (tem))
1592 XWINDOW (tem)->prev = p->prev;
1594 tem = p->prev;
1595 if (!NILP (tem))
1596 XWINDOW (tem)->next = p->next;
1598 if (EQ (window, par->hchild))
1599 par->hchild = p->next;
1600 if (EQ (window, par->vchild))
1601 par->vchild = p->next;
1603 /* Find one of our siblings to give our space to. */
1604 sib = p->prev;
1605 if (NILP (sib))
1607 /* If p gives its space to its next sibling, that sibling needs
1608 to have its top/left side pulled back to where p's is.
1609 set_window_{height,width} will re-position the sibling's
1610 children. */
1611 sib = p->next;
1612 XWINDOW (sib)->top_line = p->top_line;
1613 XWINDOW (sib)->left_col = p->left_col;
1616 /* Stretch that sibling. */
1617 if (!NILP (par->vchild))
1618 set_window_height (sib,
1619 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1621 if (!NILP (par->hchild))
1622 set_window_width (sib,
1623 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1626 /* If parent now has only one child,
1627 put the child into the parent's place. */
1628 tem = par->hchild;
1629 if (NILP (tem))
1630 tem = par->vchild;
1631 if (NILP (XWINDOW (tem)->next)) {
1632 replace_window (parent, tem);
1633 par = XWINDOW (tem);
1636 /* Since we may be deleting combination windows, we must make sure that
1637 not only p but all its children have been marked as deleted. */
1638 if (! NILP (p->hchild))
1639 delete_all_subwindows (XWINDOW (p->hchild));
1640 else if (! NILP (p->vchild))
1641 delete_all_subwindows (XWINDOW (p->vchild));
1643 /* Mark this window as deleted. */
1644 p->buffer = p->hchild = p->vchild = Qnil;
1646 if (! NILP (par->parent))
1647 par = XWINDOW (par->parent);
1649 /* Check if we have a v/hchild with a v/hchild. In that case remove
1650 one of them. */
1652 if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
1654 p = XWINDOW (par->vchild);
1655 par->vchild = p->vchild;
1656 tem = p->vchild;
1658 else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
1660 p = XWINDOW (par->hchild);
1661 par->hchild = p->hchild;
1662 tem = p->hchild;
1664 else
1665 p = 0;
1667 if (p)
1669 while (! NILP (tem)) {
1670 XWINDOW (tem)->parent = p->parent;
1671 if (NILP (XWINDOW (tem)->next))
1672 break;
1673 tem = XWINDOW (tem)->next;
1675 if (! NILP (tem)) {
1676 /* The next of the v/hchild we are removing is now the next of the
1677 last child for the v/hchild:
1678 Before v/hchild -> v/hchild -> next1 -> next2
1680 -> next3
1681 After: v/hchild -> next1 -> next2 -> next3
1683 XWINDOW (tem)->next = p->next;
1684 if (! NILP (p->next))
1685 XWINDOW (p->next)->prev = tem;
1687 p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
1691 /* Adjust glyph matrices. */
1692 adjust_glyphs (f);
1693 UNBLOCK_INPUT;
1698 /***********************************************************************
1699 Window List
1700 ***********************************************************************/
1702 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1703 pointer. This is a callback function for foreach_window, used in
1704 function window_list. */
1706 static int
1707 add_window_to_list (w, user_data)
1708 struct window *w;
1709 void *user_data;
1711 Lisp_Object *list = (Lisp_Object *) user_data;
1712 Lisp_Object window;
1713 XSETWINDOW (window, w);
1714 *list = Fcons (window, *list);
1715 return 1;
1719 /* Return a list of all windows, for use by next_window. If
1720 Vwindow_list is a list, return that list. Otherwise, build a new
1721 list, cache it in Vwindow_list, and return that. */
1723 static Lisp_Object
1724 window_list ()
1726 if (!CONSP (Vwindow_list))
1728 Lisp_Object tail;
1730 Vwindow_list = Qnil;
1731 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1733 Lisp_Object args[2];
1735 /* We are visiting windows in canonical order, and add
1736 new windows at the front of args[1], which means we
1737 have to reverse this list at the end. */
1738 args[1] = Qnil;
1739 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1740 args[0] = Vwindow_list;
1741 args[1] = Fnreverse (args[1]);
1742 Vwindow_list = Fnconc (2, args);
1746 return Vwindow_list;
1750 /* Value is non-zero if WINDOW satisfies the constraints given by
1751 OWINDOW, MINIBUF and ALL_FRAMES.
1753 MINIBUF t means WINDOW may be minibuffer windows.
1754 `lambda' means WINDOW may not be a minibuffer window.
1755 a window means a specific minibuffer window
1757 ALL_FRAMES t means search all frames,
1758 nil means search just current frame,
1759 `visible' means search just visible frames,
1760 0 means search visible and iconified frames,
1761 a window means search the frame that window belongs to,
1762 a frame means consider windows on that frame, only. */
1764 static int
1765 candidate_window_p (window, owindow, minibuf, all_frames)
1766 Lisp_Object window, owindow, minibuf, all_frames;
1768 struct window *w = XWINDOW (window);
1769 struct frame *f = XFRAME (w->frame);
1770 int candidate_p = 1;
1772 if (!BUFFERP (w->buffer))
1773 candidate_p = 0;
1774 else if (MINI_WINDOW_P (w)
1775 && (EQ (minibuf, Qlambda)
1776 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1778 /* If MINIBUF is `lambda' don't consider any mini-windows.
1779 If it is a window, consider only that one. */
1780 candidate_p = 0;
1782 else if (EQ (all_frames, Qt))
1783 candidate_p = 1;
1784 else if (NILP (all_frames))
1786 xassert (WINDOWP (owindow));
1787 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1789 else if (EQ (all_frames, Qvisible))
1791 FRAME_SAMPLE_VISIBILITY (f);
1792 candidate_p = FRAME_VISIBLE_P (f);
1794 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1796 FRAME_SAMPLE_VISIBILITY (f);
1797 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1799 else if (WINDOWP (all_frames))
1800 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1801 || EQ (XWINDOW (all_frames)->frame, w->frame)
1802 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1803 else if (FRAMEP (all_frames))
1804 candidate_p = EQ (all_frames, w->frame);
1806 return candidate_p;
1810 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1811 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1812 ALL_FRAMES. */
1814 static void
1815 decode_next_window_args (window, minibuf, all_frames)
1816 Lisp_Object *window, *minibuf, *all_frames;
1818 if (NILP (*window))
1819 *window = selected_window;
1820 else
1821 CHECK_LIVE_WINDOW (*window);
1823 /* MINIBUF nil may or may not include minibuffers. Decide if it
1824 does. */
1825 if (NILP (*minibuf))
1826 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1827 else if (!EQ (*minibuf, Qt))
1828 *minibuf = Qlambda;
1830 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1831 => count none of them, or a specific minibuffer window (the
1832 active one) to count. */
1834 /* ALL_FRAMES nil doesn't specify which frames to include. */
1835 if (NILP (*all_frames))
1836 *all_frames = (!EQ (*minibuf, Qlambda)
1837 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1838 : Qnil);
1839 else if (EQ (*all_frames, Qvisible))
1841 else if (EQ (*all_frames, make_number (0)))
1843 else if (FRAMEP (*all_frames))
1845 else if (!EQ (*all_frames, Qt))
1846 *all_frames = Qnil;
1848 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1849 search just current frame, `visible' meaning search just visible
1850 frames, 0 meaning search visible and iconified frames, or a
1851 window, meaning search the frame that window belongs to, or a
1852 frame, meaning consider windows on that frame, only. */
1856 /* Return the next or previous window of WINDOW in canonical ordering
1857 of windows. NEXT_P non-zero means return the next window. See the
1858 documentation string of next-window for the meaning of MINIBUF and
1859 ALL_FRAMES. */
1861 static Lisp_Object
1862 next_window (window, minibuf, all_frames, next_p)
1863 Lisp_Object window, minibuf, all_frames;
1864 int next_p;
1866 decode_next_window_args (&window, &minibuf, &all_frames);
1868 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1869 return the first window on the frame. */
1870 if (FRAMEP (all_frames)
1871 && !EQ (all_frames, XWINDOW (window)->frame))
1872 return Fframe_first_window (all_frames);
1874 if (next_p)
1876 Lisp_Object list;
1878 /* Find WINDOW in the list of all windows. */
1879 list = Fmemq (window, window_list ());
1881 /* Scan forward from WINDOW to the end of the window list. */
1882 if (CONSP (list))
1883 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1884 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1885 break;
1887 /* Scan from the start of the window list up to WINDOW. */
1888 if (!CONSP (list))
1889 for (list = Vwindow_list;
1890 CONSP (list) && !EQ (XCAR (list), window);
1891 list = XCDR (list))
1892 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1893 break;
1895 if (CONSP (list))
1896 window = XCAR (list);
1898 else
1900 Lisp_Object candidate, list;
1902 /* Scan through the list of windows for candidates. If there are
1903 candidate windows in front of WINDOW, the last one of these
1904 is the one we want. If there are candidates following WINDOW
1905 in the list, again the last one of these is the one we want. */
1906 candidate = Qnil;
1907 for (list = window_list (); CONSP (list); list = XCDR (list))
1909 if (EQ (XCAR (list), window))
1911 if (WINDOWP (candidate))
1912 break;
1914 else if (candidate_window_p (XCAR (list), window, minibuf,
1915 all_frames))
1916 candidate = XCAR (list);
1919 if (WINDOWP (candidate))
1920 window = candidate;
1923 return window;
1927 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1928 doc: /* Return next window after WINDOW in canonical ordering of windows.
1929 If omitted, WINDOW defaults to the selected window.
1931 Optional second arg MINIBUF t means count the minibuffer window even
1932 if not active. MINIBUF nil or omitted means count the minibuffer iff
1933 it is active. MINIBUF neither t nor nil means not to count the
1934 minibuffer even if it is active.
1936 Several frames may share a single minibuffer; if the minibuffer
1937 counts, all windows on all frames that share that minibuffer count
1938 too. Therefore, `next-window' can be used to iterate through the
1939 set of windows even when the minibuffer is on another frame. If the
1940 minibuffer does not count, only windows from WINDOW's frame count.
1942 Optional third arg ALL-FRAMES t means include windows on all frames.
1943 ALL-FRAMES nil or omitted means cycle within the frames as specified
1944 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1945 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1946 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1947 Anything else means restrict to WINDOW's frame.
1949 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1950 `next-window' to iterate through the entire cycle of acceptable
1951 windows, eventually ending up back at the window you started with.
1952 `previous-window' traverses the same cycle, in the reverse order. */)
1953 (window, minibuf, all_frames)
1954 Lisp_Object window, minibuf, all_frames;
1956 return next_window (window, minibuf, all_frames, 1);
1960 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1961 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1962 If omitted, WINDOW defaults to the selected window.
1964 Optional second arg MINIBUF t means count the minibuffer window even
1965 if not active. MINIBUF nil or omitted means count the minibuffer iff
1966 it is active. MINIBUF neither t nor nil means not to count the
1967 minibuffer even if it is active.
1969 Several frames may share a single minibuffer; if the minibuffer
1970 counts, all windows on all frames that share that minibuffer count
1971 too. Therefore, `previous-window' can be used to iterate through
1972 the set of windows even when the minibuffer is on another frame. If
1973 the minibuffer does not count, only windows from WINDOW's frame count
1975 Optional third arg ALL-FRAMES t means include windows on all frames.
1976 ALL-FRAMES nil or omitted means cycle within the frames as specified
1977 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1978 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1979 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1980 Anything else means restrict to WINDOW's frame.
1982 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1983 `previous-window' to iterate through the entire cycle of acceptable
1984 windows, eventually ending up back at the window you started with.
1985 `next-window' traverses the same cycle, in the reverse order. */)
1986 (window, minibuf, all_frames)
1987 Lisp_Object window, minibuf, all_frames;
1989 return next_window (window, minibuf, all_frames, 0);
1993 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1994 doc: /* Select the ARG'th different window on this frame.
1995 All windows on current frame are arranged in a cyclic order.
1996 This command selects the window ARG steps away in that order.
1997 A negative ARG moves in the opposite order. The optional second
1998 argument ALL-FRAMES has the same meaning as in `next-window', which see. */)
1999 (arg, all_frames)
2000 Lisp_Object arg, all_frames;
2002 Lisp_Object window;
2003 int i;
2005 CHECK_NUMBER (arg);
2006 window = selected_window;
2008 for (i = XINT (arg); i > 0; --i)
2009 window = Fnext_window (window, Qnil, all_frames);
2010 for (; i < 0; ++i)
2011 window = Fprevious_window (window, Qnil, all_frames);
2013 Fselect_window (window, Qnil);
2014 return Qnil;
2018 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2019 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2020 FRAME nil or omitted means use the selected frame.
2021 WINDOW nil or omitted means use the selected window.
2022 MINIBUF t means include the minibuffer window, even if it isn't active.
2023 MINIBUF nil or omitted means include the minibuffer window only
2024 if it's active.
2025 MINIBUF neither nil nor t means never include the minibuffer window. */)
2026 (frame, minibuf, window)
2027 Lisp_Object frame, minibuf, window;
2029 if (NILP (window))
2030 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2031 CHECK_WINDOW (window);
2032 if (NILP (frame))
2033 frame = selected_frame;
2035 if (!EQ (frame, XWINDOW (window)->frame))
2036 error ("Window is on a different frame");
2038 return window_list_1 (window, minibuf, frame);
2042 /* Return a list of windows in canonical ordering. Arguments are like
2043 for `next-window'. */
2045 static Lisp_Object
2046 window_list_1 (window, minibuf, all_frames)
2047 Lisp_Object window, minibuf, all_frames;
2049 Lisp_Object tail, list, rest;
2051 decode_next_window_args (&window, &minibuf, &all_frames);
2052 list = Qnil;
2054 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2055 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2056 list = Fcons (XCAR (tail), list);
2058 /* Rotate the list to start with WINDOW. */
2059 list = Fnreverse (list);
2060 rest = Fmemq (window, list);
2061 if (!NILP (rest) && !EQ (rest, list))
2063 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2065 XSETCDR (tail, Qnil);
2066 list = nconc2 (rest, list);
2068 return list;
2073 /* Look at all windows, performing an operation specified by TYPE
2074 with argument OBJ.
2075 If FRAMES is Qt, look at all frames;
2076 Qnil, look at just the selected frame;
2077 Qvisible, look at visible frames;
2078 a frame, just look at windows on that frame.
2079 If MINI is non-zero, perform the operation on minibuffer windows too. */
2081 enum window_loop
2083 WINDOW_LOOP_UNUSED,
2084 GET_BUFFER_WINDOW, /* Arg is buffer */
2085 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
2086 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
2087 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
2088 GET_LARGEST_WINDOW,
2089 UNSHOW_BUFFER, /* Arg is buffer */
2090 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2091 CHECK_ALL_WINDOWS
2094 static Lisp_Object
2095 window_loop (type, obj, mini, frames)
2096 enum window_loop type;
2097 Lisp_Object obj, frames;
2098 int mini;
2100 Lisp_Object window, windows, best_window, frame_arg;
2101 struct frame *f;
2102 struct gcpro gcpro1;
2104 /* If we're only looping through windows on a particular frame,
2105 frame points to that frame. If we're looping through windows
2106 on all frames, frame is 0. */
2107 if (FRAMEP (frames))
2108 f = XFRAME (frames);
2109 else if (NILP (frames))
2110 f = SELECTED_FRAME ();
2111 else
2112 f = NULL;
2114 if (f)
2115 frame_arg = Qlambda;
2116 else if (EQ (frames, make_number (0)))
2117 frame_arg = frames;
2118 else if (EQ (frames, Qvisible))
2119 frame_arg = frames;
2120 else
2121 frame_arg = Qt;
2123 /* frame_arg is Qlambda to stick to one frame,
2124 Qvisible to consider all visible frames,
2125 or Qt otherwise. */
2127 /* Pick a window to start with. */
2128 if (WINDOWP (obj))
2129 window = obj;
2130 else if (f)
2131 window = FRAME_SELECTED_WINDOW (f);
2132 else
2133 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2135 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2136 GCPRO1 (windows);
2137 best_window = Qnil;
2139 for (; CONSP (windows); windows = XCDR (windows))
2141 struct window *w;
2143 window = XCAR (windows);
2144 w = XWINDOW (window);
2146 /* Note that we do not pay attention here to whether the frame
2147 is visible, since Fwindow_list skips non-visible frames if
2148 that is desired, under the control of frame_arg. */
2149 if (!MINI_WINDOW_P (w)
2150 /* For UNSHOW_BUFFER, we must always consider all windows. */
2151 || type == UNSHOW_BUFFER
2152 || (mini && minibuf_level > 0))
2153 switch (type)
2155 case GET_BUFFER_WINDOW:
2156 if (EQ (w->buffer, obj)
2157 /* Don't find any minibuffer window
2158 except the one that is currently in use. */
2159 && (MINI_WINDOW_P (w)
2160 ? EQ (window, minibuf_window)
2161 : 1))
2163 if (NILP (best_window))
2164 best_window = window;
2165 else if (EQ (window, selected_window))
2166 /* For compatibility with 20.x, prefer to return
2167 selected-window. */
2168 best_window = window;
2170 break;
2172 case GET_LRU_WINDOW:
2173 /* `obj' is an integer encoding a bitvector.
2174 `obj & 1' means consider only full-width windows.
2175 `obj & 2' means consider also dedicated windows. */
2176 if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
2177 || (!(XINT (obj) & 2) && !NILP (w->dedicated))
2178 /* Minibuffer windows are always ignored. */
2179 || MINI_WINDOW_P (w))
2180 break;
2181 if (NILP (best_window)
2182 || (XFASTINT (XWINDOW (best_window)->use_time)
2183 > XFASTINT (w->use_time)))
2184 best_window = window;
2185 break;
2187 case DELETE_OTHER_WINDOWS:
2188 if (!EQ (window, obj))
2189 Fdelete_window (window);
2190 break;
2192 case DELETE_BUFFER_WINDOWS:
2193 if (EQ (w->buffer, obj))
2195 struct frame *f = XFRAME (WINDOW_FRAME (w));
2197 /* If this window is dedicated, and in a frame of its own,
2198 kill the frame. */
2199 if (EQ (window, FRAME_ROOT_WINDOW (f))
2200 && !NILP (w->dedicated)
2201 && other_visible_frames (f))
2203 /* Skip the other windows on this frame.
2204 There might be one, the minibuffer! */
2205 while (CONSP (XCDR (windows))
2206 && EQ (XWINDOW (XCAR (windows))->frame,
2207 XWINDOW (XCAR (XCDR (windows)))->frame))
2208 windows = XCDR (windows);
2210 /* Now we can safely delete the frame. */
2211 Fdelete_frame (w->frame, Qnil);
2213 else if (NILP (w->parent))
2215 /* If we're deleting the buffer displayed in the
2216 only window on the frame, find a new buffer to
2217 display there. */
2218 Lisp_Object buffer;
2219 buffer = Fother_buffer (obj, Qnil, w->frame);
2220 Fset_window_buffer (window, buffer, Qnil);
2221 if (EQ (window, selected_window))
2222 Fset_buffer (w->buffer);
2224 else
2225 Fdelete_window (window);
2227 break;
2229 case GET_LARGEST_WINDOW:
2230 { /* nil `obj' means to ignore dedicated windows. */
2231 /* Ignore dedicated windows and minibuffers. */
2232 if (MINI_WINDOW_P (w) || (NILP (obj) && !NILP (w->dedicated)))
2233 break;
2235 if (NILP (best_window))
2236 best_window = window;
2237 else
2239 struct window *b = XWINDOW (best_window);
2240 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2241 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2242 best_window = window;
2245 break;
2247 case UNSHOW_BUFFER:
2248 if (EQ (w->buffer, obj))
2250 Lisp_Object buffer;
2251 struct frame *f = XFRAME (w->frame);
2253 /* Find another buffer to show in this window. */
2254 buffer = Fother_buffer (obj, Qnil, w->frame);
2256 /* If this window is dedicated, and in a frame of its own,
2257 kill the frame. */
2258 if (EQ (window, FRAME_ROOT_WINDOW (f))
2259 && !NILP (w->dedicated)
2260 && other_visible_frames (f))
2262 /* Skip the other windows on this frame.
2263 There might be one, the minibuffer! */
2264 while (CONSP (XCDR (windows))
2265 && EQ (XWINDOW (XCAR (windows))->frame,
2266 XWINDOW (XCAR (XCDR (windows)))->frame))
2267 windows = XCDR (windows);
2269 /* Now we can safely delete the frame. */
2270 Fdelete_frame (w->frame, Qnil);
2272 else if (!NILP (w->dedicated) && !NILP (w->parent))
2274 Lisp_Object window;
2275 XSETWINDOW (window, w);
2276 /* If this window is dedicated and not the only window
2277 in its frame, then kill it. */
2278 Fdelete_window (window);
2280 else
2282 /* Otherwise show a different buffer in the window. */
2283 w->dedicated = Qnil;
2284 Fset_window_buffer (window, buffer, Qnil);
2285 if (EQ (window, selected_window))
2286 Fset_buffer (w->buffer);
2289 break;
2291 case REDISPLAY_BUFFER_WINDOWS:
2292 if (EQ (w->buffer, obj))
2294 mark_window_display_accurate (window, 0);
2295 w->update_mode_line = Qt;
2296 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2297 ++update_mode_lines;
2298 best_window = window;
2300 break;
2302 /* Check for a window that has a killed buffer. */
2303 case CHECK_ALL_WINDOWS:
2304 if (! NILP (w->buffer)
2305 && NILP (XBUFFER (w->buffer)->name))
2306 abort ();
2307 break;
2309 case WINDOW_LOOP_UNUSED:
2310 break;
2314 UNGCPRO;
2315 return best_window;
2318 /* Used for debugging. Abort if any window has a dead buffer. */
2320 void
2321 check_all_windows ()
2323 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2326 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
2327 doc: /* Return the window least recently selected or used for display.
2328 \(LRU means Least Recently Used.)
2330 Return a full-width window if possible.
2331 A minibuffer window is never a candidate.
2332 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2333 so if all windows are dedicated, the value is nil.
2334 If optional argument FRAME is `visible', search all visible frames.
2335 If FRAME is 0, search all visible and iconified frames.
2336 If FRAME is t, search all frames.
2337 If FRAME is nil, search only the selected frame.
2338 If FRAME is a frame, search only that frame. */)
2339 (frame, dedicated)
2340 Lisp_Object frame, dedicated;
2342 register Lisp_Object w;
2343 /* First try for a window that is full-width */
2344 w = window_loop (GET_LRU_WINDOW,
2345 NILP (dedicated) ? make_number (1) : make_number (3),
2346 0, frame);
2347 if (!NILP (w) && !EQ (w, selected_window))
2348 return w;
2349 /* If none of them, try the rest */
2350 return window_loop (GET_LRU_WINDOW,
2351 NILP (dedicated) ? make_number (0) : make_number (2),
2352 0, frame);
2355 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
2356 doc: /* Return the largest window in area.
2357 A minibuffer window is never a candidate.
2358 A dedicated window is never a candidate unless DEDICATED is non-nil,
2359 so if all windows are dedicated, the value is nil.
2360 If optional argument FRAME is `visible', search all visible frames.
2361 If FRAME is 0, search all visible and iconified frames.
2362 If FRAME is t, search all frames.
2363 If FRAME is nil, search only the selected frame.
2364 If FRAME is a frame, search only that frame. */)
2365 (frame, dedicated)
2366 Lisp_Object frame, dedicated;
2368 return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
2369 frame);
2372 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2373 doc: /* Return a window currently displaying BUFFER, or nil if none.
2374 BUFFER can be a buffer or a buffer name.
2375 If optional argument FRAME is `visible', search all visible frames.
2376 If optional argument FRAME is 0, search all visible and iconified frames.
2377 If FRAME is t, search all frames.
2378 If FRAME is nil, search only the selected frame.
2379 If FRAME is a frame, search only that frame. */)
2380 (buffer, frame)
2381 Lisp_Object buffer, frame;
2383 buffer = Fget_buffer (buffer);
2384 if (BUFFERP (buffer))
2385 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2386 else
2387 return Qnil;
2390 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2391 0, 1, "",
2392 doc: /* Make WINDOW (or the selected window) fill its frame.
2393 Only the frame WINDOW is on is affected.
2394 This function tries to reduce display jumps
2395 by keeping the text previously visible in WINDOW
2396 in the same place on the frame. Doing this depends on
2397 the value of (window-start WINDOW), so if calling this function
2398 in a program gives strange scrolling, make sure the window-start
2399 value is reasonable when this function is called. */)
2400 (window)
2401 Lisp_Object window;
2403 struct window *w;
2404 int startpos;
2405 int top, new_top;
2407 if (NILP (window))
2408 window = selected_window;
2409 else
2410 CHECK_LIVE_WINDOW (window);
2411 w = XWINDOW (window);
2413 startpos = marker_position (w->start);
2414 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2416 if (MINI_WINDOW_P (w) && top > 0)
2417 error ("Can't expand minibuffer to full frame");
2419 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2421 /* Try to minimize scrolling, by setting the window start to the point
2422 will cause the text at the old window start to be at the same place
2423 on the frame. But don't try to do this if the window start is
2424 outside the visible portion (as might happen when the display is
2425 not current, due to typeahead). */
2426 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2427 if (new_top != top
2428 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2429 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2431 struct position pos;
2432 struct buffer *obuf = current_buffer;
2434 Fset_buffer (w->buffer);
2435 /* This computation used to temporarily move point, but that can
2436 have unwanted side effects due to text properties. */
2437 pos = *vmotion (startpos, -top, w);
2439 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2440 w->window_end_valid = Qnil;
2441 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2442 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2443 : Qnil);
2444 /* We need to do this, so that the window-scroll-functions
2445 get called. */
2446 w->optional_new_start = Qt;
2448 set_buffer_internal (obuf);
2451 return Qnil;
2454 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2455 1, 2, "bDelete windows on (buffer): ",
2456 doc: /* Delete all windows showing BUFFER.
2457 BUFFER must be a buffer or the name of an existing buffer.
2458 Optional second argument FRAME controls which frames are affected.
2459 If optional argument FRAME is `visible', search all visible frames.
2460 If FRAME is 0, search all visible and iconified frames.
2461 If FRAME is nil, search all frames.
2462 If FRAME is t, search only the selected frame.
2463 If FRAME is a frame, search only that frame. */)
2464 (buffer, frame)
2465 Lisp_Object buffer, frame;
2467 /* FRAME uses t and nil to mean the opposite of what window_loop
2468 expects. */
2469 if (NILP (frame))
2470 frame = Qt;
2471 else if (EQ (frame, Qt))
2472 frame = Qnil;
2474 if (!NILP (buffer))
2476 buffer = Fget_buffer (buffer);
2477 CHECK_BUFFER (buffer);
2478 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2481 return Qnil;
2484 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2485 Sreplace_buffer_in_windows,
2486 1, 1, "bReplace buffer in windows: ",
2487 doc: /* Replace BUFFER with some other buffer in all windows showing it.
2488 BUFFER may be a buffer or the name of an existing buffer. */)
2489 (buffer)
2490 Lisp_Object buffer;
2492 if (!NILP (buffer))
2494 buffer = Fget_buffer (buffer);
2495 CHECK_BUFFER (buffer);
2496 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2498 return Qnil;
2501 /* Replace BUFFER with some other buffer in all windows
2502 of all frames, even those on other keyboards. */
2504 void
2505 replace_buffer_in_all_windows (buffer)
2506 Lisp_Object buffer;
2508 #ifdef MULTI_KBOARD
2509 Lisp_Object tail, frame;
2511 /* A single call to window_loop won't do the job
2512 because it only considers frames on the current keyboard.
2513 So loop manually over frames, and handle each one. */
2514 FOR_EACH_FRAME (tail, frame)
2515 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2516 #else
2517 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2518 #endif
2521 /* Set the height of WINDOW and all its inferiors. */
2523 /* The smallest acceptable dimensions for a window. Anything smaller
2524 might crash Emacs. */
2526 #define MIN_SAFE_WINDOW_WIDTH (2)
2527 #define MIN_SAFE_WINDOW_HEIGHT (1)
2529 /* Make sure that window_min_height and window_min_width are
2530 not too small; if they are, set them to safe minima. */
2532 static void
2533 check_min_window_sizes ()
2535 /* Smaller values might permit a crash. */
2536 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2537 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2538 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2539 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2542 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2543 minimum allowable size. */
2545 void
2546 check_frame_size (frame, rows, cols)
2547 FRAME_PTR frame;
2548 int *rows, *cols;
2550 /* For height, we have to see:
2551 how many windows the frame has at minimum (one or two),
2552 and whether it has a menu bar or other special stuff at the top. */
2553 int min_height
2554 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2555 ? MIN_SAFE_WINDOW_HEIGHT
2556 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2558 if (FRAME_TOP_MARGIN (frame) > 0)
2559 min_height += FRAME_TOP_MARGIN (frame);
2561 if (*rows < min_height)
2562 *rows = min_height;
2563 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2564 *cols = MIN_SAFE_WINDOW_WIDTH;
2567 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2568 check if W's width can be changed, otherwise check W's height.
2569 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2570 siblings, too. If none of the siblings is resizable, WINDOW isn't
2571 either. */
2573 static int
2574 window_fixed_size_p (w, width_p, check_siblings_p)
2575 struct window *w;
2576 int width_p, check_siblings_p;
2578 int fixed_p;
2579 struct window *c;
2581 if (!NILP (w->hchild))
2583 c = XWINDOW (w->hchild);
2585 if (width_p)
2587 /* A horiz. combination is fixed-width if all of if its
2588 children are. */
2589 while (c && window_fixed_size_p (c, width_p, 0))
2590 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2591 fixed_p = c == NULL;
2593 else
2595 /* A horiz. combination is fixed-height if one of if its
2596 children is. */
2597 while (c && !window_fixed_size_p (c, width_p, 0))
2598 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2599 fixed_p = c != NULL;
2602 else if (!NILP (w->vchild))
2604 c = XWINDOW (w->vchild);
2606 if (width_p)
2608 /* A vert. combination is fixed-width if one of if its
2609 children is. */
2610 while (c && !window_fixed_size_p (c, width_p, 0))
2611 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2612 fixed_p = c != NULL;
2614 else
2616 /* A vert. combination is fixed-height if all of if its
2617 children are. */
2618 while (c && window_fixed_size_p (c, width_p, 0))
2619 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2620 fixed_p = c == NULL;
2623 else if (BUFFERP (w->buffer))
2625 struct buffer *old = current_buffer;
2626 Lisp_Object val;
2628 current_buffer = XBUFFER (w->buffer);
2629 val = find_symbol_value (Qwindow_size_fixed);
2630 current_buffer = old;
2632 fixed_p = 0;
2633 if (!EQ (val, Qunbound))
2635 fixed_p = !NILP (val);
2637 if (fixed_p
2638 && ((EQ (val, Qheight) && width_p)
2639 || (EQ (val, Qwidth) && !width_p)))
2640 fixed_p = 0;
2643 /* Can't tell if this one is resizable without looking at
2644 siblings. If all siblings are fixed-size this one is too. */
2645 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2647 Lisp_Object child;
2649 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2650 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2651 break;
2653 if (NILP (child))
2654 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2655 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2656 break;
2658 if (NILP (child))
2659 fixed_p = 1;
2662 else
2663 fixed_p = 1;
2665 return fixed_p;
2668 /* Return the minimum size for leaf window W. WIDTH_P non-zero means
2669 take into account fringes and the scrollbar of W. WIDTH_P zero means
2670 take into account mode-line of W. Return 1 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 /* Don't count the header-line here. It would break
2690 splitting a window with a header-line when the new
2691 window shall have a height of two (calculator does
2692 that). */
2693 + (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)));
2695 return size;
2698 /* Return the minimum size of window W, not taking fixed-width windows
2699 into account. WIDTH_P non-zero means return the minimum width,
2700 otherwise return the minimum height. If W is a combination window,
2701 compute the minimum size from the minimum sizes of W's children. */
2703 static int
2704 window_min_size_1 (w, width_p)
2705 struct window *w;
2706 int width_p;
2708 struct window *c;
2709 int size;
2711 if (!NILP (w->hchild))
2713 c = XWINDOW (w->hchild);
2714 size = 0;
2716 if (width_p)
2718 /* The min width of a horizontal combination is
2719 the sum of the min widths of its children. */
2720 while (c)
2722 size += window_min_size_1 (c, width_p);
2723 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2726 else
2728 /* The min height a horizontal combination equals
2729 the maximum of all min height of its children. */
2730 while (c)
2732 int min_size = window_min_size_1 (c, width_p);
2733 size = max (min_size, size);
2734 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2738 else if (!NILP (w->vchild))
2740 c = XWINDOW (w->vchild);
2741 size = 0;
2743 if (width_p)
2745 /* The min width of a vertical combination is
2746 the maximum of the min widths of its children. */
2747 while (c)
2749 int min_size = window_min_size_1 (c, width_p);
2750 size = max (min_size, size);
2751 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2754 else
2756 /* The min height of a vertical combination equals
2757 the sum of the min height of its children. */
2758 while (c)
2760 size += window_min_size_1 (c, width_p);
2761 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2765 else
2766 size = window_min_size_2 (w, width_p);
2768 return size;
2772 /* Return the minimum size of window W, taking fixed-size windows into
2773 account. WIDTH_P non-zero means return the minimum width,
2774 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2775 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2776 unless FIXED is null. */
2778 static int
2779 window_min_size (w, width_p, ignore_fixed_p, fixed)
2780 struct window *w;
2781 int width_p, ignore_fixed_p, *fixed;
2783 int size, fixed_p;
2785 if (ignore_fixed_p)
2786 fixed_p = 0;
2787 else
2788 fixed_p = window_fixed_size_p (w, width_p, 1);
2790 if (fixed)
2791 *fixed = fixed_p;
2793 if (fixed_p)
2794 size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines);
2795 else
2796 size = window_min_size_1 (w, width_p);
2798 return size;
2802 /* Adjust the margins of window W if text area is too small.
2803 Return 1 if window width is ok after adjustment; 0 if window
2804 is still too narrow. */
2806 static int
2807 adjust_window_margins (w)
2808 struct window *w;
2810 int box_cols = (WINDOW_TOTAL_COLS (w)
2811 - WINDOW_FRINGE_COLS (w)
2812 - WINDOW_SCROLL_BAR_COLS (w));
2813 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2814 + WINDOW_RIGHT_MARGIN_COLS (w));
2816 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2817 return 1;
2819 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2820 return 0;
2822 /* Window's text area is too narrow, but reducing the window
2823 margins will fix that. */
2824 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2825 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2827 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2828 w->left_margin_cols = w->right_margin_cols
2829 = make_number (margin_cols/2);
2830 else
2831 w->right_margin_cols = make_number (margin_cols);
2833 else
2834 w->left_margin_cols = make_number (margin_cols);
2835 return 1;
2838 /* Calculate new sizes for windows in the list FORWARD when the window size
2839 goes from TOTAL to SIZE. TOTAL must be greater than SIZE.
2840 The number of windows in FORWARD is NCHILDREN, and the number that
2841 can shrink is SHRINKABLE.
2842 The minimum size a window can have is MIN_SIZE.
2843 If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
2844 If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
2845 shrinking rows.
2847 This function returns an allocated array of new sizes that the caller
2848 must free. The size -1 means the window is fixed and RESIZE_FIXED_P
2849 is zero. Array index 0 refers to the first window in FORWARD, 1 to
2850 the second, and so on.
2852 This function tries to keep windows at least at the minimum size
2853 and resize other windows before it resizes any window to zero (i.e.
2854 delete that window).
2856 Windows are resized proportional to their size, so bigger windows
2857 shrink more than smaller windows. */
2858 static int *
2859 shrink_windows (total, size, nchildren, shrinkable,
2860 min_size, resize_fixed_p, forward, width_p)
2861 int total, size, nchildren, shrinkable, min_size;
2862 int resize_fixed_p, width_p;
2863 Lisp_Object forward;
2865 int available_resize = 0;
2866 int *new_sizes;
2867 struct window *c;
2868 Lisp_Object child;
2869 int smallest = total;
2870 int total_removed = 0;
2871 int total_shrink = total - size;
2872 int i;
2874 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2876 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2878 int child_size;
2880 c = XWINDOW (child);
2881 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2883 if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2884 new_sizes[i] = -1;
2885 else
2887 new_sizes[i] = child_size;
2888 if (child_size > min_size)
2889 available_resize += child_size - min_size;
2892 /* We might need to shrink some windows to zero. Find the smallest
2893 windows and set them to 0 until we can fulfil the new size. */
2895 while (shrinkable > 1 && size + available_resize < total)
2897 for (i = 0; i < nchildren; ++i)
2898 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2899 smallest = new_sizes[i];
2901 for (i = 0; i < nchildren; ++i)
2902 if (new_sizes[i] == smallest)
2904 /* Resize this window down to zero. */
2905 new_sizes[i] = 0;
2906 if (smallest > min_size)
2907 available_resize -= smallest - min_size;
2908 available_resize += smallest;
2909 --shrinkable;
2910 total_removed += smallest;
2912 /* We don't know what the smallest is now. */
2913 smallest = total;
2915 /* Out of for, just remove one window at the time and
2916 check again if we have enough space. */
2917 break;
2921 /* Now, calculate the new sizes. Try to shrink each window
2922 proportional to its size. */
2923 for (i = 0; i < nchildren; ++i)
2925 if (new_sizes[i] > min_size)
2927 int to_shrink = total_shrink*new_sizes[i]/total;
2928 if (new_sizes[i] - to_shrink < min_size)
2929 to_shrink = new_sizes[i] - min_size;
2930 new_sizes[i] -= to_shrink;
2931 total_removed += to_shrink;
2935 /* Any reminder due to rounding, we just subtract from windows
2936 that are left and still can be shrunk. */
2937 while (total_shrink > total_removed)
2939 int nonzero_sizes = 0;
2940 int nonzero_idx = -1;
2942 for (i = 0; i < nchildren; ++i)
2943 if (new_sizes[i] > 0)
2945 ++nonzero_sizes;
2946 nonzero_idx = i;
2949 for (i = 0; i < nchildren; ++i)
2950 if (new_sizes[i] > min_size)
2952 --new_sizes[i];
2953 ++total_removed;
2955 /* Out of for, just shrink one window at the time and
2956 check again if we have enough space. */
2957 break;
2961 /* Special case, only one window left. */
2962 if (nonzero_sizes == 1)
2963 break;
2966 /* Any surplus due to rounding, we add to windows that are left. */
2967 while (total_shrink < total_removed)
2969 for (i = 0; i < nchildren; ++i)
2971 if (new_sizes[i] != 0 && total_shrink < total_removed)
2973 ++new_sizes[i];
2974 --total_removed;
2975 break;
2980 return new_sizes;
2983 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2984 WINDOW's width. Resize WINDOW's children, if any, so that they
2985 keep their proportionate size relative to WINDOW.
2987 If FIRST_ONLY is 1, change only the first of WINDOW's children when
2988 they are in series. If LAST_ONLY is 1, change only the last of
2989 WINDOW's children when they are in series.
2991 Propagate WINDOW's top or left edge position to children. Delete
2992 windows that become too small unless NODELETE_P is non-zero.
2994 If NODELETE_P is 2, that means we do delete windows that are
2995 too small, even if they were too small before! */
2997 static void
2998 size_window (window, size, width_p, nodelete_p, first_only, last_only)
2999 Lisp_Object window;
3000 int size, width_p, nodelete_p;
3001 int first_only, last_only;
3003 struct window *w = XWINDOW (window);
3004 struct window *c;
3005 Lisp_Object child, *forward, *sideward;
3006 int old_size, min_size, safe_min_size;
3008 check_min_window_sizes ();
3009 size = max (0, size);
3011 /* If the window has been "too small" at one point,
3012 don't delete it for being "too small" in the future.
3013 Preserve it as long as that is at all possible. */
3014 if (width_p)
3016 old_size = WINDOW_TOTAL_COLS (w);
3017 min_size = window_min_width;
3018 safe_min_size = window_min_size_2 (w, 1);
3020 else
3022 old_size = XINT (w->total_lines);
3023 min_size = window_min_height;
3024 safe_min_size = window_min_size_2 (w, 0);
3027 if (old_size < min_size && nodelete_p != 2)
3028 w->too_small_ok = Qt;
3030 /* Move the following test here since otherwise the
3031 preceding test doesn't make sense. martin. */
3032 if (nodelete_p == 2)
3033 nodelete_p = 0;
3035 /* Maybe delete WINDOW if it's too small. */
3036 if (nodelete_p != 1 && !NILP (w->parent))
3038 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
3039 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
3040 if (min_size < safe_min_size)
3041 min_size = safe_min_size;
3042 if (size < min_size)
3044 delete_window (window);
3045 return;
3049 /* Set redisplay hints. */
3050 w->last_modified = make_number (0);
3051 w->last_overlay_modified = make_number (0);
3052 windows_or_buffers_changed++;
3053 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
3055 if (width_p)
3057 sideward = &w->vchild;
3058 forward = &w->hchild;
3059 w->total_cols = make_number (size);
3060 adjust_window_margins (w);
3062 else
3064 sideward = &w->hchild;
3065 forward = &w->vchild;
3066 w->total_lines = make_number (size);
3067 w->orig_total_lines = Qnil;
3070 if (!NILP (*sideward))
3072 /* We have a chain of parallel siblings whose size should all change. */
3073 for (child = *sideward; !NILP (child); child = c->next)
3075 c = XWINDOW (child);
3076 if (width_p)
3077 c->left_col = w->left_col;
3078 else
3079 c->top_line = w->top_line;
3080 size_window (child, size, width_p, nodelete_p,
3081 first_only, last_only);
3084 else if (!NILP (*forward) && last_only)
3086 /* Change the last in a series of siblings. */
3087 Lisp_Object last_child;
3088 int child_size;
3090 for (child = *forward; !NILP (child); child = c->next)
3092 c = XWINDOW (child);
3093 last_child = child;
3096 child_size = XINT (width_p ? c->total_cols : c->total_lines);
3097 size_window (last_child,
3098 size - old_size + child_size,
3099 width_p, nodelete_p, first_only, last_only);
3101 else if (!NILP (*forward) && first_only)
3103 /* Change the first in a series of siblings. */
3104 int child_size;
3106 child = *forward;
3107 c = XWINDOW (child);
3109 if (width_p)
3110 c->left_col = w->left_col;
3111 else
3112 c->top_line = w->top_line;
3114 child_size = XINT (width_p ? c->total_cols : c->total_lines);
3115 size_window (child,
3116 size - old_size + child_size,
3117 width_p, nodelete_p, first_only, last_only);
3119 else if (!NILP (*forward))
3121 int fixed_size, each, extra, n;
3122 int resize_fixed_p, nfixed;
3123 int last_pos, first_pos, nchildren, total;
3124 int *new_sizes = NULL;
3126 /* Determine the fixed-size portion of this window, and the
3127 number of child windows. */
3128 fixed_size = nchildren = nfixed = total = 0;
3129 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
3131 int child_size;
3133 c = XWINDOW (child);
3134 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
3135 total += child_size;
3137 if (window_fixed_size_p (c, width_p, 0))
3139 fixed_size += child_size;
3140 ++nfixed;
3144 /* If the new size is smaller than fixed_size, or if there
3145 aren't any resizable windows, allow resizing fixed-size
3146 windows. */
3147 resize_fixed_p = nfixed == nchildren || size < fixed_size;
3149 /* Compute how many lines/columns to add/remove to each child. The
3150 value of extra takes care of rounding errors. */
3151 n = resize_fixed_p ? nchildren : nchildren - nfixed;
3152 if (size < total && n > 1)
3153 new_sizes = shrink_windows (total, size, nchildren, n, min_size,
3154 resize_fixed_p, *forward, width_p);
3155 else
3157 each = (size - total) / n;
3158 extra = (size - total) - n * each;
3161 /* Compute new children heights and edge positions. */
3162 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
3163 last_pos = first_pos;
3164 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
3166 int new_size, old_size;
3168 c = XWINDOW (child);
3169 old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines);
3170 new_size = old_size;
3172 /* The top or left edge position of this child equals the
3173 bottom or right edge of its predecessor. */
3174 if (width_p)
3175 c->left_col = make_number (last_pos);
3176 else
3177 c->top_line = make_number (last_pos);
3179 /* If this child can be resized, do it. */
3180 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
3182 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
3183 extra = 0;
3186 /* Set new height. Note that size_window also propagates
3187 edge positions to children, so it's not a no-op if we
3188 didn't change the child's size. */
3189 size_window (child, new_size, width_p, 1, first_only, last_only);
3191 /* Remember the bottom/right edge position of this child; it
3192 will be used to set the top/left edge of the next child. */
3193 last_pos += new_size;
3196 if (new_sizes) xfree (new_sizes);
3198 /* We should have covered the parent exactly with child windows. */
3199 xassert (size == last_pos - first_pos);
3201 /* Now delete any children that became too small. */
3202 if (!nodelete_p)
3203 for (child = *forward; !NILP (child); child = c->next)
3205 int child_size;
3206 c = XWINDOW (child);
3207 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
3208 size_window (child, child_size, width_p, 2, first_only, last_only);
3213 /* Set WINDOW's height to HEIGHT, and recursively change the height of
3214 WINDOW's children. NODELETE non-zero means don't delete windows
3215 that become too small in the process. (The caller should check
3216 later and do so if appropriate.) */
3218 void
3219 set_window_height (window, height, nodelete)
3220 Lisp_Object window;
3221 int height;
3222 int nodelete;
3224 size_window (window, height, 0, nodelete, 0, 0);
3228 /* Set WINDOW's width to WIDTH, and recursively change the width of
3229 WINDOW's children. NODELETE non-zero means don't delete windows
3230 that become too small in the process. (The caller should check
3231 later and do so if appropriate.) */
3233 void
3234 set_window_width (window, width, nodelete)
3235 Lisp_Object window;
3236 int width;
3237 int nodelete;
3239 size_window (window, width, 1, nodelete, 0, 0);
3242 /* Change window heights in windows rooted in WINDOW by N lines. */
3244 void
3245 change_window_heights (window, n)
3246 Lisp_Object window;
3247 int n;
3249 struct window *w = XWINDOW (window);
3251 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
3252 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
3254 if (INTEGERP (w->orig_top_line))
3255 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
3256 if (INTEGERP (w->orig_total_lines))
3257 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
3259 /* Handle just the top child in a vertical split. */
3260 if (!NILP (w->vchild))
3261 change_window_heights (w->vchild, n);
3263 /* Adjust all children in a horizontal split. */
3264 for (window = w->hchild; !NILP (window); window = w->next)
3266 w = XWINDOW (window);
3267 change_window_heights (window, n);
3272 int window_select_count;
3274 Lisp_Object
3275 Fset_window_buffer_unwind (obuf)
3276 Lisp_Object obuf;
3278 Fset_buffer (obuf);
3279 return Qnil;
3282 EXFUN (Fset_window_fringes, 4);
3283 EXFUN (Fset_window_scroll_bars, 4);
3285 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3286 means it's allowed to run hooks. See make_frame for a case where
3287 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3288 margins, fringes, and scroll-bar settings of the window are not
3289 reset from the buffer's local settings. */
3291 void
3292 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
3293 Lisp_Object window, buffer;
3294 int run_hooks_p, keep_margins_p;
3296 struct window *w = XWINDOW (window);
3297 struct buffer *b = XBUFFER (buffer);
3298 int count = SPECPDL_INDEX ();
3300 w->buffer = buffer;
3302 if (EQ (window, selected_window))
3303 b->last_selected_window = window;
3305 /* Let redisplay errors through. */
3306 b->display_error_modiff = 0;
3308 /* Update time stamps of buffer display. */
3309 if (INTEGERP (b->display_count))
3310 XSETINT (b->display_count, XINT (b->display_count) + 1);
3311 b->display_time = Fcurrent_time ();
3313 XSETFASTINT (w->window_end_pos, 0);
3314 XSETFASTINT (w->window_end_vpos, 0);
3315 bzero (&w->last_cursor, sizeof w->last_cursor);
3316 w->window_end_valid = Qnil;
3317 w->hscroll = w->min_hscroll = make_number (0);
3318 w->vscroll = 0;
3319 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3320 set_marker_restricted (w->start,
3321 make_number (b->last_window_start),
3322 buffer);
3323 w->start_at_line_beg = Qnil;
3324 w->force_start = Qnil;
3325 XSETFASTINT (w->last_modified, 0);
3326 XSETFASTINT (w->last_overlay_modified, 0);
3327 windows_or_buffers_changed++;
3329 /* We must select BUFFER for running the window-scroll-functions.
3330 If WINDOW is selected, switch permanently.
3331 Otherwise, switch but go back to the ambient buffer afterward. */
3332 if (EQ (window, selected_window))
3333 Fset_buffer (buffer);
3334 /* We can't check ! NILP (Vwindow_scroll_functions) here
3335 because that might itself be a local variable. */
3336 else if (window_initialized)
3338 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
3339 Fset_buffer (buffer);
3342 if (!keep_margins_p)
3344 /* Set left and right marginal area width etc. from buffer. */
3346 /* This may call adjust_window_margins three times, so
3347 temporarily disable window margins. */
3348 Lisp_Object save_left = w->left_margin_cols;
3349 Lisp_Object save_right = w->right_margin_cols;
3351 w->left_margin_cols = w->right_margin_cols = Qnil;
3353 Fset_window_fringes (window,
3354 b->left_fringe_width, b->right_fringe_width,
3355 b->fringes_outside_margins);
3357 Fset_window_scroll_bars (window,
3358 b->scroll_bar_width,
3359 b->vertical_scroll_bar_type, Qnil);
3361 w->left_margin_cols = save_left;
3362 w->right_margin_cols = save_right;
3364 Fset_window_margins (window,
3365 b->left_margin_cols, b->right_margin_cols);
3368 if (run_hooks_p)
3370 if (! NILP (Vwindow_scroll_functions))
3371 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3372 Fmarker_position (w->start));
3374 if (! NILP (Vwindow_configuration_change_hook)
3375 && ! NILP (Vrun_hooks))
3376 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3379 unbind_to (count, Qnil);
3383 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3384 doc: /* Make WINDOW display BUFFER as its contents.
3385 BUFFER can be a buffer or the name of an existing buffer.
3386 Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
3387 display margins, fringe widths, and scroll bar settings are maintained;
3388 the default is to reset these from BUFFER's local settings or the frame
3389 defaults.
3391 This function runs the hook `window-scroll-functions'. */)
3392 (window, buffer, keep_margins)
3393 register Lisp_Object window, buffer, keep_margins;
3395 register Lisp_Object tem;
3396 register struct window *w = decode_window (window);
3398 XSETWINDOW (window, w);
3399 buffer = Fget_buffer (buffer);
3400 CHECK_BUFFER (buffer);
3402 if (NILP (XBUFFER (buffer)->name))
3403 error ("Attempt to display deleted buffer");
3405 tem = w->buffer;
3406 if (NILP (tem))
3407 error ("Window is deleted");
3408 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3409 is first being set up. */
3411 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3412 error ("Window is dedicated to `%s'",
3413 SDATA (XBUFFER (tem)->name));
3415 unshow_buffer (w);
3418 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3419 return Qnil;
3422 /* Note that selected_window can be nil
3423 when this is called from Fset_window_configuration. */
3425 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3426 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3427 If WINDOW is not already selected, make WINDOW's buffer current
3428 and make WINDOW the frame's selected window. Return WINDOW.
3429 Optional second arg NORECORD non-nil means
3430 do not put this buffer at the front of the list of recently selected ones.
3432 Note that the main editor command loop
3433 selects the buffer of the selected window before each command. */)
3434 (window, norecord)
3435 register Lisp_Object window, norecord;
3437 register struct window *w;
3438 register struct window *ow;
3439 struct frame *sf;
3441 CHECK_LIVE_WINDOW (window);
3443 w = XWINDOW (window);
3444 w->frozen_window_start_p = 0;
3446 ++window_select_count;
3447 XSETFASTINT (w->use_time, window_select_count);
3448 if (EQ (window, selected_window))
3449 return window;
3451 /* Store the current buffer's actual point into the
3452 old selected window. It belongs to that window,
3453 and when the window is not selected, must be in the window. */
3454 if (!NILP (selected_window))
3456 ow = XWINDOW (selected_window);
3457 if (! NILP (ow->buffer))
3458 set_marker_both (ow->pointm, ow->buffer,
3459 BUF_PT (XBUFFER (ow->buffer)),
3460 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3463 selected_window = window;
3464 sf = SELECTED_FRAME ();
3465 if (XFRAME (WINDOW_FRAME (w)) != sf)
3467 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3468 /* Use this rather than Fhandle_switch_frame
3469 so that FRAME_FOCUS_FRAME is moved appropriately as we
3470 move around in the state where a minibuffer in a separate
3471 frame is active. */
3472 Fselect_frame (WINDOW_FRAME (w));
3474 else
3475 sf->selected_window = window;
3477 if (NILP (norecord))
3478 record_buffer (w->buffer);
3479 Fset_buffer (w->buffer);
3481 XBUFFER (w->buffer)->last_selected_window = window;
3483 /* Go to the point recorded in the window.
3484 This is important when the buffer is in more
3485 than one window. It also matters when
3486 redisplay_window has altered point after scrolling,
3487 because it makes the change only in the window. */
3489 register int new_point = marker_position (w->pointm);
3490 if (new_point < BEGV)
3491 SET_PT (BEGV);
3492 else if (new_point > ZV)
3493 SET_PT (ZV);
3494 else
3495 SET_PT (new_point);
3498 windows_or_buffers_changed++;
3499 return window;
3502 static Lisp_Object
3503 select_window_norecord (window)
3504 Lisp_Object window;
3506 return Fselect_window (window, Qt);
3509 /* Deiconify the frame containing the window WINDOW,
3510 unless it is the selected frame;
3511 then return WINDOW.
3513 The reason for the exception for the selected frame
3514 is that it seems better not to change the selected frames visibility
3515 merely because of displaying a different buffer in it.
3516 The deiconification is useful when a buffer gets shown in
3517 another frame that you were not using lately. */
3519 static Lisp_Object
3520 display_buffer_1 (window)
3521 Lisp_Object window;
3523 Lisp_Object frame = XWINDOW (window)->frame;
3524 FRAME_PTR f = XFRAME (frame);
3526 FRAME_SAMPLE_VISIBILITY (f);
3528 if (EQ (frame, selected_frame))
3529 ; /* Assume the selected frame is already visible enough. */
3530 else if (minibuf_level > 0
3531 && MINI_WINDOW_P (XWINDOW (selected_window))
3532 && WINDOW_LIVE_P (minibuf_selected_window)
3533 && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
3534 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3535 else
3537 if (FRAME_ICONIFIED_P (f))
3538 Fmake_frame_visible (frame);
3539 else if (FRAME_VISIBLE_P (f))
3540 Fraise_frame (frame);
3543 return window;
3546 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
3547 doc: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
3548 If the value is t, `display-buffer' or `pop-to-buffer' would create a
3549 special frame for that buffer using the default frame parameters.
3551 If the value is a list, it is a list of frame parameters that would be used
3552 to make a frame for that buffer.
3553 The variables `special-display-buffer-names'
3554 and `special-display-regexps' control this. */)
3555 (buffer_name)
3556 Lisp_Object buffer_name;
3558 Lisp_Object tem;
3560 CHECK_STRING (buffer_name);
3562 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
3563 if (!NILP (tem))
3564 return Qt;
3566 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
3567 if (!NILP (tem))
3568 return XCDR (tem);
3570 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
3572 Lisp_Object car = XCAR (tem);
3573 if (STRINGP (car)
3574 && fast_string_match (car, buffer_name) >= 0)
3575 return Qt;
3576 else if (CONSP (car)
3577 && STRINGP (XCAR (car))
3578 && fast_string_match (XCAR (car), buffer_name) >= 0)
3579 return XCDR (car);
3581 return Qnil;
3584 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
3585 doc: /* Returns non-nil if a buffer named BUFFER-NAME would use the same window.
3586 More precisely, if `display-buffer' or `pop-to-buffer' would display
3587 that buffer in the selected window rather than (as usual) in some other window.
3588 See `same-window-buffer-names' and `same-window-regexps'. */)
3589 (buffer_name)
3590 Lisp_Object buffer_name;
3592 Lisp_Object tem;
3594 CHECK_STRING (buffer_name);
3596 tem = Fmember (buffer_name, Vsame_window_buffer_names);
3597 if (!NILP (tem))
3598 return Qt;
3600 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
3601 if (!NILP (tem))
3602 return Qt;
3604 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3606 Lisp_Object car = XCAR (tem);
3607 if (STRINGP (car)
3608 && fast_string_match (car, buffer_name) >= 0)
3609 return Qt;
3610 else if (CONSP (car)
3611 && STRINGP (XCAR (car))
3612 && fast_string_match (XCAR (car), buffer_name) >= 0)
3613 return Qt;
3615 return Qnil;
3618 /* Use B so the default is (other-buffer). */
3619 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
3620 "BDisplay buffer: \nP",
3621 doc: /* Make BUFFER appear in some window but don't select it.
3622 BUFFER must be the name of an existing buffer, or, when called from Lisp,
3623 a buffer.
3624 If BUFFER is shown already in some window, just use that one,
3625 unless the window is the selected window and the optional second
3626 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3627 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3628 Returns the window displaying BUFFER.
3629 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3630 displaying BUFFER, then simply raise that frame.
3632 The variables `special-display-buffer-names',
3633 `special-display-regexps', `same-window-buffer-names', and
3634 `same-window-regexps' customize how certain buffer names are handled.
3635 The latter two take effect only if NOT-THIS-WINDOW is nil.
3637 If optional argument FRAME is `visible', check all visible frames
3638 for a window to use.
3639 If FRAME is 0, check all visible and iconified frames.
3640 If FRAME is t, check all frames.
3641 If FRAME is a frame, check only that frame.
3642 If FRAME is nil, check only the selected frame
3643 (actually the last nonminibuffer frame),
3644 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3645 which means search visible and iconified frames.
3647 If a full-width window on a splittable frame is available to display
3648 the buffer, it may be split, subject to the value of the variable
3649 `split-height-threshold'.
3651 If `even-window-heights' is non-nil, window heights will be evened out
3652 if displaying the buffer causes two vertically adjacent windows to be
3653 displayed. */)
3654 (buffer, not_this_window, frame)
3655 register Lisp_Object buffer, not_this_window, frame;
3657 register Lisp_Object window, tem, swp;
3658 struct frame *f;
3660 swp = Qnil;
3661 buffer = Fget_buffer (buffer);
3662 CHECK_BUFFER (buffer);
3664 if (!NILP (Vdisplay_buffer_function))
3665 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3667 if (NILP (not_this_window)
3668 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3669 return display_buffer_1 (selected_window);
3671 /* See if the user has specified this buffer should appear
3672 in the selected window. */
3673 if (NILP (not_this_window))
3675 swp = Fsame_window_p (XBUFFER (buffer)->name);
3676 if (!NILP (swp) && !no_switch_window (selected_window))
3678 Fswitch_to_buffer (buffer, Qnil);
3679 return display_buffer_1 (selected_window);
3683 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3684 look for a window showing BUFFER on any visible or iconified frame.
3685 Otherwise search only the current frame. */
3686 if (! NILP (frame))
3687 tem = frame;
3688 else if (pop_up_frames
3689 || display_buffer_reuse_frames
3690 || last_nonminibuf_frame == 0)
3691 XSETFASTINT (tem, 0);
3692 else
3693 XSETFRAME (tem, last_nonminibuf_frame);
3695 window = Fget_buffer_window (buffer, tem);
3696 if (!NILP (window)
3697 && (NILP (not_this_window) || !EQ (window, selected_window)))
3698 return display_buffer_1 (window);
3700 /* Certain buffer names get special handling. */
3701 if (!NILP (Vspecial_display_function) && NILP (swp))
3703 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3704 if (EQ (tem, Qt))
3705 return call1 (Vspecial_display_function, buffer);
3706 if (CONSP (tem))
3707 return call2 (Vspecial_display_function, buffer, tem);
3710 /* If there are no frames open that have more than a minibuffer,
3711 we need to create a new frame. */
3712 if (pop_up_frames || last_nonminibuf_frame == 0)
3714 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3715 Fset_window_buffer (window, buffer, Qnil);
3716 return display_buffer_1 (window);
3719 f = SELECTED_FRAME ();
3720 if (pop_up_windows
3721 || FRAME_MINIBUF_ONLY_P (f)
3722 /* If the current frame is a special display frame,
3723 don't try to reuse its windows. */
3724 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3726 Lisp_Object frames;
3728 frames = Qnil;
3729 if (FRAME_MINIBUF_ONLY_P (f))
3730 XSETFRAME (frames, last_nonminibuf_frame);
3732 /* Note that both Fget_largest_window and Fget_lru_window
3733 ignore minibuffers and dedicated windows.
3734 This means they can return nil. */
3736 /* If the frame we would try to split cannot be split,
3737 try other frames. */
3738 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3740 /* Try visible frames first. */
3741 window = Fget_largest_window (Qvisible, Qt);
3742 /* If that didn't work, try iconified frames. */
3743 if (NILP (window))
3744 window = Fget_largest_window (make_number (0), Qt);
3745 #if 0 /* Don't try windows on other displays. */
3746 if (NILP (window))
3747 window = Fget_largest_window (Qt, Qt);
3748 #endif
3750 else
3751 window = Fget_largest_window (frames, Qt);
3753 /* If the largest window is tall enough, full-width, and either eligible
3754 for splitting or the only window, split it. */
3755 if (!NILP (window)
3756 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3757 && WINDOW_FULL_WIDTH_P (XWINDOW (window))
3758 && (window_height (window) >= split_height_threshold
3759 || (NILP (XWINDOW (window)->parent)))
3760 && (window_height (window)
3761 >= (2 * window_min_size_2 (XWINDOW (window), 0))))
3762 window = Fsplit_window (window, Qnil, Qnil);
3763 else
3765 Lisp_Object upper, lower, other;
3767 window = Fget_lru_window (frames, Qt);
3768 /* If the LRU window is tall enough, and either eligible for splitting
3769 and selected or the only window, split it. */
3770 if (!NILP (window)
3771 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3772 && ((EQ (window, selected_window)
3773 && window_height (window) >= split_height_threshold)
3774 || (NILP (XWINDOW (window)->parent)))
3775 && (window_height (window)
3776 >= (2 * window_min_size_2 (XWINDOW (window), 0))))
3777 window = Fsplit_window (window, Qnil, Qnil);
3778 else
3779 window = Fget_lru_window (frames, Qnil);
3780 /* If Fget_lru_window returned nil, try other approaches. */
3782 /* Try visible frames first. */
3783 if (NILP (window))
3784 window = Fget_buffer_window (buffer, Qvisible);
3785 if (NILP (window))
3786 window = Fget_largest_window (Qvisible, Qnil);
3787 /* If that didn't work, try iconified frames. */
3788 if (NILP (window))
3789 window = Fget_buffer_window (buffer, make_number (0));
3790 if (NILP (window))
3791 window = Fget_largest_window (make_number (0), Qnil);
3793 #if 0 /* Don't try frames on other displays. */
3794 if (NILP (window))
3795 window = Fget_buffer_window (buffer, Qt);
3796 if (NILP (window))
3797 window = Fget_largest_window (Qt, Qnil);
3798 #endif
3799 /* As a last resort, make a new frame. */
3800 if (NILP (window))
3801 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3802 /* If window appears above or below another,
3803 even out their heights. */
3804 other = upper = lower = Qnil;
3805 if (!NILP (XWINDOW (window)->prev))
3806 other = upper = XWINDOW (window)->prev, lower = window;
3807 if (!NILP (XWINDOW (window)->next))
3808 other = lower = XWINDOW (window)->next, upper = window;
3809 if (!NILP (other)
3810 && !NILP (Veven_window_heights)
3811 /* Check that OTHER and WINDOW are vertically arrayed. */
3812 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3813 && (XFASTINT (XWINDOW (other)->total_lines)
3814 > XFASTINT (XWINDOW (window)->total_lines)))
3816 int total = (XFASTINT (XWINDOW (other)->total_lines)
3817 + XFASTINT (XWINDOW (window)->total_lines));
3818 enlarge_window (upper,
3819 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
3824 else
3825 window = Fget_lru_window (Qnil, Qnil);
3827 Fset_window_buffer (window, buffer, Qnil);
3828 return display_buffer_1 (window);
3832 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3833 0, 1, 0,
3834 doc: /* Force all windows to be updated on next redisplay.
3835 If optional arg OBJECT is a window, force redisplay of that window only.
3836 If OBJECT is a buffer or buffer name, force redisplay of all windows
3837 displaying that buffer. */)
3838 (object)
3839 Lisp_Object object;
3841 if (NILP (object))
3843 windows_or_buffers_changed++;
3844 update_mode_lines++;
3845 return Qt;
3848 if (WINDOWP (object))
3850 struct window *w = XWINDOW (object);
3851 mark_window_display_accurate (object, 0);
3852 w->update_mode_line = Qt;
3853 if (BUFFERP (w->buffer))
3854 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3855 ++update_mode_lines;
3856 return Qt;
3859 if (STRINGP (object))
3860 object = Fget_buffer (object);
3861 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3863 /* Walk all windows looking for buffer, and force update
3864 of each of those windows. */
3866 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3867 return NILP (object) ? Qnil : Qt;
3870 /* If nothing suitable was found, just return.
3871 We could signal an error, but this feature will typically be used
3872 asynchronously in timers or process sentinels, so we don't. */
3873 return Qnil;
3877 void
3878 temp_output_buffer_show (buf)
3879 register Lisp_Object buf;
3881 register struct buffer *old = current_buffer;
3882 register Lisp_Object window;
3883 register struct window *w;
3885 XBUFFER (buf)->directory = current_buffer->directory;
3887 Fset_buffer (buf);
3888 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3889 BEGV = BEG;
3890 ZV = Z;
3891 SET_PT (BEG);
3892 #if 0 /* rms: there should be no reason for this. */
3893 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3894 #endif
3895 set_buffer_internal (old);
3897 if (!NILP (Vtemp_buffer_show_function))
3898 call1 (Vtemp_buffer_show_function, buf);
3899 else
3901 window = Fdisplay_buffer (buf, Qnil, Qnil);
3903 if (!EQ (XWINDOW (window)->frame, selected_frame))
3904 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3905 Vminibuf_scroll_window = window;
3906 w = XWINDOW (window);
3907 XSETFASTINT (w->hscroll, 0);
3908 XSETFASTINT (w->min_hscroll, 0);
3909 set_marker_restricted_both (w->start, buf, BEG, BEG);
3910 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3912 /* Run temp-buffer-show-hook, with the chosen window selected
3913 and its buffer current. */
3915 if (!NILP (Vrun_hooks)
3916 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3917 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3919 int count = SPECPDL_INDEX ();
3920 Lisp_Object prev_window, prev_buffer;
3921 prev_window = selected_window;
3922 XSETBUFFER (prev_buffer, old);
3924 /* Select the window that was chosen, for running the hook.
3925 Note: Both Fselect_window and select_window_norecord may
3926 set-buffer to the buffer displayed in the window,
3927 so we need to save the current buffer. --stef */
3928 record_unwind_protect (Fset_buffer, prev_buffer);
3929 record_unwind_protect (select_window_norecord, prev_window);
3930 Fselect_window (window, Qt);
3931 Fset_buffer (w->buffer);
3932 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3933 unbind_to (count, Qnil);
3938 static void
3939 make_dummy_parent (window)
3940 Lisp_Object window;
3942 Lisp_Object new;
3943 register struct window *o, *p;
3944 int i;
3946 o = XWINDOW (window);
3947 p = allocate_window ();
3948 for (i = 0; i < VECSIZE (struct window); ++i)
3949 ((struct Lisp_Vector *) p)->contents[i]
3950 = ((struct Lisp_Vector *)o)->contents[i];
3951 XSETWINDOW (new, p);
3953 ++sequence_number;
3954 XSETFASTINT (p->sequence_number, sequence_number);
3956 /* Put new into window structure in place of window */
3957 replace_window (window, new);
3959 o->next = Qnil;
3960 o->prev = Qnil;
3961 o->vchild = Qnil;
3962 o->hchild = Qnil;
3963 o->parent = new;
3965 p->start = Qnil;
3966 p->pointm = Qnil;
3967 p->buffer = Qnil;
3970 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3971 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3972 WINDOW defaults to selected one and SIZE to half its size.
3973 If optional third arg HORFLAG is non-nil, split side by side
3974 and put SIZE columns in the first of the pair. In that case,
3975 SIZE includes that window's scroll bar, or the divider column to its right.
3976 Interactively, all arguments are nil.
3978 Returns the newly created window (which is the lower or rightmost one).
3979 The upper or leftmost window is the original one, and remains selected
3980 if it was selected before.
3982 See Info node `(elisp)Splitting Windows' for more details and examples.*/)
3983 (window, size, horflag)
3984 Lisp_Object window, size, horflag;
3986 register Lisp_Object new;
3987 register struct window *o, *p;
3988 FRAME_PTR fo;
3989 register int size_int;
3991 if (NILP (window))
3992 window = selected_window;
3993 else
3994 CHECK_LIVE_WINDOW (window);
3996 o = XWINDOW (window);
3997 fo = XFRAME (WINDOW_FRAME (o));
3999 if (NILP (size))
4001 if (!NILP (horflag))
4002 /* Calculate the size of the left-hand window, by dividing
4003 the usable space in columns by two.
4004 We round up, since the left-hand window may include
4005 a dividing line, while the right-hand may not. */
4006 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
4007 else
4008 size_int = XFASTINT (o->total_lines) >> 1;
4010 else
4012 CHECK_NUMBER (size);
4013 size_int = XINT (size);
4016 if (MINI_WINDOW_P (o))
4017 error ("Attempt to split minibuffer window");
4018 else if (window_fixed_size_p (o, !NILP (horflag), 0))
4019 error ("Attempt to split fixed-size window");
4021 check_min_window_sizes ();
4023 if (NILP (horflag))
4025 int window_safe_height = window_min_size_2 (o, 0);
4027 if (size_int < window_safe_height)
4028 error ("Window height %d too small (after splitting)", size_int);
4029 if (size_int + window_safe_height > XFASTINT (o->total_lines))
4030 error ("Window height %d too small (after splitting)",
4031 XFASTINT (o->total_lines) - size_int);
4032 if (NILP (o->parent)
4033 || NILP (XWINDOW (o->parent)->vchild))
4035 make_dummy_parent (window);
4036 new = o->parent;
4037 XWINDOW (new)->vchild = window;
4040 else
4042 int window_safe_width = window_min_size_2 (o, 1);
4044 if (size_int < window_safe_width)
4045 error ("Window width %d too small (after splitting)", size_int);
4046 if (size_int + window_safe_width > XFASTINT (o->total_cols))
4047 error ("Window width %d too small (after splitting)",
4048 XFASTINT (o->total_cols) - size_int);
4049 if (NILP (o->parent)
4050 || NILP (XWINDOW (o->parent)->hchild))
4052 make_dummy_parent (window);
4053 new = o->parent;
4054 XWINDOW (new)->hchild = window;
4058 /* Now we know that window's parent is a vertical combination
4059 if we are dividing vertically, or a horizontal combination
4060 if we are making side-by-side windows */
4062 windows_or_buffers_changed++;
4063 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
4064 new = make_window ();
4065 p = XWINDOW (new);
4067 p->frame = o->frame;
4068 p->next = o->next;
4069 if (!NILP (p->next))
4070 XWINDOW (p->next)->prev = new;
4071 p->prev = window;
4072 o->next = new;
4073 p->parent = o->parent;
4074 p->buffer = Qt;
4075 p->window_end_valid = Qnil;
4076 bzero (&p->last_cursor, sizeof p->last_cursor);
4078 /* Duplicate special geometry settings. */
4080 p->left_margin_cols = o->left_margin_cols;
4081 p->right_margin_cols = o->right_margin_cols;
4082 p->left_fringe_width = o->left_fringe_width;
4083 p->right_fringe_width = o->right_fringe_width;
4084 p->fringes_outside_margins = o->fringes_outside_margins;
4085 p->scroll_bar_width = o->scroll_bar_width;
4086 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
4088 /* Apportion the available frame space among the two new windows */
4090 if (!NILP (horflag))
4092 p->total_lines = o->total_lines;
4093 p->top_line = o->top_line;
4094 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
4095 XSETFASTINT (o->total_cols, size_int);
4096 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
4097 adjust_window_margins (p);
4098 adjust_window_margins (o);
4100 else
4102 p->left_col = o->left_col;
4103 p->total_cols = o->total_cols;
4104 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
4105 XSETFASTINT (o->total_lines, size_int);
4106 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
4109 /* Adjust glyph matrices. */
4110 adjust_glyphs (fo);
4112 Fset_window_buffer (new, o->buffer, Qt);
4113 return new;
4116 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
4117 doc: /* Make current window ARG lines bigger.
4118 From program, optional second arg non-nil means grow sideways ARG columns.
4119 Interactively, if an argument is not given, make the window one line bigger.
4120 If HORIZONTAL is non-nil, enlarge horizontally instead of vertically.
4121 This function can delete windows, even the second window, if they get
4122 too small. */)
4123 (arg, horizontal)
4124 Lisp_Object arg, horizontal;
4126 CHECK_NUMBER (arg);
4127 enlarge_window (selected_window, XINT (arg), !NILP (horizontal));
4129 if (! NILP (Vwindow_configuration_change_hook))
4130 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4132 return Qnil;
4135 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
4136 doc: /* Make current window ARG lines smaller.
4137 From program, optional second arg non-nil means shrink sideways arg columns.
4138 Interactively, if an argument is not given, make the window one line smaller.
4139 Only siblings to the right or below are changed. */)
4140 (arg, side)
4141 Lisp_Object arg, side;
4143 CHECK_NUMBER (arg);
4144 enlarge_window (selected_window, -XINT (arg), !NILP (side));
4146 if (! NILP (Vwindow_configuration_change_hook))
4147 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4149 return Qnil;
4153 window_height (window)
4154 Lisp_Object window;
4156 register struct window *p = XWINDOW (window);
4157 return WINDOW_TOTAL_LINES (p);
4161 window_width (window)
4162 Lisp_Object window;
4164 register struct window *p = XWINDOW (window);
4165 return WINDOW_TOTAL_COLS (p);
4169 #define CURBEG(w) \
4170 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
4172 #define CURSIZE(w) \
4173 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
4176 /* Enlarge WINDOW by DELTA.
4177 HORIZ_FLAG nonzero means enlarge it horizontally;
4178 zero means do it vertically.
4180 Siblings of the selected window are resized to fulfill the size
4181 request. If they become too small in the process, they will be
4182 deleted. */
4184 static void
4185 enlarge_window (window, delta, horiz_flag)
4186 Lisp_Object window;
4187 int delta, horiz_flag;
4189 Lisp_Object parent, next, prev;
4190 struct window *p;
4191 Lisp_Object *sizep;
4192 int maximum;
4193 int (*sizefun) P_ ((Lisp_Object))
4194 = horiz_flag ? window_width : window_height;
4195 void (*setsizefun) P_ ((Lisp_Object, int, int))
4196 = (horiz_flag ? set_window_width : set_window_height);
4198 /* Check values of window_min_width and window_min_height for
4199 validity. */
4200 check_min_window_sizes ();
4202 /* Give up if this window cannot be resized. */
4203 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4204 error ("Window is not resizable");
4206 /* Find the parent of the selected window. */
4207 while (1)
4209 p = XWINDOW (window);
4210 parent = p->parent;
4212 if (NILP (parent))
4214 if (horiz_flag)
4215 error ("No other window to side of this one");
4216 break;
4219 if (horiz_flag
4220 ? !NILP (XWINDOW (parent)->hchild)
4221 : !NILP (XWINDOW (parent)->vchild))
4222 break;
4224 window = parent;
4227 sizep = &CURSIZE (window);
4230 register int maxdelta;
4232 /* Compute the maximum size increment this window can have. */
4234 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
4235 /* This is a main window followed by a minibuffer. */
4236 : !NILP (p->next) ? ((*sizefun) (p->next)
4237 - window_min_size (XWINDOW (p->next),
4238 horiz_flag, 0, 0))
4239 /* This is a minibuffer following a main window. */
4240 : !NILP (p->prev) ? ((*sizefun) (p->prev)
4241 - window_min_size (XWINDOW (p->prev),
4242 horiz_flag, 0, 0))
4243 /* This is a frame with only one window, a minibuffer-only
4244 or a minibufferless frame. */
4245 : (delta = 0));
4247 if (delta > maxdelta)
4248 /* This case traps trying to make the minibuffer
4249 the full frame, or make the only window aside from the
4250 minibuffer the full frame. */
4251 delta = maxdelta;
4254 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), horiz_flag, 0, 0))
4256 delete_window (window);
4257 return;
4260 if (delta == 0)
4261 return;
4263 /* Find the total we can get from other siblings without deleting them. */
4264 maximum = 0;
4265 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
4266 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
4267 horiz_flag, 0, 0);
4268 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
4269 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
4270 horiz_flag, 0, 0);
4272 /* If we can get it all from them without deleting them, do so. */
4273 if (delta <= maximum)
4275 Lisp_Object first_unaffected;
4276 Lisp_Object first_affected;
4277 int fixed_p;
4279 next = p->next;
4280 prev = p->prev;
4281 first_affected = window;
4282 /* Look at one sibling at a time,
4283 moving away from this window in both directions alternately,
4284 and take as much as we can get without deleting that sibling. */
4285 while (delta != 0
4286 && (!NILP (next) || !NILP (prev)))
4288 if (! NILP (next))
4290 int this_one = ((*sizefun) (next)
4291 - window_min_size (XWINDOW (next),
4292 horiz_flag, 0, &fixed_p));
4293 if (!fixed_p)
4295 if (this_one > delta)
4296 this_one = delta;
4298 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
4299 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4301 delta -= this_one;
4304 next = XWINDOW (next)->next;
4307 if (delta == 0)
4308 break;
4310 if (! NILP (prev))
4312 int this_one = ((*sizefun) (prev)
4313 - window_min_size (XWINDOW (prev),
4314 horiz_flag, 0, &fixed_p));
4315 if (!fixed_p)
4317 if (this_one > delta)
4318 this_one = delta;
4320 first_affected = prev;
4322 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
4323 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4325 delta -= this_one;
4328 prev = XWINDOW (prev)->prev;
4332 xassert (delta == 0);
4334 /* Now recalculate the edge positions of all the windows affected,
4335 based on the new sizes. */
4336 first_unaffected = next;
4337 prev = first_affected;
4338 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4339 prev = next, next = XWINDOW (next)->next)
4341 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4342 /* This does not change size of NEXT,
4343 but it propagates the new top edge to its children */
4344 (*setsizefun) (next, (*sizefun) (next), 0);
4347 else
4349 register int delta1;
4350 register int opht = (*sizefun) (parent);
4352 if (opht <= XINT (*sizep) + delta)
4354 /* If trying to grow this window to or beyond size of the parent,
4355 just delete all the sibling windows. */
4356 Lisp_Object start, tem, next;
4358 start = XWINDOW (parent)->vchild;
4359 if (NILP (start))
4360 start = XWINDOW (parent)->hchild;
4362 /* Delete any siblings that come after WINDOW. */
4363 tem = XWINDOW (window)->next;
4364 while (! NILP (tem))
4366 next = XWINDOW (tem)->next;
4367 delete_window (tem);
4368 tem = next;
4371 /* Delete any siblings that come after WINDOW.
4372 Note that if START is not WINDOW, then WINDOW still
4373 Fhas siblings, so WINDOW has not yet replaced its parent. */
4374 tem = start;
4375 while (! EQ (tem, window))
4377 next = XWINDOW (tem)->next;
4378 delete_window (tem);
4379 tem = next;
4382 else
4384 /* Otherwise, make delta1 just right so that if we add
4385 delta1 lines to this window and to the parent, and then
4386 shrink the parent back to its original size, the new
4387 proportional size of this window will increase by delta.
4389 The function size_window will compute the new height h'
4390 of the window from delta1 as:
4392 e = delta1/n
4393 x = delta1 - delta1/n * n for the 1st resizable child
4394 h' = h + e + x
4396 where n is the number of children that can be resized.
4397 We can ignore x by choosing a delta1 that is a multiple of
4398 n. We want the height of this window to come out as
4400 h' = h + delta
4402 So, delta1 must be
4404 h + e = h + delta
4405 delta1/n = delta
4406 delta1 = n * delta.
4408 The number of children n equals the number of resizable
4409 children of this window + 1 because we know window itself
4410 is resizable (otherwise we would have signalled an error). */
4412 struct window *w = XWINDOW (window);
4413 Lisp_Object s;
4414 int n = 1;
4416 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
4417 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4418 ++n;
4419 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
4420 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4421 ++n;
4423 delta1 = n * delta;
4425 /* Add delta1 lines or columns to this window, and to the parent,
4426 keeping things consistent while not affecting siblings. */
4427 XSETINT (CURSIZE (parent), opht + delta1);
4428 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4430 /* Squeeze out delta1 lines or columns from our parent,
4431 shriking this window and siblings proportionately.
4432 This brings parent back to correct size.
4433 Delta1 was calculated so this makes this window the desired size,
4434 taking it all out of the siblings. */
4435 (*setsizefun) (parent, opht, 0);
4440 XSETFASTINT (p->last_modified, 0);
4441 XSETFASTINT (p->last_overlay_modified, 0);
4443 /* Adjust glyph matrices. */
4444 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4448 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4449 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4450 zero means adjust the height, moving the bottom edge.
4452 Following siblings of the selected window are resized to fulfill
4453 the size request. If they become too small in the process, they
4454 are not deleted; instead, we signal an error. */
4456 static void
4457 adjust_window_trailing_edge (window, delta, horiz_flag)
4458 Lisp_Object window;
4459 int delta, horiz_flag;
4461 Lisp_Object parent, child;
4462 struct window *p;
4463 Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
4464 int delcount = window_deletion_count;
4466 /* Check values of window_min_width and window_min_height for
4467 validity. */
4468 check_min_window_sizes ();
4470 if (NILP (window))
4471 window = Fselected_window ();
4473 CHECK_WINDOW (window);
4475 /* Give up if this window cannot be resized. */
4476 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4477 error ("Window is not resizable");
4479 while (1)
4481 Lisp_Object first_parallel = Qnil;
4483 if (NILP (window))
4485 /* This happens if WINDOW on the previous iteration was
4486 at top level of the window tree. */
4487 Fset_window_configuration (old_config);
4488 error ("Specified window edge is fixed");
4491 p = XWINDOW (window);
4492 parent = p->parent;
4494 /* See if this level has windows in parallel in the specified
4495 direction. If so, set FIRST_PARALLEL to the first one. */
4496 if (horiz_flag)
4498 if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
4499 first_parallel = XWINDOW (parent)->vchild;
4500 else if (NILP (parent) && !NILP (p->next))
4502 /* Handle the vertical chain of main window and minibuffer
4503 which has no parent. */
4504 first_parallel = window;
4505 while (! NILP (XWINDOW (first_parallel)->prev))
4506 first_parallel = XWINDOW (first_parallel)->prev;
4509 else
4511 if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
4512 first_parallel = XWINDOW (parent)->hchild;
4515 /* If this level's succession is in the desired dimension,
4516 and this window is the last one, and there is no higher level,
4517 its trailing edge is fixed. */
4518 if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
4519 && NILP (parent))
4521 Fset_window_configuration (old_config);
4522 error ("Specified window edge is fixed");
4525 /* Don't make this window too small. */
4526 if (XINT (CURSIZE (window)) + delta
4527 < window_min_size_2 (XWINDOW (window), horiz_flag))
4529 Fset_window_configuration (old_config);
4530 error ("Cannot adjust window size as specified");
4533 /* Clear out some redisplay caches. */
4534 XSETFASTINT (p->last_modified, 0);
4535 XSETFASTINT (p->last_overlay_modified, 0);
4537 /* Adjust this window's edge. */
4538 XSETINT (CURSIZE (window),
4539 XINT (CURSIZE (window)) + delta);
4541 /* If this window has following siblings in the desired dimension,
4542 make them smaller, and exit the loop.
4544 (If we reach the top of the tree and can never do this,
4545 we will fail and report an error, above.) */
4546 if (NILP (first_parallel))
4548 if (!NILP (p->next))
4550 /* This may happen for the minibuffer. In that case
4551 the window_deletion_count check below does not work. */
4552 if (XINT (CURSIZE (p->next)) - delta <= 0)
4554 Fset_window_configuration (old_config);
4555 error ("Cannot adjust window size as specified");
4558 XSETINT (CURBEG (p->next),
4559 XINT (CURBEG (p->next)) + delta);
4560 size_window (p->next, XINT (CURSIZE (p->next)) - delta,
4561 horiz_flag, 0, 1, 0);
4562 break;
4565 else
4566 /* Here we have a chain of parallel siblings, in the other dimension.
4567 Change the size of the other siblings. */
4568 for (child = first_parallel;
4569 ! NILP (child);
4570 child = XWINDOW (child)->next)
4571 if (! EQ (child, window))
4572 size_window (child, XINT (CURSIZE (child)) + delta,
4573 horiz_flag, 0, 0, 1);
4575 window = parent;
4578 /* If we made a window so small it got deleted,
4579 we failed. Report failure. */
4580 if (delcount != window_deletion_count)
4582 Fset_window_configuration (old_config);
4583 error ("Cannot adjust window size as specified");
4586 /* Adjust glyph matrices. */
4587 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4590 #undef CURBEG
4591 #undef CURSIZE
4593 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
4594 Sadjust_window_trailing_edge, 3, 3, 0,
4595 doc: /* Adjust the bottom or right edge of WINDOW by DELTA.
4596 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4597 Otherwise, adjust the height, moving the bottom edge.
4599 Following siblings of the selected window are resized to fulfill
4600 the size request. If they become too small in the process, they
4601 are not deleted; instead, we signal an error. */)
4602 (window, delta, horizontal)
4603 Lisp_Object window, delta, horizontal;
4605 CHECK_NUMBER (delta);
4606 adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
4608 if (! NILP (Vwindow_configuration_change_hook))
4609 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4611 return Qnil;
4616 /***********************************************************************
4617 Resizing Mini-Windows
4618 ***********************************************************************/
4620 static void shrink_window_lowest_first P_ ((struct window *, int));
4622 enum save_restore_action
4624 CHECK_ORIG_SIZES,
4625 SAVE_ORIG_SIZES,
4626 RESTORE_ORIG_SIZES
4629 static int save_restore_orig_size P_ ((struct window *,
4630 enum save_restore_action));
4632 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4633 from lowest windows first. */
4635 static void
4636 shrink_window_lowest_first (w, height)
4637 struct window *w;
4638 int height;
4640 struct window *c;
4641 Lisp_Object child;
4642 int old_height;
4644 xassert (!MINI_WINDOW_P (w));
4646 /* Set redisplay hints. */
4647 XSETFASTINT (w->last_modified, 0);
4648 XSETFASTINT (w->last_overlay_modified, 0);
4649 windows_or_buffers_changed++;
4650 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4652 old_height = XFASTINT (w->total_lines);
4653 XSETFASTINT (w->total_lines, height);
4655 if (!NILP (w->hchild))
4657 for (child = w->hchild; !NILP (child); child = c->next)
4659 c = XWINDOW (child);
4660 c->top_line = w->top_line;
4661 shrink_window_lowest_first (c, height);
4664 else if (!NILP (w->vchild))
4666 Lisp_Object last_child;
4667 int delta = old_height - height;
4668 int last_top;
4670 last_child = Qnil;
4672 /* Find the last child. We are taking space from lowest windows
4673 first, so we iterate over children from the last child
4674 backwards. */
4675 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
4676 last_child = child;
4678 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
4679 for (child = last_child; delta && !NILP (child); child = c->prev)
4681 int this_one;
4683 c = XWINDOW (child);
4684 this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
4686 if (this_one > delta)
4687 this_one = delta;
4689 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4690 delta -= this_one;
4693 /* Compute new positions. */
4694 last_top = XINT (w->top_line);
4695 for (child = w->vchild; !NILP (child); child = c->next)
4697 c = XWINDOW (child);
4698 c->top_line = make_number (last_top);
4699 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4700 last_top += XFASTINT (c->total_lines);
4706 /* Save, restore, or check positions and sizes in the window tree
4707 rooted at W. ACTION says what to do.
4709 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4710 orig_total_lines members are valid for all windows in the window
4711 tree. Value is non-zero if they are valid.
4713 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4714 orig_top_line and orig_total_lines for all windows in the tree.
4716 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4717 stored in orig_top_line and orig_total_lines for all windows. */
4719 static int
4720 save_restore_orig_size (w, action)
4721 struct window *w;
4722 enum save_restore_action action;
4724 int success_p = 1;
4726 while (w)
4728 if (!NILP (w->hchild))
4730 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4731 success_p = 0;
4733 else if (!NILP (w->vchild))
4735 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4736 success_p = 0;
4739 switch (action)
4741 case CHECK_ORIG_SIZES:
4742 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4743 return 0;
4744 break;
4746 case SAVE_ORIG_SIZES:
4747 w->orig_top_line = w->top_line;
4748 w->orig_total_lines = w->total_lines;
4749 XSETFASTINT (w->last_modified, 0);
4750 XSETFASTINT (w->last_overlay_modified, 0);
4751 break;
4753 case RESTORE_ORIG_SIZES:
4754 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4755 w->top_line = w->orig_top_line;
4756 w->total_lines = w->orig_total_lines;
4757 w->orig_total_lines = w->orig_top_line = Qnil;
4758 XSETFASTINT (w->last_modified, 0);
4759 XSETFASTINT (w->last_overlay_modified, 0);
4760 break;
4762 default:
4763 abort ();
4766 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4769 return success_p;
4773 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4774 without deleting other windows. */
4776 void
4777 grow_mini_window (w, delta)
4778 struct window *w;
4779 int delta;
4781 struct frame *f = XFRAME (w->frame);
4782 struct window *root;
4784 xassert (MINI_WINDOW_P (w));
4785 xassert (delta >= 0);
4787 /* Check values of window_min_width and window_min_height for
4788 validity. */
4789 check_min_window_sizes ();
4791 /* Compute how much we can enlarge the mini-window without deleting
4792 other windows. */
4793 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4794 if (delta)
4796 int min_height = window_min_size (root, 0, 0, 0);
4797 if (XFASTINT (root->total_lines) - delta < min_height)
4798 /* Note that the root window may already be smaller than
4799 min_height. */
4800 delta = max (0, XFASTINT (root->total_lines) - min_height);
4803 if (delta)
4805 /* Save original window sizes and positions, if not already done. */
4806 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4807 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4809 /* Shrink other windows. */
4810 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4812 /* Grow the mini-window. */
4813 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4814 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4815 XSETFASTINT (w->last_modified, 0);
4816 XSETFASTINT (w->last_overlay_modified, 0);
4818 adjust_glyphs (f);
4823 /* Shrink mini-window W. If there is recorded info about window sizes
4824 before a call to grow_mini_window, restore recorded window sizes.
4825 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4826 line. */
4828 void
4829 shrink_mini_window (w)
4830 struct window *w;
4832 struct frame *f = XFRAME (w->frame);
4833 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4835 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4837 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4838 adjust_glyphs (f);
4839 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4840 windows_or_buffers_changed = 1;
4842 else if (XFASTINT (w->total_lines) > 1)
4844 /* Distribute the additional lines of the mini-window
4845 among the other windows. */
4846 Lisp_Object window;
4847 XSETWINDOW (window, w);
4848 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
4854 /* Mark window cursors off for all windows in the window tree rooted
4855 at W by setting their phys_cursor_on_p flag to zero. Called from
4856 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4857 the frame are cleared. */
4859 void
4860 mark_window_cursors_off (w)
4861 struct window *w;
4863 while (w)
4865 if (!NILP (w->hchild))
4866 mark_window_cursors_off (XWINDOW (w->hchild));
4867 else if (!NILP (w->vchild))
4868 mark_window_cursors_off (XWINDOW (w->vchild));
4869 else
4870 w->phys_cursor_on_p = 0;
4872 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4877 /* Return number of lines of text (not counting mode lines) in W. */
4880 window_internal_height (w)
4881 struct window *w;
4883 int ht = XFASTINT (w->total_lines);
4885 if (!MINI_WINDOW_P (w))
4887 if (!NILP (w->parent)
4888 || !NILP (w->vchild)
4889 || !NILP (w->hchild)
4890 || !NILP (w->next)
4891 || !NILP (w->prev)
4892 || WINDOW_WANTS_MODELINE_P (w))
4893 --ht;
4895 if (WINDOW_WANTS_HEADER_LINE_P (w))
4896 --ht;
4899 return ht;
4903 /* Return the number of columns in W.
4904 Don't count columns occupied by scroll bars or the vertical bar
4905 separating W from the sibling to its right. */
4908 window_box_text_cols (w)
4909 struct window *w;
4911 struct frame *f = XFRAME (WINDOW_FRAME (w));
4912 int width = XINT (w->total_cols);
4914 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4915 /* Scroll bars occupy a few columns. */
4916 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4917 else if (!FRAME_WINDOW_P (f)
4918 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4919 /* The column of `|' characters separating side-by-side windows
4920 occupies one column only. */
4921 width -= 1;
4923 if (FRAME_WINDOW_P (f))
4924 /* On window-systems, fringes and display margins cannot be
4925 used for normal text. */
4926 width -= (WINDOW_FRINGE_COLS (w)
4927 + WINDOW_LEFT_MARGIN_COLS (w)
4928 + WINDOW_RIGHT_MARGIN_COLS (w));
4930 return width;
4934 /************************************************************************
4935 Window Scrolling
4936 ***********************************************************************/
4938 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4939 N screen-fulls, which is defined as the height of the window minus
4940 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4941 instead. Negative values of N mean scroll down. NOERROR non-zero
4942 means don't signal an error if we try to move over BEGV or ZV,
4943 respectively. */
4945 static void
4946 window_scroll (window, n, whole, noerror)
4947 Lisp_Object window;
4948 int n;
4949 int whole;
4950 int noerror;
4952 immediate_quit = 1;
4954 /* If we must, use the pixel-based version which is much slower than
4955 the line-based one but can handle varying line heights. */
4956 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4957 window_scroll_pixel_based (window, n, whole, noerror);
4958 else
4959 window_scroll_line_based (window, n, whole, noerror);
4961 immediate_quit = 0;
4965 /* Implementation of window_scroll that works based on pixel line
4966 heights. See the comment of window_scroll for parameter
4967 descriptions. */
4969 static void
4970 window_scroll_pixel_based (window, n, whole, noerror)
4971 Lisp_Object window;
4972 int n;
4973 int whole;
4974 int noerror;
4976 struct it it;
4977 struct window *w = XWINDOW (window);
4978 struct text_pos start;
4979 int this_scroll_margin;
4980 /* True if we fiddled the window vscroll field without really scrolling. */
4981 int vscrolled = 0;
4982 int x, y, rtop, rbot, rowh, vpos;
4984 SET_TEXT_POS_FROM_MARKER (start, w->start);
4986 /* If PT is not visible in WINDOW, move back one half of
4987 the screen. Allow PT to be partially visible, otherwise
4988 something like (scroll-down 1) with PT in the line before
4989 the partially visible one would recenter. */
4991 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4993 /* Move backward half the height of the window. Performance note:
4994 vmotion used here is about 10% faster, but would give wrong
4995 results for variable height lines. */
4996 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4997 it.current_y = it.last_visible_y;
4998 move_it_vertically_backward (&it, window_box_height (w) / 2);
5000 /* The function move_iterator_vertically may move over more than
5001 the specified y-distance. If it->w is small, e.g. a
5002 mini-buffer window, we may end up in front of the window's
5003 display area. This is the case when Start displaying at the
5004 start of the line containing PT in this case. */
5005 if (it.current_y <= 0)
5007 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
5008 move_it_vertically_backward (&it, 0);
5009 it.current_y = 0;
5012 start = it.current.pos;
5014 else if (auto_window_vscroll_p)
5016 if (rtop || rbot) /* partially visible */
5018 int px;
5019 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
5020 if (whole)
5021 dy = max ((window_box_height (w)
5022 - next_screen_context_lines * dy),
5023 dy);
5024 dy *= n;
5026 if (n < 0)
5028 /* Only vscroll backwards if already vscrolled forwards. */
5029 if (w->vscroll < 0 && rtop > 0)
5031 px = max (0, -w->vscroll - min (rtop, -dy));
5032 Fset_window_vscroll (window, make_number (px), Qt);
5033 return;
5036 if (n > 0)
5038 /* Do vscroll if already vscrolled or only display line. */
5039 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
5041 px = max (0, -w->vscroll + min (rbot, dy));
5042 Fset_window_vscroll (window, make_number (px), Qt);
5043 return;
5046 /* Maybe modify window start instead of scrolling. */
5047 if (rbot > 0 || w->vscroll < 0)
5049 int spos;
5051 Fset_window_vscroll (window, make_number (0), Qt);
5052 /* If there are other text lines above the current row,
5053 move window start to current row. Else to next row. */
5054 if (rbot > 0)
5055 spos = XINT (Fline_beginning_position (Qnil));
5056 else
5057 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
5058 set_marker_restricted (w->start, make_number (spos),
5059 w->buffer);
5060 w->start_at_line_beg = Qt;
5061 w->update_mode_line = Qt;
5062 XSETFASTINT (w->last_modified, 0);
5063 XSETFASTINT (w->last_overlay_modified, 0);
5064 /* Set force_start so that redisplay_window will run the
5065 window-scroll-functions. */
5066 w->force_start = Qt;
5067 return;
5071 /* Cancel previous vscroll. */
5072 Fset_window_vscroll (window, make_number (0), Qt);
5075 /* If scroll_preserve_screen_position is non-nil, we try to set
5076 point in the same window line as it is now, so get that line. */
5077 if (!NILP (Vscroll_preserve_screen_position))
5079 /* We preserve the goal pixel coordinate across consecutive
5080 calls to scroll-up or scroll-down. This avoids the
5081 possibility of point becoming "stuck" on a tall line when
5082 scrolling by one line. */
5083 if (window_scroll_pixel_based_preserve_y < 0
5084 || (!EQ (current_kboard->Vlast_command, Qscroll_up)
5085 && !EQ (current_kboard->Vlast_command, Qscroll_down)))
5087 start_display (&it, w, start);
5088 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5089 window_scroll_pixel_based_preserve_y = it.current_y;
5092 else
5093 window_scroll_pixel_based_preserve_y = -1;
5095 /* Move iterator it from start the specified distance forward or
5096 backward. The result is the new window start. */
5097 start_display (&it, w, start);
5098 if (whole)
5100 int start_pos = IT_CHARPOS (it);
5101 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
5102 dy = max ((window_box_height (w)
5103 - next_screen_context_lines * dy),
5104 dy) * n;
5106 /* Note that move_it_vertically always moves the iterator to the
5107 start of a line. So, if the last line doesn't have a newline,
5108 we would end up at the start of the line ending at ZV. */
5109 if (dy <= 0)
5111 move_it_vertically_backward (&it, -dy);
5112 /* Ensure we actually do move, e.g. in case we are currently
5113 looking at an image that is taller that the window height. */
5114 while (start_pos == IT_CHARPOS (it)
5115 && start_pos > BEGV)
5116 move_it_by_lines (&it, -1, 1);
5118 else if (dy > 0)
5120 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
5121 MOVE_TO_POS | MOVE_TO_Y);
5122 /* Ensure we actually do move, e.g. in case we are currently
5123 looking at an image that is taller that the window height. */
5124 while (start_pos == IT_CHARPOS (it)
5125 && start_pos < ZV)
5126 move_it_by_lines (&it, 1, 1);
5129 else
5130 move_it_by_lines (&it, n, 1);
5132 /* We failed if we find ZV is already on the screen (scrolling up,
5133 means there's nothing past the end), or if we can't start any
5134 earlier (scrolling down, means there's nothing past the top). */
5135 if ((n > 0 && IT_CHARPOS (it) == ZV)
5136 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
5138 if (IT_CHARPOS (it) == ZV)
5140 if (it.current_y < it.last_visible_y
5141 && (it.current_y + it.max_ascent + it.max_descent
5142 > it.last_visible_y))
5144 /* The last line was only partially visible, make it fully
5145 visible. */
5146 w->vscroll = (it.last_visible_y
5147 - it.current_y + it.max_ascent + it.max_descent);
5148 adjust_glyphs (it.f);
5150 else if (noerror)
5151 return;
5152 else if (n < 0) /* could happen with empty buffers */
5153 xsignal0 (Qbeginning_of_buffer);
5154 else
5155 xsignal0 (Qend_of_buffer);
5157 else
5159 if (w->vscroll != 0)
5160 /* The first line was only partially visible, make it fully
5161 visible. */
5162 w->vscroll = 0;
5163 else if (noerror)
5164 return;
5165 else
5166 xsignal0 (Qbeginning_of_buffer);
5169 /* If control gets here, then we vscrolled. */
5171 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5173 /* Don't try to change the window start below. */
5174 vscrolled = 1;
5177 if (! vscrolled)
5179 int pos = IT_CHARPOS (it);
5180 int bytepos;
5182 /* If in the middle of a multi-glyph character move forward to
5183 the next character. */
5184 if (in_display_vector_p (&it))
5186 ++pos;
5187 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
5190 /* Set the window start, and set up the window for redisplay. */
5191 set_marker_restricted (w->start, make_number (pos),
5192 w->buffer);
5193 bytepos = XMARKER (w->start)->bytepos;
5194 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
5195 ? Qt : Qnil);
5196 w->update_mode_line = Qt;
5197 XSETFASTINT (w->last_modified, 0);
5198 XSETFASTINT (w->last_overlay_modified, 0);
5199 /* Set force_start so that redisplay_window will run the
5200 window-scroll-functions. */
5201 w->force_start = Qt;
5204 /* The rest of this function uses current_y in a nonstandard way,
5205 not including the height of the header line if any. */
5206 it.current_y = it.vpos = 0;
5208 /* Move PT out of scroll margins.
5209 This code wants current_y to be zero at the window start position
5210 even if there is a header line. */
5211 this_scroll_margin = max (0, scroll_margin);
5212 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
5213 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5215 if (n > 0)
5217 /* We moved the window start towards ZV, so PT may be now
5218 in the scroll margin at the top. */
5219 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5220 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5221 && (NILP (Vscroll_preserve_screen_position)
5222 || EQ (Vscroll_preserve_screen_position, Qt)))
5223 /* We found PT at a legitimate height. Leave it alone. */
5225 else if (window_scroll_pixel_based_preserve_y >= 0)
5227 /* If we have a header line, take account of it.
5228 This is necessary because we set it.current_y to 0, above. */
5229 move_it_to (&it, -1, -1,
5230 window_scroll_pixel_based_preserve_y
5231 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
5232 -1, MOVE_TO_Y);
5233 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5235 else
5237 while (it.current_y < this_scroll_margin)
5239 int prev = it.current_y;
5240 move_it_by_lines (&it, 1, 1);
5241 if (prev == it.current_y)
5242 break;
5244 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5247 else if (n < 0)
5249 int charpos, bytepos;
5250 int partial_p;
5252 /* Save our position, for the
5253 window_scroll_pixel_based_preserve_y case. */
5254 charpos = IT_CHARPOS (it);
5255 bytepos = IT_BYTEPOS (it);
5257 /* We moved the window start towards BEGV, so PT may be now
5258 in the scroll margin at the bottom. */
5259 move_it_to (&it, PT, -1,
5260 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5261 - this_scroll_margin - 1),
5263 MOVE_TO_POS | MOVE_TO_Y);
5265 /* Save our position, in case it's correct. */
5266 charpos = IT_CHARPOS (it);
5267 bytepos = IT_BYTEPOS (it);
5269 /* See if point is on a partially visible line at the end. */
5270 if (it.what == IT_EOB)
5271 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5272 else
5274 move_it_by_lines (&it, 1, 1);
5275 partial_p = it.current_y > it.last_visible_y;
5278 if (charpos == PT && !partial_p
5279 && (NILP (Vscroll_preserve_screen_position)
5280 || EQ (Vscroll_preserve_screen_position, Qt)))
5281 /* We found PT before we found the display margin, so PT is ok. */
5283 else if (window_scroll_pixel_based_preserve_y >= 0)
5285 SET_TEXT_POS_FROM_MARKER (start, w->start);
5286 start_display (&it, w, start);
5287 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5288 here because we called start_display again and did not
5289 alter it.current_y this time. */
5290 move_it_to (&it, -1, -1, window_scroll_pixel_based_preserve_y, -1,
5291 MOVE_TO_Y);
5292 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5294 else
5296 if (partial_p)
5297 /* The last line was only partially visible, so back up two
5298 lines to make sure we're on a fully visible line. */
5300 move_it_by_lines (&it, -2, 0);
5301 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5303 else
5304 /* No, the position we saved is OK, so use it. */
5305 SET_PT_BOTH (charpos, bytepos);
5311 /* Implementation of window_scroll that works based on screen lines.
5312 See the comment of window_scroll for parameter descriptions. */
5314 static void
5315 window_scroll_line_based (window, n, whole, noerror)
5316 Lisp_Object window;
5317 int n;
5318 int whole;
5319 int noerror;
5321 register struct window *w = XWINDOW (window);
5322 register int opoint = PT, opoint_byte = PT_BYTE;
5323 register int pos, pos_byte;
5324 register int ht = window_internal_height (w);
5325 register Lisp_Object tem;
5326 int lose;
5327 Lisp_Object bolp;
5328 int startpos;
5329 struct position posit;
5330 int original_vpos;
5332 /* If scrolling screen-fulls, compute the number of lines to
5333 scroll from the window's height. */
5334 if (whole)
5335 n *= max (1, ht - next_screen_context_lines);
5337 startpos = marker_position (w->start);
5339 posit = *compute_motion (startpos, 0, 0, 0,
5340 PT, ht, 0,
5341 -1, XINT (w->hscroll),
5342 0, w);
5343 original_vpos = posit.vpos;
5345 XSETFASTINT (tem, PT);
5346 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5348 if (NILP (tem))
5350 Fvertical_motion (make_number (- (ht / 2)), window);
5351 startpos = PT;
5354 SET_PT (startpos);
5355 lose = n < 0 && PT == BEGV;
5356 Fvertical_motion (make_number (n), window);
5357 pos = PT;
5358 pos_byte = PT_BYTE;
5359 bolp = Fbolp ();
5360 SET_PT_BOTH (opoint, opoint_byte);
5362 if (lose)
5364 if (noerror)
5365 return;
5366 else
5367 xsignal0 (Qbeginning_of_buffer);
5370 if (pos < ZV)
5372 int this_scroll_margin = scroll_margin;
5374 /* Don't use a scroll margin that is negative or too large. */
5375 if (this_scroll_margin < 0)
5376 this_scroll_margin = 0;
5378 if (XINT (w->total_lines) < 4 * scroll_margin)
5379 this_scroll_margin = XINT (w->total_lines) / 4;
5381 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
5382 w->start_at_line_beg = bolp;
5383 w->update_mode_line = Qt;
5384 XSETFASTINT (w->last_modified, 0);
5385 XSETFASTINT (w->last_overlay_modified, 0);
5386 /* Set force_start so that redisplay_window will run
5387 the window-scroll-functions. */
5388 w->force_start = Qt;
5390 if (!NILP (Vscroll_preserve_screen_position)
5391 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5393 SET_PT_BOTH (pos, pos_byte);
5394 Fvertical_motion (make_number (original_vpos), window);
5396 /* If we scrolled forward, put point enough lines down
5397 that it is outside the scroll margin. */
5398 else if (n > 0)
5400 int top_margin;
5402 if (this_scroll_margin > 0)
5404 SET_PT_BOTH (pos, pos_byte);
5405 Fvertical_motion (make_number (this_scroll_margin), window);
5406 top_margin = PT;
5408 else
5409 top_margin = pos;
5411 if (top_margin <= opoint)
5412 SET_PT_BOTH (opoint, opoint_byte);
5413 else if (!NILP (Vscroll_preserve_screen_position))
5415 SET_PT_BOTH (pos, pos_byte);
5416 Fvertical_motion (make_number (original_vpos), window);
5418 else
5419 SET_PT (top_margin);
5421 else if (n < 0)
5423 int bottom_margin;
5425 /* If we scrolled backward, put point near the end of the window
5426 but not within the scroll margin. */
5427 SET_PT_BOTH (pos, pos_byte);
5428 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
5429 if (XFASTINT (tem) == ht - this_scroll_margin)
5430 bottom_margin = PT;
5431 else
5432 bottom_margin = PT + 1;
5434 if (bottom_margin > opoint)
5435 SET_PT_BOTH (opoint, opoint_byte);
5436 else
5438 if (!NILP (Vscroll_preserve_screen_position))
5440 SET_PT_BOTH (pos, pos_byte);
5441 Fvertical_motion (make_number (original_vpos), window);
5443 else
5444 Fvertical_motion (make_number (-1), window);
5448 else
5450 if (noerror)
5451 return;
5452 else
5453 xsignal0 (Qend_of_buffer);
5458 /* Scroll selected_window up or down. If N is nil, scroll a
5459 screen-full which is defined as the height of the window minus
5460 next_screen_context_lines. If N is the symbol `-', scroll.
5461 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5462 up. This is the guts of Fscroll_up and Fscroll_down. */
5464 static void
5465 scroll_command (n, direction)
5466 Lisp_Object n;
5467 int direction;
5469 int count = SPECPDL_INDEX ();
5471 xassert (abs (direction) == 1);
5473 /* If selected window's buffer isn't current, make it current for
5474 the moment. But don't screw up if window_scroll gets an error. */
5475 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
5477 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5478 Fset_buffer (XWINDOW (selected_window)->buffer);
5480 /* Make redisplay consider other windows than just selected_window. */
5481 ++windows_or_buffers_changed;
5484 if (NILP (n))
5485 window_scroll (selected_window, direction, 1, 0);
5486 else if (EQ (n, Qminus))
5487 window_scroll (selected_window, -direction, 1, 0);
5488 else
5490 n = Fprefix_numeric_value (n);
5491 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5494 unbind_to (count, Qnil);
5497 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
5498 doc: /* Scroll text of current window upward ARG lines.
5499 If ARG is omitted or nil, scroll upward by a near full screen.
5500 A near full screen is `next-screen-context-lines' less than a full screen.
5501 Negative ARG means scroll downward.
5502 If ARG is the atom `-', scroll downward by nearly full screen.
5503 When calling from a program, supply as argument a number, nil, or `-'. */)
5504 (arg)
5505 Lisp_Object arg;
5507 scroll_command (arg, 1);
5508 return Qnil;
5511 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
5512 doc: /* Scroll text of current window down ARG lines.
5513 If ARG is omitted or nil, scroll down by a near full screen.
5514 A near full screen is `next-screen-context-lines' less than a full screen.
5515 Negative ARG means scroll upward.
5516 If ARG is the atom `-', scroll upward by nearly full screen.
5517 When calling from a program, supply as argument a number, nil, or `-'. */)
5518 (arg)
5519 Lisp_Object arg;
5521 scroll_command (arg, -1);
5522 return Qnil;
5525 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5526 doc: /* Return the other window for \"other window scroll\" commands.
5527 If `other-window-scroll-buffer' is non-nil, a window
5528 showing that buffer is used.
5529 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5530 specifies the window. This takes precedence over
5531 `other-window-scroll-buffer'. */)
5534 Lisp_Object window;
5536 if (MINI_WINDOW_P (XWINDOW (selected_window))
5537 && !NILP (Vminibuf_scroll_window))
5538 window = Vminibuf_scroll_window;
5539 /* If buffer is specified, scroll that buffer. */
5540 else if (!NILP (Vother_window_scroll_buffer))
5542 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5543 if (NILP (window))
5544 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5546 else
5548 /* Nothing specified; look for a neighboring window on the same
5549 frame. */
5550 window = Fnext_window (selected_window, Qnil, Qnil);
5552 if (EQ (window, selected_window))
5553 /* That didn't get us anywhere; look for a window on another
5554 visible frame. */
5556 window = Fnext_window (window, Qnil, Qt);
5557 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5558 && ! EQ (window, selected_window));
5561 CHECK_LIVE_WINDOW (window);
5563 if (EQ (window, selected_window))
5564 error ("There is no other window");
5566 return window;
5569 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5570 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5571 A near full screen is `next-screen-context-lines' less than a full screen.
5572 The next window is the one below the current one; or the one at the top
5573 if the current one is at the bottom. Negative ARG means scroll downward.
5574 If ARG is the atom `-', scroll downward by nearly full screen.
5575 When calling from a program, supply as argument a number, nil, or `-'.
5577 If `other-window-scroll-buffer' is non-nil, scroll the window
5578 showing that buffer, popping the buffer up if necessary.
5579 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5580 specifies the window to scroll. This takes precedence over
5581 `other-window-scroll-buffer'. */)
5582 (arg)
5583 Lisp_Object arg;
5585 Lisp_Object window;
5586 struct window *w;
5587 int count = SPECPDL_INDEX ();
5589 window = Fother_window_for_scrolling ();
5590 w = XWINDOW (window);
5592 /* Don't screw up if window_scroll gets an error. */
5593 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5594 ++windows_or_buffers_changed;
5596 Fset_buffer (w->buffer);
5597 SET_PT (marker_position (w->pointm));
5599 if (NILP (arg))
5600 window_scroll (window, 1, 1, 1);
5601 else if (EQ (arg, Qminus))
5602 window_scroll (window, -1, 1, 1);
5603 else
5605 if (CONSP (arg))
5606 arg = Fcar (arg);
5607 CHECK_NUMBER (arg);
5608 window_scroll (window, XINT (arg), 0, 1);
5611 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5612 unbind_to (count, Qnil);
5614 return Qnil;
5617 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "P\np",
5618 doc: /* Scroll selected window display ARG columns left.
5619 Default for ARG is window width minus 2.
5620 Value is the total amount of leftward horizontal scrolling in
5621 effect after the change.
5622 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5623 lower bound for automatic scrolling, i.e. automatic scrolling
5624 will not scroll a window to a column less than the value returned
5625 by this function. This happens in an interactive call. */)
5626 (arg, set_minimum)
5627 register Lisp_Object arg, set_minimum;
5629 Lisp_Object result;
5630 int hscroll;
5631 struct window *w = XWINDOW (selected_window);
5633 if (NILP (arg))
5634 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5635 else
5636 arg = Fprefix_numeric_value (arg);
5638 hscroll = XINT (w->hscroll) + XINT (arg);
5639 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5641 if (!NILP (set_minimum))
5642 w->min_hscroll = w->hscroll;
5644 return result;
5647 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "P\np",
5648 doc: /* Scroll selected window display ARG columns right.
5649 Default for ARG is window width minus 2.
5650 Value is the total amount of leftward horizontal scrolling in
5651 effect after the change.
5652 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5653 lower bound for automatic scrolling, i.e. automatic scrolling
5654 will not scroll a window to a column less than the value returned
5655 by this function. This happens in an interactive call. */)
5656 (arg, set_minimum)
5657 register Lisp_Object arg, set_minimum;
5659 Lisp_Object result;
5660 int hscroll;
5661 struct window *w = XWINDOW (selected_window);
5663 if (NILP (arg))
5664 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5665 else
5666 arg = Fprefix_numeric_value (arg);
5668 hscroll = XINT (w->hscroll) - XINT (arg);
5669 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5671 if (!NILP (set_minimum))
5672 w->min_hscroll = w->hscroll;
5674 return result;
5677 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5678 doc: /* Return the window which was selected when entering the minibuffer.
5679 Returns nil, if current window is not a minibuffer window. */)
5682 if (minibuf_level > 0
5683 && MINI_WINDOW_P (XWINDOW (selected_window))
5684 && WINDOW_LIVE_P (minibuf_selected_window))
5685 return minibuf_selected_window;
5687 return Qnil;
5690 /* Value is the number of lines actually displayed in window W,
5691 as opposed to its height. */
5693 static int
5694 displayed_window_lines (w)
5695 struct window *w;
5697 struct it it;
5698 struct text_pos start;
5699 int height = window_box_height (w);
5700 struct buffer *old_buffer;
5701 int bottom_y;
5703 if (XBUFFER (w->buffer) != current_buffer)
5705 old_buffer = current_buffer;
5706 set_buffer_internal (XBUFFER (w->buffer));
5708 else
5709 old_buffer = NULL;
5711 /* In case W->start is out of the accessible range, do something
5712 reasonable. This happens in Info mode when Info-scroll-down
5713 calls (recenter -1) while W->start is 1. */
5714 if (XMARKER (w->start)->charpos < BEGV)
5715 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5716 else if (XMARKER (w->start)->charpos > ZV)
5717 SET_TEXT_POS (start, ZV, ZV_BYTE);
5718 else
5719 SET_TEXT_POS_FROM_MARKER (start, w->start);
5721 start_display (&it, w, start);
5722 move_it_vertically (&it, height);
5723 bottom_y = line_bottom_y (&it);
5725 /* rms: On a non-window display,
5726 the value of it.vpos at the bottom of the screen
5727 seems to be 1 larger than window_box_height (w).
5728 This kludge fixes a bug whereby (move-to-window-line -1)
5729 when ZV is on the last screen line
5730 moves to the previous screen line instead of the last one. */
5731 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5732 height++;
5734 /* Add in empty lines at the bottom of the window. */
5735 if (bottom_y < height)
5737 int uy = FRAME_LINE_HEIGHT (it.f);
5738 it.vpos += (height - bottom_y + uy - 1) / uy;
5741 if (old_buffer)
5742 set_buffer_internal (old_buffer);
5744 return it.vpos;
5748 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5749 doc: /* Center point in window and redisplay frame.
5750 With prefix argument ARG, recenter putting point on screen line ARG
5751 relative to the current window. If ARG is negative, it counts up from the
5752 bottom of the window. (ARG should be less than the height of the window.)
5754 If ARG is omitted or nil, erase the entire frame and then redraw with point
5755 in the center of the current window. If `auto-resize-tool-bars' is set to
5756 `grow-only', this resets the tool-bar's height to the minimum height needed.
5758 Just C-u as prefix means put point in the center of the window
5759 and redisplay normally--don't erase and redraw the frame. */)
5760 (arg)
5761 register Lisp_Object arg;
5763 struct window *w = XWINDOW (selected_window);
5764 struct buffer *buf = XBUFFER (w->buffer);
5765 struct buffer *obuf = current_buffer;
5766 int center_p = 0;
5767 int charpos, bytepos;
5768 int iarg;
5769 int this_scroll_margin;
5771 /* If redisplay is suppressed due to an error, try again. */
5772 obuf->display_error_modiff = 0;
5774 if (NILP (arg))
5776 int i;
5778 /* Invalidate pixel data calculated for all compositions. */
5779 for (i = 0; i < n_compositions; i++)
5780 composition_table[i]->font = NULL;
5782 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5784 Fredraw_frame (WINDOW_FRAME (w));
5785 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5786 center_p = 1;
5788 else if (CONSP (arg)) /* Just C-u. */
5789 center_p = 1;
5790 else
5792 arg = Fprefix_numeric_value (arg);
5793 CHECK_NUMBER (arg);
5794 iarg = XINT (arg);
5797 set_buffer_internal (buf);
5799 /* Do this after making BUF current
5800 in case scroll_margin is buffer-local. */
5801 this_scroll_margin = max (0, scroll_margin);
5802 this_scroll_margin = min (this_scroll_margin,
5803 XFASTINT (w->total_lines) / 4);
5805 /* Handle centering on a graphical frame specially. Such frames can
5806 have variable-height lines and centering point on the basis of
5807 line counts would lead to strange effects. */
5808 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5810 if (center_p)
5812 struct it it;
5813 struct text_pos pt;
5815 SET_TEXT_POS (pt, PT, PT_BYTE);
5816 start_display (&it, w, pt);
5817 move_it_vertically_backward (&it, window_box_height (w) / 2);
5818 charpos = IT_CHARPOS (it);
5819 bytepos = IT_BYTEPOS (it);
5821 else if (iarg < 0)
5823 struct it it;
5824 struct text_pos pt;
5825 int nlines = -iarg;
5826 int extra_line_spacing;
5827 int h = window_box_height (w);
5829 iarg = - max (-iarg, this_scroll_margin);
5831 SET_TEXT_POS (pt, PT, PT_BYTE);
5832 start_display (&it, w, pt);
5834 /* Be sure we have the exact height of the full line containing PT. */
5835 move_it_by_lines (&it, 0, 1);
5837 /* The amount of pixels we have to move back is the window
5838 height minus what's displayed in the line containing PT,
5839 and the lines below. */
5840 it.current_y = 0;
5841 it.vpos = 0;
5842 move_it_by_lines (&it, nlines, 1);
5844 if (it.vpos == nlines)
5845 h -= it.current_y;
5846 else
5848 /* Last line has no newline */
5849 h -= line_bottom_y (&it);
5850 it.vpos++;
5853 /* Don't reserve space for extra line spacing of last line. */
5854 extra_line_spacing = it.max_extra_line_spacing;
5856 /* If we can't move down NLINES lines because we hit
5857 the end of the buffer, count in some empty lines. */
5858 if (it.vpos < nlines)
5860 nlines -= it.vpos;
5861 extra_line_spacing = it.extra_line_spacing;
5862 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5864 if (h <= 0)
5865 return Qnil;
5867 /* Now find the new top line (starting position) of the window. */
5868 start_display (&it, w, pt);
5869 it.current_y = 0;
5870 move_it_vertically_backward (&it, h);
5872 /* If extra line spacing is present, we may move too far
5873 back. This causes the last line to be only partially
5874 visible (which triggers redisplay to recenter that line
5875 in the middle), so move forward.
5876 But ignore extra line spacing on last line, as it is not
5877 considered to be part of the visible height of the line.
5879 h += extra_line_spacing;
5880 while (-it.current_y > h)
5881 move_it_by_lines (&it, 1, 1);
5883 charpos = IT_CHARPOS (it);
5884 bytepos = IT_BYTEPOS (it);
5886 else
5888 struct position pos;
5890 iarg = max (iarg, this_scroll_margin);
5892 pos = *vmotion (PT, -iarg, w);
5893 charpos = pos.bufpos;
5894 bytepos = pos.bytepos;
5897 else
5899 struct position pos;
5900 int ht = window_internal_height (w);
5902 if (center_p)
5903 iarg = ht / 2;
5904 else if (iarg < 0)
5905 iarg += ht;
5907 /* Don't let it get into the margin at either top or bottom. */
5908 iarg = max (iarg, this_scroll_margin);
5909 iarg = min (iarg, ht - this_scroll_margin - 1);
5911 pos = *vmotion (PT, - iarg, w);
5912 charpos = pos.bufpos;
5913 bytepos = pos.bytepos;
5916 /* Set the new window start. */
5917 set_marker_both (w->start, w->buffer, charpos, bytepos);
5918 w->window_end_valid = Qnil;
5920 w->optional_new_start = Qt;
5922 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5923 w->start_at_line_beg = Qt;
5924 else
5925 w->start_at_line_beg = Qnil;
5927 set_buffer_internal (obuf);
5928 return Qnil;
5932 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5933 0, 1, 0,
5934 doc: /* Return the height in lines of the text display area of WINDOW.
5935 WINDOW defaults to the selected window.
5936 This doesn't include the mode-line (or header-line if any) or any
5937 partial-height lines in the text display area. */)
5938 (window)
5939 Lisp_Object window;
5941 struct window *w = decode_window (window);
5942 int pixel_height = window_box_height (w);
5943 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5944 return make_number (line_height);
5949 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5950 1, 1, "P",
5951 doc: /* Position point relative to window.
5952 With no argument, position point at center of window.
5953 An argument specifies vertical position within the window;
5954 zero means top of window, negative means relative to bottom of window. */)
5955 (arg)
5956 Lisp_Object arg;
5958 struct window *w = XWINDOW (selected_window);
5959 int lines, start;
5960 Lisp_Object window;
5961 #if 0
5962 int this_scroll_margin;
5963 #endif
5965 window = selected_window;
5966 start = marker_position (w->start);
5967 if (start < BEGV || start > ZV)
5969 int height = window_internal_height (w);
5970 Fvertical_motion (make_number (- (height / 2)), window);
5971 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5972 w->start_at_line_beg = Fbolp ();
5973 w->force_start = Qt;
5975 else
5976 Fgoto_char (w->start);
5978 lines = displayed_window_lines (w);
5980 #if 0
5981 this_scroll_margin = max (0, scroll_margin);
5982 this_scroll_margin = min (this_scroll_margin, lines / 4);
5983 #endif
5985 if (NILP (arg))
5986 XSETFASTINT (arg, lines / 2);
5987 else
5989 int iarg = XINT (Fprefix_numeric_value (arg));
5991 if (iarg < 0)
5992 iarg = iarg + lines;
5994 #if 0 /* This code would prevent move-to-window-line from moving point
5995 to a place inside the scroll margins (which would cause the
5996 next redisplay to scroll). I wrote this code, but then concluded
5997 it is probably better not to install it. However, it is here
5998 inside #if 0 so as not to lose it. -- rms. */
6000 /* Don't let it get into the margin at either top or bottom. */
6001 iarg = max (iarg, this_scroll_margin);
6002 iarg = min (iarg, lines - this_scroll_margin - 1);
6003 #endif
6005 arg = make_number (iarg);
6008 /* Skip past a partially visible first line. */
6009 if (w->vscroll)
6010 XSETINT (arg, XINT (arg) + 1);
6012 return Fvertical_motion (arg, window);
6017 /***********************************************************************
6018 Window Configuration
6019 ***********************************************************************/
6021 struct save_window_data
6023 EMACS_INT size_from_Lisp_Vector_struct;
6024 struct Lisp_Vector *next_from_Lisp_Vector_struct;
6025 Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
6026 Lisp_Object frame_tool_bar_lines;
6027 Lisp_Object selected_frame;
6028 Lisp_Object current_window;
6029 Lisp_Object current_buffer;
6030 Lisp_Object minibuf_scroll_window;
6031 Lisp_Object minibuf_selected_window;
6032 Lisp_Object root_window;
6033 Lisp_Object focus_frame;
6034 /* Record the values of window-min-width and window-min-height
6035 so that window sizes remain consistent with them. */
6036 Lisp_Object min_width, min_height;
6037 /* A vector, each of whose elements is a struct saved_window
6038 for one window. */
6039 Lisp_Object saved_windows;
6042 /* This is saved as a Lisp_Vector */
6043 struct saved_window
6045 /* these first two must agree with struct Lisp_Vector in lisp.h */
6046 EMACS_INT size_from_Lisp_Vector_struct;
6047 struct Lisp_Vector *next_from_Lisp_Vector_struct;
6049 Lisp_Object window;
6050 Lisp_Object buffer, start, pointm, mark;
6051 Lisp_Object left_col, top_line, total_cols, total_lines;
6052 Lisp_Object hscroll, min_hscroll;
6053 Lisp_Object parent, prev;
6054 Lisp_Object start_at_line_beg;
6055 Lisp_Object display_table;
6056 Lisp_Object orig_top_line, orig_total_lines;
6057 Lisp_Object left_margin_cols, right_margin_cols;
6058 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
6059 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
6060 Lisp_Object dedicated;
6063 #define SAVED_WINDOW_N(swv,n) \
6064 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
6066 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
6067 doc: /* Return t if OBJECT is a window-configuration object. */)
6068 (object)
6069 Lisp_Object object;
6071 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
6074 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
6075 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
6076 (config)
6077 Lisp_Object config;
6079 register struct save_window_data *data;
6080 struct Lisp_Vector *saved_windows;
6082 CHECK_WINDOW_CONFIGURATION (config);
6084 data = (struct save_window_data *) XVECTOR (config);
6085 saved_windows = XVECTOR (data->saved_windows);
6086 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6089 DEFUN ("set-window-configuration", Fset_window_configuration,
6090 Sset_window_configuration, 1, 1, 0,
6091 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
6092 CONFIGURATION must be a value previously returned
6093 by `current-window-configuration' (which see).
6094 If CONFIGURATION was made from a frame that is now deleted,
6095 only frame-independent values can be restored. In this case,
6096 the return value is nil. Otherwise the value is t. */)
6097 (configuration)
6098 Lisp_Object configuration;
6100 register struct save_window_data *data;
6101 struct Lisp_Vector *saved_windows;
6102 Lisp_Object new_current_buffer;
6103 Lisp_Object frame;
6104 FRAME_PTR f;
6105 int old_point = -1;
6107 CHECK_WINDOW_CONFIGURATION (configuration);
6109 data = (struct save_window_data *) XVECTOR (configuration);
6110 saved_windows = XVECTOR (data->saved_windows);
6112 new_current_buffer = data->current_buffer;
6113 if (NILP (XBUFFER (new_current_buffer)->name))
6114 new_current_buffer = Qnil;
6115 else
6117 if (XBUFFER (new_current_buffer) == current_buffer)
6118 /* The code further down "preserves point" by saving here PT in
6119 old_point and then setting it later back into PT. When the
6120 current-selected-window and the final-selected-window both show
6121 the current buffer, this suffers from the problem that the
6122 current PT is the window-point of the current-selected-window,
6123 while the final PT is the point of the final-selected-window, so
6124 this copy from one PT to the other would end up moving the
6125 window-point of the final-selected-window to the window-point of
6126 the current-selected-window. So we have to be careful which
6127 point of the current-buffer we copy into old_point. */
6128 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6129 && WINDOWP (selected_window)
6130 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
6131 && !EQ (selected_window, data->current_window))
6132 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6133 else
6134 old_point = PT;
6135 else
6136 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6137 point in new_current_buffer as of the last time this buffer was
6138 used. This can be non-deterministic since it can be changed by
6139 things like jit-lock by mere temporary selection of some random
6140 window that happens to show this buffer.
6141 So if possible we want this arbitrary choice of "which point" to
6142 be the one from the to-be-selected-window so as to prevent this
6143 window's cursor from being copied from another window. */
6144 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
6145 /* If current_window = selected_window, its point is in BUF_PT. */
6146 && !EQ (selected_window, data->current_window))
6147 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
6148 else
6149 old_point = BUF_PT (XBUFFER (new_current_buffer));
6152 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6153 f = XFRAME (frame);
6155 /* If f is a dead frame, don't bother rebuilding its window tree.
6156 However, there is other stuff we should still try to do below. */
6157 if (FRAME_LIVE_P (f))
6159 register struct window *w;
6160 register struct saved_window *p;
6161 struct window *root_window;
6162 struct window **leaf_windows;
6163 int n_leaf_windows;
6164 int k, i, n;
6166 /* If the frame has been resized since this window configuration was
6167 made, we change the frame to the size specified in the
6168 configuration, restore the configuration, and then resize it
6169 back. We keep track of the prevailing height in these variables. */
6170 int previous_frame_lines = FRAME_LINES (f);
6171 int previous_frame_cols = FRAME_COLS (f);
6172 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6173 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6175 /* The mouse highlighting code could get screwed up
6176 if it runs during this. */
6177 BLOCK_INPUT;
6179 if (XFASTINT (data->frame_lines) != previous_frame_lines
6180 || XFASTINT (data->frame_cols) != previous_frame_cols)
6181 change_frame_size (f, XFASTINT (data->frame_lines),
6182 XFASTINT (data->frame_cols), 0, 0, 0);
6183 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6184 if (XFASTINT (data->frame_menu_bar_lines)
6185 != previous_frame_menu_bar_lines)
6186 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
6187 #ifdef HAVE_WINDOW_SYSTEM
6188 if (XFASTINT (data->frame_tool_bar_lines)
6189 != previous_frame_tool_bar_lines)
6190 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
6191 #endif
6192 #endif
6194 /* "Swap out" point from the selected window's buffer
6195 into the window itself. (Normally the pointm of the selected
6196 window holds garbage.) We do this now, before
6197 restoring the window contents, and prevent it from
6198 being done later on when we select a new window. */
6199 if (! NILP (XWINDOW (selected_window)->buffer))
6201 w = XWINDOW (selected_window);
6202 set_marker_both (w->pointm,
6203 w->buffer,
6204 BUF_PT (XBUFFER (w->buffer)),
6205 BUF_PT_BYTE (XBUFFER (w->buffer)));
6208 windows_or_buffers_changed++;
6209 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
6211 /* Problem: Freeing all matrices and later allocating them again
6212 is a serious redisplay flickering problem. What we would
6213 really like to do is to free only those matrices not reused
6214 below. */
6215 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6216 leaf_windows
6217 = (struct window **) alloca (count_windows (root_window)
6218 * sizeof (struct window *));
6219 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6221 /* Temporarily avoid any problems with windows that are smaller
6222 than they are supposed to be. */
6223 window_min_height = 1;
6224 window_min_width = 1;
6226 /* Kludge Alert!
6227 Mark all windows now on frame as "deleted".
6228 Restoring the new configuration "undeletes" any that are in it.
6230 Save their current buffers in their height fields, since we may
6231 need it later, if a buffer saved in the configuration is now
6232 dead. */
6233 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6235 for (k = 0; k < saved_windows->size; k++)
6237 p = SAVED_WINDOW_N (saved_windows, k);
6238 w = XWINDOW (p->window);
6239 w->next = Qnil;
6241 if (!NILP (p->parent))
6242 w->parent = SAVED_WINDOW_N (saved_windows,
6243 XFASTINT (p->parent))->window;
6244 else
6245 w->parent = Qnil;
6247 if (!NILP (p->prev))
6249 w->prev = SAVED_WINDOW_N (saved_windows,
6250 XFASTINT (p->prev))->window;
6251 XWINDOW (w->prev)->next = p->window;
6253 else
6255 w->prev = Qnil;
6256 if (!NILP (w->parent))
6258 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
6260 XWINDOW (w->parent)->vchild = p->window;
6261 XWINDOW (w->parent)->hchild = Qnil;
6263 else
6265 XWINDOW (w->parent)->hchild = p->window;
6266 XWINDOW (w->parent)->vchild = Qnil;
6271 /* If we squirreled away the buffer in the window's height,
6272 restore it now. */
6273 if (BUFFERP (w->total_lines))
6274 w->buffer = w->total_lines;
6275 w->left_col = p->left_col;
6276 w->top_line = p->top_line;
6277 w->total_cols = p->total_cols;
6278 w->total_lines = p->total_lines;
6279 w->hscroll = p->hscroll;
6280 w->min_hscroll = p->min_hscroll;
6281 w->display_table = p->display_table;
6282 w->orig_top_line = p->orig_top_line;
6283 w->orig_total_lines = p->orig_total_lines;
6284 w->left_margin_cols = p->left_margin_cols;
6285 w->right_margin_cols = p->right_margin_cols;
6286 w->left_fringe_width = p->left_fringe_width;
6287 w->right_fringe_width = p->right_fringe_width;
6288 w->fringes_outside_margins = p->fringes_outside_margins;
6289 w->scroll_bar_width = p->scroll_bar_width;
6290 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
6291 w->dedicated = p->dedicated;
6292 XSETFASTINT (w->last_modified, 0);
6293 XSETFASTINT (w->last_overlay_modified, 0);
6295 /* Reinstall the saved buffer and pointers into it. */
6296 if (NILP (p->buffer))
6297 w->buffer = p->buffer;
6298 else
6300 if (!NILP (XBUFFER (p->buffer)->name))
6301 /* If saved buffer is alive, install it. */
6303 w->buffer = p->buffer;
6304 w->start_at_line_beg = p->start_at_line_beg;
6305 set_marker_restricted (w->start, p->start, w->buffer);
6306 set_marker_restricted (w->pointm, p->pointm, w->buffer);
6307 Fset_marker (XBUFFER (w->buffer)->mark,
6308 p->mark, w->buffer);
6310 /* As documented in Fcurrent_window_configuration, don't
6311 restore the location of point in the buffer which was
6312 current when the window configuration was recorded. */
6313 if (!EQ (p->buffer, new_current_buffer)
6314 && XBUFFER (p->buffer) == current_buffer)
6315 Fgoto_char (w->pointm);
6317 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
6318 /* Else unless window has a live buffer, get one. */
6320 w->buffer = Fcdr (Fcar (Vbuffer_alist));
6321 /* This will set the markers to beginning of visible
6322 range. */
6323 set_marker_restricted (w->start, make_number (0), w->buffer);
6324 set_marker_restricted (w->pointm, make_number (0),w->buffer);
6325 w->start_at_line_beg = Qt;
6327 else
6328 /* Keeping window's old buffer; make sure the markers
6329 are real. */
6331 /* Set window markers at start of visible range. */
6332 if (XMARKER (w->start)->buffer == 0)
6333 set_marker_restricted (w->start, make_number (0),
6334 w->buffer);
6335 if (XMARKER (w->pointm)->buffer == 0)
6336 set_marker_restricted_both (w->pointm, w->buffer,
6337 BUF_PT (XBUFFER (w->buffer)),
6338 BUF_PT_BYTE (XBUFFER (w->buffer)));
6339 w->start_at_line_beg = Qt;
6344 FRAME_ROOT_WINDOW (f) = data->root_window;
6345 /* Prevent "swapping out point" in the old selected window
6346 using the buffer that has been restored into it.
6347 We already swapped out point that from that window's old buffer. */
6348 selected_window = Qnil;
6350 /* Arrange *not* to restore point in the buffer that was
6351 current when the window configuration was saved. */
6352 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
6353 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6354 make_number (old_point),
6355 XWINDOW (data->current_window)->buffer);
6357 Fselect_window (data->current_window, Qnil);
6358 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
6359 = selected_window;
6361 if (NILP (data->focus_frame)
6362 || (FRAMEP (data->focus_frame)
6363 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6364 Fredirect_frame_focus (frame, data->focus_frame);
6366 #if 0 /* I don't understand why this is needed, and it causes problems
6367 when the frame's old selected window has been deleted. */
6368 if (f != selected_frame && FRAME_WINDOW_P (f))
6369 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
6370 0, 0);
6371 #endif
6373 /* Set the screen height to the value it had before this function. */
6374 if (previous_frame_lines != FRAME_LINES (f)
6375 || previous_frame_cols != FRAME_COLS (f))
6376 change_frame_size (f, previous_frame_lines, previous_frame_cols,
6377 0, 0, 0);
6378 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6379 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
6380 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
6381 make_number (0));
6382 #ifdef HAVE_WINDOW_SYSTEM
6383 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
6384 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
6385 make_number (0));
6386 #endif
6387 #endif
6389 /* Now, free glyph matrices in windows that were not reused. */
6390 for (i = n = 0; i < n_leaf_windows; ++i)
6392 if (NILP (leaf_windows[i]->buffer))
6394 /* Assert it's not reused as a combination. */
6395 xassert (NILP (leaf_windows[i]->hchild)
6396 && NILP (leaf_windows[i]->vchild));
6397 free_window_matrices (leaf_windows[i]);
6399 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
6400 ++n;
6403 adjust_glyphs (f);
6405 UNBLOCK_INPUT;
6407 /* Fselect_window will have made f the selected frame, so we
6408 reselect the proper frame here. Fhandle_switch_frame will change the
6409 selected window too, but that doesn't make the call to
6410 Fselect_window above totally superfluous; it still sets f's
6411 selected window. */
6412 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6413 do_switch_frame (data->selected_frame, 0, 0);
6415 if (! NILP (Vwindow_configuration_change_hook)
6416 && ! NILP (Vrun_hooks))
6417 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
6420 if (!NILP (new_current_buffer))
6421 Fset_buffer (new_current_buffer);
6423 /* Restore the minimum heights recorded in the configuration. */
6424 window_min_height = XINT (data->min_height);
6425 window_min_width = XINT (data->min_width);
6427 Vminibuf_scroll_window = data->minibuf_scroll_window;
6428 minibuf_selected_window = data->minibuf_selected_window;
6430 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6433 /* Mark all windows now on frame as deleted
6434 by setting their buffers to nil. */
6436 void
6437 delete_all_subwindows (w)
6438 register struct window *w;
6440 if (!NILP (w->next))
6441 delete_all_subwindows (XWINDOW (w->next));
6442 if (!NILP (w->vchild))
6443 delete_all_subwindows (XWINDOW (w->vchild));
6444 if (!NILP (w->hchild))
6445 delete_all_subwindows (XWINDOW (w->hchild));
6447 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
6449 if (!NILP (w->buffer))
6450 unshow_buffer (w);
6452 /* We set all three of these fields to nil, to make sure that we can
6453 distinguish this dead window from any live window. Live leaf
6454 windows will have buffer set, and combination windows will have
6455 vchild or hchild set. */
6456 w->buffer = Qnil;
6457 w->vchild = Qnil;
6458 w->hchild = Qnil;
6460 Vwindow_list = Qnil;
6463 static int
6464 count_windows (window)
6465 register struct window *window;
6467 register int count = 1;
6468 if (!NILP (window->next))
6469 count += count_windows (XWINDOW (window->next));
6470 if (!NILP (window->vchild))
6471 count += count_windows (XWINDOW (window->vchild));
6472 if (!NILP (window->hchild))
6473 count += count_windows (XWINDOW (window->hchild));
6474 return count;
6478 /* Fill vector FLAT with leaf windows under W, starting at index I.
6479 Value is last index + 1. */
6481 static int
6482 get_leaf_windows (w, flat, i)
6483 struct window *w;
6484 struct window **flat;
6485 int i;
6487 while (w)
6489 if (!NILP (w->hchild))
6490 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
6491 else if (!NILP (w->vchild))
6492 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
6493 else
6494 flat[i++] = w;
6496 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6499 return i;
6503 /* Return a pointer to the glyph W's physical cursor is on. Value is
6504 null if W's current matrix is invalid, so that no meaningfull glyph
6505 can be returned. */
6507 struct glyph *
6508 get_phys_cursor_glyph (w)
6509 struct window *w;
6511 struct glyph_row *row;
6512 struct glyph *glyph;
6514 if (w->phys_cursor.vpos >= 0
6515 && w->phys_cursor.vpos < w->current_matrix->nrows
6516 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
6517 row->enabled_p)
6518 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
6519 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
6520 else
6521 glyph = NULL;
6523 return glyph;
6527 static int
6528 save_window_save (window, vector, i)
6529 Lisp_Object window;
6530 struct Lisp_Vector *vector;
6531 int i;
6533 register struct saved_window *p;
6534 register struct window *w;
6535 register Lisp_Object tem;
6537 for (;!NILP (window); window = w->next)
6539 p = SAVED_WINDOW_N (vector, i);
6540 w = XWINDOW (window);
6542 XSETFASTINT (w->temslot, i); i++;
6543 p->window = window;
6544 p->buffer = w->buffer;
6545 p->left_col = w->left_col;
6546 p->top_line = w->top_line;
6547 p->total_cols = w->total_cols;
6548 p->total_lines = w->total_lines;
6549 p->hscroll = w->hscroll;
6550 p->min_hscroll = w->min_hscroll;
6551 p->display_table = w->display_table;
6552 p->orig_top_line = w->orig_top_line;
6553 p->orig_total_lines = w->orig_total_lines;
6554 p->left_margin_cols = w->left_margin_cols;
6555 p->right_margin_cols = w->right_margin_cols;
6556 p->left_fringe_width = w->left_fringe_width;
6557 p->right_fringe_width = w->right_fringe_width;
6558 p->fringes_outside_margins = w->fringes_outside_margins;
6559 p->scroll_bar_width = w->scroll_bar_width;
6560 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6561 p->dedicated = w->dedicated;
6562 if (!NILP (w->buffer))
6564 /* Save w's value of point in the window configuration.
6565 If w is the selected window, then get the value of point
6566 from the buffer; pointm is garbage in the selected window. */
6567 if (EQ (window, selected_window))
6569 p->pointm = Fmake_marker ();
6570 set_marker_both (p->pointm, w->buffer,
6571 BUF_PT (XBUFFER (w->buffer)),
6572 BUF_PT_BYTE (XBUFFER (w->buffer)));
6574 else
6575 p->pointm = Fcopy_marker (w->pointm, Qnil);
6577 p->start = Fcopy_marker (w->start, Qnil);
6578 p->start_at_line_beg = w->start_at_line_beg;
6580 tem = XBUFFER (w->buffer)->mark;
6581 p->mark = Fcopy_marker (tem, Qnil);
6583 else
6585 p->pointm = Qnil;
6586 p->start = Qnil;
6587 p->mark = Qnil;
6588 p->start_at_line_beg = Qnil;
6591 if (NILP (w->parent))
6592 p->parent = Qnil;
6593 else
6594 p->parent = XWINDOW (w->parent)->temslot;
6596 if (NILP (w->prev))
6597 p->prev = Qnil;
6598 else
6599 p->prev = XWINDOW (w->prev)->temslot;
6601 if (!NILP (w->vchild))
6602 i = save_window_save (w->vchild, vector, i);
6603 if (!NILP (w->hchild))
6604 i = save_window_save (w->hchild, vector, i);
6607 return i;
6610 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6611 Scurrent_window_configuration, 0, 1, 0,
6612 doc: /* Return an object representing the current window configuration of FRAME.
6613 If FRAME is nil or omitted, use the selected frame.
6614 This describes the number of windows, their sizes and current buffers,
6615 and for each displayed buffer, where display starts, and the positions of
6616 point and mark. An exception is made for point in the current buffer:
6617 its value is -not- saved.
6618 This also records the currently selected frame, and FRAME's focus
6619 redirection (see `redirect-frame-focus'). */)
6620 (frame)
6621 Lisp_Object frame;
6623 register Lisp_Object tem;
6624 register int n_windows;
6625 register struct save_window_data *data;
6626 register struct Lisp_Vector *vec;
6627 register int i;
6628 FRAME_PTR f;
6630 if (NILP (frame))
6631 frame = selected_frame;
6632 CHECK_LIVE_FRAME (frame);
6633 f = XFRAME (frame);
6635 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6636 vec = allocate_other_vector (VECSIZE (struct save_window_data));
6637 data = (struct save_window_data *)vec;
6639 XSETFASTINT (data->frame_cols, FRAME_COLS (f));
6640 XSETFASTINT (data->frame_lines, FRAME_LINES (f));
6641 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
6642 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
6643 data->selected_frame = selected_frame;
6644 data->current_window = FRAME_SELECTED_WINDOW (f);
6645 XSETBUFFER (data->current_buffer, current_buffer);
6646 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6647 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6648 data->root_window = FRAME_ROOT_WINDOW (f);
6649 data->focus_frame = FRAME_FOCUS_FRAME (f);
6650 XSETINT (data->min_height, window_min_height);
6651 XSETINT (data->min_width, window_min_width);
6652 tem = Fmake_vector (make_number (n_windows), Qnil);
6653 data->saved_windows = tem;
6654 for (i = 0; i < n_windows; i++)
6655 XVECTOR (tem)->contents[i]
6656 = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
6657 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6658 XSETWINDOW_CONFIGURATION (tem, data);
6659 return (tem);
6662 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
6663 0, UNEVALLED, 0,
6664 doc: /* Execute BODY, preserving window sizes and contents.
6665 Return the value of the last form in BODY.
6666 Restore which buffer appears in which window, where display starts,
6667 and the value of point and mark for each window.
6668 Also restore the choice of selected window.
6669 Also restore which buffer is current.
6670 Does not restore the value of point in current buffer.
6671 usage: (save-window-excursion BODY...) */)
6672 (args)
6673 Lisp_Object args;
6675 register Lisp_Object val;
6676 register int count = SPECPDL_INDEX ();
6678 record_unwind_protect (Fset_window_configuration,
6679 Fcurrent_window_configuration (Qnil));
6680 val = Fprogn (args);
6681 return unbind_to (count, val);
6686 /***********************************************************************
6687 Window Split Tree
6688 ***********************************************************************/
6690 static Lisp_Object
6691 window_tree (w)
6692 struct window *w;
6694 Lisp_Object tail = Qnil;
6695 Lisp_Object result = Qnil;
6697 while (w)
6699 Lisp_Object wn;
6701 XSETWINDOW (wn, w);
6702 if (!NILP (w->hchild))
6703 wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
6704 window_tree (XWINDOW (w->hchild))));
6705 else if (!NILP (w->vchild))
6706 wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
6707 window_tree (XWINDOW (w->vchild))));
6709 if (NILP (result))
6711 result = tail = Fcons (wn, Qnil);
6713 else
6715 XSETCDR (tail, Fcons (wn, Qnil));
6716 tail = XCDR (tail);
6719 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6722 return result;
6727 DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
6728 0, 1, 0,
6729 doc: /* Return the window tree for frame FRAME.
6731 The return value is a list of the form (ROOT MINI), where ROOT
6732 represents the window tree of the frame's root window, and MINI
6733 is the frame's minibuffer window.
6735 If the root window is not split, ROOT is the root window itself.
6736 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6737 horizontal split, and t for a vertical split, EDGES gives the combined
6738 size and position of the subwindows in the split, and the rest of the
6739 elements are the subwindows in the split. Each of the subwindows may
6740 again be a window or a list representing a window split, and so on.
6741 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6743 If FRAME is nil or omitted, return information on the currently
6744 selected frame. */)
6745 (frame)
6746 Lisp_Object frame;
6748 FRAME_PTR f;
6750 if (NILP (frame))
6751 frame = selected_frame;
6753 CHECK_FRAME (frame);
6754 f = XFRAME (frame);
6756 if (!FRAME_LIVE_P (f))
6757 return Qnil;
6759 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
6763 /***********************************************************************
6764 Marginal Areas
6765 ***********************************************************************/
6767 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6768 2, 3, 0,
6769 doc: /* Set width of marginal areas of window WINDOW.
6770 If WINDOW is nil, set margins of the currently selected window.
6771 Second arg LEFT-WIDTH specifies the number of character cells to
6772 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6773 does the same for the right marginal area. A nil width parameter
6774 means no margin. */)
6775 (window, left_width, right_width)
6776 Lisp_Object window, left_width, right_width;
6778 struct window *w = decode_window (window);
6780 /* Translate negative or zero widths to nil.
6781 Margins that are too wide have to be checked elsewhere. */
6783 if (!NILP (left_width))
6785 CHECK_NUMBER (left_width);
6786 if (XINT (left_width) <= 0)
6787 left_width = Qnil;
6790 if (!NILP (right_width))
6792 CHECK_NUMBER (right_width);
6793 if (XINT (right_width) <= 0)
6794 right_width = Qnil;
6797 if (!EQ (w->left_margin_cols, left_width)
6798 || !EQ (w->right_margin_cols, right_width))
6800 w->left_margin_cols = left_width;
6801 w->right_margin_cols = right_width;
6803 adjust_window_margins (w);
6805 ++windows_or_buffers_changed;
6806 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6809 return Qnil;
6813 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6814 0, 1, 0,
6815 doc: /* Get width of marginal areas of window WINDOW.
6816 If WINDOW is omitted or nil, use the currently selected window.
6817 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6818 If a marginal area does not exist, its width will be returned
6819 as nil. */)
6820 (window)
6821 Lisp_Object window;
6823 struct window *w = decode_window (window);
6824 return Fcons (w->left_margin_cols, w->right_margin_cols);
6829 /***********************************************************************
6830 Fringes
6831 ***********************************************************************/
6833 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6834 2, 4, 0,
6835 doc: /* Set the fringe widths of window WINDOW.
6836 If WINDOW is nil, set the fringe widths of the currently selected
6837 window.
6838 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6839 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6840 fringe width. If a fringe width arg is nil, that means to use the
6841 frame's default fringe width. Default fringe widths can be set with
6842 the command `set-fringe-style'.
6843 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6844 outside of the display margins. By default, fringes are drawn between
6845 display marginal areas and the text area. */)
6846 (window, left_width, right_width, outside_margins)
6847 Lisp_Object window, left_width, right_width, outside_margins;
6849 struct window *w = decode_window (window);
6851 if (!NILP (left_width))
6852 CHECK_NATNUM (left_width);
6853 if (!NILP (right_width))
6854 CHECK_NATNUM (right_width);
6856 /* Do nothing on a tty. */
6857 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6858 && (!EQ (w->left_fringe_width, left_width)
6859 || !EQ (w->right_fringe_width, right_width)
6860 || !EQ (w->fringes_outside_margins, outside_margins)))
6862 w->left_fringe_width = left_width;
6863 w->right_fringe_width = right_width;
6864 w->fringes_outside_margins = outside_margins;
6866 adjust_window_margins (w);
6868 clear_glyph_matrix (w->current_matrix);
6869 w->window_end_valid = Qnil;
6871 ++windows_or_buffers_changed;
6872 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6875 return Qnil;
6879 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6880 0, 1, 0,
6881 doc: /* Get width of fringes of window WINDOW.
6882 If WINDOW is omitted or nil, use the currently selected window.
6883 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6884 (window)
6885 Lisp_Object window;
6887 struct window *w = decode_window (window);
6889 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6890 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6891 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6892 ? Qt : Qnil), Qnil)));
6897 /***********************************************************************
6898 Scroll bars
6899 ***********************************************************************/
6901 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6902 2, 4, 0,
6903 doc: /* Set width and type of scroll bars of window WINDOW.
6904 If window is nil, set scroll bars of the currently selected window.
6905 Second parameter WIDTH specifies the pixel width for the scroll bar;
6906 this is automatically adjusted to a multiple of the frame column width.
6907 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6908 bar: left, right, or nil.
6909 If WIDTH is nil, use the frame's scroll-bar width.
6910 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6911 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6912 (window, width, vertical_type, horizontal_type)
6913 Lisp_Object window, width, vertical_type, horizontal_type;
6915 struct window *w = decode_window (window);
6917 if (!NILP (width))
6919 CHECK_NATNUM (width);
6921 if (XINT (width) == 0)
6922 vertical_type = Qnil;
6925 if (!(NILP (vertical_type)
6926 || EQ (vertical_type, Qleft)
6927 || EQ (vertical_type, Qright)
6928 || EQ (vertical_type, Qt)))
6929 error ("Invalid type of vertical scroll bar");
6931 if (!EQ (w->scroll_bar_width, width)
6932 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6934 w->scroll_bar_width = width;
6935 w->vertical_scroll_bar_type = vertical_type;
6937 adjust_window_margins (w);
6939 clear_glyph_matrix (w->current_matrix);
6940 w->window_end_valid = Qnil;
6942 ++windows_or_buffers_changed;
6943 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6946 return Qnil;
6950 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6951 0, 1, 0,
6952 doc: /* Get width and type of scroll bars of window WINDOW.
6953 If WINDOW is omitted or nil, use the currently selected window.
6954 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6955 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6956 value. */)
6957 (window)
6958 Lisp_Object window;
6960 struct window *w = decode_window (window);
6961 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6962 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6963 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6964 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6965 Fcons (w->vertical_scroll_bar_type,
6966 Fcons (Qnil, Qnil))));
6971 /***********************************************************************
6972 Smooth scrolling
6973 ***********************************************************************/
6975 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6976 doc: /* Return the amount by which WINDOW is scrolled vertically.
6977 Use the selected window if WINDOW is nil or omitted.
6978 Normally, value is a multiple of the canonical character height of WINDOW;
6979 optional second arg PIXELS-P means value is measured in pixels. */)
6980 (window, pixels_p)
6981 Lisp_Object window, pixels_p;
6983 Lisp_Object result;
6984 struct frame *f;
6985 struct window *w;
6987 if (NILP (window))
6988 window = selected_window;
6989 else
6990 CHECK_WINDOW (window);
6991 w = XWINDOW (window);
6992 f = XFRAME (w->frame);
6994 if (FRAME_WINDOW_P (f))
6995 result = (NILP (pixels_p)
6996 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6997 : make_number (-w->vscroll));
6998 else
6999 result = make_number (0);
7000 return result;
7004 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
7005 2, 3, 0,
7006 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
7007 WINDOW nil means use the selected window. Normally, VSCROLL is a
7008 non-negative multiple of the canonical character height of WINDOW;
7009 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
7010 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
7011 corresponds to an integral number of pixels. The return value is the
7012 result of this rounding.
7013 If PIXELS-P is non-nil, the return value is VSCROLL. */)
7014 (window, vscroll, pixels_p)
7015 Lisp_Object window, vscroll, pixels_p;
7017 struct window *w;
7018 struct frame *f;
7020 if (NILP (window))
7021 window = selected_window;
7022 else
7023 CHECK_WINDOW (window);
7024 CHECK_NUMBER_OR_FLOAT (vscroll);
7026 w = XWINDOW (window);
7027 f = XFRAME (w->frame);
7029 if (FRAME_WINDOW_P (f))
7031 int old_dy = w->vscroll;
7033 w->vscroll = - (NILP (pixels_p)
7034 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
7035 : XFLOATINT (vscroll));
7036 w->vscroll = min (w->vscroll, 0);
7038 if (w->vscroll != old_dy)
7040 /* Adjust glyph matrix of the frame if the virtual display
7041 area becomes larger than before. */
7042 if (w->vscroll < 0 && w->vscroll < old_dy)
7043 adjust_glyphs (f);
7045 /* Prevent redisplay shortcuts. */
7046 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
7050 return Fwindow_vscroll (window, pixels_p);
7054 /* Call FN for all leaf windows on frame F. FN is called with the
7055 first argument being a pointer to the leaf window, and with
7056 additional argument USER_DATA. Stops when FN returns 0. */
7058 void
7059 foreach_window (f, fn, user_data)
7060 struct frame *f;
7061 int (* fn) P_ ((struct window *, void *));
7062 void *user_data;
7064 /* Fdelete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
7065 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
7066 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
7070 /* Helper function for foreach_window. Call FN for all leaf windows
7071 reachable from W. FN is called with the first argument being a
7072 pointer to the leaf window, and with additional argument USER_DATA.
7073 Stop when FN returns 0. Value is 0 if stopped by FN. */
7075 static int
7076 foreach_window_1 (w, fn, user_data)
7077 struct window *w;
7078 int (* fn) P_ ((struct window *, void *));
7079 void *user_data;
7081 int cont;
7083 for (cont = 1; w && cont;)
7085 if (!NILP (w->hchild))
7086 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
7087 else if (!NILP (w->vchild))
7088 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
7089 else
7090 cont = fn (w, user_data);
7092 w = NILP (w->next) ? 0 : XWINDOW (w->next);
7095 return cont;
7099 /* Freeze or unfreeze the window start of W unless it is a
7100 mini-window or the selected window. FREEZE_P non-null means freeze
7101 the window start. */
7103 static int
7104 freeze_window_start (w, freeze_p)
7105 struct window *w;
7106 void *freeze_p;
7108 if (w == XWINDOW (selected_window)
7109 || MINI_WINDOW_P (w)
7110 || (MINI_WINDOW_P (XWINDOW (selected_window))
7111 && ! NILP (Vminibuf_scroll_window)
7112 && w == XWINDOW (Vminibuf_scroll_window)))
7113 freeze_p = NULL;
7115 w->frozen_window_start_p = freeze_p != NULL;
7116 return 1;
7120 /* Freeze or unfreeze the window starts of all leaf windows on frame
7121 F, except the selected window and a mini-window. FREEZE_P non-zero
7122 means freeze the window start. */
7124 void
7125 freeze_window_starts (f, freeze_p)
7126 struct frame *f;
7127 int freeze_p;
7129 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
7133 /***********************************************************************
7134 Initialization
7135 ***********************************************************************/
7137 /* Return 1 if window configurations C1 and C2
7138 describe the same state of affairs. This is used by Fequal. */
7141 compare_window_configurations (c1, c2, ignore_positions)
7142 Lisp_Object c1, c2;
7143 int ignore_positions;
7145 register struct save_window_data *d1, *d2;
7146 struct Lisp_Vector *sw1, *sw2;
7147 int i;
7149 CHECK_WINDOW_CONFIGURATION (c1);
7150 CHECK_WINDOW_CONFIGURATION (c2);
7152 d1 = (struct save_window_data *) XVECTOR (c1);
7153 d2 = (struct save_window_data *) XVECTOR (c2);
7154 sw1 = XVECTOR (d1->saved_windows);
7155 sw2 = XVECTOR (d2->saved_windows);
7157 if (! EQ (d1->frame_cols, d2->frame_cols))
7158 return 0;
7159 if (! EQ (d1->frame_lines, d2->frame_lines))
7160 return 0;
7161 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
7162 return 0;
7163 if (! EQ (d1->selected_frame, d2->selected_frame))
7164 return 0;
7165 /* Don't compare the current_window field directly.
7166 Instead see w1_is_current and w2_is_current, below. */
7167 if (! EQ (d1->current_buffer, d2->current_buffer))
7168 return 0;
7169 if (! ignore_positions)
7171 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
7172 return 0;
7173 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
7174 return 0;
7176 /* Don't compare the root_window field.
7177 We don't require the two configurations
7178 to use the same window object,
7179 and the two root windows must be equivalent
7180 if everything else compares equal. */
7181 if (! EQ (d1->focus_frame, d2->focus_frame))
7182 return 0;
7183 if (! EQ (d1->min_width, d2->min_width))
7184 return 0;
7185 if (! EQ (d1->min_height, d2->min_height))
7186 return 0;
7188 /* Verify that the two confis have the same number of windows. */
7189 if (sw1->size != sw2->size)
7190 return 0;
7192 for (i = 0; i < sw1->size; i++)
7194 struct saved_window *p1, *p2;
7195 int w1_is_current, w2_is_current;
7197 p1 = SAVED_WINDOW_N (sw1, i);
7198 p2 = SAVED_WINDOW_N (sw2, i);
7200 /* Verify that the current windows in the two
7201 configurations correspond to each other. */
7202 w1_is_current = EQ (d1->current_window, p1->window);
7203 w2_is_current = EQ (d2->current_window, p2->window);
7205 if (w1_is_current != w2_is_current)
7206 return 0;
7208 /* Verify that the corresponding windows do match. */
7209 if (! EQ (p1->buffer, p2->buffer))
7210 return 0;
7211 if (! EQ (p1->left_col, p2->left_col))
7212 return 0;
7213 if (! EQ (p1->top_line, p2->top_line))
7214 return 0;
7215 if (! EQ (p1->total_cols, p2->total_cols))
7216 return 0;
7217 if (! EQ (p1->total_lines, p2->total_lines))
7218 return 0;
7219 if (! EQ (p1->display_table, p2->display_table))
7220 return 0;
7221 if (! EQ (p1->parent, p2->parent))
7222 return 0;
7223 if (! EQ (p1->prev, p2->prev))
7224 return 0;
7225 if (! ignore_positions)
7227 if (! EQ (p1->hscroll, p2->hscroll))
7228 return 0;
7229 if (!EQ (p1->min_hscroll, p2->min_hscroll))
7230 return 0;
7231 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
7232 return 0;
7233 if (NILP (Fequal (p1->start, p2->start)))
7234 return 0;
7235 if (NILP (Fequal (p1->pointm, p2->pointm)))
7236 return 0;
7237 if (NILP (Fequal (p1->mark, p2->mark)))
7238 return 0;
7240 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
7241 return 0;
7242 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
7243 return 0;
7244 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
7245 return 0;
7246 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
7247 return 0;
7248 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
7249 return 0;
7250 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
7251 return 0;
7252 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
7253 return 0;
7256 return 1;
7259 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7260 Scompare_window_configurations, 2, 2, 0,
7261 doc: /* Compare two window configurations as regards the structure of windows.
7262 This function ignores details such as the values of point and mark
7263 and scrolling positions. */)
7264 (x, y)
7265 Lisp_Object x, y;
7267 if (compare_window_configurations (x, y, 1))
7268 return Qt;
7269 return Qnil;
7272 void
7273 init_window_once ()
7275 struct frame *f = make_terminal_frame ();
7276 XSETFRAME (selected_frame, f);
7277 Vterminal_frame = selected_frame;
7278 minibuf_window = f->minibuffer_window;
7279 selected_window = f->selected_window;
7280 last_nonminibuf_frame = f;
7282 window_initialized = 1;
7285 void
7286 init_window ()
7288 Vwindow_list = Qnil;
7291 void
7292 syms_of_window ()
7294 Qscroll_up = intern ("scroll-up");
7295 staticpro (&Qscroll_up);
7297 Qscroll_down = intern ("scroll-down");
7298 staticpro (&Qscroll_down);
7300 Qwindow_size_fixed = intern ("window-size-fixed");
7301 staticpro (&Qwindow_size_fixed);
7302 Fset (Qwindow_size_fixed, Qnil);
7304 staticpro (&Qwindow_configuration_change_hook);
7305 Qwindow_configuration_change_hook
7306 = intern ("window-configuration-change-hook");
7308 Qwindowp = intern ("windowp");
7309 staticpro (&Qwindowp);
7311 Qwindow_configuration_p = intern ("window-configuration-p");
7312 staticpro (&Qwindow_configuration_p);
7314 Qwindow_live_p = intern ("window-live-p");
7315 staticpro (&Qwindow_live_p);
7317 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
7318 staticpro (&Qtemp_buffer_show_hook);
7320 staticpro (&Vwindow_list);
7322 minibuf_selected_window = Qnil;
7323 staticpro (&minibuf_selected_window);
7325 window_scroll_pixel_based_preserve_y = -1;
7327 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
7328 doc: /* Non-nil means call as function to display a help buffer.
7329 The function is called with one argument, the buffer to be displayed.
7330 Used by `with-output-to-temp-buffer'.
7331 If this function is used, then it must do the entire job of showing
7332 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7333 Vtemp_buffer_show_function = Qnil;
7335 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
7336 doc: /* If non-nil, function to call to handle `display-buffer'.
7337 It will receive two args, the buffer and a flag which if non-nil means
7338 that the currently selected window is not acceptable.
7339 It should choose or create a window, display the specified buffer in it,
7340 and return the window.
7341 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
7342 work using this function. */);
7343 Vdisplay_buffer_function = Qnil;
7345 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
7346 doc: /* *If non-nil, `display-buffer' should even the window heights.
7347 If nil, `display-buffer' will leave the window configuration alone. */);
7348 Veven_window_heights = Qt;
7350 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
7351 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7352 Vminibuf_scroll_window = Qnil;
7354 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
7355 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7356 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7357 is displayed in the `mode-line' face. */);
7358 mode_line_in_non_selected_windows = 1;
7360 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
7361 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7362 Vother_window_scroll_buffer = Qnil;
7364 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
7365 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
7366 pop_up_frames = 0;
7368 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
7369 doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7370 auto_window_vscroll_p = 1;
7372 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
7373 doc: /* *Non-nil means `display-buffer' should reuse frames.
7374 If the buffer in question is already displayed in a frame, raise that frame. */);
7375 display_buffer_reuse_frames = 0;
7377 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
7378 doc: /* Function to call to handle automatic new frame creation.
7379 It is called with no arguments and should return a newly created frame.
7381 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
7382 where `pop-up-frame-alist' would hold the default frame parameters. */);
7383 Vpop_up_frame_function = Qnil;
7385 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
7386 doc: /* *List of buffer names that should have their own special frames.
7387 Displaying a buffer with `display-buffer' or `pop-to-buffer',
7388 if its name is in this list, makes a special frame for it
7389 using `special-display-function'. See also `special-display-regexps'.
7391 An element of the list can be a list instead of just a string.
7392 There are two ways to use a list as an element:
7393 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
7394 In the first case, the FRAME-PARAMETERS are pairs of the form
7395 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7396 In the second case, FUNCTION is called with BUFFER as the first argument,
7397 followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
7398 All this is done by the function found in `special-display-function'.
7400 If the specified frame parameters include (same-buffer . t), the
7401 buffer is displayed in the currently selected window. Otherwise, if
7402 they include (same-frame . t), the buffer is displayed in a new window
7403 in the currently selected frame.
7405 If this variable appears \"not to work\", because you add a name to it
7406 but that buffer still appears in the selected window, look at the
7407 values of `same-window-buffer-names' and `same-window-regexps'.
7408 Those variables take precedence over this one. */);
7409 Vspecial_display_buffer_names = Qnil;
7411 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
7412 doc: /* *List of regexps saying which buffers should have their own special frames.
7413 When displaying a buffer with `display-buffer' or `pop-to-buffer',
7414 if any regexp in this list matches the buffer name, it makes a
7415 special frame for the buffer by calling `special-display-function'.
7417 An element of the list can be a list instead of just a string.
7418 There are two ways to use a list as an element:
7419 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
7420 In the first case, the FRAME-PARAMETERS are pairs of the form
7421 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7422 In the second case, FUNCTION is called with BUFFER as the first argument,
7423 followed by the OTHER-ARGS--it can display the buffer in any way it likes.
7424 All this is done by the function found in `special-display-function'.
7426 If the specified frame parameters include (same-buffer . t), the
7427 buffer is displayed in the currently selected window. Otherwise, if
7428 they include (same-frame . t), the buffer is displayed in a new window
7429 in the currently selected frame.
7431 If this variable appears \"not to work\", because you add a regexp to it
7432 but the matching buffers still appear in the selected window, look at the
7433 values of `same-window-buffer-names' and `same-window-regexps'.
7434 Those variables take precedence over this one. */);
7435 Vspecial_display_regexps = Qnil;
7437 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
7438 doc: /* Function to call to make a new frame for a special buffer.
7439 It is called with two arguments, the buffer and optional buffer specific
7440 data, and should return a window displaying that buffer.
7441 The default value normally makes a separate frame for the buffer,
7442 using `special-display-frame-alist' to specify the frame parameters.
7443 But if the buffer specific data includes (same-buffer . t) then the
7444 buffer is displayed in the current selected window.
7445 Otherwise if it includes (same-frame . t) then the buffer is displayed in
7446 a new window in the currently selected frame.
7448 A buffer is special if it is listed in `special-display-buffer-names'
7449 or matches a regexp in `special-display-regexps'. */);
7450 Vspecial_display_function = Qnil;
7452 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
7453 doc: /* *List of buffer names that should appear in the selected window.
7454 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
7455 switches to it in the selected window, rather than making it appear
7456 in some other window.
7458 An element of the list can be a cons cell instead of just a string.
7459 Then the car must be a string, which specifies the buffer name.
7460 This is for compatibility with `special-display-buffer-names';
7461 the cdr of the cons cell is ignored.
7463 See also `same-window-regexps'. */);
7464 Vsame_window_buffer_names = Qnil;
7466 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
7467 doc: /* *List of regexps saying which buffers should appear in the selected window.
7468 If a buffer name matches one of these regexps, then displaying it
7469 using `display-buffer' or `pop-to-buffer' switches to it
7470 in the selected window, rather than making it appear in some other window.
7472 An element of the list can be a cons cell instead of just a string.
7473 Then the car must be a string, which specifies the buffer name.
7474 This is for compatibility with `special-display-buffer-names';
7475 the cdr of the cons cell is ignored.
7477 See also `same-window-buffer-names'. */);
7478 Vsame_window_regexps = Qnil;
7480 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
7481 doc: /* *Non-nil means display-buffer should make new windows. */);
7482 pop_up_windows = 1;
7484 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
7485 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
7486 next_screen_context_lines = 2;
7488 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
7489 doc: /* *A window must be at least this tall to be eligible for splitting
7490 by `display-buffer'. The value is in line units.
7491 If there is only one window, it is split regardless of this value. */);
7492 split_height_threshold = 500;
7494 DEFVAR_INT ("window-min-height", &window_min_height,
7495 doc: /* *Delete any window less than this tall (including its mode line).
7496 The value is in line units. */);
7497 window_min_height = 4;
7499 DEFVAR_INT ("window-min-width", &window_min_width,
7500 doc: /* *Delete any window less than this wide (measured in characters). */);
7501 window_min_width = 10;
7503 DEFVAR_LISP ("scroll-preserve-screen-position",
7504 &Vscroll_preserve_screen_position,
7505 doc: /* *Controls if scroll commands move point to keep its screen line unchanged.
7506 A value of nil means point does not keep its screen position except
7507 at the scroll margin or window boundary respectively.
7508 A value of t means point keeps its screen position if the scroll
7509 command moved it vertically out of the window, e.g. when scrolling
7510 by full screens.
7511 Any other value means point always keeps its screen position. */);
7512 Vscroll_preserve_screen_position = Qnil;
7514 DEFVAR_LISP ("window-configuration-change-hook",
7515 &Vwindow_configuration_change_hook,
7516 doc: /* Functions to call when window configuration changes.
7517 The selected frame is the one whose configuration has changed. */);
7518 Vwindow_configuration_change_hook = Qnil;
7520 defsubr (&Sselected_window);
7521 defsubr (&Sminibuffer_window);
7522 defsubr (&Swindow_minibuffer_p);
7523 defsubr (&Swindowp);
7524 defsubr (&Swindow_live_p);
7525 defsubr (&Spos_visible_in_window_p);
7526 defsubr (&Swindow_line_height);
7527 defsubr (&Swindow_buffer);
7528 defsubr (&Swindow_height);
7529 defsubr (&Swindow_width);
7530 defsubr (&Swindow_full_width_p);
7531 defsubr (&Swindow_hscroll);
7532 defsubr (&Sset_window_hscroll);
7533 defsubr (&Swindow_redisplay_end_trigger);
7534 defsubr (&Sset_window_redisplay_end_trigger);
7535 defsubr (&Swindow_edges);
7536 defsubr (&Swindow_pixel_edges);
7537 defsubr (&Swindow_inside_edges);
7538 defsubr (&Swindow_inside_pixel_edges);
7539 defsubr (&Scoordinates_in_window_p);
7540 defsubr (&Swindow_at);
7541 defsubr (&Swindow_point);
7542 defsubr (&Swindow_start);
7543 defsubr (&Swindow_end);
7544 defsubr (&Sset_window_point);
7545 defsubr (&Sset_window_start);
7546 defsubr (&Swindow_dedicated_p);
7547 defsubr (&Sset_window_dedicated_p);
7548 defsubr (&Swindow_display_table);
7549 defsubr (&Sset_window_display_table);
7550 defsubr (&Snext_window);
7551 defsubr (&Sprevious_window);
7552 defsubr (&Sother_window);
7553 defsubr (&Sget_lru_window);
7554 defsubr (&Sget_largest_window);
7555 defsubr (&Sget_buffer_window);
7556 defsubr (&Sdelete_other_windows);
7557 defsubr (&Sdelete_windows_on);
7558 defsubr (&Sreplace_buffer_in_windows);
7559 defsubr (&Sdelete_window);
7560 defsubr (&Sset_window_buffer);
7561 defsubr (&Sselect_window);
7562 defsubr (&Sspecial_display_p);
7563 defsubr (&Ssame_window_p);
7564 defsubr (&Sdisplay_buffer);
7565 defsubr (&Sforce_window_update);
7566 defsubr (&Ssplit_window);
7567 defsubr (&Senlarge_window);
7568 defsubr (&Sshrink_window);
7569 defsubr (&Sadjust_window_trailing_edge);
7570 defsubr (&Sscroll_up);
7571 defsubr (&Sscroll_down);
7572 defsubr (&Sscroll_left);
7573 defsubr (&Sscroll_right);
7574 defsubr (&Sother_window_for_scrolling);
7575 defsubr (&Sscroll_other_window);
7576 defsubr (&Sminibuffer_selected_window);
7577 defsubr (&Srecenter);
7578 defsubr (&Swindow_text_height);
7579 defsubr (&Smove_to_window_line);
7580 defsubr (&Swindow_configuration_p);
7581 defsubr (&Swindow_configuration_frame);
7582 defsubr (&Sset_window_configuration);
7583 defsubr (&Scurrent_window_configuration);
7584 defsubr (&Ssave_window_excursion);
7585 defsubr (&Swindow_tree);
7586 defsubr (&Sset_window_margins);
7587 defsubr (&Swindow_margins);
7588 defsubr (&Sset_window_fringes);
7589 defsubr (&Swindow_fringes);
7590 defsubr (&Sset_window_scroll_bars);
7591 defsubr (&Swindow_scroll_bars);
7592 defsubr (&Swindow_vscroll);
7593 defsubr (&Sset_window_vscroll);
7594 defsubr (&Scompare_window_configurations);
7595 defsubr (&Swindow_list);
7598 void
7599 keys_of_window ()
7601 initial_define_key (control_x_map, '1', "delete-other-windows");
7602 initial_define_key (control_x_map, '2', "split-window");
7603 initial_define_key (control_x_map, '0', "delete-window");
7604 initial_define_key (control_x_map, 'o', "other-window");
7605 initial_define_key (control_x_map, '^', "enlarge-window");
7606 initial_define_key (control_x_map, '<', "scroll-left");
7607 initial_define_key (control_x_map, '>', "scroll-right");
7609 initial_define_key (global_map, Ctl ('V'), "scroll-up");
7610 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7611 initial_define_key (meta_map, 'v', "scroll-down");
7613 initial_define_key (global_map, Ctl('L'), "recenter");
7614 initial_define_key (meta_map, 'r', "move-to-window-line");
7617 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7618 (do not change this comment) */