(comment-indent): Save excursion around call to comment-indent-function.
[emacs.git] / src / window.c
blob0362a7ab46aa53cd4696e246f67852f5e6d010f3
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 *));
82 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
84 /* This is the window in which the terminal's cursor should
85 be left when nothing is being done with it. This must
86 always be a leaf window, and its buffer is selected by
87 the top level editing loop at the end of each command.
89 This value is always the same as
90 FRAME_SELECTED_WINDOW (selected_frame). */
92 Lisp_Object selected_window;
94 /* A list of all windows for use by next_window and Fwindow_list.
95 Functions creating or deleting windows should invalidate this cache
96 by setting it to nil. */
98 Lisp_Object Vwindow_list;
100 /* The mini-buffer window of the selected frame.
101 Note that you cannot test for mini-bufferness of an arbitrary window
102 by comparing against this; but you can test for mini-bufferness of
103 the selected window. */
105 Lisp_Object minibuf_window;
107 /* Non-nil means it is the window for C-M-v to scroll
108 when the mini-buffer is selected. */
110 Lisp_Object Vminibuf_scroll_window;
112 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
114 Lisp_Object Vother_window_scroll_buffer;
116 /* Non-nil means it's function to call to display temp buffers. */
118 Lisp_Object Vtemp_buffer_show_function;
120 /* If a window gets smaller than either of these, it is removed. */
122 int window_min_height;
123 int window_min_width;
125 /* Nonzero implies Fdisplay_buffer should create windows. */
127 int pop_up_windows;
129 /* Nonzero implies make new frames for Fdisplay_buffer. */
131 int pop_up_frames;
133 /* Nonzero means reuse existing frames for displaying buffers. */
135 int display_buffer_reuse_frames;
137 /* Non-nil means use this function instead of default */
139 Lisp_Object Vpop_up_frame_function;
141 /* Function to call to handle Fdisplay_buffer. */
143 Lisp_Object Vdisplay_buffer_function;
145 /* List of buffer *names* for buffers that should have their own frames. */
147 Lisp_Object Vspecial_display_buffer_names;
149 /* List of regexps for buffer names that should have their own frames. */
151 Lisp_Object Vspecial_display_regexps;
153 /* Function to pop up a special frame. */
155 Lisp_Object Vspecial_display_function;
157 /* List of buffer *names* for buffers to appear in selected window. */
159 Lisp_Object Vsame_window_buffer_names;
161 /* List of regexps for buffer names to appear in selected window. */
163 Lisp_Object Vsame_window_regexps;
165 /* Hook run at end of temp_output_buffer_show. */
167 Lisp_Object Qtemp_buffer_show_hook;
169 /* Fdisplay_buffer always splits the largest window
170 if that window is more than this high. */
172 int split_height_threshold;
174 /* Number of lines of continuity in scrolling by screenfuls. */
176 int next_screen_context_lines;
178 /* Incremented for each window created. */
180 static int sequence_number;
182 /* Nonzero after init_window_once has finished. */
184 static int window_initialized;
186 /* Hook to run when window config changes. */
188 Lisp_Object Qwindow_configuration_change_hook;
189 Lisp_Object Vwindow_configuration_change_hook;
191 /* Nonzero means scroll commands try to put point
192 at the same screen height as previously. */
194 Lisp_Object Vscroll_preserve_screen_position;
196 #if 0 /* This isn't used anywhere. */
197 /* Nonzero means we can split a frame even if it is "unsplittable". */
198 static int inhibit_frame_unsplittable;
199 #endif /* 0 */
201 #define min(a, b) ((a) < (b) ? (a) : (b))
203 extern int scroll_margin;
205 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
207 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
208 "Returns t if OBJECT is a window.")
209 (object)
210 Lisp_Object object;
212 return WINDOWP (object) ? Qt : Qnil;
215 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
216 "Returns t if OBJECT is a window which is currently visible.")
217 (object)
218 Lisp_Object object;
220 return (WINDOWP (object) && ! NILP (XWINDOW (object)->buffer) ? Qt : Qnil);
223 Lisp_Object
224 make_window ()
226 Lisp_Object val;
227 register struct window *p;
228 register struct Lisp_Vector *vec;
229 int i;
231 vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
232 for (i = 0; i < VECSIZE (struct window); i++)
233 vec->contents[i] = Qnil;
234 vec->size = VECSIZE (struct window);
235 p = (struct window *) vec;
236 XSETFASTINT (p->sequence_number, ++sequence_number);
237 XSETFASTINT (p->left, 0);
238 XSETFASTINT (p->top, 0);
239 XSETFASTINT (p->height, 0);
240 XSETFASTINT (p->width, 0);
241 XSETFASTINT (p->hscroll, 0);
242 p->orig_top = p->orig_height = Qnil;
243 p->start = Fmake_marker ();
244 p->pointm = Fmake_marker ();
245 XSETFASTINT (p->use_time, 0);
246 p->frame = Qnil;
247 p->display_table = Qnil;
248 p->dedicated = Qnil;
249 p->pseudo_window_p = 0;
250 bzero (&p->cursor, sizeof (p->cursor));
251 bzero (&p->last_cursor, sizeof (p->last_cursor));
252 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
253 p->desired_matrix = p->current_matrix = 0;
254 p->phys_cursor_type = -1;
255 p->must_be_updated_p = 0;
256 XSETFASTINT (p->window_end_vpos, 0);
257 XSETFASTINT (p->window_end_pos, 0);
258 p->window_end_valid = Qnil;
259 p->vscroll = 0;
260 XSETWINDOW (val, p);
261 XSETFASTINT (p->last_point, 0);
262 p->frozen_window_start_p = 0;
264 Vwindow_list = Qnil;
265 return val;
268 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
269 "Return the window that the cursor now appears in and commands apply to.")
272 return selected_window;
275 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
276 "Return the window used now for minibuffers.\n\
277 If the optional argument FRAME is specified, return the minibuffer window\n\
278 used by that frame.")
279 (frame)
280 Lisp_Object frame;
282 if (NILP (frame))
283 frame = selected_frame;
284 CHECK_LIVE_FRAME (frame, 0);
285 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
288 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
289 "Returns non-nil if WINDOW is a minibuffer window.")
290 (window)
291 Lisp_Object window;
293 struct window *w = decode_window (window);
294 return MINI_WINDOW_P (w) ? Qt : Qnil;
298 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
299 Spos_visible_in_window_p, 0, 3, 0,
300 "Return t if position POS is currently on the frame in WINDOW.\n\
301 Return nil if that position is scrolled vertically out of view.\n\
302 If FULLY is non-nil, then only return t when POS is completely visible.\n\
303 POS defaults to point in WINDOW; WINDOW defaults to the selected window.")
304 (pos, window, fully)
305 Lisp_Object pos, window, fully;
307 register struct window *w;
308 register int posint;
309 register struct buffer *buf;
310 struct text_pos top;
311 Lisp_Object in_window;
312 int fully_p;
314 w = decode_window (window);
315 buf = XBUFFER (w->buffer);
316 SET_TEXT_POS_FROM_MARKER (top, w->start);
318 if (!NILP (pos))
320 CHECK_NUMBER_COERCE_MARKER (pos, 0);
321 posint = XINT (pos);
323 else if (w == XWINDOW (selected_window))
324 posint = PT;
325 else
326 posint = XMARKER (w->pointm)->charpos;
328 /* If position is above window start, it's not visible. */
329 if (posint < CHARPOS (top))
330 in_window = Qnil;
331 else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
332 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
333 && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
335 /* If frame is up-to-date, and POSINT is < window end pos, use
336 that info. This doesn't work for POSINT == end pos, because
337 the window end pos is actually the position _after_ the last
338 char in the window. */
339 if (!NILP (fully))
341 pos_visible_p (w, posint, &fully_p, !NILP (fully));
342 in_window = fully_p ? Qt : Qnil;
344 else
345 in_window = Qt;
347 else if (posint > BUF_ZV (buf))
348 in_window = Qnil;
349 else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
350 /* If window start is out of range, do something reasonable. */
351 in_window = Qnil;
352 else
354 if (pos_visible_p (w, posint, &fully_p, !NILP (fully)))
355 in_window = NILP (fully) || fully_p ? Qt : Qnil;
356 else
357 in_window = Qnil;
360 return in_window;
364 static struct window *
365 decode_window (window)
366 register Lisp_Object window;
368 if (NILP (window))
369 return XWINDOW (selected_window);
371 CHECK_LIVE_WINDOW (window, 0);
372 return XWINDOW (window);
375 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
376 "Return the buffer that WINDOW is displaying.")
377 (window)
378 Lisp_Object window;
380 return decode_window (window)->buffer;
383 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
384 "Return the number of lines in WINDOW (including its mode line).")
385 (window)
386 Lisp_Object window;
388 return decode_window (window)->height;
391 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
392 "Return the number of display columns in WINDOW.\n\
393 This is the width that is usable columns available for text in WINDOW.\n\
394 If you want to find out how many columns WINDOW takes up,\n\
395 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
396 (window)
397 Lisp_Object window;
399 return make_number (window_internal_width (decode_window (window)));
402 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
403 "Return the number of columns by which WINDOW is scrolled from left margin.")
404 (window)
405 Lisp_Object window;
407 return decode_window (window)->hscroll;
410 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
411 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
412 NCOL should be zero or positive.")
413 (window, ncol)
414 register Lisp_Object window, ncol;
416 register struct window *w;
418 CHECK_NUMBER (ncol, 1);
419 if (XINT (ncol) < 0) XSETFASTINT (ncol, 0);
420 w = decode_window (window);
421 if (XINT (w->hscroll) != XINT (ncol))
422 /* Prevent redisplay shortcuts */
423 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
424 w->hscroll = ncol;
425 return ncol;
428 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
429 Swindow_redisplay_end_trigger, 0, 1, 0,
430 "Return WINDOW's redisplay end trigger value.\n\
431 See `set-window-redisplay-end-trigger' for more information.")
432 (window)
433 Lisp_Object window;
435 return decode_window (window)->redisplay_end_trigger;
438 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
439 Sset_window_redisplay_end_trigger, 2, 2, 0,
440 "Set WINDOW's redisplay end trigger value to VALUE.\n\
441 VALUE should be a buffer position (typically a marker) or nil.\n\
442 If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
443 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
444 with two arguments: WINDOW, and the end trigger value.\n\
445 Afterwards the end-trigger value is reset to nil.")
446 (window, value)
447 register Lisp_Object window, value;
449 register struct window *w;
451 w = decode_window (window);
452 w->redisplay_end_trigger = value;
453 return value;
456 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
457 "Return a list of the edge coordinates of WINDOW.\n\
458 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
459 RIGHT is one more than the rightmost column used by WINDOW,\n\
460 and BOTTOM is one more than the bottommost row used by WINDOW\n\
461 and its mode-line.")
462 (window)
463 Lisp_Object window;
465 register struct window *w = decode_window (window);
467 return Fcons (w->left, Fcons (w->top,
468 Fcons (make_number (WINDOW_RIGHT_EDGE (w)),
469 Fcons (make_number (XFASTINT (w->top)
470 + XFASTINT (w->height)),
471 Qnil))));
474 /* Test if the character at column *X, row *Y is within window W.
475 If it is not, return 0;
476 if it is in the window's text area,
477 set *x and *y to its location relative to the upper left corner
478 of the window, and
479 return 1;
480 if it is on the window's modeline, return 2;
481 if it is on the border between the window and its right sibling,
482 return 3.
483 if it is on the window's top line, return 4;
484 if it is in the bitmap area to the left/right of the window,
485 return 5 or 6, and convert *X and *Y to window-relative corrdinates.
487 X and Y are frame relative pixel coordinates. */
489 static int
490 coordinates_in_window (w, x, y)
491 register struct window *w;
492 register int *x, *y;
494 struct frame *f = XFRAME (WINDOW_FRAME (w));
495 int left_x, right_x, top_y, bottom_y;
496 int flags_area_width = FRAME_LEFT_FLAGS_AREA_WIDTH (f);
498 /* Let's make this a global enum later, instead of using numbers
499 everywhere. */
500 enum {ON_NOTHING, ON_TEXT, ON_MODE_LINE, ON_VERTICAL_BORDER,
501 ON_HEADER_LINE, ON_LEFT_FRINGE, ON_RIGHT_FRINGE};
503 /* In what's below, we subtract 1 when computing right_x because we
504 want the rightmost pixel, which is given by left_pixel+width-1. */
505 if (w->pseudo_window_p)
507 left_x = 0;
508 right_x = XFASTINT (w->width) * CANON_Y_UNIT (f) - 1;
509 top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
510 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
512 else
514 left_x = (WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w)
515 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
516 right_x = WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w) - 1;
517 top_y = (WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w)
518 - FRAME_INTERNAL_BORDER_WIDTH_SAFE (f));
519 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
522 /* Completely outside anything interesting? */
523 if (*y < top_y
524 || *y >= bottom_y
525 || *x < (left_x
526 - flags_area_width
527 - (FRAME_LEFT_SCROLL_BAR_WIDTH (f)
528 * CANON_X_UNIT (f)))
529 || *x > right_x + flags_area_width)
530 return ON_NOTHING;
532 /* On the mode line or header line? If it's near the start of
533 the mode or header line of window that's has a horizontal
534 sibling, say it's on the vertical line. That's to be able
535 to resize windows horizontally in case we're using toolkit
536 scroll bars. */
538 if (WINDOW_WANTS_MODELINE_P (w)
539 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
541 if (XFASTINT (w->left) > 0
542 && (abs (*x - XFASTINT (w->left) * CANON_X_UNIT (f))
543 < CANON_X_UNIT (f) / 2))
544 return ON_VERTICAL_BORDER;
545 return ON_MODE_LINE;
548 if (WINDOW_WANTS_HEADER_LINE_P (w)
549 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
551 if (XFASTINT (w->left) > 0
552 && (abs (*x - XFASTINT (w->left) * CANON_X_UNIT (f))
553 < CANON_X_UNIT (f) / 2))
554 return ON_VERTICAL_BORDER;
555 return ON_HEADER_LINE;
558 /* Need to say "*x > right_x" rather than >=, since on character
559 terminals, the vertical line's x coordinate is right_x. */
560 if (*x < left_x || *x > right_x)
562 /* Other lines than the mode line don't include flags areas and
563 scroll bars on the left. */
565 /* Convert X and Y to window-relative pixel coordinates. */
566 *x -= left_x;
567 *y -= top_y;
568 return *x < left_x ? ON_LEFT_FRINGE : ON_RIGHT_FRINGE;
571 /* Here, too, "*x > right_x" is because of character terminals. */
572 if (!w->pseudo_window_p
573 && !WINDOW_RIGHTMOST_P (w)
574 && *x > right_x - CANON_X_UNIT (f))
575 /* On the border on the right side of the window? Assume that
576 this area begins at RIGHT_X minus a canonical char width. */
577 return ON_VERTICAL_BORDER;
579 /* Convert X and Y to window-relative pixel coordinates. */
580 *x -= left_x;
581 *y -= top_y;
582 return ON_TEXT;
585 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
586 Scoordinates_in_window_p, 2, 2, 0,
587 "Return non-nil if COORDINATES are in WINDOW.\n\
588 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
589 measured in characters from the upper-left corner of the frame.\n\
590 (0 . 0) denotes the character in the upper left corner of the\n\
591 frame.\n\
592 If COORDINATES are in the text portion of WINDOW,\n\
593 the coordinates relative to the window are returned.\n\
594 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
595 If they are in the top mode line of WINDOW, `header-line' is returned.\n\
596 If they are in the bitmap-area to the left of the window,\n\
597 `left-bitmap-area' is returned, if they are in the area on the right of\n\
598 the window, `right-bitmap-area' is returned.\n\
599 If they are on the border between WINDOW and its right sibling,\n\
600 `vertical-line' is returned.")
601 (coordinates, window)
602 register Lisp_Object coordinates, window;
604 struct window *w;
605 struct frame *f;
606 int x, y;
607 Lisp_Object lx, ly;
609 CHECK_LIVE_WINDOW (window, 0);
610 w = XWINDOW (window);
611 f = XFRAME (w->frame);
612 CHECK_CONS (coordinates, 1);
613 lx = Fcar (coordinates);
614 ly = Fcdr (coordinates);
615 CHECK_NUMBER_OR_FLOAT (lx, 1);
616 CHECK_NUMBER_OR_FLOAT (ly, 1);
617 x = PIXEL_X_FROM_CANON_X (f, lx);
618 y = PIXEL_Y_FROM_CANON_Y (f, ly);
620 switch (coordinates_in_window (w, &x, &y))
622 case 0: /* NOT in window at all. */
623 return Qnil;
625 case 1: /* In text part of window. */
626 /* X and Y are now window relative pixel coordinates.
627 Convert them to canonical char units before returning
628 them. */
629 return Fcons (CANON_X_FROM_PIXEL_X (f, x),
630 CANON_Y_FROM_PIXEL_Y (f, y));
632 case 2: /* In mode line of window. */
633 return Qmode_line;
635 case 3: /* On right border of window. */
636 return Qvertical_line;
638 case 4:
639 return Qheader_line;
641 case 5:
642 return Qleft_bitmap_area;
644 case 6:
645 return Qright_bitmap_area;
647 default:
648 abort ();
653 /* Callback for foreach_window, used in window_from_coordinates.
654 Check if window W contains coordinates specified by USER_DATA which
655 is actually a pointer to a struct check_window_data CW.
657 Check if window W contains coordinates *CW->x and *CW->y. If it
658 does, return W in *CW->window, as Lisp_Object, and return in
659 *CW->part the part of the window under coordinates *X,*Y. Return
660 zero from this function to stop iterating over windows. */
662 struct check_window_data
664 Lisp_Object *window;
665 int *x, *y, *part;
668 static int
669 check_window_containing (w, user_data)
670 struct window *w;
671 void *user_data;
673 struct check_window_data *cw = (struct check_window_data *) user_data;
674 int found;
676 found = coordinates_in_window (w, cw->x, cw->y);
677 if (found)
679 *cw->part = found - 1;
680 XSETWINDOW (*cw->window, w);
683 return !found;
687 /* Find the window containing frame-relative pixel position X/Y and
688 return it as a Lisp_Object. If X, Y is on the window's modeline,
689 set *PART to 1; if it is on the separating line between the window
690 and its right sibling, set it to 2; otherwise set it to 0. If
691 there is no window under X, Y return nil and leave *PART
692 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
694 This function was previously implemented with a loop cycling over
695 windows with Fnext_window, and starting with the frame's selected
696 window. It turned out that this doesn't work with an
697 implementation of next_window using Vwindow_list, because
698 FRAME_SELECTED_WINDOW (F) is not always contained in the window
699 tree of F when this function is called asynchronously from
700 note_mouse_highlight. The original loop didn't terminate in this
701 case. */
703 Lisp_Object
704 window_from_coordinates (f, x, y, part, tool_bar_p)
705 struct frame *f;
706 int x, y;
707 int *part;
708 int tool_bar_p;
710 Lisp_Object window;
711 struct check_window_data cw;
713 window = Qnil;
714 cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
715 foreach_window (f, check_window_containing, &cw);
717 /* If not found above, see if it's in the tool bar window, if a tool
718 bar exists. */
719 if (NILP (window)
720 && tool_bar_p
721 && WINDOWP (f->tool_bar_window)
722 && XINT (XWINDOW (f->tool_bar_window)->height) > 0
723 && coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y))
725 *part = 0;
726 window = f->tool_bar_window;
729 return window;
732 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
733 "Return window containing coordinates X and Y on FRAME.\n\
734 If omitted, FRAME defaults to the currently selected frame.\n\
735 The top left corner of the frame is considered to be row 0,\n\
736 column 0.")
737 (x, y, frame)
738 Lisp_Object x, y, frame;
740 int part;
741 struct frame *f;
743 if (NILP (frame))
744 frame = selected_frame;
745 CHECK_LIVE_FRAME (frame, 2);
746 f = XFRAME (frame);
748 /* Check that arguments are integers or floats. */
749 CHECK_NUMBER_OR_FLOAT (x, 0);
750 CHECK_NUMBER_OR_FLOAT (y, 1);
752 return window_from_coordinates (f,
753 PIXEL_X_FROM_CANON_X (f, x),
754 PIXEL_Y_FROM_CANON_Y (f, y),
755 &part, 0);
758 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
759 "Return current value of point in WINDOW.\n\
760 For a nonselected window, this is the value point would have\n\
761 if that window were selected.\n\
763 Note that, when WINDOW is the selected window and its buffer\n\
764 is also currently selected, the value returned is the same as (point).\n\
765 It would be more strictly correct to return the `top-level' value\n\
766 of point, outside of any save-excursion forms.\n\
767 But that is hard to define.")
768 (window)
769 Lisp_Object window;
771 register struct window *w = decode_window (window);
773 if (w == XWINDOW (selected_window)
774 && current_buffer == XBUFFER (w->buffer))
775 return Fpoint ();
776 return Fmarker_position (w->pointm);
779 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
780 "Return position at which display currently starts in WINDOW.\n\
781 This is updated by redisplay or by calling `set-window-start'.")
782 (window)
783 Lisp_Object window;
785 return Fmarker_position (decode_window (window)->start);
788 /* This is text temporarily removed from the doc string below.
790 This function returns nil if the position is not currently known.\n\
791 That happens when redisplay is preempted and doesn't finish.\n\
792 If in that case you want to compute where the end of the window would\n\
793 have been if redisplay had finished, do this:\n\
794 (save-excursion\n\
795 (goto-char (window-start window))\n\
796 (vertical-motion (1- (window-height window)) window)\n\
797 (point))") */
799 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
800 "Return position at which display currently ends in WINDOW.\n\
801 This is updated by redisplay, when it runs to completion.\n\
802 Simply changing the buffer text or setting `window-start'\n\
803 does not update this value.\n\
804 If UP-TO-DATE is non-nil, compute the up-to-date position\n\
805 if it isn't already recorded.")
806 (window, update)
807 Lisp_Object window, update;
809 Lisp_Object value;
810 struct window *w = decode_window (window);
811 Lisp_Object buf;
813 buf = w->buffer;
814 CHECK_BUFFER (buf, 0);
816 #if 0 /* This change broke some things. We should make it later. */
817 /* If we don't know the end position, return nil.
818 The user can compute it with vertical-motion if he wants to.
819 It would be nicer to do it automatically,
820 but that's so slow that it would probably bother people. */
821 if (NILP (w->window_end_valid))
822 return Qnil;
823 #endif
825 if (! NILP (update)
826 && ! (! NILP (w->window_end_valid)
827 && XFASTINT (w->last_modified) >= MODIFF))
829 struct text_pos startp;
830 struct it it;
832 /* In case W->start is out of the range, use something
833 reasonable. This situation occured when loading a file with
834 `-l' containing a call to `rmail' with subsequent other
835 commands. At the end, W->start happened to be BEG, while
836 rmail had already narrowed the buffer. */
837 if (XMARKER (w->start)->charpos < BEGV)
838 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
839 else if (XMARKER (w->start)->charpos > ZV)
840 SET_TEXT_POS (startp, ZV, ZV_BYTE);
841 else
842 SET_TEXT_POS_FROM_MARKER (startp, w->start);
844 /* Cannot use Fvertical_motion because that function doesn't
845 cope with variable-height lines. */
846 start_display (&it, w, startp);
847 move_it_vertically (&it, window_box_height (w));
848 value = make_number (IT_CHARPOS (it));
850 else
851 XSETINT (value, BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
853 return value;
856 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
857 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
858 (window, pos)
859 Lisp_Object window, pos;
861 register struct window *w = decode_window (window);
863 CHECK_NUMBER_COERCE_MARKER (pos, 1);
864 if (w == XWINDOW (selected_window)
865 && XBUFFER (w->buffer) == current_buffer)
866 Fgoto_char (pos);
867 else
868 set_marker_restricted (w->pointm, pos, w->buffer);
870 return pos;
873 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
874 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
875 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
876 from overriding motion of point in order to display at this exact start.")
877 (window, pos, noforce)
878 Lisp_Object window, pos, noforce;
880 register struct window *w = decode_window (window);
882 CHECK_NUMBER_COERCE_MARKER (pos, 1);
883 set_marker_restricted (w->start, pos, w->buffer);
884 /* this is not right, but much easier than doing what is right. */
885 w->start_at_line_beg = Qnil;
886 if (NILP (noforce))
887 w->force_start = Qt;
888 w->update_mode_line = Qt;
889 XSETFASTINT (w->last_modified, 0);
890 XSETFASTINT (w->last_overlay_modified, 0);
891 if (!EQ (window, selected_window))
892 windows_or_buffers_changed++;
894 return pos;
897 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
898 1, 1, 0,
899 "Return WINDOW's dedicated object, usually t or nil.\n\
900 See also `set-window-dedicated-p'.")
901 (window)
902 Lisp_Object window;
904 return decode_window (window)->dedicated;
907 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
908 Sset_window_dedicated_p, 2, 2, 0,
909 "Control whether WINDOW is dedicated to the buffer it displays.\n\
910 If it is dedicated, Emacs will not automatically change\n\
911 which buffer appears in it.\n\
912 The second argument is the new value for the dedication flag;\n\
913 non-nil means yes.")
914 (window, arg)
915 Lisp_Object window, arg;
917 register struct window *w = decode_window (window);
919 if (NILP (arg))
920 w->dedicated = Qnil;
921 else
922 w->dedicated = Qt;
924 return w->dedicated;
927 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
928 0, 1, 0,
929 "Return the display-table that WINDOW is using.")
930 (window)
931 Lisp_Object window;
933 return decode_window (window)->display_table;
936 /* Get the display table for use on window W. This is either W's
937 display table or W's buffer's display table. Ignore the specified
938 tables if they are not valid; if no valid table is specified,
939 return 0. */
941 struct Lisp_Char_Table *
942 window_display_table (w)
943 struct window *w;
945 struct Lisp_Char_Table *dp = NULL;
947 if (DISP_TABLE_P (w->display_table))
948 dp = XCHAR_TABLE (w->display_table);
949 else if (BUFFERP (w->buffer))
951 struct buffer *b = XBUFFER (w->buffer);
953 if (DISP_TABLE_P (b->display_table))
954 dp = XCHAR_TABLE (b->display_table);
955 else if (DISP_TABLE_P (Vstandard_display_table))
956 dp = XCHAR_TABLE (Vstandard_display_table);
959 return dp;
962 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
963 "Set WINDOW's display-table to TABLE.")
964 (window, table)
965 register Lisp_Object window, table;
967 register struct window *w;
969 w = decode_window (window);
970 w->display_table = table;
971 return table;
974 /* Record info on buffer window w is displaying
975 when it is about to cease to display that buffer. */
976 static void
977 unshow_buffer (w)
978 register struct window *w;
980 Lisp_Object buf;
981 struct buffer *b;
983 buf = w->buffer;
984 b = XBUFFER (buf);
985 if (b != XMARKER (w->pointm)->buffer)
986 abort ();
988 #if 0
989 if (w == XWINDOW (selected_window)
990 || ! EQ (buf, XWINDOW (selected_window)->buffer))
991 /* Do this except when the selected window's buffer
992 is being removed from some other window. */
993 #endif
994 /* last_window_start records the start position that this buffer
995 had in the last window to be disconnected from it.
996 Now that this statement is unconditional,
997 it is possible for the buffer to be displayed in the
998 selected window, while last_window_start reflects another
999 window which was recently showing the same buffer.
1000 Some people might say that might be a good thing. Let's see. */
1001 b->last_window_start = marker_position (w->start);
1003 /* Point in the selected window's buffer
1004 is actually stored in that buffer, and the window's pointm isn't used.
1005 So don't clobber point in that buffer. */
1006 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1007 /* This line helps to fix Horsley's testbug.el bug. */
1008 && !(WINDOWP (b->last_selected_window)
1009 && w != XWINDOW (b->last_selected_window)
1010 && EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
1011 temp_set_point_both (b,
1012 clip_to_bounds (BUF_BEGV (b),
1013 XMARKER (w->pointm)->charpos,
1014 BUF_ZV (b)),
1015 clip_to_bounds (BUF_BEGV_BYTE (b),
1016 marker_byte_position (w->pointm),
1017 BUF_ZV_BYTE (b)));
1019 if (WINDOWP (b->last_selected_window)
1020 && w == XWINDOW (b->last_selected_window))
1021 b->last_selected_window = Qnil;
1024 /* Put replacement into the window structure in place of old. */
1025 static void
1026 replace_window (old, replacement)
1027 Lisp_Object old, replacement;
1029 register Lisp_Object tem;
1030 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
1032 /* If OLD is its frame's root_window, then replacement is the new
1033 root_window for that frame. */
1035 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1036 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
1038 p->left = o->left;
1039 p->top = o->top;
1040 p->width = o->width;
1041 p->height = o->height;
1042 p->desired_matrix = p->current_matrix = 0;
1043 p->vscroll = 0;
1044 bzero (&p->cursor, sizeof (p->cursor));
1045 bzero (&p->last_cursor, sizeof (p->last_cursor));
1046 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
1047 p->phys_cursor_type = -1;
1048 p->must_be_updated_p = 0;
1049 p->pseudo_window_p = 0;
1050 XSETFASTINT (p->window_end_vpos, 0);
1051 XSETFASTINT (p->window_end_pos, 0);
1052 p->window_end_valid = Qnil;
1053 p->frozen_window_start_p = 0;
1054 p->orig_top = p->orig_height = Qnil;
1056 p->next = tem = o->next;
1057 if (!NILP (tem))
1058 XWINDOW (tem)->prev = replacement;
1060 p->prev = tem = o->prev;
1061 if (!NILP (tem))
1062 XWINDOW (tem)->next = replacement;
1064 p->parent = tem = o->parent;
1065 if (!NILP (tem))
1067 if (EQ (XWINDOW (tem)->vchild, old))
1068 XWINDOW (tem)->vchild = replacement;
1069 if (EQ (XWINDOW (tem)->hchild, old))
1070 XWINDOW (tem)->hchild = replacement;
1073 /*** Here, if replacement is a vertical combination
1074 and so is its new parent, we should make replacement's
1075 children be children of that parent instead. ***/
1078 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
1079 "Remove WINDOW from the display. Default is selected window.")
1080 (window)
1081 register Lisp_Object window;
1083 delete_window (window);
1085 if (! NILP (Vwindow_configuration_change_hook)
1086 && ! NILP (Vrun_hooks))
1087 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1089 return Qnil;
1092 void
1093 delete_window (window)
1094 register Lisp_Object window;
1096 register Lisp_Object tem, parent, sib;
1097 register struct window *p;
1098 register struct window *par;
1099 FRAME_PTR frame;
1101 /* Because this function is called by other C code on non-leaf
1102 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
1103 so we can't decode_window here. */
1104 if (NILP (window))
1105 window = selected_window;
1106 else
1107 CHECK_WINDOW (window, 0);
1108 p = XWINDOW (window);
1110 /* It's okay to delete an already-deleted window. */
1111 if (NILP (p->buffer)
1112 && NILP (p->hchild)
1113 && NILP (p->vchild))
1114 return;
1116 parent = p->parent;
1117 if (NILP (parent))
1118 error ("Attempt to delete minibuffer or sole ordinary window");
1119 par = XWINDOW (parent);
1121 windows_or_buffers_changed++;
1122 Vwindow_list = Qnil;
1123 frame = XFRAME (WINDOW_FRAME (p));
1124 FRAME_WINDOW_SIZES_CHANGED (frame) = 1;
1126 /* Are we trying to delete any frame's selected window? */
1128 Lisp_Object frame, pwindow;
1130 /* See if the frame's selected window is either WINDOW
1131 or any subwindow of it, by finding all that window's parents
1132 and comparing each one with WINDOW. */
1133 frame = WINDOW_FRAME (XWINDOW (window));
1134 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
1136 while (!NILP (pwindow))
1138 if (EQ (window, pwindow))
1139 break;
1140 pwindow = XWINDOW (pwindow)->parent;
1143 if (EQ (window, pwindow))
1145 Lisp_Object alternative;
1146 alternative = Fnext_window (window, Qlambda, Qnil);
1148 /* If we're about to delete the selected window on the
1149 selected frame, then we should use Fselect_window to select
1150 the new window. On the other hand, if we're about to
1151 delete the selected window on any other frame, we shouldn't do
1152 anything but set the frame's selected_window slot. */
1153 if (EQ (window, selected_window))
1154 Fselect_window (alternative);
1155 else
1156 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
1160 tem = p->buffer;
1161 /* tem is null for dummy parent windows
1162 (which have inferiors but not any contents themselves) */
1163 if (!NILP (tem))
1165 unshow_buffer (p);
1166 unchain_marker (p->pointm);
1167 unchain_marker (p->start);
1170 /* Free window glyph matrices. It is sure that they are allocated
1171 again when ADJUST_GLYPHS is called. Block input so that expose
1172 events and other events that access glyph matrices are not
1173 processed while we are changing them. */
1174 BLOCK_INPUT;
1175 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (frame)));
1177 tem = p->next;
1178 if (!NILP (tem))
1179 XWINDOW (tem)->prev = p->prev;
1181 tem = p->prev;
1182 if (!NILP (tem))
1183 XWINDOW (tem)->next = p->next;
1185 if (EQ (window, par->hchild))
1186 par->hchild = p->next;
1187 if (EQ (window, par->vchild))
1188 par->vchild = p->next;
1190 /* Find one of our siblings to give our space to. */
1191 sib = p->prev;
1192 if (NILP (sib))
1194 /* If p gives its space to its next sibling, that sibling needs
1195 to have its top/left side pulled back to where p's is.
1196 set_window_{height,width} will re-position the sibling's
1197 children. */
1198 sib = p->next;
1199 XWINDOW (sib)->top = p->top;
1200 XWINDOW (sib)->left = p->left;
1203 /* Stretch that sibling. */
1204 if (!NILP (par->vchild))
1205 set_window_height (sib,
1206 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
1208 if (!NILP (par->hchild))
1209 set_window_width (sib,
1210 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
1213 /* If parent now has only one child,
1214 put the child into the parent's place. */
1215 tem = par->hchild;
1216 if (NILP (tem))
1217 tem = par->vchild;
1218 if (NILP (XWINDOW (tem)->next))
1219 replace_window (parent, tem);
1221 /* Since we may be deleting combination windows, we must make sure that
1222 not only p but all its children have been marked as deleted. */
1223 if (! NILP (p->hchild))
1224 delete_all_subwindows (XWINDOW (p->hchild));
1225 else if (! NILP (p->vchild))
1226 delete_all_subwindows (XWINDOW (p->vchild));
1228 /* Mark this window as deleted. */
1229 p->buffer = p->hchild = p->vchild = Qnil;
1231 /* Adjust glyph matrices. */
1232 adjust_glyphs (frame);
1233 UNBLOCK_INPUT;
1238 /***********************************************************************
1239 Window List
1240 ***********************************************************************/
1242 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1243 pointer. This is a callback function for foreach_window, used in
1244 function window_list. */
1246 static int
1247 add_window_to_list (w, user_data)
1248 struct window *w;
1249 void *user_data;
1251 Lisp_Object *list = (Lisp_Object *) user_data;
1252 Lisp_Object window;
1253 XSETWINDOW (window, w);
1254 *list = Fcons (window, *list);
1255 return 1;
1259 /* Return a list of all windows, for use by next_window. If
1260 Vwindow_list is a list, return that list. Otherwise, build a new
1261 list, cache it in Vwindow_list, and return that. */
1263 static Lisp_Object
1264 window_list ()
1266 if (!CONSP (Vwindow_list))
1268 Lisp_Object tail;
1270 Vwindow_list = Qnil;
1271 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1273 Lisp_Object args[2];
1275 /* We are visiting windows in canonical order, and add
1276 new windows at the front of args[1], which means we
1277 have to reverse this list at the end. */
1278 args[1] = Qnil;
1279 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
1280 args[0] = Vwindow_list;
1281 args[1] = Fnreverse (args[1]);
1282 Vwindow_list = Fnconc (2, args);
1286 return Vwindow_list;
1290 /* Value is non-zero if WINDOW satisfies the constraints given by
1291 OWINDOW, MINIBUF and ALL_FRAMES.
1293 MINIBUF t means WINDOW may be minibuffer windows.
1294 `lambda' means WINDOW may not be a minibuffer window.
1295 a window means a specific minibuffer window
1297 ALL_FRAMES t means search all frames,
1298 nil means search just current frame,
1299 `visible' means search just visible frames,
1300 0 means search visible and iconified frames,
1301 a window means search the frame that window belongs to,
1302 a frame means consider windows on that frame, only. */
1304 static int
1305 candidate_window_p (window, owindow, minibuf, all_frames)
1306 Lisp_Object window, owindow, minibuf, all_frames;
1308 struct window *w = XWINDOW (window);
1309 struct frame *f = XFRAME (w->frame);
1310 int candidate_p = 1;
1312 if (!BUFFERP (w->buffer))
1313 candidate_p = 0;
1314 else if (MINI_WINDOW_P (w)
1315 && (EQ (minibuf, Qlambda)
1316 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
1318 /* If MINIBUF is `lambda' don't consider any mini-windows.
1319 If it is a window, consider only that one. */
1320 candidate_p = 0;
1322 else if (EQ (all_frames, Qt))
1323 candidate_p = 1;
1324 else if (NILP (all_frames))
1326 xassert (WINDOWP (owindow));
1327 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
1329 else if (EQ (all_frames, Qvisible))
1331 FRAME_SAMPLE_VISIBILITY (f);
1332 candidate_p = FRAME_VISIBLE_P (f);
1334 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
1336 FRAME_SAMPLE_VISIBILITY (f);
1337 candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
1339 else if (WINDOWP (all_frames))
1340 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
1341 || EQ (XWINDOW (all_frames)->frame, w->frame)
1342 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
1343 else if (FRAMEP (all_frames))
1344 candidate_p = EQ (all_frames, w->frame);
1346 return candidate_p;
1350 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
1351 Fwindow_list. See there for the meaning of WINDOW, MINIBUF, and
1352 ALL_FRAMES. */
1354 static void
1355 decode_next_window_args (window, minibuf, all_frames)
1356 Lisp_Object *window, *minibuf, *all_frames;
1358 if (NILP (*window))
1359 *window = selected_window;
1360 else
1361 CHECK_LIVE_WINDOW (*window, 0);
1363 /* MINIBUF nil may or may not include minibuffers. Decide if it
1364 does. */
1365 if (NILP (*minibuf))
1366 *minibuf = minibuf_level ? minibuf_window : Qlambda;
1367 else if (!EQ (*minibuf, Qt))
1368 *minibuf = Qlambda;
1370 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
1371 => count none of them, or a specific minibuffer window (the
1372 active one) to count. */
1374 /* ALL_FRAMES nil doesn't specify which frames to include. */
1375 if (NILP (*all_frames))
1376 *all_frames = (!EQ (*minibuf, Qlambda)
1377 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
1378 : Qnil);
1379 else if (EQ (*all_frames, Qvisible))
1381 else if (XFASTINT (*all_frames) == 0)
1383 else if (FRAMEP (*all_frames))
1385 else if (!EQ (*all_frames, Qt))
1386 *all_frames = Qnil;
1388 /* Now *ALL_FRAMES is t meaning search all frames, nil meaning
1389 search just current frame, `visible' meaning search just visible
1390 frames, 0 meaning search visible and iconified frames, or a
1391 window, meaning search the frame that window belongs to, or a
1392 frame, meaning consider windows on that frame, only. */
1396 /* Return the next or previous window of WINDOW in canonical ordering
1397 of windows. NEXT_P non-zero means return the next window. See the
1398 documentation string of next-window for the meaning of MINIBUF and
1399 ALL_FRAMES. */
1401 static Lisp_Object
1402 next_window (window, minibuf, all_frames, next_p)
1403 Lisp_Object window, minibuf, all_frames;
1404 int next_p;
1406 decode_next_window_args (&window, &minibuf, &all_frames);
1408 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
1409 return the first window on the frame. */
1410 if (FRAMEP (all_frames)
1411 && !EQ (all_frames, XWINDOW (window)->frame))
1412 return Fframe_first_window (all_frames);
1414 if (next_p)
1416 Lisp_Object list;
1418 /* Find WINDOW in the list of all windows. */
1419 list = Fmemq (window, window_list ());
1421 /* Scan forward from WINDOW to the end of the window list. */
1422 if (CONSP (list))
1423 for (list = XCDR (list); CONSP (list); list = XCDR (list))
1424 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1425 break;
1427 /* Scan from the start of the window list up to WINDOW. */
1428 if (!CONSP (list))
1429 for (list = Vwindow_list;
1430 CONSP (list) && !EQ (XCAR (list), window);
1431 list = XCDR (list))
1432 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
1433 break;
1435 if (CONSP (list))
1436 window = XCAR (list);
1438 else
1440 Lisp_Object candidate, list;
1442 /* Scan through the list of windows for candidates. If there are
1443 candidate windows in front of WINDOW, the last one of these
1444 is the one we want. If there are candidates following WINDOW
1445 in the list, again the last one of these is the one we want. */
1446 candidate = Qnil;
1447 for (list = window_list (); CONSP (list); list = XCDR (list))
1449 if (EQ (XCAR (list), window))
1451 if (WINDOWP (candidate))
1452 break;
1454 else if (candidate_window_p (XCAR (list), window, minibuf,
1455 all_frames))
1456 candidate = XCAR (list);
1459 if (WINDOWP (candidate))
1460 window = candidate;
1463 return window;
1467 /* This comment supplies the doc string for `next-window',
1468 for make-docfile to see. We cannot put this in the real DEFUN
1469 due to limits in the Unix cpp.
1471 DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
1472 "Return next window after WINDOW in canonical ordering of windows.\n\
1473 If omitted, WINDOW defaults to the selected window.\n\
1475 Optional second arg MINIBUF t means count the minibuffer window even\n\
1476 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1477 it is active. MINIBUF neither t nor nil means not to count the\n\
1478 minibuffer even if it is active.\n\
1480 Several frames may share a single minibuffer; if the minibuffer\n\
1481 counts, all windows on all frames that share that minibuffer count\n\
1482 too. Therefore, `next-window' can be used to iterate through the\n\
1483 set of windows even when the minibuffer is on another frame. If the\n\
1484 minibuffer does not count, only windows from WINDOW's frame count.\n\
1486 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1487 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1488 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1489 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1490 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1491 Anything else means restrict to WINDOW's frame.\n\
1493 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1494 `next-window' to iterate through the entire cycle of acceptable\n\
1495 windows, eventually ending up back at the window you started with.\n\
1496 `previous-window' traverses the same cycle, in the reverse order.")
1497 (window, minibuf, all_frames) */
1499 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1501 (window, minibuf, all_frames)
1502 Lisp_Object window, minibuf, all_frames;
1504 return next_window (window, minibuf, all_frames, 1);
1508 /* This comment supplies the doc string for `previous-window',
1509 for make-docfile to see. We cannot put this in the real DEFUN
1510 due to limits in the Unix cpp.
1512 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
1513 "Return the window preceding WINDOW in canonical ordering of windows.\n\
1514 If omitted, WINDOW defaults to the selected window.\n\
1516 Optional second arg MINIBUF t means count the minibuffer window even\n\
1517 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1518 it is active. MINIBUF neither t nor nil means not to count the\n\
1519 minibuffer even if it is active.\n\
1521 Several frames may share a single minibuffer; if the minibuffer\n\
1522 counts, all windows on all frames that share that minibuffer count\n\
1523 too. Therefore, `previous-window' can be used to iterate through\n\
1524 the set of windows even when the minibuffer is on another frame. If\n\
1525 the minibuffer does not count, only windows from WINDOW's frame count\n\
1527 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1528 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1529 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1530 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1531 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1532 Anything else means restrict to WINDOW's frame.\n\
1534 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1535 `previous-window' to iterate through the entire cycle of acceptable\n\
1536 windows, eventually ending up back at the window you started with.\n\
1537 `next-window' traverses the same cycle, in the reverse order.")
1538 (window, minibuf, all_frames) */
1541 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1543 (window, minibuf, all_frames)
1544 Lisp_Object window, minibuf, all_frames;
1546 return next_window (window, minibuf, all_frames, 0);
1550 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1551 "Select the ARG'th different window on this frame.\n\
1552 All windows on current frame are arranged in a cyclic order.\n\
1553 This command selects the window ARG steps away in that order.\n\
1554 A negative ARG moves in the opposite order. If the optional second\n\
1555 argument ALL_FRAMES is non-nil, cycle through all frames.")
1556 (arg, all_frames)
1557 Lisp_Object arg, all_frames;
1559 Lisp_Object window;
1560 int i;
1562 CHECK_NUMBER (arg, 0);
1563 window = selected_window;
1565 for (i = XINT (arg); i > 0; --i)
1566 window = Fnext_window (window, Qnil, all_frames);
1567 for (; i < 0; ++i)
1568 window = Fprevious_window (window, Qnil, all_frames);
1570 Fselect_window (window);
1571 return Qnil;
1575 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
1576 "Return a list of windows on FRAME, starting with WINDOW.\n\
1577 FRAME nil or omitted means use the selected frame.\n\
1578 WINDOW nil or omitted means use the selected window.\n\
1579 MINIBUF t means include the minibuffer window, even if it isn't active.\n\
1580 MINIBUF nil or omitted means include the minibuffer window only\n\
1581 if it's active.\n\
1582 MINIBUF neither nil nor t means never include the minibuffer window.")
1583 (frame, minibuf, window)
1584 Lisp_Object frame, minibuf, window;
1586 Lisp_Object list;
1588 if (NILP (window))
1589 window = selected_window;
1590 if (NILP (frame))
1591 frame = selected_frame;
1593 if (!EQ (frame, XWINDOW (window)->frame))
1594 error ("Window is on a different frame");
1596 return window_list_1 (window, minibuf, frame);
1600 /* Return a list of windows in canonical ordering. Arguments are like
1601 for `next-window'. */
1603 static Lisp_Object
1604 window_list_1 (window, minibuf, all_frames)
1605 Lisp_Object window, minibuf, all_frames;
1607 Lisp_Object tail, list;
1609 decode_next_window_args (&window, &minibuf, &all_frames);
1610 list = Qnil;
1612 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
1613 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
1614 list = Fcons (XCAR (tail), list);
1616 return Fnreverse (list);
1621 /* Look at all windows, performing an operation specified by TYPE
1622 with argument OBJ.
1623 If FRAMES is Qt, look at all frames;
1624 Qnil, look at just the selected frame;
1625 Qvisible, look at visible frames;
1626 a frame, just look at windows on that frame.
1627 If MINI is non-zero, perform the operation on minibuffer windows too.
1630 enum window_loop
1632 WINDOW_LOOP_UNUSED,
1633 GET_BUFFER_WINDOW, /* Arg is buffer */
1634 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1635 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1636 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1637 GET_LARGEST_WINDOW,
1638 UNSHOW_BUFFER, /* Arg is buffer */
1639 CHECK_ALL_WINDOWS
1642 static Lisp_Object
1643 window_loop (type, obj, mini, frames)
1644 enum window_loop type;
1645 Lisp_Object obj, frames;
1646 int mini;
1648 Lisp_Object window, windows, best_window, frame_arg;
1649 struct frame *f;
1650 struct gcpro gcpro1;
1652 /* If we're only looping through windows on a particular frame,
1653 frame points to that frame. If we're looping through windows
1654 on all frames, frame is 0. */
1655 if (FRAMEP (frames))
1656 f = XFRAME (frames);
1657 else if (NILP (frames))
1658 f = SELECTED_FRAME ();
1659 else
1660 f = NULL;
1662 if (f)
1663 frame_arg = Qlambda;
1664 else if (XFASTINT (frames) == 0)
1665 frame_arg = frames;
1666 else if (EQ (frames, Qvisible))
1667 frame_arg = frames;
1668 else
1669 frame_arg = Qt;
1671 /* frame_arg is Qlambda to stick to one frame,
1672 Qvisible to consider all visible frames,
1673 or Qt otherwise. */
1675 /* Pick a window to start with. */
1676 if (WINDOWP (obj))
1677 window = obj;
1678 else if (f)
1679 window = FRAME_SELECTED_WINDOW (f);
1680 else
1681 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1683 /* Figure out the last window we're going to mess with. Since
1684 Fnext_window, given the same options, is guaranteed to go in a
1685 ring, we can just use Fprevious_window to find the last one.
1687 We can't just wait until we hit the first window again, because
1688 it might be deleted. */
1690 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
1691 GCPRO1 (windows);
1692 best_window = Qnil;
1694 for (; CONSP (windows); windows = CDR (windows))
1696 struct window *w;
1698 window = XCAR (windows);
1699 w = XWINDOW (window);
1701 /* Note that we do not pay attention here to whether the frame
1702 is visible, since Fwindow_list skips non-visible frames if
1703 that is desired, under the control of frame_arg. */
1704 if (!MINI_WINDOW_P (w)
1705 /* For UNSHOW_BUFFER, we must always consider all windows. */
1706 || type == UNSHOW_BUFFER
1707 || (mini && minibuf_level > 0))
1708 switch (type)
1710 case GET_BUFFER_WINDOW:
1711 if (EQ (w->buffer, obj)
1712 /* Don't find any minibuffer window
1713 except the one that is currently in use. */
1714 && (MINI_WINDOW_P (w)
1715 ? EQ (window, minibuf_window)
1716 : 1))
1718 UNGCPRO;
1719 return window;
1721 break;
1723 case GET_LRU_WINDOW:
1724 /* t as arg means consider only full-width windows */
1725 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w))
1726 break;
1727 /* Ignore dedicated windows and minibuffers. */
1728 if (MINI_WINDOW_P (w) || !NILP (w->dedicated))
1729 break;
1730 if (NILP (best_window)
1731 || (XFASTINT (XWINDOW (best_window)->use_time)
1732 > XFASTINT (w->use_time)))
1733 best_window = window;
1734 break;
1736 case DELETE_OTHER_WINDOWS:
1737 if (!EQ (window, obj))
1738 Fdelete_window (window);
1739 break;
1741 case DELETE_BUFFER_WINDOWS:
1742 if (EQ (w->buffer, obj))
1744 struct frame *f = XFRAME (WINDOW_FRAME (w));
1746 /* If this window is dedicated, and in a frame of its own,
1747 kill the frame. */
1748 if (EQ (window, FRAME_ROOT_WINDOW (f))
1749 && !NILP (w->dedicated)
1750 && other_visible_frames (f))
1752 /* Skip the other windows on this frame.
1753 There might be one, the minibuffer! */
1754 while (CONSP (XCDR (windows))
1755 && EQ (XWINDOW (XCAR (windows))->frame,
1756 XWINDOW (XCAR (XCDR (windows)))->frame))
1757 windows = XCDR (windows);
1759 /* Now we can safely delete the frame. */
1760 Fdelete_frame (w->frame, Qnil);
1762 else if (NILP (w->parent))
1764 /* If we're deleting the buffer displayed in the
1765 only window on the frame, find a new buffer to
1766 display there. */
1767 Lisp_Object buffer;
1768 buffer = Fother_buffer (obj, Qnil, w->frame);
1769 if (NILP (buffer))
1770 buffer = Fget_buffer_create (build_string ("*scratch*"));
1771 Fset_window_buffer (window, buffer);
1772 if (EQ (window, selected_window))
1773 Fset_buffer (w->buffer);
1775 else
1776 Fdelete_window (window);
1778 break;
1780 case GET_LARGEST_WINDOW:
1782 /* Ignore dedicated windows and minibuffers. */
1783 if (MINI_WINDOW_P (w) || !NILP (w->dedicated))
1784 break;
1786 if (NILP (best_window))
1787 best_window = window;
1788 else
1790 struct window *b = XWINDOW (best_window);
1791 if (XFASTINT (w->height) * XFASTINT (w->width)
1792 > XFASTINT (b->height) * XFASTINT (b->width))
1793 best_window = window;
1796 break;
1798 case UNSHOW_BUFFER:
1799 if (EQ (w->buffer, obj))
1801 Lisp_Object buffer;
1802 struct frame *f = XFRAME (w->frame);
1804 /* Find another buffer to show in this window. */
1805 buffer = Fother_buffer (obj, Qnil, w->frame);
1806 if (NILP (buffer))
1807 buffer = Fget_buffer_create (build_string ("*scratch*"));
1809 /* If this window is dedicated, and in a frame of its own,
1810 kill the frame. */
1811 if (EQ (window, FRAME_ROOT_WINDOW (f))
1812 && !NILP (w->dedicated)
1813 && other_visible_frames (f))
1815 /* Skip the other windows on this frame.
1816 There might be one, the minibuffer! */
1817 while (CONSP (XCDR (windows))
1818 && EQ (XWINDOW (XCAR (windows))->frame,
1819 XWINDOW (XCAR (XCDR (windows)))->frame))
1820 windows = XCDR (windows);
1822 /* Now we can safely delete the frame. */
1823 Fdelete_frame (w->frame, Qnil);
1825 else
1827 /* Otherwise show a different buffer in the window. */
1828 w->dedicated = Qnil;
1829 Fset_window_buffer (window, buffer);
1830 if (EQ (window, selected_window))
1831 Fset_buffer (w->buffer);
1834 break;
1836 /* Check for a window that has a killed buffer. */
1837 case CHECK_ALL_WINDOWS:
1838 if (! NILP (w->buffer)
1839 && NILP (XBUFFER (w->buffer)->name))
1840 abort ();
1841 break;
1843 case WINDOW_LOOP_UNUSED:
1844 break;
1848 UNGCPRO;
1849 return best_window;
1852 /* Used for debugging. Abort if any window has a dead buffer. */
1854 void
1855 check_all_windows ()
1857 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
1860 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1861 "Return the window least recently selected or used for display.\n\
1862 If optional argument FRAME is `visible', search all visible frames.\n\
1863 If FRAME is 0, search all visible and iconified frames.\n\
1864 If FRAME is t, search all frames.\n\
1865 If FRAME is nil, search only the selected frame.\n\
1866 If FRAME is a frame, search only that frame.")
1867 (frame)
1868 Lisp_Object frame;
1870 register Lisp_Object w;
1871 /* First try for a window that is full-width */
1872 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
1873 if (!NILP (w) && !EQ (w, selected_window))
1874 return w;
1875 /* If none of them, try the rest */
1876 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
1879 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1880 "Return the largest window in area.\n\
1881 If optional argument FRAME is `visible', search all visible frames.\n\
1882 If FRAME is 0, search all visible and iconified frames.\n\
1883 If FRAME is t, search all frames.\n\
1884 If FRAME is nil, search only the selected frame.\n\
1885 If FRAME is a frame, search only that frame.")
1886 (frame)
1887 Lisp_Object frame;
1889 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
1890 frame);
1893 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1894 "Return a window currently displaying BUFFER, or nil if none.\n\
1895 If optional argument FRAME is `visible', search all visible frames.\n\
1896 If optional argument FRAME is 0, search all visible and iconified frames.\n\
1897 If FRAME is t, search all frames.\n\
1898 If FRAME is nil, search only the selected frame.\n\
1899 If FRAME is a frame, search only that frame.")
1900 (buffer, frame)
1901 Lisp_Object buffer, frame;
1903 buffer = Fget_buffer (buffer);
1904 if (BUFFERP (buffer))
1905 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
1906 else
1907 return Qnil;
1910 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1911 0, 1, "",
1912 "Make WINDOW (or the selected window) fill its frame.\n\
1913 Only the frame WINDOW is on is affected.\n\
1914 This function tries to reduce display jumps\n\
1915 by keeping the text previously visible in WINDOW\n\
1916 in the same place on the frame. Doing this depends on\n\
1917 the value of (window-start WINDOW), so if calling this function\n\
1918 in a program gives strange scrolling, make sure the window-start\n\
1919 value is reasonable when this function is called.")
1920 (window)
1921 Lisp_Object window;
1923 struct window *w;
1924 int startpos;
1925 int top;
1927 if (NILP (window))
1928 window = selected_window;
1929 else
1930 CHECK_LIVE_WINDOW (window, 0);
1932 w = XWINDOW (window);
1934 startpos = marker_position (w->start);
1935 top = XFASTINT (w->top) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
1937 if (MINI_WINDOW_P (w) && top > 0)
1938 error ("Can't expand minibuffer to full frame");
1940 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
1942 /* Try to minimize scrolling, by setting the window start to the point
1943 will cause the text at the old window start to be at the same place
1944 on the frame. But don't try to do this if the window start is
1945 outside the visible portion (as might happen when the display is
1946 not current, due to typeahead). */
1947 if (startpos >= BUF_BEGV (XBUFFER (w->buffer))
1948 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
1950 struct position pos;
1951 struct buffer *obuf = current_buffer;
1953 Fset_buffer (w->buffer);
1954 /* This computation used to temporarily move point, but that can
1955 have unwanted side effects due to text properties. */
1956 pos = *vmotion (startpos, -top, w);
1958 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
1959 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
1960 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
1961 : Qnil);
1962 /* We need to do this, so that the window-scroll-functions
1963 get called. */
1964 w->optional_new_start = Qt;
1966 set_buffer_internal (obuf);
1969 return Qnil;
1972 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1973 1, 2, "bDelete windows on (buffer): ",
1974 "Delete all windows showing BUFFER.\n\
1975 Optional second argument FRAME controls which frames are affected.\n\
1976 If optional argument FRAME is `visible', search all visible frames.\n\
1977 If FRAME is 0, search all visible and iconified frames.\n\
1978 If FRAME is nil, search all frames.\n\
1979 If FRAME is t, search only the selected frame.\n\
1980 If FRAME is a frame, search only that frame.")
1981 (buffer, frame)
1982 Lisp_Object buffer, frame;
1984 /* FRAME uses t and nil to mean the opposite of what window_loop
1985 expects. */
1986 if (NILP (frame))
1987 frame = Qt;
1988 else if (EQ (frame, Qt))
1989 frame = Qnil;
1991 if (!NILP (buffer))
1993 buffer = Fget_buffer (buffer);
1994 CHECK_BUFFER (buffer, 0);
1995 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
1998 return Qnil;
2001 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
2002 Sreplace_buffer_in_windows,
2003 1, 1, "bReplace buffer in windows: ",
2004 "Replace BUFFER with some other buffer in all windows showing it.")
2005 (buffer)
2006 Lisp_Object buffer;
2008 if (!NILP (buffer))
2010 buffer = Fget_buffer (buffer);
2011 CHECK_BUFFER (buffer, 0);
2012 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
2014 return Qnil;
2017 /* Replace BUFFER with some other buffer in all windows
2018 of all frames, even those on other keyboards. */
2020 void
2021 replace_buffer_in_all_windows (buffer)
2022 Lisp_Object buffer;
2024 #ifdef MULTI_KBOARD
2025 Lisp_Object tail, frame;
2027 /* A single call to window_loop won't do the job
2028 because it only considers frames on the current keyboard.
2029 So loop manually over frames, and handle each one. */
2030 FOR_EACH_FRAME (tail, frame)
2031 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
2032 #else
2033 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
2034 #endif
2037 /* Set the height of WINDOW and all its inferiors. */
2039 /* The smallest acceptable dimensions for a window. Anything smaller
2040 might crash Emacs. */
2042 #define MIN_SAFE_WINDOW_WIDTH (2)
2043 #define MIN_SAFE_WINDOW_HEIGHT (2)
2045 /* Make sure that window_min_height and window_min_width are
2046 not too small; if they are, set them to safe minima. */
2048 static void
2049 check_min_window_sizes ()
2051 /* Smaller values might permit a crash. */
2052 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
2053 window_min_width = MIN_SAFE_WINDOW_WIDTH;
2054 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
2055 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
2058 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2059 minimum allowable size. */
2061 void
2062 check_frame_size (frame, rows, cols)
2063 FRAME_PTR frame;
2064 int *rows, *cols;
2066 /* For height, we have to see:
2067 whether the frame has a minibuffer,
2068 whether it wants a mode line, and
2069 whether it has a menu bar. */
2070 int min_height =
2071 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
2072 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
2073 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
2075 if (FRAME_TOP_MARGIN (frame) > 0)
2076 min_height += FRAME_TOP_MARGIN (frame);
2078 if (*rows < min_height)
2079 *rows = min_height;
2080 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2081 *cols = MIN_SAFE_WINDOW_WIDTH;
2085 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
2086 check if W's width can be changed, otherwise check W's height.
2087 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
2088 siblings, too. If none of the siblings is resizable, WINDOW isn't
2089 either. */
2091 static int
2092 window_fixed_size_p (w, width_p, check_siblings_p)
2093 struct window *w;
2094 int width_p, check_siblings_p;
2096 int fixed_p;
2097 struct window *c;
2099 if (!NILP (w->hchild))
2101 c = XWINDOW (w->hchild);
2103 if (width_p)
2105 /* A horiz. combination is fixed-width if all of if its
2106 children are. */
2107 while (c && window_fixed_size_p (c, width_p, 0))
2108 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2109 fixed_p = c == NULL;
2111 else
2113 /* A horiz. combination is fixed-height if one of if its
2114 children is. */
2115 while (c && !window_fixed_size_p (c, width_p, 0))
2116 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2117 fixed_p = c != NULL;
2120 else if (!NILP (w->vchild))
2122 c = XWINDOW (w->vchild);
2124 if (width_p)
2126 /* A vert. combination is fixed-width if one of if its
2127 children is. */
2128 while (c && !window_fixed_size_p (c, width_p, 0))
2129 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2130 fixed_p = c != NULL;
2132 else
2134 /* A vert. combination is fixed-height if all of if its
2135 children are. */
2136 while (c && window_fixed_size_p (c, width_p, 0))
2137 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2138 fixed_p = c == NULL;
2141 else if (BUFFERP (w->buffer))
2143 if (w->height_fixed_p && !width_p)
2144 fixed_p = 1;
2145 else
2147 struct buffer *old = current_buffer;
2148 Lisp_Object val;
2150 current_buffer = XBUFFER (w->buffer);
2151 val = find_symbol_value (Qwindow_size_fixed);
2152 current_buffer = old;
2154 fixed_p = 0;
2155 if (!EQ (val, Qunbound))
2157 fixed_p = !NILP (val);
2159 if (fixed_p
2160 && ((EQ (val, Qheight) && width_p)
2161 || (EQ (val, Qwidth) && !width_p)))
2162 fixed_p = 0;
2166 /* Can't tell if this one is resizable without looking at
2167 siblings. If all siblings are fixed-size this one is too. */
2168 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2170 Lisp_Object child;
2172 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2173 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2174 break;
2176 if (NILP (child))
2177 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2178 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2179 break;
2181 if (NILP (child))
2182 fixed_p = 1;
2185 else
2186 fixed_p = 1;
2188 return fixed_p;
2192 /* Return the minimum size of window W, not taking fixed-width windows
2193 into account. WIDTH_P non-zero means return the minimum width,
2194 otherwise return the minimum height. If W is a combination window,
2195 compute the minimum size from the minimum sizes of W's children. */
2197 static int
2198 window_min_size_1 (w, width_p)
2199 struct window *w;
2200 int width_p;
2202 struct window *c;
2203 int size;
2205 if (!NILP (w->hchild))
2207 c = XWINDOW (w->hchild);
2208 size = 0;
2210 if (width_p)
2212 /* The min width of a horizontal combination is
2213 the sum of the min widths of its children. */
2214 while (c)
2216 size += window_min_size_1 (c, width_p);
2217 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2220 else
2222 /* The min height a horizontal combination equals
2223 the maximum of all min height of its children. */
2224 while (c)
2226 int min_size = window_min_size_1 (c, width_p);
2227 size = max (min_size, size);
2228 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2232 else if (!NILP (w->vchild))
2234 c = XWINDOW (w->vchild);
2235 size = 0;
2237 if (width_p)
2239 /* The min width of a vertical combination is
2240 the maximum of the min widths of its children. */
2241 while (c)
2243 int min_size = window_min_size_1 (c, width_p);
2244 size = max (min_size, size);
2245 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2248 else
2250 /* The min height of a vertical combination equals
2251 the sum of the min height of its children. */
2252 while (c)
2254 size += window_min_size_1 (c, width_p);
2255 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2259 else
2261 if (width_p)
2262 size = window_min_width;
2263 else
2265 if (MINI_WINDOW_P (w)
2266 || (!WINDOW_WANTS_MODELINE_P (w)
2267 && !WINDOW_WANTS_HEADER_LINE_P (w)))
2268 size = 1;
2269 else
2270 size = window_min_height;
2274 return size;
2278 /* Return the minimum size of window W, taking fixed-size windows into
2279 account. WIDTH_P non-zero means return the minimum width,
2280 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2281 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2282 unless FIXED is null. */
2284 static int
2285 window_min_size (w, width_p, ignore_fixed_p, fixed)
2286 struct window *w;
2287 int width_p, ignore_fixed_p, *fixed;
2289 int size, fixed_p;
2291 if (ignore_fixed_p)
2292 fixed_p = 0;
2293 else
2294 fixed_p = window_fixed_size_p (w, width_p, 1);
2296 if (fixed)
2297 *fixed = fixed_p;
2299 if (fixed_p)
2300 size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
2301 else
2302 size = window_min_size_1 (w, width_p);
2304 return size;
2308 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2309 WINDOW's width. Resize WINDOW's children, if any, so that they
2310 keep their proportionate size relative to WINDOW. Propagate
2311 WINDOW's top or left edge position to children. Delete windows
2312 that become too small unless NODELETE_P is non-zero. */
2314 static void
2315 size_window (window, size, width_p, nodelete_p)
2316 Lisp_Object window;
2317 int size, width_p, nodelete_p;
2319 struct window *w = XWINDOW (window);
2320 struct window *c;
2321 Lisp_Object child, *forward, *sideward;
2322 int old_size, min_size;
2324 check_min_window_sizes ();
2325 size = max (0, size);
2327 /* If the window has been "too small" at one point,
2328 don't delete it for being "too small" in the future.
2329 Preserve it as long as that is at all possible. */
2330 if (width_p)
2332 old_size = XINT (w->width);
2333 min_size = window_min_width;
2335 else
2337 old_size = XINT (w->height);
2338 min_size = window_min_height;
2341 if (old_size < window_min_width)
2342 w->too_small_ok = Qt;
2344 /* Maybe delete WINDOW if it's too small. */
2345 if (!nodelete_p && !NILP (w->parent))
2347 int min_size;
2349 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
2350 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
2351 else
2352 min_size = width_p ? window_min_width : window_min_height;
2354 if (size < min_size)
2356 delete_window (window);
2357 return;
2361 /* Set redisplay hints. */
2362 w->last_modified = make_number (0);
2363 w->last_overlay_modified = make_number (0);
2364 windows_or_buffers_changed++;
2365 FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
2367 if (width_p)
2369 sideward = &w->vchild;
2370 forward = &w->hchild;
2371 w->width = make_number (size);
2373 else
2375 sideward = &w->hchild;
2376 forward = &w->vchild;
2377 w->height = make_number (size);
2380 if (!NILP (*sideward))
2382 for (child = *sideward; !NILP (child); child = c->next)
2384 c = XWINDOW (child);
2385 if (width_p)
2386 c->left = w->left;
2387 else
2388 c->top = w->top;
2389 size_window (child, size, width_p, nodelete_p);
2392 else if (!NILP (*forward))
2394 int fixed_size, each, extra, n;
2395 int resize_fixed_p, nfixed;
2396 int last_pos, first_pos, nchildren, total;
2398 /* Determine the fixed-size portion of the this window, and the
2399 number of child windows. */
2400 fixed_size = nchildren = nfixed = total = 0;
2401 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
2403 int child_size;
2405 c = XWINDOW (child);
2406 child_size = width_p ? XINT (c->width) : XINT (c->height);
2407 total += child_size;
2409 if (window_fixed_size_p (c, width_p, 0))
2411 fixed_size += child_size;
2412 ++nfixed;
2416 /* If the new size is smaller than fixed_size, or if there
2417 aren't any resizable windows, allow resizing fixed-size
2418 windows. */
2419 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2421 /* Compute how many lines/columns to add to each child. The
2422 value of extra takes care of rounding errors. */
2423 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2424 each = (size - total) / n;
2425 extra = (size - total) - n * each;
2427 /* Compute new children heights and edge positions. */
2428 first_pos = width_p ? XINT (w->left) : XINT (w->top);
2429 last_pos = first_pos;
2430 for (child = *forward; !NILP (child); child = c->next)
2432 int new_size, old_size;
2434 c = XWINDOW (child);
2435 old_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2436 new_size = old_size;
2438 /* The top or left edge position of this child equals the
2439 bottom or right edge of its predecessor. */
2440 if (width_p)
2441 c->left = make_number (last_pos);
2442 else
2443 c->top = make_number (last_pos);
2445 /* If this child can be resized, do it. */
2446 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2448 new_size = old_size + each + extra;
2449 extra = 0;
2452 /* Set new height. Note that size_window also propagates
2453 edge positions to children, so it's not a no-op if we
2454 didn't change the child's size. */
2455 size_window (child, new_size, width_p, 1);
2457 /* Remember the bottom/right edge position of this child; it
2458 will be used to set the top/left edge of the next child. */
2459 last_pos += new_size;
2462 /* We should have covered the parent exactly with child windows. */
2463 xassert (size == last_pos - first_pos);
2465 /* Now delete any children that became too small. */
2466 if (!nodelete_p)
2467 for (child = *forward; !NILP (child); child = c->next)
2469 int child_size;
2470 c = XWINDOW (child);
2471 child_size = width_p ? XINT (c->width) : XINT (c->height);
2472 size_window (child, child_size, width_p, 0);
2477 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2478 WINDOW's children. NODELETE non-zero means don't delete windows
2479 that become too small in the process. (The caller should check
2480 later and do so if appropriate.) */
2482 void
2483 set_window_height (window, height, nodelete)
2484 Lisp_Object window;
2485 int height;
2486 int nodelete;
2488 size_window (window, height, 0, nodelete);
2492 /* Set WINDOW's width to WIDTH, and recursively change the width of
2493 WINDOW's children. NODELETE non-zero means don't delete windows
2494 that become too small in the process. (The caller should check
2495 later and do so if appropriate.) */
2497 void
2498 set_window_width (window, width, nodelete)
2499 Lisp_Object window;
2500 int width;
2501 int nodelete;
2503 size_window (window, width, 1, nodelete);
2507 int window_select_count;
2509 Lisp_Object
2510 Fset_window_buffer_unwind (obuf)
2511 Lisp_Object obuf;
2513 Fset_buffer (obuf);
2514 return Qnil;
2518 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2519 means it's allowed to run hooks. See make_frame for a case where
2520 it's not allowed. */
2522 void
2523 set_window_buffer (window, buffer, run_hooks_p)
2524 Lisp_Object window, buffer;
2525 int run_hooks_p;
2527 struct window *w = XWINDOW (window);
2528 struct buffer *b = XBUFFER (buffer);
2529 int count = specpdl_ptr - specpdl;
2531 w->buffer = buffer;
2533 if (EQ (window, selected_window))
2534 b->last_selected_window = window;
2536 /* Update time stamps of buffer display. */
2537 if (INTEGERP (b->display_count))
2538 XSETINT (b->display_count, XINT (b->display_count) + 1);
2539 b->display_time = Fcurrent_time ();
2541 XSETFASTINT (w->window_end_pos, 0);
2542 XSETFASTINT (w->window_end_vpos, 0);
2543 bzero (&w->last_cursor, sizeof w->last_cursor);
2544 w->window_end_valid = Qnil;
2545 XSETFASTINT (w->hscroll, 0);
2546 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
2547 set_marker_restricted (w->start,
2548 make_number (b->last_window_start),
2549 buffer);
2550 w->start_at_line_beg = Qnil;
2551 w->force_start = Qnil;
2552 XSETFASTINT (w->last_modified, 0);
2553 XSETFASTINT (w->last_overlay_modified, 0);
2554 windows_or_buffers_changed++;
2556 /* We must select BUFFER for running the window-scroll-functions.
2557 If WINDOW is selected, switch permanently.
2558 Otherwise, switch but go back to the ambient buffer afterward. */
2559 if (EQ (window, selected_window))
2560 Fset_buffer (buffer);
2561 /* We can't check ! NILP (Vwindow_scroll_functions) here
2562 because that might itself be a local variable. */
2563 else if (window_initialized)
2565 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2566 Fset_buffer (buffer);
2569 /* Set left and right marginal area width from buffer. */
2570 Fset_window_margins (window, b->left_margin_width, b->right_margin_width);
2572 if (run_hooks_p)
2574 if (! NILP (Vwindow_scroll_functions))
2575 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2576 Fmarker_position (w->start));
2578 if (! NILP (Vwindow_configuration_change_hook)
2579 && ! NILP (Vrun_hooks))
2580 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2583 unbind_to (count, Qnil);
2587 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
2588 "Make WINDOW display BUFFER as its contents.\n\
2589 BUFFER can be a buffer or buffer name.")
2590 (window, buffer)
2591 register Lisp_Object window, buffer;
2593 register Lisp_Object tem;
2594 register struct window *w = decode_window (window);
2596 XSETWINDOW (window, w);
2597 buffer = Fget_buffer (buffer);
2598 CHECK_BUFFER (buffer, 1);
2600 if (NILP (XBUFFER (buffer)->name))
2601 error ("Attempt to display deleted buffer");
2603 tem = w->buffer;
2604 if (NILP (tem))
2605 error ("Window is deleted");
2606 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
2607 is first being set up. */
2609 if (!NILP (w->dedicated) && !EQ (tem, buffer))
2610 error ("Window is dedicated to `%s'",
2611 XSTRING (XBUFFER (tem)->name)->data);
2613 unshow_buffer (w);
2616 set_window_buffer (window, buffer, 1);
2617 return Qnil;
2620 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
2621 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
2622 If WINDOW is not already selected, also make WINDOW's buffer current.\n\
2623 Note that the main editor command loop\n\
2624 selects the buffer of the selected window before each command.")
2625 (window)
2626 register Lisp_Object window;
2628 return select_window_1 (window, 1);
2631 /* Note that selected_window can be nil
2632 when this is called from Fset_window_configuration. */
2634 static Lisp_Object
2635 select_window_1 (window, recordflag)
2636 register Lisp_Object window;
2637 int recordflag;
2639 register struct window *w;
2640 register struct window *ow;
2641 struct frame *sf;
2643 CHECK_LIVE_WINDOW (window, 0);
2645 w = XWINDOW (window);
2647 if (NILP (w->buffer))
2648 error ("Trying to select deleted window or non-leaf window");
2650 XSETFASTINT (w->use_time, ++window_select_count);
2651 if (EQ (window, selected_window))
2652 return window;
2654 if (!NILP (selected_window))
2656 ow = XWINDOW (selected_window);
2657 if (! NILP (ow->buffer))
2658 set_marker_both (ow->pointm, ow->buffer,
2659 BUF_PT (XBUFFER (ow->buffer)),
2660 BUF_PT_BYTE (XBUFFER (ow->buffer)));
2663 selected_window = window;
2664 sf = SELECTED_FRAME ();
2665 if (XFRAME (WINDOW_FRAME (w)) != sf)
2667 XFRAME (WINDOW_FRAME (w))->selected_window = window;
2668 /* Use this rather than Fhandle_switch_frame
2669 so that FRAME_FOCUS_FRAME is moved appropriately as we
2670 move around in the state where a minibuffer in a separate
2671 frame is active. */
2672 Fselect_frame (WINDOW_FRAME (w), Qnil);
2674 else
2675 sf->selected_window = window;
2677 if (recordflag)
2678 record_buffer (w->buffer);
2679 Fset_buffer (w->buffer);
2681 XBUFFER (w->buffer)->last_selected_window = window;
2683 /* Go to the point recorded in the window.
2684 This is important when the buffer is in more
2685 than one window. It also matters when
2686 redisplay_window has altered point after scrolling,
2687 because it makes the change only in the window. */
2689 register int new_point = marker_position (w->pointm);
2690 if (new_point < BEGV)
2691 SET_PT (BEGV);
2692 else if (new_point > ZV)
2693 SET_PT (ZV);
2694 else
2695 SET_PT (new_point);
2698 windows_or_buffers_changed++;
2699 return window;
2702 /* Deiconify the frame containing the window WINDOW,
2703 unless it is the selected frame;
2704 then return WINDOW.
2706 The reason for the exception for the selected frame
2707 is that it seems better not to change the selected frames visibility
2708 merely because of displaying a different buffer in it.
2709 The deiconification is useful when a buffer gets shown in
2710 another frame that you were not using lately. */
2712 static Lisp_Object
2713 display_buffer_1 (window)
2714 Lisp_Object window;
2716 Lisp_Object frame = XWINDOW (window)->frame;
2717 FRAME_PTR f = XFRAME (frame);
2719 FRAME_SAMPLE_VISIBILITY (f);
2721 if (!EQ (frame, selected_frame))
2723 if (FRAME_ICONIFIED_P (f))
2724 Fmake_frame_visible (frame);
2725 else if (FRAME_VISIBLE_P (f))
2726 Fraise_frame (frame);
2729 return window;
2732 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
2733 "Returns non-nil if a buffer named BUFFER-NAME would be created specially.\n\
2734 The value is actually t if the frame should be called with default frame\n\
2735 parameters, and a list of frame parameters if they were specified.\n\
2736 See `special-display-buffer-names', and `special-display-regexps'.")
2737 (buffer_name)
2738 Lisp_Object buffer_name;
2740 Lisp_Object tem;
2742 CHECK_STRING (buffer_name, 1);
2744 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2745 if (!NILP (tem))
2746 return Qt;
2748 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2749 if (!NILP (tem))
2750 return XCDR (tem);
2752 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2754 Lisp_Object car = XCAR (tem);
2755 if (STRINGP (car)
2756 && fast_string_match (car, buffer_name) >= 0)
2757 return Qt;
2758 else if (CONSP (car)
2759 && STRINGP (XCAR (car))
2760 && fast_string_match (XCAR (car), buffer_name) >= 0)
2761 return XCDR (car);
2763 return Qnil;
2766 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
2767 "Returns non-nil if a new buffer named BUFFER-NAME would use the same window.\n\
2768 See `same-window-buffer-names' and `same-window-regexps'.")
2769 (buffer_name)
2770 Lisp_Object buffer_name;
2772 Lisp_Object tem;
2774 CHECK_STRING (buffer_name, 1);
2776 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2777 if (!NILP (tem))
2778 return Qt;
2780 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2781 if (!NILP (tem))
2782 return Qt;
2784 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
2786 Lisp_Object car = XCAR (tem);
2787 if (STRINGP (car)
2788 && fast_string_match (car, buffer_name) >= 0)
2789 return Qt;
2790 else if (CONSP (car)
2791 && STRINGP (XCAR (car))
2792 && fast_string_match (XCAR (car), buffer_name) >= 0)
2793 return Qt;
2795 return Qnil;
2798 /* Use B so the default is (other-buffer). */
2799 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
2800 "BDisplay buffer: \nP",
2801 "Make BUFFER appear in some window but don't select it.\n\
2802 BUFFER can be a buffer or a buffer name.\n\
2803 If BUFFER is shown already in some window, just use that one,\n\
2804 unless the window is the selected window and the optional second\n\
2805 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
2806 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
2807 Returns the window displaying BUFFER.\n\
2808 If `display-reuse-frames' is non-nil, and another frame is currently\n\
2809 displaying BUFFER, then simply raise that frame.\n\
2811 The variables `special-display-buffer-names', `special-display-regexps',\n\
2812 `same-window-buffer-names', and `same-window-regexps' customize how certain\n\
2813 buffer names are handled.\n\
2815 If optional argument FRAME is `visible', search all visible frames.\n\
2816 If FRAME is 0, search all visible and iconified frames.\n\
2817 If FRAME is t, search all frames.\n\
2818 If FRAME is a frame, search only that frame.\n\
2819 If FRAME is nil, search only the selected frame\n\
2820 (actually the last nonminibuffer frame),\n\
2821 unless `pop-up-frames' or `display-buffer-reuse-frames' is non-nil,\n\
2822 which means search visible and iconified frames.")
2823 (buffer, not_this_window, frame)
2824 register Lisp_Object buffer, not_this_window, frame;
2826 register Lisp_Object window, tem, swp;
2827 struct frame *f;
2829 swp = Qnil;
2830 buffer = Fget_buffer (buffer);
2831 CHECK_BUFFER (buffer, 0);
2833 if (!NILP (Vdisplay_buffer_function))
2834 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
2836 if (NILP (not_this_window)
2837 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
2838 return display_buffer_1 (selected_window);
2840 /* See if the user has specified this buffer should appear
2841 in the selected window. */
2842 if (NILP (not_this_window))
2844 swp = Fsame_window_p (XBUFFER (buffer)->name);
2845 if (!NILP (swp) && !no_switch_window (selected_window))
2847 Fswitch_to_buffer (buffer, Qnil);
2848 return display_buffer_1 (selected_window);
2852 /* If the user wants pop-up-frames or display-reuse-frames, then
2853 look for a window showing BUFFER on any visible or iconified frame.
2854 Otherwise search only the current frame. */
2855 if (! NILP (frame))
2856 tem = frame;
2857 else if (pop_up_frames
2858 || display_buffer_reuse_frames
2859 || last_nonminibuf_frame == 0)
2860 XSETFASTINT (tem, 0);
2861 else
2862 XSETFRAME (tem, last_nonminibuf_frame);
2864 window = Fget_buffer_window (buffer, tem);
2865 if (!NILP (window)
2866 && (NILP (not_this_window) || !EQ (window, selected_window)))
2867 return display_buffer_1 (window);
2869 /* Certain buffer names get special handling. */
2870 if (!NILP (Vspecial_display_function) && NILP (swp))
2872 tem = Fspecial_display_p (XBUFFER (buffer)->name);
2873 if (EQ (tem, Qt))
2874 return call1 (Vspecial_display_function, buffer);
2875 if (CONSP (tem))
2876 return call2 (Vspecial_display_function, buffer, tem);
2879 /* If there are no frames open that have more than a minibuffer,
2880 we need to create a new frame. */
2881 if (pop_up_frames || last_nonminibuf_frame == 0)
2883 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2884 Fset_window_buffer (window, buffer);
2885 return display_buffer_1 (window);
2888 f = SELECTED_FRAME ();
2889 if (pop_up_windows
2890 || FRAME_MINIBUF_ONLY_P (f)
2891 /* If the current frame is a special display frame,
2892 don't try to reuse its windows. */
2893 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
2895 Lisp_Object frames;
2897 frames = Qnil;
2898 if (FRAME_MINIBUF_ONLY_P (f))
2899 XSETFRAME (frames, last_nonminibuf_frame);
2900 /* Don't try to create a window if would get an error */
2901 if (split_height_threshold < window_min_height << 1)
2902 split_height_threshold = window_min_height << 1;
2904 /* Note that both Fget_largest_window and Fget_lru_window
2905 ignore minibuffers and dedicated windows.
2906 This means they can return nil. */
2908 /* If the frame we would try to split cannot be split,
2909 try other frames. */
2910 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
2912 /* Try visible frames first. */
2913 window = Fget_largest_window (Qvisible);
2914 /* If that didn't work, try iconified frames. */
2915 if (NILP (window))
2916 window = Fget_largest_window (make_number (0));
2917 if (NILP (window))
2918 window = Fget_largest_window (Qt);
2920 else
2921 window = Fget_largest_window (frames);
2923 /* If we got a tall enough full-width window that can be split,
2924 split it. */
2925 if (!NILP (window)
2926 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2927 && window_height (window) >= split_height_threshold
2928 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
2929 window = Fsplit_window (window, Qnil, Qnil);
2930 else
2932 Lisp_Object upper, lower, other;
2934 window = Fget_lru_window (frames);
2935 /* If the LRU window is selected, and big enough,
2936 and can be split, split it. */
2937 if (!NILP (window)
2938 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2939 && (EQ (window, selected_window)
2940 || EQ (XWINDOW (window)->parent, Qnil))
2941 && window_height (window) >= window_min_height << 1)
2942 window = Fsplit_window (window, Qnil, Qnil);
2943 /* If Fget_lru_window returned nil, try other approaches. */
2945 /* Try visible frames first. */
2946 if (NILP (window))
2947 window = Fget_buffer_window (buffer, Qvisible);
2948 if (NILP (window))
2949 window = Fget_largest_window (Qvisible);
2950 /* If that didn't work, try iconified frames. */
2951 if (NILP (window))
2952 window = Fget_buffer_window (buffer, make_number (0));
2953 if (NILP (window))
2954 window = Fget_largest_window (make_number (0));
2955 /* Try invisible frames. */
2956 if (NILP (window))
2957 window = Fget_buffer_window (buffer, Qt);
2958 if (NILP (window))
2959 window = Fget_largest_window (Qt);
2960 /* As a last resort, make a new frame. */
2961 if (NILP (window))
2962 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2963 /* If window appears above or below another,
2964 even out their heights. */
2965 other = upper = lower = Qnil;
2966 if (!NILP (XWINDOW (window)->prev))
2967 other = upper = XWINDOW (window)->prev, lower = window;
2968 if (!NILP (XWINDOW (window)->next))
2969 other = lower = XWINDOW (window)->next, upper = window;
2970 if (!NILP (other)
2971 /* Check that OTHER and WINDOW are vertically arrayed. */
2972 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
2973 && (XFASTINT (XWINDOW (other)->height)
2974 > XFASTINT (XWINDOW (window)->height)))
2976 int total = (XFASTINT (XWINDOW (other)->height)
2977 + XFASTINT (XWINDOW (window)->height));
2978 enlarge_window (upper,
2979 total / 2 - XFASTINT (XWINDOW (upper)->height),
2984 else
2985 window = Fget_lru_window (Qnil);
2987 Fset_window_buffer (window, buffer);
2988 return display_buffer_1 (window);
2991 void
2992 temp_output_buffer_show (buf)
2993 register Lisp_Object buf;
2995 register struct buffer *old = current_buffer;
2996 register Lisp_Object window;
2997 register struct window *w;
2999 XBUFFER (buf)->directory = current_buffer->directory;
3001 Fset_buffer (buf);
3002 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3003 BEGV = BEG;
3004 ZV = Z;
3005 SET_PT (BEG);
3006 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
3007 set_buffer_internal (old);
3009 if (!EQ (Vtemp_buffer_show_function, Qnil))
3010 call1 (Vtemp_buffer_show_function, buf);
3011 else
3013 window = Fdisplay_buffer (buf, Qnil, Qnil);
3015 if (!EQ (XWINDOW (window)->frame, selected_frame))
3016 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3017 Vminibuf_scroll_window = window;
3018 w = XWINDOW (window);
3019 XSETFASTINT (w->hscroll, 0);
3020 set_marker_restricted_both (w->start, buf, 1, 1);
3021 set_marker_restricted_both (w->pointm, buf, 1, 1);
3023 /* Run temp-buffer-show-hook, with the chosen window selected
3024 and it sbuffer current. */
3025 if (!NILP (Vrun_hooks))
3027 Lisp_Object tem;
3028 tem = Fboundp (Qtemp_buffer_show_hook);
3029 if (!NILP (tem))
3031 tem = Fsymbol_value (Qtemp_buffer_show_hook);
3032 if (!NILP (tem))
3034 int count = specpdl_ptr - specpdl;
3035 Lisp_Object prev_window;
3036 prev_window = selected_window;
3038 /* Select the window that was chosen, for running the hook. */
3039 record_unwind_protect (Fselect_window, prev_window);
3040 select_window_1 (window, 0);
3041 Fset_buffer (w->buffer);
3042 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
3043 select_window_1 (prev_window, 0);
3044 unbind_to (count, Qnil);
3051 static void
3052 make_dummy_parent (window)
3053 Lisp_Object window;
3055 Lisp_Object new;
3056 register struct window *o, *p;
3057 register struct Lisp_Vector *vec;
3058 int i;
3060 o = XWINDOW (window);
3061 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
3062 for (i = 0; i < VECSIZE (struct window); ++i)
3063 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
3064 vec->size = VECSIZE (struct window);
3065 p = (struct window *)vec;
3066 XSETWINDOW (new, p);
3068 XSETFASTINT (p->sequence_number, ++sequence_number);
3070 /* Put new into window structure in place of window */
3071 replace_window (window, new);
3073 o->next = Qnil;
3074 o->prev = Qnil;
3075 o->vchild = Qnil;
3076 o->hchild = Qnil;
3077 o->parent = new;
3079 p->start = Qnil;
3080 p->pointm = Qnil;
3081 p->buffer = Qnil;
3084 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
3085 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
3086 WINDOW defaults to selected one and SIZE to half its size.\n\
3087 If optional third arg HORFLAG is non-nil, split side by side\n\
3088 and put SIZE columns in the first of the pair. In that case,\n\
3089 SIZE includes that window's scroll bar, or the divider column to its right.")
3090 (window, size, horflag)
3091 Lisp_Object window, size, horflag;
3093 register Lisp_Object new;
3094 register struct window *o, *p;
3095 FRAME_PTR fo;
3096 register int size_int;
3098 if (NILP (window))
3099 window = selected_window;
3100 else
3101 CHECK_LIVE_WINDOW (window, 0);
3103 o = XWINDOW (window);
3104 fo = XFRAME (WINDOW_FRAME (o));
3106 if (NILP (size))
3108 if (!NILP (horflag))
3109 /* Calculate the size of the left-hand window, by dividing
3110 the usable space in columns by two.
3111 We round up, since the left-hand window may include
3112 a dividing line, while the right-hand may not. */
3113 size_int = (XFASTINT (o->width) + 1) >> 1;
3114 else
3115 size_int = XFASTINT (o->height) >> 1;
3117 else
3119 CHECK_NUMBER (size, 1);
3120 size_int = XINT (size);
3123 if (MINI_WINDOW_P (o))
3124 error ("Attempt to split minibuffer window");
3125 else if (window_fixed_size_p (o, !NILP (horflag), 0))
3126 error ("Attempt to split fixed-size window");
3128 check_min_window_sizes ();
3130 if (NILP (horflag))
3132 if (size_int < window_min_height)
3133 error ("Window height %d too small (after splitting)", size_int);
3134 if (size_int + window_min_height > XFASTINT (o->height))
3135 error ("Window height %d too small (after splitting)",
3136 XFASTINT (o->height) - size_int);
3137 if (NILP (o->parent)
3138 || NILP (XWINDOW (o->parent)->vchild))
3140 make_dummy_parent (window);
3141 new = o->parent;
3142 XWINDOW (new)->vchild = window;
3145 else
3147 if (size_int < window_min_width)
3148 error ("Window width %d too small (after splitting)", size_int);
3150 if (size_int + window_min_width > XFASTINT (o->width))
3151 error ("Window width %d too small (after splitting)",
3152 XFASTINT (o->width) - size_int);
3153 if (NILP (o->parent)
3154 || NILP (XWINDOW (o->parent)->hchild))
3156 make_dummy_parent (window);
3157 new = o->parent;
3158 XWINDOW (new)->hchild = window;
3162 /* Now we know that window's parent is a vertical combination
3163 if we are dividing vertically, or a horizontal combination
3164 if we are making side-by-side windows */
3166 windows_or_buffers_changed++;
3167 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3168 new = make_window ();
3169 p = XWINDOW (new);
3171 p->frame = o->frame;
3172 p->next = o->next;
3173 if (!NILP (p->next))
3174 XWINDOW (p->next)->prev = new;
3175 p->prev = window;
3176 o->next = new;
3177 p->parent = o->parent;
3178 p->buffer = Qt;
3179 p->window_end_valid = Qnil;
3180 bzero (&p->last_cursor, sizeof p->last_cursor);
3182 /* Apportion the available frame space among the two new windows */
3184 if (!NILP (horflag))
3186 p->height = o->height;
3187 p->top = o->top;
3188 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
3189 XSETFASTINT (o->width, size_int);
3190 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
3192 else
3194 p->left = o->left;
3195 p->width = o->width;
3196 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
3197 XSETFASTINT (o->height, size_int);
3198 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
3201 /* Adjust glyph matrices. */
3202 adjust_glyphs (fo);
3203 Fset_window_buffer (new, o->buffer);
3204 return new;
3207 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3208 "Make current window ARG lines bigger.\n\
3209 From program, optional second arg non-nil means grow sideways ARG columns.")
3210 (arg, side)
3211 register Lisp_Object arg, side;
3213 CHECK_NUMBER (arg, 0);
3214 enlarge_window (selected_window, XINT (arg), !NILP (side));
3216 if (! NILP (Vwindow_configuration_change_hook))
3217 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3219 return Qnil;
3222 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3223 "Make current window ARG lines smaller.\n\
3224 From program, optional second arg non-nil means shrink sideways arg columns.")
3225 (arg, side)
3226 register Lisp_Object arg, side;
3228 CHECK_NUMBER (arg, 0);
3229 enlarge_window (selected_window, -XINT (arg), !NILP (side));
3231 if (! NILP (Vwindow_configuration_change_hook))
3232 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3234 return Qnil;
3238 window_height (window)
3239 Lisp_Object window;
3241 register struct window *p = XWINDOW (window);
3242 return XFASTINT (p->height);
3246 window_width (window)
3247 Lisp_Object window;
3249 register struct window *p = XWINDOW (window);
3250 return XFASTINT (p->width);
3254 #define CURBEG(w) \
3255 *(widthflag ? &(XWINDOW (w)->left) : &(XWINDOW (w)->top))
3257 #define CURSIZE(w) \
3258 *(widthflag ? &(XWINDOW (w)->width) : &(XWINDOW (w)->height))
3261 /* Enlarge selected_window by DELTA. WIDTHFLAG non-zero means
3262 increase its width. Siblings of the selected window are resized to
3263 fullfil the size request. If they become too small in the process,
3264 they will be deleted. */
3266 static void
3267 enlarge_window (window, delta, widthflag)
3268 Lisp_Object window;
3269 int delta, widthflag;
3271 Lisp_Object parent, next, prev;
3272 struct window *p;
3273 Lisp_Object *sizep;
3274 int maximum;
3275 int (*sizefun) P_ ((Lisp_Object))
3276 = widthflag ? window_width : window_height;
3277 void (*setsizefun) P_ ((Lisp_Object, int, int))
3278 = (widthflag ? set_window_width : set_window_height);
3280 /* Check values of window_min_width and window_min_height for
3281 validity. */
3282 check_min_window_sizes ();
3284 /* Give up if this window cannot be resized. */
3285 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3286 error ("Window is not resizable");
3288 /* Find the parent of the selected window. */
3289 while (1)
3291 p = XWINDOW (window);
3292 parent = p->parent;
3294 if (NILP (parent))
3296 if (widthflag)
3297 error ("No other window to side of this one");
3298 break;
3301 if (widthflag
3302 ? !NILP (XWINDOW (parent)->hchild)
3303 : !NILP (XWINDOW (parent)->vchild))
3304 break;
3306 window = parent;
3309 sizep = &CURSIZE (window);
3312 register int maxdelta;
3314 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
3315 : !NILP (p->next) ? ((*sizefun) (p->next)
3316 - window_min_size (XWINDOW (p->next),
3317 widthflag, 0, 0))
3318 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3319 - window_min_size (XWINDOW (p->prev),
3320 widthflag, 0, 0))
3321 /* This is a frame with only one window, a minibuffer-only
3322 or a minibufferless frame. */
3323 : (delta = 0));
3325 if (delta > maxdelta)
3326 /* This case traps trying to make the minibuffer
3327 the full frame, or make the only window aside from the
3328 minibuffer the full frame. */
3329 delta = maxdelta;
3332 if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3334 delete_window (window);
3335 return;
3338 if (delta == 0)
3339 return;
3341 /* Find the total we can get from other siblings. */
3342 maximum = 0;
3343 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3344 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3345 widthflag, 0, 0);
3346 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3347 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3348 widthflag, 0, 0);
3350 /* If we can get it all from them, do so. */
3351 if (delta <= maximum)
3353 Lisp_Object first_unaffected;
3354 Lisp_Object first_affected;
3355 int fixed_p;
3357 next = p->next;
3358 prev = p->prev;
3359 first_affected = window;
3360 /* Look at one sibling at a time,
3361 moving away from this window in both directions alternately,
3362 and take as much as we can get without deleting that sibling. */
3363 while (delta != 0 && (!NILP (next) || !NILP (prev)))
3365 if (! NILP (next))
3367 int this_one = ((*sizefun) (next)
3368 - window_min_size (XWINDOW (next),
3369 widthflag, 0, &fixed_p));
3370 if (!fixed_p)
3372 if (this_one > delta)
3373 this_one = delta;
3375 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3376 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3378 delta -= this_one;
3381 next = XWINDOW (next)->next;
3384 if (delta == 0)
3385 break;
3387 if (! NILP (prev))
3389 int this_one = ((*sizefun) (prev)
3390 - window_min_size (XWINDOW (prev),
3391 widthflag, 0, &fixed_p));
3392 if (!fixed_p)
3394 if (this_one > delta)
3395 this_one = delta;
3397 first_affected = prev;
3399 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3400 (*setsizefun) (window, XINT (*sizep) + this_one, 0);
3402 delta -= this_one;
3405 prev = XWINDOW (prev)->prev;
3409 xassert (delta == 0);
3411 /* Now recalculate the edge positions of all the windows affected,
3412 based on the new sizes. */
3413 first_unaffected = next;
3414 prev = first_affected;
3415 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3416 prev = next, next = XWINDOW (next)->next)
3418 XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
3419 /* This does not change size of NEXT,
3420 but it propagates the new top edge to its children */
3421 (*setsizefun) (next, (*sizefun) (next), 0);
3424 else
3426 register int delta1;
3427 register int opht = (*sizefun) (parent);
3429 /* If trying to grow this window to or beyond size of the parent,
3430 make delta1 so big that, on shrinking back down,
3431 all the siblings end up with less than one line and are deleted. */
3432 if (opht <= XINT (*sizep) + delta)
3433 delta1 = opht * opht * 2;
3434 else
3436 /* Otherwise, make delta1 just right so that if we add
3437 delta1 lines to this window and to the parent, and then
3438 shrink the parent back to its original size, the new
3439 proportional size of this window will increase by delta.
3441 The function size_window will compute the new height h'
3442 of the window from delta1 as:
3444 e = delta1/n
3445 x = delta1 - delta1/n * n for the 1st resizable child
3446 h' = h + e + x
3448 where n is the number of children that can be resized.
3449 We can ignore x by choosing a delta1 that is a multiple of
3450 n. We want the height of this window to come out as
3452 h' = h + delta
3454 So, delta1 must be
3456 h + e = h + delta
3457 delta1/n = delta
3458 delta1 = n * delta.
3460 The number of children n rquals the number of resizable
3461 children of this window + 1 because we know window itself
3462 is resizable (otherwise we would have signalled an error. */
3464 struct window *w = XWINDOW (window);
3465 Lisp_Object s;
3466 int n = 1;
3468 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3469 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3470 ++n;
3471 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3472 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3473 ++n;
3475 delta1 = n * delta;
3478 /* Add delta1 lines or columns to this window, and to the parent,
3479 keeping things consistent while not affecting siblings. */
3480 XSETINT (CURSIZE (parent), opht + delta1);
3481 (*setsizefun) (window, XINT (*sizep) + delta1, 0);
3483 /* Squeeze out delta1 lines or columns from our parent,
3484 shriking this window and siblings proportionately.
3485 This brings parent back to correct size.
3486 Delta1 was calculated so this makes this window the desired size,
3487 taking it all out of the siblings. */
3488 (*setsizefun) (parent, opht, 0);
3491 XSETFASTINT (p->last_modified, 0);
3492 XSETFASTINT (p->last_overlay_modified, 0);
3494 /* Adjust glyph matrices. */
3495 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
3498 #undef CURBEG
3499 #undef CURSIZE
3503 /***********************************************************************
3504 Resizing Mini-Windows
3505 ***********************************************************************/
3507 static void shrink_window_lowest_first P_ ((struct window *, int));
3509 enum save_restore_action
3511 CHECK_ORIG_SIZES,
3512 SAVE_ORIG_SIZES,
3513 RESTORE_ORIG_SIZES
3516 static int save_restore_orig_size P_ ((struct window *,
3517 enum save_restore_action));
3519 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
3520 from lowest windows first. */
3522 static void
3523 shrink_window_lowest_first (w, height)
3524 struct window *w;
3525 int height;
3527 struct window *c;
3528 Lisp_Object child;
3529 int old_height;
3531 xassert (!MINI_WINDOW_P (w));
3533 /* Set redisplay hints. */
3534 XSETFASTINT (w->last_modified, 0);
3535 XSETFASTINT (w->last_overlay_modified, 0);
3536 windows_or_buffers_changed++;
3537 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
3539 old_height = XFASTINT (w->height);
3540 XSETFASTINT (w->height, height);
3542 if (!NILP (w->hchild))
3544 for (child = w->hchild; !NILP (child); child = c->next)
3546 c = XWINDOW (child);
3547 c->top = w->top;
3548 shrink_window_lowest_first (c, height);
3551 else if (!NILP (w->vchild))
3553 Lisp_Object last_child;
3554 int delta = old_height - height;
3555 int last_top;
3557 last_child = Qnil;
3559 /* Find the last child. We are taking space from lowest windows
3560 first, so we iterate over children from the last child
3561 backwards. */
3562 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
3563 last_child = child;
3565 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
3566 for (child = last_child; delta && !NILP (child); child = c->prev)
3568 int this_one;
3570 c = XWINDOW (child);
3571 this_one = XFASTINT (c->height) - MIN_SAFE_WINDOW_HEIGHT;
3573 if (this_one > delta)
3574 this_one = delta;
3576 shrink_window_lowest_first (c, XFASTINT (c->height) - this_one);
3577 delta -= this_one;
3580 /* Compute new positions. */
3581 last_top = XINT (w->top);
3582 for (child = w->vchild; !NILP (child); child = c->next)
3584 c = XWINDOW (child);
3585 c->top = make_number (last_top);
3586 shrink_window_lowest_first (c, XFASTINT (c->height));
3587 last_top += XFASTINT (c->height);
3593 /* Save, restore, or check positions and sizes in the window tree
3594 rooted at W. ACTION says what to do.
3596 If ACTION is CHECK_ORIG_SIZES, check if orig_top and orig_height
3597 members are valid for all windows in the window tree. Value is
3598 non-zero if they are valid.
3600 If ACTION is SAVE_ORIG_SIZES, save members top and height in
3601 orig_top and orig_height for all windows in the tree.
3603 If ACTION is RESTORE_ORIG_SIZES, restore top and height from
3604 values stored in orig_top and orig_height for all windows. */
3606 static int
3607 save_restore_orig_size (w, action)
3608 struct window *w;
3609 enum save_restore_action action;
3611 int success_p = 1;
3613 while (w)
3615 if (!NILP (w->hchild))
3617 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
3618 success_p = 0;
3620 else if (!NILP (w->vchild))
3622 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
3623 success_p = 0;
3626 switch (action)
3628 case CHECK_ORIG_SIZES:
3629 if (!INTEGERP (w->orig_top) || !INTEGERP (w->orig_height))
3630 return 0;
3631 break;
3633 case SAVE_ORIG_SIZES:
3634 w->orig_top = w->top;
3635 w->orig_height = w->height;
3636 XSETFASTINT (w->last_modified, 0);
3637 XSETFASTINT (w->last_overlay_modified, 0);
3638 break;
3640 case RESTORE_ORIG_SIZES:
3641 xassert (INTEGERP (w->orig_top) && INTEGERP (w->orig_height));
3642 w->top = w->orig_top;
3643 w->height = w->orig_height;
3644 w->orig_height = w->orig_top = Qnil;
3645 XSETFASTINT (w->last_modified, 0);
3646 XSETFASTINT (w->last_overlay_modified, 0);
3647 break;
3649 default:
3650 abort ();
3653 w = NILP (w->next) ? NULL : XWINDOW (w->next);
3656 return success_p;
3660 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
3661 without deleting other windows. */
3663 void
3664 grow_mini_window (w, delta)
3665 struct window *w;
3666 int delta;
3668 struct frame *f = XFRAME (w->frame);
3669 struct window *root;
3671 xassert (MINI_WINDOW_P (w));
3672 xassert (delta >= 0);
3674 /* Check values of window_min_width and window_min_height for
3675 validity. */
3676 check_min_window_sizes ();
3678 /* Compute how much we can enlarge the mini-window without deleting
3679 other windows. */
3680 root = XWINDOW (FRAME_ROOT_WINDOW (f));
3681 if (delta)
3683 int min_height = window_min_size (root, 0, 0, 0);
3684 if (XFASTINT (root->height) - delta < min_height)
3685 delta = XFASTINT (root->height) - min_height;
3688 if (delta)
3690 /* Save original window sizes and positions, if not already done. */
3691 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
3692 save_restore_orig_size (root, SAVE_ORIG_SIZES);
3694 /* Shrink other windows. */
3695 shrink_window_lowest_first (root, XFASTINT (root->height) - delta);
3697 /* Grow the mini-window. */
3698 w->top = make_number (XFASTINT (root->top) + XFASTINT (root->height));
3699 w->height = make_number (XFASTINT (w->height) + delta);
3700 XSETFASTINT (w->last_modified, 0);
3701 XSETFASTINT (w->last_overlay_modified, 0);
3703 adjust_glyphs (f);
3708 /* Shrink mini-window W. If there is recorded info about window sizes
3709 before a call to grow_mini_window, restore recorded window sizes.
3710 Otherwise, if the mini-window is higher than 1 line, resize it to 1
3711 line. */
3713 void
3714 shrink_mini_window (w)
3715 struct window *w;
3717 struct frame *f = XFRAME (w->frame);
3718 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
3720 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
3722 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
3723 adjust_glyphs (f);
3724 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3725 windows_or_buffers_changed = 1;
3727 else if (XFASTINT (w->height) > 1)
3729 Lisp_Object window;
3730 XSETWINDOW (window, w);
3731 enlarge_window (window, 1 - XFASTINT (w->height), 0);
3737 /* Mark window cursors off for all windows in the window tree rooted
3738 at W by setting their phys_cursor_on_p flag to zero. Called from
3739 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3740 the frame are cleared. */
3742 void
3743 mark_window_cursors_off (w)
3744 struct window *w;
3746 while (w)
3748 if (!NILP (w->hchild))
3749 mark_window_cursors_off (XWINDOW (w->hchild));
3750 else if (!NILP (w->vchild))
3751 mark_window_cursors_off (XWINDOW (w->vchild));
3752 else
3753 w->phys_cursor_on_p = 0;
3755 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3760 /* Return number of lines of text (not counting mode line) in W. */
3763 window_internal_height (w)
3764 struct window *w;
3766 int ht = XFASTINT (w->height);
3768 if (MINI_WINDOW_P (w))
3769 return ht;
3771 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
3772 || !NILP (w->next) || !NILP (w->prev)
3773 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
3774 return ht - 1;
3776 return ht;
3780 /* Return the number of columns in W.
3781 Don't count columns occupied by scroll bars or the vertical bar
3782 separating W from the sibling to its right. */
3785 window_internal_width (w)
3786 struct window *w;
3788 struct frame *f = XFRAME (WINDOW_FRAME (w));
3789 int width = XINT (w->width);
3791 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3792 /* Scroll bars occupy a few columns. */
3793 width -= FRAME_SCROLL_BAR_COLS (f);
3794 else if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
3795 /* The column of `|' characters separating side-by-side windows
3796 occupies one column only. */
3797 width -= 1;
3799 /* On window-systems, areas to the left and right of the window
3800 are used to display bitmaps there. */
3801 if (FRAME_WINDOW_P (f))
3802 width -= FRAME_FLAGS_AREA_COLS (f);
3804 return width;
3808 /************************************************************************
3809 Window Scrolling
3810 ***********************************************************************/
3812 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
3813 one screen-full, which is defined as the height of the window minus
3814 next_screen_context_lines. If WHOLE is zero, scroll up N lines
3815 instead. Negative values of N mean scroll down. NOERROR non-zero
3816 means don't signal an error if we try to move over BEGV or ZV,
3817 respectively. */
3819 static void
3820 window_scroll (window, n, whole, noerror)
3821 Lisp_Object window;
3822 int n;
3823 int whole;
3824 int noerror;
3826 /* If we must, use the pixel-based version which is much slower than
3827 the line-based one but can handle varying line heights. */
3828 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
3829 window_scroll_pixel_based (window, n, whole, noerror);
3830 else
3831 window_scroll_line_based (window, n, whole, noerror);
3835 /* Implementation of window_scroll that works based on pixel line
3836 heights. See the comment of window_scroll for parameter
3837 descriptions. */
3839 static void
3840 window_scroll_pixel_based (window, n, whole, noerror)
3841 Lisp_Object window;
3842 int n;
3843 int whole;
3844 int noerror;
3846 struct it it;
3847 struct window *w = XWINDOW (window);
3848 struct text_pos start;
3849 Lisp_Object tem;
3850 int this_scroll_margin;
3851 int preserve_y;
3853 SET_TEXT_POS_FROM_MARKER (start, w->start);
3855 /* If PT is not visible in WINDOW, move back one half of
3856 the screen. */
3857 XSETFASTINT (tem, PT);
3858 tem = Fpos_visible_in_window_p (tem, window, Qnil);
3859 if (NILP (tem))
3861 /* Move backward half the height of the window. Performance note:
3862 vmotion used here is about 10% faster, but would give wrong
3863 results for variable height lines. */
3864 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3865 it.current_y = it.last_visible_y;
3866 move_it_vertically (&it, -it.last_visible_y / 2);
3868 /* The function move_iterator_vertically may move over more than
3869 the specified y-distance. If it->w is small, e.g. a
3870 mini-buffer window, we may end up in front of the window's
3871 display area. This is the case when Start displaying at the
3872 start of the line containing PT in this case. */
3873 if (it.current_y <= 0)
3875 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3876 move_it_vertically (&it, 0);
3877 it.current_y = 0;
3880 start = it.current.pos;
3883 /* If scroll_preserve_screen_position is non-zero, we try to set
3884 point in the same window line as it is now, so get that line. */
3885 if (!NILP (Vscroll_preserve_screen_position))
3887 start_display (&it, w, start);
3888 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3889 preserve_y = it.current_y;
3891 else
3892 preserve_y = -1;
3894 /* Move iterator it from start the specified distance forward or
3895 backward. The result is the new window start. */
3896 start_display (&it, w, start);
3897 if (whole)
3899 int screen_full = (it.last_visible_y
3900 - next_screen_context_lines * CANON_Y_UNIT (it.f));
3901 int direction = n < 0 ? -1 : 1;
3902 move_it_vertically (&it, direction * screen_full);
3904 else
3905 move_it_by_lines (&it, n, 1);
3907 /* End if we end up at ZV or BEGV. */
3908 if ((n > 0 && IT_CHARPOS (it) == ZV)
3909 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
3911 if (noerror)
3912 return;
3913 else if (IT_CHARPOS (it) == ZV)
3914 Fsignal (Qend_of_buffer, Qnil);
3915 else
3916 Fsignal (Qbeginning_of_buffer, Qnil);
3919 /* Set the window start, and set up the window for redisplay. */
3920 set_marker_restricted (w->start, make_number (IT_CHARPOS (it)), w->buffer);
3921 w->start_at_line_beg = Fbolp ();
3922 w->update_mode_line = Qt;
3923 XSETFASTINT (w->last_modified, 0);
3924 XSETFASTINT (w->last_overlay_modified, 0);
3925 /* Set force_start so that redisplay_window will run the
3926 window-scroll-functions. */
3927 w->force_start = Qt;
3929 it.current_y = it.vpos = 0;
3931 /* Preserve the screen position if we must. */
3932 if (preserve_y >= 0)
3934 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
3935 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3937 else
3939 /* Move PT out of scroll margins. */
3940 this_scroll_margin = max (0, scroll_margin);
3941 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
3942 this_scroll_margin *= CANON_Y_UNIT (it.f);
3944 if (n > 0)
3946 /* We moved the window start towards ZV, so PT may be now
3947 in the scroll margin at the top. */
3948 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3949 while (it.current_y < this_scroll_margin)
3950 move_it_by_lines (&it, 1, 1);
3951 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3953 else if (n < 0)
3955 /* We moved the window start towards BEGV, so PT may be now
3956 in the scroll margin at the bottom. */
3957 move_it_to (&it, PT, -1,
3958 it.last_visible_y - this_scroll_margin - 1, -1,
3959 MOVE_TO_POS | MOVE_TO_Y);
3961 /* Don't put point on a partially visible line at the end. */
3962 if (it.current_y + it.max_ascent + it.max_descent
3963 > it.last_visible_y)
3964 move_it_by_lines (&it, -1, 0);
3966 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3972 /* Implementation of window_scroll that works based on screen lines.
3973 See the comment of window_scroll for parameter descriptions. */
3975 static void
3976 window_scroll_line_based (window, n, whole, noerror)
3977 Lisp_Object window;
3978 int n;
3979 int whole;
3980 int noerror;
3982 register struct window *w = XWINDOW (window);
3983 register int opoint = PT, opoint_byte = PT_BYTE;
3984 register int pos, pos_byte;
3985 register int ht = window_internal_height (w);
3986 register Lisp_Object tem;
3987 int lose;
3988 Lisp_Object bolp;
3989 int startpos;
3990 struct position posit;
3991 int original_vpos;
3993 startpos = marker_position (w->start);
3995 posit = *compute_motion (startpos, 0, 0, 0,
3996 PT, ht, 0,
3997 window_internal_width (w), XINT (w->hscroll),
3998 0, w);
3999 original_vpos = posit.vpos;
4001 XSETFASTINT (tem, PT);
4002 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4004 if (NILP (tem))
4006 Fvertical_motion (make_number (- (ht / 2)), window);
4007 startpos = PT;
4010 SET_PT (startpos);
4011 lose = n < 0 && PT == BEGV;
4012 Fvertical_motion (make_number (n), window);
4013 pos = PT;
4014 pos_byte = PT_BYTE;
4015 bolp = Fbolp ();
4016 SET_PT_BOTH (opoint, opoint_byte);
4018 if (lose)
4020 if (noerror)
4021 return;
4022 else
4023 Fsignal (Qbeginning_of_buffer, Qnil);
4026 if (pos < ZV)
4028 int this_scroll_margin = scroll_margin;
4030 /* Don't use a scroll margin that is negative or too large. */
4031 if (this_scroll_margin < 0)
4032 this_scroll_margin = 0;
4034 if (XINT (w->height) < 4 * scroll_margin)
4035 this_scroll_margin = XINT (w->height) / 4;
4037 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4038 w->start_at_line_beg = bolp;
4039 w->update_mode_line = Qt;
4040 XSETFASTINT (w->last_modified, 0);
4041 XSETFASTINT (w->last_overlay_modified, 0);
4042 /* Set force_start so that redisplay_window will run
4043 the window-scroll-functions. */
4044 w->force_start = Qt;
4046 if (whole && !NILP (Vscroll_preserve_screen_position))
4048 SET_PT_BOTH (pos, pos_byte);
4049 Fvertical_motion (make_number (original_vpos), window);
4051 /* If we scrolled forward, put point enough lines down
4052 that it is outside the scroll margin. */
4053 else if (n > 0)
4055 int top_margin;
4057 if (this_scroll_margin > 0)
4059 SET_PT_BOTH (pos, pos_byte);
4060 Fvertical_motion (make_number (this_scroll_margin), window);
4061 top_margin = PT;
4063 else
4064 top_margin = pos;
4066 if (top_margin <= opoint)
4067 SET_PT_BOTH (opoint, opoint_byte);
4068 else if (!NILP (Vscroll_preserve_screen_position))
4070 SET_PT_BOTH (pos, pos_byte);
4071 Fvertical_motion (make_number (original_vpos), window);
4073 else
4074 SET_PT (top_margin);
4076 else if (n < 0)
4078 int bottom_margin;
4080 /* If we scrolled backward, put point near the end of the window
4081 but not within the scroll margin. */
4082 SET_PT_BOTH (pos, pos_byte);
4083 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4084 if (XFASTINT (tem) == ht - this_scroll_margin)
4085 bottom_margin = PT;
4086 else
4087 bottom_margin = PT + 1;
4089 if (bottom_margin > opoint)
4090 SET_PT_BOTH (opoint, opoint_byte);
4091 else
4093 if (!NILP (Vscroll_preserve_screen_position))
4095 SET_PT_BOTH (pos, pos_byte);
4096 Fvertical_motion (make_number (original_vpos), window);
4098 else
4099 Fvertical_motion (make_number (-1), window);
4103 else
4105 if (noerror)
4106 return;
4107 else
4108 Fsignal (Qend_of_buffer, Qnil);
4113 /* Scroll selected_window up or down. If N is nil, scroll a
4114 screen-full which is defined as the height of the window minus
4115 next_screen_context_lines. If N is the symbol `-', scroll.
4116 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4117 up. This is the guts of Fscroll_up and Fscroll_down. */
4119 static void
4120 scroll_command (n, direction)
4121 Lisp_Object n;
4122 int direction;
4124 register int defalt;
4125 int count = specpdl_ptr - specpdl;
4127 xassert (abs (direction) == 1);
4129 /* If selected window's buffer isn't current, make it current for
4130 the moment. But don't screw up if window_scroll gets an error. */
4131 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4133 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4134 Fset_buffer (XWINDOW (selected_window)->buffer);
4136 /* Make redisplay consider other windows than just selected_window. */
4137 ++windows_or_buffers_changed;
4140 defalt = (window_internal_height (XWINDOW (selected_window))
4141 - next_screen_context_lines);
4142 defalt = direction * (defalt < 1 ? 1 : defalt);
4144 if (NILP (n))
4145 window_scroll (selected_window, defalt, 1, 0);
4146 else if (EQ (n, Qminus))
4147 window_scroll (selected_window, - defalt, 1, 0);
4148 else
4150 n = Fprefix_numeric_value (n);
4151 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4154 unbind_to (count, Qnil);
4157 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
4158 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
4159 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4160 Negative ARG means scroll downward.\n\
4161 If ARG is the atom `-', scroll downward by nearly full screen.\n\
4162 When calling from a program, supply as argument a number, nil, or `-'.")
4163 (arg)
4164 Lisp_Object arg;
4166 scroll_command (arg, 1);
4167 return Qnil;
4170 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
4171 "Scroll text of current window down ARG lines; or near full screen if no ARG.\n\
4172 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4173 Negative ARG means scroll upward.\n\
4174 If ARG is the atom `-', scroll upward by nearly full screen.\n\
4175 When calling from a program, supply as argument a number, nil, or `-'.")
4176 (arg)
4177 Lisp_Object arg;
4179 scroll_command (arg, -1);
4180 return Qnil;
4183 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4184 "Return the other window for \"other window scroll\" commands.\n\
4185 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
4186 specifies the window.\n\
4187 If `other-window-scroll-buffer' is non-nil, a window\n\
4188 showing that buffer is used.")
4191 Lisp_Object window;
4193 if (MINI_WINDOW_P (XWINDOW (selected_window))
4194 && !NILP (Vminibuf_scroll_window))
4195 window = Vminibuf_scroll_window;
4196 /* If buffer is specified, scroll that buffer. */
4197 else if (!NILP (Vother_window_scroll_buffer))
4199 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4200 if (NILP (window))
4201 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4203 else
4205 /* Nothing specified; look for a neighboring window on the same
4206 frame. */
4207 window = Fnext_window (selected_window, Qnil, Qnil);
4209 if (EQ (window, selected_window))
4210 /* That didn't get us anywhere; look for a window on another
4211 visible frame. */
4213 window = Fnext_window (window, Qnil, Qt);
4214 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4215 && ! EQ (window, selected_window));
4218 CHECK_LIVE_WINDOW (window, 0);
4220 if (EQ (window, selected_window))
4221 error ("There is no other window");
4223 return window;
4226 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4227 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
4228 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4229 The next window is the one below the current one; or the one at the top\n\
4230 if the current one is at the bottom. Negative ARG means scroll downward.\n\
4231 If ARG is the atom `-', scroll downward by nearly full screen.\n\
4232 When calling from a program, supply as argument a number, nil, or `-'.\n\
4234 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
4235 specifies the window to scroll.\n\
4236 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
4237 showing that buffer, popping the buffer up if necessary.")
4238 (arg)
4239 register Lisp_Object arg;
4241 register Lisp_Object window;
4242 register int defalt;
4243 register struct window *w;
4244 register int count = specpdl_ptr - specpdl;
4246 window = Fother_window_for_scrolling ();
4248 w = XWINDOW (window);
4249 defalt = window_internal_height (w) - next_screen_context_lines;
4250 if (defalt < 1) defalt = 1;
4252 /* Don't screw up if window_scroll gets an error. */
4253 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4254 ++windows_or_buffers_changed;
4256 Fset_buffer (w->buffer);
4257 SET_PT (marker_position (w->pointm));
4259 if (NILP (arg))
4260 window_scroll (window, defalt, 1, 1);
4261 else if (EQ (arg, Qminus))
4262 window_scroll (window, -defalt, 1, 1);
4263 else
4265 if (CONSP (arg))
4266 arg = Fcar (arg);
4267 CHECK_NUMBER (arg, 0);
4268 window_scroll (window, XINT (arg), 0, 1);
4271 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4272 unbind_to (count, Qnil);
4274 return Qnil;
4277 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
4278 "Scroll selected window display ARG columns left.\n\
4279 Default for ARG is window width minus 2.")
4280 (arg)
4281 register Lisp_Object arg;
4284 if (NILP (arg))
4285 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
4286 else
4287 arg = Fprefix_numeric_value (arg);
4289 return
4290 Fset_window_hscroll (selected_window,
4291 make_number (XINT (XWINDOW (selected_window)->hscroll)
4292 + XINT (arg)));
4295 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
4296 "Scroll selected window display ARG columns right.\n\
4297 Default for ARG is window width minus 2.")
4298 (arg)
4299 register Lisp_Object arg;
4301 if (NILP (arg))
4302 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
4303 else
4304 arg = Fprefix_numeric_value (arg);
4306 return
4307 Fset_window_hscroll (selected_window,
4308 make_number (XINT (XWINDOW (selected_window)->hscroll)
4309 - XINT (arg)));
4312 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
4313 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
4314 The desired position of point is always relative to the current window.\n\
4315 Just C-u as prefix means put point in the center of the window.\n\
4316 If ARG is omitted or nil, erases the entire frame and then\n\
4317 redraws with point in the center of the current window.")
4318 (arg)
4319 register Lisp_Object arg;
4321 register struct window *w = XWINDOW (selected_window);
4322 register int ht = window_internal_height (w);
4323 struct position pos;
4324 struct buffer *buf = XBUFFER (w->buffer);
4325 struct buffer *obuf = current_buffer;
4327 if (NILP (arg))
4329 extern int frame_garbaged;
4330 int i;
4332 /* Invalidate pixel data calculated for all compositions. */
4333 for (i = 0; i < n_compositions; i++)
4334 composition_table[i]->font = NULL;
4336 Fredraw_frame (w->frame);
4337 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
4338 XSETFASTINT (arg, ht / 2);
4340 else if (CONSP (arg)) /* Just C-u. */
4342 XSETFASTINT (arg, ht / 2);
4344 else
4346 arg = Fprefix_numeric_value (arg);
4347 CHECK_NUMBER (arg, 0);
4350 if (XINT (arg) < 0)
4351 XSETINT (arg, XINT (arg) + ht);
4353 set_buffer_internal (buf);
4354 pos = *vmotion (PT, - XINT (arg), w);
4356 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
4357 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
4358 || FETCH_BYTE (pos.bytepos - 1) == '\n')
4359 ? Qt : Qnil);
4360 w->force_start = Qt;
4361 set_buffer_internal (obuf);
4363 return Qnil;
4367 /* Value is the number of lines actually displayed in window W,
4368 as opposed to its height. */
4370 static int
4371 displayed_window_lines (w)
4372 struct window *w;
4374 struct it it;
4375 struct text_pos start;
4376 int height = window_box_height (w);
4377 struct buffer *old_buffer;
4378 int bottom_y;
4380 if (XBUFFER (w->buffer) != current_buffer)
4382 old_buffer = current_buffer;
4383 set_buffer_internal (XBUFFER (w->buffer));
4385 else
4386 old_buffer = NULL;
4388 SET_TEXT_POS_FROM_MARKER (start, w->start);
4389 start_display (&it, w, start);
4390 move_it_vertically (&it, height);
4392 if (old_buffer)
4393 set_buffer_internal (old_buffer);
4395 /* Add in empty lines at the bottom of the window. */
4396 bottom_y = it.current_y + it.max_ascent + it.max_descent;
4397 if (bottom_y < height)
4399 struct frame *f = XFRAME (w->frame);
4400 int rest = height - bottom_y;
4401 int lines = (rest + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
4402 it.vpos += lines;
4404 else if (it.current_y < height && bottom_y > height)
4405 /* Partially visible line at the bottom. */
4406 ++it.vpos;
4408 return it.vpos;
4413 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
4414 1, 1, "P",
4415 "Position point relative to window.\n\
4416 With no argument, position point at center of window.\n\
4417 An argument specifies vertical position within the window;\n\
4418 zero means top of window, negative means relative to bottom of window.")
4419 (arg)
4420 Lisp_Object arg;
4422 struct window *w = XWINDOW (selected_window);
4423 int lines, start;
4424 Lisp_Object window;
4426 window = selected_window;
4427 start = marker_position (w->start);
4428 if (start < BEGV || start > ZV)
4430 int height = window_internal_height (w);
4431 Fvertical_motion (make_number (- (height / 2)), window);
4432 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
4433 w->start_at_line_beg = Fbolp ();
4434 w->force_start = Qt;
4436 else
4437 Fgoto_char (w->start);
4439 lines = displayed_window_lines (w);
4440 if (NILP (arg))
4441 XSETFASTINT (arg, lines / 2);
4442 else
4444 arg = Fprefix_numeric_value (arg);
4445 if (XINT (arg) < 0)
4446 XSETINT (arg, XINT (arg) + lines);
4449 return Fvertical_motion (arg, window);
4454 /***********************************************************************
4455 Window Configuration
4456 ***********************************************************************/
4458 struct save_window_data
4460 EMACS_INT size_from_Lisp_Vector_struct;
4461 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4462 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
4463 Lisp_Object frame_tool_bar_lines;
4464 Lisp_Object selected_frame;
4465 Lisp_Object current_window;
4466 Lisp_Object current_buffer;
4467 Lisp_Object minibuf_scroll_window;
4468 Lisp_Object root_window;
4469 Lisp_Object focus_frame;
4470 /* Record the values of window-min-width and window-min-height
4471 so that window sizes remain consistent with them. */
4472 Lisp_Object min_width, min_height;
4473 /* A vector, each of whose elements is a struct saved_window
4474 for one window. */
4475 Lisp_Object saved_windows;
4478 /* This is saved as a Lisp_Vector */
4479 struct saved_window
4481 /* these first two must agree with struct Lisp_Vector in lisp.h */
4482 EMACS_INT size_from_Lisp_Vector_struct;
4483 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4485 Lisp_Object window;
4486 Lisp_Object buffer, start, pointm, mark;
4487 Lisp_Object left, top, width, height, hscroll;
4488 Lisp_Object parent, prev;
4489 Lisp_Object start_at_line_beg;
4490 Lisp_Object display_table;
4492 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
4494 #define SAVED_WINDOW_N(swv,n) \
4495 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4497 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
4498 "Return t if OBJECT is a window-configuration object.")
4499 (object)
4500 Lisp_Object object;
4502 if (WINDOW_CONFIGURATIONP (object))
4503 return Qt;
4504 return Qnil;
4507 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
4508 "Return the frame that CONFIG, a window-configuration object, is about.")
4509 (config)
4510 Lisp_Object config;
4512 register struct save_window_data *data;
4513 struct Lisp_Vector *saved_windows;
4515 if (! WINDOW_CONFIGURATIONP (config))
4516 wrong_type_argument (Qwindow_configuration_p, config);
4518 data = (struct save_window_data *) XVECTOR (config);
4519 saved_windows = XVECTOR (data->saved_windows);
4520 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4523 DEFUN ("set-window-configuration", Fset_window_configuration,
4524 Sset_window_configuration, 1, 1, 0,
4525 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
4526 CONFIGURATION must be a value previously returned\n\
4527 by `current-window-configuration' (which see).\n\
4528 If CONFIGURATION was made from a frame that is now deleted,\n\
4529 only frame-independent values can be restored. In this case,\n\
4530 the return value is nil. Otherwise the value is t.")
4531 (configuration)
4532 Lisp_Object configuration;
4534 register struct save_window_data *data;
4535 struct Lisp_Vector *saved_windows;
4536 Lisp_Object new_current_buffer;
4537 Lisp_Object frame;
4538 FRAME_PTR f;
4539 int old_point = -1;
4541 while (!WINDOW_CONFIGURATIONP (configuration))
4542 wrong_type_argument (Qwindow_configuration_p, configuration);
4544 data = (struct save_window_data *) XVECTOR (configuration);
4545 saved_windows = XVECTOR (data->saved_windows);
4547 new_current_buffer = data->current_buffer;
4548 if (NILP (XBUFFER (new_current_buffer)->name))
4549 new_current_buffer = Qnil;
4550 else
4552 if (XBUFFER (new_current_buffer) == current_buffer)
4553 old_point = PT;
4556 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4557 f = XFRAME (frame);
4559 /* If f is a dead frame, don't bother rebuilding its window tree.
4560 However, there is other stuff we should still try to do below. */
4561 if (FRAME_LIVE_P (f))
4563 register struct window *w;
4564 register struct saved_window *p;
4565 struct window *root_window;
4566 struct window **leaf_windows;
4567 int n_leaf_windows;
4568 int k, i, n;
4570 /* If the frame has been resized since this window configuration was
4571 made, we change the frame to the size specified in the
4572 configuration, restore the configuration, and then resize it
4573 back. We keep track of the prevailing height in these variables. */
4574 int previous_frame_height = FRAME_HEIGHT (f);
4575 int previous_frame_width = FRAME_WIDTH (f);
4576 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
4577 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
4579 /* The mouse highlighting code could get screwed up
4580 if it runs during this. */
4581 BLOCK_INPUT;
4583 if (XFASTINT (data->frame_height) != previous_frame_height
4584 || XFASTINT (data->frame_width) != previous_frame_width)
4585 change_frame_size (f, XFASTINT (data->frame_height),
4586 XFASTINT (data->frame_width), 0, 0, 0);
4587 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4588 if (XFASTINT (data->frame_menu_bar_lines)
4589 != previous_frame_menu_bar_lines)
4590 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
4591 #ifdef HAVE_WINDOW_SYSTEM
4592 if (XFASTINT (data->frame_tool_bar_lines)
4593 != previous_frame_tool_bar_lines)
4594 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
4595 #endif
4596 #endif
4598 /* "Swap out" point from the selected window
4599 into its buffer. We do this now, before
4600 restoring the window contents, and prevent it from
4601 being done later on when we select a new window. */
4602 if (! NILP (XWINDOW (selected_window)->buffer))
4604 w = XWINDOW (selected_window);
4605 set_marker_both (w->pointm,
4606 w->buffer,
4607 BUF_PT (XBUFFER (w->buffer)),
4608 BUF_PT_BYTE (XBUFFER (w->buffer)));
4611 windows_or_buffers_changed++;
4612 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4614 /* Problem: Freeing all matrices and later allocating them again
4615 is a serious redisplay flickering problem. What we would
4616 really like to do is to free only those matrices not reused
4617 below. */
4618 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
4619 leaf_windows
4620 = (struct window **) alloca (count_windows (root_window)
4621 * sizeof (struct window *));
4622 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
4624 /* Temporarily avoid any problems with windows that are smaller
4625 than they are supposed to be. */
4626 window_min_height = 1;
4627 window_min_width = 1;
4629 /* Kludge Alert!
4630 Mark all windows now on frame as "deleted".
4631 Restoring the new configuration "undeletes" any that are in it.
4633 Save their current buffers in their height fields, since we may
4634 need it later, if a buffer saved in the configuration is now
4635 dead. */
4636 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4638 for (k = 0; k < saved_windows->size; k++)
4640 p = SAVED_WINDOW_N (saved_windows, k);
4641 w = XWINDOW (p->window);
4642 w->next = Qnil;
4644 if (!NILP (p->parent))
4645 w->parent = SAVED_WINDOW_N (saved_windows,
4646 XFASTINT (p->parent))->window;
4647 else
4648 w->parent = Qnil;
4650 if (!NILP (p->prev))
4652 w->prev = SAVED_WINDOW_N (saved_windows,
4653 XFASTINT (p->prev))->window;
4654 XWINDOW (w->prev)->next = p->window;
4656 else
4658 w->prev = Qnil;
4659 if (!NILP (w->parent))
4661 if (EQ (p->width, XWINDOW (w->parent)->width))
4663 XWINDOW (w->parent)->vchild = p->window;
4664 XWINDOW (w->parent)->hchild = Qnil;
4666 else
4668 XWINDOW (w->parent)->hchild = p->window;
4669 XWINDOW (w->parent)->vchild = Qnil;
4674 /* If we squirreled away the buffer in the window's height,
4675 restore it now. */
4676 if (BUFFERP (w->height))
4677 w->buffer = w->height;
4678 w->left = p->left;
4679 w->top = p->top;
4680 w->width = p->width;
4681 w->height = p->height;
4682 w->hscroll = p->hscroll;
4683 w->display_table = p->display_table;
4684 XSETFASTINT (w->last_modified, 0);
4685 XSETFASTINT (w->last_overlay_modified, 0);
4687 /* Reinstall the saved buffer and pointers into it. */
4688 if (NILP (p->buffer))
4689 w->buffer = p->buffer;
4690 else
4692 if (!NILP (XBUFFER (p->buffer)->name))
4693 /* If saved buffer is alive, install it. */
4695 w->buffer = p->buffer;
4696 w->start_at_line_beg = p->start_at_line_beg;
4697 set_marker_restricted (w->start, p->start, w->buffer);
4698 set_marker_restricted (w->pointm, p->pointm, w->buffer);
4699 Fset_marker (XBUFFER (w->buffer)->mark,
4700 p->mark, w->buffer);
4702 /* As documented in Fcurrent_window_configuration, don't
4703 save the location of point in the buffer which was current
4704 when the window configuration was recorded. */
4705 if (!EQ (p->buffer, new_current_buffer)
4706 && XBUFFER (p->buffer) == current_buffer)
4707 Fgoto_char (w->pointm);
4709 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
4710 /* Else unless window has a live buffer, get one. */
4712 w->buffer = Fcdr (Fcar (Vbuffer_alist));
4713 /* This will set the markers to beginning of visible
4714 range. */
4715 set_marker_restricted (w->start, make_number (0), w->buffer);
4716 set_marker_restricted (w->pointm, make_number (0),w->buffer);
4717 w->start_at_line_beg = Qt;
4719 else
4720 /* Keeping window's old buffer; make sure the markers
4721 are real. */
4723 /* Set window markers at start of visible range. */
4724 if (XMARKER (w->start)->buffer == 0)
4725 set_marker_restricted (w->start, make_number (0),
4726 w->buffer);
4727 if (XMARKER (w->pointm)->buffer == 0)
4728 set_marker_restricted_both (w->pointm, w->buffer,
4729 BUF_PT (XBUFFER (w->buffer)),
4730 BUF_PT_BYTE (XBUFFER (w->buffer)));
4731 w->start_at_line_beg = Qt;
4736 FRAME_ROOT_WINDOW (f) = data->root_window;
4737 /* Prevent "swapping out point" in the old selected window
4738 using the buffer that has been restored into it.
4739 That swapping out has already been done,
4740 near the beginning of this function. */
4741 selected_window = Qnil;
4742 Fselect_window (data->current_window);
4743 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
4744 = selected_window;
4746 if (NILP (data->focus_frame)
4747 || (FRAMEP (data->focus_frame)
4748 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
4749 Fredirect_frame_focus (frame, data->focus_frame);
4751 #if 0 /* I don't understand why this is needed, and it causes problems
4752 when the frame's old selected window has been deleted. */
4753 if (f != selected_frame && FRAME_WINDOW_P (f))
4754 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
4755 Qnil, 0);
4756 #endif
4758 /* Set the screen height to the value it had before this function. */
4759 if (previous_frame_height != FRAME_HEIGHT (f)
4760 || previous_frame_width != FRAME_WIDTH (f))
4761 change_frame_size (f, previous_frame_height, previous_frame_width,
4762 0, 0, 0);
4763 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4764 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
4765 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
4766 make_number (0));
4767 #ifdef HAVE_WINDOW_SYSTEM
4768 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
4769 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
4770 make_number (0));
4771 #endif
4772 #endif
4774 /* Now, free glyph matrices in windows that were not reused. */
4775 for (i = n = 0; i < n_leaf_windows; ++i)
4777 if (NILP (leaf_windows[i]->buffer))
4779 /* Assert it's not reused as a combination. */
4780 xassert (NILP (leaf_windows[i]->hchild)
4781 && NILP (leaf_windows[i]->vchild));
4782 free_window_matrices (leaf_windows[i]);
4783 SET_FRAME_GARBAGED (f);
4785 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
4786 ++n;
4789 /* If more than one window shows the new and old current buffer,
4790 don't try to preserve point in that buffer. */
4791 if (old_point > 0 && n > 1)
4792 old_point = -1;
4794 adjust_glyphs (f);
4796 UNBLOCK_INPUT;
4798 /* Fselect_window will have made f the selected frame, so we
4799 reselect the proper frame here. Fhandle_switch_frame will change the
4800 selected window too, but that doesn't make the call to
4801 Fselect_window above totally superfluous; it still sets f's
4802 selected window. */
4803 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
4804 do_switch_frame (data->selected_frame, Qnil, 0);
4806 if (! NILP (Vwindow_configuration_change_hook)
4807 && ! NILP (Vrun_hooks))
4808 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4811 if (!NILP (new_current_buffer))
4813 Fset_buffer (new_current_buffer);
4815 /* If the buffer that is current now is the same
4816 that was current before setting the window configuration,
4817 don't alter its PT. */
4818 if (old_point >= 0)
4819 SET_PT (old_point);
4822 /* Restore the minimum heights recorded in the configuration. */
4823 window_min_height = XINT (data->min_height);
4824 window_min_width = XINT (data->min_width);
4826 Vminibuf_scroll_window = data->minibuf_scroll_window;
4828 return (FRAME_LIVE_P (f) ? Qt : Qnil);
4831 /* Mark all windows now on frame as deleted
4832 by setting their buffers to nil. */
4834 void
4835 delete_all_subwindows (w)
4836 register struct window *w;
4838 if (!NILP (w->next))
4839 delete_all_subwindows (XWINDOW (w->next));
4840 if (!NILP (w->vchild))
4841 delete_all_subwindows (XWINDOW (w->vchild));
4842 if (!NILP (w->hchild))
4843 delete_all_subwindows (XWINDOW (w->hchild));
4845 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
4847 if (!NILP (w->buffer))
4848 unshow_buffer (w);
4850 /* We set all three of these fields to nil, to make sure that we can
4851 distinguish this dead window from any live window. Live leaf
4852 windows will have buffer set, and combination windows will have
4853 vchild or hchild set. */
4854 w->buffer = Qnil;
4855 w->vchild = Qnil;
4856 w->hchild = Qnil;
4858 Vwindow_list = Qnil;
4861 static int
4862 count_windows (window)
4863 register struct window *window;
4865 register int count = 1;
4866 if (!NILP (window->next))
4867 count += count_windows (XWINDOW (window->next));
4868 if (!NILP (window->vchild))
4869 count += count_windows (XWINDOW (window->vchild));
4870 if (!NILP (window->hchild))
4871 count += count_windows (XWINDOW (window->hchild));
4872 return count;
4876 /* Fill vector FLAT with leaf windows under W, starting at index I.
4877 Value is last index + 1. */
4879 static int
4880 get_leaf_windows (w, flat, i)
4881 struct window *w;
4882 struct window **flat;
4883 int i;
4885 while (w)
4887 if (!NILP (w->hchild))
4888 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
4889 else if (!NILP (w->vchild))
4890 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
4891 else
4892 flat[i++] = w;
4894 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4897 return i;
4901 /* Return a pointer to the glyph W's physical cursor is on. Value is
4902 null if W's current matrix is invalid, so that no meaningfull glyph
4903 can be returned. */
4905 struct glyph *
4906 get_phys_cursor_glyph (w)
4907 struct window *w;
4909 struct glyph_row *row;
4910 struct glyph *glyph;
4912 if (w->phys_cursor.vpos >= 0
4913 && w->phys_cursor.vpos < w->current_matrix->nrows
4914 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
4915 row->enabled_p)
4916 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
4917 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
4918 else
4919 glyph = NULL;
4921 return glyph;
4925 static int
4926 save_window_save (window, vector, i)
4927 Lisp_Object window;
4928 struct Lisp_Vector *vector;
4929 int i;
4931 register struct saved_window *p;
4932 register struct window *w;
4933 register Lisp_Object tem;
4935 for (;!NILP (window); window = w->next)
4937 p = SAVED_WINDOW_N (vector, i);
4938 w = XWINDOW (window);
4940 XSETFASTINT (w->temslot, i++);
4941 p->window = window;
4942 p->buffer = w->buffer;
4943 p->left = w->left;
4944 p->top = w->top;
4945 p->width = w->width;
4946 p->height = w->height;
4947 p->hscroll = w->hscroll;
4948 p->display_table = w->display_table;
4949 if (!NILP (w->buffer))
4951 /* Save w's value of point in the window configuration.
4952 If w is the selected window, then get the value of point
4953 from the buffer; pointm is garbage in the selected window. */
4954 if (EQ (window, selected_window))
4956 p->pointm = Fmake_marker ();
4957 set_marker_both (p->pointm, w->buffer,
4958 BUF_PT (XBUFFER (w->buffer)),
4959 BUF_PT_BYTE (XBUFFER (w->buffer)));
4961 else
4962 p->pointm = Fcopy_marker (w->pointm, Qnil);
4964 p->start = Fcopy_marker (w->start, Qnil);
4965 p->start_at_line_beg = w->start_at_line_beg;
4967 tem = XBUFFER (w->buffer)->mark;
4968 p->mark = Fcopy_marker (tem, Qnil);
4970 else
4972 p->pointm = Qnil;
4973 p->start = Qnil;
4974 p->mark = Qnil;
4975 p->start_at_line_beg = Qnil;
4978 if (NILP (w->parent))
4979 p->parent = Qnil;
4980 else
4981 p->parent = XWINDOW (w->parent)->temslot;
4983 if (NILP (w->prev))
4984 p->prev = Qnil;
4985 else
4986 p->prev = XWINDOW (w->prev)->temslot;
4988 if (!NILP (w->vchild))
4989 i = save_window_save (w->vchild, vector, i);
4990 if (!NILP (w->hchild))
4991 i = save_window_save (w->hchild, vector, i);
4994 return i;
4997 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
4998 Scurrent_window_configuration, 0, 1, 0,
4999 "Return an object representing the current window configuration of FRAME.\n\
5000 If FRAME is nil or omitted, use the selected frame.\n\
5001 This describes the number of windows, their sizes and current buffers,\n\
5002 and for each displayed buffer, where display starts, and the positions of\n\
5003 point and mark. An exception is made for point in the current buffer:\n\
5004 its value is -not- saved.\n\
5005 This also records the currently selected frame, and FRAME's focus\n\
5006 redirection (see `redirect-frame-focus').")
5007 (frame)
5008 Lisp_Object frame;
5010 register Lisp_Object tem;
5011 register int n_windows;
5012 register struct save_window_data *data;
5013 register struct Lisp_Vector *vec;
5014 register int i;
5015 FRAME_PTR f;
5017 if (NILP (frame))
5018 frame = selected_frame;
5019 CHECK_LIVE_FRAME (frame, 0);
5020 f = XFRAME (frame);
5022 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5023 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
5024 for (i = 0; i < VECSIZE (struct save_window_data); i++)
5025 vec->contents[i] = Qnil;
5026 vec->size = VECSIZE (struct save_window_data);
5027 data = (struct save_window_data *)vec;
5029 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
5030 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
5031 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
5032 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
5033 data->selected_frame = selected_frame;
5034 data->current_window = FRAME_SELECTED_WINDOW (f);
5035 XSETBUFFER (data->current_buffer, current_buffer);
5036 data->minibuf_scroll_window = Vminibuf_scroll_window;
5037 data->root_window = FRAME_ROOT_WINDOW (f);
5038 data->focus_frame = FRAME_FOCUS_FRAME (f);
5039 XSETINT (data->min_height, window_min_height);
5040 XSETINT (data->min_width, window_min_width);
5041 tem = Fmake_vector (make_number (n_windows), Qnil);
5042 data->saved_windows = tem;
5043 for (i = 0; i < n_windows; i++)
5044 XVECTOR (tem)->contents[i]
5045 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
5046 save_window_save (FRAME_ROOT_WINDOW (f),
5047 XVECTOR (tem), 0);
5048 XSETWINDOW_CONFIGURATION (tem, data);
5049 return (tem);
5052 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
5053 0, UNEVALLED, 0,
5054 "Execute body, preserving window sizes and contents.\n\
5055 Restore which buffer appears in which window, where display starts,\n\
5056 and the value of point and mark for each window.\n\
5057 Also restore the choice of selected window.\n\
5058 Also restore which buffer is current.\n\
5059 Does not restore the value of point in current buffer.")
5060 (args)
5061 Lisp_Object args;
5063 register Lisp_Object val;
5064 register int count = specpdl_ptr - specpdl;
5066 record_unwind_protect (Fset_window_configuration,
5067 Fcurrent_window_configuration (Qnil));
5068 val = Fprogn (args);
5069 return unbind_to (count, val);
5073 /***********************************************************************
5074 Marginal Areas
5075 ***********************************************************************/
5077 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
5078 2, 3, 0,
5079 "Set width of marginal areas of window WINDOW.\n\
5080 If window is nil, set margins of the currently selected window.\n\
5081 First parameter LEFT-WIDTH specifies the number of character\n\
5082 cells to reserve for the left marginal area. Second parameter\n\
5083 RIGHT-WIDTH does the same for the right marginal area.\n\
5084 A nil width parameter means no margin.")
5085 (window, left, right)
5086 Lisp_Object window, left, right;
5088 struct window *w = decode_window (window);
5090 if (!NILP (left))
5091 CHECK_NUMBER_OR_FLOAT (left, 1);
5092 if (!NILP (right))
5093 CHECK_NUMBER_OR_FLOAT (right, 2);
5095 /* Check widths < 0 and translate a zero width to nil.
5096 Margins that are too wide have to be checked elsewhere. */
5097 if ((INTEGERP (left) && XINT (left) < 0)
5098 || (FLOATP (left) && XFLOAT_DATA (left) <= 0))
5099 XSETFASTINT (left, 0);
5100 if (INTEGERP (left) && XFASTINT (left) == 0)
5101 left = Qnil;
5103 if ((INTEGERP (right) && XINT (right) < 0)
5104 || (FLOATP (right) && XFLOAT_DATA (right) <= 0))
5105 XSETFASTINT (right, 0);
5106 if (INTEGERP (right) && XFASTINT (right) == 0)
5107 right = Qnil;
5109 w->left_margin_width = left;
5110 w->right_margin_width = right;
5112 ++windows_or_buffers_changed;
5113 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
5114 return Qnil;
5118 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
5119 0, 1, 0,
5120 "Get width of marginal areas of window WINDOW.\n\
5121 If WINDOW is omitted or nil, use the currently selected window.\n\
5122 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).\n\
5123 If a marginal area does not exist, its width will be returned\n\
5124 as nil.")
5125 (window)
5126 Lisp_Object window;
5128 struct window *w = decode_window (window);
5129 return Fcons (w->left_margin_width, w->right_margin_width);
5134 /***********************************************************************
5135 Smooth scrolling
5136 ***********************************************************************/
5138 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
5139 "Return the amount by which WINDOW is scrolled vertically.\n\
5140 Use the selected window if WINDOW is nil or omitted.\n\
5141 Value is a multiple of the canonical character height of WINDOW.")
5142 (window)
5143 Lisp_Object window;
5145 Lisp_Object result;
5146 struct frame *f;
5147 struct window *w;
5149 if (NILP (window))
5150 window = selected_window;
5151 else
5152 CHECK_WINDOW (window, 0);
5153 w = XWINDOW (window);
5154 f = XFRAME (w->frame);
5156 if (FRAME_WINDOW_P (f))
5157 result = CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
5158 else
5159 result = make_number (0);
5160 return result;
5164 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
5165 2, 2, 0,
5166 "Set amount by which WINDOW should be scrolled vertically to VSCROLL.\n\
5167 WINDOW nil or omitted means use the selected window. VSCROLL is a\n\
5168 non-negative multiple of the canonical character height of WINDOW.")
5169 (window, vscroll)
5170 Lisp_Object window, vscroll;
5172 struct window *w;
5173 struct frame *f;
5175 if (NILP (window))
5176 window = selected_window;
5177 else
5178 CHECK_WINDOW (window, 0);
5179 CHECK_NUMBER_OR_FLOAT (vscroll, 1);
5181 w = XWINDOW (window);
5182 f = XFRAME (w->frame);
5184 if (FRAME_WINDOW_P (f))
5186 int old_dy = w->vscroll;
5188 w->vscroll = - CANON_Y_UNIT (f) * XFLOATINT (vscroll);
5189 w->vscroll = min (w->vscroll, 0);
5191 /* Adjust glyph matrix of the frame if the virtual display
5192 area becomes larger than before. */
5193 if (w->vscroll < 0 && w->vscroll < old_dy)
5194 adjust_glyphs (f);
5196 /* Prevent redisplay shortcuts. */
5197 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5200 return Fwindow_vscroll (window);
5204 /* Call FN for all leaf windows on frame F. FN is called with the
5205 first argument being a pointer to the leaf window, and with
5206 additional argument USER_DATA. Stops when FN returns 0. */
5208 void
5209 foreach_window (f, fn, user_data)
5210 struct frame *f;
5211 int (* fn) P_ ((struct window *, void *));
5212 void *user_data;
5214 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
5218 /* Helper function for foreach_window. Call FN for all leaf windows
5219 reachable from W. FN is called with the first argument being a
5220 pointer to the leaf window, and with additional argument USER_DATA.
5221 Stop when FN returns 0. Value is 0 if stopped by FN. */
5223 static int
5224 foreach_window_1 (w, fn, user_data)
5225 struct window *w;
5226 int (* fn) P_ ((struct window *, void *));
5227 void *user_data;
5229 int cont;
5231 for (cont = 1; w && cont;)
5233 if (!NILP (w->hchild))
5234 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
5235 else if (!NILP (w->vchild))
5236 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
5237 else
5238 cont = fn (w, user_data);
5240 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5243 return cont;
5247 /* Freeze or unfreeze the window start of W if unless it is a
5248 mini-window or the selected window. FREEZE_P non-null means freeze
5249 the window start. */
5251 static int
5252 freeze_window_start (w, freeze_p)
5253 struct window *w;
5254 void *freeze_p;
5256 if (w == XWINDOW (selected_window)
5257 || MINI_WINDOW_P (w)
5258 || (MINI_WINDOW_P (XWINDOW (selected_window))
5259 && ! NILP (Vminibuf_scroll_window)
5260 && w == XWINDOW (Vminibuf_scroll_window)))
5261 freeze_p = NULL;
5263 w->frozen_window_start_p = freeze_p != NULL;
5264 return 1;
5268 /* Freeze or unfreeze the window starts of all leaf windows on frame
5269 F, except the selected window and a mini-window. FREEZE_P non-zero
5270 means freeze the window start. */
5272 void
5273 freeze_window_starts (f, freeze_p)
5274 struct frame *f;
5275 int freeze_p;
5277 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
5281 /***********************************************************************
5282 Initialization
5283 ***********************************************************************/
5285 /* Return 1 if window configurations C1 and C2
5286 describe the same state of affairs. This is used by Fequal. */
5289 compare_window_configurations (c1, c2, ignore_positions)
5290 Lisp_Object c1, c2;
5291 int ignore_positions;
5293 register struct save_window_data *d1, *d2;
5294 struct Lisp_Vector *sw1, *sw2;
5295 int i;
5297 if (!WINDOW_CONFIGURATIONP (c1))
5298 wrong_type_argument (Qwindow_configuration_p, c1);
5299 if (!WINDOW_CONFIGURATIONP (c2))
5300 wrong_type_argument (Qwindow_configuration_p, c2);
5302 d1 = (struct save_window_data *) XVECTOR (c1);
5303 d2 = (struct save_window_data *) XVECTOR (c2);
5304 sw1 = XVECTOR (d1->saved_windows);
5305 sw2 = XVECTOR (d2->saved_windows);
5307 if (! EQ (d1->frame_width, d2->frame_width))
5308 return 0;
5309 if (! EQ (d1->frame_height, d2->frame_height))
5310 return 0;
5311 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
5312 return 0;
5313 if (! EQ (d1->selected_frame, d2->selected_frame))
5314 return 0;
5315 /* Don't compare the current_window field directly.
5316 Instead see w1_is_current and w2_is_current, below. */
5317 if (! EQ (d1->current_buffer, d2->current_buffer))
5318 return 0;
5319 if (! ignore_positions)
5320 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
5321 return 0;
5322 /* Don't compare the root_window field.
5323 We don't require the two configurations
5324 to use the same window object,
5325 and the two root windows must be equivalent
5326 if everything else compares equal. */
5327 if (! EQ (d1->focus_frame, d2->focus_frame))
5328 return 0;
5329 if (! EQ (d1->min_width, d2->min_width))
5330 return 0;
5331 if (! EQ (d1->min_height, d2->min_height))
5332 return 0;
5334 /* Verify that the two confis have the same number of windows. */
5335 if (sw1->size != sw2->size)
5336 return 0;
5338 for (i = 0; i < sw1->size; i++)
5340 struct saved_window *p1, *p2;
5341 int w1_is_current, w2_is_current;
5343 p1 = SAVED_WINDOW_N (sw1, i);
5344 p2 = SAVED_WINDOW_N (sw2, i);
5346 /* Verify that the current windows in the two
5347 configurations correspond to each other. */
5348 w1_is_current = EQ (d1->current_window, p1->window);
5349 w2_is_current = EQ (d2->current_window, p2->window);
5351 if (w1_is_current != w2_is_current)
5352 return 0;
5354 /* Verify that the corresponding windows do match. */
5355 if (! EQ (p1->buffer, p2->buffer))
5356 return 0;
5357 if (! EQ (p1->left, p2->left))
5358 return 0;
5359 if (! EQ (p1->top, p2->top))
5360 return 0;
5361 if (! EQ (p1->width, p2->width))
5362 return 0;
5363 if (! EQ (p1->height, p2->height))
5364 return 0;
5365 if (! EQ (p1->display_table, p2->display_table))
5366 return 0;
5367 if (! EQ (p1->parent, p2->parent))
5368 return 0;
5369 if (! EQ (p1->prev, p2->prev))
5370 return 0;
5371 if (! ignore_positions)
5373 if (! EQ (p1->hscroll, p2->hscroll))
5374 return 0;
5375 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
5376 return 0;
5377 if (NILP (Fequal (p1->start, p2->start)))
5378 return 0;
5379 if (NILP (Fequal (p1->pointm, p2->pointm)))
5380 return 0;
5381 if (NILP (Fequal (p1->mark, p2->mark)))
5382 return 0;
5386 return 1;
5389 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
5390 Scompare_window_configurations, 2, 2, 0,
5391 "Compare two window configurations as regards the structure of windows.\n\
5392 This function ignores details such as the values of point and mark\n\
5393 and scrolling positions.")
5394 (x, y)
5395 Lisp_Object x, y;
5397 if (compare_window_configurations (x, y, 1))
5398 return Qt;
5399 return Qnil;
5402 void
5403 init_window_once ()
5405 struct frame *f = make_terminal_frame ();
5406 XSETFRAME (selected_frame, f);
5407 Vterminal_frame = selected_frame;
5408 minibuf_window = f->minibuffer_window;
5409 selected_window = f->selected_window;
5410 last_nonminibuf_frame = f;
5412 window_initialized = 1;
5415 void
5416 init_window ()
5418 Vwindow_list = Qnil;
5421 void
5422 syms_of_window ()
5424 Qleft_bitmap_area = intern ("left-bitmap-area");
5425 staticpro (&Qleft_bitmap_area);
5426 Qright_bitmap_area = intern ("right-bitmap-area");
5427 staticpro (&Qright_bitmap_area);
5429 Qwindow_size_fixed = intern ("window-size-fixed");
5430 staticpro (&Qwindow_size_fixed);
5432 staticpro (&Qwindow_configuration_change_hook);
5433 Qwindow_configuration_change_hook
5434 = intern ("window-configuration-change-hook");
5436 Qwindowp = intern ("windowp");
5437 staticpro (&Qwindowp);
5439 Qwindow_configuration_p = intern ("window-configuration-p");
5440 staticpro (&Qwindow_configuration_p);
5442 Qwindow_live_p = intern ("window-live-p");
5443 staticpro (&Qwindow_live_p);
5445 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
5446 staticpro (&Qtemp_buffer_show_hook);
5448 staticpro (&Vwindow_list);
5450 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
5451 "Non-nil means call as function to display a help buffer.\n\
5452 The function is called with one argument, the buffer to be displayed.\n\
5453 Used by `with-output-to-temp-buffer'.\n\
5454 If this function is used, then it must do the entire job of showing\n\
5455 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
5456 Vtemp_buffer_show_function = Qnil;
5458 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
5459 "If non-nil, function to call to handle `display-buffer'.\n\
5460 It will receive two args, the buffer and a flag which if non-nil means\n\
5461 that the currently selected window is not acceptable.\n\
5462 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
5463 work using this function.");
5464 Vdisplay_buffer_function = Qnil;
5466 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
5467 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
5468 Vminibuf_scroll_window = Qnil;
5470 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
5471 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
5472 Vother_window_scroll_buffer = Qnil;
5474 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
5475 "*Non-nil means `display-buffer' should make a separate frame.");
5476 pop_up_frames = 0;
5478 DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
5479 "*Non-nil means `display-buffer' should reuse frames.\n\
5480 If the buffer in question is already displayed in a frame, raise that frame.");
5481 display_buffer_reuse_frames = 0;
5483 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
5484 "Function to call to handle automatic new frame creation.\n\
5485 It is called with no arguments and should return a newly created frame.\n\
5487 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
5488 where `pop-up-frame-alist' would hold the default frame parameters.");
5489 Vpop_up_frame_function = Qnil;
5491 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
5492 "*List of buffer names that should have their own special frames.\n\
5493 Displaying a buffer whose name is in this list makes a special frame for it\n\
5494 using `special-display-function'. See also `special-display-regexps'.\n\
5496 An element of the list can be a list instead of just a string.\n\
5497 There are two ways to use a list as an element:\n\
5498 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
5499 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5500 In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
5501 followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
5502 All this is done by the function found in `special-display-function'.\n\
5504 If this variable appears \"not to work\", because you add a name to it\n\
5505 but that buffer still appears in the selected window, look at the\n\
5506 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5507 Those variables take precedence over this one.");
5508 Vspecial_display_buffer_names = Qnil;
5510 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
5511 "*List of regexps saying which buffers should have their own special frames.\n\
5512 If a buffer name matches one of these regexps, it gets its own frame.\n\
5513 Displaying a buffer whose name is in this list makes a special frame for it\n\
5514 using `special-display-function'.\n\
5516 An element of the list can be a list instead of just a string.\n\
5517 There are two ways to use a list as an element:\n\
5518 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
5519 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5520 In the latter case, FUNCTION is called with the buffer as first argument,\n\
5521 followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
5522 All this is done by the function found in `special-display-function'.\n\
5524 If this variable appears \"not to work\", because you add a regexp to it\n\
5525 but the matching buffers still appear in the selected window, look at the\n\
5526 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5527 Those variables take precedence over this one.");
5528 Vspecial_display_regexps = Qnil;
5530 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
5531 "Function to call to make a new frame for a special buffer.\n\
5532 It is called with two arguments, the buffer and optional buffer specific\n\
5533 data, and should return a window displaying that buffer.\n\
5534 The default value makes a separate frame for the buffer,\n\
5535 using `special-display-frame-alist' to specify the frame parameters.\n\
5537 A buffer is special if its is listed in `special-display-buffer-names'\n\
5538 or matches a regexp in `special-display-regexps'.");
5539 Vspecial_display_function = Qnil;
5541 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
5542 "*List of buffer names that should appear in the selected window.\n\
5543 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
5544 switches to it in the selected window, rather than making it appear\n\
5545 in some other window.\n\
5547 An element of the list can be a cons cell instead of just a string.\n\
5548 Then the car must be a string, which specifies the buffer name.\n\
5549 This is for compatibility with `special-display-buffer-names';\n\
5550 the cdr of the cons cell is ignored.\n\
5552 See also `same-window-regexps'.");
5553 Vsame_window_buffer_names = Qnil;
5555 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
5556 "*List of regexps saying which buffers should appear in the selected window.\n\
5557 If a buffer name matches one of these regexps, then displaying it\n\
5558 using `display-buffer' or `pop-to-buffer' switches to it\n\
5559 in the selected window, rather than making it appear in some other window.\n\
5561 An element of the list can be a cons cell instead of just a string.\n\
5562 Then the car must be a string, which specifies the buffer name.\n\
5563 This is for compatibility with `special-display-buffer-names';\n\
5564 the cdr of the cons cell is ignored.\n\
5566 See also `same-window-buffer-names'.");
5567 Vsame_window_regexps = Qnil;
5569 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
5570 "*Non-nil means display-buffer should make new windows.");
5571 pop_up_windows = 1;
5573 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
5574 "*Number of lines of continuity when scrolling by screenfuls.");
5575 next_screen_context_lines = 2;
5577 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
5578 "*display-buffer would prefer to split the largest window if this large.\n\
5579 If there is only one window, it is split regardless of this value.");
5580 split_height_threshold = 500;
5582 DEFVAR_INT ("window-min-height", &window_min_height,
5583 "*Delete any window less than this tall (including its mode line).");
5584 window_min_height = 4;
5586 DEFVAR_INT ("window-min-width", &window_min_width,
5587 "*Delete any window less than this wide.");
5588 window_min_width = 10;
5590 DEFVAR_LISP ("scroll-preserve-screen-position",
5591 &Vscroll_preserve_screen_position,
5592 "*Nonzero means scroll commands move point to keep its screen line unchanged.");
5593 Vscroll_preserve_screen_position = Qnil;
5595 DEFVAR_LISP ("window-configuration-change-hook",
5596 &Vwindow_configuration_change_hook,
5597 "Functions to call when window configuration changes.\n\
5598 The selected frame is the one whose configuration has changed.");
5599 Vwindow_configuration_change_hook = Qnil;
5601 defsubr (&Sselected_window);
5602 defsubr (&Sminibuffer_window);
5603 defsubr (&Swindow_minibuffer_p);
5604 defsubr (&Swindowp);
5605 defsubr (&Swindow_live_p);
5606 defsubr (&Spos_visible_in_window_p);
5607 defsubr (&Swindow_buffer);
5608 defsubr (&Swindow_height);
5609 defsubr (&Swindow_width);
5610 defsubr (&Swindow_hscroll);
5611 defsubr (&Sset_window_hscroll);
5612 defsubr (&Swindow_redisplay_end_trigger);
5613 defsubr (&Sset_window_redisplay_end_trigger);
5614 defsubr (&Swindow_edges);
5615 defsubr (&Scoordinates_in_window_p);
5616 defsubr (&Swindow_at);
5617 defsubr (&Swindow_point);
5618 defsubr (&Swindow_start);
5619 defsubr (&Swindow_end);
5620 defsubr (&Sset_window_point);
5621 defsubr (&Sset_window_start);
5622 defsubr (&Swindow_dedicated_p);
5623 defsubr (&Sset_window_dedicated_p);
5624 defsubr (&Swindow_display_table);
5625 defsubr (&Sset_window_display_table);
5626 defsubr (&Snext_window);
5627 defsubr (&Sprevious_window);
5628 defsubr (&Sother_window);
5629 defsubr (&Sget_lru_window);
5630 defsubr (&Sget_largest_window);
5631 defsubr (&Sget_buffer_window);
5632 defsubr (&Sdelete_other_windows);
5633 defsubr (&Sdelete_windows_on);
5634 defsubr (&Sreplace_buffer_in_windows);
5635 defsubr (&Sdelete_window);
5636 defsubr (&Sset_window_buffer);
5637 defsubr (&Sselect_window);
5638 defsubr (&Sspecial_display_p);
5639 defsubr (&Ssame_window_p);
5640 defsubr (&Sdisplay_buffer);
5641 defsubr (&Ssplit_window);
5642 defsubr (&Senlarge_window);
5643 defsubr (&Sshrink_window);
5644 defsubr (&Sscroll_up);
5645 defsubr (&Sscroll_down);
5646 defsubr (&Sscroll_left);
5647 defsubr (&Sscroll_right);
5648 defsubr (&Sother_window_for_scrolling);
5649 defsubr (&Sscroll_other_window);
5650 defsubr (&Srecenter);
5651 defsubr (&Smove_to_window_line);
5652 defsubr (&Swindow_configuration_p);
5653 defsubr (&Swindow_configuration_frame);
5654 defsubr (&Sset_window_configuration);
5655 defsubr (&Scurrent_window_configuration);
5656 defsubr (&Ssave_window_excursion);
5657 defsubr (&Sset_window_margins);
5658 defsubr (&Swindow_margins);
5659 defsubr (&Swindow_vscroll);
5660 defsubr (&Sset_window_vscroll);
5661 defsubr (&Scompare_window_configurations);
5662 defsubr (&Swindow_list);
5665 void
5666 keys_of_window ()
5668 initial_define_key (control_x_map, '1', "delete-other-windows");
5669 initial_define_key (control_x_map, '2', "split-window");
5670 initial_define_key (control_x_map, '0', "delete-window");
5671 initial_define_key (control_x_map, 'o', "other-window");
5672 initial_define_key (control_x_map, '^', "enlarge-window");
5673 initial_define_key (control_x_map, '<', "scroll-left");
5674 initial_define_key (control_x_map, '>', "scroll-right");
5676 initial_define_key (global_map, Ctl ('V'), "scroll-up");
5677 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
5678 initial_define_key (meta_map, 'v', "scroll-down");
5680 initial_define_key (global_map, Ctl('L'), "recenter");
5681 initial_define_key (meta_map, 'r', "move-to-window-line");