(debug-on-entry): Handle autoloaded functions and compiled macros.
[emacs.git] / src / window.c
blob93495afb1a532f1e18a5d3b3f8825f7e0509da12
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985,86,87, 1993,94,95,96,97,98, 2000,01,02,03,04
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 #include <config.h>
24 #include "lisp.h"
25 #include "buffer.h"
26 #include "keyboard.h"
27 #include "keymap.h"
28 #include "frame.h"
29 #include "window.h"
30 #include "commands.h"
31 #include "indent.h"
32 #include "termchar.h"
33 #include "disptab.h"
34 #include "dispextern.h"
35 #include "blockinput.h"
36 #include "intervals.h"
38 #ifdef HAVE_X_WINDOWS
39 #include "xterm.h"
40 #endif /* HAVE_X_WINDOWS */
41 #ifdef WINDOWSNT
42 #include "w32term.h"
43 #endif
44 #ifdef MSDOS
45 #include "msdos.h"
46 #endif
47 #ifdef MAC_OS
48 #include "macterm.h"
49 #endif
52 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
53 Lisp_Object Qwindow_size_fixed;
54 extern Lisp_Object Qleft_margin, Qright_margin;
56 static int displayed_window_lines P_ ((struct window *));
57 static struct window *decode_window P_ ((Lisp_Object));
58 static int count_windows P_ ((struct window *));
59 static int get_leaf_windows P_ ((struct window *, struct window **, int));
60 static void window_scroll P_ ((Lisp_Object, int, int, int));
61 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
62 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
63 static int window_min_size_1 P_ ((struct window *, int));
64 static int window_min_size P_ ((struct window *, int, int, int *));
65 static void size_window P_ ((Lisp_Object, int, int, int));
66 static int freeze_window_start P_ ((struct window *, void *));
67 static int window_fixed_size_p P_ ((struct window *, int, int));
68 static void enlarge_window P_ ((Lisp_Object, int, int, int));
69 static Lisp_Object window_list P_ ((void));
70 static int add_window_to_list P_ ((struct window *, void *));
71 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
72 Lisp_Object));
73 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
74 Lisp_Object, int));
75 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
76 Lisp_Object *));
77 static int foreach_window_1 P_ ((struct window *,
78 int (* fn) (struct window *, void *),
79 void *));
80 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
82 /* The value of `window-size-fixed'. */
84 int window_size_fixed;
86 /* This is the window in which the terminal's cursor should
87 be left when nothing is being done with it. This must
88 always be a leaf window, and its buffer is selected by
89 the top level editing loop at the end of each command.
91 This value is always the same as
92 FRAME_SELECTED_WINDOW (selected_frame). */
94 Lisp_Object selected_window;
96 /* A list of all windows for use by next_window and Fwindow_list.
97 Functions creating or deleting windows should invalidate this cache
98 by setting it to nil. */
100 Lisp_Object Vwindow_list;
102 /* The mini-buffer window of the selected frame.
103 Note that you cannot test for mini-bufferness of an arbitrary window
104 by comparing against this; but you can test for mini-bufferness of
105 the selected window. */
107 Lisp_Object minibuf_window;
109 /* Non-nil means it is the window whose mode line should be
110 shown as the selected window when the minibuffer is selected. */
112 Lisp_Object minibuf_selected_window;
114 /* Non-nil means it is the window for C-M-v to scroll
115 when the mini-buffer is selected. */
117 Lisp_Object Vminibuf_scroll_window;
119 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
121 Lisp_Object Vother_window_scroll_buffer;
123 /* Non-nil means it's function to call to display temp buffers. */
125 Lisp_Object Vtemp_buffer_show_function;
127 /* Non-zero means line and page scrolling on tall lines (with images)
128 does partial scrolling by modifying window-vscroll. */
130 int auto_window_vscroll_p;
132 /* Non-zero means to use mode-line-inactive face in all windows but the
133 selected-window and the minibuffer-scroll-window when the
134 minibuffer is active. */
135 int mode_line_in_non_selected_windows;
137 /* If a window gets smaller than either of these, it is removed. */
139 EMACS_INT window_min_height;
140 EMACS_INT window_min_width;
142 /* Nonzero implies Fdisplay_buffer should create windows. */
144 int pop_up_windows;
146 /* Nonzero implies make new frames for Fdisplay_buffer. */
148 int pop_up_frames;
150 /* Nonzero means reuse existing frames for displaying buffers. */
152 int display_buffer_reuse_frames;
154 /* Non-nil means use this function instead of default */
156 Lisp_Object Vpop_up_frame_function;
158 /* Function to call to handle Fdisplay_buffer. */
160 Lisp_Object Vdisplay_buffer_function;
162 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
164 Lisp_Object Veven_window_heights;
166 /* List of buffer *names* for buffers that should have their own frames. */
168 Lisp_Object Vspecial_display_buffer_names;
170 /* List of regexps for buffer names that should have their own frames. */
172 Lisp_Object Vspecial_display_regexps;
174 /* Function to pop up a special frame. */
176 Lisp_Object Vspecial_display_function;
178 /* List of buffer *names* for buffers to appear in selected window. */
180 Lisp_Object Vsame_window_buffer_names;
182 /* List of regexps for buffer names to appear in selected window. */
184 Lisp_Object Vsame_window_regexps;
186 /* Hook run at end of temp_output_buffer_show. */
188 Lisp_Object Qtemp_buffer_show_hook;
190 /* Fdisplay_buffer always splits the largest window
191 if that window is more than this high. */
193 EMACS_INT split_height_threshold;
195 /* Number of lines of continuity in scrolling by screenfuls. */
197 EMACS_INT next_screen_context_lines;
199 /* Incremented for each window created. */
201 static int sequence_number;
203 /* Nonzero after init_window_once has finished. */
205 static int window_initialized;
207 /* Hook to run when window config changes. */
209 Lisp_Object Qwindow_configuration_change_hook;
210 Lisp_Object Vwindow_configuration_change_hook;
212 /* Non-nil means scroll commands try to put point
213 at the same screen height as previously. */
215 Lisp_Object Vscroll_preserve_screen_position;
217 #if 0 /* This isn't used anywhere. */
218 /* Nonzero means we can split a frame even if it is "unsplittable". */
219 static int inhibit_frame_unsplittable;
220 #endif /* 0 */
222 extern EMACS_INT scroll_margin;
224 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
226 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
227 doc: /* Returns t if OBJECT is a window. */)
228 (object)
229 Lisp_Object object;
231 return WINDOWP (object) ? Qt : Qnil;
234 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
235 doc: /* Returns t if OBJECT is a window which is currently visible. */)
236 (object)
237 Lisp_Object object;
239 return WINDOW_LIVE_P (object) ? Qt : Qnil;
242 Lisp_Object
243 make_window ()
245 Lisp_Object val;
246 register struct window *p;
248 p = allocate_window ();
249 ++sequence_number;
250 XSETFASTINT (p->sequence_number, sequence_number);
251 XSETFASTINT (p->left_col, 0);
252 XSETFASTINT (p->top_line, 0);
253 XSETFASTINT (p->total_lines, 0);
254 XSETFASTINT (p->total_cols, 0);
255 XSETFASTINT (p->hscroll, 0);
256 XSETFASTINT (p->min_hscroll, 0);
257 p->orig_top_line = p->orig_total_lines = Qnil;
258 p->start = Fmake_marker ();
259 p->pointm = Fmake_marker ();
260 XSETFASTINT (p->use_time, 0);
261 p->frame = Qnil;
262 p->display_table = Qnil;
263 p->dedicated = Qnil;
264 p->pseudo_window_p = 0;
265 bzero (&p->cursor, sizeof (p->cursor));
266 bzero (&p->last_cursor, sizeof (p->last_cursor));
267 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
268 p->desired_matrix = p->current_matrix = 0;
269 p->nrows_scale_factor = p->ncols_scale_factor = 1;
270 p->phys_cursor_type = -1;
271 p->phys_cursor_width = -1;
272 p->must_be_updated_p = 0;
273 XSETFASTINT (p->window_end_vpos, 0);
274 XSETFASTINT (p->window_end_pos, 0);
275 p->window_end_valid = Qnil;
276 p->vscroll = 0;
277 XSETWINDOW (val, p);
278 XSETFASTINT (p->last_point, 0);
279 p->frozen_window_start_p = 0;
280 p->height_fixed_p = 0;
281 p->last_cursor_off_p = p->cursor_off_p = 0;
282 p->left_margin_cols = Qnil;
283 p->right_margin_cols = Qnil;
284 p->left_fringe_width = Qnil;
285 p->right_fringe_width = Qnil;
286 p->fringes_outside_margins = Qnil;
287 p->scroll_bar_width = Qnil;
288 p->vertical_scroll_bar_type = Qt;
289 p->overlay_arrow_bitmap = 0;
291 Vwindow_list = Qnil;
292 return val;
295 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
296 doc: /* Return the window that the cursor now appears in and commands apply to. */)
299 return selected_window;
302 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
303 doc: /* Return the window used now for minibuffers.
304 If the optional argument FRAME is specified, return the minibuffer window
305 used by that frame. */)
306 (frame)
307 Lisp_Object frame;
309 if (NILP (frame))
310 frame = selected_frame;
311 CHECK_LIVE_FRAME (frame);
312 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
315 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
316 doc: /* Returns non-nil if WINDOW is a minibuffer window.
317 WINDOW defaults to the selected window. */)
318 (window)
319 Lisp_Object window;
321 struct window *w = decode_window (window);
322 return MINI_WINDOW_P (w) ? Qt : Qnil;
326 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
327 Spos_visible_in_window_p, 0, 3, 0,
328 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
329 Return nil if that position is scrolled vertically out of view.
330 If a character is only partially visible, nil is returned, unless the
331 optional argument PARTIALLY is non-nil.
332 If POS is only out of view because of horizontal scrolling, return non-nil.
333 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
335 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
336 return value is a list (X Y PARTIAL) where X and Y are the pixel coordinates
337 relative to the top left corner of the window. PARTIAL is nil if the character
338 after POS is fully visible; otherwise it is a cons (RTOP . RBOT) where RTOP
339 and RBOT are the number of pixels invisible at the top and bottom of the row. */)
340 (pos, window, partially)
341 Lisp_Object pos, window, partially;
343 register struct window *w;
344 register int posint;
345 register struct buffer *buf;
346 struct text_pos top;
347 Lisp_Object in_window = Qnil;
348 int rtop, rbot, fully_p = 1;
349 int x, y;
351 w = decode_window (window);
352 buf = XBUFFER (w->buffer);
353 SET_TEXT_POS_FROM_MARKER (top, w->start);
355 if (!NILP (pos))
357 CHECK_NUMBER_COERCE_MARKER (pos);
358 posint = XINT (pos);
360 else if (w == XWINDOW (selected_window))
361 posint = PT;
362 else
363 posint = XMARKER (w->pointm)->charpos;
365 /* If position is above window start or outside buffer boundaries,
366 or if window start is out of range, position is not visible. */
367 if (posint >= CHARPOS (top)
368 && posint <= BUF_ZV (buf)
369 && CHARPOS (top) >= BUF_BEGV (buf)
370 && CHARPOS (top) <= BUF_ZV (buf)
371 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, NILP (partially))
372 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
373 in_window = Qt;
375 if (!NILP (in_window) && !NILP (partially))
376 in_window = Fcons (make_number (x),
377 Fcons (make_number (y),
378 Fcons ((fully_p ? Qnil
379 : Fcons (make_number (rtop),
380 make_number (rbot))),
381 Qnil)));
382 return in_window;
386 static struct window *
387 decode_window (window)
388 register Lisp_Object window;
390 if (NILP (window))
391 return XWINDOW (selected_window);
393 CHECK_LIVE_WINDOW (window);
394 return XWINDOW (window);
397 static struct window *
398 decode_any_window (window)
399 register Lisp_Object window;
401 if (NILP (window))
402 return XWINDOW (selected_window);
404 CHECK_WINDOW (window);
405 return XWINDOW (window);
408 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
409 doc: /* Return the buffer that WINDOW is displaying.
410 WINDOW defaults to the selected window. */)
411 (window)
412 Lisp_Object window;
414 return decode_window (window)->buffer;
417 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
418 doc: /* Return the number of lines in WINDOW (including its mode line). */)
419 (window)
420 Lisp_Object window;
422 return decode_any_window (window)->total_lines;
425 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
426 doc: /* Return the number of display columns in WINDOW.
427 This is the width that is usable columns available for text in WINDOW.
428 If you want to find out how many columns WINDOW takes up,
429 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
430 (window)
431 Lisp_Object window;
433 return make_number (window_box_text_cols (decode_any_window (window)));
436 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
437 doc: /* Return the number of columns by which WINDOW is scrolled from left margin. */)
438 (window)
439 Lisp_Object window;
441 return decode_window (window)->hscroll;
444 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
445 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
446 Return NCOL. NCOL should be zero or positive.
448 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
449 window so that the location of point becomes invisible. */)
450 (window, ncol)
451 Lisp_Object window, ncol;
453 struct window *w = decode_window (window);
454 int hscroll;
456 CHECK_NUMBER (ncol);
457 hscroll = max (0, XINT (ncol));
459 /* Prevent redisplay shortcuts when changing the hscroll. */
460 if (XINT (w->hscroll) != hscroll)
461 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
463 w->hscroll = make_number (hscroll);
464 return ncol;
467 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
468 Swindow_redisplay_end_trigger, 0, 1, 0,
469 doc: /* Return WINDOW's redisplay end trigger value.
470 See `set-window-redisplay-end-trigger' for more information. */)
471 (window)
472 Lisp_Object window;
474 return decode_window (window)->redisplay_end_trigger;
477 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
478 Sset_window_redisplay_end_trigger, 2, 2, 0,
479 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
480 VALUE should be a buffer position (typically a marker) or nil.
481 If it is a buffer position, then if redisplay in WINDOW reaches a position
482 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
483 with two arguments: WINDOW, and the end trigger value.
484 Afterwards the end-trigger value is reset to nil. */)
485 (window, value)
486 register Lisp_Object window, value;
488 register struct window *w;
490 w = decode_window (window);
491 w->redisplay_end_trigger = value;
492 return value;
495 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
496 doc: /* Return a list of the edge coordinates of WINDOW.
497 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
498 RIGHT is one more than the rightmost column occupied by WINDOW,
499 and BOTTOM is one more than the bottommost row occupied by WINDOW.
500 The edges include the space used by the window's scroll bar,
501 display margins, fringes, header line, and mode line, if it has them.
502 To get the edges of the actual text area, use `window-inside-edges'. */)
503 (window)
504 Lisp_Object window;
506 register struct window *w = decode_any_window (window);
508 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
509 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
510 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
511 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
512 Qnil))));
515 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
516 doc: /* Return a list of the edge pixel coordinates of WINDOW.
517 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
518 RIGHT is one more than the rightmost x position occupied by WINDOW,
519 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
520 The pixel edges include the space used by the window's scroll bar,
521 display margins, fringes, header line, and mode line, if it has them.
522 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
523 (window)
524 Lisp_Object window;
526 register struct window *w = decode_any_window (window);
528 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
529 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
530 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
531 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
532 Qnil))));
535 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
536 doc: /* Return a list of the edge coordinates of WINDOW.
537 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
538 RIGHT is one more than the rightmost column used by text in WINDOW,
539 and BOTTOM is one more than the bottommost row used by text in WINDOW.
540 The inside edges do not include the space used by the window's scroll bar,
541 display margins, fringes, header line, and/or mode line. */)
542 (window)
543 Lisp_Object window;
545 register struct window *w = decode_any_window (window);
547 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
548 + WINDOW_LEFT_MARGIN_COLS (w)
549 + WINDOW_LEFT_FRINGE_COLS (w)),
550 make_number (WINDOW_TOP_EDGE_LINE (w)
551 + WINDOW_HEADER_LINE_LINES (w)),
552 make_number (WINDOW_RIGHT_EDGE_COL (w)
553 - WINDOW_RIGHT_MARGIN_COLS (w)
554 - WINDOW_RIGHT_FRINGE_COLS (w)),
555 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
556 - WINDOW_MODE_LINE_LINES (w)));
559 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
560 doc: /* Return a list of the edge pixel coordinates of WINDOW.
561 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
562 RIGHT is one more than the rightmost x position used by text in WINDOW,
563 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
564 The inside edges do not include the space used by the window's scroll bar,
565 display margins, fringes, header line, and/or mode line. */)
566 (window)
567 Lisp_Object window;
569 register struct window *w = decode_any_window (window);
571 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
572 + WINDOW_LEFT_MARGIN_WIDTH (w)
573 + WINDOW_LEFT_FRINGE_WIDTH (w)),
574 make_number (WINDOW_TOP_EDGE_Y (w)
575 + WINDOW_HEADER_LINE_HEIGHT (w)),
576 make_number (WINDOW_RIGHT_EDGE_X (w)
577 - WINDOW_RIGHT_MARGIN_WIDTH (w)
578 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
579 make_number (WINDOW_BOTTOM_EDGE_Y (w)
580 - WINDOW_MODE_LINE_HEIGHT (w)));
583 /* Test if the character at column *X, row *Y is within window W.
584 If it is not, return ON_NOTHING;
585 if it is in the window's text area,
586 set *x and *y to its location relative to the upper left corner
587 of the window, and
588 return ON_TEXT;
589 if it is on the window's modeline, return ON_MODE_LINE;
590 if it is on the border between the window and its right sibling,
591 return ON_VERTICAL_BORDER.
592 if it is on a scroll bar,
593 return ON_SCROLL_BAR.
594 if it is on the window's top line, return ON_HEADER_LINE;
595 if it is in left or right fringe of the window,
596 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
597 to window-relative coordinates;
598 if it is in the marginal area to the left/right of the window,
599 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
600 to window-relative coordinates.
602 X and Y are frame relative pixel coordinates. */
604 static enum window_part
605 coordinates_in_window (w, x, y)
606 register struct window *w;
607 register int *x, *y;
609 struct frame *f = XFRAME (WINDOW_FRAME (w));
610 int left_x, right_x, top_y, bottom_y;
611 enum window_part part;
612 int ux = FRAME_COLUMN_WIDTH (f);
613 int x0 = WINDOW_LEFT_EDGE_X (w);
614 int x1 = WINDOW_RIGHT_EDGE_X (w);
615 /* The width of the area where the vertical line can be dragged.
616 (Between mode lines for instance. */
617 int grabbable_width = ux;
618 int lmargin_width, rmargin_width, text_left, text_right;
620 /* In what's below, we subtract 1 when computing right_x because we
621 want the rightmost pixel, which is given by left_pixel+width-1. */
622 if (w->pseudo_window_p)
624 left_x = 0;
625 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
626 top_y = WINDOW_TOP_EDGE_Y (w);
627 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
629 else
631 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
632 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
633 top_y = WINDOW_TOP_EDGE_Y (w);
634 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
637 /* Outside any interesting row? */
638 if (*y < top_y || *y >= bottom_y)
639 return ON_NOTHING;
641 /* On the mode line or header line? If it's near the start of
642 the mode or header line of window that's has a horizontal
643 sibling, say it's on the vertical line. That's to be able
644 to resize windows horizontally in case we're using toolkit
645 scroll bars. */
647 if (WINDOW_WANTS_MODELINE_P (w)
648 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
650 part = ON_MODE_LINE;
652 header_vertical_border_check:
653 /* We're somewhere on the mode line. We consider the place
654 between mode lines of horizontally adjacent mode lines
655 as the vertical border. If scroll bars on the left,
656 return the right window. */
657 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
658 || WINDOW_RIGHTMOST_P (w))
660 if (!WINDOW_LEFTMOST_P (w) && abs (*x - x0) < grabbable_width)
661 return ON_VERTICAL_BORDER;
663 else
665 if (abs (*x - x1) < grabbable_width)
666 return ON_VERTICAL_BORDER;
669 if (*x < x0 || *x >= x1)
670 return ON_NOTHING;
672 /* Convert X and Y to window relative coordinates.
673 Mode line starts at left edge of window. */
674 *x -= x0;
675 *y -= top_y;
676 return part;
679 if (WINDOW_WANTS_HEADER_LINE_P (w)
680 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
682 part = ON_HEADER_LINE;
683 goto header_vertical_border_check;
686 if (*x < x0 || *x >= x1)
687 return ON_NOTHING;
689 /* Outside any interesting column? */
690 if (*x < left_x || *x > right_x)
691 return ON_SCROLL_BAR;
693 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
694 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
696 text_left = window_box_left (w, TEXT_AREA);
697 text_right = text_left + window_box_width (w, TEXT_AREA);
699 if (FRAME_WINDOW_P (f))
701 if (!w->pseudo_window_p
702 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
703 && !WINDOW_RIGHTMOST_P (w)
704 && (abs (*x - right_x) < grabbable_width))
705 return ON_VERTICAL_BORDER;
707 else
709 /* Need to say "*x > right_x" rather than >=, since on character
710 terminals, the vertical line's x coordinate is right_x. */
711 if (!w->pseudo_window_p
712 && !WINDOW_RIGHTMOST_P (w)
713 && *x > right_x - ux)
715 /* On the border on the right side of the window? Assume that
716 this area begins at RIGHT_X minus a canonical char width. */
717 return ON_VERTICAL_BORDER;
721 if (*x < text_left)
723 if (lmargin_width > 0
724 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
725 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
726 : (*x < left_x + lmargin_width)))
728 *x -= left_x;
729 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
730 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
731 *y -= top_y;
732 return ON_LEFT_MARGIN;
735 /* Convert X and Y to window-relative pixel coordinates. */
736 *x -= left_x;
737 *y -= top_y;
738 return ON_LEFT_FRINGE;
741 if (*x >= text_right)
743 if (rmargin_width > 0
744 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
745 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
746 : (*x >= right_x - rmargin_width)))
748 *x -= right_x;
749 if (!WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
750 *x -= WINDOW_RIGHT_FRINGE_WIDTH (w);
751 *y -= top_y;
752 return ON_RIGHT_MARGIN;
755 /* Convert X and Y to window-relative pixel coordinates. */
756 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
757 *y -= top_y;
758 return ON_RIGHT_FRINGE;
761 /* Everything special ruled out - must be on text area */
762 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
763 *y -= top_y;
764 return ON_TEXT;
768 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
769 Scoordinates_in_window_p, 2, 2, 0,
770 doc: /* Return non-nil if COORDINATES are in WINDOW.
771 COORDINATES is a cons of the form (X . Y), X and Y being distances
772 measured in characters from the upper-left corner of the frame.
773 \(0 . 0) denotes the character in the upper left corner of the
774 frame.
775 If COORDINATES are in the text portion of WINDOW,
776 the coordinates relative to the window are returned.
777 If they are in the mode line of WINDOW, `mode-line' is returned.
778 If they are in the top mode line of WINDOW, `header-line' is returned.
779 If they are in the left fringe of WINDOW, `left-fringe' is returned.
780 If they are in the right fringe of WINDOW, `right-fringe' is returned.
781 If they are on the border between WINDOW and its right sibling,
782 `vertical-line' is returned.
783 If they are in the windows's left or right marginal areas, `left-margin'\n\
784 or `right-margin' is returned. */)
785 (coordinates, window)
786 register Lisp_Object coordinates, window;
788 struct window *w;
789 struct frame *f;
790 int x, y;
791 Lisp_Object lx, ly;
793 CHECK_WINDOW (window);
794 w = XWINDOW (window);
795 f = XFRAME (w->frame);
796 CHECK_CONS (coordinates);
797 lx = Fcar (coordinates);
798 ly = Fcdr (coordinates);
799 CHECK_NUMBER_OR_FLOAT (lx);
800 CHECK_NUMBER_OR_FLOAT (ly);
801 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
802 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
804 switch (coordinates_in_window (w, &x, &y))
806 case ON_NOTHING:
807 return Qnil;
809 case ON_TEXT:
810 /* X and Y are now window relative pixel coordinates. Convert
811 them to canonical char units before returning them. */
812 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
813 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
815 case ON_MODE_LINE:
816 return Qmode_line;
818 case ON_VERTICAL_BORDER:
819 return Qvertical_line;
821 case ON_HEADER_LINE:
822 return Qheader_line;
824 case ON_LEFT_FRINGE:
825 return Qleft_fringe;
827 case ON_RIGHT_FRINGE:
828 return Qright_fringe;
830 case ON_LEFT_MARGIN:
831 return Qleft_margin;
833 case ON_RIGHT_MARGIN:
834 return Qright_margin;
836 case ON_SCROLL_BAR:
837 /* Historically we are supposed to return nil in this case. */
838 return Qnil;
840 default:
841 abort ();
846 /* Callback for foreach_window, used in window_from_coordinates.
847 Check if window W contains coordinates specified by USER_DATA which
848 is actually a pointer to a struct check_window_data CW.
850 Check if window W contains coordinates *CW->x and *CW->y. If it
851 does, return W in *CW->window, as Lisp_Object, and return in
852 *CW->part the part of the window under coordinates *X,*Y. Return
853 zero from this function to stop iterating over windows. */
855 struct check_window_data
857 Lisp_Object *window;
858 int *x, *y;
859 enum window_part *part;
862 static int
863 check_window_containing (w, user_data)
864 struct window *w;
865 void *user_data;
867 struct check_window_data *cw = (struct check_window_data *) user_data;
868 enum window_part found;
869 int continue_p = 1;
871 found = coordinates_in_window (w, cw->x, cw->y);
872 if (found != ON_NOTHING)
874 *cw->part = found;
875 XSETWINDOW (*cw->window, w);
876 continue_p = 0;
879 return continue_p;
883 /* Find the window containing frame-relative pixel position X/Y and
884 return it as a Lisp_Object.
886 If X, Y is on one of the window's special `window_part' elements,
887 set *PART to the id of that element, and return X and Y converted
888 to window relative coordinates in WX and WY.
890 If there is no window under X, Y return nil and leave *PART
891 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
893 This function was previously implemented with a loop cycling over
894 windows with Fnext_window, and starting with the frame's selected
895 window. It turned out that this doesn't work with an
896 implementation of next_window using Vwindow_list, because
897 FRAME_SELECTED_WINDOW (F) is not always contained in the window
898 tree of F when this function is called asynchronously from
899 note_mouse_highlight. The original loop didn't terminate in this
900 case. */
902 Lisp_Object
903 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
904 struct frame *f;
905 int x, y;
906 enum window_part *part;
907 int *wx, *wy;
908 int tool_bar_p;
910 Lisp_Object window;
911 struct check_window_data cw;
912 enum window_part dummy;
914 if (part == 0)
915 part = &dummy;
917 window = Qnil;
918 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
919 foreach_window (f, check_window_containing, &cw);
921 /* If not found above, see if it's in the tool bar window, if a tool
922 bar exists. */
923 if (NILP (window)
924 && tool_bar_p
925 && WINDOWP (f->tool_bar_window)
926 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
927 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
928 != ON_NOTHING))
930 *part = ON_TEXT;
931 window = f->tool_bar_window;
934 if (wx) *wx = x;
935 if (wy) *wy = y;
937 return window;
940 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
941 doc: /* Return window containing coordinates X and Y on FRAME.
942 If omitted, FRAME defaults to the currently selected frame.
943 The top left corner of the frame is considered to be row 0,
944 column 0. */)
945 (x, y, frame)
946 Lisp_Object x, y, frame;
948 struct frame *f;
950 if (NILP (frame))
951 frame = selected_frame;
952 CHECK_LIVE_FRAME (frame);
953 f = XFRAME (frame);
955 /* Check that arguments are integers or floats. */
956 CHECK_NUMBER_OR_FLOAT (x);
957 CHECK_NUMBER_OR_FLOAT (y);
959 return window_from_coordinates (f,
960 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
961 + FRAME_INTERNAL_BORDER_WIDTH (f)),
962 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
963 + FRAME_INTERNAL_BORDER_WIDTH (f)),
964 0, 0, 0, 0);
967 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
968 doc: /* Return current value of point in WINDOW.
969 For a nonselected window, this is the value point would have
970 if that window were selected.
972 Note that, when WINDOW is the selected window and its buffer
973 is also currently selected, the value returned is the same as (point).
974 It would be more strictly correct to return the `top-level' value
975 of point, outside of any save-excursion forms.
976 But that is hard to define. */)
977 (window)
978 Lisp_Object window;
980 register struct window *w = decode_window (window);
982 if (w == XWINDOW (selected_window)
983 && current_buffer == XBUFFER (w->buffer))
984 return Fpoint ();
985 return Fmarker_position (w->pointm);
988 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
989 doc: /* Return position at which display currently starts in WINDOW.
990 This is updated by redisplay or by calling `set-window-start'. */)
991 (window)
992 Lisp_Object window;
994 return Fmarker_position (decode_window (window)->start);
997 /* This is text temporarily removed from the doc string below.
999 This function returns nil if the position is not currently known.
1000 That happens when redisplay is preempted and doesn't finish.
1001 If in that case you want to compute where the end of the window would
1002 have been if redisplay had finished, do this:
1003 (save-excursion
1004 (goto-char (window-start window))
1005 (vertical-motion (1- (window-height window)) window)
1006 (point))") */
1008 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1009 doc: /* Return position at which display currently ends in WINDOW.
1010 This is updated by redisplay, when it runs to completion.
1011 Simply changing the buffer text or setting `window-start'
1012 does not update this value.
1013 Return nil if there is no recorded value. \(This can happen if the
1014 last redisplay of WINDOW was preempted, and did not finish.)
1015 If UPDATE is non-nil, compute the up-to-date position
1016 if it isn't already recorded. */)
1017 (window, update)
1018 Lisp_Object window, update;
1020 Lisp_Object value;
1021 struct window *w = decode_window (window);
1022 Lisp_Object buf;
1024 buf = w->buffer;
1025 CHECK_BUFFER (buf);
1027 #if 0 /* This change broke some things. We should make it later. */
1028 /* If we don't know the end position, return nil.
1029 The user can compute it with vertical-motion if he wants to.
1030 It would be nicer to do it automatically,
1031 but that's so slow that it would probably bother people. */
1032 if (NILP (w->window_end_valid))
1033 return Qnil;
1034 #endif
1036 if (! NILP (update)
1037 && ! (! NILP (w->window_end_valid)
1038 && XFASTINT (w->last_modified) >= MODIFF))
1040 struct text_pos startp;
1041 struct it it;
1042 struct buffer *old_buffer = NULL, *b = XBUFFER (buf);
1044 /* In case W->start is out of the range, use something
1045 reasonable. This situation occurred when loading a file with
1046 `-l' containing a call to `rmail' with subsequent other
1047 commands. At the end, W->start happened to be BEG, while
1048 rmail had already narrowed the buffer. */
1049 if (XMARKER (w->start)->charpos < BEGV)
1050 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1051 else if (XMARKER (w->start)->charpos > ZV)
1052 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1053 else
1054 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1056 /* Cannot use Fvertical_motion because that function doesn't
1057 cope with variable-height lines. */
1058 if (b != current_buffer)
1060 old_buffer = current_buffer;
1061 set_buffer_internal (b);
1064 start_display (&it, w, startp);
1065 move_it_vertically (&it, window_box_height (w));
1066 if (it.current_y < it.last_visible_y)
1067 move_it_past_eol (&it);
1068 value = make_number (IT_CHARPOS (it));
1070 if (old_buffer)
1071 set_buffer_internal (old_buffer);
1073 else
1074 XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
1076 return value;
1079 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1080 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1081 Return POS. */)
1082 (window, pos)
1083 Lisp_Object window, pos;
1085 register struct window *w = decode_window (window);
1087 CHECK_NUMBER_COERCE_MARKER (pos);
1088 if (w == XWINDOW (selected_window)
1089 && XBUFFER (w->buffer) == current_buffer)
1090 Fgoto_char (pos);
1091 else
1092 set_marker_restricted (w->pointm, pos, w->buffer);
1094 /* We have to make sure that redisplay updates the window to show
1095 the new value of point. */
1096 if (!EQ (window, selected_window))
1097 ++windows_or_buffers_changed;
1099 return pos;
1102 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1103 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1104 Return POS.
1105 Optional third arg NOFORCE non-nil inhibits next redisplay
1106 from overriding motion of point in order to display at this exact start. */)
1107 (window, pos, noforce)
1108 Lisp_Object window, pos, noforce;
1110 register struct window *w = decode_window (window);
1112 CHECK_NUMBER_COERCE_MARKER (pos);
1113 set_marker_restricted (w->start, pos, w->buffer);
1114 /* this is not right, but much easier than doing what is right. */
1115 w->start_at_line_beg = Qnil;
1116 if (NILP (noforce))
1117 w->force_start = Qt;
1118 w->update_mode_line = Qt;
1119 XSETFASTINT (w->last_modified, 0);
1120 XSETFASTINT (w->last_overlay_modified, 0);
1121 if (!EQ (window, selected_window))
1122 windows_or_buffers_changed++;
1124 return pos;
1127 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1128 1, 1, 0,
1129 doc: /* Return WINDOW's dedicated object, usually t or nil.
1130 See also `set-window-dedicated-p'. */)
1131 (window)
1132 Lisp_Object window;
1134 return decode_window (window)->dedicated;
1137 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1138 Sset_window_dedicated_p, 2, 2, 0,
1139 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1140 If it is dedicated, Emacs will not automatically change
1141 which buffer appears in it.
1142 The second argument is the new value for the dedication flag;
1143 non-nil means yes. */)
1144 (window, arg)
1145 Lisp_Object window, arg;
1147 register struct window *w = decode_window (window);
1149 w->dedicated = arg;
1151 return w->dedicated;
1154 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1155 0, 1, 0,
1156 doc: /* Return the display-table that WINDOW is using. */)
1157 (window)
1158 Lisp_Object window;
1160 return decode_window (window)->display_table;
1163 /* Get the display table for use on window W. This is either W's
1164 display table or W's buffer's display table. Ignore the specified
1165 tables if they are not valid; if no valid table is specified,
1166 return 0. */
1168 struct Lisp_Char_Table *
1169 window_display_table (w)
1170 struct window *w;
1172 struct Lisp_Char_Table *dp = NULL;
1174 if (DISP_TABLE_P (w->display_table))
1175 dp = XCHAR_TABLE (w->display_table);
1176 else if (BUFFERP (w->buffer))
1178 struct buffer *b = XBUFFER (w->buffer);
1180 if (DISP_TABLE_P (b->display_table))
1181 dp = XCHAR_TABLE (b->display_table);
1182 else if (DISP_TABLE_P (Vstandard_display_table))
1183 dp = XCHAR_TABLE (Vstandard_display_table);
1186 return dp;
1189 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1190 doc: /* Set WINDOW's display-table to TABLE. */)
1191 (window, table)
1192 register Lisp_Object window, table;
1194 register struct window *w;
1196 w = decode_window (window);
1197 w->display_table = table;
1198 return table;
1201 /* Record info on buffer window w is displaying
1202 when it is about to cease to display that buffer. */
1203 static void
1204 unshow_buffer (w)
1205 register struct window *w;
1207 Lisp_Object buf;
1208 struct buffer *b;
1210 buf = w->buffer;
1211 b = XBUFFER (buf);
1212 if (b != XMARKER (w->pointm)->buffer)
1213 abort ();
1215 #if 0
1216 if (w == XWINDOW (selected_window)
1217 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1218 /* Do this except when the selected window's buffer
1219 is being removed from some other window. */
1220 #endif
1221 /* last_window_start records the start position that this buffer
1222 had in the last window to be disconnected from it.
1223 Now that this statement is unconditional,
1224 it is possible for the buffer to be displayed in the
1225 selected window, while last_window_start reflects another
1226 window which was recently showing the same buffer.
1227 Some people might say that might be a good thing. Let's see. */
1228 b->last_window_start = marker_position (w->start);
1230 /* Point in the selected window's buffer
1231 is actually stored in that buffer, and the window's pointm isn't used.
1232 So don't clobber point in that buffer. */
1233 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1234 /* This line helps to fix Horsley's testbug.el bug. */
1235 && !(WINDOWP (b->last_selected_window)
1236 && w != XWINDOW (b->last_selected_window)
1237 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1238 temp_set_point_both (b,
1239 clip_to_bounds (BUF_BEGV (b),
1240 XMARKER (w->pointm)->charpos,
1241 BUF_ZV (b)),
1242 clip_to_bounds (BUF_BEGV_BYTE (b),
1243 marker_byte_position (w->pointm),
1244 BUF_ZV_BYTE (b)));
1246 if (WINDOWP (b->last_selected_window)
1247 && w == XWINDOW (b->last_selected_window))
1248 b->last_selected_window = Qnil;
1251 /* Put replacement into the window structure in place of old. */
1252 static void
1253 replace_window (old, replacement)
1254 Lisp_Object old, replacement;
1256 register Lisp_Object tem;
1257 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1259 /* If OLD is its frame's root_window, then replacement is the new
1260 root_window for that frame. */
1262 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1263 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1265 p->left_col = o->left_col;
1266 p->top_line = o->top_line;
1267 p->total_cols = o->total_cols;
1268 p->total_lines = o->total_lines;
1269 p->desired_matrix = p->current_matrix = 0;
1270 p->vscroll = 0;
1271 bzero (&p->cursor, sizeof (p->cursor));
1272 bzero (&p->last_cursor, sizeof (p->last_cursor));
1273 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1274 p->phys_cursor_type = -1;
1275 p->phys_cursor_width = -1;
1276 p->must_be_updated_p = 0;
1277 p->pseudo_window_p = 0;
1278 XSETFASTINT (p->window_end_vpos, 0);
1279 XSETFASTINT (p->window_end_pos, 0);
1280 p->window_end_valid = Qnil;
1281 p->frozen_window_start_p = 0;
1282 p->orig_top_line = p->orig_total_lines = Qnil;
1284 p->next = tem = o->next;
1285 if (!NILP (tem))
1286 XWINDOW (tem)->prev = replacement;
1288 p->prev = tem = o->prev;
1289 if (!NILP (tem))
1290 XWINDOW (tem)->next = replacement;
1292 p->parent = tem = o->parent;
1293 if (!NILP (tem))
1295 if (EQ (XWINDOW (tem)->vchild, old))
1296 XWINDOW (tem)->vchild = replacement;
1297 if (EQ (XWINDOW (tem)->hchild, old))
1298 XWINDOW (tem)->hchild = replacement;
1301 /*** Here, if replacement is a vertical combination
1302 and so is its new parent, we should make replacement's
1303 children be children of that parent instead. ***/
1306 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1307 doc: /* Remove WINDOW from the display. Default is selected window. */)
1308 (window)
1309 register Lisp_Object window;
1311 delete_window (window);
1313 if (! NILP (Vwindow_configuration_change_hook)
1314 && ! NILP (Vrun_hooks))
1315 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1317 return Qnil;
1320 void
1321 delete_window (window)
1322 register Lisp_Object window;
1324 register Lisp_Object tem, parent, sib;
1325 register struct window *p;
1326 register struct window *par;
1327 struct frame *f;
1329 /* Because this function is called by other C code on non-leaf
1330 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1331 so we can't decode_window here. */
1332 if (NILP (window))
1333 window = selected_window;
1334 else
1335 CHECK_WINDOW (window);
1336 p = XWINDOW (window);
1338 /* It's okay to delete an already-deleted window. */
1339 if (NILP (p->buffer)
1340 && NILP (p->hchild)
1341 && NILP (p->vchild))
1342 return;
1344 parent = p->parent;
1345 if (NILP (parent))
1346 error ("Attempt to delete minibuffer or sole ordinary window");
1347 par = XWINDOW (parent);
1349 windows_or_buffers_changed++;
1350 Vwindow_list = Qnil;
1351 f = XFRAME (WINDOW_FRAME (p));
1352 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1354 /* Are we trying to delete any frame's selected window? */
1356 Lisp_Object swindow, pwindow;
1358 /* See if the frame's selected window is either WINDOW
1359 or any subwindow of it, by finding all that window's parents
1360 and comparing each one with WINDOW. */
1361 swindow = FRAME_SELECTED_WINDOW (f);
1363 while (1)
1365 pwindow = swindow;
1366 while (!NILP (pwindow))
1368 if (EQ (window, pwindow))
1369 break;
1370 pwindow = XWINDOW (pwindow)->parent;
1373 /* If the window being deleted is not a parent of SWINDOW,
1374 then SWINDOW is ok as the new selected window. */
1375 if (!EQ (window, pwindow))
1376 break;
1377 /* Otherwise, try another window for SWINDOW. */
1378 swindow = Fnext_window (swindow, Qlambda, Qnil);;
1380 /* If we get back to the frame's selected window,
1381 it means there was no acceptable alternative,
1382 so we cannot delete. */
1383 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1384 error ("Cannot delete window");
1387 /* If we need to change SWINDOW, do it. */
1388 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1390 /* If we're about to delete the selected window on the
1391 selected frame, then we should use Fselect_window to select
1392 the new window. On the other hand, if we're about to
1393 delete the selected window on any other frame, we shouldn't do
1394 anything but set the frame's selected_window slot. */
1395 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1396 Fselect_window (swindow, Qnil);
1397 else
1398 FRAME_SELECTED_WINDOW (f) = swindow;
1402 tem = p->buffer;
1403 /* tem is null for dummy parent windows
1404 (which have inferiors but not any contents themselves) */
1405 if (!NILP (tem))
1407 unshow_buffer (p);
1408 unchain_marker (XMARKER (p->pointm));
1409 unchain_marker (XMARKER (p->start));
1412 /* Free window glyph matrices. It is sure that they are allocated
1413 again when ADJUST_GLYPHS is called. Block input so that expose
1414 events and other events that access glyph matrices are not
1415 processed while we are changing them. */
1416 BLOCK_INPUT;
1417 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1419 tem = p->next;
1420 if (!NILP (tem))
1421 XWINDOW (tem)->prev = p->prev;
1423 tem = p->prev;
1424 if (!NILP (tem))
1425 XWINDOW (tem)->next = p->next;
1427 if (EQ (window, par->hchild))
1428 par->hchild = p->next;
1429 if (EQ (window, par->vchild))
1430 par->vchild = p->next;
1432 /* Find one of our siblings to give our space to. */
1433 sib = p->prev;
1434 if (NILP (sib))
1436 /* If p gives its space to its next sibling, that sibling needs
1437 to have its top/left side pulled back to where p's is.
1438 set_window_{height,width} will re-position the sibling's
1439 children. */
1440 sib = p->next;
1441 XWINDOW (sib)->top_line = p->top_line;
1442 XWINDOW (sib)->left_col = p->left_col;
1445 /* Stretch that sibling. */
1446 if (!NILP (par->vchild))
1447 set_window_height (sib,
1448 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1450 if (!NILP (par->hchild))
1451 set_window_width (sib,
1452 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1455 /* If parent now has only one child,
1456 put the child into the parent's place. */
1457 tem = par->hchild;
1458 if (NILP (tem))
1459 tem = par->vchild;
1460 if (NILP (XWINDOW (tem)->next))
1461 replace_window (parent, tem);
1463 /* Since we may be deleting combination windows, we must make sure that
1464 not only p but all its children have been marked as deleted. */
1465 if (! NILP (p->hchild))
1466 delete_all_subwindows (XWINDOW (p->hchild));
1467 else if (! NILP (p->vchild))
1468 delete_all_subwindows (XWINDOW (p->vchild));
1470 /* Mark this window as deleted. */
1471 p->buffer = p->hchild = p->vchild = Qnil;
1473 /* Adjust glyph matrices. */
1474 adjust_glyphs (f);
1475 UNBLOCK_INPUT;
1480 /***********************************************************************
1481 Window List
1482 ***********************************************************************/
1484 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1485 pointer. This is a callback function for foreach_window, used in
1486 function window_list. */
1488 static int
1489 add_window_to_list (w, user_data)
1490 struct window *w;
1491 void *user_data;
1493 Lisp_Object *list = (Lisp_Object *) user_data;
1494 Lisp_Object window;
1495 XSETWINDOW (window, w);
1496 *list = Fcons (window, *list);
1497 return 1;
1501 /* Return a list of all windows, for use by next_window. If
1502 Vwindow_list is a list, return that list. Otherwise, build a new
1503 list, cache it in Vwindow_list, and return that. */
1505 static Lisp_Object
1506 window_list ()
1508 if (!CONSP (Vwindow_list))
1510 Lisp_Object tail;
1512 Vwindow_list = Qnil;
1513 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1515 Lisp_Object args[2];
1517 /* We are visiting windows in canonical order, and add
1518 new windows at the front of args[1], which means we
1519 have to reverse this list at the end. */
1520 args[1] = Qnil;
1521 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1522 args[0] = Vwindow_list;
1523 args[1] = Fnreverse (args[1]);
1524 Vwindow_list = Fnconc (2, args);
1528 return Vwindow_list;
1532 /* Value is non-zero if WINDOW satisfies the constraints given by
1533 OWINDOW, MINIBUF and ALL_FRAMES.
1535 MINIBUF t means WINDOW may be minibuffer windows.
1536 `lambda' means WINDOW may not be a minibuffer window.
1537 a window means a specific minibuffer window
1539 ALL_FRAMES t means search all frames,
1540 nil means search just current frame,
1541 `visible' means search just visible frames,
1542 0 means search visible and iconified frames,
1543 a window means search the frame that window belongs to,
1544 a frame means consider windows on that frame, only. */
1546 static int
1547 candidate_window_p (window, owindow, minibuf, all_frames)
1548 Lisp_Object window, owindow, minibuf, all_frames;
1550 struct window *w = XWINDOW (window);
1551 struct frame *f = XFRAME (w->frame);
1552 int candidate_p = 1;
1554 if (!BUFFERP (w->buffer))
1555 candidate_p = 0;
1556 else if (MINI_WINDOW_P (w)
1557 && (EQ (minibuf, Qlambda)
1558 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1560 /* If MINIBUF is `lambda' don't consider any mini-windows.
1561 If it is a window, consider only that one. */
1562 candidate_p = 0;
1564 else if (EQ (all_frames, Qt))
1565 candidate_p = 1;
1566 else if (NILP (all_frames))
1568 xassert (WINDOWP (owindow));
1569 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1571 else if (EQ (all_frames, Qvisible))
1573 FRAME_SAMPLE_VISIBILITY (f);
1574 candidate_p = FRAME_VISIBLE_P (f);
1576 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1578 FRAME_SAMPLE_VISIBILITY (f);
1579 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1581 else if (WINDOWP (all_frames))
1582 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1583 || EQ (XWINDOW (all_frames)->frame, w->frame)
1584 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1585 else if (FRAMEP (all_frames))
1586 candidate_p = EQ (all_frames, w->frame);
1588 return candidate_p;
1592 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1593 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1594 ALL_FRAMES. */
1596 static void
1597 decode_next_window_args (window, minibuf, all_frames)
1598 Lisp_Object *window, *minibuf, *all_frames;
1600 if (NILP (*window))
1601 *window = selected_window;
1602 else
1603 CHECK_LIVE_WINDOW (*window);
1605 /* MINIBUF nil may or may not include minibuffers. Decide if it
1606 does. */
1607 if (NILP (*minibuf))
1608 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1609 else if (!EQ (*minibuf, Qt))
1610 *minibuf = Qlambda;
1612 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1613 => count none of them, or a specific minibuffer window (the
1614 active one) to count. */
1616 /* ALL_FRAMES nil doesn't specify which frames to include. */
1617 if (NILP (*all_frames))
1618 *all_frames = (!EQ (*minibuf, Qlambda)
1619 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1620 : Qnil);
1621 else if (EQ (*all_frames, Qvisible))
1623 else if (EQ (*all_frames, make_number (0)))
1625 else if (FRAMEP (*all_frames))
1627 else if (!EQ (*all_frames, Qt))
1628 *all_frames = Qnil;
1630 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1631 search just current frame, `visible' meaning search just visible
1632 frames, 0 meaning search visible and iconified frames, or a
1633 window, meaning search the frame that window belongs to, or a
1634 frame, meaning consider windows on that frame, only. */
1638 /* Return the next or previous window of WINDOW in canonical ordering
1639 of windows. NEXT_P non-zero means return the next window. See the
1640 documentation string of next-window for the meaning of MINIBUF and
1641 ALL_FRAMES. */
1643 static Lisp_Object
1644 next_window (window, minibuf, all_frames, next_p)
1645 Lisp_Object window, minibuf, all_frames;
1646 int next_p;
1648 decode_next_window_args (&window, &minibuf, &all_frames);
1650 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1651 return the first window on the frame. */
1652 if (FRAMEP (all_frames)
1653 && !EQ (all_frames, XWINDOW (window)->frame))
1654 return Fframe_first_window (all_frames);
1656 if (next_p)
1658 Lisp_Object list;
1660 /* Find WINDOW in the list of all windows. */
1661 list = Fmemq (window, window_list ());
1663 /* Scan forward from WINDOW to the end of the window list. */
1664 if (CONSP (list))
1665 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1666 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1667 break;
1669 /* Scan from the start of the window list up to WINDOW. */
1670 if (!CONSP (list))
1671 for (list = Vwindow_list;
1672 CONSP (list) && !EQ (XCAR (list), window);
1673 list = XCDR (list))
1674 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1675 break;
1677 if (CONSP (list))
1678 window = XCAR (list);
1680 else
1682 Lisp_Object candidate, list;
1684 /* Scan through the list of windows for candidates. If there are
1685 candidate windows in front of WINDOW, the last one of these
1686 is the one we want. If there are candidates following WINDOW
1687 in the list, again the last one of these is the one we want. */
1688 candidate = Qnil;
1689 for (list = window_list (); CONSP (list); list = XCDR (list))
1691 if (EQ (XCAR (list), window))
1693 if (WINDOWP (candidate))
1694 break;
1696 else if (candidate_window_p (XCAR (list), window, minibuf,
1697 all_frames))
1698 candidate = XCAR (list);
1701 if (WINDOWP (candidate))
1702 window = candidate;
1705 return window;
1709 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1710 doc: /* Return next window after WINDOW in canonical ordering of windows.
1711 If omitted, WINDOW defaults to the selected window.
1713 Optional second arg MINIBUF t means count the minibuffer window even
1714 if not active. MINIBUF nil or omitted means count the minibuffer iff
1715 it is active. MINIBUF neither t nor nil means not to count the
1716 minibuffer even if it is active.
1718 Several frames may share a single minibuffer; if the minibuffer
1719 counts, all windows on all frames that share that minibuffer count
1720 too. Therefore, `next-window' can be used to iterate through the
1721 set of windows even when the minibuffer is on another frame. If the
1722 minibuffer does not count, only windows from WINDOW's frame count.
1724 Optional third arg ALL-FRAMES t means include windows on all frames.
1725 ALL-FRAMES nil or omitted means cycle within the frames as specified
1726 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1727 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1728 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1729 Anything else means restrict to WINDOW's frame.
1731 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1732 `next-window' to iterate through the entire cycle of acceptable
1733 windows, eventually ending up back at the window you started with.
1734 `previous-window' traverses the same cycle, in the reverse order. */)
1735 (window, minibuf, all_frames)
1736 Lisp_Object window, minibuf, all_frames;
1738 return next_window (window, minibuf, all_frames, 1);
1742 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1743 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1744 If omitted, WINDOW defaults to the selected window.
1746 Optional second arg MINIBUF t means count the minibuffer window even
1747 if not active. MINIBUF nil or omitted means count the minibuffer iff
1748 it is active. MINIBUF neither t nor nil means not to count the
1749 minibuffer even if it is active.
1751 Several frames may share a single minibuffer; if the minibuffer
1752 counts, all windows on all frames that share that minibuffer count
1753 too. Therefore, `previous-window' can be used to iterate through
1754 the set of windows even when the minibuffer is on another frame. If
1755 the minibuffer does not count, only windows from WINDOW's frame count
1757 Optional third arg ALL-FRAMES t means include windows on all frames.
1758 ALL-FRAMES nil or omitted means cycle within the frames as specified
1759 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1760 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1761 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1762 Anything else means restrict to WINDOW's frame.
1764 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1765 `previous-window' to iterate through the entire cycle of acceptable
1766 windows, eventually ending up back at the window you started with.
1767 `next-window' traverses the same cycle, in the reverse order. */)
1768 (window, minibuf, all_frames)
1769 Lisp_Object window, minibuf, all_frames;
1771 return next_window (window, minibuf, all_frames, 0);
1775 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1776 doc: /* Select the ARG'th different window on this frame.
1777 All windows on current frame are arranged in a cyclic order.
1778 This command selects the window ARG steps away in that order.
1779 A negative ARG moves in the opposite order. The optional second
1780 argument ALL_FRAMES has the same meaning as in `next-window', which see. */)
1781 (arg, all_frames)
1782 Lisp_Object arg, all_frames;
1784 Lisp_Object window;
1785 int i;
1787 CHECK_NUMBER (arg);
1788 window = selected_window;
1790 for (i = XINT (arg); i > 0; --i)
1791 window = Fnext_window (window, Qnil, all_frames);
1792 for (; i < 0; ++i)
1793 window = Fprevious_window (window, Qnil, all_frames);
1795 Fselect_window (window, Qnil);
1796 return Qnil;
1800 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
1801 doc: /* Return a list of windows on FRAME, starting with WINDOW.
1802 FRAME nil or omitted means use the selected frame.
1803 WINDOW nil or omitted means use the selected window.
1804 MINIBUF t means include the minibuffer window, even if it isn't active.
1805 MINIBUF nil or omitted means include the minibuffer window only
1806 if it's active.
1807 MINIBUF neither nil nor t means never include the minibuffer window. */)
1808 (frame, minibuf, window)
1809 Lisp_Object frame, minibuf, window;
1811 if (NILP (window))
1812 window = selected_window;
1813 if (NILP (frame))
1814 frame = selected_frame;
1816 if (!EQ (frame, XWINDOW (window)->frame))
1817 error ("Window is on a different frame");
1819 return window_list_1 (window, minibuf, frame);
1823 /* Return a list of windows in canonical ordering. Arguments are like
1824 for `next-window'. */
1826 static Lisp_Object
1827 window_list_1 (window, minibuf, all_frames)
1828 Lisp_Object window, minibuf, all_frames;
1830 Lisp_Object tail, list, rest;
1832 decode_next_window_args (&window, &minibuf, &all_frames);
1833 list = Qnil;
1835 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
1836 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
1837 list = Fcons (XCAR (tail), list);
1839 /* Rotate the list to start with WINDOW. */
1840 list = Fnreverse (list);
1841 rest = Fmemq (window, list);
1842 if (!NILP (rest) && !EQ (rest, list))
1844 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
1846 XSETCDR (tail, Qnil);
1847 list = nconc2 (rest, list);
1849 return list;
1854 /* Look at all windows, performing an operation specified by TYPE
1855 with argument OBJ.
1856 If FRAMES is Qt, look at all frames;
1857 Qnil, look at just the selected frame;
1858 Qvisible, look at visible frames;
1859 a frame, just look at windows on that frame.
1860 If MINI is non-zero, perform the operation on minibuffer windows too. */
1862 enum window_loop
1864 WINDOW_LOOP_UNUSED,
1865 GET_BUFFER_WINDOW, /* Arg is buffer */
1866 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1867 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1868 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1869 GET_LARGEST_WINDOW,
1870 UNSHOW_BUFFER, /* Arg is buffer */
1871 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
1872 CHECK_ALL_WINDOWS
1875 static Lisp_Object
1876 window_loop (type, obj, mini, frames)
1877 enum window_loop type;
1878 Lisp_Object obj, frames;
1879 int mini;
1881 Lisp_Object window, windows, best_window, frame_arg;
1882 struct frame *f;
1883 struct gcpro gcpro1;
1885 /* If we're only looping through windows on a particular frame,
1886 frame points to that frame. If we're looping through windows
1887 on all frames, frame is 0. */
1888 if (FRAMEP (frames))
1889 f = XFRAME (frames);
1890 else if (NILP (frames))
1891 f = SELECTED_FRAME ();
1892 else
1893 f = NULL;
1895 if (f)
1896 frame_arg = Qlambda;
1897 else if (EQ (frames, make_number (0)))
1898 frame_arg = frames;
1899 else if (EQ (frames, Qvisible))
1900 frame_arg = frames;
1901 else
1902 frame_arg = Qt;
1904 /* frame_arg is Qlambda to stick to one frame,
1905 Qvisible to consider all visible frames,
1906 or Qt otherwise. */
1908 /* Pick a window to start with. */
1909 if (WINDOWP (obj))
1910 window = obj;
1911 else if (f)
1912 window = FRAME_SELECTED_WINDOW (f);
1913 else
1914 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1916 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
1917 GCPRO1 (windows);
1918 best_window = Qnil;
1920 for (; CONSP (windows); windows = CDR (windows))
1922 struct window *w;
1924 window = XCAR (windows);
1925 w = XWINDOW (window);
1927 /* Note that we do not pay attention here to whether the frame
1928 is visible, since Fwindow_list skips non-visible frames if
1929 that is desired, under the control of frame_arg. */
1930 if (!MINI_WINDOW_P (w)
1931 /* For UNSHOW_BUFFER, we must always consider all windows. */
1932 || type == UNSHOW_BUFFER
1933 || (mini && minibuf_level > 0))
1934 switch (type)
1936 case GET_BUFFER_WINDOW:
1937 if (EQ (w->buffer, obj)
1938 /* Don't find any minibuffer window
1939 except the one that is currently in use. */
1940 && (MINI_WINDOW_P (w)
1941 ? EQ (window, minibuf_window)
1942 : 1))
1944 if (NILP (best_window))
1945 best_window = window;
1946 else if (EQ (window, selected_window))
1947 /* For compatibility with 20.x, prefer to return
1948 selected-window. */
1949 best_window = window;
1951 break;
1953 case GET_LRU_WINDOW:
1954 /* t as arg means consider only full-width windows */
1955 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w))
1956 break;
1957 /* Ignore dedicated windows and minibuffers. */
1958 if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
1959 break;
1960 if (NILP (best_window)
1961 || (XFASTINT (XWINDOW (best_window)->use_time)
1962 > XFASTINT (w->use_time)))
1963 best_window = window;
1964 break;
1966 case DELETE_OTHER_WINDOWS:
1967 if (!EQ (window, obj))
1968 Fdelete_window (window);
1969 break;
1971 case DELETE_BUFFER_WINDOWS:
1972 if (EQ (w->buffer, obj))
1974 struct frame *f = XFRAME (WINDOW_FRAME (w));
1976 /* If this window is dedicated, and in a frame of its own,
1977 kill the frame. */
1978 if (EQ (window, FRAME_ROOT_WINDOW (f))
1979 && !NILP (w->dedicated)
1980 && other_visible_frames (f))
1982 /* Skip the other windows on this frame.
1983 There might be one, the minibuffer! */
1984 while (CONSP (XCDR (windows))
1985 && EQ (XWINDOW (XCAR (windows))->frame,
1986 XWINDOW (XCAR (XCDR (windows)))->frame))
1987 windows = XCDR (windows);
1989 /* Now we can safely delete the frame. */
1990 Fdelete_frame (w->frame, Qnil);
1992 else if (NILP (w->parent))
1994 /* If we're deleting the buffer displayed in the
1995 only window on the frame, find a new buffer to
1996 display there. */
1997 Lisp_Object buffer;
1998 buffer = Fother_buffer (obj, Qnil, w->frame);
1999 Fset_window_buffer (window, buffer, Qnil);
2000 if (EQ (window, selected_window))
2001 Fset_buffer (w->buffer);
2003 else
2004 Fdelete_window (window);
2006 break;
2008 case GET_LARGEST_WINDOW:
2010 /* Ignore dedicated windows and minibuffers. */
2011 if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
2012 break;
2014 if (NILP (best_window))
2015 best_window = window;
2016 else
2018 struct window *b = XWINDOW (best_window);
2019 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2020 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2021 best_window = window;
2024 break;
2026 case UNSHOW_BUFFER:
2027 if (EQ (w->buffer, obj))
2029 Lisp_Object buffer;
2030 struct frame *f = XFRAME (w->frame);
2032 /* Find another buffer to show in this window. */
2033 buffer = Fother_buffer (obj, Qnil, w->frame);
2035 /* If this window is dedicated, and in a frame of its own,
2036 kill the frame. */
2037 if (EQ (window, FRAME_ROOT_WINDOW (f))
2038 && !NILP (w->dedicated)
2039 && other_visible_frames (f))
2041 /* Skip the other windows on this frame.
2042 There might be one, the minibuffer! */
2043 while (CONSP (XCDR (windows))
2044 && EQ (XWINDOW (XCAR (windows))->frame,
2045 XWINDOW (XCAR (XCDR (windows)))->frame))
2046 windows = XCDR (windows);
2048 /* Now we can safely delete the frame. */
2049 Fdelete_frame (w->frame, Qnil);
2051 else if (!NILP (w->dedicated) && !NILP (w->parent))
2053 Lisp_Object window;
2054 XSETWINDOW (window, w);
2055 /* If this window is dedicated and not the only window
2056 in its frame, then kill it. */
2057 Fdelete_window (window);
2059 else
2061 /* Otherwise show a different buffer in the window. */
2062 w->dedicated = Qnil;
2063 Fset_window_buffer (window, buffer, Qnil);
2064 if (EQ (window, selected_window))
2065 Fset_buffer (w->buffer);
2068 break;
2070 case REDISPLAY_BUFFER_WINDOWS:
2071 if (EQ (w->buffer, obj))
2073 mark_window_display_accurate (window, 0);
2074 w->update_mode_line = Qt;
2075 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2076 ++update_mode_lines;
2077 best_window = window;
2079 break;
2081 /* Check for a window that has a killed buffer. */
2082 case CHECK_ALL_WINDOWS:
2083 if (! NILP (w->buffer)
2084 && NILP (XBUFFER (w->buffer)->name))
2085 abort ();
2086 break;
2088 case WINDOW_LOOP_UNUSED:
2089 break;
2093 UNGCPRO;
2094 return best_window;
2097 /* Used for debugging. Abort if any window has a dead buffer. */
2099 void
2100 check_all_windows ()
2102 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2105 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
2106 doc: /* Return the window least recently selected or used for display.
2107 Return a full-width window if possible.
2108 A minibuffer window is never a candidate.
2109 A dedicated window is never a candidate, so if all windows are dedicated,
2110 the value is nil.
2111 If optional argument FRAME is `visible', search all visible frames.
2112 If FRAME is 0, search all visible and iconified frames.
2113 If FRAME is t, search all frames.
2114 If FRAME is nil, search only the selected frame.
2115 If FRAME is a frame, search only that frame. */)
2116 (frame)
2117 Lisp_Object frame;
2119 register Lisp_Object w;
2120 /* First try for a window that is full-width */
2121 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
2122 if (!NILP (w) && !EQ (w, selected_window))
2123 return w;
2124 /* If none of them, try the rest */
2125 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
2128 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
2129 doc: /* Return the largest window in area.
2130 A minibuffer window is never a candidate.
2131 A dedicated window is never a candidate, so if all windows are dedicated,
2132 the value is nil.
2133 If optional argument FRAME is `visible', search all visible frames.
2134 If FRAME is 0, search all visible and iconified frames.
2135 If FRAME is t, search all frames.
2136 If FRAME is nil, search only the selected frame.
2137 If FRAME is a frame, search only that frame. */)
2138 (frame)
2139 Lisp_Object frame;
2141 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
2142 frame);
2145 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2146 doc: /* Return a window currently displaying BUFFER, or nil if none.
2147 BUFFER can be a buffer or a buffer name.
2148 If optional argument FRAME is `visible', search all visible frames.
2149 If optional argument FRAME is 0, search all visible and iconified frames.
2150 If FRAME is t, search all frames.
2151 If FRAME is nil, search only the selected frame.
2152 If FRAME is a frame, search only that frame. */)
2153 (buffer, frame)
2154 Lisp_Object buffer, frame;
2156 buffer = Fget_buffer (buffer);
2157 if (BUFFERP (buffer))
2158 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2159 else
2160 return Qnil;
2163 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2164 0, 1, "",
2165 doc: /* Make WINDOW (or the selected window) fill its frame.
2166 Only the frame WINDOW is on is affected.
2167 This function tries to reduce display jumps
2168 by keeping the text previously visible in WINDOW
2169 in the same place on the frame. Doing this depends on
2170 the value of (window-start WINDOW), so if calling this function
2171 in a program gives strange scrolling, make sure the window-start
2172 value is reasonable when this function is called. */)
2173 (window)
2174 Lisp_Object window;
2176 struct window *w;
2177 int startpos;
2178 int top, new_top;
2180 if (NILP (window))
2181 window = selected_window;
2182 else
2183 CHECK_LIVE_WINDOW (window);
2184 w = XWINDOW (window);
2186 startpos = marker_position (w->start);
2187 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2189 if (MINI_WINDOW_P (w) && top > 0)
2190 error ("Can't expand minibuffer to full frame");
2192 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2194 /* Try to minimize scrolling, by setting the window start to the point
2195 will cause the text at the old window start to be at the same place
2196 on the frame. But don't try to do this if the window start is
2197 outside the visible portion (as might happen when the display is
2198 not current, due to typeahead). */
2199 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2200 if (new_top != top
2201 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2202 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2204 struct position pos;
2205 struct buffer *obuf = current_buffer;
2207 Fset_buffer (w->buffer);
2208 /* This computation used to temporarily move point, but that can
2209 have unwanted side effects due to text properties. */
2210 pos = *vmotion (startpos, -top, w);
2212 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2213 w->window_end_valid = Qnil;
2214 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2215 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2216 : Qnil);
2217 /* We need to do this, so that the window-scroll-functions
2218 get called. */
2219 w->optional_new_start = Qt;
2221 set_buffer_internal (obuf);
2224 return Qnil;
2227 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2228 1, 2, "bDelete windows on (buffer): ",
2229 doc: /* Delete all windows showing BUFFER.
2230 BUFFER must be a buffer or the name of an existing buffer.
2231 Optional second argument FRAME controls which frames are affected.
2232 If optional argument FRAME is `visible', search all visible frames.
2233 If FRAME is 0, search all visible and iconified frames.
2234 If FRAME is nil, search all frames.
2235 If FRAME is t, search only the selected frame.
2236 If FRAME is a frame, search only that frame. */)
2237 (buffer, frame)
2238 Lisp_Object buffer, frame;
2240 /* FRAME uses t and nil to mean the opposite of what window_loop
2241 expects. */
2242 if (NILP (frame))
2243 frame = Qt;
2244 else if (EQ (frame, Qt))
2245 frame = Qnil;
2247 if (!NILP (buffer))
2249 buffer = Fget_buffer (buffer);
2250 CHECK_BUFFER (buffer);
2251 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2254 return Qnil;
2257 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2258 Sreplace_buffer_in_windows,
2259 1, 1, "bReplace buffer in windows: ",
2260 doc: /* Replace BUFFER with some other buffer in all windows showing it.
2261 BUFFER may be a buffer or the name of an existing buffer. */)
2262 (buffer)
2263 Lisp_Object buffer;
2265 if (!NILP (buffer))
2267 buffer = Fget_buffer (buffer);
2268 CHECK_BUFFER (buffer);
2269 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2271 return Qnil;
2274 /* Replace BUFFER with some other buffer in all windows
2275 of all frames, even those on other keyboards. */
2277 void
2278 replace_buffer_in_all_windows (buffer)
2279 Lisp_Object buffer;
2281 #ifdef MULTI_KBOARD
2282 Lisp_Object tail, frame;
2284 /* A single call to window_loop won't do the job
2285 because it only considers frames on the current keyboard.
2286 So loop manually over frames, and handle each one. */
2287 FOR_EACH_FRAME (tail, frame)
2288 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2289 #else
2290 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2291 #endif
2294 /* Set the height of WINDOW and all its inferiors. */
2296 /* The smallest acceptable dimensions for a window. Anything smaller
2297 might crash Emacs. */
2299 #define MIN_SAFE_WINDOW_WIDTH (2)
2300 #define MIN_SAFE_WINDOW_HEIGHT (1)
2302 /* Make sure that window_min_height and window_min_width are
2303 not too small; if they are, set them to safe minima. */
2305 static void
2306 check_min_window_sizes ()
2308 /* Smaller values might permit a crash. */
2309 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2310 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2311 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2312 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2315 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2316 minimum allowable size. */
2318 void
2319 check_frame_size (frame, rows, cols)
2320 FRAME_PTR frame;
2321 int *rows, *cols;
2323 /* For height, we have to see:
2324 how many windows the frame has at minimum (one or two),
2325 and whether it has a menu bar or other special stuff at the top. */
2326 int min_height
2327 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2328 ? MIN_SAFE_WINDOW_HEIGHT
2329 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2331 if (FRAME_TOP_MARGIN (frame) > 0)
2332 min_height += FRAME_TOP_MARGIN (frame);
2334 if (*rows < min_height)
2335 *rows = min_height;
2336 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2337 *cols = MIN_SAFE_WINDOW_WIDTH;
2341 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2342 check if W's width can be changed, otherwise check W's height.
2343 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2344 siblings, too. If none of the siblings is resizable, WINDOW isn't
2345 either. */
2347 static int
2348 window_fixed_size_p (w, width_p, check_siblings_p)
2349 struct window *w;
2350 int width_p, check_siblings_p;
2352 int fixed_p;
2353 struct window *c;
2355 if (!NILP (w->hchild))
2357 c = XWINDOW (w->hchild);
2359 if (width_p)
2361 /* A horiz. combination is fixed-width if all of if its
2362 children are. */
2363 while (c && window_fixed_size_p (c, width_p, 0))
2364 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2365 fixed_p = c == NULL;
2367 else
2369 /* A horiz. combination is fixed-height if one of if its
2370 children is. */
2371 while (c && !window_fixed_size_p (c, width_p, 0))
2372 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2373 fixed_p = c != NULL;
2376 else if (!NILP (w->vchild))
2378 c = XWINDOW (w->vchild);
2380 if (width_p)
2382 /* A vert. combination is fixed-width if one of if its
2383 children is. */
2384 while (c && !window_fixed_size_p (c, width_p, 0))
2385 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2386 fixed_p = c != NULL;
2388 else
2390 /* A vert. combination is fixed-height if all of if its
2391 children are. */
2392 while (c && window_fixed_size_p (c, width_p, 0))
2393 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2394 fixed_p = c == NULL;
2397 else if (BUFFERP (w->buffer))
2399 if (w->height_fixed_p && !width_p)
2400 fixed_p = 1;
2401 else
2403 struct buffer *old = current_buffer;
2404 Lisp_Object val;
2406 current_buffer = XBUFFER (w->buffer);
2407 val = find_symbol_value (Qwindow_size_fixed);
2408 current_buffer = old;
2410 fixed_p = 0;
2411 if (!EQ (val, Qunbound))
2413 fixed_p = !NILP (val);
2415 if (fixed_p
2416 && ((EQ (val, Qheight) && width_p)
2417 || (EQ (val, Qwidth) && !width_p)))
2418 fixed_p = 0;
2422 /* Can't tell if this one is resizable without looking at
2423 siblings. If all siblings are fixed-size this one is too. */
2424 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2426 Lisp_Object child;
2428 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2429 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2430 break;
2432 if (NILP (child))
2433 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2434 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2435 break;
2437 if (NILP (child))
2438 fixed_p = 1;
2441 else
2442 fixed_p = 1;
2444 return fixed_p;
2448 /* Return the minimum size of window W, not taking fixed-width windows
2449 into account. WIDTH_P non-zero means return the minimum width,
2450 otherwise return the minimum height. If W is a combination window,
2451 compute the minimum size from the minimum sizes of W's children. */
2453 static int
2454 window_min_size_1 (w, width_p)
2455 struct window *w;
2456 int width_p;
2458 struct window *c;
2459 int size;
2461 if (!NILP (w->hchild))
2463 c = XWINDOW (w->hchild);
2464 size = 0;
2466 if (width_p)
2468 /* The min width of a horizontal combination is
2469 the sum of the min widths of its children. */
2470 while (c)
2472 size += window_min_size_1 (c, width_p);
2473 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2476 else
2478 /* The min height a horizontal combination equals
2479 the maximum of all min height of its children. */
2480 while (c)
2482 int min_size = window_min_size_1 (c, width_p);
2483 size = max (min_size, size);
2484 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2488 else if (!NILP (w->vchild))
2490 c = XWINDOW (w->vchild);
2491 size = 0;
2493 if (width_p)
2495 /* The min width of a vertical combination is
2496 the maximum of the min widths of its children. */
2497 while (c)
2499 int min_size = window_min_size_1 (c, width_p);
2500 size = max (min_size, size);
2501 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2504 else
2506 /* The min height of a vertical combination equals
2507 the sum of the min height of its children. */
2508 while (c)
2510 size += window_min_size_1 (c, width_p);
2511 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2515 else
2517 if (width_p)
2518 size = window_min_width;
2519 else
2521 if (MINI_WINDOW_P (w)
2522 || (!WINDOW_WANTS_MODELINE_P (w)
2523 && !WINDOW_WANTS_HEADER_LINE_P (w)))
2524 size = 1;
2525 else
2526 size = window_min_height;
2530 return size;
2534 /* Return the minimum size of window W, taking fixed-size windows into
2535 account. WIDTH_P non-zero means return the minimum width,
2536 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2537 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2538 unless FIXED is null. */
2540 static int
2541 window_min_size (w, width_p, ignore_fixed_p, fixed)
2542 struct window *w;
2543 int width_p, ignore_fixed_p, *fixed;
2545 int size, fixed_p;
2547 if (ignore_fixed_p)
2548 fixed_p = 0;
2549 else
2550 fixed_p = window_fixed_size_p (w, width_p, 1);
2552 if (fixed)
2553 *fixed = fixed_p;
2555 if (fixed_p)
2556 size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines);
2557 else
2558 size = window_min_size_1 (w, width_p);
2560 return size;
2564 /* Adjust the margins of window W if text area is too small.
2565 Return 1 if window width is ok after adjustment; 0 if window
2566 is still too narrow. */
2568 static int
2569 adjust_window_margins (w)
2570 struct window *w;
2572 int box_cols = (WINDOW_TOTAL_COLS (w)
2573 - WINDOW_FRINGE_COLS (w)
2574 - WINDOW_SCROLL_BAR_COLS (w));
2575 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2576 + WINDOW_RIGHT_MARGIN_COLS (w));
2578 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2579 return 1;
2581 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2582 return 0;
2584 /* Window's text area is too narrow, but reducing the window
2585 margins will fix that. */
2586 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2587 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2589 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2590 w->left_margin_cols = w->right_margin_cols
2591 = make_number (margin_cols/2);
2592 else
2593 w->right_margin_cols = make_number (margin_cols);
2595 else
2596 w->left_margin_cols = make_number (margin_cols);
2597 return 1;
2600 /* Calculate new sizes for windows in the list FORWARD when the window size
2601 goes from TOTAL to SIZE. TOTAL must be greater than SIZE.
2602 The number of windows in FORWARD is NCHILDREN, and the number that
2603 can shrink is SHRINKABLE.
2604 The minimum size a window can have is MIN_SIZE.
2605 If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
2606 If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
2607 shrinking rows.
2609 This function returns an allocated array of new sizes that the caller
2610 must free. The size -1 means the window is fixed and RESIZE_FIXED_P
2611 is zero. Array index 0 refers to the first window in FORWARD, 1 to
2612 the second, and so on.
2614 This function tries to keep windows at least at the minimum size
2615 and resize other windows before it resizes any window to zero (i.e.
2616 delete that window).
2618 Windows are resized proportional to their size, so bigger windows
2619 shrink more than smaller windows. */
2620 static int *
2621 shrink_windows (total, size, nchildren, shrinkable,
2622 min_size, resize_fixed_p, forward, width_p)
2623 int total, size, nchildren, shrinkable, min_size;
2624 int resize_fixed_p, width_p;
2625 Lisp_Object forward;
2627 int available_resize = 0;
2628 int *new_sizes;
2629 struct window *c;
2630 Lisp_Object child;
2631 int smallest = total;
2632 int total_removed = 0;
2633 int total_shrink = total - size;
2634 int i;
2636 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2638 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2640 int child_size;
2642 c = XWINDOW (child);
2643 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2645 if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2646 new_sizes[i] = -1;
2647 else
2649 new_sizes[i] = child_size;
2650 if (child_size > min_size)
2651 available_resize += child_size - min_size;
2654 /* We might need to shrink some windows to zero. Find the smallest
2655 windows and set them to 0 until we can fulfil the new size. */
2657 while (shrinkable > 1 && size + available_resize < total)
2659 for (i = 0; i < nchildren; ++i)
2660 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2661 smallest = new_sizes[i];
2663 for (i = 0; i < nchildren; ++i)
2664 if (new_sizes[i] == smallest)
2666 /* Resize this window down to zero. */
2667 new_sizes[i] = 0;
2668 if (smallest > min_size)
2669 available_resize -= smallest - min_size;
2670 available_resize += smallest;
2671 --shrinkable;
2672 total_removed += smallest;
2674 /* We don't know what the smallest is now. */
2675 smallest = total;
2677 /* Out of for, just remove one window at the time and
2678 check again if we have enough space. */
2679 break;
2683 /* Now, calculate the new sizes. Try to shrink each window
2684 proportional to its size. */
2685 for (i = 0; i < nchildren; ++i)
2687 if (new_sizes[i] > min_size)
2689 int to_shrink = total_shrink*new_sizes[i]/total;
2690 if (new_sizes[i] - to_shrink < min_size)
2691 to_shrink = new_sizes[i] - min_size;
2692 new_sizes[i] -= to_shrink;
2693 total_removed += to_shrink;
2697 /* Any reminder due to rounding, we just subtract from windows
2698 that are left and still can be shrunk. */
2699 while (total_shrink > total_removed)
2701 int nonzero_sizes = 0;
2702 int nonzero_idx = -1;
2704 for (i = 0; i < nchildren; ++i)
2705 if (new_sizes[i] > 0)
2707 ++nonzero_sizes;
2708 nonzero_idx = i;
2711 for (i = 0; i < nchildren; ++i)
2712 if (new_sizes[i] > min_size)
2714 --new_sizes[i];
2715 ++total_removed;
2717 /* Out of for, just shrink one window at the time and
2718 check again if we have enough space. */
2719 break;
2723 /* Special case, only one window left. */
2724 if (nonzero_sizes == 1)
2725 break;
2728 /* Any surplus due to rounding, we add to windows that are left. */
2729 while (total_shrink < total_removed)
2731 for (i = 0; i < nchildren; ++i)
2733 if (new_sizes[i] != 0 && total_shrink < total_removed)
2735 ++new_sizes[i];
2736 --total_removed;
2737 break;
2742 return new_sizes;
2745 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2746 WINDOW's width. Resize WINDOW's children, if any, so that they
2747 keep their proportionate size relative to WINDOW. Propagate
2748 WINDOW's top or left edge position to children. Delete windows
2749 that become too small unless NODELETE_P is non-zero.
2751 If NODELETE_P is 2, that means we do delete windows that are
2752 too small, even if they were too small before! */
2754 static void
2755 size_window (window, size, width_p, nodelete_p)
2756 Lisp_Object window;
2757 int size, width_p, nodelete_p;
2759 struct window *w = XWINDOW (window);
2760 struct window *c;
2761 Lisp_Object child, *forward, *sideward;
2762 int old_size, min_size, safe_min_size;
2764 /* We test nodelete_p != 2 and nodelete_p != 1 below, so it
2765 seems like it's too soon to do this here. ++KFS. */
2766 if (nodelete_p == 2)
2767 nodelete_p = 0;
2769 check_min_window_sizes ();
2770 size = max (0, size);
2772 /* If the window has been "too small" at one point,
2773 don't delete it for being "too small" in the future.
2774 Preserve it as long as that is at all possible. */
2775 if (width_p)
2777 old_size = WINDOW_TOTAL_COLS (w);
2778 min_size = window_min_width;
2779 /* Ensure that there is room for the scroll bar and fringes!
2780 We may reduce display margins though. */
2781 safe_min_size = (MIN_SAFE_WINDOW_WIDTH
2782 + WINDOW_FRINGE_COLS (w)
2783 + WINDOW_SCROLL_BAR_COLS (w));
2785 else
2787 old_size = XINT (w->total_lines);
2788 min_size = window_min_height;
2789 safe_min_size = MIN_SAFE_WINDOW_HEIGHT;
2792 if (old_size < min_size && nodelete_p != 2)
2793 w->too_small_ok = Qt;
2795 /* Maybe delete WINDOW if it's too small. */
2796 if (nodelete_p != 1 && !NILP (w->parent))
2798 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
2799 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
2800 if (min_size < safe_min_size)
2801 min_size = safe_min_size;
2802 if (size < min_size)
2804 delete_window (window);
2805 return;
2809 /* Set redisplay hints. */
2810 w->last_modified = make_number (0);
2811 w->last_overlay_modified = make_number (0);
2812 windows_or_buffers_changed++;
2813 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
2815 if (width_p)
2817 sideward = &w->vchild;
2818 forward = &w->hchild;
2819 w->total_cols = make_number (size);
2820 adjust_window_margins (w);
2822 else
2824 sideward = &w->hchild;
2825 forward = &w->vchild;
2826 w->total_lines = make_number (size);
2827 w->orig_total_lines = Qnil;
2830 if (!NILP (*sideward))
2832 for (child = *sideward; !NILP (child); child = c->next)
2834 c = XWINDOW (child);
2835 if (width_p)
2836 c->left_col = w->left_col;
2837 else
2838 c->top_line = w->top_line;
2839 size_window (child, size, width_p, nodelete_p);
2842 else if (!NILP (*forward))
2844 int fixed_size, each, extra, n;
2845 int resize_fixed_p, nfixed;
2846 int last_pos, first_pos, nchildren, total;
2847 int *new_sizes = NULL;
2849 /* Determine the fixed-size portion of the this window, and the
2850 number of child windows. */
2851 fixed_size = nchildren = nfixed = total = 0;
2852 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
2854 int child_size;
2856 c = XWINDOW (child);
2857 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2858 total += child_size;
2860 if (window_fixed_size_p (c, width_p, 0))
2862 fixed_size += child_size;
2863 ++nfixed;
2867 /* If the new size is smaller than fixed_size, or if there
2868 aren't any resizable windows, allow resizing fixed-size
2869 windows. */
2870 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2872 /* Compute how many lines/columns to add/remove to each child. The
2873 value of extra takes care of rounding errors. */
2874 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2875 if (size < total && n > 1)
2876 new_sizes = shrink_windows (total, size, nchildren, n, min_size,
2877 resize_fixed_p, *forward, width_p);
2878 else
2880 each = (size - total) / n;
2881 extra = (size - total) - n * each;
2884 /* Compute new children heights and edge positions. */
2885 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
2886 last_pos = first_pos;
2887 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
2889 int new_size, old_size;
2891 c = XWINDOW (child);
2892 old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines);
2893 new_size = old_size;
2895 /* The top or left edge position of this child equals the
2896 bottom or right edge of its predecessor. */
2897 if (width_p)
2898 c->left_col = make_number (last_pos);
2899 else
2900 c->top_line = make_number (last_pos);
2902 /* If this child can be resized, do it. */
2903 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2905 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
2906 extra = 0;
2909 /* Set new height. Note that size_window also propagates
2910 edge positions to children, so it's not a no-op if we
2911 didn't change the child's size. */
2912 size_window (child, new_size, width_p, 1);
2914 /* Remember the bottom/right edge position of this child; it
2915 will be used to set the top/left edge of the next child. */
2916 last_pos += new_size;
2919 if (new_sizes) xfree (new_sizes);
2921 /* We should have covered the parent exactly with child windows. */
2922 xassert (size == last_pos - first_pos);
2924 /* Now delete any children that became too small. */
2925 if (!nodelete_p)
2926 for (child = *forward; !NILP (child); child = c->next)
2928 int child_size;
2929 c = XWINDOW (child);
2930 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2931 size_window (child, child_size, width_p, 2);
2936 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2937 WINDOW's children. NODELETE non-zero means don't delete windows
2938 that become too small in the process. (The caller should check
2939 later and do so if appropriate.) */
2941 void
2942 set_window_height (window, height, nodelete)
2943 Lisp_Object window;
2944 int height;
2945 int nodelete;
2947 size_window (window, height, 0, nodelete);
2951 /* Set WINDOW's width to WIDTH, and recursively change the width of
2952 WINDOW's children. NODELETE non-zero means don't delete windows
2953 that become too small in the process. (The caller should check
2954 later and do so if appropriate.) */
2956 void
2957 set_window_width (window, width, nodelete)
2958 Lisp_Object window;
2959 int width;
2960 int nodelete;
2962 size_window (window, width, 1, nodelete);
2965 /* Change window heights in windows rooted in WINDOW by N lines. */
2967 void
2968 change_window_heights (window, n)
2969 Lisp_Object window;
2970 int n;
2972 struct window *w = XWINDOW (window);
2974 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
2975 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
2977 if (INTEGERP (w->orig_top_line))
2978 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
2979 if (INTEGERP (w->orig_total_lines))
2980 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
2982 /* Handle just the top child in a vertical split. */
2983 if (!NILP (w->vchild))
2984 change_window_heights (w->vchild, n);
2986 /* Adjust all children in a horizontal split. */
2987 for (window = w->hchild; !NILP (window); window = w->next)
2989 w = XWINDOW (window);
2990 change_window_heights (window, n);
2995 int window_select_count;
2997 Lisp_Object
2998 Fset_window_buffer_unwind (obuf)
2999 Lisp_Object obuf;
3001 Fset_buffer (obuf);
3002 return Qnil;
3005 EXFUN (Fset_window_fringes, 4);
3006 EXFUN (Fset_window_scroll_bars, 4);
3008 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3009 means it's allowed to run hooks. See make_frame for a case where
3010 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3011 margins, fringes, and scroll-bar settings of the window are not
3012 reset from the buffer's local settings. */
3014 void
3015 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
3016 Lisp_Object window, buffer;
3017 int run_hooks_p, keep_margins_p;
3019 struct window *w = XWINDOW (window);
3020 struct buffer *b = XBUFFER (buffer);
3021 int count = SPECPDL_INDEX ();
3023 w->buffer = buffer;
3025 if (EQ (window, selected_window))
3026 b->last_selected_window = window;
3028 /* Let redisplay errors through. */
3029 b->display_error_modiff = 0;
3031 /* Update time stamps of buffer display. */
3032 if (INTEGERP (b->display_count))
3033 XSETINT (b->display_count, XINT (b->display_count) + 1);
3034 b->display_time = Fcurrent_time ();
3036 XSETFASTINT (w->window_end_pos, 0);
3037 XSETFASTINT (w->window_end_vpos, 0);
3038 bzero (&w->last_cursor, sizeof w->last_cursor);
3039 w->window_end_valid = Qnil;
3040 w->hscroll = w->min_hscroll = make_number (0);
3041 w->vscroll = 0;
3042 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3043 set_marker_restricted (w->start,
3044 make_number (b->last_window_start),
3045 buffer);
3046 w->start_at_line_beg = Qnil;
3047 w->force_start = Qnil;
3048 XSETFASTINT (w->last_modified, 0);
3049 XSETFASTINT (w->last_overlay_modified, 0);
3050 windows_or_buffers_changed++;
3052 /* We must select BUFFER for running the window-scroll-functions.
3053 If WINDOW is selected, switch permanently.
3054 Otherwise, switch but go back to the ambient buffer afterward. */
3055 if (EQ (window, selected_window))
3056 Fset_buffer (buffer);
3057 /* We can't check ! NILP (Vwindow_scroll_functions) here
3058 because that might itself be a local variable. */
3059 else if (window_initialized)
3061 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
3062 Fset_buffer (buffer);
3065 if (!keep_margins_p)
3067 /* Set left and right marginal area width etc. from buffer. */
3069 /* This may call adjust_window_margins three times, so
3070 temporarily disable window margins. */
3071 Lisp_Object save_left = w->left_margin_cols;
3072 Lisp_Object save_right = w->right_margin_cols;
3074 w->left_margin_cols = w->right_margin_cols = Qnil;
3076 Fset_window_fringes (window,
3077 b->left_fringe_width, b->right_fringe_width,
3078 b->fringes_outside_margins);
3080 Fset_window_scroll_bars (window,
3081 b->scroll_bar_width,
3082 b->vertical_scroll_bar_type, Qnil);
3084 w->left_margin_cols = save_left;
3085 w->right_margin_cols = save_right;
3087 Fset_window_margins (window,
3088 b->left_margin_cols, b->right_margin_cols);
3091 if (run_hooks_p)
3093 if (! NILP (Vwindow_scroll_functions))
3094 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3095 Fmarker_position (w->start));
3097 if (! NILP (Vwindow_configuration_change_hook)
3098 && ! NILP (Vrun_hooks))
3099 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3102 unbind_to (count, Qnil);
3106 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3107 doc: /* Make WINDOW display BUFFER as its contents.
3108 BUFFER can be a buffer or the name of an existing buffer.
3109 Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
3110 display margins, fringe widths, and scroll bar settings are maintained;
3111 the default is to reset these from BUFFER's local settings or the frame
3112 defaults.
3114 This function runs the hook `window-scroll-functions'. */)
3115 (window, buffer, keep_margins)
3116 register Lisp_Object window, buffer, keep_margins;
3118 register Lisp_Object tem;
3119 register struct window *w = decode_window (window);
3121 XSETWINDOW (window, w);
3122 buffer = Fget_buffer (buffer);
3123 CHECK_BUFFER (buffer);
3125 if (NILP (XBUFFER (buffer)->name))
3126 error ("Attempt to display deleted buffer");
3128 tem = w->buffer;
3129 if (NILP (tem))
3130 error ("Window is deleted");
3131 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3132 is first being set up. */
3134 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3135 error ("Window is dedicated to `%s'",
3136 SDATA (XBUFFER (tem)->name));
3138 unshow_buffer (w);
3141 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3142 return Qnil;
3145 /* Note that selected_window can be nil
3146 when this is called from Fset_window_configuration. */
3148 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3149 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3150 If WINDOW is not already selected, make WINDOW's buffer current
3151 and make WINDOW the frame's selected window. Return WINDOW.
3152 Optional second arg NORECORD non-nil means
3153 do not put this buffer at the front of the list of recently selected ones.
3155 Note that the main editor command loop
3156 selects the buffer of the selected window before each command. */)
3157 (window, norecord)
3158 register Lisp_Object window, norecord;
3160 register struct window *w;
3161 register struct window *ow;
3162 struct frame *sf;
3164 CHECK_LIVE_WINDOW (window);
3166 w = XWINDOW (window);
3167 w->frozen_window_start_p = 0;
3169 ++window_select_count;
3170 XSETFASTINT (w->use_time, window_select_count);
3171 if (EQ (window, selected_window))
3172 return window;
3174 if (!NILP (selected_window))
3176 ow = XWINDOW (selected_window);
3177 if (! NILP (ow->buffer))
3178 set_marker_both (ow->pointm, ow->buffer,
3179 BUF_PT (XBUFFER (ow->buffer)),
3180 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3183 selected_window = window;
3184 sf = SELECTED_FRAME ();
3185 if (XFRAME (WINDOW_FRAME (w)) != sf)
3187 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3188 /* Use this rather than Fhandle_switch_frame
3189 so that FRAME_FOCUS_FRAME is moved appropriately as we
3190 move around in the state where a minibuffer in a separate
3191 frame is active. */
3192 Fselect_frame (WINDOW_FRAME (w), Qnil);
3194 else
3195 sf->selected_window = window;
3197 if (NILP (norecord))
3198 record_buffer (w->buffer);
3199 Fset_buffer (w->buffer);
3201 XBUFFER (w->buffer)->last_selected_window = window;
3203 /* Go to the point recorded in the window.
3204 This is important when the buffer is in more
3205 than one window. It also matters when
3206 redisplay_window has altered point after scrolling,
3207 because it makes the change only in the window. */
3209 register int new_point = marker_position (w->pointm);
3210 if (new_point < BEGV)
3211 SET_PT (BEGV);
3212 else if (new_point > ZV)
3213 SET_PT (ZV);
3214 else
3215 SET_PT (new_point);
3218 windows_or_buffers_changed++;
3219 return window;
3222 static Lisp_Object
3223 select_window_norecord (window)
3224 Lisp_Object window;
3226 return Fselect_window (window, Qt);
3229 /* Deiconify the frame containing the window WINDOW,
3230 unless it is the selected frame;
3231 then return WINDOW.
3233 The reason for the exception for the selected frame
3234 is that it seems better not to change the selected frames visibility
3235 merely because of displaying a different buffer in it.
3236 The deiconification is useful when a buffer gets shown in
3237 another frame that you were not using lately. */
3239 static Lisp_Object
3240 display_buffer_1 (window)
3241 Lisp_Object window;
3243 Lisp_Object frame = XWINDOW (window)->frame;
3244 FRAME_PTR f = XFRAME (frame);
3246 FRAME_SAMPLE_VISIBILITY (f);
3248 if (EQ (frame, selected_frame))
3249 ; /* Assume the selected frame is already visible enough. */
3250 else if (minibuf_level > 0
3251 && MINI_WINDOW_P (XWINDOW (selected_window))
3252 && WINDOW_LIVE_P (minibuf_selected_window)
3253 && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
3254 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3255 else
3257 if (FRAME_ICONIFIED_P (f))
3258 Fmake_frame_visible (frame);
3259 else if (FRAME_VISIBLE_P (f))
3260 Fraise_frame (frame);
3263 return window;
3266 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
3267 doc: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
3268 If the value is t, a frame would be created for that buffer
3269 using the default frame parameters. If the value is a list,
3270 it is a list of frame parameters that would be used
3271 to make a frame for that buffer.
3272 The variables `special-display-buffer-names'
3273 and `special-display-regexps' control this. */)
3274 (buffer_name)
3275 Lisp_Object buffer_name;
3277 Lisp_Object tem;
3279 CHECK_STRING (buffer_name);
3281 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
3282 if (!NILP (tem))
3283 return Qt;
3285 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
3286 if (!NILP (tem))
3287 return XCDR (tem);
3289 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
3291 Lisp_Object car = XCAR (tem);
3292 if (STRINGP (car)
3293 && fast_string_match (car, buffer_name) >= 0)
3294 return Qt;
3295 else if (CONSP (car)
3296 && STRINGP (XCAR (car))
3297 && fast_string_match (XCAR (car), buffer_name) >= 0)
3298 return XCDR (car);
3300 return Qnil;
3303 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
3304 doc: /* Returns non-nil if a new buffer named BUFFER-NAME would use the same window.
3305 See `same-window-buffer-names' and `same-window-regexps'. */)
3306 (buffer_name)
3307 Lisp_Object buffer_name;
3309 Lisp_Object tem;
3311 CHECK_STRING (buffer_name);
3313 tem = Fmember (buffer_name, Vsame_window_buffer_names);
3314 if (!NILP (tem))
3315 return Qt;
3317 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
3318 if (!NILP (tem))
3319 return Qt;
3321 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3323 Lisp_Object car = XCAR (tem);
3324 if (STRINGP (car)
3325 && fast_string_match (car, buffer_name) >= 0)
3326 return Qt;
3327 else if (CONSP (car)
3328 && STRINGP (XCAR (car))
3329 && fast_string_match (XCAR (car), buffer_name) >= 0)
3330 return Qt;
3332 return Qnil;
3335 /* Use B so the default is (other-buffer). */
3336 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
3337 "BDisplay buffer: \nP",
3338 doc: /* Make BUFFER appear in some window but don't select it.
3339 BUFFER must be the name of an existing buffer, or, when called from Lisp,
3340 a buffer.
3341 If BUFFER is shown already in some window, just use that one,
3342 unless the window is the selected window and the optional second
3343 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3344 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3345 Returns the window displaying BUFFER.
3346 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3347 displaying BUFFER, then simply raise that frame.
3349 The variables `special-display-buffer-names',
3350 `special-display-regexps', `same-window-buffer-names', and
3351 `same-window-regexps' customize how certain buffer names are handled.
3352 The latter two take effect only if NOT-THIS-WINDOW is t.
3354 If optional argument FRAME is `visible', search all visible frames.
3355 If FRAME is 0, search all visible and iconified frames.
3356 If FRAME is t, search all frames.
3357 If FRAME is a frame, search only that frame.
3358 If FRAME is nil, search only the selected frame
3359 (actually the last nonminibuffer frame),
3360 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3361 which means search visible and iconified frames.
3363 If a full-width window on a splittable frame is available to display
3364 the buffer, it may be split, subject to the value of the variable
3365 `split-height-threshold'.
3367 If `even-window-heights' is non-nil, window heights will be evened out
3368 if displaying the buffer causes two vertically adjacent windows to be
3369 displayed. */)
3370 (buffer, not_this_window, frame)
3371 register Lisp_Object buffer, not_this_window, frame;
3373 register Lisp_Object window, tem, swp;
3374 struct frame *f;
3376 swp = Qnil;
3377 buffer = Fget_buffer (buffer);
3378 CHECK_BUFFER (buffer);
3380 if (!NILP (Vdisplay_buffer_function))
3381 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3383 if (NILP (not_this_window)
3384 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3385 return display_buffer_1 (selected_window);
3387 /* See if the user has specified this buffer should appear
3388 in the selected window. */
3389 if (NILP (not_this_window))
3391 swp = Fsame_window_p (XBUFFER (buffer)->name);
3392 if (!NILP (swp) && !no_switch_window (selected_window))
3394 Fswitch_to_buffer (buffer, Qnil);
3395 return display_buffer_1 (selected_window);
3399 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3400 look for a window showing BUFFER on any visible or iconified frame.
3401 Otherwise search only the current frame. */
3402 if (! NILP (frame))
3403 tem = frame;
3404 else if (pop_up_frames
3405 || display_buffer_reuse_frames
3406 || last_nonminibuf_frame == 0)
3407 XSETFASTINT (tem, 0);
3408 else
3409 XSETFRAME (tem, last_nonminibuf_frame);
3411 window = Fget_buffer_window (buffer, tem);
3412 if (!NILP (window)
3413 && (NILP (not_this_window) || !EQ (window, selected_window)))
3414 return display_buffer_1 (window);
3416 /* Certain buffer names get special handling. */
3417 if (!NILP (Vspecial_display_function) && NILP (swp))
3419 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3420 if (EQ (tem, Qt))
3421 return call1 (Vspecial_display_function, buffer);
3422 if (CONSP (tem))
3423 return call2 (Vspecial_display_function, buffer, tem);
3426 /* If there are no frames open that have more than a minibuffer,
3427 we need to create a new frame. */
3428 if (pop_up_frames || last_nonminibuf_frame == 0)
3430 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3431 Fset_window_buffer (window, buffer, Qnil);
3432 return display_buffer_1 (window);
3435 f = SELECTED_FRAME ();
3436 if (pop_up_windows
3437 || FRAME_MINIBUF_ONLY_P (f)
3438 /* If the current frame is a special display frame,
3439 don't try to reuse its windows. */
3440 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3442 Lisp_Object frames;
3444 frames = Qnil;
3445 if (FRAME_MINIBUF_ONLY_P (f))
3446 XSETFRAME (frames, last_nonminibuf_frame);
3447 /* Don't try to create a window if we would get an error. */
3448 if (split_height_threshold < window_min_height << 1)
3449 split_height_threshold = window_min_height << 1;
3451 /* Note that both Fget_largest_window and Fget_lru_window
3452 ignore minibuffers and dedicated windows.
3453 This means they can return nil. */
3455 /* If the frame we would try to split cannot be split,
3456 try other frames. */
3457 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3459 /* Try visible frames first. */
3460 window = Fget_largest_window (Qvisible);
3461 /* If that didn't work, try iconified frames. */
3462 if (NILP (window))
3463 window = Fget_largest_window (make_number (0));
3464 if (NILP (window))
3465 window = Fget_largest_window (Qt);
3467 else
3468 window = Fget_largest_window (frames);
3470 /* If we got a tall enough full-width window that can be split,
3471 split it. */
3472 if (!NILP (window)
3473 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3474 && window_height (window) >= split_height_threshold
3475 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
3476 window = Fsplit_window (window, Qnil, Qnil);
3477 else
3479 Lisp_Object upper, lower, other;
3481 window = Fget_lru_window (frames);
3482 /* If the LRU window is selected, and big enough,
3483 and can be split, split it. */
3484 if (!NILP (window)
3485 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3486 && (EQ (window, selected_window)
3487 || EQ (XWINDOW (window)->parent, Qnil))
3488 && window_height (window) >= window_min_height << 1)
3489 window = Fsplit_window (window, Qnil, Qnil);
3490 /* If Fget_lru_window returned nil, try other approaches. */
3492 /* Try visible frames first. */
3493 if (NILP (window))
3494 window = Fget_buffer_window (buffer, Qvisible);
3495 if (NILP (window))
3496 window = Fget_largest_window (Qvisible);
3497 /* If that didn't work, try iconified frames. */
3498 if (NILP (window))
3499 window = Fget_buffer_window (buffer, make_number (0));
3500 if (NILP (window))
3501 window = Fget_largest_window (make_number (0));
3502 /* Try invisible frames. */
3503 if (NILP (window))
3504 window = Fget_buffer_window (buffer, Qt);
3505 if (NILP (window))
3506 window = Fget_largest_window (Qt);
3507 /* As a last resort, make a new frame. */
3508 if (NILP (window))
3509 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3510 /* If window appears above or below another,
3511 even out their heights. */
3512 other = upper = lower = Qnil;
3513 if (!NILP (XWINDOW (window)->prev))
3514 other = upper = XWINDOW (window)->prev, lower = window;
3515 if (!NILP (XWINDOW (window)->next))
3516 other = lower = XWINDOW (window)->next, upper = window;
3517 if (!NILP (other)
3518 && !NILP (Veven_window_heights)
3519 /* Check that OTHER and WINDOW are vertically arrayed. */
3520 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3521 && (XFASTINT (XWINDOW (other)->total_lines)
3522 > XFASTINT (XWINDOW (window)->total_lines)))
3524 int total = (XFASTINT (XWINDOW (other)->total_lines)
3525 + XFASTINT (XWINDOW (window)->total_lines));
3526 enlarge_window (upper,
3527 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
3528 0, 0);
3532 else
3533 window = Fget_lru_window (Qnil);
3535 Fset_window_buffer (window, buffer, Qnil);
3536 return display_buffer_1 (window);
3540 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3541 0, 1, 0,
3542 doc: /* Force redisplay of all windows.
3543 If optional arg OBJECT is a window, force redisplay of that window only.
3544 If OBJECT is a buffer or buffer name, force redisplay of all windows
3545 displaying that buffer. */)
3546 (object)
3547 Lisp_Object object;
3549 if (NILP (object))
3551 windows_or_buffers_changed++;
3552 update_mode_lines++;
3553 return Qt;
3556 if (WINDOWP (object))
3558 struct window *w = XWINDOW (object);
3559 mark_window_display_accurate (object, 0);
3560 w->update_mode_line = Qt;
3561 if (BUFFERP (w->buffer))
3562 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3563 ++update_mode_lines;
3564 return Qt;
3567 if (STRINGP (object))
3568 object = Fget_buffer (object);
3569 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3571 /* Walk all windows looking for buffer, and force update
3572 of each of those windows. */
3574 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3575 return NILP (object) ? Qnil : Qt;
3578 /* If nothing suitable was found, just return.
3579 We could signal an error, but this feature will typically be used
3580 asynchronously in timers or process sentinels, so we don't. */
3581 return Qnil;
3585 void
3586 temp_output_buffer_show (buf)
3587 register Lisp_Object buf;
3589 register struct buffer *old = current_buffer;
3590 register Lisp_Object window;
3591 register struct window *w;
3593 XBUFFER (buf)->directory = current_buffer->directory;
3595 Fset_buffer (buf);
3596 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3597 BEGV = BEG;
3598 ZV = Z;
3599 SET_PT (BEG);
3600 #if 0 /* rms: there should be no reason for this. */
3601 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3602 #endif
3603 set_buffer_internal (old);
3605 if (!EQ (Vtemp_buffer_show_function, Qnil))
3606 call1 (Vtemp_buffer_show_function, buf);
3607 else
3609 window = Fdisplay_buffer (buf, Qnil, Qnil);
3611 if (!EQ (XWINDOW (window)->frame, selected_frame))
3612 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3613 Vminibuf_scroll_window = window;
3614 w = XWINDOW (window);
3615 XSETFASTINT (w->hscroll, 0);
3616 XSETFASTINT (w->min_hscroll, 0);
3617 set_marker_restricted_both (w->start, buf, BEG, BEG);
3618 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3620 /* Run temp-buffer-show-hook, with the chosen window selected
3621 and its buffer current. */
3623 if (!NILP (Vrun_hooks)
3624 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3625 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3627 int count = SPECPDL_INDEX ();
3628 Lisp_Object prev_window, prev_buffer;
3629 prev_window = selected_window;
3630 XSETBUFFER (prev_buffer, old);
3632 /* Select the window that was chosen, for running the hook.
3633 Note: Both Fselect_window and select_window_norecord may
3634 set-buffer to the buffer displayed in the window,
3635 so we need to save the current buffer. --stef */
3636 record_unwind_protect (Fset_buffer, prev_buffer);
3637 record_unwind_protect (select_window_norecord, prev_window);
3638 Fselect_window (window, Qt);
3639 Fset_buffer (w->buffer);
3640 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3641 unbind_to (count, Qnil);
3646 static void
3647 make_dummy_parent (window)
3648 Lisp_Object window;
3650 Lisp_Object new;
3651 register struct window *o, *p;
3652 int i;
3654 o = XWINDOW (window);
3655 p = allocate_window ();
3656 for (i = 0; i < VECSIZE (struct window); ++i)
3657 ((struct Lisp_Vector *) p)->contents[i]
3658 = ((struct Lisp_Vector *)o)->contents[i];
3659 XSETWINDOW (new, p);
3661 ++sequence_number;
3662 XSETFASTINT (p->sequence_number, sequence_number);
3664 /* Put new into window structure in place of window */
3665 replace_window (window, new);
3667 o->next = Qnil;
3668 o->prev = Qnil;
3669 o->vchild = Qnil;
3670 o->hchild = Qnil;
3671 o->parent = new;
3673 p->start = Qnil;
3674 p->pointm = Qnil;
3675 p->buffer = Qnil;
3678 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3679 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3680 WINDOW defaults to selected one and SIZE to half its size.
3681 If optional third arg HORFLAG is non-nil, split side by side
3682 and put SIZE columns in the first of the pair. In that case,
3683 SIZE includes that window's scroll bar, or the divider column to its right.
3684 Interactively, all arguments are nil.
3686 Returns the newly created window (which is the lower or rightmost one).
3687 The upper or leftmost window is the original one and remains selected.
3688 See Info node `(elisp)Splitting Windows' for more details and examples.*/)
3689 (window, size, horflag)
3690 Lisp_Object window, size, horflag;
3692 register Lisp_Object new;
3693 register struct window *o, *p;
3694 FRAME_PTR fo;
3695 register int size_int;
3697 if (NILP (window))
3698 window = selected_window;
3699 else
3700 CHECK_LIVE_WINDOW (window);
3702 o = XWINDOW (window);
3703 fo = XFRAME (WINDOW_FRAME (o));
3705 if (NILP (size))
3707 if (!NILP (horflag))
3708 /* Calculate the size of the left-hand window, by dividing
3709 the usable space in columns by two.
3710 We round up, since the left-hand window may include
3711 a dividing line, while the right-hand may not. */
3712 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
3713 else
3714 size_int = XFASTINT (o->total_lines) >> 1;
3716 else
3718 CHECK_NUMBER (size);
3719 size_int = XINT (size);
3722 if (MINI_WINDOW_P (o))
3723 error ("Attempt to split minibuffer window");
3724 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3725 error ("Attempt to split fixed-size window");
3727 check_min_window_sizes ();
3729 if (NILP (horflag))
3731 if (size_int < window_min_height)
3732 error ("Window height %d too small (after splitting)", size_int);
3733 if (size_int + window_min_height > XFASTINT (o->total_lines))
3734 error ("Window height %d too small (after splitting)",
3735 XFASTINT (o->total_lines) - size_int);
3736 if (NILP (o->parent)
3737 || NILP (XWINDOW (o->parent)->vchild))
3739 make_dummy_parent (window);
3740 new = o->parent;
3741 XWINDOW (new)->vchild = window;
3744 else
3746 if (size_int < window_min_width)
3747 error ("Window width %d too small (after splitting)", size_int);
3749 if (size_int + window_min_width > XFASTINT (o->total_cols))
3750 error ("Window width %d too small (after splitting)",
3751 XFASTINT (o->total_cols) - size_int);
3752 if (NILP (o->parent)
3753 || NILP (XWINDOW (o->parent)->hchild))
3755 make_dummy_parent (window);
3756 new = o->parent;
3757 XWINDOW (new)->hchild = window;
3761 /* Now we know that window's parent is a vertical combination
3762 if we are dividing vertically, or a horizontal combination
3763 if we are making side-by-side windows */
3765 windows_or_buffers_changed++;
3766 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3767 new = make_window ();
3768 p = XWINDOW (new);
3770 p->frame = o->frame;
3771 p->next = o->next;
3772 if (!NILP (p->next))
3773 XWINDOW (p->next)->prev = new;
3774 p->prev = window;
3775 o->next = new;
3776 p->parent = o->parent;
3777 p->buffer = Qt;
3778 p->window_end_valid = Qnil;
3779 bzero (&p->last_cursor, sizeof p->last_cursor);
3781 /* Duplicate special geometry settings. */
3783 p->left_margin_cols = o->left_margin_cols;
3784 p->right_margin_cols = o->right_margin_cols;
3785 p->left_fringe_width = o->left_fringe_width;
3786 p->right_fringe_width = o->right_fringe_width;
3787 p->fringes_outside_margins = o->fringes_outside_margins;
3788 p->scroll_bar_width = o->scroll_bar_width;
3789 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
3791 /* Apportion the available frame space among the two new windows */
3793 if (!NILP (horflag))
3795 p->total_lines = o->total_lines;
3796 p->top_line = o->top_line;
3797 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
3798 XSETFASTINT (o->total_cols, size_int);
3799 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
3800 adjust_window_margins (p);
3801 adjust_window_margins (o);
3803 else
3805 p->left_col = o->left_col;
3806 p->total_cols = o->total_cols;
3807 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
3808 XSETFASTINT (o->total_lines, size_int);
3809 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
3812 /* Adjust glyph matrices. */
3813 adjust_glyphs (fo);
3815 Fset_window_buffer (new, o->buffer, Qt);
3816 return new;
3819 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 3, "p",
3820 doc: /* Make current window ARG lines bigger.
3821 From program, optional second arg non-nil means grow sideways ARG columns.
3822 Interactively, if an argument is not given, make the window one line bigger.
3824 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3825 of the siblings above or to the left of the selected window. Only
3826 siblings to the right or below are changed. */)
3827 (arg, side, preserve_before)
3828 register Lisp_Object arg, side, preserve_before;
3830 CHECK_NUMBER (arg);
3831 enlarge_window (selected_window, XINT (arg), !NILP (side),
3832 !NILP (preserve_before));
3834 if (! NILP (Vwindow_configuration_change_hook))
3835 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3837 return Qnil;
3840 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 3, "p",
3841 doc: /* Make current window ARG lines smaller.
3842 From program, optional second arg non-nil means shrink sideways arg columns.
3843 Interactively, if an argument is not given, make the window one line smaller.
3845 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3846 of the siblings above or to the left of the selected window. Only
3847 siblings to the right or below are changed. */)
3848 (arg, side, preserve_before)
3849 register Lisp_Object arg, side, preserve_before;
3851 CHECK_NUMBER (arg);
3852 enlarge_window (selected_window, -XINT (arg), !NILP (side),
3853 !NILP (preserve_before));
3855 if (! NILP (Vwindow_configuration_change_hook))
3856 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3858 return Qnil;
3862 window_height (window)
3863 Lisp_Object window;
3865 register struct window *p = XWINDOW (window);
3866 return WINDOW_TOTAL_LINES (p);
3870 window_width (window)
3871 Lisp_Object window;
3873 register struct window *p = XWINDOW (window);
3874 return WINDOW_TOTAL_COLS (p);
3878 #define CURBEG(w) \
3879 *(widthflag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
3881 #define CURSIZE(w) \
3882 *(widthflag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
3885 /* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means
3886 increase its width. Siblings of the selected window are resized to
3887 fulfill the size request. If they become too small in the process,
3888 they will be deleted.
3890 If PRESERVE_BEFORE is nonzero, that means don't alter
3891 the siblings to the left or above WINDOW. */
3893 static void
3894 enlarge_window (window, delta, widthflag, preserve_before)
3895 Lisp_Object window;
3896 int delta, widthflag, preserve_before;
3898 Lisp_Object parent, next, prev;
3899 struct window *p;
3900 Lisp_Object *sizep;
3901 int maximum;
3902 int (*sizefun) P_ ((Lisp_Object))
3903 = widthflag ? window_width : window_height;
3904 void (*setsizefun) P_ ((Lisp_Object, int, int))
3905 = (widthflag ? set_window_width : set_window_height);
3907 /* Check values of window_min_width and window_min_height for
3908 validity. */
3909 check_min_window_sizes ();
3911 /* Give up if this window cannot be resized. */
3912 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3913 error ("Window is not resizable");
3915 /* Find the parent of the selected window. */
3916 while (1)
3918 p = XWINDOW (window);
3919 parent = p->parent;
3921 if (NILP (parent))
3923 if (widthflag)
3924 error ("No other window to side of this one");
3925 break;
3928 if (widthflag
3929 ? !NILP (XWINDOW (parent)->hchild)
3930 : !NILP (XWINDOW (parent)->vchild))
3931 break;
3933 window = parent;
3936 sizep = &CURSIZE (window);
3939 register int maxdelta;
3941 /* Compute the maximum size increment this window can have. */
3943 if (preserve_before)
3945 if (!NILP (parent))
3947 maxdelta = (*sizefun) (parent) - XINT (*sizep);
3948 /* Subtract size of siblings before, since we can't take that. */
3949 maxdelta -= XINT (CURBEG (window)) - XINT (CURBEG (parent));
3951 else
3952 maxdelta = (!NILP (p->next) ? ((*sizefun) (p->next)
3953 - window_min_size (XWINDOW (p->next),
3954 widthflag, 0, 0))
3955 : (delta = 0));
3957 else
3958 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
3959 /* This is a main window followed by a minibuffer. */
3960 : !NILP (p->next) ? ((*sizefun) (p->next)
3961 - window_min_size (XWINDOW (p->next),
3962 widthflag, 0, 0))
3963 /* This is a minibuffer following a main window. */
3964 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3965 - window_min_size (XWINDOW (p->prev),
3966 widthflag, 0, 0))
3967 /* This is a frame with only one window, a minibuffer-only
3968 or a minibufferless frame. */
3969 : (delta = 0));
3971 if (delta > maxdelta)
3972 /* This case traps trying to make the minibuffer
3973 the full frame, or make the only window aside from the
3974 minibuffer the full frame. */
3975 delta = maxdelta;
3978 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3980 delete_window (window);
3981 return;
3984 if (delta == 0)
3985 return;
3987 /* Find the total we can get from other siblings without deleting them. */
3988 maximum = 0;
3989 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3990 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3991 widthflag, 0, 0);
3992 if (! preserve_before)
3993 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3994 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3995 widthflag, 0, 0);
3997 /* If we can get it all from them without deleting them, do so. */
3998 if (delta <= maximum)
4000 Lisp_Object first_unaffected;
4001 Lisp_Object first_affected;
4002 int fixed_p;
4004 next = p->next;
4005 prev = p->prev;
4006 first_affected = window;
4007 /* Look at one sibling at a time,
4008 moving away from this window in both directions alternately,
4009 and take as much as we can get without deleting that sibling. */
4010 while (delta != 0
4011 && (!NILP (next) || (!preserve_before && !NILP (prev))))
4013 if (! NILP (next))
4015 int this_one = ((*sizefun) (next)
4016 - window_min_size (XWINDOW (next),
4017 widthflag, 0, &fixed_p));
4018 if (!fixed_p)
4020 if (this_one > delta)
4021 this_one = delta;
4023 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
4024 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4026 delta -= this_one;
4029 next = XWINDOW (next)->next;
4032 if (delta == 0)
4033 break;
4035 if (!preserve_before && ! NILP (prev))
4037 int this_one = ((*sizefun) (prev)
4038 - window_min_size (XWINDOW (prev),
4039 widthflag, 0, &fixed_p));
4040 if (!fixed_p)
4042 if (this_one > delta)
4043 this_one = delta;
4045 first_affected = prev;
4047 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
4048 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4050 delta -= this_one;
4053 prev = XWINDOW (prev)->prev;
4057 xassert (delta == 0);
4059 /* Now recalculate the edge positions of all the windows affected,
4060 based on the new sizes. */
4061 first_unaffected = next;
4062 prev = first_affected;
4063 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4064 prev = next, next = XWINDOW (next)->next)
4066 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4067 /* This does not change size of NEXT,
4068 but it propagates the new top edge to its children */
4069 (*setsizefun) (next, (*sizefun) (next), 0);
4072 else
4074 register int delta1;
4075 register int opht = (*sizefun) (parent);
4077 if (opht <= XINT (*sizep) + delta)
4079 /* If trying to grow this window to or beyond size of the parent,
4080 just delete all the sibling windows. */
4081 Lisp_Object start, tem, next;
4083 start = XWINDOW (parent)->vchild;
4084 if (NILP (start))
4085 start = XWINDOW (parent)->hchild;
4087 /* Delete any siblings that come after WINDOW. */
4088 tem = XWINDOW (window)->next;
4089 while (! NILP (tem))
4091 next = XWINDOW (tem)->next;
4092 delete_window (tem);
4093 tem = next;
4096 /* Delete any siblings that come after WINDOW.
4097 Note that if START is not WINDOW, then WINDOW still
4098 Fhas siblings, so WINDOW has not yet replaced its parent. */
4099 tem = start;
4100 while (! EQ (tem, window))
4102 next = XWINDOW (tem)->next;
4103 delete_window (tem);
4104 tem = next;
4107 else
4109 /* Otherwise, make delta1 just right so that if we add
4110 delta1 lines to this window and to the parent, and then
4111 shrink the parent back to its original size, the new
4112 proportional size of this window will increase by delta.
4114 The function size_window will compute the new height h'
4115 of the window from delta1 as:
4117 e = delta1/n
4118 x = delta1 - delta1/n * n for the 1st resizable child
4119 h' = h + e + x
4121 where n is the number of children that can be resized.
4122 We can ignore x by choosing a delta1 that is a multiple of
4123 n. We want the height of this window to come out as
4125 h' = h + delta
4127 So, delta1 must be
4129 h + e = h + delta
4130 delta1/n = delta
4131 delta1 = n * delta.
4133 The number of children n equals the number of resizable
4134 children of this window + 1 because we know window itself
4135 is resizable (otherwise we would have signalled an error. */
4137 struct window *w = XWINDOW (window);
4138 Lisp_Object s;
4139 int n = 1;
4141 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
4142 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
4143 ++n;
4144 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
4145 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
4146 ++n;
4148 delta1 = n * delta;
4150 /* Add delta1 lines or columns to this window, and to the parent,
4151 keeping things consistent while not affecting siblings. */
4152 XSETINT (CURSIZE (parent), opht + delta1);
4153 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4155 /* Squeeze out delta1 lines or columns from our parent,
4156 shriking this window and siblings proportionately.
4157 This brings parent back to correct size.
4158 Delta1 was calculated so this makes this window the desired size,
4159 taking it all out of the siblings. */
4160 (*setsizefun) (parent, opht, 0);
4165 XSETFASTINT (p->last_modified, 0);
4166 XSETFASTINT (p->last_overlay_modified, 0);
4168 /* Adjust glyph matrices. */
4169 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4172 #undef CURBEG
4173 #undef CURSIZE
4177 /***********************************************************************
4178 Resizing Mini-Windows
4179 ***********************************************************************/
4181 static void shrink_window_lowest_first P_ ((struct window *, int));
4183 enum save_restore_action
4185 CHECK_ORIG_SIZES,
4186 SAVE_ORIG_SIZES,
4187 RESTORE_ORIG_SIZES
4190 static int save_restore_orig_size P_ ((struct window *,
4191 enum save_restore_action));
4193 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4194 from lowest windows first. */
4196 static void
4197 shrink_window_lowest_first (w, height)
4198 struct window *w;
4199 int height;
4201 struct window *c;
4202 Lisp_Object child;
4203 int old_height;
4205 xassert (!MINI_WINDOW_P (w));
4207 /* Set redisplay hints. */
4208 XSETFASTINT (w->last_modified, 0);
4209 XSETFASTINT (w->last_overlay_modified, 0);
4210 windows_or_buffers_changed++;
4211 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4213 old_height = XFASTINT (w->total_lines);
4214 XSETFASTINT (w->total_lines, height);
4216 if (!NILP (w->hchild))
4218 for (child = w->hchild; !NILP (child); child = c->next)
4220 c = XWINDOW (child);
4221 c->top_line = w->top_line;
4222 shrink_window_lowest_first (c, height);
4225 else if (!NILP (w->vchild))
4227 Lisp_Object last_child;
4228 int delta = old_height - height;
4229 int last_top;
4231 last_child = Qnil;
4233 /* Find the last child. We are taking space from lowest windows
4234 first, so we iterate over children from the last child
4235 backwards. */
4236 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
4237 last_child = child;
4239 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
4240 for (child = last_child; delta && !NILP (child); child = c->prev)
4242 int this_one;
4244 c = XWINDOW (child);
4245 this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
4247 if (this_one > delta)
4248 this_one = delta;
4250 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4251 delta -= this_one;
4254 /* Compute new positions. */
4255 last_top = XINT (w->top_line);
4256 for (child = w->vchild; !NILP (child); child = c->next)
4258 c = XWINDOW (child);
4259 c->top_line = make_number (last_top);
4260 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4261 last_top += XFASTINT (c->total_lines);
4267 /* Save, restore, or check positions and sizes in the window tree
4268 rooted at W. ACTION says what to do.
4270 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4271 orig_total_lines members are valid for all windows in the window
4272 tree. Value is non-zero if they are valid.
4274 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4275 orig_top_line and orig_total_lines for all windows in the tree.
4277 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4278 stored in orig_top_line and orig_total_lines for all windows. */
4280 static int
4281 save_restore_orig_size (w, action)
4282 struct window *w;
4283 enum save_restore_action action;
4285 int success_p = 1;
4287 while (w)
4289 if (!NILP (w->hchild))
4291 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4292 success_p = 0;
4294 else if (!NILP (w->vchild))
4296 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4297 success_p = 0;
4300 switch (action)
4302 case CHECK_ORIG_SIZES:
4303 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4304 return 0;
4305 break;
4307 case SAVE_ORIG_SIZES:
4308 w->orig_top_line = w->top_line;
4309 w->orig_total_lines = w->total_lines;
4310 XSETFASTINT (w->last_modified, 0);
4311 XSETFASTINT (w->last_overlay_modified, 0);
4312 break;
4314 case RESTORE_ORIG_SIZES:
4315 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4316 w->top_line = w->orig_top_line;
4317 w->total_lines = w->orig_total_lines;
4318 w->orig_total_lines = w->orig_top_line = Qnil;
4319 XSETFASTINT (w->last_modified, 0);
4320 XSETFASTINT (w->last_overlay_modified, 0);
4321 break;
4323 default:
4324 abort ();
4327 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4330 return success_p;
4334 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4335 without deleting other windows. */
4337 void
4338 grow_mini_window (w, delta)
4339 struct window *w;
4340 int delta;
4342 struct frame *f = XFRAME (w->frame);
4343 struct window *root;
4345 xassert (MINI_WINDOW_P (w));
4346 xassert (delta >= 0);
4348 /* Check values of window_min_width and window_min_height for
4349 validity. */
4350 check_min_window_sizes ();
4352 /* Compute how much we can enlarge the mini-window without deleting
4353 other windows. */
4354 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4355 if (delta)
4357 int min_height = window_min_size (root, 0, 0, 0);
4358 if (XFASTINT (root->total_lines) - delta < min_height)
4359 /* Note that the root window may already be smaller than
4360 min_height. */
4361 delta = max (0, XFASTINT (root->total_lines) - min_height);
4364 if (delta)
4366 /* Save original window sizes and positions, if not already done. */
4367 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4368 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4370 /* Shrink other windows. */
4371 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4373 /* Grow the mini-window. */
4374 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4375 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4376 XSETFASTINT (w->last_modified, 0);
4377 XSETFASTINT (w->last_overlay_modified, 0);
4379 adjust_glyphs (f);
4384 /* Shrink mini-window W. If there is recorded info about window sizes
4385 before a call to grow_mini_window, restore recorded window sizes.
4386 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4387 line. */
4389 void
4390 shrink_mini_window (w)
4391 struct window *w;
4393 struct frame *f = XFRAME (w->frame);
4394 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4396 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4398 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4399 adjust_glyphs (f);
4400 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4401 windows_or_buffers_changed = 1;
4403 else if (XFASTINT (w->total_lines) > 1)
4405 /* Distribute the additional lines of the mini-window
4406 among the other windows. */
4407 Lisp_Object window;
4408 XSETWINDOW (window, w);
4409 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0, 0);
4415 /* Mark window cursors off for all windows in the window tree rooted
4416 at W by setting their phys_cursor_on_p flag to zero. Called from
4417 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4418 the frame are cleared. */
4420 void
4421 mark_window_cursors_off (w)
4422 struct window *w;
4424 while (w)
4426 if (!NILP (w->hchild))
4427 mark_window_cursors_off (XWINDOW (w->hchild));
4428 else if (!NILP (w->vchild))
4429 mark_window_cursors_off (XWINDOW (w->vchild));
4430 else
4431 w->phys_cursor_on_p = 0;
4433 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4438 /* Return number of lines of text (not counting mode lines) in W. */
4441 window_internal_height (w)
4442 struct window *w;
4444 int ht = XFASTINT (w->total_lines);
4446 if (!MINI_WINDOW_P (w))
4448 if (!NILP (w->parent)
4449 || !NILP (w->vchild)
4450 || !NILP (w->hchild)
4451 || !NILP (w->next)
4452 || !NILP (w->prev)
4453 || WINDOW_WANTS_MODELINE_P (w))
4454 --ht;
4456 if (WINDOW_WANTS_HEADER_LINE_P (w))
4457 --ht;
4460 return ht;
4464 /* Return the number of columns in W.
4465 Don't count columns occupied by scroll bars or the vertical bar
4466 separating W from the sibling to its right. */
4469 window_box_text_cols (w)
4470 struct window *w;
4472 struct frame *f = XFRAME (WINDOW_FRAME (w));
4473 int width = XINT (w->total_cols);
4475 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4476 /* Scroll bars occupy a few columns. */
4477 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4478 else if (!FRAME_WINDOW_P (f)
4479 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4480 /* The column of `|' characters separating side-by-side windows
4481 occupies one column only. */
4482 width -= 1;
4484 if (FRAME_WINDOW_P (f))
4485 /* On window-systems, fringes and display margins cannot be
4486 used for normal text. */
4487 width -= (WINDOW_FRINGE_COLS (w)
4488 + WINDOW_LEFT_MARGIN_COLS (w)
4489 + WINDOW_RIGHT_MARGIN_COLS (w));
4491 return width;
4495 /************************************************************************
4496 Window Scrolling
4497 ***********************************************************************/
4499 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4500 N screen-fulls, which is defined as the height of the window minus
4501 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4502 instead. Negative values of N mean scroll down. NOERROR non-zero
4503 means don't signal an error if we try to move over BEGV or ZV,
4504 respectively. */
4506 static void
4507 window_scroll (window, n, whole, noerror)
4508 Lisp_Object window;
4509 int n;
4510 int whole;
4511 int noerror;
4513 immediate_quit = 1;
4515 /* If we must, use the pixel-based version which is much slower than
4516 the line-based one but can handle varying line heights. */
4517 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4518 window_scroll_pixel_based (window, n, whole, noerror);
4519 else
4520 window_scroll_line_based (window, n, whole, noerror);
4522 immediate_quit = 0;
4526 /* Implementation of window_scroll that works based on pixel line
4527 heights. See the comment of window_scroll for parameter
4528 descriptions. */
4530 static void
4531 window_scroll_pixel_based (window, n, whole, noerror)
4532 Lisp_Object window;
4533 int n;
4534 int whole;
4535 int noerror;
4537 struct it it;
4538 struct window *w = XWINDOW (window);
4539 struct text_pos start;
4540 Lisp_Object tem;
4541 int this_scroll_margin;
4542 int preserve_y;
4543 /* True if we fiddled the window vscroll field without really scrolling. */
4544 int vscrolled = 0;
4546 SET_TEXT_POS_FROM_MARKER (start, w->start);
4548 /* If PT is not visible in WINDOW, move back one half of
4549 the screen. Allow PT to be partially visible, otherwise
4550 something like (scroll-down 1) with PT in the line before
4551 the partially visible one would recenter. */
4552 tem = Fpos_visible_in_window_p (make_number (PT), window, Qt);
4553 if (NILP (tem))
4555 /* Move backward half the height of the window. Performance note:
4556 vmotion used here is about 10% faster, but would give wrong
4557 results for variable height lines. */
4558 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4559 it.current_y = it.last_visible_y;
4560 move_it_vertically_backward (&it, window_box_height (w) / 2);
4562 /* The function move_iterator_vertically may move over more than
4563 the specified y-distance. If it->w is small, e.g. a
4564 mini-buffer window, we may end up in front of the window's
4565 display area. This is the case when Start displaying at the
4566 start of the line containing PT in this case. */
4567 if (it.current_y <= 0)
4569 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4570 move_it_vertically_backward (&it, 0);
4571 it.current_y = 0;
4574 start = it.current.pos;
4576 else if (auto_window_vscroll_p)
4578 if (tem = XCAR (XCDR (XCDR (tem))), CONSP (tem))
4580 int px;
4581 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4582 if (whole)
4583 dy = max ((window_box_height (w)
4584 - next_screen_context_lines * dy),
4585 dy);
4586 dy *= n;
4588 if (n < 0 && (px = XINT (XCAR (tem))) > 0)
4590 px = max (0, -w->vscroll - min (px, -dy));
4591 Fset_window_vscroll (window, make_number (px), Qt);
4592 return;
4594 if (n > 0 && (px = XINT (XCDR (tem))) > 0)
4596 px = max (0, -w->vscroll + min (px, dy));
4597 Fset_window_vscroll (window, make_number (px), Qt);
4598 return;
4601 Fset_window_vscroll (window, make_number (0), Qt);
4604 /* If scroll_preserve_screen_position is non-nil, we try to set
4605 point in the same window line as it is now, so get that line. */
4606 if (!NILP (Vscroll_preserve_screen_position))
4608 start_display (&it, w, start);
4609 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4610 preserve_y = it.current_y;
4612 else
4613 preserve_y = -1;
4615 /* Move iterator it from start the specified distance forward or
4616 backward. The result is the new window start. */
4617 start_display (&it, w, start);
4618 if (whole)
4620 int start_pos = IT_CHARPOS (it);
4621 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4622 dy = max ((window_box_height (w)
4623 - next_screen_context_lines * dy),
4624 dy) * n;
4626 /* Note that move_it_vertically always moves the iterator to the
4627 start of a line. So, if the last line doesn't have a newline,
4628 we would end up at the start of the line ending at ZV. */
4629 if (dy <= 0)
4631 move_it_vertically_backward (&it, -dy);
4632 /* Ensure we actually does move, e.g. in case we are currently
4633 looking at an image that is taller that the window height. */
4634 while (start_pos == IT_CHARPOS (it)
4635 && start_pos > BEGV)
4636 move_it_by_lines (&it, -1, 1);
4638 else if (dy > 0)
4640 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4641 MOVE_TO_POS | MOVE_TO_Y);
4642 /* Ensure we actually does move, e.g. in case we are currently
4643 looking at an image that is taller that the window height. */
4644 while (start_pos == IT_CHARPOS (it)
4645 && start_pos < ZV)
4646 move_it_by_lines (&it, 1, 1);
4649 else
4650 move_it_by_lines (&it, n, 1);
4652 /* We failed if we find ZV is already on the screen (scrolling up,
4653 means there's nothing past the end), or if we can't start any
4654 earlier (scrolling down, means there's nothing past the top). */
4655 if ((n > 0 && IT_CHARPOS (it) == ZV)
4656 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4658 if (IT_CHARPOS (it) == ZV)
4660 if (it.current_y < it.last_visible_y
4661 && (it.current_y + it.max_ascent + it.max_descent
4662 >= it.last_visible_y))
4664 /* The last line was only partially visible, make it fully
4665 visible. */
4666 w->vscroll = (it.last_visible_y
4667 - it.current_y + it.max_ascent + it.max_descent);
4668 adjust_glyphs (it.f);
4670 else if (noerror)
4671 return;
4672 else
4673 Fsignal (Qend_of_buffer, Qnil);
4675 else
4677 if (w->vscroll != 0)
4678 /* The first line was only partially visible, make it fully
4679 visible. */
4680 w->vscroll = 0;
4681 else if (noerror)
4682 return;
4683 else
4684 Fsignal (Qbeginning_of_buffer, Qnil);
4687 /* If control gets here, then we vscrolled. */
4689 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4691 /* Don't try to change the window start below. */
4692 vscrolled = 1;
4695 if (! vscrolled)
4697 int pos = IT_CHARPOS (it);
4698 int bytepos;
4700 /* If in the middle of a multi-glyph character move forward to
4701 the next character. */
4702 if (in_display_vector_p (&it))
4704 ++pos;
4705 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4708 /* Set the window start, and set up the window for redisplay. */
4709 set_marker_restricted (w->start, make_number (pos),
4710 w->buffer);
4711 bytepos = XMARKER (w->start)->bytepos;
4712 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
4713 ? Qt : Qnil);
4714 w->update_mode_line = Qt;
4715 XSETFASTINT (w->last_modified, 0);
4716 XSETFASTINT (w->last_overlay_modified, 0);
4717 /* Set force_start so that redisplay_window will run the
4718 window-scroll-functions. */
4719 w->force_start = Qt;
4722 /* The rest of this function uses current_y in a nonstandard way,
4723 not including the height of the header line if any. */
4724 it.current_y = it.vpos = 0;
4726 /* Move PT out of scroll margins.
4727 This code wants current_y to be zero at the window start position
4728 even if there is a header line. */
4729 this_scroll_margin = max (0, scroll_margin);
4730 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4731 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4733 if (n > 0)
4735 /* We moved the window start towards ZV, so PT may be now
4736 in the scroll margin at the top. */
4737 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4738 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin)
4739 /* We found PT at a legitimate height. Leave it alone. */
4741 else if (preserve_y >= 0)
4743 /* If we have a header line, take account of it.
4744 This is necessary because we set it.current_y to 0, above. */
4745 if (WINDOW_WANTS_HEADER_LINE_P (w))
4746 preserve_y -= CURRENT_HEADER_LINE_HEIGHT (w);
4748 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
4749 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4751 else
4753 while (it.current_y < this_scroll_margin)
4755 int prev = it.current_y;
4756 move_it_by_lines (&it, 1, 1);
4757 if (prev == it.current_y)
4758 break;
4760 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4763 else if (n < 0)
4765 int charpos, bytepos;
4766 int partial_p;
4768 /* Save our position, for the preserve_y case. */
4769 charpos = IT_CHARPOS (it);
4770 bytepos = IT_BYTEPOS (it);
4772 /* We moved the window start towards BEGV, so PT may be now
4773 in the scroll margin at the bottom. */
4774 move_it_to (&it, PT, -1,
4775 it.last_visible_y - this_scroll_margin - 1, -1,
4776 MOVE_TO_POS | MOVE_TO_Y);
4778 /* Save our position, in case it's correct. */
4779 charpos = IT_CHARPOS (it);
4780 bytepos = IT_BYTEPOS (it);
4782 /* See if point is on a partially visible line at the end. */
4783 if (it.what == IT_EOB)
4784 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
4785 else
4787 move_it_by_lines (&it, 1, 1);
4788 partial_p = it.current_y > it.last_visible_y;
4791 if (charpos == PT && !partial_p)
4792 /* We found PT before we found the display margin, so PT is ok. */
4794 else if (preserve_y >= 0)
4796 SET_TEXT_POS_FROM_MARKER (start, w->start);
4797 start_display (&it, w, start);
4798 #if 0 /* It's wrong to subtract this here
4799 because we called start_display again
4800 and did not alter it.current_y this time. */
4802 /* If we have a header line, take account of it. */
4803 if (WINDOW_WANTS_HEADER_LINE_P (w))
4804 preserve_y -= CURRENT_HEADER_LINE_HEIGHT (w);
4805 #endif
4807 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
4808 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4810 else
4812 if (partial_p)
4813 /* The last line was only partially visible, so back up two
4814 lines to make sure we're on a fully visible line. */
4816 move_it_by_lines (&it, -2, 0);
4817 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4819 else
4820 /* No, the position we saved is OK, so use it. */
4821 SET_PT_BOTH (charpos, bytepos);
4827 /* Implementation of window_scroll that works based on screen lines.
4828 See the comment of window_scroll for parameter descriptions. */
4830 static void
4831 window_scroll_line_based (window, n, whole, noerror)
4832 Lisp_Object window;
4833 int n;
4834 int whole;
4835 int noerror;
4837 register struct window *w = XWINDOW (window);
4838 register int opoint = PT, opoint_byte = PT_BYTE;
4839 register int pos, pos_byte;
4840 register int ht = window_internal_height (w);
4841 register Lisp_Object tem;
4842 int lose;
4843 Lisp_Object bolp;
4844 int startpos;
4845 struct position posit;
4846 int original_vpos;
4848 /* If scrolling screen-fulls, compute the number of lines to
4849 scroll from the window's height. */
4850 if (whole)
4851 n *= max (1, ht - next_screen_context_lines);
4853 startpos = marker_position (w->start);
4855 posit = *compute_motion (startpos, 0, 0, 0,
4856 PT, ht, 0,
4857 -1, XINT (w->hscroll),
4858 0, w);
4859 original_vpos = posit.vpos;
4861 XSETFASTINT (tem, PT);
4862 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4864 if (NILP (tem))
4866 Fvertical_motion (make_number (- (ht / 2)), window);
4867 startpos = PT;
4870 SET_PT (startpos);
4871 lose = n < 0 && PT == BEGV;
4872 Fvertical_motion (make_number (n), window);
4873 pos = PT;
4874 pos_byte = PT_BYTE;
4875 bolp = Fbolp ();
4876 SET_PT_BOTH (opoint, opoint_byte);
4878 if (lose)
4880 if (noerror)
4881 return;
4882 else
4883 Fsignal (Qbeginning_of_buffer, Qnil);
4886 if (pos < ZV)
4888 int this_scroll_margin = scroll_margin;
4890 /* Don't use a scroll margin that is negative or too large. */
4891 if (this_scroll_margin < 0)
4892 this_scroll_margin = 0;
4894 if (XINT (w->total_lines) < 4 * scroll_margin)
4895 this_scroll_margin = XINT (w->total_lines) / 4;
4897 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4898 w->start_at_line_beg = bolp;
4899 w->update_mode_line = Qt;
4900 XSETFASTINT (w->last_modified, 0);
4901 XSETFASTINT (w->last_overlay_modified, 0);
4902 /* Set force_start so that redisplay_window will run
4903 the window-scroll-functions. */
4904 w->force_start = Qt;
4906 if (whole && !NILP (Vscroll_preserve_screen_position))
4908 SET_PT_BOTH (pos, pos_byte);
4909 Fvertical_motion (make_number (original_vpos), window);
4911 /* If we scrolled forward, put point enough lines down
4912 that it is outside the scroll margin. */
4913 else if (n > 0)
4915 int top_margin;
4917 if (this_scroll_margin > 0)
4919 SET_PT_BOTH (pos, pos_byte);
4920 Fvertical_motion (make_number (this_scroll_margin), window);
4921 top_margin = PT;
4923 else
4924 top_margin = pos;
4926 if (top_margin <= opoint)
4927 SET_PT_BOTH (opoint, opoint_byte);
4928 else if (!NILP (Vscroll_preserve_screen_position))
4930 SET_PT_BOTH (pos, pos_byte);
4931 Fvertical_motion (make_number (original_vpos), window);
4933 else
4934 SET_PT (top_margin);
4936 else if (n < 0)
4938 int bottom_margin;
4940 /* If we scrolled backward, put point near the end of the window
4941 but not within the scroll margin. */
4942 SET_PT_BOTH (pos, pos_byte);
4943 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4944 if (XFASTINT (tem) == ht - this_scroll_margin)
4945 bottom_margin = PT;
4946 else
4947 bottom_margin = PT + 1;
4949 if (bottom_margin > opoint)
4950 SET_PT_BOTH (opoint, opoint_byte);
4951 else
4953 if (!NILP (Vscroll_preserve_screen_position))
4955 SET_PT_BOTH (pos, pos_byte);
4956 Fvertical_motion (make_number (original_vpos), window);
4958 else
4959 Fvertical_motion (make_number (-1), window);
4963 else
4965 if (noerror)
4966 return;
4967 else
4968 Fsignal (Qend_of_buffer, Qnil);
4973 /* Scroll selected_window up or down. If N is nil, scroll a
4974 screen-full which is defined as the height of the window minus
4975 next_screen_context_lines. If N is the symbol `-', scroll.
4976 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4977 up. This is the guts of Fscroll_up and Fscroll_down. */
4979 static void
4980 scroll_command (n, direction)
4981 Lisp_Object n;
4982 int direction;
4984 int count = SPECPDL_INDEX ();
4986 xassert (abs (direction) == 1);
4988 /* If selected window's buffer isn't current, make it current for
4989 the moment. But don't screw up if window_scroll gets an error. */
4990 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4992 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4993 Fset_buffer (XWINDOW (selected_window)->buffer);
4995 /* Make redisplay consider other windows than just selected_window. */
4996 ++windows_or_buffers_changed;
4999 if (NILP (n))
5000 window_scroll (selected_window, direction, 1, 0);
5001 else if (EQ (n, Qminus))
5002 window_scroll (selected_window, -direction, 1, 0);
5003 else
5005 n = Fprefix_numeric_value (n);
5006 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5009 unbind_to (count, Qnil);
5012 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
5013 doc: /* Scroll text of current window upward ARG lines.
5014 If ARG is omitted or nil, scroll upward by a near full screen.
5015 A near full screen is `next-screen-context-lines' less than a full screen.
5016 Negative ARG means scroll downward.
5017 If ARG is the atom `-', scroll downward by nearly full screen.
5018 When calling from a program, supply as argument a number, nil, or `-'. */)
5019 (arg)
5020 Lisp_Object arg;
5022 scroll_command (arg, 1);
5023 return Qnil;
5026 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
5027 doc: /* Scroll text of current window down ARG lines.
5028 If ARG is omitted or nil, scroll down by a near full screen.
5029 A near full screen is `next-screen-context-lines' less than a full screen.
5030 Negative ARG means scroll upward.
5031 If ARG is the atom `-', scroll upward by nearly full screen.
5032 When calling from a program, supply as argument a number, nil, or `-'. */)
5033 (arg)
5034 Lisp_Object arg;
5036 scroll_command (arg, -1);
5037 return Qnil;
5040 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5041 doc: /* Return the other window for \"other window scroll\" commands.
5042 If `other-window-scroll-buffer' is non-nil, a window
5043 showing that buffer is used.
5044 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5045 specifies the window. This takes precedence over
5046 `other-window-scroll-buffer'. */)
5049 Lisp_Object window;
5051 if (MINI_WINDOW_P (XWINDOW (selected_window))
5052 && !NILP (Vminibuf_scroll_window))
5053 window = Vminibuf_scroll_window;
5054 /* If buffer is specified, scroll that buffer. */
5055 else if (!NILP (Vother_window_scroll_buffer))
5057 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5058 if (NILP (window))
5059 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5061 else
5063 /* Nothing specified; look for a neighboring window on the same
5064 frame. */
5065 window = Fnext_window (selected_window, Qnil, Qnil);
5067 if (EQ (window, selected_window))
5068 /* That didn't get us anywhere; look for a window on another
5069 visible frame. */
5071 window = Fnext_window (window, Qnil, Qt);
5072 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5073 && ! EQ (window, selected_window));
5076 CHECK_LIVE_WINDOW (window);
5078 if (EQ (window, selected_window))
5079 error ("There is no other window");
5081 return window;
5084 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5085 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5086 A near full screen is `next-screen-context-lines' less than a full screen.
5087 The next window is the one below the current one; or the one at the top
5088 if the current one is at the bottom. Negative ARG means scroll downward.
5089 If ARG is the atom `-', scroll downward by nearly full screen.
5090 When calling from a program, supply as argument a number, nil, or `-'.
5092 If `other-window-scroll-buffer' is non-nil, scroll the window
5093 showing that buffer, popping the buffer up if necessary.
5094 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5095 specifies the window to scroll. This takes precedence over
5096 `other-window-scroll-buffer'. */)
5097 (arg)
5098 Lisp_Object arg;
5100 Lisp_Object window;
5101 struct window *w;
5102 int count = SPECPDL_INDEX ();
5104 window = Fother_window_for_scrolling ();
5105 w = XWINDOW (window);
5107 /* Don't screw up if window_scroll gets an error. */
5108 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5109 ++windows_or_buffers_changed;
5111 Fset_buffer (w->buffer);
5112 SET_PT (marker_position (w->pointm));
5114 if (NILP (arg))
5115 window_scroll (window, 1, 1, 1);
5116 else if (EQ (arg, Qminus))
5117 window_scroll (window, -1, 1, 1);
5118 else
5120 if (CONSP (arg))
5121 arg = Fcar (arg);
5122 CHECK_NUMBER (arg);
5123 window_scroll (window, XINT (arg), 0, 1);
5126 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5127 unbind_to (count, Qnil);
5129 return Qnil;
5132 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "P\np",
5133 doc: /* Scroll selected window display ARG columns left.
5134 Default for ARG is window width minus 2.
5135 Value is the total amount of leftward horizontal scrolling in
5136 effect after the change.
5137 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5138 lower bound for automatic scrolling, i.e. automatic scrolling
5139 will not scroll a window to a column less than the value returned
5140 by this function. This happens in an interactive call. */)
5141 (arg, set_minimum)
5142 register Lisp_Object arg, set_minimum;
5144 Lisp_Object result;
5145 int hscroll;
5146 struct window *w = XWINDOW (selected_window);
5148 if (NILP (arg))
5149 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5150 else
5151 arg = Fprefix_numeric_value (arg);
5153 hscroll = XINT (w->hscroll) + XINT (arg);
5154 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5156 if (!NILP (set_minimum))
5157 w->min_hscroll = w->hscroll;
5159 return result;
5162 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "P\np",
5163 doc: /* Scroll selected window display ARG columns right.
5164 Default for ARG is window width minus 2.
5165 Value is the total amount of leftward horizontal scrolling in
5166 effect after the change.
5167 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5168 lower bound for automatic scrolling, i.e. automatic scrolling
5169 will not scroll a window to a column less than the value returned
5170 by this function. This happens in an interactive call. */)
5171 (arg, set_minimum)
5172 register Lisp_Object arg, set_minimum;
5174 Lisp_Object result;
5175 int hscroll;
5176 struct window *w = XWINDOW (selected_window);
5178 if (NILP (arg))
5179 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5180 else
5181 arg = Fprefix_numeric_value (arg);
5183 hscroll = XINT (w->hscroll) - XINT (arg);
5184 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5186 if (!NILP (set_minimum))
5187 w->min_hscroll = w->hscroll;
5189 return result;
5192 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5193 doc: /* Return the window which was selected when entering the minibuffer.
5194 Returns nil, if current window is not a minibuffer window. */)
5197 if (minibuf_level > 0
5198 && MINI_WINDOW_P (XWINDOW (selected_window))
5199 && WINDOW_LIVE_P (minibuf_selected_window))
5200 return minibuf_selected_window;
5202 return Qnil;
5205 /* Value is the number of lines actually displayed in window W,
5206 as opposed to its height. */
5208 static int
5209 displayed_window_lines (w)
5210 struct window *w;
5212 struct it it;
5213 struct text_pos start;
5214 int height = window_box_height (w);
5215 struct buffer *old_buffer;
5216 int bottom_y;
5218 if (XBUFFER (w->buffer) != current_buffer)
5220 old_buffer = current_buffer;
5221 set_buffer_internal (XBUFFER (w->buffer));
5223 else
5224 old_buffer = NULL;
5226 /* In case W->start is out of the accessible range, do something
5227 reasonable. This happens in Info mode when Info-scroll-down
5228 calls (recenter -1) while W->start is 1. */
5229 if (XMARKER (w->start)->charpos < BEGV)
5230 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5231 else if (XMARKER (w->start)->charpos > ZV)
5232 SET_TEXT_POS (start, ZV, ZV_BYTE);
5233 else
5234 SET_TEXT_POS_FROM_MARKER (start, w->start);
5236 start_display (&it, w, start);
5237 move_it_vertically (&it, height);
5238 bottom_y = line_bottom_y (&it);
5240 /* rms: On a non-window display,
5241 the value of it.vpos at the bottom of the screen
5242 seems to be 1 larger than window_box_height (w).
5243 This kludge fixes a bug whereby (move-to-window-line -1)
5244 when ZV is on the last screen line
5245 moves to the previous screen line instead of the last one. */
5246 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5247 height++;
5249 /* Add in empty lines at the bottom of the window. */
5250 if (bottom_y < height)
5252 int uy = FRAME_LINE_HEIGHT (it.f);
5253 it.vpos += (height - bottom_y + uy - 1) / uy;
5256 if (old_buffer)
5257 set_buffer_internal (old_buffer);
5259 return it.vpos;
5263 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5264 doc: /* Center point in window and redisplay frame.
5265 With prefix argument ARG, recenter putting point on screen line ARG
5266 relative to the current window. If ARG is negative, it counts up from the
5267 bottom of the window. (ARG should be less than the height of the window.)
5269 If ARG is omitted or nil, erase the entire frame and then
5270 redraw with point in the center of the current window.
5271 Just C-u as prefix means put point in the center of the window
5272 and redisplay normally--don't erase and redraw the frame. */)
5273 (arg)
5274 register Lisp_Object arg;
5276 struct window *w = XWINDOW (selected_window);
5277 struct buffer *buf = XBUFFER (w->buffer);
5278 struct buffer *obuf = current_buffer;
5279 int center_p = 0;
5280 int charpos, bytepos;
5282 /* If redisplay is suppressed due to an error, try again. */
5283 obuf->display_error_modiff = 0;
5285 if (NILP (arg))
5287 int i;
5289 /* Invalidate pixel data calculated for all compositions. */
5290 for (i = 0; i < n_compositions; i++)
5291 composition_table[i]->font = NULL;
5293 Fredraw_frame (w->frame);
5294 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
5295 center_p = 1;
5297 else if (CONSP (arg)) /* Just C-u. */
5298 center_p = 1;
5299 else
5301 arg = Fprefix_numeric_value (arg);
5302 CHECK_NUMBER (arg);
5305 set_buffer_internal (buf);
5307 /* Handle centering on a graphical frame specially. Such frames can
5308 have variable-height lines and centering point on the basis of
5309 line counts would lead to strange effects. */
5310 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5312 if (center_p)
5314 struct it it;
5315 struct text_pos pt;
5317 SET_TEXT_POS (pt, PT, PT_BYTE);
5318 start_display (&it, w, pt);
5319 move_it_vertically_backward (&it, window_box_height (w) / 2);
5320 charpos = IT_CHARPOS (it);
5321 bytepos = IT_BYTEPOS (it);
5323 else if (XINT (arg) < 0)
5325 struct it it;
5326 struct text_pos pt;
5327 int nlines = - XINT (arg);
5328 int extra_line_spacing;
5329 int h = window_box_height (w);
5331 SET_TEXT_POS (pt, PT, PT_BYTE);
5332 start_display (&it, w, pt);
5334 /* Be sure we have the exact height of the full line containing PT. */
5335 move_it_by_lines (&it, 0, 1);
5337 /* The amount of pixels we have to move back is the window
5338 height minus what's displayed in the line containing PT,
5339 and the lines below. */
5340 it.current_y = 0;
5341 it.vpos = 0;
5342 move_it_by_lines (&it, nlines, 1);
5344 if (it.vpos == nlines)
5345 h -= it.current_y;
5346 else
5348 /* Last line has no newline */
5349 h -= line_bottom_y (&it);
5350 it.vpos++;
5353 /* Don't reserve space for extra line spacing of last line. */
5354 extra_line_spacing = it.max_extra_line_spacing;
5356 /* If we can't move down NLINES lines because we hit
5357 the end of the buffer, count in some empty lines. */
5358 if (it.vpos < nlines)
5360 nlines -= it.vpos;
5361 extra_line_spacing = it.extra_line_spacing;
5362 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5364 if (h <= 0)
5365 return Qnil;
5367 /* Now find the new top line (starting position) of the window. */
5368 start_display (&it, w, pt);
5369 it.current_y = 0;
5370 move_it_vertically_backward (&it, h);
5372 /* If extra line spacing is present, we may move too far
5373 back. This causes the last line to be only partially
5374 visible (which triggers redisplay to recenter that line
5375 in the middle), so move forward.
5376 But ignore extra line spacing on last line, as it is not
5377 considered to be part of the visible height of the line.
5379 h += extra_line_spacing;
5380 while (-it.current_y > h)
5381 move_it_by_lines (&it, 1, 1);
5383 charpos = IT_CHARPOS (it);
5384 bytepos = IT_BYTEPOS (it);
5386 else
5388 struct position pos;
5389 pos = *vmotion (PT, - XINT (arg), w);
5390 charpos = pos.bufpos;
5391 bytepos = pos.bytepos;
5394 else
5396 struct position pos;
5397 int ht = window_internal_height (w);
5399 if (center_p)
5400 arg = make_number (ht / 2);
5401 else if (XINT (arg) < 0)
5402 arg = make_number (XINT (arg) + ht);
5404 pos = *vmotion (PT, - XINT (arg), w);
5405 charpos = pos.bufpos;
5406 bytepos = pos.bytepos;
5409 /* Set the new window start. */
5410 set_marker_both (w->start, w->buffer, charpos, bytepos);
5411 w->window_end_valid = Qnil;
5413 w->optional_new_start = Qt;
5415 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5416 w->start_at_line_beg = Qt;
5417 else
5418 w->start_at_line_beg = Qnil;
5420 set_buffer_internal (obuf);
5421 return Qnil;
5425 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5426 0, 1, 0,
5427 doc: /* Return the height in lines of the text display area of WINDOW.
5428 This doesn't include the mode-line (or header-line if any) or any
5429 partial-height lines in the text display area. */)
5430 (window)
5431 Lisp_Object window;
5433 struct window *w = decode_window (window);
5434 int pixel_height = window_box_height (w);
5435 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5436 return make_number (line_height);
5441 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5442 1, 1, "P",
5443 doc: /* Position point relative to window.
5444 With no argument, position point at center of window.
5445 An argument specifies vertical position within the window;
5446 zero means top of window, negative means relative to bottom of window. */)
5447 (arg)
5448 Lisp_Object arg;
5450 struct window *w = XWINDOW (selected_window);
5451 int lines, start;
5452 Lisp_Object window;
5454 window = selected_window;
5455 start = marker_position (w->start);
5456 if (start < BEGV || start > ZV)
5458 int height = window_internal_height (w);
5459 Fvertical_motion (make_number (- (height / 2)), window);
5460 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5461 w->start_at_line_beg = Fbolp ();
5462 w->force_start = Qt;
5464 else
5465 Fgoto_char (w->start);
5467 lines = displayed_window_lines (w);
5468 if (NILP (arg))
5469 XSETFASTINT (arg, lines / 2);
5470 else
5472 arg = Fprefix_numeric_value (arg);
5473 if (XINT (arg) < 0)
5474 XSETINT (arg, XINT (arg) + lines);
5477 /* Skip past a partially visible first line. */
5478 if (w->vscroll)
5479 XSETINT (arg, XINT (arg) + 1);
5481 return Fvertical_motion (arg, window);
5486 /***********************************************************************
5487 Window Configuration
5488 ***********************************************************************/
5490 struct save_window_data
5492 EMACS_INT size_from_Lisp_Vector_struct;
5493 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5494 Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
5495 Lisp_Object frame_tool_bar_lines;
5496 Lisp_Object selected_frame;
5497 Lisp_Object current_window;
5498 Lisp_Object current_buffer;
5499 Lisp_Object minibuf_scroll_window;
5500 Lisp_Object minibuf_selected_window;
5501 Lisp_Object root_window;
5502 Lisp_Object focus_frame;
5503 /* Record the values of window-min-width and window-min-height
5504 so that window sizes remain consistent with them. */
5505 Lisp_Object min_width, min_height;
5506 /* A vector, each of whose elements is a struct saved_window
5507 for one window. */
5508 Lisp_Object saved_windows;
5511 /* This is saved as a Lisp_Vector */
5512 struct saved_window
5514 /* these first two must agree with struct Lisp_Vector in lisp.h */
5515 EMACS_INT size_from_Lisp_Vector_struct;
5516 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5518 Lisp_Object window;
5519 Lisp_Object buffer, start, pointm, mark;
5520 Lisp_Object left_col, top_line, total_cols, total_lines;
5521 Lisp_Object hscroll, min_hscroll;
5522 Lisp_Object parent, prev;
5523 Lisp_Object start_at_line_beg;
5524 Lisp_Object display_table;
5525 Lisp_Object orig_top_line, orig_total_lines;
5526 Lisp_Object left_margin_cols, right_margin_cols;
5527 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5528 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
5531 #define SAVED_WINDOW_VECTOR_SIZE 24 /* Arg to Fmake_vector */
5533 #define SAVED_WINDOW_N(swv,n) \
5534 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5536 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5537 doc: /* Return t if OBJECT is a window-configuration object. */)
5538 (object)
5539 Lisp_Object object;
5541 if (WINDOW_CONFIGURATIONP (object))
5542 return Qt;
5543 return Qnil;
5546 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5547 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5548 (config)
5549 Lisp_Object config;
5551 register struct save_window_data *data;
5552 struct Lisp_Vector *saved_windows;
5554 if (! WINDOW_CONFIGURATIONP (config))
5555 wrong_type_argument (Qwindow_configuration_p, config);
5557 data = (struct save_window_data *) XVECTOR (config);
5558 saved_windows = XVECTOR (data->saved_windows);
5559 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5562 DEFUN ("set-window-configuration", Fset_window_configuration,
5563 Sset_window_configuration, 1, 1, 0,
5564 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5565 CONFIGURATION must be a value previously returned
5566 by `current-window-configuration' (which see).
5567 If CONFIGURATION was made from a frame that is now deleted,
5568 only frame-independent values can be restored. In this case,
5569 the return value is nil. Otherwise the value is t. */)
5570 (configuration)
5571 Lisp_Object configuration;
5573 register struct save_window_data *data;
5574 struct Lisp_Vector *saved_windows;
5575 Lisp_Object new_current_buffer;
5576 Lisp_Object frame;
5577 FRAME_PTR f;
5578 int old_point = -1;
5580 while (!WINDOW_CONFIGURATIONP (configuration))
5581 wrong_type_argument (Qwindow_configuration_p, configuration);
5583 data = (struct save_window_data *) XVECTOR (configuration);
5584 saved_windows = XVECTOR (data->saved_windows);
5586 new_current_buffer = data->current_buffer;
5587 if (NILP (XBUFFER (new_current_buffer)->name))
5588 new_current_buffer = Qnil;
5589 else
5591 if (XBUFFER (new_current_buffer) == current_buffer)
5592 old_point = PT;
5593 else
5594 old_point = BUF_PT (XBUFFER (new_current_buffer));
5597 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5598 f = XFRAME (frame);
5600 /* If f is a dead frame, don't bother rebuilding its window tree.
5601 However, there is other stuff we should still try to do below. */
5602 if (FRAME_LIVE_P (f))
5604 register struct window *w;
5605 register struct saved_window *p;
5606 struct window *root_window;
5607 struct window **leaf_windows;
5608 int n_leaf_windows;
5609 int k, i, n;
5611 /* If the frame has been resized since this window configuration was
5612 made, we change the frame to the size specified in the
5613 configuration, restore the configuration, and then resize it
5614 back. We keep track of the prevailing height in these variables. */
5615 int previous_frame_lines = FRAME_LINES (f);
5616 int previous_frame_cols = FRAME_COLS (f);
5617 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5618 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5620 /* The mouse highlighting code could get screwed up
5621 if it runs during this. */
5622 BLOCK_INPUT;
5624 if (XFASTINT (data->frame_lines) != previous_frame_lines
5625 || XFASTINT (data->frame_cols) != previous_frame_cols)
5626 change_frame_size (f, XFASTINT (data->frame_lines),
5627 XFASTINT (data->frame_cols), 0, 0, 0);
5628 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5629 if (XFASTINT (data->frame_menu_bar_lines)
5630 != previous_frame_menu_bar_lines)
5631 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
5632 #ifdef HAVE_WINDOW_SYSTEM
5633 if (XFASTINT (data->frame_tool_bar_lines)
5634 != previous_frame_tool_bar_lines)
5635 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
5636 #endif
5637 #endif
5639 /* "Swap out" point from the selected window
5640 into its buffer. We do this now, before
5641 restoring the window contents, and prevent it from
5642 being done later on when we select a new window. */
5643 if (! NILP (XWINDOW (selected_window)->buffer))
5645 w = XWINDOW (selected_window);
5646 set_marker_both (w->pointm,
5647 w->buffer,
5648 BUF_PT (XBUFFER (w->buffer)),
5649 BUF_PT_BYTE (XBUFFER (w->buffer)));
5652 windows_or_buffers_changed++;
5653 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5655 /* Problem: Freeing all matrices and later allocating them again
5656 is a serious redisplay flickering problem. What we would
5657 really like to do is to free only those matrices not reused
5658 below. */
5659 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5660 leaf_windows
5661 = (struct window **) alloca (count_windows (root_window)
5662 * sizeof (struct window *));
5663 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5665 /* Temporarily avoid any problems with windows that are smaller
5666 than they are supposed to be. */
5667 window_min_height = 1;
5668 window_min_width = 1;
5670 /* Kludge Alert!
5671 Mark all windows now on frame as "deleted".
5672 Restoring the new configuration "undeletes" any that are in it.
5674 Save their current buffers in their height fields, since we may
5675 need it later, if a buffer saved in the configuration is now
5676 dead. */
5677 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5679 for (k = 0; k < saved_windows->size; k++)
5681 p = SAVED_WINDOW_N (saved_windows, k);
5682 w = XWINDOW (p->window);
5683 w->next = Qnil;
5685 if (!NILP (p->parent))
5686 w->parent = SAVED_WINDOW_N (saved_windows,
5687 XFASTINT (p->parent))->window;
5688 else
5689 w->parent = Qnil;
5691 if (!NILP (p->prev))
5693 w->prev = SAVED_WINDOW_N (saved_windows,
5694 XFASTINT (p->prev))->window;
5695 XWINDOW (w->prev)->next = p->window;
5697 else
5699 w->prev = Qnil;
5700 if (!NILP (w->parent))
5702 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
5704 XWINDOW (w->parent)->vchild = p->window;
5705 XWINDOW (w->parent)->hchild = Qnil;
5707 else
5709 XWINDOW (w->parent)->hchild = p->window;
5710 XWINDOW (w->parent)->vchild = Qnil;
5715 /* If we squirreled away the buffer in the window's height,
5716 restore it now. */
5717 if (BUFFERP (w->total_lines))
5718 w->buffer = w->total_lines;
5719 w->left_col = p->left_col;
5720 w->top_line = p->top_line;
5721 w->total_cols = p->total_cols;
5722 w->total_lines = p->total_lines;
5723 w->hscroll = p->hscroll;
5724 w->min_hscroll = p->min_hscroll;
5725 w->display_table = p->display_table;
5726 w->orig_top_line = p->orig_top_line;
5727 w->orig_total_lines = p->orig_total_lines;
5728 w->left_margin_cols = p->left_margin_cols;
5729 w->right_margin_cols = p->right_margin_cols;
5730 w->left_fringe_width = p->left_fringe_width;
5731 w->right_fringe_width = p->right_fringe_width;
5732 w->fringes_outside_margins = p->fringes_outside_margins;
5733 w->scroll_bar_width = p->scroll_bar_width;
5734 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
5735 XSETFASTINT (w->last_modified, 0);
5736 XSETFASTINT (w->last_overlay_modified, 0);
5738 /* Reinstall the saved buffer and pointers into it. */
5739 if (NILP (p->buffer))
5740 w->buffer = p->buffer;
5741 else
5743 if (!NILP (XBUFFER (p->buffer)->name))
5744 /* If saved buffer is alive, install it. */
5746 w->buffer = p->buffer;
5747 w->start_at_line_beg = p->start_at_line_beg;
5748 set_marker_restricted (w->start, p->start, w->buffer);
5749 set_marker_restricted (w->pointm, p->pointm, w->buffer);
5750 Fset_marker (XBUFFER (w->buffer)->mark,
5751 p->mark, w->buffer);
5753 /* As documented in Fcurrent_window_configuration, don't
5754 restore the location of point in the buffer which was
5755 current when the window configuration was recorded. */
5756 if (!EQ (p->buffer, new_current_buffer)
5757 && XBUFFER (p->buffer) == current_buffer)
5758 Fgoto_char (w->pointm);
5760 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
5761 /* Else unless window has a live buffer, get one. */
5763 w->buffer = Fcdr (Fcar (Vbuffer_alist));
5764 /* This will set the markers to beginning of visible
5765 range. */
5766 set_marker_restricted (w->start, make_number (0), w->buffer);
5767 set_marker_restricted (w->pointm, make_number (0),w->buffer);
5768 w->start_at_line_beg = Qt;
5770 else
5771 /* Keeping window's old buffer; make sure the markers
5772 are real. */
5774 /* Set window markers at start of visible range. */
5775 if (XMARKER (w->start)->buffer == 0)
5776 set_marker_restricted (w->start, make_number (0),
5777 w->buffer);
5778 if (XMARKER (w->pointm)->buffer == 0)
5779 set_marker_restricted_both (w->pointm, w->buffer,
5780 BUF_PT (XBUFFER (w->buffer)),
5781 BUF_PT_BYTE (XBUFFER (w->buffer)));
5782 w->start_at_line_beg = Qt;
5787 FRAME_ROOT_WINDOW (f) = data->root_window;
5788 /* Prevent "swapping out point" in the old selected window
5789 using the buffer that has been restored into it.
5790 Use the point value from the beginning of this function
5791 since unshow_buffer (called from delete_all_subwindows)
5792 could have altered it. */
5793 selected_window = Qnil;
5794 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5795 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5796 make_number (old_point),
5797 XWINDOW (data->current_window)->buffer);
5799 Fselect_window (data->current_window, Qnil);
5800 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
5801 = selected_window;
5803 if (NILP (data->focus_frame)
5804 || (FRAMEP (data->focus_frame)
5805 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5806 Fredirect_frame_focus (frame, data->focus_frame);
5808 #if 0 /* I don't understand why this is needed, and it causes problems
5809 when the frame's old selected window has been deleted. */
5810 if (f != selected_frame && FRAME_WINDOW_P (f))
5811 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
5812 0, 0);
5813 #endif
5815 /* Set the screen height to the value it had before this function. */
5816 if (previous_frame_lines != FRAME_LINES (f)
5817 || previous_frame_cols != FRAME_COLS (f))
5818 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5819 0, 0, 0);
5820 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5821 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5822 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5823 make_number (0));
5824 #ifdef HAVE_WINDOW_SYSTEM
5825 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5826 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5827 make_number (0));
5828 #endif
5829 #endif
5831 /* Now, free glyph matrices in windows that were not reused. */
5832 for (i = n = 0; i < n_leaf_windows; ++i)
5834 if (NILP (leaf_windows[i]->buffer))
5836 /* Assert it's not reused as a combination. */
5837 xassert (NILP (leaf_windows[i]->hchild)
5838 && NILP (leaf_windows[i]->vchild));
5839 free_window_matrices (leaf_windows[i]);
5841 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5842 ++n;
5845 adjust_glyphs (f);
5847 UNBLOCK_INPUT;
5849 /* Fselect_window will have made f the selected frame, so we
5850 reselect the proper frame here. Fhandle_switch_frame will change the
5851 selected window too, but that doesn't make the call to
5852 Fselect_window above totally superfluous; it still sets f's
5853 selected window. */
5854 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5855 do_switch_frame (data->selected_frame, 0, 0);
5857 if (! NILP (Vwindow_configuration_change_hook)
5858 && ! NILP (Vrun_hooks))
5859 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
5862 if (!NILP (new_current_buffer))
5863 Fset_buffer (new_current_buffer);
5865 /* Restore the minimum heights recorded in the configuration. */
5866 window_min_height = XINT (data->min_height);
5867 window_min_width = XINT (data->min_width);
5869 Vminibuf_scroll_window = data->minibuf_scroll_window;
5870 minibuf_selected_window = data->minibuf_selected_window;
5872 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5875 /* Mark all windows now on frame as deleted
5876 by setting their buffers to nil. */
5878 void
5879 delete_all_subwindows (w)
5880 register struct window *w;
5882 if (!NILP (w->next))
5883 delete_all_subwindows (XWINDOW (w->next));
5884 if (!NILP (w->vchild))
5885 delete_all_subwindows (XWINDOW (w->vchild));
5886 if (!NILP (w->hchild))
5887 delete_all_subwindows (XWINDOW (w->hchild));
5889 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
5891 if (!NILP (w->buffer))
5892 unshow_buffer (w);
5894 /* We set all three of these fields to nil, to make sure that we can
5895 distinguish this dead window from any live window. Live leaf
5896 windows will have buffer set, and combination windows will have
5897 vchild or hchild set. */
5898 w->buffer = Qnil;
5899 w->vchild = Qnil;
5900 w->hchild = Qnil;
5902 Vwindow_list = Qnil;
5905 static int
5906 count_windows (window)
5907 register struct window *window;
5909 register int count = 1;
5910 if (!NILP (window->next))
5911 count += count_windows (XWINDOW (window->next));
5912 if (!NILP (window->vchild))
5913 count += count_windows (XWINDOW (window->vchild));
5914 if (!NILP (window->hchild))
5915 count += count_windows (XWINDOW (window->hchild));
5916 return count;
5920 /* Fill vector FLAT with leaf windows under W, starting at index I.
5921 Value is last index + 1. */
5923 static int
5924 get_leaf_windows (w, flat, i)
5925 struct window *w;
5926 struct window **flat;
5927 int i;
5929 while (w)
5931 if (!NILP (w->hchild))
5932 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5933 else if (!NILP (w->vchild))
5934 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5935 else
5936 flat[i++] = w;
5938 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5941 return i;
5945 /* Return a pointer to the glyph W's physical cursor is on. Value is
5946 null if W's current matrix is invalid, so that no meaningfull glyph
5947 can be returned. */
5949 struct glyph *
5950 get_phys_cursor_glyph (w)
5951 struct window *w;
5953 struct glyph_row *row;
5954 struct glyph *glyph;
5956 if (w->phys_cursor.vpos >= 0
5957 && w->phys_cursor.vpos < w->current_matrix->nrows
5958 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
5959 row->enabled_p)
5960 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
5961 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
5962 else
5963 glyph = NULL;
5965 return glyph;
5969 static int
5970 save_window_save (window, vector, i)
5971 Lisp_Object window;
5972 struct Lisp_Vector *vector;
5973 int i;
5975 register struct saved_window *p;
5976 register struct window *w;
5977 register Lisp_Object tem;
5979 for (;!NILP (window); window = w->next)
5981 p = SAVED_WINDOW_N (vector, i);
5982 w = XWINDOW (window);
5984 XSETFASTINT (w->temslot, i); i++;
5985 p->window = window;
5986 p->buffer = w->buffer;
5987 p->left_col = w->left_col;
5988 p->top_line = w->top_line;
5989 p->total_cols = w->total_cols;
5990 p->total_lines = w->total_lines;
5991 p->hscroll = w->hscroll;
5992 p->min_hscroll = w->min_hscroll;
5993 p->display_table = w->display_table;
5994 p->orig_top_line = w->orig_top_line;
5995 p->orig_total_lines = w->orig_total_lines;
5996 p->left_margin_cols = w->left_margin_cols;
5997 p->right_margin_cols = w->right_margin_cols;
5998 p->left_fringe_width = w->left_fringe_width;
5999 p->right_fringe_width = w->right_fringe_width;
6000 p->fringes_outside_margins = w->fringes_outside_margins;
6001 p->scroll_bar_width = w->scroll_bar_width;
6002 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6003 if (!NILP (w->buffer))
6005 /* Save w's value of point in the window configuration.
6006 If w is the selected window, then get the value of point
6007 from the buffer; pointm is garbage in the selected window. */
6008 if (EQ (window, selected_window))
6010 p->pointm = Fmake_marker ();
6011 set_marker_both (p->pointm, w->buffer,
6012 BUF_PT (XBUFFER (w->buffer)),
6013 BUF_PT_BYTE (XBUFFER (w->buffer)));
6015 else
6016 p->pointm = Fcopy_marker (w->pointm, Qnil);
6018 p->start = Fcopy_marker (w->start, Qnil);
6019 p->start_at_line_beg = w->start_at_line_beg;
6021 tem = XBUFFER (w->buffer)->mark;
6022 p->mark = Fcopy_marker (tem, Qnil);
6024 else
6026 p->pointm = Qnil;
6027 p->start = Qnil;
6028 p->mark = Qnil;
6029 p->start_at_line_beg = Qnil;
6032 if (NILP (w->parent))
6033 p->parent = Qnil;
6034 else
6035 p->parent = XWINDOW (w->parent)->temslot;
6037 if (NILP (w->prev))
6038 p->prev = Qnil;
6039 else
6040 p->prev = XWINDOW (w->prev)->temslot;
6042 if (!NILP (w->vchild))
6043 i = save_window_save (w->vchild, vector, i);
6044 if (!NILP (w->hchild))
6045 i = save_window_save (w->hchild, vector, i);
6048 return i;
6051 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6052 Scurrent_window_configuration, 0, 1, 0,
6053 doc: /* Return an object representing the current window configuration of FRAME.
6054 If FRAME is nil or omitted, use the selected frame.
6055 This describes the number of windows, their sizes and current buffers,
6056 and for each displayed buffer, where display starts, and the positions of
6057 point and mark. An exception is made for point in the current buffer:
6058 its value is -not- saved.
6059 This also records the currently selected frame, and FRAME's focus
6060 redirection (see `redirect-frame-focus'). */)
6061 (frame)
6062 Lisp_Object frame;
6064 register Lisp_Object tem;
6065 register int n_windows;
6066 register struct save_window_data *data;
6067 register struct Lisp_Vector *vec;
6068 register int i;
6069 FRAME_PTR f;
6071 if (NILP (frame))
6072 frame = selected_frame;
6073 CHECK_LIVE_FRAME (frame);
6074 f = XFRAME (frame);
6076 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6077 vec = allocate_other_vector (VECSIZE (struct save_window_data));
6078 data = (struct save_window_data *)vec;
6080 XSETFASTINT (data->frame_cols, FRAME_COLS (f));
6081 XSETFASTINT (data->frame_lines, FRAME_LINES (f));
6082 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
6083 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
6084 data->selected_frame = selected_frame;
6085 data->current_window = FRAME_SELECTED_WINDOW (f);
6086 XSETBUFFER (data->current_buffer, current_buffer);
6087 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6088 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6089 data->root_window = FRAME_ROOT_WINDOW (f);
6090 data->focus_frame = FRAME_FOCUS_FRAME (f);
6091 XSETINT (data->min_height, window_min_height);
6092 XSETINT (data->min_width, window_min_width);
6093 tem = Fmake_vector (make_number (n_windows), Qnil);
6094 data->saved_windows = tem;
6095 for (i = 0; i < n_windows; i++)
6096 XVECTOR (tem)->contents[i]
6097 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
6098 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6099 XSETWINDOW_CONFIGURATION (tem, data);
6100 return (tem);
6103 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
6104 0, UNEVALLED, 0,
6105 doc: /* Execute BODY, preserving window sizes and contents.
6106 Return the value of the last form in BODY.
6107 Restore which buffer appears in which window, where display starts,
6108 and the value of point and mark for each window.
6109 Also restore the choice of selected window.
6110 Also restore which buffer is current.
6111 Does not restore the value of point in current buffer.
6112 usage: (save-window-excursion BODY ...) */)
6113 (args)
6114 Lisp_Object args;
6116 register Lisp_Object val;
6117 register int count = SPECPDL_INDEX ();
6119 record_unwind_protect (Fset_window_configuration,
6120 Fcurrent_window_configuration (Qnil));
6121 val = Fprogn (args);
6122 return unbind_to (count, val);
6126 /***********************************************************************
6127 Marginal Areas
6128 ***********************************************************************/
6130 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6131 2, 3, 0,
6132 doc: /* Set width of marginal areas of window WINDOW.
6133 If WINDOW is nil, set margins of the currently selected window.
6134 Second arg LEFT-WIDTH specifies the number of character cells to
6135 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6136 does the same for the right marginal area. A nil width parameter
6137 means no margin. */)
6138 (window, left, right)
6139 Lisp_Object window, left, right;
6141 struct window *w = decode_window (window);
6143 /* Translate negative or zero widths to nil.
6144 Margins that are too wide have to be checked elsewhere. */
6146 if (!NILP (left))
6148 CHECK_NUMBER (left);
6149 if (XINT (left) <= 0)
6150 left = Qnil;
6153 if (!NILP (right))
6155 CHECK_NUMBER (right);
6156 if (XINT (right) <= 0)
6157 right = Qnil;
6160 if (!EQ (w->left_margin_cols, left)
6161 || !EQ (w->right_margin_cols, right))
6163 w->left_margin_cols = left;
6164 w->right_margin_cols = right;
6166 adjust_window_margins (w);
6168 ++windows_or_buffers_changed;
6169 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6172 return Qnil;
6176 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6177 0, 1, 0,
6178 doc: /* Get width of marginal areas of window WINDOW.
6179 If WINDOW is omitted or nil, use the currently selected window.
6180 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6181 If a marginal area does not exist, its width will be returned
6182 as nil. */)
6183 (window)
6184 Lisp_Object window;
6186 struct window *w = decode_window (window);
6187 return Fcons (w->left_margin_cols, w->right_margin_cols);
6192 /***********************************************************************
6193 Fringes
6194 ***********************************************************************/
6196 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6197 2, 4, 0,
6198 doc: /* Set the fringe widths of window WINDOW.
6199 If WINDOW is nil, set the fringe widths of the currently selected
6200 window.
6201 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6202 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6203 fringe width. If a fringe width arg is nil, that means to use the
6204 frame's default fringe width. Default fringe widths can be set with
6205 the command `set-fringe-style'.
6206 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6207 outside of the display margins. By default, fringes are drawn between
6208 display marginal areas and the text area. */)
6209 (window, left, right, outside_margins)
6210 Lisp_Object window, left, right, outside_margins;
6212 struct window *w = decode_window (window);
6214 if (!NILP (left))
6215 CHECK_NATNUM (left);
6216 if (!NILP (right))
6217 CHECK_NATNUM (right);
6219 if (!EQ (w->left_fringe_width, left)
6220 || !EQ (w->right_fringe_width, right)
6221 || !EQ (w->fringes_outside_margins, outside_margins))
6223 w->left_fringe_width = left;
6224 w->right_fringe_width = right;
6225 w->fringes_outside_margins = outside_margins;
6227 adjust_window_margins (w);
6229 clear_glyph_matrix (w->current_matrix);
6230 w->window_end_valid = Qnil;
6232 ++windows_or_buffers_changed;
6233 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6236 return Qnil;
6240 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6241 0, 1, 0,
6242 doc: /* Get width of fringes of window WINDOW.
6243 If WINDOW is omitted or nil, use the currently selected window.
6244 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6245 (window)
6246 Lisp_Object window;
6248 struct window *w = decode_window (window);
6249 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6250 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6251 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ?
6252 Qt : Qnil), Qnil)));
6257 /***********************************************************************
6258 Scroll bars
6259 ***********************************************************************/
6261 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6262 2, 4, 0,
6263 doc: /* Set width and type of scroll bars of window WINDOW.
6264 If window is nil, set scroll bars of the currently selected window.
6265 Second parameter WIDTH specifies the pixel width for the scroll bar;
6266 this is automatically adjusted to a multiple of the frame column width.
6267 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6268 bar: left, right, or nil.
6269 If WIDTH is nil, use the frame's scroll-bar width.
6270 If TYPE is t, use the frame's scroll-bar type. */)
6271 (window, width, vertical_type, horizontal_type)
6272 Lisp_Object window, width, vertical_type, horizontal_type;
6274 struct window *w = decode_window (window);
6276 if (!NILP (width))
6278 CHECK_NATNUM (width);
6280 if (XINT (width) == 0)
6281 vertical_type = Qnil;
6284 if (!(EQ (vertical_type, Qnil)
6285 || EQ (vertical_type, Qleft)
6286 || EQ (vertical_type, Qright)
6287 || EQ (vertical_type, Qt)))
6288 error ("Invalid type of vertical scroll bar");
6290 if (!EQ (w->scroll_bar_width, width)
6291 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6293 w->scroll_bar_width = width;
6294 w->vertical_scroll_bar_type = vertical_type;
6296 adjust_window_margins (w);
6298 clear_glyph_matrix (w->current_matrix);
6299 w->window_end_valid = Qnil;
6301 ++windows_or_buffers_changed;
6302 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6305 return Qnil;
6309 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6310 0, 1, 0,
6311 doc: /* Get width and type of scroll bars of window WINDOW.
6312 If WINDOW is omitted or nil, use the currently selected window.
6313 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6314 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6315 value. */)
6316 (window)
6317 Lisp_Object window;
6319 struct window *w = decode_window (window);
6320 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6321 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6322 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6323 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6324 Fcons (w->vertical_scroll_bar_type,
6325 Fcons (Qnil, Qnil))));
6330 /***********************************************************************
6331 Smooth scrolling
6332 ***********************************************************************/
6334 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6335 doc: /* Return the amount by which WINDOW is scrolled vertically.
6336 Use the selected window if WINDOW is nil or omitted.
6337 Normally, value is a multiple of the canonical character height of WINDOW;
6338 optional second arg PIXELS_P means value is measured in pixels. */)
6339 (window, pixels_p)
6340 Lisp_Object window, pixels_p;
6342 Lisp_Object result;
6343 struct frame *f;
6344 struct window *w;
6346 if (NILP (window))
6347 window = selected_window;
6348 else
6349 CHECK_WINDOW (window);
6350 w = XWINDOW (window);
6351 f = XFRAME (w->frame);
6353 if (FRAME_WINDOW_P (f))
6354 result = (NILP (pixels_p)
6355 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6356 : make_number (-w->vscroll));
6357 else
6358 result = make_number (0);
6359 return result;
6363 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6364 2, 3, 0,
6365 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6366 WINDOW nil means use the selected window. Normally, VSCROLL is a
6367 non-negative multiple of the canonical character height of WINDOW;
6368 optional third arg PIXELS_P non-nil means that VSCROLL is in pixels.
6369 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6370 corresponds to an integral number of pixels. The return value is the
6371 result of this rounding.
6372 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6373 (window, vscroll, pixels_p)
6374 Lisp_Object window, vscroll, pixels_p;
6376 struct window *w;
6377 struct frame *f;
6379 if (NILP (window))
6380 window = selected_window;
6381 else
6382 CHECK_WINDOW (window);
6383 CHECK_NUMBER_OR_FLOAT (vscroll);
6385 w = XWINDOW (window);
6386 f = XFRAME (w->frame);
6388 if (FRAME_WINDOW_P (f))
6390 int old_dy = w->vscroll;
6392 w->vscroll = - (NILP (pixels_p)
6393 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6394 : XFLOATINT (vscroll));
6395 w->vscroll = min (w->vscroll, 0);
6397 if (w->vscroll != old_dy)
6399 /* Adjust glyph matrix of the frame if the virtual display
6400 area becomes larger than before. */
6401 if (w->vscroll < 0 && w->vscroll < old_dy)
6402 adjust_glyphs (f);
6404 /* Prevent redisplay shortcuts. */
6405 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6409 return Fwindow_vscroll (window, pixels_p);
6413 /* Call FN for all leaf windows on frame F. FN is called with the
6414 first argument being a pointer to the leaf window, and with
6415 additional argument USER_DATA. Stops when FN returns 0. */
6417 void
6418 foreach_window (f, fn, user_data)
6419 struct frame *f;
6420 int (* fn) P_ ((struct window *, void *));
6421 void *user_data;
6423 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6427 /* Helper function for foreach_window. Call FN for all leaf windows
6428 reachable from W. FN is called with the first argument being a
6429 pointer to the leaf window, and with additional argument USER_DATA.
6430 Stop when FN returns 0. Value is 0 if stopped by FN. */
6432 static int
6433 foreach_window_1 (w, fn, user_data)
6434 struct window *w;
6435 int (* fn) P_ ((struct window *, void *));
6436 void *user_data;
6438 int cont;
6440 for (cont = 1; w && cont;)
6442 if (!NILP (w->hchild))
6443 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6444 else if (!NILP (w->vchild))
6445 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6446 else
6447 cont = fn (w, user_data);
6449 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6452 return cont;
6456 /* Freeze or unfreeze the window start of W unless it is a
6457 mini-window or the selected window. FREEZE_P non-null means freeze
6458 the window start. */
6460 static int
6461 freeze_window_start (w, freeze_p)
6462 struct window *w;
6463 void *freeze_p;
6465 if (w == XWINDOW (selected_window)
6466 || MINI_WINDOW_P (w)
6467 || (MINI_WINDOW_P (XWINDOW (selected_window))
6468 && ! NILP (Vminibuf_scroll_window)
6469 && w == XWINDOW (Vminibuf_scroll_window)))
6470 freeze_p = NULL;
6472 w->frozen_window_start_p = freeze_p != NULL;
6473 return 1;
6477 /* Freeze or unfreeze the window starts of all leaf windows on frame
6478 F, except the selected window and a mini-window. FREEZE_P non-zero
6479 means freeze the window start. */
6481 void
6482 freeze_window_starts (f, freeze_p)
6483 struct frame *f;
6484 int freeze_p;
6486 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6490 /***********************************************************************
6491 Initialization
6492 ***********************************************************************/
6494 /* Return 1 if window configurations C1 and C2
6495 describe the same state of affairs. This is used by Fequal. */
6498 compare_window_configurations (c1, c2, ignore_positions)
6499 Lisp_Object c1, c2;
6500 int ignore_positions;
6502 register struct save_window_data *d1, *d2;
6503 struct Lisp_Vector *sw1, *sw2;
6504 int i;
6506 if (!WINDOW_CONFIGURATIONP (c1))
6507 wrong_type_argument (Qwindow_configuration_p, c1);
6508 if (!WINDOW_CONFIGURATIONP (c2))
6509 wrong_type_argument (Qwindow_configuration_p, c2);
6511 d1 = (struct save_window_data *) XVECTOR (c1);
6512 d2 = (struct save_window_data *) XVECTOR (c2);
6513 sw1 = XVECTOR (d1->saved_windows);
6514 sw2 = XVECTOR (d2->saved_windows);
6516 if (! EQ (d1->frame_cols, d2->frame_cols))
6517 return 0;
6518 if (! EQ (d1->frame_lines, d2->frame_lines))
6519 return 0;
6520 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
6521 return 0;
6522 if (! EQ (d1->selected_frame, d2->selected_frame))
6523 return 0;
6524 /* Don't compare the current_window field directly.
6525 Instead see w1_is_current and w2_is_current, below. */
6526 if (! EQ (d1->current_buffer, d2->current_buffer))
6527 return 0;
6528 if (! ignore_positions)
6530 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
6531 return 0;
6532 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
6533 return 0;
6535 /* Don't compare the root_window field.
6536 We don't require the two configurations
6537 to use the same window object,
6538 and the two root windows must be equivalent
6539 if everything else compares equal. */
6540 if (! EQ (d1->focus_frame, d2->focus_frame))
6541 return 0;
6542 if (! EQ (d1->min_width, d2->min_width))
6543 return 0;
6544 if (! EQ (d1->min_height, d2->min_height))
6545 return 0;
6547 /* Verify that the two confis have the same number of windows. */
6548 if (sw1->size != sw2->size)
6549 return 0;
6551 for (i = 0; i < sw1->size; i++)
6553 struct saved_window *p1, *p2;
6554 int w1_is_current, w2_is_current;
6556 p1 = SAVED_WINDOW_N (sw1, i);
6557 p2 = SAVED_WINDOW_N (sw2, i);
6559 /* Verify that the current windows in the two
6560 configurations correspond to each other. */
6561 w1_is_current = EQ (d1->current_window, p1->window);
6562 w2_is_current = EQ (d2->current_window, p2->window);
6564 if (w1_is_current != w2_is_current)
6565 return 0;
6567 /* Verify that the corresponding windows do match. */
6568 if (! EQ (p1->buffer, p2->buffer))
6569 return 0;
6570 if (! EQ (p1->left_col, p2->left_col))
6571 return 0;
6572 if (! EQ (p1->top_line, p2->top_line))
6573 return 0;
6574 if (! EQ (p1->total_cols, p2->total_cols))
6575 return 0;
6576 if (! EQ (p1->total_lines, p2->total_lines))
6577 return 0;
6578 if (! EQ (p1->display_table, p2->display_table))
6579 return 0;
6580 if (! EQ (p1->parent, p2->parent))
6581 return 0;
6582 if (! EQ (p1->prev, p2->prev))
6583 return 0;
6584 if (! ignore_positions)
6586 if (! EQ (p1->hscroll, p2->hscroll))
6587 return 0;
6588 if (!EQ (p1->min_hscroll, p2->min_hscroll))
6589 return 0;
6590 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
6591 return 0;
6592 if (NILP (Fequal (p1->start, p2->start)))
6593 return 0;
6594 if (NILP (Fequal (p1->pointm, p2->pointm)))
6595 return 0;
6596 if (NILP (Fequal (p1->mark, p2->mark)))
6597 return 0;
6599 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
6600 return 0;
6601 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
6602 return 0;
6603 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
6604 return 0;
6605 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
6606 return 0;
6607 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
6608 return 0;
6609 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
6610 return 0;
6611 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
6612 return 0;
6615 return 1;
6618 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6619 Scompare_window_configurations, 2, 2, 0,
6620 doc: /* Compare two window configurations as regards the structure of windows.
6621 This function ignores details such as the values of point and mark
6622 and scrolling positions. */)
6623 (x, y)
6624 Lisp_Object x, y;
6626 if (compare_window_configurations (x, y, 1))
6627 return Qt;
6628 return Qnil;
6631 void
6632 init_window_once ()
6634 struct frame *f = make_terminal_frame ();
6635 XSETFRAME (selected_frame, f);
6636 Vterminal_frame = selected_frame;
6637 minibuf_window = f->minibuffer_window;
6638 selected_window = f->selected_window;
6639 last_nonminibuf_frame = f;
6641 window_initialized = 1;
6644 void
6645 init_window ()
6647 Vwindow_list = Qnil;
6650 void
6651 syms_of_window ()
6653 Qwindow_size_fixed = intern ("window-size-fixed");
6654 staticpro (&Qwindow_size_fixed);
6656 staticpro (&Qwindow_configuration_change_hook);
6657 Qwindow_configuration_change_hook
6658 = intern ("window-configuration-change-hook");
6660 Qwindowp = intern ("windowp");
6661 staticpro (&Qwindowp);
6663 Qwindow_configuration_p = intern ("window-configuration-p");
6664 staticpro (&Qwindow_configuration_p);
6666 Qwindow_live_p = intern ("window-live-p");
6667 staticpro (&Qwindow_live_p);
6669 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
6670 staticpro (&Qtemp_buffer_show_hook);
6672 staticpro (&Vwindow_list);
6674 minibuf_selected_window = Qnil;
6675 staticpro (&minibuf_selected_window);
6677 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
6678 doc: /* Non-nil means call as function to display a help buffer.
6679 The function is called with one argument, the buffer to be displayed.
6680 Used by `with-output-to-temp-buffer'.
6681 If this function is used, then it must do the entire job of showing
6682 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6683 Vtemp_buffer_show_function = Qnil;
6685 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
6686 doc: /* If non-nil, function to call to handle `display-buffer'.
6687 It will receive two args, the buffer and a flag which if non-nil means
6688 that the currently selected window is not acceptable.
6689 It should choose or create a window, display the specified buffer in it,
6690 and return the window.
6691 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
6692 work using this function. */);
6693 Vdisplay_buffer_function = Qnil;
6695 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
6696 doc: /* *If non-nil, `display-buffer' should even the window heights.
6697 If nil, `display-buffer' will leave the window configuration alone. */);
6698 Veven_window_heights = Qt;
6700 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
6701 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6702 Vminibuf_scroll_window = Qnil;
6704 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
6705 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6706 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6707 is displayed in the `mode-line' face. */);
6708 mode_line_in_non_selected_windows = 1;
6710 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
6711 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6712 Vother_window_scroll_buffer = Qnil;
6714 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
6715 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
6716 pop_up_frames = 0;
6718 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
6719 doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
6720 auto_window_vscroll_p = 1;
6722 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
6723 doc: /* *Non-nil means `display-buffer' should reuse frames.
6724 If the buffer in question is already displayed in a frame, raise that frame. */);
6725 display_buffer_reuse_frames = 0;
6727 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
6728 doc: /* Function to call to handle automatic new frame creation.
6729 It is called with no arguments and should return a newly created frame.
6731 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
6732 where `pop-up-frame-alist' would hold the default frame parameters. */);
6733 Vpop_up_frame_function = Qnil;
6735 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
6736 doc: /* *List of buffer names that should have their own special frames.
6737 Displaying a buffer whose name is in this list makes a special frame for it
6738 using `special-display-function'. See also `special-display-regexps'.
6740 An element of the list can be a list instead of just a string.
6741 There are two ways to use a list as an element:
6742 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
6743 In the first case, the FRAME-PARAMETERS are pairs of the form
6744 \(PARAMETER . VALUE); these parameter values are used to create the frame.
6745 In the second case, FUNCTION is called with BUFFER as the first argument,
6746 followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
6747 All this is done by the function found in `special-display-function'.
6749 If the specified frame parameters include (same-buffer . t), the
6750 buffer is displayed in the currently selected window. Otherwise, if
6751 they include (same-frame . t), the buffer is displayed in a new window
6752 in the currently selected frame.
6754 If this variable appears \"not to work\", because you add a name to it
6755 but that buffer still appears in the selected window, look at the
6756 values of `same-window-buffer-names' and `same-window-regexps'.
6757 Those variables take precedence over this one. */);
6758 Vspecial_display_buffer_names = Qnil;
6760 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
6761 doc: /* *List of regexps saying which buffers should have their own special frames.
6762 If a buffer name matches one of these regexps, it gets its own frame.
6763 Displaying a buffer whose name is in this list makes a special frame for it
6764 using `special-display-function'.
6766 An element of the list can be a list instead of just a string.
6767 There are two ways to use a list as an element:
6768 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
6769 In the first case, the FRAME-PARAMETERS are pairs of the form
6770 \(PARAMETER . VALUE); these parameter values are used to create the frame.
6771 In the second case, FUNCTION is called with BUFFER as the first argument,
6772 followed by the OTHER-ARGS--it can display the buffer in any way it likes.
6773 All this is done by the function found in `special-display-function'.
6775 If the specified frame parameters include (same-buffer . t), the
6776 buffer is displayed in the currently selected window. Otherwise, if
6777 they include (same-frame . t), the buffer is displayed in a new window
6778 in the currently selected frame.
6780 If this variable appears \"not to work\", because you add a regexp to it
6781 but the matching buffers still appear in the selected window, look at the
6782 values of `same-window-buffer-names' and `same-window-regexps'.
6783 Those variables take precedence over this one. */);
6784 Vspecial_display_regexps = Qnil;
6786 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
6787 doc: /* Function to call to make a new frame for a special buffer.
6788 It is called with two arguments, the buffer and optional buffer specific
6789 data, and should return a window displaying that buffer.
6790 The default value normally makes a separate frame for the buffer,
6791 using `special-display-frame-alist' to specify the frame parameters.
6792 But if the buffer specific data includes (same-buffer . t) then the
6793 buffer is displayed in the current selected window.
6794 Otherwise if it includes (same-frame . t) then the buffer is displayed in
6795 a new window in the currently selected frame.
6797 A buffer is special if it is listed in `special-display-buffer-names'
6798 or matches a regexp in `special-display-regexps'. */);
6799 Vspecial_display_function = Qnil;
6801 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
6802 doc: /* *List of buffer names that should appear in the selected window.
6803 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
6804 switches to it in the selected window, rather than making it appear
6805 in some other window.
6807 An element of the list can be a cons cell instead of just a string.
6808 Then the car must be a string, which specifies the buffer name.
6809 This is for compatibility with `special-display-buffer-names';
6810 the cdr of the cons cell is ignored.
6812 See also `same-window-regexps'. */);
6813 Vsame_window_buffer_names = Qnil;
6815 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
6816 doc: /* *List of regexps saying which buffers should appear in the selected window.
6817 If a buffer name matches one of these regexps, then displaying it
6818 using `display-buffer' or `pop-to-buffer' switches to it
6819 in the selected window, rather than making it appear in some other window.
6821 An element of the list can be a cons cell instead of just a string.
6822 Then the car must be a string, which specifies the buffer name.
6823 This is for compatibility with `special-display-buffer-names';
6824 the cdr of the cons cell is ignored.
6826 See also `same-window-buffer-names'. */);
6827 Vsame_window_regexps = Qnil;
6829 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
6830 doc: /* *Non-nil means display-buffer should make new windows. */);
6831 pop_up_windows = 1;
6833 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
6834 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
6835 next_screen_context_lines = 2;
6837 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
6838 doc: /* *A window must be at least this tall to be eligible for splitting by `display-buffer'.
6839 If there is only one window, it is split regardless of this value. */);
6840 split_height_threshold = 500;
6842 DEFVAR_INT ("window-min-height", &window_min_height,
6843 doc: /* *Delete any window less than this tall (including its mode line). */);
6844 window_min_height = 4;
6846 DEFVAR_INT ("window-min-width", &window_min_width,
6847 doc: /* *Delete any window less than this wide. */);
6848 window_min_width = 10;
6850 DEFVAR_LISP ("scroll-preserve-screen-position",
6851 &Vscroll_preserve_screen_position,
6852 doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged.
6853 This is only when it is impossible to keep point fixed and still
6854 scroll as specified. */);
6855 Vscroll_preserve_screen_position = Qnil;
6857 DEFVAR_LISP ("window-configuration-change-hook",
6858 &Vwindow_configuration_change_hook,
6859 doc: /* Functions to call when window configuration changes.
6860 The selected frame is the one whose configuration has changed. */);
6861 Vwindow_configuration_change_hook = Qnil;
6863 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed,
6864 doc: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
6865 If the value is`height', then only the window's height is fixed.
6866 If the value is `width', then only the window's width is fixed.
6867 Any other non-nil value fixes both the width and the height.
6868 Emacs won't change the size of any window displaying that buffer,
6869 unless you explicitly change the size, or Emacs has no other choice. */);
6870 Fmake_variable_buffer_local (Qwindow_size_fixed);
6871 window_size_fixed = 0;
6873 defsubr (&Sselected_window);
6874 defsubr (&Sminibuffer_window);
6875 defsubr (&Swindow_minibuffer_p);
6876 defsubr (&Swindowp);
6877 defsubr (&Swindow_live_p);
6878 defsubr (&Spos_visible_in_window_p);
6879 defsubr (&Swindow_buffer);
6880 defsubr (&Swindow_height);
6881 defsubr (&Swindow_width);
6882 defsubr (&Swindow_hscroll);
6883 defsubr (&Sset_window_hscroll);
6884 defsubr (&Swindow_redisplay_end_trigger);
6885 defsubr (&Sset_window_redisplay_end_trigger);
6886 defsubr (&Swindow_edges);
6887 defsubr (&Swindow_pixel_edges);
6888 defsubr (&Swindow_inside_edges);
6889 defsubr (&Swindow_inside_pixel_edges);
6890 defsubr (&Scoordinates_in_window_p);
6891 defsubr (&Swindow_at);
6892 defsubr (&Swindow_point);
6893 defsubr (&Swindow_start);
6894 defsubr (&Swindow_end);
6895 defsubr (&Sset_window_point);
6896 defsubr (&Sset_window_start);
6897 defsubr (&Swindow_dedicated_p);
6898 defsubr (&Sset_window_dedicated_p);
6899 defsubr (&Swindow_display_table);
6900 defsubr (&Sset_window_display_table);
6901 defsubr (&Snext_window);
6902 defsubr (&Sprevious_window);
6903 defsubr (&Sother_window);
6904 defsubr (&Sget_lru_window);
6905 defsubr (&Sget_largest_window);
6906 defsubr (&Sget_buffer_window);
6907 defsubr (&Sdelete_other_windows);
6908 defsubr (&Sdelete_windows_on);
6909 defsubr (&Sreplace_buffer_in_windows);
6910 defsubr (&Sdelete_window);
6911 defsubr (&Sset_window_buffer);
6912 defsubr (&Sselect_window);
6913 defsubr (&Sspecial_display_p);
6914 defsubr (&Ssame_window_p);
6915 defsubr (&Sdisplay_buffer);
6916 defsubr (&Sforce_window_update);
6917 defsubr (&Ssplit_window);
6918 defsubr (&Senlarge_window);
6919 defsubr (&Sshrink_window);
6920 defsubr (&Sscroll_up);
6921 defsubr (&Sscroll_down);
6922 defsubr (&Sscroll_left);
6923 defsubr (&Sscroll_right);
6924 defsubr (&Sother_window_for_scrolling);
6925 defsubr (&Sscroll_other_window);
6926 defsubr (&Sminibuffer_selected_window);
6927 defsubr (&Srecenter);
6928 defsubr (&Swindow_text_height);
6929 defsubr (&Smove_to_window_line);
6930 defsubr (&Swindow_configuration_p);
6931 defsubr (&Swindow_configuration_frame);
6932 defsubr (&Sset_window_configuration);
6933 defsubr (&Scurrent_window_configuration);
6934 defsubr (&Ssave_window_excursion);
6935 defsubr (&Sset_window_margins);
6936 defsubr (&Swindow_margins);
6937 defsubr (&Sset_window_fringes);
6938 defsubr (&Swindow_fringes);
6939 defsubr (&Sset_window_scroll_bars);
6940 defsubr (&Swindow_scroll_bars);
6941 defsubr (&Swindow_vscroll);
6942 defsubr (&Sset_window_vscroll);
6943 defsubr (&Scompare_window_configurations);
6944 defsubr (&Swindow_list);
6947 void
6948 keys_of_window ()
6950 initial_define_key (control_x_map, '1', "delete-other-windows");
6951 initial_define_key (control_x_map, '2', "split-window");
6952 initial_define_key (control_x_map, '0', "delete-window");
6953 initial_define_key (control_x_map, 'o', "other-window");
6954 initial_define_key (control_x_map, '^', "enlarge-window");
6955 initial_define_key (control_x_map, '<', "scroll-left");
6956 initial_define_key (control_x_map, '>', "scroll-right");
6958 initial_define_key (global_map, Ctl ('V'), "scroll-up");
6959 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6960 initial_define_key (meta_map, 'v', "scroll-down");
6962 initial_define_key (global_map, Ctl('L'), "recenter");
6963 initial_define_key (meta_map, 'r', "move-to-window-line");
6966 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
6967 (do not change this comment) */