(xml-parse-dtd): Fix misplaced paren.
[emacs.git] / src / window.c
blob7e4b57675613656595bef0616aebf3e801ca1c47
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985,86,87,93,94,95,96,97,1998,2000, 2001, 2002, 2003
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 #include <config.h>
24 #include "lisp.h"
25 #include "buffer.h"
26 #include "keyboard.h"
27 #include "keymap.h"
28 #include "frame.h"
29 #include "window.h"
30 #include "commands.h"
31 #include "indent.h"
32 #include "termchar.h"
33 #include "disptab.h"
34 #include "dispextern.h"
35 #include "blockinput.h"
36 #include "intervals.h"
38 #ifdef HAVE_X_WINDOWS
39 #include "xterm.h"
40 #endif /* HAVE_X_WINDOWS */
41 #ifdef WINDOWSNT
42 #include "w32term.h"
43 #endif
44 #ifdef MSDOS
45 #include "msdos.h"
46 #endif
47 #ifdef MAC_OS
48 #include "macterm.h"
49 #endif
52 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
53 Lisp_Object Qwindow_size_fixed;
54 extern Lisp_Object Qleft_margin, Qright_margin;
56 static int displayed_window_lines P_ ((struct window *));
57 static struct window *decode_window P_ ((Lisp_Object));
58 static int count_windows P_ ((struct window *));
59 static int get_leaf_windows P_ ((struct window *, struct window **, int));
60 static void window_scroll P_ ((Lisp_Object, int, int, int));
61 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
62 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
63 static int window_min_size_1 P_ ((struct window *, int));
64 static int window_min_size P_ ((struct window *, int, int, int *));
65 static void size_window P_ ((Lisp_Object, int, int, int));
66 static int freeze_window_start P_ ((struct window *, void *));
67 static int window_fixed_size_p P_ ((struct window *, int, int));
68 static void enlarge_window P_ ((Lisp_Object, int, int, int));
69 static Lisp_Object window_list P_ ((void));
70 static int add_window_to_list P_ ((struct window *, void *));
71 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
72 Lisp_Object));
73 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
74 Lisp_Object, int));
75 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
76 Lisp_Object *));
77 static int foreach_window_1 P_ ((struct window *,
78 int (* fn) (struct window *, void *),
79 void *));
80 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
82 /* The value of `window-size-fixed'. */
84 int window_size_fixed;
86 /* This is the window in which the terminal's cursor should
87 be left when nothing is being done with it. This must
88 always be a leaf window, and its buffer is selected by
89 the top level editing loop at the end of each command.
91 This value is always the same as
92 FRAME_SELECTED_WINDOW (selected_frame). */
94 Lisp_Object selected_window;
96 /* A list of all windows for use by next_window and Fwindow_list.
97 Functions creating or deleting windows should invalidate this cache
98 by setting it to nil. */
100 Lisp_Object Vwindow_list;
102 /* The mini-buffer window of the selected frame.
103 Note that you cannot test for mini-bufferness of an arbitrary window
104 by comparing against this; but you can test for mini-bufferness of
105 the selected window. */
107 Lisp_Object minibuf_window;
109 /* Non-nil means it is the window whose mode line should be
110 shown as the selected window when the minibuffer is selected. */
112 Lisp_Object minibuf_selected_window;
114 /* Non-nil means it is the window for C-M-v to scroll
115 when the mini-buffer is selected. */
117 Lisp_Object Vminibuf_scroll_window;
119 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
121 Lisp_Object Vother_window_scroll_buffer;
123 /* Non-nil means it's function to call to display temp buffers. */
125 Lisp_Object Vtemp_buffer_show_function;
127 /* Non-zero means to use mode-line-inactive face in all windows but the
128 selected-window and the minibuffer-scroll-window when the
129 minibuffer is active. */
130 int mode_line_in_non_selected_windows;
132 /* If a window gets smaller than either of these, it is removed. */
134 EMACS_INT window_min_height;
135 EMACS_INT window_min_width;
137 /* Nonzero implies Fdisplay_buffer should create windows. */
139 int pop_up_windows;
141 /* Nonzero implies make new frames for Fdisplay_buffer. */
143 int pop_up_frames;
145 /* Nonzero means reuse existing frames for displaying buffers. */
147 int display_buffer_reuse_frames;
149 /* Non-nil means use this function instead of default */
151 Lisp_Object Vpop_up_frame_function;
153 /* Function to call to handle Fdisplay_buffer. */
155 Lisp_Object Vdisplay_buffer_function;
157 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
159 Lisp_Object Veven_window_heights;
161 /* List of buffer *names* for buffers that should have their own frames. */
163 Lisp_Object Vspecial_display_buffer_names;
165 /* List of regexps for buffer names that should have their own frames. */
167 Lisp_Object Vspecial_display_regexps;
169 /* Function to pop up a special frame. */
171 Lisp_Object Vspecial_display_function;
173 /* List of buffer *names* for buffers to appear in selected window. */
175 Lisp_Object Vsame_window_buffer_names;
177 /* List of regexps for buffer names to appear in selected window. */
179 Lisp_Object Vsame_window_regexps;
181 /* Hook run at end of temp_output_buffer_show. */
183 Lisp_Object Qtemp_buffer_show_hook;
185 /* Fdisplay_buffer always splits the largest window
186 if that window is more than this high. */
188 EMACS_INT split_height_threshold;
190 /* Number of lines of continuity in scrolling by screenfuls. */
192 EMACS_INT next_screen_context_lines;
194 /* Incremented for each window created. */
196 static int sequence_number;
198 /* Nonzero after init_window_once has finished. */
200 static int window_initialized;
202 /* Hook to run when window config changes. */
204 Lisp_Object Qwindow_configuration_change_hook;
205 Lisp_Object Vwindow_configuration_change_hook;
207 /* Nonzero means scroll commands try to put point
208 at the same screen height as previously. */
210 Lisp_Object Vscroll_preserve_screen_position;
212 #if 0 /* This isn't used anywhere. */
213 /* Nonzero means we can split a frame even if it is "unsplittable". */
214 static int inhibit_frame_unsplittable;
215 #endif /* 0 */
217 extern EMACS_INT scroll_margin;
219 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
221 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
222 doc: /* Returns t if OBJECT is a window. */)
223 (object)
224 Lisp_Object object;
226 return WINDOWP (object) ? Qt : Qnil;
229 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
230 doc: /* Returns t if OBJECT is a window which is currently visible. */)
231 (object)
232 Lisp_Object object;
234 return WINDOW_LIVE_P (object) ? Qt : Qnil;
237 Lisp_Object
238 make_window ()
240 Lisp_Object val;
241 register struct window *p;
243 p = allocate_window ();
244 XSETFASTINT (p->sequence_number, ++sequence_number);
245 XSETFASTINT (p->left_col, 0);
246 XSETFASTINT (p->top_line, 0);
247 XSETFASTINT (p->total_lines, 0);
248 XSETFASTINT (p->total_cols, 0);
249 XSETFASTINT (p->hscroll, 0);
250 XSETFASTINT (p->min_hscroll, 0);
251 p->orig_top_line = p->orig_total_lines = Qnil;
252 p->start = Fmake_marker ();
253 p->pointm = Fmake_marker ();
254 XSETFASTINT (p->use_time, 0);
255 p->frame = Qnil;
256 p->display_table = Qnil;
257 p->dedicated = Qnil;
258 p->pseudo_window_p = 0;
259 bzero (&p->cursor, sizeof (p->cursor));
260 bzero (&p->last_cursor, sizeof (p->last_cursor));
261 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
262 p->desired_matrix = p->current_matrix = 0;
263 p->phys_cursor_type = -1;
264 p->phys_cursor_width = -1;
265 p->must_be_updated_p = 0;
266 XSETFASTINT (p->window_end_vpos, 0);
267 XSETFASTINT (p->window_end_pos, 0);
268 p->window_end_valid = Qnil;
269 p->vscroll = 0;
270 XSETWINDOW (val, p);
271 XSETFASTINT (p->last_point, 0);
272 p->frozen_window_start_p = 0;
273 p->height_fixed_p = 0;
274 p->last_cursor_off_p = p->cursor_off_p = 0;
275 p->left_margin_cols = Qnil;
276 p->right_margin_cols = Qnil;
277 p->left_fringe_width = Qnil;
278 p->right_fringe_width = Qnil;
279 p->fringes_outside_margins = Qnil;
280 p->scroll_bar_width = Qnil;
281 p->vertical_scroll_bar_type = Qt;
283 Vwindow_list = Qnil;
284 return val;
287 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
288 doc: /* Return the window that the cursor now appears in and commands apply to. */)
291 return selected_window;
294 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
295 doc: /* Return the window used now for minibuffers.
296 If the optional argument FRAME is specified, return the minibuffer window
297 used by that frame. */)
298 (frame)
299 Lisp_Object frame;
301 if (NILP (frame))
302 frame = selected_frame;
303 CHECK_LIVE_FRAME (frame);
304 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
307 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
308 doc: /* Returns non-nil if WINDOW is a minibuffer window. */)
309 (window)
310 Lisp_Object window;
312 struct window *w = decode_window (window);
313 return MINI_WINDOW_P (w) ? Qt : Qnil;
317 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
318 Spos_visible_in_window_p, 0, 3, 0,
319 doc: /* Return t if position POS is currently on the frame in WINDOW.
320 Return nil if that position is scrolled vertically out of view.
321 If a character is only partially visible, nil is returned, unless the
322 optional argument PARTIALLY is non-nil.
323 POS defaults to point in WINDOW; WINDOW defaults to the selected window. */)
324 (pos, window, partially)
325 Lisp_Object pos, window, partially;
327 register struct window *w;
328 register int posint;
329 register struct buffer *buf;
330 struct text_pos top;
331 Lisp_Object in_window;
332 int fully_p;
334 w = decode_window (window);
335 buf = XBUFFER (w->buffer);
336 SET_TEXT_POS_FROM_MARKER (top, w->start);
338 if (!NILP (pos))
340 CHECK_NUMBER_COERCE_MARKER (pos);
341 posint = XINT (pos);
343 else if (w == XWINDOW (selected_window))
344 posint = PT;
345 else
346 posint = XMARKER (w->pointm)->charpos;
348 /* If position is above window start, it's not visible. */
349 if (posint < CHARPOS (top))
350 in_window = Qnil;
351 else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
352 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
353 && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
355 /* If frame is up-to-date, and POSINT is < window end pos, use
356 that info. This doesn't work for POSINT == end pos, because
357 the window end pos is actually the position _after_ the last
358 char in the window. */
359 if (NILP (partially))
361 pos_visible_p (w, posint, &fully_p, NILP (partially));
362 in_window = fully_p ? Qt : Qnil;
364 else
365 in_window = Qt;
367 else if (posint > BUF_ZV (buf))
368 in_window = Qnil;
369 else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
370 /* If window start is out of range, do something reasonable. */
371 in_window = Qnil;
372 else
374 if (pos_visible_p (w, posint, &fully_p, NILP (partially)))
375 in_window = !NILP (partially) || fully_p ? Qt : Qnil;
376 else
377 in_window = Qnil;
380 return in_window;
384 static struct window *
385 decode_window (window)
386 register Lisp_Object window;
388 if (NILP (window))
389 return XWINDOW (selected_window);
391 CHECK_LIVE_WINDOW (window);
392 return XWINDOW (window);
395 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
396 doc: /* Return the buffer that WINDOW is displaying. */)
397 (window)
398 Lisp_Object window;
400 return decode_window (window)->buffer;
403 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
404 doc: /* Return the number of lines in WINDOW (including its mode line). */)
405 (window)
406 Lisp_Object window;
408 return decode_window (window)->total_lines;
411 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
412 doc: /* Return the number of display columns in WINDOW.
413 This is the width that is usable columns available for text in WINDOW.
414 If you want to find out how many columns WINDOW takes up,
415 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
416 (window)
417 Lisp_Object window;
419 return make_number (window_box_text_cols (decode_window (window)));
422 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
423 doc: /* Return the number of columns by which WINDOW is scrolled from left margin. */)
424 (window)
425 Lisp_Object window;
427 return decode_window (window)->hscroll;
430 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
431 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
432 NCOL should be zero or positive.
434 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
435 window so that the location of point becomes invisible. */)
436 (window, ncol)
437 Lisp_Object window, ncol;
439 struct window *w = decode_window (window);
440 int hscroll;
442 CHECK_NUMBER (ncol);
443 hscroll = max (0, XINT (ncol));
445 /* Prevent redisplay shortcuts when changing the hscroll. */
446 if (XINT (w->hscroll) != hscroll)
447 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
449 w->hscroll = make_number (hscroll);
450 return ncol;
453 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
454 Swindow_redisplay_end_trigger, 0, 1, 0,
455 doc: /* Return WINDOW's redisplay end trigger value.
456 See `set-window-redisplay-end-trigger' for more information. */)
457 (window)
458 Lisp_Object window;
460 return decode_window (window)->redisplay_end_trigger;
463 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
464 Sset_window_redisplay_end_trigger, 2, 2, 0,
465 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
466 VALUE should be a buffer position (typically a marker) or nil.
467 If it is a buffer position, then if redisplay in WINDOW reaches a position
468 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
469 with two arguments: WINDOW, and the end trigger value.
470 Afterwards the end-trigger value is reset to nil. */)
471 (window, value)
472 register Lisp_Object window, value;
474 register struct window *w;
476 w = decode_window (window);
477 w->redisplay_end_trigger = value;
478 return value;
481 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
482 doc: /* Return a list of the edge coordinates of WINDOW.
483 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
484 RIGHT is one more than the rightmost column occupied by WINDOW,
485 and BOTTOM is one more than the bottommost row occupied by WINDOW.
486 The edges include the space used by the window's scroll bar,
487 display margins, fringes, header line, and mode line, if it has them.
488 To get the edges of the actual text area, use `window-inside-edges'. */)
489 (window)
490 Lisp_Object window;
492 register struct window *w = decode_window (window);
494 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
495 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
496 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
497 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
498 Qnil))));
501 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
502 doc: /* Return a list of the edge pixel coordinates of WINDOW.
503 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
504 RIGHT is one more than the rightmost x position occupied by WINDOW,
505 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
506 The pixel edges include the space used by the window's scroll bar,
507 display margins, fringes, header line, and mode line, if it has them.
508 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
509 (window)
510 Lisp_Object window;
512 register struct window *w = decode_window (window);
514 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
515 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
516 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
517 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
518 Qnil))));
521 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
522 doc: /* Return a list of the edge coordinates of WINDOW.
523 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
524 RIGHT is one more than the rightmost column used by text in WINDOW,
525 and BOTTOM is one more than the bottommost row used by text in WINDOW.
526 The inside edges do not include the space used by the window's scroll bar,
527 display margins, fringes, header line, and/or mode line. */)
528 (window)
529 Lisp_Object window;
531 register struct window *w = decode_window (window);
533 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
534 + WINDOW_LEFT_MARGIN_COLS (w)
535 + WINDOW_LEFT_FRINGE_COLS (w)),
536 make_number (WINDOW_TOP_EDGE_LINE (w)
537 + WINDOW_HEADER_LINE_LINES (w)),
538 make_number (WINDOW_RIGHT_EDGE_COL (w)
539 - WINDOW_RIGHT_MARGIN_COLS (w)
540 - WINDOW_RIGHT_FRINGE_COLS (w)),
541 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
542 - WINDOW_MODE_LINE_LINES (w)));
545 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
546 doc: /* Return a list of the edge coordinates of WINDOW.
547 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
548 RIGHT is one more than the rightmost x position used by text in WINDOW,
549 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
550 The inside edges do not include the space used by the window's scroll bar,
551 display margins, fringes, header line, and/or mode line. */)
552 (window)
553 Lisp_Object window;
555 register struct window *w = decode_window (window);
557 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
558 + WINDOW_LEFT_MARGIN_WIDTH (w)
559 + WINDOW_LEFT_FRINGE_WIDTH (w)),
560 make_number (WINDOW_TOP_EDGE_Y (w)
561 + WINDOW_HEADER_LINE_HEIGHT (w)),
562 make_number (WINDOW_RIGHT_EDGE_X (w)
563 - WINDOW_RIGHT_MARGIN_WIDTH (w)
564 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
565 make_number (WINDOW_BOTTOM_EDGE_Y (w)
566 - WINDOW_MODE_LINE_HEIGHT (w)));
569 /* Test if the character at column *X, row *Y is within window W.
570 If it is not, return ON_NOTHING;
571 if it is in the window's text area,
572 set *x and *y to its location relative to the upper left corner
573 of the window, and
574 return ON_TEXT;
575 if it is on the window's modeline, return ON_MODE_LINE;
576 if it is on the border between the window and its right sibling,
577 return ON_VERTICAL_BORDER.
578 if it is on the window's top line, return ON_HEADER_LINE;
579 if it is in left or right fringe of the window,
580 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
581 to window-relative coordinates;
582 if it is in the marginal area to the left/right of the window,
583 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
584 to window-relative coordinates.
586 X and Y are frame relative pixel coordinates. */
588 static enum window_part
589 coordinates_in_window (w, x, y)
590 register struct window *w;
591 register int *x, *y;
593 struct frame *f = XFRAME (WINDOW_FRAME (w));
594 int left_x, right_x, top_y, bottom_y;
595 enum window_part part;
596 int ux = FRAME_COLUMN_WIDTH (f);
597 int x0 = WINDOW_LEFT_EDGE_X (w);
598 int x1 = WINDOW_RIGHT_EDGE_X (w);
599 /* The width of the area where the vertical line can be dragged.
600 (Between mode lines for instance. */
601 int grabbable_width = ux;
602 int lmargin_width, rmargin_width, text_left, text_right;
604 if (*x < x0 || *x >= x1)
605 return ON_NOTHING;
607 /* In what's below, we subtract 1 when computing right_x because we
608 want the rightmost pixel, which is given by left_pixel+width-1. */
609 if (w->pseudo_window_p)
611 left_x = 0;
612 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
613 top_y = WINDOW_TOP_EDGE_Y (w);
614 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
616 else
618 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
619 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
620 top_y = WINDOW_TOP_EDGE_Y (w);
621 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
624 /* Outside any interesting row? */
625 if (*y < top_y || *y >= bottom_y)
626 return ON_NOTHING;
628 /* On the mode line or header line? If it's near the start of
629 the mode or header line of window that's has a horizontal
630 sibling, say it's on the vertical line. That's to be able
631 to resize windows horizontally in case we're using toolkit
632 scroll bars. */
634 if (WINDOW_WANTS_MODELINE_P (w)
635 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
636 && *y < bottom_y)
638 part = ON_MODE_LINE;
640 header_vertical_border_check:
641 /* We're somewhere on the mode line. We consider the place
642 between mode lines of horizontally adjacent mode lines
643 as the vertical border. If scroll bars on the left,
644 return the right window. */
645 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
646 || WINDOW_RIGHTMOST_P (w))
648 if (!WINDOW_LEFTMOST_P (w) && abs (*x - x0) < grabbable_width)
649 return ON_VERTICAL_BORDER;
651 else
653 if (abs (*x - x1) < grabbable_width)
654 return ON_VERTICAL_BORDER;
657 /* Convert X and Y to window relative coordinates.
658 Mode line starts at left edge of window. */
659 *x -= x0;
660 *y -= top_y;
661 return part;
664 if (WINDOW_WANTS_HEADER_LINE_P (w)
665 && *y >= top_y
666 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
668 part = ON_HEADER_LINE;
669 goto header_vertical_border_check;
672 /* Outside any interesting column? */
673 if (*x < left_x || *x > right_x)
674 return ON_NOTHING;
676 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
677 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
679 text_left = window_box_left (w, TEXT_AREA);
680 text_right = text_left + window_box_width (w, TEXT_AREA);
682 if (FRAME_WINDOW_P (f))
684 if (!w->pseudo_window_p
685 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
686 && !WINDOW_RIGHTMOST_P (w)
687 && (abs (*x - right_x) < grabbable_width))
688 return ON_VERTICAL_BORDER;
690 else
692 /* Need to say "*x > right_x" rather than >=, since on character
693 terminals, the vertical line's x coordinate is right_x. */
694 if (!w->pseudo_window_p
695 && !WINDOW_RIGHTMOST_P (w)
696 && *x > right_x - ux)
698 /* On the border on the right side of the window? Assume that
699 this area begins at RIGHT_X minus a canonical char width. */
700 return ON_VERTICAL_BORDER;
704 if (*x < text_left)
706 if (lmargin_width > 0
707 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
708 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
709 : (*x < left_x + lmargin_width)))
711 *x -= x0;
712 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
713 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
714 *y -= top_y;
715 return ON_LEFT_MARGIN;
718 /* Convert X and Y to window-relative pixel coordinates. */
719 *x -= left_x;
720 *y -= top_y;
721 return ON_LEFT_FRINGE;
724 if (*x >= text_right)
726 if (rmargin_width > 0
727 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
728 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
729 : (*x >= right_x - rmargin_width)))
731 *x -= right_x;
732 if (!WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
733 *x -= WINDOW_RIGHT_FRINGE_WIDTH (w);
734 *y -= top_y;
735 return ON_RIGHT_MARGIN;
738 /* Convert X and Y to window-relative pixel coordinates. */
739 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
740 *y -= top_y;
741 return ON_RIGHT_FRINGE;
744 /* Everything special ruled out - must be on text area */
745 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
746 *y -= top_y;
747 return ON_TEXT;
751 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
752 Scoordinates_in_window_p, 2, 2, 0,
753 doc: /* Return non-nil if COORDINATES are in WINDOW.
754 COORDINATES is a cons of the form (X . Y), X and Y being distances
755 measured in characters from the upper-left corner of the frame.
756 \(0 . 0) denotes the character in the upper left corner of the
757 frame.
758 If COORDINATES are in the text portion of WINDOW,
759 the coordinates relative to the window are returned.
760 If they are in the mode line of WINDOW, `mode-line' is returned.
761 If they are in the top mode line of WINDOW, `header-line' is returned.
762 If they are in the left fringe of WINDOW, `left-fringe' is returned.
763 If they are in the right fringe of WINDOW, `right-fringe' is returned.
764 If they are on the border between WINDOW and its right sibling,
765 `vertical-line' is returned.
766 If they are in the windows's left or right marginal areas, `left-margin'\n\
767 or `right-margin' is returned. */)
768 (coordinates, window)
769 register Lisp_Object coordinates, window;
771 struct window *w;
772 struct frame *f;
773 int x, y;
774 Lisp_Object lx, ly;
776 CHECK_LIVE_WINDOW (window);
777 w = XWINDOW (window);
778 f = XFRAME (w->frame);
779 CHECK_CONS (coordinates);
780 lx = Fcar (coordinates);
781 ly = Fcdr (coordinates);
782 CHECK_NUMBER_OR_FLOAT (lx);
783 CHECK_NUMBER_OR_FLOAT (ly);
784 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx);
785 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly);
787 switch (coordinates_in_window (w, &x, &y))
789 case ON_NOTHING:
790 return Qnil;
792 case ON_TEXT:
793 /* X and Y are now window relative pixel coordinates. Convert
794 them to canonical char units before returning them. */
795 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
796 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
798 case ON_MODE_LINE:
799 return Qmode_line;
801 case ON_VERTICAL_BORDER:
802 return Qvertical_line;
804 case ON_HEADER_LINE:
805 return Qheader_line;
807 case ON_LEFT_FRINGE:
808 return Qleft_fringe;
810 case ON_RIGHT_FRINGE:
811 return Qright_fringe;
813 case ON_LEFT_MARGIN:
814 return Qleft_margin;
816 case ON_RIGHT_MARGIN:
817 return Qright_margin;
819 default:
820 abort ();
825 /* Callback for foreach_window, used in window_from_coordinates.
826 Check if window W contains coordinates specified by USER_DATA which
827 is actually a pointer to a struct check_window_data CW.
829 Check if window W contains coordinates *CW->x and *CW->y. If it
830 does, return W in *CW->window, as Lisp_Object, and return in
831 *CW->part the part of the window under coordinates *X,*Y. Return
832 zero from this function to stop iterating over windows. */
834 struct check_window_data
836 Lisp_Object *window;
837 int *x, *y;
838 enum window_part *part;
841 static int
842 check_window_containing (w, user_data)
843 struct window *w;
844 void *user_data;
846 struct check_window_data *cw = (struct check_window_data *) user_data;
847 enum window_part found;
848 int continue_p = 1;
850 found = coordinates_in_window (w, cw->x, cw->y);
851 if (found != ON_NOTHING)
853 *cw->part = found;
854 XSETWINDOW (*cw->window, w);
855 continue_p = 0;
858 return continue_p;
862 /* Find the window containing frame-relative pixel position X/Y and
863 return it as a Lisp_Object.
865 If X, Y is on one of the window's special `window_part' elements,
866 set *PART to the id of that element, and return X and Y converted
867 to window relative coordinates in WX and WY.
869 If there is no window under X, Y return nil and leave *PART
870 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
872 This function was previously implemented with a loop cycling over
873 windows with Fnext_window, and starting with the frame's selected
874 window. It turned out that this doesn't work with an
875 implementation of next_window using Vwindow_list, because
876 FRAME_SELECTED_WINDOW (F) is not always contained in the window
877 tree of F when this function is called asynchronously from
878 note_mouse_highlight. The original loop didn't terminate in this
879 case. */
881 Lisp_Object
882 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
883 struct frame *f;
884 int x, y;
885 enum window_part *part;
886 int *wx, *wy;
887 int tool_bar_p;
889 Lisp_Object window;
890 struct check_window_data cw;
891 enum window_part dummy;
893 if (part == 0)
894 part = &dummy;
896 window = Qnil;
897 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
898 foreach_window (f, check_window_containing, &cw);
900 /* If not found above, see if it's in the tool bar window, if a tool
901 bar exists. */
902 if (NILP (window)
903 && tool_bar_p
904 && WINDOWP (f->tool_bar_window)
905 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
906 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
907 != ON_NOTHING))
909 *part = ON_TEXT;
910 window = f->tool_bar_window;
913 if (wx) *wx = x;
914 if (wy) *wy = y;
916 return window;
919 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
920 doc: /* Return window containing coordinates X and Y on FRAME.
921 If omitted, FRAME defaults to the currently selected frame.
922 The top left corner of the frame is considered to be row 0,
923 column 0. */)
924 (x, y, frame)
925 Lisp_Object x, y, frame;
927 struct frame *f;
929 if (NILP (frame))
930 frame = selected_frame;
931 CHECK_LIVE_FRAME (frame);
932 f = XFRAME (frame);
934 /* Check that arguments are integers or floats. */
935 CHECK_NUMBER_OR_FLOAT (x);
936 CHECK_NUMBER_OR_FLOAT (y);
938 return window_from_coordinates (f,
939 FRAME_PIXEL_X_FROM_CANON_X (f, x),
940 FRAME_PIXEL_Y_FROM_CANON_Y (f, y),
941 0, 0, 0, 0);
944 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
945 doc: /* Return current value of point in WINDOW.
946 For a nonselected window, this is the value point would have
947 if that window were selected.
949 Note that, when WINDOW is the selected window and its buffer
950 is also currently selected, the value returned is the same as (point).
951 It would be more strictly correct to return the `top-level' value
952 of point, outside of any save-excursion forms.
953 But that is hard to define. */)
954 (window)
955 Lisp_Object window;
957 register struct window *w = decode_window (window);
959 if (w == XWINDOW (selected_window)
960 && current_buffer == XBUFFER (w->buffer))
961 return Fpoint ();
962 return Fmarker_position (w->pointm);
965 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
966 doc: /* Return position at which display currently starts in WINDOW.
967 This is updated by redisplay or by calling `set-window-start'. */)
968 (window)
969 Lisp_Object window;
971 return Fmarker_position (decode_window (window)->start);
974 /* This is text temporarily removed from the doc string below.
976 This function returns nil if the position is not currently known.
977 That happens when redisplay is preempted and doesn't finish.
978 If in that case you want to compute where the end of the window would
979 have been if redisplay had finished, do this:
980 (save-excursion
981 (goto-char (window-start window))
982 (vertical-motion (1- (window-height window)) window)
983 (point))") */
985 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
986 doc: /* Return position at which display currently ends in WINDOW.
987 This is updated by redisplay, when it runs to completion.
988 Simply changing the buffer text or setting `window-start'
989 does not update this value.
990 If UPDATE is non-nil, compute the up-to-date position
991 if it isn't already recorded. */)
992 (window, update)
993 Lisp_Object window, update;
995 Lisp_Object value;
996 struct window *w = decode_window (window);
997 Lisp_Object buf;
999 buf = w->buffer;
1000 CHECK_BUFFER (buf);
1002 #if 0 /* This change broke some things. We should make it later. */
1003 /* If we don't know the end position, return nil.
1004 The user can compute it with vertical-motion if he wants to.
1005 It would be nicer to do it automatically,
1006 but that's so slow that it would probably bother people. */
1007 if (NILP (w->window_end_valid))
1008 return Qnil;
1009 #endif
1011 if (! NILP (update)
1012 && ! (! NILP (w->window_end_valid)
1013 && XFASTINT (w->last_modified) >= MODIFF))
1015 struct text_pos startp;
1016 struct it it;
1017 struct buffer *old_buffer = NULL, *b = XBUFFER (buf);
1019 /* In case W->start is out of the range, use something
1020 reasonable. This situation occurred when loading a file with
1021 `-l' containing a call to `rmail' with subsequent other
1022 commands. At the end, W->start happened to be BEG, while
1023 rmail had already narrowed the buffer. */
1024 if (XMARKER (w->start)->charpos < BEGV)
1025 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1026 else if (XMARKER (w->start)->charpos > ZV)
1027 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1028 else
1029 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1031 /* Cannot use Fvertical_motion because that function doesn't
1032 cope with variable-height lines. */
1033 if (b != current_buffer)
1035 old_buffer = current_buffer;
1036 set_buffer_internal (b);
1039 start_display (&it, w, startp);
1040 move_it_vertically (&it, window_box_height (w));
1041 if (it.current_y < it.last_visible_y)
1042 move_it_past_eol (&it);
1043 value = make_number (IT_CHARPOS (it));
1045 if (old_buffer)
1046 set_buffer_internal (old_buffer);
1048 else
1049 XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
1051 return value;
1054 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1055 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer. */)
1056 (window, pos)
1057 Lisp_Object window, pos;
1059 register struct window *w = decode_window (window);
1061 CHECK_NUMBER_COERCE_MARKER (pos);
1062 if (w == XWINDOW (selected_window)
1063 && XBUFFER (w->buffer) == current_buffer)
1064 Fgoto_char (pos);
1065 else
1066 set_marker_restricted (w->pointm, pos, w->buffer);
1068 /* We have to make sure that redisplay updates the window to show
1069 the new value of point. */
1070 if (!EQ (window, selected_window))
1071 ++windows_or_buffers_changed;
1073 return pos;
1076 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1077 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1078 Optional third arg NOFORCE non-nil inhibits next redisplay
1079 from overriding motion of point in order to display at this exact start. */)
1080 (window, pos, noforce)
1081 Lisp_Object window, pos, noforce;
1083 register struct window *w = decode_window (window);
1085 CHECK_NUMBER_COERCE_MARKER (pos);
1086 set_marker_restricted (w->start, pos, w->buffer);
1087 /* this is not right, but much easier than doing what is right. */
1088 w->start_at_line_beg = Qnil;
1089 if (NILP (noforce))
1090 w->force_start = Qt;
1091 w->update_mode_line = Qt;
1092 XSETFASTINT (w->last_modified, 0);
1093 XSETFASTINT (w->last_overlay_modified, 0);
1094 if (!EQ (window, selected_window))
1095 windows_or_buffers_changed++;
1097 return pos;
1100 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1101 1, 1, 0,
1102 doc: /* Return WINDOW's dedicated object, usually t or nil.
1103 See also `set-window-dedicated-p'. */)
1104 (window)
1105 Lisp_Object window;
1107 return decode_window (window)->dedicated;
1110 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1111 Sset_window_dedicated_p, 2, 2, 0,
1112 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1113 If it is dedicated, Emacs will not automatically change
1114 which buffer appears in it.
1115 The second argument is the new value for the dedication flag;
1116 non-nil means yes. */)
1117 (window, arg)
1118 Lisp_Object window, arg;
1120 register struct window *w = decode_window (window);
1122 w->dedicated = arg;
1124 return w->dedicated;
1127 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1128 0, 1, 0,
1129 doc: /* Return the display-table that WINDOW is using. */)
1130 (window)
1131 Lisp_Object window;
1133 return decode_window (window)->display_table;
1136 /* Get the display table for use on window W. This is either W's
1137 display table or W's buffer's display table. Ignore the specified
1138 tables if they are not valid; if no valid table is specified,
1139 return 0. */
1141 struct Lisp_Char_Table *
1142 window_display_table (w)
1143 struct window *w;
1145 struct Lisp_Char_Table *dp = NULL;
1147 if (DISP_TABLE_P (w->display_table))
1148 dp = XCHAR_TABLE (w->display_table);
1149 else if (BUFFERP (w->buffer))
1151 struct buffer *b = XBUFFER (w->buffer);
1153 if (DISP_TABLE_P (b->display_table))
1154 dp = XCHAR_TABLE (b->display_table);
1155 else if (DISP_TABLE_P (Vstandard_display_table))
1156 dp = XCHAR_TABLE (Vstandard_display_table);
1159 return dp;
1162 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1163 doc: /* Set WINDOW's display-table to TABLE. */)
1164 (window, table)
1165 register Lisp_Object window, table;
1167 register struct window *w;
1169 w = decode_window (window);
1170 w->display_table = table;
1171 return table;
1174 /* Record info on buffer window w is displaying
1175 when it is about to cease to display that buffer. */
1176 static void
1177 unshow_buffer (w)
1178 register struct window *w;
1180 Lisp_Object buf;
1181 struct buffer *b;
1183 buf = w->buffer;
1184 b = XBUFFER (buf);
1185 if (b != XMARKER (w->pointm)->buffer)
1186 abort ();
1188 #if 0
1189 if (w == XWINDOW (selected_window)
1190 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1191 /* Do this except when the selected window's buffer
1192 is being removed from some other window. */
1193 #endif
1194 /* last_window_start records the start position that this buffer
1195 had in the last window to be disconnected from it.
1196 Now that this statement is unconditional,
1197 it is possible for the buffer to be displayed in the
1198 selected window, while last_window_start reflects another
1199 window which was recently showing the same buffer.
1200 Some people might say that might be a good thing. Let's see. */
1201 b->last_window_start = marker_position (w->start);
1203 /* Point in the selected window's buffer
1204 is actually stored in that buffer, and the window's pointm isn't used.
1205 So don't clobber point in that buffer. */
1206 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1207 /* This line helps to fix Horsley's testbug.el bug. */
1208 && !(WINDOWP (b->last_selected_window)
1209 && w != XWINDOW (b->last_selected_window)
1210 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1211 temp_set_point_both (b,
1212 clip_to_bounds (BUF_BEGV (b),
1213 XMARKER (w->pointm)->charpos,
1214 BUF_ZV (b)),
1215 clip_to_bounds (BUF_BEGV_BYTE (b),
1216 marker_byte_position (w->pointm),
1217 BUF_ZV_BYTE (b)));
1219 if (WINDOWP (b->last_selected_window)
1220 && w == XWINDOW (b->last_selected_window))
1221 b->last_selected_window = Qnil;
1224 /* Put replacement into the window structure in place of old. */
1225 static void
1226 replace_window (old, replacement)
1227 Lisp_Object old, replacement;
1229 register Lisp_Object tem;
1230 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1232 /* If OLD is its frame's root_window, then replacement is the new
1233 root_window for that frame. */
1235 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1236 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1238 p->left_col = o->left_col;
1239 p->top_line = o->top_line;
1240 p->total_cols = o->total_cols;
1241 p->total_lines = o->total_lines;
1242 p->desired_matrix = p->current_matrix = 0;
1243 p->vscroll = 0;
1244 bzero (&p->cursor, sizeof (p->cursor));
1245 bzero (&p->last_cursor, sizeof (p->last_cursor));
1246 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1247 p->phys_cursor_type = -1;
1248 p->phys_cursor_width = -1;
1249 p->must_be_updated_p = 0;
1250 p->pseudo_window_p = 0;
1251 XSETFASTINT (p->window_end_vpos, 0);
1252 XSETFASTINT (p->window_end_pos, 0);
1253 p->window_end_valid = Qnil;
1254 p->frozen_window_start_p = 0;
1255 p->orig_top_line = p->orig_total_lines = Qnil;
1257 p->next = tem = o->next;
1258 if (!NILP (tem))
1259 XWINDOW (tem)->prev = replacement;
1261 p->prev = tem = o->prev;
1262 if (!NILP (tem))
1263 XWINDOW (tem)->next = replacement;
1265 p->parent = tem = o->parent;
1266 if (!NILP (tem))
1268 if (EQ (XWINDOW (tem)->vchild, old))
1269 XWINDOW (tem)->vchild = replacement;
1270 if (EQ (XWINDOW (tem)->hchild, old))
1271 XWINDOW (tem)->hchild = replacement;
1274 /*** Here, if replacement is a vertical combination
1275 and so is its new parent, we should make replacement's
1276 children be children of that parent instead. ***/
1279 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1280 doc: /* Remove WINDOW from the display. Default is selected window. */)
1281 (window)
1282 register Lisp_Object window;
1284 delete_window (window);
1286 if (! NILP (Vwindow_configuration_change_hook)
1287 && ! NILP (Vrun_hooks))
1288 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1290 return Qnil;
1293 void
1294 delete_window (window)
1295 register Lisp_Object window;
1297 register Lisp_Object tem, parent, sib;
1298 register struct window *p;
1299 register struct window *par;
1300 struct frame *f;
1302 /* Because this function is called by other C code on non-leaf
1303 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1304 so we can't decode_window here. */
1305 if (NILP (window))
1306 window = selected_window;
1307 else
1308 CHECK_WINDOW (window);
1309 p = XWINDOW (window);
1311 /* It's okay to delete an already-deleted window. */
1312 if (NILP (p->buffer)
1313 && NILP (p->hchild)
1314 && NILP (p->vchild))
1315 return;
1317 parent = p->parent;
1318 if (NILP (parent))
1319 error ("Attempt to delete minibuffer or sole ordinary window");
1320 par = XWINDOW (parent);
1322 windows_or_buffers_changed++;
1323 Vwindow_list = Qnil;
1324 f = XFRAME (WINDOW_FRAME (p));
1325 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1327 /* Are we trying to delete any frame's selected window? */
1329 Lisp_Object swindow, pwindow;
1331 /* See if the frame's selected window is either WINDOW
1332 or any subwindow of it, by finding all that window's parents
1333 and comparing each one with WINDOW. */
1334 swindow = FRAME_SELECTED_WINDOW (f);
1336 while (1)
1338 pwindow = swindow;
1339 while (!NILP (pwindow))
1341 if (EQ (window, pwindow))
1342 break;
1343 pwindow = XWINDOW (pwindow)->parent;
1346 /* If the window being deleted is not a parent of SWINDOW,
1347 then SWINDOW is ok as the new selected window. */
1348 if (!EQ (window, pwindow))
1349 break;
1350 /* Otherwise, try another window for SWINDOW. */
1351 swindow = Fnext_window (swindow, Qlambda, Qnil);;
1353 /* If we get back to the frame's selected window,
1354 it means there was no acceptable alternative,
1355 so we cannot delete. */
1356 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1357 error ("Cannot delete window");
1360 /* If we need to change SWINDOW, do it. */
1361 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1363 /* If we're about to delete the selected window on the
1364 selected frame, then we should use Fselect_window to select
1365 the new window. On the other hand, if we're about to
1366 delete the selected window on any other frame, we shouldn't do
1367 anything but set the frame's selected_window slot. */
1368 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1369 Fselect_window (swindow, Qnil);
1370 else
1371 FRAME_SELECTED_WINDOW (f) = swindow;
1375 tem = p->buffer;
1376 /* tem is null for dummy parent windows
1377 (which have inferiors but not any contents themselves) */
1378 if (!NILP (tem))
1380 unshow_buffer (p);
1381 unchain_marker (XMARKER (p->pointm));
1382 unchain_marker (XMARKER (p->start));
1385 /* Free window glyph matrices. It is sure that they are allocated
1386 again when ADJUST_GLYPHS is called. Block input so that expose
1387 events and other events that access glyph matrices are not
1388 processed while we are changing them. */
1389 BLOCK_INPUT;
1390 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1392 tem = p->next;
1393 if (!NILP (tem))
1394 XWINDOW (tem)->prev = p->prev;
1396 tem = p->prev;
1397 if (!NILP (tem))
1398 XWINDOW (tem)->next = p->next;
1400 if (EQ (window, par->hchild))
1401 par->hchild = p->next;
1402 if (EQ (window, par->vchild))
1403 par->vchild = p->next;
1405 /* Find one of our siblings to give our space to. */
1406 sib = p->prev;
1407 if (NILP (sib))
1409 /* If p gives its space to its next sibling, that sibling needs
1410 to have its top/left side pulled back to where p's is.
1411 set_window_{height,width} will re-position the sibling's
1412 children. */
1413 sib = p->next;
1414 XWINDOW (sib)->top_line = p->top_line;
1415 XWINDOW (sib)->left_col = p->left_col;
1418 /* Stretch that sibling. */
1419 if (!NILP (par->vchild))
1420 set_window_height (sib,
1421 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1423 if (!NILP (par->hchild))
1424 set_window_width (sib,
1425 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1428 /* If parent now has only one child,
1429 put the child into the parent's place. */
1430 tem = par->hchild;
1431 if (NILP (tem))
1432 tem = par->vchild;
1433 if (NILP (XWINDOW (tem)->next))
1434 replace_window (parent, tem);
1436 /* Since we may be deleting combination windows, we must make sure that
1437 not only p but all its children have been marked as deleted. */
1438 if (! NILP (p->hchild))
1439 delete_all_subwindows (XWINDOW (p->hchild));
1440 else if (! NILP (p->vchild))
1441 delete_all_subwindows (XWINDOW (p->vchild));
1443 /* Mark this window as deleted. */
1444 p->buffer = p->hchild = p->vchild = Qnil;
1446 /* Adjust glyph matrices. */
1447 adjust_glyphs (f);
1448 UNBLOCK_INPUT;
1453 /***********************************************************************
1454 Window List
1455 ***********************************************************************/
1457 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1458 pointer. This is a callback function for foreach_window, used in
1459 function window_list. */
1461 static int
1462 add_window_to_list (w, user_data)
1463 struct window *w;
1464 void *user_data;
1466 Lisp_Object *list = (Lisp_Object *) user_data;
1467 Lisp_Object window;
1468 XSETWINDOW (window, w);
1469 *list = Fcons (window, *list);
1470 return 1;
1474 /* Return a list of all windows, for use by next_window. If
1475 Vwindow_list is a list, return that list. Otherwise, build a new
1476 list, cache it in Vwindow_list, and return that. */
1478 static Lisp_Object
1479 window_list ()
1481 if (!CONSP (Vwindow_list))
1483 Lisp_Object tail;
1485 Vwindow_list = Qnil;
1486 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1488 Lisp_Object args[2];
1490 /* We are visiting windows in canonical order, and add
1491 new windows at the front of args[1], which means we
1492 have to reverse this list at the end. */
1493 args[1] = Qnil;
1494 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1495 args[0] = Vwindow_list;
1496 args[1] = Fnreverse (args[1]);
1497 Vwindow_list = Fnconc (2, args);
1501 return Vwindow_list;
1505 /* Value is non-zero if WINDOW satisfies the constraints given by
1506 OWINDOW, MINIBUF and ALL_FRAMES.
1508 MINIBUF t means WINDOW may be minibuffer windows.
1509 `lambda' means WINDOW may not be a minibuffer window.
1510 a window means a specific minibuffer window
1512 ALL_FRAMES t means search all frames,
1513 nil means search just current frame,
1514 `visible' means search just visible frames,
1515 0 means search visible and iconified frames,
1516 a window means search the frame that window belongs to,
1517 a frame means consider windows on that frame, only. */
1519 static int
1520 candidate_window_p (window, owindow, minibuf, all_frames)
1521 Lisp_Object window, owindow, minibuf, all_frames;
1523 struct window *w = XWINDOW (window);
1524 struct frame *f = XFRAME (w->frame);
1525 int candidate_p = 1;
1527 if (!BUFFERP (w->buffer))
1528 candidate_p = 0;
1529 else if (MINI_WINDOW_P (w)
1530 && (EQ (minibuf, Qlambda)
1531 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1533 /* If MINIBUF is `lambda' don't consider any mini-windows.
1534 If it is a window, consider only that one. */
1535 candidate_p = 0;
1537 else if (EQ (all_frames, Qt))
1538 candidate_p = 1;
1539 else if (NILP (all_frames))
1541 xassert (WINDOWP (owindow));
1542 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1544 else if (EQ (all_frames, Qvisible))
1546 FRAME_SAMPLE_VISIBILITY (f);
1547 candidate_p = FRAME_VISIBLE_P (f);
1549 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1551 FRAME_SAMPLE_VISIBILITY (f);
1552 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1554 else if (WINDOWP (all_frames))
1555 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1556 || EQ (XWINDOW (all_frames)->frame, w->frame)
1557 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1558 else if (FRAMEP (all_frames))
1559 candidate_p = EQ (all_frames, w->frame);
1561 return candidate_p;
1565 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1566 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1567 ALL_FRAMES. */
1569 static void
1570 decode_next_window_args (window, minibuf, all_frames)
1571 Lisp_Object *window, *minibuf, *all_frames;
1573 if (NILP (*window))
1574 *window = selected_window;
1575 else
1576 CHECK_LIVE_WINDOW (*window);
1578 /* MINIBUF nil may or may not include minibuffers. Decide if it
1579 does. */
1580 if (NILP (*minibuf))
1581 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1582 else if (!EQ (*minibuf, Qt))
1583 *minibuf = Qlambda;
1585 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1586 => count none of them, or a specific minibuffer window (the
1587 active one) to count. */
1589 /* ALL_FRAMES nil doesn't specify which frames to include. */
1590 if (NILP (*all_frames))
1591 *all_frames = (!EQ (*minibuf, Qlambda)
1592 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1593 : Qnil);
1594 else if (EQ (*all_frames, Qvisible))
1596 else if (XFASTINT (*all_frames) == 0)
1598 else if (FRAMEP (*all_frames))
1600 else if (!EQ (*all_frames, Qt))
1601 *all_frames = Qnil;
1603 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1604 search just current frame, `visible' meaning search just visible
1605 frames, 0 meaning search visible and iconified frames, or a
1606 window, meaning search the frame that window belongs to, or a
1607 frame, meaning consider windows on that frame, only. */
1611 /* Return the next or previous window of WINDOW in canonical ordering
1612 of windows. NEXT_P non-zero means return the next window. See the
1613 documentation string of next-window for the meaning of MINIBUF and
1614 ALL_FRAMES. */
1616 static Lisp_Object
1617 next_window (window, minibuf, all_frames, next_p)
1618 Lisp_Object window, minibuf, all_frames;
1619 int next_p;
1621 decode_next_window_args (&window, &minibuf, &all_frames);
1623 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1624 return the first window on the frame. */
1625 if (FRAMEP (all_frames)
1626 && !EQ (all_frames, XWINDOW (window)->frame))
1627 return Fframe_first_window (all_frames);
1629 if (next_p)
1631 Lisp_Object list;
1633 /* Find WINDOW in the list of all windows. */
1634 list = Fmemq (window, window_list ());
1636 /* Scan forward from WINDOW to the end of the window list. */
1637 if (CONSP (list))
1638 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1639 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1640 break;
1642 /* Scan from the start of the window list up to WINDOW. */
1643 if (!CONSP (list))
1644 for (list = Vwindow_list;
1645 CONSP (list) && !EQ (XCAR (list), window);
1646 list = XCDR (list))
1647 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1648 break;
1650 if (CONSP (list))
1651 window = XCAR (list);
1653 else
1655 Lisp_Object candidate, list;
1657 /* Scan through the list of windows for candidates. If there are
1658 candidate windows in front of WINDOW, the last one of these
1659 is the one we want. If there are candidates following WINDOW
1660 in the list, again the last one of these is the one we want. */
1661 candidate = Qnil;
1662 for (list = window_list (); CONSP (list); list = XCDR (list))
1664 if (EQ (XCAR (list), window))
1666 if (WINDOWP (candidate))
1667 break;
1669 else if (candidate_window_p (XCAR (list), window, minibuf,
1670 all_frames))
1671 candidate = XCAR (list);
1674 if (WINDOWP (candidate))
1675 window = candidate;
1678 return window;
1682 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1683 doc: /* Return next window after WINDOW in canonical ordering of windows.
1684 If omitted, WINDOW defaults to the selected window.
1686 Optional second arg MINIBUF t means count the minibuffer window even
1687 if not active. MINIBUF nil or omitted means count the minibuffer iff
1688 it is active. MINIBUF neither t nor nil means not to count the
1689 minibuffer even if it is active.
1691 Several frames may share a single minibuffer; if the minibuffer
1692 counts, all windows on all frames that share that minibuffer count
1693 too. Therefore, `next-window' can be used to iterate through the
1694 set of windows even when the minibuffer is on another frame. If the
1695 minibuffer does not count, only windows from WINDOW's frame count.
1697 Optional third arg ALL-FRAMES t means include windows on all frames.
1698 ALL-FRAMES nil or omitted means cycle within the frames as specified
1699 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1700 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1701 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1702 Anything else means restrict to WINDOW's frame.
1704 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1705 `next-window' to iterate through the entire cycle of acceptable
1706 windows, eventually ending up back at the window you started with.
1707 `previous-window' traverses the same cycle, in the reverse order. */)
1708 (window, minibuf, all_frames)
1709 Lisp_Object window, minibuf, all_frames;
1711 return next_window (window, minibuf, all_frames, 1);
1715 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1716 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1717 If omitted, WINDOW defaults to the selected window.
1719 Optional second arg MINIBUF t means count the minibuffer window even
1720 if not active. MINIBUF nil or omitted means count the minibuffer iff
1721 it is active. MINIBUF neither t nor nil means not to count the
1722 minibuffer even if it is active.
1724 Several frames may share a single minibuffer; if the minibuffer
1725 counts, all windows on all frames that share that minibuffer count
1726 too. Therefore, `previous-window' can be used to iterate through
1727 the set of windows even when the minibuffer is on another frame. If
1728 the minibuffer does not count, only windows from WINDOW's frame count
1730 Optional third arg ALL-FRAMES t means include windows on all frames.
1731 ALL-FRAMES nil or omitted means cycle within the frames as specified
1732 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1733 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1734 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1735 Anything else means restrict to WINDOW's frame.
1737 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1738 `previous-window' to iterate through the entire cycle of acceptable
1739 windows, eventually ending up back at the window you started with.
1740 `next-window' traverses the same cycle, in the reverse order. */)
1741 (window, minibuf, all_frames)
1742 Lisp_Object window, minibuf, all_frames;
1744 return next_window (window, minibuf, all_frames, 0);
1748 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1749 doc: /* Select the ARG'th different window on this frame.
1750 All windows on current frame are arranged in a cyclic order.
1751 This command selects the window ARG steps away in that order.
1752 A negative ARG moves in the opposite order. If the optional second
1753 argument ALL_FRAMES is non-nil, cycle through all frames. */)
1754 (arg, all_frames)
1755 Lisp_Object arg, all_frames;
1757 Lisp_Object window;
1758 int i;
1760 CHECK_NUMBER (arg);
1761 window = selected_window;
1763 for (i = XINT (arg); i > 0; --i)
1764 window = Fnext_window (window, Qnil, all_frames);
1765 for (; i < 0; ++i)
1766 window = Fprevious_window (window, Qnil, all_frames);
1768 Fselect_window (window, Qnil);
1769 return Qnil;
1773 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
1774 doc: /* Return a list of windows on FRAME, starting with WINDOW.
1775 FRAME nil or omitted means use the selected frame.
1776 WINDOW nil or omitted means use the selected window.
1777 MINIBUF t means include the minibuffer window, even if it isn't active.
1778 MINIBUF nil or omitted means include the minibuffer window only
1779 if it's active.
1780 MINIBUF neither nil nor t means never include the minibuffer window. */)
1781 (frame, minibuf, window)
1782 Lisp_Object frame, minibuf, window;
1784 if (NILP (window))
1785 window = selected_window;
1786 if (NILP (frame))
1787 frame = selected_frame;
1789 if (!EQ (frame, XWINDOW (window)->frame))
1790 error ("Window is on a different frame");
1792 return window_list_1 (window, minibuf, frame);
1796 /* Return a list of windows in canonical ordering. Arguments are like
1797 for `next-window'. */
1799 static Lisp_Object
1800 window_list_1 (window, minibuf, all_frames)
1801 Lisp_Object window, minibuf, all_frames;
1803 Lisp_Object tail, list;
1805 decode_next_window_args (&window, &minibuf, &all_frames);
1806 list = Qnil;
1808 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
1809 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
1810 list = Fcons (XCAR (tail), list);
1812 return Fnreverse (list);
1817 /* Look at all windows, performing an operation specified by TYPE
1818 with argument OBJ.
1819 If FRAMES is Qt, look at all frames;
1820 Qnil, look at just the selected frame;
1821 Qvisible, look at visible frames;
1822 a frame, just look at windows on that frame.
1823 If MINI is non-zero, perform the operation on minibuffer windows too. */
1825 enum window_loop
1827 WINDOW_LOOP_UNUSED,
1828 GET_BUFFER_WINDOW, /* Arg is buffer */
1829 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1830 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1831 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1832 GET_LARGEST_WINDOW,
1833 UNSHOW_BUFFER, /* Arg is buffer */
1834 CHECK_ALL_WINDOWS
1837 static Lisp_Object
1838 window_loop (type, obj, mini, frames)
1839 enum window_loop type;
1840 Lisp_Object obj, frames;
1841 int mini;
1843 Lisp_Object window, windows, best_window, frame_arg;
1844 struct frame *f;
1845 struct gcpro gcpro1;
1847 /* If we're only looping through windows on a particular frame,
1848 frame points to that frame. If we're looping through windows
1849 on all frames, frame is 0. */
1850 if (FRAMEP (frames))
1851 f = XFRAME (frames);
1852 else if (NILP (frames))
1853 f = SELECTED_FRAME ();
1854 else
1855 f = NULL;
1857 if (f)
1858 frame_arg = Qlambda;
1859 else if (XFASTINT (frames) == 0)
1860 frame_arg = frames;
1861 else if (EQ (frames, Qvisible))
1862 frame_arg = frames;
1863 else
1864 frame_arg = Qt;
1866 /* frame_arg is Qlambda to stick to one frame,
1867 Qvisible to consider all visible frames,
1868 or Qt otherwise. */
1870 /* Pick a window to start with. */
1871 if (WINDOWP (obj))
1872 window = obj;
1873 else if (f)
1874 window = FRAME_SELECTED_WINDOW (f);
1875 else
1876 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1878 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
1879 GCPRO1 (windows);
1880 best_window = Qnil;
1882 for (; CONSP (windows); windows = CDR (windows))
1884 struct window *w;
1886 window = XCAR (windows);
1887 w = XWINDOW (window);
1889 /* Note that we do not pay attention here to whether the frame
1890 is visible, since Fwindow_list skips non-visible frames if
1891 that is desired, under the control of frame_arg. */
1892 if (!MINI_WINDOW_P (w)
1893 /* For UNSHOW_BUFFER, we must always consider all windows. */
1894 || type == UNSHOW_BUFFER
1895 || (mini && minibuf_level > 0))
1896 switch (type)
1898 case GET_BUFFER_WINDOW:
1899 if (EQ (w->buffer, obj)
1900 /* Don't find any minibuffer window
1901 except the one that is currently in use. */
1902 && (MINI_WINDOW_P (w)
1903 ? EQ (window, minibuf_window)
1904 : 1))
1906 if (NILP (best_window))
1907 best_window = window;
1908 else if (EQ (window, selected_window))
1909 /* For compatibility with 20.x, prefer to return
1910 selected-window. */
1911 best_window = window;
1913 break;
1915 case GET_LRU_WINDOW:
1916 /* t as arg means consider only full-width windows */
1917 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w))
1918 break;
1919 /* Ignore dedicated windows and minibuffers. */
1920 if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
1921 break;
1922 if (NILP (best_window)
1923 || (XFASTINT (XWINDOW (best_window)->use_time)
1924 > XFASTINT (w->use_time)))
1925 best_window = window;
1926 break;
1928 case DELETE_OTHER_WINDOWS:
1929 if (!EQ (window, obj))
1930 Fdelete_window (window);
1931 break;
1933 case DELETE_BUFFER_WINDOWS:
1934 if (EQ (w->buffer, obj))
1936 struct frame *f = XFRAME (WINDOW_FRAME (w));
1938 /* If this window is dedicated, and in a frame of its own,
1939 kill the frame. */
1940 if (EQ (window, FRAME_ROOT_WINDOW (f))
1941 && !NILP (w->dedicated)
1942 && other_visible_frames (f))
1944 /* Skip the other windows on this frame.
1945 There might be one, the minibuffer! */
1946 while (CONSP (XCDR (windows))
1947 && EQ (XWINDOW (XCAR (windows))->frame,
1948 XWINDOW (XCAR (XCDR (windows)))->frame))
1949 windows = XCDR (windows);
1951 /* Now we can safely delete the frame. */
1952 Fdelete_frame (w->frame, Qnil);
1954 else if (NILP (w->parent))
1956 /* If we're deleting the buffer displayed in the
1957 only window on the frame, find a new buffer to
1958 display there. */
1959 Lisp_Object buffer;
1960 buffer = Fother_buffer (obj, Qnil, w->frame);
1961 Fset_window_buffer (window, buffer, Qnil);
1962 if (EQ (window, selected_window))
1963 Fset_buffer (w->buffer);
1965 else
1966 Fdelete_window (window);
1968 break;
1970 case GET_LARGEST_WINDOW:
1972 /* Ignore dedicated windows and minibuffers. */
1973 if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
1974 break;
1976 if (NILP (best_window))
1977 best_window = window;
1978 else
1980 struct window *b = XWINDOW (best_window);
1981 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
1982 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
1983 best_window = window;
1986 break;
1988 case UNSHOW_BUFFER:
1989 if (EQ (w->buffer, obj))
1991 Lisp_Object buffer;
1992 struct frame *f = XFRAME (w->frame);
1994 /* Find another buffer to show in this window. */
1995 buffer = Fother_buffer (obj, Qnil, w->frame);
1997 /* If this window is dedicated, and in a frame of its own,
1998 kill the frame. */
1999 if (EQ (window, FRAME_ROOT_WINDOW (f))
2000 && !NILP (w->dedicated)
2001 && other_visible_frames (f))
2003 /* Skip the other windows on this frame.
2004 There might be one, the minibuffer! */
2005 while (CONSP (XCDR (windows))
2006 && EQ (XWINDOW (XCAR (windows))->frame,
2007 XWINDOW (XCAR (XCDR (windows)))->frame))
2008 windows = XCDR (windows);
2010 /* Now we can safely delete the frame. */
2011 Fdelete_frame (w->frame, Qnil);
2013 else if (!NILP (w->dedicated) && !NILP (w->parent))
2015 Lisp_Object window;
2016 XSETWINDOW (window, w);
2017 /* If this window is dedicated and not the only window
2018 in its frame, then kill it. */
2019 Fdelete_window (window);
2021 else
2023 /* Otherwise show a different buffer in the window. */
2024 w->dedicated = Qnil;
2025 Fset_window_buffer (window, buffer, Qnil);
2026 if (EQ (window, selected_window))
2027 Fset_buffer (w->buffer);
2030 break;
2032 /* Check for a window that has a killed buffer. */
2033 case CHECK_ALL_WINDOWS:
2034 if (! NILP (w->buffer)
2035 && NILP (XBUFFER (w->buffer)->name))
2036 abort ();
2037 break;
2039 case WINDOW_LOOP_UNUSED:
2040 break;
2044 UNGCPRO;
2045 return best_window;
2048 /* Used for debugging. Abort if any window has a dead buffer. */
2050 void
2051 check_all_windows ()
2053 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2056 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
2057 doc: /* Return the window least recently selected or used for display.
2058 If optional argument FRAME is `visible', search all visible frames.
2059 If FRAME is 0, search all visible and iconified frames.
2060 If FRAME is t, search all frames.
2061 If FRAME is nil, search only the selected frame.
2062 If FRAME is a frame, search only that frame. */)
2063 (frame)
2064 Lisp_Object frame;
2066 register Lisp_Object w;
2067 /* First try for a window that is full-width */
2068 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
2069 if (!NILP (w) && !EQ (w, selected_window))
2070 return w;
2071 /* If none of them, try the rest */
2072 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
2075 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
2076 doc: /* Return the largest window in area.
2077 If optional argument FRAME is `visible', search all visible frames.
2078 If FRAME is 0, search all visible and iconified frames.
2079 If FRAME is t, search all frames.
2080 If FRAME is nil, search only the selected frame.
2081 If FRAME is a frame, search only that frame. */)
2082 (frame)
2083 Lisp_Object frame;
2085 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
2086 frame);
2089 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2090 doc: /* Return a window currently displaying BUFFER, or nil if none.
2091 If optional argument FRAME is `visible', search all visible frames.
2092 If optional argument FRAME is 0, search all visible and iconified frames.
2093 If FRAME is t, search all frames.
2094 If FRAME is nil, search only the selected frame.
2095 If FRAME is a frame, search only that frame. */)
2096 (buffer, frame)
2097 Lisp_Object buffer, frame;
2099 buffer = Fget_buffer (buffer);
2100 if (BUFFERP (buffer))
2101 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2102 else
2103 return Qnil;
2106 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2107 0, 1, "",
2108 doc: /* Make WINDOW (or the selected window) fill its frame.
2109 Only the frame WINDOW is on is affected.
2110 This function tries to reduce display jumps
2111 by keeping the text previously visible in WINDOW
2112 in the same place on the frame. Doing this depends on
2113 the value of (window-start WINDOW), so if calling this function
2114 in a program gives strange scrolling, make sure the window-start
2115 value is reasonable when this function is called. */)
2116 (window)
2117 Lisp_Object window;
2119 struct window *w;
2120 int startpos;
2121 int top, new_top;
2123 if (NILP (window))
2124 window = selected_window;
2125 else
2126 CHECK_LIVE_WINDOW (window);
2127 w = XWINDOW (window);
2129 startpos = marker_position (w->start);
2130 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2132 if (MINI_WINDOW_P (w) && top > 0)
2133 error ("Can't expand minibuffer to full frame");
2135 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2137 /* Try to minimize scrolling, by setting the window start to the point
2138 will cause the text at the old window start to be at the same place
2139 on the frame. But don't try to do this if the window start is
2140 outside the visible portion (as might happen when the display is
2141 not current, due to typeahead). */
2142 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2143 if (new_top != top
2144 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2145 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2147 struct position pos;
2148 struct buffer *obuf = current_buffer;
2150 Fset_buffer (w->buffer);
2151 /* This computation used to temporarily move point, but that can
2152 have unwanted side effects due to text properties. */
2153 pos = *vmotion (startpos, -top, w);
2155 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2156 w->window_end_valid = Qnil;
2157 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2158 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2159 : Qnil);
2160 /* We need to do this, so that the window-scroll-functions
2161 get called. */
2162 w->optional_new_start = Qt;
2164 set_buffer_internal (obuf);
2167 return Qnil;
2170 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2171 1, 2, "bDelete windows on (buffer): ",
2172 doc: /* Delete all windows showing BUFFER.
2173 Optional second argument FRAME controls which frames are affected.
2174 If optional argument FRAME is `visible', search all visible frames.
2175 If FRAME is 0, search all visible and iconified frames.
2176 If FRAME is nil, search all frames.
2177 If FRAME is t, search only the selected frame.
2178 If FRAME is a frame, search only that frame. */)
2179 (buffer, frame)
2180 Lisp_Object buffer, frame;
2182 /* FRAME uses t and nil to mean the opposite of what window_loop
2183 expects. */
2184 if (NILP (frame))
2185 frame = Qt;
2186 else if (EQ (frame, Qt))
2187 frame = Qnil;
2189 if (!NILP (buffer))
2191 buffer = Fget_buffer (buffer);
2192 CHECK_BUFFER (buffer);
2193 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2196 return Qnil;
2199 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2200 Sreplace_buffer_in_windows,
2201 1, 1, "bReplace buffer in windows: ",
2202 doc: /* Replace BUFFER with some other buffer in all windows showing it. */)
2203 (buffer)
2204 Lisp_Object buffer;
2206 if (!NILP (buffer))
2208 buffer = Fget_buffer (buffer);
2209 CHECK_BUFFER (buffer);
2210 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2212 return Qnil;
2215 /* Replace BUFFER with some other buffer in all windows
2216 of all frames, even those on other keyboards. */
2218 void
2219 replace_buffer_in_all_windows (buffer)
2220 Lisp_Object buffer;
2222 #ifdef MULTI_KBOARD
2223 Lisp_Object tail, frame;
2225 /* A single call to window_loop won't do the job
2226 because it only considers frames on the current keyboard.
2227 So loop manually over frames, and handle each one. */
2228 FOR_EACH_FRAME (tail, frame)
2229 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2230 #else
2231 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2232 #endif
2235 /* Set the height of WINDOW and all its inferiors. */
2237 /* The smallest acceptable dimensions for a window. Anything smaller
2238 might crash Emacs. */
2240 #define MIN_SAFE_WINDOW_WIDTH (2)
2241 #define MIN_SAFE_WINDOW_HEIGHT (1)
2243 /* Make sure that window_min_height and window_min_width are
2244 not too small; if they are, set them to safe minima. */
2246 static void
2247 check_min_window_sizes ()
2249 /* Smaller values might permit a crash. */
2250 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2251 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2252 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2253 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2256 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2257 minimum allowable size. */
2259 void
2260 check_frame_size (frame, rows, cols)
2261 FRAME_PTR frame;
2262 int *rows, *cols;
2264 /* For height, we have to see:
2265 how many windows the frame has at minimum (one or two),
2266 and whether it has a menu bar or other special stuff at the top. */
2267 int min_height
2268 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2269 ? MIN_SAFE_WINDOW_HEIGHT
2270 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2272 if (FRAME_TOP_MARGIN (frame) > 0)
2273 min_height += FRAME_TOP_MARGIN (frame);
2275 if (*rows < min_height)
2276 *rows = min_height;
2277 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2278 *cols = MIN_SAFE_WINDOW_WIDTH;
2282 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2283 check if W's width can be changed, otherwise check W's height.
2284 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2285 siblings, too. If none of the siblings is resizable, WINDOW isn't
2286 either. */
2288 static int
2289 window_fixed_size_p (w, width_p, check_siblings_p)
2290 struct window *w;
2291 int width_p, check_siblings_p;
2293 int fixed_p;
2294 struct window *c;
2296 if (!NILP (w->hchild))
2298 c = XWINDOW (w->hchild);
2300 if (width_p)
2302 /* A horiz. combination is fixed-width if all of if its
2303 children are. */
2304 while (c && window_fixed_size_p (c, width_p, 0))
2305 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2306 fixed_p = c == NULL;
2308 else
2310 /* A horiz. combination is fixed-height if one of if its
2311 children is. */
2312 while (c && !window_fixed_size_p (c, width_p, 0))
2313 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2314 fixed_p = c != NULL;
2317 else if (!NILP (w->vchild))
2319 c = XWINDOW (w->vchild);
2321 if (width_p)
2323 /* A vert. combination is fixed-width if one of if its
2324 children is. */
2325 while (c && !window_fixed_size_p (c, width_p, 0))
2326 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2327 fixed_p = c != NULL;
2329 else
2331 /* A vert. combination is fixed-height if all of if its
2332 children are. */
2333 while (c && window_fixed_size_p (c, width_p, 0))
2334 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2335 fixed_p = c == NULL;
2338 else if (BUFFERP (w->buffer))
2340 if (w->height_fixed_p && !width_p)
2341 fixed_p = 1;
2342 else
2344 struct buffer *old = current_buffer;
2345 Lisp_Object val;
2347 current_buffer = XBUFFER (w->buffer);
2348 val = find_symbol_value (Qwindow_size_fixed);
2349 current_buffer = old;
2351 fixed_p = 0;
2352 if (!EQ (val, Qunbound))
2354 fixed_p = !NILP (val);
2356 if (fixed_p
2357 && ((EQ (val, Qheight) && width_p)
2358 || (EQ (val, Qwidth) && !width_p)))
2359 fixed_p = 0;
2363 /* Can't tell if this one is resizable without looking at
2364 siblings. If all siblings are fixed-size this one is too. */
2365 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2367 Lisp_Object child;
2369 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2370 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2371 break;
2373 if (NILP (child))
2374 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2375 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2376 break;
2378 if (NILP (child))
2379 fixed_p = 1;
2382 else
2383 fixed_p = 1;
2385 return fixed_p;
2389 /* Return the minimum size of window W, not taking fixed-width windows
2390 into account. WIDTH_P non-zero means return the minimum width,
2391 otherwise return the minimum height. If W is a combination window,
2392 compute the minimum size from the minimum sizes of W's children. */
2394 static int
2395 window_min_size_1 (w, width_p)
2396 struct window *w;
2397 int width_p;
2399 struct window *c;
2400 int size;
2402 if (!NILP (w->hchild))
2404 c = XWINDOW (w->hchild);
2405 size = 0;
2407 if (width_p)
2409 /* The min width of a horizontal combination is
2410 the sum of the min widths of its children. */
2411 while (c)
2413 size += window_min_size_1 (c, width_p);
2414 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2417 else
2419 /* The min height a horizontal combination equals
2420 the maximum of all min height of its children. */
2421 while (c)
2423 int min_size = window_min_size_1 (c, width_p);
2424 size = max (min_size, size);
2425 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2429 else if (!NILP (w->vchild))
2431 c = XWINDOW (w->vchild);
2432 size = 0;
2434 if (width_p)
2436 /* The min width of a vertical combination is
2437 the maximum of the min widths of its children. */
2438 while (c)
2440 int min_size = window_min_size_1 (c, width_p);
2441 size = max (min_size, size);
2442 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2445 else
2447 /* The min height of a vertical combination equals
2448 the sum of the min height of its children. */
2449 while (c)
2451 size += window_min_size_1 (c, width_p);
2452 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2456 else
2458 if (width_p)
2459 size = window_min_width;
2460 else
2462 if (MINI_WINDOW_P (w)
2463 || (!WINDOW_WANTS_MODELINE_P (w)
2464 && !WINDOW_WANTS_HEADER_LINE_P (w)))
2465 size = 1;
2466 else
2467 size = window_min_height;
2471 return size;
2475 /* Return the minimum size of window W, taking fixed-size windows into
2476 account. WIDTH_P non-zero means return the minimum width,
2477 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2478 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2479 unless FIXED is null. */
2481 static int
2482 window_min_size (w, width_p, ignore_fixed_p, fixed)
2483 struct window *w;
2484 int width_p, ignore_fixed_p, *fixed;
2486 int size, fixed_p;
2488 if (ignore_fixed_p)
2489 fixed_p = 0;
2490 else
2491 fixed_p = window_fixed_size_p (w, width_p, 1);
2493 if (fixed)
2494 *fixed = fixed_p;
2496 if (fixed_p)
2497 size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines);
2498 else
2499 size = window_min_size_1 (w, width_p);
2501 return size;
2505 /* Adjust the margins of window W if text area is too small.
2506 Return 1 if window width is ok after adjustment; 0 if window
2507 is still too narrow. */
2509 static int
2510 adjust_window_margins (w)
2511 struct window *w;
2513 int box_cols = (WINDOW_TOTAL_COLS (w)
2514 - WINDOW_FRINGE_COLS (w)
2515 - WINDOW_SCROLL_BAR_COLS (w));
2516 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2517 + WINDOW_RIGHT_MARGIN_COLS (w));
2519 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2520 return 1;
2522 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2523 return 0;
2525 /* Window's text area is too narrow, but reducing the window
2526 margins will fix that. */
2527 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2528 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2530 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2531 w->left_margin_cols = w->right_margin_cols
2532 = make_number (margin_cols/2);
2533 else
2534 w->right_margin_cols = make_number (margin_cols);
2536 else
2537 w->left_margin_cols = make_number (margin_cols);
2538 return 1;
2541 /* Calculate new sizes for windows in the list FORWARD when the window size
2542 goes from TOTAL to SIZE. TOTAL must be greater than SIZE.
2543 The number of windows in FORWARD is NCHILDREN, and the number that
2544 can shrink is SHRINKABLE.
2545 The minimum size a window can have is MIN_SIZE.
2546 If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
2547 If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
2548 shrinking rows.
2550 This function returns an allocated array of new sizes that the caller
2551 must free. The size -1 means the window is fixed and RESIZE_FIXED_P
2552 is zero. Array index 0 refers to the first window in FORWARD, 1 to
2553 the second, and so on.
2555 This function tries to keep windows at least at the minimum size
2556 and resize other windows before it resizes any window to zero (i.e.
2557 delete that window).
2559 Windows are resized proportional to their size, so bigger windows
2560 shrink more than smaller windows. */
2561 static int *
2562 shrink_windows (total, size, nchildren, shrinkable,
2563 min_size, resize_fixed_p, forward, width_p)
2564 int total, size, nchildren, shrinkable, min_size;
2565 int resize_fixed_p, width_p;
2566 Lisp_Object forward;
2568 int available_resize = 0;
2569 int *new_sizes;
2570 struct window *c;
2571 Lisp_Object child;
2572 int smallest = total;
2573 int total_removed = 0;
2574 int total_shrink = total - size;
2575 int i;
2577 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2579 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2581 int child_size;
2583 c = XWINDOW (child);
2584 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2586 if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2587 new_sizes[i] = -1;
2588 else
2590 new_sizes[i] = child_size;
2591 if (child_size > min_size)
2592 available_resize += child_size - min_size;
2595 /* We might need to shrink some windows to zero. Find the smallest
2596 windows and set them to 0 until we can fulfil the new size. */
2598 while (shrinkable > 1 && size + available_resize < total)
2600 for (i = 0; i < nchildren; ++i)
2601 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2602 smallest = new_sizes[i];
2604 for (i = 0; i < nchildren; ++i)
2605 if (new_sizes[i] == smallest)
2607 /* Resize this window down to zero. */
2608 new_sizes[i] = 0;
2609 if (smallest > min_size)
2610 available_resize -= smallest - min_size;
2611 available_resize += smallest;
2612 --shrinkable;
2613 total_removed += smallest;
2615 /* Out of for, just remove one window at the time and
2616 check again if we have enough space. */
2617 break;
2621 /* Now, calculate the new sizes. Try to shrink each window
2622 proportional to its size. */
2623 for (i = 0; i < nchildren; ++i)
2625 if (new_sizes[i] > min_size)
2627 int to_shrink = total_shrink*new_sizes[i]/total;
2628 if (new_sizes[i] - to_shrink < min_size)
2629 to_shrink = new_sizes[i] - min_size;
2630 new_sizes[i] -= to_shrink;
2631 total_removed += to_shrink;
2635 /* Any reminder due to rounding, we just subtract from windows
2636 that are left and still can be shrunk. */
2637 while (total_shrink > total_removed)
2639 for (i = 0; i < nchildren; ++i)
2640 if (new_sizes[i] > min_size)
2642 --new_sizes[i];
2643 ++total_removed;
2645 /* Out of for, just shrink one window at the time and
2646 check again if we have enough space. */
2647 break;
2651 return new_sizes;
2654 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2655 WINDOW's width. Resize WINDOW's children, if any, so that they
2656 keep their proportionate size relative to WINDOW. Propagate
2657 WINDOW's top or left edge position to children. Delete windows
2658 that become too small unless NODELETE_P is non-zero.
2660 If NODELETE_P is 2, that means we do delete windows that are
2661 too small, even if they were too small before! */
2663 static void
2664 size_window (window, size, width_p, nodelete_p)
2665 Lisp_Object window;
2666 int size, width_p, nodelete_p;
2668 struct window *w = XWINDOW (window);
2669 struct window *c;
2670 Lisp_Object child, *forward, *sideward;
2671 int old_size, min_size, safe_min_size;
2673 /* We test nodelete_p != 2 and nodelete_p != 1 below, so it
2674 seems like it's too soon to do this here. ++KFS. */
2675 if (nodelete_p == 2)
2676 nodelete_p = 0;
2678 check_min_window_sizes ();
2679 size = max (0, size);
2681 /* If the window has been "too small" at one point,
2682 don't delete it for being "too small" in the future.
2683 Preserve it as long as that is at all possible. */
2684 if (width_p)
2686 old_size = WINDOW_TOTAL_COLS (w);
2687 min_size = window_min_width;
2688 /* Ensure that there is room for the scroll bar and fringes!
2689 We may reduce display margins though. */
2690 safe_min_size = (MIN_SAFE_WINDOW_WIDTH
2691 + WINDOW_FRINGE_COLS (w)
2692 + WINDOW_SCROLL_BAR_COLS (w));
2694 else
2696 old_size = XINT (w->total_lines);
2697 min_size = window_min_height;
2698 safe_min_size = MIN_SAFE_WINDOW_HEIGHT;
2701 if (old_size < min_size && nodelete_p != 2)
2702 w->too_small_ok = Qt;
2704 /* Maybe delete WINDOW if it's too small. */
2705 if (nodelete_p != 1 && !NILP (w->parent))
2707 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
2708 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
2709 if (min_size < safe_min_size)
2710 min_size = safe_min_size;
2711 if (size < min_size)
2713 delete_window (window);
2714 return;
2718 /* Set redisplay hints. */
2719 w->last_modified = make_number (0);
2720 w->last_overlay_modified = make_number (0);
2721 windows_or_buffers_changed++;
2722 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
2724 if (width_p)
2726 sideward = &w->vchild;
2727 forward = &w->hchild;
2728 w->total_cols = make_number (size);
2729 adjust_window_margins (w);
2731 else
2733 sideward = &w->hchild;
2734 forward = &w->vchild;
2735 w->total_lines = make_number (size);
2736 w->orig_total_lines = Qnil;
2739 if (!NILP (*sideward))
2741 for (child = *sideward; !NILP (child); child = c->next)
2743 c = XWINDOW (child);
2744 if (width_p)
2745 c->left_col = w->left_col;
2746 else
2747 c->top_line = w->top_line;
2748 size_window (child, size, width_p, nodelete_p);
2751 else if (!NILP (*forward))
2753 int fixed_size, each, extra, n;
2754 int resize_fixed_p, nfixed;
2755 int last_pos, first_pos, nchildren, total;
2756 int *new_sizes = NULL;
2758 /* Determine the fixed-size portion of the this window, and the
2759 number of child windows. */
2760 fixed_size = nchildren = nfixed = total = 0;
2761 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
2763 int child_size;
2765 c = XWINDOW (child);
2766 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2767 total += child_size;
2769 if (window_fixed_size_p (c, width_p, 0))
2771 fixed_size += child_size;
2772 ++nfixed;
2776 /* If the new size is smaller than fixed_size, or if there
2777 aren't any resizable windows, allow resizing fixed-size
2778 windows. */
2779 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2781 /* Compute how many lines/columns to add/remove to each child. The
2782 value of extra takes care of rounding errors. */
2783 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2784 if (size < total && n > 1)
2785 new_sizes = shrink_windows (total, size, nchildren, n, min_size,
2786 resize_fixed_p, *forward, width_p);
2787 else
2789 each = (size - total) / n;
2790 extra = (size - total) - n * each;
2793 /* Compute new children heights and edge positions. */
2794 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
2795 last_pos = first_pos;
2796 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
2798 int new_size, old_size;
2800 c = XWINDOW (child);
2801 old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines);
2802 new_size = old_size;
2804 /* The top or left edge position of this child equals the
2805 bottom or right edge of its predecessor. */
2806 if (width_p)
2807 c->left_col = make_number (last_pos);
2808 else
2809 c->top_line = make_number (last_pos);
2811 /* If this child can be resized, do it. */
2812 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2814 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
2815 extra = 0;
2818 /* Set new height. Note that size_window also propagates
2819 edge positions to children, so it's not a no-op if we
2820 didn't change the child's size. */
2821 size_window (child, new_size, width_p, 1);
2823 /* Remember the bottom/right edge position of this child; it
2824 will be used to set the top/left edge of the next child. */
2825 last_pos += new_size;
2828 if (new_sizes) xfree (new_sizes);
2830 /* We should have covered the parent exactly with child windows. */
2831 xassert (size == last_pos - first_pos);
2833 /* Now delete any children that became too small. */
2834 if (!nodelete_p)
2835 for (child = *forward; !NILP (child); child = c->next)
2837 int child_size;
2838 c = XWINDOW (child);
2839 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2840 size_window (child, child_size, width_p, 2);
2845 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2846 WINDOW's children. NODELETE non-zero means don't delete windows
2847 that become too small in the process. (The caller should check
2848 later and do so if appropriate.) */
2850 void
2851 set_window_height (window, height, nodelete)
2852 Lisp_Object window;
2853 int height;
2854 int nodelete;
2856 size_window (window, height, 0, nodelete);
2860 /* Set WINDOW's width to WIDTH, and recursively change the width of
2861 WINDOW's children. NODELETE non-zero means don't delete windows
2862 that become too small in the process. (The caller should check
2863 later and do so if appropriate.) */
2865 void
2866 set_window_width (window, width, nodelete)
2867 Lisp_Object window;
2868 int width;
2869 int nodelete;
2871 size_window (window, width, 1, nodelete);
2874 /* Change window heights in windows rooted in WINDOW by N lines. */
2876 void
2877 change_window_heights (window, n)
2878 Lisp_Object window;
2879 int n;
2881 struct window *w = XWINDOW (window);
2883 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
2884 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
2886 if (INTEGERP (w->orig_top_line))
2887 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
2888 if (INTEGERP (w->orig_total_lines))
2889 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
2891 /* Handle just the top child in a vertical split. */
2892 if (!NILP (w->vchild))
2893 change_window_heights (w->vchild, n);
2895 /* Adjust all children in a horizontal split. */
2896 for (window = w->hchild; !NILP (window); window = w->next)
2898 w = XWINDOW (window);
2899 change_window_heights (window, n);
2904 int window_select_count;
2906 Lisp_Object
2907 Fset_window_buffer_unwind (obuf)
2908 Lisp_Object obuf;
2910 Fset_buffer (obuf);
2911 return Qnil;
2914 EXFUN (Fset_window_fringes, 4);
2915 EXFUN (Fset_window_scroll_bars, 4);
2917 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2918 means it's allowed to run hooks. See make_frame for a case where
2919 it's not allowed. KEEP_MARGINS_P non-zero means that the current
2920 margins, fringes, and scroll-bar settings of the window are not
2921 reset from the buffer's local settings. */
2923 void
2924 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
2925 Lisp_Object window, buffer;
2926 int run_hooks_p, keep_margins_p;
2928 struct window *w = XWINDOW (window);
2929 struct buffer *b = XBUFFER (buffer);
2930 int count = SPECPDL_INDEX ();
2932 w->buffer = buffer;
2934 if (EQ (window, selected_window))
2935 b->last_selected_window = window;
2937 /* Update time stamps of buffer display. */
2938 if (INTEGERP (b->display_count))
2939 XSETINT (b->display_count, XINT (b->display_count) + 1);
2940 b->display_time = Fcurrent_time ();
2942 XSETFASTINT (w->window_end_pos, 0);
2943 XSETFASTINT (w->window_end_vpos, 0);
2944 bzero (&w->last_cursor, sizeof w->last_cursor);
2945 w->window_end_valid = Qnil;
2946 w->hscroll = w->min_hscroll = make_number (0);
2947 w->vscroll = 0;
2948 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
2949 set_marker_restricted (w->start,
2950 make_number (b->last_window_start),
2951 buffer);
2952 w->start_at_line_beg = Qnil;
2953 w->force_start = Qnil;
2954 XSETFASTINT (w->last_modified, 0);
2955 XSETFASTINT (w->last_overlay_modified, 0);
2956 windows_or_buffers_changed++;
2958 /* We must select BUFFER for running the window-scroll-functions.
2959 If WINDOW is selected, switch permanently.
2960 Otherwise, switch but go back to the ambient buffer afterward. */
2961 if (EQ (window, selected_window))
2962 Fset_buffer (buffer);
2963 /* We can't check ! NILP (Vwindow_scroll_functions) here
2964 because that might itself be a local variable. */
2965 else if (window_initialized)
2967 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2968 Fset_buffer (buffer);
2971 if (!keep_margins_p)
2973 /* Set left and right marginal area width etc. from buffer. */
2975 /* This may call adjust_window_margins three times, so
2976 temporarily disable window margins. */
2977 Lisp_Object save_left = w->left_margin_cols;
2978 Lisp_Object save_right = w->right_margin_cols;
2980 w->left_margin_cols = w->right_margin_cols = Qnil;
2982 Fset_window_fringes (window,
2983 b->left_fringe_width, b->right_fringe_width,
2984 b->fringes_outside_margins);
2986 Fset_window_scroll_bars (window,
2987 b->scroll_bar_width,
2988 b->vertical_scroll_bar_type, Qnil);
2990 w->left_margin_cols = save_left;
2991 w->right_margin_cols = save_right;
2993 Fset_window_margins (window,
2994 b->left_margin_cols, b->right_margin_cols);
2997 if (run_hooks_p)
2999 if (! NILP (Vwindow_scroll_functions))
3000 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3001 Fmarker_position (w->start));
3003 if (! NILP (Vwindow_configuration_change_hook)
3004 && ! NILP (Vrun_hooks))
3005 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3008 unbind_to (count, Qnil);
3012 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3013 doc: /* Make WINDOW display BUFFER as its contents.
3014 BUFFER can be a buffer or buffer name.
3015 Optional third arg KEEP_MARGINS non-nil means that WINDOW's current
3016 display margins, fringe widths, and scroll bar settings are maintained;
3017 the default is to reset these from BUFFER's local settings or the frame
3018 defaults. */)
3019 (window, buffer, keep_margins)
3020 register Lisp_Object window, buffer, keep_margins;
3022 register Lisp_Object tem;
3023 register struct window *w = decode_window (window);
3025 XSETWINDOW (window, w);
3026 buffer = Fget_buffer (buffer);
3027 CHECK_BUFFER (buffer);
3029 if (NILP (XBUFFER (buffer)->name))
3030 error ("Attempt to display deleted buffer");
3032 tem = w->buffer;
3033 if (NILP (tem))
3034 error ("Window is deleted");
3035 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3036 is first being set up. */
3038 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3039 error ("Window is dedicated to `%s'",
3040 SDATA (XBUFFER (tem)->name));
3042 unshow_buffer (w);
3045 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3046 return Qnil;
3049 /* Note that selected_window can be nil
3050 when this is called from Fset_window_configuration. */
3052 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3053 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3054 If WINDOW is not already selected, also make WINDOW's buffer current.
3055 Also make WINDOW the frame's selected window.
3056 Optional second arg NORECORD non-nil means
3057 do not put this buffer at the front of the list of recently selected ones.
3059 Note that the main editor command loop
3060 selects the buffer of the selected window before each command. */)
3061 (window, norecord)
3062 register Lisp_Object window, norecord;
3064 register struct window *w;
3065 register struct window *ow;
3066 struct frame *sf;
3068 CHECK_LIVE_WINDOW (window);
3070 w = XWINDOW (window);
3071 w->frozen_window_start_p = 0;
3073 XSETFASTINT (w->use_time, ++window_select_count);
3074 if (EQ (window, selected_window))
3075 return window;
3077 if (!NILP (selected_window))
3079 ow = XWINDOW (selected_window);
3080 if (! NILP (ow->buffer))
3081 set_marker_both (ow->pointm, ow->buffer,
3082 BUF_PT (XBUFFER (ow->buffer)),
3083 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3086 selected_window = window;
3087 sf = SELECTED_FRAME ();
3088 if (XFRAME (WINDOW_FRAME (w)) != sf)
3090 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3091 /* Use this rather than Fhandle_switch_frame
3092 so that FRAME_FOCUS_FRAME is moved appropriately as we
3093 move around in the state where a minibuffer in a separate
3094 frame is active. */
3095 Fselect_frame (WINDOW_FRAME (w), Qnil);
3097 else
3098 sf->selected_window = window;
3100 if (NILP (norecord))
3101 record_buffer (w->buffer);
3102 Fset_buffer (w->buffer);
3104 XBUFFER (w->buffer)->last_selected_window = window;
3106 /* Go to the point recorded in the window.
3107 This is important when the buffer is in more
3108 than one window. It also matters when
3109 redisplay_window has altered point after scrolling,
3110 because it makes the change only in the window. */
3112 register int new_point = marker_position (w->pointm);
3113 if (new_point < BEGV)
3114 SET_PT (BEGV);
3115 else if (new_point > ZV)
3116 SET_PT (ZV);
3117 else
3118 SET_PT (new_point);
3121 windows_or_buffers_changed++;
3122 return window;
3125 static Lisp_Object
3126 select_window_norecord (window)
3127 Lisp_Object window;
3129 return Fselect_window (window, Qt);
3132 /* Deiconify the frame containing the window WINDOW,
3133 unless it is the selected frame;
3134 then return WINDOW.
3136 The reason for the exception for the selected frame
3137 is that it seems better not to change the selected frames visibility
3138 merely because of displaying a different buffer in it.
3139 The deiconification is useful when a buffer gets shown in
3140 another frame that you were not using lately. */
3142 static Lisp_Object
3143 display_buffer_1 (window)
3144 Lisp_Object window;
3146 Lisp_Object frame = XWINDOW (window)->frame;
3147 FRAME_PTR f = XFRAME (frame);
3149 FRAME_SAMPLE_VISIBILITY (f);
3151 if (EQ (frame, selected_frame))
3152 ; /* Assume the selected frame is already visible enough. */
3153 else if (minibuf_level > 0
3154 && MINI_WINDOW_P (XWINDOW (selected_window))
3155 && WINDOW_LIVE_P (minibuf_selected_window)
3156 && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
3157 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3158 else
3160 if (FRAME_ICONIFIED_P (f))
3161 Fmake_frame_visible (frame);
3162 else if (FRAME_VISIBLE_P (f))
3163 Fraise_frame (frame);
3166 return window;
3169 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
3170 doc: /* Returns non-nil if a buffer named BUFFER-NAME would be created specially.
3171 The value is actually t if the frame should be called with default frame
3172 parameters, and a list of frame parameters if they were specified.
3173 See `special-display-buffer-names', and `special-display-regexps'. */)
3174 (buffer_name)
3175 Lisp_Object buffer_name;
3177 Lisp_Object tem;
3179 CHECK_STRING (buffer_name);
3181 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
3182 if (!NILP (tem))
3183 return Qt;
3185 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
3186 if (!NILP (tem))
3187 return XCDR (tem);
3189 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
3191 Lisp_Object car = XCAR (tem);
3192 if (STRINGP (car)
3193 && fast_string_match (car, buffer_name) >= 0)
3194 return Qt;
3195 else if (CONSP (car)
3196 && STRINGP (XCAR (car))
3197 && fast_string_match (XCAR (car), buffer_name) >= 0)
3198 return XCDR (car);
3200 return Qnil;
3203 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
3204 doc: /* Returns non-nil if a new buffer named BUFFER-NAME would use the same window.
3205 See `same-window-buffer-names' and `same-window-regexps'. */)
3206 (buffer_name)
3207 Lisp_Object buffer_name;
3209 Lisp_Object tem;
3211 CHECK_STRING (buffer_name);
3213 tem = Fmember (buffer_name, Vsame_window_buffer_names);
3214 if (!NILP (tem))
3215 return Qt;
3217 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
3218 if (!NILP (tem))
3219 return Qt;
3221 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3223 Lisp_Object car = XCAR (tem);
3224 if (STRINGP (car)
3225 && fast_string_match (car, buffer_name) >= 0)
3226 return Qt;
3227 else if (CONSP (car)
3228 && STRINGP (XCAR (car))
3229 && fast_string_match (XCAR (car), buffer_name) >= 0)
3230 return Qt;
3232 return Qnil;
3235 /* Use B so the default is (other-buffer). */
3236 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
3237 "BDisplay buffer: \nP",
3238 doc: /* Make BUFFER appear in some window but don't select it.
3239 BUFFER can be a buffer or a buffer name.
3240 If BUFFER is shown already in some window, just use that one,
3241 unless the window is the selected window and the optional second
3242 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3243 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3244 Returns the window displaying BUFFER.
3245 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3246 displaying BUFFER, then simply raise that frame.
3248 The variables `special-display-buffer-names', `special-display-regexps',
3249 `same-window-buffer-names', and `same-window-regexps' customize how certain
3250 buffer names are handled.
3252 If optional argument FRAME is `visible', search all visible frames.
3253 If FRAME is 0, search all visible and iconified frames.
3254 If FRAME is t, search all frames.
3255 If FRAME is a frame, search only that frame.
3256 If FRAME is nil, search only the selected frame
3257 (actually the last nonminibuffer frame),
3258 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3259 which means search visible and iconified frames.
3261 If `even-window-heights' is non-nil, window heights will be evened out
3262 if displaying the buffer causes two vertically adjacent windows to be
3263 displayed. */)
3264 (buffer, not_this_window, frame)
3265 register Lisp_Object buffer, not_this_window, frame;
3267 register Lisp_Object window, tem, swp;
3268 struct frame *f;
3270 swp = Qnil;
3271 buffer = Fget_buffer (buffer);
3272 CHECK_BUFFER (buffer);
3274 if (!NILP (Vdisplay_buffer_function))
3275 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3277 if (NILP (not_this_window)
3278 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3279 return display_buffer_1 (selected_window);
3281 /* See if the user has specified this buffer should appear
3282 in the selected window. */
3283 if (NILP (not_this_window))
3285 swp = Fsame_window_p (XBUFFER (buffer)->name);
3286 if (!NILP (swp) && !no_switch_window (selected_window))
3288 Fswitch_to_buffer (buffer, Qnil);
3289 return display_buffer_1 (selected_window);
3293 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3294 look for a window showing BUFFER on any visible or iconified frame.
3295 Otherwise search only the current frame. */
3296 if (! NILP (frame))
3297 tem = frame;
3298 else if (pop_up_frames
3299 || display_buffer_reuse_frames
3300 || last_nonminibuf_frame == 0)
3301 XSETFASTINT (tem, 0);
3302 else
3303 XSETFRAME (tem, last_nonminibuf_frame);
3305 window = Fget_buffer_window (buffer, tem);
3306 if (!NILP (window)
3307 && (NILP (not_this_window) || !EQ (window, selected_window)))
3308 return display_buffer_1 (window);
3310 /* Certain buffer names get special handling. */
3311 if (!NILP (Vspecial_display_function) && NILP (swp))
3313 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3314 if (EQ (tem, Qt))
3315 return call1 (Vspecial_display_function, buffer);
3316 if (CONSP (tem))
3317 return call2 (Vspecial_display_function, buffer, tem);
3320 /* If there are no frames open that have more than a minibuffer,
3321 we need to create a new frame. */
3322 if (pop_up_frames || last_nonminibuf_frame == 0)
3324 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3325 Fset_window_buffer (window, buffer, Qnil);
3326 return display_buffer_1 (window);
3329 f = SELECTED_FRAME ();
3330 if (pop_up_windows
3331 || FRAME_MINIBUF_ONLY_P (f)
3332 /* If the current frame is a special display frame,
3333 don't try to reuse its windows. */
3334 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3336 Lisp_Object frames;
3338 frames = Qnil;
3339 if (FRAME_MINIBUF_ONLY_P (f))
3340 XSETFRAME (frames, last_nonminibuf_frame);
3341 /* Don't try to create a window if we would get an error. */
3342 if (split_height_threshold < window_min_height << 1)
3343 split_height_threshold = window_min_height << 1;
3345 /* Note that both Fget_largest_window and Fget_lru_window
3346 ignore minibuffers and dedicated windows.
3347 This means they can return nil. */
3349 /* If the frame we would try to split cannot be split,
3350 try other frames. */
3351 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3353 /* Try visible frames first. */
3354 window = Fget_largest_window (Qvisible);
3355 /* If that didn't work, try iconified frames. */
3356 if (NILP (window))
3357 window = Fget_largest_window (make_number (0));
3358 if (NILP (window))
3359 window = Fget_largest_window (Qt);
3361 else
3362 window = Fget_largest_window (frames);
3364 /* If we got a tall enough full-width window that can be split,
3365 split it. */
3366 if (!NILP (window)
3367 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3368 && window_height (window) >= split_height_threshold
3369 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
3370 window = Fsplit_window (window, Qnil, Qnil);
3371 else
3373 Lisp_Object upper, lower, other;
3375 window = Fget_lru_window (frames);
3376 /* If the LRU window is selected, and big enough,
3377 and can be split, split it. */
3378 if (!NILP (window)
3379 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3380 && (EQ (window, selected_window)
3381 || EQ (XWINDOW (window)->parent, Qnil))
3382 && window_height (window) >= window_min_height << 1)
3383 window = Fsplit_window (window, Qnil, Qnil);
3384 /* If Fget_lru_window returned nil, try other approaches. */
3386 /* Try visible frames first. */
3387 if (NILP (window))
3388 window = Fget_buffer_window (buffer, Qvisible);
3389 if (NILP (window))
3390 window = Fget_largest_window (Qvisible);
3391 /* If that didn't work, try iconified frames. */
3392 if (NILP (window))
3393 window = Fget_buffer_window (buffer, make_number (0));
3394 if (NILP (window))
3395 window = Fget_largest_window (make_number (0));
3396 /* Try invisible frames. */
3397 if (NILP (window))
3398 window = Fget_buffer_window (buffer, Qt);
3399 if (NILP (window))
3400 window = Fget_largest_window (Qt);
3401 /* As a last resort, make a new frame. */
3402 if (NILP (window))
3403 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3404 /* If window appears above or below another,
3405 even out their heights. */
3406 other = upper = lower = Qnil;
3407 if (!NILP (XWINDOW (window)->prev))
3408 other = upper = XWINDOW (window)->prev, lower = window;
3409 if (!NILP (XWINDOW (window)->next))
3410 other = lower = XWINDOW (window)->next, upper = window;
3411 if (!NILP (other)
3412 && !NILP (Veven_window_heights)
3413 /* Check that OTHER and WINDOW are vertically arrayed. */
3414 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3415 && (XFASTINT (XWINDOW (other)->total_lines)
3416 > XFASTINT (XWINDOW (window)->total_lines)))
3418 int total = (XFASTINT (XWINDOW (other)->total_lines)
3419 + XFASTINT (XWINDOW (window)->total_lines));
3420 enlarge_window (upper,
3421 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
3422 0, 0);
3426 else
3427 window = Fget_lru_window (Qnil);
3429 Fset_window_buffer (window, buffer, Qnil);
3430 return display_buffer_1 (window);
3433 void
3434 temp_output_buffer_show (buf)
3435 register Lisp_Object buf;
3437 register struct buffer *old = current_buffer;
3438 register Lisp_Object window;
3439 register struct window *w;
3441 XBUFFER (buf)->directory = current_buffer->directory;
3443 Fset_buffer (buf);
3444 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3445 BEGV = BEG;
3446 ZV = Z;
3447 SET_PT (BEG);
3448 #if 0 /* rms: there should be no reason for this. */
3449 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3450 #endif
3451 set_buffer_internal (old);
3453 if (!EQ (Vtemp_buffer_show_function, Qnil))
3454 call1 (Vtemp_buffer_show_function, buf);
3455 else
3457 window = Fdisplay_buffer (buf, Qnil, Qnil);
3459 if (!EQ (XWINDOW (window)->frame, selected_frame))
3460 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3461 Vminibuf_scroll_window = window;
3462 w = XWINDOW (window);
3463 XSETFASTINT (w->hscroll, 0);
3464 XSETFASTINT (w->min_hscroll, 0);
3465 set_marker_restricted_both (w->start, buf, BEG, BEG);
3466 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3468 /* Run temp-buffer-show-hook, with the chosen window selected
3469 and its buffer current. */
3471 if (!NILP (Vrun_hooks)
3472 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3473 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3475 int count = SPECPDL_INDEX ();
3476 Lisp_Object prev_window, prev_buffer;
3477 prev_window = selected_window;
3478 XSETBUFFER (prev_buffer, old);
3480 /* Select the window that was chosen, for running the hook.
3481 Note: Both Fselect_window and select_window_norecord may
3482 set-buffer to the buffer displayed in the window,
3483 so we need to save the current buffer. --stef */
3484 record_unwind_protect (Fset_buffer, prev_buffer);
3485 record_unwind_protect (select_window_norecord, prev_window);
3486 Fselect_window (window, Qt);
3487 Fset_buffer (w->buffer);
3488 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3489 unbind_to (count, Qnil);
3494 static void
3495 make_dummy_parent (window)
3496 Lisp_Object window;
3498 Lisp_Object new;
3499 register struct window *o, *p;
3500 int i;
3502 o = XWINDOW (window);
3503 p = allocate_window ();
3504 for (i = 0; i < VECSIZE (struct window); ++i)
3505 ((struct Lisp_Vector *) p)->contents[i]
3506 = ((struct Lisp_Vector *)o)->contents[i];
3507 XSETWINDOW (new, p);
3509 XSETFASTINT (p->sequence_number, ++sequence_number);
3511 /* Put new into window structure in place of window */
3512 replace_window (window, new);
3514 o->next = Qnil;
3515 o->prev = Qnil;
3516 o->vchild = Qnil;
3517 o->hchild = Qnil;
3518 o->parent = new;
3520 p->start = Qnil;
3521 p->pointm = Qnil;
3522 p->buffer = Qnil;
3525 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3526 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3527 WINDOW defaults to selected one and SIZE to half its size.
3528 If optional third arg HORFLAG is non-nil, split side by side
3529 and put SIZE columns in the first of the pair. In that case,
3530 SIZE includes that window's scroll bar, or the divider column to its right. */)
3531 (window, size, horflag)
3532 Lisp_Object window, size, horflag;
3534 register Lisp_Object new;
3535 register struct window *o, *p;
3536 FRAME_PTR fo;
3537 register int size_int;
3539 if (NILP (window))
3540 window = selected_window;
3541 else
3542 CHECK_LIVE_WINDOW (window);
3544 o = XWINDOW (window);
3545 fo = XFRAME (WINDOW_FRAME (o));
3547 if (NILP (size))
3549 if (!NILP (horflag))
3550 /* Calculate the size of the left-hand window, by dividing
3551 the usable space in columns by two.
3552 We round up, since the left-hand window may include
3553 a dividing line, while the right-hand may not. */
3554 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
3555 else
3556 size_int = XFASTINT (o->total_lines) >> 1;
3558 else
3560 CHECK_NUMBER (size);
3561 size_int = XINT (size);
3564 if (MINI_WINDOW_P (o))
3565 error ("Attempt to split minibuffer window");
3566 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3567 error ("Attempt to split fixed-size window");
3569 check_min_window_sizes ();
3571 if (NILP (horflag))
3573 if (size_int < window_min_height)
3574 error ("Window height %d too small (after splitting)", size_int);
3575 if (size_int + window_min_height > XFASTINT (o->total_lines))
3576 error ("Window height %d too small (after splitting)",
3577 XFASTINT (o->total_lines) - size_int);
3578 if (NILP (o->parent)
3579 || NILP (XWINDOW (o->parent)->vchild))
3581 make_dummy_parent (window);
3582 new = o->parent;
3583 XWINDOW (new)->vchild = window;
3586 else
3588 if (size_int < window_min_width)
3589 error ("Window width %d too small (after splitting)", size_int);
3591 if (size_int + window_min_width > XFASTINT (o->total_cols))
3592 error ("Window width %d too small (after splitting)",
3593 XFASTINT (o->total_cols) - size_int);
3594 if (NILP (o->parent)
3595 || NILP (XWINDOW (o->parent)->hchild))
3597 make_dummy_parent (window);
3598 new = o->parent;
3599 XWINDOW (new)->hchild = window;
3603 /* Now we know that window's parent is a vertical combination
3604 if we are dividing vertically, or a horizontal combination
3605 if we are making side-by-side windows */
3607 windows_or_buffers_changed++;
3608 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3609 new = make_window ();
3610 p = XWINDOW (new);
3612 p->frame = o->frame;
3613 p->next = o->next;
3614 if (!NILP (p->next))
3615 XWINDOW (p->next)->prev = new;
3616 p->prev = window;
3617 o->next = new;
3618 p->parent = o->parent;
3619 p->buffer = Qt;
3620 p->window_end_valid = Qnil;
3621 bzero (&p->last_cursor, sizeof p->last_cursor);
3623 /* Duplicate special geometry settings. */
3625 p->left_margin_cols = o->left_margin_cols;
3626 p->right_margin_cols = o->right_margin_cols;
3627 p->left_fringe_width = o->left_fringe_width;
3628 p->right_fringe_width = o->right_fringe_width;
3629 p->fringes_outside_margins = o->fringes_outside_margins;
3630 p->scroll_bar_width = o->scroll_bar_width;
3631 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
3633 /* Apportion the available frame space among the two new windows */
3635 if (!NILP (horflag))
3637 p->total_lines = o->total_lines;
3638 p->top_line = o->top_line;
3639 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
3640 XSETFASTINT (o->total_cols, size_int);
3641 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
3642 adjust_window_margins (p);
3643 adjust_window_margins (o);
3645 else
3647 p->left_col = o->left_col;
3648 p->total_cols = o->total_cols;
3649 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
3650 XSETFASTINT (o->total_lines, size_int);
3651 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
3654 /* Adjust glyph matrices. */
3655 adjust_glyphs (fo);
3657 Fset_window_buffer (new, o->buffer, Qt);
3658 return new;
3661 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 3, "p",
3662 doc: /* Make current window ARG lines bigger.
3663 From program, optional second arg non-nil means grow sideways ARG columns.
3664 Interactively, if an argument is not given, make the window one line bigger.
3666 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3667 of the siblings above or to the left of the selected window. Only
3668 siblings to the right or below are changed. */)
3669 (arg, side, preserve_before)
3670 register Lisp_Object arg, side, preserve_before;
3672 CHECK_NUMBER (arg);
3673 enlarge_window (selected_window, XINT (arg), !NILP (side),
3674 !NILP (preserve_before));
3676 if (! NILP (Vwindow_configuration_change_hook))
3677 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3679 return Qnil;
3682 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 3, "p",
3683 doc: /* Make current window ARG lines smaller.
3684 From program, optional second arg non-nil means shrink sideways arg columns.
3685 Interactively, if an argument is not given, make the window one line smaller.
3687 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3688 of the siblings above or to the left of the selected window. Only
3689 siblings to the right or below are changed. */)
3690 (arg, side, preserve_before)
3691 register Lisp_Object arg, side, preserve_before;
3693 CHECK_NUMBER (arg);
3694 enlarge_window (selected_window, -XINT (arg), !NILP (side),
3695 !NILP (preserve_before));
3697 if (! NILP (Vwindow_configuration_change_hook))
3698 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3700 return Qnil;
3704 window_height (window)
3705 Lisp_Object window;
3707 register struct window *p = XWINDOW (window);
3708 return WINDOW_TOTAL_LINES (p);
3712 window_width (window)
3713 Lisp_Object window;
3715 register struct window *p = XWINDOW (window);
3716 return WINDOW_TOTAL_COLS (p);
3720 #define CURBEG(w) \
3721 *(widthflag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
3723 #define CURSIZE(w) \
3724 *(widthflag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
3727 /* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means
3728 increase its width. Siblings of the selected window are resized to
3729 fulfill the size request. If they become too small in the process,
3730 they will be deleted.
3732 If PRESERVE_BEFORE is nonzero, that means don't alter
3733 the siblings to the left or above WINDOW. */
3735 static void
3736 enlarge_window (window, delta, widthflag, preserve_before)
3737 Lisp_Object window;
3738 int delta, widthflag, preserve_before;
3740 Lisp_Object parent, next, prev;
3741 struct window *p;
3742 Lisp_Object *sizep;
3743 int maximum;
3744 int (*sizefun) P_ ((Lisp_Object))
3745 = widthflag ? window_width : window_height;
3746 void (*setsizefun) P_ ((Lisp_Object, int, int))
3747 = (widthflag ? set_window_width : set_window_height);
3749 /* Check values of window_min_width and window_min_height for
3750 validity. */
3751 check_min_window_sizes ();
3753 /* Give up if this window cannot be resized. */
3754 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3755 error ("Window is not resizable");
3757 /* Find the parent of the selected window. */
3758 while (1)
3760 p = XWINDOW (window);
3761 parent = p->parent;
3763 if (NILP (parent))
3765 if (widthflag)
3766 error ("No other window to side of this one");
3767 break;
3770 if (widthflag
3771 ? !NILP (XWINDOW (parent)->hchild)
3772 : !NILP (XWINDOW (parent)->vchild))
3773 break;
3775 window = parent;
3778 sizep = &CURSIZE (window);
3781 register int maxdelta;
3783 /* Compute the maximum size increment this window can have. */
3785 if (preserve_before)
3787 if (!NILP (parent))
3789 maxdelta = (*sizefun) (parent) - XINT (*sizep);
3790 /* Subtract size of siblings before, since we can't take that. */
3791 maxdelta -= XINT (CURBEG (window)) - XINT (CURBEG (parent));
3793 else
3794 maxdelta = (!NILP (p->next) ? ((*sizefun) (p->next)
3795 - window_min_size (XWINDOW (p->next),
3796 widthflag, 0, 0))
3797 : (delta = 0));
3799 else
3800 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
3801 /* This is a main window followed by a minibuffer. */
3802 : !NILP (p->next) ? ((*sizefun) (p->next)
3803 - window_min_size (XWINDOW (p->next),
3804 widthflag, 0, 0))
3805 /* This is a minibuffer following a main window. */
3806 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3807 - window_min_size (XWINDOW (p->prev),
3808 widthflag, 0, 0))
3809 /* This is a frame with only one window, a minibuffer-only
3810 or a minibufferless frame. */
3811 : (delta = 0));
3813 if (delta > maxdelta)
3814 /* This case traps trying to make the minibuffer
3815 the full frame, or make the only window aside from the
3816 minibuffer the full frame. */
3817 delta = maxdelta;
3820 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3822 delete_window (window);
3823 return;
3826 if (delta == 0)
3827 return;
3829 /* Find the total we can get from other siblings without deleting them. */
3830 maximum = 0;
3831 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3832 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3833 widthflag, 0, 0);
3834 if (! preserve_before)
3835 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3836 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3837 widthflag, 0, 0);
3839 /* If we can get it all from them without deleting them, do so. */
3840 if (delta <= maximum)
3842 Lisp_Object first_unaffected;
3843 Lisp_Object first_affected;
3844 int fixed_p;
3846 next = p->next;
3847 prev = p->prev;
3848 first_affected = window;
3849 /* Look at one sibling at a time,
3850 moving away from this window in both directions alternately,
3851 and take as much as we can get without deleting that sibling. */
3852 while (delta != 0
3853 && (!NILP (next) || (!preserve_before && !NILP (prev))))
3855 if (! NILP (next))
3857 int this_one = ((*sizefun) (next)
3858 - window_min_size (XWINDOW (next),
3859 widthflag, 0, &fixed_p));
3860 if (!fixed_p)
3862 if (this_one > delta)
3863 this_one = delta;
3865 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3866 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3868 delta -= this_one;
3871 next = XWINDOW (next)->next;
3874 if (delta == 0)
3875 break;
3877 if (!preserve_before && ! NILP (prev))
3879 int this_one = ((*sizefun) (prev)
3880 - window_min_size (XWINDOW (prev),
3881 widthflag, 0, &fixed_p));
3882 if (!fixed_p)
3884 if (this_one > delta)
3885 this_one = delta;
3887 first_affected = prev;
3889 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3890 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3892 delta -= this_one;
3895 prev = XWINDOW (prev)->prev;
3899 xassert (delta == 0);
3901 /* Now recalculate the edge positions of all the windows affected,
3902 based on the new sizes. */
3903 first_unaffected = next;
3904 prev = first_affected;
3905 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3906 prev = next, next = XWINDOW (next)->next)
3908 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
3909 /* This does not change size of NEXT,
3910 but it propagates the new top edge to its children */
3911 (*setsizefun) (next, (*sizefun) (next), 0);
3914 else
3916 register int delta1;
3917 register int opht = (*sizefun) (parent);
3919 if (opht <= XINT (*sizep) + delta)
3921 /* If trying to grow this window to or beyond size of the parent,
3922 just delete all the sibling windows. */
3923 Lisp_Object start, tem, next;
3925 start = XWINDOW (parent)->vchild;
3926 if (NILP (start))
3927 start = XWINDOW (parent)->hchild;
3929 /* Delete any siblings that come after WINDOW. */
3930 tem = XWINDOW (window)->next;
3931 while (! NILP (tem))
3933 next = XWINDOW (tem)->next;
3934 delete_window (tem);
3935 tem = next;
3938 /* Delete any siblings that come after WINDOW.
3939 Note that if START is not WINDOW, then WINDOW still
3940 Fhas siblings, so WINDOW has not yet replaced its parent. */
3941 tem = start;
3942 while (! EQ (tem, window))
3944 next = XWINDOW (tem)->next;
3945 delete_window (tem);
3946 tem = next;
3949 else
3951 /* Otherwise, make delta1 just right so that if we add
3952 delta1 lines to this window and to the parent, and then
3953 shrink the parent back to its original size, the new
3954 proportional size of this window will increase by delta.
3956 The function size_window will compute the new height h'
3957 of the window from delta1 as:
3959 e = delta1/n
3960 x = delta1 - delta1/n * n for the 1st resizable child
3961 h' = h + e + x
3963 where n is the number of children that can be resized.
3964 We can ignore x by choosing a delta1 that is a multiple of
3965 n. We want the height of this window to come out as
3967 h' = h + delta
3969 So, delta1 must be
3971 h + e = h + delta
3972 delta1/n = delta
3973 delta1 = n * delta.
3975 The number of children n equals the number of resizable
3976 children of this window + 1 because we know window itself
3977 is resizable (otherwise we would have signalled an error. */
3979 struct window *w = XWINDOW (window);
3980 Lisp_Object s;
3981 int n = 1;
3983 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3984 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3985 ++n;
3986 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3987 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3988 ++n;
3990 delta1 = n * delta;
3992 /* Add delta1 lines or columns to this window, and to the parent,
3993 keeping things consistent while not affecting siblings. */
3994 XSETINT (CURSIZE (parent), opht + delta1);
3995 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
3997 /* Squeeze out delta1 lines or columns from our parent,
3998 shriking this window and siblings proportionately.
3999 This brings parent back to correct size.
4000 Delta1 was calculated so this makes this window the desired size,
4001 taking it all out of the siblings. */
4002 (*setsizefun) (parent, opht, 0);
4007 XSETFASTINT (p->last_modified, 0);
4008 XSETFASTINT (p->last_overlay_modified, 0);
4010 /* Adjust glyph matrices. */
4011 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4014 #undef CURBEG
4015 #undef CURSIZE
4019 /***********************************************************************
4020 Resizing Mini-Windows
4021 ***********************************************************************/
4023 static void shrink_window_lowest_first P_ ((struct window *, int));
4025 enum save_restore_action
4027 CHECK_ORIG_SIZES,
4028 SAVE_ORIG_SIZES,
4029 RESTORE_ORIG_SIZES
4032 static int save_restore_orig_size P_ ((struct window *,
4033 enum save_restore_action));
4035 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4036 from lowest windows first. */
4038 static void
4039 shrink_window_lowest_first (w, height)
4040 struct window *w;
4041 int height;
4043 struct window *c;
4044 Lisp_Object child;
4045 int old_height;
4047 xassert (!MINI_WINDOW_P (w));
4049 /* Set redisplay hints. */
4050 XSETFASTINT (w->last_modified, 0);
4051 XSETFASTINT (w->last_overlay_modified, 0);
4052 windows_or_buffers_changed++;
4053 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4055 old_height = XFASTINT (w->total_lines);
4056 XSETFASTINT (w->total_lines, height);
4058 if (!NILP (w->hchild))
4060 for (child = w->hchild; !NILP (child); child = c->next)
4062 c = XWINDOW (child);
4063 c->top_line = w->top_line;
4064 shrink_window_lowest_first (c, height);
4067 else if (!NILP (w->vchild))
4069 Lisp_Object last_child;
4070 int delta = old_height - height;
4071 int last_top;
4073 last_child = Qnil;
4075 /* Find the last child. We are taking space from lowest windows
4076 first, so we iterate over children from the last child
4077 backwards. */
4078 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
4079 last_child = child;
4081 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
4082 for (child = last_child; delta && !NILP (child); child = c->prev)
4084 int this_one;
4086 c = XWINDOW (child);
4087 this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
4089 if (this_one > delta)
4090 this_one = delta;
4092 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4093 delta -= this_one;
4096 /* Compute new positions. */
4097 last_top = XINT (w->top_line);
4098 for (child = w->vchild; !NILP (child); child = c->next)
4100 c = XWINDOW (child);
4101 c->top_line = make_number (last_top);
4102 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4103 last_top += XFASTINT (c->total_lines);
4109 /* Save, restore, or check positions and sizes in the window tree
4110 rooted at W. ACTION says what to do.
4112 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4113 orig_total_lines members are valid for all windows in the window
4114 tree. Value is non-zero if they are valid.
4116 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4117 orig_top_line and orig_total_lines for all windows in the tree.
4119 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4120 stored in orig_top_line and orig_total_lines for all windows. */
4122 static int
4123 save_restore_orig_size (w, action)
4124 struct window *w;
4125 enum save_restore_action action;
4127 int success_p = 1;
4129 while (w)
4131 if (!NILP (w->hchild))
4133 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4134 success_p = 0;
4136 else if (!NILP (w->vchild))
4138 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4139 success_p = 0;
4142 switch (action)
4144 case CHECK_ORIG_SIZES:
4145 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4146 return 0;
4147 break;
4149 case SAVE_ORIG_SIZES:
4150 w->orig_top_line = w->top_line;
4151 w->orig_total_lines = w->total_lines;
4152 XSETFASTINT (w->last_modified, 0);
4153 XSETFASTINT (w->last_overlay_modified, 0);
4154 break;
4156 case RESTORE_ORIG_SIZES:
4157 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4158 w->top_line = w->orig_top_line;
4159 w->total_lines = w->orig_total_lines;
4160 w->orig_total_lines = w->orig_top_line = Qnil;
4161 XSETFASTINT (w->last_modified, 0);
4162 XSETFASTINT (w->last_overlay_modified, 0);
4163 break;
4165 default:
4166 abort ();
4169 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4172 return success_p;
4176 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4177 without deleting other windows. */
4179 void
4180 grow_mini_window (w, delta)
4181 struct window *w;
4182 int delta;
4184 struct frame *f = XFRAME (w->frame);
4185 struct window *root;
4187 xassert (MINI_WINDOW_P (w));
4188 xassert (delta >= 0);
4190 /* Check values of window_min_width and window_min_height for
4191 validity. */
4192 check_min_window_sizes ();
4194 /* Compute how much we can enlarge the mini-window without deleting
4195 other windows. */
4196 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4197 if (delta)
4199 int min_height = window_min_size (root, 0, 0, 0);
4200 if (XFASTINT (root->total_lines) - delta < min_height)
4201 /* Note that the root window may already be smaller than
4202 min_height. */
4203 delta = max (0, XFASTINT (root->total_lines) - min_height);
4206 if (delta)
4208 /* Save original window sizes and positions, if not already done. */
4209 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4210 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4212 /* Shrink other windows. */
4213 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4215 /* Grow the mini-window. */
4216 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4217 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4218 XSETFASTINT (w->last_modified, 0);
4219 XSETFASTINT (w->last_overlay_modified, 0);
4221 adjust_glyphs (f);
4226 /* Shrink mini-window W. If there is recorded info about window sizes
4227 before a call to grow_mini_window, restore recorded window sizes.
4228 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4229 line. */
4231 void
4232 shrink_mini_window (w)
4233 struct window *w;
4235 struct frame *f = XFRAME (w->frame);
4236 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4238 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4240 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4241 adjust_glyphs (f);
4242 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4243 windows_or_buffers_changed = 1;
4245 else if (XFASTINT (w->total_lines) > 1)
4247 /* Distribute the additional lines of the mini-window
4248 among the other windows. */
4249 Lisp_Object window;
4250 XSETWINDOW (window, w);
4251 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0, 0);
4257 /* Mark window cursors off for all windows in the window tree rooted
4258 at W by setting their phys_cursor_on_p flag to zero. Called from
4259 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4260 the frame are cleared. */
4262 void
4263 mark_window_cursors_off (w)
4264 struct window *w;
4266 while (w)
4268 if (!NILP (w->hchild))
4269 mark_window_cursors_off (XWINDOW (w->hchild));
4270 else if (!NILP (w->vchild))
4271 mark_window_cursors_off (XWINDOW (w->vchild));
4272 else
4273 w->phys_cursor_on_p = 0;
4275 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4280 /* Return number of lines of text (not counting mode lines) in W. */
4283 window_internal_height (w)
4284 struct window *w;
4286 int ht = XFASTINT (w->total_lines);
4288 if (!MINI_WINDOW_P (w))
4290 if (!NILP (w->parent)
4291 || !NILP (w->vchild)
4292 || !NILP (w->hchild)
4293 || !NILP (w->next)
4294 || !NILP (w->prev)
4295 || WINDOW_WANTS_MODELINE_P (w))
4296 --ht;
4298 if (WINDOW_WANTS_HEADER_LINE_P (w))
4299 --ht;
4302 return ht;
4306 /* Return the number of columns in W.
4307 Don't count columns occupied by scroll bars or the vertical bar
4308 separating W from the sibling to its right. */
4311 window_box_text_cols (w)
4312 struct window *w;
4314 struct frame *f = XFRAME (WINDOW_FRAME (w));
4315 int width = XINT (w->total_cols);
4317 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4318 /* Scroll bars occupy a few columns. */
4319 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4320 else if (!FRAME_WINDOW_P (f)
4321 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4322 /* The column of `|' characters separating side-by-side windows
4323 occupies one column only. */
4324 width -= 1;
4326 if (FRAME_WINDOW_P (f))
4327 /* On window-systems, fringes and display margins cannot be
4328 used for normal text. */
4329 width -= (WINDOW_FRINGE_COLS (w)
4330 + WINDOW_LEFT_MARGIN_COLS (w)
4331 + WINDOW_RIGHT_MARGIN_COLS (w));
4333 return width;
4337 /************************************************************************
4338 Window Scrolling
4339 ***********************************************************************/
4341 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4342 N screen-fulls, which is defined as the height of the window minus
4343 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4344 instead. Negative values of N mean scroll down. NOERROR non-zero
4345 means don't signal an error if we try to move over BEGV or ZV,
4346 respectively. */
4348 static void
4349 window_scroll (window, n, whole, noerror)
4350 Lisp_Object window;
4351 int n;
4352 int whole;
4353 int noerror;
4355 immediate_quit = 1;
4357 /* If we must, use the pixel-based version which is much slower than
4358 the line-based one but can handle varying line heights. */
4359 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4360 window_scroll_pixel_based (window, n, whole, noerror);
4361 else
4362 window_scroll_line_based (window, n, whole, noerror);
4364 immediate_quit = 0;
4368 /* Implementation of window_scroll that works based on pixel line
4369 heights. See the comment of window_scroll for parameter
4370 descriptions. */
4372 static void
4373 window_scroll_pixel_based (window, n, whole, noerror)
4374 Lisp_Object window;
4375 int n;
4376 int whole;
4377 int noerror;
4379 struct it it;
4380 struct window *w = XWINDOW (window);
4381 struct text_pos start;
4382 Lisp_Object tem;
4383 int this_scroll_margin;
4384 int preserve_y;
4385 /* True if we fiddled the window vscroll field without really scrolling. */
4386 int vscrolled = 0;
4388 SET_TEXT_POS_FROM_MARKER (start, w->start);
4390 /* If PT is not visible in WINDOW, move back one half of
4391 the screen. Allow PT to be partially visible, otherwise
4392 something like (scroll-down 1) with PT in the line before
4393 the partially visible one would recenter. */
4394 tem = Fpos_visible_in_window_p (make_number (PT), window, Qt);
4395 if (NILP (tem))
4397 /* Move backward half the height of the window. Performance note:
4398 vmotion used here is about 10% faster, but would give wrong
4399 results for variable height lines. */
4400 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4401 it.current_y = it.last_visible_y;
4402 move_it_vertically (&it, - window_box_height (w) / 2);
4404 /* The function move_iterator_vertically may move over more than
4405 the specified y-distance. If it->w is small, e.g. a
4406 mini-buffer window, we may end up in front of the window's
4407 display area. This is the case when Start displaying at the
4408 start of the line containing PT in this case. */
4409 if (it.current_y <= 0)
4411 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4412 move_it_vertically (&it, 0);
4413 it.current_y = 0;
4416 start = it.current.pos;
4419 /* If scroll_preserve_screen_position is non-zero, we try to set
4420 point in the same window line as it is now, so get that line. */
4421 if (!NILP (Vscroll_preserve_screen_position))
4423 start_display (&it, w, start);
4424 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4425 preserve_y = it.current_y;
4427 else
4428 preserve_y = -1;
4430 /* Move iterator it from start the specified distance forward or
4431 backward. The result is the new window start. */
4432 start_display (&it, w, start);
4433 if (whole)
4435 int screen_full = (window_box_height (w)
4436 - next_screen_context_lines * FRAME_LINE_HEIGHT (it.f));
4437 int dy = n * screen_full;
4439 /* Note that move_it_vertically always moves the iterator to the
4440 start of a line. So, if the last line doesn't have a newline,
4441 we would end up at the start of the line ending at ZV. */
4442 if (dy <= 0)
4443 move_it_vertically_backward (&it, -dy);
4444 else if (dy > 0)
4445 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4446 MOVE_TO_POS | MOVE_TO_Y);
4448 else
4449 move_it_by_lines (&it, n, 1);
4451 /* We failed if we find ZV is already on the screen (scrolling up,
4452 means there's nothing past the end), or if we can't start any
4453 earlier (scrolling down, means there's nothing past the top). */
4454 if ((n > 0 && IT_CHARPOS (it) == ZV)
4455 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4457 if (IT_CHARPOS (it) == ZV)
4459 if (it.current_y < it.last_visible_y
4460 && (it.current_y + it.max_ascent + it.max_descent
4461 >= it.last_visible_y))
4463 /* The last line was only partially visible, make it fully
4464 visible. */
4465 w->vscroll = (it.last_visible_y
4466 - it.current_y + it.max_ascent + it.max_descent);
4467 adjust_glyphs (it.f);
4469 else if (noerror)
4470 return;
4471 else
4472 Fsignal (Qend_of_buffer, Qnil);
4474 else
4476 if (w->vscroll != 0)
4477 /* The first line was only partially visible, make it fully
4478 visible. */
4479 w->vscroll = 0;
4480 else if (noerror)
4481 return;
4482 else
4483 Fsignal (Qbeginning_of_buffer, Qnil);
4486 /* If control gets here, then we vscrolled. */
4488 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4490 /* Don't try to change the window start below. */
4491 vscrolled = 1;
4494 if (! vscrolled)
4496 int pos = IT_CHARPOS (it);
4497 int bytepos;
4499 /* If in the middle of a multi-glyph character move forward to
4500 the next character. */
4501 if (in_display_vector_p (&it))
4503 ++pos;
4504 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4507 /* Set the window start, and set up the window for redisplay. */
4508 set_marker_restricted (w->start, make_number (pos),
4509 w->buffer);
4510 bytepos = XMARKER (w->start)->bytepos;
4511 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
4512 ? Qt : Qnil);
4513 w->update_mode_line = Qt;
4514 XSETFASTINT (w->last_modified, 0);
4515 XSETFASTINT (w->last_overlay_modified, 0);
4516 /* Set force_start so that redisplay_window will run the
4517 window-scroll-functions. */
4518 w->force_start = Qt;
4521 it.current_y = it.vpos = 0;
4523 /* Preserve the screen position if we must. */
4524 if (preserve_y >= 0)
4526 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
4527 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4529 else
4531 /* Move PT out of scroll margins. */
4532 this_scroll_margin = max (0, scroll_margin);
4533 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4534 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4536 if (n > 0)
4538 /* We moved the window start towards ZV, so PT may be now
4539 in the scroll margin at the top. */
4540 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4541 while (it.current_y < this_scroll_margin)
4543 int prev = it.current_y;
4544 move_it_by_lines (&it, 1, 1);
4545 if (prev == it.current_y)
4546 break;
4548 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4550 else if (n < 0)
4552 int charpos, bytepos;
4554 /* We moved the window start towards BEGV, so PT may be now
4555 in the scroll margin at the bottom. */
4556 move_it_to (&it, PT, -1,
4557 it.last_visible_y - this_scroll_margin - 1, -1,
4558 MOVE_TO_POS | MOVE_TO_Y);
4560 /* Save our position, in case it's correct. */
4561 charpos = IT_CHARPOS (it);
4562 bytepos = IT_BYTEPOS (it);
4564 /* See if point is on a partially visible line at the end. */
4565 move_it_by_lines (&it, 1, 1);
4566 if (it.current_y > it.last_visible_y)
4567 /* The last line was only partially visible, so back up two
4568 lines to make sure we're on a fully visible line. */
4570 move_it_by_lines (&it, -2, 0);
4571 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4573 else
4574 /* No, the position we saved is OK, so use it. */
4575 SET_PT_BOTH (charpos, bytepos);
4581 /* Implementation of window_scroll that works based on screen lines.
4582 See the comment of window_scroll for parameter descriptions. */
4584 static void
4585 window_scroll_line_based (window, n, whole, noerror)
4586 Lisp_Object window;
4587 int n;
4588 int whole;
4589 int noerror;
4591 register struct window *w = XWINDOW (window);
4592 register int opoint = PT, opoint_byte = PT_BYTE;
4593 register int pos, pos_byte;
4594 register int ht = window_internal_height (w);
4595 register Lisp_Object tem;
4596 int lose;
4597 Lisp_Object bolp;
4598 int startpos;
4599 struct position posit;
4600 int original_vpos;
4602 /* If scrolling screen-fulls, compute the number of lines to
4603 scroll from the window's height. */
4604 if (whole)
4605 n *= max (1, ht - next_screen_context_lines);
4607 startpos = marker_position (w->start);
4609 posit = *compute_motion (startpos, 0, 0, 0,
4610 PT, ht, 0,
4611 window_box_text_cols (w), XINT (w->hscroll),
4612 0, w);
4613 original_vpos = posit.vpos;
4615 XSETFASTINT (tem, PT);
4616 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4618 if (NILP (tem))
4620 Fvertical_motion (make_number (- (ht / 2)), window);
4621 startpos = PT;
4624 SET_PT (startpos);
4625 lose = n < 0 && PT == BEGV;
4626 Fvertical_motion (make_number (n), window);
4627 pos = PT;
4628 pos_byte = PT_BYTE;
4629 bolp = Fbolp ();
4630 SET_PT_BOTH (opoint, opoint_byte);
4632 if (lose)
4634 if (noerror)
4635 return;
4636 else
4637 Fsignal (Qbeginning_of_buffer, Qnil);
4640 if (pos < ZV)
4642 int this_scroll_margin = scroll_margin;
4644 /* Don't use a scroll margin that is negative or too large. */
4645 if (this_scroll_margin < 0)
4646 this_scroll_margin = 0;
4648 if (XINT (w->total_lines) < 4 * scroll_margin)
4649 this_scroll_margin = XINT (w->total_lines) / 4;
4651 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4652 w->start_at_line_beg = bolp;
4653 w->update_mode_line = Qt;
4654 XSETFASTINT (w->last_modified, 0);
4655 XSETFASTINT (w->last_overlay_modified, 0);
4656 /* Set force_start so that redisplay_window will run
4657 the window-scroll-functions. */
4658 w->force_start = Qt;
4660 if (whole && !NILP (Vscroll_preserve_screen_position))
4662 SET_PT_BOTH (pos, pos_byte);
4663 Fvertical_motion (make_number (original_vpos), window);
4665 /* If we scrolled forward, put point enough lines down
4666 that it is outside the scroll margin. */
4667 else if (n > 0)
4669 int top_margin;
4671 if (this_scroll_margin > 0)
4673 SET_PT_BOTH (pos, pos_byte);
4674 Fvertical_motion (make_number (this_scroll_margin), window);
4675 top_margin = PT;
4677 else
4678 top_margin = pos;
4680 if (top_margin <= opoint)
4681 SET_PT_BOTH (opoint, opoint_byte);
4682 else if (!NILP (Vscroll_preserve_screen_position))
4684 SET_PT_BOTH (pos, pos_byte);
4685 Fvertical_motion (make_number (original_vpos), window);
4687 else
4688 SET_PT (top_margin);
4690 else if (n < 0)
4692 int bottom_margin;
4694 /* If we scrolled backward, put point near the end of the window
4695 but not within the scroll margin. */
4696 SET_PT_BOTH (pos, pos_byte);
4697 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4698 if (XFASTINT (tem) == ht - this_scroll_margin)
4699 bottom_margin = PT;
4700 else
4701 bottom_margin = PT + 1;
4703 if (bottom_margin > opoint)
4704 SET_PT_BOTH (opoint, opoint_byte);
4705 else
4707 if (!NILP (Vscroll_preserve_screen_position))
4709 SET_PT_BOTH (pos, pos_byte);
4710 Fvertical_motion (make_number (original_vpos), window);
4712 else
4713 Fvertical_motion (make_number (-1), window);
4717 else
4719 if (noerror)
4720 return;
4721 else
4722 Fsignal (Qend_of_buffer, Qnil);
4727 /* Scroll selected_window up or down. If N is nil, scroll a
4728 screen-full which is defined as the height of the window minus
4729 next_screen_context_lines. If N is the symbol `-', scroll.
4730 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4731 up. This is the guts of Fscroll_up and Fscroll_down. */
4733 static void
4734 scroll_command (n, direction)
4735 Lisp_Object n;
4736 int direction;
4738 int count = SPECPDL_INDEX ();
4740 xassert (abs (direction) == 1);
4742 /* If selected window's buffer isn't current, make it current for
4743 the moment. But don't screw up if window_scroll gets an error. */
4744 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4746 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4747 Fset_buffer (XWINDOW (selected_window)->buffer);
4749 /* Make redisplay consider other windows than just selected_window. */
4750 ++windows_or_buffers_changed;
4753 if (NILP (n))
4754 window_scroll (selected_window, direction, 1, 0);
4755 else if (EQ (n, Qminus))
4756 window_scroll (selected_window, -direction, 1, 0);
4757 else
4759 n = Fprefix_numeric_value (n);
4760 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4763 unbind_to (count, Qnil);
4766 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
4767 doc: /* Scroll text of current window upward ARG lines; or near full screen if no ARG.
4768 A near full screen is `next-screen-context-lines' less than a full screen.
4769 Negative ARG means scroll downward.
4770 If ARG is the atom `-', scroll downward by nearly full screen.
4771 When calling from a program, supply as argument a number, nil, or `-'. */)
4772 (arg)
4773 Lisp_Object arg;
4775 scroll_command (arg, 1);
4776 return Qnil;
4779 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
4780 doc: /* Scroll text of current window down ARG lines; or near full screen if no ARG.
4781 A near full screen is `next-screen-context-lines' less than a full screen.
4782 Negative ARG means scroll upward.
4783 If ARG is the atom `-', scroll upward by nearly full screen.
4784 When calling from a program, supply as argument a number, nil, or `-'. */)
4785 (arg)
4786 Lisp_Object arg;
4788 scroll_command (arg, -1);
4789 return Qnil;
4792 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4793 doc: /* Return the other window for \"other window scroll\" commands.
4794 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4795 specifies the window.
4796 If `other-window-scroll-buffer' is non-nil, a window
4797 showing that buffer is used. */)
4800 Lisp_Object window;
4802 if (MINI_WINDOW_P (XWINDOW (selected_window))
4803 && !NILP (Vminibuf_scroll_window))
4804 window = Vminibuf_scroll_window;
4805 /* If buffer is specified, scroll that buffer. */
4806 else if (!NILP (Vother_window_scroll_buffer))
4808 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4809 if (NILP (window))
4810 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4812 else
4814 /* Nothing specified; look for a neighboring window on the same
4815 frame. */
4816 window = Fnext_window (selected_window, Qnil, Qnil);
4818 if (EQ (window, selected_window))
4819 /* That didn't get us anywhere; look for a window on another
4820 visible frame. */
4822 window = Fnext_window (window, Qnil, Qt);
4823 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4824 && ! EQ (window, selected_window));
4827 CHECK_LIVE_WINDOW (window);
4829 if (EQ (window, selected_window))
4830 error ("There is no other window");
4832 return window;
4835 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4836 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4837 A near full screen is `next-screen-context-lines' less than a full screen.
4838 The next window is the one below the current one; or the one at the top
4839 if the current one is at the bottom. Negative ARG means scroll downward.
4840 If ARG is the atom `-', scroll downward by nearly full screen.
4841 When calling from a program, supply as argument a number, nil, or `-'.
4843 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4844 specifies the window to scroll.
4845 If `other-window-scroll-buffer' is non-nil, scroll the window
4846 showing that buffer, popping the buffer up if necessary. */)
4847 (arg)
4848 Lisp_Object arg;
4850 Lisp_Object window;
4851 struct window *w;
4852 int count = SPECPDL_INDEX ();
4854 window = Fother_window_for_scrolling ();
4855 w = XWINDOW (window);
4857 /* Don't screw up if window_scroll gets an error. */
4858 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4859 ++windows_or_buffers_changed;
4861 Fset_buffer (w->buffer);
4862 SET_PT (marker_position (w->pointm));
4864 if (NILP (arg))
4865 window_scroll (window, 1, 1, 1);
4866 else if (EQ (arg, Qminus))
4867 window_scroll (window, -1, 1, 1);
4868 else
4870 if (CONSP (arg))
4871 arg = Fcar (arg);
4872 CHECK_NUMBER (arg);
4873 window_scroll (window, XINT (arg), 0, 1);
4876 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4877 unbind_to (count, Qnil);
4879 return Qnil;
4882 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
4883 doc: /* Scroll selected window display ARG columns left.
4884 Default for ARG is window width minus 2.
4885 Value is the total amount of leftward horizontal scrolling in
4886 effect after the change.
4887 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4888 a lower bound for automatic scrolling, i.e. automatic scrolling
4889 will not scroll a window to a column less than the value returned
4890 by this function. */)
4891 (arg)
4892 register Lisp_Object arg;
4894 Lisp_Object result;
4895 int hscroll;
4896 struct window *w = XWINDOW (selected_window);
4898 if (NILP (arg))
4899 XSETFASTINT (arg, window_box_text_cols (w) - 2);
4900 else
4901 arg = Fprefix_numeric_value (arg);
4903 hscroll = XINT (w->hscroll) + XINT (arg);
4904 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4906 if (interactive_p (0))
4907 w->min_hscroll = w->hscroll;
4909 return result;
4912 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
4913 doc: /* Scroll selected window display ARG columns right.
4914 Default for ARG is window width minus 2.
4915 Value is the total amount of leftward horizontal scrolling in
4916 effect after the change.
4917 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4918 a lower bound for automatic scrolling, i.e. automatic scrolling
4919 will not scroll a window to a column less than the value returned
4920 by this function. */)
4921 (arg)
4922 register Lisp_Object arg;
4924 Lisp_Object result;
4925 int hscroll;
4926 struct window *w = XWINDOW (selected_window);
4928 if (NILP (arg))
4929 XSETFASTINT (arg, window_box_text_cols (w) - 2);
4930 else
4931 arg = Fprefix_numeric_value (arg);
4933 hscroll = XINT (w->hscroll) - XINT (arg);
4934 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4936 if (interactive_p (0))
4937 w->min_hscroll = w->hscroll;
4939 return result;
4942 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
4943 doc: /* Return the window which was selected when entering the minibuffer.
4944 Returns nil, if current window is not a minibuffer window. */)
4947 if (minibuf_level > 0
4948 && MINI_WINDOW_P (XWINDOW (selected_window))
4949 && WINDOW_LIVE_P (minibuf_selected_window))
4950 return minibuf_selected_window;
4952 return Qnil;
4955 /* Value is the number of lines actually displayed in window W,
4956 as opposed to its height. */
4958 static int
4959 displayed_window_lines (w)
4960 struct window *w;
4962 struct it it;
4963 struct text_pos start;
4964 int height = window_box_height (w);
4965 struct buffer *old_buffer;
4966 int bottom_y;
4968 if (XBUFFER (w->buffer) != current_buffer)
4970 old_buffer = current_buffer;
4971 set_buffer_internal (XBUFFER (w->buffer));
4973 else
4974 old_buffer = NULL;
4976 /* In case W->start is out of the accessible range, do something
4977 reasonable. This happens in Info mode when Info-scroll-down
4978 calls (recenter -1) while W->start is 1. */
4979 if (XMARKER (w->start)->charpos < BEGV)
4980 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4981 else if (XMARKER (w->start)->charpos > ZV)
4982 SET_TEXT_POS (start, ZV, ZV_BYTE);
4983 else
4984 SET_TEXT_POS_FROM_MARKER (start, w->start);
4986 start_display (&it, w, start);
4987 move_it_vertically (&it, height);
4988 bottom_y = line_bottom_y (&it);
4990 /* rms: On a non-window display,
4991 the value of it.vpos at the bottom of the screen
4992 seems to be 1 larger than window_box_height (w).
4993 This kludge fixes a bug whereby (move-to-window-line -1)
4994 when ZV is on the last screen line
4995 moves to the previous screen line instead of the last one. */
4996 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
4997 height++;
4999 /* Add in empty lines at the bottom of the window. */
5000 if (bottom_y < height)
5002 int uy = FRAME_LINE_HEIGHT (it.f);
5003 it.vpos += (height - bottom_y + uy - 1) / uy;
5006 if (old_buffer)
5007 set_buffer_internal (old_buffer);
5009 return it.vpos;
5013 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5014 doc: /* Center point in window and redisplay frame.
5015 With prefix argument ARG, recenter putting point on screen line ARG
5016 relative to the current window. If ARG is negative, it counts up from the
5017 bottom of the window. (ARG should be less than the height of the window.)
5019 If ARG is omitted or nil, erase the entire frame and then
5020 redraw with point in the center of the current window.
5021 Just C-u as prefix means put point in the center of the window
5022 and redisplay normally--don't erase and redraw the frame. */)
5023 (arg)
5024 register Lisp_Object arg;
5026 struct window *w = XWINDOW (selected_window);
5027 struct buffer *buf = XBUFFER (w->buffer);
5028 struct buffer *obuf = current_buffer;
5029 int center_p = 0;
5030 int charpos, bytepos;
5032 /* If redisplay is suppressed due to an error, try again. */
5033 obuf->display_error_modiff = 0;
5035 if (NILP (arg))
5037 int i;
5039 /* Invalidate pixel data calculated for all compositions. */
5040 for (i = 0; i < n_compositions; i++)
5041 composition_table[i]->font = NULL;
5043 Fredraw_frame (w->frame);
5044 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
5045 center_p = 1;
5047 else if (CONSP (arg)) /* Just C-u. */
5048 center_p = 1;
5049 else
5051 arg = Fprefix_numeric_value (arg);
5052 CHECK_NUMBER (arg);
5055 set_buffer_internal (buf);
5057 /* Handle centering on a graphical frame specially. Such frames can
5058 have variable-height lines and centering point on the basis of
5059 line counts would lead to strange effects. */
5060 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5062 if (center_p)
5064 struct it it;
5065 struct text_pos pt;
5067 SET_TEXT_POS (pt, PT, PT_BYTE);
5068 start_display (&it, w, pt);
5069 move_it_vertically (&it, - window_box_height (w) / 2);
5070 charpos = IT_CHARPOS (it);
5071 bytepos = IT_BYTEPOS (it);
5073 else if (XINT (arg) < 0)
5075 struct it it;
5076 struct text_pos pt;
5077 int y0, y1, h, nlines;
5079 SET_TEXT_POS (pt, PT, PT_BYTE);
5080 start_display (&it, w, pt);
5081 y0 = it.current_y;
5083 /* The amount of pixels we have to move back is the window
5084 height minus what's displayed in the line containing PT,
5085 and the lines below. */
5086 nlines = - XINT (arg) - 1;
5087 move_it_by_lines (&it, nlines, 1);
5089 y1 = line_bottom_y (&it);
5091 /* If we can't move down NLINES lines because we hit
5092 the end of the buffer, count in some empty lines. */
5093 if (it.vpos < nlines)
5094 y1 += (nlines - it.vpos) * FRAME_LINE_HEIGHT (it.f);
5096 h = window_box_height (w) - (y1 - y0);
5098 start_display (&it, w, pt);
5099 move_it_vertically (&it, - h);
5100 charpos = IT_CHARPOS (it);
5101 bytepos = IT_BYTEPOS (it);
5103 else
5105 struct position pos;
5106 pos = *vmotion (PT, - XINT (arg), w);
5107 charpos = pos.bufpos;
5108 bytepos = pos.bytepos;
5111 else
5113 struct position pos;
5114 int ht = window_internal_height (w);
5116 if (center_p)
5117 arg = make_number (ht / 2);
5118 else if (XINT (arg) < 0)
5119 arg = make_number (XINT (arg) + ht);
5121 pos = *vmotion (PT, - XINT (arg), w);
5122 charpos = pos.bufpos;
5123 bytepos = pos.bytepos;
5126 /* Set the new window start. */
5127 set_marker_both (w->start, w->buffer, charpos, bytepos);
5128 w->window_end_valid = Qnil;
5130 w->optional_new_start = Qt;
5132 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5133 w->start_at_line_beg = Qt;
5134 else
5135 w->start_at_line_beg = Qnil;
5137 set_buffer_internal (obuf);
5138 return Qnil;
5142 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5143 0, 1, 0,
5144 doc: /* Return the height in lines of the text display area of WINDOW.
5145 This doesn't include the mode-line (or header-line if any) or any
5146 partial-height lines in the text display area. */)
5147 (window)
5148 Lisp_Object window;
5150 struct window *w = decode_window (window);
5151 int pixel_height = window_box_height (w);
5152 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5153 return make_number (line_height);
5158 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5159 1, 1, "P",
5160 doc: /* Position point relative to window.
5161 With no argument, position point at center of window.
5162 An argument specifies vertical position within the window;
5163 zero means top of window, negative means relative to bottom of window. */)
5164 (arg)
5165 Lisp_Object arg;
5167 struct window *w = XWINDOW (selected_window);
5168 int lines, start;
5169 Lisp_Object window;
5171 window = selected_window;
5172 start = marker_position (w->start);
5173 if (start < BEGV || start > ZV)
5175 int height = window_internal_height (w);
5176 Fvertical_motion (make_number (- (height / 2)), window);
5177 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5178 w->start_at_line_beg = Fbolp ();
5179 w->force_start = Qt;
5181 else
5182 Fgoto_char (w->start);
5184 lines = displayed_window_lines (w);
5185 if (NILP (arg))
5186 XSETFASTINT (arg, lines / 2);
5187 else
5189 arg = Fprefix_numeric_value (arg);
5190 if (XINT (arg) < 0)
5191 XSETINT (arg, XINT (arg) + lines);
5194 /* Skip past a partially visible first line. */
5195 if (w->vscroll)
5196 XSETINT (arg, XINT (arg) + 1);
5198 return Fvertical_motion (arg, window);
5203 /***********************************************************************
5204 Window Configuration
5205 ***********************************************************************/
5207 struct save_window_data
5209 EMACS_INT size_from_Lisp_Vector_struct;
5210 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5211 Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
5212 Lisp_Object frame_tool_bar_lines;
5213 Lisp_Object selected_frame;
5214 Lisp_Object current_window;
5215 Lisp_Object current_buffer;
5216 Lisp_Object minibuf_scroll_window;
5217 Lisp_Object minibuf_selected_window;
5218 Lisp_Object root_window;
5219 Lisp_Object focus_frame;
5220 /* Record the values of window-min-width and window-min-height
5221 so that window sizes remain consistent with them. */
5222 Lisp_Object min_width, min_height;
5223 /* A vector, each of whose elements is a struct saved_window
5224 for one window. */
5225 Lisp_Object saved_windows;
5228 /* This is saved as a Lisp_Vector */
5229 struct saved_window
5231 /* these first two must agree with struct Lisp_Vector in lisp.h */
5232 EMACS_INT size_from_Lisp_Vector_struct;
5233 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5235 Lisp_Object window;
5236 Lisp_Object buffer, start, pointm, mark;
5237 Lisp_Object left_col, top_line, total_cols, total_lines;
5238 Lisp_Object hscroll, min_hscroll;
5239 Lisp_Object parent, prev;
5240 Lisp_Object start_at_line_beg;
5241 Lisp_Object display_table;
5242 Lisp_Object orig_top_line, orig_total_lines;
5243 Lisp_Object left_margin_cols, right_margin_cols;
5244 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5245 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
5248 #define SAVED_WINDOW_VECTOR_SIZE 24 /* Arg to Fmake_vector */
5250 #define SAVED_WINDOW_N(swv,n) \
5251 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5253 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5254 doc: /* Return t if OBJECT is a window-configuration object. */)
5255 (object)
5256 Lisp_Object object;
5258 if (WINDOW_CONFIGURATIONP (object))
5259 return Qt;
5260 return Qnil;
5263 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5264 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5265 (config)
5266 Lisp_Object config;
5268 register struct save_window_data *data;
5269 struct Lisp_Vector *saved_windows;
5271 if (! WINDOW_CONFIGURATIONP (config))
5272 wrong_type_argument (Qwindow_configuration_p, config);
5274 data = (struct save_window_data *) XVECTOR (config);
5275 saved_windows = XVECTOR (data->saved_windows);
5276 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5279 DEFUN ("set-window-configuration", Fset_window_configuration,
5280 Sset_window_configuration, 1, 1, 0,
5281 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5282 CONFIGURATION must be a value previously returned
5283 by `current-window-configuration' (which see).
5284 If CONFIGURATION was made from a frame that is now deleted,
5285 only frame-independent values can be restored. In this case,
5286 the return value is nil. Otherwise the value is t. */)
5287 (configuration)
5288 Lisp_Object configuration;
5290 register struct save_window_data *data;
5291 struct Lisp_Vector *saved_windows;
5292 Lisp_Object new_current_buffer;
5293 Lisp_Object frame;
5294 FRAME_PTR f;
5295 int old_point = -1;
5297 while (!WINDOW_CONFIGURATIONP (configuration))
5298 wrong_type_argument (Qwindow_configuration_p, configuration);
5300 data = (struct save_window_data *) XVECTOR (configuration);
5301 saved_windows = XVECTOR (data->saved_windows);
5303 new_current_buffer = data->current_buffer;
5304 if (NILP (XBUFFER (new_current_buffer)->name))
5305 new_current_buffer = Qnil;
5306 else
5308 if (XBUFFER (new_current_buffer) == current_buffer)
5309 old_point = PT;
5310 else
5311 old_point = BUF_PT (XBUFFER (new_current_buffer));
5314 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5315 f = XFRAME (frame);
5317 /* If f is a dead frame, don't bother rebuilding its window tree.
5318 However, there is other stuff we should still try to do below. */
5319 if (FRAME_LIVE_P (f))
5321 register struct window *w;
5322 register struct saved_window *p;
5323 struct window *root_window;
5324 struct window **leaf_windows;
5325 int n_leaf_windows;
5326 int k, i, n;
5328 /* If the frame has been resized since this window configuration was
5329 made, we change the frame to the size specified in the
5330 configuration, restore the configuration, and then resize it
5331 back. We keep track of the prevailing height in these variables. */
5332 int previous_frame_lines = FRAME_LINES (f);
5333 int previous_frame_cols = FRAME_COLS (f);
5334 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5335 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5337 /* The mouse highlighting code could get screwed up
5338 if it runs during this. */
5339 BLOCK_INPUT;
5341 if (XFASTINT (data->frame_lines) != previous_frame_lines
5342 || XFASTINT (data->frame_cols) != previous_frame_cols)
5343 change_frame_size (f, XFASTINT (data->frame_lines),
5344 XFASTINT (data->frame_cols), 0, 0, 0);
5345 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5346 if (XFASTINT (data->frame_menu_bar_lines)
5347 != previous_frame_menu_bar_lines)
5348 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
5349 #ifdef HAVE_WINDOW_SYSTEM
5350 if (XFASTINT (data->frame_tool_bar_lines)
5351 != previous_frame_tool_bar_lines)
5352 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
5353 #endif
5354 #endif
5356 /* "Swap out" point from the selected window
5357 into its buffer. We do this now, before
5358 restoring the window contents, and prevent it from
5359 being done later on when we select a new window. */
5360 if (! NILP (XWINDOW (selected_window)->buffer))
5362 w = XWINDOW (selected_window);
5363 set_marker_both (w->pointm,
5364 w->buffer,
5365 BUF_PT (XBUFFER (w->buffer)),
5366 BUF_PT_BYTE (XBUFFER (w->buffer)));
5369 windows_or_buffers_changed++;
5370 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5372 /* Problem: Freeing all matrices and later allocating them again
5373 is a serious redisplay flickering problem. What we would
5374 really like to do is to free only those matrices not reused
5375 below. */
5376 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5377 leaf_windows
5378 = (struct window **) alloca (count_windows (root_window)
5379 * sizeof (struct window *));
5380 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5382 /* Temporarily avoid any problems with windows that are smaller
5383 than they are supposed to be. */
5384 window_min_height = 1;
5385 window_min_width = 1;
5387 /* Kludge Alert!
5388 Mark all windows now on frame as "deleted".
5389 Restoring the new configuration "undeletes" any that are in it.
5391 Save their current buffers in their height fields, since we may
5392 need it later, if a buffer saved in the configuration is now
5393 dead. */
5394 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5396 for (k = 0; k < saved_windows->size; k++)
5398 p = SAVED_WINDOW_N (saved_windows, k);
5399 w = XWINDOW (p->window);
5400 w->next = Qnil;
5402 if (!NILP (p->parent))
5403 w->parent = SAVED_WINDOW_N (saved_windows,
5404 XFASTINT (p->parent))->window;
5405 else
5406 w->parent = Qnil;
5408 if (!NILP (p->prev))
5410 w->prev = SAVED_WINDOW_N (saved_windows,
5411 XFASTINT (p->prev))->window;
5412 XWINDOW (w->prev)->next = p->window;
5414 else
5416 w->prev = Qnil;
5417 if (!NILP (w->parent))
5419 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
5421 XWINDOW (w->parent)->vchild = p->window;
5422 XWINDOW (w->parent)->hchild = Qnil;
5424 else
5426 XWINDOW (w->parent)->hchild = p->window;
5427 XWINDOW (w->parent)->vchild = Qnil;
5432 /* If we squirreled away the buffer in the window's height,
5433 restore it now. */
5434 if (BUFFERP (w->total_lines))
5435 w->buffer = w->total_lines;
5436 w->left_col = p->left_col;
5437 w->top_line = p->top_line;
5438 w->total_cols = p->total_cols;
5439 w->total_lines = p->total_lines;
5440 w->hscroll = p->hscroll;
5441 w->min_hscroll = p->min_hscroll;
5442 w->display_table = p->display_table;
5443 w->orig_top_line = p->orig_top_line;
5444 w->orig_total_lines = p->orig_total_lines;
5445 w->left_margin_cols = p->left_margin_cols;
5446 w->right_margin_cols = p->right_margin_cols;
5447 w->left_fringe_width = p->left_fringe_width;
5448 w->right_fringe_width = p->right_fringe_width;
5449 w->fringes_outside_margins = p->fringes_outside_margins;
5450 w->scroll_bar_width = p->scroll_bar_width;
5451 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
5452 XSETFASTINT (w->last_modified, 0);
5453 XSETFASTINT (w->last_overlay_modified, 0);
5455 /* Reinstall the saved buffer and pointers into it. */
5456 if (NILP (p->buffer))
5457 w->buffer = p->buffer;
5458 else
5460 if (!NILP (XBUFFER (p->buffer)->name))
5461 /* If saved buffer is alive, install it. */
5463 w->buffer = p->buffer;
5464 w->start_at_line_beg = p->start_at_line_beg;
5465 set_marker_restricted (w->start, p->start, w->buffer);
5466 set_marker_restricted (w->pointm, p->pointm, w->buffer);
5467 Fset_marker (XBUFFER (w->buffer)->mark,
5468 p->mark, w->buffer);
5470 /* As documented in Fcurrent_window_configuration, don't
5471 restore the location of point in the buffer which was
5472 current when the window configuration was recorded. */
5473 if (!EQ (p->buffer, new_current_buffer)
5474 && XBUFFER (p->buffer) == current_buffer)
5475 Fgoto_char (w->pointm);
5477 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
5478 /* Else unless window has a live buffer, get one. */
5480 w->buffer = Fcdr (Fcar (Vbuffer_alist));
5481 /* This will set the markers to beginning of visible
5482 range. */
5483 set_marker_restricted (w->start, make_number (0), w->buffer);
5484 set_marker_restricted (w->pointm, make_number (0),w->buffer);
5485 w->start_at_line_beg = Qt;
5487 else
5488 /* Keeping window's old buffer; make sure the markers
5489 are real. */
5491 /* Set window markers at start of visible range. */
5492 if (XMARKER (w->start)->buffer == 0)
5493 set_marker_restricted (w->start, make_number (0),
5494 w->buffer);
5495 if (XMARKER (w->pointm)->buffer == 0)
5496 set_marker_restricted_both (w->pointm, w->buffer,
5497 BUF_PT (XBUFFER (w->buffer)),
5498 BUF_PT_BYTE (XBUFFER (w->buffer)));
5499 w->start_at_line_beg = Qt;
5504 FRAME_ROOT_WINDOW (f) = data->root_window;
5505 /* Prevent "swapping out point" in the old selected window
5506 using the buffer that has been restored into it.
5507 Use the point value from the beginning of this function
5508 since unshow_buffer (called from delete_all_subwindows)
5509 could have altered it. */
5510 selected_window = Qnil;
5511 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5512 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5513 make_number (old_point),
5514 XWINDOW (data->current_window)->buffer);
5516 Fselect_window (data->current_window, Qnil);
5517 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
5518 = selected_window;
5520 if (NILP (data->focus_frame)
5521 || (FRAMEP (data->focus_frame)
5522 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5523 Fredirect_frame_focus (frame, data->focus_frame);
5525 #if 0 /* I don't understand why this is needed, and it causes problems
5526 when the frame's old selected window has been deleted. */
5527 if (f != selected_frame && FRAME_WINDOW_P (f))
5528 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
5529 0, 0);
5530 #endif
5532 /* Set the screen height to the value it had before this function. */
5533 if (previous_frame_lines != FRAME_LINES (f)
5534 || previous_frame_cols != FRAME_COLS (f))
5535 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5536 0, 0, 0);
5537 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5538 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5539 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5540 make_number (0));
5541 #ifdef HAVE_WINDOW_SYSTEM
5542 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5543 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5544 make_number (0));
5545 #endif
5546 #endif
5548 /* Now, free glyph matrices in windows that were not reused. */
5549 for (i = n = 0; i < n_leaf_windows; ++i)
5551 if (NILP (leaf_windows[i]->buffer))
5553 /* Assert it's not reused as a combination. */
5554 xassert (NILP (leaf_windows[i]->hchild)
5555 && NILP (leaf_windows[i]->vchild));
5556 free_window_matrices (leaf_windows[i]);
5558 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5559 ++n;
5562 adjust_glyphs (f);
5564 UNBLOCK_INPUT;
5566 /* Fselect_window will have made f the selected frame, so we
5567 reselect the proper frame here. Fhandle_switch_frame will change the
5568 selected window too, but that doesn't make the call to
5569 Fselect_window above totally superfluous; it still sets f's
5570 selected window. */
5571 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5572 do_switch_frame (data->selected_frame, 0, 0);
5574 if (! NILP (Vwindow_configuration_change_hook)
5575 && ! NILP (Vrun_hooks))
5576 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
5579 if (!NILP (new_current_buffer))
5580 Fset_buffer (new_current_buffer);
5582 /* Restore the minimum heights recorded in the configuration. */
5583 window_min_height = XINT (data->min_height);
5584 window_min_width = XINT (data->min_width);
5586 Vminibuf_scroll_window = data->minibuf_scroll_window;
5587 minibuf_selected_window = data->minibuf_selected_window;
5589 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5592 /* Mark all windows now on frame as deleted
5593 by setting their buffers to nil. */
5595 void
5596 delete_all_subwindows (w)
5597 register struct window *w;
5599 if (!NILP (w->next))
5600 delete_all_subwindows (XWINDOW (w->next));
5601 if (!NILP (w->vchild))
5602 delete_all_subwindows (XWINDOW (w->vchild));
5603 if (!NILP (w->hchild))
5604 delete_all_subwindows (XWINDOW (w->hchild));
5606 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
5608 if (!NILP (w->buffer))
5609 unshow_buffer (w);
5611 /* We set all three of these fields to nil, to make sure that we can
5612 distinguish this dead window from any live window. Live leaf
5613 windows will have buffer set, and combination windows will have
5614 vchild or hchild set. */
5615 w->buffer = Qnil;
5616 w->vchild = Qnil;
5617 w->hchild = Qnil;
5619 Vwindow_list = Qnil;
5622 static int
5623 count_windows (window)
5624 register struct window *window;
5626 register int count = 1;
5627 if (!NILP (window->next))
5628 count += count_windows (XWINDOW (window->next));
5629 if (!NILP (window->vchild))
5630 count += count_windows (XWINDOW (window->vchild));
5631 if (!NILP (window->hchild))
5632 count += count_windows (XWINDOW (window->hchild));
5633 return count;
5637 /* Fill vector FLAT with leaf windows under W, starting at index I.
5638 Value is last index + 1. */
5640 static int
5641 get_leaf_windows (w, flat, i)
5642 struct window *w;
5643 struct window **flat;
5644 int i;
5646 while (w)
5648 if (!NILP (w->hchild))
5649 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5650 else if (!NILP (w->vchild))
5651 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5652 else
5653 flat[i++] = w;
5655 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5658 return i;
5662 /* Return a pointer to the glyph W's physical cursor is on. Value is
5663 null if W's current matrix is invalid, so that no meaningfull glyph
5664 can be returned. */
5666 struct glyph *
5667 get_phys_cursor_glyph (w)
5668 struct window *w;
5670 struct glyph_row *row;
5671 struct glyph *glyph;
5673 if (w->phys_cursor.vpos >= 0
5674 && w->phys_cursor.vpos < w->current_matrix->nrows
5675 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
5676 row->enabled_p)
5677 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
5678 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
5679 else
5680 glyph = NULL;
5682 return glyph;
5686 static int
5687 save_window_save (window, vector, i)
5688 Lisp_Object window;
5689 struct Lisp_Vector *vector;
5690 int i;
5692 register struct saved_window *p;
5693 register struct window *w;
5694 register Lisp_Object tem;
5696 for (;!NILP (window); window = w->next)
5698 p = SAVED_WINDOW_N (vector, i);
5699 w = XWINDOW (window);
5701 XSETFASTINT (w->temslot, i++);
5702 p->window = window;
5703 p->buffer = w->buffer;
5704 p->left_col = w->left_col;
5705 p->top_line = w->top_line;
5706 p->total_cols = w->total_cols;
5707 p->total_lines = w->total_lines;
5708 p->hscroll = w->hscroll;
5709 p->min_hscroll = w->min_hscroll;
5710 p->display_table = w->display_table;
5711 p->orig_top_line = w->orig_top_line;
5712 p->orig_total_lines = w->orig_total_lines;
5713 p->left_margin_cols = w->left_margin_cols;
5714 p->right_margin_cols = w->right_margin_cols;
5715 p->left_fringe_width = w->left_fringe_width;
5716 p->right_fringe_width = w->right_fringe_width;
5717 p->fringes_outside_margins = w->fringes_outside_margins;
5718 p->scroll_bar_width = w->scroll_bar_width;
5719 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
5720 if (!NILP (w->buffer))
5722 /* Save w's value of point in the window configuration.
5723 If w is the selected window, then get the value of point
5724 from the buffer; pointm is garbage in the selected window. */
5725 if (EQ (window, selected_window))
5727 p->pointm = Fmake_marker ();
5728 set_marker_both (p->pointm, w->buffer,
5729 BUF_PT (XBUFFER (w->buffer)),
5730 BUF_PT_BYTE (XBUFFER (w->buffer)));
5732 else
5733 p->pointm = Fcopy_marker (w->pointm, Qnil);
5735 p->start = Fcopy_marker (w->start, Qnil);
5736 p->start_at_line_beg = w->start_at_line_beg;
5738 tem = XBUFFER (w->buffer)->mark;
5739 p->mark = Fcopy_marker (tem, Qnil);
5741 else
5743 p->pointm = Qnil;
5744 p->start = Qnil;
5745 p->mark = Qnil;
5746 p->start_at_line_beg = Qnil;
5749 if (NILP (w->parent))
5750 p->parent = Qnil;
5751 else
5752 p->parent = XWINDOW (w->parent)->temslot;
5754 if (NILP (w->prev))
5755 p->prev = Qnil;
5756 else
5757 p->prev = XWINDOW (w->prev)->temslot;
5759 if (!NILP (w->vchild))
5760 i = save_window_save (w->vchild, vector, i);
5761 if (!NILP (w->hchild))
5762 i = save_window_save (w->hchild, vector, i);
5765 return i;
5768 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
5769 Scurrent_window_configuration, 0, 1, 0,
5770 doc: /* Return an object representing the current window configuration of FRAME.
5771 If FRAME is nil or omitted, use the selected frame.
5772 This describes the number of windows, their sizes and current buffers,
5773 and for each displayed buffer, where display starts, and the positions of
5774 point and mark. An exception is made for point in the current buffer:
5775 its value is -not- saved.
5776 This also records the currently selected frame, and FRAME's focus
5777 redirection (see `redirect-frame-focus'). */)
5778 (frame)
5779 Lisp_Object frame;
5781 register Lisp_Object tem;
5782 register int n_windows;
5783 register struct save_window_data *data;
5784 register struct Lisp_Vector *vec;
5785 register int i;
5786 FRAME_PTR f;
5788 if (NILP (frame))
5789 frame = selected_frame;
5790 CHECK_LIVE_FRAME (frame);
5791 f = XFRAME (frame);
5793 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5794 vec = allocate_other_vector (VECSIZE (struct save_window_data));
5795 data = (struct save_window_data *)vec;
5797 XSETFASTINT (data->frame_cols, FRAME_COLS (f));
5798 XSETFASTINT (data->frame_lines, FRAME_LINES (f));
5799 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
5800 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
5801 data->selected_frame = selected_frame;
5802 data->current_window = FRAME_SELECTED_WINDOW (f);
5803 XSETBUFFER (data->current_buffer, current_buffer);
5804 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
5805 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
5806 data->root_window = FRAME_ROOT_WINDOW (f);
5807 data->focus_frame = FRAME_FOCUS_FRAME (f);
5808 XSETINT (data->min_height, window_min_height);
5809 XSETINT (data->min_width, window_min_width);
5810 tem = Fmake_vector (make_number (n_windows), Qnil);
5811 data->saved_windows = tem;
5812 for (i = 0; i < n_windows; i++)
5813 XVECTOR (tem)->contents[i]
5814 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
5815 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
5816 XSETWINDOW_CONFIGURATION (tem, data);
5817 return (tem);
5820 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
5821 0, UNEVALLED, 0,
5822 doc: /* Execute body, preserving window sizes and contents.
5823 Restore which buffer appears in which window, where display starts,
5824 and the value of point and mark for each window.
5825 Also restore the choice of selected window.
5826 Also restore which buffer is current.
5827 Does not restore the value of point in current buffer.
5828 usage: (save-window-excursion BODY ...) */)
5829 (args)
5830 Lisp_Object args;
5832 register Lisp_Object val;
5833 register int count = SPECPDL_INDEX ();
5835 record_unwind_protect (Fset_window_configuration,
5836 Fcurrent_window_configuration (Qnil));
5837 val = Fprogn (args);
5838 return unbind_to (count, val);
5842 /***********************************************************************
5843 Marginal Areas
5844 ***********************************************************************/
5846 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
5847 2, 3, 0,
5848 doc: /* Set width of marginal areas of window WINDOW.
5849 If window is nil, set margins of the currently selected window.
5850 First parameter LEFT-WIDTH specifies the number of character
5851 cells to reserve for the left marginal area. Second parameter
5852 RIGHT-WIDTH does the same for the right marginal area.
5853 A nil width parameter means no margin. */)
5854 (window, left, right)
5855 Lisp_Object window, left, right;
5857 struct window *w = decode_window (window);
5859 /* Translate negative or zero widths to nil.
5860 Margins that are too wide have to be checked elsewhere. */
5862 if (!NILP (left))
5864 CHECK_NUMBER (left);
5865 if (XINT (left) <= 0)
5866 left = Qnil;
5869 if (!NILP (right))
5871 CHECK_NUMBER (right);
5872 if (XINT (right) <= 0)
5873 right = Qnil;
5876 if (!EQ (w->left_margin_cols, left)
5877 || !EQ (w->right_margin_cols, right))
5879 w->left_margin_cols = left;
5880 w->right_margin_cols = right;
5882 adjust_window_margins (w);
5884 ++windows_or_buffers_changed;
5885 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5888 return Qnil;
5892 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
5893 0, 1, 0,
5894 doc: /* Get width of marginal areas of window WINDOW.
5895 If WINDOW is omitted or nil, use the currently selected window.
5896 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
5897 If a marginal area does not exist, its width will be returned
5898 as nil. */)
5899 (window)
5900 Lisp_Object window;
5902 struct window *w = decode_window (window);
5903 return Fcons (w->left_margin_cols, w->right_margin_cols);
5908 /***********************************************************************
5909 Fringes
5910 ***********************************************************************/
5912 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
5913 2, 4, 0,
5914 doc: /* Set the fringe widths of window WINDOW.
5916 If WINDOW is nil, set the fringe widths of the currently selected
5917 window.
5919 The second parameter LEFT-WIDTH specifies the number of pixels to
5920 reserve for the left fringe. The third parameter RIGHT-WIDTH
5921 specifies the right fringe width. If a fringe width parameter is nil,
5922 that means to use the frame's default fringe width. Default fringe
5923 widths can be set with the command `set-fringe-style'.
5925 If the fourth parameter OUTSIDE-MARGINS is non-nil, draw the fringes
5926 outside of the display margins. By default, fringes are drawn between
5927 display marginal areas and the text area. */)
5928 (window, left, right, outside_margins)
5929 Lisp_Object window, left, right, outside_margins;
5931 struct window *w = decode_window (window);
5933 if (!NILP (left))
5934 CHECK_NUMBER (left);
5935 if (!NILP (right))
5936 CHECK_NUMBER (right);
5938 if (!EQ (w->left_fringe_width, left)
5939 || !EQ (w->right_fringe_width, right)
5940 || !EQ (w->fringes_outside_margins, outside_margins))
5942 w->left_fringe_width = left;
5943 w->right_fringe_width = right;
5944 w->fringes_outside_margins = outside_margins;
5946 adjust_window_margins (w);
5948 clear_glyph_matrix (w->current_matrix);
5949 w->window_end_valid = Qnil;
5951 ++windows_or_buffers_changed;
5952 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5955 return Qnil;
5959 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
5960 0, 1, 0,
5961 doc: /* Get width of fringes of window WINDOW.
5962 If WINDOW is omitted or nil, use the currently selected window.
5963 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS).
5964 If a window specific fringe width is not set, its width will be returned
5965 as nil. */)
5966 (window)
5967 Lisp_Object window;
5969 struct window *w = decode_window (window);
5970 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
5971 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
5972 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ?
5973 Qt : Qnil), Qnil)));
5978 /***********************************************************************
5979 Scroll bars
5980 ***********************************************************************/
5982 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
5983 2, 4, 0,
5984 doc: /* Set width and type of scroll bars of window WINDOW.
5985 If window is nil, set scroll bars of the currently selected window.
5986 Second parameter WIDTH specifies the pixel width for the scroll bar;
5987 this is automatically adjusted to a multiple of the frame column width.
5988 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
5989 bar: left, right, or nil.
5990 If WIDTH is nil, use the frame's scroll-bar width.
5991 If TYPE is t, use the frame's scroll-bar type. */)
5992 (window, width, vertical_type, horizontal_type)
5993 Lisp_Object window, width, vertical_type, horizontal_type;
5995 struct window *w = decode_window (window);
5997 if (!NILP (width))
5998 CHECK_NUMBER (width);
6000 if (XINT (width) == 0)
6001 vertical_type = Qnil;
6003 if (!(EQ (vertical_type, Qnil)
6004 || EQ (vertical_type, Qleft)
6005 || EQ (vertical_type, Qright)
6006 || EQ (vertical_type, Qt)))
6007 error ("Invalid type of vertical scroll bar");
6009 if (!EQ (w->scroll_bar_width, width)
6010 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6012 w->scroll_bar_width = width;
6013 w->vertical_scroll_bar_type = vertical_type;
6015 adjust_window_margins (w);
6017 clear_glyph_matrix (w->current_matrix);
6018 w->window_end_valid = Qnil;
6020 ++windows_or_buffers_changed;
6021 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6024 return Qnil;
6028 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6029 0, 1, 0,
6030 doc: /* Get width and type of scroll bars of window WINDOW.
6031 If WINDOW is omitted or nil, use the currently selected window.
6032 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6033 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6034 value. */)
6035 (window)
6036 Lisp_Object window;
6038 struct window *w = decode_window (window);
6039 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6040 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6041 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6042 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6043 Fcons (w->vertical_scroll_bar_type,
6044 Fcons (Qnil, Qnil))));
6049 /***********************************************************************
6050 Smooth scrolling
6051 ***********************************************************************/
6053 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
6054 doc: /* Return the amount by which WINDOW is scrolled vertically.
6055 Use the selected window if WINDOW is nil or omitted.
6056 Value is a multiple of the canonical character height of WINDOW. */)
6057 (window)
6058 Lisp_Object window;
6060 Lisp_Object result;
6061 struct frame *f;
6062 struct window *w;
6064 if (NILP (window))
6065 window = selected_window;
6066 else
6067 CHECK_WINDOW (window);
6068 w = XWINDOW (window);
6069 f = XFRAME (w->frame);
6071 if (FRAME_WINDOW_P (f))
6072 result = FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
6073 else
6074 result = make_number (0);
6075 return result;
6079 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6080 2, 2, 0,
6081 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6082 WINDOW nil means use the selected window. VSCROLL is a non-negative
6083 multiple of the canonical character height of WINDOW. */)
6084 (window, vscroll)
6085 Lisp_Object window, vscroll;
6087 struct window *w;
6088 struct frame *f;
6090 if (NILP (window))
6091 window = selected_window;
6092 else
6093 CHECK_WINDOW (window);
6094 CHECK_NUMBER_OR_FLOAT (vscroll);
6096 w = XWINDOW (window);
6097 f = XFRAME (w->frame);
6099 if (FRAME_WINDOW_P (f))
6101 int old_dy = w->vscroll;
6103 w->vscroll = - FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll);
6104 w->vscroll = min (w->vscroll, 0);
6106 /* Adjust glyph matrix of the frame if the virtual display
6107 area becomes larger than before. */
6108 if (w->vscroll < 0 && w->vscroll < old_dy)
6109 adjust_glyphs (f);
6111 /* Prevent redisplay shortcuts. */
6112 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6115 return Fwindow_vscroll (window);
6119 /* Call FN for all leaf windows on frame F. FN is called with the
6120 first argument being a pointer to the leaf window, and with
6121 additional argument USER_DATA. Stops when FN returns 0. */
6123 void
6124 foreach_window (f, fn, user_data)
6125 struct frame *f;
6126 int (* fn) P_ ((struct window *, void *));
6127 void *user_data;
6129 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6133 /* Helper function for foreach_window. Call FN for all leaf windows
6134 reachable from W. FN is called with the first argument being a
6135 pointer to the leaf window, and with additional argument USER_DATA.
6136 Stop when FN returns 0. Value is 0 if stopped by FN. */
6138 static int
6139 foreach_window_1 (w, fn, user_data)
6140 struct window *w;
6141 int (* fn) P_ ((struct window *, void *));
6142 void *user_data;
6144 int cont;
6146 for (cont = 1; w && cont;)
6148 if (!NILP (w->hchild))
6149 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6150 else if (!NILP (w->vchild))
6151 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6152 else
6153 cont = fn (w, user_data);
6155 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6158 return cont;
6162 /* Freeze or unfreeze the window start of W unless it is a
6163 mini-window or the selected window. FREEZE_P non-null means freeze
6164 the window start. */
6166 static int
6167 freeze_window_start (w, freeze_p)
6168 struct window *w;
6169 void *freeze_p;
6171 if (w == XWINDOW (selected_window)
6172 || MINI_WINDOW_P (w)
6173 || (MINI_WINDOW_P (XWINDOW (selected_window))
6174 && ! NILP (Vminibuf_scroll_window)
6175 && w == XWINDOW (Vminibuf_scroll_window)))
6176 freeze_p = NULL;
6178 w->frozen_window_start_p = freeze_p != NULL;
6179 return 1;
6183 /* Freeze or unfreeze the window starts of all leaf windows on frame
6184 F, except the selected window and a mini-window. FREEZE_P non-zero
6185 means freeze the window start. */
6187 void
6188 freeze_window_starts (f, freeze_p)
6189 struct frame *f;
6190 int freeze_p;
6192 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6196 /***********************************************************************
6197 Initialization
6198 ***********************************************************************/
6200 /* Return 1 if window configurations C1 and C2
6201 describe the same state of affairs. This is used by Fequal. */
6204 compare_window_configurations (c1, c2, ignore_positions)
6205 Lisp_Object c1, c2;
6206 int ignore_positions;
6208 register struct save_window_data *d1, *d2;
6209 struct Lisp_Vector *sw1, *sw2;
6210 int i;
6212 if (!WINDOW_CONFIGURATIONP (c1))
6213 wrong_type_argument (Qwindow_configuration_p, c1);
6214 if (!WINDOW_CONFIGURATIONP (c2))
6215 wrong_type_argument (Qwindow_configuration_p, c2);
6217 d1 = (struct save_window_data *) XVECTOR (c1);
6218 d2 = (struct save_window_data *) XVECTOR (c2);
6219 sw1 = XVECTOR (d1->saved_windows);
6220 sw2 = XVECTOR (d2->saved_windows);
6222 if (! EQ (d1->frame_cols, d2->frame_cols))
6223 return 0;
6224 if (! EQ (d1->frame_lines, d2->frame_lines))
6225 return 0;
6226 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
6227 return 0;
6228 if (! EQ (d1->selected_frame, d2->selected_frame))
6229 return 0;
6230 /* Don't compare the current_window field directly.
6231 Instead see w1_is_current and w2_is_current, below. */
6232 if (! EQ (d1->current_buffer, d2->current_buffer))
6233 return 0;
6234 if (! ignore_positions)
6236 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
6237 return 0;
6238 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
6239 return 0;
6241 /* Don't compare the root_window field.
6242 We don't require the two configurations
6243 to use the same window object,
6244 and the two root windows must be equivalent
6245 if everything else compares equal. */
6246 if (! EQ (d1->focus_frame, d2->focus_frame))
6247 return 0;
6248 if (! EQ (d1->min_width, d2->min_width))
6249 return 0;
6250 if (! EQ (d1->min_height, d2->min_height))
6251 return 0;
6253 /* Verify that the two confis have the same number of windows. */
6254 if (sw1->size != sw2->size)
6255 return 0;
6257 for (i = 0; i < sw1->size; i++)
6259 struct saved_window *p1, *p2;
6260 int w1_is_current, w2_is_current;
6262 p1 = SAVED_WINDOW_N (sw1, i);
6263 p2 = SAVED_WINDOW_N (sw2, i);
6265 /* Verify that the current windows in the two
6266 configurations correspond to each other. */
6267 w1_is_current = EQ (d1->current_window, p1->window);
6268 w2_is_current = EQ (d2->current_window, p2->window);
6270 if (w1_is_current != w2_is_current)
6271 return 0;
6273 /* Verify that the corresponding windows do match. */
6274 if (! EQ (p1->buffer, p2->buffer))
6275 return 0;
6276 if (! EQ (p1->left_col, p2->left_col))
6277 return 0;
6278 if (! EQ (p1->top_line, p2->top_line))
6279 return 0;
6280 if (! EQ (p1->total_cols, p2->total_cols))
6281 return 0;
6282 if (! EQ (p1->total_lines, p2->total_lines))
6283 return 0;
6284 if (! EQ (p1->display_table, p2->display_table))
6285 return 0;
6286 if (! EQ (p1->parent, p2->parent))
6287 return 0;
6288 if (! EQ (p1->prev, p2->prev))
6289 return 0;
6290 if (! ignore_positions)
6292 if (! EQ (p1->hscroll, p2->hscroll))
6293 return 0;
6294 if (!EQ (p1->min_hscroll, p2->min_hscroll))
6295 return 0;
6296 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
6297 return 0;
6298 if (NILP (Fequal (p1->start, p2->start)))
6299 return 0;
6300 if (NILP (Fequal (p1->pointm, p2->pointm)))
6301 return 0;
6302 if (NILP (Fequal (p1->mark, p2->mark)))
6303 return 0;
6305 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
6306 return 0;
6307 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
6308 return 0;
6309 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
6310 return 0;
6311 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
6312 return 0;
6313 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
6314 return 0;
6315 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
6316 return 0;
6317 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
6318 return 0;
6321 return 1;
6324 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6325 Scompare_window_configurations, 2, 2, 0,
6326 doc: /* Compare two window configurations as regards the structure of windows.
6327 This function ignores details such as the values of point and mark
6328 and scrolling positions. */)
6329 (x, y)
6330 Lisp_Object x, y;
6332 if (compare_window_configurations (x, y, 1))
6333 return Qt;
6334 return Qnil;
6337 void
6338 init_window_once ()
6340 struct frame *f = make_terminal_frame ();
6341 XSETFRAME (selected_frame, f);
6342 Vterminal_frame = selected_frame;
6343 minibuf_window = f->minibuffer_window;
6344 selected_window = f->selected_window;
6345 last_nonminibuf_frame = f;
6347 window_initialized = 1;
6350 void
6351 init_window ()
6353 Vwindow_list = Qnil;
6356 void
6357 syms_of_window ()
6359 Qwindow_size_fixed = intern ("window-size-fixed");
6360 staticpro (&Qwindow_size_fixed);
6362 staticpro (&Qwindow_configuration_change_hook);
6363 Qwindow_configuration_change_hook
6364 = intern ("window-configuration-change-hook");
6366 Qwindowp = intern ("windowp");
6367 staticpro (&Qwindowp);
6369 Qwindow_configuration_p = intern ("window-configuration-p");
6370 staticpro (&Qwindow_configuration_p);
6372 Qwindow_live_p = intern ("window-live-p");
6373 staticpro (&Qwindow_live_p);
6375 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
6376 staticpro (&Qtemp_buffer_show_hook);
6378 staticpro (&Vwindow_list);
6380 minibuf_selected_window = Qnil;
6381 staticpro (&minibuf_selected_window);
6383 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
6384 doc: /* Non-nil means call as function to display a help buffer.
6385 The function is called with one argument, the buffer to be displayed.
6386 Used by `with-output-to-temp-buffer'.
6387 If this function is used, then it must do the entire job of showing
6388 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6389 Vtemp_buffer_show_function = Qnil;
6391 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
6392 doc: /* If non-nil, function to call to handle `display-buffer'.
6393 It will receive two args, the buffer and a flag which if non-nil means
6394 that the currently selected window is not acceptable.
6395 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
6396 work using this function. */);
6397 Vdisplay_buffer_function = Qnil;
6399 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
6400 doc: /* *If non-nil, `display-buffer' should even the window heights.
6401 If nil, `display-buffer' will leave the window configuration alone. */);
6402 Veven_window_heights = Qt;
6404 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
6405 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6406 Vminibuf_scroll_window = Qnil;
6408 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
6409 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6410 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6411 is displayed in the `mode-line' face. */);
6412 mode_line_in_non_selected_windows = 1;
6414 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
6415 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6416 Vother_window_scroll_buffer = Qnil;
6418 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
6419 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
6420 pop_up_frames = 0;
6422 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
6423 doc: /* *Non-nil means `display-buffer' should reuse frames.
6424 If the buffer in question is already displayed in a frame, raise that frame. */);
6425 display_buffer_reuse_frames = 0;
6427 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
6428 doc: /* Function to call to handle automatic new frame creation.
6429 It is called with no arguments and should return a newly created frame.
6431 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
6432 where `pop-up-frame-alist' would hold the default frame parameters. */);
6433 Vpop_up_frame_function = Qnil;
6435 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
6436 doc: /* *List of buffer names that should have their own special frames.
6437 Displaying a buffer whose name is in this list makes a special frame for it
6438 using `special-display-function'. See also `special-display-regexps'.
6440 An element of the list can be a list instead of just a string.
6441 There are two ways to use a list as an element:
6442 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
6443 In the first case, FRAME-PARAMETERS are used to create the frame.
6444 In the latter case, FUNCTION is called with BUFFER as the first argument,
6445 followed by OTHER-ARGS--it can display BUFFER in any way it likes.
6446 All this is done by the function found in `special-display-function'.
6448 If the specified frame parameters include (same-buffer . t), the
6449 buffer is displayed in the currently selected window. Otherwise, if
6450 they include (same-frame . t), the buffer is displayed in a new window
6451 in the currently selected frame.
6453 If this variable appears \"not to work\", because you add a name to it
6454 but that buffer still appears in the selected window, look at the
6455 values of `same-window-buffer-names' and `same-window-regexps'.
6456 Those variables take precedence over this one. */);
6457 Vspecial_display_buffer_names = Qnil;
6459 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
6460 doc: /* *List of regexps saying which buffers should have their own special frames.
6461 If a buffer name matches one of these regexps, it gets its own frame.
6462 Displaying a buffer whose name is in this list makes a special frame for it
6463 using `special-display-function'.
6465 An element of the list can be a list instead of just a string.
6466 There are two ways to use a list as an element:
6467 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
6468 In the first case, FRAME-PARAMETERS are used to create the frame.
6469 In the latter case, FUNCTION is called with the buffer as first argument,
6470 followed by OTHER-ARGS--it can display the buffer in any way it likes.
6471 All this is done by the function found in `special-display-function'.
6473 If the specified frame parameters include (same-buffer . t), the
6474 buffer is displayed in the currently selected window. Otherwise, if
6475 they include (same-frame . t), the buffer is displayed in a new window
6476 in the currently selected frame.
6478 If this variable appears \"not to work\", because you add a regexp to it
6479 but the matching buffers still appear in the selected window, look at the
6480 values of `same-window-buffer-names' and `same-window-regexps'.
6481 Those variables take precedence over this one. */);
6482 Vspecial_display_regexps = Qnil;
6484 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
6485 doc: /* Function to call to make a new frame for a special buffer.
6486 It is called with two arguments, the buffer and optional buffer specific
6487 data, and should return a window displaying that buffer.
6488 The default value normally makes a separate frame for the buffer,
6489 using `special-display-frame-alist' to specify the frame parameters.
6490 But if the buffer specific data includes (same-buffer . t) then the
6491 buffer is displayed in the current selected window.
6492 Otherwise if it includes (same-frame . t) then the buffer is displayed in
6493 a new window in the currently selected frame.
6495 A buffer is special if it is listed in `special-display-buffer-names'
6496 or matches a regexp in `special-display-regexps'. */);
6497 Vspecial_display_function = Qnil;
6499 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
6500 doc: /* *List of buffer names that should appear in the selected window.
6501 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
6502 switches to it in the selected window, rather than making it appear
6503 in some other window.
6505 An element of the list can be a cons cell instead of just a string.
6506 Then the car must be a string, which specifies the buffer name.
6507 This is for compatibility with `special-display-buffer-names';
6508 the cdr of the cons cell is ignored.
6510 See also `same-window-regexps'. */);
6511 Vsame_window_buffer_names = Qnil;
6513 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
6514 doc: /* *List of regexps saying which buffers should appear in the selected window.
6515 If a buffer name matches one of these regexps, then displaying it
6516 using `display-buffer' or `pop-to-buffer' switches to it
6517 in the selected window, rather than making it appear in some other window.
6519 An element of the list can be a cons cell instead of just a string.
6520 Then the car must be a string, which specifies the buffer name.
6521 This is for compatibility with `special-display-buffer-names';
6522 the cdr of the cons cell is ignored.
6524 See also `same-window-buffer-names'. */);
6525 Vsame_window_regexps = Qnil;
6527 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
6528 doc: /* *Non-nil means display-buffer should make new windows. */);
6529 pop_up_windows = 1;
6531 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
6532 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
6533 next_screen_context_lines = 2;
6535 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
6536 doc: /* *display-buffer would prefer to split the largest window if this large.
6537 If there is only one window, it is split regardless of this value. */);
6538 split_height_threshold = 500;
6540 DEFVAR_INT ("window-min-height", &window_min_height,
6541 doc: /* *Delete any window less than this tall (including its mode line). */);
6542 window_min_height = 4;
6544 DEFVAR_INT ("window-min-width", &window_min_width,
6545 doc: /* *Delete any window less than this wide. */);
6546 window_min_width = 10;
6548 DEFVAR_LISP ("scroll-preserve-screen-position",
6549 &Vscroll_preserve_screen_position,
6550 doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged. */);
6551 Vscroll_preserve_screen_position = Qnil;
6553 DEFVAR_LISP ("window-configuration-change-hook",
6554 &Vwindow_configuration_change_hook,
6555 doc: /* Functions to call when window configuration changes.
6556 The selected frame is the one whose configuration has changed. */);
6557 Vwindow_configuration_change_hook = Qnil;
6559 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed,
6560 doc: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
6561 Emacs won't change the size of any window displaying that buffer,
6562 unless you explicitly change the size, or Emacs has no other choice.
6563 This variable automatically becomes buffer-local when set. */);
6564 Fmake_variable_buffer_local (Qwindow_size_fixed);
6565 window_size_fixed = 0;
6567 defsubr (&Sselected_window);
6568 defsubr (&Sminibuffer_window);
6569 defsubr (&Swindow_minibuffer_p);
6570 defsubr (&Swindowp);
6571 defsubr (&Swindow_live_p);
6572 defsubr (&Spos_visible_in_window_p);
6573 defsubr (&Swindow_buffer);
6574 defsubr (&Swindow_height);
6575 defsubr (&Swindow_width);
6576 defsubr (&Swindow_hscroll);
6577 defsubr (&Sset_window_hscroll);
6578 defsubr (&Swindow_redisplay_end_trigger);
6579 defsubr (&Sset_window_redisplay_end_trigger);
6580 defsubr (&Swindow_edges);
6581 defsubr (&Swindow_pixel_edges);
6582 defsubr (&Swindow_inside_edges);
6583 defsubr (&Swindow_inside_pixel_edges);
6584 defsubr (&Scoordinates_in_window_p);
6585 defsubr (&Swindow_at);
6586 defsubr (&Swindow_point);
6587 defsubr (&Swindow_start);
6588 defsubr (&Swindow_end);
6589 defsubr (&Sset_window_point);
6590 defsubr (&Sset_window_start);
6591 defsubr (&Swindow_dedicated_p);
6592 defsubr (&Sset_window_dedicated_p);
6593 defsubr (&Swindow_display_table);
6594 defsubr (&Sset_window_display_table);
6595 defsubr (&Snext_window);
6596 defsubr (&Sprevious_window);
6597 defsubr (&Sother_window);
6598 defsubr (&Sget_lru_window);
6599 defsubr (&Sget_largest_window);
6600 defsubr (&Sget_buffer_window);
6601 defsubr (&Sdelete_other_windows);
6602 defsubr (&Sdelete_windows_on);
6603 defsubr (&Sreplace_buffer_in_windows);
6604 defsubr (&Sdelete_window);
6605 defsubr (&Sset_window_buffer);
6606 defsubr (&Sselect_window);
6607 defsubr (&Sspecial_display_p);
6608 defsubr (&Ssame_window_p);
6609 defsubr (&Sdisplay_buffer);
6610 defsubr (&Ssplit_window);
6611 defsubr (&Senlarge_window);
6612 defsubr (&Sshrink_window);
6613 defsubr (&Sscroll_up);
6614 defsubr (&Sscroll_down);
6615 defsubr (&Sscroll_left);
6616 defsubr (&Sscroll_right);
6617 defsubr (&Sother_window_for_scrolling);
6618 defsubr (&Sscroll_other_window);
6619 defsubr (&Sminibuffer_selected_window);
6620 defsubr (&Srecenter);
6621 defsubr (&Swindow_text_height);
6622 defsubr (&Smove_to_window_line);
6623 defsubr (&Swindow_configuration_p);
6624 defsubr (&Swindow_configuration_frame);
6625 defsubr (&Sset_window_configuration);
6626 defsubr (&Scurrent_window_configuration);
6627 defsubr (&Ssave_window_excursion);
6628 defsubr (&Sset_window_margins);
6629 defsubr (&Swindow_margins);
6630 defsubr (&Sset_window_fringes);
6631 defsubr (&Swindow_fringes);
6632 defsubr (&Sset_window_scroll_bars);
6633 defsubr (&Swindow_scroll_bars);
6634 defsubr (&Swindow_vscroll);
6635 defsubr (&Sset_window_vscroll);
6636 defsubr (&Scompare_window_configurations);
6637 defsubr (&Swindow_list);
6640 void
6641 keys_of_window ()
6643 initial_define_key (control_x_map, '1', "delete-other-windows");
6644 initial_define_key (control_x_map, '2', "split-window");
6645 initial_define_key (control_x_map, '0', "delete-window");
6646 initial_define_key (control_x_map, 'o', "other-window");
6647 initial_define_key (control_x_map, '^', "enlarge-window");
6648 initial_define_key (control_x_map, '<', "scroll-left");
6649 initial_define_key (control_x_map, '>', "scroll-right");
6651 initial_define_key (global_map, Ctl ('V'), "scroll-up");
6652 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6653 initial_define_key (meta_map, 'v', "scroll-down");
6655 initial_define_key (global_map, Ctl('L'), "recenter");
6656 initial_define_key (meta_map, 'r', "move-to-window-line");
6659 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
6660 (do not change this comment) */