*** empty log message ***
[emacs.git] / src / window.c
blob626de53e21e8ee6f6c0f9d0b20209e04da189dd0
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;
282 p->overlay_arrow_bitmap = 0;
284 Vwindow_list = Qnil;
285 return val;
288 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
289 doc: /* Return the window that the cursor now appears in and commands apply to. */)
292 return selected_window;
295 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
296 doc: /* Return the window used now for minibuffers.
297 If the optional argument FRAME is specified, return the minibuffer window
298 used by that frame. */)
299 (frame)
300 Lisp_Object frame;
302 if (NILP (frame))
303 frame = selected_frame;
304 CHECK_LIVE_FRAME (frame);
305 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
308 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
309 doc: /* Returns non-nil if WINDOW is a minibuffer window.
310 WINDOW defaults to the selected window. */)
311 (window)
312 Lisp_Object window;
314 struct window *w = decode_window (window);
315 return MINI_WINDOW_P (w) ? Qt : Qnil;
319 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
320 Spos_visible_in_window_p, 0, 3, 0,
321 doc: /* Return t if position POS is currently on the frame in WINDOW.
322 Return nil if that position is scrolled vertically out of view.
323 If a character is only partially visible, nil is returned, unless the
324 optional argument PARTIALLY is non-nil.
325 POS defaults to point in WINDOW; WINDOW defaults to the selected window. */)
326 (pos, window, partially)
327 Lisp_Object pos, window, partially;
329 register struct window *w;
330 register int posint;
331 register struct buffer *buf;
332 struct text_pos top;
333 Lisp_Object in_window;
334 int fully_p;
336 w = decode_window (window);
337 buf = XBUFFER (w->buffer);
338 SET_TEXT_POS_FROM_MARKER (top, w->start);
340 if (!NILP (pos))
342 CHECK_NUMBER_COERCE_MARKER (pos);
343 posint = XINT (pos);
345 else if (w == XWINDOW (selected_window))
346 posint = PT;
347 else
348 posint = XMARKER (w->pointm)->charpos;
350 /* If position is above window start, it's not visible. */
351 if (posint < CHARPOS (top))
352 in_window = Qnil;
353 else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
354 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
355 && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
357 /* If frame is up-to-date, and POSINT is < window end pos, use
358 that info. This doesn't work for POSINT == end pos, because
359 the window end pos is actually the position _after_ the last
360 char in the window. */
361 if (NILP (partially))
363 pos_visible_p (w, posint, &fully_p, NILP (partially));
364 in_window = fully_p ? Qt : Qnil;
366 else
367 in_window = Qt;
369 else if (posint > BUF_ZV (buf))
370 in_window = Qnil;
371 else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
372 /* If window start is out of range, do something reasonable. */
373 in_window = Qnil;
374 else
376 if (pos_visible_p (w, posint, &fully_p, NILP (partially)))
377 in_window = !NILP (partially) || fully_p ? Qt : Qnil;
378 else
379 in_window = Qnil;
382 return in_window;
386 static struct window *
387 decode_window (window)
388 register Lisp_Object window;
390 if (NILP (window))
391 return XWINDOW (selected_window);
393 CHECK_LIVE_WINDOW (window);
394 return XWINDOW (window);
397 static struct window *
398 decode_any_window (window)
399 register Lisp_Object window;
401 if (NILP (window))
402 return XWINDOW (selected_window);
404 CHECK_WINDOW (window);
405 return XWINDOW (window);
408 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
409 doc: /* Return the buffer that WINDOW is displaying. */)
410 (window)
411 Lisp_Object window;
413 return decode_window (window)->buffer;
416 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
417 doc: /* Return the number of lines in WINDOW (including its mode line). */)
418 (window)
419 Lisp_Object window;
421 return decode_any_window (window)->total_lines;
424 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
425 doc: /* Return the number of display columns in WINDOW.
426 This is the width that is usable columns available for text in WINDOW.
427 If you want to find out how many columns WINDOW takes up,
428 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
429 (window)
430 Lisp_Object window;
432 return make_number (window_box_text_cols (decode_any_window (window)));
435 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
436 doc: /* Return the number of columns by which WINDOW is scrolled from left margin. */)
437 (window)
438 Lisp_Object window;
440 return decode_window (window)->hscroll;
443 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
444 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
445 NCOL should be zero or positive.
447 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
448 window so that the location of point becomes invisible. */)
449 (window, ncol)
450 Lisp_Object window, ncol;
452 struct window *w = decode_window (window);
453 int hscroll;
455 CHECK_NUMBER (ncol);
456 hscroll = max (0, XINT (ncol));
458 /* Prevent redisplay shortcuts when changing the hscroll. */
459 if (XINT (w->hscroll) != hscroll)
460 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
462 w->hscroll = make_number (hscroll);
463 return ncol;
466 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
467 Swindow_redisplay_end_trigger, 0, 1, 0,
468 doc: /* Return WINDOW's redisplay end trigger value.
469 See `set-window-redisplay-end-trigger' for more information. */)
470 (window)
471 Lisp_Object window;
473 return decode_window (window)->redisplay_end_trigger;
476 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
477 Sset_window_redisplay_end_trigger, 2, 2, 0,
478 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
479 VALUE should be a buffer position (typically a marker) or nil.
480 If it is a buffer position, then if redisplay in WINDOW reaches a position
481 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
482 with two arguments: WINDOW, and the end trigger value.
483 Afterwards the end-trigger value is reset to nil. */)
484 (window, value)
485 register Lisp_Object window, value;
487 register struct window *w;
489 w = decode_window (window);
490 w->redisplay_end_trigger = value;
491 return value;
494 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
495 doc: /* Return a list of the edge coordinates of WINDOW.
496 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
497 RIGHT is one more than the rightmost column occupied by WINDOW,
498 and BOTTOM is one more than the bottommost row occupied by WINDOW.
499 The edges include the space used by the window's scroll bar,
500 display margins, fringes, header line, and mode line, if it has them.
501 To get the edges of the actual text area, use `window-inside-edges'. */)
502 (window)
503 Lisp_Object window;
505 register struct window *w = decode_any_window (window);
507 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
508 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
509 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
510 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
511 Qnil))));
514 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
515 doc: /* Return a list of the edge pixel coordinates of WINDOW.
516 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
517 RIGHT is one more than the rightmost x position occupied by WINDOW,
518 and BOTTOM is one more than the bottommost y position occupied by WINDOW.
519 The pixel edges include the space used by the window's scroll bar,
520 display margins, fringes, header line, and mode line, if it has them.
521 To get the edges of the actual text area, use `window-inside-pixel-edges'. */)
522 (window)
523 Lisp_Object window;
525 register struct window *w = decode_any_window (window);
527 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
528 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
529 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
530 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
531 Qnil))));
534 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
535 doc: /* Return a list of the edge coordinates of WINDOW.
536 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
537 RIGHT is one more than the rightmost column used by text in WINDOW,
538 and BOTTOM is one more than the bottommost row used by text in WINDOW.
539 The inside edges do not include the space used by the window's scroll bar,
540 display margins, fringes, header line, and/or mode line. */)
541 (window)
542 Lisp_Object window;
544 register struct window *w = decode_any_window (window);
546 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
547 + WINDOW_LEFT_MARGIN_COLS (w)
548 + WINDOW_LEFT_FRINGE_COLS (w)),
549 make_number (WINDOW_TOP_EDGE_LINE (w)
550 + WINDOW_HEADER_LINE_LINES (w)),
551 make_number (WINDOW_RIGHT_EDGE_COL (w)
552 - WINDOW_RIGHT_MARGIN_COLS (w)
553 - WINDOW_RIGHT_FRINGE_COLS (w)),
554 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
555 - WINDOW_MODE_LINE_LINES (w)));
558 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
559 doc: /* Return a list of the edge coordinates of WINDOW.
560 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
561 RIGHT is one more than the rightmost x position used by text in WINDOW,
562 and BOTTOM is one more than the bottommost y position used by text in WINDOW.
563 The inside edges do not include the space used by the window's scroll bar,
564 display margins, fringes, header line, and/or mode line. */)
565 (window)
566 Lisp_Object window;
568 register struct window *w = decode_any_window (window);
570 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
571 + WINDOW_LEFT_MARGIN_WIDTH (w)
572 + WINDOW_LEFT_FRINGE_WIDTH (w)),
573 make_number (WINDOW_TOP_EDGE_Y (w)
574 + WINDOW_HEADER_LINE_HEIGHT (w)),
575 make_number (WINDOW_RIGHT_EDGE_X (w)
576 - WINDOW_RIGHT_MARGIN_WIDTH (w)
577 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
578 make_number (WINDOW_BOTTOM_EDGE_Y (w)
579 - WINDOW_MODE_LINE_HEIGHT (w)));
582 /* Test if the character at column *X, row *Y is within window W.
583 If it is not, return ON_NOTHING;
584 if it is in the window's text area,
585 set *x and *y to its location relative to the upper left corner
586 of the window, and
587 return ON_TEXT;
588 if it is on the window's modeline, return ON_MODE_LINE;
589 if it is on the border between the window and its right sibling,
590 return ON_VERTICAL_BORDER.
591 if it is on the window's top line, return ON_HEADER_LINE;
592 if it is in left or right fringe of the window,
593 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
594 to window-relative coordinates;
595 if it is in the marginal area to the left/right of the window,
596 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
597 to window-relative coordinates.
599 X and Y are frame relative pixel coordinates. */
601 static enum window_part
602 coordinates_in_window (w, x, y)
603 register struct window *w;
604 register int *x, *y;
606 struct frame *f = XFRAME (WINDOW_FRAME (w));
607 int left_x, right_x, top_y, bottom_y;
608 enum window_part part;
609 int ux = FRAME_COLUMN_WIDTH (f);
610 int x0 = WINDOW_LEFT_EDGE_X (w);
611 int x1 = WINDOW_RIGHT_EDGE_X (w);
612 /* The width of the area where the vertical line can be dragged.
613 (Between mode lines for instance. */
614 int grabbable_width = ux;
615 int lmargin_width, rmargin_width, text_left, text_right;
617 if (*x < x0 || *x >= x1)
618 return ON_NOTHING;
620 /* In what's below, we subtract 1 when computing right_x because we
621 want the rightmost pixel, which is given by left_pixel+width-1. */
622 if (w->pseudo_window_p)
624 left_x = 0;
625 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
626 top_y = WINDOW_TOP_EDGE_Y (w);
627 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
629 else
631 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
632 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
633 top_y = WINDOW_TOP_EDGE_Y (w);
634 bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
637 /* Outside any interesting row? */
638 if (*y < top_y || *y >= bottom_y)
639 return ON_NOTHING;
641 /* On the mode line or header line? If it's near the start of
642 the mode or header line of window that's has a horizontal
643 sibling, say it's on the vertical line. That's to be able
644 to resize windows horizontally in case we're using toolkit
645 scroll bars. */
647 if (WINDOW_WANTS_MODELINE_P (w)
648 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
650 part = ON_MODE_LINE;
652 header_vertical_border_check:
653 /* We're somewhere on the mode line. We consider the place
654 between mode lines of horizontally adjacent mode lines
655 as the vertical border. If scroll bars on the left,
656 return the right window. */
657 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
658 || WINDOW_RIGHTMOST_P (w))
660 if (!WINDOW_LEFTMOST_P (w) && abs (*x - x0) < grabbable_width)
661 return ON_VERTICAL_BORDER;
663 else
665 if (abs (*x - x1) < grabbable_width)
666 return ON_VERTICAL_BORDER;
669 /* Convert X and Y to window relative coordinates.
670 Mode line starts at left edge of window. */
671 *x -= x0;
672 *y -= top_y;
673 return part;
676 if (WINDOW_WANTS_HEADER_LINE_P (w)
677 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
679 part = ON_HEADER_LINE;
680 goto header_vertical_border_check;
683 /* Outside any interesting column? */
684 if (*x < left_x || *x > right_x)
685 return ON_NOTHING;
687 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
688 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
690 text_left = window_box_left (w, TEXT_AREA);
691 text_right = text_left + window_box_width (w, TEXT_AREA);
693 if (FRAME_WINDOW_P (f))
695 if (!w->pseudo_window_p
696 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
697 && !WINDOW_RIGHTMOST_P (w)
698 && (abs (*x - right_x) < grabbable_width))
699 return ON_VERTICAL_BORDER;
701 else
703 /* Need to say "*x > right_x" rather than >=, since on character
704 terminals, the vertical line's x coordinate is right_x. */
705 if (!w->pseudo_window_p
706 && !WINDOW_RIGHTMOST_P (w)
707 && *x > right_x - ux)
709 /* On the border on the right side of the window? Assume that
710 this area begins at RIGHT_X minus a canonical char width. */
711 return ON_VERTICAL_BORDER;
715 if (*x < text_left)
717 if (lmargin_width > 0
718 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
719 ? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
720 : (*x < left_x + lmargin_width)))
722 *x -= left_x;
723 if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
724 *x -= WINDOW_LEFT_FRINGE_WIDTH (w);
725 *y -= top_y;
726 return ON_LEFT_MARGIN;
729 /* Convert X and Y to window-relative pixel coordinates. */
730 *x -= left_x;
731 *y -= top_y;
732 return ON_LEFT_FRINGE;
735 if (*x >= text_right)
737 if (rmargin_width > 0
738 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
739 ? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
740 : (*x >= right_x - rmargin_width)))
742 *x -= right_x;
743 if (!WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
744 *x -= WINDOW_RIGHT_FRINGE_WIDTH (w);
745 *y -= top_y;
746 return ON_RIGHT_MARGIN;
749 /* Convert X and Y to window-relative pixel coordinates. */
750 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
751 *y -= top_y;
752 return ON_RIGHT_FRINGE;
755 /* Everything special ruled out - must be on text area */
756 *x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
757 *y -= top_y;
758 return ON_TEXT;
762 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
763 Scoordinates_in_window_p, 2, 2, 0,
764 doc: /* Return non-nil if COORDINATES are in WINDOW.
765 COORDINATES is a cons of the form (X . Y), X and Y being distances
766 measured in characters from the upper-left corner of the frame.
767 \(0 . 0) denotes the character in the upper left corner of the
768 frame.
769 If COORDINATES are in the text portion of WINDOW,
770 the coordinates relative to the window are returned.
771 If they are in the mode line of WINDOW, `mode-line' is returned.
772 If they are in the top mode line of WINDOW, `header-line' is returned.
773 If they are in the left fringe of WINDOW, `left-fringe' is returned.
774 If they are in the right fringe of WINDOW, `right-fringe' is returned.
775 If they are on the border between WINDOW and its right sibling,
776 `vertical-line' is returned.
777 If they are in the windows's left or right marginal areas, `left-margin'\n\
778 or `right-margin' is returned. */)
779 (coordinates, window)
780 register Lisp_Object coordinates, window;
782 struct window *w;
783 struct frame *f;
784 int x, y;
785 Lisp_Object lx, ly;
787 CHECK_WINDOW (window);
788 w = XWINDOW (window);
789 f = XFRAME (w->frame);
790 CHECK_CONS (coordinates);
791 lx = Fcar (coordinates);
792 ly = Fcdr (coordinates);
793 CHECK_NUMBER_OR_FLOAT (lx);
794 CHECK_NUMBER_OR_FLOAT (ly);
795 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx);
796 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly);
798 switch (coordinates_in_window (w, &x, &y))
800 case ON_NOTHING:
801 return Qnil;
803 case ON_TEXT:
804 /* X and Y are now window relative pixel coordinates. Convert
805 them to canonical char units before returning them. */
806 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
807 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
809 case ON_MODE_LINE:
810 return Qmode_line;
812 case ON_VERTICAL_BORDER:
813 return Qvertical_line;
815 case ON_HEADER_LINE:
816 return Qheader_line;
818 case ON_LEFT_FRINGE:
819 return Qleft_fringe;
821 case ON_RIGHT_FRINGE:
822 return Qright_fringe;
824 case ON_LEFT_MARGIN:
825 return Qleft_margin;
827 case ON_RIGHT_MARGIN:
828 return Qright_margin;
830 default:
831 abort ();
836 /* Callback for foreach_window, used in window_from_coordinates.
837 Check if window W contains coordinates specified by USER_DATA which
838 is actually a pointer to a struct check_window_data CW.
840 Check if window W contains coordinates *CW->x and *CW->y. If it
841 does, return W in *CW->window, as Lisp_Object, and return in
842 *CW->part the part of the window under coordinates *X,*Y. Return
843 zero from this function to stop iterating over windows. */
845 struct check_window_data
847 Lisp_Object *window;
848 int *x, *y;
849 enum window_part *part;
852 static int
853 check_window_containing (w, user_data)
854 struct window *w;
855 void *user_data;
857 struct check_window_data *cw = (struct check_window_data *) user_data;
858 enum window_part found;
859 int continue_p = 1;
861 found = coordinates_in_window (w, cw->x, cw->y);
862 if (found != ON_NOTHING)
864 *cw->part = found;
865 XSETWINDOW (*cw->window, w);
866 continue_p = 0;
869 return continue_p;
873 /* Find the window containing frame-relative pixel position X/Y and
874 return it as a Lisp_Object.
876 If X, Y is on one of the window's special `window_part' elements,
877 set *PART to the id of that element, and return X and Y converted
878 to window relative coordinates in WX and WY.
880 If there is no window under X, Y return nil and leave *PART
881 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
883 This function was previously implemented with a loop cycling over
884 windows with Fnext_window, and starting with the frame's selected
885 window. It turned out that this doesn't work with an
886 implementation of next_window using Vwindow_list, because
887 FRAME_SELECTED_WINDOW (F) is not always contained in the window
888 tree of F when this function is called asynchronously from
889 note_mouse_highlight. The original loop didn't terminate in this
890 case. */
892 Lisp_Object
893 window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
894 struct frame *f;
895 int x, y;
896 enum window_part *part;
897 int *wx, *wy;
898 int tool_bar_p;
900 Lisp_Object window;
901 struct check_window_data cw;
902 enum window_part dummy;
904 if (part == 0)
905 part = &dummy;
907 window = Qnil;
908 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
909 foreach_window (f, check_window_containing, &cw);
911 /* If not found above, see if it's in the tool bar window, if a tool
912 bar exists. */
913 if (NILP (window)
914 && tool_bar_p
915 && WINDOWP (f->tool_bar_window)
916 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
917 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
918 != ON_NOTHING))
920 *part = ON_TEXT;
921 window = f->tool_bar_window;
924 if (wx) *wx = x;
925 if (wy) *wy = y;
927 return window;
930 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
931 doc: /* Return window containing coordinates X and Y on FRAME.
932 If omitted, FRAME defaults to the currently selected frame.
933 The top left corner of the frame is considered to be row 0,
934 column 0. */)
935 (x, y, frame)
936 Lisp_Object x, y, frame;
938 struct frame *f;
940 if (NILP (frame))
941 frame = selected_frame;
942 CHECK_LIVE_FRAME (frame);
943 f = XFRAME (frame);
945 /* Check that arguments are integers or floats. */
946 CHECK_NUMBER_OR_FLOAT (x);
947 CHECK_NUMBER_OR_FLOAT (y);
949 return window_from_coordinates (f,
950 FRAME_PIXEL_X_FROM_CANON_X (f, x),
951 FRAME_PIXEL_Y_FROM_CANON_Y (f, y),
952 0, 0, 0, 0);
955 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
956 doc: /* Return current value of point in WINDOW.
957 For a nonselected window, this is the value point would have
958 if that window were selected.
960 Note that, when WINDOW is the selected window and its buffer
961 is also currently selected, the value returned is the same as (point).
962 It would be more strictly correct to return the `top-level' value
963 of point, outside of any save-excursion forms.
964 But that is hard to define. */)
965 (window)
966 Lisp_Object window;
968 register struct window *w = decode_window (window);
970 if (w == XWINDOW (selected_window)
971 && current_buffer == XBUFFER (w->buffer))
972 return Fpoint ();
973 return Fmarker_position (w->pointm);
976 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
977 doc: /* Return position at which display currently starts in WINDOW.
978 This is updated by redisplay or by calling `set-window-start'. */)
979 (window)
980 Lisp_Object window;
982 return Fmarker_position (decode_window (window)->start);
985 /* This is text temporarily removed from the doc string below.
987 This function returns nil if the position is not currently known.
988 That happens when redisplay is preempted and doesn't finish.
989 If in that case you want to compute where the end of the window would
990 have been if redisplay had finished, do this:
991 (save-excursion
992 (goto-char (window-start window))
993 (vertical-motion (1- (window-height window)) window)
994 (point))") */
996 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
997 doc: /* Return position at which display currently ends in WINDOW.
998 This is updated by redisplay, when it runs to completion.
999 Simply changing the buffer text or setting `window-start'
1000 does not update this value.
1001 If UPDATE is non-nil, compute the up-to-date position
1002 if it isn't already recorded. */)
1003 (window, update)
1004 Lisp_Object window, update;
1006 Lisp_Object value;
1007 struct window *w = decode_window (window);
1008 Lisp_Object buf;
1010 buf = w->buffer;
1011 CHECK_BUFFER (buf);
1013 #if 0 /* This change broke some things. We should make it later. */
1014 /* If we don't know the end position, return nil.
1015 The user can compute it with vertical-motion if he wants to.
1016 It would be nicer to do it automatically,
1017 but that's so slow that it would probably bother people. */
1018 if (NILP (w->window_end_valid))
1019 return Qnil;
1020 #endif
1022 if (! NILP (update)
1023 && ! (! NILP (w->window_end_valid)
1024 && XFASTINT (w->last_modified) >= MODIFF))
1026 struct text_pos startp;
1027 struct it it;
1028 struct buffer *old_buffer = NULL, *b = XBUFFER (buf);
1030 /* In case W->start is out of the range, use something
1031 reasonable. This situation occurred when loading a file with
1032 `-l' containing a call to `rmail' with subsequent other
1033 commands. At the end, W->start happened to be BEG, while
1034 rmail had already narrowed the buffer. */
1035 if (XMARKER (w->start)->charpos < BEGV)
1036 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1037 else if (XMARKER (w->start)->charpos > ZV)
1038 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1039 else
1040 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1042 /* Cannot use Fvertical_motion because that function doesn't
1043 cope with variable-height lines. */
1044 if (b != current_buffer)
1046 old_buffer = current_buffer;
1047 set_buffer_internal (b);
1050 start_display (&it, w, startp);
1051 move_it_vertically (&it, window_box_height (w));
1052 if (it.current_y < it.last_visible_y)
1053 move_it_past_eol (&it);
1054 value = make_number (IT_CHARPOS (it));
1056 if (old_buffer)
1057 set_buffer_internal (old_buffer);
1059 else
1060 XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
1062 return value;
1065 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1066 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer. */)
1067 (window, pos)
1068 Lisp_Object window, pos;
1070 register struct window *w = decode_window (window);
1072 CHECK_NUMBER_COERCE_MARKER (pos);
1073 if (w == XWINDOW (selected_window)
1074 && XBUFFER (w->buffer) == current_buffer)
1075 Fgoto_char (pos);
1076 else
1077 set_marker_restricted (w->pointm, pos, w->buffer);
1079 /* We have to make sure that redisplay updates the window to show
1080 the new value of point. */
1081 if (!EQ (window, selected_window))
1082 ++windows_or_buffers_changed;
1084 return pos;
1087 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1088 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1089 Optional third arg NOFORCE non-nil inhibits next redisplay
1090 from overriding motion of point in order to display at this exact start. */)
1091 (window, pos, noforce)
1092 Lisp_Object window, pos, noforce;
1094 register struct window *w = decode_window (window);
1096 CHECK_NUMBER_COERCE_MARKER (pos);
1097 set_marker_restricted (w->start, pos, w->buffer);
1098 /* this is not right, but much easier than doing what is right. */
1099 w->start_at_line_beg = Qnil;
1100 if (NILP (noforce))
1101 w->force_start = Qt;
1102 w->update_mode_line = Qt;
1103 XSETFASTINT (w->last_modified, 0);
1104 XSETFASTINT (w->last_overlay_modified, 0);
1105 if (!EQ (window, selected_window))
1106 windows_or_buffers_changed++;
1108 return pos;
1111 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1112 1, 1, 0,
1113 doc: /* Return WINDOW's dedicated object, usually t or nil.
1114 See also `set-window-dedicated-p'. */)
1115 (window)
1116 Lisp_Object window;
1118 return decode_window (window)->dedicated;
1121 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1122 Sset_window_dedicated_p, 2, 2, 0,
1123 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1124 If it is dedicated, Emacs will not automatically change
1125 which buffer appears in it.
1126 The second argument is the new value for the dedication flag;
1127 non-nil means yes. */)
1128 (window, arg)
1129 Lisp_Object window, arg;
1131 register struct window *w = decode_window (window);
1133 w->dedicated = arg;
1135 return w->dedicated;
1138 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1139 0, 1, 0,
1140 doc: /* Return the display-table that WINDOW is using. */)
1141 (window)
1142 Lisp_Object window;
1144 return decode_window (window)->display_table;
1147 /* Get the display table for use on window W. This is either W's
1148 display table or W's buffer's display table. Ignore the specified
1149 tables if they are not valid; if no valid table is specified,
1150 return 0. */
1152 struct Lisp_Char_Table *
1153 window_display_table (w)
1154 struct window *w;
1156 struct Lisp_Char_Table *dp = NULL;
1158 if (DISP_TABLE_P (w->display_table))
1159 dp = XCHAR_TABLE (w->display_table);
1160 else if (BUFFERP (w->buffer))
1162 struct buffer *b = XBUFFER (w->buffer);
1164 if (DISP_TABLE_P (b->display_table))
1165 dp = XCHAR_TABLE (b->display_table);
1166 else if (DISP_TABLE_P (Vstandard_display_table))
1167 dp = XCHAR_TABLE (Vstandard_display_table);
1170 return dp;
1173 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1174 doc: /* Set WINDOW's display-table to TABLE. */)
1175 (window, table)
1176 register Lisp_Object window, table;
1178 register struct window *w;
1180 w = decode_window (window);
1181 w->display_table = table;
1182 return table;
1185 /* Record info on buffer window w is displaying
1186 when it is about to cease to display that buffer. */
1187 static void
1188 unshow_buffer (w)
1189 register struct window *w;
1191 Lisp_Object buf;
1192 struct buffer *b;
1194 buf = w->buffer;
1195 b = XBUFFER (buf);
1196 if (b != XMARKER (w->pointm)->buffer)
1197 abort ();
1199 #if 0
1200 if (w == XWINDOW (selected_window)
1201 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1202 /* Do this except when the selected window's buffer
1203 is being removed from some other window. */
1204 #endif
1205 /* last_window_start records the start position that this buffer
1206 had in the last window to be disconnected from it.
1207 Now that this statement is unconditional,
1208 it is possible for the buffer to be displayed in the
1209 selected window, while last_window_start reflects another
1210 window which was recently showing the same buffer.
1211 Some people might say that might be a good thing. Let's see. */
1212 b->last_window_start = marker_position (w->start);
1214 /* Point in the selected window's buffer
1215 is actually stored in that buffer, and the window's pointm isn't used.
1216 So don't clobber point in that buffer. */
1217 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1218 /* This line helps to fix Horsley's testbug.el bug. */
1219 && !(WINDOWP (b->last_selected_window)
1220 && w != XWINDOW (b->last_selected_window)
1221 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1222 temp_set_point_both (b,
1223 clip_to_bounds (BUF_BEGV (b),
1224 XMARKER (w->pointm)->charpos,
1225 BUF_ZV (b)),
1226 clip_to_bounds (BUF_BEGV_BYTE (b),
1227 marker_byte_position (w->pointm),
1228 BUF_ZV_BYTE (b)));
1230 if (WINDOWP (b->last_selected_window)
1231 && w == XWINDOW (b->last_selected_window))
1232 b->last_selected_window = Qnil;
1235 /* Put replacement into the window structure in place of old. */
1236 static void
1237 replace_window (old, replacement)
1238 Lisp_Object old, replacement;
1240 register Lisp_Object tem;
1241 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1243 /* If OLD is its frame's root_window, then replacement is the new
1244 root_window for that frame. */
1246 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1247 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1249 p->left_col = o->left_col;
1250 p->top_line = o->top_line;
1251 p->total_cols = o->total_cols;
1252 p->total_lines = o->total_lines;
1253 p->desired_matrix = p->current_matrix = 0;
1254 p->vscroll = 0;
1255 bzero (&p->cursor, sizeof (p->cursor));
1256 bzero (&p->last_cursor, sizeof (p->last_cursor));
1257 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1258 p->phys_cursor_type = -1;
1259 p->phys_cursor_width = -1;
1260 p->must_be_updated_p = 0;
1261 p->pseudo_window_p = 0;
1262 XSETFASTINT (p->window_end_vpos, 0);
1263 XSETFASTINT (p->window_end_pos, 0);
1264 p->window_end_valid = Qnil;
1265 p->frozen_window_start_p = 0;
1266 p->orig_top_line = p->orig_total_lines = Qnil;
1268 p->next = tem = o->next;
1269 if (!NILP (tem))
1270 XWINDOW (tem)->prev = replacement;
1272 p->prev = tem = o->prev;
1273 if (!NILP (tem))
1274 XWINDOW (tem)->next = replacement;
1276 p->parent = tem = o->parent;
1277 if (!NILP (tem))
1279 if (EQ (XWINDOW (tem)->vchild, old))
1280 XWINDOW (tem)->vchild = replacement;
1281 if (EQ (XWINDOW (tem)->hchild, old))
1282 XWINDOW (tem)->hchild = replacement;
1285 /*** Here, if replacement is a vertical combination
1286 and so is its new parent, we should make replacement's
1287 children be children of that parent instead. ***/
1290 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1291 doc: /* Remove WINDOW from the display. Default is selected window. */)
1292 (window)
1293 register Lisp_Object window;
1295 delete_window (window);
1297 if (! NILP (Vwindow_configuration_change_hook)
1298 && ! NILP (Vrun_hooks))
1299 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1301 return Qnil;
1304 void
1305 delete_window (window)
1306 register Lisp_Object window;
1308 register Lisp_Object tem, parent, sib;
1309 register struct window *p;
1310 register struct window *par;
1311 struct frame *f;
1313 /* Because this function is called by other C code on non-leaf
1314 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1315 so we can't decode_window here. */
1316 if (NILP (window))
1317 window = selected_window;
1318 else
1319 CHECK_WINDOW (window);
1320 p = XWINDOW (window);
1322 /* It's okay to delete an already-deleted window. */
1323 if (NILP (p->buffer)
1324 && NILP (p->hchild)
1325 && NILP (p->vchild))
1326 return;
1328 parent = p->parent;
1329 if (NILP (parent))
1330 error ("Attempt to delete minibuffer or sole ordinary window");
1331 par = XWINDOW (parent);
1333 windows_or_buffers_changed++;
1334 Vwindow_list = Qnil;
1335 f = XFRAME (WINDOW_FRAME (p));
1336 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1338 /* Are we trying to delete any frame's selected window? */
1340 Lisp_Object swindow, pwindow;
1342 /* See if the frame's selected window is either WINDOW
1343 or any subwindow of it, by finding all that window's parents
1344 and comparing each one with WINDOW. */
1345 swindow = FRAME_SELECTED_WINDOW (f);
1347 while (1)
1349 pwindow = swindow;
1350 while (!NILP (pwindow))
1352 if (EQ (window, pwindow))
1353 break;
1354 pwindow = XWINDOW (pwindow)->parent;
1357 /* If the window being deleted is not a parent of SWINDOW,
1358 then SWINDOW is ok as the new selected window. */
1359 if (!EQ (window, pwindow))
1360 break;
1361 /* Otherwise, try another window for SWINDOW. */
1362 swindow = Fnext_window (swindow, Qlambda, Qnil);;
1364 /* If we get back to the frame's selected window,
1365 it means there was no acceptable alternative,
1366 so we cannot delete. */
1367 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1368 error ("Cannot delete window");
1371 /* If we need to change SWINDOW, do it. */
1372 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1374 /* If we're about to delete the selected window on the
1375 selected frame, then we should use Fselect_window to select
1376 the new window. On the other hand, if we're about to
1377 delete the selected window on any other frame, we shouldn't do
1378 anything but set the frame's selected_window slot. */
1379 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1380 Fselect_window (swindow, Qnil);
1381 else
1382 FRAME_SELECTED_WINDOW (f) = swindow;
1386 tem = p->buffer;
1387 /* tem is null for dummy parent windows
1388 (which have inferiors but not any contents themselves) */
1389 if (!NILP (tem))
1391 unshow_buffer (p);
1392 unchain_marker (XMARKER (p->pointm));
1393 unchain_marker (XMARKER (p->start));
1396 /* Free window glyph matrices. It is sure that they are allocated
1397 again when ADJUST_GLYPHS is called. Block input so that expose
1398 events and other events that access glyph matrices are not
1399 processed while we are changing them. */
1400 BLOCK_INPUT;
1401 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1403 tem = p->next;
1404 if (!NILP (tem))
1405 XWINDOW (tem)->prev = p->prev;
1407 tem = p->prev;
1408 if (!NILP (tem))
1409 XWINDOW (tem)->next = p->next;
1411 if (EQ (window, par->hchild))
1412 par->hchild = p->next;
1413 if (EQ (window, par->vchild))
1414 par->vchild = p->next;
1416 /* Find one of our siblings to give our space to. */
1417 sib = p->prev;
1418 if (NILP (sib))
1420 /* If p gives its space to its next sibling, that sibling needs
1421 to have its top/left side pulled back to where p's is.
1422 set_window_{height,width} will re-position the sibling's
1423 children. */
1424 sib = p->next;
1425 XWINDOW (sib)->top_line = p->top_line;
1426 XWINDOW (sib)->left_col = p->left_col;
1429 /* Stretch that sibling. */
1430 if (!NILP (par->vchild))
1431 set_window_height (sib,
1432 XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1434 if (!NILP (par->hchild))
1435 set_window_width (sib,
1436 XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1439 /* If parent now has only one child,
1440 put the child into the parent's place. */
1441 tem = par->hchild;
1442 if (NILP (tem))
1443 tem = par->vchild;
1444 if (NILP (XWINDOW (tem)->next))
1445 replace_window (parent, tem);
1447 /* Since we may be deleting combination windows, we must make sure that
1448 not only p but all its children have been marked as deleted. */
1449 if (! NILP (p->hchild))
1450 delete_all_subwindows (XWINDOW (p->hchild));
1451 else if (! NILP (p->vchild))
1452 delete_all_subwindows (XWINDOW (p->vchild));
1454 /* Mark this window as deleted. */
1455 p->buffer = p->hchild = p->vchild = Qnil;
1457 /* Adjust glyph matrices. */
1458 adjust_glyphs (f);
1459 UNBLOCK_INPUT;
1464 /***********************************************************************
1465 Window List
1466 ***********************************************************************/
1468 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1469 pointer. This is a callback function for foreach_window, used in
1470 function window_list. */
1472 static int
1473 add_window_to_list (w, user_data)
1474 struct window *w;
1475 void *user_data;
1477 Lisp_Object *list = (Lisp_Object *) user_data;
1478 Lisp_Object window;
1479 XSETWINDOW (window, w);
1480 *list = Fcons (window, *list);
1481 return 1;
1485 /* Return a list of all windows, for use by next_window. If
1486 Vwindow_list is a list, return that list. Otherwise, build a new
1487 list, cache it in Vwindow_list, and return that. */
1489 static Lisp_Object
1490 window_list ()
1492 if (!CONSP (Vwindow_list))
1494 Lisp_Object tail;
1496 Vwindow_list = Qnil;
1497 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1499 Lisp_Object args[2];
1501 /* We are visiting windows in canonical order, and add
1502 new windows at the front of args[1], which means we
1503 have to reverse this list at the end. */
1504 args[1] = Qnil;
1505 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1506 args[0] = Vwindow_list;
1507 args[1] = Fnreverse (args[1]);
1508 Vwindow_list = Fnconc (2, args);
1512 return Vwindow_list;
1516 /* Value is non-zero if WINDOW satisfies the constraints given by
1517 OWINDOW, MINIBUF and ALL_FRAMES.
1519 MINIBUF t means WINDOW may be minibuffer windows.
1520 `lambda' means WINDOW may not be a minibuffer window.
1521 a window means a specific minibuffer window
1523 ALL_FRAMES t means search all frames,
1524 nil means search just current frame,
1525 `visible' means search just visible frames,
1526 0 means search visible and iconified frames,
1527 a window means search the frame that window belongs to,
1528 a frame means consider windows on that frame, only. */
1530 static int
1531 candidate_window_p (window, owindow, minibuf, all_frames)
1532 Lisp_Object window, owindow, minibuf, all_frames;
1534 struct window *w = XWINDOW (window);
1535 struct frame *f = XFRAME (w->frame);
1536 int candidate_p = 1;
1538 if (!BUFFERP (w->buffer))
1539 candidate_p = 0;
1540 else if (MINI_WINDOW_P (w)
1541 && (EQ (minibuf, Qlambda)
1542 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1544 /* If MINIBUF is `lambda' don't consider any mini-windows.
1545 If it is a window, consider only that one. */
1546 candidate_p = 0;
1548 else if (EQ (all_frames, Qt))
1549 candidate_p = 1;
1550 else if (NILP (all_frames))
1552 xassert (WINDOWP (owindow));
1553 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1555 else if (EQ (all_frames, Qvisible))
1557 FRAME_SAMPLE_VISIBILITY (f);
1558 candidate_p = FRAME_VISIBLE_P (f);
1560 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1562 FRAME_SAMPLE_VISIBILITY (f);
1563 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1565 else if (WINDOWP (all_frames))
1566 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1567 || EQ (XWINDOW (all_frames)->frame, w->frame)
1568 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1569 else if (FRAMEP (all_frames))
1570 candidate_p = EQ (all_frames, w->frame);
1572 return candidate_p;
1576 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1577 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1578 ALL_FRAMES. */
1580 static void
1581 decode_next_window_args (window, minibuf, all_frames)
1582 Lisp_Object *window, *minibuf, *all_frames;
1584 if (NILP (*window))
1585 *window = selected_window;
1586 else
1587 CHECK_LIVE_WINDOW (*window);
1589 /* MINIBUF nil may or may not include minibuffers. Decide if it
1590 does. */
1591 if (NILP (*minibuf))
1592 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1593 else if (!EQ (*minibuf, Qt))
1594 *minibuf = Qlambda;
1596 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1597 => count none of them, or a specific minibuffer window (the
1598 active one) to count. */
1600 /* ALL_FRAMES nil doesn't specify which frames to include. */
1601 if (NILP (*all_frames))
1602 *all_frames = (!EQ (*minibuf, Qlambda)
1603 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1604 : Qnil);
1605 else if (EQ (*all_frames, Qvisible))
1607 else if (XFASTINT (*all_frames) == 0)
1609 else if (FRAMEP (*all_frames))
1611 else if (!EQ (*all_frames, Qt))
1612 *all_frames = Qnil;
1614 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1615 search just current frame, `visible' meaning search just visible
1616 frames, 0 meaning search visible and iconified frames, or a
1617 window, meaning search the frame that window belongs to, or a
1618 frame, meaning consider windows on that frame, only. */
1622 /* Return the next or previous window of WINDOW in canonical ordering
1623 of windows. NEXT_P non-zero means return the next window. See the
1624 documentation string of next-window for the meaning of MINIBUF and
1625 ALL_FRAMES. */
1627 static Lisp_Object
1628 next_window (window, minibuf, all_frames, next_p)
1629 Lisp_Object window, minibuf, all_frames;
1630 int next_p;
1632 decode_next_window_args (&window, &minibuf, &all_frames);
1634 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1635 return the first window on the frame. */
1636 if (FRAMEP (all_frames)
1637 && !EQ (all_frames, XWINDOW (window)->frame))
1638 return Fframe_first_window (all_frames);
1640 if (next_p)
1642 Lisp_Object list;
1644 /* Find WINDOW in the list of all windows. */
1645 list = Fmemq (window, window_list ());
1647 /* Scan forward from WINDOW to the end of the window list. */
1648 if (CONSP (list))
1649 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1650 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1651 break;
1653 /* Scan from the start of the window list up to WINDOW. */
1654 if (!CONSP (list))
1655 for (list = Vwindow_list;
1656 CONSP (list) && !EQ (XCAR (list), window);
1657 list = XCDR (list))
1658 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1659 break;
1661 if (CONSP (list))
1662 window = XCAR (list);
1664 else
1666 Lisp_Object candidate, list;
1668 /* Scan through the list of windows for candidates. If there are
1669 candidate windows in front of WINDOW, the last one of these
1670 is the one we want. If there are candidates following WINDOW
1671 in the list, again the last one of these is the one we want. */
1672 candidate = Qnil;
1673 for (list = window_list (); CONSP (list); list = XCDR (list))
1675 if (EQ (XCAR (list), window))
1677 if (WINDOWP (candidate))
1678 break;
1680 else if (candidate_window_p (XCAR (list), window, minibuf,
1681 all_frames))
1682 candidate = XCAR (list);
1685 if (WINDOWP (candidate))
1686 window = candidate;
1689 return window;
1693 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1694 doc: /* Return next window after WINDOW in canonical ordering of windows.
1695 If omitted, WINDOW defaults to the selected window.
1697 Optional second arg MINIBUF t means count the minibuffer window even
1698 if not active. MINIBUF nil or omitted means count the minibuffer iff
1699 it is active. MINIBUF neither t nor nil means not to count the
1700 minibuffer even if it is active.
1702 Several frames may share a single minibuffer; if the minibuffer
1703 counts, all windows on all frames that share that minibuffer count
1704 too. Therefore, `next-window' can be used to iterate through the
1705 set of windows even when the minibuffer is on another frame. If the
1706 minibuffer does not count, only windows from WINDOW's frame count.
1708 Optional third arg ALL-FRAMES t means include windows on all frames.
1709 ALL-FRAMES nil or omitted means cycle within the frames as specified
1710 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1711 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1712 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1713 Anything else means restrict to WINDOW's frame.
1715 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1716 `next-window' to iterate through the entire cycle of acceptable
1717 windows, eventually ending up back at the window you started with.
1718 `previous-window' traverses the same cycle, in the reverse order. */)
1719 (window, minibuf, all_frames)
1720 Lisp_Object window, minibuf, all_frames;
1722 return next_window (window, minibuf, all_frames, 1);
1726 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1727 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1728 If omitted, WINDOW defaults to the selected window.
1730 Optional second arg MINIBUF t means count the minibuffer window even
1731 if not active. MINIBUF nil or omitted means count the minibuffer iff
1732 it is active. MINIBUF neither t nor nil means not to count the
1733 minibuffer even if it is active.
1735 Several frames may share a single minibuffer; if the minibuffer
1736 counts, all windows on all frames that share that minibuffer count
1737 too. Therefore, `previous-window' can be used to iterate through
1738 the set of windows even when the minibuffer is on another frame. If
1739 the minibuffer does not count, only windows from WINDOW's frame count
1741 Optional third arg ALL-FRAMES t means include windows on all frames.
1742 ALL-FRAMES nil or omitted means cycle within the frames as specified
1743 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1744 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1745 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1746 Anything else means restrict to WINDOW's frame.
1748 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1749 `previous-window' to iterate through the entire cycle of acceptable
1750 windows, eventually ending up back at the window you started with.
1751 `next-window' traverses the same cycle, in the reverse order. */)
1752 (window, minibuf, all_frames)
1753 Lisp_Object window, minibuf, all_frames;
1755 return next_window (window, minibuf, all_frames, 0);
1759 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1760 doc: /* Select the ARG'th different window on this frame.
1761 All windows on current frame are arranged in a cyclic order.
1762 This command selects the window ARG steps away in that order.
1763 A negative ARG moves in the opposite order. If the optional second
1764 argument ALL_FRAMES is non-nil, cycle through all frames. */)
1765 (arg, all_frames)
1766 Lisp_Object arg, all_frames;
1768 Lisp_Object window;
1769 int i;
1771 CHECK_NUMBER (arg);
1772 window = selected_window;
1774 for (i = XINT (arg); i > 0; --i)
1775 window = Fnext_window (window, Qnil, all_frames);
1776 for (; i < 0; ++i)
1777 window = Fprevious_window (window, Qnil, all_frames);
1779 Fselect_window (window, Qnil);
1780 return Qnil;
1784 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
1785 doc: /* Return a list of windows on FRAME, starting with WINDOW.
1786 FRAME nil or omitted means use the selected frame.
1787 WINDOW nil or omitted means use the selected window.
1788 MINIBUF t means include the minibuffer window, even if it isn't active.
1789 MINIBUF nil or omitted means include the minibuffer window only
1790 if it's active.
1791 MINIBUF neither nil nor t means never include the minibuffer window. */)
1792 (frame, minibuf, window)
1793 Lisp_Object frame, minibuf, window;
1795 if (NILP (window))
1796 window = selected_window;
1797 if (NILP (frame))
1798 frame = selected_frame;
1800 if (!EQ (frame, XWINDOW (window)->frame))
1801 error ("Window is on a different frame");
1803 return window_list_1 (window, minibuf, frame);
1807 /* Return a list of windows in canonical ordering. Arguments are like
1808 for `next-window'. */
1810 static Lisp_Object
1811 window_list_1 (window, minibuf, all_frames)
1812 Lisp_Object window, minibuf, all_frames;
1814 Lisp_Object tail, list;
1816 decode_next_window_args (&window, &minibuf, &all_frames);
1817 list = Qnil;
1819 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
1820 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
1821 list = Fcons (XCAR (tail), list);
1823 return Fnreverse (list);
1828 /* Look at all windows, performing an operation specified by TYPE
1829 with argument OBJ.
1830 If FRAMES is Qt, look at all frames;
1831 Qnil, look at just the selected frame;
1832 Qvisible, look at visible frames;
1833 a frame, just look at windows on that frame.
1834 If MINI is non-zero, perform the operation on minibuffer windows too. */
1836 enum window_loop
1838 WINDOW_LOOP_UNUSED,
1839 GET_BUFFER_WINDOW, /* Arg is buffer */
1840 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1841 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1842 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1843 GET_LARGEST_WINDOW,
1844 UNSHOW_BUFFER, /* Arg is buffer */
1845 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
1846 CHECK_ALL_WINDOWS
1849 static Lisp_Object
1850 window_loop (type, obj, mini, frames)
1851 enum window_loop type;
1852 Lisp_Object obj, frames;
1853 int mini;
1855 Lisp_Object window, windows, best_window, frame_arg;
1856 struct frame *f;
1857 struct gcpro gcpro1;
1859 /* If we're only looping through windows on a particular frame,
1860 frame points to that frame. If we're looping through windows
1861 on all frames, frame is 0. */
1862 if (FRAMEP (frames))
1863 f = XFRAME (frames);
1864 else if (NILP (frames))
1865 f = SELECTED_FRAME ();
1866 else
1867 f = NULL;
1869 if (f)
1870 frame_arg = Qlambda;
1871 else if (XFASTINT (frames) == 0)
1872 frame_arg = frames;
1873 else if (EQ (frames, Qvisible))
1874 frame_arg = frames;
1875 else
1876 frame_arg = Qt;
1878 /* frame_arg is Qlambda to stick to one frame,
1879 Qvisible to consider all visible frames,
1880 or Qt otherwise. */
1882 /* Pick a window to start with. */
1883 if (WINDOWP (obj))
1884 window = obj;
1885 else if (f)
1886 window = FRAME_SELECTED_WINDOW (f);
1887 else
1888 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1890 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
1891 GCPRO1 (windows);
1892 best_window = Qnil;
1894 for (; CONSP (windows); windows = CDR (windows))
1896 struct window *w;
1898 window = XCAR (windows);
1899 w = XWINDOW (window);
1901 /* Note that we do not pay attention here to whether the frame
1902 is visible, since Fwindow_list skips non-visible frames if
1903 that is desired, under the control of frame_arg. */
1904 if (!MINI_WINDOW_P (w)
1905 /* For UNSHOW_BUFFER, we must always consider all windows. */
1906 || type == UNSHOW_BUFFER
1907 || (mini && minibuf_level > 0))
1908 switch (type)
1910 case GET_BUFFER_WINDOW:
1911 if (EQ (w->buffer, obj)
1912 /* Don't find any minibuffer window
1913 except the one that is currently in use. */
1914 && (MINI_WINDOW_P (w)
1915 ? EQ (window, minibuf_window)
1916 : 1))
1918 if (NILP (best_window))
1919 best_window = window;
1920 else if (EQ (window, selected_window))
1921 /* For compatibility with 20.x, prefer to return
1922 selected-window. */
1923 best_window = window;
1925 break;
1927 case GET_LRU_WINDOW:
1928 /* t as arg means consider only full-width windows */
1929 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w))
1930 break;
1931 /* Ignore dedicated windows and minibuffers. */
1932 if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
1933 break;
1934 if (NILP (best_window)
1935 || (XFASTINT (XWINDOW (best_window)->use_time)
1936 > XFASTINT (w->use_time)))
1937 best_window = window;
1938 break;
1940 case DELETE_OTHER_WINDOWS:
1941 if (!EQ (window, obj))
1942 Fdelete_window (window);
1943 break;
1945 case DELETE_BUFFER_WINDOWS:
1946 if (EQ (w->buffer, obj))
1948 struct frame *f = XFRAME (WINDOW_FRAME (w));
1950 /* If this window is dedicated, and in a frame of its own,
1951 kill the frame. */
1952 if (EQ (window, FRAME_ROOT_WINDOW (f))
1953 && !NILP (w->dedicated)
1954 && other_visible_frames (f))
1956 /* Skip the other windows on this frame.
1957 There might be one, the minibuffer! */
1958 while (CONSP (XCDR (windows))
1959 && EQ (XWINDOW (XCAR (windows))->frame,
1960 XWINDOW (XCAR (XCDR (windows)))->frame))
1961 windows = XCDR (windows);
1963 /* Now we can safely delete the frame. */
1964 Fdelete_frame (w->frame, Qnil);
1966 else if (NILP (w->parent))
1968 /* If we're deleting the buffer displayed in the
1969 only window on the frame, find a new buffer to
1970 display there. */
1971 Lisp_Object buffer;
1972 buffer = Fother_buffer (obj, Qnil, w->frame);
1973 Fset_window_buffer (window, buffer, Qnil);
1974 if (EQ (window, selected_window))
1975 Fset_buffer (w->buffer);
1977 else
1978 Fdelete_window (window);
1980 break;
1982 case GET_LARGEST_WINDOW:
1984 /* Ignore dedicated windows and minibuffers. */
1985 if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
1986 break;
1988 if (NILP (best_window))
1989 best_window = window;
1990 else
1992 struct window *b = XWINDOW (best_window);
1993 if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
1994 > XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
1995 best_window = window;
1998 break;
2000 case UNSHOW_BUFFER:
2001 if (EQ (w->buffer, obj))
2003 Lisp_Object buffer;
2004 struct frame *f = XFRAME (w->frame);
2006 /* Find another buffer to show in this window. */
2007 buffer = Fother_buffer (obj, Qnil, w->frame);
2009 /* If this window is dedicated, and in a frame of its own,
2010 kill the frame. */
2011 if (EQ (window, FRAME_ROOT_WINDOW (f))
2012 && !NILP (w->dedicated)
2013 && other_visible_frames (f))
2015 /* Skip the other windows on this frame.
2016 There might be one, the minibuffer! */
2017 while (CONSP (XCDR (windows))
2018 && EQ (XWINDOW (XCAR (windows))->frame,
2019 XWINDOW (XCAR (XCDR (windows)))->frame))
2020 windows = XCDR (windows);
2022 /* Now we can safely delete the frame. */
2023 Fdelete_frame (w->frame, Qnil);
2025 else if (!NILP (w->dedicated) && !NILP (w->parent))
2027 Lisp_Object window;
2028 XSETWINDOW (window, w);
2029 /* If this window is dedicated and not the only window
2030 in its frame, then kill it. */
2031 Fdelete_window (window);
2033 else
2035 /* Otherwise show a different buffer in the window. */
2036 w->dedicated = Qnil;
2037 Fset_window_buffer (window, buffer, Qnil);
2038 if (EQ (window, selected_window))
2039 Fset_buffer (w->buffer);
2042 break;
2044 case REDISPLAY_BUFFER_WINDOWS:
2045 if (EQ (w->buffer, obj))
2047 mark_window_display_accurate (window, 0);
2048 w->update_mode_line = Qt;
2049 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2050 ++update_mode_lines;
2051 best_window = window;
2053 break;
2055 /* Check for a window that has a killed buffer. */
2056 case CHECK_ALL_WINDOWS:
2057 if (! NILP (w->buffer)
2058 && NILP (XBUFFER (w->buffer)->name))
2059 abort ();
2060 break;
2062 case WINDOW_LOOP_UNUSED:
2063 break;
2067 UNGCPRO;
2068 return best_window;
2071 /* Used for debugging. Abort if any window has a dead buffer. */
2073 void
2074 check_all_windows ()
2076 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2079 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
2080 doc: /* Return the window least recently selected or used for display.
2081 If optional argument FRAME is `visible', search all visible frames.
2082 If FRAME is 0, search all visible and iconified frames.
2083 If FRAME is t, search all frames.
2084 If FRAME is nil, search only the selected frame.
2085 If FRAME is a frame, search only that frame. */)
2086 (frame)
2087 Lisp_Object frame;
2089 register Lisp_Object w;
2090 /* First try for a window that is full-width */
2091 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
2092 if (!NILP (w) && !EQ (w, selected_window))
2093 return w;
2094 /* If none of them, try the rest */
2095 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
2098 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
2099 doc: /* Return the largest window in area.
2100 If optional argument FRAME is `visible', search all visible frames.
2101 If FRAME is 0, search all visible and iconified frames.
2102 If FRAME is t, search all frames.
2103 If FRAME is nil, search only the selected frame.
2104 If FRAME is a frame, search only that frame. */)
2105 (frame)
2106 Lisp_Object frame;
2108 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
2109 frame);
2112 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2113 doc: /* Return a window currently displaying BUFFER, or nil if none.
2114 If optional argument FRAME is `visible', search all visible frames.
2115 If optional argument FRAME is 0, search all visible and iconified frames.
2116 If FRAME is t, search all frames.
2117 If FRAME is nil, search only the selected frame.
2118 If FRAME is a frame, search only that frame. */)
2119 (buffer, frame)
2120 Lisp_Object buffer, frame;
2122 buffer = Fget_buffer (buffer);
2123 if (BUFFERP (buffer))
2124 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2125 else
2126 return Qnil;
2129 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2130 0, 1, "",
2131 doc: /* Make WINDOW (or the selected window) fill its frame.
2132 Only the frame WINDOW is on is affected.
2133 This function tries to reduce display jumps
2134 by keeping the text previously visible in WINDOW
2135 in the same place on the frame. Doing this depends on
2136 the value of (window-start WINDOW), so if calling this function
2137 in a program gives strange scrolling, make sure the window-start
2138 value is reasonable when this function is called. */)
2139 (window)
2140 Lisp_Object window;
2142 struct window *w;
2143 int startpos;
2144 int top, new_top;
2146 if (NILP (window))
2147 window = selected_window;
2148 else
2149 CHECK_LIVE_WINDOW (window);
2150 w = XWINDOW (window);
2152 startpos = marker_position (w->start);
2153 top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2155 if (MINI_WINDOW_P (w) && top > 0)
2156 error ("Can't expand minibuffer to full frame");
2158 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2160 /* Try to minimize scrolling, by setting the window start to the point
2161 will cause the text at the old window start to be at the same place
2162 on the frame. But don't try to do this if the window start is
2163 outside the visible portion (as might happen when the display is
2164 not current, due to typeahead). */
2165 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2166 if (new_top != top
2167 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2168 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2170 struct position pos;
2171 struct buffer *obuf = current_buffer;
2173 Fset_buffer (w->buffer);
2174 /* This computation used to temporarily move point, but that can
2175 have unwanted side effects due to text properties. */
2176 pos = *vmotion (startpos, -top, w);
2178 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2179 w->window_end_valid = Qnil;
2180 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2181 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2182 : Qnil);
2183 /* We need to do this, so that the window-scroll-functions
2184 get called. */
2185 w->optional_new_start = Qt;
2187 set_buffer_internal (obuf);
2190 return Qnil;
2193 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2194 1, 2, "bDelete windows on (buffer): ",
2195 doc: /* Delete all windows showing BUFFER.
2196 Optional second argument FRAME controls which frames are affected.
2197 If optional argument FRAME is `visible', search all visible frames.
2198 If FRAME is 0, search all visible and iconified frames.
2199 If FRAME is nil, search all frames.
2200 If FRAME is t, search only the selected frame.
2201 If FRAME is a frame, search only that frame. */)
2202 (buffer, frame)
2203 Lisp_Object buffer, frame;
2205 /* FRAME uses t and nil to mean the opposite of what window_loop
2206 expects. */
2207 if (NILP (frame))
2208 frame = Qt;
2209 else if (EQ (frame, Qt))
2210 frame = Qnil;
2212 if (!NILP (buffer))
2214 buffer = Fget_buffer (buffer);
2215 CHECK_BUFFER (buffer);
2216 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2219 return Qnil;
2222 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2223 Sreplace_buffer_in_windows,
2224 1, 1, "bReplace buffer in windows: ",
2225 doc: /* Replace BUFFER with some other buffer in all windows showing it. */)
2226 (buffer)
2227 Lisp_Object buffer;
2229 if (!NILP (buffer))
2231 buffer = Fget_buffer (buffer);
2232 CHECK_BUFFER (buffer);
2233 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2235 return Qnil;
2238 /* Replace BUFFER with some other buffer in all windows
2239 of all frames, even those on other keyboards. */
2241 void
2242 replace_buffer_in_all_windows (buffer)
2243 Lisp_Object buffer;
2245 #ifdef MULTI_KBOARD
2246 Lisp_Object tail, frame;
2248 /* A single call to window_loop won't do the job
2249 because it only considers frames on the current keyboard.
2250 So loop manually over frames, and handle each one. */
2251 FOR_EACH_FRAME (tail, frame)
2252 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2253 #else
2254 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2255 #endif
2258 /* Set the height of WINDOW and all its inferiors. */
2260 /* The smallest acceptable dimensions for a window. Anything smaller
2261 might crash Emacs. */
2263 #define MIN_SAFE_WINDOW_WIDTH (2)
2264 #define MIN_SAFE_WINDOW_HEIGHT (1)
2266 /* Make sure that window_min_height and window_min_width are
2267 not too small; if they are, set them to safe minima. */
2269 static void
2270 check_min_window_sizes ()
2272 /* Smaller values might permit a crash. */
2273 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2274 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2275 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2276 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2279 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2280 minimum allowable size. */
2282 void
2283 check_frame_size (frame, rows, cols)
2284 FRAME_PTR frame;
2285 int *rows, *cols;
2287 /* For height, we have to see:
2288 how many windows the frame has at minimum (one or two),
2289 and whether it has a menu bar or other special stuff at the top. */
2290 int min_height
2291 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2292 ? MIN_SAFE_WINDOW_HEIGHT
2293 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2295 if (FRAME_TOP_MARGIN (frame) > 0)
2296 min_height += FRAME_TOP_MARGIN (frame);
2298 if (*rows < min_height)
2299 *rows = min_height;
2300 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2301 *cols = MIN_SAFE_WINDOW_WIDTH;
2305 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2306 check if W's width can be changed, otherwise check W's height.
2307 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2308 siblings, too. If none of the siblings is resizable, WINDOW isn't
2309 either. */
2311 static int
2312 window_fixed_size_p (w, width_p, check_siblings_p)
2313 struct window *w;
2314 int width_p, check_siblings_p;
2316 int fixed_p;
2317 struct window *c;
2319 if (!NILP (w->hchild))
2321 c = XWINDOW (w->hchild);
2323 if (width_p)
2325 /* A horiz. combination is fixed-width if all of if its
2326 children are. */
2327 while (c && window_fixed_size_p (c, width_p, 0))
2328 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2329 fixed_p = c == NULL;
2331 else
2333 /* A horiz. combination is fixed-height if one of if its
2334 children is. */
2335 while (c && !window_fixed_size_p (c, width_p, 0))
2336 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2337 fixed_p = c != NULL;
2340 else if (!NILP (w->vchild))
2342 c = XWINDOW (w->vchild);
2344 if (width_p)
2346 /* A vert. combination is fixed-width if one of if its
2347 children is. */
2348 while (c && !window_fixed_size_p (c, width_p, 0))
2349 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2350 fixed_p = c != NULL;
2352 else
2354 /* A vert. combination is fixed-height if all of if its
2355 children are. */
2356 while (c && window_fixed_size_p (c, width_p, 0))
2357 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2358 fixed_p = c == NULL;
2361 else if (BUFFERP (w->buffer))
2363 if (w->height_fixed_p && !width_p)
2364 fixed_p = 1;
2365 else
2367 struct buffer *old = current_buffer;
2368 Lisp_Object val;
2370 current_buffer = XBUFFER (w->buffer);
2371 val = find_symbol_value (Qwindow_size_fixed);
2372 current_buffer = old;
2374 fixed_p = 0;
2375 if (!EQ (val, Qunbound))
2377 fixed_p = !NILP (val);
2379 if (fixed_p
2380 && ((EQ (val, Qheight) && width_p)
2381 || (EQ (val, Qwidth) && !width_p)))
2382 fixed_p = 0;
2386 /* Can't tell if this one is resizable without looking at
2387 siblings. If all siblings are fixed-size this one is too. */
2388 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2390 Lisp_Object child;
2392 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2393 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2394 break;
2396 if (NILP (child))
2397 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2398 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2399 break;
2401 if (NILP (child))
2402 fixed_p = 1;
2405 else
2406 fixed_p = 1;
2408 return fixed_p;
2412 /* Return the minimum size of window W, not taking fixed-width windows
2413 into account. WIDTH_P non-zero means return the minimum width,
2414 otherwise return the minimum height. If W is a combination window,
2415 compute the minimum size from the minimum sizes of W's children. */
2417 static int
2418 window_min_size_1 (w, width_p)
2419 struct window *w;
2420 int width_p;
2422 struct window *c;
2423 int size;
2425 if (!NILP (w->hchild))
2427 c = XWINDOW (w->hchild);
2428 size = 0;
2430 if (width_p)
2432 /* The min width of a horizontal combination is
2433 the sum of the min widths of its children. */
2434 while (c)
2436 size += window_min_size_1 (c, width_p);
2437 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2440 else
2442 /* The min height a horizontal combination equals
2443 the maximum of all min height of its children. */
2444 while (c)
2446 int min_size = window_min_size_1 (c, width_p);
2447 size = max (min_size, size);
2448 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2452 else if (!NILP (w->vchild))
2454 c = XWINDOW (w->vchild);
2455 size = 0;
2457 if (width_p)
2459 /* The min width of a vertical combination is
2460 the maximum of the min widths of its children. */
2461 while (c)
2463 int min_size = window_min_size_1 (c, width_p);
2464 size = max (min_size, size);
2465 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2468 else
2470 /* The min height of a vertical combination equals
2471 the sum of the min height of its children. */
2472 while (c)
2474 size += window_min_size_1 (c, width_p);
2475 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2479 else
2481 if (width_p)
2482 size = window_min_width;
2483 else
2485 if (MINI_WINDOW_P (w)
2486 || (!WINDOW_WANTS_MODELINE_P (w)
2487 && !WINDOW_WANTS_HEADER_LINE_P (w)))
2488 size = 1;
2489 else
2490 size = window_min_height;
2494 return size;
2498 /* Return the minimum size of window W, taking fixed-size windows into
2499 account. WIDTH_P non-zero means return the minimum width,
2500 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2501 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2502 unless FIXED is null. */
2504 static int
2505 window_min_size (w, width_p, ignore_fixed_p, fixed)
2506 struct window *w;
2507 int width_p, ignore_fixed_p, *fixed;
2509 int size, fixed_p;
2511 if (ignore_fixed_p)
2512 fixed_p = 0;
2513 else
2514 fixed_p = window_fixed_size_p (w, width_p, 1);
2516 if (fixed)
2517 *fixed = fixed_p;
2519 if (fixed_p)
2520 size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines);
2521 else
2522 size = window_min_size_1 (w, width_p);
2524 return size;
2528 /* Adjust the margins of window W if text area is too small.
2529 Return 1 if window width is ok after adjustment; 0 if window
2530 is still too narrow. */
2532 static int
2533 adjust_window_margins (w)
2534 struct window *w;
2536 int box_cols = (WINDOW_TOTAL_COLS (w)
2537 - WINDOW_FRINGE_COLS (w)
2538 - WINDOW_SCROLL_BAR_COLS (w));
2539 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2540 + WINDOW_RIGHT_MARGIN_COLS (w));
2542 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2543 return 1;
2545 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2546 return 0;
2548 /* Window's text area is too narrow, but reducing the window
2549 margins will fix that. */
2550 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2551 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2553 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2554 w->left_margin_cols = w->right_margin_cols
2555 = make_number (margin_cols/2);
2556 else
2557 w->right_margin_cols = make_number (margin_cols);
2559 else
2560 w->left_margin_cols = make_number (margin_cols);
2561 return 1;
2564 /* Calculate new sizes for windows in the list FORWARD when the window size
2565 goes from TOTAL to SIZE. TOTAL must be greater than SIZE.
2566 The number of windows in FORWARD is NCHILDREN, and the number that
2567 can shrink is SHRINKABLE.
2568 The minimum size a window can have is MIN_SIZE.
2569 If we are shrinking fixed windows, RESIZE_FIXED_P is non-zero.
2570 If we are shrinking columns, WIDTH_P is non-zero, otherwise we are
2571 shrinking rows.
2573 This function returns an allocated array of new sizes that the caller
2574 must free. The size -1 means the window is fixed and RESIZE_FIXED_P
2575 is zero. Array index 0 refers to the first window in FORWARD, 1 to
2576 the second, and so on.
2578 This function tries to keep windows at least at the minimum size
2579 and resize other windows before it resizes any window to zero (i.e.
2580 delete that window).
2582 Windows are resized proportional to their size, so bigger windows
2583 shrink more than smaller windows. */
2584 static int *
2585 shrink_windows (total, size, nchildren, shrinkable,
2586 min_size, resize_fixed_p, forward, width_p)
2587 int total, size, nchildren, shrinkable, min_size;
2588 int resize_fixed_p, width_p;
2589 Lisp_Object forward;
2591 int available_resize = 0;
2592 int *new_sizes;
2593 struct window *c;
2594 Lisp_Object child;
2595 int smallest = total;
2596 int total_removed = 0;
2597 int total_shrink = total - size;
2598 int i;
2600 new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
2602 for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
2604 int child_size;
2606 c = XWINDOW (child);
2607 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2609 if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
2610 new_sizes[i] = -1;
2611 else
2613 new_sizes[i] = child_size;
2614 if (child_size > min_size)
2615 available_resize += child_size - min_size;
2618 /* We might need to shrink some windows to zero. Find the smallest
2619 windows and set them to 0 until we can fulfil the new size. */
2621 while (shrinkable > 1 && size + available_resize < total)
2623 for (i = 0; i < nchildren; ++i)
2624 if (new_sizes[i] > 0 && smallest > new_sizes[i])
2625 smallest = new_sizes[i];
2627 for (i = 0; i < nchildren; ++i)
2628 if (new_sizes[i] == smallest)
2630 /* Resize this window down to zero. */
2631 new_sizes[i] = 0;
2632 if (smallest > min_size)
2633 available_resize -= smallest - min_size;
2634 available_resize += smallest;
2635 --shrinkable;
2636 total_removed += smallest;
2638 /* Out of for, just remove one window at the time and
2639 check again if we have enough space. */
2640 break;
2644 /* Now, calculate the new sizes. Try to shrink each window
2645 proportional to its size. */
2646 for (i = 0; i < nchildren; ++i)
2648 if (new_sizes[i] > min_size)
2650 int to_shrink = total_shrink*new_sizes[i]/total;
2651 if (new_sizes[i] - to_shrink < min_size)
2652 to_shrink = new_sizes[i] - min_size;
2653 new_sizes[i] -= to_shrink;
2654 total_removed += to_shrink;
2658 /* Any reminder due to rounding, we just subtract from windows
2659 that are left and still can be shrunk. */
2660 while (total_shrink > total_removed)
2662 for (i = 0; i < nchildren; ++i)
2663 if (new_sizes[i] > min_size)
2665 --new_sizes[i];
2666 ++total_removed;
2668 /* Out of for, just shrink one window at the time and
2669 check again if we have enough space. */
2670 break;
2674 return new_sizes;
2677 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2678 WINDOW's width. Resize WINDOW's children, if any, so that they
2679 keep their proportionate size relative to WINDOW. Propagate
2680 WINDOW's top or left edge position to children. Delete windows
2681 that become too small unless NODELETE_P is non-zero.
2683 If NODELETE_P is 2, that means we do delete windows that are
2684 too small, even if they were too small before! */
2686 static void
2687 size_window (window, size, width_p, nodelete_p)
2688 Lisp_Object window;
2689 int size, width_p, nodelete_p;
2691 struct window *w = XWINDOW (window);
2692 struct window *c;
2693 Lisp_Object child, *forward, *sideward;
2694 int old_size, min_size, safe_min_size;
2696 /* We test nodelete_p != 2 and nodelete_p != 1 below, so it
2697 seems like it's too soon to do this here. ++KFS. */
2698 if (nodelete_p == 2)
2699 nodelete_p = 0;
2701 check_min_window_sizes ();
2702 size = max (0, size);
2704 /* If the window has been "too small" at one point,
2705 don't delete it for being "too small" in the future.
2706 Preserve it as long as that is at all possible. */
2707 if (width_p)
2709 old_size = WINDOW_TOTAL_COLS (w);
2710 min_size = window_min_width;
2711 /* Ensure that there is room for the scroll bar and fringes!
2712 We may reduce display margins though. */
2713 safe_min_size = (MIN_SAFE_WINDOW_WIDTH
2714 + WINDOW_FRINGE_COLS (w)
2715 + WINDOW_SCROLL_BAR_COLS (w));
2717 else
2719 old_size = XINT (w->total_lines);
2720 min_size = window_min_height;
2721 safe_min_size = MIN_SAFE_WINDOW_HEIGHT;
2724 if (old_size < min_size && nodelete_p != 2)
2725 w->too_small_ok = Qt;
2727 /* Maybe delete WINDOW if it's too small. */
2728 if (nodelete_p != 1 && !NILP (w->parent))
2730 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
2731 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
2732 if (min_size < safe_min_size)
2733 min_size = safe_min_size;
2734 if (size < min_size)
2736 delete_window (window);
2737 return;
2741 /* Set redisplay hints. */
2742 w->last_modified = make_number (0);
2743 w->last_overlay_modified = make_number (0);
2744 windows_or_buffers_changed++;
2745 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
2747 if (width_p)
2749 sideward = &w->vchild;
2750 forward = &w->hchild;
2751 w->total_cols = make_number (size);
2752 adjust_window_margins (w);
2754 else
2756 sideward = &w->hchild;
2757 forward = &w->vchild;
2758 w->total_lines = make_number (size);
2759 w->orig_total_lines = Qnil;
2762 if (!NILP (*sideward))
2764 for (child = *sideward; !NILP (child); child = c->next)
2766 c = XWINDOW (child);
2767 if (width_p)
2768 c->left_col = w->left_col;
2769 else
2770 c->top_line = w->top_line;
2771 size_window (child, size, width_p, nodelete_p);
2774 else if (!NILP (*forward))
2776 int fixed_size, each, extra, n;
2777 int resize_fixed_p, nfixed;
2778 int last_pos, first_pos, nchildren, total;
2779 int *new_sizes = NULL;
2781 /* Determine the fixed-size portion of the this window, and the
2782 number of child windows. */
2783 fixed_size = nchildren = nfixed = total = 0;
2784 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
2786 int child_size;
2788 c = XWINDOW (child);
2789 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2790 total += child_size;
2792 if (window_fixed_size_p (c, width_p, 0))
2794 fixed_size += child_size;
2795 ++nfixed;
2799 /* If the new size is smaller than fixed_size, or if there
2800 aren't any resizable windows, allow resizing fixed-size
2801 windows. */
2802 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2804 /* Compute how many lines/columns to add/remove to each child. The
2805 value of extra takes care of rounding errors. */
2806 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2807 if (size < total && n > 1)
2808 new_sizes = shrink_windows (total, size, nchildren, n, min_size,
2809 resize_fixed_p, *forward, width_p);
2810 else
2812 each = (size - total) / n;
2813 extra = (size - total) - n * each;
2816 /* Compute new children heights and edge positions. */
2817 first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
2818 last_pos = first_pos;
2819 for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
2821 int new_size, old_size;
2823 c = XWINDOW (child);
2824 old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines);
2825 new_size = old_size;
2827 /* The top or left edge position of this child equals the
2828 bottom or right edge of its predecessor. */
2829 if (width_p)
2830 c->left_col = make_number (last_pos);
2831 else
2832 c->top_line = make_number (last_pos);
2834 /* If this child can be resized, do it. */
2835 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2837 new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
2838 extra = 0;
2841 /* Set new height. Note that size_window also propagates
2842 edge positions to children, so it's not a no-op if we
2843 didn't change the child's size. */
2844 size_window (child, new_size, width_p, 1);
2846 /* Remember the bottom/right edge position of this child; it
2847 will be used to set the top/left edge of the next child. */
2848 last_pos += new_size;
2851 if (new_sizes) xfree (new_sizes);
2853 /* We should have covered the parent exactly with child windows. */
2854 xassert (size == last_pos - first_pos);
2856 /* Now delete any children that became too small. */
2857 if (!nodelete_p)
2858 for (child = *forward; !NILP (child); child = c->next)
2860 int child_size;
2861 c = XWINDOW (child);
2862 child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
2863 size_window (child, child_size, width_p, 2);
2868 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2869 WINDOW's children. NODELETE non-zero means don't delete windows
2870 that become too small in the process. (The caller should check
2871 later and do so if appropriate.) */
2873 void
2874 set_window_height (window, height, nodelete)
2875 Lisp_Object window;
2876 int height;
2877 int nodelete;
2879 size_window (window, height, 0, nodelete);
2883 /* Set WINDOW's width to WIDTH, and recursively change the width of
2884 WINDOW's children. NODELETE non-zero means don't delete windows
2885 that become too small in the process. (The caller should check
2886 later and do so if appropriate.) */
2888 void
2889 set_window_width (window, width, nodelete)
2890 Lisp_Object window;
2891 int width;
2892 int nodelete;
2894 size_window (window, width, 1, nodelete);
2897 /* Change window heights in windows rooted in WINDOW by N lines. */
2899 void
2900 change_window_heights (window, n)
2901 Lisp_Object window;
2902 int n;
2904 struct window *w = XWINDOW (window);
2906 XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
2907 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
2909 if (INTEGERP (w->orig_top_line))
2910 XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
2911 if (INTEGERP (w->orig_total_lines))
2912 XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
2914 /* Handle just the top child in a vertical split. */
2915 if (!NILP (w->vchild))
2916 change_window_heights (w->vchild, n);
2918 /* Adjust all children in a horizontal split. */
2919 for (window = w->hchild; !NILP (window); window = w->next)
2921 w = XWINDOW (window);
2922 change_window_heights (window, n);
2927 int window_select_count;
2929 Lisp_Object
2930 Fset_window_buffer_unwind (obuf)
2931 Lisp_Object obuf;
2933 Fset_buffer (obuf);
2934 return Qnil;
2937 EXFUN (Fset_window_fringes, 4);
2938 EXFUN (Fset_window_scroll_bars, 4);
2940 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2941 means it's allowed to run hooks. See make_frame for a case where
2942 it's not allowed. KEEP_MARGINS_P non-zero means that the current
2943 margins, fringes, and scroll-bar settings of the window are not
2944 reset from the buffer's local settings. */
2946 void
2947 set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
2948 Lisp_Object window, buffer;
2949 int run_hooks_p, keep_margins_p;
2951 struct window *w = XWINDOW (window);
2952 struct buffer *b = XBUFFER (buffer);
2953 int count = SPECPDL_INDEX ();
2955 w->buffer = buffer;
2957 if (EQ (window, selected_window))
2958 b->last_selected_window = window;
2960 /* Update time stamps of buffer display. */
2961 if (INTEGERP (b->display_count))
2962 XSETINT (b->display_count, XINT (b->display_count) + 1);
2963 b->display_time = Fcurrent_time ();
2965 XSETFASTINT (w->window_end_pos, 0);
2966 XSETFASTINT (w->window_end_vpos, 0);
2967 bzero (&w->last_cursor, sizeof w->last_cursor);
2968 w->window_end_valid = Qnil;
2969 w->hscroll = w->min_hscroll = make_number (0);
2970 w->vscroll = 0;
2971 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
2972 set_marker_restricted (w->start,
2973 make_number (b->last_window_start),
2974 buffer);
2975 w->start_at_line_beg = Qnil;
2976 w->force_start = Qnil;
2977 XSETFASTINT (w->last_modified, 0);
2978 XSETFASTINT (w->last_overlay_modified, 0);
2979 windows_or_buffers_changed++;
2981 /* We must select BUFFER for running the window-scroll-functions.
2982 If WINDOW is selected, switch permanently.
2983 Otherwise, switch but go back to the ambient buffer afterward. */
2984 if (EQ (window, selected_window))
2985 Fset_buffer (buffer);
2986 /* We can't check ! NILP (Vwindow_scroll_functions) here
2987 because that might itself be a local variable. */
2988 else if (window_initialized)
2990 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2991 Fset_buffer (buffer);
2994 if (!keep_margins_p)
2996 /* Set left and right marginal area width etc. from buffer. */
2998 /* This may call adjust_window_margins three times, so
2999 temporarily disable window margins. */
3000 Lisp_Object save_left = w->left_margin_cols;
3001 Lisp_Object save_right = w->right_margin_cols;
3003 w->left_margin_cols = w->right_margin_cols = Qnil;
3005 Fset_window_fringes (window,
3006 b->left_fringe_width, b->right_fringe_width,
3007 b->fringes_outside_margins);
3009 Fset_window_scroll_bars (window,
3010 b->scroll_bar_width,
3011 b->vertical_scroll_bar_type, Qnil);
3013 w->left_margin_cols = save_left;
3014 w->right_margin_cols = save_right;
3016 Fset_window_margins (window,
3017 b->left_margin_cols, b->right_margin_cols);
3020 if (run_hooks_p)
3022 if (! NILP (Vwindow_scroll_functions))
3023 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3024 Fmarker_position (w->start));
3026 if (! NILP (Vwindow_configuration_change_hook)
3027 && ! NILP (Vrun_hooks))
3028 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3031 unbind_to (count, Qnil);
3035 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3036 doc: /* Make WINDOW display BUFFER as its contents.
3037 BUFFER can be a buffer or buffer name.
3038 Optional third arg KEEP_MARGINS non-nil means that WINDOW's current
3039 display margins, fringe widths, and scroll bar settings are maintained;
3040 the default is to reset these from BUFFER's local settings or the frame
3041 defaults. */)
3042 (window, buffer, keep_margins)
3043 register Lisp_Object window, buffer, keep_margins;
3045 register Lisp_Object tem;
3046 register struct window *w = decode_window (window);
3048 XSETWINDOW (window, w);
3049 buffer = Fget_buffer (buffer);
3050 CHECK_BUFFER (buffer);
3052 if (NILP (XBUFFER (buffer)->name))
3053 error ("Attempt to display deleted buffer");
3055 tem = w->buffer;
3056 if (NILP (tem))
3057 error ("Window is deleted");
3058 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
3059 is first being set up. */
3061 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3062 error ("Window is dedicated to `%s'",
3063 SDATA (XBUFFER (tem)->name));
3065 unshow_buffer (w);
3068 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3069 return Qnil;
3072 /* Note that selected_window can be nil
3073 when this is called from Fset_window_configuration. */
3075 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
3076 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
3077 If WINDOW is not already selected, also make WINDOW's buffer current.
3078 Also make WINDOW the frame's selected window.
3079 Optional second arg NORECORD non-nil means
3080 do not put this buffer at the front of the list of recently selected ones.
3082 Note that the main editor command loop
3083 selects the buffer of the selected window before each command. */)
3084 (window, norecord)
3085 register Lisp_Object window, norecord;
3087 register struct window *w;
3088 register struct window *ow;
3089 struct frame *sf;
3091 CHECK_LIVE_WINDOW (window);
3093 w = XWINDOW (window);
3094 w->frozen_window_start_p = 0;
3096 XSETFASTINT (w->use_time, ++window_select_count);
3097 if (EQ (window, selected_window))
3098 return window;
3100 if (!NILP (selected_window))
3102 ow = XWINDOW (selected_window);
3103 if (! NILP (ow->buffer))
3104 set_marker_both (ow->pointm, ow->buffer,
3105 BUF_PT (XBUFFER (ow->buffer)),
3106 BUF_PT_BYTE (XBUFFER (ow->buffer)));
3109 selected_window = window;
3110 sf = SELECTED_FRAME ();
3111 if (XFRAME (WINDOW_FRAME (w)) != sf)
3113 XFRAME (WINDOW_FRAME (w))->selected_window = window;
3114 /* Use this rather than Fhandle_switch_frame
3115 so that FRAME_FOCUS_FRAME is moved appropriately as we
3116 move around in the state where a minibuffer in a separate
3117 frame is active. */
3118 Fselect_frame (WINDOW_FRAME (w), Qnil);
3120 else
3121 sf->selected_window = window;
3123 if (NILP (norecord))
3124 record_buffer (w->buffer);
3125 Fset_buffer (w->buffer);
3127 XBUFFER (w->buffer)->last_selected_window = window;
3129 /* Go to the point recorded in the window.
3130 This is important when the buffer is in more
3131 than one window. It also matters when
3132 redisplay_window has altered point after scrolling,
3133 because it makes the change only in the window. */
3135 register int new_point = marker_position (w->pointm);
3136 if (new_point < BEGV)
3137 SET_PT (BEGV);
3138 else if (new_point > ZV)
3139 SET_PT (ZV);
3140 else
3141 SET_PT (new_point);
3144 windows_or_buffers_changed++;
3145 return window;
3148 static Lisp_Object
3149 select_window_norecord (window)
3150 Lisp_Object window;
3152 return Fselect_window (window, Qt);
3155 /* Deiconify the frame containing the window WINDOW,
3156 unless it is the selected frame;
3157 then return WINDOW.
3159 The reason for the exception for the selected frame
3160 is that it seems better not to change the selected frames visibility
3161 merely because of displaying a different buffer in it.
3162 The deiconification is useful when a buffer gets shown in
3163 another frame that you were not using lately. */
3165 static Lisp_Object
3166 display_buffer_1 (window)
3167 Lisp_Object window;
3169 Lisp_Object frame = XWINDOW (window)->frame;
3170 FRAME_PTR f = XFRAME (frame);
3172 FRAME_SAMPLE_VISIBILITY (f);
3174 if (EQ (frame, selected_frame))
3175 ; /* Assume the selected frame is already visible enough. */
3176 else if (minibuf_level > 0
3177 && MINI_WINDOW_P (XWINDOW (selected_window))
3178 && WINDOW_LIVE_P (minibuf_selected_window)
3179 && EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
3180 ; /* Assume the frame from which we invoked the minibuffer is visible. */
3181 else
3183 if (FRAME_ICONIFIED_P (f))
3184 Fmake_frame_visible (frame);
3185 else if (FRAME_VISIBLE_P (f))
3186 Fraise_frame (frame);
3189 return window;
3192 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
3193 doc: /* Returns non-nil if a buffer named BUFFER-NAME would be created specially.
3194 The value is actually t if the frame should be called with default frame
3195 parameters, and a list of frame parameters if they were specified.
3196 See `special-display-buffer-names', and `special-display-regexps'. */)
3197 (buffer_name)
3198 Lisp_Object buffer_name;
3200 Lisp_Object tem;
3202 CHECK_STRING (buffer_name);
3204 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
3205 if (!NILP (tem))
3206 return Qt;
3208 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
3209 if (!NILP (tem))
3210 return XCDR (tem);
3212 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
3214 Lisp_Object car = XCAR (tem);
3215 if (STRINGP (car)
3216 && fast_string_match (car, buffer_name) >= 0)
3217 return Qt;
3218 else if (CONSP (car)
3219 && STRINGP (XCAR (car))
3220 && fast_string_match (XCAR (car), buffer_name) >= 0)
3221 return XCDR (car);
3223 return Qnil;
3226 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
3227 doc: /* Returns non-nil if a new buffer named BUFFER-NAME would use the same window.
3228 See `same-window-buffer-names' and `same-window-regexps'. */)
3229 (buffer_name)
3230 Lisp_Object buffer_name;
3232 Lisp_Object tem;
3234 CHECK_STRING (buffer_name);
3236 tem = Fmember (buffer_name, Vsame_window_buffer_names);
3237 if (!NILP (tem))
3238 return Qt;
3240 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
3241 if (!NILP (tem))
3242 return Qt;
3244 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
3246 Lisp_Object car = XCAR (tem);
3247 if (STRINGP (car)
3248 && fast_string_match (car, buffer_name) >= 0)
3249 return Qt;
3250 else if (CONSP (car)
3251 && STRINGP (XCAR (car))
3252 && fast_string_match (XCAR (car), buffer_name) >= 0)
3253 return Qt;
3255 return Qnil;
3258 /* Use B so the default is (other-buffer). */
3259 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
3260 "BDisplay buffer: \nP",
3261 doc: /* Make BUFFER appear in some window but don't select it.
3262 BUFFER can be a buffer or a buffer name.
3263 If BUFFER is shown already in some window, just use that one,
3264 unless the window is the selected window and the optional second
3265 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
3266 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
3267 Returns the window displaying BUFFER.
3268 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
3269 displaying BUFFER, then simply raise that frame.
3271 The variables `special-display-buffer-names',
3272 `special-display-regexps', `same-window-buffer-names', and
3273 `same-window-regexps' customize how certain buffer names are handled.
3274 The latter two take effect only if NOT-THIS-WINDOW is t.
3276 If optional argument FRAME is `visible', search all visible frames.
3277 If FRAME is 0, search all visible and iconified frames.
3278 If FRAME is t, search all frames.
3279 If FRAME is a frame, search only that frame.
3280 If FRAME is nil, search only the selected frame
3281 (actually the last nonminibuffer frame),
3282 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
3283 which means search visible and iconified frames.
3285 If `even-window-heights' is non-nil, window heights will be evened out
3286 if displaying the buffer causes two vertically adjacent windows to be
3287 displayed. */)
3288 (buffer, not_this_window, frame)
3289 register Lisp_Object buffer, not_this_window, frame;
3291 register Lisp_Object window, tem, swp;
3292 struct frame *f;
3294 swp = Qnil;
3295 buffer = Fget_buffer (buffer);
3296 CHECK_BUFFER (buffer);
3298 if (!NILP (Vdisplay_buffer_function))
3299 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3301 if (NILP (not_this_window)
3302 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3303 return display_buffer_1 (selected_window);
3305 /* See if the user has specified this buffer should appear
3306 in the selected window. */
3307 if (NILP (not_this_window))
3309 swp = Fsame_window_p (XBUFFER (buffer)->name);
3310 if (!NILP (swp) && !no_switch_window (selected_window))
3312 Fswitch_to_buffer (buffer, Qnil);
3313 return display_buffer_1 (selected_window);
3317 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3318 look for a window showing BUFFER on any visible or iconified frame.
3319 Otherwise search only the current frame. */
3320 if (! NILP (frame))
3321 tem = frame;
3322 else if (pop_up_frames
3323 || display_buffer_reuse_frames
3324 || last_nonminibuf_frame == 0)
3325 XSETFASTINT (tem, 0);
3326 else
3327 XSETFRAME (tem, last_nonminibuf_frame);
3329 window = Fget_buffer_window (buffer, tem);
3330 if (!NILP (window)
3331 && (NILP (not_this_window) || !EQ (window, selected_window)))
3332 return display_buffer_1 (window);
3334 /* Certain buffer names get special handling. */
3335 if (!NILP (Vspecial_display_function) && NILP (swp))
3337 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3338 if (EQ (tem, Qt))
3339 return call1 (Vspecial_display_function, buffer);
3340 if (CONSP (tem))
3341 return call2 (Vspecial_display_function, buffer, tem);
3344 /* If there are no frames open that have more than a minibuffer,
3345 we need to create a new frame. */
3346 if (pop_up_frames || last_nonminibuf_frame == 0)
3348 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3349 Fset_window_buffer (window, buffer, Qnil);
3350 return display_buffer_1 (window);
3353 f = SELECTED_FRAME ();
3354 if (pop_up_windows
3355 || FRAME_MINIBUF_ONLY_P (f)
3356 /* If the current frame is a special display frame,
3357 don't try to reuse its windows. */
3358 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3360 Lisp_Object frames;
3362 frames = Qnil;
3363 if (FRAME_MINIBUF_ONLY_P (f))
3364 XSETFRAME (frames, last_nonminibuf_frame);
3365 /* Don't try to create a window if we would get an error. */
3366 if (split_height_threshold < window_min_height << 1)
3367 split_height_threshold = window_min_height << 1;
3369 /* Note that both Fget_largest_window and Fget_lru_window
3370 ignore minibuffers and dedicated windows.
3371 This means they can return nil. */
3373 /* If the frame we would try to split cannot be split,
3374 try other frames. */
3375 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3377 /* Try visible frames first. */
3378 window = Fget_largest_window (Qvisible);
3379 /* If that didn't work, try iconified frames. */
3380 if (NILP (window))
3381 window = Fget_largest_window (make_number (0));
3382 if (NILP (window))
3383 window = Fget_largest_window (Qt);
3385 else
3386 window = Fget_largest_window (frames);
3388 /* If we got a tall enough full-width window that can be split,
3389 split it. */
3390 if (!NILP (window)
3391 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3392 && window_height (window) >= split_height_threshold
3393 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
3394 window = Fsplit_window (window, Qnil, Qnil);
3395 else
3397 Lisp_Object upper, lower, other;
3399 window = Fget_lru_window (frames);
3400 /* If the LRU window is selected, and big enough,
3401 and can be split, split it. */
3402 if (!NILP (window)
3403 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3404 && (EQ (window, selected_window)
3405 || EQ (XWINDOW (window)->parent, Qnil))
3406 && window_height (window) >= window_min_height << 1)
3407 window = Fsplit_window (window, Qnil, Qnil);
3408 /* If Fget_lru_window returned nil, try other approaches. */
3410 /* Try visible frames first. */
3411 if (NILP (window))
3412 window = Fget_buffer_window (buffer, Qvisible);
3413 if (NILP (window))
3414 window = Fget_largest_window (Qvisible);
3415 /* If that didn't work, try iconified frames. */
3416 if (NILP (window))
3417 window = Fget_buffer_window (buffer, make_number (0));
3418 if (NILP (window))
3419 window = Fget_largest_window (make_number (0));
3420 /* Try invisible frames. */
3421 if (NILP (window))
3422 window = Fget_buffer_window (buffer, Qt);
3423 if (NILP (window))
3424 window = Fget_largest_window (Qt);
3425 /* As a last resort, make a new frame. */
3426 if (NILP (window))
3427 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3428 /* If window appears above or below another,
3429 even out their heights. */
3430 other = upper = lower = Qnil;
3431 if (!NILP (XWINDOW (window)->prev))
3432 other = upper = XWINDOW (window)->prev, lower = window;
3433 if (!NILP (XWINDOW (window)->next))
3434 other = lower = XWINDOW (window)->next, upper = window;
3435 if (!NILP (other)
3436 && !NILP (Veven_window_heights)
3437 /* Check that OTHER and WINDOW are vertically arrayed. */
3438 && !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
3439 && (XFASTINT (XWINDOW (other)->total_lines)
3440 > XFASTINT (XWINDOW (window)->total_lines)))
3442 int total = (XFASTINT (XWINDOW (other)->total_lines)
3443 + XFASTINT (XWINDOW (window)->total_lines));
3444 enlarge_window (upper,
3445 total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
3446 0, 0);
3450 else
3451 window = Fget_lru_window (Qnil);
3453 Fset_window_buffer (window, buffer, Qnil);
3454 return display_buffer_1 (window);
3458 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3459 0, 1, 0,
3460 doc: /* Force redisplay of all windows.
3461 If optional arg OBJECT is a window, force redisplay of that window only.
3462 If OBJECT is a buffer or buffer name, force redisplay of all windows
3463 displaying that buffer. */)
3464 (object)
3465 Lisp_Object object;
3467 if (NILP (object))
3469 windows_or_buffers_changed++;
3470 update_mode_lines++;
3471 return Qt;
3474 if (WINDOWP (object))
3476 struct window *w = XWINDOW (object);
3477 mark_window_display_accurate (object, 0);
3478 w->update_mode_line = Qt;
3479 if (BUFFERP (w->buffer))
3480 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3481 ++update_mode_lines;
3482 return Qt;
3485 if (STRINGP (object))
3486 object = Fget_buffer (object);
3487 if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
3489 /* Walk all windows looking for buffer, and force update
3490 of each of those windows. */
3492 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3493 return NILP (object) ? Qnil : Qt;
3496 /* If nothing suitable was found, just return.
3497 We could signal an error, but this feature will typically be used
3498 asynchronously in timers or process sentinels, so we don't. */
3499 return Qnil;
3503 void
3504 temp_output_buffer_show (buf)
3505 register Lisp_Object buf;
3507 register struct buffer *old = current_buffer;
3508 register Lisp_Object window;
3509 register struct window *w;
3511 XBUFFER (buf)->directory = current_buffer->directory;
3513 Fset_buffer (buf);
3514 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3515 BEGV = BEG;
3516 ZV = Z;
3517 SET_PT (BEG);
3518 #if 0 /* rms: there should be no reason for this. */
3519 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3520 #endif
3521 set_buffer_internal (old);
3523 if (!EQ (Vtemp_buffer_show_function, Qnil))
3524 call1 (Vtemp_buffer_show_function, buf);
3525 else
3527 window = Fdisplay_buffer (buf, Qnil, Qnil);
3529 if (!EQ (XWINDOW (window)->frame, selected_frame))
3530 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3531 Vminibuf_scroll_window = window;
3532 w = XWINDOW (window);
3533 XSETFASTINT (w->hscroll, 0);
3534 XSETFASTINT (w->min_hscroll, 0);
3535 set_marker_restricted_both (w->start, buf, BEG, BEG);
3536 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3538 /* Run temp-buffer-show-hook, with the chosen window selected
3539 and its buffer current. */
3541 if (!NILP (Vrun_hooks)
3542 && !NILP (Fboundp (Qtemp_buffer_show_hook))
3543 && !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
3545 int count = SPECPDL_INDEX ();
3546 Lisp_Object prev_window, prev_buffer;
3547 prev_window = selected_window;
3548 XSETBUFFER (prev_buffer, old);
3550 /* Select the window that was chosen, for running the hook.
3551 Note: Both Fselect_window and select_window_norecord may
3552 set-buffer to the buffer displayed in the window,
3553 so we need to save the current buffer. --stef */
3554 record_unwind_protect (Fset_buffer, prev_buffer);
3555 record_unwind_protect (select_window_norecord, prev_window);
3556 Fselect_window (window, Qt);
3557 Fset_buffer (w->buffer);
3558 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3559 unbind_to (count, Qnil);
3564 static void
3565 make_dummy_parent (window)
3566 Lisp_Object window;
3568 Lisp_Object new;
3569 register struct window *o, *p;
3570 int i;
3572 o = XWINDOW (window);
3573 p = allocate_window ();
3574 for (i = 0; i < VECSIZE (struct window); ++i)
3575 ((struct Lisp_Vector *) p)->contents[i]
3576 = ((struct Lisp_Vector *)o)->contents[i];
3577 XSETWINDOW (new, p);
3579 XSETFASTINT (p->sequence_number, ++sequence_number);
3581 /* Put new into window structure in place of window */
3582 replace_window (window, new);
3584 o->next = Qnil;
3585 o->prev = Qnil;
3586 o->vchild = Qnil;
3587 o->hchild = Qnil;
3588 o->parent = new;
3590 p->start = Qnil;
3591 p->pointm = Qnil;
3592 p->buffer = Qnil;
3595 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3596 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3597 WINDOW defaults to selected one and SIZE to half its size.
3598 If optional third arg HORFLAG is non-nil, split side by side
3599 and put SIZE columns in the first of the pair. In that case,
3600 SIZE includes that window's scroll bar, or the divider column to its right. */)
3601 (window, size, horflag)
3602 Lisp_Object window, size, horflag;
3604 register Lisp_Object new;
3605 register struct window *o, *p;
3606 FRAME_PTR fo;
3607 register int size_int;
3609 if (NILP (window))
3610 window = selected_window;
3611 else
3612 CHECK_LIVE_WINDOW (window);
3614 o = XWINDOW (window);
3615 fo = XFRAME (WINDOW_FRAME (o));
3617 if (NILP (size))
3619 if (!NILP (horflag))
3620 /* Calculate the size of the left-hand window, by dividing
3621 the usable space in columns by two.
3622 We round up, since the left-hand window may include
3623 a dividing line, while the right-hand may not. */
3624 size_int = (XFASTINT (o->total_cols) + 1) >> 1;
3625 else
3626 size_int = XFASTINT (o->total_lines) >> 1;
3628 else
3630 CHECK_NUMBER (size);
3631 size_int = XINT (size);
3634 if (MINI_WINDOW_P (o))
3635 error ("Attempt to split minibuffer window");
3636 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3637 error ("Attempt to split fixed-size window");
3639 check_min_window_sizes ();
3641 if (NILP (horflag))
3643 if (size_int < window_min_height)
3644 error ("Window height %d too small (after splitting)", size_int);
3645 if (size_int + window_min_height > XFASTINT (o->total_lines))
3646 error ("Window height %d too small (after splitting)",
3647 XFASTINT (o->total_lines) - size_int);
3648 if (NILP (o->parent)
3649 || NILP (XWINDOW (o->parent)->vchild))
3651 make_dummy_parent (window);
3652 new = o->parent;
3653 XWINDOW (new)->vchild = window;
3656 else
3658 if (size_int < window_min_width)
3659 error ("Window width %d too small (after splitting)", size_int);
3661 if (size_int + window_min_width > XFASTINT (o->total_cols))
3662 error ("Window width %d too small (after splitting)",
3663 XFASTINT (o->total_cols) - size_int);
3664 if (NILP (o->parent)
3665 || NILP (XWINDOW (o->parent)->hchild))
3667 make_dummy_parent (window);
3668 new = o->parent;
3669 XWINDOW (new)->hchild = window;
3673 /* Now we know that window's parent is a vertical combination
3674 if we are dividing vertically, or a horizontal combination
3675 if we are making side-by-side windows */
3677 windows_or_buffers_changed++;
3678 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3679 new = make_window ();
3680 p = XWINDOW (new);
3682 p->frame = o->frame;
3683 p->next = o->next;
3684 if (!NILP (p->next))
3685 XWINDOW (p->next)->prev = new;
3686 p->prev = window;
3687 o->next = new;
3688 p->parent = o->parent;
3689 p->buffer = Qt;
3690 p->window_end_valid = Qnil;
3691 bzero (&p->last_cursor, sizeof p->last_cursor);
3693 /* Duplicate special geometry settings. */
3695 p->left_margin_cols = o->left_margin_cols;
3696 p->right_margin_cols = o->right_margin_cols;
3697 p->left_fringe_width = o->left_fringe_width;
3698 p->right_fringe_width = o->right_fringe_width;
3699 p->fringes_outside_margins = o->fringes_outside_margins;
3700 p->scroll_bar_width = o->scroll_bar_width;
3701 p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
3703 /* Apportion the available frame space among the two new windows */
3705 if (!NILP (horflag))
3707 p->total_lines = o->total_lines;
3708 p->top_line = o->top_line;
3709 XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
3710 XSETFASTINT (o->total_cols, size_int);
3711 XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
3712 adjust_window_margins (p);
3713 adjust_window_margins (o);
3715 else
3717 p->left_col = o->left_col;
3718 p->total_cols = o->total_cols;
3719 XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
3720 XSETFASTINT (o->total_lines, size_int);
3721 XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
3724 /* Adjust glyph matrices. */
3725 adjust_glyphs (fo);
3727 Fset_window_buffer (new, o->buffer, Qt);
3728 return new;
3731 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 3, "p",
3732 doc: /* Make current window ARG lines bigger.
3733 From program, optional second arg non-nil means grow sideways ARG columns.
3734 Interactively, if an argument is not given, make the window one line bigger.
3736 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3737 of the siblings above or to the left of the selected window. Only
3738 siblings to the right or below are changed. */)
3739 (arg, side, preserve_before)
3740 register Lisp_Object arg, side, preserve_before;
3742 CHECK_NUMBER (arg);
3743 enlarge_window (selected_window, XINT (arg), !NILP (side),
3744 !NILP (preserve_before));
3746 if (! NILP (Vwindow_configuration_change_hook))
3747 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3749 return Qnil;
3752 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 3, "p",
3753 doc: /* Make current window ARG lines smaller.
3754 From program, optional second arg non-nil means shrink sideways arg columns.
3755 Interactively, if an argument is not given, make the window one line smaller.
3757 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3758 of the siblings above or to the left of the selected window. Only
3759 siblings to the right or below are changed. */)
3760 (arg, side, preserve_before)
3761 register Lisp_Object arg, side, preserve_before;
3763 CHECK_NUMBER (arg);
3764 enlarge_window (selected_window, -XINT (arg), !NILP (side),
3765 !NILP (preserve_before));
3767 if (! NILP (Vwindow_configuration_change_hook))
3768 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3770 return Qnil;
3774 window_height (window)
3775 Lisp_Object window;
3777 register struct window *p = XWINDOW (window);
3778 return WINDOW_TOTAL_LINES (p);
3782 window_width (window)
3783 Lisp_Object window;
3785 register struct window *p = XWINDOW (window);
3786 return WINDOW_TOTAL_COLS (p);
3790 #define CURBEG(w) \
3791 *(widthflag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
3793 #define CURSIZE(w) \
3794 *(widthflag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
3797 /* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means
3798 increase its width. Siblings of the selected window are resized to
3799 fulfill the size request. If they become too small in the process,
3800 they will be deleted.
3802 If PRESERVE_BEFORE is nonzero, that means don't alter
3803 the siblings to the left or above WINDOW. */
3805 static void
3806 enlarge_window (window, delta, widthflag, preserve_before)
3807 Lisp_Object window;
3808 int delta, widthflag, preserve_before;
3810 Lisp_Object parent, next, prev;
3811 struct window *p;
3812 Lisp_Object *sizep;
3813 int maximum;
3814 int (*sizefun) P_ ((Lisp_Object))
3815 = widthflag ? window_width : window_height;
3816 void (*setsizefun) P_ ((Lisp_Object, int, int))
3817 = (widthflag ? set_window_width : set_window_height);
3819 /* Check values of window_min_width and window_min_height for
3820 validity. */
3821 check_min_window_sizes ();
3823 /* Give up if this window cannot be resized. */
3824 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3825 error ("Window is not resizable");
3827 /* Find the parent of the selected window. */
3828 while (1)
3830 p = XWINDOW (window);
3831 parent = p->parent;
3833 if (NILP (parent))
3835 if (widthflag)
3836 error ("No other window to side of this one");
3837 break;
3840 if (widthflag
3841 ? !NILP (XWINDOW (parent)->hchild)
3842 : !NILP (XWINDOW (parent)->vchild))
3843 break;
3845 window = parent;
3848 sizep = &CURSIZE (window);
3851 register int maxdelta;
3853 /* Compute the maximum size increment this window can have. */
3855 if (preserve_before)
3857 if (!NILP (parent))
3859 maxdelta = (*sizefun) (parent) - XINT (*sizep);
3860 /* Subtract size of siblings before, since we can't take that. */
3861 maxdelta -= XINT (CURBEG (window)) - XINT (CURBEG (parent));
3863 else
3864 maxdelta = (!NILP (p->next) ? ((*sizefun) (p->next)
3865 - window_min_size (XWINDOW (p->next),
3866 widthflag, 0, 0))
3867 : (delta = 0));
3869 else
3870 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
3871 /* This is a main window followed by a minibuffer. */
3872 : !NILP (p->next) ? ((*sizefun) (p->next)
3873 - window_min_size (XWINDOW (p->next),
3874 widthflag, 0, 0))
3875 /* This is a minibuffer following a main window. */
3876 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3877 - window_min_size (XWINDOW (p->prev),
3878 widthflag, 0, 0))
3879 /* This is a frame with only one window, a minibuffer-only
3880 or a minibufferless frame. */
3881 : (delta = 0));
3883 if (delta > maxdelta)
3884 /* This case traps trying to make the minibuffer
3885 the full frame, or make the only window aside from the
3886 minibuffer the full frame. */
3887 delta = maxdelta;
3890 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3892 delete_window (window);
3893 return;
3896 if (delta == 0)
3897 return;
3899 /* Find the total we can get from other siblings without deleting them. */
3900 maximum = 0;
3901 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3902 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3903 widthflag, 0, 0);
3904 if (! preserve_before)
3905 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3906 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3907 widthflag, 0, 0);
3909 /* If we can get it all from them without deleting them, do so. */
3910 if (delta <= maximum)
3912 Lisp_Object first_unaffected;
3913 Lisp_Object first_affected;
3914 int fixed_p;
3916 next = p->next;
3917 prev = p->prev;
3918 first_affected = window;
3919 /* Look at one sibling at a time,
3920 moving away from this window in both directions alternately,
3921 and take as much as we can get without deleting that sibling. */
3922 while (delta != 0
3923 && (!NILP (next) || (!preserve_before && !NILP (prev))))
3925 if (! NILP (next))
3927 int this_one = ((*sizefun) (next)
3928 - window_min_size (XWINDOW (next),
3929 widthflag, 0, &fixed_p));
3930 if (!fixed_p)
3932 if (this_one > delta)
3933 this_one = delta;
3935 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3936 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3938 delta -= this_one;
3941 next = XWINDOW (next)->next;
3944 if (delta == 0)
3945 break;
3947 if (!preserve_before && ! NILP (prev))
3949 int this_one = ((*sizefun) (prev)
3950 - window_min_size (XWINDOW (prev),
3951 widthflag, 0, &fixed_p));
3952 if (!fixed_p)
3954 if (this_one > delta)
3955 this_one = delta;
3957 first_affected = prev;
3959 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3960 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3962 delta -= this_one;
3965 prev = XWINDOW (prev)->prev;
3969 xassert (delta == 0);
3971 /* Now recalculate the edge positions of all the windows affected,
3972 based on the new sizes. */
3973 first_unaffected = next;
3974 prev = first_affected;
3975 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3976 prev = next, next = XWINDOW (next)->next)
3978 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
3979 /* This does not change size of NEXT,
3980 but it propagates the new top edge to its children */
3981 (*setsizefun) (next, (*sizefun) (next), 0);
3984 else
3986 register int delta1;
3987 register int opht = (*sizefun) (parent);
3989 if (opht <= XINT (*sizep) + delta)
3991 /* If trying to grow this window to or beyond size of the parent,
3992 just delete all the sibling windows. */
3993 Lisp_Object start, tem, next;
3995 start = XWINDOW (parent)->vchild;
3996 if (NILP (start))
3997 start = XWINDOW (parent)->hchild;
3999 /* Delete any siblings that come after WINDOW. */
4000 tem = XWINDOW (window)->next;
4001 while (! NILP (tem))
4003 next = XWINDOW (tem)->next;
4004 delete_window (tem);
4005 tem = next;
4008 /* Delete any siblings that come after WINDOW.
4009 Note that if START is not WINDOW, then WINDOW still
4010 Fhas siblings, so WINDOW has not yet replaced its parent. */
4011 tem = start;
4012 while (! EQ (tem, window))
4014 next = XWINDOW (tem)->next;
4015 delete_window (tem);
4016 tem = next;
4019 else
4021 /* Otherwise, make delta1 just right so that if we add
4022 delta1 lines to this window and to the parent, and then
4023 shrink the parent back to its original size, the new
4024 proportional size of this window will increase by delta.
4026 The function size_window will compute the new height h'
4027 of the window from delta1 as:
4029 e = delta1/n
4030 x = delta1 - delta1/n * n for the 1st resizable child
4031 h' = h + e + x
4033 where n is the number of children that can be resized.
4034 We can ignore x by choosing a delta1 that is a multiple of
4035 n. We want the height of this window to come out as
4037 h' = h + delta
4039 So, delta1 must be
4041 h + e = h + delta
4042 delta1/n = delta
4043 delta1 = n * delta.
4045 The number of children n equals the number of resizable
4046 children of this window + 1 because we know window itself
4047 is resizable (otherwise we would have signalled an error. */
4049 struct window *w = XWINDOW (window);
4050 Lisp_Object s;
4051 int n = 1;
4053 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
4054 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
4055 ++n;
4056 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
4057 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
4058 ++n;
4060 delta1 = n * delta;
4062 /* Add delta1 lines or columns to this window, and to the parent,
4063 keeping things consistent while not affecting siblings. */
4064 XSETINT (CURSIZE (parent), opht + delta1);
4065 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
4067 /* Squeeze out delta1 lines or columns from our parent,
4068 shriking this window and siblings proportionately.
4069 This brings parent back to correct size.
4070 Delta1 was calculated so this makes this window the desired size,
4071 taking it all out of the siblings. */
4072 (*setsizefun) (parent, opht, 0);
4077 XSETFASTINT (p->last_modified, 0);
4078 XSETFASTINT (p->last_overlay_modified, 0);
4080 /* Adjust glyph matrices. */
4081 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
4084 #undef CURBEG
4085 #undef CURSIZE
4089 /***********************************************************************
4090 Resizing Mini-Windows
4091 ***********************************************************************/
4093 static void shrink_window_lowest_first P_ ((struct window *, int));
4095 enum save_restore_action
4097 CHECK_ORIG_SIZES,
4098 SAVE_ORIG_SIZES,
4099 RESTORE_ORIG_SIZES
4102 static int save_restore_orig_size P_ ((struct window *,
4103 enum save_restore_action));
4105 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
4106 from lowest windows first. */
4108 static void
4109 shrink_window_lowest_first (w, height)
4110 struct window *w;
4111 int height;
4113 struct window *c;
4114 Lisp_Object child;
4115 int old_height;
4117 xassert (!MINI_WINDOW_P (w));
4119 /* Set redisplay hints. */
4120 XSETFASTINT (w->last_modified, 0);
4121 XSETFASTINT (w->last_overlay_modified, 0);
4122 windows_or_buffers_changed++;
4123 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
4125 old_height = XFASTINT (w->total_lines);
4126 XSETFASTINT (w->total_lines, height);
4128 if (!NILP (w->hchild))
4130 for (child = w->hchild; !NILP (child); child = c->next)
4132 c = XWINDOW (child);
4133 c->top_line = w->top_line;
4134 shrink_window_lowest_first (c, height);
4137 else if (!NILP (w->vchild))
4139 Lisp_Object last_child;
4140 int delta = old_height - height;
4141 int last_top;
4143 last_child = Qnil;
4145 /* Find the last child. We are taking space from lowest windows
4146 first, so we iterate over children from the last child
4147 backwards. */
4148 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
4149 last_child = child;
4151 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
4152 for (child = last_child; delta && !NILP (child); child = c->prev)
4154 int this_one;
4156 c = XWINDOW (child);
4157 this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
4159 if (this_one > delta)
4160 this_one = delta;
4162 shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
4163 delta -= this_one;
4166 /* Compute new positions. */
4167 last_top = XINT (w->top_line);
4168 for (child = w->vchild; !NILP (child); child = c->next)
4170 c = XWINDOW (child);
4171 c->top_line = make_number (last_top);
4172 shrink_window_lowest_first (c, XFASTINT (c->total_lines));
4173 last_top += XFASTINT (c->total_lines);
4179 /* Save, restore, or check positions and sizes in the window tree
4180 rooted at W. ACTION says what to do.
4182 If ACTION is CHECK_ORIG_SIZES, check if orig_top_line and
4183 orig_total_lines members are valid for all windows in the window
4184 tree. Value is non-zero if they are valid.
4186 If ACTION is SAVE_ORIG_SIZES, save members top and height in
4187 orig_top_line and orig_total_lines for all windows in the tree.
4189 If ACTION is RESTORE_ORIG_SIZES, restore top and height from values
4190 stored in orig_top_line and orig_total_lines for all windows. */
4192 static int
4193 save_restore_orig_size (w, action)
4194 struct window *w;
4195 enum save_restore_action action;
4197 int success_p = 1;
4199 while (w)
4201 if (!NILP (w->hchild))
4203 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
4204 success_p = 0;
4206 else if (!NILP (w->vchild))
4208 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
4209 success_p = 0;
4212 switch (action)
4214 case CHECK_ORIG_SIZES:
4215 if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
4216 return 0;
4217 break;
4219 case SAVE_ORIG_SIZES:
4220 w->orig_top_line = w->top_line;
4221 w->orig_total_lines = w->total_lines;
4222 XSETFASTINT (w->last_modified, 0);
4223 XSETFASTINT (w->last_overlay_modified, 0);
4224 break;
4226 case RESTORE_ORIG_SIZES:
4227 xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
4228 w->top_line = w->orig_top_line;
4229 w->total_lines = w->orig_total_lines;
4230 w->orig_total_lines = w->orig_top_line = Qnil;
4231 XSETFASTINT (w->last_modified, 0);
4232 XSETFASTINT (w->last_overlay_modified, 0);
4233 break;
4235 default:
4236 abort ();
4239 w = NILP (w->next) ? NULL : XWINDOW (w->next);
4242 return success_p;
4246 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
4247 without deleting other windows. */
4249 void
4250 grow_mini_window (w, delta)
4251 struct window *w;
4252 int delta;
4254 struct frame *f = XFRAME (w->frame);
4255 struct window *root;
4257 xassert (MINI_WINDOW_P (w));
4258 xassert (delta >= 0);
4260 /* Check values of window_min_width and window_min_height for
4261 validity. */
4262 check_min_window_sizes ();
4264 /* Compute how much we can enlarge the mini-window without deleting
4265 other windows. */
4266 root = XWINDOW (FRAME_ROOT_WINDOW (f));
4267 if (delta)
4269 int min_height = window_min_size (root, 0, 0, 0);
4270 if (XFASTINT (root->total_lines) - delta < min_height)
4271 /* Note that the root window may already be smaller than
4272 min_height. */
4273 delta = max (0, XFASTINT (root->total_lines) - min_height);
4276 if (delta)
4278 /* Save original window sizes and positions, if not already done. */
4279 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
4280 save_restore_orig_size (root, SAVE_ORIG_SIZES);
4282 /* Shrink other windows. */
4283 shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
4285 /* Grow the mini-window. */
4286 w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
4287 w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
4288 XSETFASTINT (w->last_modified, 0);
4289 XSETFASTINT (w->last_overlay_modified, 0);
4291 adjust_glyphs (f);
4296 /* Shrink mini-window W. If there is recorded info about window sizes
4297 before a call to grow_mini_window, restore recorded window sizes.
4298 Otherwise, if the mini-window is higher than 1 line, resize it to 1
4299 line. */
4301 void
4302 shrink_mini_window (w)
4303 struct window *w;
4305 struct frame *f = XFRAME (w->frame);
4306 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
4308 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
4310 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
4311 adjust_glyphs (f);
4312 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4313 windows_or_buffers_changed = 1;
4315 else if (XFASTINT (w->total_lines) > 1)
4317 /* Distribute the additional lines of the mini-window
4318 among the other windows. */
4319 Lisp_Object window;
4320 XSETWINDOW (window, w);
4321 enlarge_window (window, 1 - XFASTINT (w->total_lines), 0, 0);
4327 /* Mark window cursors off for all windows in the window tree rooted
4328 at W by setting their phys_cursor_on_p flag to zero. Called from
4329 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4330 the frame are cleared. */
4332 void
4333 mark_window_cursors_off (w)
4334 struct window *w;
4336 while (w)
4338 if (!NILP (w->hchild))
4339 mark_window_cursors_off (XWINDOW (w->hchild));
4340 else if (!NILP (w->vchild))
4341 mark_window_cursors_off (XWINDOW (w->vchild));
4342 else
4343 w->phys_cursor_on_p = 0;
4345 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4350 /* Return number of lines of text (not counting mode lines) in W. */
4353 window_internal_height (w)
4354 struct window *w;
4356 int ht = XFASTINT (w->total_lines);
4358 if (!MINI_WINDOW_P (w))
4360 if (!NILP (w->parent)
4361 || !NILP (w->vchild)
4362 || !NILP (w->hchild)
4363 || !NILP (w->next)
4364 || !NILP (w->prev)
4365 || WINDOW_WANTS_MODELINE_P (w))
4366 --ht;
4368 if (WINDOW_WANTS_HEADER_LINE_P (w))
4369 --ht;
4372 return ht;
4376 /* Return the number of columns in W.
4377 Don't count columns occupied by scroll bars or the vertical bar
4378 separating W from the sibling to its right. */
4381 window_box_text_cols (w)
4382 struct window *w;
4384 struct frame *f = XFRAME (WINDOW_FRAME (w));
4385 int width = XINT (w->total_cols);
4387 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
4388 /* Scroll bars occupy a few columns. */
4389 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
4390 else if (!FRAME_WINDOW_P (f)
4391 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4392 /* The column of `|' characters separating side-by-side windows
4393 occupies one column only. */
4394 width -= 1;
4396 if (FRAME_WINDOW_P (f))
4397 /* On window-systems, fringes and display margins cannot be
4398 used for normal text. */
4399 width -= (WINDOW_FRINGE_COLS (w)
4400 + WINDOW_LEFT_MARGIN_COLS (w)
4401 + WINDOW_RIGHT_MARGIN_COLS (w));
4403 return width;
4407 /************************************************************************
4408 Window Scrolling
4409 ***********************************************************************/
4411 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4412 N screen-fulls, which is defined as the height of the window minus
4413 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4414 instead. Negative values of N mean scroll down. NOERROR non-zero
4415 means don't signal an error if we try to move over BEGV or ZV,
4416 respectively. */
4418 static void
4419 window_scroll (window, n, whole, noerror)
4420 Lisp_Object window;
4421 int n;
4422 int whole;
4423 int noerror;
4425 immediate_quit = 1;
4427 /* If we must, use the pixel-based version which is much slower than
4428 the line-based one but can handle varying line heights. */
4429 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4430 window_scroll_pixel_based (window, n, whole, noerror);
4431 else
4432 window_scroll_line_based (window, n, whole, noerror);
4434 immediate_quit = 0;
4438 /* Implementation of window_scroll that works based on pixel line
4439 heights. See the comment of window_scroll for parameter
4440 descriptions. */
4442 static void
4443 window_scroll_pixel_based (window, n, whole, noerror)
4444 Lisp_Object window;
4445 int n;
4446 int whole;
4447 int noerror;
4449 struct it it;
4450 struct window *w = XWINDOW (window);
4451 struct text_pos start;
4452 Lisp_Object tem;
4453 int this_scroll_margin;
4454 int preserve_y;
4455 /* True if we fiddled the window vscroll field without really scrolling. */
4456 int vscrolled = 0;
4458 SET_TEXT_POS_FROM_MARKER (start, w->start);
4460 /* If PT is not visible in WINDOW, move back one half of
4461 the screen. Allow PT to be partially visible, otherwise
4462 something like (scroll-down 1) with PT in the line before
4463 the partially visible one would recenter. */
4464 tem = Fpos_visible_in_window_p (make_number (PT), window, Qt);
4465 if (NILP (tem))
4467 /* Move backward half the height of the window. Performance note:
4468 vmotion used here is about 10% faster, but would give wrong
4469 results for variable height lines. */
4470 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4471 it.current_y = it.last_visible_y;
4472 move_it_vertically (&it, - window_box_height (w) / 2);
4474 /* The function move_iterator_vertically may move over more than
4475 the specified y-distance. If it->w is small, e.g. a
4476 mini-buffer window, we may end up in front of the window's
4477 display area. This is the case when Start displaying at the
4478 start of the line containing PT in this case. */
4479 if (it.current_y <= 0)
4481 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4482 move_it_vertically (&it, 0);
4483 it.current_y = 0;
4486 start = it.current.pos;
4489 /* If scroll_preserve_screen_position is non-zero, we try to set
4490 point in the same window line as it is now, so get that line. */
4491 if (!NILP (Vscroll_preserve_screen_position))
4493 start_display (&it, w, start);
4494 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4495 preserve_y = it.current_y;
4497 else
4498 preserve_y = -1;
4500 /* Move iterator it from start the specified distance forward or
4501 backward. The result is the new window start. */
4502 start_display (&it, w, start);
4503 if (whole)
4505 int screen_full = (window_box_height (w)
4506 - next_screen_context_lines * FRAME_LINE_HEIGHT (it.f));
4507 int dy = n * screen_full;
4509 /* Note that move_it_vertically always moves the iterator to the
4510 start of a line. So, if the last line doesn't have a newline,
4511 we would end up at the start of the line ending at ZV. */
4512 if (dy <= 0)
4513 move_it_vertically_backward (&it, -dy);
4514 else if (dy > 0)
4515 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4516 MOVE_TO_POS | MOVE_TO_Y);
4518 else
4519 move_it_by_lines (&it, n, 1);
4521 /* We failed if we find ZV is already on the screen (scrolling up,
4522 means there's nothing past the end), or if we can't start any
4523 earlier (scrolling down, means there's nothing past the top). */
4524 if ((n > 0 && IT_CHARPOS (it) == ZV)
4525 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4527 if (IT_CHARPOS (it) == ZV)
4529 if (it.current_y < it.last_visible_y
4530 && (it.current_y + it.max_ascent + it.max_descent
4531 >= it.last_visible_y))
4533 /* The last line was only partially visible, make it fully
4534 visible. */
4535 w->vscroll = (it.last_visible_y
4536 - it.current_y + it.max_ascent + it.max_descent);
4537 adjust_glyphs (it.f);
4539 else if (noerror)
4540 return;
4541 else
4542 Fsignal (Qend_of_buffer, Qnil);
4544 else
4546 if (w->vscroll != 0)
4547 /* The first line was only partially visible, make it fully
4548 visible. */
4549 w->vscroll = 0;
4550 else if (noerror)
4551 return;
4552 else
4553 Fsignal (Qbeginning_of_buffer, Qnil);
4556 /* If control gets here, then we vscrolled. */
4558 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4560 /* Don't try to change the window start below. */
4561 vscrolled = 1;
4564 if (! vscrolled)
4566 int pos = IT_CHARPOS (it);
4567 int bytepos;
4569 /* If in the middle of a multi-glyph character move forward to
4570 the next character. */
4571 if (in_display_vector_p (&it))
4573 ++pos;
4574 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4577 /* Set the window start, and set up the window for redisplay. */
4578 set_marker_restricted (w->start, make_number (pos),
4579 w->buffer);
4580 bytepos = XMARKER (w->start)->bytepos;
4581 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
4582 ? Qt : Qnil);
4583 w->update_mode_line = Qt;
4584 XSETFASTINT (w->last_modified, 0);
4585 XSETFASTINT (w->last_overlay_modified, 0);
4586 /* Set force_start so that redisplay_window will run the
4587 window-scroll-functions. */
4588 w->force_start = Qt;
4591 it.current_y = it.vpos = 0;
4593 /* Preserve the screen position if we must. */
4594 if (preserve_y >= 0)
4596 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
4597 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4599 else
4601 /* Move PT out of scroll margins. */
4602 this_scroll_margin = max (0, scroll_margin);
4603 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4604 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4606 if (n > 0)
4608 /* We moved the window start towards ZV, so PT may be now
4609 in the scroll margin at the top. */
4610 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4611 while (it.current_y < this_scroll_margin)
4613 int prev = it.current_y;
4614 move_it_by_lines (&it, 1, 1);
4615 if (prev == it.current_y)
4616 break;
4618 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4620 else if (n < 0)
4622 int charpos, bytepos;
4624 /* We moved the window start towards BEGV, so PT may be now
4625 in the scroll margin at the bottom. */
4626 move_it_to (&it, PT, -1,
4627 it.last_visible_y - this_scroll_margin - 1, -1,
4628 MOVE_TO_POS | MOVE_TO_Y);
4630 /* Save our position, in case it's correct. */
4631 charpos = IT_CHARPOS (it);
4632 bytepos = IT_BYTEPOS (it);
4634 /* See if point is on a partially visible line at the end. */
4635 move_it_by_lines (&it, 1, 1);
4636 if (it.current_y > it.last_visible_y)
4637 /* The last line was only partially visible, so back up two
4638 lines to make sure we're on a fully visible line. */
4640 move_it_by_lines (&it, -2, 0);
4641 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4643 else
4644 /* No, the position we saved is OK, so use it. */
4645 SET_PT_BOTH (charpos, bytepos);
4651 /* Implementation of window_scroll that works based on screen lines.
4652 See the comment of window_scroll for parameter descriptions. */
4654 static void
4655 window_scroll_line_based (window, n, whole, noerror)
4656 Lisp_Object window;
4657 int n;
4658 int whole;
4659 int noerror;
4661 register struct window *w = XWINDOW (window);
4662 register int opoint = PT, opoint_byte = PT_BYTE;
4663 register int pos, pos_byte;
4664 register int ht = window_internal_height (w);
4665 register Lisp_Object tem;
4666 int lose;
4667 Lisp_Object bolp;
4668 int startpos;
4669 struct position posit;
4670 int original_vpos;
4672 /* If scrolling screen-fulls, compute the number of lines to
4673 scroll from the window's height. */
4674 if (whole)
4675 n *= max (1, ht - next_screen_context_lines);
4677 startpos = marker_position (w->start);
4679 posit = *compute_motion (startpos, 0, 0, 0,
4680 PT, ht, 0,
4681 window_box_text_cols (w), XINT (w->hscroll),
4682 0, w);
4683 original_vpos = posit.vpos;
4685 XSETFASTINT (tem, PT);
4686 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4688 if (NILP (tem))
4690 Fvertical_motion (make_number (- (ht / 2)), window);
4691 startpos = PT;
4694 SET_PT (startpos);
4695 lose = n < 0 && PT == BEGV;
4696 Fvertical_motion (make_number (n), window);
4697 pos = PT;
4698 pos_byte = PT_BYTE;
4699 bolp = Fbolp ();
4700 SET_PT_BOTH (opoint, opoint_byte);
4702 if (lose)
4704 if (noerror)
4705 return;
4706 else
4707 Fsignal (Qbeginning_of_buffer, Qnil);
4710 if (pos < ZV)
4712 int this_scroll_margin = scroll_margin;
4714 /* Don't use a scroll margin that is negative or too large. */
4715 if (this_scroll_margin < 0)
4716 this_scroll_margin = 0;
4718 if (XINT (w->total_lines) < 4 * scroll_margin)
4719 this_scroll_margin = XINT (w->total_lines) / 4;
4721 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4722 w->start_at_line_beg = bolp;
4723 w->update_mode_line = Qt;
4724 XSETFASTINT (w->last_modified, 0);
4725 XSETFASTINT (w->last_overlay_modified, 0);
4726 /* Set force_start so that redisplay_window will run
4727 the window-scroll-functions. */
4728 w->force_start = Qt;
4730 if (whole && !NILP (Vscroll_preserve_screen_position))
4732 SET_PT_BOTH (pos, pos_byte);
4733 Fvertical_motion (make_number (original_vpos), window);
4735 /* If we scrolled forward, put point enough lines down
4736 that it is outside the scroll margin. */
4737 else if (n > 0)
4739 int top_margin;
4741 if (this_scroll_margin > 0)
4743 SET_PT_BOTH (pos, pos_byte);
4744 Fvertical_motion (make_number (this_scroll_margin), window);
4745 top_margin = PT;
4747 else
4748 top_margin = pos;
4750 if (top_margin <= opoint)
4751 SET_PT_BOTH (opoint, opoint_byte);
4752 else if (!NILP (Vscroll_preserve_screen_position))
4754 SET_PT_BOTH (pos, pos_byte);
4755 Fvertical_motion (make_number (original_vpos), window);
4757 else
4758 SET_PT (top_margin);
4760 else if (n < 0)
4762 int bottom_margin;
4764 /* If we scrolled backward, put point near the end of the window
4765 but not within the scroll margin. */
4766 SET_PT_BOTH (pos, pos_byte);
4767 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4768 if (XFASTINT (tem) == ht - this_scroll_margin)
4769 bottom_margin = PT;
4770 else
4771 bottom_margin = PT + 1;
4773 if (bottom_margin > opoint)
4774 SET_PT_BOTH (opoint, opoint_byte);
4775 else
4777 if (!NILP (Vscroll_preserve_screen_position))
4779 SET_PT_BOTH (pos, pos_byte);
4780 Fvertical_motion (make_number (original_vpos), window);
4782 else
4783 Fvertical_motion (make_number (-1), window);
4787 else
4789 if (noerror)
4790 return;
4791 else
4792 Fsignal (Qend_of_buffer, Qnil);
4797 /* Scroll selected_window up or down. If N is nil, scroll a
4798 screen-full which is defined as the height of the window minus
4799 next_screen_context_lines. If N is the symbol `-', scroll.
4800 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4801 up. This is the guts of Fscroll_up and Fscroll_down. */
4803 static void
4804 scroll_command (n, direction)
4805 Lisp_Object n;
4806 int direction;
4808 int count = SPECPDL_INDEX ();
4810 xassert (abs (direction) == 1);
4812 /* If selected window's buffer isn't current, make it current for
4813 the moment. But don't screw up if window_scroll gets an error. */
4814 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4816 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4817 Fset_buffer (XWINDOW (selected_window)->buffer);
4819 /* Make redisplay consider other windows than just selected_window. */
4820 ++windows_or_buffers_changed;
4823 if (NILP (n))
4824 window_scroll (selected_window, direction, 1, 0);
4825 else if (EQ (n, Qminus))
4826 window_scroll (selected_window, -direction, 1, 0);
4827 else
4829 n = Fprefix_numeric_value (n);
4830 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4833 unbind_to (count, Qnil);
4836 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
4837 doc: /* Scroll text of current window upward ARG lines; or near full screen if no ARG.
4838 A near full screen is `next-screen-context-lines' less than a full screen.
4839 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 `-'. */)
4842 (arg)
4843 Lisp_Object arg;
4845 scroll_command (arg, 1);
4846 return Qnil;
4849 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
4850 doc: /* Scroll text of current window down ARG lines; or near full screen if no ARG.
4851 A near full screen is `next-screen-context-lines' less than a full screen.
4852 Negative ARG means scroll upward.
4853 If ARG is the atom `-', scroll upward by nearly full screen.
4854 When calling from a program, supply as argument a number, nil, or `-'. */)
4855 (arg)
4856 Lisp_Object arg;
4858 scroll_command (arg, -1);
4859 return Qnil;
4862 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4863 doc: /* Return the other window for \"other window scroll\" commands.
4864 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4865 specifies the window.
4866 If `other-window-scroll-buffer' is non-nil, a window
4867 showing that buffer is used. */)
4870 Lisp_Object window;
4872 if (MINI_WINDOW_P (XWINDOW (selected_window))
4873 && !NILP (Vminibuf_scroll_window))
4874 window = Vminibuf_scroll_window;
4875 /* If buffer is specified, scroll that buffer. */
4876 else if (!NILP (Vother_window_scroll_buffer))
4878 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4879 if (NILP (window))
4880 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4882 else
4884 /* Nothing specified; look for a neighboring window on the same
4885 frame. */
4886 window = Fnext_window (selected_window, Qnil, Qnil);
4888 if (EQ (window, selected_window))
4889 /* That didn't get us anywhere; look for a window on another
4890 visible frame. */
4892 window = Fnext_window (window, Qnil, Qt);
4893 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4894 && ! EQ (window, selected_window));
4897 CHECK_LIVE_WINDOW (window);
4899 if (EQ (window, selected_window))
4900 error ("There is no other window");
4902 return window;
4905 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4906 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4907 A near full screen is `next-screen-context-lines' less than a full screen.
4908 The next window is the one below the current one; or the one at the top
4909 if the current one is at the bottom. Negative ARG means scroll downward.
4910 If ARG is the atom `-', scroll downward by nearly full screen.
4911 When calling from a program, supply as argument a number, nil, or `-'.
4913 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4914 specifies the window to scroll.
4915 If `other-window-scroll-buffer' is non-nil, scroll the window
4916 showing that buffer, popping the buffer up if necessary. */)
4917 (arg)
4918 Lisp_Object arg;
4920 Lisp_Object window;
4921 struct window *w;
4922 int count = SPECPDL_INDEX ();
4924 window = Fother_window_for_scrolling ();
4925 w = XWINDOW (window);
4927 /* Don't screw up if window_scroll gets an error. */
4928 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4929 ++windows_or_buffers_changed;
4931 Fset_buffer (w->buffer);
4932 SET_PT (marker_position (w->pointm));
4934 if (NILP (arg))
4935 window_scroll (window, 1, 1, 1);
4936 else if (EQ (arg, Qminus))
4937 window_scroll (window, -1, 1, 1);
4938 else
4940 if (CONSP (arg))
4941 arg = Fcar (arg);
4942 CHECK_NUMBER (arg);
4943 window_scroll (window, XINT (arg), 0, 1);
4946 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4947 unbind_to (count, Qnil);
4949 return Qnil;
4952 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
4953 doc: /* Scroll selected window display ARG columns left.
4954 Default for ARG is window width minus 2.
4955 Value is the total amount of leftward horizontal scrolling in
4956 effect after the change.
4957 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4958 a lower bound for automatic scrolling, i.e. automatic scrolling
4959 will not scroll a window to a column less than the value returned
4960 by this function. */)
4961 (arg)
4962 register Lisp_Object arg;
4964 Lisp_Object result;
4965 int hscroll;
4966 struct window *w = XWINDOW (selected_window);
4968 if (NILP (arg))
4969 XSETFASTINT (arg, window_box_text_cols (w) - 2);
4970 else
4971 arg = Fprefix_numeric_value (arg);
4973 hscroll = XINT (w->hscroll) + XINT (arg);
4974 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4976 if (interactive_p (0))
4977 w->min_hscroll = w->hscroll;
4979 return result;
4982 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
4983 doc: /* Scroll selected window display ARG columns right.
4984 Default for ARG is window width minus 2.
4985 Value is the total amount of leftward horizontal scrolling in
4986 effect after the change.
4987 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4988 a lower bound for automatic scrolling, i.e. automatic scrolling
4989 will not scroll a window to a column less than the value returned
4990 by this function. */)
4991 (arg)
4992 register Lisp_Object arg;
4994 Lisp_Object result;
4995 int hscroll;
4996 struct window *w = XWINDOW (selected_window);
4998 if (NILP (arg))
4999 XSETFASTINT (arg, window_box_text_cols (w) - 2);
5000 else
5001 arg = Fprefix_numeric_value (arg);
5003 hscroll = XINT (w->hscroll) - XINT (arg);
5004 result = Fset_window_hscroll (selected_window, make_number (hscroll));
5006 if (interactive_p (0))
5007 w->min_hscroll = w->hscroll;
5009 return result;
5012 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5013 doc: /* Return the window which was selected when entering the minibuffer.
5014 Returns nil, if current window is not a minibuffer window. */)
5017 if (minibuf_level > 0
5018 && MINI_WINDOW_P (XWINDOW (selected_window))
5019 && WINDOW_LIVE_P (minibuf_selected_window))
5020 return minibuf_selected_window;
5022 return Qnil;
5025 /* Value is the number of lines actually displayed in window W,
5026 as opposed to its height. */
5028 static int
5029 displayed_window_lines (w)
5030 struct window *w;
5032 struct it it;
5033 struct text_pos start;
5034 int height = window_box_height (w);
5035 struct buffer *old_buffer;
5036 int bottom_y;
5038 if (XBUFFER (w->buffer) != current_buffer)
5040 old_buffer = current_buffer;
5041 set_buffer_internal (XBUFFER (w->buffer));
5043 else
5044 old_buffer = NULL;
5046 /* In case W->start is out of the accessible range, do something
5047 reasonable. This happens in Info mode when Info-scroll-down
5048 calls (recenter -1) while W->start is 1. */
5049 if (XMARKER (w->start)->charpos < BEGV)
5050 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5051 else if (XMARKER (w->start)->charpos > ZV)
5052 SET_TEXT_POS (start, ZV, ZV_BYTE);
5053 else
5054 SET_TEXT_POS_FROM_MARKER (start, w->start);
5056 start_display (&it, w, start);
5057 move_it_vertically (&it, height);
5058 bottom_y = line_bottom_y (&it);
5060 /* rms: On a non-window display,
5061 the value of it.vpos at the bottom of the screen
5062 seems to be 1 larger than window_box_height (w).
5063 This kludge fixes a bug whereby (move-to-window-line -1)
5064 when ZV is on the last screen line
5065 moves to the previous screen line instead of the last one. */
5066 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5067 height++;
5069 /* Add in empty lines at the bottom of the window. */
5070 if (bottom_y < height)
5072 int uy = FRAME_LINE_HEIGHT (it.f);
5073 it.vpos += (height - bottom_y + uy - 1) / uy;
5076 if (old_buffer)
5077 set_buffer_internal (old_buffer);
5079 return it.vpos;
5083 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5084 doc: /* Center point in window and redisplay frame.
5085 With prefix argument ARG, recenter putting point on screen line ARG
5086 relative to the current window. If ARG is negative, it counts up from the
5087 bottom of the window. (ARG should be less than the height of the window.)
5089 If ARG is omitted or nil, erase the entire frame and then
5090 redraw with point in the center of the current window.
5091 Just C-u as prefix means put point in the center of the window
5092 and redisplay normally--don't erase and redraw the frame. */)
5093 (arg)
5094 register Lisp_Object arg;
5096 struct window *w = XWINDOW (selected_window);
5097 struct buffer *buf = XBUFFER (w->buffer);
5098 struct buffer *obuf = current_buffer;
5099 int center_p = 0;
5100 int charpos, bytepos;
5102 /* If redisplay is suppressed due to an error, try again. */
5103 obuf->display_error_modiff = 0;
5105 if (NILP (arg))
5107 int i;
5109 /* Invalidate pixel data calculated for all compositions. */
5110 for (i = 0; i < n_compositions; i++)
5111 composition_table[i]->font = NULL;
5113 Fredraw_frame (w->frame);
5114 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
5115 center_p = 1;
5117 else if (CONSP (arg)) /* Just C-u. */
5118 center_p = 1;
5119 else
5121 arg = Fprefix_numeric_value (arg);
5122 CHECK_NUMBER (arg);
5125 set_buffer_internal (buf);
5127 /* Handle centering on a graphical frame specially. Such frames can
5128 have variable-height lines and centering point on the basis of
5129 line counts would lead to strange effects. */
5130 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5132 if (center_p)
5134 struct it it;
5135 struct text_pos pt;
5137 SET_TEXT_POS (pt, PT, PT_BYTE);
5138 start_display (&it, w, pt);
5139 move_it_vertically (&it, - window_box_height (w) / 2);
5140 charpos = IT_CHARPOS (it);
5141 bytepos = IT_BYTEPOS (it);
5143 else if (XINT (arg) < 0)
5145 struct it it;
5146 struct text_pos pt;
5147 int y0, y1, h, nlines;
5149 SET_TEXT_POS (pt, PT, PT_BYTE);
5150 start_display (&it, w, pt);
5151 y0 = it.current_y;
5153 /* The amount of pixels we have to move back is the window
5154 height minus what's displayed in the line containing PT,
5155 and the lines below. */
5156 nlines = - XINT (arg) - 1;
5157 move_it_by_lines (&it, nlines, 1);
5159 y1 = line_bottom_y (&it);
5161 /* If we can't move down NLINES lines because we hit
5162 the end of the buffer, count in some empty lines. */
5163 if (it.vpos < nlines)
5164 y1 += (nlines - it.vpos) * FRAME_LINE_HEIGHT (it.f);
5166 h = window_box_height (w) - (y1 - y0);
5168 start_display (&it, w, pt);
5169 move_it_vertically (&it, - h);
5170 charpos = IT_CHARPOS (it);
5171 bytepos = IT_BYTEPOS (it);
5173 else
5175 struct position pos;
5176 pos = *vmotion (PT, - XINT (arg), w);
5177 charpos = pos.bufpos;
5178 bytepos = pos.bytepos;
5181 else
5183 struct position pos;
5184 int ht = window_internal_height (w);
5186 if (center_p)
5187 arg = make_number (ht / 2);
5188 else if (XINT (arg) < 0)
5189 arg = make_number (XINT (arg) + ht);
5191 pos = *vmotion (PT, - XINT (arg), w);
5192 charpos = pos.bufpos;
5193 bytepos = pos.bytepos;
5196 /* Set the new window start. */
5197 set_marker_both (w->start, w->buffer, charpos, bytepos);
5198 w->window_end_valid = Qnil;
5200 w->optional_new_start = Qt;
5202 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5203 w->start_at_line_beg = Qt;
5204 else
5205 w->start_at_line_beg = Qnil;
5207 set_buffer_internal (obuf);
5208 return Qnil;
5212 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5213 0, 1, 0,
5214 doc: /* Return the height in lines of the text display area of WINDOW.
5215 This doesn't include the mode-line (or header-line if any) or any
5216 partial-height lines in the text display area. */)
5217 (window)
5218 Lisp_Object window;
5220 struct window *w = decode_window (window);
5221 int pixel_height = window_box_height (w);
5222 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5223 return make_number (line_height);
5228 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5229 1, 1, "P",
5230 doc: /* Position point relative to window.
5231 With no argument, position point at center of window.
5232 An argument specifies vertical position within the window;
5233 zero means top of window, negative means relative to bottom of window. */)
5234 (arg)
5235 Lisp_Object arg;
5237 struct window *w = XWINDOW (selected_window);
5238 int lines, start;
5239 Lisp_Object window;
5241 window = selected_window;
5242 start = marker_position (w->start);
5243 if (start < BEGV || start > ZV)
5245 int height = window_internal_height (w);
5246 Fvertical_motion (make_number (- (height / 2)), window);
5247 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5248 w->start_at_line_beg = Fbolp ();
5249 w->force_start = Qt;
5251 else
5252 Fgoto_char (w->start);
5254 lines = displayed_window_lines (w);
5255 if (NILP (arg))
5256 XSETFASTINT (arg, lines / 2);
5257 else
5259 arg = Fprefix_numeric_value (arg);
5260 if (XINT (arg) < 0)
5261 XSETINT (arg, XINT (arg) + lines);
5264 /* Skip past a partially visible first line. */
5265 if (w->vscroll)
5266 XSETINT (arg, XINT (arg) + 1);
5268 return Fvertical_motion (arg, window);
5273 /***********************************************************************
5274 Window Configuration
5275 ***********************************************************************/
5277 struct save_window_data
5279 EMACS_INT size_from_Lisp_Vector_struct;
5280 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5281 Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
5282 Lisp_Object frame_tool_bar_lines;
5283 Lisp_Object selected_frame;
5284 Lisp_Object current_window;
5285 Lisp_Object current_buffer;
5286 Lisp_Object minibuf_scroll_window;
5287 Lisp_Object minibuf_selected_window;
5288 Lisp_Object root_window;
5289 Lisp_Object focus_frame;
5290 /* Record the values of window-min-width and window-min-height
5291 so that window sizes remain consistent with them. */
5292 Lisp_Object min_width, min_height;
5293 /* A vector, each of whose elements is a struct saved_window
5294 for one window. */
5295 Lisp_Object saved_windows;
5298 /* This is saved as a Lisp_Vector */
5299 struct saved_window
5301 /* these first two must agree with struct Lisp_Vector in lisp.h */
5302 EMACS_INT size_from_Lisp_Vector_struct;
5303 struct Lisp_Vector *next_from_Lisp_Vector_struct;
5305 Lisp_Object window;
5306 Lisp_Object buffer, start, pointm, mark;
5307 Lisp_Object left_col, top_line, total_cols, total_lines;
5308 Lisp_Object hscroll, min_hscroll;
5309 Lisp_Object parent, prev;
5310 Lisp_Object start_at_line_beg;
5311 Lisp_Object display_table;
5312 Lisp_Object orig_top_line, orig_total_lines;
5313 Lisp_Object left_margin_cols, right_margin_cols;
5314 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5315 Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
5318 #define SAVED_WINDOW_VECTOR_SIZE 24 /* Arg to Fmake_vector */
5320 #define SAVED_WINDOW_N(swv,n) \
5321 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5323 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5324 doc: /* Return t if OBJECT is a window-configuration object. */)
5325 (object)
5326 Lisp_Object object;
5328 if (WINDOW_CONFIGURATIONP (object))
5329 return Qt;
5330 return Qnil;
5333 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5334 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5335 (config)
5336 Lisp_Object config;
5338 register struct save_window_data *data;
5339 struct Lisp_Vector *saved_windows;
5341 if (! WINDOW_CONFIGURATIONP (config))
5342 wrong_type_argument (Qwindow_configuration_p, config);
5344 data = (struct save_window_data *) XVECTOR (config);
5345 saved_windows = XVECTOR (data->saved_windows);
5346 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5349 DEFUN ("set-window-configuration", Fset_window_configuration,
5350 Sset_window_configuration, 1, 1, 0,
5351 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5352 CONFIGURATION must be a value previously returned
5353 by `current-window-configuration' (which see).
5354 If CONFIGURATION was made from a frame that is now deleted,
5355 only frame-independent values can be restored. In this case,
5356 the return value is nil. Otherwise the value is t. */)
5357 (configuration)
5358 Lisp_Object configuration;
5360 register struct save_window_data *data;
5361 struct Lisp_Vector *saved_windows;
5362 Lisp_Object new_current_buffer;
5363 Lisp_Object frame;
5364 FRAME_PTR f;
5365 int old_point = -1;
5367 while (!WINDOW_CONFIGURATIONP (configuration))
5368 wrong_type_argument (Qwindow_configuration_p, configuration);
5370 data = (struct save_window_data *) XVECTOR (configuration);
5371 saved_windows = XVECTOR (data->saved_windows);
5373 new_current_buffer = data->current_buffer;
5374 if (NILP (XBUFFER (new_current_buffer)->name))
5375 new_current_buffer = Qnil;
5376 else
5378 if (XBUFFER (new_current_buffer) == current_buffer)
5379 old_point = PT;
5380 else
5381 old_point = BUF_PT (XBUFFER (new_current_buffer));
5384 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5385 f = XFRAME (frame);
5387 /* If f is a dead frame, don't bother rebuilding its window tree.
5388 However, there is other stuff we should still try to do below. */
5389 if (FRAME_LIVE_P (f))
5391 register struct window *w;
5392 register struct saved_window *p;
5393 struct window *root_window;
5394 struct window **leaf_windows;
5395 int n_leaf_windows;
5396 int k, i, n;
5398 /* If the frame has been resized since this window configuration was
5399 made, we change the frame to the size specified in the
5400 configuration, restore the configuration, and then resize it
5401 back. We keep track of the prevailing height in these variables. */
5402 int previous_frame_lines = FRAME_LINES (f);
5403 int previous_frame_cols = FRAME_COLS (f);
5404 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5405 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5407 /* The mouse highlighting code could get screwed up
5408 if it runs during this. */
5409 BLOCK_INPUT;
5411 if (XFASTINT (data->frame_lines) != previous_frame_lines
5412 || XFASTINT (data->frame_cols) != previous_frame_cols)
5413 change_frame_size (f, XFASTINT (data->frame_lines),
5414 XFASTINT (data->frame_cols), 0, 0, 0);
5415 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5416 if (XFASTINT (data->frame_menu_bar_lines)
5417 != previous_frame_menu_bar_lines)
5418 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
5419 #ifdef HAVE_WINDOW_SYSTEM
5420 if (XFASTINT (data->frame_tool_bar_lines)
5421 != previous_frame_tool_bar_lines)
5422 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
5423 #endif
5424 #endif
5426 /* "Swap out" point from the selected window
5427 into its buffer. We do this now, before
5428 restoring the window contents, and prevent it from
5429 being done later on when we select a new window. */
5430 if (! NILP (XWINDOW (selected_window)->buffer))
5432 w = XWINDOW (selected_window);
5433 set_marker_both (w->pointm,
5434 w->buffer,
5435 BUF_PT (XBUFFER (w->buffer)),
5436 BUF_PT_BYTE (XBUFFER (w->buffer)));
5439 windows_or_buffers_changed++;
5440 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5442 /* Problem: Freeing all matrices and later allocating them again
5443 is a serious redisplay flickering problem. What we would
5444 really like to do is to free only those matrices not reused
5445 below. */
5446 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5447 leaf_windows
5448 = (struct window **) alloca (count_windows (root_window)
5449 * sizeof (struct window *));
5450 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5452 /* Temporarily avoid any problems with windows that are smaller
5453 than they are supposed to be. */
5454 window_min_height = 1;
5455 window_min_width = 1;
5457 /* Kludge Alert!
5458 Mark all windows now on frame as "deleted".
5459 Restoring the new configuration "undeletes" any that are in it.
5461 Save their current buffers in their height fields, since we may
5462 need it later, if a buffer saved in the configuration is now
5463 dead. */
5464 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5466 for (k = 0; k < saved_windows->size; k++)
5468 p = SAVED_WINDOW_N (saved_windows, k);
5469 w = XWINDOW (p->window);
5470 w->next = Qnil;
5472 if (!NILP (p->parent))
5473 w->parent = SAVED_WINDOW_N (saved_windows,
5474 XFASTINT (p->parent))->window;
5475 else
5476 w->parent = Qnil;
5478 if (!NILP (p->prev))
5480 w->prev = SAVED_WINDOW_N (saved_windows,
5481 XFASTINT (p->prev))->window;
5482 XWINDOW (w->prev)->next = p->window;
5484 else
5486 w->prev = Qnil;
5487 if (!NILP (w->parent))
5489 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
5491 XWINDOW (w->parent)->vchild = p->window;
5492 XWINDOW (w->parent)->hchild = Qnil;
5494 else
5496 XWINDOW (w->parent)->hchild = p->window;
5497 XWINDOW (w->parent)->vchild = Qnil;
5502 /* If we squirreled away the buffer in the window's height,
5503 restore it now. */
5504 if (BUFFERP (w->total_lines))
5505 w->buffer = w->total_lines;
5506 w->left_col = p->left_col;
5507 w->top_line = p->top_line;
5508 w->total_cols = p->total_cols;
5509 w->total_lines = p->total_lines;
5510 w->hscroll = p->hscroll;
5511 w->min_hscroll = p->min_hscroll;
5512 w->display_table = p->display_table;
5513 w->orig_top_line = p->orig_top_line;
5514 w->orig_total_lines = p->orig_total_lines;
5515 w->left_margin_cols = p->left_margin_cols;
5516 w->right_margin_cols = p->right_margin_cols;
5517 w->left_fringe_width = p->left_fringe_width;
5518 w->right_fringe_width = p->right_fringe_width;
5519 w->fringes_outside_margins = p->fringes_outside_margins;
5520 w->scroll_bar_width = p->scroll_bar_width;
5521 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
5522 XSETFASTINT (w->last_modified, 0);
5523 XSETFASTINT (w->last_overlay_modified, 0);
5525 /* Reinstall the saved buffer and pointers into it. */
5526 if (NILP (p->buffer))
5527 w->buffer = p->buffer;
5528 else
5530 if (!NILP (XBUFFER (p->buffer)->name))
5531 /* If saved buffer is alive, install it. */
5533 w->buffer = p->buffer;
5534 w->start_at_line_beg = p->start_at_line_beg;
5535 set_marker_restricted (w->start, p->start, w->buffer);
5536 set_marker_restricted (w->pointm, p->pointm, w->buffer);
5537 Fset_marker (XBUFFER (w->buffer)->mark,
5538 p->mark, w->buffer);
5540 /* As documented in Fcurrent_window_configuration, don't
5541 restore the location of point in the buffer which was
5542 current when the window configuration was recorded. */
5543 if (!EQ (p->buffer, new_current_buffer)
5544 && XBUFFER (p->buffer) == current_buffer)
5545 Fgoto_char (w->pointm);
5547 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
5548 /* Else unless window has a live buffer, get one. */
5550 w->buffer = Fcdr (Fcar (Vbuffer_alist));
5551 /* This will set the markers to beginning of visible
5552 range. */
5553 set_marker_restricted (w->start, make_number (0), w->buffer);
5554 set_marker_restricted (w->pointm, make_number (0),w->buffer);
5555 w->start_at_line_beg = Qt;
5557 else
5558 /* Keeping window's old buffer; make sure the markers
5559 are real. */
5561 /* Set window markers at start of visible range. */
5562 if (XMARKER (w->start)->buffer == 0)
5563 set_marker_restricted (w->start, make_number (0),
5564 w->buffer);
5565 if (XMARKER (w->pointm)->buffer == 0)
5566 set_marker_restricted_both (w->pointm, w->buffer,
5567 BUF_PT (XBUFFER (w->buffer)),
5568 BUF_PT_BYTE (XBUFFER (w->buffer)));
5569 w->start_at_line_beg = Qt;
5574 FRAME_ROOT_WINDOW (f) = data->root_window;
5575 /* Prevent "swapping out point" in the old selected window
5576 using the buffer that has been restored into it.
5577 Use the point value from the beginning of this function
5578 since unshow_buffer (called from delete_all_subwindows)
5579 could have altered it. */
5580 selected_window = Qnil;
5581 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5582 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5583 make_number (old_point),
5584 XWINDOW (data->current_window)->buffer);
5586 Fselect_window (data->current_window, Qnil);
5587 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
5588 = selected_window;
5590 if (NILP (data->focus_frame)
5591 || (FRAMEP (data->focus_frame)
5592 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5593 Fredirect_frame_focus (frame, data->focus_frame);
5595 #if 0 /* I don't understand why this is needed, and it causes problems
5596 when the frame's old selected window has been deleted. */
5597 if (f != selected_frame && FRAME_WINDOW_P (f))
5598 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
5599 0, 0);
5600 #endif
5602 /* Set the screen height to the value it had before this function. */
5603 if (previous_frame_lines != FRAME_LINES (f)
5604 || previous_frame_cols != FRAME_COLS (f))
5605 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5606 0, 0, 0);
5607 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5608 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5609 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5610 make_number (0));
5611 #ifdef HAVE_WINDOW_SYSTEM
5612 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5613 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5614 make_number (0));
5615 #endif
5616 #endif
5618 /* Now, free glyph matrices in windows that were not reused. */
5619 for (i = n = 0; i < n_leaf_windows; ++i)
5621 if (NILP (leaf_windows[i]->buffer))
5623 /* Assert it's not reused as a combination. */
5624 xassert (NILP (leaf_windows[i]->hchild)
5625 && NILP (leaf_windows[i]->vchild));
5626 free_window_matrices (leaf_windows[i]);
5628 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5629 ++n;
5632 adjust_glyphs (f);
5634 UNBLOCK_INPUT;
5636 /* Fselect_window will have made f the selected frame, so we
5637 reselect the proper frame here. Fhandle_switch_frame will change the
5638 selected window too, but that doesn't make the call to
5639 Fselect_window above totally superfluous; it still sets f's
5640 selected window. */
5641 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5642 do_switch_frame (data->selected_frame, 0, 0);
5644 if (! NILP (Vwindow_configuration_change_hook)
5645 && ! NILP (Vrun_hooks))
5646 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
5649 if (!NILP (new_current_buffer))
5650 Fset_buffer (new_current_buffer);
5652 /* Restore the minimum heights recorded in the configuration. */
5653 window_min_height = XINT (data->min_height);
5654 window_min_width = XINT (data->min_width);
5656 Vminibuf_scroll_window = data->minibuf_scroll_window;
5657 minibuf_selected_window = data->minibuf_selected_window;
5659 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5662 /* Mark all windows now on frame as deleted
5663 by setting their buffers to nil. */
5665 void
5666 delete_all_subwindows (w)
5667 register struct window *w;
5669 if (!NILP (w->next))
5670 delete_all_subwindows (XWINDOW (w->next));
5671 if (!NILP (w->vchild))
5672 delete_all_subwindows (XWINDOW (w->vchild));
5673 if (!NILP (w->hchild))
5674 delete_all_subwindows (XWINDOW (w->hchild));
5676 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
5678 if (!NILP (w->buffer))
5679 unshow_buffer (w);
5681 /* We set all three of these fields to nil, to make sure that we can
5682 distinguish this dead window from any live window. Live leaf
5683 windows will have buffer set, and combination windows will have
5684 vchild or hchild set. */
5685 w->buffer = Qnil;
5686 w->vchild = Qnil;
5687 w->hchild = Qnil;
5689 Vwindow_list = Qnil;
5692 static int
5693 count_windows (window)
5694 register struct window *window;
5696 register int count = 1;
5697 if (!NILP (window->next))
5698 count += count_windows (XWINDOW (window->next));
5699 if (!NILP (window->vchild))
5700 count += count_windows (XWINDOW (window->vchild));
5701 if (!NILP (window->hchild))
5702 count += count_windows (XWINDOW (window->hchild));
5703 return count;
5707 /* Fill vector FLAT with leaf windows under W, starting at index I.
5708 Value is last index + 1. */
5710 static int
5711 get_leaf_windows (w, flat, i)
5712 struct window *w;
5713 struct window **flat;
5714 int i;
5716 while (w)
5718 if (!NILP (w->hchild))
5719 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5720 else if (!NILP (w->vchild))
5721 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5722 else
5723 flat[i++] = w;
5725 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5728 return i;
5732 /* Return a pointer to the glyph W's physical cursor is on. Value is
5733 null if W's current matrix is invalid, so that no meaningfull glyph
5734 can be returned. */
5736 struct glyph *
5737 get_phys_cursor_glyph (w)
5738 struct window *w;
5740 struct glyph_row *row;
5741 struct glyph *glyph;
5743 if (w->phys_cursor.vpos >= 0
5744 && w->phys_cursor.vpos < w->current_matrix->nrows
5745 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
5746 row->enabled_p)
5747 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
5748 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
5749 else
5750 glyph = NULL;
5752 return glyph;
5756 static int
5757 save_window_save (window, vector, i)
5758 Lisp_Object window;
5759 struct Lisp_Vector *vector;
5760 int i;
5762 register struct saved_window *p;
5763 register struct window *w;
5764 register Lisp_Object tem;
5766 for (;!NILP (window); window = w->next)
5768 p = SAVED_WINDOW_N (vector, i);
5769 w = XWINDOW (window);
5771 XSETFASTINT (w->temslot, i++);
5772 p->window = window;
5773 p->buffer = w->buffer;
5774 p->left_col = w->left_col;
5775 p->top_line = w->top_line;
5776 p->total_cols = w->total_cols;
5777 p->total_lines = w->total_lines;
5778 p->hscroll = w->hscroll;
5779 p->min_hscroll = w->min_hscroll;
5780 p->display_table = w->display_table;
5781 p->orig_top_line = w->orig_top_line;
5782 p->orig_total_lines = w->orig_total_lines;
5783 p->left_margin_cols = w->left_margin_cols;
5784 p->right_margin_cols = w->right_margin_cols;
5785 p->left_fringe_width = w->left_fringe_width;
5786 p->right_fringe_width = w->right_fringe_width;
5787 p->fringes_outside_margins = w->fringes_outside_margins;
5788 p->scroll_bar_width = w->scroll_bar_width;
5789 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
5790 if (!NILP (w->buffer))
5792 /* Save w's value of point in the window configuration.
5793 If w is the selected window, then get the value of point
5794 from the buffer; pointm is garbage in the selected window. */
5795 if (EQ (window, selected_window))
5797 p->pointm = Fmake_marker ();
5798 set_marker_both (p->pointm, w->buffer,
5799 BUF_PT (XBUFFER (w->buffer)),
5800 BUF_PT_BYTE (XBUFFER (w->buffer)));
5802 else
5803 p->pointm = Fcopy_marker (w->pointm, Qnil);
5805 p->start = Fcopy_marker (w->start, Qnil);
5806 p->start_at_line_beg = w->start_at_line_beg;
5808 tem = XBUFFER (w->buffer)->mark;
5809 p->mark = Fcopy_marker (tem, Qnil);
5811 else
5813 p->pointm = Qnil;
5814 p->start = Qnil;
5815 p->mark = Qnil;
5816 p->start_at_line_beg = Qnil;
5819 if (NILP (w->parent))
5820 p->parent = Qnil;
5821 else
5822 p->parent = XWINDOW (w->parent)->temslot;
5824 if (NILP (w->prev))
5825 p->prev = Qnil;
5826 else
5827 p->prev = XWINDOW (w->prev)->temslot;
5829 if (!NILP (w->vchild))
5830 i = save_window_save (w->vchild, vector, i);
5831 if (!NILP (w->hchild))
5832 i = save_window_save (w->hchild, vector, i);
5835 return i;
5838 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
5839 Scurrent_window_configuration, 0, 1, 0,
5840 doc: /* Return an object representing the current window configuration of FRAME.
5841 If FRAME is nil or omitted, use the selected frame.
5842 This describes the number of windows, their sizes and current buffers,
5843 and for each displayed buffer, where display starts, and the positions of
5844 point and mark. An exception is made for point in the current buffer:
5845 its value is -not- saved.
5846 This also records the currently selected frame, and FRAME's focus
5847 redirection (see `redirect-frame-focus'). */)
5848 (frame)
5849 Lisp_Object frame;
5851 register Lisp_Object tem;
5852 register int n_windows;
5853 register struct save_window_data *data;
5854 register struct Lisp_Vector *vec;
5855 register int i;
5856 FRAME_PTR f;
5858 if (NILP (frame))
5859 frame = selected_frame;
5860 CHECK_LIVE_FRAME (frame);
5861 f = XFRAME (frame);
5863 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5864 vec = allocate_other_vector (VECSIZE (struct save_window_data));
5865 data = (struct save_window_data *)vec;
5867 XSETFASTINT (data->frame_cols, FRAME_COLS (f));
5868 XSETFASTINT (data->frame_lines, FRAME_LINES (f));
5869 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
5870 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
5871 data->selected_frame = selected_frame;
5872 data->current_window = FRAME_SELECTED_WINDOW (f);
5873 XSETBUFFER (data->current_buffer, current_buffer);
5874 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
5875 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
5876 data->root_window = FRAME_ROOT_WINDOW (f);
5877 data->focus_frame = FRAME_FOCUS_FRAME (f);
5878 XSETINT (data->min_height, window_min_height);
5879 XSETINT (data->min_width, window_min_width);
5880 tem = Fmake_vector (make_number (n_windows), Qnil);
5881 data->saved_windows = tem;
5882 for (i = 0; i < n_windows; i++)
5883 XVECTOR (tem)->contents[i]
5884 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
5885 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
5886 XSETWINDOW_CONFIGURATION (tem, data);
5887 return (tem);
5890 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
5891 0, UNEVALLED, 0,
5892 doc: /* Execute body, preserving window sizes and contents.
5893 Restore which buffer appears in which window, where display starts,
5894 and the value of point and mark for each window.
5895 Also restore the choice of selected window.
5896 Also restore which buffer is current.
5897 Does not restore the value of point in current buffer.
5898 usage: (save-window-excursion BODY ...) */)
5899 (args)
5900 Lisp_Object args;
5902 register Lisp_Object val;
5903 register int count = SPECPDL_INDEX ();
5905 record_unwind_protect (Fset_window_configuration,
5906 Fcurrent_window_configuration (Qnil));
5907 val = Fprogn (args);
5908 return unbind_to (count, val);
5912 /***********************************************************************
5913 Marginal Areas
5914 ***********************************************************************/
5916 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
5917 2, 3, 0,
5918 doc: /* Set width of marginal areas of window WINDOW.
5919 If WINDOW is nil, set margins of the currently selected window.
5920 Second arg LEFT-WIDTH specifies the number of character cells to
5921 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
5922 does the same for the right marginal area. A nil width parameter
5923 means no margin. */)
5924 (window, left, right)
5925 Lisp_Object window, left, right;
5927 struct window *w = decode_window (window);
5929 /* Translate negative or zero widths to nil.
5930 Margins that are too wide have to be checked elsewhere. */
5932 if (!NILP (left))
5934 CHECK_NUMBER (left);
5935 if (XINT (left) <= 0)
5936 left = Qnil;
5939 if (!NILP (right))
5941 CHECK_NUMBER (right);
5942 if (XINT (right) <= 0)
5943 right = Qnil;
5946 if (!EQ (w->left_margin_cols, left)
5947 || !EQ (w->right_margin_cols, right))
5949 w->left_margin_cols = left;
5950 w->right_margin_cols = right;
5952 adjust_window_margins (w);
5954 ++windows_or_buffers_changed;
5955 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5958 return Qnil;
5962 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
5963 0, 1, 0,
5964 doc: /* Get width of marginal areas of window WINDOW.
5965 If WINDOW is omitted or nil, use the currently selected window.
5966 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
5967 If a marginal area does not exist, its width will be returned
5968 as nil. */)
5969 (window)
5970 Lisp_Object window;
5972 struct window *w = decode_window (window);
5973 return Fcons (w->left_margin_cols, w->right_margin_cols);
5978 /***********************************************************************
5979 Fringes
5980 ***********************************************************************/
5982 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
5983 2, 4, 0,
5984 doc: /* Set the fringe widths of window WINDOW.
5985 If WINDOW is nil, set the fringe widths of the currently selected
5986 window.
5987 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
5988 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
5989 fringe width. If a fringe width arg is nil, that means to use the
5990 frame's default fringe width. Default fringe widths can be set with
5991 the command `set-fringe-style'.
5992 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
5993 outside of the display margins. By default, fringes are drawn between
5994 display marginal areas and the text area. */)
5995 (window, left, right, outside_margins)
5996 Lisp_Object window, left, right, outside_margins;
5998 struct window *w = decode_window (window);
6000 if (!NILP (left))
6001 CHECK_NUMBER (left);
6002 if (!NILP (right))
6003 CHECK_NUMBER (right);
6005 if (!EQ (w->left_fringe_width, left)
6006 || !EQ (w->right_fringe_width, right)
6007 || !EQ (w->fringes_outside_margins, outside_margins))
6009 w->left_fringe_width = left;
6010 w->right_fringe_width = right;
6011 w->fringes_outside_margins = outside_margins;
6013 adjust_window_margins (w);
6015 clear_glyph_matrix (w->current_matrix);
6016 w->window_end_valid = Qnil;
6018 ++windows_or_buffers_changed;
6019 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6022 return Qnil;
6026 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6027 0, 1, 0,
6028 doc: /* Get width of fringes of window WINDOW.
6029 If WINDOW is omitted or nil, use the currently selected window.
6030 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6031 (window)
6032 Lisp_Object window;
6034 struct window *w = decode_window (window);
6035 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6036 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6037 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ?
6038 Qt : Qnil), Qnil)));
6043 /***********************************************************************
6044 Scroll bars
6045 ***********************************************************************/
6047 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
6048 2, 4, 0,
6049 doc: /* Set width and type of scroll bars of window WINDOW.
6050 If window is nil, set scroll bars of the currently selected window.
6051 Second parameter WIDTH specifies the pixel width for the scroll bar;
6052 this is automatically adjusted to a multiple of the frame column width.
6053 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6054 bar: left, right, or nil.
6055 If WIDTH is nil, use the frame's scroll-bar width.
6056 If TYPE is t, use the frame's scroll-bar type. */)
6057 (window, width, vertical_type, horizontal_type)
6058 Lisp_Object window, width, vertical_type, horizontal_type;
6060 struct window *w = decode_window (window);
6062 if (!NILP (width))
6063 CHECK_NUMBER (width);
6065 if (XINT (width) == 0)
6066 vertical_type = Qnil;
6068 if (!(EQ (vertical_type, Qnil)
6069 || EQ (vertical_type, Qleft)
6070 || EQ (vertical_type, Qright)
6071 || EQ (vertical_type, Qt)))
6072 error ("Invalid type of vertical scroll bar");
6074 if (!EQ (w->scroll_bar_width, width)
6075 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6077 w->scroll_bar_width = width;
6078 w->vertical_scroll_bar_type = vertical_type;
6080 adjust_window_margins (w);
6082 clear_glyph_matrix (w->current_matrix);
6083 w->window_end_valid = Qnil;
6085 ++windows_or_buffers_changed;
6086 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6089 return Qnil;
6093 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6094 0, 1, 0,
6095 doc: /* Get width and type of scroll bars of window WINDOW.
6096 If WINDOW is omitted or nil, use the currently selected window.
6097 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6098 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6099 value. */)
6100 (window)
6101 Lisp_Object window;
6103 struct window *w = decode_window (window);
6104 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6105 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6106 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6107 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6108 Fcons (w->vertical_scroll_bar_type,
6109 Fcons (Qnil, Qnil))));
6114 /***********************************************************************
6115 Smooth scrolling
6116 ***********************************************************************/
6118 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
6119 doc: /* Return the amount by which WINDOW is scrolled vertically.
6120 Use the selected window if WINDOW is nil or omitted.
6121 Value is a multiple of the canonical character height of WINDOW. */)
6122 (window)
6123 Lisp_Object window;
6125 Lisp_Object result;
6126 struct frame *f;
6127 struct window *w;
6129 if (NILP (window))
6130 window = selected_window;
6131 else
6132 CHECK_WINDOW (window);
6133 w = XWINDOW (window);
6134 f = XFRAME (w->frame);
6136 if (FRAME_WINDOW_P (f))
6137 result = FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
6138 else
6139 result = make_number (0);
6140 return result;
6144 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6145 2, 2, 0,
6146 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6147 WINDOW nil means use the selected window. VSCROLL is a non-negative
6148 multiple of the canonical character height of WINDOW. */)
6149 (window, vscroll)
6150 Lisp_Object window, vscroll;
6152 struct window *w;
6153 struct frame *f;
6155 if (NILP (window))
6156 window = selected_window;
6157 else
6158 CHECK_WINDOW (window);
6159 CHECK_NUMBER_OR_FLOAT (vscroll);
6161 w = XWINDOW (window);
6162 f = XFRAME (w->frame);
6164 if (FRAME_WINDOW_P (f))
6166 int old_dy = w->vscroll;
6168 w->vscroll = - FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll);
6169 w->vscroll = min (w->vscroll, 0);
6171 /* Adjust glyph matrix of the frame if the virtual display
6172 area becomes larger than before. */
6173 if (w->vscroll < 0 && w->vscroll < old_dy)
6174 adjust_glyphs (f);
6176 /* Prevent redisplay shortcuts. */
6177 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6180 return Fwindow_vscroll (window);
6184 /* Call FN for all leaf windows on frame F. FN is called with the
6185 first argument being a pointer to the leaf window, and with
6186 additional argument USER_DATA. Stops when FN returns 0. */
6188 void
6189 foreach_window (f, fn, user_data)
6190 struct frame *f;
6191 int (* fn) P_ ((struct window *, void *));
6192 void *user_data;
6194 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6198 /* Helper function for foreach_window. Call FN for all leaf windows
6199 reachable from W. FN is called with the first argument being a
6200 pointer to the leaf window, and with additional argument USER_DATA.
6201 Stop when FN returns 0. Value is 0 if stopped by FN. */
6203 static int
6204 foreach_window_1 (w, fn, user_data)
6205 struct window *w;
6206 int (* fn) P_ ((struct window *, void *));
6207 void *user_data;
6209 int cont;
6211 for (cont = 1; w && cont;)
6213 if (!NILP (w->hchild))
6214 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6215 else if (!NILP (w->vchild))
6216 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6217 else
6218 cont = fn (w, user_data);
6220 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6223 return cont;
6227 /* Freeze or unfreeze the window start of W unless it is a
6228 mini-window or the selected window. FREEZE_P non-null means freeze
6229 the window start. */
6231 static int
6232 freeze_window_start (w, freeze_p)
6233 struct window *w;
6234 void *freeze_p;
6236 if (w == XWINDOW (selected_window)
6237 || MINI_WINDOW_P (w)
6238 || (MINI_WINDOW_P (XWINDOW (selected_window))
6239 && ! NILP (Vminibuf_scroll_window)
6240 && w == XWINDOW (Vminibuf_scroll_window)))
6241 freeze_p = NULL;
6243 w->frozen_window_start_p = freeze_p != NULL;
6244 return 1;
6248 /* Freeze or unfreeze the window starts of all leaf windows on frame
6249 F, except the selected window and a mini-window. FREEZE_P non-zero
6250 means freeze the window start. */
6252 void
6253 freeze_window_starts (f, freeze_p)
6254 struct frame *f;
6255 int freeze_p;
6257 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6261 /***********************************************************************
6262 Initialization
6263 ***********************************************************************/
6265 /* Return 1 if window configurations C1 and C2
6266 describe the same state of affairs. This is used by Fequal. */
6269 compare_window_configurations (c1, c2, ignore_positions)
6270 Lisp_Object c1, c2;
6271 int ignore_positions;
6273 register struct save_window_data *d1, *d2;
6274 struct Lisp_Vector *sw1, *sw2;
6275 int i;
6277 if (!WINDOW_CONFIGURATIONP (c1))
6278 wrong_type_argument (Qwindow_configuration_p, c1);
6279 if (!WINDOW_CONFIGURATIONP (c2))
6280 wrong_type_argument (Qwindow_configuration_p, c2);
6282 d1 = (struct save_window_data *) XVECTOR (c1);
6283 d2 = (struct save_window_data *) XVECTOR (c2);
6284 sw1 = XVECTOR (d1->saved_windows);
6285 sw2 = XVECTOR (d2->saved_windows);
6287 if (! EQ (d1->frame_cols, d2->frame_cols))
6288 return 0;
6289 if (! EQ (d1->frame_lines, d2->frame_lines))
6290 return 0;
6291 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
6292 return 0;
6293 if (! EQ (d1->selected_frame, d2->selected_frame))
6294 return 0;
6295 /* Don't compare the current_window field directly.
6296 Instead see w1_is_current and w2_is_current, below. */
6297 if (! EQ (d1->current_buffer, d2->current_buffer))
6298 return 0;
6299 if (! ignore_positions)
6301 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
6302 return 0;
6303 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
6304 return 0;
6306 /* Don't compare the root_window field.
6307 We don't require the two configurations
6308 to use the same window object,
6309 and the two root windows must be equivalent
6310 if everything else compares equal. */
6311 if (! EQ (d1->focus_frame, d2->focus_frame))
6312 return 0;
6313 if (! EQ (d1->min_width, d2->min_width))
6314 return 0;
6315 if (! EQ (d1->min_height, d2->min_height))
6316 return 0;
6318 /* Verify that the two confis have the same number of windows. */
6319 if (sw1->size != sw2->size)
6320 return 0;
6322 for (i = 0; i < sw1->size; i++)
6324 struct saved_window *p1, *p2;
6325 int w1_is_current, w2_is_current;
6327 p1 = SAVED_WINDOW_N (sw1, i);
6328 p2 = SAVED_WINDOW_N (sw2, i);
6330 /* Verify that the current windows in the two
6331 configurations correspond to each other. */
6332 w1_is_current = EQ (d1->current_window, p1->window);
6333 w2_is_current = EQ (d2->current_window, p2->window);
6335 if (w1_is_current != w2_is_current)
6336 return 0;
6338 /* Verify that the corresponding windows do match. */
6339 if (! EQ (p1->buffer, p2->buffer))
6340 return 0;
6341 if (! EQ (p1->left_col, p2->left_col))
6342 return 0;
6343 if (! EQ (p1->top_line, p2->top_line))
6344 return 0;
6345 if (! EQ (p1->total_cols, p2->total_cols))
6346 return 0;
6347 if (! EQ (p1->total_lines, p2->total_lines))
6348 return 0;
6349 if (! EQ (p1->display_table, p2->display_table))
6350 return 0;
6351 if (! EQ (p1->parent, p2->parent))
6352 return 0;
6353 if (! EQ (p1->prev, p2->prev))
6354 return 0;
6355 if (! ignore_positions)
6357 if (! EQ (p1->hscroll, p2->hscroll))
6358 return 0;
6359 if (!EQ (p1->min_hscroll, p2->min_hscroll))
6360 return 0;
6361 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
6362 return 0;
6363 if (NILP (Fequal (p1->start, p2->start)))
6364 return 0;
6365 if (NILP (Fequal (p1->pointm, p2->pointm)))
6366 return 0;
6367 if (NILP (Fequal (p1->mark, p2->mark)))
6368 return 0;
6370 if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
6371 return 0;
6372 if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
6373 return 0;
6374 if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
6375 return 0;
6376 if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
6377 return 0;
6378 if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
6379 return 0;
6380 if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
6381 return 0;
6382 if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
6383 return 0;
6386 return 1;
6389 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6390 Scompare_window_configurations, 2, 2, 0,
6391 doc: /* Compare two window configurations as regards the structure of windows.
6392 This function ignores details such as the values of point and mark
6393 and scrolling positions. */)
6394 (x, y)
6395 Lisp_Object x, y;
6397 if (compare_window_configurations (x, y, 1))
6398 return Qt;
6399 return Qnil;
6402 void
6403 init_window_once ()
6405 struct frame *f = make_terminal_frame ();
6406 XSETFRAME (selected_frame, f);
6407 Vterminal_frame = selected_frame;
6408 minibuf_window = f->minibuffer_window;
6409 selected_window = f->selected_window;
6410 last_nonminibuf_frame = f;
6412 window_initialized = 1;
6415 void
6416 init_window ()
6418 Vwindow_list = Qnil;
6421 void
6422 syms_of_window ()
6424 Qwindow_size_fixed = intern ("window-size-fixed");
6425 staticpro (&Qwindow_size_fixed);
6427 staticpro (&Qwindow_configuration_change_hook);
6428 Qwindow_configuration_change_hook
6429 = intern ("window-configuration-change-hook");
6431 Qwindowp = intern ("windowp");
6432 staticpro (&Qwindowp);
6434 Qwindow_configuration_p = intern ("window-configuration-p");
6435 staticpro (&Qwindow_configuration_p);
6437 Qwindow_live_p = intern ("window-live-p");
6438 staticpro (&Qwindow_live_p);
6440 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
6441 staticpro (&Qtemp_buffer_show_hook);
6443 staticpro (&Vwindow_list);
6445 minibuf_selected_window = Qnil;
6446 staticpro (&minibuf_selected_window);
6448 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
6449 doc: /* Non-nil means call as function to display a help buffer.
6450 The function is called with one argument, the buffer to be displayed.
6451 Used by `with-output-to-temp-buffer'.
6452 If this function is used, then it must do the entire job of showing
6453 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6454 Vtemp_buffer_show_function = Qnil;
6456 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
6457 doc: /* If non-nil, function to call to handle `display-buffer'.
6458 It will receive two args, the buffer and a flag which if non-nil means
6459 that the currently selected window is not acceptable.
6460 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
6461 work using this function. */);
6462 Vdisplay_buffer_function = Qnil;
6464 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
6465 doc: /* *If non-nil, `display-buffer' should even the window heights.
6466 If nil, `display-buffer' will leave the window configuration alone. */);
6467 Veven_window_heights = Qt;
6469 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
6470 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6471 Vminibuf_scroll_window = Qnil;
6473 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
6474 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6475 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6476 is displayed in the `mode-line' face. */);
6477 mode_line_in_non_selected_windows = 1;
6479 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
6480 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6481 Vother_window_scroll_buffer = Qnil;
6483 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
6484 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
6485 pop_up_frames = 0;
6487 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
6488 doc: /* *Non-nil means `display-buffer' should reuse frames.
6489 If the buffer in question is already displayed in a frame, raise that frame. */);
6490 display_buffer_reuse_frames = 0;
6492 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
6493 doc: /* Function to call to handle automatic new frame creation.
6494 It is called with no arguments and should return a newly created frame.
6496 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
6497 where `pop-up-frame-alist' would hold the default frame parameters. */);
6498 Vpop_up_frame_function = Qnil;
6500 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
6501 doc: /* *List of buffer names that should have their own special frames.
6502 Displaying a buffer whose name is in this list makes a special frame for it
6503 using `special-display-function'. See also `special-display-regexps'.
6505 An element of the list can be a list instead of just a string.
6506 There are two ways to use a list as an element:
6507 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
6508 In the first case, FRAME-PARAMETERS are used to create the frame.
6509 In the latter case, FUNCTION is called with BUFFER as the first argument,
6510 followed by OTHER-ARGS--it can display BUFFER in any way it likes.
6511 All this is done by the function found in `special-display-function'.
6513 If the specified frame parameters include (same-buffer . t), the
6514 buffer is displayed in the currently selected window. Otherwise, if
6515 they include (same-frame . t), the buffer is displayed in a new window
6516 in the currently selected frame.
6518 If this variable appears \"not to work\", because you add a name to it
6519 but that buffer still appears in the selected window, look at the
6520 values of `same-window-buffer-names' and `same-window-regexps'.
6521 Those variables take precedence over this one. */);
6522 Vspecial_display_buffer_names = Qnil;
6524 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
6525 doc: /* *List of regexps saying which buffers should have their own special frames.
6526 If a buffer name matches one of these regexps, it gets its own frame.
6527 Displaying a buffer whose name is in this list makes a special frame for it
6528 using `special-display-function'.
6530 An element of the list can be a list instead of just a string.
6531 There are two ways to use a list as an element:
6532 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
6533 In the first case, FRAME-PARAMETERS are used to create the frame.
6534 In the latter case, FUNCTION is called with the buffer as first argument,
6535 followed by OTHER-ARGS--it can display the buffer in any way it likes.
6536 All this is done by the function found in `special-display-function'.
6538 If the specified frame parameters include (same-buffer . t), the
6539 buffer is displayed in the currently selected window. Otherwise, if
6540 they include (same-frame . t), the buffer is displayed in a new window
6541 in the currently selected frame.
6543 If this variable appears \"not to work\", because you add a regexp to it
6544 but the matching buffers still appear in the selected window, look at the
6545 values of `same-window-buffer-names' and `same-window-regexps'.
6546 Those variables take precedence over this one. */);
6547 Vspecial_display_regexps = Qnil;
6549 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
6550 doc: /* Function to call to make a new frame for a special buffer.
6551 It is called with two arguments, the buffer and optional buffer specific
6552 data, and should return a window displaying that buffer.
6553 The default value normally makes a separate frame for the buffer,
6554 using `special-display-frame-alist' to specify the frame parameters.
6555 But if the buffer specific data includes (same-buffer . t) then the
6556 buffer is displayed in the current selected window.
6557 Otherwise if it includes (same-frame . t) then the buffer is displayed in
6558 a new window in the currently selected frame.
6560 A buffer is special if it is listed in `special-display-buffer-names'
6561 or matches a regexp in `special-display-regexps'. */);
6562 Vspecial_display_function = Qnil;
6564 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
6565 doc: /* *List of buffer names that should appear in the selected window.
6566 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
6567 switches to it in the selected window, rather than making it appear
6568 in some other window.
6570 An element of the list can be a cons cell instead of just a string.
6571 Then the car must be a string, which specifies the buffer name.
6572 This is for compatibility with `special-display-buffer-names';
6573 the cdr of the cons cell is ignored.
6575 See also `same-window-regexps'. */);
6576 Vsame_window_buffer_names = Qnil;
6578 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
6579 doc: /* *List of regexps saying which buffers should appear in the selected window.
6580 If a buffer name matches one of these regexps, then displaying it
6581 using `display-buffer' or `pop-to-buffer' switches to it
6582 in the selected window, rather than making it appear in some other window.
6584 An element of the list can be a cons cell instead of just a string.
6585 Then the car must be a string, which specifies the buffer name.
6586 This is for compatibility with `special-display-buffer-names';
6587 the cdr of the cons cell is ignored.
6589 See also `same-window-buffer-names'. */);
6590 Vsame_window_regexps = Qnil;
6592 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
6593 doc: /* *Non-nil means display-buffer should make new windows. */);
6594 pop_up_windows = 1;
6596 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
6597 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
6598 next_screen_context_lines = 2;
6600 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
6601 doc: /* *display-buffer would prefer to split the largest window if this large.
6602 If there is only one window, it is split regardless of this value. */);
6603 split_height_threshold = 500;
6605 DEFVAR_INT ("window-min-height", &window_min_height,
6606 doc: /* *Delete any window less than this tall (including its mode line). */);
6607 window_min_height = 4;
6609 DEFVAR_INT ("window-min-width", &window_min_width,
6610 doc: /* *Delete any window less than this wide. */);
6611 window_min_width = 10;
6613 DEFVAR_LISP ("scroll-preserve-screen-position",
6614 &Vscroll_preserve_screen_position,
6615 doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged. */);
6616 Vscroll_preserve_screen_position = Qnil;
6618 DEFVAR_LISP ("window-configuration-change-hook",
6619 &Vwindow_configuration_change_hook,
6620 doc: /* Functions to call when window configuration changes.
6621 The selected frame is the one whose configuration has changed. */);
6622 Vwindow_configuration_change_hook = Qnil;
6624 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed,
6625 doc: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
6626 Emacs won't change the size of any window displaying that buffer,
6627 unless you explicitly change the size, or Emacs has no other choice.
6628 This variable automatically becomes buffer-local when set. */);
6629 Fmake_variable_buffer_local (Qwindow_size_fixed);
6630 window_size_fixed = 0;
6632 defsubr (&Sselected_window);
6633 defsubr (&Sminibuffer_window);
6634 defsubr (&Swindow_minibuffer_p);
6635 defsubr (&Swindowp);
6636 defsubr (&Swindow_live_p);
6637 defsubr (&Spos_visible_in_window_p);
6638 defsubr (&Swindow_buffer);
6639 defsubr (&Swindow_height);
6640 defsubr (&Swindow_width);
6641 defsubr (&Swindow_hscroll);
6642 defsubr (&Sset_window_hscroll);
6643 defsubr (&Swindow_redisplay_end_trigger);
6644 defsubr (&Sset_window_redisplay_end_trigger);
6645 defsubr (&Swindow_edges);
6646 defsubr (&Swindow_pixel_edges);
6647 defsubr (&Swindow_inside_edges);
6648 defsubr (&Swindow_inside_pixel_edges);
6649 defsubr (&Scoordinates_in_window_p);
6650 defsubr (&Swindow_at);
6651 defsubr (&Swindow_point);
6652 defsubr (&Swindow_start);
6653 defsubr (&Swindow_end);
6654 defsubr (&Sset_window_point);
6655 defsubr (&Sset_window_start);
6656 defsubr (&Swindow_dedicated_p);
6657 defsubr (&Sset_window_dedicated_p);
6658 defsubr (&Swindow_display_table);
6659 defsubr (&Sset_window_display_table);
6660 defsubr (&Snext_window);
6661 defsubr (&Sprevious_window);
6662 defsubr (&Sother_window);
6663 defsubr (&Sget_lru_window);
6664 defsubr (&Sget_largest_window);
6665 defsubr (&Sget_buffer_window);
6666 defsubr (&Sdelete_other_windows);
6667 defsubr (&Sdelete_windows_on);
6668 defsubr (&Sreplace_buffer_in_windows);
6669 defsubr (&Sdelete_window);
6670 defsubr (&Sset_window_buffer);
6671 defsubr (&Sselect_window);
6672 defsubr (&Sspecial_display_p);
6673 defsubr (&Ssame_window_p);
6674 defsubr (&Sdisplay_buffer);
6675 defsubr (&Sforce_window_update);
6676 defsubr (&Ssplit_window);
6677 defsubr (&Senlarge_window);
6678 defsubr (&Sshrink_window);
6679 defsubr (&Sscroll_up);
6680 defsubr (&Sscroll_down);
6681 defsubr (&Sscroll_left);
6682 defsubr (&Sscroll_right);
6683 defsubr (&Sother_window_for_scrolling);
6684 defsubr (&Sscroll_other_window);
6685 defsubr (&Sminibuffer_selected_window);
6686 defsubr (&Srecenter);
6687 defsubr (&Swindow_text_height);
6688 defsubr (&Smove_to_window_line);
6689 defsubr (&Swindow_configuration_p);
6690 defsubr (&Swindow_configuration_frame);
6691 defsubr (&Sset_window_configuration);
6692 defsubr (&Scurrent_window_configuration);
6693 defsubr (&Ssave_window_excursion);
6694 defsubr (&Sset_window_margins);
6695 defsubr (&Swindow_margins);
6696 defsubr (&Sset_window_fringes);
6697 defsubr (&Swindow_fringes);
6698 defsubr (&Sset_window_scroll_bars);
6699 defsubr (&Swindow_scroll_bars);
6700 defsubr (&Swindow_vscroll);
6701 defsubr (&Sset_window_vscroll);
6702 defsubr (&Scompare_window_configurations);
6703 defsubr (&Swindow_list);
6706 void
6707 keys_of_window ()
6709 initial_define_key (control_x_map, '1', "delete-other-windows");
6710 initial_define_key (control_x_map, '2', "split-window");
6711 initial_define_key (control_x_map, '0', "delete-window");
6712 initial_define_key (control_x_map, 'o', "other-window");
6713 initial_define_key (control_x_map, '^', "enlarge-window");
6714 initial_define_key (control_x_map, '<', "scroll-left");
6715 initial_define_key (control_x_map, '>', "scroll-right");
6717 initial_define_key (global_map, Ctl ('V'), "scroll-up");
6718 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6719 initial_define_key (meta_map, 'v', "scroll-down");
6721 initial_define_key (global_map, Ctl('L'), "recenter");
6722 initial_define_key (meta_map, 'r', "move-to-window-line");
6725 /* arch-tag: 90a9c576-0590-48f1-a5f1-6c96a0452d9f
6726 (do not change this comment) */