*** empty log message ***
[emacs.git] / src / window.c
blobe88873528c83f574329c8e2692fb4bfb88579a88
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
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 macintosh
48 #include "macterm.h"
49 #endif
51 /* Values returned from coordinates_in_window. */
53 enum window_part
55 ON_NOTHING,
56 ON_TEXT,
57 ON_MODE_LINE,
58 ON_VERTICAL_BORDER,
59 ON_HEADER_LINE,
60 ON_LEFT_FRINGE,
61 ON_RIGHT_FRINGE,
62 ON_LEFT_MARGIN,
63 ON_RIGHT_MARGIN
67 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
68 Lisp_Object Qwindow_size_fixed;
69 extern Lisp_Object Qleft_margin, Qright_margin;
70 extern Lisp_Object Qheight, Qwidth;
72 static int displayed_window_lines P_ ((struct window *));
73 static struct window *decode_window P_ ((Lisp_Object));
74 static Lisp_Object select_window_1 P_ ((Lisp_Object, int));
75 static int count_windows P_ ((struct window *));
76 static int get_leaf_windows P_ ((struct window *, struct window **, int));
77 static void window_scroll P_ ((Lisp_Object, int, int, int));
78 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
79 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
80 static int window_min_size_1 P_ ((struct window *, int));
81 static int window_min_size P_ ((struct window *, int, int, int *));
82 static void size_window P_ ((Lisp_Object, int, int, int));
83 static int freeze_window_start P_ ((struct window *, void *));
84 static int window_fixed_size_p P_ ((struct window *, int, int));
85 static void enlarge_window P_ ((Lisp_Object, int, int, int));
86 static Lisp_Object window_list P_ ((void));
87 static int add_window_to_list P_ ((struct window *, void *));
88 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
89 Lisp_Object));
90 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
91 Lisp_Object, int));
92 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
93 Lisp_Object *));
94 static int foreach_window_1 P_ ((struct window *,
95 int (* fn) (struct window *, void *),
96 void *));
97 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
99 /* The value of `window-size-fixed'. */
101 int window_size_fixed;
103 /* This is the window in which the terminal's cursor should
104 be left when nothing is being done with it. This must
105 always be a leaf window, and its buffer is selected by
106 the top level editing loop at the end of each command.
108 This value is always the same as
109 FRAME_SELECTED_WINDOW (selected_frame). */
111 Lisp_Object selected_window;
113 /* A list of all windows for use by next_window and Fwindow_list.
114 Functions creating or deleting windows should invalidate this cache
115 by setting it to nil. */
117 Lisp_Object Vwindow_list;
119 /* The mini-buffer window of the selected frame.
120 Note that you cannot test for mini-bufferness of an arbitrary window
121 by comparing against this; but you can test for mini-bufferness of
122 the selected window. */
124 Lisp_Object minibuf_window;
126 /* Non-nil means it is the window whose mode line should be
127 shown as the selected window when the minibuffer is selected. */
129 Lisp_Object minibuf_selected_window;
131 /* Non-nil means it is the window for C-M-v to scroll
132 when the mini-buffer is selected. */
134 Lisp_Object Vminibuf_scroll_window;
136 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
138 Lisp_Object Vother_window_scroll_buffer;
140 /* Non-nil means it's function to call to display temp buffers. */
142 Lisp_Object Vtemp_buffer_show_function;
144 /* Non-zero means to use mode-line-inactive face in all windows but the
145 selected-window and the minibuffer-scroll-window when the
146 minibuffer is active. */
147 int mode_line_in_non_selected_windows;
149 /* If a window gets smaller than either of these, it is removed. */
151 EMACS_INT window_min_height;
152 EMACS_INT window_min_width;
154 /* Nonzero implies Fdisplay_buffer should create windows. */
156 int pop_up_windows;
158 /* Nonzero implies make new frames for Fdisplay_buffer. */
160 int pop_up_frames;
162 /* Nonzero means reuse existing frames for displaying buffers. */
164 int display_buffer_reuse_frames;
166 /* Non-nil means use this function instead of default */
168 Lisp_Object Vpop_up_frame_function;
170 /* Function to call to handle Fdisplay_buffer. */
172 Lisp_Object Vdisplay_buffer_function;
174 /* Non-nil means that Fdisplay_buffer should even the heights of windows. */
176 Lisp_Object Veven_window_heights;
178 /* List of buffer *names* for buffers that should have their own frames. */
180 Lisp_Object Vspecial_display_buffer_names;
182 /* List of regexps for buffer names that should have their own frames. */
184 Lisp_Object Vspecial_display_regexps;
186 /* Function to pop up a special frame. */
188 Lisp_Object Vspecial_display_function;
190 /* List of buffer *names* for buffers to appear in selected window. */
192 Lisp_Object Vsame_window_buffer_names;
194 /* List of regexps for buffer names to appear in selected window. */
196 Lisp_Object Vsame_window_regexps;
198 /* Hook run at end of temp_output_buffer_show. */
200 Lisp_Object Qtemp_buffer_show_hook;
202 /* Fdisplay_buffer always splits the largest window
203 if that window is more than this high. */
205 EMACS_INT split_height_threshold;
207 /* Number of lines of continuity in scrolling by screenfuls. */
209 EMACS_INT next_screen_context_lines;
211 /* Incremented for each window created. */
213 static int sequence_number;
215 /* Nonzero after init_window_once has finished. */
217 static int window_initialized;
219 /* Hook to run when window config changes. */
221 Lisp_Object Qwindow_configuration_change_hook;
222 Lisp_Object Vwindow_configuration_change_hook;
224 /* Nonzero means scroll commands try to put point
225 at the same screen height as previously. */
227 Lisp_Object Vscroll_preserve_screen_position;
229 #if 0 /* This isn't used anywhere. */
230 /* Nonzero means we can split a frame even if it is "unsplittable". */
231 static int inhibit_frame_unsplittable;
232 #endif /* 0 */
234 extern EMACS_INT scroll_margin;
236 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
238 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
239 doc: /* Returns t if OBJECT is a window. */)
240 (object)
241 Lisp_Object object;
243 return WINDOWP (object) ? Qt : Qnil;
246 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
247 doc: /* Returns t if OBJECT is a window which is currently visible. */)
248 (object)
249 Lisp_Object object;
251 return WINDOW_LIVE_P (object) ? Qt : Qnil;
254 Lisp_Object
255 make_window ()
257 Lisp_Object val;
258 register struct window *p;
260 p = allocate_window ();
261 XSETFASTINT (p->sequence_number, ++sequence_number);
262 XSETFASTINT (p->left, 0);
263 XSETFASTINT (p->top, 0);
264 XSETFASTINT (p->height, 0);
265 XSETFASTINT (p->width, 0);
266 XSETFASTINT (p->hscroll, 0);
267 XSETFASTINT (p->min_hscroll, 0);
268 p->orig_top = p->orig_height = Qnil;
269 p->start = Fmake_marker ();
270 p->pointm = Fmake_marker ();
271 XSETFASTINT (p->use_time, 0);
272 p->frame = Qnil;
273 p->display_table = Qnil;
274 p->dedicated = Qnil;
275 p->pseudo_window_p = 0;
276 bzero (&p->cursor, sizeof (p->cursor));
277 bzero (&p->last_cursor, sizeof (p->last_cursor));
278 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
279 p->desired_matrix = p->current_matrix = 0;
280 p->phys_cursor_type = -1;
281 p->phys_cursor_width = -1;
282 p->must_be_updated_p = 0;
283 XSETFASTINT (p->window_end_vpos, 0);
284 XSETFASTINT (p->window_end_pos, 0);
285 p->window_end_valid = Qnil;
286 p->vscroll = 0;
287 XSETWINDOW (val, p);
288 XSETFASTINT (p->last_point, 0);
289 p->frozen_window_start_p = 0;
291 Vwindow_list = Qnil;
292 return val;
295 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
296 doc: /* Return the window that the cursor now appears in and commands apply to. */)
299 return selected_window;
302 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
303 doc: /* Return the window used now for minibuffers.
304 If the optional argument FRAME is specified, return the minibuffer window
305 used by that frame. */)
306 (frame)
307 Lisp_Object frame;
309 if (NILP (frame))
310 frame = selected_frame;
311 CHECK_LIVE_FRAME (frame);
312 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
315 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
316 doc: /* Returns non-nil if WINDOW is a minibuffer window. */)
317 (window)
318 Lisp_Object window;
320 struct window *w = decode_window (window);
321 return MINI_WINDOW_P (w) ? Qt : Qnil;
325 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
326 Spos_visible_in_window_p, 0, 3, 0,
327 doc: /* Return t if position POS is currently on the frame in WINDOW.
328 Return nil if that position is scrolled vertically out of view.
329 If a character is only partially visible, nil is returned, unless the
330 optional argument PARTIALLY is non-nil.
331 POS defaults to point in WINDOW; WINDOW defaults to the selected window. */)
332 (pos, window, partially)
333 Lisp_Object pos, window, partially;
335 register struct window *w;
336 register int posint;
337 register struct buffer *buf;
338 struct text_pos top;
339 Lisp_Object in_window;
340 int fully_p;
342 w = decode_window (window);
343 buf = XBUFFER (w->buffer);
344 SET_TEXT_POS_FROM_MARKER (top, w->start);
346 if (!NILP (pos))
348 CHECK_NUMBER_COERCE_MARKER (pos);
349 posint = XINT (pos);
351 else if (w == XWINDOW (selected_window))
352 posint = PT;
353 else
354 posint = XMARKER (w->pointm)->charpos;
356 /* If position is above window start, it's not visible. */
357 if (posint < CHARPOS (top))
358 in_window = Qnil;
359 else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
360 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
361 && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
363 /* If frame is up-to-date, and POSINT is < window end pos, use
364 that info. This doesn't work for POSINT == end pos, because
365 the window end pos is actually the position _after_ the last
366 char in the window. */
367 if (NILP (partially))
369 pos_visible_p (w, posint, &fully_p, NILP (partially));
370 in_window = fully_p ? Qt : Qnil;
372 else
373 in_window = Qt;
375 else if (posint > BUF_ZV (buf))
376 in_window = Qnil;
377 else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
378 /* If window start is out of range, do something reasonable. */
379 in_window = Qnil;
380 else
382 if (pos_visible_p (w, posint, &fully_p, NILP (partially)))
383 in_window = !NILP (partially) || fully_p ? Qt : Qnil;
384 else
385 in_window = Qnil;
388 return in_window;
392 static struct window *
393 decode_window (window)
394 register Lisp_Object window;
396 if (NILP (window))
397 return XWINDOW (selected_window);
399 CHECK_LIVE_WINDOW (window);
400 return XWINDOW (window);
403 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
404 doc: /* Return the buffer that WINDOW is displaying. */)
405 (window)
406 Lisp_Object window;
408 return decode_window (window)->buffer;
411 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
412 doc: /* Return the number of lines in WINDOW (including its mode line). */)
413 (window)
414 Lisp_Object window;
416 return decode_window (window)->height;
419 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
420 doc: /* Return the number of display columns in WINDOW.
421 This is the width that is usable columns available for text in WINDOW.
422 If you want to find out how many columns WINDOW takes up,
423 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))). */)
424 (window)
425 Lisp_Object window;
427 return make_number (window_internal_width (decode_window (window)));
430 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
431 doc: /* Return the number of columns by which WINDOW is scrolled from left margin. */)
432 (window)
433 Lisp_Object window;
435 return decode_window (window)->hscroll;
438 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
439 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
440 NCOL should be zero or positive. */)
441 (window, ncol)
442 Lisp_Object window, ncol;
444 struct window *w = decode_window (window);
445 int hscroll;
447 CHECK_NUMBER (ncol);
448 hscroll = max (0, XINT (ncol));
450 /* Prevent redisplay shortcuts when changing the hscroll. */
451 if (XINT (w->hscroll) != hscroll)
452 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
454 w->hscroll = make_number (hscroll);
455 return ncol;
458 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
459 Swindow_redisplay_end_trigger, 0, 1, 0,
460 doc: /* Return WINDOW's redisplay end trigger value.
461 See `set-window-redisplay-end-trigger' for more information. */)
462 (window)
463 Lisp_Object window;
465 return decode_window (window)->redisplay_end_trigger;
468 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
469 Sset_window_redisplay_end_trigger, 2, 2, 0,
470 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
471 VALUE should be a buffer position (typically a marker) or nil.
472 If it is a buffer position, then if redisplay in WINDOW reaches a position
473 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
474 with two arguments: WINDOW, and the end trigger value.
475 Afterwards the end-trigger value is reset to nil. */)
476 (window, value)
477 register Lisp_Object window, value;
479 register struct window *w;
481 w = decode_window (window);
482 w->redisplay_end_trigger = value;
483 return value;
486 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
487 doc: /* Return a list of the edge coordinates of WINDOW.
488 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
489 RIGHT is one more than the rightmost column used by WINDOW,
490 and BOTTOM is one more than the bottommost row used by WINDOW
491 and its mode-line. */)
492 (window)
493 Lisp_Object window;
495 register struct window *w = decode_window (window);
497 return Fcons (w->left, Fcons (w->top,
498 Fcons (make_number (WINDOW_RIGHT_EDGE (w)),
499 Fcons (make_number (XFASTINT (w->top)
500 + XFASTINT (w->height)),
501 Qnil))));
504 /* Test if the character at column *X, row *Y is within window W.
505 If it is not, return 0;
506 if it is in the window's text area,
507 set *x and *y to its location relative to the upper left corner
508 of the window, and
509 return 1;
510 if it is on the window's modeline, return 2;
511 if it is on the border between the window and its right sibling,
512 return 3.
513 if it is on the window's top line, return 4;
514 if it is in left or right fringe of the window,
515 return 5 or 6, and convert *X and *Y to window-relative coordinates;
516 if it is in the marginal area to the left/right of the window,
517 return 7 or 8, and convert *X and *Y to window-relative coordinates.
519 X and Y are frame relative pixel coordinates. */
521 static enum window_part
522 coordinates_in_window (w, x, y)
523 register struct window *w;
524 register int *x, *y;
526 /* Let's make this a global enum later, instead of using numbers
527 everywhere. */
528 struct frame *f = XFRAME (WINDOW_FRAME (w));
529 int left_x, right_x, top_y, bottom_y;
530 enum window_part part;
531 int ux = CANON_X_UNIT (f);
532 int x0 = XFASTINT (w->left) * ux;
533 int x1 = x0 + XFASTINT (w->width) * ux;
534 /* The width of the area where the vertical line can be dragged.
535 (Between mode lines for instance. */
536 int grabbable_width = ux;
537 int lmargin_width = 0, rmargin_width = 0;
539 if (*x < x0 || *x >= x1)
540 return ON_NOTHING;
542 /* In what's below, we subtract 1 when computing right_x because we
543 want the rightmost pixel, which is given by left_pixel+width-1. */
544 if (w->pseudo_window_p)
546 left_x = 0;
547 right_x = XFASTINT (w->width) * CANON_X_UNIT (f) - 1;
548 top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
549 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
551 else
553 left_x = (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w)
554 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
555 right_x = WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w) - 1;
556 top_y = (WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w)
557 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
558 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
561 /* On the mode line or header line? If it's near the start of
562 the mode or header line of window that's has a horizontal
563 sibling, say it's on the vertical line. That's to be able
564 to resize windows horizontally in case we're using toolkit
565 scroll bars. */
567 if (WINDOW_WANTS_MODELINE_P (w)
568 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
569 && *y < bottom_y)
571 /* We're somewhere on the mode line. We consider the place
572 between mode lines of horizontally adjacent mode lines
573 as the vertical border. If scroll bars on the left,
574 return the right window. */
575 part = ON_MODE_LINE;
577 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
579 if (abs (*x - x0) < grabbable_width)
580 part = ON_VERTICAL_BORDER;
582 else if (!WINDOW_RIGHTMOST_P (w) && abs (*x - x1) < grabbable_width)
583 part = ON_VERTICAL_BORDER;
585 else if (WINDOW_WANTS_HEADER_LINE_P (w)
586 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
587 && *y >= top_y)
589 part = ON_HEADER_LINE;
591 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
593 if (abs (*x - x0) < grabbable_width)
594 part = ON_VERTICAL_BORDER;
596 else if (!WINDOW_RIGHTMOST_P (w) && abs (*x - x1) < grabbable_width)
597 part = ON_VERTICAL_BORDER;
599 /* Outside anything interesting? */
600 else if (*y < top_y
601 || *y >= bottom_y
602 || *x < (left_x
603 - FRAME_LEFT_FRINGE_WIDTH (f)
604 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * ux)
605 || *x > (right_x
606 + FRAME_RIGHT_FRINGE_WIDTH (f)
607 + FRAME_RIGHT_SCROLL_BAR_WIDTH (f) * ux))
609 part = ON_NOTHING;
611 else if (FRAME_WINDOW_P (f))
613 if (!w->pseudo_window_p
614 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)
615 && !WINDOW_RIGHTMOST_P (w)
616 && (abs (*x - right_x - FRAME_RIGHT_FRINGE_WIDTH (f)) < grabbable_width))
618 part = ON_VERTICAL_BORDER;
620 else if (*x < left_x || *x > right_x)
622 /* Other lines than the mode line don't include fringes and
623 scroll bars on the left. */
625 /* Convert X and Y to window-relative pixel coordinates. */
626 *x -= left_x;
627 *y -= top_y;
628 part = *x < left_x ? ON_LEFT_FRINGE : ON_RIGHT_FRINGE;
630 else
632 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
633 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
634 /* You can never be on a margin area if its width is zero. */
635 if (lmargin_width
636 && *x <= window_box_right (w, LEFT_MARGIN_AREA))
637 part = ON_LEFT_MARGIN;
638 else if (rmargin_width
639 && *x >= window_box_left (w, RIGHT_MARGIN_AREA))
640 part = ON_RIGHT_MARGIN;
641 else
643 part = ON_TEXT;
644 *x -= left_x;
645 *y -= top_y;
649 else
651 /* Need to say "*x > right_x" rather than >=, since on character
652 terminals, the vertical line's x coordinate is right_x. */
653 if (*x < left_x || *x > right_x)
655 /* Other lines than the mode line don't include fringes and
656 scroll bars on the left. */
658 /* Convert X and Y to window-relative pixel coordinates. */
659 *x -= left_x;
660 *y -= top_y;
661 part = *x < left_x ? ON_LEFT_FRINGE : ON_RIGHT_FRINGE;
663 /* Here, too, "*x > right_x" is because of character terminals. */
664 else if (!w->pseudo_window_p
665 && !WINDOW_RIGHTMOST_P (w)
666 && *x > right_x - ux)
668 /* On the border on the right side of the window? Assume that
669 this area begins at RIGHT_X minus a canonical char width. */
670 part = ON_VERTICAL_BORDER;
672 else
674 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
675 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
676 /* You can never be on a margin area if its width is zero.
677 This is especially important for character terminals. */
678 if (lmargin_width
679 && *x <= window_box_right (w, LEFT_MARGIN_AREA))
680 part = ON_LEFT_MARGIN;
681 else if (rmargin_width
682 && *x >= window_box_left (w, RIGHT_MARGIN_AREA))
683 part = ON_RIGHT_MARGIN;
684 else
686 part = ON_TEXT;
687 /* Convert X and Y to window-relative pixel coordinates. */
688 *x -= left_x;
689 *y -= top_y;
694 return part;
698 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
699 Scoordinates_in_window_p, 2, 2, 0,
700 doc: /* Return non-nil if COORDINATES are in WINDOW.
701 COORDINATES is a cons of the form (X . Y), X and Y being distances
702 measured in characters from the upper-left corner of the frame.
703 \(0 . 0) denotes the character in the upper left corner of the
704 frame.
705 If COORDINATES are in the text portion of WINDOW,
706 the coordinates relative to the window are returned.
707 If they are in the mode line of WINDOW, `mode-line' is returned.
708 If they are in the top mode line of WINDOW, `header-line' is returned.
709 If they are in the left fringe of WINDOW, `left-fringe' is returned.
710 If they are in the right fringe of WINDOW, `right-fringe' is returned.
711 If they are on the border between WINDOW and its right sibling,
712 `vertical-line' is returned.
713 If they are in the windows's left or right marginal areas, `left-margin'\n\
714 or `right-margin' is returned. */)
715 (coordinates, window)
716 register Lisp_Object coordinates, window;
718 struct window *w;
719 struct frame *f;
720 int x, y;
721 Lisp_Object lx, ly;
723 CHECK_LIVE_WINDOW (window);
724 w = XWINDOW (window);
725 f = XFRAME (w->frame);
726 CHECK_CONS (coordinates);
727 lx = Fcar (coordinates);
728 ly = Fcdr (coordinates);
729 CHECK_NUMBER_OR_FLOAT (lx);
730 CHECK_NUMBER_OR_FLOAT (ly);
731 x = PIXEL_X_FROM_CANON_X (f, lx);
732 y = PIXEL_Y_FROM_CANON_Y (f, ly);
734 switch (coordinates_in_window (w, &x, &y))
736 case ON_NOTHING:
737 return Qnil;
739 case ON_TEXT:
740 /* X and Y are now window relative pixel coordinates. Convert
741 them to canonical char units before returning them. */
742 return Fcons (CANON_X_FROM_PIXEL_X (f, x),
743 CANON_Y_FROM_PIXEL_Y (f, y));
745 case ON_MODE_LINE:
746 return Qmode_line;
748 case ON_VERTICAL_BORDER:
749 return Qvertical_line;
751 case ON_HEADER_LINE:
752 return Qheader_line;
754 case ON_LEFT_FRINGE:
755 return Qleft_fringe;
757 case ON_RIGHT_FRINGE:
758 return Qright_fringe;
760 case ON_LEFT_MARGIN:
761 return Qleft_margin;
763 case ON_RIGHT_MARGIN:
764 return Qright_margin;
766 default:
767 abort ();
772 /* Callback for foreach_window, used in window_from_coordinates.
773 Check if window W contains coordinates specified by USER_DATA which
774 is actually a pointer to a struct check_window_data CW.
776 Check if window W contains coordinates *CW->x and *CW->y. If it
777 does, return W in *CW->window, as Lisp_Object, and return in
778 *CW->part the part of the window under coordinates *X,*Y. Return
779 zero from this function to stop iterating over windows. */
781 struct check_window_data
783 Lisp_Object *window;
784 int *x, *y, *part;
787 static int
788 check_window_containing (w, user_data)
789 struct window *w;
790 void *user_data;
792 struct check_window_data *cw = (struct check_window_data *) user_data;
793 enum window_part found;
794 int continue_p = 1;
796 found = coordinates_in_window (w, cw->x, cw->y);
797 if (found != ON_NOTHING)
799 *cw->part = found - 1;
800 XSETWINDOW (*cw->window, w);
801 continue_p = 0;
804 return continue_p;
808 /* Find the window containing frame-relative pixel position X/Y and
809 return it as a Lisp_Object. If X, Y is on the window's modeline,
810 set *PART to 1; if it is on the separating line between the window
811 and its right sibling, set it to 2; otherwise set it to 0. If
812 there is no window under X, Y return nil and leave *PART
813 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
815 This function was previously implemented with a loop cycling over
816 windows with Fnext_window, and starting with the frame's selected
817 window. It turned out that this doesn't work with an
818 implementation of next_window using Vwindow_list, because
819 FRAME_SELECTED_WINDOW (F) is not always contained in the window
820 tree of F when this function is called asynchronously from
821 note_mouse_highlight. The original loop didn't terminate in this
822 case. */
824 Lisp_Object
825 window_from_coordinates (f, x, y, part, tool_bar_p)
826 struct frame *f;
827 int x, y;
828 int *part;
829 int tool_bar_p;
831 Lisp_Object window;
832 struct check_window_data cw;
834 window = Qnil;
835 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
836 foreach_window (f, check_window_containing, &cw);
838 /* If not found above, see if it's in the tool bar window, if a tool
839 bar exists. */
840 if (NILP (window)
841 && tool_bar_p
842 && WINDOWP (f->tool_bar_window)
843 && XINT (XWINDOW (f->tool_bar_window)->height) > 0
844 && (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
845 != ON_NOTHING))
847 *part = 0;
848 window = f->tool_bar_window;
851 return window;
854 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
855 doc: /* Return window containing coordinates X and Y on FRAME.
856 If omitted, FRAME defaults to the currently selected frame.
857 The top left corner of the frame is considered to be row 0,
858 column 0. */)
859 (x, y, frame)
860 Lisp_Object x, y, frame;
862 int part;
863 struct frame *f;
865 if (NILP (frame))
866 frame = selected_frame;
867 CHECK_LIVE_FRAME (frame);
868 f = XFRAME (frame);
870 /* Check that arguments are integers or floats. */
871 CHECK_NUMBER_OR_FLOAT (x);
872 CHECK_NUMBER_OR_FLOAT (y);
874 return window_from_coordinates (f,
875 PIXEL_X_FROM_CANON_X (f, x),
876 PIXEL_Y_FROM_CANON_Y (f, y),
877 &part, 0);
880 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
881 doc: /* Return current value of point in WINDOW.
882 For a nonselected window, this is the value point would have
883 if that window were selected.
885 Note that, when WINDOW is the selected window and its buffer
886 is also currently selected, the value returned is the same as (point).
887 It would be more strictly correct to return the `top-level' value
888 of point, outside of any save-excursion forms.
889 But that is hard to define. */)
890 (window)
891 Lisp_Object window;
893 register struct window *w = decode_window (window);
895 if (w == XWINDOW (selected_window)
896 && current_buffer == XBUFFER (w->buffer))
897 return Fpoint ();
898 return Fmarker_position (w->pointm);
901 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
902 doc: /* Return position at which display currently starts in WINDOW.
903 This is updated by redisplay or by calling `set-window-start'. */)
904 (window)
905 Lisp_Object window;
907 return Fmarker_position (decode_window (window)->start);
910 /* This is text temporarily removed from the doc string below.
912 This function returns nil if the position is not currently known.
913 That happens when redisplay is preempted and doesn't finish.
914 If in that case you want to compute where the end of the window would
915 have been if redisplay had finished, do this:
916 (save-excursion
917 (goto-char (window-start window))
918 (vertical-motion (1- (window-height window)) window)
919 (point))") */
921 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
922 doc: /* Return position at which display currently ends in WINDOW.
923 This is updated by redisplay, when it runs to completion.
924 Simply changing the buffer text or setting `window-start'
925 does not update this value.
926 If UPDATE is non-nil, compute the up-to-date position
927 if it isn't already recorded. */)
928 (window, update)
929 Lisp_Object window, update;
931 Lisp_Object value;
932 struct window *w = decode_window (window);
933 Lisp_Object buf;
935 buf = w->buffer;
936 CHECK_BUFFER (buf);
938 #if 0 /* This change broke some things. We should make it later. */
939 /* If we don't know the end position, return nil.
940 The user can compute it with vertical-motion if he wants to.
941 It would be nicer to do it automatically,
942 but that's so slow that it would probably bother people. */
943 if (NILP (w->window_end_valid))
944 return Qnil;
945 #endif
947 if (! NILP (update)
948 && ! (! NILP (w->window_end_valid)
949 && XFASTINT (w->last_modified) >= MODIFF))
951 struct text_pos startp;
952 struct it it;
953 struct buffer *old_buffer = NULL, *b = XBUFFER (buf);
955 /* In case W->start is out of the range, use something
956 reasonable. This situation occured when loading a file with
957 `-l' containing a call to `rmail' with subsequent other
958 commands. At the end, W->start happened to be BEG, while
959 rmail had already narrowed the buffer. */
960 if (XMARKER (w->start)->charpos < BEGV)
961 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
962 else if (XMARKER (w->start)->charpos > ZV)
963 SET_TEXT_POS (startp, ZV, ZV_BYTE);
964 else
965 SET_TEXT_POS_FROM_MARKER (startp, w->start);
967 /* Cannot use Fvertical_motion because that function doesn't
968 cope with variable-height lines. */
969 if (b != current_buffer)
971 old_buffer = current_buffer;
972 set_buffer_internal (b);
975 start_display (&it, w, startp);
976 move_it_vertically (&it, window_box_height (w));
977 if (it.current_y < it.last_visible_y)
978 move_it_past_eol (&it);
979 value = make_number (IT_CHARPOS (it));
981 if (old_buffer)
982 set_buffer_internal (old_buffer);
984 else
985 XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
987 return value;
990 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
991 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer. */)
992 (window, pos)
993 Lisp_Object window, pos;
995 register struct window *w = decode_window (window);
997 CHECK_NUMBER_COERCE_MARKER (pos);
998 if (w == XWINDOW (selected_window)
999 && XBUFFER (w->buffer) == current_buffer)
1000 Fgoto_char (pos);
1001 else
1002 set_marker_restricted (w->pointm, pos, w->buffer);
1004 /* We have to make sure that redisplay updates the window to show
1005 the new value of point. */
1006 if (!EQ (window, selected_window))
1007 ++windows_or_buffers_changed;
1009 return pos;
1012 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1013 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1014 Optional third arg NOFORCE non-nil inhibits next redisplay
1015 from overriding motion of point in order to display at this exact start. */)
1016 (window, pos, noforce)
1017 Lisp_Object window, pos, noforce;
1019 register struct window *w = decode_window (window);
1021 CHECK_NUMBER_COERCE_MARKER (pos);
1022 set_marker_restricted (w->start, pos, w->buffer);
1023 /* this is not right, but much easier than doing what is right. */
1024 w->start_at_line_beg = Qnil;
1025 if (NILP (noforce))
1026 w->force_start = Qt;
1027 w->update_mode_line = Qt;
1028 XSETFASTINT (w->last_modified, 0);
1029 XSETFASTINT (w->last_overlay_modified, 0);
1030 if (!EQ (window, selected_window))
1031 windows_or_buffers_changed++;
1033 return pos;
1036 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1037 1, 1, 0,
1038 doc: /* Return WINDOW's dedicated object, usually t or nil.
1039 See also `set-window-dedicated-p'. */)
1040 (window)
1041 Lisp_Object window;
1043 return decode_window (window)->dedicated;
1046 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1047 Sset_window_dedicated_p, 2, 2, 0,
1048 doc: /* Control whether WINDOW is dedicated to the buffer it displays.
1049 If it is dedicated, Emacs will not automatically change
1050 which buffer appears in it.
1051 The second argument is the new value for the dedication flag;
1052 non-nil means yes. */)
1053 (window, arg)
1054 Lisp_Object window, arg;
1056 register struct window *w = decode_window (window);
1058 if (NILP (arg))
1059 w->dedicated = Qnil;
1060 else
1061 w->dedicated = Qt;
1063 return w->dedicated;
1066 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1067 0, 1, 0,
1068 doc: /* Return the display-table that WINDOW is using. */)
1069 (window)
1070 Lisp_Object window;
1072 return decode_window (window)->display_table;
1075 /* Get the display table for use on window W. This is either W's
1076 display table or W's buffer's display table. Ignore the specified
1077 tables if they are not valid; if no valid table is specified,
1078 return 0. */
1080 struct Lisp_Char_Table *
1081 window_display_table (w)
1082 struct window *w;
1084 struct Lisp_Char_Table *dp = NULL;
1086 if (DISP_TABLE_P (w->display_table))
1087 dp = XCHAR_TABLE (w->display_table);
1088 else if (BUFFERP (w->buffer))
1090 struct buffer *b = XBUFFER (w->buffer);
1092 if (DISP_TABLE_P (b->display_table))
1093 dp = XCHAR_TABLE (b->display_table);
1094 else if (DISP_TABLE_P (Vstandard_display_table))
1095 dp = XCHAR_TABLE (Vstandard_display_table);
1098 return dp;
1101 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1102 doc: /* Set WINDOW's display-table to TABLE. */)
1103 (window, table)
1104 register Lisp_Object window, table;
1106 register struct window *w;
1108 w = decode_window (window);
1109 w->display_table = table;
1110 return table;
1113 /* Record info on buffer window w is displaying
1114 when it is about to cease to display that buffer. */
1115 static void
1116 unshow_buffer (w)
1117 register struct window *w;
1119 Lisp_Object buf;
1120 struct buffer *b;
1122 buf = w->buffer;
1123 b = XBUFFER (buf);
1124 if (b != XMARKER (w->pointm)->buffer)
1125 abort ();
1127 #if 0
1128 if (w == XWINDOW (selected_window)
1129 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1130 /* Do this except when the selected window's buffer
1131 is being removed from some other window. */
1132 #endif
1133 /* last_window_start records the start position that this buffer
1134 had in the last window to be disconnected from it.
1135 Now that this statement is unconditional,
1136 it is possible for the buffer to be displayed in the
1137 selected window, while last_window_start reflects another
1138 window which was recently showing the same buffer.
1139 Some people might say that might be a good thing. Let's see. */
1140 b->last_window_start = marker_position (w->start);
1142 /* Point in the selected window's buffer
1143 is actually stored in that buffer, and the window's pointm isn't used.
1144 So don't clobber point in that buffer. */
1145 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1146 /* This line helps to fix Horsley's testbug.el bug. */
1147 && !(WINDOWP (b->last_selected_window)
1148 && w != XWINDOW (b->last_selected_window)
1149 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1150 temp_set_point_both (b,
1151 clip_to_bounds (BUF_BEGV (b),
1152 XMARKER (w->pointm)->charpos,
1153 BUF_ZV (b)),
1154 clip_to_bounds (BUF_BEGV_BYTE (b),
1155 marker_byte_position (w->pointm),
1156 BUF_ZV_BYTE (b)));
1158 if (WINDOWP (b->last_selected_window)
1159 && w == XWINDOW (b->last_selected_window))
1160 b->last_selected_window = Qnil;
1163 /* Put replacement into the window structure in place of old. */
1164 static void
1165 replace_window (old, replacement)
1166 Lisp_Object old, replacement;
1168 register Lisp_Object tem;
1169 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1171 /* If OLD is its frame's root_window, then replacement is the new
1172 root_window for that frame. */
1174 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1175 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1177 p->left = o->left;
1178 p->top = o->top;
1179 p->width = o->width;
1180 p->height = o->height;
1181 p->desired_matrix = p->current_matrix = 0;
1182 p->vscroll = 0;
1183 bzero (&p->cursor, sizeof (p->cursor));
1184 bzero (&p->last_cursor, sizeof (p->last_cursor));
1185 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1186 p->phys_cursor_type = -1;
1187 p->phys_cursor_width = -1;
1188 p->must_be_updated_p = 0;
1189 p->pseudo_window_p = 0;
1190 XSETFASTINT (p->window_end_vpos, 0);
1191 XSETFASTINT (p->window_end_pos, 0);
1192 p->window_end_valid = Qnil;
1193 p->frozen_window_start_p = 0;
1194 p->orig_top = p->orig_height = Qnil;
1196 p->next = tem = o->next;
1197 if (!NILP (tem))
1198 XWINDOW (tem)->prev = replacement;
1200 p->prev = tem = o->prev;
1201 if (!NILP (tem))
1202 XWINDOW (tem)->next = replacement;
1204 p->parent = tem = o->parent;
1205 if (!NILP (tem))
1207 if (EQ (XWINDOW (tem)->vchild, old))
1208 XWINDOW (tem)->vchild = replacement;
1209 if (EQ (XWINDOW (tem)->hchild, old))
1210 XWINDOW (tem)->hchild = replacement;
1213 /*** Here, if replacement is a vertical combination
1214 and so is its new parent, we should make replacement's
1215 children be children of that parent instead. ***/
1218 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1219 doc: /* Remove WINDOW from the display. Default is selected window. */)
1220 (window)
1221 register Lisp_Object window;
1223 delete_window (window);
1225 if (! NILP (Vwindow_configuration_change_hook)
1226 && ! NILP (Vrun_hooks))
1227 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1229 return Qnil;
1232 void
1233 delete_window (window)
1234 register Lisp_Object window;
1236 register Lisp_Object tem, parent, sib;
1237 register struct window *p;
1238 register struct window *par;
1239 struct frame *f;
1241 /* Because this function is called by other C code on non-leaf
1242 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1243 so we can't decode_window here. */
1244 if (NILP (window))
1245 window = selected_window;
1246 else
1247 CHECK_WINDOW (window);
1248 p = XWINDOW (window);
1250 /* It's okay to delete an already-deleted window. */
1251 if (NILP (p->buffer)
1252 && NILP (p->hchild)
1253 && NILP (p->vchild))
1254 return;
1256 parent = p->parent;
1257 if (NILP (parent))
1258 error ("Attempt to delete minibuffer or sole ordinary window");
1259 par = XWINDOW (parent);
1261 windows_or_buffers_changed++;
1262 Vwindow_list = Qnil;
1263 f = XFRAME (WINDOW_FRAME (p));
1264 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
1266 /* Are we trying to delete any frame's selected window? */
1268 Lisp_Object swindow, pwindow;
1270 /* See if the frame's selected window is either WINDOW
1271 or any subwindow of it, by finding all that window's parents
1272 and comparing each one with WINDOW. */
1273 swindow = FRAME_SELECTED_WINDOW (f);
1275 while (1)
1277 pwindow = swindow;
1278 while (!NILP (pwindow))
1280 if (EQ (window, pwindow))
1281 break;
1282 pwindow = XWINDOW (pwindow)->parent;
1285 /* If the window being deleted is not a parent of SWINDOW,
1286 then SWINDOW is ok as the new selected window. */
1287 if (!EQ (window, pwindow))
1288 break;
1289 /* Otherwise, try another window for SWINDOW. */
1290 swindow = Fnext_window (swindow, Qlambda, Qnil);;
1292 /* If we get back to the frame's selected window,
1293 it means there was no acceptable alternative,
1294 so we cannot delete. */
1295 if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1296 error ("Cannot delete window");
1299 /* If we need to change SWINDOW, do it. */
1300 if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
1302 /* If we're about to delete the selected window on the
1303 selected frame, then we should use Fselect_window to select
1304 the new window. On the other hand, if we're about to
1305 delete the selected window on any other frame, we shouldn't do
1306 anything but set the frame's selected_window slot. */
1307 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
1308 Fselect_window (swindow);
1309 else
1310 FRAME_SELECTED_WINDOW (f) = swindow;
1314 tem = p->buffer;
1315 /* tem is null for dummy parent windows
1316 (which have inferiors but not any contents themselves) */
1317 if (!NILP (tem))
1319 unshow_buffer (p);
1320 unchain_marker (p->pointm);
1321 unchain_marker (p->start);
1324 /* Free window glyph matrices. It is sure that they are allocated
1325 again when ADJUST_GLYPHS is called. Block input so that expose
1326 events and other events that access glyph matrices are not
1327 processed while we are changing them. */
1328 BLOCK_INPUT;
1329 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
1331 tem = p->next;
1332 if (!NILP (tem))
1333 XWINDOW (tem)->prev = p->prev;
1335 tem = p->prev;
1336 if (!NILP (tem))
1337 XWINDOW (tem)->next = p->next;
1339 if (EQ (window, par->hchild))
1340 par->hchild = p->next;
1341 if (EQ (window, par->vchild))
1342 par->vchild = p->next;
1344 /* Find one of our siblings to give our space to. */
1345 sib = p->prev;
1346 if (NILP (sib))
1348 /* If p gives its space to its next sibling, that sibling needs
1349 to have its top/left side pulled back to where p's is.
1350 set_window_{height,width} will re-position the sibling's
1351 children. */
1352 sib = p->next;
1353 XWINDOW (sib)->top = p->top;
1354 XWINDOW (sib)->left = p->left;
1357 /* Stretch that sibling. */
1358 if (!NILP (par->vchild))
1359 set_window_height (sib,
1360 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
1362 if (!NILP (par->hchild))
1363 set_window_width (sib,
1364 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
1367 /* If parent now has only one child,
1368 put the child into the parent's place. */
1369 tem = par->hchild;
1370 if (NILP (tem))
1371 tem = par->vchild;
1372 if (NILP (XWINDOW (tem)->next))
1373 replace_window (parent, tem);
1375 /* Since we may be deleting combination windows, we must make sure that
1376 not only p but all its children have been marked as deleted. */
1377 if (! NILP (p->hchild))
1378 delete_all_subwindows (XWINDOW (p->hchild));
1379 else if (! NILP (p->vchild))
1380 delete_all_subwindows (XWINDOW (p->vchild));
1382 /* Mark this window as deleted. */
1383 p->buffer = p->hchild = p->vchild = Qnil;
1385 /* Adjust glyph matrices. */
1386 adjust_glyphs (f);
1387 UNBLOCK_INPUT;
1392 /***********************************************************************
1393 Window List
1394 ***********************************************************************/
1396 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1397 pointer. This is a callback function for foreach_window, used in
1398 function window_list. */
1400 static int
1401 add_window_to_list (w, user_data)
1402 struct window *w;
1403 void *user_data;
1405 Lisp_Object *list = (Lisp_Object *) user_data;
1406 Lisp_Object window;
1407 XSETWINDOW (window, w);
1408 *list = Fcons (window, *list);
1409 return 1;
1413 /* Return a list of all windows, for use by next_window. If
1414 Vwindow_list is a list, return that list. Otherwise, build a new
1415 list, cache it in Vwindow_list, and return that. */
1417 static Lisp_Object
1418 window_list ()
1420 if (!CONSP (Vwindow_list))
1422 Lisp_Object tail;
1424 Vwindow_list = Qnil;
1425 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1427 Lisp_Object args[2];
1429 /* We are visiting windows in canonical order, and add
1430 new windows at the front of args[1], which means we
1431 have to reverse this list at the end. */
1432 args[1] = Qnil;
1433 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1434 args[0] = Vwindow_list;
1435 args[1] = Fnreverse (args[1]);
1436 Vwindow_list = Fnconc (2, args);
1440 return Vwindow_list;
1444 /* Value is non-zero if WINDOW satisfies the constraints given by
1445 OWINDOW, MINIBUF and ALL_FRAMES.
1447 MINIBUF t means WINDOW may be minibuffer windows.
1448 `lambda' means WINDOW may not be a minibuffer window.
1449 a window means a specific minibuffer window
1451 ALL_FRAMES t means search all frames,
1452 nil means search just current frame,
1453 `visible' means search just visible frames,
1454 0 means search visible and iconified frames,
1455 a window means search the frame that window belongs to,
1456 a frame means consider windows on that frame, only. */
1458 static int
1459 candidate_window_p (window, owindow, minibuf, all_frames)
1460 Lisp_Object window, owindow, minibuf, all_frames;
1462 struct window *w = XWINDOW (window);
1463 struct frame *f = XFRAME (w->frame);
1464 int candidate_p = 1;
1466 if (!BUFFERP (w->buffer))
1467 candidate_p = 0;
1468 else if (MINI_WINDOW_P (w)
1469 && (EQ (minibuf, Qlambda)
1470 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1472 /* If MINIBUF is `lambda' don't consider any mini-windows.
1473 If it is a window, consider only that one. */
1474 candidate_p = 0;
1476 else if (EQ (all_frames, Qt))
1477 candidate_p = 1;
1478 else if (NILP (all_frames))
1480 xassert (WINDOWP (owindow));
1481 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1483 else if (EQ (all_frames, Qvisible))
1485 FRAME_SAMPLE_VISIBILITY (f);
1486 candidate_p = FRAME_VISIBLE_P (f);
1488 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1490 FRAME_SAMPLE_VISIBILITY (f);
1491 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1493 else if (WINDOWP (all_frames))
1494 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1495 || EQ (XWINDOW (all_frames)->frame, w->frame)
1496 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1497 else if (FRAMEP (all_frames))
1498 candidate_p = EQ (all_frames, w->frame);
1500 return candidate_p;
1504 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1505 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1506 ALL_FRAMES. */
1508 static void
1509 decode_next_window_args (window, minibuf, all_frames)
1510 Lisp_Object *window, *minibuf, *all_frames;
1512 if (NILP (*window))
1513 *window = selected_window;
1514 else
1515 CHECK_LIVE_WINDOW (*window);
1517 /* MINIBUF nil may or may not include minibuffers. Decide if it
1518 does. */
1519 if (NILP (*minibuf))
1520 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1521 else if (!EQ (*minibuf, Qt))
1522 *minibuf = Qlambda;
1524 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1525 => count none of them, or a specific minibuffer window (the
1526 active one) to count. */
1528 /* ALL_FRAMES nil doesn't specify which frames to include. */
1529 if (NILP (*all_frames))
1530 *all_frames = (!EQ (*minibuf, Qlambda)
1531 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1532 : Qnil);
1533 else if (EQ (*all_frames, Qvisible))
1535 else if (XFASTINT (*all_frames) == 0)
1537 else if (FRAMEP (*all_frames))
1539 else if (!EQ (*all_frames, Qt))
1540 *all_frames = Qnil;
1542 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1543 search just current frame, `visible' meaning search just visible
1544 frames, 0 meaning search visible and iconified frames, or a
1545 window, meaning search the frame that window belongs to, or a
1546 frame, meaning consider windows on that frame, only. */
1550 /* Return the next or previous window of WINDOW in canonical ordering
1551 of windows. NEXT_P non-zero means return the next window. See the
1552 documentation string of next-window for the meaning of MINIBUF and
1553 ALL_FRAMES. */
1555 static Lisp_Object
1556 next_window (window, minibuf, all_frames, next_p)
1557 Lisp_Object window, minibuf, all_frames;
1558 int next_p;
1560 decode_next_window_args (&window, &minibuf, &all_frames);
1562 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1563 return the first window on the frame. */
1564 if (FRAMEP (all_frames)
1565 && !EQ (all_frames, XWINDOW (window)->frame))
1566 return Fframe_first_window (all_frames);
1568 if (next_p)
1570 Lisp_Object list;
1572 /* Find WINDOW in the list of all windows. */
1573 list = Fmemq (window, window_list ());
1575 /* Scan forward from WINDOW to the end of the window list. */
1576 if (CONSP (list))
1577 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1578 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1579 break;
1581 /* Scan from the start of the window list up to WINDOW. */
1582 if (!CONSP (list))
1583 for (list = Vwindow_list;
1584 CONSP (list) && !EQ (XCAR (list), window);
1585 list = XCDR (list))
1586 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1587 break;
1589 if (CONSP (list))
1590 window = XCAR (list);
1592 else
1594 Lisp_Object candidate, list;
1596 /* Scan through the list of windows for candidates. If there are
1597 candidate windows in front of WINDOW, the last one of these
1598 is the one we want. If there are candidates following WINDOW
1599 in the list, again the last one of these is the one we want. */
1600 candidate = Qnil;
1601 for (list = window_list (); CONSP (list); list = XCDR (list))
1603 if (EQ (XCAR (list), window))
1605 if (WINDOWP (candidate))
1606 break;
1608 else if (candidate_window_p (XCAR (list), window, minibuf,
1609 all_frames))
1610 candidate = XCAR (list);
1613 if (WINDOWP (candidate))
1614 window = candidate;
1617 return window;
1621 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1622 doc: /* Return next window after WINDOW in canonical ordering of windows.
1623 If omitted, WINDOW defaults to the selected window.
1625 Optional second arg MINIBUF t means count the minibuffer window even
1626 if not active. MINIBUF nil or omitted means count the minibuffer iff
1627 it is active. MINIBUF neither t nor nil means not to count the
1628 minibuffer even if it is active.
1630 Several frames may share a single minibuffer; if the minibuffer
1631 counts, all windows on all frames that share that minibuffer count
1632 too. Therefore, `next-window' can be used to iterate through the
1633 set of windows even when the minibuffer is on another frame. If the
1634 minibuffer does not count, only windows from WINDOW's frame count.
1636 Optional third arg ALL-FRAMES t means include windows on all frames.
1637 ALL-FRAMES nil or omitted means cycle within the frames as specified
1638 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1639 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1640 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1641 Anything else means restrict to WINDOW's frame.
1643 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1644 `next-window' to iterate through the entire cycle of acceptable
1645 windows, eventually ending up back at the window you started with.
1646 `previous-window' traverses the same cycle, in the reverse order. */)
1647 (window, minibuf, all_frames)
1648 Lisp_Object window, minibuf, all_frames;
1650 return next_window (window, minibuf, all_frames, 1);
1654 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1655 doc: /* Return the window preceding WINDOW in canonical ordering of windows.
1656 If omitted, WINDOW defaults to the selected window.
1658 Optional second arg MINIBUF t means count the minibuffer window even
1659 if not active. MINIBUF nil or omitted means count the minibuffer iff
1660 it is active. MINIBUF neither t nor nil means not to count the
1661 minibuffer even if it is active.
1663 Several frames may share a single minibuffer; if the minibuffer
1664 counts, all windows on all frames that share that minibuffer count
1665 too. Therefore, `previous-window' can be used to iterate through
1666 the set of windows even when the minibuffer is on another frame. If
1667 the minibuffer does not count, only windows from WINDOW's frame count
1669 Optional third arg ALL-FRAMES t means include windows on all frames.
1670 ALL-FRAMES nil or omitted means cycle within the frames as specified
1671 above. ALL-FRAMES = `visible' means include windows on all visible frames.
1672 ALL-FRAMES = 0 means include windows on all visible and iconified frames.
1673 If ALL-FRAMES is a frame, restrict search to windows on that frame.
1674 Anything else means restrict to WINDOW's frame.
1676 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
1677 `previous-window' to iterate through the entire cycle of acceptable
1678 windows, eventually ending up back at the window you started with.
1679 `next-window' traverses the same cycle, in the reverse order. */)
1680 (window, minibuf, all_frames)
1681 Lisp_Object window, minibuf, all_frames;
1683 return next_window (window, minibuf, all_frames, 0);
1687 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1688 doc: /* Select the ARG'th different window on this frame.
1689 All windows on current frame are arranged in a cyclic order.
1690 This command selects the window ARG steps away in that order.
1691 A negative ARG moves in the opposite order. If the optional second
1692 argument ALL_FRAMES is non-nil, cycle through all frames. */)
1693 (arg, all_frames)
1694 Lisp_Object arg, all_frames;
1696 Lisp_Object window;
1697 int i;
1699 CHECK_NUMBER (arg);
1700 window = selected_window;
1702 for (i = XINT (arg); i > 0; --i)
1703 window = Fnext_window (window, Qnil, all_frames);
1704 for (; i < 0; ++i)
1705 window = Fprevious_window (window, Qnil, all_frames);
1707 Fselect_window (window);
1708 return Qnil;
1712 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
1713 doc: /* Return a list of windows on FRAME, starting with WINDOW.
1714 FRAME nil or omitted means use the selected frame.
1715 WINDOW nil or omitted means use the selected window.
1716 MINIBUF t means include the minibuffer window, even if it isn't active.
1717 MINIBUF nil or omitted means include the minibuffer window only
1718 if it's active.
1719 MINIBUF neither nil nor t means never include the minibuffer window. */)
1720 (frame, minibuf, window)
1721 Lisp_Object frame, minibuf, window;
1723 if (NILP (window))
1724 window = selected_window;
1725 if (NILP (frame))
1726 frame = selected_frame;
1728 if (!EQ (frame, XWINDOW (window)->frame))
1729 error ("Window is on a different frame");
1731 return window_list_1 (window, minibuf, frame);
1735 /* Return a list of windows in canonical ordering. Arguments are like
1736 for `next-window'. */
1738 static Lisp_Object
1739 window_list_1 (window, minibuf, all_frames)
1740 Lisp_Object window, minibuf, all_frames;
1742 Lisp_Object tail, list;
1744 decode_next_window_args (&window, &minibuf, &all_frames);
1745 list = Qnil;
1747 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
1748 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
1749 list = Fcons (XCAR (tail), list);
1751 return Fnreverse (list);
1756 /* Look at all windows, performing an operation specified by TYPE
1757 with argument OBJ.
1758 If FRAMES is Qt, look at all frames;
1759 Qnil, look at just the selected frame;
1760 Qvisible, look at visible frames;
1761 a frame, just look at windows on that frame.
1762 If MINI is non-zero, perform the operation on minibuffer windows too. */
1764 enum window_loop
1766 WINDOW_LOOP_UNUSED,
1767 GET_BUFFER_WINDOW, /* Arg is buffer */
1768 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1769 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1770 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1771 GET_LARGEST_WINDOW,
1772 UNSHOW_BUFFER, /* Arg is buffer */
1773 CHECK_ALL_WINDOWS
1776 static Lisp_Object
1777 window_loop (type, obj, mini, frames)
1778 enum window_loop type;
1779 Lisp_Object obj, frames;
1780 int mini;
1782 Lisp_Object window, windows, best_window, frame_arg;
1783 struct frame *f;
1784 struct gcpro gcpro1;
1786 /* If we're only looping through windows on a particular frame,
1787 frame points to that frame. If we're looping through windows
1788 on all frames, frame is 0. */
1789 if (FRAMEP (frames))
1790 f = XFRAME (frames);
1791 else if (NILP (frames))
1792 f = SELECTED_FRAME ();
1793 else
1794 f = NULL;
1796 if (f)
1797 frame_arg = Qlambda;
1798 else if (XFASTINT (frames) == 0)
1799 frame_arg = frames;
1800 else if (EQ (frames, Qvisible))
1801 frame_arg = frames;
1802 else
1803 frame_arg = Qt;
1805 /* frame_arg is Qlambda to stick to one frame,
1806 Qvisible to consider all visible frames,
1807 or Qt otherwise. */
1809 /* Pick a window to start with. */
1810 if (WINDOWP (obj))
1811 window = obj;
1812 else if (f)
1813 window = FRAME_SELECTED_WINDOW (f);
1814 else
1815 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1817 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
1818 GCPRO1 (windows);
1819 best_window = Qnil;
1821 for (; CONSP (windows); windows = CDR (windows))
1823 struct window *w;
1825 window = XCAR (windows);
1826 w = XWINDOW (window);
1828 /* Note that we do not pay attention here to whether the frame
1829 is visible, since Fwindow_list skips non-visible frames if
1830 that is desired, under the control of frame_arg. */
1831 if (!MINI_WINDOW_P (w)
1832 /* For UNSHOW_BUFFER, we must always consider all windows. */
1833 || type == UNSHOW_BUFFER
1834 || (mini && minibuf_level > 0))
1835 switch (type)
1837 case GET_BUFFER_WINDOW:
1838 if (EQ (w->buffer, obj)
1839 /* Don't find any minibuffer window
1840 except the one that is currently in use. */
1841 && (MINI_WINDOW_P (w)
1842 ? EQ (window, minibuf_window)
1843 : 1))
1845 if (NILP (best_window))
1846 best_window = window;
1847 else if (EQ (window, selected_window))
1848 /* For compatibility with 20.x, prefer to return
1849 selected-window. */
1850 best_window = window;
1852 break;
1854 case GET_LRU_WINDOW:
1855 /* t as arg means consider only full-width windows */
1856 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w))
1857 break;
1858 /* Ignore dedicated windows and minibuffers. */
1859 if (MINI_WINDOW_P (w) || !NILP (w->dedicated))
1860 break;
1861 if (NILP (best_window)
1862 || (XFASTINT (XWINDOW (best_window)->use_time)
1863 > XFASTINT (w->use_time)))
1864 best_window = window;
1865 break;
1867 case DELETE_OTHER_WINDOWS:
1868 if (!EQ (window, obj))
1869 Fdelete_window (window);
1870 break;
1872 case DELETE_BUFFER_WINDOWS:
1873 if (EQ (w->buffer, obj))
1875 struct frame *f = XFRAME (WINDOW_FRAME (w));
1877 /* If this window is dedicated, and in a frame of its own,
1878 kill the frame. */
1879 if (EQ (window, FRAME_ROOT_WINDOW (f))
1880 && !NILP (w->dedicated)
1881 && other_visible_frames (f))
1883 /* Skip the other windows on this frame.
1884 There might be one, the minibuffer! */
1885 while (CONSP (XCDR (windows))
1886 && EQ (XWINDOW (XCAR (windows))->frame,
1887 XWINDOW (XCAR (XCDR (windows)))->frame))
1888 windows = XCDR (windows);
1890 /* Now we can safely delete the frame. */
1891 Fdelete_frame (w->frame, Qnil);
1893 else if (NILP (w->parent))
1895 /* If we're deleting the buffer displayed in the
1896 only window on the frame, find a new buffer to
1897 display there. */
1898 Lisp_Object buffer;
1899 buffer = Fother_buffer (obj, Qnil, w->frame);
1900 Fset_window_buffer (window, buffer);
1901 if (EQ (window, selected_window))
1902 Fset_buffer (w->buffer);
1904 else
1905 Fdelete_window (window);
1907 break;
1909 case GET_LARGEST_WINDOW:
1911 /* Ignore dedicated windows and minibuffers. */
1912 if (MINI_WINDOW_P (w) || !NILP (w->dedicated))
1913 break;
1915 if (NILP (best_window))
1916 best_window = window;
1917 else
1919 struct window *b = XWINDOW (best_window);
1920 if (XFASTINT (w->height) * XFASTINT (w->width)
1921 > XFASTINT (b->height) * XFASTINT (b->width))
1922 best_window = window;
1925 break;
1927 case UNSHOW_BUFFER:
1928 if (EQ (w->buffer, obj))
1930 Lisp_Object buffer;
1931 struct frame *f = XFRAME (w->frame);
1933 /* Find another buffer to show in this window. */
1934 buffer = Fother_buffer (obj, Qnil, w->frame);
1936 /* If this window is dedicated, and in a frame of its own,
1937 kill the frame. */
1938 if (EQ (window, FRAME_ROOT_WINDOW (f))
1939 && !NILP (w->dedicated)
1940 && other_visible_frames (f))
1942 /* Skip the other windows on this frame.
1943 There might be one, the minibuffer! */
1944 while (CONSP (XCDR (windows))
1945 && EQ (XWINDOW (XCAR (windows))->frame,
1946 XWINDOW (XCAR (XCDR (windows)))->frame))
1947 windows = XCDR (windows);
1949 /* Now we can safely delete the frame. */
1950 Fdelete_frame (w->frame, Qnil);
1952 else
1954 /* Otherwise show a different buffer in the window. */
1955 w->dedicated = Qnil;
1956 Fset_window_buffer (window, buffer);
1957 if (EQ (window, selected_window))
1958 Fset_buffer (w->buffer);
1961 break;
1963 /* Check for a window that has a killed buffer. */
1964 case CHECK_ALL_WINDOWS:
1965 if (! NILP (w->buffer)
1966 && NILP (XBUFFER (w->buffer)->name))
1967 abort ();
1968 break;
1970 case WINDOW_LOOP_UNUSED:
1971 break;
1975 UNGCPRO;
1976 return best_window;
1979 /* Used for debugging. Abort if any window has a dead buffer. */
1981 void
1982 check_all_windows ()
1984 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
1987 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1988 doc: /* Return the window least recently selected or used for display.
1989 If optional argument FRAME is `visible', search all visible frames.
1990 If FRAME is 0, search all visible and iconified frames.
1991 If FRAME is t, search all frames.
1992 If FRAME is nil, search only the selected frame.
1993 If FRAME is a frame, search only that frame. */)
1994 (frame)
1995 Lisp_Object frame;
1997 register Lisp_Object w;
1998 /* First try for a window that is full-width */
1999 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
2000 if (!NILP (w) && !EQ (w, selected_window))
2001 return w;
2002 /* If none of them, try the rest */
2003 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
2006 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
2007 doc: /* Return the largest window in area.
2008 If optional argument FRAME is `visible', search all visible frames.
2009 If FRAME is 0, search all visible and iconified frames.
2010 If FRAME is t, search all frames.
2011 If FRAME is nil, search only the selected frame.
2012 If FRAME is a frame, search only that frame. */)
2013 (frame)
2014 Lisp_Object frame;
2016 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
2017 frame);
2020 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
2021 doc: /* Return a window currently displaying BUFFER, or nil if none.
2022 If optional argument FRAME is `visible', search all visible frames.
2023 If optional argument FRAME is 0, search all visible and iconified frames.
2024 If FRAME is t, search all frames.
2025 If FRAME is nil, search only the selected frame.
2026 If FRAME is a frame, search only that frame. */)
2027 (buffer, frame)
2028 Lisp_Object buffer, frame;
2030 buffer = Fget_buffer (buffer);
2031 if (BUFFERP (buffer))
2032 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
2033 else
2034 return Qnil;
2037 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
2038 0, 1, "",
2039 doc: /* Make WINDOW (or the selected window) fill its frame.
2040 Only the frame WINDOW is on is affected.
2041 This function tries to reduce display jumps
2042 by keeping the text previously visible in WINDOW
2043 in the same place on the frame. Doing this depends on
2044 the value of (window-start WINDOW), so if calling this function
2045 in a program gives strange scrolling, make sure the window-start
2046 value is reasonable when this function is called. */)
2047 (window)
2048 Lisp_Object window;
2050 struct window *w;
2051 int startpos;
2052 int top, new_top;
2054 if (NILP (window))
2055 window = selected_window;
2056 else
2057 CHECK_LIVE_WINDOW (window);
2058 w = XWINDOW (window);
2060 startpos = marker_position (w->start);
2061 top = XFASTINT (w->top) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2063 if (MINI_WINDOW_P (w) && top > 0)
2064 error ("Can't expand minibuffer to full frame");
2066 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
2068 /* Try to minimize scrolling, by setting the window start to the point
2069 will cause the text at the old window start to be at the same place
2070 on the frame. But don't try to do this if the window start is
2071 outside the visible portion (as might happen when the display is
2072 not current, due to typeahead). */
2073 new_top = XFASTINT (w->top) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2074 if (new_top != top
2075 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2076 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2078 struct position pos;
2079 struct buffer *obuf = current_buffer;
2081 Fset_buffer (w->buffer);
2082 /* This computation used to temporarily move point, but that can
2083 have unwanted side effects due to text properties. */
2084 pos = *vmotion (startpos, -top, w);
2086 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2087 w->window_end_valid = Qnil;
2088 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2089 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2090 : Qnil);
2091 /* We need to do this, so that the window-scroll-functions
2092 get called. */
2093 w->optional_new_start = Qt;
2095 set_buffer_internal (obuf);
2098 return Qnil;
2101 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
2102 1, 2, "bDelete windows on (buffer): ",
2103 doc: /* Delete all windows showing BUFFER.
2104 Optional second argument FRAME controls which frames are affected.
2105 If optional argument FRAME is `visible', search all visible frames.
2106 If FRAME is 0, search all visible and iconified frames.
2107 If FRAME is nil, search all frames.
2108 If FRAME is t, search only the selected frame.
2109 If FRAME is a frame, search only that frame. */)
2110 (buffer, frame)
2111 Lisp_Object buffer, frame;
2113 /* FRAME uses t and nil to mean the opposite of what window_loop
2114 expects. */
2115 if (NILP (frame))
2116 frame = Qt;
2117 else if (EQ (frame, Qt))
2118 frame = Qnil;
2120 if (!NILP (buffer))
2122 buffer = Fget_buffer (buffer);
2123 CHECK_BUFFER (buffer);
2124 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
2127 return Qnil;
2130 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2131 Sreplace_buffer_in_windows,
2132 1, 1, "bReplace buffer in windows: ",
2133 doc: /* Replace BUFFER with some other buffer in all windows showing it. */)
2134 (buffer)
2135 Lisp_Object buffer;
2137 if (!NILP (buffer))
2139 buffer = Fget_buffer (buffer);
2140 CHECK_BUFFER (buffer);
2141 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2143 return Qnil;
2146 /* Replace BUFFER with some other buffer in all windows
2147 of all frames, even those on other keyboards. */
2149 void
2150 replace_buffer_in_all_windows (buffer)
2151 Lisp_Object buffer;
2153 #ifdef MULTI_KBOARD
2154 Lisp_Object tail, frame;
2156 /* A single call to window_loop won't do the job
2157 because it only considers frames on the current keyboard.
2158 So loop manually over frames, and handle each one. */
2159 FOR_EACH_FRAME (tail, frame)
2160 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2161 #else
2162 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2163 #endif
2166 /* Set the height of WINDOW and all its inferiors. */
2168 /* The smallest acceptable dimensions for a window. Anything smaller
2169 might crash Emacs. */
2171 #define MIN_SAFE_WINDOW_WIDTH (2)
2172 #define MIN_SAFE_WINDOW_HEIGHT (1)
2174 /* Make sure that window_min_height and window_min_width are
2175 not too small; if they are, set them to safe minima. */
2177 static void
2178 check_min_window_sizes ()
2180 /* Smaller values might permit a crash. */
2181 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2182 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2183 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2184 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2187 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2188 minimum allowable size. */
2190 void
2191 check_frame_size (frame, rows, cols)
2192 FRAME_PTR frame;
2193 int *rows, *cols;
2195 /* For height, we have to see:
2196 how many windows the frame has at minimum (one or two),
2197 and whether it has a menu bar or other special stuff at the top. */
2198 int min_height
2199 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2200 ? MIN_SAFE_WINDOW_HEIGHT
2201 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2203 if (FRAME_TOP_MARGIN (frame) > 0)
2204 min_height += FRAME_TOP_MARGIN (frame);
2206 if (*rows < min_height)
2207 *rows = min_height;
2208 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2209 *cols = MIN_SAFE_WINDOW_WIDTH;
2213 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2214 check if W's width can be changed, otherwise check W's height.
2215 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2216 siblings, too. If none of the siblings is resizable, WINDOW isn't
2217 either. */
2219 static int
2220 window_fixed_size_p (w, width_p, check_siblings_p)
2221 struct window *w;
2222 int width_p, check_siblings_p;
2224 int fixed_p;
2225 struct window *c;
2227 if (!NILP (w->hchild))
2229 c = XWINDOW (w->hchild);
2231 if (width_p)
2233 /* A horiz. combination is fixed-width if all of if its
2234 children are. */
2235 while (c && window_fixed_size_p (c, width_p, 0))
2236 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2237 fixed_p = c == NULL;
2239 else
2241 /* A horiz. combination is fixed-height if one of if its
2242 children is. */
2243 while (c && !window_fixed_size_p (c, width_p, 0))
2244 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2245 fixed_p = c != NULL;
2248 else if (!NILP (w->vchild))
2250 c = XWINDOW (w->vchild);
2252 if (width_p)
2254 /* A vert. combination is fixed-width if one of if its
2255 children is. */
2256 while (c && !window_fixed_size_p (c, width_p, 0))
2257 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2258 fixed_p = c != NULL;
2260 else
2262 /* A vert. combination is fixed-height if all of if its
2263 children are. */
2264 while (c && window_fixed_size_p (c, width_p, 0))
2265 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2266 fixed_p = c == NULL;
2269 else if (BUFFERP (w->buffer))
2271 if (w->height_fixed_p && !width_p)
2272 fixed_p = 1;
2273 else
2275 struct buffer *old = current_buffer;
2276 Lisp_Object val;
2278 current_buffer = XBUFFER (w->buffer);
2279 val = find_symbol_value (Qwindow_size_fixed);
2280 current_buffer = old;
2282 fixed_p = 0;
2283 if (!EQ (val, Qunbound))
2285 fixed_p = !NILP (val);
2287 if (fixed_p
2288 && ((EQ (val, Qheight) && width_p)
2289 || (EQ (val, Qwidth) && !width_p)))
2290 fixed_p = 0;
2294 /* Can't tell if this one is resizable without looking at
2295 siblings. If all siblings are fixed-size this one is too. */
2296 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2298 Lisp_Object child;
2300 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2301 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2302 break;
2304 if (NILP (child))
2305 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2306 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2307 break;
2309 if (NILP (child))
2310 fixed_p = 1;
2313 else
2314 fixed_p = 1;
2316 return fixed_p;
2320 /* Return the minimum size of window W, not taking fixed-width windows
2321 into account. WIDTH_P non-zero means return the minimum width,
2322 otherwise return the minimum height. If W is a combination window,
2323 compute the minimum size from the minimum sizes of W's children. */
2325 static int
2326 window_min_size_1 (w, width_p)
2327 struct window *w;
2328 int width_p;
2330 struct window *c;
2331 int size;
2333 if (!NILP (w->hchild))
2335 c = XWINDOW (w->hchild);
2336 size = 0;
2338 if (width_p)
2340 /* The min width of a horizontal combination is
2341 the sum of the min widths of its children. */
2342 while (c)
2344 size += window_min_size_1 (c, width_p);
2345 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2348 else
2350 /* The min height a horizontal combination equals
2351 the maximum of all min height of its children. */
2352 while (c)
2354 int min_size = window_min_size_1 (c, width_p);
2355 size = max (min_size, size);
2356 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2360 else if (!NILP (w->vchild))
2362 c = XWINDOW (w->vchild);
2363 size = 0;
2365 if (width_p)
2367 /* The min width of a vertical combination is
2368 the maximum of the min widths of its children. */
2369 while (c)
2371 int min_size = window_min_size_1 (c, width_p);
2372 size = max (min_size, size);
2373 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2376 else
2378 /* The min height of a vertical combination equals
2379 the sum of the min height of its children. */
2380 while (c)
2382 size += window_min_size_1 (c, width_p);
2383 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2387 else
2389 if (width_p)
2390 size = window_min_width;
2391 else
2393 if (MINI_WINDOW_P (w)
2394 || (!WINDOW_WANTS_MODELINE_P (w)
2395 && !WINDOW_WANTS_HEADER_LINE_P (w)))
2396 size = 1;
2397 else
2398 size = window_min_height;
2402 return size;
2406 /* Return the minimum size of window W, taking fixed-size windows into
2407 account. WIDTH_P non-zero means return the minimum width,
2408 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2409 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2410 unless FIXED is null. */
2412 static int
2413 window_min_size (w, width_p, ignore_fixed_p, fixed)
2414 struct window *w;
2415 int width_p, ignore_fixed_p, *fixed;
2417 int size, fixed_p;
2419 if (ignore_fixed_p)
2420 fixed_p = 0;
2421 else
2422 fixed_p = window_fixed_size_p (w, width_p, 1);
2424 if (fixed)
2425 *fixed = fixed_p;
2427 if (fixed_p)
2428 size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
2429 else
2430 size = window_min_size_1 (w, width_p);
2432 return size;
2436 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2437 WINDOW's width. Resize WINDOW's children, if any, so that they
2438 keep their proportionate size relative to WINDOW. Propagate
2439 WINDOW's top or left edge position to children. Delete windows
2440 that become too small unless NODELETE_P is non-zero.
2442 If NODELETE_P is 2, that means we do delete windows that are
2443 too small, even if they were too small before! */
2445 static void
2446 size_window (window, size, width_p, nodelete_p)
2447 Lisp_Object window;
2448 int size, width_p, nodelete_p;
2450 struct window *w = XWINDOW (window);
2451 struct window *c;
2452 Lisp_Object child, *forward, *sideward;
2453 int old_size, min_size;
2455 if (nodelete_p == 2)
2456 nodelete_p = 0;
2458 check_min_window_sizes ();
2459 size = max (0, size);
2461 /* If the window has been "too small" at one point,
2462 don't delete it for being "too small" in the future.
2463 Preserve it as long as that is at all possible. */
2464 if (width_p)
2466 old_size = XINT (w->width);
2467 min_size = window_min_width;
2469 else
2471 old_size = XINT (w->height);
2472 min_size = window_min_height;
2475 if (old_size < min_size && nodelete_p != 2)
2476 w->too_small_ok = Qt;
2478 /* Maybe delete WINDOW if it's too small. */
2479 if (nodelete_p != 1 && !NILP (w->parent))
2481 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
2482 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
2483 else
2484 min_size = width_p ? window_min_width : window_min_height;
2486 if (size < min_size)
2488 delete_window (window);
2489 return;
2493 /* Set redisplay hints. */
2494 w->last_modified = make_number (0);
2495 w->last_overlay_modified = make_number (0);
2496 windows_or_buffers_changed++;
2497 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
2499 if (width_p)
2501 sideward = &w->vchild;
2502 forward = &w->hchild;
2503 w->width = make_number (size);
2505 else
2507 sideward = &w->hchild;
2508 forward = &w->vchild;
2509 w->height = make_number (size);
2510 w->orig_height = Qnil;
2513 if (!NILP (*sideward))
2515 for (child = *sideward; !NILP (child); child = c->next)
2517 c = XWINDOW (child);
2518 if (width_p)
2519 c->left = w->left;
2520 else
2521 c->top = w->top;
2522 size_window (child, size, width_p, nodelete_p);
2525 else if (!NILP (*forward))
2527 int fixed_size, each, extra, n;
2528 int resize_fixed_p, nfixed;
2529 int last_pos, first_pos, nchildren, total;
2531 /* Determine the fixed-size portion of the this window, and the
2532 number of child windows. */
2533 fixed_size = nchildren = nfixed = total = 0;
2534 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
2536 int child_size;
2538 c = XWINDOW (child);
2539 child_size = width_p ? XINT (c->width) : XINT (c->height);
2540 total += child_size;
2542 if (window_fixed_size_p (c, width_p, 0))
2544 fixed_size += child_size;
2545 ++nfixed;
2549 /* If the new size is smaller than fixed_size, or if there
2550 aren't any resizable windows, allow resizing fixed-size
2551 windows. */
2552 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2554 /* Compute how many lines/columns to add to each child. The
2555 value of extra takes care of rounding errors. */
2556 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2557 each = (size - total) / n;
2558 extra = (size - total) - n * each;
2560 /* Compute new children heights and edge positions. */
2561 first_pos = width_p ? XINT (w->left) : XINT (w->top);
2562 last_pos = first_pos;
2563 for (child = *forward; !NILP (child); child = c->next)
2565 int new_size, old_size;
2567 c = XWINDOW (child);
2568 old_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2569 new_size = old_size;
2571 /* The top or left edge position of this child equals the
2572 bottom or right edge of its predecessor. */
2573 if (width_p)
2574 c->left = make_number (last_pos);
2575 else
2576 c->top = make_number (last_pos);
2578 /* If this child can be resized, do it. */
2579 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2581 new_size = old_size + each + extra;
2582 extra = 0;
2585 /* Set new height. Note that size_window also propagates
2586 edge positions to children, so it's not a no-op if we
2587 didn't change the child's size. */
2588 size_window (child, new_size, width_p, 1);
2590 /* Remember the bottom/right edge position of this child; it
2591 will be used to set the top/left edge of the next child. */
2592 last_pos += new_size;
2595 /* We should have covered the parent exactly with child windows. */
2596 xassert (size == last_pos - first_pos);
2598 /* Now delete any children that became too small. */
2599 if (!nodelete_p)
2600 for (child = *forward; !NILP (child); child = c->next)
2602 int child_size;
2603 c = XWINDOW (child);
2604 child_size = width_p ? XINT (c->width) : XINT (c->height);
2605 size_window (child, child_size, width_p, 2);
2610 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2611 WINDOW's children. NODELETE non-zero means don't delete windows
2612 that become too small in the process. (The caller should check
2613 later and do so if appropriate.) */
2615 void
2616 set_window_height (window, height, nodelete)
2617 Lisp_Object window;
2618 int height;
2619 int nodelete;
2621 size_window (window, height, 0, nodelete);
2625 /* Set WINDOW's width to WIDTH, and recursively change the width of
2626 WINDOW's children. NODELETE non-zero means don't delete windows
2627 that become too small in the process. (The caller should check
2628 later and do so if appropriate.) */
2630 void
2631 set_window_width (window, width, nodelete)
2632 Lisp_Object window;
2633 int width;
2634 int nodelete;
2636 size_window (window, width, 1, nodelete);
2640 int window_select_count;
2642 Lisp_Object
2643 Fset_window_buffer_unwind (obuf)
2644 Lisp_Object obuf;
2646 Fset_buffer (obuf);
2647 return Qnil;
2651 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2652 means it's allowed to run hooks. See make_frame for a case where
2653 it's not allowed. */
2655 void
2656 set_window_buffer (window, buffer, run_hooks_p)
2657 Lisp_Object window, buffer;
2658 int run_hooks_p;
2660 struct window *w = XWINDOW (window);
2661 struct buffer *b = XBUFFER (buffer);
2662 int count = specpdl_ptr - specpdl;
2664 w->buffer = buffer;
2666 if (EQ (window, selected_window))
2667 b->last_selected_window = window;
2669 /* Update time stamps of buffer display. */
2670 if (INTEGERP (b->display_count))
2671 XSETINT (b->display_count, XINT (b->display_count) + 1);
2672 b->display_time = Fcurrent_time ();
2674 XSETFASTINT (w->window_end_pos, 0);
2675 XSETFASTINT (w->window_end_vpos, 0);
2676 bzero (&w->last_cursor, sizeof w->last_cursor);
2677 w->window_end_valid = Qnil;
2678 w->hscroll = w->min_hscroll = make_number (0);
2679 w->vscroll = 0;
2680 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
2681 set_marker_restricted (w->start,
2682 make_number (b->last_window_start),
2683 buffer);
2684 w->start_at_line_beg = Qnil;
2685 w->force_start = Qnil;
2686 XSETFASTINT (w->last_modified, 0);
2687 XSETFASTINT (w->last_overlay_modified, 0);
2688 windows_or_buffers_changed++;
2690 /* We must select BUFFER for running the window-scroll-functions.
2691 If WINDOW is selected, switch permanently.
2692 Otherwise, switch but go back to the ambient buffer afterward. */
2693 if (EQ (window, selected_window))
2694 Fset_buffer (buffer);
2695 /* We can't check ! NILP (Vwindow_scroll_functions) here
2696 because that might itself be a local variable. */
2697 else if (window_initialized)
2699 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2700 Fset_buffer (buffer);
2703 /* Set left and right marginal area width from buffer. */
2704 Fset_window_margins (window, b->left_margin_width, b->right_margin_width);
2706 if (run_hooks_p)
2708 if (! NILP (Vwindow_scroll_functions))
2709 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2710 Fmarker_position (w->start));
2712 if (! NILP (Vwindow_configuration_change_hook)
2713 && ! NILP (Vrun_hooks))
2714 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2717 unbind_to (count, Qnil);
2721 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
2722 doc: /* Make WINDOW display BUFFER as its contents.
2723 BUFFER can be a buffer or buffer name. */)
2724 (window, buffer)
2725 register Lisp_Object window, buffer;
2727 register Lisp_Object tem;
2728 register struct window *w = decode_window (window);
2730 XSETWINDOW (window, w);
2731 buffer = Fget_buffer (buffer);
2732 CHECK_BUFFER (buffer);
2734 if (NILP (XBUFFER (buffer)->name))
2735 error ("Attempt to display deleted buffer");
2737 tem = w->buffer;
2738 if (NILP (tem))
2739 error ("Window is deleted");
2740 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
2741 is first being set up. */
2743 if (!NILP (w->dedicated) && !EQ (tem, buffer))
2744 error ("Window is dedicated to `%s'",
2745 XSTRING (XBUFFER (tem)->name)->data);
2747 unshow_buffer (w);
2750 set_window_buffer (window, buffer, 1);
2751 return Qnil;
2754 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
2755 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
2756 If WINDOW is not already selected, also make WINDOW's buffer current.
2757 Note that the main editor command loop
2758 selects the buffer of the selected window before each command. */)
2759 (window)
2760 register Lisp_Object window;
2762 return select_window_1 (window, 1);
2765 /* Note that selected_window can be nil
2766 when this is called from Fset_window_configuration. */
2768 static Lisp_Object
2769 select_window_1 (window, recordflag)
2770 register Lisp_Object window;
2771 int recordflag;
2773 register struct window *w;
2774 register struct window *ow;
2775 struct frame *sf;
2777 CHECK_LIVE_WINDOW (window);
2779 w = XWINDOW (window);
2780 w->frozen_window_start_p = 0;
2782 XSETFASTINT (w->use_time, ++window_select_count);
2783 if (EQ (window, selected_window))
2784 return window;
2786 if (!NILP (selected_window))
2788 ow = XWINDOW (selected_window);
2789 if (! NILP (ow->buffer))
2790 set_marker_both (ow->pointm, ow->buffer,
2791 BUF_PT (XBUFFER (ow->buffer)),
2792 BUF_PT_BYTE (XBUFFER (ow->buffer)));
2795 selected_window = window;
2796 sf = SELECTED_FRAME ();
2797 if (XFRAME (WINDOW_FRAME (w)) != sf)
2799 XFRAME (WINDOW_FRAME (w))->selected_window = window;
2800 /* Use this rather than Fhandle_switch_frame
2801 so that FRAME_FOCUS_FRAME is moved appropriately as we
2802 move around in the state where a minibuffer in a separate
2803 frame is active. */
2804 Fselect_frame (WINDOW_FRAME (w), Qnil);
2806 else
2807 sf->selected_window = window;
2809 if (recordflag)
2810 record_buffer (w->buffer);
2811 Fset_buffer (w->buffer);
2813 XBUFFER (w->buffer)->last_selected_window = window;
2815 /* Go to the point recorded in the window.
2816 This is important when the buffer is in more
2817 than one window. It also matters when
2818 redisplay_window has altered point after scrolling,
2819 because it makes the change only in the window. */
2821 register int new_point = marker_position (w->pointm);
2822 if (new_point < BEGV)
2823 SET_PT (BEGV);
2824 else if (new_point > ZV)
2825 SET_PT (ZV);
2826 else
2827 SET_PT (new_point);
2830 windows_or_buffers_changed++;
2831 return window;
2834 /* Deiconify the frame containing the window WINDOW,
2835 unless it is the selected frame;
2836 then return WINDOW.
2838 The reason for the exception for the selected frame
2839 is that it seems better not to change the selected frames visibility
2840 merely because of displaying a different buffer in it.
2841 The deiconification is useful when a buffer gets shown in
2842 another frame that you were not using lately. */
2844 static Lisp_Object
2845 display_buffer_1 (window)
2846 Lisp_Object window;
2848 Lisp_Object frame = XWINDOW (window)->frame;
2849 FRAME_PTR f = XFRAME (frame);
2851 FRAME_SAMPLE_VISIBILITY (f);
2853 if (!EQ (frame, selected_frame))
2855 if (FRAME_ICONIFIED_P (f))
2856 Fmake_frame_visible (frame);
2857 else if (FRAME_VISIBLE_P (f))
2858 Fraise_frame (frame);
2861 return window;
2864 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
2865 doc: /* Returns non-nil if a buffer named BUFFER-NAME would be created specially.
2866 The value is actually t if the frame should be called with default frame
2867 parameters, and a list of frame parameters if they were specified.
2868 See `special-display-buffer-names', and `special-display-regexps'. */)
2869 (buffer_name)
2870 Lisp_Object buffer_name;
2872 Lisp_Object tem;
2874 CHECK_STRING (buffer_name);
2876 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2877 if (!NILP (tem))
2878 return Qt;
2880 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2881 if (!NILP (tem))
2882 return XCDR (tem);
2884 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2886 Lisp_Object car = XCAR (tem);
2887 if (STRINGP (car)
2888 && fast_string_match (car, buffer_name) >= 0)
2889 return Qt;
2890 else if (CONSP (car)
2891 && STRINGP (XCAR (car))
2892 && fast_string_match (XCAR (car), buffer_name) >= 0)
2893 return XCDR (car);
2895 return Qnil;
2898 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
2899 doc: /* Returns non-nil if a new buffer named BUFFER-NAME would use the same window.
2900 See `same-window-buffer-names' and `same-window-regexps'. */)
2901 (buffer_name)
2902 Lisp_Object buffer_name;
2904 Lisp_Object tem;
2906 CHECK_STRING (buffer_name);
2908 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2909 if (!NILP (tem))
2910 return Qt;
2912 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2913 if (!NILP (tem))
2914 return Qt;
2916 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
2918 Lisp_Object car = XCAR (tem);
2919 if (STRINGP (car)
2920 && fast_string_match (car, buffer_name) >= 0)
2921 return Qt;
2922 else if (CONSP (car)
2923 && STRINGP (XCAR (car))
2924 && fast_string_match (XCAR (car), buffer_name) >= 0)
2925 return Qt;
2927 return Qnil;
2930 /* Use B so the default is (other-buffer). */
2931 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
2932 "BDisplay buffer: \nP",
2933 doc: /* Make BUFFER appear in some window but don't select it.
2934 BUFFER can be a buffer or a buffer name.
2935 If BUFFER is shown already in some window, just use that one,
2936 unless the window is the selected window and the optional second
2937 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
2938 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
2939 Returns the window displaying BUFFER.
2940 If `display-buffer-reuse-frames' is non-nil, and another frame is currently
2941 displaying BUFFER, then simply raise that frame.
2943 The variables `special-display-buffer-names', `special-display-regexps',
2944 `same-window-buffer-names', and `same-window-regexps' customize how certain
2945 buffer names are handled.
2947 If optional argument FRAME is `visible', search all visible frames.
2948 If FRAME is 0, search all visible and iconified frames.
2949 If FRAME is t, search all frames.
2950 If FRAME is a frame, search only that frame.
2951 If FRAME is nil, search only the selected frame
2952 (actually the last nonminibuffer frame),
2953 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,
2954 which means search visible and iconified frames.
2956 If `even-window-heights' is non-nil, window heights will be evened out
2957 if displaying the buffer causes two vertically adjacent windows to be
2958 displayed. */)
2959 (buffer, not_this_window, frame)
2960 register Lisp_Object buffer, not_this_window, frame;
2962 register Lisp_Object window, tem, swp;
2963 struct frame *f;
2965 swp = Qnil;
2966 buffer = Fget_buffer (buffer);
2967 CHECK_BUFFER (buffer);
2969 if (!NILP (Vdisplay_buffer_function))
2970 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
2972 if (NILP (not_this_window)
2973 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
2974 return display_buffer_1 (selected_window);
2976 /* See if the user has specified this buffer should appear
2977 in the selected window. */
2978 if (NILP (not_this_window))
2980 swp = Fsame_window_p (XBUFFER (buffer)->name);
2981 if (!NILP (swp) && !no_switch_window (selected_window))
2983 Fswitch_to_buffer (buffer, Qnil);
2984 return display_buffer_1 (selected_window);
2988 /* If the user wants pop-up-frames or display-buffer-reuse-frames,
2989 look for a window showing BUFFER on any visible or iconified frame.
2990 Otherwise search only the current frame. */
2991 if (! NILP (frame))
2992 tem = frame;
2993 else if (pop_up_frames
2994 || display_buffer_reuse_frames
2995 || last_nonminibuf_frame == 0)
2996 XSETFASTINT (tem, 0);
2997 else
2998 XSETFRAME (tem, last_nonminibuf_frame);
3000 window = Fget_buffer_window (buffer, tem);
3001 if (!NILP (window)
3002 && (NILP (not_this_window) || !EQ (window, selected_window)))
3003 return display_buffer_1 (window);
3005 /* Certain buffer names get special handling. */
3006 if (!NILP (Vspecial_display_function) && NILP (swp))
3008 tem = Fspecial_display_p (XBUFFER (buffer)->name);
3009 if (EQ (tem, Qt))
3010 return call1 (Vspecial_display_function, buffer);
3011 if (CONSP (tem))
3012 return call2 (Vspecial_display_function, buffer, tem);
3015 /* If there are no frames open that have more than a minibuffer,
3016 we need to create a new frame. */
3017 if (pop_up_frames || last_nonminibuf_frame == 0)
3019 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3020 Fset_window_buffer (window, buffer);
3021 return display_buffer_1 (window);
3024 f = SELECTED_FRAME ();
3025 if (pop_up_windows
3026 || FRAME_MINIBUF_ONLY_P (f)
3027 /* If the current frame is a special display frame,
3028 don't try to reuse its windows. */
3029 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
3031 Lisp_Object frames;
3033 frames = Qnil;
3034 if (FRAME_MINIBUF_ONLY_P (f))
3035 XSETFRAME (frames, last_nonminibuf_frame);
3036 /* Don't try to create a window if would get an error */
3037 if (split_height_threshold < window_min_height << 1)
3038 split_height_threshold = window_min_height << 1;
3040 /* Note that both Fget_largest_window and Fget_lru_window
3041 ignore minibuffers and dedicated windows.
3042 This means they can return nil. */
3044 /* If the frame we would try to split cannot be split,
3045 try other frames. */
3046 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
3048 /* Try visible frames first. */
3049 window = Fget_largest_window (Qvisible);
3050 /* If that didn't work, try iconified frames. */
3051 if (NILP (window))
3052 window = Fget_largest_window (make_number (0));
3053 if (NILP (window))
3054 window = Fget_largest_window (Qt);
3056 else
3057 window = Fget_largest_window (frames);
3059 /* If we got a tall enough full-width window that can be split,
3060 split it. */
3061 if (!NILP (window)
3062 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3063 && window_height (window) >= split_height_threshold
3064 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
3065 window = Fsplit_window (window, Qnil, Qnil);
3066 else
3068 Lisp_Object upper, lower, other;
3070 window = Fget_lru_window (frames);
3071 /* If the LRU window is selected, and big enough,
3072 and can be split, split it. */
3073 if (!NILP (window)
3074 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
3075 && (EQ (window, selected_window)
3076 || EQ (XWINDOW (window)->parent, Qnil))
3077 && window_height (window) >= window_min_height << 1)
3078 window = Fsplit_window (window, Qnil, Qnil);
3079 /* If Fget_lru_window returned nil, try other approaches. */
3081 /* Try visible frames first. */
3082 if (NILP (window))
3083 window = Fget_buffer_window (buffer, Qvisible);
3084 if (NILP (window))
3085 window = Fget_largest_window (Qvisible);
3086 /* If that didn't work, try iconified frames. */
3087 if (NILP (window))
3088 window = Fget_buffer_window (buffer, make_number (0));
3089 if (NILP (window))
3090 window = Fget_largest_window (make_number (0));
3091 /* Try invisible frames. */
3092 if (NILP (window))
3093 window = Fget_buffer_window (buffer, Qt);
3094 if (NILP (window))
3095 window = Fget_largest_window (Qt);
3096 /* As a last resort, make a new frame. */
3097 if (NILP (window))
3098 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
3099 /* If window appears above or below another,
3100 even out their heights. */
3101 other = upper = lower = Qnil;
3102 if (!NILP (XWINDOW (window)->prev))
3103 other = upper = XWINDOW (window)->prev, lower = window;
3104 if (!NILP (XWINDOW (window)->next))
3105 other = lower = XWINDOW (window)->next, upper = window;
3106 if (!NILP (other)
3107 && !NILP (Veven_window_heights)
3108 /* Check that OTHER and WINDOW are vertically arrayed. */
3109 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
3110 && (XFASTINT (XWINDOW (other)->height)
3111 > XFASTINT (XWINDOW (window)->height)))
3113 int total = (XFASTINT (XWINDOW (other)->height)
3114 + XFASTINT (XWINDOW (window)->height));
3115 enlarge_window (upper,
3116 total / 2 - XFASTINT (XWINDOW (upper)->height),
3117 0, 0);
3121 else
3122 window = Fget_lru_window (Qnil);
3124 Fset_window_buffer (window, buffer);
3125 return display_buffer_1 (window);
3128 void
3129 temp_output_buffer_show (buf)
3130 register Lisp_Object buf;
3132 register struct buffer *old = current_buffer;
3133 register Lisp_Object window;
3134 register struct window *w;
3136 XBUFFER (buf)->directory = current_buffer->directory;
3138 Fset_buffer (buf);
3139 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3140 BEGV = BEG;
3141 ZV = Z;
3142 SET_PT (BEG);
3143 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3144 set_buffer_internal (old);
3146 if (!EQ (Vtemp_buffer_show_function, Qnil))
3147 call1 (Vtemp_buffer_show_function, buf);
3148 else
3150 window = Fdisplay_buffer (buf, Qnil, Qnil);
3152 if (!EQ (XWINDOW (window)->frame, selected_frame))
3153 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3154 Vminibuf_scroll_window = window;
3155 w = XWINDOW (window);
3156 XSETFASTINT (w->hscroll, 0);
3157 XSETFASTINT (w->min_hscroll, 0);
3158 set_marker_restricted_both (w->start, buf, 1, 1);
3159 set_marker_restricted_both (w->pointm, buf, 1, 1);
3161 /* Run temp-buffer-show-hook, with the chosen window selected
3162 and it sbuffer current. */
3163 if (!NILP (Vrun_hooks))
3165 Lisp_Object tem;
3166 tem = Fboundp (Qtemp_buffer_show_hook);
3167 if (!NILP (tem))
3169 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3170 if (!NILP (tem))
3172 int count = specpdl_ptr - specpdl;
3173 Lisp_Object prev_window;
3174 prev_window = selected_window;
3176 /* Select the window that was chosen, for running the hook. */
3177 record_unwind_protect (Fselect_window, prev_window);
3178 select_window_1 (window, 0);
3179 Fset_buffer (w->buffer);
3180 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3181 select_window_1 (prev_window, 0);
3182 unbind_to (count, Qnil);
3189 static void
3190 make_dummy_parent (window)
3191 Lisp_Object window;
3193 Lisp_Object new;
3194 register struct window *o, *p;
3195 int i;
3197 o = XWINDOW (window);
3198 p = allocate_window ();
3199 for (i = 0; i < VECSIZE (struct window); ++i)
3200 ((struct Lisp_Vector *) p)->contents[i]
3201 = ((struct Lisp_Vector *)o)->contents[i];
3202 XSETWINDOW (new, p);
3204 XSETFASTINT (p->sequence_number, ++sequence_number);
3206 /* Put new into window structure in place of window */
3207 replace_window (window, new);
3209 o->next = Qnil;
3210 o->prev = Qnil;
3211 o->vchild = Qnil;
3212 o->hchild = Qnil;
3213 o->parent = new;
3215 p->start = Qnil;
3216 p->pointm = Qnil;
3217 p->buffer = Qnil;
3220 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3221 doc: /* Split WINDOW, putting SIZE lines in the first of the pair.
3222 WINDOW defaults to selected one and SIZE to half its size.
3223 If optional third arg HORFLAG is non-nil, split side by side
3224 and put SIZE columns in the first of the pair. In that case,
3225 SIZE includes that window's scroll bar, or the divider column to its right. */)
3226 (window, size, horflag)
3227 Lisp_Object window, size, horflag;
3229 register Lisp_Object new;
3230 register struct window *o, *p;
3231 FRAME_PTR fo;
3232 register int size_int;
3234 if (NILP (window))
3235 window = selected_window;
3236 else
3237 CHECK_LIVE_WINDOW (window);
3239 o = XWINDOW (window);
3240 fo = XFRAME (WINDOW_FRAME (o));
3242 if (NILP (size))
3244 if (!NILP (horflag))
3245 /* Calculate the size of the left-hand window, by dividing
3246 the usable space in columns by two.
3247 We round up, since the left-hand window may include
3248 a dividing line, while the right-hand may not. */
3249 size_int = (XFASTINT (o->width) + 1) >> 1;
3250 else
3251 size_int = XFASTINT (o->height) >> 1;
3253 else
3255 CHECK_NUMBER (size);
3256 size_int = XINT (size);
3259 if (MINI_WINDOW_P (o))
3260 error ("Attempt to split minibuffer window");
3261 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3262 error ("Attempt to split fixed-size window");
3264 check_min_window_sizes ();
3266 if (NILP (horflag))
3268 if (size_int < window_min_height)
3269 error ("Window height %d too small (after splitting)", size_int);
3270 if (size_int + window_min_height > XFASTINT (o->height))
3271 error ("Window height %d too small (after splitting)",
3272 XFASTINT (o->height) - size_int);
3273 if (NILP (o->parent)
3274 || NILP (XWINDOW (o->parent)->vchild))
3276 make_dummy_parent (window);
3277 new = o->parent;
3278 XWINDOW (new)->vchild = window;
3281 else
3283 if (size_int < window_min_width)
3284 error ("Window width %d too small (after splitting)", size_int);
3286 if (size_int + window_min_width > XFASTINT (o->width))
3287 error ("Window width %d too small (after splitting)",
3288 XFASTINT (o->width) - size_int);
3289 if (NILP (o->parent)
3290 || NILP (XWINDOW (o->parent)->hchild))
3292 make_dummy_parent (window);
3293 new = o->parent;
3294 XWINDOW (new)->hchild = window;
3298 /* Now we know that window's parent is a vertical combination
3299 if we are dividing vertically, or a horizontal combination
3300 if we are making side-by-side windows */
3302 windows_or_buffers_changed++;
3303 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3304 new = make_window ();
3305 p = XWINDOW (new);
3307 p->frame = o->frame;
3308 p->next = o->next;
3309 if (!NILP (p->next))
3310 XWINDOW (p->next)->prev = new;
3311 p->prev = window;
3312 o->next = new;
3313 p->parent = o->parent;
3314 p->buffer = Qt;
3315 p->window_end_valid = Qnil;
3316 bzero (&p->last_cursor, sizeof p->last_cursor);
3318 /* Apportion the available frame space among the two new windows */
3320 if (!NILP (horflag))
3322 p->height = o->height;
3323 p->top = o->top;
3324 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
3325 XSETFASTINT (o->width, size_int);
3326 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
3328 else
3330 p->left = o->left;
3331 p->width = o->width;
3332 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
3333 XSETFASTINT (o->height, size_int);
3334 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
3337 /* Adjust glyph matrices. */
3338 adjust_glyphs (fo);
3339 Fset_window_buffer (new, o->buffer);
3340 return new;
3343 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 3, "p",
3344 doc: /* Make current window ARG lines bigger.
3345 From program, optional second arg non-nil means grow sideways ARG columns.
3346 Interactively, if an argument is not given, make the window one line bigger.
3348 Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
3349 of the siblings above or to the left of the selected window. Only
3350 siblings to the right or below are changed. */)
3351 (arg, side, preserve_before)
3352 register Lisp_Object arg, side, preserve_before;
3354 CHECK_NUMBER (arg);
3355 enlarge_window (selected_window, XINT (arg), !NILP (side),
3356 !NILP (preserve_before));
3358 if (! NILP (Vwindow_configuration_change_hook))
3359 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3361 return Qnil;
3364 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3365 doc: /* Make current window ARG lines smaller.
3366 From program, optional second arg non-nil means shrink sideways arg columns.
3367 Interactively, if an argument is not given, make the window one line smaller. */)
3368 (arg, side)
3369 register Lisp_Object arg, side;
3371 CHECK_NUMBER (arg);
3372 enlarge_window (selected_window, -XINT (arg), !NILP (side), 0);
3374 if (! NILP (Vwindow_configuration_change_hook))
3375 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3377 return Qnil;
3381 window_height (window)
3382 Lisp_Object window;
3384 register struct window *p = XWINDOW (window);
3385 return XFASTINT (p->height);
3389 window_width (window)
3390 Lisp_Object window;
3392 register struct window *p = XWINDOW (window);
3393 return XFASTINT (p->width);
3397 #define CURBEG(w) \
3398 *(widthflag ? &(XWINDOW (w)->left) : &(XWINDOW (w)->top))
3400 #define CURSIZE(w) \
3401 *(widthflag ? &(XWINDOW (w)->width) : &(XWINDOW (w)->height))
3404 /* Enlarge WINDOW by DELTA. WIDTHFLAG non-zero means
3405 increase its width. Siblings of the selected window are resized to
3406 fulfill the size request. If they become too small in the process,
3407 they will be deleted.
3409 If PRESERVE_BEFORE is nonzero, that means don't alter
3410 the siblings to the left or above WINDOW. */
3412 static void
3413 enlarge_window (window, delta, widthflag, preserve_before)
3414 Lisp_Object window;
3415 int delta, widthflag, preserve_before;
3417 Lisp_Object parent, next, prev;
3418 struct window *p;
3419 Lisp_Object *sizep;
3420 int maximum;
3421 int (*sizefun) P_ ((Lisp_Object))
3422 = widthflag ? window_width : window_height;
3423 void (*setsizefun) P_ ((Lisp_Object, int, int))
3424 = (widthflag ? set_window_width : set_window_height);
3426 /* Check values of window_min_width and window_min_height for
3427 validity. */
3428 check_min_window_sizes ();
3430 /* Give up if this window cannot be resized. */
3431 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3432 error ("Window is not resizable");
3434 /* Find the parent of the selected window. */
3435 while (1)
3437 p = XWINDOW (window);
3438 parent = p->parent;
3440 if (NILP (parent))
3442 if (widthflag)
3443 error ("No other window to side of this one");
3444 break;
3447 if (widthflag
3448 ? !NILP (XWINDOW (parent)->hchild)
3449 : !NILP (XWINDOW (parent)->vchild))
3450 break;
3452 window = parent;
3455 sizep = &CURSIZE (window);
3458 register int maxdelta;
3460 /* Compute the maximum size increment this window can have. */
3462 if (preserve_before)
3464 if (!NILP (parent))
3466 maxdelta = (*sizefun) (parent) - XINT (*sizep);
3467 /* Subtract size of siblings before, since we can't take that. */
3468 maxdelta -= XINT (CURBEG (window)) - XINT (CURBEG (parent));
3470 else
3471 maxdelta = (!NILP (p->next) ? ((*sizefun) (p->next)
3472 - window_min_size (XWINDOW (p->next),
3473 widthflag, 0, 0))
3474 : (delta = 0));
3476 else
3477 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
3478 /* This is a main window followed by a minibuffer. */
3479 : !NILP (p->next) ? ((*sizefun) (p->next)
3480 - window_min_size (XWINDOW (p->next),
3481 widthflag, 0, 0))
3482 /* This is a minibuffer following a main window. */
3483 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3484 - window_min_size (XWINDOW (p->prev),
3485 widthflag, 0, 0))
3486 /* This is a frame with only one window, a minibuffer-only
3487 or a minibufferless frame. */
3488 : (delta = 0));
3490 if (delta > maxdelta)
3491 /* This case traps trying to make the minibuffer
3492 the full frame, or make the only window aside from the
3493 minibuffer the full frame. */
3494 delta = maxdelta;
3497 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3499 delete_window (window);
3500 return;
3503 if (delta == 0)
3504 return;
3506 /* Find the total we can get from other siblings without deleting them. */
3507 maximum = 0;
3508 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3509 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3510 widthflag, 0, 0);
3511 if (! preserve_before)
3512 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3513 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3514 widthflag, 0, 0);
3516 /* If we can get it all from them without deleting them, do so. */
3517 if (delta <= maximum)
3519 Lisp_Object first_unaffected;
3520 Lisp_Object first_affected;
3521 int fixed_p;
3523 next = p->next;
3524 prev = p->prev;
3525 first_affected = window;
3526 /* Look at one sibling at a time,
3527 moving away from this window in both directions alternately,
3528 and take as much as we can get without deleting that sibling. */
3529 while (delta != 0
3530 && (!NILP (next) || (!preserve_before && !NILP (prev))))
3532 if (! NILP (next))
3534 int this_one = ((*sizefun) (next)
3535 - window_min_size (XWINDOW (next),
3536 widthflag, 0, &fixed_p));
3537 if (!fixed_p)
3539 if (this_one > delta)
3540 this_one = delta;
3542 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3543 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3545 delta -= this_one;
3548 next = XWINDOW (next)->next;
3551 if (delta == 0)
3552 break;
3554 if (!preserve_before && ! NILP (prev))
3556 int this_one = ((*sizefun) (prev)
3557 - window_min_size (XWINDOW (prev),
3558 widthflag, 0, &fixed_p));
3559 if (!fixed_p)
3561 if (this_one > delta)
3562 this_one = delta;
3564 first_affected = prev;
3566 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3567 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3569 delta -= this_one;
3572 prev = XWINDOW (prev)->prev;
3576 xassert (delta == 0);
3578 /* Now recalculate the edge positions of all the windows affected,
3579 based on the new sizes. */
3580 first_unaffected = next;
3581 prev = first_affected;
3582 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3583 prev = next, next = XWINDOW (next)->next)
3585 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
3586 /* This does not change size of NEXT,
3587 but it propagates the new top edge to its children */
3588 (*setsizefun) (next, (*sizefun) (next), 0);
3591 else
3593 register int delta1;
3594 register int opht = (*sizefun) (parent);
3596 if (opht <= XINT (*sizep) + delta)
3598 /* If trying to grow this window to or beyond size of the parent,
3599 just delete all the sibling windows. */
3600 Lisp_Object start, tem, next;
3602 start = XWINDOW (parent)->vchild;
3603 if (NILP (start))
3604 start = XWINDOW (parent)->hchild;
3606 /* Delete any siblings that come after WINDOW. */
3607 tem = XWINDOW (window)->next;
3608 while (! NILP (tem))
3610 next = XWINDOW (tem)->next;
3611 delete_window (tem);
3612 tem = next;
3615 /* Delete any siblings that come after WINDOW.
3616 Note that if START is not WINDOW, then WINDOW still
3617 Fhas siblings, so WINDOW has not yet replaced its parent. */
3618 tem = start;
3619 while (! EQ (tem, window))
3621 next = XWINDOW (tem)->next;
3622 delete_window (tem);
3623 tem = next;
3626 else
3628 /* Otherwise, make delta1 just right so that if we add
3629 delta1 lines to this window and to the parent, and then
3630 shrink the parent back to its original size, the new
3631 proportional size of this window will increase by delta.
3633 The function size_window will compute the new height h'
3634 of the window from delta1 as:
3636 e = delta1/n
3637 x = delta1 - delta1/n * n for the 1st resizable child
3638 h' = h + e + x
3640 where n is the number of children that can be resized.
3641 We can ignore x by choosing a delta1 that is a multiple of
3642 n. We want the height of this window to come out as
3644 h' = h + delta
3646 So, delta1 must be
3648 h + e = h + delta
3649 delta1/n = delta
3650 delta1 = n * delta.
3652 The number of children n rquals the number of resizable
3653 children of this window + 1 because we know window itself
3654 is resizable (otherwise we would have signalled an error. */
3656 struct window *w = XWINDOW (window);
3657 Lisp_Object s;
3658 int n = 1;
3660 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3661 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3662 ++n;
3663 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3664 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3665 ++n;
3667 delta1 = n * delta;
3669 /* Add delta1 lines or columns to this window, and to the parent,
3670 keeping things consistent while not affecting siblings. */
3671 XSETINT (CURSIZE (parent), opht + delta1);
3672 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
3674 /* Squeeze out delta1 lines or columns from our parent,
3675 shriking this window and siblings proportionately.
3676 This brings parent back to correct size.
3677 Delta1 was calculated so this makes this window the desired size,
3678 taking it all out of the siblings. */
3679 (*setsizefun) (parent, opht, 0);
3684 XSETFASTINT (p->last_modified, 0);
3685 XSETFASTINT (p->last_overlay_modified, 0);
3687 /* Adjust glyph matrices. */
3688 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
3691 #undef CURBEG
3692 #undef CURSIZE
3696 /***********************************************************************
3697 Resizing Mini-Windows
3698 ***********************************************************************/
3700 static void shrink_window_lowest_first P_ ((struct window *, int));
3702 enum save_restore_action
3704 CHECK_ORIG_SIZES,
3705 SAVE_ORIG_SIZES,
3706 RESTORE_ORIG_SIZES
3709 static int save_restore_orig_size P_ ((struct window *,
3710 enum save_restore_action));
3712 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
3713 from lowest windows first. */
3715 static void
3716 shrink_window_lowest_first (w, height)
3717 struct window *w;
3718 int height;
3720 struct window *c;
3721 Lisp_Object child;
3722 int old_height;
3724 xassert (!MINI_WINDOW_P (w));
3726 /* Set redisplay hints. */
3727 XSETFASTINT (w->last_modified, 0);
3728 XSETFASTINT (w->last_overlay_modified, 0);
3729 windows_or_buffers_changed++;
3730 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
3732 old_height = XFASTINT (w->height);
3733 XSETFASTINT (w->height, height);
3735 if (!NILP (w->hchild))
3737 for (child = w->hchild; !NILP (child); child = c->next)
3739 c = XWINDOW (child);
3740 c->top = w->top;
3741 shrink_window_lowest_first (c, height);
3744 else if (!NILP (w->vchild))
3746 Lisp_Object last_child;
3747 int delta = old_height - height;
3748 int last_top;
3750 last_child = Qnil;
3752 /* Find the last child. We are taking space from lowest windows
3753 first, so we iterate over children from the last child
3754 backwards. */
3755 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
3756 last_child = child;
3758 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
3759 for (child = last_child; delta && !NILP (child); child = c->prev)
3761 int this_one;
3763 c = XWINDOW (child);
3764 this_one = XFASTINT (c->height) - MIN_SAFE_WINDOW_HEIGHT;
3766 if (this_one > delta)
3767 this_one = delta;
3769 shrink_window_lowest_first (c, XFASTINT (c->height) - this_one);
3770 delta -= this_one;
3773 /* Compute new positions. */
3774 last_top = XINT (w->top);
3775 for (child = w->vchild; !NILP (child); child = c->next)
3777 c = XWINDOW (child);
3778 c->top = make_number (last_top);
3779 shrink_window_lowest_first (c, XFASTINT (c->height));
3780 last_top += XFASTINT (c->height);
3786 /* Save, restore, or check positions and sizes in the window tree
3787 rooted at W. ACTION says what to do.
3789 If ACTION is CHECK_ORIG_SIZES, check if orig_top and orig_height
3790 members are valid for all windows in the window tree. Value is
3791 non-zero if they are valid.
3793 If ACTION is SAVE_ORIG_SIZES, save members top and height in
3794 orig_top and orig_height for all windows in the tree.
3796 If ACTION is RESTORE_ORIG_SIZES, restore top and height from
3797 values stored in orig_top and orig_height for all windows. */
3799 static int
3800 save_restore_orig_size (w, action)
3801 struct window *w;
3802 enum save_restore_action action;
3804 int success_p = 1;
3806 while (w)
3808 if (!NILP (w->hchild))
3810 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
3811 success_p = 0;
3813 else if (!NILP (w->vchild))
3815 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
3816 success_p = 0;
3819 switch (action)
3821 case CHECK_ORIG_SIZES:
3822 if (!INTEGERP (w->orig_top) || !INTEGERP (w->orig_height))
3823 return 0;
3824 break;
3826 case SAVE_ORIG_SIZES:
3827 w->orig_top = w->top;
3828 w->orig_height = w->height;
3829 XSETFASTINT (w->last_modified, 0);
3830 XSETFASTINT (w->last_overlay_modified, 0);
3831 break;
3833 case RESTORE_ORIG_SIZES:
3834 xassert (INTEGERP (w->orig_top) && INTEGERP (w->orig_height));
3835 w->top = w->orig_top;
3836 w->height = w->orig_height;
3837 w->orig_height = w->orig_top = Qnil;
3838 XSETFASTINT (w->last_modified, 0);
3839 XSETFASTINT (w->last_overlay_modified, 0);
3840 break;
3842 default:
3843 abort ();
3846 w = NILP (w->next) ? NULL : XWINDOW (w->next);
3849 return success_p;
3853 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
3854 without deleting other windows. */
3856 void
3857 grow_mini_window (w, delta)
3858 struct window *w;
3859 int delta;
3861 struct frame *f = XFRAME (w->frame);
3862 struct window *root;
3864 xassert (MINI_WINDOW_P (w));
3865 xassert (delta >= 0);
3867 /* Check values of window_min_width and window_min_height for
3868 validity. */
3869 check_min_window_sizes ();
3871 /* Compute how much we can enlarge the mini-window without deleting
3872 other windows. */
3873 root = XWINDOW (FRAME_ROOT_WINDOW (f));
3874 if (delta)
3876 int min_height = window_min_size (root, 0, 0, 0);
3877 if (XFASTINT (root->height) - delta < min_height)
3878 /* Note that the root window may already be smaller than
3879 min_height. */
3880 delta = max (0, XFASTINT (root->height) - min_height);
3883 if (delta)
3885 /* Save original window sizes and positions, if not already done. */
3886 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
3887 save_restore_orig_size (root, SAVE_ORIG_SIZES);
3889 /* Shrink other windows. */
3890 shrink_window_lowest_first (root, XFASTINT (root->height) - delta);
3892 /* Grow the mini-window. */
3893 w->top = make_number (XFASTINT (root->top) + XFASTINT (root->height));
3894 w->height = make_number (XFASTINT (w->height) + delta);
3895 XSETFASTINT (w->last_modified, 0);
3896 XSETFASTINT (w->last_overlay_modified, 0);
3898 adjust_glyphs (f);
3903 /* Shrink mini-window W. If there is recorded info about window sizes
3904 before a call to grow_mini_window, restore recorded window sizes.
3905 Otherwise, if the mini-window is higher than 1 line, resize it to 1
3906 line. */
3908 void
3909 shrink_mini_window (w)
3910 struct window *w;
3912 struct frame *f = XFRAME (w->frame);
3913 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
3915 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
3917 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
3918 adjust_glyphs (f);
3919 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3920 windows_or_buffers_changed = 1;
3922 else if (XFASTINT (w->height) > 1)
3924 /* Distribute the additional lines of the mini-window
3925 among the other windows. */
3926 Lisp_Object window;
3927 XSETWINDOW (window, w);
3928 enlarge_window (window, 1 - XFASTINT (w->height), 0, 0);
3934 /* Mark window cursors off for all windows in the window tree rooted
3935 at W by setting their phys_cursor_on_p flag to zero. Called from
3936 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3937 the frame are cleared. */
3939 void
3940 mark_window_cursors_off (w)
3941 struct window *w;
3943 while (w)
3945 if (!NILP (w->hchild))
3946 mark_window_cursors_off (XWINDOW (w->hchild));
3947 else if (!NILP (w->vchild))
3948 mark_window_cursors_off (XWINDOW (w->vchild));
3949 else
3950 w->phys_cursor_on_p = 0;
3952 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3957 /* Return number of lines of text (not counting mode lines) in W. */
3960 window_internal_height (w)
3961 struct window *w;
3963 int ht = XFASTINT (w->height);
3965 if (!MINI_WINDOW_P (w))
3967 if (!NILP (w->parent)
3968 || !NILP (w->vchild)
3969 || !NILP (w->hchild)
3970 || !NILP (w->next)
3971 || !NILP (w->prev)
3972 || WINDOW_WANTS_MODELINE_P (w))
3973 --ht;
3975 if (WINDOW_WANTS_HEADER_LINE_P (w))
3976 --ht;
3979 return ht;
3983 /* Return the number of columns in W.
3984 Don't count columns occupied by scroll bars or the vertical bar
3985 separating W from the sibling to its right. */
3988 window_internal_width (w)
3989 struct window *w;
3991 struct frame *f = XFRAME (WINDOW_FRAME (w));
3992 int width = XINT (w->width);
3994 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3995 /* Scroll bars occupy a few columns. */
3996 width -= FRAME_SCROLL_BAR_COLS (f);
3997 else if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
3998 /* The column of `|' characters separating side-by-side windows
3999 occupies one column only. */
4000 width -= 1;
4002 /* On window-systems, areas to the left and right of the window
4003 are used as fringes. */
4004 if (FRAME_WINDOW_P (f))
4005 width -= FRAME_FRINGE_COLS (f);
4007 return width;
4011 /************************************************************************
4012 Window Scrolling
4013 ***********************************************************************/
4015 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4016 N screen-fulls, which is defined as the height of the window minus
4017 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4018 instead. Negative values of N mean scroll down. NOERROR non-zero
4019 means don't signal an error if we try to move over BEGV or ZV,
4020 respectively. */
4022 static void
4023 window_scroll (window, n, whole, noerror)
4024 Lisp_Object window;
4025 int n;
4026 int whole;
4027 int noerror;
4029 /* If we must, use the pixel-based version which is much slower than
4030 the line-based one but can handle varying line heights. */
4031 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4032 window_scroll_pixel_based (window, n, whole, noerror);
4033 else
4034 window_scroll_line_based (window, n, whole, noerror);
4038 /* Implementation of window_scroll that works based on pixel line
4039 heights. See the comment of window_scroll for parameter
4040 descriptions. */
4042 static void
4043 window_scroll_pixel_based (window, n, whole, noerror)
4044 Lisp_Object window;
4045 int n;
4046 int whole;
4047 int noerror;
4049 struct it it;
4050 struct window *w = XWINDOW (window);
4051 struct text_pos start;
4052 Lisp_Object tem;
4053 int this_scroll_margin;
4054 int preserve_y;
4055 /* True if we fiddled the window vscroll field without really scrolling. */
4056 int vscrolled = 0;
4058 SET_TEXT_POS_FROM_MARKER (start, w->start);
4060 /* If PT is not visible in WINDOW, move back one half of
4061 the screen. Allow PT to be partially visible, otherwise
4062 something like (scroll-down 1) with PT in the line before
4063 the partially visible one would recenter. */
4064 tem = Fpos_visible_in_window_p (make_number (PT), window, Qt);
4065 if (NILP (tem))
4067 /* Move backward half the height of the window. Performance note:
4068 vmotion used here is about 10% faster, but would give wrong
4069 results for variable height lines. */
4070 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4071 it.current_y = it.last_visible_y;
4072 move_it_vertically (&it, - window_box_height (w) / 2);
4074 /* The function move_iterator_vertically may move over more than
4075 the specified y-distance. If it->w is small, e.g. a
4076 mini-buffer window, we may end up in front of the window's
4077 display area. This is the case when Start displaying at the
4078 start of the line containing PT in this case. */
4079 if (it.current_y <= 0)
4081 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4082 move_it_vertically (&it, 0);
4083 it.current_y = 0;
4086 start = it.current.pos;
4089 /* If scroll_preserve_screen_position is non-zero, we try to set
4090 point in the same window line as it is now, so get that line. */
4091 if (!NILP (Vscroll_preserve_screen_position))
4093 start_display (&it, w, start);
4094 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4095 preserve_y = it.current_y;
4097 else
4098 preserve_y = -1;
4100 /* Move iterator it from start the specified distance forward or
4101 backward. The result is the new window start. */
4102 start_display (&it, w, start);
4103 if (whole)
4105 int screen_full = (window_box_height (w)
4106 - next_screen_context_lines * CANON_Y_UNIT (it.f));
4107 int dy = n * screen_full;
4109 /* Note that move_it_vertically always moves the iterator to the
4110 start of a line. So, if the last line doesn't have a newline,
4111 we would end up at the start of the line ending at ZV. */
4112 if (dy <= 0)
4113 move_it_vertically_backward (&it, -dy);
4114 else if (dy > 0)
4115 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4116 MOVE_TO_POS | MOVE_TO_Y);
4118 else
4119 move_it_by_lines (&it, n, 1);
4121 /* End if we end up at ZV or BEGV. */
4122 if ((n > 0 && IT_CHARPOS (it) == ZV)
4123 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4125 if (IT_CHARPOS (it) == ZV)
4127 if (it.current_y + it.max_ascent + it.max_descent
4128 > it.last_visible_y)
4130 /* The last line was only partially visible, make it fully
4131 visible. */
4132 w->vscroll = (it.last_visible_y
4133 - it.current_y + it.max_ascent + it.max_descent);
4134 adjust_glyphs (it.f);
4136 else if (noerror)
4137 return;
4138 else
4139 Fsignal (Qend_of_buffer, Qnil);
4141 else
4143 if (w->vscroll != 0)
4144 /* The first line was only partially visible, make it fully
4145 visible. */
4146 w->vscroll = 0;
4147 else if (noerror)
4148 return;
4149 else
4150 Fsignal (Qbeginning_of_buffer, Qnil);
4153 /* If control gets here, then we vscrolled. */
4155 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4157 /* Don't try to change the window start below. */
4158 vscrolled = 1;
4161 if (! vscrolled)
4163 /* Set the window start, and set up the window for redisplay. */
4164 set_marker_restricted (w->start, make_number (IT_CHARPOS (it)),
4165 w->buffer);
4166 w->start_at_line_beg = Fbolp ();
4167 w->update_mode_line = Qt;
4168 XSETFASTINT (w->last_modified, 0);
4169 XSETFASTINT (w->last_overlay_modified, 0);
4170 /* Set force_start so that redisplay_window will run the
4171 window-scroll-functions. */
4172 w->force_start = Qt;
4175 it.current_y = it.vpos = 0;
4177 /* Preserve the screen position if we must. */
4178 if (preserve_y >= 0)
4180 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
4181 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4183 else
4185 /* Move PT out of scroll margins. */
4186 this_scroll_margin = max (0, scroll_margin);
4187 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
4188 this_scroll_margin *= CANON_Y_UNIT (it.f);
4190 if (n > 0)
4192 /* We moved the window start towards ZV, so PT may be now
4193 in the scroll margin at the top. */
4194 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4195 while (it.current_y < this_scroll_margin)
4197 int prev = it.current_y;
4198 move_it_by_lines (&it, 1, 1);
4199 if (prev == it.current_y)
4200 break;
4202 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4204 else if (n < 0)
4206 int charpos, bytepos;
4208 /* We moved the window start towards BEGV, so PT may be now
4209 in the scroll margin at the bottom. */
4210 move_it_to (&it, PT, -1,
4211 it.last_visible_y - this_scroll_margin - 1, -1,
4212 MOVE_TO_POS | MOVE_TO_Y);
4214 /* Save our position, in case it's correct. */
4215 charpos = IT_CHARPOS (it);
4216 bytepos = IT_BYTEPOS (it);
4218 /* See if point is on a partially visible line at the end. */
4219 move_it_by_lines (&it, 1, 1);
4220 if (it.current_y > it.last_visible_y)
4221 /* The last line was only partially visible, so back up two
4222 lines to make sure we're on a fully visible line. */
4224 move_it_by_lines (&it, -2, 0);
4225 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4227 else
4228 /* No, the position we saved is OK, so use it. */
4229 SET_PT_BOTH (charpos, bytepos);
4235 /* Implementation of window_scroll that works based on screen lines.
4236 See the comment of window_scroll for parameter descriptions. */
4238 static void
4239 window_scroll_line_based (window, n, whole, noerror)
4240 Lisp_Object window;
4241 int n;
4242 int whole;
4243 int noerror;
4245 register struct window *w = XWINDOW (window);
4246 register int opoint = PT, opoint_byte = PT_BYTE;
4247 register int pos, pos_byte;
4248 register int ht = window_internal_height (w);
4249 register Lisp_Object tem;
4250 int lose;
4251 Lisp_Object bolp;
4252 int startpos;
4253 struct position posit;
4254 int original_vpos;
4256 /* If scrolling screen-fulls, compute the number of lines to
4257 scroll from the window's height. */
4258 if (whole)
4259 n *= max (1, ht - next_screen_context_lines);
4261 startpos = marker_position (w->start);
4263 posit = *compute_motion (startpos, 0, 0, 0,
4264 PT, ht, 0,
4265 window_internal_width (w), XINT (w->hscroll),
4266 0, w);
4267 original_vpos = posit.vpos;
4269 XSETFASTINT (tem, PT);
4270 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4272 if (NILP (tem))
4274 Fvertical_motion (make_number (- (ht / 2)), window);
4275 startpos = PT;
4278 SET_PT (startpos);
4279 lose = n < 0 && PT == BEGV;
4280 Fvertical_motion (make_number (n), window);
4281 pos = PT;
4282 pos_byte = PT_BYTE;
4283 bolp = Fbolp ();
4284 SET_PT_BOTH (opoint, opoint_byte);
4286 if (lose)
4288 if (noerror)
4289 return;
4290 else
4291 Fsignal (Qbeginning_of_buffer, Qnil);
4294 if (pos < ZV)
4296 int this_scroll_margin = scroll_margin;
4298 /* Don't use a scroll margin that is negative or too large. */
4299 if (this_scroll_margin < 0)
4300 this_scroll_margin = 0;
4302 if (XINT (w->height) < 4 * scroll_margin)
4303 this_scroll_margin = XINT (w->height) / 4;
4305 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4306 w->start_at_line_beg = bolp;
4307 w->update_mode_line = Qt;
4308 XSETFASTINT (w->last_modified, 0);
4309 XSETFASTINT (w->last_overlay_modified, 0);
4310 /* Set force_start so that redisplay_window will run
4311 the window-scroll-functions. */
4312 w->force_start = Qt;
4314 if (whole && !NILP (Vscroll_preserve_screen_position))
4316 SET_PT_BOTH (pos, pos_byte);
4317 Fvertical_motion (make_number (original_vpos), window);
4319 /* If we scrolled forward, put point enough lines down
4320 that it is outside the scroll margin. */
4321 else if (n > 0)
4323 int top_margin;
4325 if (this_scroll_margin > 0)
4327 SET_PT_BOTH (pos, pos_byte);
4328 Fvertical_motion (make_number (this_scroll_margin), window);
4329 top_margin = PT;
4331 else
4332 top_margin = pos;
4334 if (top_margin <= opoint)
4335 SET_PT_BOTH (opoint, opoint_byte);
4336 else if (!NILP (Vscroll_preserve_screen_position))
4338 SET_PT_BOTH (pos, pos_byte);
4339 Fvertical_motion (make_number (original_vpos), window);
4341 else
4342 SET_PT (top_margin);
4344 else if (n < 0)
4346 int bottom_margin;
4348 /* If we scrolled backward, put point near the end of the window
4349 but not within the scroll margin. */
4350 SET_PT_BOTH (pos, pos_byte);
4351 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4352 if (XFASTINT (tem) == ht - this_scroll_margin)
4353 bottom_margin = PT;
4354 else
4355 bottom_margin = PT + 1;
4357 if (bottom_margin > opoint)
4358 SET_PT_BOTH (opoint, opoint_byte);
4359 else
4361 if (!NILP (Vscroll_preserve_screen_position))
4363 SET_PT_BOTH (pos, pos_byte);
4364 Fvertical_motion (make_number (original_vpos), window);
4366 else
4367 Fvertical_motion (make_number (-1), window);
4371 else
4373 if (noerror)
4374 return;
4375 else
4376 Fsignal (Qend_of_buffer, Qnil);
4381 /* Scroll selected_window up or down. If N is nil, scroll a
4382 screen-full which is defined as the height of the window minus
4383 next_screen_context_lines. If N is the symbol `-', scroll.
4384 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4385 up. This is the guts of Fscroll_up and Fscroll_down. */
4387 static void
4388 scroll_command (n, direction)
4389 Lisp_Object n;
4390 int direction;
4392 int count = BINDING_STACK_SIZE ();
4394 xassert (abs (direction) == 1);
4396 /* If selected window's buffer isn't current, make it current for
4397 the moment. But don't screw up if window_scroll gets an error. */
4398 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4400 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4401 Fset_buffer (XWINDOW (selected_window)->buffer);
4403 /* Make redisplay consider other windows than just selected_window. */
4404 ++windows_or_buffers_changed;
4407 if (NILP (n))
4408 window_scroll (selected_window, direction, 1, 0);
4409 else if (EQ (n, Qminus))
4410 window_scroll (selected_window, -direction, 1, 0);
4411 else
4413 n = Fprefix_numeric_value (n);
4414 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4417 unbind_to (count, Qnil);
4420 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
4421 doc: /* Scroll text of current window upward ARG lines; or near full screen if no ARG.
4422 A near full screen is `next-screen-context-lines' less than a full screen.
4423 Negative ARG means scroll downward.
4424 If ARG is the atom `-', scroll downward by nearly full screen.
4425 When calling from a program, supply as argument a number, nil, or `-'. */)
4426 (arg)
4427 Lisp_Object arg;
4429 scroll_command (arg, 1);
4430 return Qnil;
4433 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
4434 doc: /* Scroll text of current window down ARG lines; or near full screen if no ARG.
4435 A near full screen is `next-screen-context-lines' less than a full screen.
4436 Negative ARG means scroll upward.
4437 If ARG is the atom `-', scroll upward by nearly full screen.
4438 When calling from a program, supply as argument a number, nil, or `-'. */)
4439 (arg)
4440 Lisp_Object arg;
4442 scroll_command (arg, -1);
4443 return Qnil;
4446 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4447 doc: /* Return the other window for \"other window scroll\" commands.
4448 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4449 specifies the window.
4450 If `other-window-scroll-buffer' is non-nil, a window
4451 showing that buffer is used. */)
4454 Lisp_Object window;
4456 if (MINI_WINDOW_P (XWINDOW (selected_window))
4457 && !NILP (Vminibuf_scroll_window))
4458 window = Vminibuf_scroll_window;
4459 /* If buffer is specified, scroll that buffer. */
4460 else if (!NILP (Vother_window_scroll_buffer))
4462 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4463 if (NILP (window))
4464 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4466 else
4468 /* Nothing specified; look for a neighboring window on the same
4469 frame. */
4470 window = Fnext_window (selected_window, Qnil, Qnil);
4472 if (EQ (window, selected_window))
4473 /* That didn't get us anywhere; look for a window on another
4474 visible frame. */
4476 window = Fnext_window (window, Qnil, Qt);
4477 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4478 && ! EQ (window, selected_window));
4481 CHECK_LIVE_WINDOW (window);
4483 if (EQ (window, selected_window))
4484 error ("There is no other window");
4486 return window;
4489 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4490 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4491 A near full screen is `next-screen-context-lines' less than a full screen.
4492 The next window is the one below the current one; or the one at the top
4493 if the current one is at the bottom. Negative ARG means scroll downward.
4494 If ARG is the atom `-', scroll downward by nearly full screen.
4495 When calling from a program, supply as argument a number, nil, or `-'.
4497 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4498 specifies the window to scroll.
4499 If `other-window-scroll-buffer' is non-nil, scroll the window
4500 showing that buffer, popping the buffer up if necessary. */)
4501 (arg)
4502 Lisp_Object arg;
4504 Lisp_Object window;
4505 struct window *w;
4506 int count = BINDING_STACK_SIZE ();
4508 window = Fother_window_for_scrolling ();
4509 w = XWINDOW (window);
4511 /* Don't screw up if window_scroll gets an error. */
4512 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4513 ++windows_or_buffers_changed;
4515 Fset_buffer (w->buffer);
4516 SET_PT (marker_position (w->pointm));
4518 if (NILP (arg))
4519 window_scroll (window, 1, 1, 1);
4520 else if (EQ (arg, Qminus))
4521 window_scroll (window, -1, 1, 1);
4522 else
4524 if (CONSP (arg))
4525 arg = Fcar (arg);
4526 CHECK_NUMBER (arg);
4527 window_scroll (window, XINT (arg), 0, 1);
4530 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4531 unbind_to (count, Qnil);
4533 return Qnil;
4536 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
4537 doc: /* Scroll selected window display ARG columns left.
4538 Default for ARG is window width minus 2.
4539 Value is the total amount of leftward horizontal scrolling in
4540 effect after the change.
4541 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4542 a lower bound for automatic scrolling, i.e. automatic scrolling
4543 will not scroll a window to a column less than the value returned
4544 by this function. */)
4545 (arg)
4546 register Lisp_Object arg;
4548 Lisp_Object result;
4549 int hscroll;
4550 struct window *w = XWINDOW (selected_window);
4552 if (NILP (arg))
4553 XSETFASTINT (arg, window_internal_width (w) - 2);
4554 else
4555 arg = Fprefix_numeric_value (arg);
4557 hscroll = XINT (w->hscroll) + XINT (arg);
4558 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4560 if (interactive_p (0))
4561 w->min_hscroll = w->hscroll;
4563 return result;
4566 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
4567 doc: /* Scroll selected window display ARG columns right.
4568 Default for ARG is window width minus 2.
4569 Value is the total amount of leftward horizontal scrolling in
4570 effect after the change.
4571 If `automatic-hscrolling' is non-nil, the argument ARG modifies
4572 a lower bound for automatic scrolling, i.e. automatic scrolling
4573 will not scroll a window to a column less than the value returned
4574 by this function. */)
4575 (arg)
4576 register Lisp_Object arg;
4578 Lisp_Object result;
4579 int hscroll;
4580 struct window *w = XWINDOW (selected_window);
4582 if (NILP (arg))
4583 XSETFASTINT (arg, window_internal_width (w) - 2);
4584 else
4585 arg = Fprefix_numeric_value (arg);
4587 hscroll = XINT (w->hscroll) - XINT (arg);
4588 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4590 if (interactive_p (0))
4591 w->min_hscroll = w->hscroll;
4593 return result;
4596 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
4597 doc: /* Return the window which was selected when entering the minibuffer.
4598 Returns nil, if current window is not a minibuffer window. */)
4601 if (minibuf_level > 0
4602 && MINI_WINDOW_P (XWINDOW (selected_window))
4603 && !NILP (minibuf_selected_window)
4604 && WINDOW_LIVE_P (minibuf_selected_window))
4605 return minibuf_selected_window;
4607 return Qnil;
4610 /* Value is the number of lines actually displayed in window W,
4611 as opposed to its height. */
4613 static int
4614 displayed_window_lines (w)
4615 struct window *w;
4617 struct it it;
4618 struct text_pos start;
4619 int height = window_box_height (w);
4620 struct buffer *old_buffer;
4621 int bottom_y;
4623 if (XBUFFER (w->buffer) != current_buffer)
4625 old_buffer = current_buffer;
4626 set_buffer_internal (XBUFFER (w->buffer));
4628 else
4629 old_buffer = NULL;
4631 /* In case W->start is out of the accessible range, do something
4632 reasonable. This happens in Info mode when Info-scroll-down
4633 calls (recenter -1) while W->start is 1. */
4634 if (XMARKER (w->start)->charpos < BEGV)
4635 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4636 else if (XMARKER (w->start)->charpos > ZV)
4637 SET_TEXT_POS (start, ZV, ZV_BYTE);
4638 else
4639 SET_TEXT_POS_FROM_MARKER (start, w->start);
4641 start_display (&it, w, start);
4642 move_it_vertically (&it, height);
4643 bottom_y = line_bottom_y (&it);
4645 /* Add in empty lines at the bottom of the window. */
4646 if (bottom_y < height)
4648 int uy = CANON_Y_UNIT (it.f);
4649 it.vpos += (height - bottom_y + uy - 1) / uy;
4652 if (old_buffer)
4653 set_buffer_internal (old_buffer);
4655 return it.vpos;
4659 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
4660 doc: /* Center point in window and redisplay frame.
4661 With prefix argument ARG, recenter putting point on screen line ARG
4662 relative to the current window. If ARG is negative, it counts up from the
4663 bottom of the window. (ARG should be less than the height of the window.)
4665 If ARG is omitted or nil, erase the entire frame and then
4666 redraw with point in the center of the current window.
4667 Just C-u as prefix means put point in the center of the window
4668 and redisplay normally--don't erase and redraw the frame. */)
4669 (arg)
4670 register Lisp_Object arg;
4672 struct window *w = XWINDOW (selected_window);
4673 struct buffer *buf = XBUFFER (w->buffer);
4674 struct buffer *obuf = current_buffer;
4675 int center_p = 0;
4676 int charpos, bytepos;
4678 /* If redisplay is suppressed due to an error, try again. */
4679 obuf->display_error_modiff = 0;
4681 if (NILP (arg))
4683 int i;
4685 /* Invalidate pixel data calculated for all compositions. */
4686 for (i = 0; i < n_compositions; i++)
4687 composition_table[i]->font = NULL;
4689 Fredraw_frame (w->frame);
4690 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
4691 center_p = 1;
4693 else if (CONSP (arg)) /* Just C-u. */
4694 center_p = 1;
4695 else
4697 arg = Fprefix_numeric_value (arg);
4698 CHECK_NUMBER (arg);
4701 set_buffer_internal (buf);
4703 /* Handle centering on a graphical frame specially. Such frames can
4704 have variable-height lines and centering point on the basis of
4705 line counts would lead to strange effects. */
4706 if (FRAME_WINDOW_P (XFRAME (w->frame)))
4708 if (center_p)
4710 struct it it;
4711 struct text_pos pt;
4713 SET_TEXT_POS (pt, PT, PT_BYTE);
4714 start_display (&it, w, pt);
4715 move_it_vertically (&it, - window_box_height (w) / 2);
4716 charpos = IT_CHARPOS (it);
4717 bytepos = IT_BYTEPOS (it);
4719 else if (XINT (arg) < 0)
4721 struct it it;
4722 struct text_pos pt;
4723 int y0, y1, h, nlines;
4725 SET_TEXT_POS (pt, PT, PT_BYTE);
4726 start_display (&it, w, pt);
4727 y0 = it.current_y;
4729 /* The amount of pixels we have to move back is the window
4730 height minus what's displayed in the line containing PT,
4731 and the lines below. */
4732 nlines = - XINT (arg) - 1;
4733 move_it_by_lines (&it, nlines, 1);
4735 y1 = line_bottom_y (&it);
4737 /* If we can't move down NLINES lines because we hit
4738 the end of the buffer, count in some empty lines. */
4739 if (it.vpos < nlines)
4740 y1 += (nlines - it.vpos) * CANON_Y_UNIT (it.f);
4742 h = window_box_height (w) - (y1 - y0);
4744 start_display (&it, w, pt);
4745 move_it_vertically (&it, - h);
4746 charpos = IT_CHARPOS (it);
4747 bytepos = IT_BYTEPOS (it);
4749 else
4751 struct position pos;
4752 pos = *vmotion (PT, - XINT (arg), w);
4753 charpos = pos.bufpos;
4754 bytepos = pos.bytepos;
4757 else
4759 struct position pos;
4760 int ht = window_internal_height (w);
4762 if (center_p)
4763 arg = make_number (ht / 2);
4764 else if (XINT (arg) < 0)
4765 arg = make_number (XINT (arg) + ht);
4767 pos = *vmotion (PT, - XINT (arg), w);
4768 charpos = pos.bufpos;
4769 bytepos = pos.bytepos;
4772 /* Set the new window start. */
4773 set_marker_both (w->start, w->buffer, charpos, bytepos);
4774 w->window_end_valid = Qnil;
4775 w->force_start = Qt;
4776 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
4777 w->start_at_line_beg = Qt;
4778 else
4779 w->start_at_line_beg = Qnil;
4781 set_buffer_internal (obuf);
4782 return Qnil;
4786 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
4787 0, 1, 0,
4788 doc: /* Return the height in lines of the text display area of WINDOW.
4789 This doesn't include the mode-line (or header-line if any) or any
4790 partial-height lines in the text display area. */)
4791 (window)
4792 Lisp_Object window;
4794 struct window *w = decode_window (window);
4795 int pixel_height = window_box_height (w);
4796 int line_height = pixel_height / CANON_Y_UNIT (XFRAME (w->frame));
4797 return make_number (line_height);
4802 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
4803 1, 1, "P",
4804 doc: /* Position point relative to window.
4805 With no argument, position point at center of window.
4806 An argument specifies vertical position within the window;
4807 zero means top of window, negative means relative to bottom of window. */)
4808 (arg)
4809 Lisp_Object arg;
4811 struct window *w = XWINDOW (selected_window);
4812 int lines, start;
4813 Lisp_Object window;
4815 window = selected_window;
4816 start = marker_position (w->start);
4817 if (start < BEGV || start > ZV)
4819 int height = window_internal_height (w);
4820 Fvertical_motion (make_number (- (height / 2)), window);
4821 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
4822 w->start_at_line_beg = Fbolp ();
4823 w->force_start = Qt;
4825 else
4826 Fgoto_char (w->start);
4828 lines = displayed_window_lines (w);
4829 if (NILP (arg))
4830 XSETFASTINT (arg, lines / 2);
4831 else
4833 arg = Fprefix_numeric_value (arg);
4834 if (XINT (arg) < 0)
4835 XSETINT (arg, XINT (arg) + lines);
4838 /* Skip past a partially visible first line. */
4839 if (w->vscroll)
4840 XSETINT (arg, XINT (arg) + 1);
4842 return Fvertical_motion (arg, window);
4847 /***********************************************************************
4848 Window Configuration
4849 ***********************************************************************/
4851 struct save_window_data
4853 EMACS_INT size_from_Lisp_Vector_struct;
4854 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4855 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
4856 Lisp_Object frame_tool_bar_lines;
4857 Lisp_Object selected_frame;
4858 Lisp_Object current_window;
4859 Lisp_Object current_buffer;
4860 Lisp_Object minibuf_scroll_window;
4861 Lisp_Object minibuf_selected_window;
4862 Lisp_Object root_window;
4863 Lisp_Object focus_frame;
4864 /* Record the values of window-min-width and window-min-height
4865 so that window sizes remain consistent with them. */
4866 Lisp_Object min_width, min_height;
4867 /* A vector, each of whose elements is a struct saved_window
4868 for one window. */
4869 Lisp_Object saved_windows;
4872 /* This is saved as a Lisp_Vector */
4873 struct saved_window
4875 /* these first two must agree with struct Lisp_Vector in lisp.h */
4876 EMACS_INT size_from_Lisp_Vector_struct;
4877 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4879 Lisp_Object window;
4880 Lisp_Object buffer, start, pointm, mark;
4881 Lisp_Object left, top, width, height, hscroll, min_hscroll;
4882 Lisp_Object parent, prev;
4883 Lisp_Object start_at_line_beg;
4884 Lisp_Object display_table;
4885 Lisp_Object orig_top, orig_height;
4888 #define SAVED_WINDOW_VECTOR_SIZE 17 /* Arg to Fmake_vector */
4890 #define SAVED_WINDOW_N(swv,n) \
4891 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4893 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
4894 doc: /* Return t if OBJECT is a window-configuration object. */)
4895 (object)
4896 Lisp_Object object;
4898 if (WINDOW_CONFIGURATIONP (object))
4899 return Qt;
4900 return Qnil;
4903 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
4904 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
4905 (config)
4906 Lisp_Object config;
4908 register struct save_window_data *data;
4909 struct Lisp_Vector *saved_windows;
4911 if (! WINDOW_CONFIGURATIONP (config))
4912 wrong_type_argument (Qwindow_configuration_p, config);
4914 data = (struct save_window_data *) XVECTOR (config);
4915 saved_windows = XVECTOR (data->saved_windows);
4916 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4919 DEFUN ("set-window-configuration", Fset_window_configuration,
4920 Sset_window_configuration, 1, 1, 0,
4921 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
4922 CONFIGURATION must be a value previously returned
4923 by `current-window-configuration' (which see).
4924 If CONFIGURATION was made from a frame that is now deleted,
4925 only frame-independent values can be restored. In this case,
4926 the return value is nil. Otherwise the value is t. */)
4927 (configuration)
4928 Lisp_Object configuration;
4930 register struct save_window_data *data;
4931 struct Lisp_Vector *saved_windows;
4932 Lisp_Object new_current_buffer;
4933 Lisp_Object frame;
4934 FRAME_PTR f;
4935 int old_point = -1;
4937 while (!WINDOW_CONFIGURATIONP (configuration))
4938 wrong_type_argument (Qwindow_configuration_p, configuration);
4940 data = (struct save_window_data *) XVECTOR (configuration);
4941 saved_windows = XVECTOR (data->saved_windows);
4943 new_current_buffer = data->current_buffer;
4944 if (NILP (XBUFFER (new_current_buffer)->name))
4945 new_current_buffer = Qnil;
4946 else
4948 if (XBUFFER (new_current_buffer) == current_buffer)
4949 old_point = PT;
4952 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4953 f = XFRAME (frame);
4955 /* If f is a dead frame, don't bother rebuilding its window tree.
4956 However, there is other stuff we should still try to do below. */
4957 if (FRAME_LIVE_P (f))
4959 register struct window *w;
4960 register struct saved_window *p;
4961 struct window *root_window;
4962 struct window **leaf_windows;
4963 int n_leaf_windows;
4964 int k, i, n;
4966 /* If the frame has been resized since this window configuration was
4967 made, we change the frame to the size specified in the
4968 configuration, restore the configuration, and then resize it
4969 back. We keep track of the prevailing height in these variables. */
4970 int previous_frame_height = FRAME_HEIGHT (f);
4971 int previous_frame_width = FRAME_WIDTH (f);
4972 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
4973 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
4975 /* The mouse highlighting code could get screwed up
4976 if it runs during this. */
4977 BLOCK_INPUT;
4979 if (XFASTINT (data->frame_height) != previous_frame_height
4980 || XFASTINT (data->frame_width) != previous_frame_width)
4981 change_frame_size (f, XFASTINT (data->frame_height),
4982 XFASTINT (data->frame_width), 0, 0, 0);
4983 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4984 if (XFASTINT (data->frame_menu_bar_lines)
4985 != previous_frame_menu_bar_lines)
4986 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
4987 #ifdef HAVE_WINDOW_SYSTEM
4988 if (XFASTINT (data->frame_tool_bar_lines)
4989 != previous_frame_tool_bar_lines)
4990 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
4991 #endif
4992 #endif
4994 /* "Swap out" point from the selected window
4995 into its buffer. We do this now, before
4996 restoring the window contents, and prevent it from
4997 being done later on when we select a new window. */
4998 if (! NILP (XWINDOW (selected_window)->buffer))
5000 w = XWINDOW (selected_window);
5001 set_marker_both (w->pointm,
5002 w->buffer,
5003 BUF_PT (XBUFFER (w->buffer)),
5004 BUF_PT_BYTE (XBUFFER (w->buffer)));
5007 windows_or_buffers_changed++;
5008 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5010 /* Problem: Freeing all matrices and later allocating them again
5011 is a serious redisplay flickering problem. What we would
5012 really like to do is to free only those matrices not reused
5013 below. */
5014 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5015 leaf_windows
5016 = (struct window **) alloca (count_windows (root_window)
5017 * sizeof (struct window *));
5018 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5020 /* Temporarily avoid any problems with windows that are smaller
5021 than they are supposed to be. */
5022 window_min_height = 1;
5023 window_min_width = 1;
5025 /* Kludge Alert!
5026 Mark all windows now on frame as "deleted".
5027 Restoring the new configuration "undeletes" any that are in it.
5029 Save their current buffers in their height fields, since we may
5030 need it later, if a buffer saved in the configuration is now
5031 dead. */
5032 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5034 for (k = 0; k < saved_windows->size; k++)
5036 p = SAVED_WINDOW_N (saved_windows, k);
5037 w = XWINDOW (p->window);
5038 w->next = Qnil;
5040 if (!NILP (p->parent))
5041 w->parent = SAVED_WINDOW_N (saved_windows,
5042 XFASTINT (p->parent))->window;
5043 else
5044 w->parent = Qnil;
5046 if (!NILP (p->prev))
5048 w->prev = SAVED_WINDOW_N (saved_windows,
5049 XFASTINT (p->prev))->window;
5050 XWINDOW (w->prev)->next = p->window;
5052 else
5054 w->prev = Qnil;
5055 if (!NILP (w->parent))
5057 if (EQ (p->width, XWINDOW (w->parent)->width))
5059 XWINDOW (w->parent)->vchild = p->window;
5060 XWINDOW (w->parent)->hchild = Qnil;
5062 else
5064 XWINDOW (w->parent)->hchild = p->window;
5065 XWINDOW (w->parent)->vchild = Qnil;
5070 /* If we squirreled away the buffer in the window's height,
5071 restore it now. */
5072 if (BUFFERP (w->height))
5073 w->buffer = w->height;
5074 w->left = p->left;
5075 w->top = p->top;
5076 w->width = p->width;
5077 w->height = p->height;
5078 w->hscroll = p->hscroll;
5079 w->min_hscroll = p->min_hscroll;
5080 w->display_table = p->display_table;
5081 w->orig_top = p->orig_top;
5082 w->orig_height = p->orig_height;
5083 XSETFASTINT (w->last_modified, 0);
5084 XSETFASTINT (w->last_overlay_modified, 0);
5086 /* Reinstall the saved buffer and pointers into it. */
5087 if (NILP (p->buffer))
5088 w->buffer = p->buffer;
5089 else
5091 if (!NILP (XBUFFER (p->buffer)->name))
5092 /* If saved buffer is alive, install it. */
5094 w->buffer = p->buffer;
5095 w->start_at_line_beg = p->start_at_line_beg;
5096 set_marker_restricted (w->start, p->start, w->buffer);
5097 set_marker_restricted (w->pointm, p->pointm, w->buffer);
5098 Fset_marker (XBUFFER (w->buffer)->mark,
5099 p->mark, w->buffer);
5101 /* As documented in Fcurrent_window_configuration, don't
5102 save the location of point in the buffer which was current
5103 when the window configuration was recorded. */
5104 if (!EQ (p->buffer, new_current_buffer)
5105 && XBUFFER (p->buffer) == current_buffer)
5106 Fgoto_char (w->pointm);
5108 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
5109 /* Else unless window has a live buffer, get one. */
5111 w->buffer = Fcdr (Fcar (Vbuffer_alist));
5112 /* This will set the markers to beginning of visible
5113 range. */
5114 set_marker_restricted (w->start, make_number (0), w->buffer);
5115 set_marker_restricted (w->pointm, make_number (0),w->buffer);
5116 w->start_at_line_beg = Qt;
5118 else
5119 /* Keeping window's old buffer; make sure the markers
5120 are real. */
5122 /* Set window markers at start of visible range. */
5123 if (XMARKER (w->start)->buffer == 0)
5124 set_marker_restricted (w->start, make_number (0),
5125 w->buffer);
5126 if (XMARKER (w->pointm)->buffer == 0)
5127 set_marker_restricted_both (w->pointm, w->buffer,
5128 BUF_PT (XBUFFER (w->buffer)),
5129 BUF_PT_BYTE (XBUFFER (w->buffer)));
5130 w->start_at_line_beg = Qt;
5135 FRAME_ROOT_WINDOW (f) = data->root_window;
5136 /* Prevent "swapping out point" in the old selected window
5137 using the buffer that has been restored into it.
5138 That swapping out has already been done,
5139 near the beginning of this function. */
5140 selected_window = Qnil;
5141 Fselect_window (data->current_window);
5142 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
5143 = selected_window;
5145 if (NILP (data->focus_frame)
5146 || (FRAMEP (data->focus_frame)
5147 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5148 Fredirect_frame_focus (frame, data->focus_frame);
5150 #if 0 /* I don't understand why this is needed, and it causes problems
5151 when the frame's old selected window has been deleted. */
5152 if (f != selected_frame && FRAME_WINDOW_P (f))
5153 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
5154 0, 0);
5155 #endif
5157 /* Set the screen height to the value it had before this function. */
5158 if (previous_frame_height != FRAME_HEIGHT (f)
5159 || previous_frame_width != FRAME_WIDTH (f))
5160 change_frame_size (f, previous_frame_height, previous_frame_width,
5161 0, 0, 0);
5162 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5163 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5164 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5165 make_number (0));
5166 #ifdef HAVE_WINDOW_SYSTEM
5167 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5168 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5169 make_number (0));
5170 #endif
5171 #endif
5173 /* Now, free glyph matrices in windows that were not reused. */
5174 for (i = n = 0; i < n_leaf_windows; ++i)
5176 if (NILP (leaf_windows[i]->buffer))
5178 /* Assert it's not reused as a combination. */
5179 xassert (NILP (leaf_windows[i]->hchild)
5180 && NILP (leaf_windows[i]->vchild));
5181 free_window_matrices (leaf_windows[i]);
5183 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5184 ++n;
5187 /* If more than one window shows the new and old current buffer,
5188 don't try to preserve point in that buffer. */
5189 if (old_point > 0 && n > 1)
5190 old_point = -1;
5192 adjust_glyphs (f);
5194 UNBLOCK_INPUT;
5196 /* Fselect_window will have made f the selected frame, so we
5197 reselect the proper frame here. Fhandle_switch_frame will change the
5198 selected window too, but that doesn't make the call to
5199 Fselect_window above totally superfluous; it still sets f's
5200 selected window. */
5201 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5202 do_switch_frame (data->selected_frame, 0, 0);
5204 if (! NILP (Vwindow_configuration_change_hook)
5205 && ! NILP (Vrun_hooks))
5206 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
5209 if (!NILP (new_current_buffer))
5211 Fset_buffer (new_current_buffer);
5213 /* If the buffer that is current now is the same
5214 that was current before setting the window configuration,
5215 don't alter its PT. */
5216 if (old_point >= 0)
5217 SET_PT (old_point);
5220 /* Restore the minimum heights recorded in the configuration. */
5221 window_min_height = XINT (data->min_height);
5222 window_min_width = XINT (data->min_width);
5224 Vminibuf_scroll_window = data->minibuf_scroll_window;
5225 minibuf_selected_window = data->minibuf_selected_window;
5227 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5230 /* Mark all windows now on frame as deleted
5231 by setting their buffers to nil. */
5233 void
5234 delete_all_subwindows (w)
5235 register struct window *w;
5237 if (!NILP (w->next))
5238 delete_all_subwindows (XWINDOW (w->next));
5239 if (!NILP (w->vchild))
5240 delete_all_subwindows (XWINDOW (w->vchild));
5241 if (!NILP (w->hchild))
5242 delete_all_subwindows (XWINDOW (w->hchild));
5244 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
5246 if (!NILP (w->buffer))
5247 unshow_buffer (w);
5249 /* We set all three of these fields to nil, to make sure that we can
5250 distinguish this dead window from any live window. Live leaf
5251 windows will have buffer set, and combination windows will have
5252 vchild or hchild set. */
5253 w->buffer = Qnil;
5254 w->vchild = Qnil;
5255 w->hchild = Qnil;
5257 Vwindow_list = Qnil;
5260 static int
5261 count_windows (window)
5262 register struct window *window;
5264 register int count = 1;
5265 if (!NILP (window->next))
5266 count += count_windows (XWINDOW (window->next));
5267 if (!NILP (window->vchild))
5268 count += count_windows (XWINDOW (window->vchild));
5269 if (!NILP (window->hchild))
5270 count += count_windows (XWINDOW (window->hchild));
5271 return count;
5275 /* Fill vector FLAT with leaf windows under W, starting at index I.
5276 Value is last index + 1. */
5278 static int
5279 get_leaf_windows (w, flat, i)
5280 struct window *w;
5281 struct window **flat;
5282 int i;
5284 while (w)
5286 if (!NILP (w->hchild))
5287 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5288 else if (!NILP (w->vchild))
5289 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5290 else
5291 flat[i++] = w;
5293 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5296 return i;
5300 /* Return a pointer to the glyph W's physical cursor is on. Value is
5301 null if W's current matrix is invalid, so that no meaningfull glyph
5302 can be returned. */
5304 struct glyph *
5305 get_phys_cursor_glyph (w)
5306 struct window *w;
5308 struct glyph_row *row;
5309 struct glyph *glyph;
5311 if (w->phys_cursor.vpos >= 0
5312 && w->phys_cursor.vpos < w->current_matrix->nrows
5313 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
5314 row->enabled_p)
5315 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
5316 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
5317 else
5318 glyph = NULL;
5320 return glyph;
5324 static int
5325 save_window_save (window, vector, i)
5326 Lisp_Object window;
5327 struct Lisp_Vector *vector;
5328 int i;
5330 register struct saved_window *p;
5331 register struct window *w;
5332 register Lisp_Object tem;
5334 for (;!NILP (window); window = w->next)
5336 p = SAVED_WINDOW_N (vector, i);
5337 w = XWINDOW (window);
5339 XSETFASTINT (w->temslot, i++);
5340 p->window = window;
5341 p->buffer = w->buffer;
5342 p->left = w->left;
5343 p->top = w->top;
5344 p->width = w->width;
5345 p->height = w->height;
5346 p->hscroll = w->hscroll;
5347 p->min_hscroll = w->min_hscroll;
5348 p->display_table = w->display_table;
5349 p->orig_top = w->orig_top;
5350 p->orig_height = w->orig_height;
5351 if (!NILP (w->buffer))
5353 /* Save w's value of point in the window configuration.
5354 If w is the selected window, then get the value of point
5355 from the buffer; pointm is garbage in the selected window. */
5356 if (EQ (window, selected_window))
5358 p->pointm = Fmake_marker ();
5359 set_marker_both (p->pointm, w->buffer,
5360 BUF_PT (XBUFFER (w->buffer)),
5361 BUF_PT_BYTE (XBUFFER (w->buffer)));
5363 else
5364 p->pointm = Fcopy_marker (w->pointm, Qnil);
5366 p->start = Fcopy_marker (w->start, Qnil);
5367 p->start_at_line_beg = w->start_at_line_beg;
5369 tem = XBUFFER (w->buffer)->mark;
5370 p->mark = Fcopy_marker (tem, Qnil);
5372 else
5374 p->pointm = Qnil;
5375 p->start = Qnil;
5376 p->mark = Qnil;
5377 p->start_at_line_beg = Qnil;
5380 if (NILP (w->parent))
5381 p->parent = Qnil;
5382 else
5383 p->parent = XWINDOW (w->parent)->temslot;
5385 if (NILP (w->prev))
5386 p->prev = Qnil;
5387 else
5388 p->prev = XWINDOW (w->prev)->temslot;
5390 if (!NILP (w->vchild))
5391 i = save_window_save (w->vchild, vector, i);
5392 if (!NILP (w->hchild))
5393 i = save_window_save (w->hchild, vector, i);
5396 return i;
5399 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
5400 Scurrent_window_configuration, 0, 1, 0,
5401 doc: /* Return an object representing the current window configuration of FRAME.
5402 If FRAME is nil or omitted, use the selected frame.
5403 This describes the number of windows, their sizes and current buffers,
5404 and for each displayed buffer, where display starts, and the positions of
5405 point and mark. An exception is made for point in the current buffer:
5406 its value is -not- saved.
5407 This also records the currently selected frame, and FRAME's focus
5408 redirection (see `redirect-frame-focus'). */)
5409 (frame)
5410 Lisp_Object frame;
5412 register Lisp_Object tem;
5413 register int n_windows;
5414 register struct save_window_data *data;
5415 register struct Lisp_Vector *vec;
5416 register int i;
5417 FRAME_PTR f;
5419 if (NILP (frame))
5420 frame = selected_frame;
5421 CHECK_LIVE_FRAME (frame);
5422 f = XFRAME (frame);
5424 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5425 vec = allocate_other_vector (VECSIZE (struct save_window_data));
5426 data = (struct save_window_data *)vec;
5428 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
5429 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
5430 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
5431 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
5432 data->selected_frame = selected_frame;
5433 data->current_window = FRAME_SELECTED_WINDOW (f);
5434 XSETBUFFER (data->current_buffer, current_buffer);
5435 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
5436 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
5437 data->root_window = FRAME_ROOT_WINDOW (f);
5438 data->focus_frame = FRAME_FOCUS_FRAME (f);
5439 XSETINT (data->min_height, window_min_height);
5440 XSETINT (data->min_width, window_min_width);
5441 tem = Fmake_vector (make_number (n_windows), Qnil);
5442 data->saved_windows = tem;
5443 for (i = 0; i < n_windows; i++)
5444 XVECTOR (tem)->contents[i]
5445 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
5446 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
5447 XSETWINDOW_CONFIGURATION (tem, data);
5448 return (tem);
5451 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
5452 0, UNEVALLED, 0,
5453 doc: /* Execute body, preserving window sizes and contents.
5454 Restore which buffer appears in which window, where display starts,
5455 and the value of point and mark for each window.
5456 Also restore the choice of selected window.
5457 Also restore which buffer is current.
5458 Does not restore the value of point in current buffer.
5459 usage: (save-window-excursion BODY ...) */)
5460 (args)
5461 Lisp_Object args;
5463 register Lisp_Object val;
5464 register int count = specpdl_ptr - specpdl;
5466 record_unwind_protect (Fset_window_configuration,
5467 Fcurrent_window_configuration (Qnil));
5468 val = Fprogn (args);
5469 return unbind_to (count, val);
5473 /***********************************************************************
5474 Marginal Areas
5475 ***********************************************************************/
5477 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
5478 2, 3, 0,
5479 doc: /* Set width of marginal areas of window WINDOW.
5480 If window is nil, set margins of the currently selected window.
5481 First parameter LEFT-WIDTH specifies the number of character
5482 cells to reserve for the left marginal area. Second parameter
5483 RIGHT-WIDTH does the same for the right marginal area.
5484 A nil width parameter means no margin. */)
5485 (window, left, right)
5486 Lisp_Object window, left, right;
5488 struct window *w = decode_window (window);
5490 if (!NILP (left))
5491 CHECK_NUMBER_OR_FLOAT (left);
5492 if (!NILP (right))
5493 CHECK_NUMBER_OR_FLOAT (right);
5495 /* Check widths < 0 and translate a zero width to nil.
5496 Margins that are too wide have to be checked elsewhere. */
5497 if ((INTEGERP (left) && XINT (left) < 0)
5498 || (FLOATP (left) && XFLOAT_DATA (left) <= 0))
5499 XSETFASTINT (left, 0);
5500 if (INTEGERP (left) && XFASTINT (left) == 0)
5501 left = Qnil;
5503 if ((INTEGERP (right) && XINT (right) < 0)
5504 || (FLOATP (right) && XFLOAT_DATA (right) <= 0))
5505 XSETFASTINT (right, 0);
5506 if (INTEGERP (right) && XFASTINT (right) == 0)
5507 right = Qnil;
5509 w->left_margin_width = left;
5510 w->right_margin_width = right;
5512 ++windows_or_buffers_changed;
5513 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5514 return Qnil;
5518 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
5519 0, 1, 0,
5520 doc: /* Get width of marginal areas of window WINDOW.
5521 If WINDOW is omitted or nil, use the currently selected window.
5522 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
5523 If a marginal area does not exist, its width will be returned
5524 as nil. */)
5525 (window)
5526 Lisp_Object window;
5528 struct window *w = decode_window (window);
5529 return Fcons (w->left_margin_width, w->right_margin_width);
5534 /***********************************************************************
5535 Smooth scrolling
5536 ***********************************************************************/
5538 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
5539 doc: /* Return the amount by which WINDOW is scrolled vertically.
5540 Use the selected window if WINDOW is nil or omitted.
5541 Value is a multiple of the canonical character height of WINDOW. */)
5542 (window)
5543 Lisp_Object window;
5545 Lisp_Object result;
5546 struct frame *f;
5547 struct window *w;
5549 if (NILP (window))
5550 window = selected_window;
5551 else
5552 CHECK_WINDOW (window);
5553 w = XWINDOW (window);
5554 f = XFRAME (w->frame);
5556 if (FRAME_WINDOW_P (f))
5557 result = CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
5558 else
5559 result = make_number (0);
5560 return result;
5564 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
5565 2, 2, 0,
5566 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
5567 WINDOW nil means use the selected window. VSCROLL is a non-negative
5568 multiple of the canonical character height of WINDOW. */)
5569 (window, vscroll)
5570 Lisp_Object window, vscroll;
5572 struct window *w;
5573 struct frame *f;
5575 if (NILP (window))
5576 window = selected_window;
5577 else
5578 CHECK_WINDOW (window);
5579 CHECK_NUMBER_OR_FLOAT (vscroll);
5581 w = XWINDOW (window);
5582 f = XFRAME (w->frame);
5584 if (FRAME_WINDOW_P (f))
5586 int old_dy = w->vscroll;
5588 w->vscroll = - CANON_Y_UNIT (f) * XFLOATINT (vscroll);
5589 w->vscroll = min (w->vscroll, 0);
5591 /* Adjust glyph matrix of the frame if the virtual display
5592 area becomes larger than before. */
5593 if (w->vscroll < 0 && w->vscroll < old_dy)
5594 adjust_glyphs (f);
5596 /* Prevent redisplay shortcuts. */
5597 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5600 return Fwindow_vscroll (window);
5604 /* Call FN for all leaf windows on frame F. FN is called with the
5605 first argument being a pointer to the leaf window, and with
5606 additional argument USER_DATA. Stops when FN returns 0. */
5608 void
5609 foreach_window (f, fn, user_data)
5610 struct frame *f;
5611 int (* fn) P_ ((struct window *, void *));
5612 void *user_data;
5614 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
5618 /* Helper function for foreach_window. Call FN for all leaf windows
5619 reachable from W. FN is called with the first argument being a
5620 pointer to the leaf window, and with additional argument USER_DATA.
5621 Stop when FN returns 0. Value is 0 if stopped by FN. */
5623 static int
5624 foreach_window_1 (w, fn, user_data)
5625 struct window *w;
5626 int (* fn) P_ ((struct window *, void *));
5627 void *user_data;
5629 int cont;
5631 for (cont = 1; w && cont;)
5633 if (!NILP (w->hchild))
5634 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
5635 else if (!NILP (w->vchild))
5636 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
5637 else
5638 cont = fn (w, user_data);
5640 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5643 return cont;
5647 /* Freeze or unfreeze the window start of W unless it is a
5648 mini-window or the selected window. FREEZE_P non-null means freeze
5649 the window start. */
5651 static int
5652 freeze_window_start (w, freeze_p)
5653 struct window *w;
5654 void *freeze_p;
5656 if (w == XWINDOW (selected_window)
5657 || MINI_WINDOW_P (w)
5658 || (MINI_WINDOW_P (XWINDOW (selected_window))
5659 && ! NILP (Vminibuf_scroll_window)
5660 && w == XWINDOW (Vminibuf_scroll_window)))
5661 freeze_p = NULL;
5663 w->frozen_window_start_p = freeze_p != NULL;
5664 return 1;
5668 /* Freeze or unfreeze the window starts of all leaf windows on frame
5669 F, except the selected window and a mini-window. FREEZE_P non-zero
5670 means freeze the window start. */
5672 void
5673 freeze_window_starts (f, freeze_p)
5674 struct frame *f;
5675 int freeze_p;
5677 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
5681 /***********************************************************************
5682 Initialization
5683 ***********************************************************************/
5685 /* Return 1 if window configurations C1 and C2
5686 describe the same state of affairs. This is used by Fequal. */
5689 compare_window_configurations (c1, c2, ignore_positions)
5690 Lisp_Object c1, c2;
5691 int ignore_positions;
5693 register struct save_window_data *d1, *d2;
5694 struct Lisp_Vector *sw1, *sw2;
5695 int i;
5697 if (!WINDOW_CONFIGURATIONP (c1))
5698 wrong_type_argument (Qwindow_configuration_p, c1);
5699 if (!WINDOW_CONFIGURATIONP (c2))
5700 wrong_type_argument (Qwindow_configuration_p, c2);
5702 d1 = (struct save_window_data *) XVECTOR (c1);
5703 d2 = (struct save_window_data *) XVECTOR (c2);
5704 sw1 = XVECTOR (d1->saved_windows);
5705 sw2 = XVECTOR (d2->saved_windows);
5707 if (! EQ (d1->frame_width, d2->frame_width))
5708 return 0;
5709 if (! EQ (d1->frame_height, d2->frame_height))
5710 return 0;
5711 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
5712 return 0;
5713 if (! EQ (d1->selected_frame, d2->selected_frame))
5714 return 0;
5715 /* Don't compare the current_window field directly.
5716 Instead see w1_is_current and w2_is_current, below. */
5717 if (! EQ (d1->current_buffer, d2->current_buffer))
5718 return 0;
5719 if (! ignore_positions)
5721 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
5722 return 0;
5723 if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
5724 return 0;
5726 /* Don't compare the root_window field.
5727 We don't require the two configurations
5728 to use the same window object,
5729 and the two root windows must be equivalent
5730 if everything else compares equal. */
5731 if (! EQ (d1->focus_frame, d2->focus_frame))
5732 return 0;
5733 if (! EQ (d1->min_width, d2->min_width))
5734 return 0;
5735 if (! EQ (d1->min_height, d2->min_height))
5736 return 0;
5738 /* Verify that the two confis have the same number of windows. */
5739 if (sw1->size != sw2->size)
5740 return 0;
5742 for (i = 0; i < sw1->size; i++)
5744 struct saved_window *p1, *p2;
5745 int w1_is_current, w2_is_current;
5747 p1 = SAVED_WINDOW_N (sw1, i);
5748 p2 = SAVED_WINDOW_N (sw2, i);
5750 /* Verify that the current windows in the two
5751 configurations correspond to each other. */
5752 w1_is_current = EQ (d1->current_window, p1->window);
5753 w2_is_current = EQ (d2->current_window, p2->window);
5755 if (w1_is_current != w2_is_current)
5756 return 0;
5758 /* Verify that the corresponding windows do match. */
5759 if (! EQ (p1->buffer, p2->buffer))
5760 return 0;
5761 if (! EQ (p1->left, p2->left))
5762 return 0;
5763 if (! EQ (p1->top, p2->top))
5764 return 0;
5765 if (! EQ (p1->width, p2->width))
5766 return 0;
5767 if (! EQ (p1->height, p2->height))
5768 return 0;
5769 if (! EQ (p1->display_table, p2->display_table))
5770 return 0;
5771 if (! EQ (p1->parent, p2->parent))
5772 return 0;
5773 if (! EQ (p1->prev, p2->prev))
5774 return 0;
5775 if (! ignore_positions)
5777 if (! EQ (p1->hscroll, p2->hscroll))
5778 return 0;
5779 if (!EQ (p1->min_hscroll, p2->min_hscroll))
5780 return 0;
5781 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
5782 return 0;
5783 if (NILP (Fequal (p1->start, p2->start)))
5784 return 0;
5785 if (NILP (Fequal (p1->pointm, p2->pointm)))
5786 return 0;
5787 if (NILP (Fequal (p1->mark, p2->mark)))
5788 return 0;
5792 return 1;
5795 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
5796 Scompare_window_configurations, 2, 2, 0,
5797 doc: /* Compare two window configurations as regards the structure of windows.
5798 This function ignores details such as the values of point and mark
5799 and scrolling positions. */)
5800 (x, y)
5801 Lisp_Object x, y;
5803 if (compare_window_configurations (x, y, 1))
5804 return Qt;
5805 return Qnil;
5808 void
5809 init_window_once ()
5811 struct frame *f = make_terminal_frame ();
5812 XSETFRAME (selected_frame, f);
5813 Vterminal_frame = selected_frame;
5814 minibuf_window = f->minibuffer_window;
5815 selected_window = f->selected_window;
5816 last_nonminibuf_frame = f;
5818 window_initialized = 1;
5821 void
5822 init_window ()
5824 Vwindow_list = Qnil;
5827 void
5828 syms_of_window ()
5830 Qwindow_size_fixed = intern ("window-size-fixed");
5831 staticpro (&Qwindow_size_fixed);
5833 staticpro (&Qwindow_configuration_change_hook);
5834 Qwindow_configuration_change_hook
5835 = intern ("window-configuration-change-hook");
5837 Qwindowp = intern ("windowp");
5838 staticpro (&Qwindowp);
5840 Qwindow_configuration_p = intern ("window-configuration-p");
5841 staticpro (&Qwindow_configuration_p);
5843 Qwindow_live_p = intern ("window-live-p");
5844 staticpro (&Qwindow_live_p);
5846 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
5847 staticpro (&Qtemp_buffer_show_hook);
5849 staticpro (&Vwindow_list);
5851 minibuf_selected_window = Qnil;
5852 staticpro (&minibuf_selected_window);
5854 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
5855 doc: /* Non-nil means call as function to display a help buffer.
5856 The function is called with one argument, the buffer to be displayed.
5857 Used by `with-output-to-temp-buffer'.
5858 If this function is used, then it must do the entire job of showing
5859 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
5860 Vtemp_buffer_show_function = Qnil;
5862 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
5863 doc: /* If non-nil, function to call to handle `display-buffer'.
5864 It will receive two args, the buffer and a flag which if non-nil means
5865 that the currently selected window is not acceptable.
5866 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'
5867 work using this function. */);
5868 Vdisplay_buffer_function = Qnil;
5870 DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
5871 doc: /* *If non-nil, `display-buffer' should even the window heights.
5872 If nil, `display-buffer' will leave the window configuration alone. */);
5873 Veven_window_heights = Qt;
5875 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
5876 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
5877 Vminibuf_scroll_window = Qnil;
5879 DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
5880 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
5881 If the minibuffer is active, the `minibuffer-scroll-window' mode line
5882 is displayed in the `mode-line' face. */);
5883 mode_line_in_non_selected_windows = 1;
5885 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
5886 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
5887 Vother_window_scroll_buffer = Qnil;
5889 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
5890 doc: /* *Non-nil means `display-buffer' should make a separate frame. */);
5891 pop_up_frames = 0;
5893 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
5894 doc: /* *Non-nil means `display-buffer' should reuse frames.
5895 If the buffer in question is already displayed in a frame, raise that frame. */);
5896 display_buffer_reuse_frames = 0;
5898 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
5899 doc: /* Function to call to handle automatic new frame creation.
5900 It is called with no arguments and should return a newly created frame.
5902 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'
5903 where `pop-up-frame-alist' would hold the default frame parameters. */);
5904 Vpop_up_frame_function = Qnil;
5906 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
5907 doc: /* *List of buffer names that should have their own special frames.
5908 Displaying a buffer whose name is in this list makes a special frame for it
5909 using `special-display-function'. See also `special-display-regexps'.
5911 An element of the list can be a list instead of just a string.
5912 There are two ways to use a list as an element:
5913 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)
5914 In the first case, FRAME-PARAMETERS are used to create the frame.
5915 In the latter case, FUNCTION is called with BUFFER as the first argument,
5916 followed by OTHER-ARGS--it can display BUFFER in any way it likes.
5917 All this is done by the function found in `special-display-function'.
5919 If this variable appears \"not to work\", because you add a name to it
5920 but that buffer still appears in the selected window, look at the
5921 values of `same-window-buffer-names' and `same-window-regexps'.
5922 Those variables take precedence over this one. */);
5923 Vspecial_display_buffer_names = Qnil;
5925 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
5926 doc: /* *List of regexps saying which buffers should have their own special frames.
5927 If a buffer name matches one of these regexps, it gets its own frame.
5928 Displaying a buffer whose name is in this list makes a special frame for it
5929 using `special-display-function'.
5931 An element of the list can be a list instead of just a string.
5932 There are two ways to use a list as an element:
5933 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)
5934 In the first case, FRAME-PARAMETERS are used to create the frame.
5935 In the latter case, FUNCTION is called with the buffer as first argument,
5936 followed by OTHER-ARGS--it can display the buffer in any way it likes.
5937 All this is done by the function found in `special-display-function'.
5939 If this variable appears \"not to work\", because you add a regexp to it
5940 but the matching buffers still appear in the selected window, look at the
5941 values of `same-window-buffer-names' and `same-window-regexps'.
5942 Those variables take precedence over this one. */);
5943 Vspecial_display_regexps = Qnil;
5945 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
5946 doc: /* Function to call to make a new frame for a special buffer.
5947 It is called with two arguments, the buffer and optional buffer specific
5948 data, and should return a window displaying that buffer.
5949 The default value makes a separate frame for the buffer,
5950 using `special-display-frame-alist' to specify the frame parameters.
5952 A buffer is special if its is listed in `special-display-buffer-names'
5953 or matches a regexp in `special-display-regexps'. */);
5954 Vspecial_display_function = Qnil;
5956 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
5957 doc: /* *List of buffer names that should appear in the selected window.
5958 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'
5959 switches to it in the selected window, rather than making it appear
5960 in some other window.
5962 An element of the list can be a cons cell instead of just a string.
5963 Then the car must be a string, which specifies the buffer name.
5964 This is for compatibility with `special-display-buffer-names';
5965 the cdr of the cons cell is ignored.
5967 See also `same-window-regexps'. */);
5968 Vsame_window_buffer_names = Qnil;
5970 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
5971 doc: /* *List of regexps saying which buffers should appear in the selected window.
5972 If a buffer name matches one of these regexps, then displaying it
5973 using `display-buffer' or `pop-to-buffer' switches to it
5974 in the selected window, rather than making it appear in some other window.
5976 An element of the list can be a cons cell instead of just a string.
5977 Then the car must be a string, which specifies the buffer name.
5978 This is for compatibility with `special-display-buffer-names';
5979 the cdr of the cons cell is ignored.
5981 See also `same-window-buffer-names'. */);
5982 Vsame_window_regexps = Qnil;
5984 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
5985 doc: /* *Non-nil means display-buffer should make new windows. */);
5986 pop_up_windows = 1;
5988 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
5989 doc: /* *Number of lines of continuity when scrolling by screenfuls. */);
5990 next_screen_context_lines = 2;
5992 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
5993 doc: /* *display-buffer would prefer to split the largest window if this large.
5994 If there is only one window, it is split regardless of this value. */);
5995 split_height_threshold = 500;
5997 DEFVAR_INT ("window-min-height", &window_min_height,
5998 doc: /* *Delete any window less than this tall (including its mode line). */);
5999 window_min_height = 4;
6001 DEFVAR_INT ("window-min-width", &window_min_width,
6002 doc: /* *Delete any window less than this wide. */);
6003 window_min_width = 10;
6005 DEFVAR_LISP ("scroll-preserve-screen-position",
6006 &Vscroll_preserve_screen_position,
6007 doc: /* *Non-nil means scroll commands move point to keep its screen line unchanged. */);
6008 Vscroll_preserve_screen_position = Qnil;
6010 DEFVAR_LISP ("window-configuration-change-hook",
6011 &Vwindow_configuration_change_hook,
6012 doc: /* Functions to call when window configuration changes.
6013 The selected frame is the one whose configuration has changed. */);
6014 Vwindow_configuration_change_hook = Qnil;
6016 DEFVAR_BOOL ("window-size-fixed", &window_size_fixed,
6017 doc: /* Non-nil in a buffer means windows displaying the buffer are fixed-size.
6018 Emacs won't change the size of any window displaying that buffer,
6019 unless you explicitly change the size, or Emacs has no other choice.
6020 This variable automatically becomes buffer-local when set. */);
6021 Fmake_variable_buffer_local (Qwindow_size_fixed);
6022 window_size_fixed = 0;
6024 defsubr (&Sselected_window);
6025 defsubr (&Sminibuffer_window);
6026 defsubr (&Swindow_minibuffer_p);
6027 defsubr (&Swindowp);
6028 defsubr (&Swindow_live_p);
6029 defsubr (&Spos_visible_in_window_p);
6030 defsubr (&Swindow_buffer);
6031 defsubr (&Swindow_height);
6032 defsubr (&Swindow_width);
6033 defsubr (&Swindow_hscroll);
6034 defsubr (&Sset_window_hscroll);
6035 defsubr (&Swindow_redisplay_end_trigger);
6036 defsubr (&Sset_window_redisplay_end_trigger);
6037 defsubr (&Swindow_edges);
6038 defsubr (&Scoordinates_in_window_p);
6039 defsubr (&Swindow_at);
6040 defsubr (&Swindow_point);
6041 defsubr (&Swindow_start);
6042 defsubr (&Swindow_end);
6043 defsubr (&Sset_window_point);
6044 defsubr (&Sset_window_start);
6045 defsubr (&Swindow_dedicated_p);
6046 defsubr (&Sset_window_dedicated_p);
6047 defsubr (&Swindow_display_table);
6048 defsubr (&Sset_window_display_table);
6049 defsubr (&Snext_window);
6050 defsubr (&Sprevious_window);
6051 defsubr (&Sother_window);
6052 defsubr (&Sget_lru_window);
6053 defsubr (&Sget_largest_window);
6054 defsubr (&Sget_buffer_window);
6055 defsubr (&Sdelete_other_windows);
6056 defsubr (&Sdelete_windows_on);
6057 defsubr (&Sreplace_buffer_in_windows);
6058 defsubr (&Sdelete_window);
6059 defsubr (&Sset_window_buffer);
6060 defsubr (&Sselect_window);
6061 defsubr (&Sspecial_display_p);
6062 defsubr (&Ssame_window_p);
6063 defsubr (&Sdisplay_buffer);
6064 defsubr (&Ssplit_window);
6065 defsubr (&Senlarge_window);
6066 defsubr (&Sshrink_window);
6067 defsubr (&Sscroll_up);
6068 defsubr (&Sscroll_down);
6069 defsubr (&Sscroll_left);
6070 defsubr (&Sscroll_right);
6071 defsubr (&Sother_window_for_scrolling);
6072 defsubr (&Sscroll_other_window);
6073 defsubr (&Sminibuffer_selected_window);
6074 defsubr (&Srecenter);
6075 defsubr (&Swindow_text_height);
6076 defsubr (&Smove_to_window_line);
6077 defsubr (&Swindow_configuration_p);
6078 defsubr (&Swindow_configuration_frame);
6079 defsubr (&Sset_window_configuration);
6080 defsubr (&Scurrent_window_configuration);
6081 defsubr (&Ssave_window_excursion);
6082 defsubr (&Sset_window_margins);
6083 defsubr (&Swindow_margins);
6084 defsubr (&Swindow_vscroll);
6085 defsubr (&Sset_window_vscroll);
6086 defsubr (&Scompare_window_configurations);
6087 defsubr (&Swindow_list);
6090 void
6091 keys_of_window ()
6093 initial_define_key (control_x_map, '1', "delete-other-windows");
6094 initial_define_key (control_x_map, '2', "split-window");
6095 initial_define_key (control_x_map, '0', "delete-window");
6096 initial_define_key (control_x_map, 'o', "other-window");
6097 initial_define_key (control_x_map, '^', "enlarge-window");
6098 initial_define_key (control_x_map, '<', "scroll-left");
6099 initial_define_key (control_x_map, '>', "scroll-right");
6101 initial_define_key (global_map, Ctl ('V'), "scroll-up");
6102 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6103 initial_define_key (meta_map, 'v', "scroll-down");
6105 initial_define_key (global_map, Ctl('L'), "recenter");
6106 initial_define_key (meta_map, 'r', "move-to-window-line");