Fix typo in comment.
[emacs.git] / src / window.c
blob8b179cb29e970577e835fd9d836cadff1d228dad
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 Lisp_Object select_window_1 P_ ((Lisp_Object, int));
59 static int count_windows P_ ((struct window *));
60 static int get_leaf_windows P_ ((struct window *, struct window **, int));
61 static void window_scroll P_ ((Lisp_Object, int, int, int));
62 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
63 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
64 static int window_min_size_1 P_ ((struct window *, int));
65 static int window_min_size P_ ((struct window *, int, int, int *));
66 static void size_window P_ ((Lisp_Object, int, int, int));
67 static int freeze_window_start P_ ((struct window *, void *));
68 static int window_fixed_size_p P_ ((struct window *, int, int));
69 static void enlarge_window P_ ((Lisp_Object, int, int, int));
70 static Lisp_Object window_list P_ ((void));
71 static int add_window_to_list P_ ((struct window *, void *));
72 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
73 Lisp_Object));
74 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
75 Lisp_Object, int));
76 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
77 Lisp_Object *));
78 static int foreach_window_1 P_ ((struct window *,
79 int (* fn) (struct window *, void *),
80 void *));
81 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
83 /* The value of `window-size-fixed'. */
85 int window_size_fixed;
87 /* This is the window in which the terminal's cursor should
88 be left when nothing is being done with it. This must
89 always be a leaf window, and its buffer is selected by
90 the top level editing loop at the end of each command.
92 This value is always the same as
93 FRAME_SELECTED_WINDOW (selected_frame). */
95 Lisp_Object selected_window;
97 /* A list of all windows for use by next_window and Fwindow_list.
98 Functions creating or deleting windows should invalidate this cache
99 by setting it to nil. */
101 Lisp_Object Vwindow_list;
103 /* The mini-buffer window of the selected frame.
104 Note that you cannot test for mini-bufferness of an arbitrary window
105 by comparing against this; but you can test for mini-bufferness of
106 the selected window. */
108 Lisp_Object minibuf_window;
110 /* Non-nil means it is the window whose mode line should be
111 shown as the selected window when the minibuffer is selected. */
113 Lisp_Object minibuf_selected_window;
115 /* Non-nil means it is the window for C-M-v to scroll
116 when the mini-buffer is selected. */
118 Lisp_Object Vminibuf_scroll_window;
120 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
122 Lisp_Object Vother_window_scroll_buffer;
124 /* Non-nil means it's function to call to display temp buffers. */
126 Lisp_Object Vtemp_buffer_show_function;
128 /* Non-zero means to use mode-line-inactive face in all windows but the
129 selected-window and the minibuffer-scroll-window when the
130 minibuffer is active. */
131 int mode_line_in_non_selected_windows;
133 /* If a window gets smaller than either of these, it is removed. */
135 EMACS_INT window_min_height;
136 EMACS_INT window_min_width;
138 /* Nonzero implies Fdisplay_buffer should create windows. */
140 int pop_up_windows;
142 /* Nonzero implies make new frames for Fdisplay_buffer. */
144 int pop_up_frames;
146 /* Nonzero means reuse existing frames for displaying buffers. */
148 int display_buffer_reuse_frames;
150 /* Non-nil means use this function instead of default */
152 Lisp_Object Vpop_up_frame_function;
154 /* Function to call to handle Fdisplay_buffer. */
156 Lisp_Object Vdisplay_buffer_function;
158 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
160 Lisp_Object Veven_window_heights;
162 /* List of buffer *names* for buffers that should have their own frames. */
164 Lisp_Object Vspecial_display_buffer_names;
166 /* List of regexps for buffer names that should have their own frames. */
168 Lisp_Object Vspecial_display_regexps;
170 /* Function to pop up a special frame. */
172 Lisp_Object Vspecial_display_function;
174 /* List of buffer *names* for buffers to appear in selected window. */
176 Lisp_Object Vsame_window_buffer_names;
178 /* List of regexps for buffer names to appear in selected window. */
180 Lisp_Object Vsame_window_regexps;
182 /* Hook run at end of temp_output_buffer_show. */
184 Lisp_Object Qtemp_buffer_show_hook;
186 /* Fdisplay_buffer always splits the largest window
187 if that window is more than this high. */
189 EMACS_INT split_height_threshold;
191 /* Number of lines of continuity in scrolling by screenfuls. */
193 EMACS_INT next_screen_context_lines;
195 /* Incremented for each window created. */
197 static int sequence_number;
199 /* Nonzero after init_window_once has finished. */
201 static int window_initialized;
203 /* Hook to run when window config changes. */
205 Lisp_Object Qwindow_configuration_change_hook;
206 Lisp_Object Vwindow_configuration_change_hook;
208 /* Nonzero means scroll commands try to put point
209 at the same screen height as previously. */
211 Lisp_Object Vscroll_preserve_screen_position;
213 #if 0 /* This isn't used anywhere. */
214 /* Nonzero means we can split a frame even if it is "unsplittable". */
215 static int inhibit_frame_unsplittable;
216 #endif /* 0 */
218 extern EMACS_INT scroll_margin;
220 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
222 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
223 doc: /* Returns t if OBJECT is a window. */)
224 (object)
225 Lisp_Object object;
227 return WINDOWP (object) ? Qt : Qnil;
230 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
231 doc: /* Returns t if OBJECT is a window which is currently visible. */)
232 (object)
233 Lisp_Object object;
235 return WINDOW_LIVE_P (object) ? Qt : Qnil;
238 Lisp_Object
239 make_window ()
241 Lisp_Object val;
242 register struct window *p;
244 p = allocate_window ();
245 XSETFASTINT (p->sequence_number, ++sequence_number);
246 XSETFASTINT (p->left, 0);
247 XSETFASTINT (p->top, 0);
248 XSETFASTINT (p->height, 0);
249 XSETFASTINT (p->width, 0);
250 XSETFASTINT (p->hscroll, 0);
251 XSETFASTINT (p->min_hscroll, 0);
252 p->orig_top = p->orig_height = Qnil;
253 p->start = Fmake_marker ();
254 p->pointm = Fmake_marker ();
255 XSETFASTINT (p->use_time, 0);
256 p->frame = Qnil;
257 p->display_table = Qnil;
258 p->dedicated = Qnil;
259 p->pseudo_window_p = 0;
260 bzero (&p->cursor, sizeof (p->cursor));
261 bzero (&p->last_cursor, sizeof (p->last_cursor));
262 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
263 p->desired_matrix = p->current_matrix = 0;
264 p->phys_cursor_type = -1;
265 p->phys_cursor_width = -1;
266 p->must_be_updated_p = 0;
267 XSETFASTINT (p->window_end_vpos, 0);
268 XSETFASTINT (p->window_end_pos, 0);
269 p->window_end_valid = Qnil;
270 p->vscroll = 0;
271 XSETWINDOW (val, p);
272 XSETFASTINT (p->last_point, 0);
273 p->frozen_window_start_p = 0;
274 p->height_fixed_p = 0;
275 p->last_cursor_off_p = p->cursor_off_p = 0;
277 Vwindow_list = Qnil;
278 return val;
281 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
282 doc: /* Return the window that the cursor now appears in and commands apply to. */)
285 return selected_window;
288 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
289 doc: /* Return the window used now for minibuffers.
290 If the optional argument FRAME is specified, return the minibuffer window
291 used by that frame. */)
292 (frame)
293 Lisp_Object frame;
295 if (NILP (frame))
296 frame = selected_frame;
297 CHECK_LIVE_FRAME (frame);
298 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
301 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
302 doc: /* Returns non-nil if WINDOW is a minibuffer window. */)
303 (window)
304 Lisp_Object window;
306 struct window *w = decode_window (window);
307 return MINI_WINDOW_P (w) ? Qt : Qnil;
311 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
312 Spos_visible_in_window_p, 0, 3, 0,
313 doc: /* Return t if position POS is currently on the frame in WINDOW.
314 Return nil if that position is scrolled vertically out of view.
315 If a character is only partially visible, nil is returned, unless the
316 optional argument PARTIALLY is non-nil.
317 POS defaults to point in WINDOW; WINDOW defaults to the selected window. */)
318 (pos, window, partially)
319 Lisp_Object pos, window, partially;
321 register struct window *w;
322 register int posint;
323 register struct buffer *buf;
324 struct text_pos top;
325 Lisp_Object in_window;
326 int fully_p;
328 w = decode_window (window);
329 buf = XBUFFER (w->buffer);
330 SET_TEXT_POS_FROM_MARKER (top, w->start);
332 if (!NILP (pos))
334 CHECK_NUMBER_COERCE_MARKER (pos);
335 posint = XINT (pos);
337 else if (w == XWINDOW (selected_window))
338 posint = PT;
339 else
340 posint = XMARKER (w->pointm)->charpos;
342 /* If position is above window start, it's not visible. */
343 if (posint < CHARPOS (top))
344 in_window = Qnil;
345 else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
346 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
347 && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
349 /* If frame is up-to-date, and POSINT is < window end pos, use
350 that info. This doesn't work for POSINT == end pos, because
351 the window end pos is actually the position _after_ the last
352 char in the window. */
353 if (NILP (partially))
355 pos_visible_p (w, posint, &fully_p, NILP (partially));
356 in_window = fully_p ? Qt : Qnil;
358 else
359 in_window = Qt;
361 else if (posint > BUF_ZV (buf))
362 in_window = Qnil;
363 else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
364 /* If window start is out of range, do something reasonable. */
365 in_window = Qnil;
366 else
368 if (pos_visible_p (w, posint, &fully_p, NILP (partially)))
369 in_window = !NILP (partially) || fully_p ? Qt : Qnil;
370 else
371 in_window = Qnil;
374 return in_window;
378 static struct window *
379 decode_window (window)
380 register Lisp_Object window;
382 if (NILP (window))
383 return XWINDOW (selected_window);
385 CHECK_LIVE_WINDOW (window);
386 return XWINDOW (window);
389 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
390 doc: /* Return the buffer that WINDOW is displaying. */)
391 (window)
392 Lisp_Object window;
394 return decode_window (window)->buffer;
397 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
398 doc: /* Return the number of lines in WINDOW (including its mode line). */)
399 (window)
400 Lisp_Object window;
402 return decode_window (window)->height;
405 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
406 doc: /* Return the number of display columns in WINDOW.
407 This is the width that is usable columns available for text in WINDOW.
408 If you want to find out how many columns WINDOW takes up,
409 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
410 (window)
411 Lisp_Object window;
413 return make_number (window_internal_width (decode_window (window)));
416 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
417 doc: /* Return the number of columns by which WINDOW is scrolled from left margin. */)
418 (window)
419 Lisp_Object window;
421 return decode_window (window)->hscroll;
424 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
425 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
426 NCOL should be zero or positive.
428 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
429 window so that the location of point becomes invisible. */)
430 (window, ncol)
431 Lisp_Object window, ncol;
433 struct window *w = decode_window (window);
434 int hscroll;
436 CHECK_NUMBER (ncol);
437 hscroll = max (0, XINT (ncol));
439 /* Prevent redisplay shortcuts when changing the hscroll. */
440 if (XINT (w->hscroll) != hscroll)
441 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
443 w->hscroll = make_number (hscroll);
444 return ncol;
447 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
448 Swindow_redisplay_end_trigger, 0, 1, 0,
449 doc: /* Return WINDOW's redisplay end trigger value.
450 See `set-window-redisplay-end-trigger' for more information. */)
451 (window)
452 Lisp_Object window;
454 return decode_window (window)->redisplay_end_trigger;
457 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
458 Sset_window_redisplay_end_trigger, 2, 2, 0,
459 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
460 VALUE should be a buffer position (typically a marker) or nil.
461 If it is a buffer position, then if redisplay in WINDOW reaches a position
462 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
463 with two arguments: WINDOW, and the end trigger value.
464 Afterwards the end-trigger value is reset to nil. */)
465 (window, value)
466 register Lisp_Object window, value;
468 register struct window *w;
470 w = decode_window (window);
471 w->redisplay_end_trigger = value;
472 return value;
475 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
476 doc: /* Return a list of the edge coordinates of WINDOW.
477 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
478 RIGHT is one more than the rightmost column used by WINDOW,
479 and BOTTOM is one more than the bottommost row used by WINDOW
480 and its mode-line. */)
481 (window)
482 Lisp_Object window;
484 register struct window *w = decode_window (window);
486 return Fcons (w->left, Fcons (w->top,
487 Fcons (make_number (WINDOW_RIGHT_EDGE (w)),
488 Fcons (make_number (XFASTINT (w->top)
489 + XFASTINT (w->height)),
490 Qnil))));
493 /* Test if the character at column *X, row *Y is within window W.
494 If it is not, return ON_NOTHING;
495 if it is in the window's text area,
496 set *x and *y to its location relative to the upper left corner
497 of the window, and
498 return ON_TEXT;
499 if it is on the window's modeline, return ON_MODE_LINE;
500 if it is on the border between the window and its right sibling,
501 return ON_VERTICAL_BORDER.
502 if it is on the window's top line, return ON_HEADER_LINE;
503 if it is in left or right fringe of the window,
504 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE, and convert *X and *Y
505 to window-relative coordinates;
506 if it is in the marginal area to the left/right of the window,
507 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN, and convert *X and *Y
508 to window-relative coordinates.
510 X and Y are frame relative pixel coordinates. */
512 static enum window_part
513 coordinates_in_window (w, x, y)
514 register struct window *w;
515 register int *x, *y;
517 /* Let's make this a global enum later, instead of using numbers
518 everywhere. */
519 struct frame *f = XFRAME (WINDOW_FRAME (w));
520 int left_x, right_x, top_y, bottom_y;
521 enum window_part part;
522 int ux = CANON_X_UNIT (f);
523 int x0 = XFASTINT (w->left) * ux;
524 int x1 = x0 + XFASTINT (w->width) * ux;
525 /* The width of the area where the vertical line can be dragged.
526 (Between mode lines for instance. */
527 int grabbable_width = ux;
528 int lmargin_width = 0, rmargin_width = 0;
530 if (*x < x0 || *x >= x1)
531 return ON_NOTHING;
533 /* In what's below, we subtract 1 when computing right_x because we
534 want the rightmost pixel, which is given by left_pixel+width-1. */
535 if (w->pseudo_window_p)
537 left_x = 0;
538 right_x = XFASTINT (w->width) * CANON_X_UNIT (f) - 1;
539 top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
540 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
542 else
544 left_x = (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w)
545 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
546 right_x = WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w) - 1;
547 top_y = (WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w)
548 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
549 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
552 /* On the mode line or header line? If it's near the start of
553 the mode or header line of window that's has a horizontal
554 sibling, say it's on the vertical line. That's to be able
555 to resize windows horizontally in case we're using toolkit
556 scroll bars. */
558 if (WINDOW_WANTS_MODELINE_P (w)
559 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
560 && *y < bottom_y)
562 /* We're somewhere on the mode line. We consider the place
563 between mode lines of horizontally adjacent mode lines
564 as the vertical border. If scroll bars on the left,
565 return the right window. */
566 part = ON_MODE_LINE;
568 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
570 if (abs (*x - x0) < grabbable_width)
571 part = ON_VERTICAL_BORDER;
573 else if (!WINDOW_RIGHTMOST_P (w) && abs (*x - x1) < grabbable_width)
574 part = ON_VERTICAL_BORDER;
576 else if (WINDOW_WANTS_HEADER_LINE_P (w)
577 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
578 && *y >= top_y)
580 part = ON_HEADER_LINE;
582 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
584 if (abs (*x - x0) < grabbable_width)
585 part = ON_VERTICAL_BORDER;
587 else if (!WINDOW_RIGHTMOST_P (w) && abs (*x - x1) < grabbable_width)
588 part = ON_VERTICAL_BORDER;
590 /* Outside anything interesting? */
591 else if (*y < top_y
592 || *y >= bottom_y
593 || *x < (left_x
594 - FRAME_LEFT_FRINGE_WIDTH (f)
595 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * ux)
596 || *x > (right_x
597 + FRAME_RIGHT_FRINGE_WIDTH (f)
598 + FRAME_RIGHT_SCROLL_BAR_WIDTH (f) * ux))
600 part = ON_NOTHING;
602 else if (FRAME_WINDOW_P (f))
604 if (!w->pseudo_window_p
605 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)
606 && !WINDOW_RIGHTMOST_P (w)
607 && (abs (*x - right_x - FRAME_RIGHT_FRINGE_WIDTH (f)) < grabbable_width))
609 part = ON_VERTICAL_BORDER;
611 else if (*x < left_x || *x > right_x)
613 /* Other lines than the mode line don't include fringes and
614 scroll bars on the left. */
616 /* Convert X and Y to window-relative pixel coordinates. */
617 *x -= left_x;
618 *y -= top_y;
619 part = *x < left_x ? ON_LEFT_FRINGE : ON_RIGHT_FRINGE;
621 else
623 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
624 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
625 /* You can never be on a margin area if its width is zero. */
626 if (lmargin_width
627 && *x <= window_box_right (w, LEFT_MARGIN_AREA))
628 part = ON_LEFT_MARGIN;
629 else if (rmargin_width
630 && *x >= window_box_left (w, RIGHT_MARGIN_AREA))
631 part = ON_RIGHT_MARGIN;
632 else
634 part = ON_TEXT;
635 *x -= left_x;
636 *y -= top_y;
640 else
642 /* Need to say "*x > right_x" rather than >=, since on character
643 terminals, the vertical line's x coordinate is right_x. */
644 if (*x < left_x || *x > right_x)
646 /* Other lines than the mode line don't include fringes and
647 scroll bars on the left. */
649 /* Convert X and Y to window-relative pixel coordinates. */
650 *x -= left_x;
651 *y -= top_y;
652 part = *x < left_x ? ON_LEFT_FRINGE : ON_RIGHT_FRINGE;
654 /* Here, too, "*x > right_x" is because of character terminals. */
655 else if (!w->pseudo_window_p
656 && !WINDOW_RIGHTMOST_P (w)
657 && *x > right_x - ux)
659 /* On the border on the right side of the window? Assume that
660 this area begins at RIGHT_X minus a canonical char width. */
661 part = ON_VERTICAL_BORDER;
663 else
665 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
666 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
667 /* You can never be on a margin area if its width is zero.
668 This is especially important for character terminals. */
669 if (lmargin_width
670 && *x <= window_box_right (w, LEFT_MARGIN_AREA))
671 part = ON_LEFT_MARGIN;
672 else if (rmargin_width
673 && *x >= window_box_left (w, RIGHT_MARGIN_AREA))
674 part = ON_RIGHT_MARGIN;
675 else
677 part = ON_TEXT;
678 /* Convert X and Y to window-relative pixel coordinates. */
679 *x -= left_x;
680 *y -= top_y;
685 return part;
689 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
690 Scoordinates_in_window_p, 2, 2, 0,
691 doc: /* Return non-nil if COORDINATES are in WINDOW.
692 COORDINATES is a cons of the form (X . Y), X and Y being distances
693 measured in characters from the upper-left corner of the frame.
694 \(0 . 0) denotes the character in the upper left corner of the
695 frame.
696 If COORDINATES are in the text portion of WINDOW,
697 the coordinates relative to the window are returned.
698 If they are in the mode line of WINDOW, `mode-line' is returned.
699 If they are in the top mode line of WINDOW, `header-line' is returned.
700 If they are in the left fringe of WINDOW, `left-fringe' is returned.
701 If they are in the right fringe of WINDOW, `right-fringe' is returned.
702 If they are on the border between WINDOW and its right sibling,
703 `vertical-line' is returned.
704 If they are in the windows's left or right marginal areas, `left-margin'\n\
705 or `right-margin' is returned. */)
706 (coordinates, window)
707 register Lisp_Object coordinates, window;
709 struct window *w;
710 struct frame *f;
711 int x, y;
712 Lisp_Object lx, ly;
714 CHECK_LIVE_WINDOW (window);
715 w = XWINDOW (window);
716 f = XFRAME (w->frame);
717 CHECK_CONS (coordinates);
718 lx = Fcar (coordinates);
719 ly = Fcdr (coordinates);
720 CHECK_NUMBER_OR_FLOAT (lx);
721 CHECK_NUMBER_OR_FLOAT (ly);
722 x = PIXEL_X_FROM_CANON_X (f, lx);
723 y = PIXEL_Y_FROM_CANON_Y (f, ly);
725 switch (coordinates_in_window (w, &x, &y))
727 case ON_NOTHING:
728 return Qnil;
730 case ON_TEXT:
731 /* X and Y are now window relative pixel coordinates. Convert
732 them to canonical char units before returning them. */
733 return Fcons (CANON_X_FROM_PIXEL_X (f, x),
734 CANON_Y_FROM_PIXEL_Y (f, y));
736 case ON_MODE_LINE:
737 return Qmode_line;
739 case ON_VERTICAL_BORDER:
740 return Qvertical_line;
742 case ON_HEADER_LINE:
743 return Qheader_line;
745 case ON_LEFT_FRINGE:
746 return Qleft_fringe;
748 case ON_RIGHT_FRINGE:
749 return Qright_fringe;
751 case ON_LEFT_MARGIN:
752 return Qleft_margin;
754 case ON_RIGHT_MARGIN:
755 return Qright_margin;
757 default:
758 abort ();
763 /* Callback for foreach_window, used in window_from_coordinates.
764 Check if window W contains coordinates specified by USER_DATA which
765 is actually a pointer to a struct check_window_data CW.
767 Check if window W contains coordinates *CW->x and *CW->y. If it
768 does, return W in *CW->window, as Lisp_Object, and return in
769 *CW->part the part of the window under coordinates *X,*Y. Return
770 zero from this function to stop iterating over windows. */
772 struct check_window_data
774 Lisp_Object *window;
775 int *x, *y;
776 enum window_part *part;
779 static int
780 check_window_containing (w, user_data)
781 struct window *w;
782 void *user_data;
784 struct check_window_data *cw = (struct check_window_data *) user_data;
785 enum window_part found;
786 int continue_p = 1;
788 found = coordinates_in_window (w, cw->x, cw->y);
789 if (found != ON_NOTHING)
791 *cw->part = found;
792 XSETWINDOW (*cw->window, w);
793 continue_p = 0;
796 return continue_p;
800 /* Find the window containing frame-relative pixel position X/Y and
801 return it as a Lisp_Object. If X, Y is on one of the window's
802 special `window_part' elements, set *PART to the id of that element.
803 If there is no window under X, Y return nil and leave *PART
804 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
806 This function was previously implemented with a loop cycling over
807 windows with Fnext_window, and starting with the frame's selected
808 window. It turned out that this doesn't work with an
809 implementation of next_window using Vwindow_list, because
810 FRAME_SELECTED_WINDOW (F) is not always contained in the window
811 tree of F when this function is called asynchronously from
812 note_mouse_highlight. The original loop didn't terminate in this
813 case. */
815 Lisp_Object
816 window_from_coordinates (f, x, y, part, tool_bar_p)
817 struct frame *f;
818 int x, y;
819 enum window_part *part;
820 int tool_bar_p;
822 Lisp_Object window;
823 struct check_window_data cw;
824 enum window_part dummy;
826 if (part == 0)
827 part = &dummy;
829 window = Qnil;
830 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
831 foreach_window (f, check_window_containing, &cw);
833 /* If not found above, see if it's in the tool bar window, if a tool
834 bar exists. */
835 if (NILP (window)
836 && tool_bar_p
837 && WINDOWP (f->tool_bar_window)
838 && XINT (XWINDOW (f->tool_bar_window)->height) > 0
839 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
840 != ON_NOTHING))
842 *part = ON_TEXT;
843 window = f->tool_bar_window;
846 return window;
849 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
850 doc: /* Return window containing coordinates X and Y on FRAME.
851 If omitted, FRAME defaults to the currently selected frame.
852 The top left corner of the frame is considered to be row 0,
853 column 0. */)
854 (x, y, frame)
855 Lisp_Object x, y, frame;
857 struct frame *f;
859 if (NILP (frame))
860 frame = selected_frame;
861 CHECK_LIVE_FRAME (frame);
862 f = XFRAME (frame);
864 /* Check that arguments are integers or floats. */
865 CHECK_NUMBER_OR_FLOAT (x);
866 CHECK_NUMBER_OR_FLOAT (y);
868 return window_from_coordinates (f,
869 PIXEL_X_FROM_CANON_X (f, x),
870 PIXEL_Y_FROM_CANON_Y (f, y),
871 0, 0);
874 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
875 doc: /* Return current value of point in WINDOW.
876 For a nonselected window, this is the value point would have
877 if that window were selected.
879 Note that, when WINDOW is the selected window and its buffer
880 is also currently selected, the value returned is the same as (point).
881 It would be more strictly correct to return the `top-level' value
882 of point, outside of any save-excursion forms.
883 But that is hard to define. */)
884 (window)
885 Lisp_Object window;
887 register struct window *w = decode_window (window);
889 if (w == XWINDOW (selected_window)
890 && current_buffer == XBUFFER (w->buffer))
891 return Fpoint ();
892 return Fmarker_position (w->pointm);
895 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
896 doc: /* Return position at which display currently starts in WINDOW.
897 This is updated by redisplay or by calling `set-window-start'. */)
898 (window)
899 Lisp_Object window;
901 return Fmarker_position (decode_window (window)->start);
904 /* This is text temporarily removed from the doc string below.
906 This function returns nil if the position is not currently known.
907 That happens when redisplay is preempted and doesn't finish.
908 If in that case you want to compute where the end of the window would
909 have been if redisplay had finished, do this:
910 (save-excursion
911 (goto-char (window-start window))
912 (vertical-motion (1- (window-height window)) window)
913 (point))") */
915 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
916 doc: /* Return position at which display currently ends in WINDOW.
917 This is updated by redisplay, when it runs to completion.
918 Simply changing the buffer text or setting `window-start'
919 does not update this value.
920 If UPDATE is non-nil, compute the up-to-date position
921 if it isn't already recorded. */)
922 (window, update)
923 Lisp_Object window, update;
925 Lisp_Object value;
926 struct window *w = decode_window (window);
927 Lisp_Object buf;
929 buf = w->buffer;
930 CHECK_BUFFER (buf);
932 #if 0 /* This change broke some things. We should make it later. */
933 /* If we don't know the end position, return nil.
934 The user can compute it with vertical-motion if he wants to.
935 It would be nicer to do it automatically,
936 but that's so slow that it would probably bother people. */
937 if (NILP (w->window_end_valid))
938 return Qnil;
939 #endif
941 if (! NILP (update)
942 && ! (! NILP (w->window_end_valid)
943 && XFASTINT (w->last_modified) >= MODIFF))
945 struct text_pos startp;
946 struct it it;
947 struct buffer *old_buffer = NULL, *b = XBUFFER (buf);
949 /* In case W->start is out of the range, use something
950 reasonable. This situation occurred when loading a file with
951 `-l' containing a call to `rmail' with subsequent other
952 commands. At the end, W->start happened to be BEG, while
953 rmail had already narrowed the buffer. */
954 if (XMARKER (w->start)->charpos < BEGV)
955 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
956 else if (XMARKER (w->start)->charpos > ZV)
957 SET_TEXT_POS (startp, ZV, ZV_BYTE);
958 else
959 SET_TEXT_POS_FROM_MARKER (startp, w->start);
961 /* Cannot use Fvertical_motion because that function doesn't
962 cope with variable-height lines. */
963 if (b != current_buffer)
965 old_buffer = current_buffer;
966 set_buffer_internal (b);
969 start_display (&it, w, startp);
970 move_it_vertically (&it, window_box_height (w));
971 if (it.current_y < it.last_visible_y)
972 move_it_past_eol (&it);
973 value = make_number (IT_CHARPOS (it));
975 if (old_buffer)
976 set_buffer_internal (old_buffer);
978 else
979 XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
981 return value;
984 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
985 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer. */)
986 (window, pos)
987 Lisp_Object window, pos;
989 register struct window *w = decode_window (window);
991 CHECK_NUMBER_COERCE_MARKER (pos);
992 if (w == XWINDOW (selected_window)
993 && XBUFFER (w->buffer) == current_buffer)
994 Fgoto_char (pos);
995 else
996 set_marker_restricted (w->pointm, pos, w->buffer);
998 /* We have to make sure that redisplay updates the window to show
999 the new value of point. */
1000 if (!EQ (window, selected_window))
1001 ++windows_or_buffers_changed;
1003 return pos;
1006 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1007 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1008 Optional third arg NOFORCE non-nil inhibits next redisplay
1009 from overriding motion of point in order to display at this exact start. */)
1010 (window, pos, noforce)
1011 Lisp_Object window, pos, noforce;
1013 register struct window *w = decode_window (window);
1015 CHECK_NUMBER_COERCE_MARKER (pos);
1016 set_marker_restricted (w->start, pos, w->buffer);
1017 /* this is not right, but much easier than doing what is right. */
1018 w->start_at_line_beg = Qnil;
1019 if (NILP (noforce))
1020 w->force_start = Qt;
1021 w->update_mode_line = Qt;
1022 XSETFASTINT (w->last_modified, 0);
1023 XSETFASTINT (w->last_overlay_modified, 0);
1024 if (!EQ (window, selected_window))
1025 windows_or_buffers_changed++;
1027 return pos;
1030 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1031 1, 1, 0,
1032 doc: /* Return WINDOW's dedicated object, usually t or nil.
1033 See also `set-window-dedicated-p'. */)
1034 (window)
1035 Lisp_Object window;
1037 return decode_window (window)->dedicated;
1040 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1041 Sset_window_dedicated_p, 2, 2, 0,
1042 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1043 If it is dedicated, Emacs will not automatically change
1044 which buffer appears in it.
1045 The second argument is the new value for the dedication flag;
1046 non-nil means yes. */)
1047 (window, arg)
1048 Lisp_Object window, arg;
1050 register struct window *w = decode_window (window);
1052 if (NILP (arg))
1053 w->dedicated = Qnil;
1054 else
1055 w->dedicated = Qt;
1057 return w->dedicated;
1060 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1061 0, 1, 0,
1062 doc: /* Return the display-table that WINDOW is using. */)
1063 (window)
1064 Lisp_Object window;
1066 return decode_window (window)->display_table;
1069 /* Get the display table for use on window W. This is either W's
1070 display table or W's buffer's display table. Ignore the specified
1071 tables if they are not valid; if no valid table is specified,
1072 return 0. */
1074 struct Lisp_Char_Table *
1075 window_display_table (w)
1076 struct window *w;
1078 struct Lisp_Char_Table *dp = NULL;
1080 if (DISP_TABLE_P (w->display_table))
1081 dp = XCHAR_TABLE (w->display_table);
1082 else if (BUFFERP (w->buffer))
1084 struct buffer *b = XBUFFER (w->buffer);
1086 if (DISP_TABLE_P (b->display_table))
1087 dp = XCHAR_TABLE (b->display_table);
1088 else if (DISP_TABLE_P (Vstandard_display_table))
1089 dp = XCHAR_TABLE (Vstandard_display_table);
1092 return dp;
1095 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1096 doc: /* Set WINDOW's display-table to TABLE. */)
1097 (window, table)
1098 register Lisp_Object window, table;
1100 register struct window *w;
1102 w = decode_window (window);
1103 w->display_table = table;
1104 return table;
1107 /* Record info on buffer window w is displaying
1108 when it is about to cease to display that buffer. */
1109 static void
1110 unshow_buffer (w)
1111 register struct window *w;
1113 Lisp_Object buf;
1114 struct buffer *b;
1116 buf = w->buffer;
1117 b = XBUFFER (buf);
1118 if (b != XMARKER (w->pointm)->buffer)
1119 abort ();
1121 #if 0
1122 if (w == XWINDOW (selected_window)
1123 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1124 /* Do this except when the selected window's buffer
1125 is being removed from some other window. */
1126 #endif
1127 /* last_window_start records the start position that this buffer
1128 had in the last window to be disconnected from it.
1129 Now that this statement is unconditional,
1130 it is possible for the buffer to be displayed in the
1131 selected window, while last_window_start reflects another
1132 window which was recently showing the same buffer.
1133 Some people might say that might be a good thing. Let's see. */
1134 b->last_window_start = marker_position (w->start);
1136 /* Point in the selected window's buffer
1137 is actually stored in that buffer, and the window's pointm isn't used.
1138 So don't clobber point in that buffer. */
1139 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1140 /* This line helps to fix Horsley's testbug.el bug. */
1141 && !(WINDOWP (b->last_selected_window)
1142 && w != XWINDOW (b->last_selected_window)
1143 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1144 temp_set_point_both (b,
1145 clip_to_bounds (BUF_BEGV (b),
1146 XMARKER (w->pointm)->charpos,
1147 BUF_ZV (b)),
1148 clip_to_bounds (BUF_BEGV_BYTE (b),
1149 marker_byte_position (w->pointm),
1150 BUF_ZV_BYTE (b)));
1152 if (WINDOWP (b->last_selected_window)
1153 && w == XWINDOW (b->last_selected_window))
1154 b->last_selected_window = Qnil;
1157 /* Put replacement into the window structure in place of old. */
1158 static void
1159 replace_window (old, replacement)
1160 Lisp_Object old, replacement;
1162 register Lisp_Object tem;
1163 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1165 /* If OLD is its frame's root_window, then replacement is the new
1166 root_window for that frame. */
1168 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1169 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1171 p->left = o->left;
1172 p->top = o->top;
1173 p->width = o->width;
1174 p->height = o->height;
1175 p->desired_matrix = p->current_matrix = 0;
1176 p->vscroll = 0;
1177 bzero (&p->cursor, sizeof (p->cursor));
1178 bzero (&p->last_cursor, sizeof (p->last_cursor));
1179 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1180 p->phys_cursor_type = -1;
1181 p->phys_cursor_width = -1;
1182 p->must_be_updated_p = 0;
1183 p->pseudo_window_p = 0;
1184 XSETFASTINT (p->window_end_vpos, 0);
1185 XSETFASTINT (p->window_end_pos, 0);
1186 p->window_end_valid = Qnil;
1187 p->frozen_window_start_p = 0;
1188 p->orig_top = p->orig_height = Qnil;
1190 p->next = tem = o->next;
1191 if (!NILP (tem))
1192 XWINDOW (tem)->prev = replacement;
1194 p->prev = tem = o->prev;
1195 if (!NILP (tem))
1196 XWINDOW (tem)->next = replacement;
1198 p->parent = tem = o->parent;
1199 if (!NILP (tem))
1201 if (EQ (XWINDOW (tem)->vchild, old))
1202 XWINDOW (tem)->vchild = replacement;
1203 if (EQ (XWINDOW (tem)->hchild, old))
1204 XWINDOW (tem)->hchild = replacement;
1207 /*** Here, if replacement is a vertical combination
1208 and so is its new parent, we should make replacement's
1209 children be children of that parent instead. ***/
1212 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1213 doc: /* Remove WINDOW from the display. Default is selected window. */)
1214 (window)
1215 register Lisp_Object window;
1217 delete_window (window);
1219 if (! NILP (Vwindow_configuration_change_hook)
1220 && ! NILP (Vrun_hooks))
1221 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1223 return Qnil;
1226 void
1227 delete_window (window)
1228 register Lisp_Object window;
1230 register Lisp_Object tem, parent, sib;
1231 register struct window *p;
1232 register struct window *par;
1233 struct frame *f;
1235 /* Because this function is called by other C code on non-leaf
1236 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1237 so we can't decode_window here. */
1238 if (NILP (window))
1239 window = selected_window;
1240 else
1241 CHECK_WINDOW (window);
1242 p = XWINDOW (window);
1244 /* It's okay to delete an already-deleted window. */
1245 if (NILP (p->buffer)
1246 && NILP (p->hchild)
1247 && NILP (p->vchild))
1248 return;
1250 parent = p->parent;
1251 if (NILP (parent))
1252 error ("Attempt to delete minibuffer or sole ordinary window");
1253 par = XWINDOW (parent);
1255 windows_or_buffers_changed++;
1256 Vwindow_list = Qnil;
1257 f = XFRAME (WINDOW_FRAME (p));
1258 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1260 /* Are we trying to delete any frame's selected window? */
1262 Lisp_Object swindow, pwindow;
1264 /* See if the frame's selected window is either WINDOW
1265 or any subwindow of it, by finding all that window's parents
1266 and comparing each one with WINDOW. */
1267 swindow = FRAME_SELECTED_WINDOW (f);
1269 while (1)
1271 pwindow = swindow;
1272 while (!NILP (pwindow))
1274 if (EQ (window, pwindow))
1275 break;
1276 pwindow = XWINDOW (pwindow)->parent;
1279 /* If the window being deleted is not a parent of SWINDOW,
1280 then SWINDOW is ok as the new selected window. */
1281 if (!EQ (window, pwindow))
1282 break;
1283 /* Otherwise, try another window for SWINDOW. */
1284 swindow = Fnext_window (swindow, Qlambda, Qnil);;
1286 /* If we get back to the frame's selected window,
1287 it means there was no acceptable alternative,
1288 so we cannot delete. */
1289 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1290 error ("Cannot delete window");
1293 /* If we need to change SWINDOW, do it. */
1294 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1296 /* If we're about to delete the selected window on the
1297 selected frame, then we should use Fselect_window to select
1298 the new window. On the other hand, if we're about to
1299 delete the selected window on any other frame, we shouldn't do
1300 anything but set the frame's selected_window slot. */
1301 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1302 Fselect_window (swindow);
1303 else
1304 FRAME_SELECTED_WINDOW (f) = swindow;
1308 tem = p->buffer;
1309 /* tem is null for dummy parent windows
1310 (which have inferiors but not any contents themselves) */
1311 if (!NILP (tem))
1313 unshow_buffer (p);
1314 unchain_marker (p->pointm);
1315 unchain_marker (p->start);
1318 /* Free window glyph matrices. It is sure that they are allocated
1319 again when ADJUST_GLYPHS is called. Block input so that expose
1320 events and other events that access glyph matrices are not
1321 processed while we are changing them. */
1322 BLOCK_INPUT;
1323 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1325 tem = p->next;
1326 if (!NILP (tem))
1327 XWINDOW (tem)->prev = p->prev;
1329 tem = p->prev;
1330 if (!NILP (tem))
1331 XWINDOW (tem)->next = p->next;
1333 if (EQ (window, par->hchild))
1334 par->hchild = p->next;
1335 if (EQ (window, par->vchild))
1336 par->vchild = p->next;
1338 /* Find one of our siblings to give our space to. */
1339 sib = p->prev;
1340 if (NILP (sib))
1342 /* If p gives its space to its next sibling, that sibling needs
1343 to have its top/left side pulled back to where p's is.
1344 set_window_{height,width} will re-position the sibling's
1345 children. */
1346 sib = p->next;
1347 XWINDOW (sib)->top = p->top;
1348 XWINDOW (sib)->left = p->left;
1351 /* Stretch that sibling. */
1352 if (!NILP (par->vchild))
1353 set_window_height (sib,
1354 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
1356 if (!NILP (par->hchild))
1357 set_window_width (sib,
1358 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
1361 /* If parent now has only one child,
1362 put the child into the parent's place. */
1363 tem = par->hchild;
1364 if (NILP (tem))
1365 tem = par->vchild;
1366 if (NILP (XWINDOW (tem)->next))
1367 replace_window (parent, tem);
1369 /* Since we may be deleting combination windows, we must make sure that
1370 not only p but all its children have been marked as deleted. */
1371 if (! NILP (p->hchild))
1372 delete_all_subwindows (XWINDOW (p->hchild));
1373 else if (! NILP (p->vchild))
1374 delete_all_subwindows (XWINDOW (p->vchild));
1376 /* Mark this window as deleted. */
1377 p->buffer = p->hchild = p->vchild = Qnil;
1379 /* Adjust glyph matrices. */
1380 adjust_glyphs (f);
1381 UNBLOCK_INPUT;
1386 /***********************************************************************
1387 Window List
1388 ***********************************************************************/
1390 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1391 pointer. This is a callback function for foreach_window, used in
1392 function window_list. */
1394 static int
1395 add_window_to_list (w, user_data)
1396 struct window *w;
1397 void *user_data;
1399 Lisp_Object *list = (Lisp_Object *) user_data;
1400 Lisp_Object window;
1401 XSETWINDOW (window, w);
1402 *list = Fcons (window, *list);
1403 return 1;
1407 /* Return a list of all windows, for use by next_window. If
1408 Vwindow_list is a list, return that list. Otherwise, build a new
1409 list, cache it in Vwindow_list, and return that. */
1411 static Lisp_Object
1412 window_list ()
1414 if (!CONSP (Vwindow_list))
1416 Lisp_Object tail;
1418 Vwindow_list = Qnil;
1419 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1421 Lisp_Object args[2];
1423 /* We are visiting windows in canonical order, and add
1424 new windows at the front of args[1], which means we
1425 have to reverse this list at the end. */
1426 args[1] = Qnil;
1427 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1428 args[0] = Vwindow_list;
1429 args[1] = Fnreverse (args[1]);
1430 Vwindow_list = Fnconc (2, args);
1434 return Vwindow_list;
1438 /* Value is non-zero if WINDOW satisfies the constraints given by
1439 OWINDOW, MINIBUF and ALL_FRAMES.
1441 MINIBUF t means WINDOW may be minibuffer windows.
1442 `lambda' means WINDOW may not be a minibuffer window.
1443 a window means a specific minibuffer window
1445 ALL_FRAMES t means search all frames,
1446 nil means search just current frame,
1447 `visible' means search just visible frames,
1448 0 means search visible and iconified frames,
1449 a window means search the frame that window belongs to,
1450 a frame means consider windows on that frame, only. */
1452 static int
1453 candidate_window_p (window, owindow, minibuf, all_frames)
1454 Lisp_Object window, owindow, minibuf, all_frames;
1456 struct window *w = XWINDOW (window);
1457 struct frame *f = XFRAME (w->frame);
1458 int candidate_p = 1;
1460 if (!BUFFERP (w->buffer))
1461 candidate_p = 0;
1462 else if (MINI_WINDOW_P (w)
1463 && (EQ (minibuf, Qlambda)
1464 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1466 /* If MINIBUF is `lambda' don't consider any mini-windows.
1467 If it is a window, consider only that one. */
1468 candidate_p = 0;
1470 else if (EQ (all_frames, Qt))
1471 candidate_p = 1;
1472 else if (NILP (all_frames))
1474 xassert (WINDOWP (owindow));
1475 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1477 else if (EQ (all_frames, Qvisible))
1479 FRAME_SAMPLE_VISIBILITY (f);
1480 candidate_p = FRAME_VISIBLE_P (f);
1482 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1484 FRAME_SAMPLE_VISIBILITY (f);
1485 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1487 else if (WINDOWP (all_frames))
1488 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1489 || EQ (XWINDOW (all_frames)->frame, w->frame)
1490 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1491 else if (FRAMEP (all_frames))
1492 candidate_p = EQ (all_frames, w->frame);
1494 return candidate_p;
1498 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1499 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1500 ALL_FRAMES. */
1502 static void
1503 decode_next_window_args (window, minibuf, all_frames)
1504 Lisp_Object *window, *minibuf, *all_frames;
1506 if (NILP (*window))
1507 *window = selected_window;
1508 else
1509 CHECK_LIVE_WINDOW (*window);
1511 /* MINIBUF nil may or may not include minibuffers. Decide if it
1512 does. */
1513 if (NILP (*minibuf))
1514 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1515 else if (!EQ (*minibuf, Qt))
1516 *minibuf = Qlambda;
1518 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1519 => count none of them, or a specific minibuffer window (the
1520 active one) to count. */
1522 /* ALL_FRAMES nil doesn't specify which frames to include. */
1523 if (NILP (*all_frames))
1524 *all_frames = (!EQ (*minibuf, Qlambda)
1525 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1526 : Qnil);
1527 else if (EQ (*all_frames, Qvisible))
1529 else if (XFASTINT (*all_frames) == 0)
1531 else if (FRAMEP (*all_frames))
1533 else if (!EQ (*all_frames, Qt))
1534 *all_frames = Qnil;
1536 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1537 search just current frame, `visible' meaning search just visible
1538 frames, 0 meaning search visible and iconified frames, or a
1539 window, meaning search the frame that window belongs to, or a
1540 frame, meaning consider windows on that frame, only. */
1544 /* Return the next or previous window of WINDOW in canonical ordering
1545 of windows. NEXT_P non-zero means return the next window. See the
1546 documentation string of next-window for the meaning of MINIBUF and
1547 ALL_FRAMES. */
1549 static Lisp_Object
1550 next_window (window, minibuf, all_frames, next_p)
1551 Lisp_Object window, minibuf, all_frames;
1552 int next_p;
1554 decode_next_window_args (&window, &minibuf, &all_frames);
1556 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1557 return the first window on the frame. */
1558 if (FRAMEP (all_frames)
1559 && !EQ (all_frames, XWINDOW (window)->frame))
1560 return Fframe_first_window (all_frames);
1562 if (next_p)
1564 Lisp_Object list;
1566 /* Find WINDOW in the list of all windows. */
1567 list = Fmemq (window, window_list ());
1569 /* Scan forward from WINDOW to the end of the window list. */
1570 if (CONSP (list))
1571 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1572 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1573 break;
1575 /* Scan from the start of the window list up to WINDOW. */
1576 if (!CONSP (list))
1577 for (list = Vwindow_list;
1578 CONSP (list) && !EQ (XCAR (list), window);
1579 list = XCDR (list))
1580 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1581 break;
1583 if (CONSP (list))
1584 window = XCAR (list);
1586 else
1588 Lisp_Object candidate, list;
1590 /* Scan through the list of windows for candidates. If there are
1591 candidate windows in front of WINDOW, the last one of these
1592 is the one we want. If there are candidates following WINDOW
1593 in the list, again the last one of these is the one we want. */
1594 candidate = Qnil;
1595 for (list = window_list (); CONSP (list); list = XCDR (list))
1597 if (EQ (XCAR (list), window))
1599 if (WINDOWP (candidate))
1600 break;
1602 else if (candidate_window_p (XCAR (list), window, minibuf,
1603 all_frames))
1604 candidate = XCAR (list);
1607 if (WINDOWP (candidate))
1608 window = candidate;
1611 return window;
1615 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1616 doc: /* Return next window after WINDOW in canonical ordering of windows.
1617 If omitted, WINDOW defaults to the selected window.
1619 Optional second arg MINIBUF t means count the minibuffer window even
1620 if not active. MINIBUF nil or omitted means count the minibuffer iff
1621 it is active. MINIBUF neither t nor nil means not to count the
1622 minibuffer even if it is active.
1624 Several frames may share a single minibuffer; if the minibuffer
1625 counts, all windows on all frames that share that minibuffer count
1626 too. Therefore, `next-window' can be used to iterate through the
1627 set of windows even when the minibuffer is on another frame. If the
1628 minibuffer does not count, only windows from WINDOW's frame count.
1630 Optional third arg ALL-FRAMES t means include windows on all frames.
1631 ALL-FRAMES nil or omitted means cycle within the frames as specified
1632 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1633 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1634 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1635 Anything else means restrict to WINDOW's frame.
1637 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1638 `next-window' to iterate through the entire cycle of acceptable
1639 windows, eventually ending up back at the window you started with.
1640 `previous-window' traverses the same cycle, in the reverse order. */)
1641 (window, minibuf, all_frames)
1642 Lisp_Object window, minibuf, all_frames;
1644 return next_window (window, minibuf, all_frames, 1);
1648 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1649 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1650 If omitted, WINDOW defaults to the selected window.
1652 Optional second arg MINIBUF t means count the minibuffer window even
1653 if not active. MINIBUF nil or omitted means count the minibuffer iff
1654 it is active. MINIBUF neither t nor nil means not to count the
1655 minibuffer even if it is active.
1657 Several frames may share a single minibuffer; if the minibuffer
1658 counts, all windows on all frames that share that minibuffer count
1659 too. Therefore, `previous-window' can be used to iterate through
1660 the set of windows even when the minibuffer is on another frame. If
1661 the minibuffer does not count, only windows from WINDOW's frame count
1663 Optional third arg ALL-FRAMES t means include windows on all frames.
1664 ALL-FRAMES nil or omitted means cycle within the frames as specified
1665 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1666 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1667 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1668 Anything else means restrict to WINDOW's frame.
1670 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1671 `previous-window' to iterate through the entire cycle of acceptable
1672 windows, eventually ending up back at the window you started with.
1673 `next-window' traverses the same cycle, in the reverse order. */)
1674 (window, minibuf, all_frames)
1675 Lisp_Object window, minibuf, all_frames;
1677 return next_window (window, minibuf, all_frames, 0);
1681 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1682 doc: /* Select the ARG'th different window on this frame.
1683 All windows on current frame are arranged in a cyclic order.
1684 This command selects the window ARG steps away in that order.
1685 A negative ARG moves in the opposite order. If the optional second
1686 argument ALL_FRAMES is non-nil, cycle through all frames. */)
1687 (arg, all_frames)
1688 Lisp_Object arg, all_frames;
1690 Lisp_Object window;
1691 int i;
1693 CHECK_NUMBER (arg);
1694 window = selected_window;
1696 for (i = XINT (arg); i > 0; --i)
1697 window = Fnext_window (window, Qnil, all_frames);
1698 for (; i < 0; ++i)
1699 window = Fprevious_window (window, Qnil, all_frames);
1701 Fselect_window (window);
1702 return Qnil;
1706 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
1707 doc: /* Return a list of windows on FRAME, starting with WINDOW.
1708 FRAME nil or omitted means use the selected frame.
1709 WINDOW nil or omitted means use the selected window.
1710 MINIBUF t means include the minibuffer window, even if it isn't active.
1711 MINIBUF nil or omitted means include the minibuffer window only
1712 if it's active.
1713 MINIBUF neither nil nor t means never include the minibuffer window. */)
1714 (frame, minibuf, window)
1715 Lisp_Object frame, minibuf, window;
1717 if (NILP (window))
1718 window = selected_window;
1719 if (NILP (frame))
1720 frame = selected_frame;
1722 if (!EQ (frame, XWINDOW (window)->frame))
1723 error ("Window is on a different frame");
1725 return window_list_1 (window, minibuf, frame);
1729 /* Return a list of windows in canonical ordering. Arguments are like
1730 for `next-window'. */
1732 static Lisp_Object
1733 window_list_1 (window, minibuf, all_frames)
1734 Lisp_Object window, minibuf, all_frames;
1736 Lisp_Object tail, list;
1738 decode_next_window_args (&window, &minibuf, &all_frames);
1739 list = Qnil;
1741 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
1742 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
1743 list = Fcons (XCAR (tail), list);
1745 return Fnreverse (list);
1750 /* Look at all windows, performing an operation specified by TYPE
1751 with argument OBJ.
1752 If FRAMES is Qt, look at all frames;
1753 Qnil, look at just the selected frame;
1754 Qvisible, look at visible frames;
1755 a frame, just look at windows on that frame.
1756 If MINI is non-zero, perform the operation on minibuffer windows too. */
1758 enum window_loop
1760 WINDOW_LOOP_UNUSED,
1761 GET_BUFFER_WINDOW, /* Arg is buffer */
1762 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1763 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1764 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1765 GET_LARGEST_WINDOW,
1766 UNSHOW_BUFFER, /* Arg is buffer */
1767 CHECK_ALL_WINDOWS
1770 static Lisp_Object
1771 window_loop (type, obj, mini, frames)
1772 enum window_loop type;
1773 Lisp_Object obj, frames;
1774 int mini;
1776 Lisp_Object window, windows, best_window, frame_arg;
1777 struct frame *f;
1778 struct gcpro gcpro1;
1780 /* If we're only looping through windows on a particular frame,
1781 frame points to that frame. If we're looping through windows
1782 on all frames, frame is 0. */
1783 if (FRAMEP (frames))
1784 f = XFRAME (frames);
1785 else if (NILP (frames))
1786 f = SELECTED_FRAME ();
1787 else
1788 f = NULL;
1790 if (f)
1791 frame_arg = Qlambda;
1792 else if (XFASTINT (frames) == 0)
1793 frame_arg = frames;
1794 else if (EQ (frames, Qvisible))
1795 frame_arg = frames;
1796 else
1797 frame_arg = Qt;
1799 /* frame_arg is Qlambda to stick to one frame,
1800 Qvisible to consider all visible frames,
1801 or Qt otherwise. */
1803 /* Pick a window to start with. */
1804 if (WINDOWP (obj))
1805 window = obj;
1806 else if (f)
1807 window = FRAME_SELECTED_WINDOW (f);
1808 else
1809 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1811 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
1812 GCPRO1 (windows);
1813 best_window = Qnil;
1815 for (; CONSP (windows); windows = CDR (windows))
1817 struct window *w;
1819 window = XCAR (windows);
1820 w = XWINDOW (window);
1822 /* Note that we do not pay attention here to whether the frame
1823 is visible, since Fwindow_list skips non-visible frames if
1824 that is desired, under the control of frame_arg. */
1825 if (!MINI_WINDOW_P (w)
1826 /* For UNSHOW_BUFFER, we must always consider all windows. */
1827 || type == UNSHOW_BUFFER
1828 || (mini && minibuf_level > 0))
1829 switch (type)
1831 case GET_BUFFER_WINDOW:
1832 if (EQ (w->buffer, obj)
1833 /* Don't find any minibuffer window
1834 except the one that is currently in use. */
1835 && (MINI_WINDOW_P (w)
1836 ? EQ (window, minibuf_window)
1837 : 1))
1839 if (NILP (best_window))
1840 best_window = window;
1841 else if (EQ (window, selected_window))
1842 /* For compatibility with 20.x, prefer to return
1843 selected-window. */
1844 best_window = window;
1846 break;
1848 case GET_LRU_WINDOW:
1849 /* t as arg means consider only full-width windows */
1850 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w))
1851 break;
1852 /* Ignore dedicated windows and minibuffers. */
1853 if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
1854 break;
1855 if (NILP (best_window)
1856 || (XFASTINT (XWINDOW (best_window)->use_time)
1857 > XFASTINT (w->use_time)))
1858 best_window = window;
1859 break;
1861 case DELETE_OTHER_WINDOWS:
1862 if (!EQ (window, obj))
1863 Fdelete_window (window);
1864 break;
1866 case DELETE_BUFFER_WINDOWS:
1867 if (EQ (w->buffer, obj))
1869 struct frame *f = XFRAME (WINDOW_FRAME (w));
1871 /* If this window is dedicated, and in a frame of its own,
1872 kill the frame. */
1873 if (EQ (window, FRAME_ROOT_WINDOW (f))
1874 && !NILP (w->dedicated)
1875 && other_visible_frames (f))
1877 /* Skip the other windows on this frame.
1878 There might be one, the minibuffer! */
1879 while (CONSP (XCDR (windows))
1880 && EQ (XWINDOW (XCAR (windows))->frame,
1881 XWINDOW (XCAR (XCDR (windows)))->frame))
1882 windows = XCDR (windows);
1884 /* Now we can safely delete the frame. */
1885 Fdelete_frame (w->frame, Qnil);
1887 else if (NILP (w->parent))
1889 /* If we're deleting the buffer displayed in the
1890 only window on the frame, find a new buffer to
1891 display there. */
1892 Lisp_Object buffer;
1893 buffer = Fother_buffer (obj, Qnil, w->frame);
1894 Fset_window_buffer (window, buffer);
1895 if (EQ (window, selected_window))
1896 Fset_buffer (w->buffer);
1898 else
1899 Fdelete_window (window);
1901 break;
1903 case GET_LARGEST_WINDOW:
1905 /* Ignore dedicated windows and minibuffers. */
1906 if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
1907 break;
1909 if (NILP (best_window))
1910 best_window = window;
1911 else
1913 struct window *b = XWINDOW (best_window);
1914 if (XFASTINT (w->height) * XFASTINT (w->width)
1915 > XFASTINT (b->height) * XFASTINT (b->width))
1916 best_window = window;
1919 break;
1921 case UNSHOW_BUFFER:
1922 if (EQ (w->buffer, obj))
1924 Lisp_Object buffer;
1925 struct frame *f = XFRAME (w->frame);
1927 /* Find another buffer to show in this window. */
1928 buffer = Fother_buffer (obj, Qnil, w->frame);
1930 /* If this window is dedicated, and in a frame of its own,
1931 kill the frame. */
1932 if (EQ (window, FRAME_ROOT_WINDOW (f))
1933 && !NILP (w->dedicated)
1934 && other_visible_frames (f))
1936 /* Skip the other windows on this frame.
1937 There might be one, the minibuffer! */
1938 while (CONSP (XCDR (windows))
1939 && EQ (XWINDOW (XCAR (windows))->frame,
1940 XWINDOW (XCAR (XCDR (windows)))->frame))
1941 windows = XCDR (windows);
1943 /* Now we can safely delete the frame. */
1944 Fdelete_frame (w->frame, Qnil);
1946 else if (!NILP (w->dedicated) && !NILP (w->parent))
1948 Lisp_Object window;
1949 XSETWINDOW (window, w);
1950 /* If this window is dedicated and not the only window
1951 in its frame, then kill it. */
1952 Fdelete_window (window);
1954 else
1956 /* Otherwise show a different buffer in the window. */
1957 w->dedicated = Qnil;
1958 Fset_window_buffer (window, buffer);
1959 if (EQ (window, selected_window))
1960 Fset_buffer (w->buffer);
1963 break;
1965 /* Check for a window that has a killed buffer. */
1966 case CHECK_ALL_WINDOWS:
1967 if (! NILP (w->buffer)
1968 && NILP (XBUFFER (w->buffer)->name))
1969 abort ();
1970 break;
1972 case WINDOW_LOOP_UNUSED:
1973 break;
1977 UNGCPRO;
1978 return best_window;
1981 /* Used for debugging. Abort if any window has a dead buffer. */
1983 void
1984 check_all_windows ()
1986 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
1989 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1990 doc: /* Return the window least recently selected or used for display.
1991 If optional argument FRAME is `visible', search all visible frames.
1992 If FRAME is 0, search all visible and iconified frames.
1993 If FRAME is t, search all frames.
1994 If FRAME is nil, search only the selected frame.
1995 If FRAME is a frame, search only that frame. */)
1996 (frame)
1997 Lisp_Object frame;
1999 register Lisp_Object w;
2000 /* First try for a window that is full-width */
2001 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
2002 if (!NILP (w) && !EQ (w, selected_window))
2003 return w;
2004 /* If none of them, try the rest */
2005 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
2008 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
2009 doc: /* Return the largest window in area.
2010 If optional argument FRAME is `visible', search all visible frames.
2011 If FRAME is 0, search all visible and iconified frames.
2012 If FRAME is t, search all frames.
2013 If FRAME is nil, search only the selected frame.
2014 If FRAME is a frame, search only that frame. */)
2015 (frame)
2016 Lisp_Object frame;
2018 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
2019 frame);
2022 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2023 doc: /* Return a window currently displaying BUFFER, or nil if none.
2024 If optional argument FRAME is `visible', search all visible frames.
2025 If optional argument FRAME is 0, search all visible and iconified frames.
2026 If FRAME is t, search all frames.
2027 If FRAME is nil, search only the selected frame.
2028 If FRAME is a frame, search only that frame. */)
2029 (buffer, frame)
2030 Lisp_Object buffer, frame;
2032 buffer = Fget_buffer (buffer);
2033 if (BUFFERP (buffer))
2034 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2035 else
2036 return Qnil;
2039 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2040 0, 1, "",
2041 doc: /* Make WINDOW (or the selected window) fill its frame.
2042 Only the frame WINDOW is on is affected.
2043 This function tries to reduce display jumps
2044 by keeping the text previously visible in WINDOW
2045 in the same place on the frame. Doing this depends on
2046 the value of (window-start WINDOW), so if calling this function
2047 in a program gives strange scrolling, make sure the window-start
2048 value is reasonable when this function is called. */)
2049 (window)
2050 Lisp_Object window;
2052 struct window *w;
2053 int startpos;
2054 int top, new_top;
2056 if (NILP (window))
2057 window = selected_window;
2058 else
2059 CHECK_LIVE_WINDOW (window);
2060 w = XWINDOW (window);
2062 startpos = marker_position (w->start);
2063 top = XFASTINT (w->top) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2065 if (MINI_WINDOW_P (w) && top > 0)
2066 error ("Can't expand minibuffer to full frame");
2068 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2070 /* Try to minimize scrolling, by setting the window start to the point
2071 will cause the text at the old window start to be at the same place
2072 on the frame. But don't try to do this if the window start is
2073 outside the visible portion (as might happen when the display is
2074 not current, due to typeahead). */
2075 new_top = XFASTINT (w->top) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2076 if (new_top != top
2077 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2078 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2080 struct position pos;
2081 struct buffer *obuf = current_buffer;
2083 Fset_buffer (w->buffer);
2084 /* This computation used to temporarily move point, but that can
2085 have unwanted side effects due to text properties. */
2086 pos = *vmotion (startpos, -top, w);
2088 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2089 w->window_end_valid = Qnil;
2090 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2091 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2092 : Qnil);
2093 /* We need to do this, so that the window-scroll-functions
2094 get called. */
2095 w->optional_new_start = Qt;
2097 set_buffer_internal (obuf);
2100 return Qnil;
2103 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2104 1, 2, "bDelete windows on (buffer): ",
2105 doc: /* Delete all windows showing BUFFER.
2106 Optional second argument FRAME controls which frames are affected.
2107 If optional argument FRAME is `visible', search all visible frames.
2108 If FRAME is 0, search all visible and iconified frames.
2109 If FRAME is nil, search all frames.
2110 If FRAME is t, search only the selected frame.
2111 If FRAME is a frame, search only that frame. */)
2112 (buffer, frame)
2113 Lisp_Object buffer, frame;
2115 /* FRAME uses t and nil to mean the opposite of what window_loop
2116 expects. */
2117 if (NILP (frame))
2118 frame = Qt;
2119 else if (EQ (frame, Qt))
2120 frame = Qnil;
2122 if (!NILP (buffer))
2124 buffer = Fget_buffer (buffer);
2125 CHECK_BUFFER (buffer);
2126 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2129 return Qnil;
2132 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2133 Sreplace_buffer_in_windows,
2134 1, 1, "bReplace buffer in windows: ",
2135 doc: /* Replace BUFFER with some other buffer in all windows showing it. */)
2136 (buffer)
2137 Lisp_Object buffer;
2139 if (!NILP (buffer))
2141 buffer = Fget_buffer (buffer);
2142 CHECK_BUFFER (buffer);
2143 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2145 return Qnil;
2148 /* Replace BUFFER with some other buffer in all windows
2149 of all frames, even those on other keyboards. */
2151 void
2152 replace_buffer_in_all_windows (buffer)
2153 Lisp_Object buffer;
2155 #ifdef MULTI_KBOARD
2156 Lisp_Object tail, frame;
2158 /* A single call to window_loop won't do the job
2159 because it only considers frames on the current keyboard.
2160 So loop manually over frames, and handle each one. */
2161 FOR_EACH_FRAME (tail, frame)
2162 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2163 #else
2164 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2165 #endif
2168 /* Set the height of WINDOW and all its inferiors. */
2170 /* The smallest acceptable dimensions for a window. Anything smaller
2171 might crash Emacs. */
2173 #define MIN_SAFE_WINDOW_WIDTH (2)
2174 #define MIN_SAFE_WINDOW_HEIGHT (1)
2176 /* Make sure that window_min_height and window_min_width are
2177 not too small; if they are, set them to safe minima. */
2179 static void
2180 check_min_window_sizes ()
2182 /* Smaller values might permit a crash. */
2183 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2184 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2185 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2186 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2189 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2190 minimum allowable size. */
2192 void
2193 check_frame_size (frame, rows, cols)
2194 FRAME_PTR frame;
2195 int *rows, *cols;
2197 /* For height, we have to see:
2198 how many windows the frame has at minimum (one or two),
2199 and whether it has a menu bar or other special stuff at the top. */
2200 int min_height
2201 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2202 ? MIN_SAFE_WINDOW_HEIGHT
2203 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2205 if (FRAME_TOP_MARGIN (frame) > 0)
2206 min_height += FRAME_TOP_MARGIN (frame);
2208 if (*rows < min_height)
2209 *rows = min_height;
2210 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2211 *cols = MIN_SAFE_WINDOW_WIDTH;
2215 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2216 check if W's width can be changed, otherwise check W's height.
2217 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2218 siblings, too. If none of the siblings is resizable, WINDOW isn't
2219 either. */
2221 static int
2222 window_fixed_size_p (w, width_p, check_siblings_p)
2223 struct window *w;
2224 int width_p, check_siblings_p;
2226 int fixed_p;
2227 struct window *c;
2229 if (!NILP (w->hchild))
2231 c = XWINDOW (w->hchild);
2233 if (width_p)
2235 /* A horiz. combination is fixed-width if all of if its
2236 children are. */
2237 while (c && window_fixed_size_p (c, width_p, 0))
2238 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2239 fixed_p = c == NULL;
2241 else
2243 /* A horiz. combination is fixed-height if one of if its
2244 children is. */
2245 while (c && !window_fixed_size_p (c, width_p, 0))
2246 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2247 fixed_p = c != NULL;
2250 else if (!NILP (w->vchild))
2252 c = XWINDOW (w->vchild);
2254 if (width_p)
2256 /* A vert. combination is fixed-width if one of if its
2257 children is. */
2258 while (c && !window_fixed_size_p (c, width_p, 0))
2259 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2260 fixed_p = c != NULL;
2262 else
2264 /* A vert. combination is fixed-height if all of if its
2265 children are. */
2266 while (c && window_fixed_size_p (c, width_p, 0))
2267 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2268 fixed_p = c == NULL;
2271 else if (BUFFERP (w->buffer))
2273 if (w->height_fixed_p && !width_p)
2274 fixed_p = 1;
2275 else
2277 struct buffer *old = current_buffer;
2278 Lisp_Object val;
2280 current_buffer = XBUFFER (w->buffer);
2281 val = find_symbol_value (Qwindow_size_fixed);
2282 current_buffer = old;
2284 fixed_p = 0;
2285 if (!EQ (val, Qunbound))
2287 fixed_p = !NILP (val);
2289 if (fixed_p
2290 && ((EQ (val, Qheight) && width_p)
2291 || (EQ (val, Qwidth) && !width_p)))
2292 fixed_p = 0;
2296 /* Can't tell if this one is resizable without looking at
2297 siblings. If all siblings are fixed-size this one is too. */
2298 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2300 Lisp_Object child;
2302 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2303 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2304 break;
2306 if (NILP (child))
2307 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2308 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2309 break;
2311 if (NILP (child))
2312 fixed_p = 1;
2315 else
2316 fixed_p = 1;
2318 return fixed_p;
2322 /* Return the minimum size of window W, not taking fixed-width windows
2323 into account. WIDTH_P non-zero means return the minimum width,
2324 otherwise return the minimum height. If W is a combination window,
2325 compute the minimum size from the minimum sizes of W's children. */
2327 static int
2328 window_min_size_1 (w, width_p)
2329 struct window *w;
2330 int width_p;
2332 struct window *c;
2333 int size;
2335 if (!NILP (w->hchild))
2337 c = XWINDOW (w->hchild);
2338 size = 0;
2340 if (width_p)
2342 /* The min width of a horizontal combination is
2343 the sum of the min widths of its children. */
2344 while (c)
2346 size += window_min_size_1 (c, width_p);
2347 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2350 else
2352 /* The min height a horizontal combination equals
2353 the maximum of all min height of its children. */
2354 while (c)
2356 int min_size = window_min_size_1 (c, width_p);
2357 size = max (min_size, size);
2358 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2362 else if (!NILP (w->vchild))
2364 c = XWINDOW (w->vchild);
2365 size = 0;
2367 if (width_p)
2369 /* The min width of a vertical combination is
2370 the maximum of the min widths of its children. */
2371 while (c)
2373 int min_size = window_min_size_1 (c, width_p);
2374 size = max (min_size, size);
2375 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2378 else
2380 /* The min height of a vertical combination equals
2381 the sum of the min height of its children. */
2382 while (c)
2384 size += window_min_size_1 (c, width_p);
2385 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2389 else
2391 if (width_p)
2392 size = window_min_width;
2393 else
2395 if (MINI_WINDOW_P (w)
2396 || (!WINDOW_WANTS_MODELINE_P (w)
2397 && !WINDOW_WANTS_HEADER_LINE_P (w)))
2398 size = 1;
2399 else
2400 size = window_min_height;
2404 return size;
2408 /* Return the minimum size of window W, taking fixed-size windows into
2409 account. WIDTH_P non-zero means return the minimum width,
2410 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2411 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2412 unless FIXED is null. */
2414 static int
2415 window_min_size (w, width_p, ignore_fixed_p, fixed)
2416 struct window *w;
2417 int width_p, ignore_fixed_p, *fixed;
2419 int size, fixed_p;
2421 if (ignore_fixed_p)
2422 fixed_p = 0;
2423 else
2424 fixed_p = window_fixed_size_p (w, width_p, 1);
2426 if (fixed)
2427 *fixed = fixed_p;
2429 if (fixed_p)
2430 size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
2431 else
2432 size = window_min_size_1 (w, width_p);
2434 return size;
2438 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2439 WINDOW's width. Resize WINDOW's children, if any, so that they
2440 keep their proportionate size relative to WINDOW. Propagate
2441 WINDOW's top or left edge position to children. Delete windows
2442 that become too small unless NODELETE_P is non-zero.
2444 If NODELETE_P is 2, that means we do delete windows that are
2445 too small, even if they were too small before! */
2447 static void
2448 size_window (window, size, width_p, nodelete_p)
2449 Lisp_Object window;
2450 int size, width_p, nodelete_p;
2452 struct window *w = XWINDOW (window);
2453 struct window *c;
2454 Lisp_Object child, *forward, *sideward;
2455 int old_size, min_size;
2457 if (nodelete_p == 2)
2458 nodelete_p = 0;
2460 check_min_window_sizes ();
2461 size = max (0, size);
2463 /* If the window has been "too small" at one point,
2464 don't delete it for being "too small" in the future.
2465 Preserve it as long as that is at all possible. */
2466 if (width_p)
2468 old_size = XINT (w->width);
2469 min_size = window_min_width;
2471 else
2473 old_size = XINT (w->height);
2474 min_size = window_min_height;
2477 if (old_size < min_size && nodelete_p != 2)
2478 w->too_small_ok = Qt;
2480 /* Maybe delete WINDOW if it's too small. */
2481 if (nodelete_p != 1 && !NILP (w->parent))
2483 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
2484 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
2485 else
2486 min_size = width_p ? window_min_width : window_min_height;
2488 if (size < min_size)
2490 delete_window (window);
2491 return;
2495 /* Set redisplay hints. */
2496 w->last_modified = make_number (0);
2497 w->last_overlay_modified = make_number (0);
2498 windows_or_buffers_changed++;
2499 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
2501 if (width_p)
2503 sideward = &w->vchild;
2504 forward = &w->hchild;
2505 w->width = make_number (size);
2507 else
2509 sideward = &w->hchild;
2510 forward = &w->vchild;
2511 w->height = make_number (size);
2512 w->orig_height = Qnil;
2515 if (!NILP (*sideward))
2517 for (child = *sideward; !NILP (child); child = c->next)
2519 c = XWINDOW (child);
2520 if (width_p)
2521 c->left = w->left;
2522 else
2523 c->top = w->top;
2524 size_window (child, size, width_p, nodelete_p);
2527 else if (!NILP (*forward))
2529 int fixed_size, each, extra, n;
2530 int resize_fixed_p, nfixed;
2531 int last_pos, first_pos, nchildren, total;
2533 /* Determine the fixed-size portion of the this window, and the
2534 number of child windows. */
2535 fixed_size = nchildren = nfixed = total = 0;
2536 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
2538 int child_size;
2540 c = XWINDOW (child);
2541 child_size = width_p ? XINT (c->width) : XINT (c->height);
2542 total += child_size;
2544 if (window_fixed_size_p (c, width_p, 0))
2546 fixed_size += child_size;
2547 ++nfixed;
2551 /* If the new size is smaller than fixed_size, or if there
2552 aren't any resizable windows, allow resizing fixed-size
2553 windows. */
2554 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2556 /* Compute how many lines/columns to add to each child. The
2557 value of extra takes care of rounding errors. */
2558 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2559 each = (size - total) / n;
2560 extra = (size - total) - n * each;
2562 /* Compute new children heights and edge positions. */
2563 first_pos = width_p ? XINT (w->left) : XINT (w->top);
2564 last_pos = first_pos;
2565 for (child = *forward; !NILP (child); child = c->next)
2567 int new_size, old_size;
2569 c = XWINDOW (child);
2570 old_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2571 new_size = old_size;
2573 /* The top or left edge position of this child equals the
2574 bottom or right edge of its predecessor. */
2575 if (width_p)
2576 c->left = make_number (last_pos);
2577 else
2578 c->top = make_number (last_pos);
2580 /* If this child can be resized, do it. */
2581 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2583 new_size = old_size + each + extra;
2584 extra = 0;
2587 /* Set new height. Note that size_window also propagates
2588 edge positions to children, so it's not a no-op if we
2589 didn't change the child's size. */
2590 size_window (child, new_size, width_p, 1);
2592 /* Remember the bottom/right edge position of this child; it
2593 will be used to set the top/left edge of the next child. */
2594 last_pos += new_size;
2597 /* We should have covered the parent exactly with child windows. */
2598 xassert (size == last_pos - first_pos);
2600 /* Now delete any children that became too small. */
2601 if (!nodelete_p)
2602 for (child = *forward; !NILP (child); child = c->next)
2604 int child_size;
2605 c = XWINDOW (child);
2606 child_size = width_p ? XINT (c->width) : XINT (c->height);
2607 size_window (child, child_size, width_p, 2);
2612 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2613 WINDOW's children. NODELETE non-zero means don't delete windows
2614 that become too small in the process. (The caller should check
2615 later and do so if appropriate.) */
2617 void
2618 set_window_height (window, height, nodelete)
2619 Lisp_Object window;
2620 int height;
2621 int nodelete;
2623 size_window (window, height, 0, nodelete);
2627 /* Set WINDOW's width to WIDTH, and recursively change the width of
2628 WINDOW's children. NODELETE non-zero means don't delete windows
2629 that become too small in the process. (The caller should check
2630 later and do so if appropriate.) */
2632 void
2633 set_window_width (window, width, nodelete)
2634 Lisp_Object window;
2635 int width;
2636 int nodelete;
2638 size_window (window, width, 1, nodelete);
2641 /* Change window heights in windows rooted in WINDOW by N lines. */
2643 void
2644 change_window_heights (window, n)
2645 Lisp_Object window;
2646 int n;
2648 struct window *w = XWINDOW (window);
2650 XSETFASTINT (w->top, XFASTINT (w->top) + n);
2651 XSETFASTINT (w->height, XFASTINT (w->height) - n);
2653 if (INTEGERP (w->orig_top))
2654 XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
2655 if (INTEGERP (w->orig_height))
2656 XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
2658 /* Handle just the top child in a vertical split. */
2659 if (!NILP (w->vchild))
2660 change_window_heights (w->vchild, n);
2662 /* Adjust all children in a horizontal split. */
2663 for (window = w->hchild; !NILP (window); window = w->next)
2665 w = XWINDOW (window);
2666 change_window_heights (window, n);
2671 int window_select_count;
2673 Lisp_Object
2674 Fset_window_buffer_unwind (obuf)
2675 Lisp_Object obuf;
2677 Fset_buffer (obuf);
2678 return Qnil;
2682 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2683 means it's allowed to run hooks. See make_frame for a case where
2684 it's not allowed. */
2686 void
2687 set_window_buffer (window, buffer, run_hooks_p)
2688 Lisp_Object window, buffer;
2689 int run_hooks_p;
2691 struct window *w = XWINDOW (window);
2692 struct buffer *b = XBUFFER (buffer);
2693 int count = SPECPDL_INDEX ();
2695 w->buffer = buffer;
2697 if (EQ (window, selected_window))
2698 b->last_selected_window = window;
2700 /* Update time stamps of buffer display. */
2701 if (INTEGERP (b->display_count))
2702 XSETINT (b->display_count, XINT (b->display_count) + 1);
2703 b->display_time = Fcurrent_time ();
2705 XSETFASTINT (w->window_end_pos, 0);
2706 XSETFASTINT (w->window_end_vpos, 0);
2707 bzero (&w->last_cursor, sizeof w->last_cursor);
2708 w->window_end_valid = Qnil;
2709 w->hscroll = w->min_hscroll = make_number (0);
2710 w->vscroll = 0;
2711 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
2712 set_marker_restricted (w->start,
2713 make_number (b->last_window_start),
2714 buffer);
2715 w->start_at_line_beg = Qnil;
2716 w->force_start = Qnil;
2717 XSETFASTINT (w->last_modified, 0);
2718 XSETFASTINT (w->last_overlay_modified, 0);
2719 windows_or_buffers_changed++;
2721 /* We must select BUFFER for running the window-scroll-functions.
2722 If WINDOW is selected, switch permanently.
2723 Otherwise, switch but go back to the ambient buffer afterward. */
2724 if (EQ (window, selected_window))
2725 Fset_buffer (buffer);
2726 /* We can't check ! NILP (Vwindow_scroll_functions) here
2727 because that might itself be a local variable. */
2728 else if (window_initialized)
2730 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2731 Fset_buffer (buffer);
2734 /* Set left and right marginal area width from buffer. */
2735 Fset_window_margins (window, b->left_margin_width, b->right_margin_width);
2737 if (run_hooks_p)
2739 if (! NILP (Vwindow_scroll_functions))
2740 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2741 Fmarker_position (w->start));
2743 if (! NILP (Vwindow_configuration_change_hook)
2744 && ! NILP (Vrun_hooks))
2745 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2748 unbind_to (count, Qnil);
2752 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
2753 doc: /* Make WINDOW display BUFFER as its contents.
2754 BUFFER can be a buffer or buffer name. */)
2755 (window, buffer)
2756 register Lisp_Object window, buffer;
2758 register Lisp_Object tem;
2759 register struct window *w = decode_window (window);
2761 XSETWINDOW (window, w);
2762 buffer = Fget_buffer (buffer);
2763 CHECK_BUFFER (buffer);
2765 if (NILP (XBUFFER (buffer)->name))
2766 error ("Attempt to display deleted buffer");
2768 tem = w->buffer;
2769 if (NILP (tem))
2770 error ("Window is deleted");
2771 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
2772 is first being set up. */
2774 if (!NILP (w->dedicated) && !EQ (tem, buffer))
2775 error ("Window is dedicated to `%s'",
2776 SDATA (XBUFFER (tem)->name));
2778 unshow_buffer (w);
2781 set_window_buffer (window, buffer, 1);
2782 return Qnil;
2785 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
2786 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
2787 If WINDOW is not already selected, also make WINDOW's buffer current.
2788 Also make WINDOW the frame's selected window.
2790 Note that the main editor command loop
2791 selects the buffer of the selected window before each command. */)
2792 (window)
2793 register Lisp_Object window;
2795 return select_window_1 (window, 1);
2798 /* Note that selected_window can be nil
2799 when this is called from Fset_window_configuration. */
2801 static Lisp_Object
2802 select_window_1 (window, recordflag)
2803 register Lisp_Object window;
2804 int recordflag;
2806 register struct window *w;
2807 register struct window *ow;
2808 struct frame *sf;
2810 CHECK_LIVE_WINDOW (window);
2812 w = XWINDOW (window);
2813 w->frozen_window_start_p = 0;
2815 XSETFASTINT (w->use_time, ++window_select_count);
2816 if (EQ (window, selected_window))
2817 return window;
2819 if (!NILP (selected_window))
2821 ow = XWINDOW (selected_window);
2822 if (! NILP (ow->buffer))
2823 set_marker_both (ow->pointm, ow->buffer,
2824 BUF_PT (XBUFFER (ow->buffer)),
2825 BUF_PT_BYTE (XBUFFER (ow->buffer)));
2828 selected_window = window;
2829 sf = SELECTED_FRAME ();
2830 if (XFRAME (WINDOW_FRAME (w)) != sf)
2832 XFRAME (WINDOW_FRAME (w))->selected_window = window;
2833 /* Use this rather than Fhandle_switch_frame
2834 so that FRAME_FOCUS_FRAME is moved appropriately as we
2835 move around in the state where a minibuffer in a separate
2836 frame is active. */
2837 Fselect_frame (WINDOW_FRAME (w), Qnil);
2839 else
2840 sf->selected_window = window;
2842 if (recordflag)
2843 record_buffer (w->buffer);
2844 Fset_buffer (w->buffer);
2846 XBUFFER (w->buffer)->last_selected_window = window;
2848 /* Go to the point recorded in the window.
2849 This is important when the buffer is in more
2850 than one window. It also matters when
2851 redisplay_window has altered point after scrolling,
2852 because it makes the change only in the window. */
2854 register int new_point = marker_position (w->pointm);
2855 if (new_point < BEGV)
2856 SET_PT (BEGV);
2857 else if (new_point > ZV)
2858 SET_PT (ZV);
2859 else
2860 SET_PT (new_point);
2863 windows_or_buffers_changed++;
2864 return window;
2867 /* Deiconify the frame containing the window WINDOW,
2868 unless it is the selected frame;
2869 then return WINDOW.
2871 The reason for the exception for the selected frame
2872 is that it seems better not to change the selected frames visibility
2873 merely because of displaying a different buffer in it.
2874 The deiconification is useful when a buffer gets shown in
2875 another frame that you were not using lately. */
2877 static Lisp_Object
2878 display_buffer_1 (window)
2879 Lisp_Object window;
2881 Lisp_Object frame = XWINDOW (window)->frame;
2882 FRAME_PTR f = XFRAME (frame);
2884 FRAME_SAMPLE_VISIBILITY (f);
2886 if (!EQ (frame, selected_frame))
2888 if (FRAME_ICONIFIED_P (f))
2889 Fmake_frame_visible (frame);
2890 else if (FRAME_VISIBLE_P (f))
2891 Fraise_frame (frame);
2894 return window;
2897 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
2898 doc: /* Returns non-nil if a buffer named BUFFER-NAME would be created specially.
2899 The value is actually t if the frame should be called with default frame
2900 parameters, and a list of frame parameters if they were specified.
2901 See `special-display-buffer-names', and `special-display-regexps'. */)
2902 (buffer_name)
2903 Lisp_Object buffer_name;
2905 Lisp_Object tem;
2907 CHECK_STRING (buffer_name);
2909 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2910 if (!NILP (tem))
2911 return Qt;
2913 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2914 if (!NILP (tem))
2915 return XCDR (tem);
2917 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2919 Lisp_Object car = XCAR (tem);
2920 if (STRINGP (car)
2921 && fast_string_match (car, buffer_name) >= 0)
2922 return Qt;
2923 else if (CONSP (car)
2924 && STRINGP (XCAR (car))
2925 && fast_string_match (XCAR (car), buffer_name) >= 0)
2926 return XCDR (car);
2928 return Qnil;
2931 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
2932 doc: /* Returns non-nil if a new buffer named BUFFER-NAME would use the same window.
2933 See `same-window-buffer-names' and `same-window-regexps'. */)
2934 (buffer_name)
2935 Lisp_Object buffer_name;
2937 Lisp_Object tem;
2939 CHECK_STRING (buffer_name);
2941 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2942 if (!NILP (tem))
2943 return Qt;
2945 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2946 if (!NILP (tem))
2947 return Qt;
2949 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
2951 Lisp_Object car = XCAR (tem);
2952 if (STRINGP (car)
2953 && fast_string_match (car, buffer_name) >= 0)
2954 return Qt;
2955 else if (CONSP (car)
2956 && STRINGP (XCAR (car))
2957 && fast_string_match (XCAR (car), buffer_name) >= 0)
2958 return Qt;
2960 return Qnil;
2963 /* Use B so the default is (other-buffer). */
2964 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
2965 "BDisplay buffer: \nP",
2966 doc: /* Make BUFFER appear in some window but don't select it.
2967 BUFFER can be a buffer or a buffer name.
2968 If BUFFER is shown already in some window, just use that one,
2969 unless the window is the selected window and the optional second
2970 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
2971 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
2972 Returns the window displaying BUFFER.
2973 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
2974 displaying BUFFER, then simply raise that frame.
2976 The variables `special-display-buffer-names', `special-display-regexps',
2977 `same-window-buffer-names', and `same-window-regexps' customize how certain
2978 buffer names are handled.
2980 If optional argument FRAME is `visible', search all visible frames.
2981 If FRAME is 0, search all visible and iconified frames.
2982 If FRAME is t, search all frames.
2983 If FRAME is a frame, search only that frame.
2984 If FRAME is nil, search only the selected frame
2985 (actually the last nonminibuffer frame),
2986 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
2987 which means search visible and iconified frames.
2989 If `even-window-heights' is non-nil, window heights will be evened out
2990 if displaying the buffer causes two vertically adjacent windows to be
2991 displayed. */)
2992 (buffer, not_this_window, frame)
2993 register Lisp_Object buffer, not_this_window, frame;
2995 register Lisp_Object window, tem, swp;
2996 struct frame *f;
2998 swp = Qnil;
2999 buffer = Fget_buffer (buffer);
3000 CHECK_BUFFER (buffer);
3002 if (!NILP (Vdisplay_buffer_function))
3003 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
3005 if (NILP (not_this_window)
3006 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
3007 return display_buffer_1 (selected_window);
3009 /* See if the user has specified this buffer should appear
3010 in the selected window. */
3011 if (NILP (not_this_window))
3013 swp = Fsame_window_p (XBUFFER (buffer)->name);
3014 if (!NILP (swp) && !no_switch_window (selected_window))
3016 Fswitch_to_buffer (buffer, Qnil);
3017 return display_buffer_1 (selected_window);
3021 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
3022 look for a window showing BUFFER on any visible or iconified frame.
3023 Otherwise search only the current frame. */
3024 if (! NILP (frame))
3025 tem = frame;
3026 else if (pop_up_frames
3027 || display_buffer_reuse_frames
3028 || last_nonminibuf_frame == 0)
3029 XSETFASTINT (tem, 0);
3030 else
3031 XSETFRAME (tem, last_nonminibuf_frame);
3033 window = Fget_buffer_window (buffer, tem);
3034 if (!NILP (window)
3035 && (NILP (not_this_window) || !EQ (window, selected_window)))
3036 return display_buffer_1 (window);
3038 /* Certain buffer names get special handling. */
3039 if (!NILP (Vspecial_display_function) && NILP (swp))
3041 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3042 if (EQ (tem, Qt))
3043 return call1 (Vspecial_display_function, buffer);
3044 if (CONSP (tem))
3045 return call2 (Vspecial_display_function, buffer, tem);
3048 /* If there are no frames open that have more than a minibuffer,
3049 we need to create a new frame. */
3050 if (pop_up_frames || last_nonminibuf_frame == 0)
3052 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3053 Fset_window_buffer (window, buffer);
3054 return display_buffer_1 (window);
3057 f = SELECTED_FRAME ();
3058 if (pop_up_windows
3059 || FRAME_MINIBUF_ONLY_P (f)
3060 /* If the current frame is a special display frame,
3061 don't try to reuse its windows. */
3062 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3064 Lisp_Object frames;
3066 frames = Qnil;
3067 if (FRAME_MINIBUF_ONLY_P (f))
3068 XSETFRAME (frames, last_nonminibuf_frame);
3069 /* Don't try to create a window if we would get an error. */
3070 if (split_height_threshold < window_min_height << 1)
3071 split_height_threshold = window_min_height << 1;
3073 /* Note that both Fget_largest_window and Fget_lru_window
3074 ignore minibuffers and dedicated windows.
3075 This means they can return nil. */
3077 /* If the frame we would try to split cannot be split,
3078 try other frames. */
3079 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3081 /* Try visible frames first. */
3082 window = Fget_largest_window (Qvisible);
3083 /* If that didn't work, try iconified frames. */
3084 if (NILP (window))
3085 window = Fget_largest_window (make_number (0));
3086 if (NILP (window))
3087 window = Fget_largest_window (Qt);
3089 else
3090 window = Fget_largest_window (frames);
3092 /* If we got a tall enough full-width window that can be split,
3093 split it. */
3094 if (!NILP (window)
3095 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3096 && window_height (window) >= split_height_threshold
3097 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
3098 window = Fsplit_window (window, Qnil, Qnil);
3099 else
3101 Lisp_Object upper, lower, other;
3103 window = Fget_lru_window (frames);
3104 /* If the LRU window is selected, and big enough,
3105 and can be split, split it. */
3106 if (!NILP (window)
3107 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3108 && (EQ (window, selected_window)
3109 || EQ (XWINDOW (window)->parent, Qnil))
3110 && window_height (window) >= window_min_height << 1)
3111 window = Fsplit_window (window, Qnil, Qnil);
3112 /* If Fget_lru_window returned nil, try other approaches. */
3114 /* Try visible frames first. */
3115 if (NILP (window))
3116 window = Fget_buffer_window (buffer, Qvisible);
3117 if (NILP (window))
3118 window = Fget_largest_window (Qvisible);
3119 /* If that didn't work, try iconified frames. */
3120 if (NILP (window))
3121 window = Fget_buffer_window (buffer, make_number (0));
3122 if (NILP (window))
3123 window = Fget_largest_window (make_number (0));
3124 /* Try invisible frames. */
3125 if (NILP (window))
3126 window = Fget_buffer_window (buffer, Qt);
3127 if (NILP (window))
3128 window = Fget_largest_window (Qt);
3129 /* As a last resort, make a new frame. */
3130 if (NILP (window))
3131 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3132 /* If window appears above or below another,
3133 even out their heights. */
3134 other = upper = lower = Qnil;
3135 if (!NILP (XWINDOW (window)->prev))
3136 other = upper = XWINDOW (window)->prev, lower = window;
3137 if (!NILP (XWINDOW (window)->next))
3138 other = lower = XWINDOW (window)->next, upper = window;
3139 if (!NILP (other)
3140 && !NILP (Veven_window_heights)
3141 /* Check that OTHER and WINDOW are vertically arrayed. */
3142 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
3143 && (XFASTINT (XWINDOW (other)->height)
3144 > XFASTINT (XWINDOW (window)->height)))
3146 int total = (XFASTINT (XWINDOW (other)->height)
3147 + XFASTINT (XWINDOW (window)->height));
3148 enlarge_window (upper,
3149 total / 2 - XFASTINT (XWINDOW (upper)->height),
3150 0, 0);
3154 else
3155 window = Fget_lru_window (Qnil);
3157 Fset_window_buffer (window, buffer);
3158 return display_buffer_1 (window);
3161 void
3162 temp_output_buffer_show (buf)
3163 register Lisp_Object buf;
3165 register struct buffer *old = current_buffer;
3166 register Lisp_Object window;
3167 register struct window *w;
3169 XBUFFER (buf)->directory = current_buffer->directory;
3171 Fset_buffer (buf);
3172 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3173 BEGV = BEG;
3174 ZV = Z;
3175 SET_PT (BEG);
3176 #if 0 /* rms: there should be no reason for this. */
3177 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3178 #endif
3179 set_buffer_internal (old);
3181 if (!EQ (Vtemp_buffer_show_function, Qnil))
3182 call1 (Vtemp_buffer_show_function, buf);
3183 else
3185 window = Fdisplay_buffer (buf, Qnil, Qnil);
3187 if (!EQ (XWINDOW (window)->frame, selected_frame))
3188 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3189 Vminibuf_scroll_window = window;
3190 w = XWINDOW (window);
3191 XSETFASTINT (w->hscroll, 0);
3192 XSETFASTINT (w->min_hscroll, 0);
3193 set_marker_restricted_both (w->start, buf, 1, 1);
3194 set_marker_restricted_both (w->pointm, buf, 1, 1);
3196 /* Run temp-buffer-show-hook, with the chosen window selected
3197 and its buffer current. */
3198 if (!NILP (Vrun_hooks))
3200 Lisp_Object tem;
3201 tem = Fboundp (Qtemp_buffer_show_hook);
3202 if (!NILP (tem))
3204 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3205 if (!NILP (tem))
3207 int count = SPECPDL_INDEX ();
3208 Lisp_Object prev_window;
3209 prev_window = selected_window;
3211 /* Select the window that was chosen, for running the hook. */
3212 /* Both this Fselect_window and the select_window_1
3213 below will (may) incorrectly set-buffer to the buffer
3214 displayed in the window. --stef */
3215 record_unwind_protect (Fselect_window, prev_window);
3216 select_window_1 (window, 0);
3217 Fset_buffer (w->buffer);
3218 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3219 select_window_1 (prev_window, 0);
3220 unbind_to (count, Qnil);
3227 static void
3228 make_dummy_parent (window)
3229 Lisp_Object window;
3231 Lisp_Object new;
3232 register struct window *o, *p;
3233 int i;
3235 o = XWINDOW (window);
3236 p = allocate_window ();
3237 for (i = 0; i < VECSIZE (struct window); ++i)
3238 ((struct Lisp_Vector *) p)->contents[i]
3239 = ((struct Lisp_Vector *)o)->contents[i];
3240 XSETWINDOW (new, p);
3242 XSETFASTINT (p->sequence_number, ++sequence_number);
3244 /* Put new into window structure in place of window */
3245 replace_window (window, new);
3247 o->next = Qnil;
3248 o->prev = Qnil;
3249 o->vchild = Qnil;
3250 o->hchild = Qnil;
3251 o->parent = new;
3253 p->start = Qnil;
3254 p->pointm = Qnil;
3255 p->buffer = Qnil;
3258 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3259 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3260 WINDOW defaults to selected one and SIZE to half its size.
3261 If optional third arg HORFLAG is non-nil, split side by side
3262 and put SIZE columns in the first of the pair. In that case,
3263 SIZE includes that window's scroll bar, or the divider column to its right. */)
3264 (window, size, horflag)
3265 Lisp_Object window, size, horflag;
3267 register Lisp_Object new;
3268 register struct window *o, *p;
3269 FRAME_PTR fo;
3270 register int size_int;
3272 if (NILP (window))
3273 window = selected_window;
3274 else
3275 CHECK_LIVE_WINDOW (window);
3277 o = XWINDOW (window);
3278 fo = XFRAME (WINDOW_FRAME (o));
3280 if (NILP (size))
3282 if (!NILP (horflag))
3283 /* Calculate the size of the left-hand window, by dividing
3284 the usable space in columns by two.
3285 We round up, since the left-hand window may include
3286 a dividing line, while the right-hand may not. */
3287 size_int = (XFASTINT (o->width) + 1) >> 1;
3288 else
3289 size_int = XFASTINT (o->height) >> 1;
3291 else
3293 CHECK_NUMBER (size);
3294 size_int = XINT (size);
3297 if (MINI_WINDOW_P (o))
3298 error ("Attempt to split minibuffer window");
3299 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3300 error ("Attempt to split fixed-size window");
3302 check_min_window_sizes ();
3304 if (NILP (horflag))
3306 if (size_int < window_min_height)
3307 error ("Window height %d too small (after splitting)", size_int);
3308 if (size_int + window_min_height > XFASTINT (o->height))
3309 error ("Window height %d too small (after splitting)",
3310 XFASTINT (o->height) - size_int);
3311 if (NILP (o->parent)
3312 || NILP (XWINDOW (o->parent)->vchild))
3314 make_dummy_parent (window);
3315 new = o->parent;
3316 XWINDOW (new)->vchild = window;
3319 else
3321 if (size_int < window_min_width)
3322 error ("Window width %d too small (after splitting)", size_int);
3324 if (size_int + window_min_width > XFASTINT (o->width))
3325 error ("Window width %d too small (after splitting)",
3326 XFASTINT (o->width) - size_int);
3327 if (NILP (o->parent)
3328 || NILP (XWINDOW (o->parent)->hchild))
3330 make_dummy_parent (window);
3331 new = o->parent;
3332 XWINDOW (new)->hchild = window;
3336 /* Now we know that window's parent is a vertical combination
3337 if we are dividing vertically, or a horizontal combination
3338 if we are making side-by-side windows */
3340 windows_or_buffers_changed++;
3341 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3342 new = make_window ();
3343 p = XWINDOW (new);
3345 p->frame = o->frame;
3346 p->next = o->next;
3347 if (!NILP (p->next))
3348 XWINDOW (p->next)->prev = new;
3349 p->prev = window;
3350 o->next = new;
3351 p->parent = o->parent;
3352 p->buffer = Qt;
3353 p->window_end_valid = Qnil;
3354 bzero (&p->last_cursor, sizeof p->last_cursor);
3356 /* Apportion the available frame space among the two new windows */
3358 if (!NILP (horflag))
3360 p->height = o->height;
3361 p->top = o->top;
3362 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
3363 XSETFASTINT (o->width, size_int);
3364 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
3366 else
3368 p->left = o->left;
3369 p->width = o->width;
3370 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
3371 XSETFASTINT (o->height, size_int);
3372 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
3375 /* Adjust glyph matrices. */
3376 adjust_glyphs (fo);
3377 Fset_window_buffer (new, o->buffer);
3378 return new;
3381 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 3, "p",
3382 doc: /* Make current window ARG lines bigger.
3383 From program, optional second arg non-nil means grow sideways ARG columns.
3384 Interactively, if an argument is not given, make the window one line bigger.
3386 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3387 of the siblings above or to the left of the selected window. Only
3388 siblings to the right or below are changed. */)
3389 (arg, side, preserve_before)
3390 register Lisp_Object arg, side, preserve_before;
3392 CHECK_NUMBER (arg);
3393 enlarge_window (selected_window, XINT (arg), !NILP (side),
3394 !NILP (preserve_before));
3396 if (! NILP (Vwindow_configuration_change_hook))
3397 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3399 return Qnil;
3402 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 3, "p",
3403 doc: /* Make current window ARG lines smaller.
3404 From program, optional second arg non-nil means shrink sideways arg columns.
3405 Interactively, if an argument is not given, make the window one line smaller.
3407 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3408 of the siblings above or to the left of the selected window. Only
3409 siblings to the right or below are changed. */)
3410 (arg, side, preserve_before)
3411 register Lisp_Object arg, side, preserve_before;
3413 CHECK_NUMBER (arg);
3414 enlarge_window (selected_window, -XINT (arg), !NILP (side),
3415 !NILP (preserve_before));
3417 if (! NILP (Vwindow_configuration_change_hook))
3418 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3420 return Qnil;
3424 window_height (window)
3425 Lisp_Object window;
3427 register struct window *p = XWINDOW (window);
3428 return XFASTINT (p->height);
3432 window_width (window)
3433 Lisp_Object window;
3435 register struct window *p = XWINDOW (window);
3436 return XFASTINT (p->width);
3440 #define CURBEG(w) \
3441 *(widthflag ? &(XWINDOW (w)->left) : &(XWINDOW (w)->top))
3443 #define CURSIZE(w) \
3444 *(widthflag ? &(XWINDOW (w)->width) : &(XWINDOW (w)->height))
3447 /* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means
3448 increase its width. Siblings of the selected window are resized to
3449 fulfill the size request. If they become too small in the process,
3450 they will be deleted.
3452 If PRESERVE_BEFORE is nonzero, that means don't alter
3453 the siblings to the left or above WINDOW. */
3455 static void
3456 enlarge_window (window, delta, widthflag, preserve_before)
3457 Lisp_Object window;
3458 int delta, widthflag, preserve_before;
3460 Lisp_Object parent, next, prev;
3461 struct window *p;
3462 Lisp_Object *sizep;
3463 int maximum;
3464 int (*sizefun) P_ ((Lisp_Object))
3465 = widthflag ? window_width : window_height;
3466 void (*setsizefun) P_ ((Lisp_Object, int, int))
3467 = (widthflag ? set_window_width : set_window_height);
3469 /* Check values of window_min_width and window_min_height for
3470 validity. */
3471 check_min_window_sizes ();
3473 /* Give up if this window cannot be resized. */
3474 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3475 error ("Window is not resizable");
3477 /* Find the parent of the selected window. */
3478 while (1)
3480 p = XWINDOW (window);
3481 parent = p->parent;
3483 if (NILP (parent))
3485 if (widthflag)
3486 error ("No other window to side of this one");
3487 break;
3490 if (widthflag
3491 ? !NILP (XWINDOW (parent)->hchild)
3492 : !NILP (XWINDOW (parent)->vchild))
3493 break;
3495 window = parent;
3498 sizep = &CURSIZE (window);
3501 register int maxdelta;
3503 /* Compute the maximum size increment this window can have. */
3505 if (preserve_before)
3507 if (!NILP (parent))
3509 maxdelta = (*sizefun) (parent) - XINT (*sizep);
3510 /* Subtract size of siblings before, since we can't take that. */
3511 maxdelta -= XINT (CURBEG (window)) - XINT (CURBEG (parent));
3513 else
3514 maxdelta = (!NILP (p->next) ? ((*sizefun) (p->next)
3515 - window_min_size (XWINDOW (p->next),
3516 widthflag, 0, 0))
3517 : (delta = 0));
3519 else
3520 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
3521 /* This is a main window followed by a minibuffer. */
3522 : !NILP (p->next) ? ((*sizefun) (p->next)
3523 - window_min_size (XWINDOW (p->next),
3524 widthflag, 0, 0))
3525 /* This is a minibuffer following a main window. */
3526 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3527 - window_min_size (XWINDOW (p->prev),
3528 widthflag, 0, 0))
3529 /* This is a frame with only one window, a minibuffer-only
3530 or a minibufferless frame. */
3531 : (delta = 0));
3533 if (delta > maxdelta)
3534 /* This case traps trying to make the minibuffer
3535 the full frame, or make the only window aside from the
3536 minibuffer the full frame. */
3537 delta = maxdelta;
3540 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3542 delete_window (window);
3543 return;
3546 if (delta == 0)
3547 return;
3549 /* Find the total we can get from other siblings without deleting them. */
3550 maximum = 0;
3551 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3552 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3553 widthflag, 0, 0);
3554 if (! preserve_before)
3555 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3556 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3557 widthflag, 0, 0);
3559 /* If we can get it all from them without deleting them, do so. */
3560 if (delta <= maximum)
3562 Lisp_Object first_unaffected;
3563 Lisp_Object first_affected;
3564 int fixed_p;
3566 next = p->next;
3567 prev = p->prev;
3568 first_affected = window;
3569 /* Look at one sibling at a time,
3570 moving away from this window in both directions alternately,
3571 and take as much as we can get without deleting that sibling. */
3572 while (delta != 0
3573 && (!NILP (next) || (!preserve_before && !NILP (prev))))
3575 if (! NILP (next))
3577 int this_one = ((*sizefun) (next)
3578 - window_min_size (XWINDOW (next),
3579 widthflag, 0, &fixed_p));
3580 if (!fixed_p)
3582 if (this_one > delta)
3583 this_one = delta;
3585 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3586 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3588 delta -= this_one;
3591 next = XWINDOW (next)->next;
3594 if (delta == 0)
3595 break;
3597 if (!preserve_before && ! NILP (prev))
3599 int this_one = ((*sizefun) (prev)
3600 - window_min_size (XWINDOW (prev),
3601 widthflag, 0, &fixed_p));
3602 if (!fixed_p)
3604 if (this_one > delta)
3605 this_one = delta;
3607 first_affected = prev;
3609 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3610 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3612 delta -= this_one;
3615 prev = XWINDOW (prev)->prev;
3619 xassert (delta == 0);
3621 /* Now recalculate the edge positions of all the windows affected,
3622 based on the new sizes. */
3623 first_unaffected = next;
3624 prev = first_affected;
3625 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3626 prev = next, next = XWINDOW (next)->next)
3628 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
3629 /* This does not change size of NEXT,
3630 but it propagates the new top edge to its children */
3631 (*setsizefun) (next, (*sizefun) (next), 0);
3634 else
3636 register int delta1;
3637 register int opht = (*sizefun) (parent);
3639 if (opht <= XINT (*sizep) + delta)
3641 /* If trying to grow this window to or beyond size of the parent,
3642 just delete all the sibling windows. */
3643 Lisp_Object start, tem, next;
3645 start = XWINDOW (parent)->vchild;
3646 if (NILP (start))
3647 start = XWINDOW (parent)->hchild;
3649 /* Delete any siblings that come after WINDOW. */
3650 tem = XWINDOW (window)->next;
3651 while (! NILP (tem))
3653 next = XWINDOW (tem)->next;
3654 delete_window (tem);
3655 tem = next;
3658 /* Delete any siblings that come after WINDOW.
3659 Note that if START is not WINDOW, then WINDOW still
3660 Fhas siblings, so WINDOW has not yet replaced its parent. */
3661 tem = start;
3662 while (! EQ (tem, window))
3664 next = XWINDOW (tem)->next;
3665 delete_window (tem);
3666 tem = next;
3669 else
3671 /* Otherwise, make delta1 just right so that if we add
3672 delta1 lines to this window and to the parent, and then
3673 shrink the parent back to its original size, the new
3674 proportional size of this window will increase by delta.
3676 The function size_window will compute the new height h'
3677 of the window from delta1 as:
3679 e = delta1/n
3680 x = delta1 - delta1/n * n for the 1st resizable child
3681 h' = h + e + x
3683 where n is the number of children that can be resized.
3684 We can ignore x by choosing a delta1 that is a multiple of
3685 n. We want the height of this window to come out as
3687 h' = h + delta
3689 So, delta1 must be
3691 h + e = h + delta
3692 delta1/n = delta
3693 delta1 = n * delta.
3695 The number of children n equals the number of resizable
3696 children of this window + 1 because we know window itself
3697 is resizable (otherwise we would have signalled an error. */
3699 struct window *w = XWINDOW (window);
3700 Lisp_Object s;
3701 int n = 1;
3703 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3704 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3705 ++n;
3706 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3707 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3708 ++n;
3710 delta1 = n * delta;
3712 /* Add delta1 lines or columns to this window, and to the parent,
3713 keeping things consistent while not affecting siblings. */
3714 XSETINT (CURSIZE (parent), opht + delta1);
3715 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
3717 /* Squeeze out delta1 lines or columns from our parent,
3718 shriking this window and siblings proportionately.
3719 This brings parent back to correct size.
3720 Delta1 was calculated so this makes this window the desired size,
3721 taking it all out of the siblings. */
3722 (*setsizefun) (parent, opht, 0);
3727 XSETFASTINT (p->last_modified, 0);
3728 XSETFASTINT (p->last_overlay_modified, 0);
3730 /* Adjust glyph matrices. */
3731 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
3734 #undef CURBEG
3735 #undef CURSIZE
3739 /***********************************************************************
3740 Resizing Mini-Windows
3741 ***********************************************************************/
3743 static void shrink_window_lowest_first P_ ((struct window *, int));
3745 enum save_restore_action
3747 CHECK_ORIG_SIZES,
3748 SAVE_ORIG_SIZES,
3749 RESTORE_ORIG_SIZES
3752 static int save_restore_orig_size P_ ((struct window *,
3753 enum save_restore_action));
3755 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
3756 from lowest windows first. */
3758 static void
3759 shrink_window_lowest_first (w, height)
3760 struct window *w;
3761 int height;
3763 struct window *c;
3764 Lisp_Object child;
3765 int old_height;
3767 xassert (!MINI_WINDOW_P (w));
3769 /* Set redisplay hints. */
3770 XSETFASTINT (w->last_modified, 0);
3771 XSETFASTINT (w->last_overlay_modified, 0);
3772 windows_or_buffers_changed++;
3773 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
3775 old_height = XFASTINT (w->height);
3776 XSETFASTINT (w->height, height);
3778 if (!NILP (w->hchild))
3780 for (child = w->hchild; !NILP (child); child = c->next)
3782 c = XWINDOW (child);
3783 c->top = w->top;
3784 shrink_window_lowest_first (c, height);
3787 else if (!NILP (w->vchild))
3789 Lisp_Object last_child;
3790 int delta = old_height - height;
3791 int last_top;
3793 last_child = Qnil;
3795 /* Find the last child. We are taking space from lowest windows
3796 first, so we iterate over children from the last child
3797 backwards. */
3798 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
3799 last_child = child;
3801 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
3802 for (child = last_child; delta && !NILP (child); child = c->prev)
3804 int this_one;
3806 c = XWINDOW (child);
3807 this_one = XFASTINT (c->height) - MIN_SAFE_WINDOW_HEIGHT;
3809 if (this_one > delta)
3810 this_one = delta;
3812 shrink_window_lowest_first (c, XFASTINT (c->height) - this_one);
3813 delta -= this_one;
3816 /* Compute new positions. */
3817 last_top = XINT (w->top);
3818 for (child = w->vchild; !NILP (child); child = c->next)
3820 c = XWINDOW (child);
3821 c->top = make_number (last_top);
3822 shrink_window_lowest_first (c, XFASTINT (c->height));
3823 last_top += XFASTINT (c->height);
3829 /* Save, restore, or check positions and sizes in the window tree
3830 rooted at W. ACTION says what to do.
3832 If ACTION is CHECK_ORIG_SIZES, check if orig_top and orig_height
3833 members are valid for all windows in the window tree. Value is
3834 non-zero if they are valid.
3836 If ACTION is SAVE_ORIG_SIZES, save members top and height in
3837 orig_top and orig_height for all windows in the tree.
3839 If ACTION is RESTORE_ORIG_SIZES, restore top and height from
3840 values stored in orig_top and orig_height for all windows. */
3842 static int
3843 save_restore_orig_size (w, action)
3844 struct window *w;
3845 enum save_restore_action action;
3847 int success_p = 1;
3849 while (w)
3851 if (!NILP (w->hchild))
3853 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
3854 success_p = 0;
3856 else if (!NILP (w->vchild))
3858 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
3859 success_p = 0;
3862 switch (action)
3864 case CHECK_ORIG_SIZES:
3865 if (!INTEGERP (w->orig_top) || !INTEGERP (w->orig_height))
3866 return 0;
3867 break;
3869 case SAVE_ORIG_SIZES:
3870 w->orig_top = w->top;
3871 w->orig_height = w->height;
3872 XSETFASTINT (w->last_modified, 0);
3873 XSETFASTINT (w->last_overlay_modified, 0);
3874 break;
3876 case RESTORE_ORIG_SIZES:
3877 xassert (INTEGERP (w->orig_top) && INTEGERP (w->orig_height));
3878 w->top = w->orig_top;
3879 w->height = w->orig_height;
3880 w->orig_height = w->orig_top = Qnil;
3881 XSETFASTINT (w->last_modified, 0);
3882 XSETFASTINT (w->last_overlay_modified, 0);
3883 break;
3885 default:
3886 abort ();
3889 w = NILP (w->next) ? NULL : XWINDOW (w->next);
3892 return success_p;
3896 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
3897 without deleting other windows. */
3899 void
3900 grow_mini_window (w, delta)
3901 struct window *w;
3902 int delta;
3904 struct frame *f = XFRAME (w->frame);
3905 struct window *root;
3907 xassert (MINI_WINDOW_P (w));
3908 xassert (delta >= 0);
3910 /* Check values of window_min_width and window_min_height for
3911 validity. */
3912 check_min_window_sizes ();
3914 /* Compute how much we can enlarge the mini-window without deleting
3915 other windows. */
3916 root = XWINDOW (FRAME_ROOT_WINDOW (f));
3917 if (delta)
3919 int min_height = window_min_size (root, 0, 0, 0);
3920 if (XFASTINT (root->height) - delta < min_height)
3921 /* Note that the root window may already be smaller than
3922 min_height. */
3923 delta = max (0, XFASTINT (root->height) - min_height);
3926 if (delta)
3928 /* Save original window sizes and positions, if not already done. */
3929 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
3930 save_restore_orig_size (root, SAVE_ORIG_SIZES);
3932 /* Shrink other windows. */
3933 shrink_window_lowest_first (root, XFASTINT (root->height) - delta);
3935 /* Grow the mini-window. */
3936 w->top = make_number (XFASTINT (root->top) + XFASTINT (root->height));
3937 w->height = make_number (XFASTINT (w->height) + delta);
3938 XSETFASTINT (w->last_modified, 0);
3939 XSETFASTINT (w->last_overlay_modified, 0);
3941 adjust_glyphs (f);
3946 /* Shrink mini-window W. If there is recorded info about window sizes
3947 before a call to grow_mini_window, restore recorded window sizes.
3948 Otherwise, if the mini-window is higher than 1 line, resize it to 1
3949 line. */
3951 void
3952 shrink_mini_window (w)
3953 struct window *w;
3955 struct frame *f = XFRAME (w->frame);
3956 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
3958 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
3960 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
3961 adjust_glyphs (f);
3962 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3963 windows_or_buffers_changed = 1;
3965 else if (XFASTINT (w->height) > 1)
3967 /* Distribute the additional lines of the mini-window
3968 among the other windows. */
3969 Lisp_Object window;
3970 XSETWINDOW (window, w);
3971 enlarge_window (window, 1 - XFASTINT (w->height), 0, 0);
3977 /* Mark window cursors off for all windows in the window tree rooted
3978 at W by setting their phys_cursor_on_p flag to zero. Called from
3979 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3980 the frame are cleared. */
3982 void
3983 mark_window_cursors_off (w)
3984 struct window *w;
3986 while (w)
3988 if (!NILP (w->hchild))
3989 mark_window_cursors_off (XWINDOW (w->hchild));
3990 else if (!NILP (w->vchild))
3991 mark_window_cursors_off (XWINDOW (w->vchild));
3992 else
3993 w->phys_cursor_on_p = 0;
3995 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4000 /* Return number of lines of text (not counting mode lines) in W. */
4003 window_internal_height (w)
4004 struct window *w;
4006 int ht = XFASTINT (w->height);
4008 if (!MINI_WINDOW_P (w))
4010 if (!NILP (w->parent)
4011 || !NILP (w->vchild)
4012 || !NILP (w->hchild)
4013 || !NILP (w->next)
4014 || !NILP (w->prev)
4015 || WINDOW_WANTS_MODELINE_P (w))
4016 --ht;
4018 if (WINDOW_WANTS_HEADER_LINE_P (w))
4019 --ht;
4022 return ht;
4026 /* Return the number of columns in W.
4027 Don't count columns occupied by scroll bars or the vertical bar
4028 separating W from the sibling to its right. */
4031 window_internal_width (w)
4032 struct window *w;
4034 struct frame *f = XFRAME (WINDOW_FRAME (w));
4035 int width = XINT (w->width);
4037 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4038 /* Scroll bars occupy a few columns. */
4039 width -= FRAME_SCROLL_BAR_COLS (f);
4040 else if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
4041 /* The column of `|' characters separating side-by-side windows
4042 occupies one column only. */
4043 width -= 1;
4045 /* On window-systems, areas to the left and right of the window
4046 are used as fringes. */
4047 if (FRAME_WINDOW_P (f))
4048 width -= FRAME_FRINGE_COLS (f);
4050 return width;
4054 /************************************************************************
4055 Window Scrolling
4056 ***********************************************************************/
4058 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4059 N screen-fulls, which is defined as the height of the window minus
4060 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4061 instead. Negative values of N mean scroll down. NOERROR non-zero
4062 means don't signal an error if we try to move over BEGV or ZV,
4063 respectively. */
4065 static void
4066 window_scroll (window, n, whole, noerror)
4067 Lisp_Object window;
4068 int n;
4069 int whole;
4070 int noerror;
4072 immediate_quit = 1;
4074 /* If we must, use the pixel-based version which is much slower than
4075 the line-based one but can handle varying line heights. */
4076 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4077 window_scroll_pixel_based (window, n, whole, noerror);
4078 else
4079 window_scroll_line_based (window, n, whole, noerror);
4081 immediate_quit = 0;
4085 /* Implementation of window_scroll that works based on pixel line
4086 heights. See the comment of window_scroll for parameter
4087 descriptions. */
4089 static void
4090 window_scroll_pixel_based (window, n, whole, noerror)
4091 Lisp_Object window;
4092 int n;
4093 int whole;
4094 int noerror;
4096 struct it it;
4097 struct window *w = XWINDOW (window);
4098 struct text_pos start;
4099 Lisp_Object tem;
4100 int this_scroll_margin;
4101 int preserve_y;
4102 /* True if we fiddled the window vscroll field without really scrolling. */
4103 int vscrolled = 0;
4105 SET_TEXT_POS_FROM_MARKER (start, w->start);
4107 /* If PT is not visible in WINDOW, move back one half of
4108 the screen. Allow PT to be partially visible, otherwise
4109 something like (scroll-down 1) with PT in the line before
4110 the partially visible one would recenter. */
4111 tem = Fpos_visible_in_window_p (make_number (PT), window, Qt);
4112 if (NILP (tem))
4114 /* Move backward half the height of the window. Performance note:
4115 vmotion used here is about 10% faster, but would give wrong
4116 results for variable height lines. */
4117 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4118 it.current_y = it.last_visible_y;
4119 move_it_vertically (&it, - window_box_height (w) / 2);
4121 /* The function move_iterator_vertically may move over more than
4122 the specified y-distance. If it->w is small, e.g. a
4123 mini-buffer window, we may end up in front of the window's
4124 display area. This is the case when Start displaying at the
4125 start of the line containing PT in this case. */
4126 if (it.current_y <= 0)
4128 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4129 move_it_vertically (&it, 0);
4130 it.current_y = 0;
4133 start = it.current.pos;
4136 /* If scroll_preserve_screen_position is non-zero, we try to set
4137 point in the same window line as it is now, so get that line. */
4138 if (!NILP (Vscroll_preserve_screen_position))
4140 start_display (&it, w, start);
4141 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4142 preserve_y = it.current_y;
4144 else
4145 preserve_y = -1;
4147 /* Move iterator it from start the specified distance forward or
4148 backward. The result is the new window start. */
4149 start_display (&it, w, start);
4150 if (whole)
4152 int screen_full = (window_box_height (w)
4153 - next_screen_context_lines * CANON_Y_UNIT (it.f));
4154 int dy = n * screen_full;
4156 /* Note that move_it_vertically always moves the iterator to the
4157 start of a line. So, if the last line doesn't have a newline,
4158 we would end up at the start of the line ending at ZV. */
4159 if (dy <= 0)
4160 move_it_vertically_backward (&it, -dy);
4161 else if (dy > 0)
4162 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4163 MOVE_TO_POS | MOVE_TO_Y);
4165 else
4166 move_it_by_lines (&it, n, 1);
4168 /* We failed if we find ZV is already on the screen (scrolling up,
4169 means there's nothing past the end), or if we can't start any
4170 earlier (scrolling down, means there's nothing past the top). */
4171 if ((n > 0 && IT_CHARPOS (it) == ZV)
4172 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4174 if (IT_CHARPOS (it) == ZV)
4176 if (it.current_y < it.last_visible_y
4177 && (it.current_y + it.max_ascent + it.max_descent
4178 >= it.last_visible_y))
4180 /* The last line was only partially visible, make it fully
4181 visible. */
4182 w->vscroll = (it.last_visible_y
4183 - it.current_y + it.max_ascent + it.max_descent);
4184 adjust_glyphs (it.f);
4186 else if (noerror)
4187 return;
4188 else
4189 Fsignal (Qend_of_buffer, Qnil);
4191 else
4193 if (w->vscroll != 0)
4194 /* The first line was only partially visible, make it fully
4195 visible. */
4196 w->vscroll = 0;
4197 else if (noerror)
4198 return;
4199 else
4200 Fsignal (Qbeginning_of_buffer, Qnil);
4203 /* If control gets here, then we vscrolled. */
4205 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4207 /* Don't try to change the window start below. */
4208 vscrolled = 1;
4211 if (! vscrolled)
4213 int pos = IT_CHARPOS (it);
4214 int bytepos;
4216 /* If in the middle of a multi-glyph character move forward to
4217 the next character. */
4218 if (in_display_vector_p (&it))
4220 ++pos;
4221 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4224 /* Set the window start, and set up the window for redisplay. */
4225 set_marker_restricted (w->start, make_number (pos),
4226 w->buffer);
4227 bytepos = XMARKER (w->start)->bytepos;
4228 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
4229 ? Qt : Qnil);
4230 w->update_mode_line = Qt;
4231 XSETFASTINT (w->last_modified, 0);
4232 XSETFASTINT (w->last_overlay_modified, 0);
4233 /* Set force_start so that redisplay_window will run the
4234 window-scroll-functions. */
4235 w->force_start = Qt;
4238 it.current_y = it.vpos = 0;
4240 /* Preserve the screen position if we must. */
4241 if (preserve_y >= 0)
4243 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
4244 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4246 else
4248 /* Move PT out of scroll margins. */
4249 this_scroll_margin = max (0, scroll_margin);
4250 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
4251 this_scroll_margin *= CANON_Y_UNIT (it.f);
4253 if (n > 0)
4255 /* We moved the window start towards ZV, so PT may be now
4256 in the scroll margin at the top. */
4257 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4258 while (it.current_y < this_scroll_margin)
4260 int prev = it.current_y;
4261 move_it_by_lines (&it, 1, 1);
4262 if (prev == it.current_y)
4263 break;
4265 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4267 else if (n < 0)
4269 int charpos, bytepos;
4271 /* We moved the window start towards BEGV, so PT may be now
4272 in the scroll margin at the bottom. */
4273 move_it_to (&it, PT, -1,
4274 it.last_visible_y - this_scroll_margin - 1, -1,
4275 MOVE_TO_POS | MOVE_TO_Y);
4277 /* Save our position, in case it's correct. */
4278 charpos = IT_CHARPOS (it);
4279 bytepos = IT_BYTEPOS (it);
4281 /* See if point is on a partially visible line at the end. */
4282 move_it_by_lines (&it, 1, 1);
4283 if (it.current_y > it.last_visible_y)
4284 /* The last line was only partially visible, so back up two
4285 lines to make sure we're on a fully visible line. */
4287 move_it_by_lines (&it, -2, 0);
4288 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4290 else
4291 /* No, the position we saved is OK, so use it. */
4292 SET_PT_BOTH (charpos, bytepos);
4298 /* Implementation of window_scroll that works based on screen lines.
4299 See the comment of window_scroll for parameter descriptions. */
4301 static void
4302 window_scroll_line_based (window, n, whole, noerror)
4303 Lisp_Object window;
4304 int n;
4305 int whole;
4306 int noerror;
4308 register struct window *w = XWINDOW (window);
4309 register int opoint = PT, opoint_byte = PT_BYTE;
4310 register int pos, pos_byte;
4311 register int ht = window_internal_height (w);
4312 register Lisp_Object tem;
4313 int lose;
4314 Lisp_Object bolp;
4315 int startpos;
4316 struct position posit;
4317 int original_vpos;
4319 /* If scrolling screen-fulls, compute the number of lines to
4320 scroll from the window's height. */
4321 if (whole)
4322 n *= max (1, ht - next_screen_context_lines);
4324 startpos = marker_position (w->start);
4326 posit = *compute_motion (startpos, 0, 0, 0,
4327 PT, ht, 0,
4328 window_internal_width (w), XINT (w->hscroll),
4329 0, w);
4330 original_vpos = posit.vpos;
4332 XSETFASTINT (tem, PT);
4333 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4335 if (NILP (tem))
4337 Fvertical_motion (make_number (- (ht / 2)), window);
4338 startpos = PT;
4341 SET_PT (startpos);
4342 lose = n < 0 && PT == BEGV;
4343 Fvertical_motion (make_number (n), window);
4344 pos = PT;
4345 pos_byte = PT_BYTE;
4346 bolp = Fbolp ();
4347 SET_PT_BOTH (opoint, opoint_byte);
4349 if (lose)
4351 if (noerror)
4352 return;
4353 else
4354 Fsignal (Qbeginning_of_buffer, Qnil);
4357 if (pos < ZV)
4359 int this_scroll_margin = scroll_margin;
4361 /* Don't use a scroll margin that is negative or too large. */
4362 if (this_scroll_margin < 0)
4363 this_scroll_margin = 0;
4365 if (XINT (w->height) < 4 * scroll_margin)
4366 this_scroll_margin = XINT (w->height) / 4;
4368 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4369 w->start_at_line_beg = bolp;
4370 w->update_mode_line = Qt;
4371 XSETFASTINT (w->last_modified, 0);
4372 XSETFASTINT (w->last_overlay_modified, 0);
4373 /* Set force_start so that redisplay_window will run
4374 the window-scroll-functions. */
4375 w->force_start = Qt;
4377 if (whole && !NILP (Vscroll_preserve_screen_position))
4379 SET_PT_BOTH (pos, pos_byte);
4380 Fvertical_motion (make_number (original_vpos), window);
4382 /* If we scrolled forward, put point enough lines down
4383 that it is outside the scroll margin. */
4384 else if (n > 0)
4386 int top_margin;
4388 if (this_scroll_margin > 0)
4390 SET_PT_BOTH (pos, pos_byte);
4391 Fvertical_motion (make_number (this_scroll_margin), window);
4392 top_margin = PT;
4394 else
4395 top_margin = pos;
4397 if (top_margin <= opoint)
4398 SET_PT_BOTH (opoint, opoint_byte);
4399 else if (!NILP (Vscroll_preserve_screen_position))
4401 SET_PT_BOTH (pos, pos_byte);
4402 Fvertical_motion (make_number (original_vpos), window);
4404 else
4405 SET_PT (top_margin);
4407 else if (n < 0)
4409 int bottom_margin;
4411 /* If we scrolled backward, put point near the end of the window
4412 but not within the scroll margin. */
4413 SET_PT_BOTH (pos, pos_byte);
4414 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4415 if (XFASTINT (tem) == ht - this_scroll_margin)
4416 bottom_margin = PT;
4417 else
4418 bottom_margin = PT + 1;
4420 if (bottom_margin > opoint)
4421 SET_PT_BOTH (opoint, opoint_byte);
4422 else
4424 if (!NILP (Vscroll_preserve_screen_position))
4426 SET_PT_BOTH (pos, pos_byte);
4427 Fvertical_motion (make_number (original_vpos), window);
4429 else
4430 Fvertical_motion (make_number (-1), window);
4434 else
4436 if (noerror)
4437 return;
4438 else
4439 Fsignal (Qend_of_buffer, Qnil);
4444 /* Scroll selected_window up or down. If N is nil, scroll a
4445 screen-full which is defined as the height of the window minus
4446 next_screen_context_lines. If N is the symbol `-', scroll.
4447 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4448 up. This is the guts of Fscroll_up and Fscroll_down. */
4450 static void
4451 scroll_command (n, direction)
4452 Lisp_Object n;
4453 int direction;
4455 int count = SPECPDL_INDEX ();
4457 xassert (abs (direction) == 1);
4459 /* If selected window's buffer isn't current, make it current for
4460 the moment. But don't screw up if window_scroll gets an error. */
4461 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4463 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4464 Fset_buffer (XWINDOW (selected_window)->buffer);
4466 /* Make redisplay consider other windows than just selected_window. */
4467 ++windows_or_buffers_changed;
4470 if (NILP (n))
4471 window_scroll (selected_window, direction, 1, 0);
4472 else if (EQ (n, Qminus))
4473 window_scroll (selected_window, -direction, 1, 0);
4474 else
4476 n = Fprefix_numeric_value (n);
4477 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4480 unbind_to (count, Qnil);
4483 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
4484 doc: /* Scroll text of current window upward ARG lines; or near full screen if no ARG.
4485 A near full screen is `next-screen-context-lines' less than a full screen.
4486 Negative ARG means scroll downward.
4487 If ARG is the atom `-', scroll downward by nearly full screen.
4488 When calling from a program, supply as argument a number, nil, or `-'. */)
4489 (arg)
4490 Lisp_Object arg;
4492 scroll_command (arg, 1);
4493 return Qnil;
4496 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
4497 doc: /* Scroll text of current window down ARG lines; or near full screen if no ARG.
4498 A near full screen is `next-screen-context-lines' less than a full screen.
4499 Negative ARG means scroll upward.
4500 If ARG is the atom `-', scroll upward by nearly full screen.
4501 When calling from a program, supply as argument a number, nil, or `-'. */)
4502 (arg)
4503 Lisp_Object arg;
4505 scroll_command (arg, -1);
4506 return Qnil;
4509 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4510 doc: /* Return the other window for \"other window scroll\" commands.
4511 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4512 specifies the window.
4513 If `other-window-scroll-buffer' is non-nil, a window
4514 showing that buffer is used. */)
4517 Lisp_Object window;
4519 if (MINI_WINDOW_P (XWINDOW (selected_window))
4520 && !NILP (Vminibuf_scroll_window))
4521 window = Vminibuf_scroll_window;
4522 /* If buffer is specified, scroll that buffer. */
4523 else if (!NILP (Vother_window_scroll_buffer))
4525 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4526 if (NILP (window))
4527 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4529 else
4531 /* Nothing specified; look for a neighboring window on the same
4532 frame. */
4533 window = Fnext_window (selected_window, Qnil, Qnil);
4535 if (EQ (window, selected_window))
4536 /* That didn't get us anywhere; look for a window on another
4537 visible frame. */
4539 window = Fnext_window (window, Qnil, Qt);
4540 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4541 && ! EQ (window, selected_window));
4544 CHECK_LIVE_WINDOW (window);
4546 if (EQ (window, selected_window))
4547 error ("There is no other window");
4549 return window;
4552 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4553 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4554 A near full screen is `next-screen-context-lines' less than a full screen.
4555 The next window is the one below the current one; or the one at the top
4556 if the current one is at the bottom. Negative ARG means scroll downward.
4557 If ARG is the atom `-', scroll downward by nearly full screen.
4558 When calling from a program, supply as argument a number, nil, or `-'.
4560 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4561 specifies the window to scroll.
4562 If `other-window-scroll-buffer' is non-nil, scroll the window
4563 showing that buffer, popping the buffer up if necessary. */)
4564 (arg)
4565 Lisp_Object arg;
4567 Lisp_Object window;
4568 struct window *w;
4569 int count = SPECPDL_INDEX ();
4571 window = Fother_window_for_scrolling ();
4572 w = XWINDOW (window);
4574 /* Don't screw up if window_scroll gets an error. */
4575 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4576 ++windows_or_buffers_changed;
4578 Fset_buffer (w->buffer);
4579 SET_PT (marker_position (w->pointm));
4581 if (NILP (arg))
4582 window_scroll (window, 1, 1, 1);
4583 else if (EQ (arg, Qminus))
4584 window_scroll (window, -1, 1, 1);
4585 else
4587 if (CONSP (arg))
4588 arg = Fcar (arg);
4589 CHECK_NUMBER (arg);
4590 window_scroll (window, XINT (arg), 0, 1);
4593 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4594 unbind_to (count, Qnil);
4596 return Qnil;
4599 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
4600 doc: /* Scroll selected window display ARG columns left.
4601 Default for ARG is window width minus 2.
4602 Value is the total amount of leftward horizontal scrolling in
4603 effect after the change.
4604 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4605 a lower bound for automatic scrolling, i.e. automatic scrolling
4606 will not scroll a window to a column less than the value returned
4607 by this function. */)
4608 (arg)
4609 register Lisp_Object arg;
4611 Lisp_Object result;
4612 int hscroll;
4613 struct window *w = XWINDOW (selected_window);
4615 if (NILP (arg))
4616 XSETFASTINT (arg, window_internal_width (w) - 2);
4617 else
4618 arg = Fprefix_numeric_value (arg);
4620 hscroll = XINT (w->hscroll) + XINT (arg);
4621 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4623 if (interactive_p (0))
4624 w->min_hscroll = w->hscroll;
4626 return result;
4629 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
4630 doc: /* Scroll selected window display ARG columns right.
4631 Default for ARG is window width minus 2.
4632 Value is the total amount of leftward horizontal scrolling in
4633 effect after the change.
4634 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4635 a lower bound for automatic scrolling, i.e. automatic scrolling
4636 will not scroll a window to a column less than the value returned
4637 by this function. */)
4638 (arg)
4639 register Lisp_Object arg;
4641 Lisp_Object result;
4642 int hscroll;
4643 struct window *w = XWINDOW (selected_window);
4645 if (NILP (arg))
4646 XSETFASTINT (arg, window_internal_width (w) - 2);
4647 else
4648 arg = Fprefix_numeric_value (arg);
4650 hscroll = XINT (w->hscroll) - XINT (arg);
4651 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4653 if (interactive_p (0))
4654 w->min_hscroll = w->hscroll;
4656 return result;
4659 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
4660 doc: /* Return the window which was selected when entering the minibuffer.
4661 Returns nil, if current window is not a minibuffer window. */)
4664 if (minibuf_level > 0
4665 && MINI_WINDOW_P (XWINDOW (selected_window))
4666 && !NILP (minibuf_selected_window)
4667 && WINDOW_LIVE_P (minibuf_selected_window))
4668 return minibuf_selected_window;
4670 return Qnil;
4673 /* Value is the number of lines actually displayed in window W,
4674 as opposed to its height. */
4676 static int
4677 displayed_window_lines (w)
4678 struct window *w;
4680 struct it it;
4681 struct text_pos start;
4682 int height = window_box_height (w);
4683 struct buffer *old_buffer;
4684 int bottom_y;
4686 if (XBUFFER (w->buffer) != current_buffer)
4688 old_buffer = current_buffer;
4689 set_buffer_internal (XBUFFER (w->buffer));
4691 else
4692 old_buffer = NULL;
4694 /* In case W->start is out of the accessible range, do something
4695 reasonable. This happens in Info mode when Info-scroll-down
4696 calls (recenter -1) while W->start is 1. */
4697 if (XMARKER (w->start)->charpos < BEGV)
4698 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4699 else if (XMARKER (w->start)->charpos > ZV)
4700 SET_TEXT_POS (start, ZV, ZV_BYTE);
4701 else
4702 SET_TEXT_POS_FROM_MARKER (start, w->start);
4704 start_display (&it, w, start);
4705 move_it_vertically (&it, height);
4706 bottom_y = line_bottom_y (&it);
4708 /* rms: On a non-window display,
4709 the value of it.vpos at the bottom of the screen
4710 seems to be 1 larger than window_box_height (w).
4711 This kludge fixes a bug whereby (move-to-window-line -1)
4712 when ZV is on the last screen line
4713 moves to the previous screen line instead of the last one. */
4714 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
4715 height++;
4717 /* Add in empty lines at the bottom of the window. */
4718 if (bottom_y < height)
4720 int uy = CANON_Y_UNIT (it.f);
4721 it.vpos += (height - bottom_y + uy - 1) / uy;
4724 if (old_buffer)
4725 set_buffer_internal (old_buffer);
4727 return it.vpos;
4731 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
4732 doc: /* Center point in window and redisplay frame.
4733 With prefix argument ARG, recenter putting point on screen line ARG
4734 relative to the current window. If ARG is negative, it counts up from the
4735 bottom of the window. (ARG should be less than the height of the window.)
4737 If ARG is omitted or nil, erase the entire frame and then
4738 redraw with point in the center of the current window.
4739 Just C-u as prefix means put point in the center of the window
4740 and redisplay normally--don't erase and redraw the frame. */)
4741 (arg)
4742 register Lisp_Object arg;
4744 struct window *w = XWINDOW (selected_window);
4745 struct buffer *buf = XBUFFER (w->buffer);
4746 struct buffer *obuf = current_buffer;
4747 int center_p = 0;
4748 int charpos, bytepos;
4750 /* If redisplay is suppressed due to an error, try again. */
4751 obuf->display_error_modiff = 0;
4753 if (NILP (arg))
4755 int i;
4757 /* Invalidate pixel data calculated for all compositions. */
4758 for (i = 0; i < n_compositions; i++)
4759 composition_table[i]->font = NULL;
4761 Fredraw_frame (w->frame);
4762 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
4763 center_p = 1;
4765 else if (CONSP (arg)) /* Just C-u. */
4766 center_p = 1;
4767 else
4769 arg = Fprefix_numeric_value (arg);
4770 CHECK_NUMBER (arg);
4773 set_buffer_internal (buf);
4775 /* Handle centering on a graphical frame specially. Such frames can
4776 have variable-height lines and centering point on the basis of
4777 line counts would lead to strange effects. */
4778 if (FRAME_WINDOW_P (XFRAME (w->frame)))
4780 if (center_p)
4782 struct it it;
4783 struct text_pos pt;
4785 SET_TEXT_POS (pt, PT, PT_BYTE);
4786 start_display (&it, w, pt);
4787 move_it_vertically (&it, - window_box_height (w) / 2);
4788 charpos = IT_CHARPOS (it);
4789 bytepos = IT_BYTEPOS (it);
4791 else if (XINT (arg) < 0)
4793 struct it it;
4794 struct text_pos pt;
4795 int y0, y1, h, nlines;
4797 SET_TEXT_POS (pt, PT, PT_BYTE);
4798 start_display (&it, w, pt);
4799 y0 = it.current_y;
4801 /* The amount of pixels we have to move back is the window
4802 height minus what's displayed in the line containing PT,
4803 and the lines below. */
4804 nlines = - XINT (arg) - 1;
4805 move_it_by_lines (&it, nlines, 1);
4807 y1 = line_bottom_y (&it);
4809 /* If we can't move down NLINES lines because we hit
4810 the end of the buffer, count in some empty lines. */
4811 if (it.vpos < nlines)
4812 y1 += (nlines - it.vpos) * CANON_Y_UNIT (it.f);
4814 h = window_box_height (w) - (y1 - y0);
4816 start_display (&it, w, pt);
4817 move_it_vertically (&it, - h);
4818 charpos = IT_CHARPOS (it);
4819 bytepos = IT_BYTEPOS (it);
4821 else
4823 struct position pos;
4824 pos = *vmotion (PT, - XINT (arg), w);
4825 charpos = pos.bufpos;
4826 bytepos = pos.bytepos;
4829 else
4831 struct position pos;
4832 int ht = window_internal_height (w);
4834 if (center_p)
4835 arg = make_number (ht / 2);
4836 else if (XINT (arg) < 0)
4837 arg = make_number (XINT (arg) + ht);
4839 pos = *vmotion (PT, - XINT (arg), w);
4840 charpos = pos.bufpos;
4841 bytepos = pos.bytepos;
4844 /* Set the new window start. */
4845 set_marker_both (w->start, w->buffer, charpos, bytepos);
4846 w->window_end_valid = Qnil;
4848 w->optional_new_start = Qt;
4850 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
4851 w->start_at_line_beg = Qt;
4852 else
4853 w->start_at_line_beg = Qnil;
4855 set_buffer_internal (obuf);
4856 return Qnil;
4860 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
4861 0, 1, 0,
4862 doc: /* Return the height in lines of the text display area of WINDOW.
4863 This doesn't include the mode-line (or header-line if any) or any
4864 partial-height lines in the text display area. */)
4865 (window)
4866 Lisp_Object window;
4868 struct window *w = decode_window (window);
4869 int pixel_height = window_box_height (w);
4870 int line_height = pixel_height / CANON_Y_UNIT (XFRAME (w->frame));
4871 return make_number (line_height);
4876 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
4877 1, 1, "P",
4878 doc: /* Position point relative to window.
4879 With no argument, position point at center of window.
4880 An argument specifies vertical position within the window;
4881 zero means top of window, negative means relative to bottom of window. */)
4882 (arg)
4883 Lisp_Object arg;
4885 struct window *w = XWINDOW (selected_window);
4886 int lines, start;
4887 Lisp_Object window;
4889 window = selected_window;
4890 start = marker_position (w->start);
4891 if (start < BEGV || start > ZV)
4893 int height = window_internal_height (w);
4894 Fvertical_motion (make_number (- (height / 2)), window);
4895 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
4896 w->start_at_line_beg = Fbolp ();
4897 w->force_start = Qt;
4899 else
4900 Fgoto_char (w->start);
4902 lines = displayed_window_lines (w);
4903 if (NILP (arg))
4904 XSETFASTINT (arg, lines / 2);
4905 else
4907 arg = Fprefix_numeric_value (arg);
4908 if (XINT (arg) < 0)
4909 XSETINT (arg, XINT (arg) + lines);
4912 /* Skip past a partially visible first line. */
4913 if (w->vscroll)
4914 XSETINT (arg, XINT (arg) + 1);
4916 return Fvertical_motion (arg, window);
4921 /***********************************************************************
4922 Window Configuration
4923 ***********************************************************************/
4925 struct save_window_data
4927 EMACS_INT size_from_Lisp_Vector_struct;
4928 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4929 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
4930 Lisp_Object frame_tool_bar_lines;
4931 Lisp_Object selected_frame;
4932 Lisp_Object current_window;
4933 Lisp_Object current_buffer;
4934 Lisp_Object minibuf_scroll_window;
4935 Lisp_Object minibuf_selected_window;
4936 Lisp_Object root_window;
4937 Lisp_Object focus_frame;
4938 /* Record the values of window-min-width and window-min-height
4939 so that window sizes remain consistent with them. */
4940 Lisp_Object min_width, min_height;
4941 /* A vector, each of whose elements is a struct saved_window
4942 for one window. */
4943 Lisp_Object saved_windows;
4946 /* This is saved as a Lisp_Vector */
4947 struct saved_window
4949 /* these first two must agree with struct Lisp_Vector in lisp.h */
4950 EMACS_INT size_from_Lisp_Vector_struct;
4951 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4953 Lisp_Object window;
4954 Lisp_Object buffer, start, pointm, mark;
4955 Lisp_Object left, top, width, height, hscroll, min_hscroll;
4956 Lisp_Object parent, prev;
4957 Lisp_Object start_at_line_beg;
4958 Lisp_Object display_table;
4959 Lisp_Object orig_top, orig_height;
4962 #define SAVED_WINDOW_VECTOR_SIZE 17 /* Arg to Fmake_vector */
4964 #define SAVED_WINDOW_N(swv,n) \
4965 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4967 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
4968 doc: /* Return t if OBJECT is a window-configuration object. */)
4969 (object)
4970 Lisp_Object object;
4972 if (WINDOW_CONFIGURATIONP (object))
4973 return Qt;
4974 return Qnil;
4977 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
4978 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
4979 (config)
4980 Lisp_Object config;
4982 register struct save_window_data *data;
4983 struct Lisp_Vector *saved_windows;
4985 if (! WINDOW_CONFIGURATIONP (config))
4986 wrong_type_argument (Qwindow_configuration_p, config);
4988 data = (struct save_window_data *) XVECTOR (config);
4989 saved_windows = XVECTOR (data->saved_windows);
4990 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4993 DEFUN ("set-window-configuration", Fset_window_configuration,
4994 Sset_window_configuration, 1, 1, 0,
4995 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
4996 CONFIGURATION must be a value previously returned
4997 by `current-window-configuration' (which see).
4998 If CONFIGURATION was made from a frame that is now deleted,
4999 only frame-independent values can be restored. In this case,
5000 the return value is nil. Otherwise the value is t. */)
5001 (configuration)
5002 Lisp_Object configuration;
5004 register struct save_window_data *data;
5005 struct Lisp_Vector *saved_windows;
5006 Lisp_Object new_current_buffer;
5007 Lisp_Object frame;
5008 FRAME_PTR f;
5009 int old_point = -1;
5011 while (!WINDOW_CONFIGURATIONP (configuration))
5012 wrong_type_argument (Qwindow_configuration_p, configuration);
5014 data = (struct save_window_data *) XVECTOR (configuration);
5015 saved_windows = XVECTOR (data->saved_windows);
5017 new_current_buffer = data->current_buffer;
5018 if (NILP (XBUFFER (new_current_buffer)->name))
5019 new_current_buffer = Qnil;
5020 else
5022 if (XBUFFER (new_current_buffer) == current_buffer)
5023 old_point = PT;
5024 else
5025 old_point = BUF_PT (XBUFFER (new_current_buffer));
5028 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5029 f = XFRAME (frame);
5031 /* If f is a dead frame, don't bother rebuilding its window tree.
5032 However, there is other stuff we should still try to do below. */
5033 if (FRAME_LIVE_P (f))
5035 register struct window *w;
5036 register struct saved_window *p;
5037 struct window *root_window;
5038 struct window **leaf_windows;
5039 int n_leaf_windows;
5040 int k, i, n;
5042 /* If the frame has been resized since this window configuration was
5043 made, we change the frame to the size specified in the
5044 configuration, restore the configuration, and then resize it
5045 back. We keep track of the prevailing height in these variables. */
5046 int previous_frame_height = FRAME_HEIGHT (f);
5047 int previous_frame_width = FRAME_WIDTH (f);
5048 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5049 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5051 /* The mouse highlighting code could get screwed up
5052 if it runs during this. */
5053 BLOCK_INPUT;
5055 if (XFASTINT (data->frame_height) != previous_frame_height
5056 || XFASTINT (data->frame_width) != previous_frame_width)
5057 change_frame_size (f, XFASTINT (data->frame_height),
5058 XFASTINT (data->frame_width), 0, 0, 0);
5059 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5060 if (XFASTINT (data->frame_menu_bar_lines)
5061 != previous_frame_menu_bar_lines)
5062 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
5063 #ifdef HAVE_WINDOW_SYSTEM
5064 if (XFASTINT (data->frame_tool_bar_lines)
5065 != previous_frame_tool_bar_lines)
5066 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
5067 #endif
5068 #endif
5070 /* "Swap out" point from the selected window
5071 into its buffer. We do this now, before
5072 restoring the window contents, and prevent it from
5073 being done later on when we select a new window. */
5074 if (! NILP (XWINDOW (selected_window)->buffer))
5076 w = XWINDOW (selected_window);
5077 set_marker_both (w->pointm,
5078 w->buffer,
5079 BUF_PT (XBUFFER (w->buffer)),
5080 BUF_PT_BYTE (XBUFFER (w->buffer)));
5083 windows_or_buffers_changed++;
5084 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5086 /* Problem: Freeing all matrices and later allocating them again
5087 is a serious redisplay flickering problem. What we would
5088 really like to do is to free only those matrices not reused
5089 below. */
5090 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5091 leaf_windows
5092 = (struct window **) alloca (count_windows (root_window)
5093 * sizeof (struct window *));
5094 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5096 /* Temporarily avoid any problems with windows that are smaller
5097 than they are supposed to be. */
5098 window_min_height = 1;
5099 window_min_width = 1;
5101 /* Kludge Alert!
5102 Mark all windows now on frame as "deleted".
5103 Restoring the new configuration "undeletes" any that are in it.
5105 Save their current buffers in their height fields, since we may
5106 need it later, if a buffer saved in the configuration is now
5107 dead. */
5108 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5110 for (k = 0; k < saved_windows->size; k++)
5112 p = SAVED_WINDOW_N (saved_windows, k);
5113 w = XWINDOW (p->window);
5114 w->next = Qnil;
5116 if (!NILP (p->parent))
5117 w->parent = SAVED_WINDOW_N (saved_windows,
5118 XFASTINT (p->parent))->window;
5119 else
5120 w->parent = Qnil;
5122 if (!NILP (p->prev))
5124 w->prev = SAVED_WINDOW_N (saved_windows,
5125 XFASTINT (p->prev))->window;
5126 XWINDOW (w->prev)->next = p->window;
5128 else
5130 w->prev = Qnil;
5131 if (!NILP (w->parent))
5133 if (EQ (p->width, XWINDOW (w->parent)->width))
5135 XWINDOW (w->parent)->vchild = p->window;
5136 XWINDOW (w->parent)->hchild = Qnil;
5138 else
5140 XWINDOW (w->parent)->hchild = p->window;
5141 XWINDOW (w->parent)->vchild = Qnil;
5146 /* If we squirreled away the buffer in the window's height,
5147 restore it now. */
5148 if (BUFFERP (w->height))
5149 w->buffer = w->height;
5150 w->left = p->left;
5151 w->top = p->top;
5152 w->width = p->width;
5153 w->height = p->height;
5154 w->hscroll = p->hscroll;
5155 w->min_hscroll = p->min_hscroll;
5156 w->display_table = p->display_table;
5157 w->orig_top = p->orig_top;
5158 w->orig_height = p->orig_height;
5159 XSETFASTINT (w->last_modified, 0);
5160 XSETFASTINT (w->last_overlay_modified, 0);
5162 /* Reinstall the saved buffer and pointers into it. */
5163 if (NILP (p->buffer))
5164 w->buffer = p->buffer;
5165 else
5167 if (!NILP (XBUFFER (p->buffer)->name))
5168 /* If saved buffer is alive, install it. */
5170 w->buffer = p->buffer;
5171 w->start_at_line_beg = p->start_at_line_beg;
5172 set_marker_restricted (w->start, p->start, w->buffer);
5173 set_marker_restricted (w->pointm, p->pointm, w->buffer);
5174 Fset_marker (XBUFFER (w->buffer)->mark,
5175 p->mark, w->buffer);
5177 /* As documented in Fcurrent_window_configuration, don't
5178 restore the location of point in the buffer which was
5179 current when the window configuration was recorded. */
5180 if (!EQ (p->buffer, new_current_buffer)
5181 && XBUFFER (p->buffer) == current_buffer)
5182 Fgoto_char (w->pointm);
5184 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
5185 /* Else unless window has a live buffer, get one. */
5187 w->buffer = Fcdr (Fcar (Vbuffer_alist));
5188 /* This will set the markers to beginning of visible
5189 range. */
5190 set_marker_restricted (w->start, make_number (0), w->buffer);
5191 set_marker_restricted (w->pointm, make_number (0),w->buffer);
5192 w->start_at_line_beg = Qt;
5194 else
5195 /* Keeping window's old buffer; make sure the markers
5196 are real. */
5198 /* Set window markers at start of visible range. */
5199 if (XMARKER (w->start)->buffer == 0)
5200 set_marker_restricted (w->start, make_number (0),
5201 w->buffer);
5202 if (XMARKER (w->pointm)->buffer == 0)
5203 set_marker_restricted_both (w->pointm, w->buffer,
5204 BUF_PT (XBUFFER (w->buffer)),
5205 BUF_PT_BYTE (XBUFFER (w->buffer)));
5206 w->start_at_line_beg = Qt;
5211 FRAME_ROOT_WINDOW (f) = data->root_window;
5212 /* Prevent "swapping out point" in the old selected window
5213 using the buffer that has been restored into it.
5214 Use the point value from the beginning of this function
5215 since unshow_buffer (called from delete_all_subwindows)
5216 could have altered it. */
5217 selected_window = Qnil;
5218 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5219 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5220 make_number (old_point),
5221 XWINDOW (data->current_window)->buffer);
5223 Fselect_window (data->current_window);
5224 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
5225 = selected_window;
5227 if (NILP (data->focus_frame)
5228 || (FRAMEP (data->focus_frame)
5229 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5230 Fredirect_frame_focus (frame, data->focus_frame);
5232 #if 0 /* I don't understand why this is needed, and it causes problems
5233 when the frame's old selected window has been deleted. */
5234 if (f != selected_frame && FRAME_WINDOW_P (f))
5235 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
5236 0, 0);
5237 #endif
5239 /* Set the screen height to the value it had before this function. */
5240 if (previous_frame_height != FRAME_HEIGHT (f)
5241 || previous_frame_width != FRAME_WIDTH (f))
5242 change_frame_size (f, previous_frame_height, previous_frame_width,
5243 0, 0, 0);
5244 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5245 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5246 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5247 make_number (0));
5248 #ifdef HAVE_WINDOW_SYSTEM
5249 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5250 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5251 make_number (0));
5252 #endif
5253 #endif
5255 /* Now, free glyph matrices in windows that were not reused. */
5256 for (i = n = 0; i < n_leaf_windows; ++i)
5258 if (NILP (leaf_windows[i]->buffer))
5260 /* Assert it's not reused as a combination. */
5261 xassert (NILP (leaf_windows[i]->hchild)
5262 && NILP (leaf_windows[i]->vchild));
5263 free_window_matrices (leaf_windows[i]);
5265 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5266 ++n;
5269 adjust_glyphs (f);
5271 UNBLOCK_INPUT;
5273 /* Fselect_window will have made f the selected frame, so we
5274 reselect the proper frame here. Fhandle_switch_frame will change the
5275 selected window too, but that doesn't make the call to
5276 Fselect_window above totally superfluous; it still sets f's
5277 selected window. */
5278 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5279 do_switch_frame (data->selected_frame, 0, 0);
5281 if (! NILP (Vwindow_configuration_change_hook)
5282 && ! NILP (Vrun_hooks))
5283 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
5286 if (!NILP (new_current_buffer))
5287 Fset_buffer (new_current_buffer);
5289 /* Restore the minimum heights recorded in the configuration. */
5290 window_min_height = XINT (data->min_height);
5291 window_min_width = XINT (data->min_width);
5293 Vminibuf_scroll_window = data->minibuf_scroll_window;
5294 minibuf_selected_window = data->minibuf_selected_window;
5296 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5299 /* Mark all windows now on frame as deleted
5300 by setting their buffers to nil. */
5302 void
5303 delete_all_subwindows (w)
5304 register struct window *w;
5306 if (!NILP (w->next))
5307 delete_all_subwindows (XWINDOW (w->next));
5308 if (!NILP (w->vchild))
5309 delete_all_subwindows (XWINDOW (w->vchild));
5310 if (!NILP (w->hchild))
5311 delete_all_subwindows (XWINDOW (w->hchild));
5313 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
5315 if (!NILP (w->buffer))
5316 unshow_buffer (w);
5318 /* We set all three of these fields to nil, to make sure that we can
5319 distinguish this dead window from any live window. Live leaf
5320 windows will have buffer set, and combination windows will have
5321 vchild or hchild set. */
5322 w->buffer = Qnil;
5323 w->vchild = Qnil;
5324 w->hchild = Qnil;
5326 Vwindow_list = Qnil;
5329 static int
5330 count_windows (window)
5331 register struct window *window;
5333 register int count = 1;
5334 if (!NILP (window->next))
5335 count += count_windows (XWINDOW (window->next));
5336 if (!NILP (window->vchild))
5337 count += count_windows (XWINDOW (window->vchild));
5338 if (!NILP (window->hchild))
5339 count += count_windows (XWINDOW (window->hchild));
5340 return count;
5344 /* Fill vector FLAT with leaf windows under W, starting at index I.
5345 Value is last index + 1. */
5347 static int
5348 get_leaf_windows (w, flat, i)
5349 struct window *w;
5350 struct window **flat;
5351 int i;
5353 while (w)
5355 if (!NILP (w->hchild))
5356 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5357 else if (!NILP (w->vchild))
5358 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5359 else
5360 flat[i++] = w;
5362 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5365 return i;
5369 /* Return a pointer to the glyph W's physical cursor is on. Value is
5370 null if W's current matrix is invalid, so that no meaningfull glyph
5371 can be returned. */
5373 struct glyph *
5374 get_phys_cursor_glyph (w)
5375 struct window *w;
5377 struct glyph_row *row;
5378 struct glyph *glyph;
5380 if (w->phys_cursor.vpos >= 0
5381 && w->phys_cursor.vpos < w->current_matrix->nrows
5382 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
5383 row->enabled_p)
5384 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
5385 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
5386 else
5387 glyph = NULL;
5389 return glyph;
5393 static int
5394 save_window_save (window, vector, i)
5395 Lisp_Object window;
5396 struct Lisp_Vector *vector;
5397 int i;
5399 register struct saved_window *p;
5400 register struct window *w;
5401 register Lisp_Object tem;
5403 for (;!NILP (window); window = w->next)
5405 p = SAVED_WINDOW_N (vector, i);
5406 w = XWINDOW (window);
5408 XSETFASTINT (w->temslot, i++);
5409 p->window = window;
5410 p->buffer = w->buffer;
5411 p->left = w->left;
5412 p->top = w->top;
5413 p->width = w->width;
5414 p->height = w->height;
5415 p->hscroll = w->hscroll;
5416 p->min_hscroll = w->min_hscroll;
5417 p->display_table = w->display_table;
5418 p->orig_top = w->orig_top;
5419 p->orig_height = w->orig_height;
5420 if (!NILP (w->buffer))
5422 /* Save w's value of point in the window configuration.
5423 If w is the selected window, then get the value of point
5424 from the buffer; pointm is garbage in the selected window. */
5425 if (EQ (window, selected_window))
5427 p->pointm = Fmake_marker ();
5428 set_marker_both (p->pointm, w->buffer,
5429 BUF_PT (XBUFFER (w->buffer)),
5430 BUF_PT_BYTE (XBUFFER (w->buffer)));
5432 else
5433 p->pointm = Fcopy_marker (w->pointm, Qnil);
5435 p->start = Fcopy_marker (w->start, Qnil);
5436 p->start_at_line_beg = w->start_at_line_beg;
5438 tem = XBUFFER (w->buffer)->mark;
5439 p->mark = Fcopy_marker (tem, Qnil);
5441 else
5443 p->pointm = Qnil;
5444 p->start = Qnil;
5445 p->mark = Qnil;
5446 p->start_at_line_beg = Qnil;
5449 if (NILP (w->parent))
5450 p->parent = Qnil;
5451 else
5452 p->parent = XWINDOW (w->parent)->temslot;
5454 if (NILP (w->prev))
5455 p->prev = Qnil;
5456 else
5457 p->prev = XWINDOW (w->prev)->temslot;
5459 if (!NILP (w->vchild))
5460 i = save_window_save (w->vchild, vector, i);
5461 if (!NILP (w->hchild))
5462 i = save_window_save (w->hchild, vector, i);
5465 return i;
5468 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
5469 Scurrent_window_configuration, 0, 1, 0,
5470 doc: /* Return an object representing the current window configuration of FRAME.
5471 If FRAME is nil or omitted, use the selected frame.
5472 This describes the number of windows, their sizes and current buffers,
5473 and for each displayed buffer, where display starts, and the positions of
5474 point and mark. An exception is made for point in the current buffer:
5475 its value is -not- saved.
5476 This also records the currently selected frame, and FRAME's focus
5477 redirection (see `redirect-frame-focus'). */)
5478 (frame)
5479 Lisp_Object frame;
5481 register Lisp_Object tem;
5482 register int n_windows;
5483 register struct save_window_data *data;
5484 register struct Lisp_Vector *vec;
5485 register int i;
5486 FRAME_PTR f;
5488 if (NILP (frame))
5489 frame = selected_frame;
5490 CHECK_LIVE_FRAME (frame);
5491 f = XFRAME (frame);
5493 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5494 vec = allocate_other_vector (VECSIZE (struct save_window_data));
5495 data = (struct save_window_data *)vec;
5497 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
5498 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
5499 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
5500 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
5501 data->selected_frame = selected_frame;
5502 data->current_window = FRAME_SELECTED_WINDOW (f);
5503 XSETBUFFER (data->current_buffer, current_buffer);
5504 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
5505 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
5506 data->root_window = FRAME_ROOT_WINDOW (f);
5507 data->focus_frame = FRAME_FOCUS_FRAME (f);
5508 XSETINT (data->min_height, window_min_height);
5509 XSETINT (data->min_width, window_min_width);
5510 tem = Fmake_vector (make_number (n_windows), Qnil);
5511 data->saved_windows = tem;
5512 for (i = 0; i < n_windows; i++)
5513 XVECTOR (tem)->contents[i]
5514 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
5515 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
5516 XSETWINDOW_CONFIGURATION (tem, data);
5517 return (tem);
5520 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
5521 0, UNEVALLED, 0,
5522 doc: /* Execute body, preserving window sizes and contents.
5523 Restore which buffer appears in which window, where display starts,
5524 and the value of point and mark for each window.
5525 Also restore the choice of selected window.
5526 Also restore which buffer is current.
5527 Does not restore the value of point in current buffer.
5528 usage: (save-window-excursion BODY ...) */)
5529 (args)
5530 Lisp_Object args;
5532 register Lisp_Object val;
5533 register int count = SPECPDL_INDEX ();
5535 record_unwind_protect (Fset_window_configuration,
5536 Fcurrent_window_configuration (Qnil));
5537 val = Fprogn (args);
5538 return unbind_to (count, val);
5542 /***********************************************************************
5543 Marginal Areas
5544 ***********************************************************************/
5546 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
5547 2, 3, 0,
5548 doc: /* Set width of marginal areas of window WINDOW.
5549 If window is nil, set margins of the currently selected window.
5550 First parameter LEFT-WIDTH specifies the number of character
5551 cells to reserve for the left marginal area. Second parameter
5552 RIGHT-WIDTH does the same for the right marginal area.
5553 A nil width parameter means no margin. */)
5554 (window, left, right)
5555 Lisp_Object window, left, right;
5557 struct window *w = decode_window (window);
5559 if (!NILP (left))
5560 CHECK_NUMBER_OR_FLOAT (left);
5561 if (!NILP (right))
5562 CHECK_NUMBER_OR_FLOAT (right);
5564 /* Check widths < 0 and translate a zero width to nil.
5565 Margins that are too wide have to be checked elsewhere. */
5566 if ((INTEGERP (left) && XINT (left) < 0)
5567 || (FLOATP (left) && XFLOAT_DATA (left) <= 0))
5568 XSETFASTINT (left, 0);
5569 if (INTEGERP (left) && XFASTINT (left) == 0)
5570 left = Qnil;
5572 if ((INTEGERP (right) && XINT (right) < 0)
5573 || (FLOATP (right) && XFLOAT_DATA (right) <= 0))
5574 XSETFASTINT (right, 0);
5575 if (INTEGERP (right) && XFASTINT (right) == 0)
5576 right = Qnil;
5578 w->left_margin_width = left;
5579 w->right_margin_width = right;
5581 ++windows_or_buffers_changed;
5582 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5583 return Qnil;
5587 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
5588 0, 1, 0,
5589 doc: /* Get width of marginal areas of window WINDOW.
5590 If WINDOW is omitted or nil, use the currently selected window.
5591 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
5592 If a marginal area does not exist, its width will be returned
5593 as nil. */)
5594 (window)
5595 Lisp_Object window;
5597 struct window *w = decode_window (window);
5598 return Fcons (w->left_margin_width, w->right_margin_width);
5603 /***********************************************************************
5604 Smooth scrolling
5605 ***********************************************************************/
5607 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
5608 doc: /* Return the amount by which WINDOW is scrolled vertically.
5609 Use the selected window if WINDOW is nil or omitted.
5610 Value is a multiple of the canonical character height of WINDOW. */)
5611 (window)
5612 Lisp_Object window;
5614 Lisp_Object result;
5615 struct frame *f;
5616 struct window *w;
5618 if (NILP (window))
5619 window = selected_window;
5620 else
5621 CHECK_WINDOW (window);
5622 w = XWINDOW (window);
5623 f = XFRAME (w->frame);
5625 if (FRAME_WINDOW_P (f))
5626 result = CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
5627 else
5628 result = make_number (0);
5629 return result;
5633 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
5634 2, 2, 0,
5635 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
5636 WINDOW nil means use the selected window. VSCROLL is a non-negative
5637 multiple of the canonical character height of WINDOW. */)
5638 (window, vscroll)
5639 Lisp_Object window, vscroll;
5641 struct window *w;
5642 struct frame *f;
5644 if (NILP (window))
5645 window = selected_window;
5646 else
5647 CHECK_WINDOW (window);
5648 CHECK_NUMBER_OR_FLOAT (vscroll);
5650 w = XWINDOW (window);
5651 f = XFRAME (w->frame);
5653 if (FRAME_WINDOW_P (f))
5655 int old_dy = w->vscroll;
5657 w->vscroll = - CANON_Y_UNIT (f) * XFLOATINT (vscroll);
5658 w->vscroll = min (w->vscroll, 0);
5660 /* Adjust glyph matrix of the frame if the virtual display
5661 area becomes larger than before. */
5662 if (w->vscroll < 0 && w->vscroll < old_dy)
5663 adjust_glyphs (f);
5665 /* Prevent redisplay shortcuts. */
5666 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5669 return Fwindow_vscroll (window);
5673 /* Call FN for all leaf windows on frame F. FN is called with the
5674 first argument being a pointer to the leaf window, and with
5675 additional argument USER_DATA. Stops when FN returns 0. */
5677 void
5678 foreach_window (f, fn, user_data)
5679 struct frame *f;
5680 int (* fn) P_ ((struct window *, void *));
5681 void *user_data;
5683 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
5687 /* Helper function for foreach_window. Call FN for all leaf windows
5688 reachable from W. FN is called with the first argument being a
5689 pointer to the leaf window, and with additional argument USER_DATA.
5690 Stop when FN returns 0. Value is 0 if stopped by FN. */
5692 static int
5693 foreach_window_1 (w, fn, user_data)
5694 struct window *w;
5695 int (* fn) P_ ((struct window *, void *));
5696 void *user_data;
5698 int cont;
5700 for (cont = 1; w && cont;)
5702 if (!NILP (w->hchild))
5703 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
5704 else if (!NILP (w->vchild))
5705 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
5706 else
5707 cont = fn (w, user_data);
5709 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5712 return cont;
5716 /* Freeze or unfreeze the window start of W unless it is a
5717 mini-window or the selected window. FREEZE_P non-null means freeze
5718 the window start. */
5720 static int
5721 freeze_window_start (w, freeze_p)
5722 struct window *w;
5723 void *freeze_p;
5725 if (w == XWINDOW (selected_window)
5726 || MINI_WINDOW_P (w)
5727 || (MINI_WINDOW_P (XWINDOW (selected_window))
5728 && ! NILP (Vminibuf_scroll_window)
5729 && w == XWINDOW (Vminibuf_scroll_window)))
5730 freeze_p = NULL;
5732 w->frozen_window_start_p = freeze_p != NULL;
5733 return 1;
5737 /* Freeze or unfreeze the window starts of all leaf windows on frame
5738 F, except the selected window and a mini-window. FREEZE_P non-zero
5739 means freeze the window start. */
5741 void
5742 freeze_window_starts (f, freeze_p)
5743 struct frame *f;
5744 int freeze_p;
5746 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
5750 /***********************************************************************
5751 Initialization
5752 ***********************************************************************/
5754 /* Return 1 if window configurations C1 and C2
5755 describe the same state of affairs. This is used by Fequal. */
5758 compare_window_configurations (c1, c2, ignore_positions)
5759 Lisp_Object c1, c2;
5760 int ignore_positions;
5762 register struct save_window_data *d1, *d2;
5763 struct Lisp_Vector *sw1, *sw2;
5764 int i;
5766 if (!WINDOW_CONFIGURATIONP (c1))
5767 wrong_type_argument (Qwindow_configuration_p, c1);
5768 if (!WINDOW_CONFIGURATIONP (c2))
5769 wrong_type_argument (Qwindow_configuration_p, c2);
5771 d1 = (struct save_window_data *) XVECTOR (c1);
5772 d2 = (struct save_window_data *) XVECTOR (c2);
5773 sw1 = XVECTOR (d1->saved_windows);
5774 sw2 = XVECTOR (d2->saved_windows);
5776 if (! EQ (d1->frame_width, d2->frame_width))
5777 return 0;
5778 if (! EQ (d1->frame_height, d2->frame_height))
5779 return 0;
5780 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
5781 return 0;
5782 if (! EQ (d1->selected_frame, d2->selected_frame))
5783 return 0;
5784 /* Don't compare the current_window field directly.
5785 Instead see w1_is_current and w2_is_current, below. */
5786 if (! EQ (d1->current_buffer, d2->current_buffer))
5787 return 0;
5788 if (! ignore_positions)
5790 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
5791 return 0;
5792 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
5793 return 0;
5795 /* Don't compare the root_window field.
5796 We don't require the two configurations
5797 to use the same window object,
5798 and the two root windows must be equivalent
5799 if everything else compares equal. */
5800 if (! EQ (d1->focus_frame, d2->focus_frame))
5801 return 0;
5802 if (! EQ (d1->min_width, d2->min_width))
5803 return 0;
5804 if (! EQ (d1->min_height, d2->min_height))
5805 return 0;
5807 /* Verify that the two confis have the same number of windows. */
5808 if (sw1->size != sw2->size)
5809 return 0;
5811 for (i = 0; i < sw1->size; i++)
5813 struct saved_window *p1, *p2;
5814 int w1_is_current, w2_is_current;
5816 p1 = SAVED_WINDOW_N (sw1, i);
5817 p2 = SAVED_WINDOW_N (sw2, i);
5819 /* Verify that the current windows in the two
5820 configurations correspond to each other. */
5821 w1_is_current = EQ (d1->current_window, p1->window);
5822 w2_is_current = EQ (d2->current_window, p2->window);
5824 if (w1_is_current != w2_is_current)
5825 return 0;
5827 /* Verify that the corresponding windows do match. */
5828 if (! EQ (p1->buffer, p2->buffer))
5829 return 0;
5830 if (! EQ (p1->left, p2->left))
5831 return 0;
5832 if (! EQ (p1->top, p2->top))
5833 return 0;
5834 if (! EQ (p1->width, p2->width))
5835 return 0;
5836 if (! EQ (p1->height, p2->height))
5837 return 0;
5838 if (! EQ (p1->display_table, p2->display_table))
5839 return 0;
5840 if (! EQ (p1->parent, p2->parent))
5841 return 0;
5842 if (! EQ (p1->prev, p2->prev))
5843 return 0;
5844 if (! ignore_positions)
5846 if (! EQ (p1->hscroll, p2->hscroll))
5847 return 0;
5848 if (!EQ (p1->min_hscroll, p2->min_hscroll))
5849 return 0;
5850 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
5851 return 0;
5852 if (NILP (Fequal (p1->start, p2->start)))
5853 return 0;
5854 if (NILP (Fequal (p1->pointm, p2->pointm)))
5855 return 0;
5856 if (NILP (Fequal (p1->mark, p2->mark)))
5857 return 0;
5861 return 1;
5864 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
5865 Scompare_window_configurations, 2, 2, 0,
5866 doc: /* Compare two window configurations as regards the structure of windows.
5867 This function ignores details such as the values of point and mark
5868 and scrolling positions. */)
5869 (x, y)
5870 Lisp_Object x, y;
5872 if (compare_window_configurations (x, y, 1))
5873 return Qt;
5874 return Qnil;
5877 void
5878 init_window_once ()
5880 struct frame *f = make_terminal_frame ();
5881 XSETFRAME (selected_frame, f);
5882 Vterminal_frame = selected_frame;
5883 minibuf_window = f->minibuffer_window;
5884 selected_window = f->selected_window;
5885 last_nonminibuf_frame = f;
5887 window_initialized = 1;
5890 void
5891 init_window ()
5893 Vwindow_list = Qnil;
5896 void
5897 syms_of_window ()
5899 Qwindow_size_fixed = intern ("window-size-fixed");
5900 staticpro (&Qwindow_size_fixed);
5902 staticpro (&Qwindow_configuration_change_hook);
5903 Qwindow_configuration_change_hook
5904 = intern ("window-configuration-change-hook");
5906 Qwindowp = intern ("windowp");
5907 staticpro (&Qwindowp);
5909 Qwindow_configuration_p = intern ("window-configuration-p");
5910 staticpro (&Qwindow_configuration_p);
5912 Qwindow_live_p = intern ("window-live-p");
5913 staticpro (&Qwindow_live_p);
5915 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
5916 staticpro (&Qtemp_buffer_show_hook);
5918 staticpro (&Vwindow_list);
5920 minibuf_selected_window = Qnil;
5921 staticpro (&minibuf_selected_window);
5923 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
5924 doc: /* Non-nil means call as function to display a help buffer.
5925 The function is called with one argument, the buffer to be displayed.
5926 Used by `with-output-to-temp-buffer'.
5927 If this function is used, then it must do the entire job of showing
5928 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
5929 Vtemp_buffer_show_function = Qnil;
5931 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
5932 doc: /* If non-nil, function to call to handle `display-buffer'.
5933 It will receive two args, the buffer and a flag which if non-nil means
5934 that the currently selected window is not acceptable.
5935 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
5936 work using this function. */);
5937 Vdisplay_buffer_function = Qnil;
5939 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
5940 doc: /* *If non-nil, `display-buffer' should even the window heights.
5941 If nil, `display-buffer' will leave the window configuration alone. */);
5942 Veven_window_heights = Qt;
5944 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
5945 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
5946 Vminibuf_scroll_window = Qnil;
5948 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
5949 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
5950 If the minibuffer is active, the `minibuffer-scroll-window' mode line
5951 is displayed in the `mode-line' face. */);
5952 mode_line_in_non_selected_windows = 1;
5954 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
5955 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
5956 Vother_window_scroll_buffer = Qnil;
5958 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
5959 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
5960 pop_up_frames = 0;
5962 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
5963 doc: /* *Non-nil means `display-buffer' should reuse frames.
5964 If the buffer in question is already displayed in a frame, raise that frame. */);
5965 display_buffer_reuse_frames = 0;
5967 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
5968 doc: /* Function to call to handle automatic new frame creation.
5969 It is called with no arguments and should return a newly created frame.
5971 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
5972 where `pop-up-frame-alist' would hold the default frame parameters. */);
5973 Vpop_up_frame_function = Qnil;
5975 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
5976 doc: /* *List of buffer names that should have their own special frames.
5977 Displaying a buffer whose name is in this list makes a special frame for it
5978 using `special-display-function'. See also `special-display-regexps'.
5980 An element of the list can be a list instead of just a string.
5981 There are two ways to use a list as an element:
5982 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
5983 In the first case, FRAME-PARAMETERS are used to create the frame.
5984 In the latter case, FUNCTION is called with BUFFER as the first argument,
5985 followed by OTHER-ARGS--it can display BUFFER in any way it likes.
5986 All this is done by the function found in `special-display-function'.
5988 If this variable appears \"not to work\", because you add a name to it
5989 but that buffer still appears in the selected window, look at the
5990 values of `same-window-buffer-names' and `same-window-regexps'.
5991 Those variables take precedence over this one. */);
5992 Vspecial_display_buffer_names = Qnil;
5994 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
5995 doc: /* *List of regexps saying which buffers should have their own special frames.
5996 If a buffer name matches one of these regexps, it gets its own frame.
5997 Displaying a buffer whose name is in this list makes a special frame for it
5998 using `special-display-function'.
6000 An element of the list can be a list instead of just a string.
6001 There are two ways to use a list as an element:
6002 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
6003 In the first case, FRAME-PARAMETERS are used to create the frame.
6004 In the latter case, FUNCTION is called with the buffer as first argument,
6005 followed by OTHER-ARGS--it can display the buffer in any way it likes.
6006 All this is done by the function found in `special-display-function'.
6008 If this variable appears \"not to work\", because you add a regexp to it
6009 but the matching buffers still appear in the selected window, look at the
6010 values of `same-window-buffer-names' and `same-window-regexps'.
6011 Those variables take precedence over this one. */);
6012 Vspecial_display_regexps = Qnil;
6014 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
6015 doc: /* Function to call to make a new frame for a special buffer.
6016 It is called with two arguments, the buffer and optional buffer specific
6017 data, and should return a window displaying that buffer.
6018 The default value normally makes a separate frame for the buffer,
6019 using `special-display-frame-alist' to specify the frame parameters.
6020 But if the buffer specific data includes (same-buffer . t) then the
6021 buffer is displayed in the current selected window.
6022 Otherwise if it includes (same-frame . t) then the buffer is displayed in
6023 a new window in the currently selected frame.
6025 A buffer is special if it is listed in `special-display-buffer-names'
6026 or matches a regexp in `special-display-regexps'. */);
6027 Vspecial_display_function = Qnil;
6029 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
6030 doc: /* *List of buffer names that should appear in the selected window.
6031 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
6032 switches to it in the selected window, rather than making it appear
6033 in some other window.
6035 An element of the list can be a cons cell instead of just a string.
6036 Then the car must be a string, which specifies the buffer name.
6037 This is for compatibility with `special-display-buffer-names';
6038 the cdr of the cons cell is ignored.
6040 See also `same-window-regexps'. */);
6041 Vsame_window_buffer_names = Qnil;
6043 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
6044 doc: /* *List of regexps saying which buffers should appear in the selected window.
6045 If a buffer name matches one of these regexps, then displaying it
6046 using `display-buffer' or `pop-to-buffer' switches to it
6047 in the selected window, rather than making it appear in some other window.
6049 An element of the list can be a cons cell instead of just a string.
6050 Then the car must be a string, which specifies the buffer name.
6051 This is for compatibility with `special-display-buffer-names';
6052 the cdr of the cons cell is ignored.
6054 See also `same-window-buffer-names'. */);
6055 Vsame_window_regexps = Qnil;
6057 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
6058 doc: /* *Non-nil means display-buffer should make new windows. */);
6059 pop_up_windows = 1;
6061 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
6062 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
6063 next_screen_context_lines = 2;
6065 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
6066 doc: /* *display-buffer would prefer to split the largest window if this large.
6067 If there is only one window, it is split regardless of this value. */);
6068 split_height_threshold = 500;
6070 DEFVAR_INT ("window-min-height", &window_min_height,
6071 doc: /* *Delete any window less than this tall (including its mode line). */);
6072 window_min_height = 4;
6074 DEFVAR_INT ("window-min-width", &window_min_width,
6075 doc: /* *Delete any window less than this wide. */);
6076 window_min_width = 10;
6078 DEFVAR_LISP ("scroll-preserve-screen-position",
6079 &Vscroll_preserve_screen_position,
6080 doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged. */);
6081 Vscroll_preserve_screen_position = Qnil;
6083 DEFVAR_LISP ("window-configuration-change-hook",
6084 &Vwindow_configuration_change_hook,
6085 doc: /* Functions to call when window configuration changes.
6086 The selected frame is the one whose configuration has changed. */);
6087 Vwindow_configuration_change_hook = Qnil;
6089 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed,
6090 doc: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
6091 Emacs won't change the size of any window displaying that buffer,
6092 unless you explicitly change the size, or Emacs has no other choice.
6093 This variable automatically becomes buffer-local when set. */);
6094 Fmake_variable_buffer_local (Qwindow_size_fixed);
6095 window_size_fixed = 0;
6097 defsubr (&Sselected_window);
6098 defsubr (&Sminibuffer_window);
6099 defsubr (&Swindow_minibuffer_p);
6100 defsubr (&Swindowp);
6101 defsubr (&Swindow_live_p);
6102 defsubr (&Spos_visible_in_window_p);
6103 defsubr (&Swindow_buffer);
6104 defsubr (&Swindow_height);
6105 defsubr (&Swindow_width);
6106 defsubr (&Swindow_hscroll);
6107 defsubr (&Sset_window_hscroll);
6108 defsubr (&Swindow_redisplay_end_trigger);
6109 defsubr (&Sset_window_redisplay_end_trigger);
6110 defsubr (&Swindow_edges);
6111 defsubr (&Scoordinates_in_window_p);
6112 defsubr (&Swindow_at);
6113 defsubr (&Swindow_point);
6114 defsubr (&Swindow_start);
6115 defsubr (&Swindow_end);
6116 defsubr (&Sset_window_point);
6117 defsubr (&Sset_window_start);
6118 defsubr (&Swindow_dedicated_p);
6119 defsubr (&Sset_window_dedicated_p);
6120 defsubr (&Swindow_display_table);
6121 defsubr (&Sset_window_display_table);
6122 defsubr (&Snext_window);
6123 defsubr (&Sprevious_window);
6124 defsubr (&Sother_window);
6125 defsubr (&Sget_lru_window);
6126 defsubr (&Sget_largest_window);
6127 defsubr (&Sget_buffer_window);
6128 defsubr (&Sdelete_other_windows);
6129 defsubr (&Sdelete_windows_on);
6130 defsubr (&Sreplace_buffer_in_windows);
6131 defsubr (&Sdelete_window);
6132 defsubr (&Sset_window_buffer);
6133 defsubr (&Sselect_window);
6134 defsubr (&Sspecial_display_p);
6135 defsubr (&Ssame_window_p);
6136 defsubr (&Sdisplay_buffer);
6137 defsubr (&Ssplit_window);
6138 defsubr (&Senlarge_window);
6139 defsubr (&Sshrink_window);
6140 defsubr (&Sscroll_up);
6141 defsubr (&Sscroll_down);
6142 defsubr (&Sscroll_left);
6143 defsubr (&Sscroll_right);
6144 defsubr (&Sother_window_for_scrolling);
6145 defsubr (&Sscroll_other_window);
6146 defsubr (&Sminibuffer_selected_window);
6147 defsubr (&Srecenter);
6148 defsubr (&Swindow_text_height);
6149 defsubr (&Smove_to_window_line);
6150 defsubr (&Swindow_configuration_p);
6151 defsubr (&Swindow_configuration_frame);
6152 defsubr (&Sset_window_configuration);
6153 defsubr (&Scurrent_window_configuration);
6154 defsubr (&Ssave_window_excursion);
6155 defsubr (&Sset_window_margins);
6156 defsubr (&Swindow_margins);
6157 defsubr (&Swindow_vscroll);
6158 defsubr (&Sset_window_vscroll);
6159 defsubr (&Scompare_window_configurations);
6160 defsubr (&Swindow_list);
6163 void
6164 keys_of_window ()
6166 initial_define_key (control_x_map, '1', "delete-other-windows");
6167 initial_define_key (control_x_map, '2', "split-window");
6168 initial_define_key (control_x_map, '0', "delete-window");
6169 initial_define_key (control_x_map, 'o', "other-window");
6170 initial_define_key (control_x_map, '^', "enlarge-window");
6171 initial_define_key (control_x_map, '<', "scroll-left");
6172 initial_define_key (control_x_map, '>', "scroll-right");
6174 initial_define_key (global_map, Ctl ('V'), "scroll-up");
6175 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6176 initial_define_key (meta_map, 'v', "scroll-down");
6178 initial_define_key (global_map, Ctl('L'), "recenter");
6179 initial_define_key (meta_map, 'r', "move-to-window-line");