* help.el (describe-key): Handle string and vector `follow-link' values.
[emacs.git] / src / window.c
blobcd7c1e6a6256ef87d09c01ba9a9cf9bf28dd65c5
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
4 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
23 #include <config.h>
24 #include "lisp.h"
25 #include "buffer.h"
26 #include "keyboard.h"
27 #include "keymap.h"
28 #include "frame.h"
29 #include "window.h"
30 #include "commands.h"
31 #include "indent.h"
32 #include "termchar.h"
33 #include "disptab.h"
34 #include "dispextern.h"
35 #include "blockinput.h"
36 #include "intervals.h"
38 #ifdef HAVE_X_WINDOWS
39 #include "xterm.h"
40 #endif /* HAVE_X_WINDOWS */
41 #ifdef WINDOWSNT
42 #include "w32term.h"
43 #endif
44 #ifdef MSDOS
45 #include "msdos.h"
46 #endif
47 #ifdef MAC_OS
48 #include "macterm.h"
49 #endif
52 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
53 Lisp_Object Qscroll_up, Qscroll_down;
54 Lisp_Object Qwindow_size_fixed;
55 extern Lisp_Object Qleft_margin, Qright_margin;
57 static int displayed_window_lines P_ ((struct window *));
58 static struct window *decode_window P_ ((Lisp_Object));
59 static int count_windows P_ ((struct window *));
60 static int get_leaf_windows P_ ((struct window *, struct window **, int));
61 static void window_scroll P_ ((Lisp_Object, int, int, int));
62 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
63 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
64 static int window_min_size_1 P_ ((struct window *, int));
65 static int window_min_size P_ ((struct window *, int, int, int *));
66 static void size_window P_ ((Lisp_Object, int, int, int));
67 static int freeze_window_start P_ ((struct window *, void *));
68 static int window_fixed_size_p P_ ((struct window *, int, int));
69 static void enlarge_window P_ ((Lisp_Object, int, int));
70 static Lisp_Object window_list P_ ((void));
71 static int add_window_to_list P_ ((struct window *, void *));
72 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
73 Lisp_Object));
74 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
75 Lisp_Object, int));
76 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
77 Lisp_Object *));
78 static int foreach_window_1 P_ ((struct window *,
79 int (* fn) (struct window *, void *),
80 void *));
81 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
83 /* This is the window in which the terminal's cursor should
84 be left when nothing is being done with it. This must
85 always be a leaf window, and its buffer is selected by
86 the top level editing loop at the end of each command.
88 This value is always the same as
89 FRAME_SELECTED_WINDOW (selected_frame). */
91 Lisp_Object selected_window;
93 /* A list of all windows for use by next_window and Fwindow_list.
94 Functions creating or deleting windows should invalidate this cache
95 by setting it to nil. */
97 Lisp_Object Vwindow_list;
99 /* The mini-buffer window of the selected frame.
100 Note that you cannot test for mini-bufferness of an arbitrary window
101 by comparing against this; but you can test for mini-bufferness of
102 the selected window. */
104 Lisp_Object minibuf_window;
106 /* Non-nil means it is the window whose mode line should be
107 shown as the selected window when the minibuffer is selected. */
109 Lisp_Object minibuf_selected_window;
111 /* Non-nil means it is the window for C-M-v to scroll
112 when the mini-buffer is selected. */
114 Lisp_Object Vminibuf_scroll_window;
116 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
118 Lisp_Object Vother_window_scroll_buffer;
120 /* Non-nil means it's function to call to display temp buffers. */
122 Lisp_Object Vtemp_buffer_show_function;
124 /* Non-zero means line and page scrolling on tall lines (with images)
125 does partial scrolling by modifying window-vscroll. */
127 int auto_window_vscroll_p;
129 /* Non-zero means to use mode-line-inactive face in all windows but the
130 selected-window and the minibuffer-scroll-window when the
131 minibuffer is active. */
132 int mode_line_in_non_selected_windows;
134 /* If a window gets smaller than either of these, it is removed. */
136 EMACS_INT window_min_height;
137 EMACS_INT window_min_width;
139 /* Nonzero implies Fdisplay_buffer should create windows. */
141 int pop_up_windows;
143 /* Nonzero implies make new frames for Fdisplay_buffer. */
145 int pop_up_frames;
147 /* Nonzero means reuse existing frames for displaying buffers. */
149 int display_buffer_reuse_frames;
151 /* Non-nil means use this function instead of default */
153 Lisp_Object Vpop_up_frame_function;
155 /* Function to call to handle Fdisplay_buffer. */
157 Lisp_Object Vdisplay_buffer_function;
159 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
161 Lisp_Object Veven_window_heights;
163 /* List of buffer *names* for buffers that should have their own frames. */
165 Lisp_Object Vspecial_display_buffer_names;
167 /* List of regexps for buffer names that should have their own frames. */
169 Lisp_Object Vspecial_display_regexps;
171 /* Function to pop up a special frame. */
173 Lisp_Object Vspecial_display_function;
175 /* List of buffer *names* for buffers to appear in selected window. */
177 Lisp_Object Vsame_window_buffer_names;
179 /* List of regexps for buffer names to appear in selected window. */
181 Lisp_Object Vsame_window_regexps;
183 /* Hook run at end of temp_output_buffer_show. */
185 Lisp_Object Qtemp_buffer_show_hook;
187 /* Fdisplay_buffer always splits the largest window
188 if that window is more than this high. */
190 EMACS_INT split_height_threshold;
192 /* Number of lines of continuity in scrolling by screenfuls. */
194 EMACS_INT next_screen_context_lines;
196 /* Incremented for each window created. */
198 static int sequence_number;
200 /* Nonzero after init_window_once has finished. */
202 static int window_initialized;
204 /* Hook to run when window config changes. */
206 Lisp_Object Qwindow_configuration_change_hook;
207 Lisp_Object Vwindow_configuration_change_hook;
209 /* Non-nil means scroll commands try to put point
210 at the same screen height as previously. */
212 Lisp_Object Vscroll_preserve_screen_position;
214 /* Incremented by 1 whenever a window is deleted. */
216 int window_deletion_count;
218 #if 0 /* This isn't used anywhere. */
219 /* Nonzero means we can split a frame even if it is "unsplittable". */
220 static int inhibit_frame_unsplittable;
221 #endif /* 0 */
223 extern EMACS_INT scroll_margin;
225 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
227 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
228 doc: /* Returns t if OBJECT is a window. */)
229 (object)
230 Lisp_Object object;
232 return WINDOWP (object) ? Qt : Qnil;
235 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
236 doc: /* Returns t if OBJECT is a window which is currently visible. */)
237 (object)
238 Lisp_Object object;
240 return WINDOW_LIVE_P (object) ? Qt : Qnil;
243 Lisp_Object
244 make_window ()
246 Lisp_Object val;
247 register struct window *p;
249 p = allocate_window ();
250 ++sequence_number;
251 XSETFASTINT (p->sequence_number, sequence_number);
252 XSETFASTINT (p->left_col, 0);
253 XSETFASTINT (p->top_line, 0);
254 XSETFASTINT (p->total_lines, 0);
255 XSETFASTINT (p->total_cols, 0);
256 XSETFASTINT (p->hscroll, 0);
257 XSETFASTINT (p->min_hscroll, 0);
258 p->orig_top_line = p->orig_total_lines = Qnil;
259 p->start = Fmake_marker ();
260 p->pointm = Fmake_marker ();
261 XSETFASTINT (p->use_time, 0);
262 p->frame = Qnil;
263 p->display_table = Qnil;
264 p->dedicated = Qnil;
265 p->pseudo_window_p = 0;
266 bzero (&p->cursor, sizeof (p->cursor));
267 bzero (&p->last_cursor, sizeof (p->last_cursor));
268 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
269 p->desired_matrix = p->current_matrix = 0;
270 p->nrows_scale_factor = p->ncols_scale_factor = 1;
271 p->phys_cursor_type = -1;
272 p->phys_cursor_width = -1;
273 p->must_be_updated_p = 0;
274 XSETFASTINT (p->window_end_vpos, 0);
275 XSETFASTINT (p->window_end_pos, 0);
276 p->window_end_valid = Qnil;
277 p->vscroll = 0;
278 XSETWINDOW (val, p);
279 XSETFASTINT (p->last_point, 0);
280 p->frozen_window_start_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;
290 Vwindow_list = Qnil;
291 return val;
294 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
295 doc: /* Return the window that the cursor now appears in and commands apply to. */)
298 return selected_window;
301 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
302 doc: /* Return the window used now for minibuffers.
303 If the optional argument FRAME is specified, return the minibuffer window
304 used by that frame. */)
305 (frame)
306 Lisp_Object frame;
308 if (NILP (frame))
309 frame = selected_frame;
310 CHECK_LIVE_FRAME (frame);
311 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
314 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
315 doc: /* Returns non-nil if WINDOW is a minibuffer window.
316 WINDOW defaults to the selected window. */)
317 (window)
318 Lisp_Object window;
320 struct window *w = decode_window (window);
321 return MINI_WINDOW_P (w) ? Qt : Qnil;
325 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
326 Spos_visible_in_window_p, 0, 3, 0,
327 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
328 Return nil if that position is scrolled vertically out of view.
329 If a character is only partially visible, nil is returned, unless the
330 optional argument PARTIALLY is non-nil.
331 If POS is only out of view because of horizontal scrolling, return non-nil.
332 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
334 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
335 return value is a list (X Y PARTIAL) where X and Y are the pixel coordinates
336 relative to the top left corner of the window. PARTIAL is nil if the character
337 after POS is fully visible; otherwise it is a cons (RTOP . RBOT) where RTOP
338 and RBOT are the number of pixels invisible at the top and bottom of the row. */)
339 (pos, window, partially)
340 Lisp_Object pos, window, partially;
342 register struct window *w;
343 register int posint;
344 register struct buffer *buf;
345 struct text_pos top;
346 Lisp_Object in_window = Qnil;
347 int rtop, rbot, fully_p = 1;
348 int x, y;
350 w = decode_window (window);
351 buf = XBUFFER (w->buffer);
352 SET_TEXT_POS_FROM_MARKER (top, w->start);
354 if (!NILP (pos))
356 CHECK_NUMBER_COERCE_MARKER (pos);
357 posint = XINT (pos);
359 else if (w == XWINDOW (selected_window))
360 posint = PT;
361 else
362 posint = XMARKER (w->pointm)->charpos;
364 /* If position is above window start or outside buffer boundaries,
365 or if window start is out of range, position is not visible. */
366 if (posint >= CHARPOS (top)
367 && posint <= BUF_ZV (buf)
368 && CHARPOS (top) >= BUF_BEGV (buf)
369 && CHARPOS (top) <= BUF_ZV (buf)
370 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, NILP (partially))
371 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
372 in_window = Qt;
374 if (!NILP (in_window) && !NILP (partially))
375 in_window = Fcons (make_number (x),
376 Fcons (make_number (y),
377 Fcons ((fully_p ? Qnil
378 : Fcons (make_number (rtop),
379 make_number (rbot))),
380 Qnil)));
381 return in_window;
385 static struct window *
386 decode_window (window)
387 register Lisp_Object window;
389 if (NILP (window))
390 return XWINDOW (selected_window);
392 CHECK_LIVE_WINDOW (window);
393 return XWINDOW (window);
396 static struct window *
397 decode_any_window (window)
398 register Lisp_Object window;
400 if (NILP (window))
401 return XWINDOW (selected_window);
403 CHECK_WINDOW (window);
404 return XWINDOW (window);
407 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
408 doc: /* Return the buffer that WINDOW is displaying.
409 WINDOW defaults to the selected window. */)
410 (window)
411 Lisp_Object window;
413 return decode_window (window)->buffer;
416 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
417 doc: /* Return the number of lines in WINDOW (including its mode line). */)
418 (window)
419 Lisp_Object window;
421 return decode_any_window (window)->total_lines;
424 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
425 doc: /* Return the number of display columns in WINDOW.
426 This is the width that is usable columns available for text in WINDOW.
427 If you want to find out how many columns WINDOW takes up,
428 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
429 (window)
430 Lisp_Object window;
432 return make_number (window_box_text_cols (decode_any_window (window)));
435 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
436 doc: /* Return the number of columns by which WINDOW is scrolled from left margin. */)
437 (window)
438 Lisp_Object window;
440 return decode_window (window)->hscroll;
443 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
444 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
445 Return NCOL. NCOL should be zero or positive.
447 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
448 window so that the location of point becomes invisible. */)
449 (window, ncol)
450 Lisp_Object window, ncol;
452 struct window *w = decode_window (window);
453 int hscroll;
455 CHECK_NUMBER (ncol);
456 hscroll = max (0, XINT (ncol));
458 /* Prevent redisplay shortcuts when changing the hscroll. */
459 if (XINT (w->hscroll) != hscroll)
460 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
462 w->hscroll = make_number (hscroll);
463 return ncol;
466 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
467 Swindow_redisplay_end_trigger, 0, 1, 0,
468 doc: /* Return WINDOW's redisplay end trigger value.
469 See `set-window-redisplay-end-trigger' for more information. */)
470 (window)
471 Lisp_Object window;
473 return decode_window (window)->redisplay_end_trigger;
476 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
477 Sset_window_redisplay_end_trigger, 2, 2, 0,
478 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
479 VALUE should be a buffer position (typically a marker) or nil.
480 If it is a buffer position, then if redisplay in WINDOW reaches a position
481 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
482 with two arguments: WINDOW, and the end trigger value.
483 Afterwards the end-trigger value is reset to nil. */)
484 (window, value)
485 register Lisp_Object window, value;
487 register struct window *w;
489 w = decode_window (window);
490 w->redisplay_end_trigger = value;
491 return value;
494 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
495 doc: /* Return a list of the edge coordinates of WINDOW.
496 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
497 RIGHT is one more than the rightmost column occupied by WINDOW,
498 and BOTTOM is one more than the bottommost row occupied by WINDOW.
499 The edges include the space used by the window's scroll bar,
500 display margins, fringes, header line, and mode line, if it has them.
501 To get the edges of the actual text area, use `window-inside-edges'. */)
502 (window)
503 Lisp_Object window;
505 register struct window *w = decode_any_window (window);
507 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
508 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
509 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
510 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
511 Qnil))));
514 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
515 doc: /* Return a list of the edge pixel coordinates of WINDOW.
516 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
517 RIGHT is one more than the rightmost x position occupied by WINDOW,
518 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
519 The pixel edges include the space used by the window's scroll bar,
520 display margins, fringes, header line, and mode line, if it has them.
521 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
522 (window)
523 Lisp_Object window;
525 register struct window *w = decode_any_window (window);
527 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
528 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
529 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
530 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
531 Qnil))));
534 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
535 doc: /* Return a list of the edge coordinates of WINDOW.
536 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
537 RIGHT is one more than the rightmost column used by text in WINDOW,
538 and BOTTOM is one more than the bottommost row used by text in WINDOW.
539 The inside edges do not include the space used by the window's scroll bar,
540 display margins, fringes, header line, and/or mode line. */)
541 (window)
542 Lisp_Object window;
544 register struct window *w = decode_any_window (window);
546 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
547 + WINDOW_LEFT_MARGIN_COLS (w)
548 + WINDOW_LEFT_FRINGE_COLS (w)),
549 make_number (WINDOW_TOP_EDGE_LINE (w)
550 + WINDOW_HEADER_LINE_LINES (w)),
551 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
552 - WINDOW_RIGHT_MARGIN_COLS (w)
553 - WINDOW_RIGHT_FRINGE_COLS (w)),
554 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
555 - WINDOW_MODE_LINE_LINES (w)));
558 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
559 doc: /* Return a list of the edge pixel coordinates of WINDOW.
560 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
561 RIGHT is one more than the rightmost x position used by text in WINDOW,
562 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
563 The inside edges do not include the space used by the window's scroll bar,
564 display margins, fringes, header line, and/or mode line. */)
565 (window)
566 Lisp_Object window;
568 register struct window *w = decode_any_window (window);
570 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
571 + WINDOW_LEFT_MARGIN_WIDTH (w)
572 + WINDOW_LEFT_FRINGE_WIDTH (w)),
573 make_number (WINDOW_TOP_EDGE_Y (w)
574 + WINDOW_HEADER_LINE_HEIGHT (w)),
575 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
576 - WINDOW_RIGHT_MARGIN_WIDTH (w)
577 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
578 make_number (WINDOW_BOTTOM_EDGE_Y (w)
579 - WINDOW_MODE_LINE_HEIGHT (w)));
582 /* Test if the character at column *X, row *Y is within window W.
583 If it is not, return ON_NOTHING;
584 if it is in the window's text area,
585 set *x and *y to its location relative to the upper left corner
586 of the window, and
587 return ON_TEXT;
588 if it is on the window's modeline, return ON_MODE_LINE;
589 if it is on the border between the window and its right sibling,
590 return ON_VERTICAL_BORDER.
591 if it is on a scroll bar,
592 return ON_SCROLL_BAR.
593 if it is on the window's top line, return ON_HEADER_LINE;
594 if it is in left or right fringe of the window,
595 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
596 to window-relative coordinates;
597 if it is in the marginal area to the left/right of the window,
598 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
599 to window-relative coordinates.
601 X and Y are frame relative pixel coordinates. */
603 static enum window_part
604 coordinates_in_window (w, x, y)
605 register struct window *w;
606 register int *x, *y;
608 struct frame *f = XFRAME (WINDOW_FRAME (w));
609 int left_x, right_x, top_y, bottom_y;
610 enum window_part part;
611 int ux = FRAME_COLUMN_WIDTH (f);
612 int x0 = WINDOW_LEFT_EDGE_X (w);
613 int x1 = WINDOW_RIGHT_EDGE_X (w);
614 /* The width of the area where the vertical line can be dragged.
615 (Between mode lines for instance. */
616 int grabbable_width = ux;
617 int lmargin_width, rmargin_width, text_left, text_right;
619 /* In what's below, we subtract 1 when computing right_x because we
620 want the rightmost pixel, which is given by left_pixel+width-1. */
621 if (w->pseudo_window_p)
623 left_x = 0;
624 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
625 top_y = WINDOW_TOP_EDGE_Y (w);
626 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
628 else
630 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
631 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
632 top_y = WINDOW_TOP_EDGE_Y (w);
633 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
636 /* Outside any interesting row? */
637 if (*y < top_y || *y >= bottom_y)
638 return ON_NOTHING;
640 /* On the mode line or header line? If it's near the start of
641 the mode or header line of window that's has a horizontal
642 sibling, say it's on the vertical line. That's to be able
643 to resize windows horizontally in case we're using toolkit
644 scroll bars. */
646 if (WINDOW_WANTS_MODELINE_P (w)
647 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
649 part = ON_MODE_LINE;
651 header_vertical_border_check:
652 /* We're somewhere on the mode line. We consider the place
653 between mode lines of horizontally adjacent mode lines
654 as the vertical border. If scroll bars on the left,
655 return the right window. */
656 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
657 || WINDOW_RIGHTMOST_P (w))
659 if (!WINDOW_LEFTMOST_P (w) && abs (*x - x0) < grabbable_width)
660 return ON_VERTICAL_BORDER;
662 else
664 if (abs (*x - x1) < grabbable_width)
665 return ON_VERTICAL_BORDER;
668 if (*x < x0 || *x >= x1)
669 return ON_NOTHING;
671 /* Convert X and Y to window relative coordinates.
672 Mode line starts at left edge of window. */
673 *x -= x0;
674 *y -= top_y;
675 return part;
678 if (WINDOW_WANTS_HEADER_LINE_P (w)
679 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
681 part = ON_HEADER_LINE;
682 goto header_vertical_border_check;
685 if (*x < x0 || *x >= x1)
686 return ON_NOTHING;
688 /* Outside any interesting column? */
689 if (*x < left_x || *x > right_x)
691 *y -= top_y;
692 return ON_SCROLL_BAR;
695 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
696 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
698 text_left = window_box_left (w, TEXT_AREA);
699 text_right = text_left + window_box_width (w, TEXT_AREA);
701 if (FRAME_WINDOW_P (f))
703 if (!w->pseudo_window_p
704 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
705 && !WINDOW_RIGHTMOST_P (w)
706 && (abs (*x - right_x) < grabbable_width))
707 return ON_VERTICAL_BORDER;
709 else
711 /* Need to say "*x > right_x" rather than >=, since on character
712 terminals, the vertical line's x coordinate is right_x. */
713 if (!w->pseudo_window_p
714 && !WINDOW_RIGHTMOST_P (w)
715 && *x > right_x - ux)
717 /* On the border on the right side of the window? Assume that
718 this area begins at RIGHT_X minus a canonical char width. */
719 return ON_VERTICAL_BORDER;
723 if (*x < text_left)
725 if (lmargin_width > 0
726 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
727 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
728 : (*x < left_x + lmargin_width)))
730 *x -= left_x;
731 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
732 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
733 *y -= top_y;
734 return ON_LEFT_MARGIN;
737 /* Convert X and Y to window-relative pixel coordinates. */
738 *x -= left_x;
739 *y -= top_y;
740 return ON_LEFT_FRINGE;
743 if (*x >= text_right)
745 if (rmargin_width > 0
746 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
747 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
748 : (*x >= right_x - rmargin_width)))
750 *x -= right_x - rmargin_width;
751 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
752 *x += WINDOW_RIGHT_FRINGE_WIDTH (w);
753 *y -= top_y;
754 return ON_RIGHT_MARGIN;
757 /* Convert X and Y to window-relative pixel coordinates. */
758 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
759 *y -= top_y;
760 return ON_RIGHT_FRINGE;
763 /* Everything special ruled out - must be on text area */
764 *x -= text_left;
765 *y -= top_y;
766 return ON_TEXT;
770 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
771 Scoordinates_in_window_p, 2, 2, 0,
772 doc: /* Return non-nil if COORDINATES are in WINDOW.
773 COORDINATES is a cons of the form (X . Y), X and Y being distances
774 measured in characters from the upper-left corner of the frame.
775 \(0 . 0) denotes the character in the upper left corner of the
776 frame.
777 If COORDINATES are in the text portion of WINDOW,
778 the coordinates relative to the window are returned.
779 If they are in the mode line of WINDOW, `mode-line' is returned.
780 If they are in the top mode line of WINDOW, `header-line' is returned.
781 If they are in the left fringe of WINDOW, `left-fringe' is returned.
782 If they are in the right fringe of WINDOW, `right-fringe' is returned.
783 If they are on the border between WINDOW and its right sibling,
784 `vertical-line' is returned.
785 If they are in the windows's left or right marginal areas, `left-margin'\n\
786 or `right-margin' is returned. */)
787 (coordinates, window)
788 register Lisp_Object coordinates, window;
790 struct window *w;
791 struct frame *f;
792 int x, y;
793 Lisp_Object lx, ly;
795 CHECK_WINDOW (window);
796 w = XWINDOW (window);
797 f = XFRAME (w->frame);
798 CHECK_CONS (coordinates);
799 lx = Fcar (coordinates);
800 ly = Fcdr (coordinates);
801 CHECK_NUMBER_OR_FLOAT (lx);
802 CHECK_NUMBER_OR_FLOAT (ly);
803 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
804 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
806 switch (coordinates_in_window (w, &x, &y))
808 case ON_NOTHING:
809 return Qnil;
811 case ON_TEXT:
812 /* X and Y are now window relative pixel coordinates. Convert
813 them to canonical char units before returning them. */
814 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
815 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
817 case ON_MODE_LINE:
818 return Qmode_line;
820 case ON_VERTICAL_BORDER:
821 return Qvertical_line;
823 case ON_HEADER_LINE:
824 return Qheader_line;
826 case ON_LEFT_FRINGE:
827 return Qleft_fringe;
829 case ON_RIGHT_FRINGE:
830 return Qright_fringe;
832 case ON_LEFT_MARGIN:
833 return Qleft_margin;
835 case ON_RIGHT_MARGIN:
836 return Qright_margin;
838 case ON_SCROLL_BAR:
839 /* Historically we are supposed to return nil in this case. */
840 return Qnil;
842 default:
843 abort ();
848 /* Callback for foreach_window, used in window_from_coordinates.
849 Check if window W contains coordinates specified by USER_DATA which
850 is actually a pointer to a struct check_window_data CW.
852 Check if window W contains coordinates *CW->x and *CW->y. If it
853 does, return W in *CW->window, as Lisp_Object, and return in
854 *CW->part the part of the window under coordinates *X,*Y. Return
855 zero from this function to stop iterating over windows. */
857 struct check_window_data
859 Lisp_Object *window;
860 int *x, *y;
861 enum window_part *part;
864 static int
865 check_window_containing (w, user_data)
866 struct window *w;
867 void *user_data;
869 struct check_window_data *cw = (struct check_window_data *) user_data;
870 enum window_part found;
871 int continue_p = 1;
873 found = coordinates_in_window (w, cw->x, cw->y);
874 if (found != ON_NOTHING)
876 *cw->part = found;
877 XSETWINDOW (*cw->window, w);
878 continue_p = 0;
881 return continue_p;
885 /* Find the window containing frame-relative pixel position X/Y and
886 return it as a Lisp_Object.
888 If X, Y is on one of the window's special `window_part' elements,
889 set *PART to the id of that element, and return X and Y converted
890 to window relative coordinates in WX and WY.
892 If there is no window under X, Y return nil and leave *PART
893 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
895 This function was previously implemented with a loop cycling over
896 windows with Fnext_window, and starting with the frame's selected
897 window. It turned out that this doesn't work with an
898 implementation of next_window using Vwindow_list, because
899 FRAME_SELECTED_WINDOW (F) is not always contained in the window
900 tree of F when this function is called asynchronously from
901 note_mouse_highlight. The original loop didn't terminate in this
902 case. */
904 Lisp_Object
905 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
906 struct frame *f;
907 int x, y;
908 enum window_part *part;
909 int *wx, *wy;
910 int tool_bar_p;
912 Lisp_Object window;
913 struct check_window_data cw;
914 enum window_part dummy;
916 if (part == 0)
917 part = &dummy;
919 window = Qnil;
920 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
921 foreach_window (f, check_window_containing, &cw);
923 /* If not found above, see if it's in the tool bar window, if a tool
924 bar exists. */
925 if (NILP (window)
926 && tool_bar_p
927 && WINDOWP (f->tool_bar_window)
928 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
929 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
930 != ON_NOTHING))
932 *part = ON_TEXT;
933 window = f->tool_bar_window;
936 if (wx) *wx = x;
937 if (wy) *wy = y;
939 return window;
942 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
943 doc: /* Return window containing coordinates X and Y on FRAME.
944 If omitted, FRAME defaults to the currently selected frame.
945 The top left corner of the frame is considered to be row 0,
946 column 0. */)
947 (x, y, frame)
948 Lisp_Object x, y, frame;
950 struct frame *f;
952 if (NILP (frame))
953 frame = selected_frame;
954 CHECK_LIVE_FRAME (frame);
955 f = XFRAME (frame);
957 /* Check that arguments are integers or floats. */
958 CHECK_NUMBER_OR_FLOAT (x);
959 CHECK_NUMBER_OR_FLOAT (y);
961 return window_from_coordinates (f,
962 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
963 + FRAME_INTERNAL_BORDER_WIDTH (f)),
964 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
965 + FRAME_INTERNAL_BORDER_WIDTH (f)),
966 0, 0, 0, 0);
969 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
970 doc: /* Return current value of point in WINDOW.
971 For a nonselected window, this is the value point would have
972 if that window were selected.
974 Note that, when WINDOW is the selected window and its buffer
975 is also currently selected, the value returned is the same as (point).
976 It would be more strictly correct to return the `top-level' value
977 of point, outside of any save-excursion forms.
978 But that is hard to define. */)
979 (window)
980 Lisp_Object window;
982 register struct window *w = decode_window (window);
984 if (w == XWINDOW (selected_window)
985 && current_buffer == XBUFFER (w->buffer))
986 return Fpoint ();
987 return Fmarker_position (w->pointm);
990 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
991 doc: /* Return position at which display currently starts in WINDOW.
992 This is updated by redisplay or by calling `set-window-start'. */)
993 (window)
994 Lisp_Object window;
996 return Fmarker_position (decode_window (window)->start);
999 /* This is text temporarily removed from the doc string below.
1001 This function returns nil if the position is not currently known.
1002 That happens when redisplay is preempted and doesn't finish.
1003 If in that case you want to compute where the end of the window would
1004 have been if redisplay had finished, do this:
1005 (save-excursion
1006 (goto-char (window-start window))
1007 (vertical-motion (1- (window-height window)) window)
1008 (point))") */
1010 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1011 doc: /* Return position at which display currently ends in WINDOW.
1012 This is updated by redisplay, when it runs to completion.
1013 Simply changing the buffer text or setting `window-start'
1014 does not update this value.
1015 Return nil if there is no recorded value. \(This can happen if the
1016 last redisplay of WINDOW was preempted, and did not finish.)
1017 If UPDATE is non-nil, compute the up-to-date position
1018 if it isn't already recorded. */)
1019 (window, update)
1020 Lisp_Object window, update;
1022 Lisp_Object value;
1023 struct window *w = decode_window (window);
1024 Lisp_Object buf;
1026 buf = w->buffer;
1027 CHECK_BUFFER (buf);
1029 #if 0 /* This change broke some things. We should make it later. */
1030 /* If we don't know the end position, return nil.
1031 The user can compute it with vertical-motion if he wants to.
1032 It would be nicer to do it automatically,
1033 but that's so slow that it would probably bother people. */
1034 if (NILP (w->window_end_valid))
1035 return Qnil;
1036 #endif
1038 if (! NILP (update)
1039 && ! (! NILP (w->window_end_valid)
1040 && XFASTINT (w->last_modified) >= MODIFF)
1041 && !noninteractive)
1043 struct text_pos startp;
1044 struct it it;
1045 struct buffer *old_buffer = NULL, *b = XBUFFER (buf);
1047 /* In case W->start is out of the range, use something
1048 reasonable. This situation occurred when loading a file with
1049 `-l' containing a call to `rmail' with subsequent other
1050 commands. At the end, W->start happened to be BEG, while
1051 rmail had already narrowed the buffer. */
1052 if (XMARKER (w->start)->charpos < BEGV)
1053 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1054 else if (XMARKER (w->start)->charpos > ZV)
1055 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1056 else
1057 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1059 /* Cannot use Fvertical_motion because that function doesn't
1060 cope with variable-height lines. */
1061 if (b != current_buffer)
1063 old_buffer = current_buffer;
1064 set_buffer_internal (b);
1067 start_display (&it, w, startp);
1068 move_it_vertically (&it, window_box_height (w));
1069 if (it.current_y < it.last_visible_y)
1070 move_it_past_eol (&it);
1071 value = make_number (IT_CHARPOS (it));
1073 if (old_buffer)
1074 set_buffer_internal (old_buffer);
1076 else
1077 XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
1079 return value;
1082 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1083 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1084 Return POS. */)
1085 (window, pos)
1086 Lisp_Object window, pos;
1088 register struct window *w = decode_window (window);
1090 CHECK_NUMBER_COERCE_MARKER (pos);
1091 if (w == XWINDOW (selected_window)
1092 && XBUFFER (w->buffer) == current_buffer)
1093 Fgoto_char (pos);
1094 else
1095 set_marker_restricted (w->pointm, pos, w->buffer);
1097 /* We have to make sure that redisplay updates the window to show
1098 the new value of point. */
1099 if (!EQ (window, selected_window))
1100 ++windows_or_buffers_changed;
1102 return pos;
1105 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1106 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1107 Return POS.
1108 Optional third arg NOFORCE non-nil inhibits next redisplay
1109 from overriding motion of point in order to display at this exact start. */)
1110 (window, pos, noforce)
1111 Lisp_Object window, pos, noforce;
1113 register struct window *w = decode_window (window);
1115 CHECK_NUMBER_COERCE_MARKER (pos);
1116 set_marker_restricted (w->start, pos, w->buffer);
1117 /* this is not right, but much easier than doing what is right. */
1118 w->start_at_line_beg = Qnil;
1119 if (NILP (noforce))
1120 w->force_start = Qt;
1121 w->update_mode_line = Qt;
1122 XSETFASTINT (w->last_modified, 0);
1123 XSETFASTINT (w->last_overlay_modified, 0);
1124 if (!EQ (window, selected_window))
1125 windows_or_buffers_changed++;
1127 return pos;
1130 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1131 1, 1, 0,
1132 doc: /* Return WINDOW's dedicated object, usually t or nil.
1133 See also `set-window-dedicated-p'. */)
1134 (window)
1135 Lisp_Object window;
1137 return decode_window (window)->dedicated;
1140 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1141 Sset_window_dedicated_p, 2, 2, 0,
1142 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1143 If it is dedicated, Emacs will not automatically change
1144 which buffer appears in it.
1145 The second argument is the new value for the dedication flag;
1146 non-nil means yes. */)
1147 (window, arg)
1148 Lisp_Object window, arg;
1150 register struct window *w = decode_window (window);
1152 w->dedicated = arg;
1154 return w->dedicated;
1157 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1158 0, 1, 0,
1159 doc: /* Return the display-table that WINDOW is using. */)
1160 (window)
1161 Lisp_Object window;
1163 return decode_window (window)->display_table;
1166 /* Get the display table for use on window W. This is either W's
1167 display table or W's buffer's display table. Ignore the specified
1168 tables if they are not valid; if no valid table is specified,
1169 return 0. */
1171 struct Lisp_Char_Table *
1172 window_display_table (w)
1173 struct window *w;
1175 struct Lisp_Char_Table *dp = NULL;
1177 if (DISP_TABLE_P (w->display_table))
1178 dp = XCHAR_TABLE (w->display_table);
1179 else if (BUFFERP (w->buffer))
1181 struct buffer *b = XBUFFER (w->buffer);
1183 if (DISP_TABLE_P (b->display_table))
1184 dp = XCHAR_TABLE (b->display_table);
1185 else if (DISP_TABLE_P (Vstandard_display_table))
1186 dp = XCHAR_TABLE (Vstandard_display_table);
1189 return dp;
1192 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1193 doc: /* Set WINDOW's display-table to TABLE. */)
1194 (window, table)
1195 register Lisp_Object window, table;
1197 register struct window *w;
1199 w = decode_window (window);
1200 w->display_table = table;
1201 return table;
1204 /* Record info on buffer window w is displaying
1205 when it is about to cease to display that buffer. */
1206 static void
1207 unshow_buffer (w)
1208 register struct window *w;
1210 Lisp_Object buf;
1211 struct buffer *b;
1213 buf = w->buffer;
1214 b = XBUFFER (buf);
1215 if (b != XMARKER (w->pointm)->buffer)
1216 abort ();
1218 #if 0
1219 if (w == XWINDOW (selected_window)
1220 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1221 /* Do this except when the selected window's buffer
1222 is being removed from some other window. */
1223 #endif
1224 /* last_window_start records the start position that this buffer
1225 had in the last window to be disconnected from it.
1226 Now that this statement is unconditional,
1227 it is possible for the buffer to be displayed in the
1228 selected window, while last_window_start reflects another
1229 window which was recently showing the same buffer.
1230 Some people might say that might be a good thing. Let's see. */
1231 b->last_window_start = marker_position (w->start);
1233 /* Point in the selected window's buffer
1234 is actually stored in that buffer, and the window's pointm isn't used.
1235 So don't clobber point in that buffer. */
1236 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1237 /* This line helps to fix Horsley's testbug.el bug. */
1238 && !(WINDOWP (b->last_selected_window)
1239 && w != XWINDOW (b->last_selected_window)
1240 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1241 temp_set_point_both (b,
1242 clip_to_bounds (BUF_BEGV (b),
1243 XMARKER (w->pointm)->charpos,
1244 BUF_ZV (b)),
1245 clip_to_bounds (BUF_BEGV_BYTE (b),
1246 marker_byte_position (w->pointm),
1247 BUF_ZV_BYTE (b)));
1249 if (WINDOWP (b->last_selected_window)
1250 && w == XWINDOW (b->last_selected_window))
1251 b->last_selected_window = Qnil;
1254 /* Put replacement into the window structure in place of old. */
1255 static void
1256 replace_window (old, replacement)
1257 Lisp_Object old, replacement;
1259 register Lisp_Object tem;
1260 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1262 /* If OLD is its frame's root_window, then replacement is the new
1263 root_window for that frame. */
1265 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1266 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1268 p->left_col = o->left_col;
1269 p->top_line = o->top_line;
1270 p->total_cols = o->total_cols;
1271 p->total_lines = o->total_lines;
1272 p->desired_matrix = p->current_matrix = 0;
1273 p->vscroll = 0;
1274 bzero (&p->cursor, sizeof (p->cursor));
1275 bzero (&p->last_cursor, sizeof (p->last_cursor));
1276 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1277 p->phys_cursor_type = -1;
1278 p->phys_cursor_width = -1;
1279 p->must_be_updated_p = 0;
1280 p->pseudo_window_p = 0;
1281 XSETFASTINT (p->window_end_vpos, 0);
1282 XSETFASTINT (p->window_end_pos, 0);
1283 p->window_end_valid = Qnil;
1284 p->frozen_window_start_p = 0;
1285 p->orig_top_line = p->orig_total_lines = Qnil;
1287 p->next = tem = o->next;
1288 if (!NILP (tem))
1289 XWINDOW (tem)->prev = replacement;
1291 p->prev = tem = o->prev;
1292 if (!NILP (tem))
1293 XWINDOW (tem)->next = replacement;
1295 p->parent = tem = o->parent;
1296 if (!NILP (tem))
1298 if (EQ (XWINDOW (tem)->vchild, old))
1299 XWINDOW (tem)->vchild = replacement;
1300 if (EQ (XWINDOW (tem)->hchild, old))
1301 XWINDOW (tem)->hchild = replacement;
1304 /*** Here, if replacement is a vertical combination
1305 and so is its new parent, we should make replacement's
1306 children be children of that parent instead. ***/
1309 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1310 doc: /* Remove WINDOW from the display. Default is selected window. */)
1311 (window)
1312 register Lisp_Object window;
1314 delete_window (window);
1316 if (! NILP (Vwindow_configuration_change_hook)
1317 && ! NILP (Vrun_hooks))
1318 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1320 return Qnil;
1323 void
1324 delete_window (window)
1325 register Lisp_Object window;
1327 register Lisp_Object tem, parent, sib;
1328 register struct window *p;
1329 register struct window *par;
1330 struct frame *f;
1332 /* Because this function is called by other C code on non-leaf
1333 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1334 so we can't decode_window here. */
1335 if (NILP (window))
1336 window = selected_window;
1337 else
1338 CHECK_WINDOW (window);
1339 p = XWINDOW (window);
1341 /* It's a no-op to delete an already-deleted window. */
1342 if (NILP (p->buffer)
1343 && NILP (p->hchild)
1344 && NILP (p->vchild))
1345 return;
1347 parent = p->parent;
1348 if (NILP (parent))
1349 error ("Attempt to delete minibuffer or sole ordinary window");
1350 par = XWINDOW (parent);
1352 windows_or_buffers_changed++;
1353 Vwindow_list = Qnil;
1354 f = XFRAME (WINDOW_FRAME (p));
1355 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1357 /* Are we trying to delete any frame's selected window? */
1359 Lisp_Object swindow, pwindow;
1361 /* See if the frame's selected window is either WINDOW
1362 or any subwindow of it, by finding all that window's parents
1363 and comparing each one with WINDOW. */
1364 swindow = FRAME_SELECTED_WINDOW (f);
1366 while (1)
1368 pwindow = swindow;
1369 while (!NILP (pwindow))
1371 if (EQ (window, pwindow))
1372 break;
1373 pwindow = XWINDOW (pwindow)->parent;
1376 /* If the window being deleted is not a parent of SWINDOW,
1377 then SWINDOW is ok as the new selected window. */
1378 if (!EQ (window, pwindow))
1379 break;
1380 /* Otherwise, try another window for SWINDOW. */
1381 swindow = Fnext_window (swindow, Qlambda, Qnil);;
1383 /* If we get back to the frame's selected window,
1384 it means there was no acceptable alternative,
1385 so we cannot delete. */
1386 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1387 error ("Cannot delete window");
1390 /* If we need to change SWINDOW, do it. */
1391 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1393 /* If we're about to delete the selected window on the
1394 selected frame, then we should use Fselect_window to select
1395 the new window. On the other hand, if we're about to
1396 delete the selected window on any other frame, we shouldn't do
1397 anything but set the frame's selected_window slot. */
1398 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1399 Fselect_window (swindow, Qnil);
1400 else
1401 FRAME_SELECTED_WINDOW (f) = swindow;
1405 /* Now we know we can delete this one. */
1406 window_deletion_count++;
1408 tem = p->buffer;
1409 /* tem is null for dummy parent windows
1410 (which have inferiors but not any contents themselves) */
1411 if (!NILP (tem))
1413 unshow_buffer (p);
1414 unchain_marker (XMARKER (p->pointm));
1415 unchain_marker (XMARKER (p->start));
1418 /* Free window glyph matrices. It is sure that they are allocated
1419 again when ADJUST_GLYPHS is called. Block input so that expose
1420 events and other events that access glyph matrices are not
1421 processed while we are changing them. */
1422 BLOCK_INPUT;
1423 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1425 tem = p->next;
1426 if (!NILP (tem))
1427 XWINDOW (tem)->prev = p->prev;
1429 tem = p->prev;
1430 if (!NILP (tem))
1431 XWINDOW (tem)->next = p->next;
1433 if (EQ (window, par->hchild))
1434 par->hchild = p->next;
1435 if (EQ (window, par->vchild))
1436 par->vchild = p->next;
1438 /* Find one of our siblings to give our space to. */
1439 sib = p->prev;
1440 if (NILP (sib))
1442 /* If p gives its space to its next sibling, that sibling needs
1443 to have its top/left side pulled back to where p's is.
1444 set_window_{height,width} will re-position the sibling's
1445 children. */
1446 sib = p->next;
1447 XWINDOW (sib)->top_line = p->top_line;
1448 XWINDOW (sib)->left_col = p->left_col;
1451 /* Stretch that sibling. */
1452 if (!NILP (par->vchild))
1453 set_window_height (sib,
1454 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1456 if (!NILP (par->hchild))
1457 set_window_width (sib,
1458 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1461 /* If parent now has only one child,
1462 put the child into the parent's place. */
1463 tem = par->hchild;
1464 if (NILP (tem))
1465 tem = par->vchild;
1466 if (NILP (XWINDOW (tem)->next)) {
1467 replace_window (parent, tem);
1468 par = XWINDOW (tem);
1471 /* Since we may be deleting combination windows, we must make sure that
1472 not only p but all its children have been marked as deleted. */
1473 if (! NILP (p->hchild))
1474 delete_all_subwindows (XWINDOW (p->hchild));
1475 else if (! NILP (p->vchild))
1476 delete_all_subwindows (XWINDOW (p->vchild));
1478 /* Mark this window as deleted. */
1479 p->buffer = p->hchild = p->vchild = Qnil;
1481 if (! NILP (par->parent))
1482 par = XWINDOW (par->parent);
1484 /* Check if we have a v/hchild with a v/hchild. In that case remove
1485 one of them. */
1487 if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
1489 p = XWINDOW (par->vchild);
1490 par->vchild = p->vchild;
1491 tem = p->vchild;
1493 else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
1495 p = XWINDOW (par->hchild);
1496 par->hchild = p->hchild;
1497 tem = p->hchild;
1499 else
1500 p = 0;
1502 if (p)
1504 while (! NILP (tem)) {
1505 XWINDOW (tem)->parent = p->parent;
1506 if (NILP (XWINDOW (tem)->next))
1507 break;
1508 tem = XWINDOW (tem)->next;
1510 if (! NILP (tem)) {
1511 /* The next of the v/hchild we are removing is now the next of the
1512 last child for the v/hchild:
1513 Before v/hchild -> v/hchild -> next1 -> next2
1515 -> next3
1516 After: v/hchild -> next1 -> next2 -> next3
1518 XWINDOW (tem)->next = p->next;
1519 if (! NILP (p->next))
1520 XWINDOW (p->next)->prev = tem;
1522 p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
1526 /* Adjust glyph matrices. */
1527 adjust_glyphs (f);
1528 UNBLOCK_INPUT;
1533 /***********************************************************************
1534 Window List
1535 ***********************************************************************/
1537 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1538 pointer. This is a callback function for foreach_window, used in
1539 function window_list. */
1541 static int
1542 add_window_to_list (w, user_data)
1543 struct window *w;
1544 void *user_data;
1546 Lisp_Object *list = (Lisp_Object *) user_data;
1547 Lisp_Object window;
1548 XSETWINDOW (window, w);
1549 *list = Fcons (window, *list);
1550 return 1;
1554 /* Return a list of all windows, for use by next_window. If
1555 Vwindow_list is a list, return that list. Otherwise, build a new
1556 list, cache it in Vwindow_list, and return that. */
1558 static Lisp_Object
1559 window_list ()
1561 if (!CONSP (Vwindow_list))
1563 Lisp_Object tail;
1565 Vwindow_list = Qnil;
1566 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1568 Lisp_Object args[2];
1570 /* We are visiting windows in canonical order, and add
1571 new windows at the front of args[1], which means we
1572 have to reverse this list at the end. */
1573 args[1] = Qnil;
1574 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1575 args[0] = Vwindow_list;
1576 args[1] = Fnreverse (args[1]);
1577 Vwindow_list = Fnconc (2, args);
1581 return Vwindow_list;
1585 /* Value is non-zero if WINDOW satisfies the constraints given by
1586 OWINDOW, MINIBUF and ALL_FRAMES.
1588 MINIBUF t means WINDOW may be minibuffer windows.
1589 `lambda' means WINDOW may not be a minibuffer window.
1590 a window means a specific minibuffer window
1592 ALL_FRAMES t means search all frames,
1593 nil means search just current frame,
1594 `visible' means search just visible frames,
1595 0 means search visible and iconified frames,
1596 a window means search the frame that window belongs to,
1597 a frame means consider windows on that frame, only. */
1599 static int
1600 candidate_window_p (window, owindow, minibuf, all_frames)
1601 Lisp_Object window, owindow, minibuf, all_frames;
1603 struct window *w = XWINDOW (window);
1604 struct frame *f = XFRAME (w->frame);
1605 int candidate_p = 1;
1607 if (!BUFFERP (w->buffer))
1608 candidate_p = 0;
1609 else if (MINI_WINDOW_P (w)
1610 && (EQ (minibuf, Qlambda)
1611 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1613 /* If MINIBUF is `lambda' don't consider any mini-windows.
1614 If it is a window, consider only that one. */
1615 candidate_p = 0;
1617 else if (EQ (all_frames, Qt))
1618 candidate_p = 1;
1619 else if (NILP (all_frames))
1621 xassert (WINDOWP (owindow));
1622 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1624 else if (EQ (all_frames, Qvisible))
1626 FRAME_SAMPLE_VISIBILITY (f);
1627 candidate_p = FRAME_VISIBLE_P (f);
1629 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1631 FRAME_SAMPLE_VISIBILITY (f);
1632 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1634 else if (WINDOWP (all_frames))
1635 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1636 || EQ (XWINDOW (all_frames)->frame, w->frame)
1637 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1638 else if (FRAMEP (all_frames))
1639 candidate_p = EQ (all_frames, w->frame);
1641 return candidate_p;
1645 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1646 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1647 ALL_FRAMES. */
1649 static void
1650 decode_next_window_args (window, minibuf, all_frames)
1651 Lisp_Object *window, *minibuf, *all_frames;
1653 if (NILP (*window))
1654 *window = selected_window;
1655 else
1656 CHECK_LIVE_WINDOW (*window);
1658 /* MINIBUF nil may or may not include minibuffers. Decide if it
1659 does. */
1660 if (NILP (*minibuf))
1661 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1662 else if (!EQ (*minibuf, Qt))
1663 *minibuf = Qlambda;
1665 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1666 => count none of them, or a specific minibuffer window (the
1667 active one) to count. */
1669 /* ALL_FRAMES nil doesn't specify which frames to include. */
1670 if (NILP (*all_frames))
1671 *all_frames = (!EQ (*minibuf, Qlambda)
1672 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1673 : Qnil);
1674 else if (EQ (*all_frames, Qvisible))
1676 else if (EQ (*all_frames, make_number (0)))
1678 else if (FRAMEP (*all_frames))
1680 else if (!EQ (*all_frames, Qt))
1681 *all_frames = Qnil;
1683 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1684 search just current frame, `visible' meaning search just visible
1685 frames, 0 meaning search visible and iconified frames, or a
1686 window, meaning search the frame that window belongs to, or a
1687 frame, meaning consider windows on that frame, only. */
1691 /* Return the next or previous window of WINDOW in canonical ordering
1692 of windows. NEXT_P non-zero means return the next window. See the
1693 documentation string of next-window for the meaning of MINIBUF and
1694 ALL_FRAMES. */
1696 static Lisp_Object
1697 next_window (window, minibuf, all_frames, next_p)
1698 Lisp_Object window, minibuf, all_frames;
1699 int next_p;
1701 decode_next_window_args (&window, &minibuf, &all_frames);
1703 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1704 return the first window on the frame. */
1705 if (FRAMEP (all_frames)
1706 && !EQ (all_frames, XWINDOW (window)->frame))
1707 return Fframe_first_window (all_frames);
1709 if (next_p)
1711 Lisp_Object list;
1713 /* Find WINDOW in the list of all windows. */
1714 list = Fmemq (window, window_list ());
1716 /* Scan forward from WINDOW to the end of the window list. */
1717 if (CONSP (list))
1718 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1719 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1720 break;
1722 /* Scan from the start of the window list up to WINDOW. */
1723 if (!CONSP (list))
1724 for (list = Vwindow_list;
1725 CONSP (list) && !EQ (XCAR (list), window);
1726 list = XCDR (list))
1727 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1728 break;
1730 if (CONSP (list))
1731 window = XCAR (list);
1733 else
1735 Lisp_Object candidate, list;
1737 /* Scan through the list of windows for candidates. If there are
1738 candidate windows in front of WINDOW, the last one of these
1739 is the one we want. If there are candidates following WINDOW
1740 in the list, again the last one of these is the one we want. */
1741 candidate = Qnil;
1742 for (list = window_list (); CONSP (list); list = XCDR (list))
1744 if (EQ (XCAR (list), window))
1746 if (WINDOWP (candidate))
1747 break;
1749 else if (candidate_window_p (XCAR (list), window, minibuf,
1750 all_frames))
1751 candidate = XCAR (list);
1754 if (WINDOWP (candidate))
1755 window = candidate;
1758 return window;
1762 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1763 doc: /* Return next window after WINDOW in canonical ordering of windows.
1764 If omitted, WINDOW defaults to the selected window.
1766 Optional second arg MINIBUF t means count the minibuffer window even
1767 if not active. MINIBUF nil or omitted means count the minibuffer iff
1768 it is active. MINIBUF neither t nor nil means not to count the
1769 minibuffer even if it is active.
1771 Several frames may share a single minibuffer; if the minibuffer
1772 counts, all windows on all frames that share that minibuffer count
1773 too. Therefore, `next-window' can be used to iterate through the
1774 set of windows even when the minibuffer is on another frame. If the
1775 minibuffer does not count, only windows from WINDOW's frame count.
1777 Optional third arg ALL-FRAMES t means include windows on all frames.
1778 ALL-FRAMES nil or omitted means cycle within the frames as specified
1779 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1780 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1781 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1782 Anything else means restrict to WINDOW's frame.
1784 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1785 `next-window' to iterate through the entire cycle of acceptable
1786 windows, eventually ending up back at the window you started with.
1787 `previous-window' traverses the same cycle, in the reverse order. */)
1788 (window, minibuf, all_frames)
1789 Lisp_Object window, minibuf, all_frames;
1791 return next_window (window, minibuf, all_frames, 1);
1795 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1796 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1797 If omitted, WINDOW defaults to the selected window.
1799 Optional second arg MINIBUF t means count the minibuffer window even
1800 if not active. MINIBUF nil or omitted means count the minibuffer iff
1801 it is active. MINIBUF neither t nor nil means not to count the
1802 minibuffer even if it is active.
1804 Several frames may share a single minibuffer; if the minibuffer
1805 counts, all windows on all frames that share that minibuffer count
1806 too. Therefore, `previous-window' can be used to iterate through
1807 the set of windows even when the minibuffer is on another frame. If
1808 the minibuffer does not count, only windows from WINDOW's frame count
1810 Optional third arg ALL-FRAMES t means include windows on all frames.
1811 ALL-FRAMES nil or omitted means cycle within the frames as specified
1812 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1813 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1814 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1815 Anything else means restrict to WINDOW's frame.
1817 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1818 `previous-window' to iterate through the entire cycle of acceptable
1819 windows, eventually ending up back at the window you started with.
1820 `next-window' traverses the same cycle, in the reverse order. */)
1821 (window, minibuf, all_frames)
1822 Lisp_Object window, minibuf, all_frames;
1824 return next_window (window, minibuf, all_frames, 0);
1828 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1829 doc: /* Select the ARG'th different window on this frame.
1830 All windows on current frame are arranged in a cyclic order.
1831 This command selects the window ARG steps away in that order.
1832 A negative ARG moves in the opposite order. The optional second
1833 argument ALL-FRAMES has the same meaning as in `next-window', which see. */)
1834 (arg, all_frames)
1835 Lisp_Object arg, all_frames;
1837 Lisp_Object window;
1838 int i;
1840 CHECK_NUMBER (arg);
1841 window = selected_window;
1843 for (i = XINT (arg); i > 0; --i)
1844 window = Fnext_window (window, Qnil, all_frames);
1845 for (; i < 0; ++i)
1846 window = Fprevious_window (window, Qnil, all_frames);
1848 Fselect_window (window, Qnil);
1849 return Qnil;
1853 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
1854 doc: /* Return a list of windows on FRAME, starting with WINDOW.
1855 FRAME nil or omitted means use the selected frame.
1856 WINDOW nil or omitted means use the selected window.
1857 MINIBUF t means include the minibuffer window, even if it isn't active.
1858 MINIBUF nil or omitted means include the minibuffer window only
1859 if it's active.
1860 MINIBUF neither nil nor t means never include the minibuffer window. */)
1861 (frame, minibuf, window)
1862 Lisp_Object frame, minibuf, window;
1864 if (NILP (window))
1865 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
1866 CHECK_WINDOW (window);
1867 if (NILP (frame))
1868 frame = selected_frame;
1870 if (!EQ (frame, XWINDOW (window)->frame))
1871 error ("Window is on a different frame");
1873 return window_list_1 (window, minibuf, frame);
1877 /* Return a list of windows in canonical ordering. Arguments are like
1878 for `next-window'. */
1880 static Lisp_Object
1881 window_list_1 (window, minibuf, all_frames)
1882 Lisp_Object window, minibuf, all_frames;
1884 Lisp_Object tail, list, rest;
1886 decode_next_window_args (&window, &minibuf, &all_frames);
1887 list = Qnil;
1889 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
1890 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
1891 list = Fcons (XCAR (tail), list);
1893 /* Rotate the list to start with WINDOW. */
1894 list = Fnreverse (list);
1895 rest = Fmemq (window, list);
1896 if (!NILP (rest) && !EQ (rest, list))
1898 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
1900 XSETCDR (tail, Qnil);
1901 list = nconc2 (rest, list);
1903 return list;
1908 /* Look at all windows, performing an operation specified by TYPE
1909 with argument OBJ.
1910 If FRAMES is Qt, look at all frames;
1911 Qnil, look at just the selected frame;
1912 Qvisible, look at visible frames;
1913 a frame, just look at windows on that frame.
1914 If MINI is non-zero, perform the operation on minibuffer windows too. */
1916 enum window_loop
1918 WINDOW_LOOP_UNUSED,
1919 GET_BUFFER_WINDOW, /* Arg is buffer */
1920 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1921 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1922 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1923 GET_LARGEST_WINDOW,
1924 UNSHOW_BUFFER, /* Arg is buffer */
1925 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
1926 CHECK_ALL_WINDOWS
1929 static Lisp_Object
1930 window_loop (type, obj, mini, frames)
1931 enum window_loop type;
1932 Lisp_Object obj, frames;
1933 int mini;
1935 Lisp_Object window, windows, best_window, frame_arg;
1936 struct frame *f;
1937 struct gcpro gcpro1;
1939 /* If we're only looping through windows on a particular frame,
1940 frame points to that frame. If we're looping through windows
1941 on all frames, frame is 0. */
1942 if (FRAMEP (frames))
1943 f = XFRAME (frames);
1944 else if (NILP (frames))
1945 f = SELECTED_FRAME ();
1946 else
1947 f = NULL;
1949 if (f)
1950 frame_arg = Qlambda;
1951 else if (EQ (frames, make_number (0)))
1952 frame_arg = frames;
1953 else if (EQ (frames, Qvisible))
1954 frame_arg = frames;
1955 else
1956 frame_arg = Qt;
1958 /* frame_arg is Qlambda to stick to one frame,
1959 Qvisible to consider all visible frames,
1960 or Qt otherwise. */
1962 /* Pick a window to start with. */
1963 if (WINDOWP (obj))
1964 window = obj;
1965 else if (f)
1966 window = FRAME_SELECTED_WINDOW (f);
1967 else
1968 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1970 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
1971 GCPRO1 (windows);
1972 best_window = Qnil;
1974 for (; CONSP (windows); windows = XCDR (windows))
1976 struct window *w;
1978 window = XCAR (windows);
1979 w = XWINDOW (window);
1981 /* Note that we do not pay attention here to whether the frame
1982 is visible, since Fwindow_list skips non-visible frames if
1983 that is desired, under the control of frame_arg. */
1984 if (!MINI_WINDOW_P (w)
1985 /* For UNSHOW_BUFFER, we must always consider all windows. */
1986 || type == UNSHOW_BUFFER
1987 || (mini && minibuf_level > 0))
1988 switch (type)
1990 case GET_BUFFER_WINDOW:
1991 if (EQ (w->buffer, obj)
1992 /* Don't find any minibuffer window
1993 except the one that is currently in use. */
1994 && (MINI_WINDOW_P (w)
1995 ? EQ (window, minibuf_window)
1996 : 1))
1998 if (NILP (best_window))
1999 best_window = window;
2000 else if (EQ (window, selected_window))
2001 /* For compatibility with 20.x, prefer to return
2002 selected-window. */
2003 best_window = window;
2005 break;
2007 case GET_LRU_WINDOW:
2008 /* `obj' is an integer encoding a bitvector.
2009 `obj & 1' means consider only full-width windows.
2010 `obj & 2' means consider also dedicated windows. */
2011 if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
2012 || (!(XINT (obj) & 2) && EQ (w->dedicated, Qt))
2013 /* Minibuffer windows are always ignored. */
2014 || MINI_WINDOW_P (w))
2015 break;
2016 if (NILP (best_window)
2017 || (XFASTINT (XWINDOW (best_window)->use_time)
2018 > XFASTINT (w->use_time)))
2019 best_window = window;
2020 break;
2022 case DELETE_OTHER_WINDOWS:
2023 if (!EQ (window, obj))
2024 Fdelete_window (window);
2025 break;
2027 case DELETE_BUFFER_WINDOWS:
2028 if (EQ (w->buffer, obj))
2030 struct frame *f = XFRAME (WINDOW_FRAME (w));
2032 /* If this window is dedicated, and in a frame of its own,
2033 kill the frame. */
2034 if (EQ (window, FRAME_ROOT_WINDOW (f))
2035 && !NILP (w->dedicated)
2036 && other_visible_frames (f))
2038 /* Skip the other windows on this frame.
2039 There might be one, the minibuffer! */
2040 while (CONSP (XCDR (windows))
2041 && EQ (XWINDOW (XCAR (windows))->frame,
2042 XWINDOW (XCAR (XCDR (windows)))->frame))
2043 windows = XCDR (windows);
2045 /* Now we can safely delete the frame. */
2046 Fdelete_frame (w->frame, Qnil);
2048 else if (NILP (w->parent))
2050 /* If we're deleting the buffer displayed in the
2051 only window on the frame, find a new buffer to
2052 display there. */
2053 Lisp_Object buffer;
2054 buffer = Fother_buffer (obj, Qnil, w->frame);
2055 Fset_window_buffer (window, buffer, Qnil);
2056 if (EQ (window, selected_window))
2057 Fset_buffer (w->buffer);
2059 else
2060 Fdelete_window (window);
2062 break;
2064 case GET_LARGEST_WINDOW:
2065 { /* nil `obj' means to ignore dedicated windows. */
2066 /* Ignore dedicated windows and minibuffers. */
2067 if (MINI_WINDOW_P (w) || (NILP (obj) && EQ (w->dedicated, Qt)))
2068 break;
2070 if (NILP (best_window))
2071 best_window = window;
2072 else
2074 struct window *b = XWINDOW (best_window);
2075 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
2076 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
2077 best_window = window;
2080 break;
2082 case UNSHOW_BUFFER:
2083 if (EQ (w->buffer, obj))
2085 Lisp_Object buffer;
2086 struct frame *f = XFRAME (w->frame);
2088 /* Find another buffer to show in this window. */
2089 buffer = Fother_buffer (obj, Qnil, w->frame);
2091 /* If this window is dedicated, and in a frame of its own,
2092 kill the frame. */
2093 if (EQ (window, FRAME_ROOT_WINDOW (f))
2094 && !NILP (w->dedicated)
2095 && other_visible_frames (f))
2097 /* Skip the other windows on this frame.
2098 There might be one, the minibuffer! */
2099 while (CONSP (XCDR (windows))
2100 && EQ (XWINDOW (XCAR (windows))->frame,
2101 XWINDOW (XCAR (XCDR (windows)))->frame))
2102 windows = XCDR (windows);
2104 /* Now we can safely delete the frame. */
2105 Fdelete_frame (w->frame, Qnil);
2107 else if (!NILP (w->dedicated) && !NILP (w->parent))
2109 Lisp_Object window;
2110 XSETWINDOW (window, w);
2111 /* If this window is dedicated and not the only window
2112 in its frame, then kill it. */
2113 Fdelete_window (window);
2115 else
2117 /* Otherwise show a different buffer in the window. */
2118 w->dedicated = Qnil;
2119 Fset_window_buffer (window, buffer, Qnil);
2120 if (EQ (window, selected_window))
2121 Fset_buffer (w->buffer);
2124 break;
2126 case REDISPLAY_BUFFER_WINDOWS:
2127 if (EQ (w->buffer, obj))
2129 mark_window_display_accurate (window, 0);
2130 w->update_mode_line = Qt;
2131 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2132 ++update_mode_lines;
2133 best_window = window;
2135 break;
2137 /* Check for a window that has a killed buffer. */
2138 case CHECK_ALL_WINDOWS:
2139 if (! NILP (w->buffer)
2140 && NILP (XBUFFER (w->buffer)->name))
2141 abort ();
2142 break;
2144 case WINDOW_LOOP_UNUSED:
2145 break;
2149 UNGCPRO;
2150 return best_window;
2153 /* Used for debugging. Abort if any window has a dead buffer. */
2155 void
2156 check_all_windows ()
2158 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2161 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
2162 doc: /* Return the window least recently selected or used for display.
2163 Return a full-width window if possible.
2164 A minibuffer window is never a candidate.
2165 A dedicated window is never a candidate, unless DEDICATED is non-nil,
2166 so if all windows are dedicated, the value is nil.
2167 If optional argument FRAME is `visible', search all visible frames.
2168 If FRAME is 0, search all visible and iconified frames.
2169 If FRAME is t, search all frames.
2170 If FRAME is nil, search only the selected frame.
2171 If FRAME is a frame, search only that frame. */)
2172 (frame, dedicated)
2173 Lisp_Object frame, dedicated;
2175 register Lisp_Object w;
2176 /* First try for a window that is full-width */
2177 w = window_loop (GET_LRU_WINDOW,
2178 NILP (dedicated) ? make_number (1) : make_number (3),
2179 0, frame);
2180 if (!NILP (w) && !EQ (w, selected_window))
2181 return w;
2182 /* If none of them, try the rest */
2183 return window_loop (GET_LRU_WINDOW,
2184 NILP (dedicated) ? make_number (0) : make_number (2),
2185 0, frame);
2188 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
2189 doc: /* Return the largest window in area.
2190 A minibuffer window is never a candidate.
2191 A dedicated window is never a candidate unless DEDICATED is non-nil,
2192 so if all windows are dedicated, the value is nil.
2193 If optional argument FRAME is `visible', search all visible frames.
2194 If FRAME is 0, search all visible and iconified frames.
2195 If FRAME is t, search all frames.
2196 If FRAME is nil, search only the selected frame.
2197 If FRAME is a frame, search only that frame. */)
2198 (frame, dedicated)
2199 Lisp_Object frame, dedicated;
2201 return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
2202 frame);
2205 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2206 doc: /* Return a window currently displaying BUFFER, or nil if none.
2207 BUFFER can be a buffer or a buffer name.
2208 If optional argument FRAME is `visible', search all visible frames.
2209 If optional argument FRAME is 0, search all visible and iconified frames.
2210 If FRAME is t, search all frames.
2211 If FRAME is nil, search only the selected frame.
2212 If FRAME is a frame, search only that frame. */)
2213 (buffer, frame)
2214 Lisp_Object buffer, frame;
2216 buffer = Fget_buffer (buffer);
2217 if (BUFFERP (buffer))
2218 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2219 else
2220 return Qnil;
2223 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2224 0, 1, "",
2225 doc: /* Make WINDOW (or the selected window) fill its frame.
2226 Only the frame WINDOW is on is affected.
2227 This function tries to reduce display jumps
2228 by keeping the text previously visible in WINDOW
2229 in the same place on the frame. Doing this depends on
2230 the value of (window-start WINDOW), so if calling this function
2231 in a program gives strange scrolling, make sure the window-start
2232 value is reasonable when this function is called. */)
2233 (window)
2234 Lisp_Object window;
2236 struct window *w;
2237 int startpos;
2238 int top, new_top;
2240 if (NILP (window))
2241 window = selected_window;
2242 else
2243 CHECK_LIVE_WINDOW (window);
2244 w = XWINDOW (window);
2246 startpos = marker_position (w->start);
2247 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2249 if (MINI_WINDOW_P (w) && top > 0)
2250 error ("Can't expand minibuffer to full frame");
2252 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2254 /* Try to minimize scrolling, by setting the window start to the point
2255 will cause the text at the old window start to be at the same place
2256 on the frame. But don't try to do this if the window start is
2257 outside the visible portion (as might happen when the display is
2258 not current, due to typeahead). */
2259 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2260 if (new_top != top
2261 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2262 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2264 struct position pos;
2265 struct buffer *obuf = current_buffer;
2267 Fset_buffer (w->buffer);
2268 /* This computation used to temporarily move point, but that can
2269 have unwanted side effects due to text properties. */
2270 pos = *vmotion (startpos, -top, w);
2272 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2273 w->window_end_valid = Qnil;
2274 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2275 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2276 : Qnil);
2277 /* We need to do this, so that the window-scroll-functions
2278 get called. */
2279 w->optional_new_start = Qt;
2281 set_buffer_internal (obuf);
2284 return Qnil;
2287 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2288 1, 2, "bDelete windows on (buffer): ",
2289 doc: /* Delete all windows showing BUFFER.
2290 BUFFER must be a buffer or the name of an existing buffer.
2291 Optional second argument FRAME controls which frames are affected.
2292 If optional argument FRAME is `visible', search all visible frames.
2293 If FRAME is 0, search all visible and iconified frames.
2294 If FRAME is nil, search all frames.
2295 If FRAME is t, search only the selected frame.
2296 If FRAME is a frame, search only that frame. */)
2297 (buffer, frame)
2298 Lisp_Object buffer, frame;
2300 /* FRAME uses t and nil to mean the opposite of what window_loop
2301 expects. */
2302 if (NILP (frame))
2303 frame = Qt;
2304 else if (EQ (frame, Qt))
2305 frame = Qnil;
2307 if (!NILP (buffer))
2309 buffer = Fget_buffer (buffer);
2310 CHECK_BUFFER (buffer);
2311 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2314 return Qnil;
2317 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2318 Sreplace_buffer_in_windows,
2319 1, 1, "bReplace buffer in windows: ",
2320 doc: /* Replace BUFFER with some other buffer in all windows showing it.
2321 BUFFER may be a buffer or the name of an existing buffer. */)
2322 (buffer)
2323 Lisp_Object buffer;
2325 if (!NILP (buffer))
2327 buffer = Fget_buffer (buffer);
2328 CHECK_BUFFER (buffer);
2329 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2331 return Qnil;
2334 /* Replace BUFFER with some other buffer in all windows
2335 of all frames, even those on other keyboards. */
2337 void
2338 replace_buffer_in_all_windows (buffer)
2339 Lisp_Object buffer;
2341 #ifdef MULTI_KBOARD
2342 Lisp_Object tail, frame;
2344 /* A single call to window_loop won't do the job
2345 because it only considers frames on the current keyboard.
2346 So loop manually over frames, and handle each one. */
2347 FOR_EACH_FRAME (tail, frame)
2348 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2349 #else
2350 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2351 #endif
2354 /* Set the height of WINDOW and all its inferiors. */
2356 /* The smallest acceptable dimensions for a window. Anything smaller
2357 might crash Emacs. */
2359 #define MIN_SAFE_WINDOW_WIDTH (2)
2360 #define MIN_SAFE_WINDOW_HEIGHT (1)
2362 /* Make sure that window_min_height and window_min_width are
2363 not too small; if they are, set them to safe minima. */
2365 static void
2366 check_min_window_sizes ()
2368 /* Smaller values might permit a crash. */
2369 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2370 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2371 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2372 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2375 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2376 minimum allowable size. */
2378 void
2379 check_frame_size (frame, rows, cols)
2380 FRAME_PTR frame;
2381 int *rows, *cols;
2383 /* For height, we have to see:
2384 how many windows the frame has at minimum (one or two),
2385 and whether it has a menu bar or other special stuff at the top. */
2386 int min_height
2387 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2388 ? MIN_SAFE_WINDOW_HEIGHT
2389 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2391 if (FRAME_TOP_MARGIN (frame) > 0)
2392 min_height += FRAME_TOP_MARGIN (frame);
2394 if (*rows < min_height)
2395 *rows = min_height;
2396 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2397 *cols = MIN_SAFE_WINDOW_WIDTH;
2401 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2402 check if W's width can be changed, otherwise check W's height.
2403 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2404 siblings, too. If none of the siblings is resizable, WINDOW isn't
2405 either. */
2407 static int
2408 window_fixed_size_p (w, width_p, check_siblings_p)
2409 struct window *w;
2410 int width_p, check_siblings_p;
2412 int fixed_p;
2413 struct window *c;
2415 if (!NILP (w->hchild))
2417 c = XWINDOW (w->hchild);
2419 if (width_p)
2421 /* A horiz. combination is fixed-width if all of if its
2422 children are. */
2423 while (c && window_fixed_size_p (c, width_p, 0))
2424 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2425 fixed_p = c == NULL;
2427 else
2429 /* A horiz. combination is fixed-height if one of if its
2430 children is. */
2431 while (c && !window_fixed_size_p (c, width_p, 0))
2432 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2433 fixed_p = c != NULL;
2436 else if (!NILP (w->vchild))
2438 c = XWINDOW (w->vchild);
2440 if (width_p)
2442 /* A vert. combination is fixed-width if one of if its
2443 children is. */
2444 while (c && !window_fixed_size_p (c, width_p, 0))
2445 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2446 fixed_p = c != NULL;
2448 else
2450 /* A vert. combination is fixed-height if all of if its
2451 children are. */
2452 while (c && window_fixed_size_p (c, width_p, 0))
2453 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2454 fixed_p = c == NULL;
2457 else if (BUFFERP (w->buffer))
2459 struct buffer *old = current_buffer;
2460 Lisp_Object val;
2462 current_buffer = XBUFFER (w->buffer);
2463 val = find_symbol_value (Qwindow_size_fixed);
2464 current_buffer = old;
2466 fixed_p = 0;
2467 if (!EQ (val, Qunbound))
2469 fixed_p = !NILP (val);
2471 if (fixed_p
2472 && ((EQ (val, Qheight) && width_p)
2473 || (EQ (val, Qwidth) && !width_p)))
2474 fixed_p = 0;
2477 /* Can't tell if this one is resizable without looking at
2478 siblings. If all siblings are fixed-size this one is too. */
2479 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2481 Lisp_Object child;
2483 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2484 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2485 break;
2487 if (NILP (child))
2488 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2489 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2490 break;
2492 if (NILP (child))
2493 fixed_p = 1;
2496 else
2497 fixed_p = 1;
2499 return fixed_p;
2503 /* Return the minimum size of window W, not taking fixed-width windows
2504 into account. WIDTH_P non-zero means return the minimum width,
2505 otherwise return the minimum height. If W is a combination window,
2506 compute the minimum size from the minimum sizes of W's children. */
2508 static int
2509 window_min_size_1 (w, width_p)
2510 struct window *w;
2511 int width_p;
2513 struct window *c;
2514 int size;
2516 if (!NILP (w->hchild))
2518 c = XWINDOW (w->hchild);
2519 size = 0;
2521 if (width_p)
2523 /* The min width of a horizontal combination is
2524 the sum of the min widths of its children. */
2525 while (c)
2527 size += window_min_size_1 (c, width_p);
2528 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2531 else
2533 /* The min height a horizontal combination equals
2534 the maximum of all min height of its children. */
2535 while (c)
2537 int min_size = window_min_size_1 (c, width_p);
2538 size = max (min_size, size);
2539 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2543 else if (!NILP (w->vchild))
2545 c = XWINDOW (w->vchild);
2546 size = 0;
2548 if (width_p)
2550 /* The min width of a vertical combination is
2551 the maximum of the min widths of its children. */
2552 while (c)
2554 int min_size = window_min_size_1 (c, width_p);
2555 size = max (min_size, size);
2556 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2559 else
2561 /* The min height of a vertical combination equals
2562 the sum of the min height of its children. */
2563 while (c)
2565 size += window_min_size_1 (c, width_p);
2566 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2570 else
2572 if (width_p)
2573 size = max (window_min_width,
2574 (MIN_SAFE_WINDOW_WIDTH
2575 + WINDOW_FRINGE_COLS (w)
2576 + WINDOW_SCROLL_BAR_COLS (w)));
2577 else
2579 if (MINI_WINDOW_P (w)
2580 || (!WINDOW_WANTS_MODELINE_P (w)
2581 && !WINDOW_WANTS_HEADER_LINE_P (w)))
2582 size = 1;
2583 else
2584 size = window_min_height;
2588 return size;
2592 /* Return the minimum size of window W, taking fixed-size windows into
2593 account. WIDTH_P non-zero means return the minimum width,
2594 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2595 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2596 unless FIXED is null. */
2598 static int
2599 window_min_size (w, width_p, ignore_fixed_p, fixed)
2600 struct window *w;
2601 int width_p, ignore_fixed_p, *fixed;
2603 int size, fixed_p;
2605 if (ignore_fixed_p)
2606 fixed_p = 0;
2607 else
2608 fixed_p = window_fixed_size_p (w, width_p, 1);
2610 if (fixed)
2611 *fixed = fixed_p;
2613 if (fixed_p)
2614 size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines);
2615 else
2616 size = window_min_size_1 (w, width_p);
2618 return size;
2622 /* Adjust the margins of window W if text area is too small.
2623 Return 1 if window width is ok after adjustment; 0 if window
2624 is still too narrow. */
2626 static int
2627 adjust_window_margins (w)
2628 struct window *w;
2630 int box_cols = (WINDOW_TOTAL_COLS (w)
2631 - WINDOW_FRINGE_COLS (w)
2632 - WINDOW_SCROLL_BAR_COLS (w));
2633 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2634 + WINDOW_RIGHT_MARGIN_COLS (w));
2636 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2637 return 1;
2639 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2640 return 0;
2642 /* Window's text area is too narrow, but reducing the window
2643 margins will fix that. */
2644 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2645 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2647 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2648 w->left_margin_cols = w->right_margin_cols
2649 = make_number (margin_cols/2);
2650 else
2651 w->right_margin_cols = make_number (margin_cols);
2653 else
2654 w->left_margin_cols = make_number (margin_cols);
2655 return 1;
2658 /* Calculate new sizes for windows in the list FORWARD when the window size
2659 goes from TOTAL to SIZE. TOTAL must be greater than SIZE.
2660 The number of windows in FORWARD is NCHILDREN, and the number that
2661 can shrink is SHRINKABLE.
2662 The minimum size a window can have is MIN_SIZE.
2663 If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
2664 If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
2665 shrinking rows.
2667 This function returns an allocated array of new sizes that the caller
2668 must free. The size -1 means the window is fixed and RESIZE_FIXED_P
2669 is zero. Array index 0 refers to the first window in FORWARD, 1 to
2670 the second, and so on.
2672 This function tries to keep windows at least at the minimum size
2673 and resize other windows before it resizes any window to zero (i.e.
2674 delete that window).
2676 Windows are resized proportional to their size, so bigger windows
2677 shrink more than smaller windows. */
2678 static int *
2679 shrink_windows (total, size, nchildren, shrinkable,
2680 min_size, resize_fixed_p, forward, width_p)
2681 int total, size, nchildren, shrinkable, min_size;
2682 int resize_fixed_p, width_p;
2683 Lisp_Object forward;
2685 int available_resize = 0;
2686 int *new_sizes;
2687 struct window *c;
2688 Lisp_Object child;
2689 int smallest = total;
2690 int total_removed = 0;
2691 int total_shrink = total - size;
2692 int i;
2694 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2696 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2698 int child_size;
2700 c = XWINDOW (child);
2701 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2703 if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2704 new_sizes[i] = -1;
2705 else
2707 new_sizes[i] = child_size;
2708 if (child_size > min_size)
2709 available_resize += child_size - min_size;
2712 /* We might need to shrink some windows to zero. Find the smallest
2713 windows and set them to 0 until we can fulfil the new size. */
2715 while (shrinkable > 1 && size + available_resize < total)
2717 for (i = 0; i < nchildren; ++i)
2718 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2719 smallest = new_sizes[i];
2721 for (i = 0; i < nchildren; ++i)
2722 if (new_sizes[i] == smallest)
2724 /* Resize this window down to zero. */
2725 new_sizes[i] = 0;
2726 if (smallest > min_size)
2727 available_resize -= smallest - min_size;
2728 available_resize += smallest;
2729 --shrinkable;
2730 total_removed += smallest;
2732 /* We don't know what the smallest is now. */
2733 smallest = total;
2735 /* Out of for, just remove one window at the time and
2736 check again if we have enough space. */
2737 break;
2741 /* Now, calculate the new sizes. Try to shrink each window
2742 proportional to its size. */
2743 for (i = 0; i < nchildren; ++i)
2745 if (new_sizes[i] > min_size)
2747 int to_shrink = total_shrink*new_sizes[i]/total;
2748 if (new_sizes[i] - to_shrink < min_size)
2749 to_shrink = new_sizes[i] - min_size;
2750 new_sizes[i] -= to_shrink;
2751 total_removed += to_shrink;
2755 /* Any reminder due to rounding, we just subtract from windows
2756 that are left and still can be shrunk. */
2757 while (total_shrink > total_removed)
2759 int nonzero_sizes = 0;
2760 int nonzero_idx = -1;
2762 for (i = 0; i < nchildren; ++i)
2763 if (new_sizes[i] > 0)
2765 ++nonzero_sizes;
2766 nonzero_idx = i;
2769 for (i = 0; i < nchildren; ++i)
2770 if (new_sizes[i] > min_size)
2772 --new_sizes[i];
2773 ++total_removed;
2775 /* Out of for, just shrink one window at the time and
2776 check again if we have enough space. */
2777 break;
2781 /* Special case, only one window left. */
2782 if (nonzero_sizes == 1)
2783 break;
2786 /* Any surplus due to rounding, we add to windows that are left. */
2787 while (total_shrink < total_removed)
2789 for (i = 0; i < nchildren; ++i)
2791 if (new_sizes[i] != 0 && total_shrink < total_removed)
2793 ++new_sizes[i];
2794 --total_removed;
2795 break;
2800 return new_sizes;
2803 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2804 WINDOW's width. Resize WINDOW's children, if any, so that they
2805 keep their proportionate size relative to WINDOW. Propagate
2806 WINDOW's top or left edge position to children. Delete windows
2807 that become too small unless NODELETE_P is non-zero.
2809 If NODELETE_P is 2, that means we do delete windows that are
2810 too small, even if they were too small before! */
2812 static void
2813 size_window (window, size, width_p, nodelete_p)
2814 Lisp_Object window;
2815 int size, width_p, nodelete_p;
2817 struct window *w = XWINDOW (window);
2818 struct window *c;
2819 Lisp_Object child, *forward, *sideward;
2820 int old_size, min_size, safe_min_size;
2822 /* We test nodelete_p != 2 and nodelete_p != 1 below, so it
2823 seems like it's too soon to do this here. ++KFS. */
2824 if (nodelete_p == 2)
2825 nodelete_p = 0;
2827 check_min_window_sizes ();
2828 size = max (0, size);
2830 /* If the window has been "too small" at one point,
2831 don't delete it for being "too small" in the future.
2832 Preserve it as long as that is at all possible. */
2833 if (width_p)
2835 old_size = WINDOW_TOTAL_COLS (w);
2836 min_size = window_min_width;
2837 /* Ensure that there is room for the scroll bar and fringes!
2838 We may reduce display margins though. */
2839 safe_min_size = (MIN_SAFE_WINDOW_WIDTH
2840 + WINDOW_FRINGE_COLS (w)
2841 + WINDOW_SCROLL_BAR_COLS (w));
2843 else
2845 old_size = XINT (w->total_lines);
2846 min_size = window_min_height;
2847 safe_min_size = MIN_SAFE_WINDOW_HEIGHT;
2850 if (old_size < min_size && nodelete_p != 2)
2851 w->too_small_ok = Qt;
2853 /* Maybe delete WINDOW if it's too small. */
2854 if (nodelete_p != 1 && !NILP (w->parent))
2856 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
2857 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
2858 if (min_size < safe_min_size)
2859 min_size = safe_min_size;
2860 if (size < min_size)
2862 delete_window (window);
2863 return;
2867 /* Set redisplay hints. */
2868 w->last_modified = make_number (0);
2869 w->last_overlay_modified = make_number (0);
2870 windows_or_buffers_changed++;
2871 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
2873 if (width_p)
2875 sideward = &w->vchild;
2876 forward = &w->hchild;
2877 w->total_cols = make_number (size);
2878 adjust_window_margins (w);
2880 else
2882 sideward = &w->hchild;
2883 forward = &w->vchild;
2884 w->total_lines = make_number (size);
2885 w->orig_total_lines = Qnil;
2888 if (!NILP (*sideward))
2890 for (child = *sideward; !NILP (child); child = c->next)
2892 c = XWINDOW (child);
2893 if (width_p)
2894 c->left_col = w->left_col;
2895 else
2896 c->top_line = w->top_line;
2897 size_window (child, size, width_p, nodelete_p);
2900 else if (!NILP (*forward))
2902 int fixed_size, each, extra, n;
2903 int resize_fixed_p, nfixed;
2904 int last_pos, first_pos, nchildren, total;
2905 int *new_sizes = NULL;
2907 /* Determine the fixed-size portion of the this window, and the
2908 number of child windows. */
2909 fixed_size = nchildren = nfixed = total = 0;
2910 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
2912 int child_size;
2914 c = XWINDOW (child);
2915 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2916 total += child_size;
2918 if (window_fixed_size_p (c, width_p, 0))
2920 fixed_size += child_size;
2921 ++nfixed;
2925 /* If the new size is smaller than fixed_size, or if there
2926 aren't any resizable windows, allow resizing fixed-size
2927 windows. */
2928 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2930 /* Compute how many lines/columns to add/remove to each child. The
2931 value of extra takes care of rounding errors. */
2932 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2933 if (size < total && n > 1)
2934 new_sizes = shrink_windows (total, size, nchildren, n, min_size,
2935 resize_fixed_p, *forward, width_p);
2936 else
2938 each = (size - total) / n;
2939 extra = (size - total) - n * each;
2942 /* Compute new children heights and edge positions. */
2943 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
2944 last_pos = first_pos;
2945 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
2947 int new_size, old_size;
2949 c = XWINDOW (child);
2950 old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines);
2951 new_size = old_size;
2953 /* The top or left edge position of this child equals the
2954 bottom or right edge of its predecessor. */
2955 if (width_p)
2956 c->left_col = make_number (last_pos);
2957 else
2958 c->top_line = make_number (last_pos);
2960 /* If this child can be resized, do it. */
2961 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2963 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
2964 extra = 0;
2967 /* Set new height. Note that size_window also propagates
2968 edge positions to children, so it's not a no-op if we
2969 didn't change the child's size. */
2970 size_window (child, new_size, width_p, 1);
2972 /* Remember the bottom/right edge position of this child; it
2973 will be used to set the top/left edge of the next child. */
2974 last_pos += new_size;
2977 if (new_sizes) xfree (new_sizes);
2979 /* We should have covered the parent exactly with child windows. */
2980 xassert (size == last_pos - first_pos);
2982 /* Now delete any children that became too small. */
2983 if (!nodelete_p)
2984 for (child = *forward; !NILP (child); child = c->next)
2986 int child_size;
2987 c = XWINDOW (child);
2988 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2989 size_window (child, child_size, width_p, 2);
2994 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2995 WINDOW's children. NODELETE non-zero means don't delete windows
2996 that become too small in the process. (The caller should check
2997 later and do so if appropriate.) */
2999 void
3000 set_window_height (window, height, nodelete)
3001 Lisp_Object window;
3002 int height;
3003 int nodelete;
3005 size_window (window, height, 0, nodelete);
3009 /* Set WINDOW's width to WIDTH, and recursively change the width of
3010 WINDOW's children. NODELETE non-zero means don't delete windows
3011 that become too small in the process. (The caller should check
3012 later and do so if appropriate.) */
3014 void
3015 set_window_width (window, width, nodelete)
3016 Lisp_Object window;
3017 int width;
3018 int nodelete;
3020 size_window (window, width, 1, nodelete);
3023 /* Change window heights in windows rooted in WINDOW by N lines. */
3025 void
3026 change_window_heights (window, n)
3027 Lisp_Object window;
3028 int n;
3030 struct window *w = XWINDOW (window);
3032 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
3033 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
3035 if (INTEGERP (w->orig_top_line))
3036 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
3037 if (INTEGERP (w->orig_total_lines))
3038 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
3040 /* Handle just the top child in a vertical split. */
3041 if (!NILP (w->vchild))
3042 change_window_heights (w->vchild, n);
3044 /* Adjust all children in a horizontal split. */
3045 for (window = w->hchild; !NILP (window); window = w->next)
3047 w = XWINDOW (window);
3048 change_window_heights (window, n);
3053 int window_select_count;
3055 Lisp_Object
3056 Fset_window_buffer_unwind (obuf)
3057 Lisp_Object obuf;
3059 Fset_buffer (obuf);
3060 return Qnil;
3063 EXFUN (Fset_window_fringes, 4);
3064 EXFUN (Fset_window_scroll_bars, 4);
3066 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3067 means it's allowed to run hooks. See make_frame for a case where
3068 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3069 margins, fringes, and scroll-bar settings of the window are not
3070 reset from the buffer's local settings. */
3072 void
3073 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
3074 Lisp_Object window, buffer;
3075 int run_hooks_p, keep_margins_p;
3077 struct window *w = XWINDOW (window);
3078 struct buffer *b = XBUFFER (buffer);
3079 int count = SPECPDL_INDEX ();
3081 w->buffer = buffer;
3083 if (EQ (window, selected_window))
3084 b->last_selected_window = window;
3086 /* Let redisplay errors through. */
3087 b->display_error_modiff = 0;
3089 /* Update time stamps of buffer display. */
3090 if (INTEGERP (b->display_count))
3091 XSETINT (b->display_count, XINT (b->display_count) + 1);
3092 b->display_time = Fcurrent_time ();
3094 XSETFASTINT (w->window_end_pos, 0);
3095 XSETFASTINT (w->window_end_vpos, 0);
3096 bzero (&w->last_cursor, sizeof w->last_cursor);
3097 w->window_end_valid = Qnil;
3098 w->hscroll = w->min_hscroll = make_number (0);
3099 w->vscroll = 0;
3100 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3101 set_marker_restricted (w->start,
3102 make_number (b->last_window_start),
3103 buffer);
3104 w->start_at_line_beg = Qnil;
3105 w->force_start = Qnil;
3106 XSETFASTINT (w->last_modified, 0);
3107 XSETFASTINT (w->last_overlay_modified, 0);
3108 windows_or_buffers_changed++;
3110 /* We must select BUFFER for running the window-scroll-functions.
3111 If WINDOW is selected, switch permanently.
3112 Otherwise, switch but go back to the ambient buffer afterward. */
3113 if (EQ (window, selected_window))
3114 Fset_buffer (buffer);
3115 /* We can't check ! NILP (Vwindow_scroll_functions) here
3116 because that might itself be a local variable. */
3117 else if (window_initialized)
3119 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
3120 Fset_buffer (buffer);
3123 if (!keep_margins_p)
3125 /* Set left and right marginal area width etc. from buffer. */
3127 /* This may call adjust_window_margins three times, so
3128 temporarily disable window margins. */
3129 Lisp_Object save_left = w->left_margin_cols;
3130 Lisp_Object save_right = w->right_margin_cols;
3132 w->left_margin_cols = w->right_margin_cols = Qnil;
3134 Fset_window_fringes (window,
3135 b->left_fringe_width, b->right_fringe_width,
3136 b->fringes_outside_margins);
3138 Fset_window_scroll_bars (window,
3139 b->scroll_bar_width,
3140 b->vertical_scroll_bar_type, Qnil);
3142 w->left_margin_cols = save_left;
3143 w->right_margin_cols = save_right;
3145 Fset_window_margins (window,
3146 b->left_margin_cols, b->right_margin_cols);
3149 if (run_hooks_p)
3151 if (! NILP (Vwindow_scroll_functions))
3152 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3153 Fmarker_position (w->start));
3155 if (! NILP (Vwindow_configuration_change_hook)
3156 && ! NILP (Vrun_hooks))
3157 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3160 unbind_to (count, Qnil);
3164 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3165 doc: /* Make WINDOW display BUFFER as its contents.
3166 BUFFER can be a buffer or the name of an existing buffer.
3167 Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
3168 display margins, fringe widths, and scroll bar settings are maintained;
3169 the default is to reset these from BUFFER's local settings or the frame
3170 defaults.
3172 This function runs the hook `window-scroll-functions'. */)
3173 (window, buffer, keep_margins)
3174 register Lisp_Object window, buffer, keep_margins;
3176 register Lisp_Object tem;
3177 register struct window *w = decode_window (window);
3179 XSETWINDOW (window, w);
3180 buffer = Fget_buffer (buffer);
3181 CHECK_BUFFER (buffer);
3183 if (NILP (XBUFFER (buffer)->name))
3184 error ("Attempt to display deleted buffer");
3186 tem = w->buffer;
3187 if (NILP (tem))
3188 error ("Window is deleted");
3189 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3190 is first being set up. */
3192 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3193 error ("Window is dedicated to `%s'",
3194 SDATA (XBUFFER (tem)->name));
3196 unshow_buffer (w);
3199 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3200 return Qnil;
3203 /* Note that selected_window can be nil
3204 when this is called from Fset_window_configuration. */
3206 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3207 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3208 If WINDOW is not already selected, make WINDOW's buffer current
3209 and make WINDOW the frame's selected window. Return WINDOW.
3210 Optional second arg NORECORD non-nil means
3211 do not put this buffer at the front of the list of recently selected ones.
3213 Note that the main editor command loop
3214 selects the buffer of the selected window before each command. */)
3215 (window, norecord)
3216 register Lisp_Object window, norecord;
3218 register struct window *w;
3219 register struct window *ow;
3220 struct frame *sf;
3222 CHECK_LIVE_WINDOW (window);
3224 w = XWINDOW (window);
3225 w->frozen_window_start_p = 0;
3227 ++window_select_count;
3228 XSETFASTINT (w->use_time, window_select_count);
3229 if (EQ (window, selected_window))
3230 return window;
3232 /* Store the current buffer's actual point into the
3233 old selected window. It belongs to that window,
3234 and when the window is not selected, must be in the window. */
3235 if (!NILP (selected_window))
3237 ow = XWINDOW (selected_window);
3238 if (! NILP (ow->buffer))
3239 set_marker_both (ow->pointm, ow->buffer,
3240 BUF_PT (XBUFFER (ow->buffer)),
3241 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3244 selected_window = window;
3245 sf = SELECTED_FRAME ();
3246 if (XFRAME (WINDOW_FRAME (w)) != sf)
3248 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3249 /* Use this rather than Fhandle_switch_frame
3250 so that FRAME_FOCUS_FRAME is moved appropriately as we
3251 move around in the state where a minibuffer in a separate
3252 frame is active. */
3253 Fselect_frame (WINDOW_FRAME (w));
3255 else
3256 sf->selected_window = window;
3258 if (NILP (norecord))
3259 record_buffer (w->buffer);
3260 Fset_buffer (w->buffer);
3262 XBUFFER (w->buffer)->last_selected_window = window;
3264 /* Go to the point recorded in the window.
3265 This is important when the buffer is in more
3266 than one window. It also matters when
3267 redisplay_window has altered point after scrolling,
3268 because it makes the change only in the window. */
3270 register int new_point = marker_position (w->pointm);
3271 if (new_point < BEGV)
3272 SET_PT (BEGV);
3273 else if (new_point > ZV)
3274 SET_PT (ZV);
3275 else
3276 SET_PT (new_point);
3279 windows_or_buffers_changed++;
3280 return window;
3283 static Lisp_Object
3284 select_window_norecord (window)
3285 Lisp_Object window;
3287 return Fselect_window (window, Qt);
3290 /* Deiconify the frame containing the window WINDOW,
3291 unless it is the selected frame;
3292 then return WINDOW.
3294 The reason for the exception for the selected frame
3295 is that it seems better not to change the selected frames visibility
3296 merely because of displaying a different buffer in it.
3297 The deiconification is useful when a buffer gets shown in
3298 another frame that you were not using lately. */
3300 static Lisp_Object
3301 display_buffer_1 (window)
3302 Lisp_Object window;
3304 Lisp_Object frame = XWINDOW (window)->frame;
3305 FRAME_PTR f = XFRAME (frame);
3307 FRAME_SAMPLE_VISIBILITY (f);
3309 if (EQ (frame, selected_frame))
3310 ; /* Assume the selected frame is already visible enough. */
3311 else if (minibuf_level > 0
3312 && MINI_WINDOW_P (XWINDOW (selected_window))
3313 && WINDOW_LIVE_P (minibuf_selected_window)
3314 && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
3315 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3316 else
3318 if (FRAME_ICONIFIED_P (f))
3319 Fmake_frame_visible (frame);
3320 else if (FRAME_VISIBLE_P (f))
3321 Fraise_frame (frame);
3324 return window;
3327 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
3328 doc: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
3329 If the value is t, `display-buffer' or `pop-to-buffer' would create a
3330 special frame for that buffer using the default frame parameters.
3332 If the value is a list, it is a list of frame parameters that would be used
3333 to make a frame for that buffer.
3334 The variables `special-display-buffer-names'
3335 and `special-display-regexps' control this. */)
3336 (buffer_name)
3337 Lisp_Object buffer_name;
3339 Lisp_Object tem;
3341 CHECK_STRING (buffer_name);
3343 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
3344 if (!NILP (tem))
3345 return Qt;
3347 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
3348 if (!NILP (tem))
3349 return XCDR (tem);
3351 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
3353 Lisp_Object car = XCAR (tem);
3354 if (STRINGP (car)
3355 && fast_string_match (car, buffer_name) >= 0)
3356 return Qt;
3357 else if (CONSP (car)
3358 && STRINGP (XCAR (car))
3359 && fast_string_match (XCAR (car), buffer_name) >= 0)
3360 return XCDR (car);
3362 return Qnil;
3365 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
3366 doc: /* Returns non-nil if a buffer named BUFFER-NAME would use the same window.
3367 More precisely, if `display-buffer' or `pop-to-buffer' would display
3368 that buffer in the selected window rather than (as usual) in some other window.
3369 See `same-window-buffer-names' and `same-window-regexps'. */)
3370 (buffer_name)
3371 Lisp_Object buffer_name;
3373 Lisp_Object tem;
3375 CHECK_STRING (buffer_name);
3377 tem = Fmember (buffer_name, Vsame_window_buffer_names);
3378 if (!NILP (tem))
3379 return Qt;
3381 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
3382 if (!NILP (tem))
3383 return Qt;
3385 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3387 Lisp_Object car = XCAR (tem);
3388 if (STRINGP (car)
3389 && fast_string_match (car, buffer_name) >= 0)
3390 return Qt;
3391 else if (CONSP (car)
3392 && STRINGP (XCAR (car))
3393 && fast_string_match (XCAR (car), buffer_name) >= 0)
3394 return Qt;
3396 return Qnil;
3399 /* Use B so the default is (other-buffer). */
3400 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
3401 "BDisplay buffer: \nP",
3402 doc: /* Make BUFFER appear in some window but don't select it.
3403 BUFFER must be the name of an existing buffer, or, when called from Lisp,
3404 a buffer.
3405 If BUFFER is shown already in some window, just use that one,
3406 unless the window is the selected window and the optional second
3407 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3408 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3409 Returns the window displaying BUFFER.
3410 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3411 displaying BUFFER, then simply raise that frame.
3413 The variables `special-display-buffer-names',
3414 `special-display-regexps', `same-window-buffer-names', and
3415 `same-window-regexps' customize how certain buffer names are handled.
3416 The latter two take effect only if NOT-THIS-WINDOW is t.
3418 If optional argument FRAME is `visible', search all visible frames.
3419 If FRAME is 0, search all visible and iconified frames.
3420 If FRAME is t, search all frames.
3421 If FRAME is a frame, search only that frame.
3422 If FRAME is nil, search only the selected frame
3423 (actually the last nonminibuffer frame),
3424 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3425 which means search visible and iconified frames.
3427 If a full-width window on a splittable frame is available to display
3428 the buffer, it may be split, subject to the value of the variable
3429 `split-height-threshold'.
3431 If `even-window-heights' is non-nil, window heights will be evened out
3432 if displaying the buffer causes two vertically adjacent windows to be
3433 displayed. */)
3434 (buffer, not_this_window, frame)
3435 register Lisp_Object buffer, not_this_window, frame;
3437 register Lisp_Object window, tem, swp;
3438 struct frame *f;
3440 swp = Qnil;
3441 buffer = Fget_buffer (buffer);
3442 CHECK_BUFFER (buffer);
3444 if (!NILP (Vdisplay_buffer_function))
3445 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3447 if (NILP (not_this_window)
3448 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3449 return display_buffer_1 (selected_window);
3451 /* See if the user has specified this buffer should appear
3452 in the selected window. */
3453 if (NILP (not_this_window))
3455 swp = Fsame_window_p (XBUFFER (buffer)->name);
3456 if (!NILP (swp) && !no_switch_window (selected_window))
3458 Fswitch_to_buffer (buffer, Qnil);
3459 return display_buffer_1 (selected_window);
3463 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3464 look for a window showing BUFFER on any visible or iconified frame.
3465 Otherwise search only the current frame. */
3466 if (! NILP (frame))
3467 tem = frame;
3468 else if (pop_up_frames
3469 || display_buffer_reuse_frames
3470 || last_nonminibuf_frame == 0)
3471 XSETFASTINT (tem, 0);
3472 else
3473 XSETFRAME (tem, last_nonminibuf_frame);
3475 window = Fget_buffer_window (buffer, tem);
3476 if (!NILP (window)
3477 && (NILP (not_this_window) || !EQ (window, selected_window)))
3478 return display_buffer_1 (window);
3480 /* Certain buffer names get special handling. */
3481 if (!NILP (Vspecial_display_function) && NILP (swp))
3483 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3484 if (EQ (tem, Qt))
3485 return call1 (Vspecial_display_function, buffer);
3486 if (CONSP (tem))
3487 return call2 (Vspecial_display_function, buffer, tem);
3490 /* If there are no frames open that have more than a minibuffer,
3491 we need to create a new frame. */
3492 if (pop_up_frames || last_nonminibuf_frame == 0)
3494 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3495 Fset_window_buffer (window, buffer, Qnil);
3496 return display_buffer_1 (window);
3499 f = SELECTED_FRAME ();
3500 if (pop_up_windows
3501 || FRAME_MINIBUF_ONLY_P (f)
3502 /* If the current frame is a special display frame,
3503 don't try to reuse its windows. */
3504 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3506 Lisp_Object frames;
3508 frames = Qnil;
3509 if (FRAME_MINIBUF_ONLY_P (f))
3510 XSETFRAME (frames, last_nonminibuf_frame);
3511 /* Don't try to create a window if we would get an error. */
3512 if (split_height_threshold < window_min_height << 1)
3513 split_height_threshold = window_min_height << 1;
3515 /* Note that both Fget_largest_window and Fget_lru_window
3516 ignore minibuffers and dedicated windows.
3517 This means they can return nil. */
3519 /* If the frame we would try to split cannot be split,
3520 try other frames. */
3521 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3523 /* Try visible frames first. */
3524 window = Fget_largest_window (Qvisible, Qt);
3525 /* If that didn't work, try iconified frames. */
3526 if (NILP (window))
3527 window = Fget_largest_window (make_number (0), Qt);
3528 #if 0 /* Don't try windows on other displays. */
3529 if (NILP (window))
3530 window = Fget_largest_window (Qt, Qt);
3531 #endif
3533 else
3534 window = Fget_largest_window (frames, Qt);
3536 /* If we got a tall enough full-width window that can be split,
3537 split it. */
3538 if (!NILP (window)
3539 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3540 && window_height (window) >= split_height_threshold
3541 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
3542 window = Fsplit_window (window, Qnil, Qnil);
3543 else
3545 Lisp_Object upper, lower, other;
3547 window = Fget_lru_window (frames, Qt);
3548 /* If the LRU window is selected, and big enough,
3549 and can be split, split it. */
3550 if (!NILP (window)
3551 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3552 && (EQ (window, selected_window)
3553 || EQ (XWINDOW (window)->parent, Qnil))
3554 && window_height (window) >= window_min_height << 1)
3555 window = Fsplit_window (window, Qnil, Qnil);
3556 else
3557 window = Fget_lru_window (frames, Qnil);
3558 /* If Fget_lru_window returned nil, try other approaches. */
3560 /* Try visible frames first. */
3561 if (NILP (window))
3562 window = Fget_buffer_window (buffer, Qvisible);
3563 if (NILP (window))
3564 window = Fget_largest_window (Qvisible, Qnil);
3565 /* If that didn't work, try iconified frames. */
3566 if (NILP (window))
3567 window = Fget_buffer_window (buffer, make_number (0));
3568 if (NILP (window))
3569 window = Fget_largest_window (make_number (0), Qnil);
3571 #if 0 /* Don't try frames on other displays. */
3572 if (NILP (window))
3573 window = Fget_buffer_window (buffer, Qt);
3574 if (NILP (window))
3575 window = Fget_largest_window (Qt, Qnil);
3576 #endif
3577 /* As a last resort, make a new frame. */
3578 if (NILP (window))
3579 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3580 /* If window appears above or below another,
3581 even out their heights. */
3582 other = upper = lower = Qnil;
3583 if (!NILP (XWINDOW (window)->prev))
3584 other = upper = XWINDOW (window)->prev, lower = window;
3585 if (!NILP (XWINDOW (window)->next))
3586 other = lower = XWINDOW (window)->next, upper = window;
3587 if (!NILP (other)
3588 && !NILP (Veven_window_heights)
3589 /* Check that OTHER and WINDOW are vertically arrayed. */
3590 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3591 && (XFASTINT (XWINDOW (other)->total_lines)
3592 > XFASTINT (XWINDOW (window)->total_lines)))
3594 int total = (XFASTINT (XWINDOW (other)->total_lines)
3595 + XFASTINT (XWINDOW (window)->total_lines));
3596 enlarge_window (upper,
3597 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
3602 else
3603 window = Fget_lru_window (Qnil, Qnil);
3605 Fset_window_buffer (window, buffer, Qnil);
3606 return display_buffer_1 (window);
3610 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3611 0, 1, 0,
3612 doc: /* Force redisplay of all windows.
3613 If optional arg OBJECT is a window, force redisplay of that window only.
3614 If OBJECT is a buffer or buffer name, force redisplay of all windows
3615 displaying that buffer. */)
3616 (object)
3617 Lisp_Object object;
3619 if (NILP (object))
3621 windows_or_buffers_changed++;
3622 update_mode_lines++;
3623 return Qt;
3626 if (WINDOWP (object))
3628 struct window *w = XWINDOW (object);
3629 mark_window_display_accurate (object, 0);
3630 w->update_mode_line = Qt;
3631 if (BUFFERP (w->buffer))
3632 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3633 ++update_mode_lines;
3634 return Qt;
3637 if (STRINGP (object))
3638 object = Fget_buffer (object);
3639 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3641 /* Walk all windows looking for buffer, and force update
3642 of each of those windows. */
3644 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3645 return NILP (object) ? Qnil : Qt;
3648 /* If nothing suitable was found, just return.
3649 We could signal an error, but this feature will typically be used
3650 asynchronously in timers or process sentinels, so we don't. */
3651 return Qnil;
3655 void
3656 temp_output_buffer_show (buf)
3657 register Lisp_Object buf;
3659 register struct buffer *old = current_buffer;
3660 register Lisp_Object window;
3661 register struct window *w;
3663 XBUFFER (buf)->directory = current_buffer->directory;
3665 Fset_buffer (buf);
3666 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3667 BEGV = BEG;
3668 ZV = Z;
3669 SET_PT (BEG);
3670 #if 0 /* rms: there should be no reason for this. */
3671 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3672 #endif
3673 set_buffer_internal (old);
3675 if (!NILP (Vtemp_buffer_show_function))
3676 call1 (Vtemp_buffer_show_function, buf);
3677 else
3679 window = Fdisplay_buffer (buf, Qnil, Qnil);
3681 if (!EQ (XWINDOW (window)->frame, selected_frame))
3682 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3683 Vminibuf_scroll_window = window;
3684 w = XWINDOW (window);
3685 XSETFASTINT (w->hscroll, 0);
3686 XSETFASTINT (w->min_hscroll, 0);
3687 set_marker_restricted_both (w->start, buf, BEG, BEG);
3688 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3690 /* Run temp-buffer-show-hook, with the chosen window selected
3691 and its buffer current. */
3693 if (!NILP (Vrun_hooks)
3694 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3695 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3697 int count = SPECPDL_INDEX ();
3698 Lisp_Object prev_window, prev_buffer;
3699 prev_window = selected_window;
3700 XSETBUFFER (prev_buffer, old);
3702 /* Select the window that was chosen, for running the hook.
3703 Note: Both Fselect_window and select_window_norecord may
3704 set-buffer to the buffer displayed in the window,
3705 so we need to save the current buffer. --stef */
3706 record_unwind_protect (Fset_buffer, prev_buffer);
3707 record_unwind_protect (select_window_norecord, prev_window);
3708 Fselect_window (window, Qt);
3709 Fset_buffer (w->buffer);
3710 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3711 unbind_to (count, Qnil);
3716 static void
3717 make_dummy_parent (window)
3718 Lisp_Object window;
3720 Lisp_Object new;
3721 register struct window *o, *p;
3722 int i;
3724 o = XWINDOW (window);
3725 p = allocate_window ();
3726 for (i = 0; i < VECSIZE (struct window); ++i)
3727 ((struct Lisp_Vector *) p)->contents[i]
3728 = ((struct Lisp_Vector *)o)->contents[i];
3729 XSETWINDOW (new, p);
3731 ++sequence_number;
3732 XSETFASTINT (p->sequence_number, sequence_number);
3734 /* Put new into window structure in place of window */
3735 replace_window (window, new);
3737 o->next = Qnil;
3738 o->prev = Qnil;
3739 o->vchild = Qnil;
3740 o->hchild = Qnil;
3741 o->parent = new;
3743 p->start = Qnil;
3744 p->pointm = Qnil;
3745 p->buffer = Qnil;
3748 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3749 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3750 WINDOW defaults to selected one and SIZE to half its size.
3751 If optional third arg HORFLAG is non-nil, split side by side
3752 and put SIZE columns in the first of the pair. In that case,
3753 SIZE includes that window's scroll bar, or the divider column to its right.
3754 Interactively, all arguments are nil.
3756 Returns the newly created window (which is the lower or rightmost one).
3757 The upper or leftmost window is the original one and remains selected.
3758 See Info node `(elisp)Splitting Windows' for more details and examples.*/)
3759 (window, size, horflag)
3760 Lisp_Object window, size, horflag;
3762 register Lisp_Object new;
3763 register struct window *o, *p;
3764 FRAME_PTR fo;
3765 register int size_int;
3767 if (NILP (window))
3768 window = selected_window;
3769 else
3770 CHECK_LIVE_WINDOW (window);
3772 o = XWINDOW (window);
3773 fo = XFRAME (WINDOW_FRAME (o));
3775 if (NILP (size))
3777 if (!NILP (horflag))
3778 /* Calculate the size of the left-hand window, by dividing
3779 the usable space in columns by two.
3780 We round up, since the left-hand window may include
3781 a dividing line, while the right-hand may not. */
3782 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
3783 else
3784 size_int = XFASTINT (o->total_lines) >> 1;
3786 else
3788 CHECK_NUMBER (size);
3789 size_int = XINT (size);
3792 if (MINI_WINDOW_P (o))
3793 error ("Attempt to split minibuffer window");
3794 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3795 error ("Attempt to split fixed-size window");
3797 check_min_window_sizes ();
3799 if (NILP (horflag))
3801 if (size_int < window_min_height)
3802 error ("Window height %d too small (after splitting)", size_int);
3803 if (size_int + window_min_height > XFASTINT (o->total_lines))
3804 error ("Window height %d too small (after splitting)",
3805 XFASTINT (o->total_lines) - size_int);
3806 if (NILP (o->parent)
3807 || NILP (XWINDOW (o->parent)->vchild))
3809 make_dummy_parent (window);
3810 new = o->parent;
3811 XWINDOW (new)->vchild = window;
3814 else
3816 if (size_int < window_min_width)
3817 error ("Window width %d too small (after splitting)", size_int);
3819 if (size_int + window_min_width > XFASTINT (o->total_cols))
3820 error ("Window width %d too small (after splitting)",
3821 XFASTINT (o->total_cols) - size_int);
3822 if (NILP (o->parent)
3823 || NILP (XWINDOW (o->parent)->hchild))
3825 make_dummy_parent (window);
3826 new = o->parent;
3827 XWINDOW (new)->hchild = window;
3831 /* Now we know that window's parent is a vertical combination
3832 if we are dividing vertically, or a horizontal combination
3833 if we are making side-by-side windows */
3835 windows_or_buffers_changed++;
3836 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3837 new = make_window ();
3838 p = XWINDOW (new);
3840 p->frame = o->frame;
3841 p->next = o->next;
3842 if (!NILP (p->next))
3843 XWINDOW (p->next)->prev = new;
3844 p->prev = window;
3845 o->next = new;
3846 p->parent = o->parent;
3847 p->buffer = Qt;
3848 p->window_end_valid = Qnil;
3849 bzero (&p->last_cursor, sizeof p->last_cursor);
3851 /* Duplicate special geometry settings. */
3853 p->left_margin_cols = o->left_margin_cols;
3854 p->right_margin_cols = o->right_margin_cols;
3855 p->left_fringe_width = o->left_fringe_width;
3856 p->right_fringe_width = o->right_fringe_width;
3857 p->fringes_outside_margins = o->fringes_outside_margins;
3858 p->scroll_bar_width = o->scroll_bar_width;
3859 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
3861 /* Apportion the available frame space among the two new windows */
3863 if (!NILP (horflag))
3865 p->total_lines = o->total_lines;
3866 p->top_line = o->top_line;
3867 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
3868 XSETFASTINT (o->total_cols, size_int);
3869 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
3870 adjust_window_margins (p);
3871 adjust_window_margins (o);
3873 else
3875 p->left_col = o->left_col;
3876 p->total_cols = o->total_cols;
3877 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
3878 XSETFASTINT (o->total_lines, size_int);
3879 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
3882 /* Adjust glyph matrices. */
3883 adjust_glyphs (fo);
3885 Fset_window_buffer (new, o->buffer, Qt);
3886 return new;
3889 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3890 doc: /* Make current window ARG lines bigger.
3891 From program, optional second arg non-nil means grow sideways ARG columns.
3892 Interactively, if an argument is not given, make the window one line bigger.
3893 If HORIZONTAL is non-nil, enlarge horizontally instead of vertically.
3894 This function can delete windows, even the second window, if they get
3895 too small. */)
3896 (arg, horizontal)
3897 Lisp_Object arg, horizontal;
3899 CHECK_NUMBER (arg);
3900 enlarge_window (selected_window, XINT (arg), !NILP (horizontal));
3902 if (! NILP (Vwindow_configuration_change_hook))
3903 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3905 return Qnil;
3908 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3909 doc: /* Make current window ARG lines smaller.
3910 From program, optional second arg non-nil means shrink sideways arg columns.
3911 Interactively, if an argument is not given, make the window one line smaller. Only
3912 siblings to the right or below are changed. */)
3913 (arg, side)
3914 Lisp_Object arg, side;
3916 CHECK_NUMBER (arg);
3917 enlarge_window (selected_window, -XINT (arg), !NILP (side));
3919 if (! NILP (Vwindow_configuration_change_hook))
3920 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3922 return Qnil;
3926 window_height (window)
3927 Lisp_Object window;
3929 register struct window *p = XWINDOW (window);
3930 return WINDOW_TOTAL_LINES (p);
3934 window_width (window)
3935 Lisp_Object window;
3937 register struct window *p = XWINDOW (window);
3938 return WINDOW_TOTAL_COLS (p);
3942 #define CURBEG(w) \
3943 *(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
3945 #define CURSIZE(w) \
3946 *(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
3949 /* Enlarge WINDOW by DELTA.
3950 HORIZ_FLAG nonzero means enlarge it horizontally;
3951 zero means do it vertically.
3953 Siblings of the selected window are resized to fulfill the size
3954 request. If they become too small in the process, they will be
3955 deleted. */
3957 static void
3958 enlarge_window (window, delta, horiz_flag)
3959 Lisp_Object window;
3960 int delta, horiz_flag;
3962 Lisp_Object parent, next, prev;
3963 struct window *p;
3964 Lisp_Object *sizep;
3965 int maximum;
3966 int (*sizefun) P_ ((Lisp_Object))
3967 = horiz_flag ? window_width : window_height;
3968 void (*setsizefun) P_ ((Lisp_Object, int, int))
3969 = (horiz_flag ? set_window_width : set_window_height);
3971 /* Check values of window_min_width and window_min_height for
3972 validity. */
3973 check_min_window_sizes ();
3975 /* Give up if this window cannot be resized. */
3976 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
3977 error ("Window is not resizable");
3979 /* Find the parent of the selected window. */
3980 while (1)
3982 p = XWINDOW (window);
3983 parent = p->parent;
3985 if (NILP (parent))
3987 if (horiz_flag)
3988 error ("No other window to side of this one");
3989 break;
3992 if (horiz_flag
3993 ? !NILP (XWINDOW (parent)->hchild)
3994 : !NILP (XWINDOW (parent)->vchild))
3995 break;
3997 window = parent;
4000 sizep = &CURSIZE (window);
4003 register int maxdelta;
4005 /* Compute the maximum size increment this window can have. */
4007 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
4008 /* This is a main window followed by a minibuffer. */
4009 : !NILP (p->next) ? ((*sizefun) (p->next)
4010 - window_min_size (XWINDOW (p->next),
4011 horiz_flag, 0, 0))
4012 /* This is a minibuffer following a main window. */
4013 : !NILP (p->prev) ? ((*sizefun) (p->prev)
4014 - window_min_size (XWINDOW (p->prev),
4015 horiz_flag, 0, 0))
4016 /* This is a frame with only one window, a minibuffer-only
4017 or a minibufferless frame. */
4018 : (delta = 0));
4020 if (delta > maxdelta)
4021 /* This case traps trying to make the minibuffer
4022 the full frame, or make the only window aside from the
4023 minibuffer the full frame. */
4024 delta = maxdelta;
4027 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), horiz_flag, 0, 0))
4029 delete_window (window);
4030 return;
4033 if (delta == 0)
4034 return;
4036 /* Find the total we can get from other siblings without deleting them. */
4037 maximum = 0;
4038 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
4039 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
4040 horiz_flag, 0, 0);
4041 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
4042 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
4043 horiz_flag, 0, 0);
4045 /* If we can get it all from them without deleting them, do so. */
4046 if (delta <= maximum)
4048 Lisp_Object first_unaffected;
4049 Lisp_Object first_affected;
4050 int fixed_p;
4052 next = p->next;
4053 prev = p->prev;
4054 first_affected = window;
4055 /* Look at one sibling at a time,
4056 moving away from this window in both directions alternately,
4057 and take as much as we can get without deleting that sibling. */
4058 while (delta != 0
4059 && (!NILP (next) || !NILP (prev)))
4061 if (! NILP (next))
4063 int this_one = ((*sizefun) (next)
4064 - window_min_size (XWINDOW (next),
4065 horiz_flag, 0, &fixed_p));
4066 if (!fixed_p)
4068 if (this_one > delta)
4069 this_one = delta;
4071 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
4072 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4074 delta -= this_one;
4077 next = XWINDOW (next)->next;
4080 if (delta == 0)
4081 break;
4083 if (! NILP (prev))
4085 int this_one = ((*sizefun) (prev)
4086 - window_min_size (XWINDOW (prev),
4087 horiz_flag, 0, &fixed_p));
4088 if (!fixed_p)
4090 if (this_one > delta)
4091 this_one = delta;
4093 first_affected = prev;
4095 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
4096 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
4098 delta -= this_one;
4101 prev = XWINDOW (prev)->prev;
4105 xassert (delta == 0);
4107 /* Now recalculate the edge positions of all the windows affected,
4108 based on the new sizes. */
4109 first_unaffected = next;
4110 prev = first_affected;
4111 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
4112 prev = next, next = XWINDOW (next)->next)
4114 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
4115 /* This does not change size of NEXT,
4116 but it propagates the new top edge to its children */
4117 (*setsizefun) (next, (*sizefun) (next), 0);
4120 else
4122 register int delta1;
4123 register int opht = (*sizefun) (parent);
4125 if (opht <= XINT (*sizep) + delta)
4127 /* If trying to grow this window to or beyond size of the parent,
4128 just delete all the sibling windows. */
4129 Lisp_Object start, tem, next;
4131 start = XWINDOW (parent)->vchild;
4132 if (NILP (start))
4133 start = XWINDOW (parent)->hchild;
4135 /* Delete any siblings that come after WINDOW. */
4136 tem = XWINDOW (window)->next;
4137 while (! NILP (tem))
4139 next = XWINDOW (tem)->next;
4140 delete_window (tem);
4141 tem = next;
4144 /* Delete any siblings that come after WINDOW.
4145 Note that if START is not WINDOW, then WINDOW still
4146 Fhas siblings, so WINDOW has not yet replaced its parent. */
4147 tem = start;
4148 while (! EQ (tem, window))
4150 next = XWINDOW (tem)->next;
4151 delete_window (tem);
4152 tem = next;
4155 else
4157 /* Otherwise, make delta1 just right so that if we add
4158 delta1 lines to this window and to the parent, and then
4159 shrink the parent back to its original size, the new
4160 proportional size of this window will increase by delta.
4162 The function size_window will compute the new height h'
4163 of the window from delta1 as:
4165 e = delta1/n
4166 x = delta1 - delta1/n * n for the 1st resizable child
4167 h' = h + e + x
4169 where n is the number of children that can be resized.
4170 We can ignore x by choosing a delta1 that is a multiple of
4171 n. We want the height of this window to come out as
4173 h' = h + delta
4175 So, delta1 must be
4177 h + e = h + delta
4178 delta1/n = delta
4179 delta1 = n * delta.
4181 The number of children n equals the number of resizable
4182 children of this window + 1 because we know window itself
4183 is resizable (otherwise we would have signalled an error). */
4185 struct window *w = XWINDOW (window);
4186 Lisp_Object s;
4187 int n = 1;
4189 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
4190 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4191 ++n;
4192 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
4193 if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
4194 ++n;
4196 delta1 = n * delta;
4198 /* Add delta1 lines or columns to this window, and to the parent,
4199 keeping things consistent while not affecting siblings. */
4200 XSETINT (CURSIZE (parent), opht + delta1);
4201 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4203 /* Squeeze out delta1 lines or columns from our parent,
4204 shriking this window and siblings proportionately.
4205 This brings parent back to correct size.
4206 Delta1 was calculated so this makes this window the desired size,
4207 taking it all out of the siblings. */
4208 (*setsizefun) (parent, opht, 0);
4213 XSETFASTINT (p->last_modified, 0);
4214 XSETFASTINT (p->last_overlay_modified, 0);
4216 /* Adjust glyph matrices. */
4217 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4221 /* Adjust the size of WINDOW by DELTA, moving only its trailing edge.
4222 HORIZ_FLAG nonzero means adjust the width, moving the right edge.
4223 zero means adjust the height, moving the bottom edge.
4225 Following siblings of the selected window are resized to fulfill
4226 the size request. If they become too small in the process, they
4227 are not deleted; instead, we signal an error. */
4229 static void
4230 adjust_window_trailing_edge (window, delta, horiz_flag)
4231 Lisp_Object window;
4232 int delta, horiz_flag;
4234 Lisp_Object parent, child;
4235 struct window *p;
4236 Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
4237 int delcount = window_deletion_count;
4239 /* Check values of window_min_width and window_min_height for
4240 validity. */
4241 check_min_window_sizes ();
4243 if (NILP (window))
4244 window = Fselected_window ();
4246 CHECK_WINDOW (window);
4248 /* Give up if this window cannot be resized. */
4249 if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
4250 error ("Window is not resizable");
4252 while (1)
4254 p = XWINDOW (window);
4255 parent = p->parent;
4257 /* Make sure there is a following window. */
4258 if (NILP (parent)
4259 && (horiz_flag ? 1
4260 : NILP (XWINDOW (window)->next)))
4262 Fset_window_configuration (old_config);
4263 error ("No other window following this one");
4266 /* Don't make this window too small. */
4267 if (XINT (CURSIZE (window)) + delta
4268 < (horiz_flag ? window_min_width : window_min_height))
4270 Fset_window_configuration (old_config);
4271 error ("Cannot adjust window size as specified");
4274 /* Clear out some redisplay caches. */
4275 XSETFASTINT (p->last_modified, 0);
4276 XSETFASTINT (p->last_overlay_modified, 0);
4278 /* Adjust this window's edge. */
4279 XSETINT (CURSIZE (window),
4280 XINT (CURSIZE (window)) + delta);
4282 /* If this window has following siblings in the desired dimension,
4283 make them smaller.
4284 (If we reach the top of the tree and can never do this,
4285 we will fail and report an error, above.) */
4286 if (horiz_flag
4287 ? !NILP (XWINDOW (parent)->hchild)
4288 : !NILP (XWINDOW (parent)->vchild))
4290 if (!NILP (XWINDOW (window)->next))
4292 /* This may happen for the minibuffer. In that case
4293 the window_deletion_count check below does not work. */
4294 if (XINT (CURSIZE (p->next)) - delta <= 0)
4296 Fset_window_configuration (old_config);
4297 error ("Cannot adjust window size as specified");
4300 XSETINT (CURBEG (p->next),
4301 XINT (CURBEG (p->next)) + delta);
4302 size_window (p->next, XINT (CURSIZE (p->next)) - delta,
4303 horiz_flag, 0);
4304 break;
4307 else
4308 /* Here we have a chain of parallel siblings, in the other dimension.
4309 Change the size of the other siblings. */
4310 for (child = (horiz_flag
4311 ? XWINDOW (parent)->vchild
4312 : XWINDOW (parent)->hchild);
4313 ! NILP (child);
4314 child = XWINDOW (child)->next)
4315 if (! EQ (child, window))
4316 size_window (child, XINT (CURSIZE (child)) + delta,
4317 horiz_flag, 0);
4319 window = parent;
4322 /* If we made a window so small it got deleted,
4323 we failed. Report failure. */
4324 if (delcount != window_deletion_count)
4326 Fset_window_configuration (old_config);
4327 error ("Cannot adjust window size as specified");
4330 /* Adjust glyph matrices. */
4331 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4334 #undef CURBEG
4335 #undef CURSIZE
4337 DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
4338 Sadjust_window_trailing_edge, 3, 3, 0,
4339 doc: /* Adjust the bottom or right edge of WINDOW by DELTA.
4340 If HORIZONTAL is non-nil, that means adjust the width, moving the right edge.
4341 Otherwise, adjust the height, moving the bottom edge.
4343 Following siblings of the selected window are resized to fulfill
4344 the size request. If they become too small in the process, they
4345 are not deleted; instead, we signal an error. */)
4346 (window, delta, horizontal)
4347 Lisp_Object window, delta, horizontal;
4349 CHECK_NUMBER (delta);
4350 adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
4352 if (! NILP (Vwindow_configuration_change_hook))
4353 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4355 return Qnil;
4360 /***********************************************************************
4361 Resizing Mini-Windows
4362 ***********************************************************************/
4364 static void shrink_window_lowest_first P_ ((struct window *, int));
4366 enum save_restore_action
4368 CHECK_ORIG_SIZES,
4369 SAVE_ORIG_SIZES,
4370 RESTORE_ORIG_SIZES
4373 static int save_restore_orig_size P_ ((struct window *,
4374 enum save_restore_action));
4376 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4377 from lowest windows first. */
4379 static void
4380 shrink_window_lowest_first (w, height)
4381 struct window *w;
4382 int height;
4384 struct window *c;
4385 Lisp_Object child;
4386 int old_height;
4388 xassert (!MINI_WINDOW_P (w));
4390 /* Set redisplay hints. */
4391 XSETFASTINT (w->last_modified, 0);
4392 XSETFASTINT (w->last_overlay_modified, 0);
4393 windows_or_buffers_changed++;
4394 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4396 old_height = XFASTINT (w->total_lines);
4397 XSETFASTINT (w->total_lines, height);
4399 if (!NILP (w->hchild))
4401 for (child = w->hchild; !NILP (child); child = c->next)
4403 c = XWINDOW (child);
4404 c->top_line = w->top_line;
4405 shrink_window_lowest_first (c, height);
4408 else if (!NILP (w->vchild))
4410 Lisp_Object last_child;
4411 int delta = old_height - height;
4412 int last_top;
4414 last_child = Qnil;
4416 /* Find the last child. We are taking space from lowest windows
4417 first, so we iterate over children from the last child
4418 backwards. */
4419 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
4420 last_child = child;
4422 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
4423 for (child = last_child; delta && !NILP (child); child = c->prev)
4425 int this_one;
4427 c = XWINDOW (child);
4428 this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
4430 if (this_one > delta)
4431 this_one = delta;
4433 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4434 delta -= this_one;
4437 /* Compute new positions. */
4438 last_top = XINT (w->top_line);
4439 for (child = w->vchild; !NILP (child); child = c->next)
4441 c = XWINDOW (child);
4442 c->top_line = make_number (last_top);
4443 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4444 last_top += XFASTINT (c->total_lines);
4450 /* Save, restore, or check positions and sizes in the window tree
4451 rooted at W. ACTION says what to do.
4453 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4454 orig_total_lines members are valid for all windows in the window
4455 tree. Value is non-zero if they are valid.
4457 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4458 orig_top_line and orig_total_lines for all windows in the tree.
4460 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4461 stored in orig_top_line and orig_total_lines for all windows. */
4463 static int
4464 save_restore_orig_size (w, action)
4465 struct window *w;
4466 enum save_restore_action action;
4468 int success_p = 1;
4470 while (w)
4472 if (!NILP (w->hchild))
4474 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4475 success_p = 0;
4477 else if (!NILP (w->vchild))
4479 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4480 success_p = 0;
4483 switch (action)
4485 case CHECK_ORIG_SIZES:
4486 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4487 return 0;
4488 break;
4490 case SAVE_ORIG_SIZES:
4491 w->orig_top_line = w->top_line;
4492 w->orig_total_lines = w->total_lines;
4493 XSETFASTINT (w->last_modified, 0);
4494 XSETFASTINT (w->last_overlay_modified, 0);
4495 break;
4497 case RESTORE_ORIG_SIZES:
4498 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4499 w->top_line = w->orig_top_line;
4500 w->total_lines = w->orig_total_lines;
4501 w->orig_total_lines = w->orig_top_line = Qnil;
4502 XSETFASTINT (w->last_modified, 0);
4503 XSETFASTINT (w->last_overlay_modified, 0);
4504 break;
4506 default:
4507 abort ();
4510 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4513 return success_p;
4517 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4518 without deleting other windows. */
4520 void
4521 grow_mini_window (w, delta)
4522 struct window *w;
4523 int delta;
4525 struct frame *f = XFRAME (w->frame);
4526 struct window *root;
4528 xassert (MINI_WINDOW_P (w));
4529 xassert (delta >= 0);
4531 /* Check values of window_min_width and window_min_height for
4532 validity. */
4533 check_min_window_sizes ();
4535 /* Compute how much we can enlarge the mini-window without deleting
4536 other windows. */
4537 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4538 if (delta)
4540 int min_height = window_min_size (root, 0, 0, 0);
4541 if (XFASTINT (root->total_lines) - delta < min_height)
4542 /* Note that the root window may already be smaller than
4543 min_height. */
4544 delta = max (0, XFASTINT (root->total_lines) - min_height);
4547 if (delta)
4549 /* Save original window sizes and positions, if not already done. */
4550 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4551 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4553 /* Shrink other windows. */
4554 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4556 /* Grow the mini-window. */
4557 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4558 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4559 XSETFASTINT (w->last_modified, 0);
4560 XSETFASTINT (w->last_overlay_modified, 0);
4562 adjust_glyphs (f);
4567 /* Shrink mini-window W. If there is recorded info about window sizes
4568 before a call to grow_mini_window, restore recorded window sizes.
4569 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4570 line. */
4572 void
4573 shrink_mini_window (w)
4574 struct window *w;
4576 struct frame *f = XFRAME (w->frame);
4577 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4579 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4581 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4582 adjust_glyphs (f);
4583 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4584 windows_or_buffers_changed = 1;
4586 else if (XFASTINT (w->total_lines) > 1)
4588 /* Distribute the additional lines of the mini-window
4589 among the other windows. */
4590 Lisp_Object window;
4591 XSETWINDOW (window, w);
4592 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
4598 /* Mark window cursors off for all windows in the window tree rooted
4599 at W by setting their phys_cursor_on_p flag to zero. Called from
4600 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4601 the frame are cleared. */
4603 void
4604 mark_window_cursors_off (w)
4605 struct window *w;
4607 while (w)
4609 if (!NILP (w->hchild))
4610 mark_window_cursors_off (XWINDOW (w->hchild));
4611 else if (!NILP (w->vchild))
4612 mark_window_cursors_off (XWINDOW (w->vchild));
4613 else
4614 w->phys_cursor_on_p = 0;
4616 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4621 /* Return number of lines of text (not counting mode lines) in W. */
4624 window_internal_height (w)
4625 struct window *w;
4627 int ht = XFASTINT (w->total_lines);
4629 if (!MINI_WINDOW_P (w))
4631 if (!NILP (w->parent)
4632 || !NILP (w->vchild)
4633 || !NILP (w->hchild)
4634 || !NILP (w->next)
4635 || !NILP (w->prev)
4636 || WINDOW_WANTS_MODELINE_P (w))
4637 --ht;
4639 if (WINDOW_WANTS_HEADER_LINE_P (w))
4640 --ht;
4643 return ht;
4647 /* Return the number of columns in W.
4648 Don't count columns occupied by scroll bars or the vertical bar
4649 separating W from the sibling to its right. */
4652 window_box_text_cols (w)
4653 struct window *w;
4655 struct frame *f = XFRAME (WINDOW_FRAME (w));
4656 int width = XINT (w->total_cols);
4658 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4659 /* Scroll bars occupy a few columns. */
4660 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4661 else if (!FRAME_WINDOW_P (f)
4662 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4663 /* The column of `|' characters separating side-by-side windows
4664 occupies one column only. */
4665 width -= 1;
4667 if (FRAME_WINDOW_P (f))
4668 /* On window-systems, fringes and display margins cannot be
4669 used for normal text. */
4670 width -= (WINDOW_FRINGE_COLS (w)
4671 + WINDOW_LEFT_MARGIN_COLS (w)
4672 + WINDOW_RIGHT_MARGIN_COLS (w));
4674 return width;
4678 /************************************************************************
4679 Window Scrolling
4680 ***********************************************************************/
4682 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4683 N screen-fulls, which is defined as the height of the window minus
4684 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4685 instead. Negative values of N mean scroll down. NOERROR non-zero
4686 means don't signal an error if we try to move over BEGV or ZV,
4687 respectively. */
4689 static void
4690 window_scroll (window, n, whole, noerror)
4691 Lisp_Object window;
4692 int n;
4693 int whole;
4694 int noerror;
4696 immediate_quit = 1;
4698 /* If we must, use the pixel-based version which is much slower than
4699 the line-based one but can handle varying line heights. */
4700 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4701 window_scroll_pixel_based (window, n, whole, noerror);
4702 else
4703 window_scroll_line_based (window, n, whole, noerror);
4705 immediate_quit = 0;
4709 /* Implementation of window_scroll that works based on pixel line
4710 heights. See the comment of window_scroll for parameter
4711 descriptions. */
4713 static void
4714 window_scroll_pixel_based (window, n, whole, noerror)
4715 Lisp_Object window;
4716 int n;
4717 int whole;
4718 int noerror;
4720 struct it it;
4721 struct window *w = XWINDOW (window);
4722 struct text_pos start;
4723 Lisp_Object tem;
4724 int this_scroll_margin;
4725 /* True if we fiddled the window vscroll field without really scrolling. */
4726 int vscrolled = 0;
4727 static int preserve_y = -1;
4729 SET_TEXT_POS_FROM_MARKER (start, w->start);
4731 /* If PT is not visible in WINDOW, move back one half of
4732 the screen. Allow PT to be partially visible, otherwise
4733 something like (scroll-down 1) with PT in the line before
4734 the partially visible one would recenter. */
4735 tem = Fpos_visible_in_window_p (make_number (PT), window, Qt);
4736 if (NILP (tem))
4738 /* Move backward half the height of the window. Performance note:
4739 vmotion used here is about 10% faster, but would give wrong
4740 results for variable height lines. */
4741 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4742 it.current_y = it.last_visible_y;
4743 move_it_vertically_backward (&it, window_box_height (w) / 2);
4745 /* The function move_iterator_vertically may move over more than
4746 the specified y-distance. If it->w is small, e.g. a
4747 mini-buffer window, we may end up in front of the window's
4748 display area. This is the case when Start displaying at the
4749 start of the line containing PT in this case. */
4750 if (it.current_y <= 0)
4752 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4753 move_it_vertically_backward (&it, 0);
4754 it.current_y = 0;
4757 start = it.current.pos;
4759 else if (auto_window_vscroll_p)
4761 if (tem = XCAR (XCDR (XCDR (tem))), CONSP (tem))
4763 int px;
4764 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4765 if (whole)
4766 dy = max ((window_box_height (w)
4767 - next_screen_context_lines * dy),
4768 dy);
4769 dy *= n;
4771 if (n < 0 && (px = XINT (XCAR (tem))) > 0)
4773 px = max (0, -w->vscroll - min (px, -dy));
4774 Fset_window_vscroll (window, make_number (px), Qt);
4775 return;
4777 if (n > 0 && (px = XINT (XCDR (tem))) > 0)
4779 px = max (0, -w->vscroll + min (px, dy));
4780 Fset_window_vscroll (window, make_number (px), Qt);
4781 return;
4784 Fset_window_vscroll (window, make_number (0), Qt);
4787 /* If scroll_preserve_screen_position is non-nil, we try to set
4788 point in the same window line as it is now, so get that line. */
4789 if (!NILP (Vscroll_preserve_screen_position))
4791 /* We preserve the goal pixel coordinate across consecutive
4792 calls to scroll-up or scroll-down. This avoids the
4793 possibility of point becoming "stuck" on a tall line when
4794 scrolling by one line. */
4795 if (preserve_y < 0
4796 || (current_kboard->Vlast_command != Qscroll_up
4797 && current_kboard->Vlast_command != Qscroll_down))
4799 start_display (&it, w, start);
4800 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4801 preserve_y = it.current_y;
4804 else
4805 preserve_y = -1;
4807 /* Move iterator it from start the specified distance forward or
4808 backward. The result is the new window start. */
4809 start_display (&it, w, start);
4810 if (whole)
4812 int start_pos = IT_CHARPOS (it);
4813 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4814 dy = max ((window_box_height (w)
4815 - next_screen_context_lines * dy),
4816 dy) * n;
4818 /* Note that move_it_vertically always moves the iterator to the
4819 start of a line. So, if the last line doesn't have a newline,
4820 we would end up at the start of the line ending at ZV. */
4821 if (dy <= 0)
4823 move_it_vertically_backward (&it, -dy);
4824 /* Ensure we actually does move, e.g. in case we are currently
4825 looking at an image that is taller that the window height. */
4826 while (start_pos == IT_CHARPOS (it)
4827 && start_pos > BEGV)
4828 move_it_by_lines (&it, -1, 1);
4830 else if (dy > 0)
4832 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4833 MOVE_TO_POS | MOVE_TO_Y);
4834 /* Ensure we actually does move, e.g. in case we are currently
4835 looking at an image that is taller that the window height. */
4836 while (start_pos == IT_CHARPOS (it)
4837 && start_pos < ZV)
4838 move_it_by_lines (&it, 1, 1);
4841 else
4842 move_it_by_lines (&it, n, 1);
4844 /* We failed if we find ZV is already on the screen (scrolling up,
4845 means there's nothing past the end), or if we can't start any
4846 earlier (scrolling down, means there's nothing past the top). */
4847 if ((n > 0 && IT_CHARPOS (it) == ZV)
4848 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4850 if (IT_CHARPOS (it) == ZV)
4852 if (it.current_y < it.last_visible_y
4853 && (it.current_y + it.max_ascent + it.max_descent
4854 >= it.last_visible_y))
4856 /* The last line was only partially visible, make it fully
4857 visible. */
4858 w->vscroll = (it.last_visible_y
4859 - it.current_y + it.max_ascent + it.max_descent);
4860 adjust_glyphs (it.f);
4862 else if (noerror)
4863 return;
4864 else
4865 Fsignal (Qend_of_buffer, Qnil);
4867 else
4869 if (w->vscroll != 0)
4870 /* The first line was only partially visible, make it fully
4871 visible. */
4872 w->vscroll = 0;
4873 else if (noerror)
4874 return;
4875 else
4876 Fsignal (Qbeginning_of_buffer, Qnil);
4879 /* If control gets here, then we vscrolled. */
4881 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4883 /* Don't try to change the window start below. */
4884 vscrolled = 1;
4887 if (! vscrolled)
4889 int pos = IT_CHARPOS (it);
4890 int bytepos;
4892 /* If in the middle of a multi-glyph character move forward to
4893 the next character. */
4894 if (in_display_vector_p (&it))
4896 ++pos;
4897 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4900 /* Set the window start, and set up the window for redisplay. */
4901 set_marker_restricted (w->start, make_number (pos),
4902 w->buffer);
4903 bytepos = XMARKER (w->start)->bytepos;
4904 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
4905 ? Qt : Qnil);
4906 w->update_mode_line = Qt;
4907 XSETFASTINT (w->last_modified, 0);
4908 XSETFASTINT (w->last_overlay_modified, 0);
4909 /* Set force_start so that redisplay_window will run the
4910 window-scroll-functions. */
4911 w->force_start = Qt;
4914 /* The rest of this function uses current_y in a nonstandard way,
4915 not including the height of the header line if any. */
4916 it.current_y = it.vpos = 0;
4918 /* Move PT out of scroll margins.
4919 This code wants current_y to be zero at the window start position
4920 even if there is a header line. */
4921 this_scroll_margin = max (0, scroll_margin);
4922 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4923 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4925 if (n > 0)
4927 /* We moved the window start towards ZV, so PT may be now
4928 in the scroll margin at the top. */
4929 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4930 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
4931 && (NILP (Vscroll_preserve_screen_position)
4932 || EQ (Vscroll_preserve_screen_position, Qt)))
4933 /* We found PT at a legitimate height. Leave it alone. */
4935 else if (preserve_y >= 0)
4937 /* If we have a header line, take account of it.
4938 This is necessary because we set it.current_y to 0, above. */
4939 move_it_to (&it, -1, -1,
4940 preserve_y - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
4941 -1, MOVE_TO_Y);
4942 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4944 else
4946 while (it.current_y < this_scroll_margin)
4948 int prev = it.current_y;
4949 move_it_by_lines (&it, 1, 1);
4950 if (prev == it.current_y)
4951 break;
4953 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4956 else if (n < 0)
4958 int charpos, bytepos;
4959 int partial_p;
4961 /* Save our position, for the preserve_y case. */
4962 charpos = IT_CHARPOS (it);
4963 bytepos = IT_BYTEPOS (it);
4965 /* We moved the window start towards BEGV, so PT may be now
4966 in the scroll margin at the bottom. */
4967 move_it_to (&it, PT, -1,
4968 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
4969 - this_scroll_margin - 1),
4971 MOVE_TO_POS | MOVE_TO_Y);
4973 /* Save our position, in case it's correct. */
4974 charpos = IT_CHARPOS (it);
4975 bytepos = IT_BYTEPOS (it);
4977 /* See if point is on a partially visible line at the end. */
4978 if (it.what == IT_EOB)
4979 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
4980 else
4982 move_it_by_lines (&it, 1, 1);
4983 partial_p = it.current_y > it.last_visible_y;
4986 if (charpos == PT && !partial_p
4987 && (NILP (Vscroll_preserve_screen_position)
4988 || EQ (Vscroll_preserve_screen_position, Qt)))
4989 /* We found PT before we found the display margin, so PT is ok. */
4991 else if (preserve_y >= 0)
4993 SET_TEXT_POS_FROM_MARKER (start, w->start);
4994 start_display (&it, w, start);
4995 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
4996 here because we called start_display again and did not
4997 alter it.current_y this time. */
4998 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
4999 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5001 else
5003 if (partial_p)
5004 /* The last line was only partially visible, so back up two
5005 lines to make sure we're on a fully visible line. */
5007 move_it_by_lines (&it, -2, 0);
5008 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5010 else
5011 /* No, the position we saved is OK, so use it. */
5012 SET_PT_BOTH (charpos, bytepos);
5018 /* Implementation of window_scroll that works based on screen lines.
5019 See the comment of window_scroll for parameter descriptions. */
5021 static void
5022 window_scroll_line_based (window, n, whole, noerror)
5023 Lisp_Object window;
5024 int n;
5025 int whole;
5026 int noerror;
5028 register struct window *w = XWINDOW (window);
5029 register int opoint = PT, opoint_byte = PT_BYTE;
5030 register int pos, pos_byte;
5031 register int ht = window_internal_height (w);
5032 register Lisp_Object tem;
5033 int lose;
5034 Lisp_Object bolp;
5035 int startpos;
5036 struct position posit;
5037 int original_vpos;
5039 /* If scrolling screen-fulls, compute the number of lines to
5040 scroll from the window's height. */
5041 if (whole)
5042 n *= max (1, ht - next_screen_context_lines);
5044 startpos = marker_position (w->start);
5046 posit = *compute_motion (startpos, 0, 0, 0,
5047 PT, ht, 0,
5048 -1, XINT (w->hscroll),
5049 0, w);
5050 original_vpos = posit.vpos;
5052 XSETFASTINT (tem, PT);
5053 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5055 if (NILP (tem))
5057 Fvertical_motion (make_number (- (ht / 2)), window);
5058 startpos = PT;
5061 SET_PT (startpos);
5062 lose = n < 0 && PT == BEGV;
5063 Fvertical_motion (make_number (n), window);
5064 pos = PT;
5065 pos_byte = PT_BYTE;
5066 bolp = Fbolp ();
5067 SET_PT_BOTH (opoint, opoint_byte);
5069 if (lose)
5071 if (noerror)
5072 return;
5073 else
5074 Fsignal (Qbeginning_of_buffer, Qnil);
5077 if (pos < ZV)
5079 int this_scroll_margin = scroll_margin;
5081 /* Don't use a scroll margin that is negative or too large. */
5082 if (this_scroll_margin < 0)
5083 this_scroll_margin = 0;
5085 if (XINT (w->total_lines) < 4 * scroll_margin)
5086 this_scroll_margin = XINT (w->total_lines) / 4;
5088 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
5089 w->start_at_line_beg = bolp;
5090 w->update_mode_line = Qt;
5091 XSETFASTINT (w->last_modified, 0);
5092 XSETFASTINT (w->last_overlay_modified, 0);
5093 /* Set force_start so that redisplay_window will run
5094 the window-scroll-functions. */
5095 w->force_start = Qt;
5097 if (!NILP (Vscroll_preserve_screen_position)
5098 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5100 SET_PT_BOTH (pos, pos_byte);
5101 Fvertical_motion (make_number (original_vpos), window);
5103 /* If we scrolled forward, put point enough lines down
5104 that it is outside the scroll margin. */
5105 else if (n > 0)
5107 int top_margin;
5109 if (this_scroll_margin > 0)
5111 SET_PT_BOTH (pos, pos_byte);
5112 Fvertical_motion (make_number (this_scroll_margin), window);
5113 top_margin = PT;
5115 else
5116 top_margin = pos;
5118 if (top_margin <= opoint)
5119 SET_PT_BOTH (opoint, opoint_byte);
5120 else if (!NILP (Vscroll_preserve_screen_position))
5122 SET_PT_BOTH (pos, pos_byte);
5123 Fvertical_motion (make_number (original_vpos), window);
5125 else
5126 SET_PT (top_margin);
5128 else if (n < 0)
5130 int bottom_margin;
5132 /* If we scrolled backward, put point near the end of the window
5133 but not within the scroll margin. */
5134 SET_PT_BOTH (pos, pos_byte);
5135 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
5136 if (XFASTINT (tem) == ht - this_scroll_margin)
5137 bottom_margin = PT;
5138 else
5139 bottom_margin = PT + 1;
5141 if (bottom_margin > opoint)
5142 SET_PT_BOTH (opoint, opoint_byte);
5143 else
5145 if (!NILP (Vscroll_preserve_screen_position))
5147 SET_PT_BOTH (pos, pos_byte);
5148 Fvertical_motion (make_number (original_vpos), window);
5150 else
5151 Fvertical_motion (make_number (-1), window);
5155 else
5157 if (noerror)
5158 return;
5159 else
5160 Fsignal (Qend_of_buffer, Qnil);
5165 /* Scroll selected_window up or down. If N is nil, scroll a
5166 screen-full which is defined as the height of the window minus
5167 next_screen_context_lines. If N is the symbol `-', scroll.
5168 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5169 up. This is the guts of Fscroll_up and Fscroll_down. */
5171 static void
5172 scroll_command (n, direction)
5173 Lisp_Object n;
5174 int direction;
5176 int count = SPECPDL_INDEX ();
5178 xassert (abs (direction) == 1);
5180 /* If selected window's buffer isn't current, make it current for
5181 the moment. But don't screw up if window_scroll gets an error. */
5182 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
5184 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5185 Fset_buffer (XWINDOW (selected_window)->buffer);
5187 /* Make redisplay consider other windows than just selected_window. */
5188 ++windows_or_buffers_changed;
5191 if (NILP (n))
5192 window_scroll (selected_window, direction, 1, 0);
5193 else if (EQ (n, Qminus))
5194 window_scroll (selected_window, -direction, 1, 0);
5195 else
5197 n = Fprefix_numeric_value (n);
5198 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5201 unbind_to (count, Qnil);
5204 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
5205 doc: /* Scroll text of current window upward ARG lines.
5206 If ARG is omitted or nil, scroll upward by a near full screen.
5207 A near full screen is `next-screen-context-lines' less than a full screen.
5208 Negative ARG means scroll downward.
5209 If ARG is the atom `-', scroll downward by nearly full screen.
5210 When calling from a program, supply as argument a number, nil, or `-'. */)
5211 (arg)
5212 Lisp_Object arg;
5214 scroll_command (arg, 1);
5215 return Qnil;
5218 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
5219 doc: /* Scroll text of current window down ARG lines.
5220 If ARG is omitted or nil, scroll down by a near full screen.
5221 A near full screen is `next-screen-context-lines' less than a full screen.
5222 Negative ARG means scroll upward.
5223 If ARG is the atom `-', scroll upward by nearly full screen.
5224 When calling from a program, supply as argument a number, nil, or `-'. */)
5225 (arg)
5226 Lisp_Object arg;
5228 scroll_command (arg, -1);
5229 return Qnil;
5232 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5233 doc: /* Return the other window for \"other window scroll\" commands.
5234 If `other-window-scroll-buffer' is non-nil, a window
5235 showing that buffer is used.
5236 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5237 specifies the window. This takes precedence over
5238 `other-window-scroll-buffer'. */)
5241 Lisp_Object window;
5243 if (MINI_WINDOW_P (XWINDOW (selected_window))
5244 && !NILP (Vminibuf_scroll_window))
5245 window = Vminibuf_scroll_window;
5246 /* If buffer is specified, scroll that buffer. */
5247 else if (!NILP (Vother_window_scroll_buffer))
5249 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5250 if (NILP (window))
5251 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5253 else
5255 /* Nothing specified; look for a neighboring window on the same
5256 frame. */
5257 window = Fnext_window (selected_window, Qnil, Qnil);
5259 if (EQ (window, selected_window))
5260 /* That didn't get us anywhere; look for a window on another
5261 visible frame. */
5263 window = Fnext_window (window, Qnil, Qt);
5264 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5265 && ! EQ (window, selected_window));
5268 CHECK_LIVE_WINDOW (window);
5270 if (EQ (window, selected_window))
5271 error ("There is no other window");
5273 return window;
5276 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5277 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5278 A near full screen is `next-screen-context-lines' less than a full screen.
5279 The next window is the one below the current one; or the one at the top
5280 if the current one is at the bottom. Negative ARG means scroll downward.
5281 If ARG is the atom `-', scroll downward by nearly full screen.
5282 When calling from a program, supply as argument a number, nil, or `-'.
5284 If `other-window-scroll-buffer' is non-nil, scroll the window
5285 showing that buffer, popping the buffer up if necessary.
5286 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5287 specifies the window to scroll. This takes precedence over
5288 `other-window-scroll-buffer'. */)
5289 (arg)
5290 Lisp_Object arg;
5292 Lisp_Object window;
5293 struct window *w;
5294 int count = SPECPDL_INDEX ();
5296 window = Fother_window_for_scrolling ();
5297 w = XWINDOW (window);
5299 /* Don't screw up if window_scroll gets an error. */
5300 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5301 ++windows_or_buffers_changed;
5303 Fset_buffer (w->buffer);
5304 SET_PT (marker_position (w->pointm));
5306 if (NILP (arg))
5307 window_scroll (window, 1, 1, 1);
5308 else if (EQ (arg, Qminus))
5309 window_scroll (window, -1, 1, 1);
5310 else
5312 if (CONSP (arg))
5313 arg = Fcar (arg);
5314 CHECK_NUMBER (arg);
5315 window_scroll (window, XINT (arg), 0, 1);
5318 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5319 unbind_to (count, Qnil);
5321 return Qnil;
5324 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "P\np",
5325 doc: /* Scroll selected window display ARG columns left.
5326 Default for ARG is window width minus 2.
5327 Value is the total amount of leftward horizontal scrolling in
5328 effect after the change.
5329 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5330 lower bound for automatic scrolling, i.e. automatic scrolling
5331 will not scroll a window to a column less than the value returned
5332 by this function. This happens in an interactive call. */)
5333 (arg, set_minimum)
5334 register Lisp_Object arg, set_minimum;
5336 Lisp_Object result;
5337 int hscroll;
5338 struct window *w = XWINDOW (selected_window);
5340 if (NILP (arg))
5341 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5342 else
5343 arg = Fprefix_numeric_value (arg);
5345 hscroll = XINT (w->hscroll) + XINT (arg);
5346 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5348 if (!NILP (set_minimum))
5349 w->min_hscroll = w->hscroll;
5351 return result;
5354 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "P\np",
5355 doc: /* Scroll selected window display ARG columns right.
5356 Default for ARG is window width minus 2.
5357 Value is the total amount of leftward horizontal scrolling in
5358 effect after the change.
5359 If SET_MINIMUM is non-nil, the new scroll amount becomes the
5360 lower bound for automatic scrolling, i.e. automatic scrolling
5361 will not scroll a window to a column less than the value returned
5362 by this function. This happens in an interactive call. */)
5363 (arg, set_minimum)
5364 register Lisp_Object arg, set_minimum;
5366 Lisp_Object result;
5367 int hscroll;
5368 struct window *w = XWINDOW (selected_window);
5370 if (NILP (arg))
5371 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5372 else
5373 arg = Fprefix_numeric_value (arg);
5375 hscroll = XINT (w->hscroll) - XINT (arg);
5376 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5378 if (!NILP (set_minimum))
5379 w->min_hscroll = w->hscroll;
5381 return result;
5384 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5385 doc: /* Return the window which was selected when entering the minibuffer.
5386 Returns nil, if current window is not a minibuffer window. */)
5389 if (minibuf_level > 0
5390 && MINI_WINDOW_P (XWINDOW (selected_window))
5391 && WINDOW_LIVE_P (minibuf_selected_window))
5392 return minibuf_selected_window;
5394 return Qnil;
5397 /* Value is the number of lines actually displayed in window W,
5398 as opposed to its height. */
5400 static int
5401 displayed_window_lines (w)
5402 struct window *w;
5404 struct it it;
5405 struct text_pos start;
5406 int height = window_box_height (w);
5407 struct buffer *old_buffer;
5408 int bottom_y;
5410 if (XBUFFER (w->buffer) != current_buffer)
5412 old_buffer = current_buffer;
5413 set_buffer_internal (XBUFFER (w->buffer));
5415 else
5416 old_buffer = NULL;
5418 /* In case W->start is out of the accessible range, do something
5419 reasonable. This happens in Info mode when Info-scroll-down
5420 calls (recenter -1) while W->start is 1. */
5421 if (XMARKER (w->start)->charpos < BEGV)
5422 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5423 else if (XMARKER (w->start)->charpos > ZV)
5424 SET_TEXT_POS (start, ZV, ZV_BYTE);
5425 else
5426 SET_TEXT_POS_FROM_MARKER (start, w->start);
5428 start_display (&it, w, start);
5429 move_it_vertically (&it, height);
5430 bottom_y = line_bottom_y (&it);
5432 /* rms: On a non-window display,
5433 the value of it.vpos at the bottom of the screen
5434 seems to be 1 larger than window_box_height (w).
5435 This kludge fixes a bug whereby (move-to-window-line -1)
5436 when ZV is on the last screen line
5437 moves to the previous screen line instead of the last one. */
5438 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5439 height++;
5441 /* Add in empty lines at the bottom of the window. */
5442 if (bottom_y < height)
5444 int uy = FRAME_LINE_HEIGHT (it.f);
5445 it.vpos += (height - bottom_y + uy - 1) / uy;
5448 if (old_buffer)
5449 set_buffer_internal (old_buffer);
5451 return it.vpos;
5455 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5456 doc: /* Center point in window and redisplay frame.
5457 With prefix argument ARG, recenter putting point on screen line ARG
5458 relative to the current window. If ARG is negative, it counts up from the
5459 bottom of the window. (ARG should be less than the height of the window.)
5461 If ARG is omitted or nil, erase the entire frame and then
5462 redraw with point in the center of the current window.
5463 Just C-u as prefix means put point in the center of the window
5464 and redisplay normally--don't erase and redraw the frame. */)
5465 (arg)
5466 register Lisp_Object arg;
5468 struct window *w = XWINDOW (selected_window);
5469 struct buffer *buf = XBUFFER (w->buffer);
5470 struct buffer *obuf = current_buffer;
5471 int center_p = 0;
5472 int charpos, bytepos;
5473 int iarg;
5474 int this_scroll_margin;
5476 /* If redisplay is suppressed due to an error, try again. */
5477 obuf->display_error_modiff = 0;
5479 if (NILP (arg))
5481 int i;
5483 /* Invalidate pixel data calculated for all compositions. */
5484 for (i = 0; i < n_compositions; i++)
5485 composition_table[i]->font = NULL;
5487 Fredraw_frame (w->frame);
5488 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
5489 center_p = 1;
5491 else if (CONSP (arg)) /* Just C-u. */
5492 center_p = 1;
5493 else
5495 arg = Fprefix_numeric_value (arg);
5496 CHECK_NUMBER (arg);
5497 iarg = XINT (arg);
5500 set_buffer_internal (buf);
5502 /* Do this after making BUF current
5503 in case scroll_margin is buffer-local. */
5504 this_scroll_margin = max (0, scroll_margin);
5505 this_scroll_margin = min (this_scroll_margin,
5506 XFASTINT (w->total_lines) / 4);
5508 /* Handle centering on a graphical frame specially. Such frames can
5509 have variable-height lines and centering point on the basis of
5510 line counts would lead to strange effects. */
5511 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5513 if (center_p)
5515 struct it it;
5516 struct text_pos pt;
5518 SET_TEXT_POS (pt, PT, PT_BYTE);
5519 start_display (&it, w, pt);
5520 move_it_vertically_backward (&it, window_box_height (w) / 2);
5521 charpos = IT_CHARPOS (it);
5522 bytepos = IT_BYTEPOS (it);
5524 else if (iarg < 0)
5526 struct it it;
5527 struct text_pos pt;
5528 int nlines = -iarg;
5529 int extra_line_spacing;
5530 int h = window_box_height (w);
5532 iarg = - max (-iarg, this_scroll_margin);
5534 SET_TEXT_POS (pt, PT, PT_BYTE);
5535 start_display (&it, w, pt);
5537 /* Be sure we have the exact height of the full line containing PT. */
5538 move_it_by_lines (&it, 0, 1);
5540 /* The amount of pixels we have to move back is the window
5541 height minus what's displayed in the line containing PT,
5542 and the lines below. */
5543 it.current_y = 0;
5544 it.vpos = 0;
5545 move_it_by_lines (&it, nlines, 1);
5547 if (it.vpos == nlines)
5548 h -= it.current_y;
5549 else
5551 /* Last line has no newline */
5552 h -= line_bottom_y (&it);
5553 it.vpos++;
5556 /* Don't reserve space for extra line spacing of last line. */
5557 extra_line_spacing = it.max_extra_line_spacing;
5559 /* If we can't move down NLINES lines because we hit
5560 the end of the buffer, count in some empty lines. */
5561 if (it.vpos < nlines)
5563 nlines -= it.vpos;
5564 extra_line_spacing = it.extra_line_spacing;
5565 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5567 if (h <= 0)
5568 return Qnil;
5570 /* Now find the new top line (starting position) of the window. */
5571 start_display (&it, w, pt);
5572 it.current_y = 0;
5573 move_it_vertically_backward (&it, h);
5575 /* If extra line spacing is present, we may move too far
5576 back. This causes the last line to be only partially
5577 visible (which triggers redisplay to recenter that line
5578 in the middle), so move forward.
5579 But ignore extra line spacing on last line, as it is not
5580 considered to be part of the visible height of the line.
5582 h += extra_line_spacing;
5583 while (-it.current_y > h)
5584 move_it_by_lines (&it, 1, 1);
5586 charpos = IT_CHARPOS (it);
5587 bytepos = IT_BYTEPOS (it);
5589 else
5591 struct position pos;
5593 iarg = max (iarg, this_scroll_margin);
5595 pos = *vmotion (PT, -iarg, w);
5596 charpos = pos.bufpos;
5597 bytepos = pos.bytepos;
5600 else
5602 struct position pos;
5603 int ht = window_internal_height (w);
5605 if (center_p)
5606 iarg = ht / 2;
5607 else if (iarg < 0)
5608 iarg += ht;
5610 /* Don't let it get into the margin at either top or bottom. */
5611 iarg = max (iarg, this_scroll_margin);
5612 iarg = min (iarg, ht - this_scroll_margin - 1);
5614 pos = *vmotion (PT, - iarg, w);
5615 charpos = pos.bufpos;
5616 bytepos = pos.bytepos;
5619 /* Set the new window start. */
5620 set_marker_both (w->start, w->buffer, charpos, bytepos);
5621 w->window_end_valid = Qnil;
5623 w->optional_new_start = Qt;
5625 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5626 w->start_at_line_beg = Qt;
5627 else
5628 w->start_at_line_beg = Qnil;
5630 set_buffer_internal (obuf);
5631 return Qnil;
5635 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5636 0, 1, 0,
5637 doc: /* Return the height in lines of the text display area of WINDOW.
5638 This doesn't include the mode-line (or header-line if any) or any
5639 partial-height lines in the text display area. */)
5640 (window)
5641 Lisp_Object window;
5643 struct window *w = decode_window (window);
5644 int pixel_height = window_box_height (w);
5645 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5646 return make_number (line_height);
5651 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5652 1, 1, "P",
5653 doc: /* Position point relative to window.
5654 With no argument, position point at center of window.
5655 An argument specifies vertical position within the window;
5656 zero means top of window, negative means relative to bottom of window. */)
5657 (arg)
5658 Lisp_Object arg;
5660 struct window *w = XWINDOW (selected_window);
5661 int lines, start;
5662 Lisp_Object window;
5663 #if 0
5664 int this_scroll_margin;
5665 #endif
5667 window = selected_window;
5668 start = marker_position (w->start);
5669 if (start < BEGV || start > ZV)
5671 int height = window_internal_height (w);
5672 Fvertical_motion (make_number (- (height / 2)), window);
5673 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5674 w->start_at_line_beg = Fbolp ();
5675 w->force_start = Qt;
5677 else
5678 Fgoto_char (w->start);
5680 lines = displayed_window_lines (w);
5682 #if 0
5683 this_scroll_margin = max (0, scroll_margin);
5684 this_scroll_margin = min (this_scroll_margin, lines / 4);
5685 #endif
5687 if (NILP (arg))
5688 XSETFASTINT (arg, lines / 2);
5689 else
5691 int iarg = XINT (Fprefix_numeric_value (arg));
5693 if (iarg < 0)
5694 iarg = iarg + lines;
5696 #if 0 /* This code would prevent move-to-window-line from moving point
5697 to a place inside the scroll margins (which would cause the
5698 next redisplay to scroll). I wrote this code, but then concluded
5699 it is probably better not to install it. However, it is here
5700 inside #if 0 so as not to lose it. -- rms. */
5702 /* Don't let it get into the margin at either top or bottom. */
5703 iarg = max (iarg, this_scroll_margin);
5704 iarg = min (iarg, lines - this_scroll_margin - 1);
5705 #endif
5707 arg = make_number (iarg);
5710 /* Skip past a partially visible first line. */
5711 if (w->vscroll)
5712 XSETINT (arg, XINT (arg) + 1);
5714 return Fvertical_motion (arg, window);
5719 /***********************************************************************
5720 Window Configuration
5721 ***********************************************************************/
5723 struct save_window_data
5725 EMACS_INT size_from_Lisp_Vector_struct;
5726 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5727 Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
5728 Lisp_Object frame_tool_bar_lines;
5729 Lisp_Object selected_frame;
5730 Lisp_Object current_window;
5731 Lisp_Object current_buffer;
5732 Lisp_Object minibuf_scroll_window;
5733 Lisp_Object minibuf_selected_window;
5734 Lisp_Object root_window;
5735 Lisp_Object focus_frame;
5736 /* Record the values of window-min-width and window-min-height
5737 so that window sizes remain consistent with them. */
5738 Lisp_Object min_width, min_height;
5739 /* A vector, each of whose elements is a struct saved_window
5740 for one window. */
5741 Lisp_Object saved_windows;
5744 /* This is saved as a Lisp_Vector */
5745 struct saved_window
5747 /* these first two must agree with struct Lisp_Vector in lisp.h */
5748 EMACS_INT size_from_Lisp_Vector_struct;
5749 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5751 Lisp_Object window;
5752 Lisp_Object buffer, start, pointm, mark;
5753 Lisp_Object left_col, top_line, total_cols, total_lines;
5754 Lisp_Object hscroll, min_hscroll;
5755 Lisp_Object parent, prev;
5756 Lisp_Object start_at_line_beg;
5757 Lisp_Object display_table;
5758 Lisp_Object orig_top_line, orig_total_lines;
5759 Lisp_Object left_margin_cols, right_margin_cols;
5760 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5761 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
5764 #define SAVED_WINDOW_N(swv,n) \
5765 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5767 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5768 doc: /* Return t if OBJECT is a window-configuration object. */)
5769 (object)
5770 Lisp_Object object;
5772 if (WINDOW_CONFIGURATIONP (object))
5773 return Qt;
5774 return Qnil;
5777 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5778 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5779 (config)
5780 Lisp_Object config;
5782 register struct save_window_data *data;
5783 struct Lisp_Vector *saved_windows;
5785 if (! WINDOW_CONFIGURATIONP (config))
5786 wrong_type_argument (Qwindow_configuration_p, config);
5788 data = (struct save_window_data *) XVECTOR (config);
5789 saved_windows = XVECTOR (data->saved_windows);
5790 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5793 DEFUN ("set-window-configuration", Fset_window_configuration,
5794 Sset_window_configuration, 1, 1, 0,
5795 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5796 CONFIGURATION must be a value previously returned
5797 by `current-window-configuration' (which see).
5798 If CONFIGURATION was made from a frame that is now deleted,
5799 only frame-independent values can be restored. In this case,
5800 the return value is nil. Otherwise the value is t. */)
5801 (configuration)
5802 Lisp_Object configuration;
5804 register struct save_window_data *data;
5805 struct Lisp_Vector *saved_windows;
5806 Lisp_Object new_current_buffer;
5807 Lisp_Object frame;
5808 FRAME_PTR f;
5809 int old_point = -1;
5811 while (!WINDOW_CONFIGURATIONP (configuration))
5812 wrong_type_argument (Qwindow_configuration_p, configuration);
5814 data = (struct save_window_data *) XVECTOR (configuration);
5815 saved_windows = XVECTOR (data->saved_windows);
5817 new_current_buffer = data->current_buffer;
5818 if (NILP (XBUFFER (new_current_buffer)->name))
5819 new_current_buffer = Qnil;
5820 else
5822 if (XBUFFER (new_current_buffer) == current_buffer)
5823 /* The code further down "preserves point" by saving here PT in
5824 old_point and then setting it later back into PT. When the
5825 current-selected-window and the final-selected-window both show
5826 the current buffer, this suffers from the problem that the
5827 current PT is the window-point of the current-selected-window,
5828 while the final PT is the point of the final-selected-window, so
5829 this copy from one PT to the other would end up moving the
5830 window-point of the final-selected-window to the window-point of
5831 the current-selected-window. So we have to be careful which
5832 point of the current-buffer we copy into old_point. */
5833 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5834 && WINDOWP (selected_window)
5835 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
5836 && !EQ (selected_window, data->current_window))
5837 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5838 else
5839 old_point = PT;
5840 else
5841 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5842 point in new_current_buffer as of the last time this buffer was
5843 used. This can be non-deterministic since it can be changed by
5844 things like jit-lock by mere temporary selection of some random
5845 window that happens to show this buffer.
5846 So if possible we want this arbitrary choice of "which point" to
5847 be the one from the to-be-selected-window so as to prevent this
5848 window's cursor from being copied from another window. */
5849 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5850 /* If current_window = selected_window, its point is in BUF_PT. */
5851 && !EQ (selected_window, data->current_window))
5852 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5853 else
5854 old_point = BUF_PT (XBUFFER (new_current_buffer));
5857 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5858 f = XFRAME (frame);
5860 /* If f is a dead frame, don't bother rebuilding its window tree.
5861 However, there is other stuff we should still try to do below. */
5862 if (FRAME_LIVE_P (f))
5864 register struct window *w;
5865 register struct saved_window *p;
5866 struct window *root_window;
5867 struct window **leaf_windows;
5868 int n_leaf_windows;
5869 int k, i, n;
5871 /* If the frame has been resized since this window configuration was
5872 made, we change the frame to the size specified in the
5873 configuration, restore the configuration, and then resize it
5874 back. We keep track of the prevailing height in these variables. */
5875 int previous_frame_lines = FRAME_LINES (f);
5876 int previous_frame_cols = FRAME_COLS (f);
5877 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5878 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5880 /* The mouse highlighting code could get screwed up
5881 if it runs during this. */
5882 BLOCK_INPUT;
5884 if (XFASTINT (data->frame_lines) != previous_frame_lines
5885 || XFASTINT (data->frame_cols) != previous_frame_cols)
5886 change_frame_size (f, XFASTINT (data->frame_lines),
5887 XFASTINT (data->frame_cols), 0, 0, 0);
5888 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5889 if (XFASTINT (data->frame_menu_bar_lines)
5890 != previous_frame_menu_bar_lines)
5891 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
5892 #ifdef HAVE_WINDOW_SYSTEM
5893 if (XFASTINT (data->frame_tool_bar_lines)
5894 != previous_frame_tool_bar_lines)
5895 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
5896 #endif
5897 #endif
5899 /* "Swap out" point from the selected window's buffer
5900 into the window itself. (Normally the pointm of the selected
5901 window holds garbage.) We do this now, before
5902 restoring the window contents, and prevent it from
5903 being done later on when we select a new window. */
5904 if (! NILP (XWINDOW (selected_window)->buffer))
5906 w = XWINDOW (selected_window);
5907 set_marker_both (w->pointm,
5908 w->buffer,
5909 BUF_PT (XBUFFER (w->buffer)),
5910 BUF_PT_BYTE (XBUFFER (w->buffer)));
5913 windows_or_buffers_changed++;
5914 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5916 /* Problem: Freeing all matrices and later allocating them again
5917 is a serious redisplay flickering problem. What we would
5918 really like to do is to free only those matrices not reused
5919 below. */
5920 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5921 leaf_windows
5922 = (struct window **) alloca (count_windows (root_window)
5923 * sizeof (struct window *));
5924 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5926 /* Temporarily avoid any problems with windows that are smaller
5927 than they are supposed to be. */
5928 window_min_height = 1;
5929 window_min_width = 1;
5931 /* Kludge Alert!
5932 Mark all windows now on frame as "deleted".
5933 Restoring the new configuration "undeletes" any that are in it.
5935 Save their current buffers in their height fields, since we may
5936 need it later, if a buffer saved in the configuration is now
5937 dead. */
5938 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5940 for (k = 0; k < saved_windows->size; k++)
5942 p = SAVED_WINDOW_N (saved_windows, k);
5943 w = XWINDOW (p->window);
5944 w->next = Qnil;
5946 if (!NILP (p->parent))
5947 w->parent = SAVED_WINDOW_N (saved_windows,
5948 XFASTINT (p->parent))->window;
5949 else
5950 w->parent = Qnil;
5952 if (!NILP (p->prev))
5954 w->prev = SAVED_WINDOW_N (saved_windows,
5955 XFASTINT (p->prev))->window;
5956 XWINDOW (w->prev)->next = p->window;
5958 else
5960 w->prev = Qnil;
5961 if (!NILP (w->parent))
5963 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
5965 XWINDOW (w->parent)->vchild = p->window;
5966 XWINDOW (w->parent)->hchild = Qnil;
5968 else
5970 XWINDOW (w->parent)->hchild = p->window;
5971 XWINDOW (w->parent)->vchild = Qnil;
5976 /* If we squirreled away the buffer in the window's height,
5977 restore it now. */
5978 if (BUFFERP (w->total_lines))
5979 w->buffer = w->total_lines;
5980 w->left_col = p->left_col;
5981 w->top_line = p->top_line;
5982 w->total_cols = p->total_cols;
5983 w->total_lines = p->total_lines;
5984 w->hscroll = p->hscroll;
5985 w->min_hscroll = p->min_hscroll;
5986 w->display_table = p->display_table;
5987 w->orig_top_line = p->orig_top_line;
5988 w->orig_total_lines = p->orig_total_lines;
5989 w->left_margin_cols = p->left_margin_cols;
5990 w->right_margin_cols = p->right_margin_cols;
5991 w->left_fringe_width = p->left_fringe_width;
5992 w->right_fringe_width = p->right_fringe_width;
5993 w->fringes_outside_margins = p->fringes_outside_margins;
5994 w->scroll_bar_width = p->scroll_bar_width;
5995 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
5996 XSETFASTINT (w->last_modified, 0);
5997 XSETFASTINT (w->last_overlay_modified, 0);
5999 /* Reinstall the saved buffer and pointers into it. */
6000 if (NILP (p->buffer))
6001 w->buffer = p->buffer;
6002 else
6004 if (!NILP (XBUFFER (p->buffer)->name))
6005 /* If saved buffer is alive, install it. */
6007 w->buffer = p->buffer;
6008 w->start_at_line_beg = p->start_at_line_beg;
6009 set_marker_restricted (w->start, p->start, w->buffer);
6010 set_marker_restricted (w->pointm, p->pointm, w->buffer);
6011 Fset_marker (XBUFFER (w->buffer)->mark,
6012 p->mark, w->buffer);
6014 /* As documented in Fcurrent_window_configuration, don't
6015 restore the location of point in the buffer which was
6016 current when the window configuration was recorded. */
6017 if (!EQ (p->buffer, new_current_buffer)
6018 && XBUFFER (p->buffer) == current_buffer)
6019 Fgoto_char (w->pointm);
6021 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
6022 /* Else unless window has a live buffer, get one. */
6024 w->buffer = Fcdr (Fcar (Vbuffer_alist));
6025 /* This will set the markers to beginning of visible
6026 range. */
6027 set_marker_restricted (w->start, make_number (0), w->buffer);
6028 set_marker_restricted (w->pointm, make_number (0),w->buffer);
6029 w->start_at_line_beg = Qt;
6031 else
6032 /* Keeping window's old buffer; make sure the markers
6033 are real. */
6035 /* Set window markers at start of visible range. */
6036 if (XMARKER (w->start)->buffer == 0)
6037 set_marker_restricted (w->start, make_number (0),
6038 w->buffer);
6039 if (XMARKER (w->pointm)->buffer == 0)
6040 set_marker_restricted_both (w->pointm, w->buffer,
6041 BUF_PT (XBUFFER (w->buffer)),
6042 BUF_PT_BYTE (XBUFFER (w->buffer)));
6043 w->start_at_line_beg = Qt;
6048 FRAME_ROOT_WINDOW (f) = data->root_window;
6049 /* Prevent "swapping out point" in the old selected window
6050 using the buffer that has been restored into it.
6051 We already swapped out point that from that window's old buffer. */
6052 selected_window = Qnil;
6054 /* Arrange *not* to restore point in the buffer that was
6055 current when the window configuration was saved. */
6056 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
6057 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6058 make_number (old_point),
6059 XWINDOW (data->current_window)->buffer);
6061 Fselect_window (data->current_window, Qnil);
6062 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
6063 = selected_window;
6065 if (NILP (data->focus_frame)
6066 || (FRAMEP (data->focus_frame)
6067 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6068 Fredirect_frame_focus (frame, data->focus_frame);
6070 #if 0 /* I don't understand why this is needed, and it causes problems
6071 when the frame's old selected window has been deleted. */
6072 if (f != selected_frame && FRAME_WINDOW_P (f))
6073 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
6074 0, 0);
6075 #endif
6077 /* Set the screen height to the value it had before this function. */
6078 if (previous_frame_lines != FRAME_LINES (f)
6079 || previous_frame_cols != FRAME_COLS (f))
6080 change_frame_size (f, previous_frame_lines, previous_frame_cols,
6081 0, 0, 0);
6082 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
6083 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
6084 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
6085 make_number (0));
6086 #ifdef HAVE_WINDOW_SYSTEM
6087 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
6088 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
6089 make_number (0));
6090 #endif
6091 #endif
6093 /* Now, free glyph matrices in windows that were not reused. */
6094 for (i = n = 0; i < n_leaf_windows; ++i)
6096 if (NILP (leaf_windows[i]->buffer))
6098 /* Assert it's not reused as a combination. */
6099 xassert (NILP (leaf_windows[i]->hchild)
6100 && NILP (leaf_windows[i]->vchild));
6101 free_window_matrices (leaf_windows[i]);
6103 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
6104 ++n;
6107 adjust_glyphs (f);
6109 UNBLOCK_INPUT;
6111 /* Fselect_window will have made f the selected frame, so we
6112 reselect the proper frame here. Fhandle_switch_frame will change the
6113 selected window too, but that doesn't make the call to
6114 Fselect_window above totally superfluous; it still sets f's
6115 selected window. */
6116 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6117 do_switch_frame (data->selected_frame, 0, 0);
6119 if (! NILP (Vwindow_configuration_change_hook)
6120 && ! NILP (Vrun_hooks))
6121 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
6124 if (!NILP (new_current_buffer))
6125 Fset_buffer (new_current_buffer);
6127 /* Restore the minimum heights recorded in the configuration. */
6128 window_min_height = XINT (data->min_height);
6129 window_min_width = XINT (data->min_width);
6131 Vminibuf_scroll_window = data->minibuf_scroll_window;
6132 minibuf_selected_window = data->minibuf_selected_window;
6134 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6137 /* Mark all windows now on frame as deleted
6138 by setting their buffers to nil. */
6140 void
6141 delete_all_subwindows (w)
6142 register struct window *w;
6144 if (!NILP (w->next))
6145 delete_all_subwindows (XWINDOW (w->next));
6146 if (!NILP (w->vchild))
6147 delete_all_subwindows (XWINDOW (w->vchild));
6148 if (!NILP (w->hchild))
6149 delete_all_subwindows (XWINDOW (w->hchild));
6151 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
6153 if (!NILP (w->buffer))
6154 unshow_buffer (w);
6156 /* We set all three of these fields to nil, to make sure that we can
6157 distinguish this dead window from any live window. Live leaf
6158 windows will have buffer set, and combination windows will have
6159 vchild or hchild set. */
6160 w->buffer = Qnil;
6161 w->vchild = Qnil;
6162 w->hchild = Qnil;
6164 Vwindow_list = Qnil;
6167 static int
6168 count_windows (window)
6169 register struct window *window;
6171 register int count = 1;
6172 if (!NILP (window->next))
6173 count += count_windows (XWINDOW (window->next));
6174 if (!NILP (window->vchild))
6175 count += count_windows (XWINDOW (window->vchild));
6176 if (!NILP (window->hchild))
6177 count += count_windows (XWINDOW (window->hchild));
6178 return count;
6182 /* Fill vector FLAT with leaf windows under W, starting at index I.
6183 Value is last index + 1. */
6185 static int
6186 get_leaf_windows (w, flat, i)
6187 struct window *w;
6188 struct window **flat;
6189 int i;
6191 while (w)
6193 if (!NILP (w->hchild))
6194 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
6195 else if (!NILP (w->vchild))
6196 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
6197 else
6198 flat[i++] = w;
6200 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6203 return i;
6207 /* Return a pointer to the glyph W's physical cursor is on. Value is
6208 null if W's current matrix is invalid, so that no meaningfull glyph
6209 can be returned. */
6211 struct glyph *
6212 get_phys_cursor_glyph (w)
6213 struct window *w;
6215 struct glyph_row *row;
6216 struct glyph *glyph;
6218 if (w->phys_cursor.vpos >= 0
6219 && w->phys_cursor.vpos < w->current_matrix->nrows
6220 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
6221 row->enabled_p)
6222 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
6223 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
6224 else
6225 glyph = NULL;
6227 return glyph;
6231 static int
6232 save_window_save (window, vector, i)
6233 Lisp_Object window;
6234 struct Lisp_Vector *vector;
6235 int i;
6237 register struct saved_window *p;
6238 register struct window *w;
6239 register Lisp_Object tem;
6241 for (;!NILP (window); window = w->next)
6243 p = SAVED_WINDOW_N (vector, i);
6244 w = XWINDOW (window);
6246 XSETFASTINT (w->temslot, i); i++;
6247 p->window = window;
6248 p->buffer = w->buffer;
6249 p->left_col = w->left_col;
6250 p->top_line = w->top_line;
6251 p->total_cols = w->total_cols;
6252 p->total_lines = w->total_lines;
6253 p->hscroll = w->hscroll;
6254 p->min_hscroll = w->min_hscroll;
6255 p->display_table = w->display_table;
6256 p->orig_top_line = w->orig_top_line;
6257 p->orig_total_lines = w->orig_total_lines;
6258 p->left_margin_cols = w->left_margin_cols;
6259 p->right_margin_cols = w->right_margin_cols;
6260 p->left_fringe_width = w->left_fringe_width;
6261 p->right_fringe_width = w->right_fringe_width;
6262 p->fringes_outside_margins = w->fringes_outside_margins;
6263 p->scroll_bar_width = w->scroll_bar_width;
6264 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6265 if (!NILP (w->buffer))
6267 /* Save w's value of point in the window configuration.
6268 If w is the selected window, then get the value of point
6269 from the buffer; pointm is garbage in the selected window. */
6270 if (EQ (window, selected_window))
6272 p->pointm = Fmake_marker ();
6273 set_marker_both (p->pointm, w->buffer,
6274 BUF_PT (XBUFFER (w->buffer)),
6275 BUF_PT_BYTE (XBUFFER (w->buffer)));
6277 else
6278 p->pointm = Fcopy_marker (w->pointm, Qnil);
6280 p->start = Fcopy_marker (w->start, Qnil);
6281 p->start_at_line_beg = w->start_at_line_beg;
6283 tem = XBUFFER (w->buffer)->mark;
6284 p->mark = Fcopy_marker (tem, Qnil);
6286 else
6288 p->pointm = Qnil;
6289 p->start = Qnil;
6290 p->mark = Qnil;
6291 p->start_at_line_beg = Qnil;
6294 if (NILP (w->parent))
6295 p->parent = Qnil;
6296 else
6297 p->parent = XWINDOW (w->parent)->temslot;
6299 if (NILP (w->prev))
6300 p->prev = Qnil;
6301 else
6302 p->prev = XWINDOW (w->prev)->temslot;
6304 if (!NILP (w->vchild))
6305 i = save_window_save (w->vchild, vector, i);
6306 if (!NILP (w->hchild))
6307 i = save_window_save (w->hchild, vector, i);
6310 return i;
6313 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6314 Scurrent_window_configuration, 0, 1, 0,
6315 doc: /* Return an object representing the current window configuration of FRAME.
6316 If FRAME is nil or omitted, use the selected frame.
6317 This describes the number of windows, their sizes and current buffers,
6318 and for each displayed buffer, where display starts, and the positions of
6319 point and mark. An exception is made for point in the current buffer:
6320 its value is -not- saved.
6321 This also records the currently selected frame, and FRAME's focus
6322 redirection (see `redirect-frame-focus'). */)
6323 (frame)
6324 Lisp_Object frame;
6326 register Lisp_Object tem;
6327 register int n_windows;
6328 register struct save_window_data *data;
6329 register struct Lisp_Vector *vec;
6330 register int i;
6331 FRAME_PTR f;
6333 if (NILP (frame))
6334 frame = selected_frame;
6335 CHECK_LIVE_FRAME (frame);
6336 f = XFRAME (frame);
6338 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6339 vec = allocate_other_vector (VECSIZE (struct save_window_data));
6340 data = (struct save_window_data *)vec;
6342 XSETFASTINT (data->frame_cols, FRAME_COLS (f));
6343 XSETFASTINT (data->frame_lines, FRAME_LINES (f));
6344 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
6345 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
6346 data->selected_frame = selected_frame;
6347 data->current_window = FRAME_SELECTED_WINDOW (f);
6348 XSETBUFFER (data->current_buffer, current_buffer);
6349 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6350 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6351 data->root_window = FRAME_ROOT_WINDOW (f);
6352 data->focus_frame = FRAME_FOCUS_FRAME (f);
6353 XSETINT (data->min_height, window_min_height);
6354 XSETINT (data->min_width, window_min_width);
6355 tem = Fmake_vector (make_number (n_windows), Qnil);
6356 data->saved_windows = tem;
6357 for (i = 0; i < n_windows; i++)
6358 XVECTOR (tem)->contents[i]
6359 = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
6360 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6361 XSETWINDOW_CONFIGURATION (tem, data);
6362 return (tem);
6365 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
6366 0, UNEVALLED, 0,
6367 doc: /* Execute BODY, preserving window sizes and contents.
6368 Return the value of the last form in BODY.
6369 Restore which buffer appears in which window, where display starts,
6370 and the value of point and mark for each window.
6371 Also restore the choice of selected window.
6372 Also restore which buffer is current.
6373 Does not restore the value of point in current buffer.
6374 usage: (save-window-excursion BODY ...) */)
6375 (args)
6376 Lisp_Object args;
6378 register Lisp_Object val;
6379 register int count = SPECPDL_INDEX ();
6381 record_unwind_protect (Fset_window_configuration,
6382 Fcurrent_window_configuration (Qnil));
6383 val = Fprogn (args);
6384 return unbind_to (count, val);
6389 /***********************************************************************
6390 Window Split Tree
6391 ***********************************************************************/
6393 static Lisp_Object
6394 window_tree (w)
6395 struct window *w;
6397 Lisp_Object tail = Qnil;
6398 Lisp_Object result = Qnil;
6400 while (w)
6402 Lisp_Object wn;
6404 XSETWINDOW (wn, w);
6405 if (!NILP (w->hchild))
6406 wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
6407 window_tree (XWINDOW (w->hchild))));
6408 else if (!NILP (w->vchild))
6409 wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
6410 window_tree (XWINDOW (w->vchild))));
6412 if (NILP (result))
6414 result = tail = Fcons (wn, Qnil);
6416 else
6418 XSETCDR (tail, Fcons (wn, Qnil));
6419 tail = XCDR (tail);
6422 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6425 return result;
6430 DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
6431 0, 1, 0,
6432 doc: /* Return the window tree for frame FRAME.
6434 The return value is a list of the form (ROOT MINI), where ROOT
6435 represents the window tree of the frame's root window, and MINI
6436 is the frame's minibuffer window.
6438 If the root window is not split, ROOT is the root window itself.
6439 Otherwise, ROOT is a list (DIR EDGES W1 W2 ...) where DIR is nil for a
6440 horizontal split, and t for a vertical split, EDGES gives the combined
6441 size and position of the subwindows in the split, and the rest of the
6442 elements are the subwindows in the split. Each of the subwindows may
6443 again be a window or a list representing a window split, and so on.
6444 EDGES is a list \(LEFT TOP RIGHT BOTTOM) as returned by `window-edges'.
6446 If FRAME is nil or omitted, return information on the currently
6447 selected frame. */)
6448 (frame)
6449 Lisp_Object frame;
6451 FRAME_PTR f;
6453 if (NILP (frame))
6454 frame = selected_frame;
6456 CHECK_FRAME (frame);
6457 f = XFRAME (frame);
6459 if (!FRAME_LIVE_P (f))
6460 return Qnil;
6462 return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
6466 /***********************************************************************
6467 Marginal Areas
6468 ***********************************************************************/
6470 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6471 2, 3, 0,
6472 doc: /* Set width of marginal areas of window WINDOW.
6473 If WINDOW is nil, set margins of the currently selected window.
6474 Second arg LEFT-WIDTH specifies the number of character cells to
6475 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6476 does the same for the right marginal area. A nil width parameter
6477 means no margin. */)
6478 (window, left_width, right_width)
6479 Lisp_Object window, left_width, right_width;
6481 struct window *w = decode_window (window);
6483 /* Translate negative or zero widths to nil.
6484 Margins that are too wide have to be checked elsewhere. */
6486 if (!NILP (left_width))
6488 CHECK_NUMBER (left_width);
6489 if (XINT (left_width) <= 0)
6490 left_width = Qnil;
6493 if (!NILP (right_width))
6495 CHECK_NUMBER (right_width);
6496 if (XINT (right_width) <= 0)
6497 right_width = Qnil;
6500 if (!EQ (w->left_margin_cols, left_width)
6501 || !EQ (w->right_margin_cols, right_width))
6503 w->left_margin_cols = left_width;
6504 w->right_margin_cols = right_width;
6506 adjust_window_margins (w);
6508 ++windows_or_buffers_changed;
6509 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6512 return Qnil;
6516 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6517 0, 1, 0,
6518 doc: /* Get width of marginal areas of window WINDOW.
6519 If WINDOW is omitted or nil, use the currently selected window.
6520 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6521 If a marginal area does not exist, its width will be returned
6522 as nil. */)
6523 (window)
6524 Lisp_Object window;
6526 struct window *w = decode_window (window);
6527 return Fcons (w->left_margin_cols, w->right_margin_cols);
6532 /***********************************************************************
6533 Fringes
6534 ***********************************************************************/
6536 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6537 2, 4, 0,
6538 doc: /* Set the fringe widths of window WINDOW.
6539 If WINDOW is nil, set the fringe widths of the currently selected
6540 window.
6541 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6542 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6543 fringe width. If a fringe width arg is nil, that means to use the
6544 frame's default fringe width. Default fringe widths can be set with
6545 the command `set-fringe-style'.
6546 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6547 outside of the display margins. By default, fringes are drawn between
6548 display marginal areas and the text area. */)
6549 (window, left_width, right_width, outside_margins)
6550 Lisp_Object window, left_width, right_width, outside_margins;
6552 struct window *w = decode_window (window);
6554 if (!NILP (left_width))
6555 CHECK_NATNUM (left_width);
6556 if (!NILP (right_width))
6557 CHECK_NATNUM (right_width);
6559 if (!EQ (w->left_fringe_width, left_width)
6560 || !EQ (w->right_fringe_width, right_width)
6561 || !EQ (w->fringes_outside_margins, outside_margins))
6563 w->left_fringe_width = left_width;
6564 w->right_fringe_width = right_width;
6565 w->fringes_outside_margins = outside_margins;
6567 adjust_window_margins (w);
6569 clear_glyph_matrix (w->current_matrix);
6570 w->window_end_valid = Qnil;
6572 ++windows_or_buffers_changed;
6573 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6576 return Qnil;
6580 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6581 0, 1, 0,
6582 doc: /* Get width of fringes of window WINDOW.
6583 If WINDOW is omitted or nil, use the currently selected window.
6584 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6585 (window)
6586 Lisp_Object window;
6588 struct window *w = decode_window (window);
6589 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6590 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6591 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ?
6592 Qt : Qnil), Qnil)));
6597 /***********************************************************************
6598 Scroll bars
6599 ***********************************************************************/
6601 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6602 2, 4, 0,
6603 doc: /* Set width and type of scroll bars of window WINDOW.
6604 If window is nil, set scroll bars of the currently selected window.
6605 Second parameter WIDTH specifies the pixel width for the scroll bar;
6606 this is automatically adjusted to a multiple of the frame column width.
6607 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6608 bar: left, right, or nil.
6609 If WIDTH is nil, use the frame's scroll-bar width.
6610 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6611 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6612 (window, width, vertical_type, horizontal_type)
6613 Lisp_Object window, width, vertical_type, horizontal_type;
6615 struct window *w = decode_window (window);
6617 if (!NILP (width))
6619 CHECK_NATNUM (width);
6621 if (XINT (width) == 0)
6622 vertical_type = Qnil;
6625 if (!(EQ (vertical_type, Qnil)
6626 || EQ (vertical_type, Qleft)
6627 || EQ (vertical_type, Qright)
6628 || EQ (vertical_type, Qt)))
6629 error ("Invalid type of vertical scroll bar");
6631 if (!EQ (w->scroll_bar_width, width)
6632 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6634 w->scroll_bar_width = width;
6635 w->vertical_scroll_bar_type = vertical_type;
6637 adjust_window_margins (w);
6639 clear_glyph_matrix (w->current_matrix);
6640 w->window_end_valid = Qnil;
6642 ++windows_or_buffers_changed;
6643 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6646 return Qnil;
6650 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6651 0, 1, 0,
6652 doc: /* Get width and type of scroll bars of window WINDOW.
6653 If WINDOW is omitted or nil, use the currently selected window.
6654 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6655 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6656 value. */)
6657 (window)
6658 Lisp_Object window;
6660 struct window *w = decode_window (window);
6661 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6662 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6663 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6664 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6665 Fcons (w->vertical_scroll_bar_type,
6666 Fcons (Qnil, Qnil))));
6671 /***********************************************************************
6672 Smooth scrolling
6673 ***********************************************************************/
6675 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6676 doc: /* Return the amount by which WINDOW is scrolled vertically.
6677 Use the selected window if WINDOW is nil or omitted.
6678 Normally, value is a multiple of the canonical character height of WINDOW;
6679 optional second arg PIXELS-P means value is measured in pixels. */)
6680 (window, pixels_p)
6681 Lisp_Object window, pixels_p;
6683 Lisp_Object result;
6684 struct frame *f;
6685 struct window *w;
6687 if (NILP (window))
6688 window = selected_window;
6689 else
6690 CHECK_WINDOW (window);
6691 w = XWINDOW (window);
6692 f = XFRAME (w->frame);
6694 if (FRAME_WINDOW_P (f))
6695 result = (NILP (pixels_p)
6696 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6697 : make_number (-w->vscroll));
6698 else
6699 result = make_number (0);
6700 return result;
6704 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6705 2, 3, 0,
6706 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6707 WINDOW nil means use the selected window. Normally, VSCROLL is a
6708 non-negative multiple of the canonical character height of WINDOW;
6709 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6710 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6711 corresponds to an integral number of pixels. The return value is the
6712 result of this rounding.
6713 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6714 (window, vscroll, pixels_p)
6715 Lisp_Object window, vscroll, pixels_p;
6717 struct window *w;
6718 struct frame *f;
6720 if (NILP (window))
6721 window = selected_window;
6722 else
6723 CHECK_WINDOW (window);
6724 CHECK_NUMBER_OR_FLOAT (vscroll);
6726 w = XWINDOW (window);
6727 f = XFRAME (w->frame);
6729 if (FRAME_WINDOW_P (f))
6731 int old_dy = w->vscroll;
6733 w->vscroll = - (NILP (pixels_p)
6734 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6735 : XFLOATINT (vscroll));
6736 w->vscroll = min (w->vscroll, 0);
6738 if (w->vscroll != old_dy)
6740 /* Adjust glyph matrix of the frame if the virtual display
6741 area becomes larger than before. */
6742 if (w->vscroll < 0 && w->vscroll < old_dy)
6743 adjust_glyphs (f);
6745 /* Prevent redisplay shortcuts. */
6746 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6750 return Fwindow_vscroll (window, pixels_p);
6754 /* Call FN for all leaf windows on frame F. FN is called with the
6755 first argument being a pointer to the leaf window, and with
6756 additional argument USER_DATA. Stops when FN returns 0. */
6758 void
6759 foreach_window (f, fn, user_data)
6760 struct frame *f;
6761 int (* fn) P_ ((struct window *, void *));
6762 void *user_data;
6764 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6768 /* Helper function for foreach_window. Call FN for all leaf windows
6769 reachable from W. FN is called with the first argument being a
6770 pointer to the leaf window, and with additional argument USER_DATA.
6771 Stop when FN returns 0. Value is 0 if stopped by FN. */
6773 static int
6774 foreach_window_1 (w, fn, user_data)
6775 struct window *w;
6776 int (* fn) P_ ((struct window *, void *));
6777 void *user_data;
6779 int cont;
6781 for (cont = 1; w && cont;)
6783 if (!NILP (w->hchild))
6784 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6785 else if (!NILP (w->vchild))
6786 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6787 else
6788 cont = fn (w, user_data);
6790 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6793 return cont;
6797 /* Freeze or unfreeze the window start of W unless it is a
6798 mini-window or the selected window. FREEZE_P non-null means freeze
6799 the window start. */
6801 static int
6802 freeze_window_start (w, freeze_p)
6803 struct window *w;
6804 void *freeze_p;
6806 if (w == XWINDOW (selected_window)
6807 || MINI_WINDOW_P (w)
6808 || (MINI_WINDOW_P (XWINDOW (selected_window))
6809 && ! NILP (Vminibuf_scroll_window)
6810 && w == XWINDOW (Vminibuf_scroll_window)))
6811 freeze_p = NULL;
6813 w->frozen_window_start_p = freeze_p != NULL;
6814 return 1;
6818 /* Freeze or unfreeze the window starts of all leaf windows on frame
6819 F, except the selected window and a mini-window. FREEZE_P non-zero
6820 means freeze the window start. */
6822 void
6823 freeze_window_starts (f, freeze_p)
6824 struct frame *f;
6825 int freeze_p;
6827 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6831 /***********************************************************************
6832 Initialization
6833 ***********************************************************************/
6835 /* Return 1 if window configurations C1 and C2
6836 describe the same state of affairs. This is used by Fequal. */
6839 compare_window_configurations (c1, c2, ignore_positions)
6840 Lisp_Object c1, c2;
6841 int ignore_positions;
6843 register struct save_window_data *d1, *d2;
6844 struct Lisp_Vector *sw1, *sw2;
6845 int i;
6847 if (!WINDOW_CONFIGURATIONP (c1))
6848 wrong_type_argument (Qwindow_configuration_p, c1);
6849 if (!WINDOW_CONFIGURATIONP (c2))
6850 wrong_type_argument (Qwindow_configuration_p, c2);
6852 d1 = (struct save_window_data *) XVECTOR (c1);
6853 d2 = (struct save_window_data *) XVECTOR (c2);
6854 sw1 = XVECTOR (d1->saved_windows);
6855 sw2 = XVECTOR (d2->saved_windows);
6857 if (! EQ (d1->frame_cols, d2->frame_cols))
6858 return 0;
6859 if (! EQ (d1->frame_lines, d2->frame_lines))
6860 return 0;
6861 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
6862 return 0;
6863 if (! EQ (d1->selected_frame, d2->selected_frame))
6864 return 0;
6865 /* Don't compare the current_window field directly.
6866 Instead see w1_is_current and w2_is_current, below. */
6867 if (! EQ (d1->current_buffer, d2->current_buffer))
6868 return 0;
6869 if (! ignore_positions)
6871 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
6872 return 0;
6873 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
6874 return 0;
6876 /* Don't compare the root_window field.
6877 We don't require the two configurations
6878 to use the same window object,
6879 and the two root windows must be equivalent
6880 if everything else compares equal. */
6881 if (! EQ (d1->focus_frame, d2->focus_frame))
6882 return 0;
6883 if (! EQ (d1->min_width, d2->min_width))
6884 return 0;
6885 if (! EQ (d1->min_height, d2->min_height))
6886 return 0;
6888 /* Verify that the two confis have the same number of windows. */
6889 if (sw1->size != sw2->size)
6890 return 0;
6892 for (i = 0; i < sw1->size; i++)
6894 struct saved_window *p1, *p2;
6895 int w1_is_current, w2_is_current;
6897 p1 = SAVED_WINDOW_N (sw1, i);
6898 p2 = SAVED_WINDOW_N (sw2, i);
6900 /* Verify that the current windows in the two
6901 configurations correspond to each other. */
6902 w1_is_current = EQ (d1->current_window, p1->window);
6903 w2_is_current = EQ (d2->current_window, p2->window);
6905 if (w1_is_current != w2_is_current)
6906 return 0;
6908 /* Verify that the corresponding windows do match. */
6909 if (! EQ (p1->buffer, p2->buffer))
6910 return 0;
6911 if (! EQ (p1->left_col, p2->left_col))
6912 return 0;
6913 if (! EQ (p1->top_line, p2->top_line))
6914 return 0;
6915 if (! EQ (p1->total_cols, p2->total_cols))
6916 return 0;
6917 if (! EQ (p1->total_lines, p2->total_lines))
6918 return 0;
6919 if (! EQ (p1->display_table, p2->display_table))
6920 return 0;
6921 if (! EQ (p1->parent, p2->parent))
6922 return 0;
6923 if (! EQ (p1->prev, p2->prev))
6924 return 0;
6925 if (! ignore_positions)
6927 if (! EQ (p1->hscroll, p2->hscroll))
6928 return 0;
6929 if (!EQ (p1->min_hscroll, p2->min_hscroll))
6930 return 0;
6931 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
6932 return 0;
6933 if (NILP (Fequal (p1->start, p2->start)))
6934 return 0;
6935 if (NILP (Fequal (p1->pointm, p2->pointm)))
6936 return 0;
6937 if (NILP (Fequal (p1->mark, p2->mark)))
6938 return 0;
6940 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
6941 return 0;
6942 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
6943 return 0;
6944 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
6945 return 0;
6946 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
6947 return 0;
6948 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
6949 return 0;
6950 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
6951 return 0;
6952 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
6953 return 0;
6956 return 1;
6959 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6960 Scompare_window_configurations, 2, 2, 0,
6961 doc: /* Compare two window configurations as regards the structure of windows.
6962 This function ignores details such as the values of point and mark
6963 and scrolling positions. */)
6964 (x, y)
6965 Lisp_Object x, y;
6967 if (compare_window_configurations (x, y, 1))
6968 return Qt;
6969 return Qnil;
6972 void
6973 init_window_once ()
6975 struct frame *f = make_terminal_frame ();
6976 XSETFRAME (selected_frame, f);
6977 Vterminal_frame = selected_frame;
6978 minibuf_window = f->minibuffer_window;
6979 selected_window = f->selected_window;
6980 last_nonminibuf_frame = f;
6982 window_initialized = 1;
6985 void
6986 init_window ()
6988 Vwindow_list = Qnil;
6991 void
6992 syms_of_window ()
6994 Qscroll_up = intern ("scroll-up");
6995 staticpro (&Qscroll_up);
6997 Qscroll_down = intern ("scroll-down");
6998 staticpro (&Qscroll_down);
7000 Qwindow_size_fixed = intern ("window-size-fixed");
7001 staticpro (&Qwindow_size_fixed);
7002 Fset (Qwindow_size_fixed, Qnil);
7004 staticpro (&Qwindow_configuration_change_hook);
7005 Qwindow_configuration_change_hook
7006 = intern ("window-configuration-change-hook");
7008 Qwindowp = intern ("windowp");
7009 staticpro (&Qwindowp);
7011 Qwindow_configuration_p = intern ("window-configuration-p");
7012 staticpro (&Qwindow_configuration_p);
7014 Qwindow_live_p = intern ("window-live-p");
7015 staticpro (&Qwindow_live_p);
7017 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
7018 staticpro (&Qtemp_buffer_show_hook);
7020 staticpro (&Vwindow_list);
7022 minibuf_selected_window = Qnil;
7023 staticpro (&minibuf_selected_window);
7025 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
7026 doc: /* Non-nil means call as function to display a help buffer.
7027 The function is called with one argument, the buffer to be displayed.
7028 Used by `with-output-to-temp-buffer'.
7029 If this function is used, then it must do the entire job of showing
7030 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7031 Vtemp_buffer_show_function = Qnil;
7033 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
7034 doc: /* If non-nil, function to call to handle `display-buffer'.
7035 It will receive two args, the buffer and a flag which if non-nil means
7036 that the currently selected window is not acceptable.
7037 It should choose or create a window, display the specified buffer in it,
7038 and return the window.
7039 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
7040 work using this function. */);
7041 Vdisplay_buffer_function = Qnil;
7043 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
7044 doc: /* *If non-nil, `display-buffer' should even the window heights.
7045 If nil, `display-buffer' will leave the window configuration alone. */);
7046 Veven_window_heights = Qt;
7048 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
7049 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7050 Vminibuf_scroll_window = Qnil;
7052 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
7053 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7054 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7055 is displayed in the `mode-line' face. */);
7056 mode_line_in_non_selected_windows = 1;
7058 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
7059 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7060 Vother_window_scroll_buffer = Qnil;
7062 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
7063 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
7064 pop_up_frames = 0;
7066 DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
7067 doc: /* *Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7068 auto_window_vscroll_p = 1;
7070 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
7071 doc: /* *Non-nil means `display-buffer' should reuse frames.
7072 If the buffer in question is already displayed in a frame, raise that frame. */);
7073 display_buffer_reuse_frames = 0;
7075 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
7076 doc: /* Function to call to handle automatic new frame creation.
7077 It is called with no arguments and should return a newly created frame.
7079 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
7080 where `pop-up-frame-alist' would hold the default frame parameters. */);
7081 Vpop_up_frame_function = Qnil;
7083 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
7084 doc: /* *List of buffer names that should have their own special frames.
7085 Displaying a buffer with `display-buffer' or `pop-to-buffer',
7086 if its name is in this list, makes a special frame for it
7087 using `special-display-function'. See also `special-display-regexps'.
7089 An element of the list can be a list instead of just a string.
7090 There are two ways to use a list as an element:
7091 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
7092 In the first case, the FRAME-PARAMETERS are pairs of the form
7093 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7094 In the second case, FUNCTION is called with BUFFER as the first argument,
7095 followed by the OTHER-ARGS--it can display BUFFER in any way it likes.
7096 All this is done by the function found in `special-display-function'.
7098 If the specified frame parameters include (same-buffer . t), the
7099 buffer is displayed in the currently selected window. Otherwise, if
7100 they include (same-frame . t), the buffer is displayed in a new window
7101 in the currently selected frame.
7103 If this variable appears \"not to work\", because you add a name to it
7104 but that buffer still appears in the selected window, look at the
7105 values of `same-window-buffer-names' and `same-window-regexps'.
7106 Those variables take precedence over this one. */);
7107 Vspecial_display_buffer_names = Qnil;
7109 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
7110 doc: /* *List of regexps saying which buffers should have their own special frames.
7111 When displaying a buffer with `display-buffer' or `pop-to-buffer',
7112 if any regexp in this list matches the buffer name, it makes a
7113 special frame for the buffer by calling `special-display-function'.
7115 An element of the list can be a list instead of just a string.
7116 There are two ways to use a list as an element:
7117 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
7118 In the first case, the FRAME-PARAMETERS are pairs of the form
7119 \(PARAMETER . VALUE); these parameter values are used to create the frame.
7120 In the second case, FUNCTION is called with BUFFER as the first argument,
7121 followed by the OTHER-ARGS--it can display the buffer in any way it likes.
7122 All this is done by the function found in `special-display-function'.
7124 If the specified frame parameters include (same-buffer . t), the
7125 buffer is displayed in the currently selected window. Otherwise, if
7126 they include (same-frame . t), the buffer is displayed in a new window
7127 in the currently selected frame.
7129 If this variable appears \"not to work\", because you add a regexp to it
7130 but the matching buffers still appear in the selected window, look at the
7131 values of `same-window-buffer-names' and `same-window-regexps'.
7132 Those variables take precedence over this one. */);
7133 Vspecial_display_regexps = Qnil;
7135 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
7136 doc: /* Function to call to make a new frame for a special buffer.
7137 It is called with two arguments, the buffer and optional buffer specific
7138 data, and should return a window displaying that buffer.
7139 The default value normally makes a separate frame for the buffer,
7140 using `special-display-frame-alist' to specify the frame parameters.
7141 But if the buffer specific data includes (same-buffer . t) then the
7142 buffer is displayed in the current selected window.
7143 Otherwise if it includes (same-frame . t) then the buffer is displayed in
7144 a new window in the currently selected frame.
7146 A buffer is special if it is listed in `special-display-buffer-names'
7147 or matches a regexp in `special-display-regexps'. */);
7148 Vspecial_display_function = Qnil;
7150 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
7151 doc: /* *List of buffer names that should appear in the selected window.
7152 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
7153 switches to it in the selected window, rather than making it appear
7154 in some other window.
7156 An element of the list can be a cons cell instead of just a string.
7157 Then the car must be a string, which specifies the buffer name.
7158 This is for compatibility with `special-display-buffer-names';
7159 the cdr of the cons cell is ignored.
7161 See also `same-window-regexps'. */);
7162 Vsame_window_buffer_names = Qnil;
7164 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
7165 doc: /* *List of regexps saying which buffers should appear in the selected window.
7166 If a buffer name matches one of these regexps, then displaying it
7167 using `display-buffer' or `pop-to-buffer' switches to it
7168 in the selected window, rather than making it appear in some other window.
7170 An element of the list can be a cons cell instead of just a string.
7171 Then the car must be a string, which specifies the buffer name.
7172 This is for compatibility with `special-display-buffer-names';
7173 the cdr of the cons cell is ignored.
7175 See also `same-window-buffer-names'. */);
7176 Vsame_window_regexps = Qnil;
7178 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
7179 doc: /* *Non-nil means display-buffer should make new windows. */);
7180 pop_up_windows = 1;
7182 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
7183 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
7184 next_screen_context_lines = 2;
7186 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
7187 doc: /* *A window must be at least this tall to be eligible for splitting by `display-buffer'.
7188 If there is only one window, it is split regardless of this value. */);
7189 split_height_threshold = 500;
7191 DEFVAR_INT ("window-min-height", &window_min_height,
7192 doc: /* *Delete any window less than this tall (including its mode line). */);
7193 window_min_height = 4;
7195 DEFVAR_INT ("window-min-width", &window_min_width,
7196 doc: /* *Delete any window less than this wide. */);
7197 window_min_width = 10;
7199 DEFVAR_LISP ("scroll-preserve-screen-position",
7200 &Vscroll_preserve_screen_position,
7201 doc: /* *Controls if scroll commands move point to keep its screen line unchanged.
7202 A value of nil means point does not keep its screen position except
7203 at the scroll margin or window boundary respectively.
7204 A value of t means point keeps its screen position if the scroll
7205 command moved it vertically out of the window, e.g. when scrolling
7206 by full screens.
7207 Any other value means point always keeps its screen position. */);
7208 Vscroll_preserve_screen_position = Qnil;
7210 DEFVAR_LISP ("window-configuration-change-hook",
7211 &Vwindow_configuration_change_hook,
7212 doc: /* Functions to call when window configuration changes.
7213 The selected frame is the one whose configuration has changed. */);
7214 Vwindow_configuration_change_hook = Qnil;
7216 defsubr (&Sselected_window);
7217 defsubr (&Sminibuffer_window);
7218 defsubr (&Swindow_minibuffer_p);
7219 defsubr (&Swindowp);
7220 defsubr (&Swindow_live_p);
7221 defsubr (&Spos_visible_in_window_p);
7222 defsubr (&Swindow_buffer);
7223 defsubr (&Swindow_height);
7224 defsubr (&Swindow_width);
7225 defsubr (&Swindow_hscroll);
7226 defsubr (&Sset_window_hscroll);
7227 defsubr (&Swindow_redisplay_end_trigger);
7228 defsubr (&Sset_window_redisplay_end_trigger);
7229 defsubr (&Swindow_edges);
7230 defsubr (&Swindow_pixel_edges);
7231 defsubr (&Swindow_inside_edges);
7232 defsubr (&Swindow_inside_pixel_edges);
7233 defsubr (&Scoordinates_in_window_p);
7234 defsubr (&Swindow_at);
7235 defsubr (&Swindow_point);
7236 defsubr (&Swindow_start);
7237 defsubr (&Swindow_end);
7238 defsubr (&Sset_window_point);
7239 defsubr (&Sset_window_start);
7240 defsubr (&Swindow_dedicated_p);
7241 defsubr (&Sset_window_dedicated_p);
7242 defsubr (&Swindow_display_table);
7243 defsubr (&Sset_window_display_table);
7244 defsubr (&Snext_window);
7245 defsubr (&Sprevious_window);
7246 defsubr (&Sother_window);
7247 defsubr (&Sget_lru_window);
7248 defsubr (&Sget_largest_window);
7249 defsubr (&Sget_buffer_window);
7250 defsubr (&Sdelete_other_windows);
7251 defsubr (&Sdelete_windows_on);
7252 defsubr (&Sreplace_buffer_in_windows);
7253 defsubr (&Sdelete_window);
7254 defsubr (&Sset_window_buffer);
7255 defsubr (&Sselect_window);
7256 defsubr (&Sspecial_display_p);
7257 defsubr (&Ssame_window_p);
7258 defsubr (&Sdisplay_buffer);
7259 defsubr (&Sforce_window_update);
7260 defsubr (&Ssplit_window);
7261 defsubr (&Senlarge_window);
7262 defsubr (&Sshrink_window);
7263 defsubr (&Sadjust_window_trailing_edge);
7264 defsubr (&Sscroll_up);
7265 defsubr (&Sscroll_down);
7266 defsubr (&Sscroll_left);
7267 defsubr (&Sscroll_right);
7268 defsubr (&Sother_window_for_scrolling);
7269 defsubr (&Sscroll_other_window);
7270 defsubr (&Sminibuffer_selected_window);
7271 defsubr (&Srecenter);
7272 defsubr (&Swindow_text_height);
7273 defsubr (&Smove_to_window_line);
7274 defsubr (&Swindow_configuration_p);
7275 defsubr (&Swindow_configuration_frame);
7276 defsubr (&Sset_window_configuration);
7277 defsubr (&Scurrent_window_configuration);
7278 defsubr (&Ssave_window_excursion);
7279 defsubr (&Swindow_tree);
7280 defsubr (&Sset_window_margins);
7281 defsubr (&Swindow_margins);
7282 defsubr (&Sset_window_fringes);
7283 defsubr (&Swindow_fringes);
7284 defsubr (&Sset_window_scroll_bars);
7285 defsubr (&Swindow_scroll_bars);
7286 defsubr (&Swindow_vscroll);
7287 defsubr (&Sset_window_vscroll);
7288 defsubr (&Scompare_window_configurations);
7289 defsubr (&Swindow_list);
7292 void
7293 keys_of_window ()
7295 initial_define_key (control_x_map, '1', "delete-other-windows");
7296 initial_define_key (control_x_map, '2', "split-window");
7297 initial_define_key (control_x_map, '0', "delete-window");
7298 initial_define_key (control_x_map, 'o', "other-window");
7299 initial_define_key (control_x_map, '^', "enlarge-window");
7300 initial_define_key (control_x_map, '<', "scroll-left");
7301 initial_define_key (control_x_map, '>', "scroll-right");
7303 initial_define_key (global_map, Ctl ('V'), "scroll-up");
7304 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7305 initial_define_key (meta_map, 'v', "scroll-down");
7307 initial_define_key (global_map, Ctl('L'), "recenter");
7308 initial_define_key (meta_map, 'r', "move-to-window-line");
7311 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
7312 (do not change this comment) */