(texinfo-block-default): New var.
[emacs.git] / src / window.c
blob5257c1b0cdb26c1aeaf6fe47fecbdeba95d24fdb
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 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include "lisp.h"
24 #include "buffer.h"
25 #include "keyboard.h"
26 #include "frame.h"
27 #include "window.h"
28 #include "commands.h"
29 #include "indent.h"
30 #include "termchar.h"
31 #include "disptab.h"
32 #include "dispextern.h"
33 #include "blockinput.h"
34 #include "intervals.h"
36 #ifdef HAVE_X_WINDOWS
37 #include "xterm.h"
38 #endif /* HAVE_X_WINDOWS */
39 #ifdef WINDOWSNT
40 #include "w32term.h"
41 #endif
42 #ifdef MSDOS
43 #include "msdos.h"
44 #endif
45 #ifdef macintosh
46 #include "macterm.h"
47 #endif
49 #ifndef max
50 #define max(a, b) ((a) < (b) ? (b) : (a))
51 #endif
54 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
55 Lisp_Object Qwindow_size_fixed, Qleft_bitmap_area, Qright_bitmap_area;
56 extern Lisp_Object Qheight, Qwidth;
58 static struct window *decode_window P_ ((Lisp_Object));
59 static Lisp_Object select_window_1 P_ ((Lisp_Object, int));
60 static int count_windows P_ ((struct window *));
61 static int get_leaf_windows P_ ((struct window *, struct window **, int));
62 static void window_scroll P_ ((Lisp_Object, int, int, int));
63 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
64 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
65 static int window_min_size_1 P_ ((struct window *, int));
66 static int window_min_size P_ ((struct window *, int, int, int *));
67 static void size_window P_ ((Lisp_Object, int, int, int));
68 static int freeze_window_start P_ ((struct window *, void *));
69 static int window_fixed_size_p P_ ((struct window *, int, int));
70 static void enlarge_window P_ ((Lisp_Object, int, int));
71 static Lisp_Object window_list P_ ((void));
72 static int add_window_to_list P_ ((struct window *, void *));
73 static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
74 Lisp_Object));
75 static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
76 Lisp_Object, int));
77 static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
78 Lisp_Object *));
79 static int foreach_window_1 P_ ((struct window *,
80 int (* fn) (struct window *, void *),
81 void *));
83 /* This is the window in which the terminal's cursor should
84 be left when nothing is being done with it. This must
85 always be a leaf window, and its buffer is selected by
86 the top level editing loop at the end of each command.
88 This value is always the same as
89 FRAME_SELECTED_WINDOW (selected_frame). */
91 Lisp_Object selected_window;
93 /* A list of all windows for use by next_window and Fwindow_list.
94 Functions creating or deleting windows should invalidate this cache
95 by setting it to nil. */
97 Lisp_Object Vwindow_list;
99 /* The mini-buffer window of the selected frame.
100 Note that you cannot test for mini-bufferness of an arbitrary window
101 by comparing against this; but you can test for mini-bufferness of
102 the selected window. */
104 Lisp_Object minibuf_window;
106 /* Non-nil means it is the window for C-M-v to scroll
107 when the mini-buffer is selected. */
109 Lisp_Object Vminibuf_scroll_window;
111 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
113 Lisp_Object Vother_window_scroll_buffer;
115 /* Non-nil means it's function to call to display temp buffers. */
117 Lisp_Object Vtemp_buffer_show_function;
119 /* If a window gets smaller than either of these, it is removed. */
121 int window_min_height;
122 int window_min_width;
124 /* Nonzero implies Fdisplay_buffer should create windows. */
126 int pop_up_windows;
128 /* Nonzero implies make new frames for Fdisplay_buffer. */
130 int pop_up_frames;
132 /* Nonzero means reuse existing frames for displaying buffers. */
134 int display_buffer_reuse_frames;
136 /* Non-nil means use this function instead of default */
138 Lisp_Object Vpop_up_frame_function;
140 /* Function to call to handle Fdisplay_buffer. */
142 Lisp_Object Vdisplay_buffer_function;
144 /* List of buffer *names* for buffers that should have their own frames. */
146 Lisp_Object Vspecial_display_buffer_names;
148 /* List of regexps for buffer names that should have their own frames. */
150 Lisp_Object Vspecial_display_regexps;
152 /* Function to pop up a special frame. */
154 Lisp_Object Vspecial_display_function;
156 /* List of buffer *names* for buffers to appear in selected window. */
158 Lisp_Object Vsame_window_buffer_names;
160 /* List of regexps for buffer names to appear in selected window. */
162 Lisp_Object Vsame_window_regexps;
164 /* Hook run at end of temp_output_buffer_show. */
166 Lisp_Object Qtemp_buffer_show_hook;
168 /* Fdisplay_buffer always splits the largest window
169 if that window is more than this high. */
171 int split_height_threshold;
173 /* Number of lines of continuity in scrolling by screenfuls. */
175 int next_screen_context_lines;
177 /* Incremented for each window created. */
179 static int sequence_number;
181 /* Nonzero after init_window_once has finished. */
183 static int window_initialized;
185 /* Hook to run when window config changes. */
187 Lisp_Object Qwindow_configuration_change_hook;
188 Lisp_Object Vwindow_configuration_change_hook;
190 /* Nonzero means scroll commands try to put point
191 at the same screen height as previously. */
193 Lisp_Object Vscroll_preserve_screen_position;
195 #if 0 /* This isn't used anywhere. */
196 /* Nonzero means we can split a frame even if it is "unsplittable". */
197 static int inhibit_frame_unsplittable;
198 #endif /* 0 */
200 #define min(a, b) ((a) < (b) ? (a) : (b))
202 extern int scroll_margin;
204 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
206 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
207 "Returns t if OBJECT is a window.")
208 (object)
209 Lisp_Object object;
211 return WINDOWP (object) ? Qt : Qnil;
214 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
215 "Returns t if OBJECT is a window which is currently visible.")
216 (object)
217 Lisp_Object object;
219 return (WINDOWP (object) && ! NILP (XWINDOW (object)->buffer) ? Qt : Qnil);
222 Lisp_Object
223 make_window ()
225 Lisp_Object val;
226 register struct window *p;
227 register struct Lisp_Vector *vec;
228 int i;
230 vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
231 for (i = 0; i < VECSIZE (struct window); i++)
232 vec->contents[i] = Qnil;
233 vec->size = VECSIZE (struct window);
234 p = (struct window *) vec;
235 XSETFASTINT (p->sequence_number, ++sequence_number);
236 XSETFASTINT (p->left, 0);
237 XSETFASTINT (p->top, 0);
238 XSETFASTINT (p->height, 0);
239 XSETFASTINT (p->width, 0);
240 XSETFASTINT (p->hscroll, 0);
241 p->orig_top = p->orig_height = Qnil;
242 p->start = Fmake_marker ();
243 p->pointm = Fmake_marker ();
244 XSETFASTINT (p->use_time, 0);
245 p->frame = Qnil;
246 p->display_table = Qnil;
247 p->dedicated = Qnil;
248 p->pseudo_window_p = 0;
249 bzero (&p->cursor, sizeof (p->cursor));
250 bzero (&p->last_cursor, sizeof (p->last_cursor));
251 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
252 p->desired_matrix = p->current_matrix = 0;
253 p->phys_cursor_type = -1;
254 p->must_be_updated_p = 0;
255 XSETFASTINT (p->window_end_vpos, 0);
256 XSETFASTINT (p->window_end_pos, 0);
257 p->window_end_valid = Qnil;
258 p->vscroll = 0;
259 XSETWINDOW (val, p);
260 XSETFASTINT (p->last_point, 0);
261 p->frozen_window_start_p = 0;
263 Vwindow_list = Qnil;
264 return val;
267 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
268 "Return the window that the cursor now appears in and commands apply to.")
271 return selected_window;
274 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
275 "Return the window used now for minibuffers.\n\
276 If the optional argument FRAME is specified, return the minibuffer window\n\
277 used by that frame.")
278 (frame)
279 Lisp_Object frame;
281 if (NILP (frame))
282 frame = selected_frame;
283 CHECK_LIVE_FRAME (frame, 0);
284 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
287 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
288 "Returns non-nil if WINDOW is a minibuffer window.")
289 (window)
290 Lisp_Object window;
292 struct window *w = decode_window (window);
293 return MINI_WINDOW_P (w) ? Qt : Qnil;
297 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
298 Spos_visible_in_window_p, 0, 3, 0,
299 "Return t if position POS is currently on the frame in WINDOW.\n\
300 Return nil if that position is scrolled vertically out of view.\n\
301 If FULLY is non-nil, then only return t when POS is completely visible.\n\
302 POS defaults to point in WINDOW; WINDOW defaults to the selected window.")
303 (pos, window, fully)
304 Lisp_Object pos, window, fully;
306 register struct window *w;
307 register int posint;
308 register struct buffer *buf;
309 struct text_pos top;
310 Lisp_Object in_window;
311 int fully_p;
313 w = decode_window (window);
314 buf = XBUFFER (w->buffer);
315 SET_TEXT_POS_FROM_MARKER (top, w->start);
317 if (!NILP (pos))
319 CHECK_NUMBER_COERCE_MARKER (pos, 0);
320 posint = XINT (pos);
322 else if (w == XWINDOW (selected_window))
323 posint = PT;
324 else
325 posint = XMARKER (w->pointm)->charpos;
327 /* If position is above window start, it's not visible. */
328 if (posint < CHARPOS (top))
329 in_window = Qnil;
330 else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
331 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
332 && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
334 /* If frame is up-to-date, and POSINT is < window end pos, use
335 that info. This doesn't work for POSINT == end pos, because
336 the window end pos is actually the position _after_ the last
337 char in the window. */
338 if (!NILP (fully))
340 pos_visible_p (w, posint, &fully_p);
341 in_window = fully_p ? Qt : Qnil;
343 else
344 in_window = Qt;
346 else if (posint > BUF_ZV (buf))
347 in_window = Qnil;
348 else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
349 /* If window start is out of range, do something reasonable. */
350 in_window = Qnil;
351 else
353 if (pos_visible_p (w, posint, &fully_p))
354 in_window = NILP (fully) || fully_p ? Qt : Qnil;
355 else
356 in_window = Qnil;
359 return in_window;
363 static struct window *
364 decode_window (window)
365 register Lisp_Object window;
367 if (NILP (window))
368 return XWINDOW (selected_window);
370 CHECK_LIVE_WINDOW (window, 0);
371 return XWINDOW (window);
374 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
375 "Return the buffer that WINDOW is displaying.")
376 (window)
377 Lisp_Object window;
379 return decode_window (window)->buffer;
382 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
383 "Return the number of lines in WINDOW (including its mode line).")
384 (window)
385 Lisp_Object window;
387 return decode_window (window)->height;
390 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
391 "Return the number of display columns in WINDOW.\n\
392 This is the width that is usable columns available for text in WINDOW.\n\
393 If you want to find out how many columns WINDOW takes up,\n\
394 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
395 (window)
396 Lisp_Object window;
398 return make_number (window_internal_width (decode_window (window)));
401 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
402 "Return the number of columns by which WINDOW is scrolled from left margin.")
403 (window)
404 Lisp_Object window;
406 return decode_window (window)->hscroll;
409 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
410 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
411 NCOL should be zero or positive.")
412 (window, ncol)
413 register Lisp_Object window, ncol;
415 register struct window *w;
417 CHECK_NUMBER (ncol, 1);
418 if (XINT (ncol) < 0) XSETFASTINT (ncol, 0);
419 w = decode_window (window);
420 if (XINT (w->hscroll) != XINT (ncol))
421 /* Prevent redisplay shortcuts */
422 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
423 w->hscroll = ncol;
424 return ncol;
427 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
428 Swindow_redisplay_end_trigger, 0, 1, 0,
429 "Return WINDOW's redisplay end trigger value.\n\
430 See `set-window-redisplay-end-trigger' for more information.")
431 (window)
432 Lisp_Object window;
434 return decode_window (window)->redisplay_end_trigger;
437 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
438 Sset_window_redisplay_end_trigger, 2, 2, 0,
439 "Set WINDOW's redisplay end trigger value to VALUE.\n\
440 VALUE should be a buffer position (typically a marker) or nil.\n\
441 If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
442 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
443 with two arguments: WINDOW, and the end trigger value.\n\
444 Afterwards the end-trigger value is reset to nil.")
445 (window, value)
446 register Lisp_Object window, value;
448 register struct window *w;
450 w = decode_window (window);
451 w->redisplay_end_trigger = value;
452 return value;
455 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
456 "Return a list of the edge coordinates of WINDOW.\n\
457 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
458 RIGHT is one more than the rightmost column used by WINDOW,\n\
459 and BOTTOM is one more than the bottommost row used by WINDOW\n\
460 and its mode-line.")
461 (window)
462 Lisp_Object window;
464 register struct window *w = decode_window (window);
466 return Fcons (w->left, Fcons (w->top,
467 Fcons (make_number (WINDOW_RIGHT_EDGE (w)),
468 Fcons (make_number (XFASTINT (w->top)
469 + XFASTINT (w->height)),
470 Qnil))));
473 /* Test if the character at column *X, row *Y is within window W.
474 If it is not, return 0;
475 if it is in the window's text area,
476 set *x and *y to its location relative to the upper left corner
477 of the window, and
478 return 1;
479 if it is on the window's modeline, return 2;
480 if it is on the border between the window and its right sibling,
481 return 3.
482 if it is on the window's top line, return 4;
483 if it is in the bitmap area to the left/right of the window,
484 return 5 or 6, and convert *X and *Y to window-relative corrdinates.
486 X and Y are frame relative pixel coordinates. */
488 static int
489 coordinates_in_window (w, x, y)
490 register struct window *w;
491 register int *x, *y;
493 struct frame *f = XFRAME (WINDOW_FRAME (w));
494 int left_x, right_x, top_y, bottom_y;
495 int flags_area_width = FRAME_LEFT_FLAGS_AREA_WIDTH (f);
497 /* In what's below, we subtract 1 when computing right_x because we
498 want the rightmost pixel, which is given by left_pixel+width-1. */
499 if (w->pseudo_window_p)
501 left_x = 0;
502 right_x = XFASTINT (w->width) * CANON_Y_UNIT (f) - 1;
503 top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
504 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
506 else
508 left_x = (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w)
509 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
510 right_x = WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w) - 1;
511 top_y = (WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w)
512 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
513 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
516 if (*y < top_y
517 || *y >= bottom_y
518 || *x < (left_x
519 - flags_area_width
520 - (FRAME_LEFT_SCROLL_BAR_WIDTH (f)
521 * CANON_X_UNIT (f)))
522 || *x > right_x + flags_area_width)
523 /* Completely outside anything interesting. */
524 return 0;
525 else if (WINDOW_WANTS_MODELINE_P (w)
526 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
527 /* On the mode line. */
528 return 2;
529 else if (WINDOW_WANTS_HEADER_LINE_P (w)
530 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
531 /* On the top line. */
532 return 4;
533 /* Need to say "*x > right_x" rather than >=, since on character
534 terminals, the vertical line's x coordinate is right_x. */
535 else if (*x < left_x || *x > right_x)
537 /* Other lines than the mode line don't include flags areas and
538 scroll bars on the left. */
540 /* Convert X and Y to window-relative pixel coordinates. */
541 *x -= left_x;
542 *y -= top_y;
543 return *x < left_x ? 5 : 6;
545 /* Here, too, "*x > right_x" is because of character terminals. */
546 else if (!w->pseudo_window_p
547 && !WINDOW_RIGHTMOST_P (w)
548 && *x > right_x - CANON_X_UNIT (f))
549 /* On the border on the right side of the window? Assume that
550 this area begins at RIGHT_X minus a canonical char width. */
551 return 3;
552 else
554 /* Convert X and Y to window-relative pixel coordinates. */
555 *x -= left_x;
556 *y -= top_y;
557 return 1;
561 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
562 Scoordinates_in_window_p, 2, 2, 0,
563 "Return non-nil if COORDINATES are in WINDOW.\n\
564 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
565 measured in characters from the upper-left corner of the frame.\n\
566 (0 . 0) denotes the character in the upper left corner of the\n\
567 frame.\n\
568 If COORDINATES are in the text portion of WINDOW,\n\
569 the coordinates relative to the window are returned.\n\
570 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
571 If they are in the top mode line of WINDOW, `header-line' is returned.\n\
572 If they are in the bitmap-area to the left of the window,\n\
573 `left-bitmap-area' is returned, if they are in the area on the right of\n\
574 the window, `right-bitmap-area' is returned.\n\
575 If they are on the border between WINDOW and its right sibling,\n\
576 `vertical-line' is returned.")
577 (coordinates, window)
578 register Lisp_Object coordinates, window;
580 struct window *w;
581 struct frame *f;
582 int x, y;
583 Lisp_Object lx, ly;
585 CHECK_LIVE_WINDOW (window, 0);
586 w = XWINDOW (window);
587 f = XFRAME (w->frame);
588 CHECK_CONS (coordinates, 1);
589 lx = Fcar (coordinates);
590 ly = Fcdr (coordinates);
591 CHECK_NUMBER_OR_FLOAT (lx, 1);
592 CHECK_NUMBER_OR_FLOAT (ly, 1);
593 x = PIXEL_X_FROM_CANON_X (f, lx);
594 y = PIXEL_Y_FROM_CANON_Y (f, ly);
596 switch (coordinates_in_window (w, &x, &y))
598 case 0: /* NOT in window at all. */
599 return Qnil;
601 case 1: /* In text part of window. */
602 /* X and Y are now window relative pixel coordinates.
603 Convert them to canonical char units before returning
604 them. */
605 return Fcons (CANON_X_FROM_PIXEL_X (f, x),
606 CANON_Y_FROM_PIXEL_Y (f, y));
608 case 2: /* In mode line of window. */
609 return Qmode_line;
611 case 3: /* On right border of window. */
612 return Qvertical_line;
614 case 4:
615 return Qheader_line;
617 case 5:
618 return Qleft_bitmap_area;
620 case 6:
621 return Qright_bitmap_area;
623 default:
624 abort ();
629 /* Callback for foreach_window, used in window_from_coordinates.
630 Check if window W contains coordinates specified by USER_DATA which
631 is actually a pointer to a struct check_window_data CW.
633 Check if window W contains coordinates *CW->x and *CW->y. If it
634 does, return W in *CW->window, as Lisp_Object, and return in
635 *CW->part the part of the window under coordinates *X,*Y. Return
636 zero from this function to stop iterating over windows. */
638 struct check_window_data
640 Lisp_Object *window;
641 int *x, *y, *part;
644 static int
645 check_window_containing (w, user_data)
646 struct window *w;
647 void *user_data;
649 struct check_window_data *cw = (struct check_window_data *) user_data;
650 int found;
652 found = coordinates_in_window (w, cw->x, cw->y);
653 if (found)
655 *cw->part = found - 1;
656 XSETWINDOW (*cw->window, w);
659 return !found;
663 /* Find the window containing frame-relative pixel position X/Y and
664 return it as a Lisp_Object. If X, Y is on the window's modeline,
665 set *PART to 1; if it is on the separating line between the window
666 and its right sibling, set it to 2; otherwise set it to 0. If
667 there is no window under X, Y return nil and leave *PART
668 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
670 This function was previously implemented with a loop cycling over
671 windows with Fnext_window, and starting with the frame's selected
672 window. It turned out that this doesn't work with an
673 implementation of next_window using Vwindow_list, because
674 FRAME_SELECTED_WINDOW (F) is not always contained in the window
675 tree of F when this function is called asynchronously from
676 note_mouse_highlight. The original loop didn't terminate in this
677 case. */
679 Lisp_Object
680 window_from_coordinates (f, x, y, part, tool_bar_p)
681 struct frame *f;
682 int x, y;
683 int *part;
684 int tool_bar_p;
686 Lisp_Object window;
687 struct check_window_data cw;
689 window = Qnil;
690 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
691 foreach_window (f, check_window_containing, &cw);
693 /* If not found above, see if it's in the tool bar window, if a tool
694 bar exists. */
695 if (NILP (window)
696 && tool_bar_p
697 && WINDOWP (f->tool_bar_window)
698 && XINT (XWINDOW (f->tool_bar_window)->height) > 0
699 && coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y))
701 *part = 0;
702 window = f->tool_bar_window;
705 return window;
708 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
709 "Return window containing coordinates X and Y on FRAME.\n\
710 If omitted, FRAME defaults to the currently selected frame.\n\
711 The top left corner of the frame is considered to be row 0,\n\
712 column 0.")
713 (x, y, frame)
714 Lisp_Object x, y, frame;
716 int part;
717 struct frame *f;
719 if (NILP (frame))
720 frame = selected_frame;
721 CHECK_LIVE_FRAME (frame, 2);
722 f = XFRAME (frame);
724 /* Check that arguments are integers or floats. */
725 CHECK_NUMBER_OR_FLOAT (x, 0);
726 CHECK_NUMBER_OR_FLOAT (y, 1);
728 return window_from_coordinates (f,
729 PIXEL_X_FROM_CANON_X (f, x),
730 PIXEL_Y_FROM_CANON_Y (f, y),
731 &part, 0);
734 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
735 "Return current value of point in WINDOW.\n\
736 For a nonselected window, this is the value point would have\n\
737 if that window were selected.\n\
739 Note that, when WINDOW is the selected window and its buffer\n\
740 is also currently selected, the value returned is the same as (point).\n\
741 It would be more strictly correct to return the `top-level' value\n\
742 of point, outside of any save-excursion forms.\n\
743 But that is hard to define.")
744 (window)
745 Lisp_Object window;
747 register struct window *w = decode_window (window);
749 if (w == XWINDOW (selected_window)
750 && current_buffer == XBUFFER (w->buffer))
751 return Fpoint ();
752 return Fmarker_position (w->pointm);
755 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
756 "Return position at which display currently starts in WINDOW.\n\
757 This is updated by redisplay or by calling `set-window-start'.")
758 (window)
759 Lisp_Object window;
761 return Fmarker_position (decode_window (window)->start);
764 /* This is text temporarily removed from the doc string below.
766 This function returns nil if the position is not currently known.\n\
767 That happens when redisplay is preempted and doesn't finish.\n\
768 If in that case you want to compute where the end of the window would\n\
769 have been if redisplay had finished, do this:\n\
770 (save-excursion\n\
771 (goto-char (window-start window))\n\
772 (vertical-motion (1- (window-height window)) window)\n\
773 (point))") */
775 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
776 "Return position at which display currently ends in WINDOW.\n\
777 This is updated by redisplay, when it runs to completion.\n\
778 Simply changing the buffer text or setting `window-start'\n\
779 does not update this value.\n\
780 If UP-TO-DATE is non-nil, compute the up-to-date position\n\
781 if it isn't already recorded.")
782 (window, update)
783 Lisp_Object window, update;
785 Lisp_Object value;
786 struct window *w = decode_window (window);
787 Lisp_Object buf;
789 buf = w->buffer;
790 CHECK_BUFFER (buf, 0);
792 #if 0 /* This change broke some things. We should make it later. */
793 /* If we don't know the end position, return nil.
794 The user can compute it with vertical-motion if he wants to.
795 It would be nicer to do it automatically,
796 but that's so slow that it would probably bother people. */
797 if (NILP (w->window_end_valid))
798 return Qnil;
799 #endif
801 if (! NILP (update)
802 && ! (! NILP (w->window_end_valid)
803 && XFASTINT (w->last_modified) >= MODIFF))
805 struct text_pos startp;
806 struct it it;
808 /* In case W->start is out of the range, use something
809 reasonable. This situation occured when loading a file with
810 `-l' containing a call to `rmail' with subsequent other
811 commands. At the end, W->start happened to be BEG, while
812 rmail had already narrowed the buffer. */
813 if (XMARKER (w->start)->charpos < BEGV)
814 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
815 else if (XMARKER (w->start)->charpos > ZV)
816 SET_TEXT_POS (startp, ZV, ZV_BYTE);
817 else
818 SET_TEXT_POS_FROM_MARKER (startp, w->start);
820 /* Cannot use Fvertical_motion because that function doesn't
821 cope with variable-height lines. */
822 start_display (&it, w, startp);
823 move_it_vertically (&it, window_box_height (w));
824 value = make_number (IT_CHARPOS (it));
826 else
827 XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
829 return value;
832 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
833 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
834 (window, pos)
835 Lisp_Object window, pos;
837 register struct window *w = decode_window (window);
839 CHECK_NUMBER_COERCE_MARKER (pos, 1);
840 if (w == XWINDOW (selected_window)
841 && XBUFFER (w->buffer) == current_buffer)
842 Fgoto_char (pos);
843 else
844 set_marker_restricted (w->pointm, pos, w->buffer);
846 return pos;
849 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
850 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
851 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
852 from overriding motion of point in order to display at this exact start.")
853 (window, pos, noforce)
854 Lisp_Object window, pos, noforce;
856 register struct window *w = decode_window (window);
858 CHECK_NUMBER_COERCE_MARKER (pos, 1);
859 set_marker_restricted (w->start, pos, w->buffer);
860 /* this is not right, but much easier than doing what is right. */
861 w->start_at_line_beg = Qnil;
862 if (NILP (noforce))
863 w->force_start = Qt;
864 w->update_mode_line = Qt;
865 XSETFASTINT (w->last_modified, 0);
866 XSETFASTINT (w->last_overlay_modified, 0);
867 if (!EQ (window, selected_window))
868 windows_or_buffers_changed++;
870 return pos;
873 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
874 1, 1, 0,
875 "Return WINDOW's dedicated object, usually t or nil.\n\
876 See also `set-window-dedicated-p'.")
877 (window)
878 Lisp_Object window;
880 return decode_window (window)->dedicated;
883 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
884 Sset_window_dedicated_p, 2, 2, 0,
885 "Control whether WINDOW is dedicated to the buffer it displays.\n\
886 If it is dedicated, Emacs will not automatically change\n\
887 which buffer appears in it.\n\
888 The second argument is the new value for the dedication flag;\n\
889 non-nil means yes.")
890 (window, arg)
891 Lisp_Object window, arg;
893 register struct window *w = decode_window (window);
895 if (NILP (arg))
896 w->dedicated = Qnil;
897 else
898 w->dedicated = Qt;
900 return w->dedicated;
903 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
904 0, 1, 0,
905 "Return the display-table that WINDOW is using.")
906 (window)
907 Lisp_Object window;
909 return decode_window (window)->display_table;
912 /* Get the display table for use on window W. This is either W's
913 display table or W's buffer's display table. Ignore the specified
914 tables if they are not valid; if no valid table is specified,
915 return 0. */
917 struct Lisp_Char_Table *
918 window_display_table (w)
919 struct window *w;
921 struct Lisp_Char_Table *dp = NULL;
923 if (DISP_TABLE_P (w->display_table))
924 dp = XCHAR_TABLE (w->display_table);
925 else if (BUFFERP (w->buffer))
927 struct buffer *b = XBUFFER (w->buffer);
929 if (DISP_TABLE_P (b->display_table))
930 dp = XCHAR_TABLE (b->display_table);
931 else if (DISP_TABLE_P (Vstandard_display_table))
932 dp = XCHAR_TABLE (Vstandard_display_table);
935 return dp;
938 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
939 "Set WINDOW's display-table to TABLE.")
940 (window, table)
941 register Lisp_Object window, table;
943 register struct window *w;
945 w = decode_window (window);
946 w->display_table = table;
947 return table;
950 /* Record info on buffer window w is displaying
951 when it is about to cease to display that buffer. */
952 static void
953 unshow_buffer (w)
954 register struct window *w;
956 Lisp_Object buf;
957 struct buffer *b;
959 buf = w->buffer;
960 b = XBUFFER (buf);
961 if (b != XMARKER (w->pointm)->buffer)
962 abort ();
964 #if 0
965 if (w == XWINDOW (selected_window)
966 || ! EQ (buf, XWINDOW (selected_window)->buffer))
967 /* Do this except when the selected window's buffer
968 is being removed from some other window. */
969 #endif
970 /* last_window_start records the start position that this buffer
971 had in the last window to be disconnected from it.
972 Now that this statement is unconditional,
973 it is possible for the buffer to be displayed in the
974 selected window, while last_window_start reflects another
975 window which was recently showing the same buffer.
976 Some people might say that might be a good thing. Let's see. */
977 b->last_window_start = marker_position (w->start);
979 /* Point in the selected window's buffer
980 is actually stored in that buffer, and the window's pointm isn't used.
981 So don't clobber point in that buffer. */
982 if (! EQ (buf, XWINDOW (selected_window)->buffer)
983 /* This line helps to fix Horsley's testbug.el bug. */
984 && !(WINDOWP (b->last_selected_window)
985 && w != XWINDOW (b->last_selected_window)
986 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
987 temp_set_point_both (b,
988 clip_to_bounds (BUF_BEGV (b),
989 XMARKER (w->pointm)->charpos,
990 BUF_ZV (b)),
991 clip_to_bounds (BUF_BEGV_BYTE (b),
992 marker_byte_position (w->pointm),
993 BUF_ZV_BYTE (b)));
995 if (WINDOWP (b->last_selected_window)
996 && w == XWINDOW (b->last_selected_window))
997 b->last_selected_window = Qnil;
1000 /* Put replacement into the window structure in place of old. */
1001 static void
1002 replace_window (old, replacement)
1003 Lisp_Object old, replacement;
1005 register Lisp_Object tem;
1006 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1008 /* If OLD is its frame's root_window, then replacement is the new
1009 root_window for that frame. */
1011 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1012 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1014 p->left = o->left;
1015 p->top = o->top;
1016 p->width = o->width;
1017 p->height = o->height;
1018 p->desired_matrix = p->current_matrix = 0;
1019 p->vscroll = 0;
1020 bzero (&p->cursor, sizeof (p->cursor));
1021 bzero (&p->last_cursor, sizeof (p->last_cursor));
1022 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1023 p->phys_cursor_type = -1;
1024 p->must_be_updated_p = 0;
1025 p->pseudo_window_p = 0;
1026 XSETFASTINT (p->window_end_vpos, 0);
1027 XSETFASTINT (p->window_end_pos, 0);
1028 p->window_end_valid = Qnil;
1029 p->frozen_window_start_p = 0;
1030 p->orig_top = p->orig_height = Qnil;
1032 p->next = tem = o->next;
1033 if (!NILP (tem))
1034 XWINDOW (tem)->prev = replacement;
1036 p->prev = tem = o->prev;
1037 if (!NILP (tem))
1038 XWINDOW (tem)->next = replacement;
1040 p->parent = tem = o->parent;
1041 if (!NILP (tem))
1043 if (EQ (XWINDOW (tem)->vchild, old))
1044 XWINDOW (tem)->vchild = replacement;
1045 if (EQ (XWINDOW (tem)->hchild, old))
1046 XWINDOW (tem)->hchild = replacement;
1049 /*** Here, if replacement is a vertical combination
1050 and so is its new parent, we should make replacement's
1051 children be children of that parent instead. ***/
1054 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1055 "Remove WINDOW from the display. Default is selected window.")
1056 (window)
1057 register Lisp_Object window;
1059 delete_window (window);
1061 if (! NILP (Vwindow_configuration_change_hook)
1062 && ! NILP (Vrun_hooks))
1063 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1065 return Qnil;
1068 void
1069 delete_window (window)
1070 register Lisp_Object window;
1072 register Lisp_Object tem, parent, sib;
1073 register struct window *p;
1074 register struct window *par;
1075 FRAME_PTR frame;
1077 /* Because this function is called by other C code on non-leaf
1078 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1079 so we can't decode_window here. */
1080 if (NILP (window))
1081 window = selected_window;
1082 else
1083 CHECK_WINDOW (window, 0);
1084 p = XWINDOW (window);
1086 /* It's okay to delete an already-deleted window. */
1087 if (NILP (p->buffer)
1088 && NILP (p->hchild)
1089 && NILP (p->vchild))
1090 return;
1092 parent = p->parent;
1093 if (NILP (parent))
1094 error ("Attempt to delete minibuffer or sole ordinary window");
1095 par = XWINDOW (parent);
1097 windows_or_buffers_changed++;
1098 Vwindow_list = Qnil;
1099 frame = XFRAME (WINDOW_FRAME (p));
1100 FRAME_WINDOW_SIZES_CHANGED (frame) = 1;
1102 /* Are we trying to delete any frame's selected window? */
1104 Lisp_Object frame, pwindow;
1106 /* See if the frame's selected window is either WINDOW
1107 or any subwindow of it, by finding all that window's parents
1108 and comparing each one with WINDOW. */
1109 frame = WINDOW_FRAME (XWINDOW (window));
1110 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
1112 while (!NILP (pwindow))
1114 if (EQ (window, pwindow))
1115 break;
1116 pwindow = XWINDOW (pwindow)->parent;
1119 if (EQ (window, pwindow))
1121 Lisp_Object alternative;
1122 alternative = Fnext_window (window, Qlambda, Qnil);
1124 /* If we're about to delete the selected window on the
1125 selected frame, then we should use Fselect_window to select
1126 the new window. On the other hand, if we're about to
1127 delete the selected window on any other frame, we shouldn't do
1128 anything but set the frame's selected_window slot. */
1129 if (EQ (window, selected_window))
1130 Fselect_window (alternative);
1131 else
1132 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
1136 tem = p->buffer;
1137 /* tem is null for dummy parent windows
1138 (which have inferiors but not any contents themselves) */
1139 if (!NILP (tem))
1141 unshow_buffer (p);
1142 unchain_marker (p->pointm);
1143 unchain_marker (p->start);
1146 /* Free window glyph matrices. It is sure that they are allocated
1147 again when ADJUST_GLYPHS is called. Block input so that expose
1148 events and other events that access glyph matrices are not
1149 processed while we are changing them. */
1150 BLOCK_INPUT;
1151 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (frame)));
1153 tem = p->next;
1154 if (!NILP (tem))
1155 XWINDOW (tem)->prev = p->prev;
1157 tem = p->prev;
1158 if (!NILP (tem))
1159 XWINDOW (tem)->next = p->next;
1161 if (EQ (window, par->hchild))
1162 par->hchild = p->next;
1163 if (EQ (window, par->vchild))
1164 par->vchild = p->next;
1166 /* Find one of our siblings to give our space to. */
1167 sib = p->prev;
1168 if (NILP (sib))
1170 /* If p gives its space to its next sibling, that sibling needs
1171 to have its top/left side pulled back to where p's is.
1172 set_window_{height,width} will re-position the sibling's
1173 children. */
1174 sib = p->next;
1175 XWINDOW (sib)->top = p->top;
1176 XWINDOW (sib)->left = p->left;
1179 /* Stretch that sibling. */
1180 if (!NILP (par->vchild))
1181 set_window_height (sib,
1182 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
1184 if (!NILP (par->hchild))
1185 set_window_width (sib,
1186 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
1189 /* If parent now has only one child,
1190 put the child into the parent's place. */
1191 tem = par->hchild;
1192 if (NILP (tem))
1193 tem = par->vchild;
1194 if (NILP (XWINDOW (tem)->next))
1195 replace_window (parent, tem);
1197 /* Since we may be deleting combination windows, we must make sure that
1198 not only p but all its children have been marked as deleted. */
1199 if (! NILP (p->hchild))
1200 delete_all_subwindows (XWINDOW (p->hchild));
1201 else if (! NILP (p->vchild))
1202 delete_all_subwindows (XWINDOW (p->vchild));
1204 /* Mark this window as deleted. */
1205 p->buffer = p->hchild = p->vchild = Qnil;
1207 /* Adjust glyph matrices. */
1208 adjust_glyphs (frame);
1209 UNBLOCK_INPUT;
1214 /***********************************************************************
1215 Window List
1216 ***********************************************************************/
1218 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1219 pointer. This is a callback function for foreach_window, used in
1220 function window_list. */
1222 static int
1223 add_window_to_list (w, user_data)
1224 struct window *w;
1225 void *user_data;
1227 Lisp_Object *list = (Lisp_Object *) user_data;
1228 Lisp_Object window;
1229 XSETWINDOW (window, w);
1230 *list = Fcons (window, *list);
1231 return 1;
1235 /* Return a list of all windows, for use by next_window. If
1236 Vwindow_list is a list, return that list. Otherwise, build a new
1237 list, cache it in Vwindow_list, and return that. */
1239 static Lisp_Object
1240 window_list ()
1242 if (!CONSP (Vwindow_list))
1244 Lisp_Object tail;
1246 Vwindow_list = Qnil;
1247 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1249 Lisp_Object args[2];
1251 /* We are visiting windows in canonical order, and add
1252 new windows at the front of args[1], which means we
1253 have to reverse this list at the end. */
1254 args[1] = Qnil;
1255 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1256 args[0] = Vwindow_list;
1257 args[1] = Fnreverse (args[1]);
1258 Vwindow_list = Fnconc (2, args);
1262 return Vwindow_list;
1266 /* Value is non-zero if WINDOW satisfies the constraints given by
1267 OWINDOW, MINIBUF and ALL_FRAMES.
1269 MINIBUF t means WINDOW may be minibuffer windows.
1270 `lambda' means WINDOW may not be a minibuffer window.
1271 a window means a specific minibuffer window
1273 ALL_FRAMES t means search all frames,
1274 nil means search just current frame,
1275 `visible' means search just visible frames,
1276 0 means search visible and iconified frames,
1277 a window means search the frame that window belongs to,
1278 a frame means consider windows on that frame, only. */
1280 static int
1281 candidate_window_p (window, owindow, minibuf, all_frames)
1282 Lisp_Object window, owindow, minibuf, all_frames;
1284 struct window *w = XWINDOW (window);
1285 struct frame *f = XFRAME (w->frame);
1286 int candidate_p = 1;
1288 if (!BUFFERP (w->buffer))
1289 candidate_p = 0;
1290 else if (MINI_WINDOW_P (w)
1291 && (EQ (minibuf, Qlambda)
1292 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1294 /* If MINIBUF is `lambda' don't consider any mini-windows.
1295 If it is a window, consider only that one. */
1296 candidate_p = 0;
1298 else if (EQ (all_frames, Qt))
1299 candidate_p = 1;
1300 else if (NILP (all_frames))
1302 xassert (WINDOWP (owindow));
1303 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1305 else if (EQ (all_frames, Qvisible))
1307 FRAME_SAMPLE_VISIBILITY (f);
1308 candidate_p = FRAME_VISIBLE_P (f);
1310 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1312 FRAME_SAMPLE_VISIBILITY (f);
1313 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1315 else if (WINDOWP (all_frames))
1316 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1317 || EQ (XWINDOW (all_frames)->frame, w->frame)
1318 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1319 else if (FRAMEP (all_frames))
1320 candidate_p = EQ (all_frames, w->frame);
1322 return candidate_p;
1326 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1327 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1328 ALL_FRAMES. */
1330 static void
1331 decode_next_window_args (window, minibuf, all_frames)
1332 Lisp_Object *window, *minibuf, *all_frames;
1334 if (NILP (*window))
1335 *window = selected_window;
1336 else
1337 CHECK_LIVE_WINDOW (*window, 0);
1339 /* MINIBUF nil may or may not include minibuffers. Decide if it
1340 does. */
1341 if (NILP (*minibuf))
1342 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1343 else if (!EQ (*minibuf, Qt))
1344 *minibuf = Qlambda;
1346 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1347 => count none of them, or a specific minibuffer window (the
1348 active one) to count. */
1350 /* ALL_FRAMES nil doesn't specify which frames to include. */
1351 if (NILP (*all_frames))
1352 *all_frames = (!EQ (*minibuf, Qlambda)
1353 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1354 : Qnil);
1355 else if (EQ (*all_frames, Qvisible))
1357 else if (XFASTINT (*all_frames) == 0)
1359 else if (FRAMEP (*all_frames))
1361 else if (!EQ (*all_frames, Qt))
1362 *all_frames = Qnil;
1364 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1365 search just current frame, `visible' meaning search just visible
1366 frames, 0 meaning search visible and iconified frames, or a
1367 window, meaning search the frame that window belongs to, or a
1368 frame, meaning consider windows on that frame, only. */
1372 /* Return the next or previous window of WINDOW in canonical ordering
1373 of windows. NEXT_P non-zero means return the next window. See the
1374 documentation string of next-window for the meaning of MINIBUF and
1375 ALL_FRAMES. */
1377 static Lisp_Object
1378 next_window (window, minibuf, all_frames, next_p)
1379 Lisp_Object window, minibuf, all_frames;
1380 int next_p;
1382 decode_next_window_args (&window, &minibuf, &all_frames);
1384 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1385 return the first window on the frame. */
1386 if (FRAMEP (all_frames)
1387 && !EQ (all_frames, XWINDOW (window)->frame))
1388 return Fframe_first_window (all_frames);
1390 if (next_p)
1392 Lisp_Object list;
1394 /* Find WINDOW in the list of all windows. */
1395 list = Fmemq (window, window_list ());
1397 /* Scan forward from WINDOW to the end of the window list. */
1398 if (CONSP (list))
1399 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1400 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1401 break;
1403 /* Scan from the start of the window list up to WINDOW. */
1404 if (!CONSP (list))
1405 for (list = Vwindow_list;
1406 CONSP (list) && !EQ (XCAR (list), window);
1407 list = XCDR (list))
1408 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1409 break;
1411 if (CONSP (list))
1412 window = XCAR (list);
1414 else
1416 Lisp_Object candidate, list;
1418 /* Scan through the list of windows for candidates. If there are
1419 candidate windows in front of WINDOW, the last one of these
1420 is the one we want. If there are candidates following WINDOW
1421 in the list, again the last one of these is the one we want. */
1422 candidate = Qnil;
1423 for (list = window_list (); CONSP (list); list = XCDR (list))
1425 if (EQ (XCAR (list), window))
1427 if (WINDOWP (candidate))
1428 break;
1430 else if (candidate_window_p (XCAR (list), window, minibuf,
1431 all_frames))
1432 candidate = XCAR (list);
1435 if (WINDOWP (candidate))
1436 window = candidate;
1439 return window;
1443 /* This comment supplies the doc string for `next-window',
1444 for make-docfile to see. We cannot put this in the real DEFUN
1445 due to limits in the Unix cpp.
1447 DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
1448 "Return next window after WINDOW in canonical ordering of windows.\n\
1449 If omitted, WINDOW defaults to the selected window.\n\
1451 Optional second arg MINIBUF t means count the minibuffer window even\n\
1452 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1453 it is active. MINIBUF neither t nor nil means not to count the\n\
1454 minibuffer even if it is active.\n\
1456 Several frames may share a single minibuffer; if the minibuffer\n\
1457 counts, all windows on all frames that share that minibuffer count\n\
1458 too. Therefore, `next-window' can be used to iterate through the\n\
1459 set of windows even when the minibuffer is on another frame. If the\n\
1460 minibuffer does not count, only windows from WINDOW's frame count.\n\
1462 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1463 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1464 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1465 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1466 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1467 Anything else means restrict to WINDOW's frame.\n\
1469 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1470 `next-window' to iterate through the entire cycle of acceptable\n\
1471 windows, eventually ending up back at the window you started with.\n\
1472 `previous-window' traverses the same cycle, in the reverse order.")
1473 (window, minibuf, all_frames) */
1475 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1477 (window, minibuf, all_frames)
1478 Lisp_Object window, minibuf, all_frames;
1480 return next_window (window, minibuf, all_frames, 1);
1484 /* This comment supplies the doc string for `previous-window',
1485 for make-docfile to see. We cannot put this in the real DEFUN
1486 due to limits in the Unix cpp.
1488 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
1489 "Return the window preceding WINDOW in canonical ordering of windows.\n\
1490 If omitted, WINDOW defaults to the selected window.\n\
1492 Optional second arg MINIBUF t means count the minibuffer window even\n\
1493 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1494 it is active. MINIBUF neither t nor nil means not to count the\n\
1495 minibuffer even if it is active.\n\
1497 Several frames may share a single minibuffer; if the minibuffer\n\
1498 counts, all windows on all frames that share that minibuffer count\n\
1499 too. Therefore, `previous-window' can be used to iterate through\n\
1500 the set of windows even when the minibuffer is on another frame. If\n\
1501 the minibuffer does not count, only windows from WINDOW's frame count\n\
1503 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1504 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1505 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1506 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1507 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1508 Anything else means restrict to WINDOW's frame.\n\
1510 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1511 `previous-window' to iterate through the entire cycle of acceptable\n\
1512 windows, eventually ending up back at the window you started with.\n\
1513 `next-window' traverses the same cycle, in the reverse order.")
1514 (window, minibuf, all_frames) */
1517 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1519 (window, minibuf, all_frames)
1520 Lisp_Object window, minibuf, all_frames;
1522 return next_window (window, minibuf, all_frames, 0);
1526 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1527 "Select the ARG'th different window on this frame.\n\
1528 All windows on current frame are arranged in a cyclic order.\n\
1529 This command selects the window ARG steps away in that order.\n\
1530 A negative ARG moves in the opposite order. If the optional second\n\
1531 argument ALL_FRAMES is non-nil, cycle through all frames.")
1532 (arg, all_frames)
1533 Lisp_Object arg, all_frames;
1535 Lisp_Object window;
1536 int i;
1538 CHECK_NUMBER (arg, 0);
1539 window = selected_window;
1541 for (i = XINT (arg); i > 0; --i)
1542 window = Fnext_window (window, Qnil, all_frames);
1543 for (; i < 0; ++i)
1544 window = Fprevious_window (window, Qnil, all_frames);
1546 Fselect_window (window);
1547 return Qnil;
1551 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
1552 "Return a list of windows in canonical ordering.\n\
1553 Arguments are like for `next-window'.")
1554 (window, minibuf, all_frames)
1555 Lisp_Object window, minibuf, all_frames;
1557 Lisp_Object tail, list;
1559 decode_next_window_args (&window, &minibuf, &all_frames);
1560 list = Qnil;
1562 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
1563 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
1564 list = Fcons (XCAR (tail), list);
1566 return Fnreverse (list);
1571 /* Look at all windows, performing an operation specified by TYPE
1572 with argument OBJ.
1573 If FRAMES is Qt, look at all frames;
1574 Qnil, look at just the selected frame;
1575 Qvisible, look at visible frames;
1576 a frame, just look at windows on that frame.
1577 If MINI is non-zero, perform the operation on minibuffer windows too.
1580 enum window_loop
1582 WINDOW_LOOP_UNUSED,
1583 GET_BUFFER_WINDOW, /* Arg is buffer */
1584 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1585 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1586 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1587 GET_LARGEST_WINDOW,
1588 UNSHOW_BUFFER, /* Arg is buffer */
1589 CHECK_ALL_WINDOWS
1592 static Lisp_Object
1593 window_loop (type, obj, mini, frames)
1594 enum window_loop type;
1595 Lisp_Object obj, frames;
1596 int mini;
1598 Lisp_Object window, windows, best_window, frame_arg;
1599 struct frame *f;
1600 struct gcpro gcpro1;
1602 /* If we're only looping through windows on a particular frame,
1603 frame points to that frame. If we're looping through windows
1604 on all frames, frame is 0. */
1605 if (FRAMEP (frames))
1606 f = XFRAME (frames);
1607 else if (NILP (frames))
1608 f = SELECTED_FRAME ();
1609 else
1610 f = NULL;
1612 if (f)
1613 frame_arg = Qlambda;
1614 else if (XFASTINT (frames) == 0)
1615 frame_arg = frames;
1616 else if (EQ (frames, Qvisible))
1617 frame_arg = frames;
1618 else
1619 frame_arg = Qt;
1621 /* frame_arg is Qlambda to stick to one frame,
1622 Qvisible to consider all visible frames,
1623 or Qt otherwise. */
1625 /* Pick a window to start with. */
1626 if (WINDOWP (obj))
1627 window = obj;
1628 else if (f)
1629 window = FRAME_SELECTED_WINDOW (f);
1630 else
1631 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1633 /* Figure out the last window we're going to mess with. Since
1634 Fnext_window, given the same options, is guaranteed to go in a
1635 ring, we can just use Fprevious_window to find the last one.
1637 We can't just wait until we hit the first window again, because
1638 it might be deleted. */
1640 windows = Fwindow_list (window, mini ? Qt : Qnil, frame_arg);
1641 GCPRO1 (windows);
1642 best_window = Qnil;
1644 for (; CONSP (windows); windows = CDR (windows))
1646 struct window *w;
1648 window = XCAR (windows);
1649 w = XWINDOW (window);
1651 /* Note that we do not pay attention here to whether the frame
1652 is visible, since Fwindow_list skips non-visible frames if
1653 that is desired, under the control of frame_arg. */
1654 if (!MINI_WINDOW_P (w)
1655 /* For UNSHOW_BUFFER, we must always consider all windows. */
1656 || type == UNSHOW_BUFFER
1657 || (mini && minibuf_level > 0))
1658 switch (type)
1660 case GET_BUFFER_WINDOW:
1661 if (EQ (w->buffer, obj)
1662 /* Don't find any minibuffer window
1663 except the one that is currently in use. */
1664 && (MINI_WINDOW_P (w)
1665 ? EQ (window, minibuf_window)
1666 : 1))
1668 UNGCPRO;
1669 return window;
1671 break;
1673 case GET_LRU_WINDOW:
1674 /* t as arg means consider only full-width windows */
1675 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w))
1676 break;
1677 /* Ignore dedicated windows and minibuffers. */
1678 if (MINI_WINDOW_P (w) || !NILP (w->dedicated))
1679 break;
1680 if (NILP (best_window)
1681 || (XFASTINT (XWINDOW (best_window)->use_time)
1682 > XFASTINT (w->use_time)))
1683 best_window = window;
1684 break;
1686 case DELETE_OTHER_WINDOWS:
1687 if (!EQ (window, obj))
1688 Fdelete_window (window);
1689 break;
1691 case DELETE_BUFFER_WINDOWS:
1692 if (EQ (w->buffer, obj))
1694 struct frame *f = XFRAME (WINDOW_FRAME (w));
1696 /* If this window is dedicated, and in a frame of its own,
1697 kill the frame. */
1698 if (EQ (window, FRAME_ROOT_WINDOW (f))
1699 && !NILP (w->dedicated)
1700 && other_visible_frames (f))
1702 /* Skip the other windows on this frame.
1703 There might be one, the minibuffer! */
1704 while (CONSP (XCDR (windows))
1705 && EQ (XWINDOW (XCAR (windows))->frame,
1706 XWINDOW (XCAR (XCDR (windows)))->frame))
1707 windows = XCDR (windows);
1709 /* Now we can safely delete the frame. */
1710 Fdelete_frame (w->frame, Qnil);
1712 else if (NILP (w->parent))
1714 /* If we're deleting the buffer displayed in the
1715 only window on the frame, find a new buffer to
1716 display there. */
1717 Lisp_Object buffer;
1718 buffer = Fother_buffer (obj, Qnil, w->frame);
1719 if (NILP (buffer))
1720 buffer = Fget_buffer_create (build_string ("*scratch*"));
1721 Fset_window_buffer (window, buffer);
1722 if (EQ (window, selected_window))
1723 Fset_buffer (w->buffer);
1725 else
1726 Fdelete_window (window);
1728 break;
1730 case GET_LARGEST_WINDOW:
1732 /* Ignore dedicated windows and minibuffers. */
1733 if (MINI_WINDOW_P (w) || !NILP (w->dedicated))
1734 break;
1736 if (NILP (best_window))
1737 best_window = window;
1738 else
1740 struct window *b = XWINDOW (best_window);
1741 if (XFASTINT (w->height) * XFASTINT (w->width)
1742 > XFASTINT (b->height) * XFASTINT (b->width))
1743 best_window = window;
1746 break;
1748 case UNSHOW_BUFFER:
1749 if (EQ (w->buffer, obj))
1751 Lisp_Object buffer;
1752 struct frame *f = XFRAME (w->frame);
1754 /* Find another buffer to show in this window. */
1755 buffer = Fother_buffer (obj, Qnil, w->frame);
1756 if (NILP (buffer))
1757 buffer = Fget_buffer_create (build_string ("*scratch*"));
1759 /* If this window is dedicated, and in a frame of its own,
1760 kill the frame. */
1761 if (EQ (window, FRAME_ROOT_WINDOW (f))
1762 && !NILP (w->dedicated)
1763 && other_visible_frames (f))
1765 /* Skip the other windows on this frame.
1766 There might be one, the minibuffer! */
1767 while (CONSP (XCDR (windows))
1768 && EQ (XWINDOW (XCAR (windows))->frame,
1769 XWINDOW (XCAR (XCDR (windows)))->frame))
1770 windows = XCDR (windows);
1772 /* Now we can safely delete the frame. */
1773 Fdelete_frame (w->frame, Qnil);
1775 else
1777 /* Otherwise show a different buffer in the window. */
1778 w->dedicated = Qnil;
1779 Fset_window_buffer (window, buffer);
1780 if (EQ (window, selected_window))
1781 Fset_buffer (w->buffer);
1784 break;
1786 /* Check for a window that has a killed buffer. */
1787 case CHECK_ALL_WINDOWS:
1788 if (! NILP (w->buffer)
1789 && NILP (XBUFFER (w->buffer)->name))
1790 abort ();
1791 break;
1793 case WINDOW_LOOP_UNUSED:
1794 break;
1798 UNGCPRO;
1799 return best_window;
1802 /* Used for debugging. Abort if any window has a dead buffer. */
1804 void
1805 check_all_windows ()
1807 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
1810 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1811 "Return the window least recently selected or used for display.\n\
1812 If optional argument FRAME is `visible', search all visible frames.\n\
1813 If FRAME is 0, search all visible and iconified frames.\n\
1814 If FRAME is t, search all frames.\n\
1815 If FRAME is nil, search only the selected frame.\n\
1816 If FRAME is a frame, search only that frame.")
1817 (frame)
1818 Lisp_Object frame;
1820 register Lisp_Object w;
1821 /* First try for a window that is full-width */
1822 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
1823 if (!NILP (w) && !EQ (w, selected_window))
1824 return w;
1825 /* If none of them, try the rest */
1826 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
1829 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1830 "Return the largest window in area.\n\
1831 If optional argument FRAME is `visible', search all visible frames.\n\
1832 If FRAME is 0, search all visible and iconified frames.\n\
1833 If FRAME is t, search all frames.\n\
1834 If FRAME is nil, search only the selected frame.\n\
1835 If FRAME is a frame, search only that frame.")
1836 (frame)
1837 Lisp_Object frame;
1839 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
1840 frame);
1843 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1844 "Return a window currently displaying BUFFER, or nil if none.\n\
1845 If optional argument FRAME is `visible', search all visible frames.\n\
1846 If optional argument FRAME is 0, search all visible and iconified frames.\n\
1847 If FRAME is t, search all frames.\n\
1848 If FRAME is nil, search only the selected frame.\n\
1849 If FRAME is a frame, search only that frame.")
1850 (buffer, frame)
1851 Lisp_Object buffer, frame;
1853 buffer = Fget_buffer (buffer);
1854 if (BUFFERP (buffer))
1855 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
1856 else
1857 return Qnil;
1860 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1861 0, 1, "",
1862 "Make WINDOW (or the selected window) fill its frame.\n\
1863 Only the frame WINDOW is on is affected.\n\
1864 This function tries to reduce display jumps\n\
1865 by keeping the text previously visible in WINDOW\n\
1866 in the same place on the frame. Doing this depends on\n\
1867 the value of (window-start WINDOW), so if calling this function\n\
1868 in a program gives strange scrolling, make sure the window-start\n\
1869 value is reasonable when this function is called.")
1870 (window)
1871 Lisp_Object window;
1873 struct window *w;
1874 int startpos;
1875 int top;
1877 if (NILP (window))
1878 window = selected_window;
1879 else
1880 CHECK_LIVE_WINDOW (window, 0);
1882 w = XWINDOW (window);
1884 startpos = marker_position (w->start);
1885 top = XFASTINT (w->top) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
1887 if (MINI_WINDOW_P (w) && top > 0)
1888 error ("Can't expand minibuffer to full frame");
1890 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
1892 /* Try to minimize scrolling, by setting the window start to the point
1893 will cause the text at the old window start to be at the same place
1894 on the frame. But don't try to do this if the window start is
1895 outside the visible portion (as might happen when the display is
1896 not current, due to typeahead). */
1897 if (startpos >= BUF_BEGV (XBUFFER (w->buffer))
1898 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
1900 struct position pos;
1901 struct buffer *obuf = current_buffer;
1903 Fset_buffer (w->buffer);
1904 /* This computation used to temporarily move point, but that can
1905 have unwanted side effects due to text properties. */
1906 pos = *vmotion (startpos, -top, w);
1908 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
1909 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
1910 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
1911 : Qnil);
1912 /* We need to do this, so that the window-scroll-functions
1913 get called. */
1914 w->optional_new_start = Qt;
1916 set_buffer_internal (obuf);
1919 return Qnil;
1922 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1923 1, 2, "bDelete windows on (buffer): ",
1924 "Delete all windows showing BUFFER.\n\
1925 Optional second argument FRAME controls which frames are affected.\n\
1926 If optional argument FRAME is `visible', search all visible frames.\n\
1927 If FRAME is 0, search all visible and iconified frames.\n\
1928 If FRAME is nil, search all frames.\n\
1929 If FRAME is t, search only the selected frame.\n\
1930 If FRAME is a frame, search only that frame.")
1931 (buffer, frame)
1932 Lisp_Object buffer, frame;
1934 /* FRAME uses t and nil to mean the opposite of what window_loop
1935 expects. */
1936 if (NILP (frame))
1937 frame = Qt;
1938 else if (EQ (frame, Qt))
1939 frame = Qnil;
1941 if (!NILP (buffer))
1943 buffer = Fget_buffer (buffer);
1944 CHECK_BUFFER (buffer, 0);
1945 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
1948 return Qnil;
1951 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1952 Sreplace_buffer_in_windows,
1953 1, 1, "bReplace buffer in windows: ",
1954 "Replace BUFFER with some other buffer in all windows showing it.")
1955 (buffer)
1956 Lisp_Object buffer;
1958 if (!NILP (buffer))
1960 buffer = Fget_buffer (buffer);
1961 CHECK_BUFFER (buffer, 0);
1962 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1964 return Qnil;
1967 /* Replace BUFFER with some other buffer in all windows
1968 of all frames, even those on other keyboards. */
1970 void
1971 replace_buffer_in_all_windows (buffer)
1972 Lisp_Object buffer;
1974 #ifdef MULTI_KBOARD
1975 Lisp_Object tail, frame;
1977 /* A single call to window_loop won't do the job
1978 because it only considers frames on the current keyboard.
1979 So loop manually over frames, and handle each one. */
1980 FOR_EACH_FRAME (tail, frame)
1981 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
1982 #else
1983 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
1984 #endif
1987 /* Set the height of WINDOW and all its inferiors. */
1989 /* The smallest acceptable dimensions for a window. Anything smaller
1990 might crash Emacs. */
1992 #define MIN_SAFE_WINDOW_WIDTH (2)
1993 #define MIN_SAFE_WINDOW_HEIGHT (2)
1995 /* Make sure that window_min_height and window_min_width are
1996 not too small; if they are, set them to safe minima. */
1998 static void
1999 check_min_window_sizes ()
2001 /* Smaller values might permit a crash. */
2002 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2003 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2004 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2005 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2008 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2009 minimum allowable size. */
2011 void
2012 check_frame_size (frame, rows, cols)
2013 FRAME_PTR frame;
2014 int *rows, *cols;
2016 /* For height, we have to see:
2017 whether the frame has a minibuffer,
2018 whether it wants a mode line, and
2019 whether it has a menu bar. */
2020 int min_height =
2021 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
2022 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
2023 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
2025 if (FRAME_TOP_MARGIN (frame) > 0)
2026 min_height += FRAME_TOP_MARGIN (frame);
2028 if (*rows < min_height)
2029 *rows = min_height;
2030 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2031 *cols = MIN_SAFE_WINDOW_WIDTH;
2035 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2036 check if W's width can be changed, otherwise check W's height.
2037 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2038 siblings, too. If none of the siblings is resizable, WINDOW isn't
2039 either. */
2041 static int
2042 window_fixed_size_p (w, width_p, check_siblings_p)
2043 struct window *w;
2044 int width_p, check_siblings_p;
2046 int fixed_p;
2047 struct window *c;
2049 if (!NILP (w->hchild))
2051 c = XWINDOW (w->hchild);
2053 if (width_p)
2055 /* A horiz. combination is fixed-width if all of if its
2056 children are. */
2057 while (c && window_fixed_size_p (c, width_p, 0))
2058 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2059 fixed_p = c == NULL;
2061 else
2063 /* A horiz. combination is fixed-height if one of if its
2064 children is. */
2065 while (c && !window_fixed_size_p (c, width_p, 0))
2066 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2067 fixed_p = c != NULL;
2070 else if (!NILP (w->vchild))
2072 c = XWINDOW (w->vchild);
2074 if (width_p)
2076 /* A vert. combination is fixed-width if one of if its
2077 children is. */
2078 while (c && !window_fixed_size_p (c, width_p, 0))
2079 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2080 fixed_p = c != NULL;
2082 else
2084 /* A vert. combination is fixed-height if all of if its
2085 children are. */
2086 while (c && window_fixed_size_p (c, width_p, 0))
2087 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2088 fixed_p = c == NULL;
2091 else if (BUFFERP (w->buffer))
2093 if (w->height_fixed_p && !width_p)
2094 fixed_p = 1;
2095 else
2097 struct buffer *old = current_buffer;
2098 Lisp_Object val;
2100 current_buffer = XBUFFER (w->buffer);
2101 val = find_symbol_value (Qwindow_size_fixed);
2102 current_buffer = old;
2104 fixed_p = 0;
2105 if (!EQ (val, Qunbound))
2107 fixed_p = !NILP (val);
2109 if (fixed_p
2110 && ((EQ (val, Qheight) && width_p)
2111 || (EQ (val, Qwidth) && !width_p)))
2112 fixed_p = 0;
2116 /* Can't tell if this one is resizable without looking at
2117 siblings. If all siblings are fixed-size this one is too. */
2118 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2120 Lisp_Object child;
2122 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2123 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2124 break;
2126 if (NILP (child))
2127 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2128 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2129 break;
2131 if (NILP (child))
2132 fixed_p = 1;
2135 else
2136 fixed_p = 1;
2138 return fixed_p;
2142 /* Return the minimum size of window W, not taking fixed-width windows
2143 into account. WIDTH_P non-zero means return the minimum width,
2144 otherwise return the minimum height. If W is a combination window,
2145 compute the minimum size from the minimum sizes of W's children. */
2147 static int
2148 window_min_size_1 (w, width_p)
2149 struct window *w;
2150 int width_p;
2152 struct window *c;
2153 int size;
2155 if (!NILP (w->hchild))
2157 c = XWINDOW (w->hchild);
2158 size = 0;
2160 if (width_p)
2162 /* The min width of a horizontal combination is
2163 the sum of the min widths of its children. */
2164 while (c)
2166 size += window_min_size_1 (c, width_p);
2167 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2170 else
2172 /* The min height a horizontal combination equals
2173 the maximum of all min height of its children. */
2174 while (c)
2176 int min_size = window_min_size_1 (c, width_p);
2177 size = max (min_size, size);
2178 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2182 else if (!NILP (w->vchild))
2184 c = XWINDOW (w->vchild);
2185 size = 0;
2187 if (width_p)
2189 /* The min width of a vertical combination is
2190 the maximum of the min widths of its children. */
2191 while (c)
2193 int min_size = window_min_size_1 (c, width_p);
2194 size = max (min_size, size);
2195 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2198 else
2200 /* The min height of a vertical combination equals
2201 the sum of the min height of its children. */
2202 while (c)
2204 size += window_min_size_1 (c, width_p);
2205 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2209 else
2211 if (width_p)
2212 size = window_min_width;
2213 else
2215 if (MINI_WINDOW_P (w)
2216 || (!WINDOW_WANTS_MODELINE_P (w)
2217 && !WINDOW_WANTS_HEADER_LINE_P (w)))
2218 size = 1;
2219 else
2220 size = window_min_height;
2224 return size;
2228 /* Return the minimum size of window W, taking fixed-size windows into
2229 account. WIDTH_P non-zero means return the minimum width,
2230 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2231 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2232 unless FIXED is null. */
2234 static int
2235 window_min_size (w, width_p, ignore_fixed_p, fixed)
2236 struct window *w;
2237 int width_p, ignore_fixed_p, *fixed;
2239 int size, fixed_p;
2241 if (ignore_fixed_p)
2242 fixed_p = 0;
2243 else
2244 fixed_p = window_fixed_size_p (w, width_p, 1);
2246 if (fixed)
2247 *fixed = fixed_p;
2249 if (fixed_p)
2250 size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
2251 else
2252 size = window_min_size_1 (w, width_p);
2254 return size;
2258 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2259 WINDOW's width. Resize WINDOW's children, if any, so that they
2260 keep their proportionate size relative to WINDOW. Propagate
2261 WINDOW's top or left edge position to children. Delete windows
2262 that become too small unless NODELETE_P is non-zero. */
2264 static void
2265 size_window (window, size, width_p, nodelete_p)
2266 Lisp_Object window;
2267 int size, width_p, nodelete_p;
2269 struct window *w = XWINDOW (window);
2270 struct window *c;
2271 Lisp_Object child, *forward, *sideward;
2272 int old_size, min_size;
2274 check_min_window_sizes ();
2275 size = max (0, size);
2277 /* If the window has been "too small" at one point,
2278 don't delete it for being "too small" in the future.
2279 Preserve it as long as that is at all possible. */
2280 if (width_p)
2282 old_size = XINT (w->width);
2283 min_size = window_min_width;
2285 else
2287 old_size = XINT (w->height);
2288 min_size = window_min_height;
2291 if (old_size < window_min_width)
2292 w->too_small_ok = Qt;
2294 /* Maybe delete WINDOW if it's too small. */
2295 if (!nodelete_p && !NILP (w->parent))
2297 int min_size;
2299 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
2300 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
2301 else
2302 min_size = width_p ? window_min_width : window_min_height;
2304 if (size < min_size)
2306 delete_window (window);
2307 return;
2311 /* Set redisplay hints. */
2312 w->last_modified = make_number (0);
2313 w->last_overlay_modified = make_number (0);
2314 windows_or_buffers_changed++;
2315 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
2317 if (width_p)
2319 sideward = &w->vchild;
2320 forward = &w->hchild;
2321 w->width = make_number (size);
2323 else
2325 sideward = &w->hchild;
2326 forward = &w->vchild;
2327 w->height = make_number (size);
2330 if (!NILP (*sideward))
2332 for (child = *sideward; !NILP (child); child = c->next)
2334 c = XWINDOW (child);
2335 if (width_p)
2336 c->left = w->left;
2337 else
2338 c->top = w->top;
2339 size_window (child, size, width_p, nodelete_p);
2342 else if (!NILP (*forward))
2344 int fixed_size, each, extra, n;
2345 int resize_fixed_p, nfixed;
2346 int last_pos, first_pos, nchildren, total;
2348 /* Determine the fixed-size portion of the this window, and the
2349 number of child windows. */
2350 fixed_size = nchildren = nfixed = total = 0;
2351 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
2353 int child_size;
2355 c = XWINDOW (child);
2356 child_size = width_p ? XINT (c->width) : XINT (c->height);
2357 total += child_size;
2359 if (window_fixed_size_p (c, width_p, 0))
2361 fixed_size += child_size;
2362 ++nfixed;
2366 /* If the new size is smaller than fixed_size, or if there
2367 aren't any resizable windows, allow resizing fixed-size
2368 windows. */
2369 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2371 /* Compute how many lines/columns to add to each child. The
2372 value of extra takes care of rounding errors. */
2373 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2374 each = (size - total) / n;
2375 extra = (size - total) - n * each;
2377 /* Compute new children heights and edge positions. */
2378 first_pos = width_p ? XINT (w->left) : XINT (w->top);
2379 last_pos = first_pos;
2380 for (child = *forward; !NILP (child); child = c->next)
2382 int new_size, old_size;
2384 c = XWINDOW (child);
2385 old_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2386 new_size = old_size;
2388 /* The top or left edge position of this child equals the
2389 bottom or right edge of its predecessor. */
2390 if (width_p)
2391 c->left = make_number (last_pos);
2392 else
2393 c->top = make_number (last_pos);
2395 /* If this child can be resized, do it. */
2396 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2398 new_size = old_size + each + extra;
2399 extra = 0;
2402 /* Set new height. Note that size_window also propagates
2403 edge positions to children, so it's not a no-op if we
2404 didn't change the child's size. */
2405 size_window (child, new_size, width_p, 1);
2407 /* Remember the bottom/right edge position of this child; it
2408 will be used to set the top/left edge of the next child. */
2409 last_pos += new_size;
2412 /* We should have covered the parent exactly with child windows. */
2413 xassert (size == last_pos - first_pos);
2415 /* Now delete any children that became too small. */
2416 if (!nodelete_p)
2417 for (child = *forward; !NILP (child); child = c->next)
2419 int child_size;
2420 c = XWINDOW (child);
2421 child_size = width_p ? XINT (c->width) : XINT (c->height);
2422 size_window (child, child_size, width_p, 0);
2427 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2428 WINDOW's children. NODELETE non-zero means don't delete windows
2429 that become too small in the process. (The caller should check
2430 later and do so if appropriate.) */
2432 void
2433 set_window_height (window, height, nodelete)
2434 Lisp_Object window;
2435 int height;
2436 int nodelete;
2438 size_window (window, height, 0, nodelete);
2442 /* Set WINDOW's width to WIDTH, and recursively change the width of
2443 WINDOW's children. NODELETE non-zero means don't delete windows
2444 that become too small in the process. (The caller should check
2445 later and do so if appropriate.) */
2447 void
2448 set_window_width (window, width, nodelete)
2449 Lisp_Object window;
2450 int width;
2451 int nodelete;
2453 size_window (window, width, 1, nodelete);
2457 int window_select_count;
2459 Lisp_Object
2460 Fset_window_buffer_unwind (obuf)
2461 Lisp_Object obuf;
2463 Fset_buffer (obuf);
2464 return Qnil;
2468 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2469 means it's allowed to run hooks. See make_frame for a case where
2470 it's not allowed. */
2472 void
2473 set_window_buffer (window, buffer, run_hooks_p)
2474 Lisp_Object window, buffer;
2475 int run_hooks_p;
2477 struct window *w = XWINDOW (window);
2478 struct buffer *b = XBUFFER (buffer);
2479 int count = specpdl_ptr - specpdl;
2481 w->buffer = buffer;
2483 if (EQ (window, selected_window))
2484 b->last_selected_window = window;
2486 /* Update time stamps of buffer display. */
2487 if (INTEGERP (b->display_count))
2488 XSETINT (b->display_count, XINT (b->display_count) + 1);
2489 b->display_time = Fcurrent_time ();
2491 XSETFASTINT (w->window_end_pos, 0);
2492 XSETFASTINT (w->window_end_vpos, 0);
2493 bzero (&w->last_cursor, sizeof w->last_cursor);
2494 w->window_end_valid = Qnil;
2495 XSETFASTINT (w->hscroll, 0);
2496 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
2497 set_marker_restricted (w->start,
2498 make_number (b->last_window_start),
2499 buffer);
2500 w->start_at_line_beg = Qnil;
2501 w->force_start = Qnil;
2502 XSETFASTINT (w->last_modified, 0);
2503 XSETFASTINT (w->last_overlay_modified, 0);
2504 windows_or_buffers_changed++;
2506 /* We must select BUFFER for running the window-scroll-functions.
2507 If WINDOW is selected, switch permanently.
2508 Otherwise, switch but go back to the ambient buffer afterward. */
2509 if (EQ (window, selected_window))
2510 Fset_buffer (buffer);
2511 /* We can't check ! NILP (Vwindow_scroll_functions) here
2512 because that might itself be a local variable. */
2513 else if (window_initialized)
2515 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2516 Fset_buffer (buffer);
2519 /* Set left and right marginal area width from buffer. */
2520 Fset_window_margins (window, b->left_margin_width, b->right_margin_width);
2522 if (run_hooks_p)
2524 if (! NILP (Vwindow_scroll_functions))
2525 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2526 Fmarker_position (w->start));
2528 if (! NILP (Vwindow_configuration_change_hook)
2529 && ! NILP (Vrun_hooks))
2530 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2533 unbind_to (count, Qnil);
2537 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
2538 "Make WINDOW display BUFFER as its contents.\n\
2539 BUFFER can be a buffer or buffer name.")
2540 (window, buffer)
2541 register Lisp_Object window, buffer;
2543 register Lisp_Object tem;
2544 register struct window *w = decode_window (window);
2546 XSETWINDOW (window, w);
2547 buffer = Fget_buffer (buffer);
2548 CHECK_BUFFER (buffer, 1);
2550 if (NILP (XBUFFER (buffer)->name))
2551 error ("Attempt to display deleted buffer");
2553 tem = w->buffer;
2554 if (NILP (tem))
2555 error ("Window is deleted");
2556 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
2557 is first being set up. */
2559 if (!NILP (w->dedicated) && !EQ (tem, buffer))
2560 error ("Window is dedicated to `%s'",
2561 XSTRING (XBUFFER (tem)->name)->data);
2563 unshow_buffer (w);
2566 set_window_buffer (window, buffer, 1);
2567 return Qnil;
2570 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
2571 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
2572 If WINDOW is not already selected, also make WINDOW's buffer current.\n\
2573 Note that the main editor command loop\n\
2574 selects the buffer of the selected window before each command.")
2575 (window)
2576 register Lisp_Object window;
2578 return select_window_1 (window, 1);
2581 /* Note that selected_window can be nil
2582 when this is called from Fset_window_configuration. */
2584 static Lisp_Object
2585 select_window_1 (window, recordflag)
2586 register Lisp_Object window;
2587 int recordflag;
2589 register struct window *w;
2590 register struct window *ow;
2591 struct frame *sf;
2593 CHECK_LIVE_WINDOW (window, 0);
2595 w = XWINDOW (window);
2597 if (NILP (w->buffer))
2598 error ("Trying to select deleted window or non-leaf window");
2600 XSETFASTINT (w->use_time, ++window_select_count);
2601 if (EQ (window, selected_window))
2602 return window;
2604 if (!NILP (selected_window))
2606 ow = XWINDOW (selected_window);
2607 if (! NILP (ow->buffer))
2608 set_marker_both (ow->pointm, ow->buffer,
2609 BUF_PT (XBUFFER (ow->buffer)),
2610 BUF_PT_BYTE (XBUFFER (ow->buffer)));
2613 selected_window = window;
2614 sf = SELECTED_FRAME ();
2615 if (XFRAME (WINDOW_FRAME (w)) != sf)
2617 XFRAME (WINDOW_FRAME (w))->selected_window = window;
2618 /* Use this rather than Fhandle_switch_frame
2619 so that FRAME_FOCUS_FRAME is moved appropriately as we
2620 move around in the state where a minibuffer in a separate
2621 frame is active. */
2622 Fselect_frame (WINDOW_FRAME (w), Qnil);
2624 else
2625 sf->selected_window = window;
2627 if (recordflag)
2628 record_buffer (w->buffer);
2629 Fset_buffer (w->buffer);
2631 XBUFFER (w->buffer)->last_selected_window = window;
2633 /* Go to the point recorded in the window.
2634 This is important when the buffer is in more
2635 than one window. It also matters when
2636 redisplay_window has altered point after scrolling,
2637 because it makes the change only in the window. */
2639 register int new_point = marker_position (w->pointm);
2640 if (new_point < BEGV)
2641 SET_PT (BEGV);
2642 else if (new_point > ZV)
2643 SET_PT (ZV);
2644 else
2645 SET_PT (new_point);
2648 windows_or_buffers_changed++;
2649 return window;
2652 /* Deiconify the frame containing the window WINDOW,
2653 unless it is the selected frame;
2654 then return WINDOW.
2656 The reason for the exception for the selected frame
2657 is that it seems better not to change the selected frames visibility
2658 merely because of displaying a different buffer in it.
2659 The deiconification is useful when a buffer gets shown in
2660 another frame that you were not using lately. */
2662 static Lisp_Object
2663 display_buffer_1 (window)
2664 Lisp_Object window;
2666 Lisp_Object frame = XWINDOW (window)->frame;
2667 FRAME_PTR f = XFRAME (frame);
2669 FRAME_SAMPLE_VISIBILITY (f);
2671 if (!EQ (frame, selected_frame))
2673 if (FRAME_ICONIFIED_P (f))
2674 Fmake_frame_visible (frame);
2675 else if (FRAME_VISIBLE_P (f))
2676 Fraise_frame (frame);
2679 return window;
2682 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
2683 "Returns non-nil if a buffer named BUFFER-NAME would be created specially.\n\
2684 The value is actually t if the frame should be called with default frame\n\
2685 parameters, and a list of frame parameters if they were specified.\n\
2686 See `special-display-buffer-names', and `special-display-regexps'.")
2687 (buffer_name)
2688 Lisp_Object buffer_name;
2690 Lisp_Object tem;
2692 CHECK_STRING (buffer_name, 1);
2694 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2695 if (!NILP (tem))
2696 return Qt;
2698 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2699 if (!NILP (tem))
2700 return XCDR (tem);
2702 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2704 Lisp_Object car = XCAR (tem);
2705 if (STRINGP (car)
2706 && fast_string_match (car, buffer_name) >= 0)
2707 return Qt;
2708 else if (CONSP (car)
2709 && STRINGP (XCAR (car))
2710 && fast_string_match (XCAR (car), buffer_name) >= 0)
2711 return XCDR (car);
2713 return Qnil;
2716 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
2717 "Returns non-nil if a new buffer named BUFFER-NAME would use the same window.\n\
2718 See `same-window-buffer-names' and `same-window-regexps'.")
2719 (buffer_name)
2720 Lisp_Object buffer_name;
2722 Lisp_Object tem;
2724 CHECK_STRING (buffer_name, 1);
2726 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2727 if (!NILP (tem))
2728 return Qt;
2730 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2731 if (!NILP (tem))
2732 return Qt;
2734 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
2736 Lisp_Object car = XCAR (tem);
2737 if (STRINGP (car)
2738 && fast_string_match (car, buffer_name) >= 0)
2739 return Qt;
2740 else if (CONSP (car)
2741 && STRINGP (XCAR (car))
2742 && fast_string_match (XCAR (car), buffer_name) >= 0)
2743 return Qt;
2745 return Qnil;
2748 /* Use B so the default is (other-buffer). */
2749 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
2750 "BDisplay buffer: \nP",
2751 "Make BUFFER appear in some window but don't select it.\n\
2752 BUFFER can be a buffer or a buffer name.\n\
2753 If BUFFER is shown already in some window, just use that one,\n\
2754 unless the window is the selected window and the optional second\n\
2755 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
2756 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
2757 Returns the window displaying BUFFER.\n\
2758 If `display-reuse-frames' is non-nil, and another frame is currently\n\
2759 displaying BUFFER, then simply raise that frame.\n\
2761 The variables `special-display-buffer-names', `special-display-regexps',\n\
2762 `same-window-buffer-names', and `same-window-regexps' customize how certain\n\
2763 buffer names are handled.\n\
2765 If optional argument FRAME is `visible', search all visible frames.\n\
2766 If FRAME is 0, search all visible and iconified frames.\n\
2767 If FRAME is t, search all frames.\n\
2768 If FRAME is a frame, search only that frame.\n\
2769 If FRAME is nil, search only the selected frame\n\
2770 (actually the last nonminibuffer frame),\n\
2771 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,\n\
2772 which means search visible and iconified frames.")
2773 (buffer, not_this_window, frame)
2774 register Lisp_Object buffer, not_this_window, frame;
2776 register Lisp_Object window, tem, swp;
2777 struct frame *f;
2779 swp = Qnil;
2780 buffer = Fget_buffer (buffer);
2781 CHECK_BUFFER (buffer, 0);
2783 if (!NILP (Vdisplay_buffer_function))
2784 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
2786 if (NILP (not_this_window)
2787 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
2788 return display_buffer_1 (selected_window);
2790 /* See if the user has specified this buffer should appear
2791 in the selected window. */
2792 if (NILP (not_this_window))
2794 swp = Fsame_window_p (XBUFFER (buffer)->name);
2795 if (!NILP (swp) && !no_switch_window (selected_window))
2797 Fswitch_to_buffer (buffer, Qnil);
2798 return display_buffer_1 (selected_window);
2802 /* If the user wants pop-up-frames or display-reuse-frames, then
2803 look for a window showing BUFFER on any visible or iconified frame.
2804 Otherwise search only the current frame. */
2805 if (! NILP (frame))
2806 tem = frame;
2807 else if (pop_up_frames
2808 || display_buffer_reuse_frames
2809 || last_nonminibuf_frame == 0)
2810 XSETFASTINT (tem, 0);
2811 else
2812 XSETFRAME (tem, last_nonminibuf_frame);
2814 window = Fget_buffer_window (buffer, tem);
2815 if (!NILP (window)
2816 && (NILP (not_this_window) || !EQ (window, selected_window)))
2817 return display_buffer_1 (window);
2819 /* Certain buffer names get special handling. */
2820 if (!NILP (Vspecial_display_function) && NILP (swp))
2822 tem = Fspecial_display_p (XBUFFER (buffer)->name);
2823 if (EQ (tem, Qt))
2824 return call1 (Vspecial_display_function, buffer);
2825 if (CONSP (tem))
2826 return call2 (Vspecial_display_function, buffer, tem);
2829 /* If there are no frames open that have more than a minibuffer,
2830 we need to create a new frame. */
2831 if (pop_up_frames || last_nonminibuf_frame == 0)
2833 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2834 Fset_window_buffer (window, buffer);
2835 return display_buffer_1 (window);
2838 f = SELECTED_FRAME ();
2839 if (pop_up_windows
2840 || FRAME_MINIBUF_ONLY_P (f)
2841 /* If the current frame is a special display frame,
2842 don't try to reuse its windows. */
2843 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
2845 Lisp_Object frames;
2847 frames = Qnil;
2848 if (FRAME_MINIBUF_ONLY_P (f))
2849 XSETFRAME (frames, last_nonminibuf_frame);
2850 /* Don't try to create a window if would get an error */
2851 if (split_height_threshold < window_min_height << 1)
2852 split_height_threshold = window_min_height << 1;
2854 /* Note that both Fget_largest_window and Fget_lru_window
2855 ignore minibuffers and dedicated windows.
2856 This means they can return nil. */
2858 /* If the frame we would try to split cannot be split,
2859 try other frames. */
2860 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
2862 /* Try visible frames first. */
2863 window = Fget_largest_window (Qvisible);
2864 /* If that didn't work, try iconified frames. */
2865 if (NILP (window))
2866 window = Fget_largest_window (make_number (0));
2867 if (NILP (window))
2868 window = Fget_largest_window (Qt);
2870 else
2871 window = Fget_largest_window (frames);
2873 /* If we got a tall enough full-width window that can be split,
2874 split it. */
2875 if (!NILP (window)
2876 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2877 && window_height (window) >= split_height_threshold
2878 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
2879 window = Fsplit_window (window, Qnil, Qnil);
2880 else
2882 Lisp_Object upper, lower, other;
2884 window = Fget_lru_window (frames);
2885 /* If the LRU window is selected, and big enough,
2886 and can be split, split it. */
2887 if (!NILP (window)
2888 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2889 && (EQ (window, selected_window)
2890 || EQ (XWINDOW (window)->parent, Qnil))
2891 && window_height (window) >= window_min_height << 1)
2892 window = Fsplit_window (window, Qnil, Qnil);
2893 /* If Fget_lru_window returned nil, try other approaches. */
2895 /* Try visible frames first. */
2896 if (NILP (window))
2897 window = Fget_buffer_window (buffer, Qvisible);
2898 if (NILP (window))
2899 window = Fget_largest_window (Qvisible);
2900 /* If that didn't work, try iconified frames. */
2901 if (NILP (window))
2902 window = Fget_buffer_window (buffer, make_number (0));
2903 if (NILP (window))
2904 window = Fget_largest_window (make_number (0));
2905 /* Try invisible frames. */
2906 if (NILP (window))
2907 window = Fget_buffer_window (buffer, Qt);
2908 if (NILP (window))
2909 window = Fget_largest_window (Qt);
2910 /* As a last resort, make a new frame. */
2911 if (NILP (window))
2912 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2913 /* If window appears above or below another,
2914 even out their heights. */
2915 other = upper = lower = Qnil;
2916 if (!NILP (XWINDOW (window)->prev))
2917 other = upper = XWINDOW (window)->prev, lower = window;
2918 if (!NILP (XWINDOW (window)->next))
2919 other = lower = XWINDOW (window)->next, upper = window;
2920 if (!NILP (other)
2921 /* Check that OTHER and WINDOW are vertically arrayed. */
2922 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
2923 && (XFASTINT (XWINDOW (other)->height)
2924 > XFASTINT (XWINDOW (window)->height)))
2926 int total = (XFASTINT (XWINDOW (other)->height)
2927 + XFASTINT (XWINDOW (window)->height));
2928 enlarge_window (upper,
2929 total / 2 - XFASTINT (XWINDOW (upper)->height),
2934 else
2935 window = Fget_lru_window (Qnil);
2937 Fset_window_buffer (window, buffer);
2938 return display_buffer_1 (window);
2941 void
2942 temp_output_buffer_show (buf)
2943 register Lisp_Object buf;
2945 register struct buffer *old = current_buffer;
2946 register Lisp_Object window;
2947 register struct window *w;
2949 XBUFFER (buf)->directory = current_buffer->directory;
2951 Fset_buffer (buf);
2952 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
2953 BEGV = BEG;
2954 ZV = Z;
2955 SET_PT (BEG);
2956 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
2957 set_buffer_internal (old);
2959 if (!EQ (Vtemp_buffer_show_function, Qnil))
2960 call1 (Vtemp_buffer_show_function, buf);
2961 else
2963 window = Fdisplay_buffer (buf, Qnil, Qnil);
2965 if (!EQ (XWINDOW (window)->frame, selected_frame))
2966 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
2967 Vminibuf_scroll_window = window;
2968 w = XWINDOW (window);
2969 XSETFASTINT (w->hscroll, 0);
2970 set_marker_restricted_both (w->start, buf, 1, 1);
2971 set_marker_restricted_both (w->pointm, buf, 1, 1);
2973 /* Run temp-buffer-show-hook, with the chosen window selected
2974 and it sbuffer current. */
2975 if (!NILP (Vrun_hooks))
2977 Lisp_Object tem;
2978 tem = Fboundp (Qtemp_buffer_show_hook);
2979 if (!NILP (tem))
2981 tem = Fsymbol_value (Qtemp_buffer_show_hook);
2982 if (!NILP (tem))
2984 int count = specpdl_ptr - specpdl;
2985 Lisp_Object prev_window;
2986 prev_window = selected_window;
2988 /* Select the window that was chosen, for running the hook. */
2989 record_unwind_protect (Fselect_window, prev_window);
2990 select_window_1 (window, 0);
2991 Fset_buffer (w->buffer);
2992 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
2993 select_window_1 (prev_window, 0);
2994 unbind_to (count, Qnil);
3001 static void
3002 make_dummy_parent (window)
3003 Lisp_Object window;
3005 Lisp_Object new;
3006 register struct window *o, *p;
3007 register struct Lisp_Vector *vec;
3008 int i;
3010 o = XWINDOW (window);
3011 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
3012 for (i = 0; i < VECSIZE (struct window); ++i)
3013 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
3014 vec->size = VECSIZE (struct window);
3015 p = (struct window *)vec;
3016 XSETWINDOW (new, p);
3018 XSETFASTINT (p->sequence_number, ++sequence_number);
3020 /* Put new into window structure in place of window */
3021 replace_window (window, new);
3023 o->next = Qnil;
3024 o->prev = Qnil;
3025 o->vchild = Qnil;
3026 o->hchild = Qnil;
3027 o->parent = new;
3029 p->start = Qnil;
3030 p->pointm = Qnil;
3031 p->buffer = Qnil;
3034 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3035 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
3036 WINDOW defaults to selected one and SIZE to half its size.\n\
3037 If optional third arg HORFLAG is non-nil, split side by side\n\
3038 and put SIZE columns in the first of the pair. In that case,\n\
3039 SIZE includes that window's scroll bar, or the divider column to its right.")
3040 (window, size, horflag)
3041 Lisp_Object window, size, horflag;
3043 register Lisp_Object new;
3044 register struct window *o, *p;
3045 FRAME_PTR fo;
3046 register int size_int;
3048 if (NILP (window))
3049 window = selected_window;
3050 else
3051 CHECK_LIVE_WINDOW (window, 0);
3053 o = XWINDOW (window);
3054 fo = XFRAME (WINDOW_FRAME (o));
3056 if (NILP (size))
3058 if (!NILP (horflag))
3059 /* Calculate the size of the left-hand window, by dividing
3060 the usable space in columns by two.
3061 We round up, since the left-hand window may include
3062 a dividing line, while the right-hand may not. */
3063 size_int = (XFASTINT (o->width) + 1) >> 1;
3064 else
3065 size_int = XFASTINT (o->height) >> 1;
3067 else
3069 CHECK_NUMBER (size, 1);
3070 size_int = XINT (size);
3073 if (MINI_WINDOW_P (o))
3074 error ("Attempt to split minibuffer window");
3075 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3076 error ("Attempt to split fixed-size window");
3078 check_min_window_sizes ();
3080 if (NILP (horflag))
3082 if (size_int < window_min_height)
3083 error ("Window height %d too small (after splitting)", size_int);
3084 if (size_int + window_min_height > XFASTINT (o->height))
3085 error ("Window height %d too small (after splitting)",
3086 XFASTINT (o->height) - size_int);
3087 if (NILP (o->parent)
3088 || NILP (XWINDOW (o->parent)->vchild))
3090 make_dummy_parent (window);
3091 new = o->parent;
3092 XWINDOW (new)->vchild = window;
3095 else
3097 if (size_int < window_min_width)
3098 error ("Window width %d too small (after splitting)", size_int);
3100 if (size_int + window_min_width > XFASTINT (o->width))
3101 error ("Window width %d too small (after splitting)",
3102 XFASTINT (o->width) - size_int);
3103 if (NILP (o->parent)
3104 || NILP (XWINDOW (o->parent)->hchild))
3106 make_dummy_parent (window);
3107 new = o->parent;
3108 XWINDOW (new)->hchild = window;
3112 /* Now we know that window's parent is a vertical combination
3113 if we are dividing vertically, or a horizontal combination
3114 if we are making side-by-side windows */
3116 windows_or_buffers_changed++;
3117 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3118 new = make_window ();
3119 p = XWINDOW (new);
3121 p->frame = o->frame;
3122 p->next = o->next;
3123 if (!NILP (p->next))
3124 XWINDOW (p->next)->prev = new;
3125 p->prev = window;
3126 o->next = new;
3127 p->parent = o->parent;
3128 p->buffer = Qt;
3129 p->window_end_valid = Qnil;
3130 bzero (&p->last_cursor, sizeof p->last_cursor);
3132 /* Apportion the available frame space among the two new windows */
3134 if (!NILP (horflag))
3136 p->height = o->height;
3137 p->top = o->top;
3138 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
3139 XSETFASTINT (o->width, size_int);
3140 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
3142 else
3144 p->left = o->left;
3145 p->width = o->width;
3146 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
3147 XSETFASTINT (o->height, size_int);
3148 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
3151 /* Adjust glyph matrices. */
3152 adjust_glyphs (fo);
3153 Fset_window_buffer (new, o->buffer);
3154 return new;
3157 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3158 "Make current window ARG lines bigger.\n\
3159 From program, optional second arg non-nil means grow sideways ARG columns.")
3160 (arg, side)
3161 register Lisp_Object arg, side;
3163 CHECK_NUMBER (arg, 0);
3164 enlarge_window (selected_window, XINT (arg), !NILP (side));
3166 if (! NILP (Vwindow_configuration_change_hook))
3167 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3169 return Qnil;
3172 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3173 "Make current window ARG lines smaller.\n\
3174 From program, optional second arg non-nil means shrink sideways arg columns.")
3175 (arg, side)
3176 register Lisp_Object arg, side;
3178 CHECK_NUMBER (arg, 0);
3179 enlarge_window (selected_window, -XINT (arg), !NILP (side));
3181 if (! NILP (Vwindow_configuration_change_hook))
3182 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3184 return Qnil;
3188 window_height (window)
3189 Lisp_Object window;
3191 register struct window *p = XWINDOW (window);
3192 return XFASTINT (p->height);
3196 window_width (window)
3197 Lisp_Object window;
3199 register struct window *p = XWINDOW (window);
3200 return XFASTINT (p->width);
3204 #define CURBEG(w) \
3205 *(widthflag ? &(XWINDOW (w)->left) : &(XWINDOW (w)->top))
3207 #define CURSIZE(w) \
3208 *(widthflag ? &(XWINDOW (w)->width) : &(XWINDOW (w)->height))
3211 /* Enlarge selected_window by DELTA. WIDTHFLAG non-zero means
3212 increase its width. Siblings of the selected window are resized to
3213 fullfil the size request. If they become too small in the process,
3214 they will be deleted. */
3216 static void
3217 enlarge_window (window, delta, widthflag)
3218 Lisp_Object window;
3219 int delta, widthflag;
3221 Lisp_Object parent, next, prev;
3222 struct window *p;
3223 Lisp_Object *sizep;
3224 int maximum;
3225 int (*sizefun) P_ ((Lisp_Object))
3226 = widthflag ? window_width : window_height;
3227 void (*setsizefun) P_ ((Lisp_Object, int, int))
3228 = (widthflag ? set_window_width : set_window_height);
3230 /* Check values of window_min_width and window_min_height for
3231 validity. */
3232 check_min_window_sizes ();
3234 /* Give up if this window cannot be resized. */
3235 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3236 error ("Window is not resizable");
3238 /* Find the parent of the selected window. */
3239 while (1)
3241 p = XWINDOW (window);
3242 parent = p->parent;
3244 if (NILP (parent))
3246 if (widthflag)
3247 error ("No other window to side of this one");
3248 break;
3251 if (widthflag
3252 ? !NILP (XWINDOW (parent)->hchild)
3253 : !NILP (XWINDOW (parent)->vchild))
3254 break;
3256 window = parent;
3259 sizep = &CURSIZE (window);
3262 register int maxdelta;
3264 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
3265 : !NILP (p->next) ? ((*sizefun) (p->next)
3266 - window_min_size (XWINDOW (p->next),
3267 widthflag, 0, 0))
3268 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3269 - window_min_size (XWINDOW (p->prev),
3270 widthflag, 0, 0))
3271 /* This is a frame with only one window, a minibuffer-only
3272 or a minibufferless frame. */
3273 : (delta = 0));
3275 if (delta > maxdelta)
3276 /* This case traps trying to make the minibuffer
3277 the full frame, or make the only window aside from the
3278 minibuffer the full frame. */
3279 delta = maxdelta;
3282 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3284 delete_window (window);
3285 return;
3288 if (delta == 0)
3289 return;
3291 /* Find the total we can get from other siblings. */
3292 maximum = 0;
3293 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3294 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3295 widthflag, 0, 0);
3296 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3297 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3298 widthflag, 0, 0);
3300 /* If we can get it all from them, do so. */
3301 if (delta <= maximum)
3303 Lisp_Object first_unaffected;
3304 Lisp_Object first_affected;
3305 int fixed_p;
3307 next = p->next;
3308 prev = p->prev;
3309 first_affected = window;
3310 /* Look at one sibling at a time,
3311 moving away from this window in both directions alternately,
3312 and take as much as we can get without deleting that sibling. */
3313 while (delta != 0 && (!NILP (next) || !NILP (prev)))
3315 if (! NILP (next))
3317 int this_one = ((*sizefun) (next)
3318 - window_min_size (XWINDOW (next),
3319 widthflag, 0, &fixed_p));
3320 if (!fixed_p)
3322 if (this_one > delta)
3323 this_one = delta;
3325 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3326 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3328 delta -= this_one;
3331 next = XWINDOW (next)->next;
3334 if (delta == 0)
3335 break;
3337 if (! NILP (prev))
3339 int this_one = ((*sizefun) (prev)
3340 - window_min_size (XWINDOW (prev),
3341 widthflag, 0, &fixed_p));
3342 if (!fixed_p)
3344 if (this_one > delta)
3345 this_one = delta;
3347 first_affected = prev;
3349 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3350 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3352 delta -= this_one;
3355 prev = XWINDOW (prev)->prev;
3359 xassert (delta == 0);
3361 /* Now recalculate the edge positions of all the windows affected,
3362 based on the new sizes. */
3363 first_unaffected = next;
3364 prev = first_affected;
3365 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3366 prev = next, next = XWINDOW (next)->next)
3368 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
3369 /* This does not change size of NEXT,
3370 but it propagates the new top edge to its children */
3371 (*setsizefun) (next, (*sizefun) (next), 0);
3374 else
3376 register int delta1;
3377 register int opht = (*sizefun) (parent);
3379 /* If trying to grow this window to or beyond size of the parent,
3380 make delta1 so big that, on shrinking back down,
3381 all the siblings end up with less than one line and are deleted. */
3382 if (opht <= XINT (*sizep) + delta)
3383 delta1 = opht * opht * 2;
3384 else
3386 /* Otherwise, make delta1 just right so that if we add
3387 delta1 lines to this window and to the parent, and then
3388 shrink the parent back to its original size, the new
3389 proportional size of this window will increase by delta.
3391 The function size_window will compute the new height h'
3392 of the window from delta1 as:
3394 e = delta1/n
3395 x = delta1 - delta1/n * n for the 1st resizable child
3396 h' = h + e + x
3398 where n is the number of children that can be resized.
3399 We can ignore x by choosing a delta1 that is a multiple of
3400 n. We want the height of this window to come out as
3402 h' = h + delta
3404 So, delta1 must be
3406 h + e = h + delta
3407 delta1/n = delta
3408 delta1 = n * delta.
3410 The number of children n rquals the number of resizable
3411 children of this window + 1 because we know window itself
3412 is resizable (otherwise we would have signalled an error. */
3414 struct window *w = XWINDOW (window);
3415 Lisp_Object s;
3416 int n = 1;
3418 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3419 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3420 ++n;
3421 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3422 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3423 ++n;
3425 delta1 = n * delta;
3428 /* Add delta1 lines or columns to this window, and to the parent,
3429 keeping things consistent while not affecting siblings. */
3430 XSETINT (CURSIZE (parent), opht + delta1);
3431 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
3433 /* Squeeze out delta1 lines or columns from our parent,
3434 shriking this window and siblings proportionately.
3435 This brings parent back to correct size.
3436 Delta1 was calculated so this makes this window the desired size,
3437 taking it all out of the siblings. */
3438 (*setsizefun) (parent, opht, 0);
3441 XSETFASTINT (p->last_modified, 0);
3442 XSETFASTINT (p->last_overlay_modified, 0);
3444 /* Adjust glyph matrices. */
3445 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
3448 #undef CURBEG
3449 #undef CURSIZE
3453 /***********************************************************************
3454 Resizing Mini-Windows
3455 ***********************************************************************/
3457 static void shrink_window_lowest_first P_ ((struct window *, int));
3459 enum save_restore_action
3461 CHECK_ORIG_SIZES,
3462 SAVE_ORIG_SIZES,
3463 RESTORE_ORIG_SIZES
3466 static int save_restore_orig_size P_ ((struct window *,
3467 enum save_restore_action));
3469 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
3470 from lowest windows first. */
3472 static void
3473 shrink_window_lowest_first (w, height)
3474 struct window *w;
3475 int height;
3477 struct window *c;
3478 Lisp_Object child;
3479 int old_height;
3481 xassert (!MINI_WINDOW_P (w));
3483 /* Set redisplay hints. */
3484 XSETFASTINT (w->last_modified, 0);
3485 XSETFASTINT (w->last_overlay_modified, 0);
3486 windows_or_buffers_changed++;
3487 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
3489 old_height = XFASTINT (w->height);
3490 XSETFASTINT (w->height, height);
3492 if (!NILP (w->hchild))
3494 for (child = w->hchild; !NILP (child); child = c->next)
3496 c = XWINDOW (child);
3497 c->top = w->top;
3498 shrink_window_lowest_first (c, height);
3501 else if (!NILP (w->vchild))
3503 Lisp_Object last_child;
3504 int delta = old_height - height;
3505 int last_top;
3507 last_child = Qnil;
3509 /* Find the last child. We are taking space from lowest windows
3510 first, so we iterate over children from the last child
3511 backwards. */
3512 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
3513 last_child = child;
3515 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
3516 for (child = last_child; delta && !NILP (child); child = c->prev)
3518 int this_one;
3520 c = XWINDOW (child);
3521 this_one = XFASTINT (c->height) - MIN_SAFE_WINDOW_HEIGHT;
3523 if (this_one > delta)
3524 this_one = delta;
3526 shrink_window_lowest_first (c, XFASTINT (c->height) - this_one);
3527 delta -= this_one;
3530 /* Compute new positions. */
3531 last_top = XINT (w->top);
3532 for (child = w->vchild; !NILP (child); child = c->next)
3534 c = XWINDOW (child);
3535 c->top = make_number (last_top);
3536 shrink_window_lowest_first (c, XFASTINT (c->height));
3537 last_top += XFASTINT (c->height);
3543 /* Save, restore, or check positions and sizes in the window tree
3544 rooted at W. ACTION says what to do.
3546 If ACTION is CHECK_ORIG_SIZES, check if orig_top and orig_height
3547 members are valid for all windows in the window tree. Value is
3548 non-zero if they are valid.
3550 If ACTION is SAVE_ORIG_SIZES, save members top and height in
3551 orig_top and orig_height for all windows in the tree.
3553 If ACTION is RESTORE_ORIG_SIZES, restore top and height from
3554 values stored in orig_top and orig_height for all windows. */
3556 static int
3557 save_restore_orig_size (w, action)
3558 struct window *w;
3559 enum save_restore_action action;
3561 int success_p = 1;
3563 while (w)
3565 if (!NILP (w->hchild))
3567 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
3568 success_p = 0;
3570 else if (!NILP (w->vchild))
3572 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
3573 success_p = 0;
3576 switch (action)
3578 case CHECK_ORIG_SIZES:
3579 if (!INTEGERP (w->orig_top) || !INTEGERP (w->orig_height))
3580 return 0;
3581 break;
3583 case SAVE_ORIG_SIZES:
3584 w->orig_top = w->top;
3585 w->orig_height = w->height;
3586 XSETFASTINT (w->last_modified, 0);
3587 XSETFASTINT (w->last_overlay_modified, 0);
3588 break;
3590 case RESTORE_ORIG_SIZES:
3591 xassert (INTEGERP (w->orig_top) && INTEGERP (w->orig_height));
3592 w->top = w->orig_top;
3593 w->height = w->orig_height;
3594 w->orig_height = w->orig_top = Qnil;
3595 XSETFASTINT (w->last_modified, 0);
3596 XSETFASTINT (w->last_overlay_modified, 0);
3597 break;
3599 default:
3600 abort ();
3603 w = NILP (w->next) ? NULL : XWINDOW (w->next);
3606 return success_p;
3610 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
3611 without deleting other windows. */
3613 void
3614 grow_mini_window (w, delta)
3615 struct window *w;
3616 int delta;
3618 struct frame *f = XFRAME (w->frame);
3619 struct window *root;
3621 xassert (MINI_WINDOW_P (w));
3622 xassert (delta >= 0);
3624 /* Check values of window_min_width and window_min_height for
3625 validity. */
3626 check_min_window_sizes ();
3628 /* Compute how much we can enlarge the mini-window without deleting
3629 other windows. */
3630 root = XWINDOW (FRAME_ROOT_WINDOW (f));
3631 if (delta)
3633 int min_height = window_min_size (root, 0, 0, 0);
3634 if (XFASTINT (root->height) - delta < min_height)
3635 delta = XFASTINT (root->height) - min_height;
3638 if (delta)
3640 /* Save original window sizes and positions, if not already done. */
3641 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
3642 save_restore_orig_size (root, SAVE_ORIG_SIZES);
3644 /* Shrink other windows. */
3645 shrink_window_lowest_first (root, XFASTINT (root->height) - delta);
3647 /* Grow the mini-window. */
3648 w->top = make_number (XFASTINT (root->top) + XFASTINT (root->height));
3649 w->height = make_number (XFASTINT (w->height) + delta);
3650 XSETFASTINT (w->last_modified, 0);
3651 XSETFASTINT (w->last_overlay_modified, 0);
3653 adjust_glyphs (f);
3658 /* Shrink mini-window W. If there is recorded info about window sizes
3659 before a call to grow_mini_window, restore recorded window sizes.
3660 Otherwise, if the mini-window is higher than 1 line, resize it to 1
3661 line. */
3663 void
3664 shrink_mini_window (w)
3665 struct window *w;
3667 struct frame *f = XFRAME (w->frame);
3668 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
3670 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
3672 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
3673 adjust_glyphs (f);
3674 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3675 windows_or_buffers_changed = 1;
3677 else if (XFASTINT (w->height) > 1)
3679 Lisp_Object window;
3680 XSETWINDOW (window, w);
3681 enlarge_window (window, 1 - XFASTINT (w->height), 0);
3687 /* Mark window cursors off for all windows in the window tree rooted
3688 at W by setting their phys_cursor_on_p flag to zero. Called from
3689 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3690 the frame are cleared. */
3692 void
3693 mark_window_cursors_off (w)
3694 struct window *w;
3696 while (w)
3698 if (!NILP (w->hchild))
3699 mark_window_cursors_off (XWINDOW (w->hchild));
3700 else if (!NILP (w->vchild))
3701 mark_window_cursors_off (XWINDOW (w->vchild));
3702 else
3703 w->phys_cursor_on_p = 0;
3705 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3710 /* Return number of lines of text (not counting mode line) in W. */
3713 window_internal_height (w)
3714 struct window *w;
3716 int ht = XFASTINT (w->height);
3718 if (MINI_WINDOW_P (w))
3719 return ht;
3721 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
3722 || !NILP (w->next) || !NILP (w->prev)
3723 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
3724 return ht - 1;
3726 return ht;
3730 /* Return the number of columns in W.
3731 Don't count columns occupied by scroll bars or the vertical bar
3732 separating W from the sibling to its right. */
3735 window_internal_width (w)
3736 struct window *w;
3738 struct frame *f = XFRAME (WINDOW_FRAME (w));
3739 int width = XINT (w->width);
3741 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3742 /* Scroll bars occupy a few columns. */
3743 width -= FRAME_SCROLL_BAR_COLS (f);
3744 else if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
3745 /* The column of `|' characters separating side-by-side windows
3746 occupies one column only. */
3747 width -= 1;
3749 /* On window-systems, areas to the left and right of the window
3750 are used to display bitmaps there. */
3751 if (FRAME_WINDOW_P (f))
3752 width -= FRAME_FLAGS_AREA_COLS (f);
3754 return width;
3758 /************************************************************************
3759 Window Scrolling
3760 ***********************************************************************/
3762 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
3763 one screen-full, which is defined as the height of the window minus
3764 next_screen_context_lines. If WHOLE is zero, scroll up N lines
3765 instead. Negative values of N mean scroll down. NOERROR non-zero
3766 means don't signal an error if we try to move over BEGV or ZV,
3767 respectively. */
3769 static void
3770 window_scroll (window, n, whole, noerror)
3771 Lisp_Object window;
3772 int n;
3773 int whole;
3774 int noerror;
3776 /* If we must, use the pixel-based version which is much slower than
3777 the line-based one but can handle varying line heights. */
3778 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
3779 window_scroll_pixel_based (window, n, whole, noerror);
3780 else
3781 window_scroll_line_based (window, n, whole, noerror);
3785 /* Implementation of window_scroll that works based on pixel line
3786 heights. See the comment of window_scroll for parameter
3787 descriptions. */
3789 static void
3790 window_scroll_pixel_based (window, n, whole, noerror)
3791 Lisp_Object window;
3792 int n;
3793 int whole;
3794 int noerror;
3796 struct it it;
3797 struct window *w = XWINDOW (window);
3798 struct text_pos start;
3799 Lisp_Object tem;
3800 int this_scroll_margin;
3801 int preserve_y;
3803 SET_TEXT_POS_FROM_MARKER (start, w->start);
3805 /* If PT is not visible in WINDOW, move back one half of
3806 the screen. */
3807 XSETFASTINT (tem, PT);
3808 tem = Fpos_visible_in_window_p (tem, window, Qnil);
3809 if (NILP (tem))
3811 /* Move backward half the height of the window. Performance note:
3812 vmotion used here is about 10% faster, but would give wrong
3813 results for variable height lines. */
3814 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3815 it.current_y = it.last_visible_y;
3816 move_it_vertically (&it, -it.last_visible_y / 2);
3818 /* The function move_iterator_vertically may move over more than
3819 the specified y-distance. If it->w is small, e.g. a
3820 mini-buffer window, we may end up in front of the window's
3821 display area. This is the case when Start displaying at the
3822 start of the line containing PT in this case. */
3823 if (it.current_y <= 0)
3825 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3826 move_it_vertically (&it, 0);
3827 it.current_y = 0;
3830 start = it.current.pos;
3833 /* If scroll_preserve_screen_position is non-zero, we try to set
3834 point in the same window line as it is now, so get that line. */
3835 if (!NILP (Vscroll_preserve_screen_position))
3837 start_display (&it, w, start);
3838 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3839 preserve_y = it.current_y;
3841 else
3842 preserve_y = -1;
3844 /* Move iterator it from start the specified distance forward or
3845 backward. The result is the new window start. */
3846 start_display (&it, w, start);
3847 if (whole)
3849 int screen_full = (it.last_visible_y
3850 - next_screen_context_lines * CANON_Y_UNIT (it.f));
3851 int direction = n < 0 ? -1 : 1;
3852 move_it_vertically (&it, direction * screen_full);
3854 else
3855 move_it_by_lines (&it, n, 1);
3857 /* End if we end up at ZV or BEGV. */
3858 if ((n > 0 && IT_CHARPOS (it) == ZV)
3859 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
3861 if (noerror)
3862 return;
3863 else if (IT_CHARPOS (it) == ZV)
3864 Fsignal (Qend_of_buffer, Qnil);
3865 else
3866 Fsignal (Qbeginning_of_buffer, Qnil);
3869 /* Set the window start, and set up the window for redisplay. */
3870 set_marker_restricted (w->start, make_number (IT_CHARPOS (it)), w->buffer);
3871 w->start_at_line_beg = Fbolp ();
3872 w->update_mode_line = Qt;
3873 XSETFASTINT (w->last_modified, 0);
3874 XSETFASTINT (w->last_overlay_modified, 0);
3875 /* Set force_start so that redisplay_window will run the
3876 window-scroll-functions. */
3877 w->force_start = Qt;
3879 it.current_y = it.vpos = 0;
3881 /* Preserve the screen position if we must. */
3882 if (preserve_y >= 0)
3884 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
3885 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3887 else
3889 /* Move PT out of scroll margins. */
3890 this_scroll_margin = max (0, scroll_margin);
3891 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
3892 this_scroll_margin *= CANON_Y_UNIT (it.f);
3894 if (n > 0)
3896 /* We moved the window start towards ZV, so PT may be now
3897 in the scroll margin at the top. */
3898 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3899 while (it.current_y < this_scroll_margin)
3900 move_it_by_lines (&it, 1, 1);
3901 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3903 else if (n < 0)
3905 /* We moved the window start towards BEGV, so PT may be now
3906 in the scroll margin at the bottom. */
3907 move_it_to (&it, PT, -1,
3908 it.last_visible_y - this_scroll_margin - 1, -1,
3909 MOVE_TO_POS | MOVE_TO_Y);
3911 /* Don't put point on a partially visible line at the end. */
3912 if (it.current_y + it.max_ascent + it.max_descent
3913 > it.last_visible_y)
3914 move_it_by_lines (&it, -1, 0);
3916 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3922 /* Implementation of window_scroll that works based on screen lines.
3923 See the comment of window_scroll for parameter descriptions. */
3925 static void
3926 window_scroll_line_based (window, n, whole, noerror)
3927 Lisp_Object window;
3928 int n;
3929 int whole;
3930 int noerror;
3932 register struct window *w = XWINDOW (window);
3933 register int opoint = PT, opoint_byte = PT_BYTE;
3934 register int pos, pos_byte;
3935 register int ht = window_internal_height (w);
3936 register Lisp_Object tem;
3937 int lose;
3938 Lisp_Object bolp;
3939 int startpos;
3940 struct position posit;
3941 int original_vpos;
3943 startpos = marker_position (w->start);
3945 posit = *compute_motion (startpos, 0, 0, 0,
3946 PT, ht, 0,
3947 window_internal_width (w), XINT (w->hscroll),
3948 0, w);
3949 original_vpos = posit.vpos;
3951 XSETFASTINT (tem, PT);
3952 tem = Fpos_visible_in_window_p (tem, window, Qnil);
3954 if (NILP (tem))
3956 Fvertical_motion (make_number (- (ht / 2)), window);
3957 startpos = PT;
3960 SET_PT (startpos);
3961 lose = n < 0 && PT == BEGV;
3962 Fvertical_motion (make_number (n), window);
3963 pos = PT;
3964 pos_byte = PT_BYTE;
3965 bolp = Fbolp ();
3966 SET_PT_BOTH (opoint, opoint_byte);
3968 if (lose)
3970 if (noerror)
3971 return;
3972 else
3973 Fsignal (Qbeginning_of_buffer, Qnil);
3976 if (pos < ZV)
3978 int this_scroll_margin = scroll_margin;
3980 /* Don't use a scroll margin that is negative or too large. */
3981 if (this_scroll_margin < 0)
3982 this_scroll_margin = 0;
3984 if (XINT (w->height) < 4 * scroll_margin)
3985 this_scroll_margin = XINT (w->height) / 4;
3987 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
3988 w->start_at_line_beg = bolp;
3989 w->update_mode_line = Qt;
3990 XSETFASTINT (w->last_modified, 0);
3991 XSETFASTINT (w->last_overlay_modified, 0);
3992 /* Set force_start so that redisplay_window will run
3993 the window-scroll-functions. */
3994 w->force_start = Qt;
3996 if (whole && !NILP (Vscroll_preserve_screen_position))
3998 SET_PT_BOTH (pos, pos_byte);
3999 Fvertical_motion (make_number (original_vpos), window);
4001 /* If we scrolled forward, put point enough lines down
4002 that it is outside the scroll margin. */
4003 else if (n > 0)
4005 int top_margin;
4007 if (this_scroll_margin > 0)
4009 SET_PT_BOTH (pos, pos_byte);
4010 Fvertical_motion (make_number (this_scroll_margin), window);
4011 top_margin = PT;
4013 else
4014 top_margin = pos;
4016 if (top_margin <= opoint)
4017 SET_PT_BOTH (opoint, opoint_byte);
4018 else if (!NILP (Vscroll_preserve_screen_position))
4020 SET_PT_BOTH (pos, pos_byte);
4021 Fvertical_motion (make_number (original_vpos), window);
4023 else
4024 SET_PT (top_margin);
4026 else if (n < 0)
4028 int bottom_margin;
4030 /* If we scrolled backward, put point near the end of the window
4031 but not within the scroll margin. */
4032 SET_PT_BOTH (pos, pos_byte);
4033 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4034 if (XFASTINT (tem) == ht - this_scroll_margin)
4035 bottom_margin = PT;
4036 else
4037 bottom_margin = PT + 1;
4039 if (bottom_margin > opoint)
4040 SET_PT_BOTH (opoint, opoint_byte);
4041 else
4043 if (!NILP (Vscroll_preserve_screen_position))
4045 SET_PT_BOTH (pos, pos_byte);
4046 Fvertical_motion (make_number (original_vpos), window);
4048 else
4049 Fvertical_motion (make_number (-1), window);
4053 else
4055 if (noerror)
4056 return;
4057 else
4058 Fsignal (Qend_of_buffer, Qnil);
4063 /* Scroll selected_window up or down. If N is nil, scroll a
4064 screen-full which is defined as the height of the window minus
4065 next_screen_context_lines. If N is the symbol `-', scroll.
4066 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4067 up. This is the guts of Fscroll_up and Fscroll_down. */
4069 static void
4070 scroll_command (n, direction)
4071 Lisp_Object n;
4072 int direction;
4074 register int defalt;
4075 int count = specpdl_ptr - specpdl;
4077 xassert (abs (direction) == 1);
4079 /* If selected window's buffer isn't current, make it current for
4080 the moment. But don't screw up if window_scroll gets an error. */
4081 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4083 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4084 Fset_buffer (XWINDOW (selected_window)->buffer);
4086 /* Make redisplay consider other windows than just selected_window. */
4087 ++windows_or_buffers_changed;
4090 defalt = (window_internal_height (XWINDOW (selected_window))
4091 - next_screen_context_lines);
4092 defalt = direction * (defalt < 1 ? 1 : defalt);
4094 if (NILP (n))
4095 window_scroll (selected_window, defalt, 1, 0);
4096 else if (EQ (n, Qminus))
4097 window_scroll (selected_window, - defalt, 1, 0);
4098 else
4100 n = Fprefix_numeric_value (n);
4101 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4104 unbind_to (count, Qnil);
4107 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
4108 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
4109 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4110 Negative ARG means scroll downward.\n\
4111 If ARG is the atom `-', scroll downward by nearly full screen.\n\
4112 When calling from a program, supply as argument a number, nil, or `-'.")
4113 (arg)
4114 Lisp_Object arg;
4116 scroll_command (arg, 1);
4117 return Qnil;
4120 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
4121 "Scroll text of current window down ARG lines; or near full screen if no ARG.\n\
4122 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4123 Negative ARG means scroll upward.\n\
4124 If ARG is the atom `-', scroll upward by nearly full screen.\n\
4125 When calling from a program, supply as argument a number, nil, or `-'.")
4126 (arg)
4127 Lisp_Object arg;
4129 scroll_command (arg, -1);
4130 return Qnil;
4133 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4134 "Return the other window for \"other window scroll\" commands.\n\
4135 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
4136 specifies the window.\n\
4137 If `other-window-scroll-buffer' is non-nil, a window\n\
4138 showing that buffer is used.")
4141 Lisp_Object window;
4143 if (MINI_WINDOW_P (XWINDOW (selected_window))
4144 && !NILP (Vminibuf_scroll_window))
4145 window = Vminibuf_scroll_window;
4146 /* If buffer is specified, scroll that buffer. */
4147 else if (!NILP (Vother_window_scroll_buffer))
4149 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4150 if (NILP (window))
4151 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4153 else
4155 /* Nothing specified; look for a neighboring window on the same
4156 frame. */
4157 window = Fnext_window (selected_window, Qnil, Qnil);
4159 if (EQ (window, selected_window))
4160 /* That didn't get us anywhere; look for a window on another
4161 visible frame. */
4163 window = Fnext_window (window, Qnil, Qt);
4164 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4165 && ! EQ (window, selected_window));
4168 CHECK_LIVE_WINDOW (window, 0);
4170 if (EQ (window, selected_window))
4171 error ("There is no other window");
4173 return window;
4176 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4177 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
4178 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4179 The next window is the one below the current one; or the one at the top\n\
4180 if the current one is at the bottom. Negative ARG means scroll downward.\n\
4181 If ARG is the atom `-', scroll downward by nearly full screen.\n\
4182 When calling from a program, supply as argument a number, nil, or `-'.\n\
4184 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
4185 specifies the window to scroll.\n\
4186 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
4187 showing that buffer, popping the buffer up if necessary.")
4188 (arg)
4189 register Lisp_Object arg;
4191 register Lisp_Object window;
4192 register int defalt;
4193 register struct window *w;
4194 register int count = specpdl_ptr - specpdl;
4196 window = Fother_window_for_scrolling ();
4198 w = XWINDOW (window);
4199 defalt = window_internal_height (w) - next_screen_context_lines;
4200 if (defalt < 1) defalt = 1;
4202 /* Don't screw up if window_scroll gets an error. */
4203 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4204 ++windows_or_buffers_changed;
4206 Fset_buffer (w->buffer);
4207 SET_PT (marker_position (w->pointm));
4209 if (NILP (arg))
4210 window_scroll (window, defalt, 1, 1);
4211 else if (EQ (arg, Qminus))
4212 window_scroll (window, -defalt, 1, 1);
4213 else
4215 if (CONSP (arg))
4216 arg = Fcar (arg);
4217 CHECK_NUMBER (arg, 0);
4218 window_scroll (window, XINT (arg), 0, 1);
4221 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4222 unbind_to (count, Qnil);
4224 return Qnil;
4227 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
4228 "Scroll selected window display ARG columns left.\n\
4229 Default for ARG is window width minus 2.")
4230 (arg)
4231 register Lisp_Object arg;
4234 if (NILP (arg))
4235 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
4236 else
4237 arg = Fprefix_numeric_value (arg);
4239 return
4240 Fset_window_hscroll (selected_window,
4241 make_number (XINT (XWINDOW (selected_window)->hscroll)
4242 + XINT (arg)));
4245 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
4246 "Scroll selected window display ARG columns right.\n\
4247 Default for ARG is window width minus 2.")
4248 (arg)
4249 register Lisp_Object arg;
4251 if (NILP (arg))
4252 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
4253 else
4254 arg = Fprefix_numeric_value (arg);
4256 return
4257 Fset_window_hscroll (selected_window,
4258 make_number (XINT (XWINDOW (selected_window)->hscroll)
4259 - XINT (arg)));
4262 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
4263 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
4264 The desired position of point is always relative to the current window.\n\
4265 Just C-u as prefix means put point in the center of the window.\n\
4266 If ARG is omitted or nil, erases the entire frame and then\n\
4267 redraws with point in the center of the current window.")
4268 (arg)
4269 register Lisp_Object arg;
4271 register struct window *w = XWINDOW (selected_window);
4272 register int ht = window_internal_height (w);
4273 struct position pos;
4274 struct buffer *buf = XBUFFER (w->buffer);
4275 struct buffer *obuf = current_buffer;
4277 if (NILP (arg))
4279 extern int frame_garbaged;
4280 int i;
4282 /* Invalidate pixel data calculated for all compositions. */
4283 for (i = 0; i < n_compositions; i++)
4284 composition_table[i]->font = NULL;
4286 Fredraw_frame (w->frame);
4287 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
4288 XSETFASTINT (arg, ht / 2);
4290 else if (CONSP (arg)) /* Just C-u. */
4292 XSETFASTINT (arg, ht / 2);
4294 else
4296 arg = Fprefix_numeric_value (arg);
4297 CHECK_NUMBER (arg, 0);
4300 if (XINT (arg) < 0)
4301 XSETINT (arg, XINT (arg) + ht);
4303 set_buffer_internal (buf);
4304 pos = *vmotion (PT, - XINT (arg), w);
4306 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
4307 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
4308 || FETCH_BYTE (pos.bytepos - 1) == '\n')
4309 ? Qt : Qnil);
4310 w->force_start = Qt;
4311 set_buffer_internal (obuf);
4313 return Qnil;
4317 /* Value is the number of lines actually displayed in window W,
4318 as opposed to its height. */
4320 static int
4321 displayed_window_lines (w)
4322 struct window *w;
4324 struct it it;
4325 struct text_pos start;
4326 int height = window_box_height (w);
4327 struct buffer *old_buffer;
4328 int bottom_y;
4330 if (XBUFFER (w->buffer) != current_buffer)
4332 old_buffer = current_buffer;
4333 set_buffer_internal (XBUFFER (w->buffer));
4335 else
4336 old_buffer = NULL;
4338 SET_TEXT_POS_FROM_MARKER (start, w->start);
4339 start_display (&it, w, start);
4340 move_it_vertically (&it, height);
4342 if (old_buffer)
4343 set_buffer_internal (old_buffer);
4345 /* Add in empty lines at the bottom of the window. */
4346 bottom_y = it.current_y + it.max_ascent + it.max_descent;
4347 if (bottom_y < height)
4349 struct frame *f = XFRAME (w->frame);
4350 int rest = height - bottom_y;
4351 int lines = (rest + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
4352 it.vpos += lines;
4354 else if (it.current_y < height && bottom_y > height)
4355 /* Partially visible line at the bottom. */
4356 ++it.vpos;
4358 return it.vpos;
4363 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
4364 1, 1, "P",
4365 "Position point relative to window.\n\
4366 With no argument, position point at center of window.\n\
4367 An argument specifies vertical position within the window;\n\
4368 zero means top of window, negative means relative to bottom of window.")
4369 (arg)
4370 Lisp_Object arg;
4372 struct window *w = XWINDOW (selected_window);
4373 int lines, start;
4374 Lisp_Object window;
4376 window = selected_window;
4377 start = marker_position (w->start);
4378 if (start < BEGV || start > ZV)
4380 int height = window_internal_height (w);
4381 Fvertical_motion (make_number (- (height / 2)), window);
4382 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
4383 w->start_at_line_beg = Fbolp ();
4384 w->force_start = Qt;
4386 else
4387 Fgoto_char (w->start);
4389 lines = displayed_window_lines (w);
4390 if (NILP (arg))
4391 XSETFASTINT (arg, lines / 2);
4392 else
4394 arg = Fprefix_numeric_value (arg);
4395 if (XINT (arg) < 0)
4396 XSETINT (arg, XINT (arg) + lines);
4399 return Fvertical_motion (arg, window);
4404 /***********************************************************************
4405 Window Configuration
4406 ***********************************************************************/
4408 struct save_window_data
4410 EMACS_INT size_from_Lisp_Vector_struct;
4411 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4412 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
4413 Lisp_Object frame_tool_bar_lines;
4414 Lisp_Object selected_frame;
4415 Lisp_Object current_window;
4416 Lisp_Object current_buffer;
4417 Lisp_Object minibuf_scroll_window;
4418 Lisp_Object root_window;
4419 Lisp_Object focus_frame;
4420 /* Record the values of window-min-width and window-min-height
4421 so that window sizes remain consistent with them. */
4422 Lisp_Object min_width, min_height;
4423 /* A vector, each of whose elements is a struct saved_window
4424 for one window. */
4425 Lisp_Object saved_windows;
4428 /* This is saved as a Lisp_Vector */
4429 struct saved_window
4431 /* these first two must agree with struct Lisp_Vector in lisp.h */
4432 EMACS_INT size_from_Lisp_Vector_struct;
4433 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4435 Lisp_Object window;
4436 Lisp_Object buffer, start, pointm, mark;
4437 Lisp_Object left, top, width, height, hscroll;
4438 Lisp_Object parent, prev;
4439 Lisp_Object start_at_line_beg;
4440 Lisp_Object display_table;
4442 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
4444 #define SAVED_WINDOW_N(swv,n) \
4445 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4447 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
4448 "Return t if OBJECT is a window-configuration object.")
4449 (object)
4450 Lisp_Object object;
4452 if (WINDOW_CONFIGURATIONP (object))
4453 return Qt;
4454 return Qnil;
4457 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
4458 "Return the frame that CONFIG, a window-configuration object, is about.")
4459 (config)
4460 Lisp_Object config;
4462 register struct save_window_data *data;
4463 struct Lisp_Vector *saved_windows;
4465 if (! WINDOW_CONFIGURATIONP (config))
4466 wrong_type_argument (Qwindow_configuration_p, config);
4468 data = (struct save_window_data *) XVECTOR (config);
4469 saved_windows = XVECTOR (data->saved_windows);
4470 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4473 DEFUN ("set-window-configuration", Fset_window_configuration,
4474 Sset_window_configuration, 1, 1, 0,
4475 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
4476 CONFIGURATION must be a value previously returned\n\
4477 by `current-window-configuration' (which see).\n\
4478 If CONFIGURATION was made from a frame that is now deleted,\n\
4479 only frame-independent values can be restored. In this case,\n\
4480 the return value is nil. Otherwise the value is t.")
4481 (configuration)
4482 Lisp_Object configuration;
4484 register struct save_window_data *data;
4485 struct Lisp_Vector *saved_windows;
4486 Lisp_Object new_current_buffer;
4487 Lisp_Object frame;
4488 FRAME_PTR f;
4489 int old_point = -1;
4491 while (!WINDOW_CONFIGURATIONP (configuration))
4492 wrong_type_argument (Qwindow_configuration_p, configuration);
4494 data = (struct save_window_data *) XVECTOR (configuration);
4495 saved_windows = XVECTOR (data->saved_windows);
4497 new_current_buffer = data->current_buffer;
4498 if (NILP (XBUFFER (new_current_buffer)->name))
4499 new_current_buffer = Qnil;
4500 else
4502 if (XBUFFER (new_current_buffer) == current_buffer)
4503 old_point = PT;
4506 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4507 f = XFRAME (frame);
4509 /* If f is a dead frame, don't bother rebuilding its window tree.
4510 However, there is other stuff we should still try to do below. */
4511 if (FRAME_LIVE_P (f))
4513 register struct window *w;
4514 register struct saved_window *p;
4515 struct window *root_window;
4516 struct window **leaf_windows;
4517 int n_leaf_windows;
4518 int k, i, n;
4520 /* If the frame has been resized since this window configuration was
4521 made, we change the frame to the size specified in the
4522 configuration, restore the configuration, and then resize it
4523 back. We keep track of the prevailing height in these variables. */
4524 int previous_frame_height = FRAME_HEIGHT (f);
4525 int previous_frame_width = FRAME_WIDTH (f);
4526 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
4527 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
4529 /* The mouse highlighting code could get screwed up
4530 if it runs during this. */
4531 BLOCK_INPUT;
4533 if (XFASTINT (data->frame_height) != previous_frame_height
4534 || XFASTINT (data->frame_width) != previous_frame_width)
4535 change_frame_size (f, XFASTINT (data->frame_height),
4536 XFASTINT (data->frame_width), 0, 0, 0);
4537 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4538 if (XFASTINT (data->frame_menu_bar_lines)
4539 != previous_frame_menu_bar_lines)
4540 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
4541 #ifdef HAVE_WINDOW_SYSTEM
4542 if (XFASTINT (data->frame_tool_bar_lines)
4543 != previous_frame_tool_bar_lines)
4544 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
4545 #endif
4546 #endif
4548 /* "Swap out" point from the selected window
4549 into its buffer. We do this now, before
4550 restoring the window contents, and prevent it from
4551 being done later on when we select a new window. */
4552 if (! NILP (XWINDOW (selected_window)->buffer))
4554 w = XWINDOW (selected_window);
4555 set_marker_both (w->pointm,
4556 w->buffer,
4557 BUF_PT (XBUFFER (w->buffer)),
4558 BUF_PT_BYTE (XBUFFER (w->buffer)));
4561 windows_or_buffers_changed++;
4562 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4564 /* Problem: Freeing all matrices and later allocating them again
4565 is a serious redisplay flickering problem. What we would
4566 really like to do is to free only those matrices not reused
4567 below. */
4568 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
4569 leaf_windows
4570 = (struct window **) alloca (count_windows (root_window)
4571 * sizeof (struct window *));
4572 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
4574 /* Temporarily avoid any problems with windows that are smaller
4575 than they are supposed to be. */
4576 window_min_height = 1;
4577 window_min_width = 1;
4579 /* Kludge Alert!
4580 Mark all windows now on frame as "deleted".
4581 Restoring the new configuration "undeletes" any that are in it.
4583 Save their current buffers in their height fields, since we may
4584 need it later, if a buffer saved in the configuration is now
4585 dead. */
4586 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4588 for (k = 0; k < saved_windows->size; k++)
4590 p = SAVED_WINDOW_N (saved_windows, k);
4591 w = XWINDOW (p->window);
4592 w->next = Qnil;
4594 if (!NILP (p->parent))
4595 w->parent = SAVED_WINDOW_N (saved_windows,
4596 XFASTINT (p->parent))->window;
4597 else
4598 w->parent = Qnil;
4600 if (!NILP (p->prev))
4602 w->prev = SAVED_WINDOW_N (saved_windows,
4603 XFASTINT (p->prev))->window;
4604 XWINDOW (w->prev)->next = p->window;
4606 else
4608 w->prev = Qnil;
4609 if (!NILP (w->parent))
4611 if (EQ (p->width, XWINDOW (w->parent)->width))
4613 XWINDOW (w->parent)->vchild = p->window;
4614 XWINDOW (w->parent)->hchild = Qnil;
4616 else
4618 XWINDOW (w->parent)->hchild = p->window;
4619 XWINDOW (w->parent)->vchild = Qnil;
4624 /* If we squirreled away the buffer in the window's height,
4625 restore it now. */
4626 if (BUFFERP (w->height))
4627 w->buffer = w->height;
4628 w->left = p->left;
4629 w->top = p->top;
4630 w->width = p->width;
4631 w->height = p->height;
4632 w->hscroll = p->hscroll;
4633 w->display_table = p->display_table;
4634 XSETFASTINT (w->last_modified, 0);
4635 XSETFASTINT (w->last_overlay_modified, 0);
4637 /* Reinstall the saved buffer and pointers into it. */
4638 if (NILP (p->buffer))
4639 w->buffer = p->buffer;
4640 else
4642 if (!NILP (XBUFFER (p->buffer)->name))
4643 /* If saved buffer is alive, install it. */
4645 w->buffer = p->buffer;
4646 w->start_at_line_beg = p->start_at_line_beg;
4647 set_marker_restricted (w->start, p->start, w->buffer);
4648 set_marker_restricted (w->pointm, p->pointm, w->buffer);
4649 Fset_marker (XBUFFER (w->buffer)->mark,
4650 p->mark, w->buffer);
4652 /* As documented in Fcurrent_window_configuration, don't
4653 save the location of point in the buffer which was current
4654 when the window configuration was recorded. */
4655 if (!EQ (p->buffer, new_current_buffer)
4656 && XBUFFER (p->buffer) == current_buffer)
4657 Fgoto_char (w->pointm);
4659 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
4660 /* Else unless window has a live buffer, get one. */
4662 w->buffer = Fcdr (Fcar (Vbuffer_alist));
4663 /* This will set the markers to beginning of visible
4664 range. */
4665 set_marker_restricted (w->start, make_number (0), w->buffer);
4666 set_marker_restricted (w->pointm, make_number (0),w->buffer);
4667 w->start_at_line_beg = Qt;
4669 else
4670 /* Keeping window's old buffer; make sure the markers
4671 are real. */
4673 /* Set window markers at start of visible range. */
4674 if (XMARKER (w->start)->buffer == 0)
4675 set_marker_restricted (w->start, make_number (0),
4676 w->buffer);
4677 if (XMARKER (w->pointm)->buffer == 0)
4678 set_marker_restricted_both (w->pointm, w->buffer,
4679 BUF_PT (XBUFFER (w->buffer)),
4680 BUF_PT_BYTE (XBUFFER (w->buffer)));
4681 w->start_at_line_beg = Qt;
4686 FRAME_ROOT_WINDOW (f) = data->root_window;
4687 /* Prevent "swapping out point" in the old selected window
4688 using the buffer that has been restored into it.
4689 That swapping out has already been done,
4690 near the beginning of this function. */
4691 selected_window = Qnil;
4692 Fselect_window (data->current_window);
4693 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
4694 = selected_window;
4696 if (NILP (data->focus_frame)
4697 || (FRAMEP (data->focus_frame)
4698 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
4699 Fredirect_frame_focus (frame, data->focus_frame);
4701 #if 0 /* I don't understand why this is needed, and it causes problems
4702 when the frame's old selected window has been deleted. */
4703 if (f != selected_frame && FRAME_WINDOW_P (f))
4704 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
4705 Qnil, 0);
4706 #endif
4708 /* Set the screen height to the value it had before this function. */
4709 if (previous_frame_height != FRAME_HEIGHT (f)
4710 || previous_frame_width != FRAME_WIDTH (f))
4711 change_frame_size (f, previous_frame_height, previous_frame_width,
4712 0, 0, 0);
4713 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4714 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
4715 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
4716 make_number (0));
4717 #ifdef HAVE_WINDOW_SYSTEM
4718 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
4719 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
4720 make_number (0));
4721 #endif
4722 #endif
4724 /* Now, free glyph matrices in windows that were not reused. */
4725 for (i = n = 0; i < n_leaf_windows; ++i)
4727 if (NILP (leaf_windows[i]->buffer))
4729 /* Assert it's not reused as a combination. */
4730 xassert (NILP (leaf_windows[i]->hchild)
4731 && NILP (leaf_windows[i]->vchild));
4732 free_window_matrices (leaf_windows[i]);
4733 SET_FRAME_GARBAGED (f);
4735 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
4736 ++n;
4739 /* If more than one window shows the new and old current buffer,
4740 don't try to preserve point in that buffer. */
4741 if (old_point > 0 && n > 1)
4742 old_point = -1;
4744 adjust_glyphs (f);
4746 UNBLOCK_INPUT;
4748 /* Fselect_window will have made f the selected frame, so we
4749 reselect the proper frame here. Fhandle_switch_frame will change the
4750 selected window too, but that doesn't make the call to
4751 Fselect_window above totally superfluous; it still sets f's
4752 selected window. */
4753 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
4754 do_switch_frame (data->selected_frame, Qnil, 0);
4756 if (! NILP (Vwindow_configuration_change_hook)
4757 && ! NILP (Vrun_hooks))
4758 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4761 if (!NILP (new_current_buffer))
4763 Fset_buffer (new_current_buffer);
4765 /* If the buffer that is current now is the same
4766 that was current before setting the window configuration,
4767 don't alter its PT. */
4768 if (old_point >= 0)
4769 SET_PT (old_point);
4772 /* Restore the minimum heights recorded in the configuration. */
4773 window_min_height = XINT (data->min_height);
4774 window_min_width = XINT (data->min_width);
4776 Vminibuf_scroll_window = data->minibuf_scroll_window;
4778 return (FRAME_LIVE_P (f) ? Qt : Qnil);
4781 /* Mark all windows now on frame as deleted
4782 by setting their buffers to nil. */
4784 void
4785 delete_all_subwindows (w)
4786 register struct window *w;
4788 if (!NILP (w->next))
4789 delete_all_subwindows (XWINDOW (w->next));
4790 if (!NILP (w->vchild))
4791 delete_all_subwindows (XWINDOW (w->vchild));
4792 if (!NILP (w->hchild))
4793 delete_all_subwindows (XWINDOW (w->hchild));
4795 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
4797 if (!NILP (w->buffer))
4798 unshow_buffer (w);
4800 /* We set all three of these fields to nil, to make sure that we can
4801 distinguish this dead window from any live window. Live leaf
4802 windows will have buffer set, and combination windows will have
4803 vchild or hchild set. */
4804 w->buffer = Qnil;
4805 w->vchild = Qnil;
4806 w->hchild = Qnil;
4808 Vwindow_list = Qnil;
4811 static int
4812 count_windows (window)
4813 register struct window *window;
4815 register int count = 1;
4816 if (!NILP (window->next))
4817 count += count_windows (XWINDOW (window->next));
4818 if (!NILP (window->vchild))
4819 count += count_windows (XWINDOW (window->vchild));
4820 if (!NILP (window->hchild))
4821 count += count_windows (XWINDOW (window->hchild));
4822 return count;
4826 /* Fill vector FLAT with leaf windows under W, starting at index I.
4827 Value is last index + 1. */
4829 static int
4830 get_leaf_windows (w, flat, i)
4831 struct window *w;
4832 struct window **flat;
4833 int i;
4835 while (w)
4837 if (!NILP (w->hchild))
4838 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
4839 else if (!NILP (w->vchild))
4840 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
4841 else
4842 flat[i++] = w;
4844 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4847 return i;
4851 /* Return a pointer to the glyph W's physical cursor is on. Value is
4852 null if W's current matrix is invalid, so that no meaningfull glyph
4853 can be returned. */
4855 struct glyph *
4856 get_phys_cursor_glyph (w)
4857 struct window *w;
4859 struct glyph_row *row;
4860 struct glyph *glyph;
4862 if (w->phys_cursor.vpos >= 0
4863 && w->phys_cursor.vpos < w->current_matrix->nrows
4864 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
4865 row->enabled_p)
4866 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
4867 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
4868 else
4869 glyph = NULL;
4871 return glyph;
4875 static int
4876 save_window_save (window, vector, i)
4877 Lisp_Object window;
4878 struct Lisp_Vector *vector;
4879 int i;
4881 register struct saved_window *p;
4882 register struct window *w;
4883 register Lisp_Object tem;
4885 for (;!NILP (window); window = w->next)
4887 p = SAVED_WINDOW_N (vector, i);
4888 w = XWINDOW (window);
4890 XSETFASTINT (w->temslot, i++);
4891 p->window = window;
4892 p->buffer = w->buffer;
4893 p->left = w->left;
4894 p->top = w->top;
4895 p->width = w->width;
4896 p->height = w->height;
4897 p->hscroll = w->hscroll;
4898 p->display_table = w->display_table;
4899 if (!NILP (w->buffer))
4901 /* Save w's value of point in the window configuration.
4902 If w is the selected window, then get the value of point
4903 from the buffer; pointm is garbage in the selected window. */
4904 if (EQ (window, selected_window))
4906 p->pointm = Fmake_marker ();
4907 set_marker_both (p->pointm, w->buffer,
4908 BUF_PT (XBUFFER (w->buffer)),
4909 BUF_PT_BYTE (XBUFFER (w->buffer)));
4911 else
4912 p->pointm = Fcopy_marker (w->pointm, Qnil);
4914 p->start = Fcopy_marker (w->start, Qnil);
4915 p->start_at_line_beg = w->start_at_line_beg;
4917 tem = XBUFFER (w->buffer)->mark;
4918 p->mark = Fcopy_marker (tem, Qnil);
4920 else
4922 p->pointm = Qnil;
4923 p->start = Qnil;
4924 p->mark = Qnil;
4925 p->start_at_line_beg = Qnil;
4928 if (NILP (w->parent))
4929 p->parent = Qnil;
4930 else
4931 p->parent = XWINDOW (w->parent)->temslot;
4933 if (NILP (w->prev))
4934 p->prev = Qnil;
4935 else
4936 p->prev = XWINDOW (w->prev)->temslot;
4938 if (!NILP (w->vchild))
4939 i = save_window_save (w->vchild, vector, i);
4940 if (!NILP (w->hchild))
4941 i = save_window_save (w->hchild, vector, i);
4944 return i;
4947 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
4948 Scurrent_window_configuration, 0, 1, 0,
4949 "Return an object representing the current window configuration of FRAME.\n\
4950 If FRAME is nil or omitted, use the selected frame.\n\
4951 This describes the number of windows, their sizes and current buffers,\n\
4952 and for each displayed buffer, where display starts, and the positions of\n\
4953 point and mark. An exception is made for point in the current buffer:\n\
4954 its value is -not- saved.\n\
4955 This also records the currently selected frame, and FRAME's focus\n\
4956 redirection (see `redirect-frame-focus').")
4957 (frame)
4958 Lisp_Object frame;
4960 register Lisp_Object tem;
4961 register int n_windows;
4962 register struct save_window_data *data;
4963 register struct Lisp_Vector *vec;
4964 register int i;
4965 FRAME_PTR f;
4967 if (NILP (frame))
4968 frame = selected_frame;
4969 CHECK_LIVE_FRAME (frame, 0);
4970 f = XFRAME (frame);
4972 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4973 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
4974 for (i = 0; i < VECSIZE (struct save_window_data); i++)
4975 vec->contents[i] = Qnil;
4976 vec->size = VECSIZE (struct save_window_data);
4977 data = (struct save_window_data *)vec;
4979 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
4980 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
4981 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
4982 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
4983 data->selected_frame = selected_frame;
4984 data->current_window = FRAME_SELECTED_WINDOW (f);
4985 XSETBUFFER (data->current_buffer, current_buffer);
4986 data->minibuf_scroll_window = Vminibuf_scroll_window;
4987 data->root_window = FRAME_ROOT_WINDOW (f);
4988 data->focus_frame = FRAME_FOCUS_FRAME (f);
4989 XSETINT (data->min_height, window_min_height);
4990 XSETINT (data->min_width, window_min_width);
4991 tem = Fmake_vector (make_number (n_windows), Qnil);
4992 data->saved_windows = tem;
4993 for (i = 0; i < n_windows; i++)
4994 XVECTOR (tem)->contents[i]
4995 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
4996 save_window_save (FRAME_ROOT_WINDOW (f),
4997 XVECTOR (tem), 0);
4998 XSETWINDOW_CONFIGURATION (tem, data);
4999 return (tem);
5002 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
5003 0, UNEVALLED, 0,
5004 "Execute body, preserving window sizes and contents.\n\
5005 Restore which buffer appears in which window, where display starts,\n\
5006 and the value of point and mark for each window.\n\
5007 Also restore the choice of selected window.\n\
5008 Also restore which buffer is current.\n\
5009 Does not restore the value of point in current buffer.")
5010 (args)
5011 Lisp_Object args;
5013 register Lisp_Object val;
5014 register int count = specpdl_ptr - specpdl;
5016 record_unwind_protect (Fset_window_configuration,
5017 Fcurrent_window_configuration (Qnil));
5018 val = Fprogn (args);
5019 return unbind_to (count, val);
5023 /***********************************************************************
5024 Marginal Areas
5025 ***********************************************************************/
5027 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
5028 2, 3, 0,
5029 "Set width of marginal areas of window WINDOW.\n\
5030 If window is nil, set margins of the currently selected window.\n\
5031 First parameter LEFT-WIDTH specifies the number of character\n\
5032 cells to reserve for the left marginal area. Second parameter\n\
5033 RIGHT-WIDTH does the same for the right marginal area.\n\
5034 A nil width parameter means no margin.")
5035 (window, left, right)
5036 Lisp_Object window, left, right;
5038 struct window *w = decode_window (window);
5040 if (!NILP (left))
5041 CHECK_NUMBER_OR_FLOAT (left, 1);
5042 if (!NILP (right))
5043 CHECK_NUMBER_OR_FLOAT (right, 2);
5045 /* Check widths < 0 and translate a zero width to nil.
5046 Margins that are too wide have to be checked elsewhere. */
5047 if ((INTEGERP (left) && XINT (left) < 0)
5048 || (FLOATP (left) && XFLOAT_DATA (left) <= 0))
5049 XSETFASTINT (left, 0);
5050 if (INTEGERP (left) && XFASTINT (left) == 0)
5051 left = Qnil;
5053 if ((INTEGERP (right) && XINT (right) < 0)
5054 || (FLOATP (right) && XFLOAT_DATA (right) <= 0))
5055 XSETFASTINT (right, 0);
5056 if (INTEGERP (right) && XFASTINT (right) == 0)
5057 right = Qnil;
5059 w->left_margin_width = left;
5060 w->right_margin_width = right;
5062 ++windows_or_buffers_changed;
5063 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5064 return Qnil;
5068 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
5069 0, 1, 0,
5070 "Get width of marginal areas of window WINDOW.\n\
5071 If WINDOW is omitted or nil, use the currently selected window.\n\
5072 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).\n\
5073 If a marginal area does not exist, its width will be returned\n\
5074 as nil.")
5075 (window)
5076 Lisp_Object window;
5078 struct window *w = decode_window (window);
5079 return Fcons (w->left_margin_width, w->right_margin_width);
5084 /***********************************************************************
5085 Smooth scrolling
5086 ***********************************************************************/
5088 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
5089 "Return the amount by which WINDOW is scrolled vertically.\n\
5090 Use the selected window if WINDOW is nil or omitted.\n\
5091 Value is a multiple of the canonical character height of WINDOW.")
5092 (window)
5093 Lisp_Object window;
5095 Lisp_Object result;
5096 struct frame *f;
5097 struct window *w;
5099 if (NILP (window))
5100 window = selected_window;
5101 else
5102 CHECK_WINDOW (window, 0);
5103 w = XWINDOW (window);
5104 f = XFRAME (w->frame);
5106 if (FRAME_WINDOW_P (f))
5107 result = CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
5108 else
5109 result = make_number (0);
5110 return result;
5114 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
5115 2, 2, 0,
5116 "Set amount by which WINDOW should be scrolled vertically to VSCROLL.\n\
5117 WINDOW nil or omitted means use the selected window. VSCROLL is a\n\
5118 non-negative multiple of the canonical character height of WINDOW.")
5119 (window, vscroll)
5120 Lisp_Object window, vscroll;
5122 struct window *w;
5123 struct frame *f;
5125 if (NILP (window))
5126 window = selected_window;
5127 else
5128 CHECK_WINDOW (window, 0);
5129 CHECK_NUMBER_OR_FLOAT (vscroll, 1);
5131 w = XWINDOW (window);
5132 f = XFRAME (w->frame);
5134 if (FRAME_WINDOW_P (f))
5136 int old_dy = w->vscroll;
5138 w->vscroll = - CANON_Y_UNIT (f) * XFLOATINT (vscroll);
5139 w->vscroll = min (w->vscroll, 0);
5141 /* Adjust glyph matrix of the frame if the virtual display
5142 area becomes larger than before. */
5143 if (w->vscroll < 0 && w->vscroll < old_dy)
5144 adjust_glyphs (f);
5146 /* Prevent redisplay shortcuts. */
5147 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5150 return Fwindow_vscroll (window);
5154 /* Call FN for all leaf windows on frame F. FN is called with the
5155 first argument being a pointer to the leaf window, and with
5156 additional argument USER_DATA. Stops when FN returns 0. */
5158 void
5159 foreach_window (f, fn, user_data)
5160 struct frame *f;
5161 int (* fn) P_ ((struct window *, void *));
5162 void *user_data;
5164 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
5168 /* Helper function for foreach_window. Call FN for all leaf windows
5169 reachable from W. FN is called with the first argument being a
5170 pointer to the leaf window, and with additional argument USER_DATA.
5171 Stop when FN returns 0. Value is 0 if stopped by FN. */
5173 static int
5174 foreach_window_1 (w, fn, user_data)
5175 struct window *w;
5176 int (* fn) P_ ((struct window *, void *));
5177 void *user_data;
5179 int cont;
5181 for (cont = 1; w && cont;)
5183 if (!NILP (w->hchild))
5184 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
5185 else if (!NILP (w->vchild))
5186 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
5187 else
5188 cont = fn (w, user_data);
5190 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5193 return cont;
5197 /* Freeze or unfreeze the window start of W if unless it is a
5198 mini-window or the selected window. FREEZE_P non-null means freeze
5199 the window start. */
5201 static int
5202 freeze_window_start (w, freeze_p)
5203 struct window *w;
5204 void *freeze_p;
5206 if (w == XWINDOW (selected_window)
5207 || MINI_WINDOW_P (w)
5208 || (MINI_WINDOW_P (XWINDOW (selected_window))
5209 && ! NILP (Vminibuf_scroll_window)
5210 && w == XWINDOW (Vminibuf_scroll_window)))
5211 freeze_p = NULL;
5213 w->frozen_window_start_p = freeze_p != NULL;
5214 return 1;
5218 /* Freeze or unfreeze the window starts of all leaf windows on frame
5219 F, except the selected window and a mini-window. FREEZE_P non-zero
5220 means freeze the window start. */
5222 void
5223 freeze_window_starts (f, freeze_p)
5224 struct frame *f;
5225 int freeze_p;
5227 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
5231 /***********************************************************************
5232 Initialization
5233 ***********************************************************************/
5235 /* Return 1 if window configurations C1 and C2
5236 describe the same state of affairs. This is used by Fequal. */
5239 compare_window_configurations (c1, c2, ignore_positions)
5240 Lisp_Object c1, c2;
5241 int ignore_positions;
5243 register struct save_window_data *d1, *d2;
5244 struct Lisp_Vector *sw1, *sw2;
5245 int i;
5247 if (!WINDOW_CONFIGURATIONP (c1))
5248 wrong_type_argument (Qwindow_configuration_p, c1);
5249 if (!WINDOW_CONFIGURATIONP (c2))
5250 wrong_type_argument (Qwindow_configuration_p, c2);
5252 d1 = (struct save_window_data *) XVECTOR (c1);
5253 d2 = (struct save_window_data *) XVECTOR (c2);
5254 sw1 = XVECTOR (d1->saved_windows);
5255 sw2 = XVECTOR (d2->saved_windows);
5257 if (! EQ (d1->frame_width, d2->frame_width))
5258 return 0;
5259 if (! EQ (d1->frame_height, d2->frame_height))
5260 return 0;
5261 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
5262 return 0;
5263 if (! EQ (d1->selected_frame, d2->selected_frame))
5264 return 0;
5265 /* Don't compare the current_window field directly.
5266 Instead see w1_is_current and w2_is_current, below. */
5267 if (! EQ (d1->current_buffer, d2->current_buffer))
5268 return 0;
5269 if (! ignore_positions)
5270 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
5271 return 0;
5272 /* Don't compare the root_window field.
5273 We don't require the two configurations
5274 to use the same window object,
5275 and the two root windows must be equivalent
5276 if everything else compares equal. */
5277 if (! EQ (d1->focus_frame, d2->focus_frame))
5278 return 0;
5279 if (! EQ (d1->min_width, d2->min_width))
5280 return 0;
5281 if (! EQ (d1->min_height, d2->min_height))
5282 return 0;
5284 /* Verify that the two confis have the same number of windows. */
5285 if (sw1->size != sw2->size)
5286 return 0;
5288 for (i = 0; i < sw1->size; i++)
5290 struct saved_window *p1, *p2;
5291 int w1_is_current, w2_is_current;
5293 p1 = SAVED_WINDOW_N (sw1, i);
5294 p2 = SAVED_WINDOW_N (sw2, i);
5296 /* Verify that the current windows in the two
5297 configurations correspond to each other. */
5298 w1_is_current = EQ (d1->current_window, p1->window);
5299 w2_is_current = EQ (d2->current_window, p2->window);
5301 if (w1_is_current != w2_is_current)
5302 return 0;
5304 /* Verify that the corresponding windows do match. */
5305 if (! EQ (p1->buffer, p2->buffer))
5306 return 0;
5307 if (! EQ (p1->left, p2->left))
5308 return 0;
5309 if (! EQ (p1->top, p2->top))
5310 return 0;
5311 if (! EQ (p1->width, p2->width))
5312 return 0;
5313 if (! EQ (p1->height, p2->height))
5314 return 0;
5315 if (! EQ (p1->display_table, p2->display_table))
5316 return 0;
5317 if (! EQ (p1->parent, p2->parent))
5318 return 0;
5319 if (! EQ (p1->prev, p2->prev))
5320 return 0;
5321 if (! ignore_positions)
5323 if (! EQ (p1->hscroll, p2->hscroll))
5324 return 0;
5325 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
5326 return 0;
5327 if (NILP (Fequal (p1->start, p2->start)))
5328 return 0;
5329 if (NILP (Fequal (p1->pointm, p2->pointm)))
5330 return 0;
5331 if (NILP (Fequal (p1->mark, p2->mark)))
5332 return 0;
5336 return 1;
5339 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
5340 Scompare_window_configurations, 2, 2, 0,
5341 "Compare two window configurations as regards the structure of windows.\n\
5342 This function ignores details such as the values of point and mark\n\
5343 and scrolling positions.")
5344 (x, y)
5345 Lisp_Object x, y;
5347 if (compare_window_configurations (x, y, 1))
5348 return Qt;
5349 return Qnil;
5352 void
5353 init_window_once ()
5355 struct frame *f = make_terminal_frame ();
5356 XSETFRAME (selected_frame, f);
5357 Vterminal_frame = selected_frame;
5358 minibuf_window = f->minibuffer_window;
5359 selected_window = f->selected_window;
5360 last_nonminibuf_frame = f;
5362 window_initialized = 1;
5365 void
5366 init_window ()
5368 Vwindow_list = Qnil;
5371 void
5372 syms_of_window ()
5374 Qleft_bitmap_area = intern ("left-bitmap-area");
5375 staticpro (&Qleft_bitmap_area);
5376 Qright_bitmap_area = intern ("right-bitmap-area");
5377 staticpro (&Qright_bitmap_area);
5379 Qwindow_size_fixed = intern ("window-size-fixed");
5380 staticpro (&Qwindow_size_fixed);
5382 staticpro (&Qwindow_configuration_change_hook);
5383 Qwindow_configuration_change_hook
5384 = intern ("window-configuration-change-hook");
5386 Qwindowp = intern ("windowp");
5387 staticpro (&Qwindowp);
5389 Qwindow_configuration_p = intern ("window-configuration-p");
5390 staticpro (&Qwindow_configuration_p);
5392 Qwindow_live_p = intern ("window-live-p");
5393 staticpro (&Qwindow_live_p);
5395 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
5396 staticpro (&Qtemp_buffer_show_hook);
5398 staticpro (&Vwindow_list);
5400 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
5401 "Non-nil means call as function to display a help buffer.\n\
5402 The function is called with one argument, the buffer to be displayed.\n\
5403 Used by `with-output-to-temp-buffer'.\n\
5404 If this function is used, then it must do the entire job of showing\n\
5405 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
5406 Vtemp_buffer_show_function = Qnil;
5408 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
5409 "If non-nil, function to call to handle `display-buffer'.\n\
5410 It will receive two args, the buffer and a flag which if non-nil means\n\
5411 that the currently selected window is not acceptable.\n\
5412 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
5413 work using this function.");
5414 Vdisplay_buffer_function = Qnil;
5416 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
5417 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
5418 Vminibuf_scroll_window = Qnil;
5420 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
5421 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
5422 Vother_window_scroll_buffer = Qnil;
5424 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
5425 "*Non-nil means `display-buffer' should make a separate frame.");
5426 pop_up_frames = 0;
5428 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
5429 "*Non-nil means `display-buffer' should reuse frames.\n\
5430 If the buffer in question is already displayed in a frame, raise that frame.");
5431 display_buffer_reuse_frames = 0;
5433 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
5434 "Function to call to handle automatic new frame creation.\n\
5435 It is called with no arguments and should return a newly created frame.\n\
5437 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
5438 where `pop-up-frame-alist' would hold the default frame parameters.");
5439 Vpop_up_frame_function = Qnil;
5441 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
5442 "*List of buffer names that should have their own special frames.\n\
5443 Displaying a buffer whose name is in this list makes a special frame for it\n\
5444 using `special-display-function'. See also `special-display-regexps'.\n\
5446 An element of the list can be a list instead of just a string.\n\
5447 There are two ways to use a list as an element:\n\
5448 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
5449 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5450 In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
5451 followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
5452 All this is done by the function found in `special-display-function'.\n\
5454 If this variable appears \"not to work\", because you add a name to it\n\
5455 but that buffer still appears in the selected window, look at the\n\
5456 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5457 Those variables take precedence over this one.");
5458 Vspecial_display_buffer_names = Qnil;
5460 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
5461 "*List of regexps saying which buffers should have their own special frames.\n\
5462 If a buffer name matches one of these regexps, it gets its own frame.\n\
5463 Displaying a buffer whose name is in this list makes a special frame for it\n\
5464 using `special-display-function'.\n\
5466 An element of the list can be a list instead of just a string.\n\
5467 There are two ways to use a list as an element:\n\
5468 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
5469 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5470 In the latter case, FUNCTION is called with the buffer as first argument,\n\
5471 followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
5472 All this is done by the function found in `special-display-function'.\n\
5474 If this variable appears \"not to work\", because you add a regexp to it\n\
5475 but the matching buffers still appear in the selected window, look at the\n\
5476 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5477 Those variables take precedence over this one.");
5478 Vspecial_display_regexps = Qnil;
5480 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
5481 "Function to call to make a new frame for a special buffer.\n\
5482 It is called with two arguments, the buffer and optional buffer specific\n\
5483 data, and should return a window displaying that buffer.\n\
5484 The default value makes a separate frame for the buffer,\n\
5485 using `special-display-frame-alist' to specify the frame parameters.\n\
5487 A buffer is special if its is listed in `special-display-buffer-names'\n\
5488 or matches a regexp in `special-display-regexps'.");
5489 Vspecial_display_function = Qnil;
5491 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
5492 "*List of buffer names that should appear in the selected window.\n\
5493 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
5494 switches to it in the selected window, rather than making it appear\n\
5495 in some other window.\n\
5497 An element of the list can be a cons cell instead of just a string.\n\
5498 Then the car must be a string, which specifies the buffer name.\n\
5499 This is for compatibility with `special-display-buffer-names';\n\
5500 the cdr of the cons cell is ignored.\n\
5502 See also `same-window-regexps'.");
5503 Vsame_window_buffer_names = Qnil;
5505 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
5506 "*List of regexps saying which buffers should appear in the selected window.\n\
5507 If a buffer name matches one of these regexps, then displaying it\n\
5508 using `display-buffer' or `pop-to-buffer' switches to it\n\
5509 in the selected window, rather than making it appear in some other window.\n\
5511 An element of the list can be a cons cell instead of just a string.\n\
5512 Then the car must be a string, which specifies the buffer name.\n\
5513 This is for compatibility with `special-display-buffer-names';\n\
5514 the cdr of the cons cell is ignored.\n\
5516 See also `same-window-buffer-names'.");
5517 Vsame_window_regexps = Qnil;
5519 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
5520 "*Non-nil means display-buffer should make new windows.");
5521 pop_up_windows = 1;
5523 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
5524 "*Number of lines of continuity when scrolling by screenfuls.");
5525 next_screen_context_lines = 2;
5527 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
5528 "*display-buffer would prefer to split the largest window if this large.\n\
5529 If there is only one window, it is split regardless of this value.");
5530 split_height_threshold = 500;
5532 DEFVAR_INT ("window-min-height", &window_min_height,
5533 "*Delete any window less than this tall (including its mode line).");
5534 window_min_height = 4;
5536 DEFVAR_INT ("window-min-width", &window_min_width,
5537 "*Delete any window less than this wide.");
5538 window_min_width = 10;
5540 DEFVAR_LISP ("scroll-preserve-screen-position",
5541 &Vscroll_preserve_screen_position,
5542 "*Nonzero means scroll commands move point to keep its screen line unchanged.");
5543 Vscroll_preserve_screen_position = Qnil;
5545 DEFVAR_LISP ("window-configuration-change-hook",
5546 &Vwindow_configuration_change_hook,
5547 "Functions to call when window configuration changes.\n\
5548 The selected frame is the one whose configuration has changed.");
5549 Vwindow_configuration_change_hook = Qnil;
5551 defsubr (&Sselected_window);
5552 defsubr (&Sminibuffer_window);
5553 defsubr (&Swindow_minibuffer_p);
5554 defsubr (&Swindowp);
5555 defsubr (&Swindow_live_p);
5556 defsubr (&Spos_visible_in_window_p);
5557 defsubr (&Swindow_buffer);
5558 defsubr (&Swindow_height);
5559 defsubr (&Swindow_width);
5560 defsubr (&Swindow_hscroll);
5561 defsubr (&Sset_window_hscroll);
5562 defsubr (&Swindow_redisplay_end_trigger);
5563 defsubr (&Sset_window_redisplay_end_trigger);
5564 defsubr (&Swindow_edges);
5565 defsubr (&Scoordinates_in_window_p);
5566 defsubr (&Swindow_at);
5567 defsubr (&Swindow_point);
5568 defsubr (&Swindow_start);
5569 defsubr (&Swindow_end);
5570 defsubr (&Sset_window_point);
5571 defsubr (&Sset_window_start);
5572 defsubr (&Swindow_dedicated_p);
5573 defsubr (&Sset_window_dedicated_p);
5574 defsubr (&Swindow_display_table);
5575 defsubr (&Sset_window_display_table);
5576 defsubr (&Snext_window);
5577 defsubr (&Sprevious_window);
5578 defsubr (&Sother_window);
5579 defsubr (&Sget_lru_window);
5580 defsubr (&Sget_largest_window);
5581 defsubr (&Sget_buffer_window);
5582 defsubr (&Sdelete_other_windows);
5583 defsubr (&Sdelete_windows_on);
5584 defsubr (&Sreplace_buffer_in_windows);
5585 defsubr (&Sdelete_window);
5586 defsubr (&Sset_window_buffer);
5587 defsubr (&Sselect_window);
5588 defsubr (&Sspecial_display_p);
5589 defsubr (&Ssame_window_p);
5590 defsubr (&Sdisplay_buffer);
5591 defsubr (&Ssplit_window);
5592 defsubr (&Senlarge_window);
5593 defsubr (&Sshrink_window);
5594 defsubr (&Sscroll_up);
5595 defsubr (&Sscroll_down);
5596 defsubr (&Sscroll_left);
5597 defsubr (&Sscroll_right);
5598 defsubr (&Sother_window_for_scrolling);
5599 defsubr (&Sscroll_other_window);
5600 defsubr (&Srecenter);
5601 defsubr (&Smove_to_window_line);
5602 defsubr (&Swindow_configuration_p);
5603 defsubr (&Swindow_configuration_frame);
5604 defsubr (&Sset_window_configuration);
5605 defsubr (&Scurrent_window_configuration);
5606 defsubr (&Ssave_window_excursion);
5607 defsubr (&Sset_window_margins);
5608 defsubr (&Swindow_margins);
5609 defsubr (&Swindow_vscroll);
5610 defsubr (&Sset_window_vscroll);
5611 defsubr (&Scompare_window_configurations);
5612 defsubr (&Swindow_list);
5615 void
5616 keys_of_window ()
5618 initial_define_key (control_x_map, '1', "delete-other-windows");
5619 initial_define_key (control_x_map, '2', "split-window");
5620 initial_define_key (control_x_map, '0', "delete-window");
5621 initial_define_key (control_x_map, 'o', "other-window");
5622 initial_define_key (control_x_map, '^', "enlarge-window");
5623 initial_define_key (control_x_map, '<', "scroll-left");
5624 initial_define_key (control_x_map, '>', "scroll-right");
5626 initial_define_key (global_map, Ctl ('V'), "scroll-up");
5627 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
5628 initial_define_key (meta_map, 'v', "scroll-down");
5630 initial_define_key (global_map, Ctl('L'), "recenter");
5631 initial_define_key (meta_map, 'r', "move-to-window-line");