(Fforward_comment): Undo the previous change, since cc-mode
[emacs.git] / src / window.c
blob631ea058e903f646de6523bcaebdd0942747ef21
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 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 "frame.h"
26 #include "window.h"
27 #include "commands.h"
28 #include "indent.h"
29 #include "termchar.h"
30 #include "disptab.h"
31 #include "keyboard.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
43 #ifndef max
44 #define max(a, b) ((a) < (b) ? (b) : (a))
45 #endif
48 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
49 Lisp_Object Qwindow_size_fixed, Qleft_bitmap_area, Qright_bitmap_area;
50 extern Lisp_Object Qheight, Qwidth;
52 static struct window *decode_window P_ ((Lisp_Object));
53 static Lisp_Object select_window_1 P_ ((Lisp_Object, int));
54 static int count_windows P_ ((struct window *));
55 static int get_leaf_windows P_ ((struct window *, struct window **, int));
56 static void window_scroll P_ ((Lisp_Object, int, int, int));
57 static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
58 static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
59 static int window_min_size_1 P_ ((struct window *, int));
60 static int window_min_size P_ ((struct window *, int, int, int *));
61 static void size_window P_ ((Lisp_Object, int, int, int));
62 static void foreach_window_1 P_ ((struct window *, void (*fn) (), int, int,
63 int, int));
64 static void freeze_window_start P_ ((struct window *, int));
65 static int window_fixed_size_p P_ ((struct window *, int, int));
66 static void enlarge_window P_ ((Lisp_Object, int, int));
69 /* This is the window in which the terminal's cursor should
70 be left when nothing is being done with it. This must
71 always be a leaf window, and its buffer is selected by
72 the top level editing loop at the end of each command.
74 This value is always the same as
75 FRAME_SELECTED_WINDOW (selected_frame). */
77 Lisp_Object selected_window;
79 /* The mini-buffer window of the selected frame.
80 Note that you cannot test for mini-bufferness of an arbitrary window
81 by comparing against this; but you can test for mini-bufferness of
82 the selected window. */
84 Lisp_Object minibuf_window;
86 /* Non-nil means it is the window for C-M-v to scroll
87 when the mini-buffer is selected. */
89 Lisp_Object Vminibuf_scroll_window;
91 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
93 Lisp_Object Vother_window_scroll_buffer;
95 /* Non-nil means it's function to call to display temp buffers. */
97 Lisp_Object Vtemp_buffer_show_function;
99 /* If a window gets smaller than either of these, it is removed. */
101 int window_min_height;
102 int window_min_width;
104 /* Nonzero implies Fdisplay_buffer should create windows. */
106 int pop_up_windows;
108 /* Nonzero implies make new frames for Fdisplay_buffer. */
110 int pop_up_frames;
112 /* Non-nil means use this function instead of default */
114 Lisp_Object Vpop_up_frame_function;
116 /* Function to call to handle Fdisplay_buffer. */
118 Lisp_Object Vdisplay_buffer_function;
120 /* List of buffer *names* for buffers that should have their own frames. */
122 Lisp_Object Vspecial_display_buffer_names;
124 /* List of regexps for buffer names that should have their own frames. */
126 Lisp_Object Vspecial_display_regexps;
128 /* Function to pop up a special frame. */
130 Lisp_Object Vspecial_display_function;
132 /* List of buffer *names* for buffers to appear in selected window. */
134 Lisp_Object Vsame_window_buffer_names;
136 /* List of regexps for buffer names to appear in selected window. */
138 Lisp_Object Vsame_window_regexps;
140 /* Hook run at end of temp_output_buffer_show. */
142 Lisp_Object Qtemp_buffer_show_hook;
144 /* Fdisplay_buffer always splits the largest window
145 if that window is more than this high. */
147 int split_height_threshold;
149 /* Number of lines of continuity in scrolling by screenfuls. */
151 int next_screen_context_lines;
153 /* Incremented for each window created. */
155 static int sequence_number;
157 /* Nonzero after init_window_once has finished. */
159 static int window_initialized;
161 /* Hook to run when window config changes. */
163 Lisp_Object Qwindow_configuration_change_hook;
164 Lisp_Object Vwindow_configuration_change_hook;
166 /* Nonzero means scroll commands try to put point
167 at the same screen height as previously. */
169 Lisp_Object Vscroll_preserve_screen_position;
171 #if 0 /* This isn't used anywhere. */
172 /* Nonzero means we can split a frame even if it is "unsplittable". */
173 static int inhibit_frame_unsplittable;
174 #endif /* 0 */
176 #define min(a, b) ((a) < (b) ? (a) : (b))
178 extern int scroll_margin;
180 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
182 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
183 "Returns t if OBJECT is a window.")
184 (object)
185 Lisp_Object object;
187 return WINDOWP (object) ? Qt : Qnil;
190 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
191 "Returns t if OBJECT is a window which is currently visible.")
192 (object)
193 Lisp_Object object;
195 return (WINDOWP (object) && ! NILP (XWINDOW (object)->buffer) ? Qt : Qnil);
198 Lisp_Object
199 make_window ()
201 Lisp_Object val;
202 register struct window *p;
203 register struct Lisp_Vector *vec;
204 int i;
206 vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
207 for (i = 0; i < VECSIZE (struct window); i++)
208 vec->contents[i] = Qnil;
209 vec->size = VECSIZE (struct window);
210 p = (struct window *) vec;
211 XSETFASTINT (p->sequence_number, ++sequence_number);
212 XSETFASTINT (p->left, 0);
213 XSETFASTINT (p->top, 0);
214 XSETFASTINT (p->height, 0);
215 XSETFASTINT (p->width, 0);
216 XSETFASTINT (p->hscroll, 0);
217 p->orig_top = p->orig_height = Qnil;
218 p->start = Fmake_marker ();
219 p->pointm = Fmake_marker ();
220 XSETFASTINT (p->use_time, 0);
221 p->frame = Qnil;
222 p->display_table = Qnil;
223 p->dedicated = Qnil;
224 p->pseudo_window_p = 0;
225 bzero (&p->cursor, sizeof (p->cursor));
226 bzero (&p->last_cursor, sizeof (p->last_cursor));
227 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
228 p->desired_matrix = p->current_matrix = 0;
229 p->phys_cursor_type = -1;
230 p->must_be_updated_p = 0;
231 XSETFASTINT (p->window_end_vpos, 0);
232 XSETFASTINT (p->window_end_pos, 0);
233 p->window_end_valid = Qnil;
234 p->vscroll = 0;
235 XSETWINDOW (val, p);
236 XSETFASTINT (p->last_point, 0);
237 p->frozen_window_start_p = 0;
238 return val;
241 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
242 "Return the window that the cursor now appears in and commands apply to.")
245 return selected_window;
248 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
249 "Return the window used now for minibuffers.\n\
250 If the optional argument FRAME is specified, return the minibuffer window\n\
251 used by that frame.")
252 (frame)
253 Lisp_Object frame;
255 if (NILP (frame))
256 frame = selected_frame;
257 CHECK_LIVE_FRAME (frame, 0);
258 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
261 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
262 "Returns non-nil if WINDOW is a minibuffer window.")
263 (window)
264 Lisp_Object window;
266 struct window *w = decode_window (window);
267 return (MINI_WINDOW_P (w) ? Qt : Qnil);
270 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
271 Spos_visible_in_window_p, 0, 2, 0,
272 "Return t if position POS is currently on the frame in WINDOW.\n\
273 Returns nil if that position is scrolled vertically out of view.\n\
274 POS defaults to point; WINDOW, to the selected window.")
275 (pos, window)
276 Lisp_Object pos, window;
278 register struct window *w;
279 register int posint;
280 register struct buffer *buf;
281 struct text_pos top;
282 Lisp_Object in_window;
284 if (NILP (pos))
285 posint = PT;
286 else
288 CHECK_NUMBER_COERCE_MARKER (pos, 0);
289 posint = XINT (pos);
292 w = decode_window (window);
293 buf = XBUFFER (w->buffer);
294 SET_TEXT_POS_FROM_MARKER (top, w->start);
296 /* If position above window, it's not visible. */
297 if (posint < CHARPOS (top))
298 in_window = Qnil;
299 else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
300 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
301 && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
302 /* If frame is up to date, and POSINT is < window end pos, use
303 that info. This doesn't work for POSINT == end pos, because
304 the window end pos is actually the position _after_ the last
305 char in the window. */
306 in_window = Qt;
307 else if (posint > BUF_ZV (buf))
308 in_window = Qnil;
309 else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
310 /* If window start is out of range, do something reasonable. */
311 in_window = Qnil;
312 else
314 struct it it;
315 start_display (&it, w, top);
316 move_it_to (&it, posint, 0, it.last_visible_y, -1,
317 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
318 in_window = IT_CHARPOS (it) == posint ? Qt : Qnil;
321 return in_window;
324 static struct window *
325 decode_window (window)
326 register Lisp_Object window;
328 if (NILP (window))
329 return XWINDOW (selected_window);
331 CHECK_LIVE_WINDOW (window, 0);
332 return XWINDOW (window);
335 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
336 "Return the buffer that WINDOW is displaying.")
337 (window)
338 Lisp_Object window;
340 return decode_window (window)->buffer;
343 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
344 "Return the number of lines in WINDOW (including its mode line).")
345 (window)
346 Lisp_Object window;
348 return decode_window (window)->height;
351 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
352 "Return the number of display columns in WINDOW.\n\
353 This is the width that is usable columns available for text in WINDOW.\n\
354 If you want to find out how many columns WINDOW takes up,\n\
355 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
356 (window)
357 Lisp_Object window;
359 return make_number (window_internal_width (decode_window (window)));
362 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
363 "Return the number of columns by which WINDOW is scrolled from left margin.")
364 (window)
365 Lisp_Object window;
367 return decode_window (window)->hscroll;
370 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
371 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
372 NCOL should be zero or positive.")
373 (window, ncol)
374 register Lisp_Object window, ncol;
376 register struct window *w;
378 CHECK_NUMBER (ncol, 1);
379 if (XINT (ncol) < 0) XSETFASTINT (ncol, 0);
380 w = decode_window (window);
381 if (XINT (w->hscroll) != XINT (ncol))
382 /* Prevent redisplay shortcuts */
383 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
384 w->hscroll = ncol;
385 return ncol;
388 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
389 Swindow_redisplay_end_trigger, 0, 1, 0,
390 "Return WINDOW's redisplay end trigger value.\n\
391 See `set-window-redisplay-end-trigger' for more information.")
392 (window)
393 Lisp_Object window;
395 return decode_window (window)->redisplay_end_trigger;
398 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
399 Sset_window_redisplay_end_trigger, 2, 2, 0,
400 "Set WINDOW's redisplay end trigger value to VALUE.\n\
401 VALUE should be a buffer position (typically a marker) or nil.\n\
402 If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
403 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
404 with two arguments: WINDOW, and the end trigger value.\n\
405 Afterwards the end-trigger value is reset to nil.")
406 (window, value)
407 register Lisp_Object window, value;
409 register struct window *w;
411 w = decode_window (window);
412 w->redisplay_end_trigger = value;
413 return value;
416 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
417 "Return a list of the edge coordinates of WINDOW.\n\
418 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
419 RIGHT is one more than the rightmost column used by WINDOW,\n\
420 and BOTTOM is one more than the bottommost row used by WINDOW\n\
421 and its mode-line.")
422 (window)
423 Lisp_Object window;
425 register struct window *w = decode_window (window);
427 return Fcons (w->left, Fcons (w->top,
428 Fcons (make_number (WINDOW_RIGHT_EDGE (w)),
429 Fcons (make_number (XFASTINT (w->top)
430 + XFASTINT (w->height)),
431 Qnil))));
434 /* Test if the character at column *X, row *Y is within window W.
435 If it is not, return 0;
436 if it is in the window's text area,
437 set *x and *y to its location relative to the upper left corner
438 of the window, and
439 return 1;
440 if it is on the window's modeline, return 2;
441 if it is on the border between the window and its right sibling,
442 return 3.
443 if it is on the window's top line, return 4;
444 if it is in the bitmap area to the left/right of the window,
445 return 5 or 6, and convert *X and *Y to window-relative corrdinates.
447 X and Y are frame relative pixel coordinates. */
449 static int
450 coordinates_in_window (w, x, y)
451 register struct window *w;
452 register int *x, *y;
454 struct frame *f = XFRAME (WINDOW_FRAME (w));
455 int left_x, right_x, top_y, bottom_y;
456 int flags_area_width = FRAME_LEFT_FLAGS_AREA_WIDTH (f);
458 if (w->pseudo_window_p)
460 left_x = 0;
461 right_x = XFASTINT (w->width) * CANON_Y_UNIT (f);
462 top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
463 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
465 else
467 left_x = WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
468 right_x = WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w);
469 top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
470 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
473 if (*y < top_y
474 || *y >= bottom_y
475 || *x < (left_x
476 - flags_area_width
477 - (FRAME_LEFT_SCROLL_BAR_WIDTH (f)
478 * CANON_X_UNIT (f)))
479 || *x > right_x + flags_area_width)
480 /* Completely outside anything interesting. */
481 return 0;
482 else if (WINDOW_WANTS_MODELINE_P (w)
483 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
484 /* On the mode line. */
485 return 2;
486 else if (WINDOW_WANTS_HEADER_LINE_P (w)
487 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
488 /* On the top line. */
489 return 4;
490 else if (*x < left_x || *x >= right_x)
492 /* Other lines than the mode line don't include flags areas and
493 scroll bars on the left. */
495 /* Convert X and Y to window-relative pixel coordinates. */
496 *x -= left_x;
497 *y -= top_y;
498 return *x < left_x ? 5 : 6;
500 else if (!w->pseudo_window_p
501 && !WINDOW_RIGHTMOST_P (w)
502 && *x >= right_x - CANON_X_UNIT (f))
503 /* On the border on the right side of the window? Assume that
504 this area begins at RIGHT_X minus a canonical char width. */
505 return 3;
506 else
508 /* Convert X and Y to window-relative pixel coordinates. */
509 *x -= left_x;
510 *y -= top_y;
511 return 1;
515 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
516 Scoordinates_in_window_p, 2, 2, 0,
517 "Return non-nil if COORDINATES are in WINDOW.\n\
518 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
519 measured in characters from the upper-left corner of the frame.\n\
520 (0 . 0) denotes the character in the upper left corner of the\n\
521 frame.\n\
522 If COORDINATES are in the text portion of WINDOW,\n\
523 the coordinates relative to the window are returned.\n\
524 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
525 If they are in the top mode line of WINDOW, `header-line' is returned.\n\
526 If they are in the bitmap-area to the left of the window,\n\
527 `left-bitmap-area' is returned, if they are in the area on the right of\n\
528 the window, `right-bitmap-area' is returned.\n\
529 If they are on the border between WINDOW and its right sibling,\n\
530 `vertical-line' is returned.")
531 (coordinates, window)
532 register Lisp_Object coordinates, window;
534 struct window *w;
535 struct frame *f;
536 int x, y;
537 Lisp_Object lx, ly;
539 CHECK_LIVE_WINDOW (window, 0);
540 w = XWINDOW (window);
541 f = XFRAME (w->frame);
542 CHECK_CONS (coordinates, 1);
543 lx = Fcar (coordinates);
544 ly = Fcdr (coordinates);
545 CHECK_NUMBER_OR_FLOAT (lx, 1);
546 CHECK_NUMBER_OR_FLOAT (ly, 1);
547 x = PIXEL_X_FROM_CANON_X (f, lx);
548 y = PIXEL_Y_FROM_CANON_Y (f, ly);
550 switch (coordinates_in_window (w, &x, &y))
552 case 0: /* NOT in window at all. */
553 return Qnil;
555 case 1: /* In text part of window. */
556 /* X and Y are now window relative pixel coordinates.
557 Convert them to canonical char units before returning
558 them. */
559 return Fcons (CANON_X_FROM_PIXEL_X (f, x),
560 CANON_Y_FROM_PIXEL_Y (f, y));
562 case 2: /* In mode line of window. */
563 return Qmode_line;
565 case 3: /* On right border of window. */
566 return Qvertical_line;
568 case 4:
569 return Qheader_line;
571 case 5:
572 return Qleft_bitmap_area;
574 case 6:
575 return Qright_bitmap_area;
577 default:
578 abort ();
582 /* Find the window containing frame-relative pixel position X/Y and
583 return it as a Lisp_Object. If X, Y is on the window's modeline,
584 set *PART to 1; if it is on the separating line between the window
585 and its right sibling, set it to 2; otherwise set it to 0. If
586 there is no window under X, Y return nil and leave *PART
587 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows. */
589 Lisp_Object
590 window_from_coordinates (frame, x, y, part, tool_bar_p)
591 FRAME_PTR frame;
592 int x, y;
593 int *part;
594 int tool_bar_p;
596 register Lisp_Object tem, first;
597 int found;
599 tem = first = FRAME_SELECTED_WINDOW (frame);
603 found = coordinates_in_window (XWINDOW (tem), &x, &y);
605 if (found)
607 *part = found - 1;
608 return tem;
611 tem = Fnext_window (tem, Qt, Qlambda);
613 while (!EQ (tem, first));
615 /* See if it's in the tool bar window, if a tool bar exists. */
616 if (tool_bar_p
617 && WINDOWP (frame->tool_bar_window)
618 && XFASTINT (XWINDOW (frame->tool_bar_window)->height)
619 && coordinates_in_window (XWINDOW (frame->tool_bar_window), &x, &y))
621 *part = 0;
622 return frame->tool_bar_window;
625 return Qnil;
628 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
629 "Return window containing coordinates X and Y on FRAME.\n\
630 If omitted, FRAME defaults to the currently selected frame.\n\
631 The top left corner of the frame is considered to be row 0,\n\
632 column 0.")
633 (x, y, frame)
634 Lisp_Object x, y, frame;
636 int part;
637 struct frame *f;
639 if (NILP (frame))
640 frame = selected_frame;
641 CHECK_LIVE_FRAME (frame, 2);
642 f = XFRAME (frame);
644 /* Check that arguments are integers or floats. */
645 CHECK_NUMBER_OR_FLOAT (x, 0);
646 CHECK_NUMBER_OR_FLOAT (y, 1);
648 return window_from_coordinates (f,
649 PIXEL_X_FROM_CANON_X (f, x),
650 PIXEL_Y_FROM_CANON_Y (f, y),
651 &part, 0);
654 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
655 "Return current value of point in WINDOW.\n\
656 For a nonselected window, this is the value point would have\n\
657 if that window were selected.\n\
659 Note that, when WINDOW is the selected window and its buffer\n\
660 is also currently selected, the value returned is the same as (point).\n\
661 It would be more strictly correct to return the `top-level' value\n\
662 of point, outside of any save-excursion forms.\n\
663 But that is hard to define.")
664 (window)
665 Lisp_Object window;
667 register struct window *w = decode_window (window);
669 if (w == XWINDOW (selected_window)
670 && current_buffer == XBUFFER (w->buffer))
671 return Fpoint ();
672 return Fmarker_position (w->pointm);
675 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
676 "Return position at which display currently starts in WINDOW.\n\
677 This is updated by redisplay or by calling `set-window-start'.")
678 (window)
679 Lisp_Object window;
681 return Fmarker_position (decode_window (window)->start);
684 /* This is text temporarily removed from the doc string below.
686 This function returns nil if the position is not currently known.\n\
687 That happens when redisplay is preempted and doesn't finish.\n\
688 If in that case you want to compute where the end of the window would\n\
689 have been if redisplay had finished, do this:\n\
690 (save-excursion\n\
691 (goto-char (window-start window))\n\
692 (vertical-motion (1- (window-height window)) window)\n\
693 (point))") */
695 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
696 "Return position at which display currently ends in WINDOW.\n\
697 This is updated by redisplay, when it runs to completion.\n\
698 Simply changing the buffer text or setting `window-start'\n\
699 does not update this value.\n\
700 If UP-TO-DATE is non-nil, compute the up-to-date position\n\
701 if it isn't already recorded.")
702 (window, update)
703 Lisp_Object window, update;
705 Lisp_Object value;
706 struct window *w = decode_window (window);
707 Lisp_Object buf;
709 buf = w->buffer;
710 CHECK_BUFFER (buf, 0);
712 #if 0 /* This change broke some things. We should make it later. */
713 /* If we don't know the end position, return nil.
714 The user can compute it with vertical-motion if he wants to.
715 It would be nicer to do it automatically,
716 but that's so slow that it would probably bother people. */
717 if (NILP (w->window_end_valid))
718 return Qnil;
719 #endif
721 if (! NILP (update)
722 && ! (! NILP (w->window_end_valid)
723 && XFASTINT (w->last_modified) >= MODIFF))
725 int opoint = PT, opoint_byte = PT_BYTE;
727 /* In case W->start is out of the range, use something
728 reasonable. This situation occured when loading a file with
729 `-l' containing a call to `rmail' with subsequent other
730 commands. At the end, W->start happened to be BEG, while
731 rmail had already narrowed the buffer. This leads to an
732 abort in temp_set_pt_both. */
733 if (XMARKER (w->start)->charpos < BEGV)
734 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
735 else if (XMARKER (w->start)->charpos > ZV)
736 TEMP_SET_PT_BOTH (ZV, ZV_BYTE);
737 else
738 TEMP_SET_PT_BOTH (XMARKER (w->start)->charpos,
739 XMARKER (w->start)->bytepos);
741 Fvertical_motion (make_number (window_internal_height (w)), Qnil);
742 XSETINT (value, PT);
743 TEMP_SET_PT_BOTH (opoint, opoint_byte);
745 else
746 XSETINT (value,
747 BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
749 return value;
752 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
753 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
754 (window, pos)
755 Lisp_Object window, pos;
757 register struct window *w = decode_window (window);
759 CHECK_NUMBER_COERCE_MARKER (pos, 1);
760 if (w == XWINDOW (selected_window)
761 && XBUFFER (w->buffer) == current_buffer)
762 Fgoto_char (pos);
763 else
764 set_marker_restricted (w->pointm, pos, w->buffer);
766 return pos;
769 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
770 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
771 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
772 from overriding motion of point in order to display at this exact start.")
773 (window, pos, noforce)
774 Lisp_Object window, pos, noforce;
776 register struct window *w = decode_window (window);
778 CHECK_NUMBER_COERCE_MARKER (pos, 1);
779 set_marker_restricted (w->start, pos, w->buffer);
780 /* this is not right, but much easier than doing what is right. */
781 w->start_at_line_beg = Qnil;
782 if (NILP (noforce))
783 w->force_start = Qt;
784 w->update_mode_line = Qt;
785 XSETFASTINT (w->last_modified, 0);
786 XSETFASTINT (w->last_overlay_modified, 0);
787 if (!EQ (window, selected_window))
788 windows_or_buffers_changed++;
790 return pos;
793 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
794 1, 1, 0,
795 "Return WINDOW's dedicated object, usually t or nil.\n\
796 See also `set-window-dedicated-p'.")
797 (window)
798 Lisp_Object window;
800 return decode_window (window)->dedicated;
803 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
804 Sset_window_dedicated_p, 2, 2, 0,
805 "Control whether WINDOW is dedicated to the buffer it displays.\n\
806 If it is dedicated, Emacs will not automatically change\n\
807 which buffer appears in it.\n\
808 The second argument is the new value for the dedication flag;\n\
809 non-nil means yes.")
810 (window, arg)
811 Lisp_Object window, arg;
813 register struct window *w = decode_window (window);
815 if (NILP (arg))
816 w->dedicated = Qnil;
817 else
818 w->dedicated = Qt;
820 return w->dedicated;
823 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
824 0, 1, 0,
825 "Return the display-table that WINDOW is using.")
826 (window)
827 Lisp_Object window;
829 return decode_window (window)->display_table;
832 /* Get the display table for use on window W. This is either W's
833 display table or W's buffer's display table. Ignore the specified
834 tables if they are not valid; if no valid table is specified,
835 return 0. */
837 struct Lisp_Char_Table *
838 window_display_table (w)
839 struct window *w;
841 Lisp_Object tem;
842 tem = w->display_table;
843 if (DISP_TABLE_P (tem))
844 return XCHAR_TABLE (tem);
845 if (NILP (w->buffer))
846 return 0;
848 tem = XBUFFER (w->buffer)->display_table;
849 if (DISP_TABLE_P (tem))
850 return XCHAR_TABLE (tem);
851 tem = Vstandard_display_table;
852 if (DISP_TABLE_P (tem))
853 return XCHAR_TABLE (tem);
854 return 0;
857 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
858 "Set WINDOW's display-table to TABLE.")
859 (window, table)
860 register Lisp_Object window, table;
862 register struct window *w;
864 w = decode_window (window);
865 w->display_table = table;
866 return table;
869 /* Record info on buffer window w is displaying
870 when it is about to cease to display that buffer. */
871 static void
872 unshow_buffer (w)
873 register struct window *w;
875 Lisp_Object buf;
876 struct buffer *b;
878 buf = w->buffer;
879 b = XBUFFER (buf);
880 if (b != XMARKER (w->pointm)->buffer)
881 abort ();
883 if (w == XWINDOW (b->last_selected_window))
884 b->last_selected_window = Qnil;
886 #if 0
887 if (w == XWINDOW (selected_window)
888 || ! EQ (buf, XWINDOW (selected_window)->buffer))
889 /* Do this except when the selected window's buffer
890 is being removed from some other window. */
891 #endif
892 /* last_window_start records the start position that this buffer
893 had in the last window to be disconnected from it.
894 Now that this statement is unconditional,
895 it is possible for the buffer to be displayed in the
896 selected window, while last_window_start reflects another
897 window which was recently showing the same buffer.
898 Some people might say that might be a good thing. Let's see. */
899 b->last_window_start = marker_position (w->start);
901 /* Point in the selected window's buffer
902 is actually stored in that buffer, and the window's pointm isn't used.
903 So don't clobber point in that buffer. */
904 if (! EQ (buf, XWINDOW (selected_window)->buffer))
905 temp_set_point_both (b,
906 clip_to_bounds (BUF_BEGV (b),
907 XMARKER (w->pointm)->charpos,
908 BUF_ZV (b)),
909 clip_to_bounds (BUF_BEGV_BYTE (b),
910 marker_byte_position (w->pointm),
911 BUF_ZV_BYTE (b)));
914 /* Put replacement into the window structure in place of old. */
915 static void
916 replace_window (old, replacement)
917 Lisp_Object old, replacement;
919 register Lisp_Object tem;
920 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
922 /* If OLD is its frame's root_window, then replacement is the new
923 root_window for that frame. */
925 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
926 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
928 p->left = o->left;
929 p->top = o->top;
930 p->width = o->width;
931 p->height = o->height;
932 p->desired_matrix = p->current_matrix = 0;
933 p->vscroll = 0;
934 bzero (&p->cursor, sizeof (p->cursor));
935 bzero (&p->last_cursor, sizeof (p->last_cursor));
936 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
937 p->phys_cursor_type = -1;
938 p->must_be_updated_p = 0;
939 p->pseudo_window_p = 0;
940 XSETFASTINT (p->window_end_vpos, 0);
941 XSETFASTINT (p->window_end_pos, 0);
942 p->window_end_valid = Qnil;
943 p->frozen_window_start_p = 0;
944 p->orig_top = p->orig_height = Qnil;
946 p->next = tem = o->next;
947 if (!NILP (tem))
948 XWINDOW (tem)->prev = replacement;
950 p->prev = tem = o->prev;
951 if (!NILP (tem))
952 XWINDOW (tem)->next = replacement;
954 p->parent = tem = o->parent;
955 if (!NILP (tem))
957 if (EQ (XWINDOW (tem)->vchild, old))
958 XWINDOW (tem)->vchild = replacement;
959 if (EQ (XWINDOW (tem)->hchild, old))
960 XWINDOW (tem)->hchild = replacement;
963 /*** Here, if replacement is a vertical combination
964 and so is its new parent, we should make replacement's
965 children be children of that parent instead. ***/
968 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
969 "Remove WINDOW from the display. Default is selected window.")
970 (window)
971 register Lisp_Object window;
973 delete_window (window);
975 if (! NILP (Vwindow_configuration_change_hook)
976 && ! NILP (Vrun_hooks))
977 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
979 return Qnil;
982 void
983 delete_window (window)
984 register Lisp_Object window;
986 register Lisp_Object tem, parent, sib;
987 register struct window *p;
988 register struct window *par;
989 FRAME_PTR frame;
991 /* Because this function is called by other C code on non-leaf
992 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
993 so we can't decode_window here. */
994 if (NILP (window))
995 window = selected_window;
996 else
997 CHECK_WINDOW (window, 0);
998 p = XWINDOW (window);
1000 /* It's okay to delete an already-deleted window. */
1001 if (NILP (p->buffer)
1002 && NILP (p->hchild)
1003 && NILP (p->vchild))
1004 return;
1006 parent = p->parent;
1007 if (NILP (parent))
1008 error ("Attempt to delete minibuffer or sole ordinary window");
1009 par = XWINDOW (parent);
1011 windows_or_buffers_changed++;
1012 frame = XFRAME (WINDOW_FRAME (p));
1013 FRAME_WINDOW_SIZES_CHANGED (frame) = 1;
1015 /* Are we trying to delete any frame's selected window? */
1017 Lisp_Object frame, pwindow;
1019 /* See if the frame's selected window is either WINDOW
1020 or any subwindow of it, by finding all that window's parents
1021 and comparing each one with WINDOW. */
1022 frame = WINDOW_FRAME (XWINDOW (window));
1023 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
1025 while (!NILP (pwindow))
1027 if (EQ (window, pwindow))
1028 break;
1029 pwindow = XWINDOW (pwindow)->parent;
1032 if (EQ (window, pwindow))
1034 Lisp_Object alternative;
1035 alternative = Fnext_window (window, Qlambda, Qnil);
1037 /* If we're about to delete the selected window on the
1038 selected frame, then we should use Fselect_window to select
1039 the new window. On the other hand, if we're about to
1040 delete the selected window on any other frame, we shouldn't do
1041 anything but set the frame's selected_window slot. */
1042 if (EQ (window, selected_window))
1043 Fselect_window (alternative);
1044 else
1045 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
1049 tem = p->buffer;
1050 /* tem is null for dummy parent windows
1051 (which have inferiors but not any contents themselves) */
1052 if (!NILP (tem))
1054 unshow_buffer (p);
1055 unchain_marker (p->pointm);
1056 unchain_marker (p->start);
1059 /* Free window glyph matrices. It is sure that they are allocated
1060 again when ADJUST_GLYPHS is called. Block input so that expose
1061 events and other events that access glyph matrices are not
1062 processed while we are changing them. */
1063 BLOCK_INPUT;
1064 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (frame)));
1066 tem = p->next;
1067 if (!NILP (tem))
1068 XWINDOW (tem)->prev = p->prev;
1070 tem = p->prev;
1071 if (!NILP (tem))
1072 XWINDOW (tem)->next = p->next;
1074 if (EQ (window, par->hchild))
1075 par->hchild = p->next;
1076 if (EQ (window, par->vchild))
1077 par->vchild = p->next;
1079 /* Find one of our siblings to give our space to. */
1080 sib = p->prev;
1081 if (NILP (sib))
1083 /* If p gives its space to its next sibling, that sibling needs
1084 to have its top/left side pulled back to where p's is.
1085 set_window_{height,width} will re-position the sibling's
1086 children. */
1087 sib = p->next;
1088 XWINDOW (sib)->top = p->top;
1089 XWINDOW (sib)->left = p->left;
1092 /* Stretch that sibling. */
1093 if (!NILP (par->vchild))
1094 set_window_height (sib,
1095 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
1097 if (!NILP (par->hchild))
1098 set_window_width (sib,
1099 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
1102 /* If parent now has only one child,
1103 put the child into the parent's place. */
1104 tem = par->hchild;
1105 if (NILP (tem))
1106 tem = par->vchild;
1107 if (NILP (XWINDOW (tem)->next))
1108 replace_window (parent, tem);
1110 /* Since we may be deleting combination windows, we must make sure that
1111 not only p but all its children have been marked as deleted. */
1112 if (! NILP (p->hchild))
1113 delete_all_subwindows (XWINDOW (p->hchild));
1114 else if (! NILP (p->vchild))
1115 delete_all_subwindows (XWINDOW (p->vchild));
1117 /* Mark this window as deleted. */
1118 p->buffer = p->hchild = p->vchild = Qnil;
1120 /* Adjust glyph matrices. */
1121 adjust_glyphs (frame);
1122 UNBLOCK_INPUT;
1126 extern Lisp_Object next_frame (), prev_frame ();
1128 /* This comment supplies the doc string for `next-window',
1129 for make-docfile to see. We cannot put this in the real DEFUN
1130 due to limits in the Unix cpp.
1132 DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
1133 "Return next window after WINDOW in canonical ordering of windows.\n\
1134 If omitted, WINDOW defaults to the selected window.\n\
1136 Optional second arg MINIBUF t means count the minibuffer window even\n\
1137 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1138 it is active. MINIBUF neither t nor nil means not to count the\n\
1139 minibuffer even if it is active.\n\
1141 Several frames may share a single minibuffer; if the minibuffer\n\
1142 counts, all windows on all frames that share that minibuffer count\n\
1143 too. Therefore, `next-window' can be used to iterate through the\n\
1144 set of windows even when the minibuffer is on another frame. If the\n\
1145 minibuffer does not count, only windows from WINDOW's frame count.\n\
1147 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1148 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1149 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1150 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1151 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1152 Anything else means restrict to WINDOW's frame.\n\
1154 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1155 `next-window' to iterate through the entire cycle of acceptable\n\
1156 windows, eventually ending up back at the window you started with.\n\
1157 `previous-window' traverses the same cycle, in the reverse order.")
1158 (window, minibuf, all_frames) */
1160 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1162 (window, minibuf, all_frames)
1163 register Lisp_Object window, minibuf, all_frames;
1165 register Lisp_Object tem;
1166 Lisp_Object start_window;
1168 if (NILP (window))
1169 window = selected_window;
1170 else
1171 CHECK_LIVE_WINDOW (window, 0);
1173 start_window = window;
1175 /* minibuf == nil may or may not include minibuffers.
1176 Decide if it does. */
1177 if (NILP (minibuf))
1178 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1179 else if (! EQ (minibuf, Qt))
1180 minibuf = Qlambda;
1181 /* Now minibuf can be t => count all minibuffer windows,
1182 lambda => count none of them,
1183 or a specific minibuffer window (the active one) to count. */
1185 /* all_frames == nil doesn't specify which frames to include. */
1186 if (NILP (all_frames))
1187 all_frames = (! EQ (minibuf, Qlambda)
1188 ? (FRAME_MINIBUF_WINDOW
1189 (XFRAME
1190 (WINDOW_FRAME
1191 (XWINDOW (window)))))
1192 : Qnil);
1193 else if (EQ (all_frames, Qvisible))
1195 else if (XFASTINT (all_frames) == 0)
1197 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1198 /* If all_frames is a frame and window arg isn't on that frame, just
1199 return the first window on the frame. */
1200 return Fframe_first_window (all_frames);
1201 else if (! EQ (all_frames, Qt))
1202 all_frames = Qnil;
1203 /* Now all_frames is t meaning search all frames,
1204 nil meaning search just current frame,
1205 visible meaning search just visible frames,
1206 0 meaning search visible and iconified frames,
1207 or a window, meaning search the frame that window belongs to. */
1209 /* Do this loop at least once, to get the next window, and perhaps
1210 again, if we hit the minibuffer and that is not acceptable. */
1213 /* Find a window that actually has a next one. This loop
1214 climbs up the tree. */
1215 while (tem = XWINDOW (window)->next, NILP (tem))
1216 if (tem = XWINDOW (window)->parent, !NILP (tem))
1217 window = tem;
1218 else
1220 /* We've reached the end of this frame.
1221 Which other frames are acceptable? */
1222 tem = WINDOW_FRAME (XWINDOW (window));
1223 if (! NILP (all_frames))
1225 Lisp_Object tem1;
1227 tem1 = tem;
1228 tem = next_frame (tem, all_frames);
1229 /* In the case where the minibuffer is active,
1230 and we include its frame as well as the selected one,
1231 next_frame may get stuck in that frame.
1232 If that happens, go back to the selected frame
1233 so we can complete the cycle. */
1234 if (EQ (tem, tem1))
1235 tem = selected_frame;
1237 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1239 break;
1242 window = tem;
1244 /* If we're in a combination window, find its first child and
1245 recurse on that. Otherwise, we've found the window we want. */
1246 while (1)
1248 if (!NILP (XWINDOW (window)->hchild))
1249 window = XWINDOW (window)->hchild;
1250 else if (!NILP (XWINDOW (window)->vchild))
1251 window = XWINDOW (window)->vchild;
1252 else break;
1255 QUIT;
1257 /* Which windows are acceptable?
1258 Exit the loop and accept this window if
1259 this isn't a minibuffer window,
1260 or we're accepting all minibuffer windows,
1261 or this is the active minibuffer and we are accepting that one, or
1262 we've come all the way around and we're back at the original window. */
1263 while (MINI_WINDOW_P (XWINDOW (window))
1264 && ! EQ (minibuf, Qt)
1265 && ! EQ (minibuf, window)
1266 && ! EQ (window, start_window));
1268 return window;
1271 /* This comment supplies the doc string for `previous-window',
1272 for make-docfile to see. We cannot put this in the real DEFUN
1273 due to limits in the Unix cpp.
1275 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
1276 "Return the window preceding WINDOW in canonical ordering of windows.\n\
1277 If omitted, WINDOW defaults to the selected window.\n\
1279 Optional second arg MINIBUF t means count the minibuffer window even\n\
1280 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1281 it is active. MINIBUF neither t nor nil means not to count the\n\
1282 minibuffer even if it is active.\n\
1284 Several frames may share a single minibuffer; if the minibuffer\n\
1285 counts, all windows on all frames that share that minibuffer count\n\
1286 too. Therefore, `previous-window' can be used to iterate through\n\
1287 the set of windows even when the minibuffer is on another frame. If\n\
1288 the minibuffer does not count, only windows from WINDOW's frame count\n\
1290 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1291 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1292 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1293 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1294 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1295 Anything else means restrict to WINDOW's frame.\n\
1297 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1298 `previous-window' to iterate through the entire cycle of acceptable\n\
1299 windows, eventually ending up back at the window you started with.\n\
1300 `next-window' traverses the same cycle, in the reverse order.")
1301 (window, minibuf, all_frames) */
1304 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1306 (window, minibuf, all_frames)
1307 register Lisp_Object window, minibuf, all_frames;
1309 register Lisp_Object tem;
1310 Lisp_Object start_window;
1312 if (NILP (window))
1313 window = selected_window;
1314 else
1315 CHECK_LIVE_WINDOW (window, 0);
1317 start_window = window;
1319 /* minibuf == nil may or may not include minibuffers.
1320 Decide if it does. */
1321 if (NILP (minibuf))
1322 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1323 else if (! EQ (minibuf, Qt))
1324 minibuf = Qlambda;
1325 /* Now minibuf can be t => count all minibuffer windows,
1326 lambda => count none of them,
1327 or a specific minibuffer window (the active one) to count. */
1329 /* all_frames == nil doesn't specify which frames to include.
1330 Decide which frames it includes. */
1331 if (NILP (all_frames))
1332 all_frames = (! EQ (minibuf, Qlambda)
1333 ? (FRAME_MINIBUF_WINDOW
1334 (XFRAME
1335 (WINDOW_FRAME
1336 (XWINDOW (window)))))
1337 : Qnil);
1338 else if (EQ (all_frames, Qvisible))
1340 else if (XFASTINT (all_frames) == 0)
1342 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1343 /* If all_frames is a frame and window arg isn't on that frame, just
1344 return the first window on the frame. */
1345 return Fframe_first_window (all_frames);
1346 else if (! EQ (all_frames, Qt))
1347 all_frames = Qnil;
1348 /* Now all_frames is t meaning search all frames,
1349 nil meaning search just current frame,
1350 visible meaning search just visible frames,
1351 0 meaning search visible and iconified frames,
1352 or a window, meaning search the frame that window belongs to. */
1354 /* Do this loop at least once, to get the previous window, and perhaps
1355 again, if we hit the minibuffer and that is not acceptable. */
1358 /* Find a window that actually has a previous one. This loop
1359 climbs up the tree. */
1360 while (tem = XWINDOW (window)->prev, NILP (tem))
1361 if (tem = XWINDOW (window)->parent, !NILP (tem))
1362 window = tem;
1363 else
1365 /* We have found the top window on the frame.
1366 Which frames are acceptable? */
1367 tem = WINDOW_FRAME (XWINDOW (window));
1368 if (! NILP (all_frames))
1369 /* It's actually important that we use prev_frame here,
1370 rather than next_frame. All the windows acceptable
1371 according to the given parameters should form a ring;
1372 Fnext_window and Fprevious_window should go back and
1373 forth around the ring. If we use next_frame here,
1374 then Fnext_window and Fprevious_window take different
1375 paths through the set of acceptable windows.
1376 window_loop assumes that these `ring' requirement are
1377 met. */
1379 Lisp_Object tem1;
1381 tem1 = tem;
1382 tem = prev_frame (tem, all_frames);
1383 /* In the case where the minibuffer is active,
1384 and we include its frame as well as the selected one,
1385 next_frame may get stuck in that frame.
1386 If that happens, go back to the selected frame
1387 so we can complete the cycle. */
1388 if (EQ (tem, tem1))
1389 tem = selected_frame;
1391 /* If this frame has a minibuffer, find that window first,
1392 because it is conceptually the last window in that frame. */
1393 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
1394 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
1395 else
1396 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1398 break;
1401 window = tem;
1402 /* If we're in a combination window, find its last child and
1403 recurse on that. Otherwise, we've found the window we want. */
1404 while (1)
1406 if (!NILP (XWINDOW (window)->hchild))
1407 window = XWINDOW (window)->hchild;
1408 else if (!NILP (XWINDOW (window)->vchild))
1409 window = XWINDOW (window)->vchild;
1410 else break;
1411 while (tem = XWINDOW (window)->next, !NILP (tem))
1412 window = tem;
1415 /* Which windows are acceptable?
1416 Exit the loop and accept this window if
1417 this isn't a minibuffer window,
1418 or we're accepting all minibuffer windows,
1419 or this is the active minibuffer and we are accepting that one, or
1420 we've come all the way around and we're back at the original window. */
1421 while (MINI_WINDOW_P (XWINDOW (window))
1422 && ! EQ (minibuf, Qt)
1423 && ! EQ (minibuf, window)
1424 && ! EQ (window, start_window));
1426 return window;
1429 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1430 "Select the ARG'th different window on this frame.\n\
1431 All windows on current frame are arranged in a cyclic order.\n\
1432 This command selects the window ARG steps away in that order.\n\
1433 A negative ARG moves in the opposite order. If the optional second\n\
1434 argument ALL_FRAMES is non-nil, cycle through all frames.")
1435 (arg, all_frames)
1436 register Lisp_Object arg, all_frames;
1438 register int i;
1439 register Lisp_Object w;
1441 CHECK_NUMBER (arg, 0);
1442 w = selected_window;
1443 i = XINT (arg);
1445 while (i > 0)
1447 w = Fnext_window (w, Qnil, all_frames);
1448 i--;
1450 while (i < 0)
1452 w = Fprevious_window (w, Qnil, all_frames);
1453 i++;
1455 Fselect_window (w);
1456 return Qnil;
1459 /* Look at all windows, performing an operation specified by TYPE
1460 with argument OBJ.
1461 If FRAMES is Qt, look at all frames;
1462 Qnil, look at just the selected frame;
1463 Qvisible, look at visible frames;
1464 a frame, just look at windows on that frame.
1465 If MINI is non-zero, perform the operation on minibuffer windows too.
1468 enum window_loop
1470 WINDOW_LOOP_UNUSED,
1471 GET_BUFFER_WINDOW, /* Arg is buffer */
1472 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1473 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1474 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1475 GET_LARGEST_WINDOW,
1476 UNSHOW_BUFFER, /* Arg is buffer */
1477 CHECK_ALL_WINDOWS
1480 static Lisp_Object
1481 window_loop (type, obj, mini, frames)
1482 enum window_loop type;
1483 register Lisp_Object obj, frames;
1484 int mini;
1486 register Lisp_Object w;
1487 register Lisp_Object best_window;
1488 register Lisp_Object next_window;
1489 register Lisp_Object last_window;
1490 FRAME_PTR frame;
1491 Lisp_Object frame_arg;
1492 frame_arg = Qt;
1494 /* If we're only looping through windows on a particular frame,
1495 frame points to that frame. If we're looping through windows
1496 on all frames, frame is 0. */
1497 if (FRAMEP (frames))
1498 frame = XFRAME (frames);
1499 else if (NILP (frames))
1500 frame = SELECTED_FRAME ();
1501 else
1502 frame = 0;
1503 if (frame)
1504 frame_arg = Qlambda;
1505 else if (XFASTINT (frames) == 0)
1506 frame_arg = frames;
1507 else if (EQ (frames, Qvisible))
1508 frame_arg = frames;
1510 /* frame_arg is Qlambda to stick to one frame,
1511 Qvisible to consider all visible frames,
1512 or Qt otherwise. */
1514 /* Pick a window to start with. */
1515 if (WINDOWP (obj))
1516 w = obj;
1517 else if (frame)
1518 w = FRAME_SELECTED_WINDOW (frame);
1519 else
1520 w = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1522 /* Figure out the last window we're going to mess with. Since
1523 Fnext_window, given the same options, is guaranteed to go in a
1524 ring, we can just use Fprevious_window to find the last one.
1526 We can't just wait until we hit the first window again, because
1527 it might be deleted. */
1529 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
1531 best_window = Qnil;
1532 for (;;)
1534 /* Pick the next window now, since some operations will delete
1535 the current window. */
1536 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
1538 /* Note that we do not pay attention here to whether
1539 the frame is visible, since Fnext_window skips non-visible frames
1540 if that is desired, under the control of frame_arg. */
1541 if (! MINI_WINDOW_P (XWINDOW (w))
1542 /* For UNSHOW_BUFFER, we must always consider all windows. */
1543 || type == UNSHOW_BUFFER
1544 || (mini && minibuf_level > 0))
1545 switch (type)
1547 case GET_BUFFER_WINDOW:
1548 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj)
1549 /* Don't find any minibuffer window
1550 except the one that is currently in use. */
1551 && (MINI_WINDOW_P (XWINDOW (w))
1552 ? EQ (w, minibuf_window) : 1))
1553 return w;
1554 break;
1556 case GET_LRU_WINDOW:
1557 /* t as arg means consider only full-width windows */
1558 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (XWINDOW (w)))
1559 break;
1560 /* Ignore dedicated windows and minibuffers. */
1561 if (MINI_WINDOW_P (XWINDOW (w))
1562 || !NILP (XWINDOW (w)->dedicated))
1563 break;
1564 if (NILP (best_window)
1565 || (XFASTINT (XWINDOW (best_window)->use_time)
1566 > XFASTINT (XWINDOW (w)->use_time)))
1567 best_window = w;
1568 break;
1570 case DELETE_OTHER_WINDOWS:
1571 if (XWINDOW (w) != XWINDOW (obj))
1572 Fdelete_window (w);
1573 break;
1575 case DELETE_BUFFER_WINDOWS:
1576 if (EQ (XWINDOW (w)->buffer, obj))
1578 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1580 /* If this window is dedicated, and in a frame of its own,
1581 kill the frame. */
1582 if (EQ (w, FRAME_ROOT_WINDOW (f))
1583 && !NILP (XWINDOW (w)->dedicated)
1584 && other_visible_frames (f))
1586 /* Skip the other windows on this frame.
1587 There might be one, the minibuffer! */
1588 if (! EQ (w, last_window))
1589 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1591 /* As we go, check for the end of the loop.
1592 We mustn't start going around a second time. */
1593 if (EQ (next_window, last_window))
1595 last_window = w;
1596 break;
1598 next_window = Fnext_window (next_window,
1599 mini ? Qt : Qnil,
1600 frame_arg);
1602 /* Now we can safely delete the frame. */
1603 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
1605 else
1606 /* If we're deleting the buffer displayed in the only window
1607 on the frame, find a new buffer to display there. */
1608 if (NILP (XWINDOW (w)->parent))
1610 Lisp_Object new_buffer;
1611 new_buffer = Fother_buffer (obj, Qnil,
1612 XWINDOW (w)->frame);
1613 if (NILP (new_buffer))
1614 new_buffer
1615 = Fget_buffer_create (build_string ("*scratch*"));
1616 Fset_window_buffer (w, new_buffer);
1617 if (EQ (w, selected_window))
1618 Fset_buffer (XWINDOW (w)->buffer);
1620 else
1621 Fdelete_window (w);
1623 break;
1625 case GET_LARGEST_WINDOW:
1626 /* Ignore dedicated windows and minibuffers. */
1627 if (MINI_WINDOW_P (XWINDOW (w))
1628 || !NILP (XWINDOW (w)->dedicated))
1629 break;
1631 struct window *best_window_ptr = XWINDOW (best_window);
1632 struct window *w_ptr = XWINDOW (w);
1633 if (NILP (best_window)
1634 || (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width)
1635 > (XFASTINT (best_window_ptr->height)
1636 * XFASTINT (best_window_ptr->width))))
1637 best_window = w;
1639 break;
1641 case UNSHOW_BUFFER:
1642 if (EQ (XWINDOW (w)->buffer, obj))
1644 /* Find another buffer to show in this window. */
1645 Lisp_Object another_buffer;
1646 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1647 another_buffer = Fother_buffer (obj, Qnil, XWINDOW (w)->frame);
1648 if (NILP (another_buffer))
1649 another_buffer
1650 = Fget_buffer_create (build_string ("*scratch*"));
1651 /* If this window is dedicated, and in a frame of its own,
1652 kill the frame. */
1653 if (EQ (w, FRAME_ROOT_WINDOW (f))
1654 && !NILP (XWINDOW (w)->dedicated)
1655 && other_visible_frames (f))
1657 /* Skip the other windows on this frame.
1658 There might be one, the minibuffer! */
1659 if (! EQ (w, last_window))
1660 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1662 /* As we go, check for the end of the loop.
1663 We mustn't start going around a second time. */
1664 if (EQ (next_window, last_window))
1666 last_window = w;
1667 break;
1669 next_window = Fnext_window (next_window,
1670 mini ? Qt : Qnil,
1671 frame_arg);
1673 /* Now we can safely delete the frame. */
1674 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
1676 else
1678 /* Otherwise show a different buffer in the window. */
1679 XWINDOW (w)->dedicated = Qnil;
1680 Fset_window_buffer (w, another_buffer);
1681 if (EQ (w, selected_window))
1682 Fset_buffer (XWINDOW (w)->buffer);
1685 break;
1687 /* Check for a window that has a killed buffer. */
1688 case CHECK_ALL_WINDOWS:
1689 if (! NILP (XWINDOW (w)->buffer)
1690 && NILP (XBUFFER (XWINDOW (w)->buffer)->name))
1691 abort ();
1694 if (EQ (w, last_window))
1695 break;
1697 w = next_window;
1700 return best_window;
1703 /* Used for debugging. Abort if any window has a dead buffer. */
1705 void
1706 check_all_windows ()
1708 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
1711 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1712 "Return the window least recently selected or used for display.\n\
1713 If optional argument FRAME is `visible', search all visible frames.\n\
1714 If FRAME is 0, search all visible and iconified frames.\n\
1715 If FRAME is t, search all frames.\n\
1716 If FRAME is nil, search only the selected frame.\n\
1717 If FRAME is a frame, search only that frame.")
1718 (frame)
1719 Lisp_Object frame;
1721 register Lisp_Object w;
1722 /* First try for a window that is full-width */
1723 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
1724 if (!NILP (w) && !EQ (w, selected_window))
1725 return w;
1726 /* If none of them, try the rest */
1727 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
1730 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1731 "Return the largest window in area.\n\
1732 If optional argument FRAME is `visible', search all visible frames.\n\
1733 If FRAME is 0, search all visible and iconified frames.\n\
1734 If FRAME is t, search all frames.\n\
1735 If FRAME is nil, search only the selected frame.\n\
1736 If FRAME is a frame, search only that frame.")
1737 (frame)
1738 Lisp_Object frame;
1740 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
1741 frame);
1744 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1745 "Return a window currently displaying BUFFER, or nil if none.\n\
1746 If optional argument FRAME is `visible', search all visible frames.\n\
1747 If optional argument FRAME is 0, search all visible and iconified frames.\n\
1748 If FRAME is t, search all frames.\n\
1749 If FRAME is nil, search only the selected frame.\n\
1750 If FRAME is a frame, search only that frame.")
1751 (buffer, frame)
1752 Lisp_Object buffer, frame;
1754 buffer = Fget_buffer (buffer);
1755 if (BUFFERP (buffer))
1756 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
1757 else
1758 return Qnil;
1761 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1762 0, 1, "",
1763 "Make WINDOW (or the selected window) fill its frame.\n\
1764 Only the frame WINDOW is on is affected.\n\
1765 This function tries to reduce display jumps\n\
1766 by keeping the text previously visible in WINDOW\n\
1767 in the same place on the frame. Doing this depends on\n\
1768 the value of (window-start WINDOW), so if calling this function\n\
1769 in a program gives strange scrolling, make sure the window-start\n\
1770 value is reasonable when this function is called.")
1771 (window)
1772 Lisp_Object window;
1774 struct window *w;
1775 int startpos;
1776 int top;
1778 if (NILP (window))
1779 window = selected_window;
1780 else
1781 CHECK_LIVE_WINDOW (window, 0);
1783 w = XWINDOW (window);
1785 startpos = marker_position (w->start);
1786 top = XFASTINT (w->top) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
1788 if (MINI_WINDOW_P (w) && top > 0)
1789 error ("Can't expand minibuffer to full frame");
1791 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
1793 /* Try to minimize scrolling, by setting the window start to the point
1794 will cause the text at the old window start to be at the same place
1795 on the frame. But don't try to do this if the window start is
1796 outside the visible portion (as might happen when the display is
1797 not current, due to typeahead). */
1798 if (startpos >= BUF_BEGV (XBUFFER (w->buffer))
1799 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
1801 struct position pos;
1802 struct buffer *obuf = current_buffer;
1804 Fset_buffer (w->buffer);
1805 /* This computation used to temporarily move point, but that can
1806 have unwanted side effects due to text properties. */
1807 pos = *vmotion (startpos, -top, w);
1809 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
1810 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
1811 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
1812 : Qnil);
1813 /* We need to do this, so that the window-scroll-functions
1814 get called. */
1815 w->optional_new_start = Qt;
1817 set_buffer_internal (obuf);
1820 return Qnil;
1823 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1824 1, 2, "bDelete windows on (buffer): ",
1825 "Delete all windows showing BUFFER.\n\
1826 Optional second argument FRAME controls which frames are affected.\n\
1827 If optional argument FRAME is `visible', search all visible frames.\n\
1828 If FRAME is 0, search all visible and iconified frames.\n\
1829 If FRAME is nil, search all frames.\n\
1830 If FRAME is t, search only the selected frame.\n\
1831 If FRAME is a frame, search only that frame.")
1832 (buffer, frame)
1833 Lisp_Object buffer, frame;
1835 /* FRAME uses t and nil to mean the opposite of what window_loop
1836 expects. */
1837 if (NILP (frame))
1838 frame = Qt;
1839 else if (EQ (frame, Qt))
1840 frame = Qnil;
1842 if (!NILP (buffer))
1844 buffer = Fget_buffer (buffer);
1845 CHECK_BUFFER (buffer, 0);
1846 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
1849 return Qnil;
1852 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1853 Sreplace_buffer_in_windows,
1854 1, 1, "bReplace buffer in windows: ",
1855 "Replace BUFFER with some other buffer in all windows showing it.")
1856 (buffer)
1857 Lisp_Object buffer;
1859 if (!NILP (buffer))
1861 buffer = Fget_buffer (buffer);
1862 CHECK_BUFFER (buffer, 0);
1863 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1865 return Qnil;
1868 /* Replace BUFFER with some other buffer in all windows
1869 of all frames, even those on other keyboards. */
1871 void
1872 replace_buffer_in_all_windows (buffer)
1873 Lisp_Object buffer;
1875 #ifdef MULTI_KBOARD
1876 Lisp_Object tail, frame;
1878 /* A single call to window_loop won't do the job
1879 because it only considers frames on the current keyboard.
1880 So loop manually over frames, and handle each one. */
1881 FOR_EACH_FRAME (tail, frame)
1882 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
1883 #else
1884 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
1885 #endif
1888 /* Set the height of WINDOW and all its inferiors. */
1890 /* The smallest acceptable dimensions for a window. Anything smaller
1891 might crash Emacs. */
1893 #define MIN_SAFE_WINDOW_WIDTH (2)
1894 #define MIN_SAFE_WINDOW_HEIGHT (2)
1896 /* Make sure that window_min_height and window_min_width are
1897 not too small; if they are, set them to safe minima. */
1899 static void
1900 check_min_window_sizes ()
1902 /* Smaller values might permit a crash. */
1903 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1904 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1905 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1906 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1909 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
1910 minimum allowable size. */
1912 void
1913 check_frame_size (frame, rows, cols)
1914 FRAME_PTR frame;
1915 int *rows, *cols;
1917 /* For height, we have to see:
1918 whether the frame has a minibuffer,
1919 whether it wants a mode line, and
1920 whether it has a menu bar. */
1921 int min_height =
1922 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
1923 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
1924 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
1926 if (FRAME_TOP_MARGIN (frame) > 0)
1927 min_height += FRAME_TOP_MARGIN (frame);
1929 if (*rows < min_height)
1930 *rows = min_height;
1931 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1932 *cols = MIN_SAFE_WINDOW_WIDTH;
1936 /* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
1937 check if W's width can be changed, otherwise check W's height.
1938 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
1939 siblings, too. If none of the siblings is resizable, WINDOW isn't
1940 either. */
1942 static int
1943 window_fixed_size_p (w, width_p, check_siblings_p)
1944 struct window *w;
1945 int width_p, check_siblings_p;
1947 int fixed_p;
1948 struct window *c;
1950 if (!NILP (w->hchild))
1952 c = XWINDOW (w->hchild);
1954 if (width_p)
1956 /* A horiz. combination is fixed-width if all of if its
1957 children are. */
1958 while (c && window_fixed_size_p (c, width_p, 0))
1959 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1960 fixed_p = c == NULL;
1962 else
1964 /* A horiz. combination is fixed-height if one of if its
1965 children is. */
1966 while (c && !window_fixed_size_p (c, width_p, 0))
1967 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1968 fixed_p = c != NULL;
1971 else if (!NILP (w->vchild))
1973 c = XWINDOW (w->vchild);
1975 if (width_p)
1977 /* A vert. combination is fixed-width if one of if its
1978 children is. */
1979 while (c && !window_fixed_size_p (c, width_p, 0))
1980 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1981 fixed_p = c != NULL;
1983 else
1985 /* A vert. combination is fixed-height if all of if its
1986 children are. */
1987 while (c && window_fixed_size_p (c, width_p, 0))
1988 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1989 fixed_p = c == NULL;
1992 else if (BUFFERP (w->buffer))
1994 if (w->height_fixed_p && !width_p)
1995 fixed_p = 1;
1996 else
1998 struct buffer *old = current_buffer;
1999 Lisp_Object val;
2001 current_buffer = XBUFFER (w->buffer);
2002 val = find_symbol_value (Qwindow_size_fixed);
2003 current_buffer = old;
2005 fixed_p = 0;
2006 if (!EQ (val, Qunbound))
2008 fixed_p = !NILP (val);
2010 if (fixed_p
2011 && ((EQ (val, Qheight) && width_p)
2012 || (EQ (val, Qwidth) && !width_p)))
2013 fixed_p = 0;
2017 /* Can't tell if this one is resizable without looking at
2018 siblings. If all siblings are fixed-size this one is too. */
2019 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
2021 Lisp_Object child;
2023 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2024 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2025 break;
2027 if (NILP (child))
2028 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2029 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2030 break;
2032 if (NILP (child))
2033 fixed_p = 1;
2036 else
2037 fixed_p = 1;
2039 return fixed_p;
2043 /* Return the minimum size of window W, not taking fixed-width windows
2044 into account. WIDTH_P non-zero means return the minimum width,
2045 otherwise return the minimum height. If W is a combination window,
2046 compute the minimum size from the minimum sizes of W's children. */
2048 static int
2049 window_min_size_1 (w, width_p)
2050 struct window *w;
2051 int width_p;
2053 struct window *c;
2054 int size;
2056 if (!NILP (w->hchild))
2058 c = XWINDOW (w->hchild);
2059 size = 0;
2061 if (width_p)
2063 /* The min width of a horizontal combination is
2064 the sum of the min widths of its children. */
2065 while (c)
2067 size += window_min_size_1 (c, width_p);
2068 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2071 else
2073 /* The min height a horizontal combination equals
2074 the maximum of all min height of its children. */
2075 while (c)
2077 int min_size = window_min_size_1 (c, width_p);
2078 size = max (min_size, size);
2079 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2083 else if (!NILP (w->vchild))
2085 c = XWINDOW (w->vchild);
2086 size = 0;
2088 if (width_p)
2090 /* The min width of a vertical combination is
2091 the maximum of the min widths of its children. */
2092 while (c)
2094 int min_size = window_min_size_1 (c, width_p);
2095 size = max (min_size, size);
2096 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2099 else
2101 /* The min height of a vertical combination equals
2102 the sum of the min height of its children. */
2103 while (c)
2105 size += window_min_size_1 (c, width_p);
2106 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2110 else
2112 if (width_p)
2113 size = window_min_width;
2114 else
2116 if (MINI_WINDOW_P (w)
2117 || (!WINDOW_WANTS_MODELINE_P (w)
2118 && !WINDOW_WANTS_HEADER_LINE_P (w)))
2119 size = 1;
2120 else
2121 size = window_min_height;
2125 return size;
2129 /* Return the minimum size of window W, taking fixed-size windows into
2130 account. WIDTH_P non-zero means return the minimum width,
2131 otherwise return the minimum height. IGNORE_FIXED_P non-zero means
2132 ignore if W is fixed-size. Set *FIXED to 1 if W is fixed-size
2133 unless FIXED is null. */
2135 static int
2136 window_min_size (w, width_p, ignore_fixed_p, fixed)
2137 struct window *w;
2138 int width_p, ignore_fixed_p, *fixed;
2140 int size, fixed_p;
2142 if (ignore_fixed_p)
2143 fixed_p = 0;
2144 else
2145 fixed_p = window_fixed_size_p (w, width_p, 1);
2147 if (fixed)
2148 *fixed = fixed_p;
2150 if (fixed_p)
2151 size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
2152 else
2153 size = window_min_size_1 (w, width_p);
2155 return size;
2159 /* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2160 WINDOW's width. Resize WINDOW's children, if any, so that they
2161 keep their proportionate size relative to WINDOW. Propagate
2162 WINDOW's top or left edge position to children. Delete windows
2163 that become too small unless NODELETE_P is non-zero. */
2165 static void
2166 size_window (window, size, width_p, nodelete_p)
2167 Lisp_Object window;
2168 int size, width_p, nodelete_p;
2170 struct window *w = XWINDOW (window);
2171 struct window *c;
2172 Lisp_Object child, *forward, *sideward;
2173 int old_size, min_size;
2175 check_min_window_sizes ();
2177 /* If the window has been "too small" at one point,
2178 don't delete it for being "too small" in the future.
2179 Preserve it as long as that is at all possible. */
2180 if (width_p)
2182 old_size = XFASTINT (w->width);
2183 min_size = window_min_width;
2185 else
2187 old_size = XFASTINT (w->height);
2188 min_size = window_min_height;
2191 if (old_size < window_min_width)
2192 w->too_small_ok = Qt;
2194 /* Maybe delete WINDOW if it's too small. */
2195 if (!nodelete_p && !NILP (w->parent))
2197 int min_size;
2199 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
2200 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
2201 else
2202 min_size = width_p ? window_min_width : window_min_height;
2204 if (size < min_size)
2206 delete_window (window);
2207 return;
2211 /* Set redisplay hints. */
2212 XSETFASTINT (w->last_modified, 0);
2213 XSETFASTINT (w->last_overlay_modified, 0);
2214 windows_or_buffers_changed++;
2215 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
2217 if (width_p)
2219 sideward = &w->vchild;
2220 forward = &w->hchild;
2221 XSETFASTINT (w->width, size);
2223 else
2225 sideward = &w->hchild;
2226 forward = &w->vchild;
2227 XSETFASTINT (w->height, size);
2230 if (!NILP (*sideward))
2232 for (child = *sideward; !NILP (child); child = c->next)
2234 c = XWINDOW (child);
2235 if (width_p)
2236 c->left = w->left;
2237 else
2238 c->top = w->top;
2239 size_window (child, size, width_p, nodelete_p);
2242 else if (!NILP (*forward))
2244 int fixed_size, each, extra, n;
2245 int resize_fixed_p, nfixed;
2246 int last_pos, first_pos, nchildren;
2248 /* Determine the fixed-size portion of the this window, and the
2249 number of child windows. */
2250 fixed_size = nchildren = nfixed = 0;
2251 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
2253 c = XWINDOW (child);
2254 if (window_fixed_size_p (c, width_p, 0))
2256 fixed_size += (width_p
2257 ? XFASTINT (c->width) : XFASTINT (c->height));
2258 ++nfixed;
2262 /* If the new size is smaller than fixed_size, or if there
2263 aren't any resizable windows, allow resizing fixed-size
2264 windows. */
2265 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2267 /* Compute how many lines/columns to add to each child. The
2268 value of extra takes care of rounding errors. */
2269 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2270 each = (size - old_size) / n;
2271 extra = (size - old_size) - n * each;
2273 /* Compute new children heights and edge positions. */
2274 first_pos = width_p ? XFASTINT (w->left) : XFASTINT (w->top);
2275 last_pos = first_pos;
2276 for (child = *forward; !NILP (child); child = c->next)
2278 int new_size, old_size;
2280 c = XWINDOW (child);
2281 old_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2282 new_size = old_size;
2284 /* The top or left edge position of this child equals the
2285 bottom or right edge of its predecessor. */
2286 if (width_p)
2287 c->left = make_number (last_pos);
2288 else
2289 c->top = make_number (last_pos);
2291 /* If this child can be resized, do it. */
2292 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2294 new_size = old_size + each + extra;
2295 extra = 0;
2298 /* Set new height. Note that size_window also propagates
2299 edge positions to children, so it's not a no-op if we
2300 didn't change the child's size. */
2301 size_window (child, new_size, width_p, 1);
2303 /* Remember the bottom/right edge position of this child; it
2304 will be used to set the top/left edge of the next child. */
2305 last_pos += new_size;
2308 /* We should have covered the parent exactly with child windows. */
2309 xassert (size == last_pos - first_pos);
2311 /* Now delete any children that became too small. */
2312 if (!nodelete_p)
2313 for (child = *forward; !NILP (child); child = c->next)
2315 int child_size;
2316 c = XWINDOW (child);
2317 child_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2318 size_window (child, child_size, width_p, 0);
2323 /* Set WINDOW's height to HEIGHT, and recursively change the height of
2324 WINDOW's children. NODELETE non-zero means don't delete windows
2325 that become too small in the process. (The caller should check
2326 later and do so if appropriate.) */
2328 void
2329 set_window_height (window, height, nodelete)
2330 Lisp_Object window;
2331 int height;
2332 int nodelete;
2334 size_window (window, height, 0, nodelete);
2338 /* Set WINDOW's width to WIDTH, and recursively change the width of
2339 WINDOW's children. NODELETE non-zero means don't delete windows
2340 that become too small in the process. (The caller should check
2341 later and do so if appropriate.) */
2343 void
2344 set_window_width (window, width, nodelete)
2345 Lisp_Object window;
2346 int width;
2347 int nodelete;
2349 size_window (window, width, 1, nodelete);
2353 int window_select_count;
2355 Lisp_Object
2356 Fset_window_buffer_unwind (obuf)
2357 Lisp_Object obuf;
2359 Fset_buffer (obuf);
2360 return Qnil;
2364 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2365 means it's allowed to run hooks. See make_frame for a case where
2366 it's not allowed. */
2368 void
2369 set_window_buffer (window, buffer, run_hooks_p)
2370 Lisp_Object window, buffer;
2371 int run_hooks_p;
2373 struct window *w = XWINDOW (window);
2374 struct buffer *b = XBUFFER (buffer);
2375 int count = specpdl_ptr - specpdl;
2377 w->buffer = buffer;
2379 if (EQ (window, selected_window))
2380 b->last_selected_window = window;
2382 /* Update time stamps of buffer display. */
2383 if (INTEGERP (b->display_count))
2384 XSETINT (b->display_count, XINT (b->display_count) + 1);
2385 b->display_time = Fcurrent_time ();
2387 XSETFASTINT (w->window_end_pos, 0);
2388 XSETFASTINT (w->window_end_vpos, 0);
2389 bzero (&w->last_cursor, sizeof w->last_cursor);
2390 w->window_end_valid = Qnil;
2391 XSETFASTINT (w->hscroll, 0);
2392 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
2393 set_marker_restricted (w->start,
2394 make_number (b->last_window_start),
2395 buffer);
2396 w->start_at_line_beg = Qnil;
2397 w->force_start = Qnil;
2398 XSETFASTINT (w->last_modified, 0);
2399 XSETFASTINT (w->last_overlay_modified, 0);
2400 windows_or_buffers_changed++;
2402 /* We must select BUFFER for running the window-scroll-functions.
2403 If WINDOW is selected, switch permanently.
2404 Otherwise, switch but go back to the ambient buffer afterward. */
2405 if (EQ (window, selected_window))
2406 Fset_buffer (buffer);
2407 /* We can't check ! NILP (Vwindow_scroll_functions) here
2408 because that might itself be a local variable. */
2409 else if (window_initialized)
2411 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2412 Fset_buffer (buffer);
2415 /* Set left and right marginal area width from buffer. */
2416 Fset_window_margins (window, b->left_margin_width, b->right_margin_width);
2418 if (run_hooks_p)
2420 if (! NILP (Vwindow_scroll_functions))
2421 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2422 Fmarker_position (w->start));
2424 if (! NILP (Vwindow_configuration_change_hook)
2425 && ! NILP (Vrun_hooks))
2426 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2429 unbind_to (count, Qnil);
2433 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
2434 "Make WINDOW display BUFFER as its contents.\n\
2435 BUFFER can be a buffer or buffer name.")
2436 (window, buffer)
2437 register Lisp_Object window, buffer;
2439 register Lisp_Object tem;
2440 register struct window *w = decode_window (window);
2442 buffer = Fget_buffer (buffer);
2443 CHECK_BUFFER (buffer, 1);
2445 if (NILP (XBUFFER (buffer)->name))
2446 error ("Attempt to display deleted buffer");
2448 tem = w->buffer;
2449 if (NILP (tem))
2450 error ("Window is deleted");
2451 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
2452 is first being set up. */
2454 if (!NILP (w->dedicated) && !EQ (tem, buffer))
2455 error ("Window is dedicated to `%s'",
2456 XSTRING (XBUFFER (tem)->name)->data);
2458 unshow_buffer (w);
2461 set_window_buffer (window, buffer, 1);
2462 return Qnil;
2465 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
2466 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
2467 If WINDOW is not already selected, also make WINDOW's buffer current.\n\
2468 Note that the main editor command loop\n\
2469 selects the buffer of the selected window before each command.")
2470 (window)
2471 register Lisp_Object window;
2473 return select_window_1 (window, 1);
2476 static Lisp_Object
2477 select_window_1 (window, recordflag)
2478 register Lisp_Object window;
2479 int recordflag;
2481 register struct window *w;
2482 register struct window *ow = XWINDOW (selected_window);
2483 struct frame *sf;
2485 CHECK_LIVE_WINDOW (window, 0);
2487 w = XWINDOW (window);
2489 if (NILP (w->buffer))
2490 error ("Trying to select deleted window or non-leaf window");
2492 XSETFASTINT (w->use_time, ++window_select_count);
2493 if (EQ (window, selected_window))
2494 return window;
2496 if (! NILP (ow->buffer))
2497 set_marker_both (ow->pointm, ow->buffer,
2498 BUF_PT (XBUFFER (ow->buffer)),
2499 BUF_PT_BYTE (XBUFFER (ow->buffer)));
2501 selected_window = window;
2502 sf = SELECTED_FRAME ();
2503 if (XFRAME (WINDOW_FRAME (w)) != sf)
2505 XFRAME (WINDOW_FRAME (w))->selected_window = window;
2506 /* Use this rather than Fhandle_switch_frame
2507 so that FRAME_FOCUS_FRAME is moved appropriately as we
2508 move around in the state where a minibuffer in a separate
2509 frame is active. */
2510 Fselect_frame (WINDOW_FRAME (w), Qnil);
2512 else
2513 sf->selected_window = window;
2515 if (recordflag)
2516 record_buffer (w->buffer);
2517 Fset_buffer (w->buffer);
2519 XBUFFER (w->buffer)->last_selected_window = window;
2521 /* Go to the point recorded in the window.
2522 This is important when the buffer is in more
2523 than one window. It also matters when
2524 redisplay_window has altered point after scrolling,
2525 because it makes the change only in the window. */
2527 register int new_point = marker_position (w->pointm);
2528 if (new_point < BEGV)
2529 SET_PT (BEGV);
2530 else if (new_point > ZV)
2531 SET_PT (ZV);
2532 else
2533 SET_PT (new_point);
2536 windows_or_buffers_changed++;
2537 return window;
2540 /* Deiconify the frame containing the window WINDOW,
2541 unless it is the selected frame;
2542 then return WINDOW.
2544 The reason for the exception for the selected frame
2545 is that it seems better not to change the selected frames visibility
2546 merely because of displaying a different buffer in it.
2547 The deiconification is useful when a buffer gets shown in
2548 another frame that you were not using lately. */
2550 static Lisp_Object
2551 display_buffer_1 (window)
2552 Lisp_Object window;
2554 Lisp_Object frame = XWINDOW (window)->frame;
2555 FRAME_PTR f = XFRAME (frame);
2557 FRAME_SAMPLE_VISIBILITY (f);
2559 if (!EQ (frame, selected_frame))
2561 if (FRAME_ICONIFIED_P (f))
2562 Fmake_frame_visible (frame);
2563 else if (FRAME_VISIBLE_P (f))
2564 Fraise_frame (frame);
2567 return window;
2570 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
2571 "Returns non-nil if a buffer named BUFFER-NAME would be created specially.\n\
2572 The value is actually t if the frame should be called with default frame\n\
2573 parameters, and a list of frame parameters if they were specified.\n\
2574 See `special-display-buffer-names', and `special-display-regexps'.")
2575 (buffer_name)
2576 Lisp_Object buffer_name;
2578 Lisp_Object tem;
2580 CHECK_STRING (buffer_name, 1);
2582 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2583 if (!NILP (tem))
2584 return Qt;
2586 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2587 if (!NILP (tem))
2588 return XCDR (tem);
2590 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2592 Lisp_Object car = XCAR (tem);
2593 if (STRINGP (car)
2594 && fast_string_match (car, buffer_name) >= 0)
2595 return Qt;
2596 else if (CONSP (car)
2597 && STRINGP (XCAR (car))
2598 && fast_string_match (XCAR (car), buffer_name) >= 0)
2599 return XCDR (car);
2601 return Qnil;
2604 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
2605 "Returns non-nil if a new buffer named BUFFER-NAME would use the same window.\n\
2606 See `same-window-buffer-names' and `same-window-regexps'.")
2607 (buffer_name)
2608 Lisp_Object buffer_name;
2610 Lisp_Object tem;
2612 CHECK_STRING (buffer_name, 1);
2614 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2615 if (!NILP (tem))
2616 return Qt;
2618 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2619 if (!NILP (tem))
2620 return Qt;
2622 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
2624 Lisp_Object car = XCAR (tem);
2625 if (STRINGP (car)
2626 && fast_string_match (car, buffer_name) >= 0)
2627 return Qt;
2628 else if (CONSP (car)
2629 && STRINGP (XCAR (car))
2630 && fast_string_match (XCAR (car), buffer_name) >= 0)
2631 return Qt;
2633 return Qnil;
2636 /* Use B so the default is (other-buffer). */
2637 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
2638 "BDisplay buffer: \nP",
2639 "Make BUFFER appear in some window but don't select it.\n\
2640 BUFFER can be a buffer or a buffer name.\n\
2641 If BUFFER is shown already in some window, just use that one,\n\
2642 unless the window is the selected window and the optional second\n\
2643 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
2644 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
2645 Returns the window displaying BUFFER.\n\
2647 The variables `special-display-buffer-names', `special-display-regexps',\n\
2648 `same-window-buffer-names', and `same-window-regexps' customize how certain\n\
2649 buffer names are handled.\n\
2651 If optional argument FRAME is `visible', search all visible frames.\n\
2652 If FRAME is 0, search all visible and iconified frames.\n\
2653 If FRAME is t, search all frames.\n\
2654 If FRAME is a frame, search only that frame.\n\
2655 If FRAME is nil, search only the selected frame\n\
2656 (actually the last nonminibuffer frame),\n\
2657 unless `pop-up-frames' is non-nil,\n\
2658 which means search visible and iconified frames.")
2659 (buffer, not_this_window, frame)
2660 register Lisp_Object buffer, not_this_window, frame;
2662 register Lisp_Object window, tem, swp;
2663 struct frame *f;
2665 swp = Qnil;
2666 buffer = Fget_buffer (buffer);
2667 CHECK_BUFFER (buffer, 0);
2669 if (!NILP (Vdisplay_buffer_function))
2670 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
2672 if (NILP (not_this_window)
2673 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
2674 return display_buffer_1 (selected_window);
2676 /* See if the user has specified this buffer should appear
2677 in the selected window. */
2678 if (NILP (not_this_window))
2680 swp = Fsame_window_p (XBUFFER (buffer)->name);
2681 if (!NILP (swp) && !no_switch_window (selected_window))
2683 Fswitch_to_buffer (buffer, Qnil);
2684 return display_buffer_1 (selected_window);
2688 /* If pop_up_frames,
2689 look for a window showing BUFFER on any visible or iconified frame.
2690 Otherwise search only the current frame. */
2691 if (! NILP (frame))
2692 tem = frame;
2693 else if (pop_up_frames || last_nonminibuf_frame == 0)
2694 XSETFASTINT (tem, 0);
2695 else
2696 XSETFRAME (tem, last_nonminibuf_frame);
2697 window = Fget_buffer_window (buffer, tem);
2698 if (!NILP (window)
2699 && (NILP (not_this_window) || !EQ (window, selected_window)))
2701 return display_buffer_1 (window);
2704 /* Certain buffer names get special handling. */
2705 if (!NILP (Vspecial_display_function) && NILP (swp))
2707 tem = Fspecial_display_p (XBUFFER (buffer)->name);
2708 if (EQ (tem, Qt))
2709 return call1 (Vspecial_display_function, buffer);
2710 if (CONSP (tem))
2711 return call2 (Vspecial_display_function, buffer, tem);
2714 /* If there are no frames open that have more than a minibuffer,
2715 we need to create a new frame. */
2716 if (pop_up_frames || last_nonminibuf_frame == 0)
2718 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2719 Fset_window_buffer (window, buffer);
2720 return display_buffer_1 (window);
2723 f = SELECTED_FRAME ();
2724 if (pop_up_windows
2725 || FRAME_MINIBUF_ONLY_P (f)
2726 /* If the current frame is a special display frame,
2727 don't try to reuse its windows. */
2728 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
2730 Lisp_Object frames;
2732 frames = Qnil;
2733 if (FRAME_MINIBUF_ONLY_P (f))
2734 XSETFRAME (frames, last_nonminibuf_frame);
2735 /* Don't try to create a window if would get an error */
2736 if (split_height_threshold < window_min_height << 1)
2737 split_height_threshold = window_min_height << 1;
2739 /* Note that both Fget_largest_window and Fget_lru_window
2740 ignore minibuffers and dedicated windows.
2741 This means they can return nil. */
2743 /* If the frame we would try to split cannot be split,
2744 try other frames. */
2745 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
2747 /* Try visible frames first. */
2748 window = Fget_largest_window (Qvisible);
2749 /* If that didn't work, try iconified frames. */
2750 if (NILP (window))
2751 window = Fget_largest_window (make_number (0));
2752 if (NILP (window))
2753 window = Fget_largest_window (Qt);
2755 else
2756 window = Fget_largest_window (frames);
2758 /* If we got a tall enough full-width window that can be split,
2759 split it. */
2760 if (!NILP (window)
2761 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2762 && window_height (window) >= split_height_threshold
2763 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
2764 window = Fsplit_window (window, Qnil, Qnil);
2765 else
2767 Lisp_Object upper, lower, other;
2769 window = Fget_lru_window (frames);
2770 /* If the LRU window is selected, and big enough,
2771 and can be split, split it. */
2772 if (!NILP (window)
2773 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2774 && (EQ (window, selected_window)
2775 || EQ (XWINDOW (window)->parent, Qnil))
2776 && window_height (window) >= window_min_height << 1)
2777 window = Fsplit_window (window, Qnil, Qnil);
2778 /* If Fget_lru_window returned nil, try other approaches. */
2780 /* Try visible frames first. */
2781 if (NILP (window))
2782 window = Fget_buffer_window (buffer, Qvisible);
2783 if (NILP (window))
2784 window = Fget_largest_window (Qvisible);
2785 /* If that didn't work, try iconified frames. */
2786 if (NILP (window))
2787 window = Fget_buffer_window (buffer, make_number (0));
2788 if (NILP (window))
2789 window = Fget_largest_window (make_number (0));
2790 /* Try invisible frames. */
2791 if (NILP (window))
2792 window = Fget_buffer_window (buffer, Qt);
2793 if (NILP (window))
2794 window = Fget_largest_window (Qt);
2795 /* As a last resort, make a new frame. */
2796 if (NILP (window))
2797 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2798 /* If window appears above or below another,
2799 even out their heights. */
2800 other = upper = lower = Qnil;
2801 if (!NILP (XWINDOW (window)->prev))
2802 other = upper = XWINDOW (window)->prev, lower = window;
2803 if (!NILP (XWINDOW (window)->next))
2804 other = lower = XWINDOW (window)->next, upper = window;
2805 if (!NILP (other)
2806 /* Check that OTHER and WINDOW are vertically arrayed. */
2807 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
2808 && (XFASTINT (XWINDOW (other)->height)
2809 > XFASTINT (XWINDOW (window)->height)))
2811 int total = (XFASTINT (XWINDOW (other)->height)
2812 + XFASTINT (XWINDOW (window)->height));
2813 enlarge_window (upper,
2814 total / 2 - XFASTINT (XWINDOW (upper)->height),
2819 else
2820 window = Fget_lru_window (Qnil);
2822 Fset_window_buffer (window, buffer);
2823 return display_buffer_1 (window);
2826 void
2827 temp_output_buffer_show (buf)
2828 register Lisp_Object buf;
2830 register struct buffer *old = current_buffer;
2831 register Lisp_Object window;
2832 register struct window *w;
2834 XBUFFER (buf)->directory = current_buffer->directory;
2836 Fset_buffer (buf);
2837 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
2838 BEGV = BEG;
2839 ZV = Z;
2840 SET_PT (BEG);
2841 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
2842 set_buffer_internal (old);
2844 if (!EQ (Vtemp_buffer_show_function, Qnil))
2845 call1 (Vtemp_buffer_show_function, buf);
2846 else
2848 window = Fdisplay_buffer (buf, Qnil, Qnil);
2850 if (!EQ (XWINDOW (window)->frame, selected_frame))
2851 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
2852 Vminibuf_scroll_window = window;
2853 w = XWINDOW (window);
2854 XSETFASTINT (w->hscroll, 0);
2855 set_marker_restricted_both (w->start, buf, 1, 1);
2856 set_marker_restricted_both (w->pointm, buf, 1, 1);
2858 /* Run temp-buffer-show-hook, with the chosen window selected
2859 and it sbuffer current. */
2860 if (!NILP (Vrun_hooks))
2862 Lisp_Object tem;
2863 tem = Fboundp (Qtemp_buffer_show_hook);
2864 if (!NILP (tem))
2866 tem = Fsymbol_value (Qtemp_buffer_show_hook);
2867 if (!NILP (tem))
2869 int count = specpdl_ptr - specpdl;
2870 Lisp_Object prev_window;
2871 prev_window = selected_window;
2873 /* Select the window that was chosen, for running the hook. */
2874 record_unwind_protect (Fselect_window, prev_window);
2875 select_window_1 (window, 0);
2876 Fset_buffer (w->buffer);
2877 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
2878 select_window_1 (prev_window, 0);
2879 unbind_to (count, Qnil);
2886 static void
2887 make_dummy_parent (window)
2888 Lisp_Object window;
2890 Lisp_Object new;
2891 register struct window *o, *p;
2892 register struct Lisp_Vector *vec;
2893 int i;
2895 o = XWINDOW (window);
2896 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
2897 for (i = 0; i < VECSIZE (struct window); ++i)
2898 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
2899 vec->size = VECSIZE (struct window);
2900 p = (struct window *)vec;
2901 XSETWINDOW (new, p);
2903 XSETFASTINT (p->sequence_number, ++sequence_number);
2905 /* Put new into window structure in place of window */
2906 replace_window (window, new);
2908 o->next = Qnil;
2909 o->prev = Qnil;
2910 o->vchild = Qnil;
2911 o->hchild = Qnil;
2912 o->parent = new;
2914 p->start = Qnil;
2915 p->pointm = Qnil;
2916 p->buffer = Qnil;
2919 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
2920 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
2921 WINDOW defaults to selected one and SIZE to half its size.\n\
2922 If optional third arg HORFLAG is non-nil, split side by side\n\
2923 and put SIZE columns in the first of the pair. In that case,\n\
2924 SIZE includes that window's scroll bar, or the divider column to its right.")
2925 (window, size, horflag)
2926 Lisp_Object window, size, horflag;
2928 register Lisp_Object new;
2929 register struct window *o, *p;
2930 FRAME_PTR fo;
2931 register int size_int;
2933 if (NILP (window))
2934 window = selected_window;
2935 else
2936 CHECK_LIVE_WINDOW (window, 0);
2938 o = XWINDOW (window);
2939 fo = XFRAME (WINDOW_FRAME (o));
2941 if (NILP (size))
2943 if (!NILP (horflag))
2944 /* Calculate the size of the left-hand window, by dividing
2945 the usable space in columns by two.
2946 We round up, since the left-hand window may include
2947 a dividing line, while the right-hand may not. */
2948 size_int = (XFASTINT (o->width) + 1) >> 1;
2949 else
2950 size_int = XFASTINT (o->height) >> 1;
2952 else
2954 CHECK_NUMBER (size, 1);
2955 size_int = XINT (size);
2958 if (MINI_WINDOW_P (o))
2959 error ("Attempt to split minibuffer window");
2960 else if (window_fixed_size_p (o, !NILP (horflag), 0))
2961 error ("Attempt to split fixed-size window");
2963 check_min_window_sizes ();
2965 if (NILP (horflag))
2967 if (size_int < window_min_height)
2968 error ("Window height %d too small (after splitting)", size_int);
2969 if (size_int + window_min_height > XFASTINT (o->height))
2970 error ("Window height %d too small (after splitting)",
2971 XFASTINT (o->height) - size_int);
2972 if (NILP (o->parent)
2973 || NILP (XWINDOW (o->parent)->vchild))
2975 make_dummy_parent (window);
2976 new = o->parent;
2977 XWINDOW (new)->vchild = window;
2980 else
2982 if (size_int < window_min_width)
2983 error ("Window width %d too small (after splitting)", size_int);
2985 if (size_int + window_min_width > XFASTINT (o->width))
2986 error ("Window width %d too small (after splitting)",
2987 XFASTINT (o->width) - size_int);
2988 if (NILP (o->parent)
2989 || NILP (XWINDOW (o->parent)->hchild))
2991 make_dummy_parent (window);
2992 new = o->parent;
2993 XWINDOW (new)->hchild = window;
2997 /* Now we know that window's parent is a vertical combination
2998 if we are dividing vertically, or a horizontal combination
2999 if we are making side-by-side windows */
3001 windows_or_buffers_changed++;
3002 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
3003 new = make_window ();
3004 p = XWINDOW (new);
3006 p->frame = o->frame;
3007 p->next = o->next;
3008 if (!NILP (p->next))
3009 XWINDOW (p->next)->prev = new;
3010 p->prev = window;
3011 o->next = new;
3012 p->parent = o->parent;
3013 p->buffer = Qt;
3014 p->window_end_valid = Qnil;
3015 bzero (&p->last_cursor, sizeof p->last_cursor);
3017 /* Apportion the available frame space among the two new windows */
3019 if (!NILP (horflag))
3021 p->height = o->height;
3022 p->top = o->top;
3023 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
3024 XSETFASTINT (o->width, size_int);
3025 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
3027 else
3029 p->left = o->left;
3030 p->width = o->width;
3031 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
3032 XSETFASTINT (o->height, size_int);
3033 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
3036 /* Adjust glyph matrices. */
3037 adjust_glyphs (fo);
3038 Fset_window_buffer (new, o->buffer);
3039 return new;
3042 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3043 "Make current window ARG lines bigger.\n\
3044 From program, optional second arg non-nil means grow sideways ARG columns.")
3045 (arg, side)
3046 register Lisp_Object arg, side;
3048 CHECK_NUMBER (arg, 0);
3049 enlarge_window (selected_window, XINT (arg), !NILP (side));
3051 if (! NILP (Vwindow_configuration_change_hook))
3052 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3054 return Qnil;
3057 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3058 "Make current window ARG lines smaller.\n\
3059 From program, optional second arg non-nil means shrink sideways arg columns.")
3060 (arg, side)
3061 register Lisp_Object arg, side;
3063 CHECK_NUMBER (arg, 0);
3064 enlarge_window (selected_window, -XINT (arg), !NILP (side));
3066 if (! NILP (Vwindow_configuration_change_hook))
3067 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3069 return Qnil;
3073 window_height (window)
3074 Lisp_Object window;
3076 register struct window *p = XWINDOW (window);
3077 return XFASTINT (p->height);
3081 window_width (window)
3082 Lisp_Object window;
3084 register struct window *p = XWINDOW (window);
3085 return XFASTINT (p->width);
3089 #define CURBEG(w) \
3090 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
3092 #define CURSIZE(w) \
3093 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
3096 /* Enlarge selected_window by DELTA. WIDTHFLAG non-zero means
3097 increase its width. Siblings of the selected window are resized to
3098 fullfil the size request. If they become too small in the process,
3099 they will be deleted. */
3101 static void
3102 enlarge_window (window, delta, widthflag)
3103 Lisp_Object window;
3104 int delta, widthflag;
3106 Lisp_Object parent, next, prev;
3107 struct window *p;
3108 int *sizep, maximum;
3109 int (*sizefun) P_ ((Lisp_Object))
3110 = widthflag ? window_width : window_height;
3111 void (*setsizefun) P_ ((Lisp_Object, int, int))
3112 = (widthflag ? set_window_width : set_window_height);
3114 /* Check values of window_min_width and window_min_height for
3115 validity. */
3116 check_min_window_sizes ();
3118 /* Give up if this window cannot be resized. */
3119 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3120 error ("Window is not resizable");
3122 /* Find the parent of the selected window. */
3123 while (1)
3125 p = XWINDOW (window);
3126 parent = p->parent;
3128 if (NILP (parent))
3130 if (widthflag)
3131 error ("No other window to side of this one");
3132 break;
3135 if (widthflag
3136 ? !NILP (XWINDOW (parent)->hchild)
3137 : !NILP (XWINDOW (parent)->vchild))
3138 break;
3140 window = parent;
3143 sizep = &CURSIZE (window);
3146 register int maxdelta;
3148 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
3149 : !NILP (p->next) ? ((*sizefun) (p->next)
3150 - window_min_size (XWINDOW (p->next),
3151 widthflag, 0, 0))
3152 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3153 - window_min_size (XWINDOW (p->prev),
3154 widthflag, 0, 0))
3155 /* This is a frame with only one window, a minibuffer-only
3156 or a minibufferless frame. */
3157 : (delta = 0));
3159 if (delta > maxdelta)
3160 /* This case traps trying to make the minibuffer
3161 the full frame, or make the only window aside from the
3162 minibuffer the full frame. */
3163 delta = maxdelta;
3166 if (*sizep + delta < window_min_size (XWINDOW (window), widthflag, 0, 0))
3168 delete_window (window);
3169 return;
3172 if (delta == 0)
3173 return;
3175 /* Find the total we can get from other siblings. */
3176 maximum = 0;
3177 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
3178 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
3179 widthflag, 0, 0);
3180 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
3181 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
3182 widthflag, 0, 0);
3184 /* If we can get it all from them, do so. */
3185 if (delta <= maximum)
3187 Lisp_Object first_unaffected;
3188 Lisp_Object first_affected;
3189 int fixed_p;
3191 next = p->next;
3192 prev = p->prev;
3193 first_affected = window;
3194 /* Look at one sibling at a time,
3195 moving away from this window in both directions alternately,
3196 and take as much as we can get without deleting that sibling. */
3197 while (delta != 0 && (!NILP (next) || !NILP (prev)))
3199 if (! NILP (next))
3201 int this_one = ((*sizefun) (next)
3202 - window_min_size (XWINDOW (next),
3203 widthflag, 0, &fixed_p));
3204 if (!fixed_p)
3206 if (this_one > delta)
3207 this_one = delta;
3209 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3210 (*setsizefun) (window, *sizep + this_one, 0);
3212 delta -= this_one;
3215 next = XWINDOW (next)->next;
3218 if (delta == 0)
3219 break;
3221 if (! NILP (prev))
3223 int this_one = ((*sizefun) (prev)
3224 - window_min_size (XWINDOW (prev),
3225 widthflag, 0, &fixed_p));
3226 if (!fixed_p)
3228 if (this_one > delta)
3229 this_one = delta;
3231 first_affected = prev;
3233 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3234 (*setsizefun) (window, *sizep + this_one, 0);
3236 delta -= this_one;
3239 prev = XWINDOW (prev)->prev;
3243 xassert (delta == 0);
3245 /* Now recalculate the edge positions of all the windows affected,
3246 based on the new sizes. */
3247 first_unaffected = next;
3248 prev = first_affected;
3249 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3250 prev = next, next = XWINDOW (next)->next)
3252 CURBEG (next) = CURBEG (prev) + (*sizefun) (prev);
3253 /* This does not change size of NEXT,
3254 but it propagates the new top edge to its children */
3255 (*setsizefun) (next, (*sizefun) (next), 0);
3258 else
3260 register int delta1;
3261 register int opht = (*sizefun) (parent);
3263 /* If trying to grow this window to or beyond size of the parent,
3264 make delta1 so big that, on shrinking back down,
3265 all the siblings end up with less than one line and are deleted. */
3266 if (opht <= *sizep + delta)
3267 delta1 = opht * opht * 2;
3268 else
3270 /* Otherwise, make delta1 just right so that if we add
3271 delta1 lines to this window and to the parent, and then
3272 shrink the parent back to its original size, the new
3273 proportional size of this window will increase by delta.
3275 The function size_window will compute the new height h'
3276 of the window from delta1 as:
3278 e = delta1/n
3279 x = delta1 - delta1/n * n for the 1st resizable child
3280 h' = h + e + x
3282 where n is the number of children that can be resized.
3283 We can ignore x by choosing a delta1 that is a multiple of
3284 n. We want the height of this window to come out as
3286 h' = h + delta
3288 So, delta1 must be
3290 h + e = h + delta
3291 delta1/n = delta
3292 delta1 = n * delta.
3294 The number of children n rquals the number of resizable
3295 children of this window + 1 because we know window itself
3296 is resizable (otherwise we would have signalled an error. */
3298 struct window *w = XWINDOW (window);
3299 Lisp_Object s;
3300 int n = 1;
3302 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3303 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3304 ++n;
3305 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3306 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3307 ++n;
3309 delta1 = n * delta;
3312 /* Add delta1 lines or columns to this window, and to the parent,
3313 keeping things consistent while not affecting siblings. */
3314 CURSIZE (parent) = opht + delta1;
3315 (*setsizefun) (window, *sizep + delta1, 0);
3317 /* Squeeze out delta1 lines or columns from our parent,
3318 shriking this window and siblings proportionately.
3319 This brings parent back to correct size.
3320 Delta1 was calculated so this makes this window the desired size,
3321 taking it all out of the siblings. */
3322 (*setsizefun) (parent, opht, 0);
3325 XSETFASTINT (p->last_modified, 0);
3326 XSETFASTINT (p->last_overlay_modified, 0);
3328 /* Adjust glyph matrices. */
3329 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
3332 #undef CURBEG
3333 #undef CURSIZE
3337 /***********************************************************************
3338 Resizing Mini-Windows
3339 ***********************************************************************/
3341 static void shrink_window_lowest_first P_ ((struct window *, int));
3343 enum save_restore_action
3345 CHECK_ORIG_SIZES,
3346 SAVE_ORIG_SIZES,
3347 RESTORE_ORIG_SIZES
3350 static int save_restore_orig_size P_ ((struct window *,
3351 enum save_restore_action));
3353 /* Shrink windows rooted in window W to HEIGHT. Take the space needed
3354 from lowest windows first. */
3356 static void
3357 shrink_window_lowest_first (w, height)
3358 struct window *w;
3359 int height;
3361 struct window *c;
3362 Lisp_Object child;
3363 int old_height;
3365 xassert (!MINI_WINDOW_P (w));
3367 /* Set redisplay hints. */
3368 XSETFASTINT (w->last_modified, 0);
3369 XSETFASTINT (w->last_overlay_modified, 0);
3370 windows_or_buffers_changed++;
3371 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
3373 old_height = XFASTINT (w->height);
3374 XSETFASTINT (w->height, height);
3376 if (!NILP (w->hchild))
3378 for (child = w->hchild; !NILP (child); child = c->next)
3380 c = XWINDOW (child);
3381 c->top = w->top;
3382 shrink_window_lowest_first (c, height);
3385 else if (!NILP (w->vchild))
3387 Lisp_Object last_child;
3388 int delta = old_height - height;
3389 int last_top;
3391 /* Find the last child. We are taking space from lowest windows
3392 first, so we iterate over children from the last child
3393 backwards. */
3394 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
3395 last_child = child;
3397 /* Assign new heights. We leave only MIN_SAFE_WINDOW_HEIGHT. */
3398 for (child = last_child; delta && !NILP (child); child = c->prev)
3400 int this_one;
3402 c = XWINDOW (child);
3403 this_one = XFASTINT (c->height) - MIN_SAFE_WINDOW_HEIGHT;
3405 if (this_one > delta)
3406 this_one = delta;
3408 shrink_window_lowest_first (c, XFASTINT (c->height) - this_one);
3409 delta -= this_one;
3412 /* Compute new positions. */
3413 last_top = w->top;
3414 for (child = w->vchild; !NILP (child); child = c->next)
3416 c = XWINDOW (child);
3417 c->top = make_number (last_top);
3418 shrink_window_lowest_first (c, XFASTINT (c->height));
3419 last_top += XFASTINT (c->height);
3425 /* Save, restore, or check positions and sizes in the window tree
3426 rooted at W. ACTION says what to do.
3428 If ACTION is CHECK_ORIG_SIZES, check if orig_top and orig_height
3429 members are valid for all windows in the window tree. Value is
3430 non-zero if they are valid.
3432 If ACTION is SAVE_ORIG_SIZES, save members top and height in
3433 orig_top and orig_height for all windows in the tree.
3435 If ACTION is RESTORE_ORIG_SIZES, restore top and height from
3436 values stored in orig_top and orig_height for all windows. */
3438 static int
3439 save_restore_orig_size (w, action)
3440 struct window *w;
3441 enum save_restore_action action;
3443 int success_p = 1;
3445 while (w)
3447 if (!NILP (w->hchild))
3449 if (!save_restore_orig_size (XWINDOW (w->hchild), action))
3450 success_p = 0;
3452 else if (!NILP (w->vchild))
3454 if (!save_restore_orig_size (XWINDOW (w->vchild), action))
3455 success_p = 0;
3458 switch (action)
3460 case CHECK_ORIG_SIZES:
3461 if (!INTEGERP (w->orig_top) || !INTEGERP (w->orig_height))
3462 return 0;
3463 break;
3465 case SAVE_ORIG_SIZES:
3466 w->orig_top = w->top;
3467 w->orig_height = w->height;
3468 XSETFASTINT (w->last_modified, 0);
3469 XSETFASTINT (w->last_overlay_modified, 0);
3470 break;
3472 case RESTORE_ORIG_SIZES:
3473 xassert (INTEGERP (w->orig_top) && INTEGERP (w->orig_height));
3474 w->top = w->orig_top;
3475 w->height = w->orig_height;
3476 w->orig_height = w->orig_top = Qnil;
3477 XSETFASTINT (w->last_modified, 0);
3478 XSETFASTINT (w->last_overlay_modified, 0);
3479 break;
3481 default:
3482 abort ();
3485 w = NILP (w->next) ? NULL : XWINDOW (w->next);
3488 return success_p;
3492 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we can
3493 without deleting other windows. */
3495 void
3496 grow_mini_window (w, delta)
3497 struct window *w;
3498 int delta;
3500 struct frame *f = XFRAME (w->frame);
3501 struct window *root;
3503 xassert (MINI_WINDOW_P (w));
3504 xassert (delta >= 0);
3506 /* Check values of window_min_width and window_min_height for
3507 validity. */
3508 check_min_window_sizes ();
3510 /* Compute how much we can enlarge the mini-window without deleting
3511 other windows. */
3512 root = XWINDOW (FRAME_ROOT_WINDOW (f));
3513 if (delta)
3515 int min_height = window_min_size (root, 0, 0, 0);
3516 if (XFASTINT (root->height) - delta < min_height)
3517 delta = XFASTINT (root->height) - min_height;
3520 if (delta)
3522 /* Save original window sizes and positions, if not already done. */
3523 if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
3524 save_restore_orig_size (root, SAVE_ORIG_SIZES);
3526 /* Shrink other windows. */
3527 shrink_window_lowest_first (root, XFASTINT (root->height) - delta);
3529 /* Grow the mini-window. */
3530 w->top = make_number (XFASTINT (root->top) + XFASTINT (root)->height);
3531 w->height = make_number (XFASTINT (w->height) + delta);
3532 XSETFASTINT (w->last_modified, 0);
3533 XSETFASTINT (w->last_overlay_modified, 0);
3535 adjust_glyphs (f);
3540 /* Shrink mini-window W. If there is recorded info about window sizes
3541 before a call to grow_mini_window, restore recorded window sizes.
3542 Otherwise, if the mini-window is higher than 1 line, resize it to 1
3543 line. */
3545 void
3546 shrink_mini_window (w)
3547 struct window *w;
3549 struct frame *f = XFRAME (w->frame);
3550 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
3552 if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
3554 save_restore_orig_size (root, RESTORE_ORIG_SIZES);
3555 adjust_glyphs (f);
3556 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3557 windows_or_buffers_changed = 1;
3559 else if (XFASTINT (w->height) > 1)
3561 Lisp_Object window;
3562 XSETWINDOW (window, w);
3563 enlarge_window (window, 1 - XFASTINT (w->height), 0);
3569 /* Mark window cursors off for all windows in the window tree rooted
3570 at W by setting their phys_cursor_on_p flag to zero. Called from
3571 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3572 the frame are cleared. */
3574 void
3575 mark_window_cursors_off (w)
3576 struct window *w;
3578 while (w)
3580 if (!NILP (w->hchild))
3581 mark_window_cursors_off (XWINDOW (w->hchild));
3582 else if (!NILP (w->vchild))
3583 mark_window_cursors_off (XWINDOW (w->vchild));
3584 else
3585 w->phys_cursor_on_p = 0;
3587 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3592 /* Return number of lines of text (not counting mode line) in W. */
3595 window_internal_height (w)
3596 struct window *w;
3598 int ht = XFASTINT (w->height);
3600 if (MINI_WINDOW_P (w))
3601 return ht;
3603 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
3604 || !NILP (w->next) || !NILP (w->prev)
3605 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
3606 return ht - 1;
3608 return ht;
3612 /* Return the number of columns in W.
3613 Don't count columns occupied by scroll bars or the vertical bar
3614 separating W from the sibling to its right. */
3617 window_internal_width (w)
3618 struct window *w;
3620 struct frame *f = XFRAME (WINDOW_FRAME (w));
3621 int width = XINT (w->width);
3623 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3624 /* Scroll bars occupy a few columns. */
3625 width -= FRAME_SCROLL_BAR_COLS (f);
3626 else if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
3627 /* The column of `|' characters separating side-by-side windows
3628 occupies one column only. */
3629 width -= 1;
3631 /* On window-systems, areas to the left and right of the window
3632 are used to display bitmaps there. */
3633 if (FRAME_WINDOW_P (f))
3634 width -= FRAME_FLAGS_AREA_COLS (f);
3636 return width;
3640 /************************************************************************
3641 Window Scrolling
3642 ***********************************************************************/
3644 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
3645 one screen-full, which is defined as the height of the window minus
3646 next_screen_context_lines. If WHOLE is zero, scroll up N lines
3647 instead. Negative values of N mean scroll down. NOERROR non-zero
3648 means don't signal an error if we try to move over BEGV or ZV,
3649 respectively. */
3651 static void
3652 window_scroll (window, n, whole, noerror)
3653 Lisp_Object window;
3654 int n;
3655 int whole;
3656 int noerror;
3658 /* If we must, use the pixel-based version which is much slower than
3659 the line-based one but can handle varying line heights. */
3660 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
3661 window_scroll_pixel_based (window, n, whole, noerror);
3662 else
3663 window_scroll_line_based (window, n, whole, noerror);
3667 /* Implementation of window_scroll that works based on pixel line
3668 heights. See the comment of window_scroll for parameter
3669 descriptions. */
3671 static void
3672 window_scroll_pixel_based (window, n, whole, noerror)
3673 Lisp_Object window;
3674 int n;
3675 int whole;
3676 int noerror;
3678 struct it it;
3679 struct window *w = XWINDOW (window);
3680 struct text_pos start;
3681 Lisp_Object tem;
3682 int this_scroll_margin;
3683 int preserve_y;
3685 SET_TEXT_POS_FROM_MARKER (start, w->start);
3687 /* If PT is not visible in WINDOW, move back one half of
3688 the screen. */
3689 XSETFASTINT (tem, PT);
3690 tem = Fpos_visible_in_window_p (tem, window);
3691 if (NILP (tem))
3693 /* Move backward half the height of the window. Performance note:
3694 vmotion used here is about 10% faster, but would give wrong
3695 results for variable height lines. */
3696 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3697 it.current_y = it.last_visible_y;
3698 move_it_vertically (&it, -it.last_visible_y / 2);
3700 /* The function move_iterator_vertically may move over more than
3701 the specified y-distance. If it->w is small, e.g. a
3702 mini-buffer window, we may end up in front of the window's
3703 display area. This is the case when Start displaying at the
3704 start of the line containing PT in this case. */
3705 if (it.current_y <= 0)
3707 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3708 move_it_vertically (&it, 0);
3709 it.current_y = 0;
3712 start = it.current.pos;
3715 /* If scroll_preserve_screen_position is non-zero, we try to set
3716 point in the same window line as it is now, so get that line. */
3717 if (!NILP (Vscroll_preserve_screen_position))
3719 start_display (&it, w, start);
3720 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3721 preserve_y = it.current_y;
3723 else
3724 preserve_y = -1;
3726 /* Move iterator it from start the specified distance forward or
3727 backward. The result is the new window start. */
3728 start_display (&it, w, start);
3729 if (whole)
3731 int screen_full = (it.last_visible_y
3732 - next_screen_context_lines * CANON_Y_UNIT (it.f));
3733 int direction = n < 0 ? -1 : 1;
3734 move_it_vertically (&it, direction * screen_full);
3736 else
3737 move_it_by_lines (&it, n, 1);
3739 /* End if we end up at ZV or BEGV. */
3740 if ((n > 0 && IT_CHARPOS (it) == ZV)
3741 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
3743 if (noerror)
3744 return;
3745 else if (IT_CHARPOS (it) == ZV)
3746 Fsignal (Qend_of_buffer, Qnil);
3747 else
3748 Fsignal (Qbeginning_of_buffer, Qnil);
3751 /* Set the window start, and set up the window for redisplay. */
3752 set_marker_restricted (w->start, make_number (IT_CHARPOS (it)), w->buffer);
3753 w->start_at_line_beg = Fbolp ();
3754 w->update_mode_line = Qt;
3755 XSETFASTINT (w->last_modified, 0);
3756 XSETFASTINT (w->last_overlay_modified, 0);
3757 /* Set force_start so that redisplay_window will run the
3758 window-scroll-functions. */
3759 w->force_start = Qt;
3761 it.current_y = it.vpos = 0;
3763 /* Preserve the screen position if we must. */
3764 if (preserve_y >= 0)
3766 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
3767 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3769 else
3771 /* Move PT out of scroll margins. */
3772 this_scroll_margin = max (0, scroll_margin);
3773 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
3774 this_scroll_margin *= CANON_Y_UNIT (it.f);
3776 if (n > 0)
3778 /* We moved the window start towards ZV, so PT may be now
3779 in the scroll margin at the top. */
3780 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3781 while (it.current_y < this_scroll_margin)
3782 move_it_by_lines (&it, 1, 1);
3783 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3785 else if (n < 0)
3787 /* We moved the window start towards BEGV, so PT may be now
3788 in the scroll margin at the bottom. */
3789 move_it_to (&it, PT, -1,
3790 it.last_visible_y - this_scroll_margin - 1, -1,
3791 MOVE_TO_POS | MOVE_TO_Y);
3793 /* Don't put point on a partially visible line at the end. */
3794 if (it.current_y + it.max_ascent + it.max_descent
3795 > it.last_visible_y)
3796 move_it_by_lines (&it, -1, 0);
3798 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3804 /* Implementation of window_scroll that works based on screen lines.
3805 See the comment of window_scroll for parameter descriptions. */
3807 static void
3808 window_scroll_line_based (window, n, whole, noerror)
3809 Lisp_Object window;
3810 int n;
3811 int whole;
3812 int noerror;
3814 register struct window *w = XWINDOW (window);
3815 register int opoint = PT, opoint_byte = PT_BYTE;
3816 register int pos, pos_byte;
3817 register int ht = window_internal_height (w);
3818 register Lisp_Object tem;
3819 int lose;
3820 Lisp_Object bolp;
3821 int startpos;
3822 struct position posit;
3823 int original_vpos;
3825 startpos = marker_position (w->start);
3827 posit = *compute_motion (startpos, 0, 0, 0,
3828 PT, ht, 0,
3829 window_internal_width (w), XINT (w->hscroll),
3830 0, w);
3831 original_vpos = posit.vpos;
3833 XSETFASTINT (tem, PT);
3834 tem = Fpos_visible_in_window_p (tem, window);
3836 if (NILP (tem))
3838 Fvertical_motion (make_number (- (ht / 2)), window);
3839 startpos = PT;
3842 SET_PT (startpos);
3843 lose = n < 0 && PT == BEGV;
3844 Fvertical_motion (make_number (n), window);
3845 pos = PT;
3846 pos_byte = PT_BYTE;
3847 bolp = Fbolp ();
3848 SET_PT_BOTH (opoint, opoint_byte);
3850 if (lose)
3852 if (noerror)
3853 return;
3854 else
3855 Fsignal (Qbeginning_of_buffer, Qnil);
3858 if (pos < ZV)
3860 int this_scroll_margin = scroll_margin;
3862 /* Don't use a scroll margin that is negative or too large. */
3863 if (this_scroll_margin < 0)
3864 this_scroll_margin = 0;
3866 if (XINT (w->height) < 4 * scroll_margin)
3867 this_scroll_margin = XINT (w->height) / 4;
3869 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
3870 w->start_at_line_beg = bolp;
3871 w->update_mode_line = Qt;
3872 XSETFASTINT (w->last_modified, 0);
3873 XSETFASTINT (w->last_overlay_modified, 0);
3874 /* Set force_start so that redisplay_window will run
3875 the window-scroll-functions. */
3876 w->force_start = Qt;
3878 if (whole && !NILP (Vscroll_preserve_screen_position))
3880 SET_PT_BOTH (pos, pos_byte);
3881 Fvertical_motion (make_number (original_vpos), window);
3883 /* If we scrolled forward, put point enough lines down
3884 that it is outside the scroll margin. */
3885 else if (n > 0)
3887 int top_margin;
3889 if (this_scroll_margin > 0)
3891 SET_PT_BOTH (pos, pos_byte);
3892 Fvertical_motion (make_number (this_scroll_margin), window);
3893 top_margin = PT;
3895 else
3896 top_margin = pos;
3898 if (top_margin <= opoint)
3899 SET_PT_BOTH (opoint, opoint_byte);
3900 else if (!NILP (Vscroll_preserve_screen_position))
3902 SET_PT_BOTH (pos, pos_byte);
3903 Fvertical_motion (make_number (original_vpos), window);
3905 else
3906 SET_PT (top_margin);
3908 else if (n < 0)
3910 int bottom_margin;
3912 /* If we scrolled backward, put point near the end of the window
3913 but not within the scroll margin. */
3914 SET_PT_BOTH (pos, pos_byte);
3915 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
3916 if (XFASTINT (tem) == ht - this_scroll_margin)
3917 bottom_margin = PT;
3918 else
3919 bottom_margin = PT + 1;
3921 if (bottom_margin > opoint)
3922 SET_PT_BOTH (opoint, opoint_byte);
3923 else
3925 if (!NILP (Vscroll_preserve_screen_position))
3927 SET_PT_BOTH (pos, pos_byte);
3928 Fvertical_motion (make_number (original_vpos), window);
3930 else
3931 Fvertical_motion (make_number (-1), window);
3935 else
3937 if (noerror)
3938 return;
3939 else
3940 Fsignal (Qend_of_buffer, Qnil);
3945 /* Scroll selected_window up or down. If N is nil, scroll a
3946 screen-full which is defined as the height of the window minus
3947 next_screen_context_lines. If N is the symbol `-', scroll.
3948 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
3949 up. This is the guts of Fscroll_up and Fscroll_down. */
3951 static void
3952 scroll_command (n, direction)
3953 Lisp_Object n;
3954 int direction;
3956 register int defalt;
3957 int count = specpdl_ptr - specpdl;
3959 xassert (abs (direction) == 1);
3961 /* If selected window's buffer isn't current, make it current for
3962 the moment. But don't screw up if window_scroll gets an error. */
3963 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
3965 record_unwind_protect (save_excursion_restore, save_excursion_save ());
3966 Fset_buffer (XWINDOW (selected_window)->buffer);
3968 /* Make redisplay consider other windows than just selected_window. */
3969 ++windows_or_buffers_changed;
3972 defalt = (window_internal_height (XWINDOW (selected_window))
3973 - next_screen_context_lines);
3974 defalt = direction * (defalt < 1 ? 1 : defalt);
3976 if (NILP (n))
3977 window_scroll (selected_window, defalt, 1, 0);
3978 else if (EQ (n, Qminus))
3979 window_scroll (selected_window, - defalt, 1, 0);
3980 else
3982 n = Fprefix_numeric_value (n);
3983 window_scroll (selected_window, XINT (n) * direction, 0, 0);
3986 unbind_to (count, Qnil);
3989 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
3990 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
3991 A near full screen is `next-screen-context-lines' less than a full screen.\n\
3992 Negative ARG means scroll downward.\n\
3993 If ARG is the atom `-', scroll downward by nearly full screen.\n\
3994 When calling from a program, supply as argument a number, nil, or `-'.")
3995 (arg)
3996 Lisp_Object arg;
3998 scroll_command (arg, 1);
3999 return Qnil;
4002 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
4003 "Scroll text of current window down ARG lines; or near full screen if no ARG.\n\
4004 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4005 Negative ARG means scroll upward.\n\
4006 If ARG is the atom `-', scroll upward by nearly full screen.\n\
4007 When calling from a program, supply as argument a number, nil, or `-'.")
4008 (arg)
4009 Lisp_Object arg;
4011 scroll_command (arg, -1);
4012 return Qnil;
4015 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4016 "Return the other window for \"other window scroll\" commands.\n\
4017 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
4018 specifies the window.\n\
4019 If `other-window-scroll-buffer' is non-nil, a window\n\
4020 showing that buffer is used.")
4023 Lisp_Object window;
4025 if (MINI_WINDOW_P (XWINDOW (selected_window))
4026 && !NILP (Vminibuf_scroll_window))
4027 window = Vminibuf_scroll_window;
4028 /* If buffer is specified, scroll that buffer. */
4029 else if (!NILP (Vother_window_scroll_buffer))
4031 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4032 if (NILP (window))
4033 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4035 else
4037 /* Nothing specified; look for a neighboring window on the same
4038 frame. */
4039 window = Fnext_window (selected_window, Qnil, Qnil);
4041 if (EQ (window, selected_window))
4042 /* That didn't get us anywhere; look for a window on another
4043 visible frame. */
4045 window = Fnext_window (window, Qnil, Qt);
4046 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4047 && ! EQ (window, selected_window));
4050 CHECK_LIVE_WINDOW (window, 0);
4052 if (EQ (window, selected_window))
4053 error ("There is no other window");
4055 return window;
4058 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4059 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
4060 A near full screen is `next-screen-context-lines' less than a full screen.\n\
4061 The next window is the one below the current one; or the one at the top\n\
4062 if the current one is at the bottom. Negative ARG means scroll downward.\n\
4063 If ARG is the atom `-', scroll downward by nearly full screen.\n\
4064 When calling from a program, supply as argument a number, nil, or `-'.\n\
4066 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
4067 specifies the window to scroll.\n\
4068 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
4069 showing that buffer, popping the buffer up if necessary.")
4070 (arg)
4071 register Lisp_Object arg;
4073 register Lisp_Object window;
4074 register int defalt;
4075 register struct window *w;
4076 register int count = specpdl_ptr - specpdl;
4078 window = Fother_window_for_scrolling ();
4080 w = XWINDOW (window);
4081 defalt = window_internal_height (w) - next_screen_context_lines;
4082 if (defalt < 1) defalt = 1;
4084 /* Don't screw up if window_scroll gets an error. */
4085 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4086 ++windows_or_buffers_changed;
4088 Fset_buffer (w->buffer);
4089 SET_PT (marker_position (w->pointm));
4091 if (NILP (arg))
4092 window_scroll (window, defalt, 1, 1);
4093 else if (EQ (arg, Qminus))
4094 window_scroll (window, -defalt, 1, 1);
4095 else
4097 if (CONSP (arg))
4098 arg = Fcar (arg);
4099 CHECK_NUMBER (arg, 0);
4100 window_scroll (window, XINT (arg), 0, 1);
4103 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4104 unbind_to (count, Qnil);
4106 return Qnil;
4109 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
4110 "Scroll selected window display ARG columns left.\n\
4111 Default for ARG is window width minus 2.")
4112 (arg)
4113 register Lisp_Object arg;
4116 if (NILP (arg))
4117 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
4118 else
4119 arg = Fprefix_numeric_value (arg);
4121 return
4122 Fset_window_hscroll (selected_window,
4123 make_number (XINT (XWINDOW (selected_window)->hscroll)
4124 + XINT (arg)));
4127 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
4128 "Scroll selected window display ARG columns right.\n\
4129 Default for ARG is window width minus 2.")
4130 (arg)
4131 register Lisp_Object arg;
4133 if (NILP (arg))
4134 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
4135 else
4136 arg = Fprefix_numeric_value (arg);
4138 return
4139 Fset_window_hscroll (selected_window,
4140 make_number (XINT (XWINDOW (selected_window)->hscroll)
4141 - XINT (arg)));
4144 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
4145 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
4146 The desired position of point is always relative to the current window.\n\
4147 Just C-u as prefix means put point in the center of the window.\n\
4148 If ARG is omitted or nil, erases the entire frame and then\n\
4149 redraws with point in the center of the current window.")
4150 (arg)
4151 register Lisp_Object arg;
4153 register struct window *w = XWINDOW (selected_window);
4154 register int ht = window_internal_height (w);
4155 struct position pos;
4156 struct buffer *buf = XBUFFER (w->buffer);
4157 struct buffer *obuf = current_buffer;
4159 if (NILP (arg))
4161 extern int frame_garbaged;
4162 int i;
4164 /* Invalidate pixel data calculated for all compositions. */
4165 for (i = 0; i < n_compositions; i++)
4166 composition_table[i]->font = NULL;
4168 Fredraw_frame (w->frame);
4169 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
4170 XSETFASTINT (arg, ht / 2);
4172 else if (CONSP (arg)) /* Just C-u. */
4174 XSETFASTINT (arg, ht / 2);
4176 else
4178 arg = Fprefix_numeric_value (arg);
4179 CHECK_NUMBER (arg, 0);
4182 if (XINT (arg) < 0)
4183 XSETINT (arg, XINT (arg) + ht);
4185 set_buffer_internal (buf);
4186 pos = *vmotion (PT, - XINT (arg), w);
4188 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
4189 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
4190 || FETCH_BYTE (pos.bytepos - 1) == '\n')
4191 ? Qt : Qnil);
4192 w->force_start = Qt;
4193 set_buffer_internal (obuf);
4195 return Qnil;
4198 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
4199 1, 1, "P",
4200 "Position point relative to window.\n\
4201 With no argument, position point at center of window.\n\
4202 An argument specifies vertical position within the window;\n\
4203 zero means top of window, negative means relative to bottom of window.")
4204 (arg)
4205 register Lisp_Object arg;
4207 register struct window *w = XWINDOW (selected_window);
4208 register int height = window_internal_height (w);
4209 register int start;
4210 Lisp_Object window;
4212 if (NILP (arg))
4213 XSETFASTINT (arg, height / 2);
4214 else
4216 arg = Fprefix_numeric_value (arg);
4217 if (XINT (arg) < 0)
4218 XSETINT (arg, XINT (arg) + height);
4221 start = marker_position (w->start);
4222 XSETWINDOW (window, w);
4223 if (start < BEGV || start > ZV)
4225 Fvertical_motion (make_number (- (height / 2)), window);
4226 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
4227 w->start_at_line_beg = Fbolp ();
4228 w->force_start = Qt;
4230 else
4231 Fgoto_char (w->start);
4233 return Fvertical_motion (arg, window);
4238 /***********************************************************************
4239 Window Configuration
4240 ***********************************************************************/
4242 struct save_window_data
4244 EMACS_INT size_from_Lisp_Vector_struct;
4245 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4246 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
4247 Lisp_Object frame_tool_bar_lines;
4248 Lisp_Object selected_frame;
4249 Lisp_Object current_window;
4250 Lisp_Object current_buffer;
4251 Lisp_Object minibuf_scroll_window;
4252 Lisp_Object root_window;
4253 Lisp_Object focus_frame;
4254 /* Record the values of window-min-width and window-min-height
4255 so that window sizes remain consistent with them. */
4256 Lisp_Object min_width, min_height;
4257 /* A vector, each of whose elements is a struct saved_window
4258 for one window. */
4259 Lisp_Object saved_windows;
4262 /* This is saved as a Lisp_Vector */
4263 struct saved_window
4265 /* these first two must agree with struct Lisp_Vector in lisp.h */
4266 EMACS_INT size_from_Lisp_Vector_struct;
4267 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4269 Lisp_Object window;
4270 Lisp_Object buffer, start, pointm, mark;
4271 Lisp_Object left, top, width, height, hscroll;
4272 Lisp_Object parent, prev;
4273 Lisp_Object start_at_line_beg;
4274 Lisp_Object display_table;
4276 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
4278 #define SAVED_WINDOW_N(swv,n) \
4279 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4281 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
4282 "Return t if OBJECT is a window-configuration object.")
4283 (object)
4284 Lisp_Object object;
4286 if (WINDOW_CONFIGURATIONP (object))
4287 return Qt;
4288 return Qnil;
4291 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
4292 "Return the frame that CONFIG, a window-configuration object, is about.")
4293 (config)
4294 Lisp_Object config;
4296 register struct save_window_data *data;
4297 struct Lisp_Vector *saved_windows;
4299 if (! WINDOW_CONFIGURATIONP (config))
4300 wrong_type_argument (Qwindow_configuration_p, config);
4302 data = (struct save_window_data *) XVECTOR (config);
4303 saved_windows = XVECTOR (data->saved_windows);
4304 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4307 DEFUN ("set-window-configuration", Fset_window_configuration,
4308 Sset_window_configuration, 1, 1, 0,
4309 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
4310 CONFIGURATION must be a value previously returned\n\
4311 by `current-window-configuration' (which see).\n\
4312 If CONFIGURATION was made from a frame that is now deleted,\n\
4313 only frame-independent values can be restored. In this case,\n\
4314 the return value is nil. Otherwise the value is t.")
4315 (configuration)
4316 Lisp_Object configuration;
4318 register struct save_window_data *data;
4319 struct Lisp_Vector *saved_windows;
4320 Lisp_Object new_current_buffer;
4321 Lisp_Object frame;
4322 FRAME_PTR f;
4323 int old_point = -1;
4325 while (!WINDOW_CONFIGURATIONP (configuration))
4326 wrong_type_argument (Qwindow_configuration_p, configuration);
4328 data = (struct save_window_data *) XVECTOR (configuration);
4329 saved_windows = XVECTOR (data->saved_windows);
4331 new_current_buffer = data->current_buffer;
4332 if (NILP (XBUFFER (new_current_buffer)->name))
4333 new_current_buffer = Qnil;
4334 else
4336 if (XBUFFER (new_current_buffer) == current_buffer)
4337 old_point = PT;
4341 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4342 f = XFRAME (frame);
4344 /* If f is a dead frame, don't bother rebuilding its window tree.
4345 However, there is other stuff we should still try to do below. */
4346 if (FRAME_LIVE_P (f))
4348 register struct window *w;
4349 register struct saved_window *p;
4350 struct window *root_window;
4351 struct window **leaf_windows;
4352 int n_leaf_windows;
4353 int k, i;
4355 /* If the frame has been resized since this window configuration was
4356 made, we change the frame to the size specified in the
4357 configuration, restore the configuration, and then resize it
4358 back. We keep track of the prevailing height in these variables. */
4359 int previous_frame_height = FRAME_HEIGHT (f);
4360 int previous_frame_width = FRAME_WIDTH (f);
4361 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
4362 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
4364 /* The mouse highlighting code could get screwed up
4365 if it runs during this. */
4366 BLOCK_INPUT;
4368 if (XFASTINT (data->frame_height) != previous_frame_height
4369 || XFASTINT (data->frame_width) != previous_frame_width)
4370 change_frame_size (f, XFASTINT (data->frame_height),
4371 XFASTINT (data->frame_width), 0, 0, 0);
4372 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4373 if (XFASTINT (data->frame_menu_bar_lines)
4374 != previous_frame_menu_bar_lines)
4375 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
4376 #ifdef HAVE_WINDOW_SYSTEM
4377 if (XFASTINT (data->frame_tool_bar_lines)
4378 != previous_frame_tool_bar_lines)
4379 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
4380 #endif
4381 #endif
4383 if (! NILP (XWINDOW (selected_window)->buffer))
4385 w = XWINDOW (selected_window);
4386 set_marker_both (w->pointm,
4387 w->buffer,
4388 BUF_PT (XBUFFER (w->buffer)),
4389 BUF_PT_BYTE (XBUFFER (w->buffer)));
4392 windows_or_buffers_changed++;
4393 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4395 /* Problem: Freeing all matrices and later allocating them again
4396 is a serious redisplay flickering problem. What we would
4397 really like to do is to free only those matrices not reused
4398 below. */
4399 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
4400 leaf_windows
4401 = (struct window **) alloca (count_windows (root_window)
4402 * sizeof (struct window *));
4403 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
4405 /* Temporarily avoid any problems with windows that are smaller
4406 than they are supposed to be. */
4407 window_min_height = 1;
4408 window_min_width = 1;
4410 /* Kludge Alert!
4411 Mark all windows now on frame as "deleted".
4412 Restoring the new configuration "undeletes" any that are in it.
4414 Save their current buffers in their height fields, since we may
4415 need it later, if a buffer saved in the configuration is now
4416 dead. */
4417 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4419 for (k = 0; k < saved_windows->size; k++)
4421 p = SAVED_WINDOW_N (saved_windows, k);
4422 w = XWINDOW (p->window);
4423 w->next = Qnil;
4425 if (!NILP (p->parent))
4426 w->parent = SAVED_WINDOW_N (saved_windows,
4427 XFASTINT (p->parent))->window;
4428 else
4429 w->parent = Qnil;
4431 if (!NILP (p->prev))
4433 w->prev = SAVED_WINDOW_N (saved_windows,
4434 XFASTINT (p->prev))->window;
4435 XWINDOW (w->prev)->next = p->window;
4437 else
4439 w->prev = Qnil;
4440 if (!NILP (w->parent))
4442 if (EQ (p->width, XWINDOW (w->parent)->width))
4444 XWINDOW (w->parent)->vchild = p->window;
4445 XWINDOW (w->parent)->hchild = Qnil;
4447 else
4449 XWINDOW (w->parent)->hchild = p->window;
4450 XWINDOW (w->parent)->vchild = Qnil;
4455 /* If we squirreled away the buffer in the window's height,
4456 restore it now. */
4457 if (BUFFERP (w->height))
4458 w->buffer = w->height;
4459 w->left = p->left;
4460 w->top = p->top;
4461 w->width = p->width;
4462 w->height = p->height;
4463 w->hscroll = p->hscroll;
4464 w->display_table = p->display_table;
4465 XSETFASTINT (w->last_modified, 0);
4466 XSETFASTINT (w->last_overlay_modified, 0);
4468 /* Reinstall the saved buffer and pointers into it. */
4469 if (NILP (p->buffer))
4470 w->buffer = p->buffer;
4471 else
4473 if (!NILP (XBUFFER (p->buffer)->name))
4474 /* If saved buffer is alive, install it. */
4476 w->buffer = p->buffer;
4477 w->start_at_line_beg = p->start_at_line_beg;
4478 set_marker_restricted (w->start, p->start, w->buffer);
4479 set_marker_restricted (w->pointm, p->pointm, w->buffer);
4480 Fset_marker (XBUFFER (w->buffer)->mark,
4481 p->mark, w->buffer);
4483 /* As documented in Fcurrent_window_configuration, don't
4484 save the location of point in the buffer which was current
4485 when the window configuration was recorded. */
4486 if (!EQ (p->buffer, new_current_buffer)
4487 && XBUFFER (p->buffer) == current_buffer)
4488 Fgoto_char (w->pointm);
4490 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
4491 /* Else unless window has a live buffer, get one. */
4493 w->buffer = Fcdr (Fcar (Vbuffer_alist));
4494 /* This will set the markers to beginning of visible
4495 range. */
4496 set_marker_restricted (w->start, make_number (0), w->buffer);
4497 set_marker_restricted (w->pointm, make_number (0),w->buffer);
4498 w->start_at_line_beg = Qt;
4500 else
4501 /* Keeping window's old buffer; make sure the markers
4502 are real. */
4504 /* Set window markers at start of visible range. */
4505 if (XMARKER (w->start)->buffer == 0)
4506 set_marker_restricted (w->start, make_number (0),
4507 w->buffer);
4508 if (XMARKER (w->pointm)->buffer == 0)
4509 set_marker_restricted_both (w->pointm, w->buffer,
4510 BUF_PT (XBUFFER (w->buffer)),
4511 BUF_PT_BYTE (XBUFFER (w->buffer)));
4512 w->start_at_line_beg = Qt;
4517 FRAME_ROOT_WINDOW (f) = data->root_window;
4518 Fselect_window (data->current_window);
4519 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
4520 = selected_window;
4522 if (NILP (data->focus_frame)
4523 || (FRAMEP (data->focus_frame)
4524 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
4525 Fredirect_frame_focus (frame, data->focus_frame);
4527 #if 0 /* I don't understand why this is needed, and it causes problems
4528 when the frame's old selected window has been deleted. */
4529 if (f != selected_frame && FRAME_WINDOW_P (f))
4530 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
4531 Qnil, 0);
4532 #endif
4534 /* Set the screen height to the value it had before this function. */
4535 if (previous_frame_height != FRAME_HEIGHT (f)
4536 || previous_frame_width != FRAME_WIDTH (f))
4537 change_frame_size (f, previous_frame_height, previous_frame_width,
4538 0, 0, 0);
4539 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
4540 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
4541 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
4542 make_number (0));
4543 #ifdef HAVE_WINDOW_SYSTEM
4544 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
4545 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
4546 make_number (0));
4547 #endif
4548 #endif
4550 /* Now, free glyph matrices in windows that were not reused. */
4551 for (i = 0; i < n_leaf_windows; ++i)
4552 if (NILP (leaf_windows[i]->buffer))
4554 /* Assert it's not reused as a combination. */
4555 xassert (NILP (leaf_windows[i]->hchild)
4556 && NILP (leaf_windows[i]->vchild));
4557 free_window_matrices (leaf_windows[i]);
4558 SET_FRAME_GARBAGED (f);
4561 adjust_glyphs (f);
4563 UNBLOCK_INPUT;
4565 /* Fselect_window will have made f the selected frame, so we
4566 reselect the proper frame here. Fhandle_switch_frame will change the
4567 selected window too, but that doesn't make the call to
4568 Fselect_window above totally superfluous; it still sets f's
4569 selected window. */
4570 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
4571 do_switch_frame (data->selected_frame, Qnil, 0);
4573 if (! NILP (Vwindow_configuration_change_hook)
4574 && ! NILP (Vrun_hooks))
4575 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4578 if (!NILP (new_current_buffer))
4580 Fset_buffer (new_current_buffer);
4582 /* If the buffer that is current now is the same
4583 that was current before setting the window configuration,
4584 don't alter its PT. */
4585 if (old_point >= 0)
4586 SET_PT (old_point);
4589 /* Restore the minimum heights recorded in the configuration. */
4590 window_min_height = XINT (data->min_height);
4591 window_min_width = XINT (data->min_width);
4593 Vminibuf_scroll_window = data->minibuf_scroll_window;
4595 return (FRAME_LIVE_P (f) ? Qt : Qnil);
4598 /* Mark all windows now on frame as deleted
4599 by setting their buffers to nil. */
4601 void
4602 delete_all_subwindows (w)
4603 register struct window *w;
4605 if (!NILP (w->next))
4606 delete_all_subwindows (XWINDOW (w->next));
4607 if (!NILP (w->vchild))
4608 delete_all_subwindows (XWINDOW (w->vchild));
4609 if (!NILP (w->hchild))
4610 delete_all_subwindows (XWINDOW (w->hchild));
4612 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
4614 if (!NILP (w->buffer))
4615 unshow_buffer (w);
4617 /* We set all three of these fields to nil, to make sure that we can
4618 distinguish this dead window from any live window. Live leaf
4619 windows will have buffer set, and combination windows will have
4620 vchild or hchild set. */
4621 w->buffer = Qnil;
4622 w->vchild = Qnil;
4623 w->hchild = Qnil;
4626 static int
4627 count_windows (window)
4628 register struct window *window;
4630 register int count = 1;
4631 if (!NILP (window->next))
4632 count += count_windows (XWINDOW (window->next));
4633 if (!NILP (window->vchild))
4634 count += count_windows (XWINDOW (window->vchild));
4635 if (!NILP (window->hchild))
4636 count += count_windows (XWINDOW (window->hchild));
4637 return count;
4641 /* Fill vector FLAT with leaf windows under W, starting at index I.
4642 Value is last index + 1. */
4644 static int
4645 get_leaf_windows (w, flat, i)
4646 struct window *w;
4647 struct window **flat;
4648 int i;
4650 while (w)
4652 if (!NILP (w->hchild))
4653 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
4654 else if (!NILP (w->vchild))
4655 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
4656 else
4657 flat[i++] = w;
4659 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4662 return i;
4666 /* Return a pointer to the glyph W's physical cursor is on. Value is
4667 null if W's current matrix is invalid, so that no meaningfull glyph
4668 can be returned. */
4670 struct glyph *
4671 get_phys_cursor_glyph (w)
4672 struct window *w;
4674 struct glyph_row *row;
4675 struct glyph *glyph;
4677 if (w->phys_cursor.vpos >= 0
4678 && w->phys_cursor.vpos < w->current_matrix->nrows
4679 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
4680 row->enabled_p)
4681 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
4682 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
4683 else
4684 glyph = NULL;
4686 return glyph;
4690 static int
4691 save_window_save (window, vector, i)
4692 Lisp_Object window;
4693 struct Lisp_Vector *vector;
4694 int i;
4696 register struct saved_window *p;
4697 register struct window *w;
4698 register Lisp_Object tem;
4700 for (;!NILP (window); window = w->next)
4702 p = SAVED_WINDOW_N (vector, i);
4703 w = XWINDOW (window);
4705 XSETFASTINT (w->temslot, i++);
4706 p->window = window;
4707 p->buffer = w->buffer;
4708 p->left = w->left;
4709 p->top = w->top;
4710 p->width = w->width;
4711 p->height = w->height;
4712 p->hscroll = w->hscroll;
4713 p->display_table = w->display_table;
4714 if (!NILP (w->buffer))
4716 /* Save w's value of point in the window configuration.
4717 If w is the selected window, then get the value of point
4718 from the buffer; pointm is garbage in the selected window. */
4719 if (EQ (window, selected_window))
4721 p->pointm = Fmake_marker ();
4722 set_marker_both (p->pointm, w->buffer,
4723 BUF_PT (XBUFFER (w->buffer)),
4724 BUF_PT_BYTE (XBUFFER (w->buffer)));
4726 else
4727 p->pointm = Fcopy_marker (w->pointm, Qnil);
4729 p->start = Fcopy_marker (w->start, Qnil);
4730 p->start_at_line_beg = w->start_at_line_beg;
4732 tem = XBUFFER (w->buffer)->mark;
4733 p->mark = Fcopy_marker (tem, Qnil);
4735 else
4737 p->pointm = Qnil;
4738 p->start = Qnil;
4739 p->mark = Qnil;
4740 p->start_at_line_beg = Qnil;
4743 if (NILP (w->parent))
4744 p->parent = Qnil;
4745 else
4746 p->parent = XWINDOW (w->parent)->temslot;
4748 if (NILP (w->prev))
4749 p->prev = Qnil;
4750 else
4751 p->prev = XWINDOW (w->prev)->temslot;
4753 if (!NILP (w->vchild))
4754 i = save_window_save (w->vchild, vector, i);
4755 if (!NILP (w->hchild))
4756 i = save_window_save (w->hchild, vector, i);
4759 return i;
4762 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
4763 Scurrent_window_configuration, 0, 1, 0,
4764 "Return an object representing the current window configuration of FRAME.\n\
4765 If FRAME is nil or omitted, use the selected frame.\n\
4766 This describes the number of windows, their sizes and current buffers,\n\
4767 and for each displayed buffer, where display starts, and the positions of\n\
4768 point and mark. An exception is made for point in the current buffer:\n\
4769 its value is -not- saved.\n\
4770 This also records the currently selected frame, and FRAME's focus\n\
4771 redirection (see `redirect-frame-focus').")
4772 (frame)
4773 Lisp_Object frame;
4775 register Lisp_Object tem;
4776 register int n_windows;
4777 register struct save_window_data *data;
4778 register struct Lisp_Vector *vec;
4779 register int i;
4780 FRAME_PTR f;
4782 if (NILP (frame))
4783 frame = selected_frame;
4784 CHECK_LIVE_FRAME (frame, 0);
4785 f = XFRAME (frame);
4787 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4788 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
4789 for (i = 0; i < VECSIZE (struct save_window_data); i++)
4790 vec->contents[i] = Qnil;
4791 vec->size = VECSIZE (struct save_window_data);
4792 data = (struct save_window_data *)vec;
4794 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
4795 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
4796 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
4797 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
4798 data->selected_frame = selected_frame;
4799 data->current_window = FRAME_SELECTED_WINDOW (f);
4800 XSETBUFFER (data->current_buffer, current_buffer);
4801 data->minibuf_scroll_window = Vminibuf_scroll_window;
4802 data->root_window = FRAME_ROOT_WINDOW (f);
4803 data->focus_frame = FRAME_FOCUS_FRAME (f);
4804 XSETINT (data->min_height, window_min_height);
4805 XSETINT (data->min_width, window_min_width);
4806 tem = Fmake_vector (make_number (n_windows), Qnil);
4807 data->saved_windows = tem;
4808 for (i = 0; i < n_windows; i++)
4809 XVECTOR (tem)->contents[i]
4810 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
4811 save_window_save (FRAME_ROOT_WINDOW (f),
4812 XVECTOR (tem), 0);
4813 XSETWINDOW_CONFIGURATION (tem, data);
4814 return (tem);
4817 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
4818 0, UNEVALLED, 0,
4819 "Execute body, preserving window sizes and contents.\n\
4820 Restore which buffer appears in which window, where display starts,\n\
4821 and the value of point and mark for each window.\n\
4822 Also restore which buffer is current.\n\
4823 Does not restore the value of point in current buffer.")
4824 (args)
4825 Lisp_Object args;
4827 register Lisp_Object val;
4828 register int count = specpdl_ptr - specpdl;
4830 record_unwind_protect (Fset_window_configuration,
4831 Fcurrent_window_configuration (Qnil));
4832 val = Fprogn (args);
4833 return unbind_to (count, val);
4837 /***********************************************************************
4838 Marginal Areas
4839 ***********************************************************************/
4841 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
4842 2, 3, 0,
4843 "Set width of marginal areas of window WINDOW.\n\
4844 If window is nil, set margins of the currently selected window.\n\
4845 First parameter LEFT-WIDTH specifies the number of character\n\
4846 cells to reserve for the left marginal area. Second parameter\n\
4847 RIGHT-WIDTH does the same for the right marginal area.\n\
4848 A nil width parameter means no margin.")
4849 (window, left, right)
4850 Lisp_Object window, left, right;
4852 struct window *w = decode_window (window);
4854 if (!NILP (left))
4855 CHECK_NUMBER_OR_FLOAT (left, 1);
4856 if (!NILP (right))
4857 CHECK_NUMBER_OR_FLOAT (right, 2);
4859 /* Check widths < 0 and translate a zero width to nil.
4860 Margins that are too wide have to be checked elsewhere. */
4861 if ((INTEGERP (left) && XINT (left) < 0)
4862 || (FLOATP (left) && XFLOAT_DATA (left) <= 0))
4863 XSETFASTINT (left, 0);
4864 if (INTEGERP (left) && XFASTINT (left) == 0)
4865 left = Qnil;
4867 if ((INTEGERP (right) && XINT (right) < 0)
4868 || (FLOATP (right) && XFLOAT_DATA (right) <= 0))
4869 XSETFASTINT (right, 0);
4870 if (INTEGERP (right) && XFASTINT (right) == 0)
4871 right = Qnil;
4873 w->left_margin_width = left;
4874 w->right_margin_width = right;
4876 ++windows_or_buffers_changed;
4877 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
4878 return Qnil;
4882 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
4883 0, 1, 0,
4884 "Get width of marginal areas of window WINDOW.\n\
4885 If WINDOW is omitted or nil, use the currently selected window.\n\
4886 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).\n\
4887 If a marginal area does not exist, its width will be returned\n\
4888 as nil.")
4889 (window)
4890 Lisp_Object window;
4892 struct window *w = decode_window (window);
4893 return Fcons (w->left_margin_width, w->right_margin_width);
4898 /***********************************************************************
4899 Smooth scrolling
4900 ***********************************************************************/
4902 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
4903 "Return the amount by which WINDOW is scrolled vertically.\n\
4904 Use the selected window if WINDOW is nil or omitted.\n\
4905 Value is a multiple of the canonical character height of WINDOW.")
4906 (window)
4907 Lisp_Object window;
4909 Lisp_Object result;
4910 struct frame *f;
4911 struct window *w;
4913 if (NILP (window))
4914 window = selected_window;
4915 else
4916 CHECK_WINDOW (window, 0);
4917 w = XWINDOW (window);
4918 f = XFRAME (w->frame);
4920 if (FRAME_WINDOW_P (f))
4921 result = CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
4922 else
4923 result = make_number (0);
4924 return result;
4928 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
4929 2, 2, 0,
4930 "Set amount by which WINDOW should be scrolled vertically to VSCROLL.\n\
4931 WINDOW nil or omitted means use the selected window. VSCROLL is a\n\
4932 non-negative multiple of the canonical character height of WINDOW.")
4933 (window, vscroll)
4934 Lisp_Object window, vscroll;
4936 struct window *w;
4937 struct frame *f;
4939 if (NILP (window))
4940 window = selected_window;
4941 else
4942 CHECK_WINDOW (window, 0);
4943 CHECK_NUMBER_OR_FLOAT (vscroll, 1);
4945 w = XWINDOW (window);
4946 f = XFRAME (w->frame);
4948 if (FRAME_WINDOW_P (f))
4950 int old_dy = w->vscroll;
4952 w->vscroll = - CANON_Y_UNIT (f) * XFLOATINT (vscroll);
4953 w->vscroll = min (w->vscroll, 0);
4955 /* Adjust glyph matrix of the frame if the virtual display
4956 area becomes larger than before. */
4957 if (w->vscroll < 0 && w->vscroll < old_dy)
4958 adjust_glyphs (f);
4960 /* Prevent redisplay shortcuts. */
4961 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4964 return Fwindow_vscroll (window);
4968 /* Call FN for all leaf windows on frame F. FN is called with the
4969 first argument being a pointer to the leaf window, and with
4970 additional arguments A1..A4. */
4972 void
4973 foreach_window (f, fn, a1, a2, a3, a4)
4974 struct frame *f;
4975 void (* fn) ();
4976 int a1, a2, a3, a4;
4978 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, a1, a2, a3, a4);
4982 /* Helper function for foreach_window. Call FN for all leaf windows
4983 reachable from W. FN is called with the first argument being a
4984 pointer to the leaf window, and with additional arguments A1..A4. */
4986 static void
4987 foreach_window_1 (w, fn, a1, a2, a3, a4)
4988 struct window *w;
4989 void (* fn) ();
4990 int a1, a2, a3, a4;
4992 while (w)
4994 if (!NILP (w->hchild))
4995 foreach_window_1 (XWINDOW (w->hchild), fn, a1, a2, a3, a4);
4996 else if (!NILP (w->vchild))
4997 foreach_window_1 (XWINDOW (w->vchild), fn, a1, a2, a3, a4);
4998 else
4999 fn (w, a1, a2, a3, a4);
5001 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5006 /* Freeze or unfreeze the window start of W if unless it is a
5007 mini-window or the selected window. FREEZE_P non-zero means freeze
5008 the window start. */
5010 static void
5011 freeze_window_start (w, freeze_p)
5012 struct window *w;
5013 int freeze_p;
5015 if (w == XWINDOW (selected_window)
5016 || MINI_WINDOW_P (w)
5017 || (MINI_WINDOW_P (XWINDOW (selected_window))
5018 && w == XWINDOW (Vminibuf_scroll_window)))
5019 freeze_p = 0;
5021 w->frozen_window_start_p = freeze_p;
5025 /* Freeze or unfreeze the window starts of all leaf windows on frame
5026 F, except the selected window and a mini-window. FREEZE_P non-zero
5027 means freeze the window start. */
5029 void
5030 freeze_window_starts (f, freeze_p)
5031 struct frame *f;
5032 int freeze_p;
5034 foreach_window (f, freeze_window_start, freeze_p);
5038 /***********************************************************************
5039 Initialization
5040 ***********************************************************************/
5042 /* Return 1 if window configurations C1 and C2
5043 describe the same state of affairs. This is used by Fequal. */
5046 compare_window_configurations (c1, c2, ignore_positions)
5047 Lisp_Object c1, c2;
5048 int ignore_positions;
5050 register struct save_window_data *d1, *d2;
5051 struct Lisp_Vector *sw1, *sw2;
5052 int i;
5054 d1 = (struct save_window_data *) XVECTOR (c1);
5055 d2 = (struct save_window_data *) XVECTOR (c2);
5056 sw1 = XVECTOR (d1->saved_windows);
5057 sw2 = XVECTOR (d2->saved_windows);
5059 if (! EQ (d1->frame_width, d2->frame_width))
5060 return 0;
5061 if (! EQ (d1->frame_height, d2->frame_height))
5062 return 0;
5063 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
5064 return 0;
5065 if (! EQ (d1->selected_frame, d2->selected_frame))
5066 return 0;
5067 /* Don't compare the current_window field directly.
5068 Instead see w1_is_current and w2_is_current, below. */
5069 if (! EQ (d1->current_buffer, d2->current_buffer))
5070 return 0;
5071 if (! ignore_positions)
5072 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
5073 return 0;
5074 /* Don't compare the root_window field.
5075 We don't require the two configurations
5076 to use the same window object,
5077 and the two root windows must be equivalent
5078 if everything else compares equal. */
5079 if (! EQ (d1->focus_frame, d2->focus_frame))
5080 return 0;
5081 if (! EQ (d1->min_width, d2->min_width))
5082 return 0;
5083 if (! EQ (d1->min_height, d2->min_height))
5084 return 0;
5086 /* Verify that the two confis have the same number of windows. */
5087 if (sw1->size != sw2->size)
5088 return 0;
5090 for (i = 0; i < sw1->size; i++)
5092 struct saved_window *p1, *p2;
5093 int w1_is_current, w2_is_current;
5095 p1 = SAVED_WINDOW_N (sw1, i);
5096 p2 = SAVED_WINDOW_N (sw2, i);
5098 /* Verify that the current windows in the two
5099 configurations correspond to each other. */
5100 w1_is_current = EQ (d1->current_window, p1->window);
5101 w2_is_current = EQ (d2->current_window, p2->window);
5103 if (w1_is_current != w2_is_current)
5104 return 0;
5106 /* Verify that the corresponding windows do match. */
5107 if (! EQ (p1->buffer, p2->buffer))
5108 return 0;
5109 if (! EQ (p1->left, p2->left))
5110 return 0;
5111 if (! EQ (p1->top, p2->top))
5112 return 0;
5113 if (! EQ (p1->width, p2->width))
5114 return 0;
5115 if (! EQ (p1->height, p2->height))
5116 return 0;
5117 if (! EQ (p1->display_table, p2->display_table))
5118 return 0;
5119 if (! EQ (p1->parent, p2->parent))
5120 return 0;
5121 if (! EQ (p1->prev, p2->prev))
5122 return 0;
5123 if (! ignore_positions)
5125 if (! EQ (p1->hscroll, p2->hscroll))
5126 return 0;
5127 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
5128 return 0;
5129 if (NILP (Fequal (p1->start, p2->start)))
5130 return 0;
5131 if (NILP (Fequal (p1->pointm, p2->pointm)))
5132 return 0;
5133 if (NILP (Fequal (p1->mark, p2->mark)))
5134 return 0;
5138 return 1;
5141 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
5142 Scompare_window_configurations, 2, 2, 0,
5143 "Compare two window configurations as regards the structure of windows.\n\
5144 This function ignores details such as the values of point and mark\n\
5145 and scrolling positions.")
5146 (x, y)
5147 Lisp_Object x, y;
5149 if (compare_window_configurations (x, y, 1))
5150 return Qt;
5151 return Qnil;
5154 void
5155 init_window_once ()
5157 struct frame *f = make_terminal_frame ();
5158 XSETFRAME (selected_frame, f);
5159 Vterminal_frame = selected_frame;
5160 minibuf_window = f->minibuffer_window;
5161 selected_window = f->selected_window;
5162 last_nonminibuf_frame = f;
5164 window_initialized = 1;
5167 void
5168 syms_of_window ()
5170 Qleft_bitmap_area = intern ("left-bitmap-area");
5171 staticpro (&Qleft_bitmap_area);
5172 Qright_bitmap_area = intern ("right-bitmap-area");
5173 staticpro (&Qright_bitmap_area);
5175 Qwindow_size_fixed = intern ("window-size-fixed");
5176 staticpro (&Qwindow_size_fixed);
5178 staticpro (&Qwindow_configuration_change_hook);
5179 Qwindow_configuration_change_hook
5180 = intern ("window-configuration-change-hook");
5182 Qwindowp = intern ("windowp");
5183 staticpro (&Qwindowp);
5185 Qwindow_configuration_p = intern ("window-configuration-p");
5186 staticpro (&Qwindow_configuration_p);
5188 Qwindow_live_p = intern ("window-live-p");
5189 staticpro (&Qwindow_live_p);
5191 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
5192 staticpro (&Qtemp_buffer_show_hook);
5194 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
5195 "Non-nil means call as function to display a help buffer.\n\
5196 The function is called with one argument, the buffer to be displayed.\n\
5197 Used by `with-output-to-temp-buffer'.\n\
5198 If this function is used, then it must do the entire job of showing\n\
5199 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
5200 Vtemp_buffer_show_function = Qnil;
5202 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
5203 "If non-nil, function to call to handle `display-buffer'.\n\
5204 It will receive two args, the buffer and a flag which if non-nil means\n\
5205 that the currently selected window is not acceptable.\n\
5206 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
5207 work using this function.");
5208 Vdisplay_buffer_function = Qnil;
5210 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
5211 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
5212 Vminibuf_scroll_window = Qnil;
5214 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
5215 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
5216 Vother_window_scroll_buffer = Qnil;
5218 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
5219 "*Non-nil means `display-buffer' should make a separate frame.");
5220 pop_up_frames = 0;
5222 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
5223 "Function to call to handle automatic new frame creation.\n\
5224 It is called with no arguments and should return a newly created frame.\n\
5226 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
5227 where `pop-up-frame-alist' would hold the default frame parameters.");
5228 Vpop_up_frame_function = Qnil;
5230 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
5231 "*List of buffer names that should have their own special frames.\n\
5232 Displaying a buffer whose name is in this list makes a special frame for it\n\
5233 using `special-display-function'. See also `special-display-regexps'.\n\
5235 An element of the list can be a list instead of just a string.\n\
5236 There are two ways to use a list as an element:\n\
5237 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
5238 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5239 In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
5240 followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
5241 All this is done by the function found in `special-display-function'.\n\
5243 If this variable appears \"not to work\", because you add a name to it\n\
5244 but that buffer still appears in the selected window, look at the\n\
5245 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5246 Those variables take precedence over this one.");
5247 Vspecial_display_buffer_names = Qnil;
5249 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
5250 "*List of regexps saying which buffers should have their own special frames.\n\
5251 If a buffer name matches one of these regexps, it gets its own frame.\n\
5252 Displaying a buffer whose name is in this list makes a special frame for it\n\
5253 using `special-display-function'.\n\
5255 An element of the list can be a list instead of just a string.\n\
5256 There are two ways to use a list as an element:\n\
5257 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
5258 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
5259 In the latter case, FUNCTION is called with the buffer as first argument,\n\
5260 followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
5261 All this is done by the function found in `special-display-function'.\n\
5263 If this variable appears \"not to work\", because you add a regexp to it\n\
5264 but the matching buffers still appear in the selected window, look at the\n\
5265 values of `same-window-buffer-names' and `same-window-regexps'.\n\
5266 Those variables take precedence over this one.");
5267 Vspecial_display_regexps = Qnil;
5269 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
5270 "Function to call to make a new frame for a special buffer.\n\
5271 It is called with two arguments, the buffer and optional buffer specific\n\
5272 data, and should return a window displaying that buffer.\n\
5273 The default value makes a separate frame for the buffer,\n\
5274 using `special-display-frame-alist' to specify the frame parameters.\n\
5276 A buffer is special if its is listed in `special-display-buffer-names'\n\
5277 or matches a regexp in `special-display-regexps'.");
5278 Vspecial_display_function = Qnil;
5280 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
5281 "*List of buffer names that should appear in the selected window.\n\
5282 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
5283 switches to it in the selected window, rather than making it appear\n\
5284 in some other window.\n\
5286 An element of the list can be a cons cell instead of just a string.\n\
5287 Then the car must be a string, which specifies the buffer name.\n\
5288 This is for compatibility with `special-display-buffer-names';\n\
5289 the cdr of the cons cell is ignored.\n\
5291 See also `same-window-regexps'.");
5292 Vsame_window_buffer_names = Qnil;
5294 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
5295 "*List of regexps saying which buffers should appear in the selected window.\n\
5296 If a buffer name matches one of these regexps, then displaying it\n\
5297 using `display-buffer' or `pop-to-buffer' switches to it\n\
5298 in the selected window, rather than making it appear in some other window.\n\
5300 An element of the list can be a cons cell instead of just a string.\n\
5301 Then the car must be a string, which specifies the buffer name.\n\
5302 This is for compatibility with `special-display-buffer-names';\n\
5303 the cdr of the cons cell is ignored.\n\
5305 See also `same-window-buffer-names'.");
5306 Vsame_window_regexps = Qnil;
5308 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
5309 "*Non-nil means display-buffer should make new windows.");
5310 pop_up_windows = 1;
5312 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
5313 "*Number of lines of continuity when scrolling by screenfuls.");
5314 next_screen_context_lines = 2;
5316 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
5317 "*display-buffer would prefer to split the largest window if this large.\n\
5318 If there is only one window, it is split regardless of this value.");
5319 split_height_threshold = 500;
5321 DEFVAR_INT ("window-min-height", &window_min_height,
5322 "*Delete any window less than this tall (including its mode line).");
5323 window_min_height = 4;
5325 DEFVAR_INT ("window-min-width", &window_min_width,
5326 "*Delete any window less than this wide.");
5327 window_min_width = 10;
5329 DEFVAR_LISP ("scroll-preserve-screen-position",
5330 &Vscroll_preserve_screen_position,
5331 "*Nonzero means scroll commands move point to keep its screen line unchanged.");
5332 Vscroll_preserve_screen_position = Qnil;
5334 DEFVAR_LISP ("window-configuration-change-hook",
5335 &Vwindow_configuration_change_hook,
5336 "Functions to call when window configuration changes.\n\
5337 The selected frame is the one whose configuration has changed.");
5338 Vwindow_configuration_change_hook = Qnil;
5340 defsubr (&Sselected_window);
5341 defsubr (&Sminibuffer_window);
5342 defsubr (&Swindow_minibuffer_p);
5343 defsubr (&Swindowp);
5344 defsubr (&Swindow_live_p);
5345 defsubr (&Spos_visible_in_window_p);
5346 defsubr (&Swindow_buffer);
5347 defsubr (&Swindow_height);
5348 defsubr (&Swindow_width);
5349 defsubr (&Swindow_hscroll);
5350 defsubr (&Sset_window_hscroll);
5351 defsubr (&Swindow_redisplay_end_trigger);
5352 defsubr (&Sset_window_redisplay_end_trigger);
5353 defsubr (&Swindow_edges);
5354 defsubr (&Scoordinates_in_window_p);
5355 defsubr (&Swindow_at);
5356 defsubr (&Swindow_point);
5357 defsubr (&Swindow_start);
5358 defsubr (&Swindow_end);
5359 defsubr (&Sset_window_point);
5360 defsubr (&Sset_window_start);
5361 defsubr (&Swindow_dedicated_p);
5362 defsubr (&Sset_window_dedicated_p);
5363 defsubr (&Swindow_display_table);
5364 defsubr (&Sset_window_display_table);
5365 defsubr (&Snext_window);
5366 defsubr (&Sprevious_window);
5367 defsubr (&Sother_window);
5368 defsubr (&Sget_lru_window);
5369 defsubr (&Sget_largest_window);
5370 defsubr (&Sget_buffer_window);
5371 defsubr (&Sdelete_other_windows);
5372 defsubr (&Sdelete_windows_on);
5373 defsubr (&Sreplace_buffer_in_windows);
5374 defsubr (&Sdelete_window);
5375 defsubr (&Sset_window_buffer);
5376 defsubr (&Sselect_window);
5377 defsubr (&Sspecial_display_p);
5378 defsubr (&Ssame_window_p);
5379 defsubr (&Sdisplay_buffer);
5380 defsubr (&Ssplit_window);
5381 defsubr (&Senlarge_window);
5382 defsubr (&Sshrink_window);
5383 defsubr (&Sscroll_up);
5384 defsubr (&Sscroll_down);
5385 defsubr (&Sscroll_left);
5386 defsubr (&Sscroll_right);
5387 defsubr (&Sother_window_for_scrolling);
5388 defsubr (&Sscroll_other_window);
5389 defsubr (&Srecenter);
5390 defsubr (&Smove_to_window_line);
5391 defsubr (&Swindow_configuration_p);
5392 defsubr (&Swindow_configuration_frame);
5393 defsubr (&Sset_window_configuration);
5394 defsubr (&Scurrent_window_configuration);
5395 defsubr (&Ssave_window_excursion);
5396 defsubr (&Sset_window_margins);
5397 defsubr (&Swindow_margins);
5398 defsubr (&Swindow_vscroll);
5399 defsubr (&Sset_window_vscroll);
5400 defsubr (&Scompare_window_configurations);
5403 void
5404 keys_of_window ()
5406 initial_define_key (control_x_map, '1', "delete-other-windows");
5407 initial_define_key (control_x_map, '2', "split-window");
5408 initial_define_key (control_x_map, '0', "delete-window");
5409 initial_define_key (control_x_map, 'o', "other-window");
5410 initial_define_key (control_x_map, '^', "enlarge-window");
5411 initial_define_key (control_x_map, '<', "scroll-left");
5412 initial_define_key (control_x_map, '>', "scroll-right");
5414 initial_define_key (global_map, Ctl ('V'), "scroll-up");
5415 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
5416 initial_define_key (meta_map, 'v', "scroll-down");
5418 initial_define_key (global_map, Ctl('L'), "recenter");
5419 initial_define_key (meta_map, 'r', "move-to-window-line");