(*:Linux:*:*): Always use ${VENDOR}.
[emacs/old-mirror.git] / src / window.c
blob016c0070bb5a6b2a221d4e3dc7578e4dcf2c10c2
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985, 86, 87, 93, 94, 95, 96 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"
33 Lisp_Object Qwindowp, Qwindow_live_p;
35 Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
36 Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
38 void delete_all_subwindows ();
39 static struct window *decode_window();
41 /* This is the window in which the terminal's cursor should
42 be left when nothing is being done with it. This must
43 always be a leaf window, and its buffer is selected by
44 the top level editing loop at the end of each command.
46 This value is always the same as
47 FRAME_SELECTED_WINDOW (selected_frame). */
49 Lisp_Object selected_window;
51 /* The minibuffer window of the selected frame.
52 Note that you cannot test for minibufferness of an arbitrary window
53 by comparing against this; but you can test for minibufferness of
54 the selected window. */
55 Lisp_Object minibuf_window;
57 /* Non-nil means it is the window for C-M-v to scroll
58 when the minibuffer is selected. */
59 Lisp_Object Vminibuf_scroll_window;
61 /* Non-nil means this is the buffer whose window C-M-v should scroll. */
62 Lisp_Object Vother_window_scroll_buffer;
64 /* Non-nil means it's function to call to display temp buffers. */
65 Lisp_Object Vtemp_buffer_show_function;
67 /* If a window gets smaller than either of these, it is removed. */
68 int window_min_height;
69 int window_min_width;
71 /* Nonzero implies Fdisplay_buffer should create windows. */
72 int pop_up_windows;
74 /* Nonzero implies make new frames for Fdisplay_buffer. */
75 int pop_up_frames;
77 /* Non-nil means use this function instead of default */
78 Lisp_Object Vpop_up_frame_function;
80 /* Function to call to handle Fdisplay_buffer. */
81 Lisp_Object Vdisplay_buffer_function;
83 /* List of buffer *names* for buffers that should have their own frames. */
84 Lisp_Object Vspecial_display_buffer_names;
86 /* List of regexps for buffer names that should have their own frames. */
87 Lisp_Object Vspecial_display_regexps;
89 /* Function to pop up a special frame. */
90 Lisp_Object Vspecial_display_function;
92 /* List of buffer *names* for buffers to appear in selected window. */
93 Lisp_Object Vsame_window_buffer_names;
95 /* List of regexps for buffer names to appear in selected window. */
96 Lisp_Object Vsame_window_regexps;
98 /* Hook run at end of temp_output_buffer_show. */
99 Lisp_Object Qtemp_buffer_show_hook;
101 /* Fdisplay_buffer always splits the largest window
102 if that window is more than this high. */
103 int split_height_threshold;
105 /* Number of lines of continuity in scrolling by screenfuls. */
106 int next_screen_context_lines;
108 /* Incremented for each window created. */
109 static int sequence_number;
111 /* Nonzero after init_window_once has finished. */
112 static int window_initialized;
114 /* Hook to run when window config changes. */
115 Lisp_Object Qwindow_configuration_change_hook;
116 Lisp_Object Vwindow_configuration_change_hook;
118 /* Nonzero means scroll commands try to put point
119 at the same screen height as previously. */
120 static int scroll_preserve_screen_position;
122 /* Nonzero means we can split a frame even if it is "unsplittable". */
123 static int inhibit_frame_unsplittable;
125 #define min(a, b) ((a) < (b) ? (a) : (b))
127 extern int scroll_margin;
129 extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
131 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
132 "Returns t if OBJECT is a window.")
133 (object)
134 Lisp_Object object;
136 return WINDOWP (object) ? Qt : Qnil;
139 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
140 "Returns t if OBJECT is a window which is currently visible.")
141 (object)
142 Lisp_Object object;
144 return (WINDOWP (object) && ! NILP (XWINDOW (object)->buffer) ? Qt : Qnil);
147 Lisp_Object
148 make_window ()
150 Lisp_Object val;
151 register struct window *p;
152 register struct Lisp_Vector *vec;
153 int i;
155 vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
156 for (i = 0; i < VECSIZE (struct window); i++)
157 vec->contents[i] = Qnil;
158 vec->size = VECSIZE (struct window);
159 p = (struct window *)vec;
160 XSETFASTINT (p->sequence_number, ++sequence_number);
161 XSETFASTINT (p->left, 0);
162 XSETFASTINT (p->top, 0);
163 XSETFASTINT (p->height, 0);
164 XSETFASTINT (p->width, 0);
165 XSETFASTINT (p->hscroll, 0);
166 XSETFASTINT (p->last_point_x, 0);
167 XSETFASTINT (p->last_point_y, 0);
168 p->start = Fmake_marker ();
169 p->pointm = Fmake_marker ();
170 XSETFASTINT (p->use_time, 0);
171 p->frame = Qnil;
172 p->display_table = Qnil;
173 p->dedicated = Qnil;
174 XSETWINDOW (val, p);
175 return val;
178 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
179 "Return the window that the cursor now appears in and commands apply to.")
182 return selected_window;
185 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
186 "Return the window used now for minibuffers.\n\
187 If the optional argument FRAME is specified, return the minibuffer window\n\
188 used by that frame.")
189 (frame)
190 Lisp_Object frame;
192 if (NILP (frame))
193 XSETFRAME (frame, selected_frame);
194 else
195 CHECK_LIVE_FRAME (frame, 0);
197 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
200 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
201 "Returns non-nil if WINDOW is a minibuffer window.")
202 (window)
203 Lisp_Object window;
205 struct window *w = decode_window (window);
206 return (MINI_WINDOW_P (w) ? Qt : Qnil);
209 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
210 Spos_visible_in_window_p, 0, 2, 0,
211 "Return t if position POS is currently on the frame in WINDOW.\n\
212 Returns nil if that position is scrolled vertically out of view.\n\
213 POS defaults to point; WINDOW, to the selected window.")
214 (pos, window)
215 Lisp_Object pos, window;
217 register struct window *w;
218 register int top;
219 register int height;
220 register int posint;
221 register struct buffer *buf;
222 struct position posval;
223 int hscroll;
225 if (NILP (pos))
226 posint = PT;
227 else
229 CHECK_NUMBER_COERCE_MARKER (pos, 0);
230 posint = XINT (pos);
233 w = decode_window (window);
234 top = marker_position (w->start);
235 hscroll = XINT (w->hscroll);
237 if (posint < top)
238 return Qnil;
240 height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
242 buf = XBUFFER (w->buffer);
243 if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
244 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf))
246 /* If frame is up to date,
247 use the info recorded about how much text fit on it. */
248 if (posint < BUF_Z (buf) - XFASTINT (w->window_end_pos)
249 || (XFASTINT (w->window_end_vpos) < height))
250 return Qt;
251 return Qnil;
253 else
255 if (posint > BUF_ZV (buf))
256 return Qnil;
258 /* w->start can be out of range. If it is, do something reasonable. */
259 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
260 return Qnil;
262 /* If that info is not correct, calculate afresh */
263 /* BUG FIX for the 7th arg (TOHPOS).
265 '0' is harmless, however, ' - (1 << (BITS_PER_SHORT - 1))' is
266 more appropriate here. In case of HSCROLL > 0, this can avoid
267 needless calculation done until (HPOS == 0).
269 We want to determine if the position POSINT is in HEIGHT or
270 not. We don't have to do calculation until (HPOS == 0). We
271 can stop it when VPOS goes beyond HEIGHT. */
272 posval = *compute_motion (top, 0, (hscroll ? 1 - hscroll : 0), 0,
273 posint, height, - (1 << (BITS_PER_SHORT - 1)),
274 window_internal_width (w) - 1,
275 hscroll, 0, w);
277 return posval.vpos < height ? Qt : Qnil;
281 static struct window *
282 decode_window (window)
283 register Lisp_Object window;
285 if (NILP (window))
286 return XWINDOW (selected_window);
288 CHECK_LIVE_WINDOW (window, 0);
289 return XWINDOW (window);
292 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
293 "Return the buffer that WINDOW is displaying.")
294 (window)
295 Lisp_Object window;
297 return decode_window (window)->buffer;
300 DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
301 "Return the number of lines in WINDOW (including its mode line).")
302 (window)
303 Lisp_Object window;
305 return decode_window (window)->height;
308 DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
309 "Return the number of display columns in WINDOW.\n\
310 This is the width that is usable columns available for text in WINDOW.\n\
311 If you want to find out how many columns WINDOW takes up,\n\
312 use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
313 (window)
314 Lisp_Object window;
316 return make_number (window_internal_width (decode_window (window)));
319 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
320 "Return the number of columns by which WINDOW is scrolled from left margin.")
321 (window)
322 Lisp_Object window;
324 return decode_window (window)->hscroll;
327 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
328 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
329 NCOL should be zero or positive.")
330 (window, ncol)
331 register Lisp_Object window, ncol;
333 register struct window *w;
335 CHECK_NUMBER (ncol, 1);
336 if (XINT (ncol) < 0) XSETFASTINT (ncol, 0);
337 w = decode_window (window);
338 if (XINT (w->hscroll) != XINT (ncol))
339 XBUFFER (w->buffer)->clip_changed = 1; /* Prevent redisplay shortcuts */
340 w->hscroll = ncol;
341 return ncol;
344 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
345 Swindow_redisplay_end_trigger, 0, 1, 0,
346 "Return WINDOW's redisplay end trigger value.\n\
347 See `set-window-redisplay-end-trigger' for more information.")
348 (window)
349 Lisp_Object window;
351 return decode_window (window)->redisplay_end_trigger;
354 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
355 Sset_window_redisplay_end_trigger, 2, 2, 0,
356 "Set WINDOW's redisplay end trigger value to VALUE.\n\
357 VALUE should be a buffer position (typically a marker) or nil.\n\
358 If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
359 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
360 with two arguments: WINDOW, and the end trigger value.\n\
361 Afterwards the end-trigger value is reset to nil.")
362 (window, value)
363 register Lisp_Object window, value;
365 register struct window *w;
367 w = decode_window (window);
368 w->redisplay_end_trigger = value;
369 return value;
372 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
373 "Return a list of the edge coordinates of WINDOW.\n\
374 \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
375 RIGHT is one more than the rightmost column used by WINDOW,\n\
376 and BOTTOM is one more than the bottommost row used by WINDOW\n\
377 and its mode-line.")
378 (window)
379 Lisp_Object window;
381 register struct window *w = decode_window (window);
383 return Fcons (w->left, Fcons (w->top,
384 Fcons (make_number (WINDOW_RIGHT_EDGE (w)),
385 Fcons (make_number (XFASTINT (w->top)
386 + XFASTINT (w->height)),
387 Qnil))));
390 /* Test if the character at column *x, row *y is within window *w.
391 If it is not, return 0;
392 if it is in the window's text area,
393 set *x and *y to its location relative to the upper left corner
394 of the window, and
395 return 1;
396 if it is on the window's modeline, return 2;
397 if it is on the border between the window and its right sibling,
398 return 3. */
399 static int
400 coordinates_in_window (w, x, y)
401 register struct window *w;
402 register int *x, *y;
404 register int left = XINT (w->left);
405 register int right_edge = WINDOW_RIGHT_EDGE (w);
406 register int left_margin = WINDOW_LEFT_MARGIN (w);
407 register int right_margin = WINDOW_RIGHT_MARGIN (w);
408 register int window_height = XINT (w->height);
409 register int top = XFASTINT (w->top);
411 if ( *x < left || *x >= right_edge
412 || *y < top || *y >= top + window_height)
413 return 0;
415 if (left_margin != left && *x < left_margin && *x >= left)
416 return 3;
418 if (right_margin != right_edge && *x >= right_margin && *x < right_edge)
419 return 3;
421 /* Is the character is the mode line? */
422 if (*y == top + window_height - 1
423 && ! MINI_WINDOW_P (w))
424 return 2;
426 *x -= WINDOW_LEFT_MARGIN (w);
427 *y -= top;
428 return 1;
431 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
432 Scoordinates_in_window_p, 2, 2, 0,
433 "Return non-nil if COORDINATES are in WINDOW.\n\
434 COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
435 measured in characters from the upper-left corner of the frame.\n\
436 (0 . 0) denotes the character in the upper left corner of the\n\
437 frame.\n\
438 If COORDINATES are in the text portion of WINDOW,\n\
439 the coordinates relative to the window are returned.\n\
440 If they are in the mode line of WINDOW, `mode-line' is returned.\n\
441 If they are on the border between WINDOW and its right sibling,\n\
442 `vertical-line' is returned.")
443 (coordinates, window)
444 register Lisp_Object coordinates, window;
446 int x, y;
448 CHECK_LIVE_WINDOW (window, 0);
449 CHECK_CONS (coordinates, 1);
450 x = XINT (Fcar (coordinates));
451 y = XINT (Fcdr (coordinates));
453 switch (coordinates_in_window (XWINDOW (window), &x, &y))
455 case 0: /* NOT in window at all. */
456 return Qnil;
458 case 1: /* In text part of window. */
459 return Fcons (x, y);
461 case 2: /* In mode line of window. */
462 return Qmode_line;
464 case 3: /* On right border of window. */
465 return Qvertical_line;
467 default:
468 abort ();
472 /* Find the window containing column x, row y, and return it as a
473 Lisp_Object. If x, y is on the window's modeline, set *part
474 to 1; if it is on the separating line between the window and its
475 right sibling, set it to 2; otherwise set it to 0. If there is no
476 window under x, y return nil and leave *part unmodified. */
477 Lisp_Object
478 window_from_coordinates (frame, x, y, part)
479 FRAME_PTR frame;
480 int x, y;
481 int *part;
483 register Lisp_Object tem, first;
485 tem = first = FRAME_SELECTED_WINDOW (frame);
489 int found = coordinates_in_window (XWINDOW (tem), &x, &y);
491 if (found)
493 *part = found - 1;
494 return tem;
497 tem = Fnext_window (tem, Qt, Qlambda);
499 while (! EQ (tem, first));
501 return Qnil;
504 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
505 "Return window containing coordinates X and Y on FRAME.\n\
506 If omitted, FRAME defaults to the currently selected frame.\n\
507 The top left corner of the frame is considered to be row 0,\n\
508 column 0.")
509 (x, y, frame)
510 Lisp_Object x, y, frame;
512 int part;
514 if (NILP (frame))
515 XSETFRAME (frame, selected_frame);
516 else
517 CHECK_LIVE_FRAME (frame, 2);
518 CHECK_NUMBER (x, 0);
519 CHECK_NUMBER (y, 1);
521 return window_from_coordinates (XFRAME (frame),
522 XINT (x), XINT (y),
523 &part);
526 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
527 "Return current value of point in WINDOW.\n\
528 For a nonselected window, this is the value point would have\n\
529 if that window were selected.\n\
531 Note that, when WINDOW is the selected window and its buffer\n\
532 is also currently selected, the value returned is the same as (point).\n\
533 It would be more strictly correct to return the `top-level' value\n\
534 of point, outside of any save-excursion forms.\n\
535 But that is hard to define.")
536 (window)
537 Lisp_Object window;
539 register struct window *w = decode_window (window);
541 if (w == XWINDOW (selected_window)
542 && current_buffer == XBUFFER (w->buffer))
543 return Fpoint ();
544 return Fmarker_position (w->pointm);
547 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
548 "Return position at which display currently starts in WINDOW.\n\
549 This is updated by redisplay or by calling `set-window-start'.")
550 (window)
551 Lisp_Object window;
553 return Fmarker_position (decode_window (window)->start);
556 /* This is text temporarily removed from the doc string below.
558 This function returns nil if the position is not currently known.\n\
559 That happens when redisplay is preempted and doesn't finish.\n\
560 If in that case you want to compute where the end of the window would\n\
561 have been if redisplay had finished, do this:\n\
562 (save-excursion\n\
563 (goto-char (window-start window))\n\
564 (vertical-motion (1- (window-height window)) window)\n\
565 (point))") */
567 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 1, 0,
568 "Return position at which display currently ends in WINDOW.\n\
569 This is updated by redisplay, when it runs to completion.\n\
570 Simply changing the buffer text or setting `window-start'\n\
571 does not update this value.")
572 (window)
573 Lisp_Object window;
575 Lisp_Object value;
576 struct window *w = decode_window (window);
577 Lisp_Object buf;
579 buf = w->buffer;
580 CHECK_BUFFER (buf, 0);
582 #if 0 /* This change broke some things. We should make it later. */
583 /* If we don't know the end position, return nil.
584 The user can compute it with vertical-motion if he wants to.
585 It would be nicer to do it automatically,
586 but that's so slow that it would probably bother people. */
587 if (NILP (w->window_end_valid))
588 return Qnil;
589 #endif
591 XSETINT (value,
592 BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
594 return value;
597 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
598 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
599 (window, pos)
600 Lisp_Object window, pos;
602 register struct window *w = decode_window (window);
604 CHECK_NUMBER_COERCE_MARKER (pos, 1);
605 if (w == XWINDOW (selected_window))
606 Fgoto_char (pos);
607 else
608 set_marker_restricted (w->pointm, pos, w->buffer);
610 return pos;
613 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
614 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
615 Optional third arg NOFORCE non-nil inhibits next redisplay\n\
616 from overriding motion of point in order to display at this exact start.")
617 (window, pos, noforce)
618 Lisp_Object window, pos, noforce;
620 register struct window *w = decode_window (window);
622 CHECK_NUMBER_COERCE_MARKER (pos, 1);
623 set_marker_restricted (w->start, pos, w->buffer);
624 /* this is not right, but much easier than doing what is right. */
625 w->start_at_line_beg = Qnil;
626 if (NILP (noforce))
627 w->force_start = Qt;
628 w->update_mode_line = Qt;
629 XSETFASTINT (w->last_modified, 0);
630 XSETFASTINT (w->last_overlay_modified, 0);
631 if (!EQ (window, selected_window))
632 windows_or_buffers_changed++;
633 return pos;
636 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
637 1, 1, 0,
638 "Return WINDOW's dedicated object, usually t or nil.\n\
639 See also `set-window-dedicated-p'.")
640 (window)
641 Lisp_Object window;
643 return decode_window (window)->dedicated;
646 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
647 Sset_window_dedicated_p, 2, 2, 0,
648 "Control whether WINDOW is dedicated to the buffer it displays.\n\
649 If it is dedicated, Emacs will not automatically change\n\
650 which buffer appears in it.\n\
651 The second argument is the new value for the dedication flag;\n\
652 non-nil means yes.")
653 (window, arg)
654 Lisp_Object window, arg;
656 register struct window *w = decode_window (window);
658 if (NILP (arg))
659 w->dedicated = Qnil;
660 else
661 w->dedicated = Qt;
663 return w->dedicated;
666 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
667 0, 1, 0,
668 "Return the display-table that WINDOW is using.")
669 (window)
670 Lisp_Object window;
672 return decode_window (window)->display_table;
675 /* Get the display table for use currently on window W.
676 This is either W's display table or W's buffer's display table.
677 Ignore the specified tables if they are not valid;
678 if no valid table is specified, return 0. */
680 struct Lisp_Char_Table *
681 window_display_table (w)
682 struct window *w;
684 Lisp_Object tem;
685 tem = w->display_table;
686 if (DISP_TABLE_P (tem))
687 return XCHAR_TABLE (tem);
688 tem = XBUFFER (w->buffer)->display_table;
689 if (DISP_TABLE_P (tem))
690 return XCHAR_TABLE (tem);
691 tem = Vstandard_display_table;
692 if (DISP_TABLE_P (tem))
693 return XCHAR_TABLE (tem);
694 return 0;
697 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
698 "Set WINDOW's display-table to TABLE.")
699 (window, table)
700 register Lisp_Object window, table;
702 register struct window *w;
703 register Lisp_Object z; /* Return value. */
705 w = decode_window (window);
706 w->display_table = table;
707 return table;
710 /* Record info on buffer window w is displaying
711 when it is about to cease to display that buffer. */
712 static
713 unshow_buffer (w)
714 register struct window *w;
716 Lisp_Object buf;
718 buf = w->buffer;
719 if (XBUFFER (buf) != XMARKER (w->pointm)->buffer)
720 abort ();
722 if (w == XWINDOW (XBUFFER (buf)->last_selected_window))
723 XBUFFER (buf)->last_selected_window = Qnil;
725 #if 0
726 if (w == XWINDOW (selected_window)
727 || ! EQ (buf, XWINDOW (selected_window)->buffer))
728 /* Do this except when the selected window's buffer
729 is being removed from some other window. */
730 #endif
731 /* last_window_start records the start position that this buffer
732 had in the last window to be disconnected from it.
733 Now that this statement is unconditional,
734 it is possible for the buffer to be displayed in the
735 selected window, while last_window_start reflects another
736 window which was recently showing the same buffer.
737 Some people might say that might be a good thing. Let's see. */
738 XBUFFER (buf)->last_window_start = marker_position (w->start);
740 /* Point in the selected window's buffer
741 is actually stored in that buffer, and the window's pointm isn't used.
742 So don't clobber point in that buffer. */
743 if (! EQ (buf, XWINDOW (selected_window)->buffer))
744 BUF_PT (XBUFFER (buf))
745 = clip_to_bounds (BUF_BEGV (XBUFFER (buf)),
746 marker_position (w->pointm),
747 BUF_ZV (XBUFFER (buf)));
750 /* Put replacement into the window structure in place of old. */
751 static
752 replace_window (old, replacement)
753 Lisp_Object old, replacement;
755 register Lisp_Object tem;
756 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
758 /* If OLD is its frame's root_window, then replacement is the new
759 root_window for that frame. */
761 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
762 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
764 p->left = o->left;
765 p->top = o->top;
766 p->width = o->width;
767 p->height = o->height;
769 p->next = tem = o->next;
770 if (!NILP (tem))
771 XWINDOW (tem)->prev = replacement;
773 p->prev = tem = o->prev;
774 if (!NILP (tem))
775 XWINDOW (tem)->next = replacement;
777 p->parent = tem = o->parent;
778 if (!NILP (tem))
780 if (EQ (XWINDOW (tem)->vchild, old))
781 XWINDOW (tem)->vchild = replacement;
782 if (EQ (XWINDOW (tem)->hchild, old))
783 XWINDOW (tem)->hchild = replacement;
786 /*** Here, if replacement is a vertical combination
787 and so is its new parent, we should make replacement's
788 children be children of that parent instead. ***/
791 DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
792 "Remove WINDOW from the display. Default is selected window.")
793 (window)
794 register Lisp_Object window;
796 delete_window (window);
798 if (! NILP (Vwindow_configuration_change_hook)
799 && ! NILP (Vrun_hooks))
800 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
802 return Qnil;
805 delete_window (window)
806 register Lisp_Object window;
808 register Lisp_Object tem, parent, sib;
809 register struct window *p;
810 register struct window *par;
812 /* Because this function is called by other C code on non-leaf
813 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
814 so we can't decode_window here. */
815 if (NILP (window))
816 window = selected_window;
817 else
818 CHECK_WINDOW (window, 0);
819 p = XWINDOW (window);
821 /* It's okay to delete an already-deleted window. */
822 if (NILP (p->buffer)
823 && NILP (p->hchild)
824 && NILP (p->vchild))
825 return;
827 parent = p->parent;
828 if (NILP (parent))
829 error ("Attempt to delete minibuffer or sole ordinary window");
830 par = XWINDOW (parent);
832 windows_or_buffers_changed++;
833 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (p))) = 1;
835 /* Are we trying to delete any frame's selected window? */
837 Lisp_Object frame, pwindow;
839 /* See if the frame's selected window is either WINDOW
840 or any subwindow of it, by finding all that window's parents
841 and comparing each one with WINDOW. */
842 frame = WINDOW_FRAME (XWINDOW (window));
843 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
845 while (!NILP (pwindow))
847 if (EQ (window, pwindow))
848 break;
849 pwindow = XWINDOW (pwindow)->parent;
852 if (EQ (window, pwindow))
854 Lisp_Object alternative;
855 alternative = Fnext_window (window, Qlambda, Qnil);
857 /* If we're about to delete the selected window on the
858 selected frame, then we should use Fselect_window to select
859 the new window. On the other hand, if we're about to
860 delete the selected window on any other frame, we shouldn't do
861 anything but set the frame's selected_window slot. */
862 if (EQ (window, selected_window))
863 Fselect_window (alternative);
864 else
865 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
869 tem = p->buffer;
870 /* tem is null for dummy parent windows
871 (which have inferiors but not any contents themselves) */
872 if (!NILP (tem))
874 unshow_buffer (p);
875 unchain_marker (p->pointm);
876 unchain_marker (p->start);
879 tem = p->next;
880 if (!NILP (tem))
881 XWINDOW (tem)->prev = p->prev;
883 tem = p->prev;
884 if (!NILP (tem))
885 XWINDOW (tem)->next = p->next;
887 if (EQ (window, par->hchild))
888 par->hchild = p->next;
889 if (EQ (window, par->vchild))
890 par->vchild = p->next;
892 /* Find one of our siblings to give our space to. */
893 sib = p->prev;
894 if (NILP (sib))
896 /* If p gives its space to its next sibling, that sibling needs
897 to have its top/left side pulled back to where p's is.
898 set_window_{height,width} will re-position the sibling's
899 children. */
900 sib = p->next;
901 XWINDOW (sib)->top = p->top;
902 XWINDOW (sib)->left = p->left;
905 /* Stretch that sibling. */
906 if (!NILP (par->vchild))
907 set_window_height (sib,
908 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
910 if (!NILP (par->hchild))
911 set_window_width (sib,
912 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
915 /* If parent now has only one child,
916 put the child into the parent's place. */
917 tem = par->hchild;
918 if (NILP (tem))
919 tem = par->vchild;
920 if (NILP (XWINDOW (tem)->next))
921 replace_window (parent, tem);
923 /* Since we may be deleting combination windows, we must make sure that
924 not only p but all its children have been marked as deleted. */
925 if (! NILP (p->hchild))
926 delete_all_subwindows (XWINDOW (p->hchild));
927 else if (! NILP (p->vchild))
928 delete_all_subwindows (XWINDOW (p->vchild));
930 /* Mark this window as deleted. */
931 p->buffer = p->hchild = p->vchild = Qnil;
935 extern Lisp_Object next_frame (), prev_frame ();
937 /* This comment supplies the doc string for `next-window',
938 for make-docfile to see. We cannot put this in the real DEFUN
939 due to limits in the Unix cpp.
941 DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
942 "Return next window after WINDOW in canonical ordering of windows.\n\
943 If omitted, WINDOW defaults to the selected window.\n\
945 Optional second arg MINIBUF t means count the minibuffer window even\n\
946 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
947 it is active. MINIBUF neither t nor nil means not to count the\n\
948 minibuffer even if it is active.\n\
950 Several frames may share a single minibuffer; if the minibuffer\n\
951 counts, all windows on all frames that share that minibuffer count\n\
952 too. Therefore, `next-window' can be used to iterate through the\n\
953 set of windows even when the minibuffer is on another frame. If the\n\
954 minibuffer does not count, only windows from WINDOW's frame count.\n\
956 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
957 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
958 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
959 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
960 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
961 Anything else means restrict to WINDOW's frame.\n\
963 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
964 `next-window' to iterate through the entire cycle of acceptable\n\
965 windows, eventually ending up back at the window you started with.\n\
966 `previous-window' traverses the same cycle, in the reverse order.")
967 (window, minibuf, all_frames) */
969 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
971 (window, minibuf, all_frames)
972 register Lisp_Object window, minibuf, all_frames;
974 register Lisp_Object tem;
975 Lisp_Object start_window;
977 if (NILP (window))
978 window = selected_window;
979 else
980 CHECK_LIVE_WINDOW (window, 0);
982 start_window = window;
984 /* minibuf == nil may or may not include minibuffers.
985 Decide if it does. */
986 if (NILP (minibuf))
987 minibuf = (minibuf_level ? minibuf_window : Qlambda);
988 else if (! EQ (minibuf, Qt))
989 minibuf = Qlambda;
990 /* Now minibuf can be t => count all minibuffer windows,
991 lambda => count none of them,
992 or a specific minibuffer window (the active one) to count. */
994 /* all_frames == nil doesn't specify which frames to include. */
995 if (NILP (all_frames))
996 all_frames = (! EQ (minibuf, Qlambda)
997 ? (FRAME_MINIBUF_WINDOW
998 (XFRAME
999 (WINDOW_FRAME
1000 (XWINDOW (window)))))
1001 : Qnil);
1002 else if (EQ (all_frames, Qvisible))
1004 else if (XFASTINT (all_frames) == 0)
1006 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1007 /* If all_frames is a frame and window arg isn't on that frame, just
1008 return the first window on the frame. */
1009 return Fframe_first_window (all_frames);
1010 else if (! EQ (all_frames, Qt))
1011 all_frames = Qnil;
1012 /* Now all_frames is t meaning search all frames,
1013 nil meaning search just current frame,
1014 visible meaning search just visible frames,
1015 0 meaning search visible and iconified frames,
1016 or a window, meaning search the frame that window belongs to. */
1018 /* Do this loop at least once, to get the next window, and perhaps
1019 again, if we hit the minibuffer and that is not acceptable. */
1022 /* Find a window that actually has a next one. This loop
1023 climbs up the tree. */
1024 while (tem = XWINDOW (window)->next, NILP (tem))
1025 if (tem = XWINDOW (window)->parent, !NILP (tem))
1026 window = tem;
1027 else
1029 /* We've reached the end of this frame.
1030 Which other frames are acceptable? */
1031 tem = WINDOW_FRAME (XWINDOW (window));
1032 if (! NILP (all_frames))
1034 Lisp_Object tem1;
1036 tem1 = tem;
1037 tem = next_frame (tem, all_frames);
1038 /* In the case where the minibuffer is active,
1039 and we include its frame as well as the selected one,
1040 next_frame may get stuck in that frame.
1041 If that happens, go back to the selected frame
1042 so we can complete the cycle. */
1043 if (EQ (tem, tem1))
1044 XSETFRAME (tem, selected_frame);
1046 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1048 break;
1051 window = tem;
1053 /* If we're in a combination window, find its first child and
1054 recurse on that. Otherwise, we've found the window we want. */
1055 while (1)
1057 if (!NILP (XWINDOW (window)->hchild))
1058 window = XWINDOW (window)->hchild;
1059 else if (!NILP (XWINDOW (window)->vchild))
1060 window = XWINDOW (window)->vchild;
1061 else break;
1064 /* Which windows are acceptable?
1065 Exit the loop and accept this window if
1066 this isn't a minibuffer window,
1067 or we're accepting all minibuffer windows,
1068 or this is the active minibuffer and we are accepting that one, or
1069 we've come all the way around and we're back at the original window. */
1070 while (MINI_WINDOW_P (XWINDOW (window))
1071 && ! EQ (minibuf, Qt)
1072 && ! EQ (minibuf, window)
1073 && ! EQ (window, start_window));
1075 return window;
1078 /* This comment supplies the doc string for `previous-window',
1079 for make-docfile to see. We cannot put this in the real DEFUN
1080 due to limits in the Unix cpp.
1082 DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
1083 "Return the window preceding WINDOW in canonical ordering of windows.\n\
1084 If omitted, WINDOW defaults to the selected window.\n\
1086 Optional second arg MINIBUF t means count the minibuffer window even\n\
1087 if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1088 it is active. MINIBUF neither t nor nil means not to count the\n\
1089 minibuffer even if it is active.\n\
1091 Several frames may share a single minibuffer; if the minibuffer\n\
1092 counts, all windows on all frames that share that minibuffer count\n\
1093 too. Therefore, `previous-window' can be used to iterate through\n\
1094 the set of windows even when the minibuffer is on another frame. If\n\
1095 the minibuffer does not count, only windows from WINDOW's frame count\n\
1097 Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1098 ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
1099 above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
1100 ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1101 If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
1102 Anything else means restrict to WINDOW's frame.\n\
1104 If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1105 `previous-window' to iterate through the entire cycle of acceptable\n\
1106 windows, eventually ending up back at the window you started with.\n\
1107 `next-window' traverses the same cycle, in the reverse order.")
1108 (window, minibuf, all_frames) */
1111 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1113 (window, minibuf, all_frames)
1114 register Lisp_Object window, minibuf, all_frames;
1116 register Lisp_Object tem;
1117 Lisp_Object start_window;
1119 if (NILP (window))
1120 window = selected_window;
1121 else
1122 CHECK_LIVE_WINDOW (window, 0);
1124 start_window = window;
1126 /* minibuf == nil may or may not include minibuffers.
1127 Decide if it does. */
1128 if (NILP (minibuf))
1129 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1130 else if (! EQ (minibuf, Qt))
1131 minibuf = Qlambda;
1132 /* Now minibuf can be t => count all minibuffer windows,
1133 lambda => count none of them,
1134 or a specific minibuffer window (the active one) to count. */
1136 /* all_frames == nil doesn't specify which frames to include.
1137 Decide which frames it includes. */
1138 if (NILP (all_frames))
1139 all_frames = (! EQ (minibuf, Qlambda)
1140 ? (FRAME_MINIBUF_WINDOW
1141 (XFRAME
1142 (WINDOW_FRAME
1143 (XWINDOW (window)))))
1144 : Qnil);
1145 else if (EQ (all_frames, Qvisible))
1147 else if (XFASTINT (all_frames) == 0)
1149 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1150 /* If all_frames is a frame and window arg isn't on that frame, just
1151 return the first window on the frame. */
1152 return Fframe_first_window (all_frames);
1153 else if (! EQ (all_frames, Qt))
1154 all_frames = Qnil;
1155 /* Now all_frames is t meaning search all frames,
1156 nil meaning search just current frame,
1157 visible meaning search just visible frames,
1158 0 meaning search visible and iconified frames,
1159 or a window, meaning search the frame that window belongs to. */
1161 /* Do this loop at least once, to get the previous window, and perhaps
1162 again, if we hit the minibuffer and that is not acceptable. */
1165 /* Find a window that actually has a previous one. This loop
1166 climbs up the tree. */
1167 while (tem = XWINDOW (window)->prev, NILP (tem))
1168 if (tem = XWINDOW (window)->parent, !NILP (tem))
1169 window = tem;
1170 else
1172 /* We have found the top window on the frame.
1173 Which frames are acceptable? */
1174 tem = WINDOW_FRAME (XWINDOW (window));
1175 if (! NILP (all_frames))
1176 /* It's actually important that we use prev_frame here,
1177 rather than next_frame. All the windows acceptable
1178 according to the given parameters should form a ring;
1179 Fnext_window and Fprevious_window should go back and
1180 forth around the ring. If we use next_frame here,
1181 then Fnext_window and Fprevious_window take different
1182 paths through the set of acceptable windows.
1183 window_loop assumes that these `ring' requirement are
1184 met. */
1186 Lisp_Object tem1;
1188 tem1 = tem;
1189 tem = prev_frame (tem, all_frames);
1190 /* In the case where the minibuffer is active,
1191 and we include its frame as well as the selected one,
1192 next_frame may get stuck in that frame.
1193 If that happens, go back to the selected frame
1194 so we can complete the cycle. */
1195 if (EQ (tem, tem1))
1196 XSETFRAME (tem, selected_frame);
1198 /* If this frame has a minibuffer, find that window first,
1199 because it is conceptually the last window in that frame. */
1200 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
1201 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
1202 else
1203 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
1205 break;
1208 window = tem;
1209 /* If we're in a combination window, find its last child and
1210 recurse on that. Otherwise, we've found the window we want. */
1211 while (1)
1213 if (!NILP (XWINDOW (window)->hchild))
1214 window = XWINDOW (window)->hchild;
1215 else if (!NILP (XWINDOW (window)->vchild))
1216 window = XWINDOW (window)->vchild;
1217 else break;
1218 while (tem = XWINDOW (window)->next, !NILP (tem))
1219 window = tem;
1222 /* Which windows are acceptable?
1223 Exit the loop and accept this window if
1224 this isn't a minibuffer window,
1225 or we're accepting all minibuffer windows,
1226 or this is the active minibuffer and we are accepting that one, or
1227 we've come all the way around and we're back at the original window. */
1228 while (MINI_WINDOW_P (XWINDOW (window))
1229 && ! EQ (minibuf, Qt)
1230 && ! EQ (minibuf, window)
1231 && ! EQ (window, start_window));
1233 return window;
1236 DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
1237 "Select the ARG'th different window on this frame.\n\
1238 All windows on current frame are arranged in a cyclic order.\n\
1239 This command selects the window ARG steps away in that order.\n\
1240 A negative ARG moves in the opposite order. If the optional second\n\
1241 argument ALL_FRAMES is non-nil, cycle through all frames.")
1242 (arg, all_frames)
1243 register Lisp_Object arg, all_frames;
1245 register int i;
1246 register Lisp_Object w;
1248 CHECK_NUMBER (arg, 0);
1249 w = selected_window;
1250 i = XINT (arg);
1252 while (i > 0)
1254 w = Fnext_window (w, Qnil, all_frames);
1255 i--;
1257 while (i < 0)
1259 w = Fprevious_window (w, Qnil, all_frames);
1260 i++;
1262 Fselect_window (w);
1263 return Qnil;
1266 /* Look at all windows, performing an operation specified by TYPE
1267 with argument OBJ.
1268 If FRAMES is Qt, look at all frames;
1269 Qnil, look at just the selected frame;
1270 Qvisible, look at visible frames;
1271 a frame, just look at windows on that frame.
1272 If MINI is non-zero, perform the operation on minibuffer windows too.
1275 enum window_loop
1277 WINDOW_LOOP_UNUSED,
1278 GET_BUFFER_WINDOW, /* Arg is buffer */
1279 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1280 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1281 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1282 GET_LARGEST_WINDOW,
1283 UNSHOW_BUFFER /* Arg is buffer */
1286 static Lisp_Object
1287 window_loop (type, obj, mini, frames)
1288 enum window_loop type;
1289 register Lisp_Object obj, frames;
1290 int mini;
1292 register Lisp_Object w;
1293 register Lisp_Object best_window;
1294 register Lisp_Object next_window;
1295 register Lisp_Object last_window;
1296 FRAME_PTR frame;
1297 Lisp_Object frame_arg;
1298 frame_arg = Qt;
1300 /* If we're only looping through windows on a particular frame,
1301 frame points to that frame. If we're looping through windows
1302 on all frames, frame is 0. */
1303 if (FRAMEP (frames))
1304 frame = XFRAME (frames);
1305 else if (NILP (frames))
1306 frame = selected_frame;
1307 else
1308 frame = 0;
1309 if (frame)
1310 frame_arg = Qlambda;
1311 else if (XFASTINT (frames) == 0)
1312 frame_arg = frames;
1313 else if (EQ (frames, Qvisible))
1314 frame_arg = frames;
1316 /* frame_arg is Qlambda to stick to one frame,
1317 Qvisible to consider all visible frames,
1318 or Qt otherwise. */
1320 /* Pick a window to start with. */
1321 if (WINDOWP (obj))
1322 w = obj;
1323 else if (frame)
1324 w = FRAME_SELECTED_WINDOW (frame);
1325 else
1326 w = FRAME_SELECTED_WINDOW (selected_frame);
1328 /* Figure out the last window we're going to mess with. Since
1329 Fnext_window, given the same options, is guaranteed to go in a
1330 ring, we can just use Fprevious_window to find the last one.
1332 We can't just wait until we hit the first window again, because
1333 it might be deleted. */
1335 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
1337 best_window = Qnil;
1338 for (;;)
1340 FRAME_PTR w_frame = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1342 /* Pick the next window now, since some operations will delete
1343 the current window. */
1344 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
1346 /* Note that we do not pay attention here to whether
1347 the frame is visible, since Fnext_window skips non-visible frames
1348 if that is desired, under the control of frame_arg. */
1349 if (! MINI_WINDOW_P (XWINDOW (w))
1350 || (mini && minibuf_level > 0))
1351 switch (type)
1353 case GET_BUFFER_WINDOW:
1354 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj)
1355 /* Don't find any minibuffer window
1356 except the one that is currently in use. */
1357 && (MINI_WINDOW_P (XWINDOW (w))
1358 ? EQ (w, minibuf_window) : 1))
1359 return w;
1360 break;
1362 case GET_LRU_WINDOW:
1363 /* t as arg means consider only full-width windows */
1364 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (XWINDOW (w)))
1365 break;
1366 /* Ignore dedicated windows and minibuffers. */
1367 if (MINI_WINDOW_P (XWINDOW (w))
1368 || !NILP (XWINDOW (w)->dedicated))
1369 break;
1370 if (NILP (best_window)
1371 || (XFASTINT (XWINDOW (best_window)->use_time)
1372 > XFASTINT (XWINDOW (w)->use_time)))
1373 best_window = w;
1374 break;
1376 case DELETE_OTHER_WINDOWS:
1377 if (XWINDOW (w) != XWINDOW (obj))
1378 Fdelete_window (w);
1379 break;
1381 case DELETE_BUFFER_WINDOWS:
1382 if (EQ (XWINDOW (w)->buffer, obj))
1384 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1386 /* If this window is dedicated, and in a frame of its own,
1387 kill the frame. */
1388 if (EQ (w, FRAME_ROOT_WINDOW (f))
1389 && !NILP (XWINDOW (w)->dedicated)
1390 && other_visible_frames (f))
1392 /* Skip the other windows on this frame.
1393 There might be one, the minibuffer! */
1394 if (! EQ (w, last_window))
1395 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1397 /* As we go, check for the end of the loop.
1398 We mustn't start going around a second time. */
1399 if (EQ (next_window, last_window))
1401 last_window = w;
1402 break;
1404 next_window = Fnext_window (next_window,
1405 mini ? Qt : Qnil,
1406 frame_arg);
1408 /* Now we can safely delete the frame. */
1409 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
1411 else
1412 /* If we're deleting the buffer displayed in the only window
1413 on the frame, find a new buffer to display there. */
1414 if (NILP (XWINDOW (w)->parent))
1416 Lisp_Object new_buffer;
1417 new_buffer = Fother_buffer (obj, Qnil);
1418 if (NILP (new_buffer))
1419 new_buffer
1420 = Fget_buffer_create (build_string ("*scratch*"));
1421 Fset_window_buffer (w, new_buffer);
1422 if (EQ (w, selected_window))
1423 Fset_buffer (XWINDOW (w)->buffer);
1425 else
1426 Fdelete_window (w);
1428 break;
1430 case GET_LARGEST_WINDOW:
1431 /* Ignore dedicated windows and minibuffers. */
1432 if (MINI_WINDOW_P (XWINDOW (w))
1433 || !NILP (XWINDOW (w)->dedicated))
1434 break;
1436 struct window *best_window_ptr = XWINDOW (best_window);
1437 struct window *w_ptr = XWINDOW (w);
1438 if (NILP (best_window)
1439 || (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width)
1440 > (XFASTINT (best_window_ptr->height)
1441 * XFASTINT (best_window_ptr->width))))
1442 best_window = w;
1444 break;
1446 case UNSHOW_BUFFER:
1447 if (EQ (XWINDOW (w)->buffer, obj))
1449 /* Find another buffer to show in this window. */
1450 Lisp_Object another_buffer;
1451 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1452 another_buffer = Fother_buffer (obj, Qnil);
1453 if (NILP (another_buffer))
1454 another_buffer
1455 = Fget_buffer_create (build_string ("*scratch*"));
1456 /* If this window is dedicated, and in a frame of its own,
1457 kill the frame. */
1458 if (EQ (w, FRAME_ROOT_WINDOW (f))
1459 && !NILP (XWINDOW (w)->dedicated)
1460 && other_visible_frames (f))
1462 /* Skip the other windows on this frame.
1463 There might be one, the minibuffer! */
1464 if (! EQ (w, last_window))
1465 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1467 /* As we go, check for the end of the loop.
1468 We mustn't start going around a second time. */
1469 if (EQ (next_window, last_window))
1471 last_window = w;
1472 break;
1474 next_window = Fnext_window (next_window,
1475 mini ? Qt : Qnil,
1476 frame_arg);
1478 /* Now we can safely delete the frame. */
1479 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
1481 else
1483 /* Otherwise show a different buffer in the window. */
1484 XWINDOW (w)->dedicated = Qnil;
1485 Fset_window_buffer (w, another_buffer);
1486 if (EQ (w, selected_window))
1487 Fset_buffer (XWINDOW (w)->buffer);
1490 break;
1493 if (EQ (w, last_window))
1494 break;
1496 w = next_window;
1499 return best_window;
1502 DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1503 "Return the window least recently selected or used for display.\n\
1504 If optional argument FRAME is `visible', search all visible frames.\n\
1505 If FRAME is 0, search all visible and iconified frames.\n\
1506 If FRAME is t, search all frames.\n\
1507 If FRAME is nil, search only the selected frame.\n\
1508 If FRAME is a frame, search only that frame.")
1509 (frame)
1510 Lisp_Object frame;
1512 register Lisp_Object w;
1513 /* First try for a window that is full-width */
1514 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
1515 if (!NILP (w) && !EQ (w, selected_window))
1516 return w;
1517 /* If none of them, try the rest */
1518 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
1521 DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1522 "Return the largest window in area.\n\
1523 If optional argument FRAME is `visible', search all visible frames.\n\
1524 If FRAME is 0, search all visible and iconified frames.\n\
1525 If FRAME is t, search all frames.\n\
1526 If FRAME is nil, search only the selected frame.\n\
1527 If FRAME is a frame, search only that frame.")
1528 (frame)
1529 Lisp_Object frame;
1531 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
1532 frame);
1535 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1536 "Return a window currently displaying BUFFER, or nil if none.\n\
1537 If optional argument FRAME is `visible', search all visible frames.\n\
1538 If optional argument FRAME is 0, search all visible and iconified frames.\n\
1539 If FRAME is t, search all frames.\n\
1540 If FRAME is nil, search only the selected frame.\n\
1541 If FRAME is a frame, search only that frame.")
1542 (buffer, frame)
1543 Lisp_Object buffer, frame;
1545 buffer = Fget_buffer (buffer);
1546 if (BUFFERP (buffer))
1547 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
1548 else
1549 return Qnil;
1552 DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1553 0, 1, "",
1554 "Make WINDOW (or the selected window) fill its frame.\n\
1555 Only the frame WINDOW is on is affected.\n\
1556 This function tries to reduce display jumps\n\
1557 by keeping the text previously visible in WINDOW\n\
1558 in the same place on the frame. Doing this depends on\n\
1559 the value of (window-start WINDOW), so if calling this function\n\
1560 in a program gives strange scrolling, make sure the window-start\n\
1561 value is reasonable when this function is called.")
1562 (window)
1563 Lisp_Object window;
1565 struct window *w;
1566 int startpos;
1567 int top;
1569 if (NILP (window))
1570 window = selected_window;
1571 else
1572 CHECK_LIVE_WINDOW (window, 0);
1574 w = XWINDOW (window);
1576 startpos = marker_position (w->start);
1577 top = XFASTINT (w->top) - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w)));
1579 if (MINI_WINDOW_P (w) && top > 0)
1580 error ("Can't expand minibuffer to full frame");
1582 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
1584 /* Try to minimize scrolling, by setting the window start to the point
1585 will cause the text at the old window start to be at the same place
1586 on the frame. But don't try to do this if the window start is
1587 outside the visible portion (as might happen when the display is
1588 not current, due to typeahead). */
1589 if (startpos >= BUF_BEGV (XBUFFER (w->buffer))
1590 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
1592 struct position pos;
1593 struct buffer *obuf = current_buffer;
1595 Fset_buffer (w->buffer);
1596 /* This computation used to temporarily move point, but that can
1597 have unwanted side effects due to text properties. */
1598 pos = *vmotion (startpos, -top, w);
1600 Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
1601 w->start_at_line_beg = ((pos.bufpos == BEGV
1602 || FETCH_BYTE (pos.bufpos - 1) == '\n') ? Qt
1603 : Qnil);
1604 /* We need to do this, so that the window-scroll-functions
1605 get called. */
1606 w->optional_new_start = Qt;
1608 set_buffer_internal (obuf);
1610 return Qnil;
1613 DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1614 1, 2, "bDelete windows on (buffer): ",
1615 "Delete all windows showing BUFFER.\n\
1616 Optional second argument FRAME controls which frames are affected.\n\
1617 If nil or omitted, delete all windows showing BUFFER in any frame.\n\
1618 If t, delete only windows showing BUFFER in the selected frame.\n\
1619 If `visible', delete all windows showing BUFFER in any visible frame.\n\
1620 If a frame, delete only windows showing BUFFER in that frame.")
1621 (buffer, frame)
1622 Lisp_Object buffer, frame;
1624 /* FRAME uses t and nil to mean the opposite of what window_loop
1625 expects. */
1626 if (! FRAMEP (frame))
1627 frame = NILP (frame) ? Qt : Qnil;
1629 if (!NILP (buffer))
1631 buffer = Fget_buffer (buffer);
1632 CHECK_BUFFER (buffer, 0);
1633 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
1635 return Qnil;
1638 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1639 Sreplace_buffer_in_windows,
1640 1, 1, "bReplace buffer in windows: ",
1641 "Replace BUFFER with some other buffer in all windows showing it.")
1642 (buffer)
1643 Lisp_Object buffer;
1645 if (!NILP (buffer))
1647 buffer = Fget_buffer (buffer);
1648 CHECK_BUFFER (buffer, 0);
1649 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1651 return Qnil;
1654 /* Replace BUFFER with some other buffer in all windows
1655 of all frames, even those on other keyboards. */
1657 void
1658 replace_buffer_in_all_windows (buffer)
1659 Lisp_Object buffer;
1661 #ifdef MULTI_KBOARD
1662 Lisp_Object tail, frame;
1664 /* A single call to window_loop won't do the job
1665 because it only considers frames on the current keyboard.
1666 So loop manually over frames, and handle each one. */
1667 FOR_EACH_FRAME (tail, frame)
1668 window_loop (UNSHOW_BUFFER, buffer, 0, frame);
1669 #else
1670 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1671 #endif
1674 /* Set the height of WINDOW and all its inferiors. */
1676 /* The smallest acceptable dimensions for a window. Anything smaller
1677 might crash Emacs. */
1678 #define MIN_SAFE_WINDOW_WIDTH (2)
1679 #define MIN_SAFE_WINDOW_HEIGHT (2)
1681 /* Make sure that window_min_height and window_min_width are
1682 not too small; if they are, set them to safe minima. */
1684 static void
1685 check_min_window_sizes ()
1687 /* Smaller values might permit a crash. */
1688 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1689 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1690 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1691 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1694 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
1695 minimum allowable size. */
1696 void
1697 check_frame_size (frame, rows, cols)
1698 FRAME_PTR frame;
1699 int *rows, *cols;
1701 /* For height, we have to see:
1702 whether the frame has a minibuffer,
1703 whether it wants a mode line, and
1704 whether it has a menu bar. */
1705 int min_height =
1706 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
1707 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
1708 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
1709 if (FRAME_MENU_BAR_LINES (frame) > 0)
1710 min_height += FRAME_MENU_BAR_LINES (frame);
1712 if (*rows < min_height)
1713 *rows = min_height;
1714 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1715 *cols = MIN_SAFE_WINDOW_WIDTH;
1718 /* Normally the window is deleted if it gets too small.
1719 nodelete nonzero means do not do this.
1720 (The caller should check later and do so if appropriate) */
1722 set_window_height (window, height, nodelete)
1723 Lisp_Object window;
1724 int height;
1725 int nodelete;
1727 register struct window *w = XWINDOW (window);
1728 register struct window *c;
1729 int oheight = XFASTINT (w->height);
1730 int top, pos, lastbot, opos, lastobot;
1731 Lisp_Object child;
1733 check_min_window_sizes ();
1735 if (!nodelete
1736 && ! NILP (w->parent)
1737 && height < window_min_height)
1739 delete_window (window);
1740 return;
1743 XSETFASTINT (w->last_modified, 0);
1744 XSETFASTINT (w->last_overlay_modified, 0);
1745 windows_or_buffers_changed++;
1746 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
1748 XSETFASTINT (w->height, height);
1749 if (!NILP (w->hchild))
1751 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1753 XWINDOW (child)->top = w->top;
1754 set_window_height (child, height, nodelete);
1757 else if (!NILP (w->vchild))
1759 lastbot = top = XFASTINT (w->top);
1760 lastobot = 0;
1761 for (child = w->vchild; !NILP (child); child = c->next)
1763 c = XWINDOW (child);
1765 opos = lastobot + XFASTINT (c->height);
1767 XSETFASTINT (c->top, lastbot);
1769 pos = (((opos * height) << 1) + oheight) / (oheight << 1);
1771 /* Avoid confusion: inhibit deletion of child if becomes too small */
1772 set_window_height (child, pos + top - lastbot, 1);
1774 /* Now advance child to next window,
1775 and set lastbot if child was not just deleted. */
1776 lastbot = pos + top;
1777 lastobot = opos;
1779 /* Now delete any children that became too small. */
1780 if (!nodelete)
1781 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1783 set_window_height (child, XINT (XWINDOW (child)->height), 0);
1788 /* Recursively set width of WINDOW and its inferiors. */
1790 set_window_width (window, width, nodelete)
1791 Lisp_Object window;
1792 int width;
1793 int nodelete;
1795 register struct window *w = XWINDOW (window);
1796 register struct window *c;
1797 int owidth = XFASTINT (w->width);
1798 int left, pos, lastright, opos, lastoright;
1799 Lisp_Object child;
1801 if (!nodelete && width < window_min_width && !NILP (w->parent))
1803 delete_window (window);
1804 return;
1807 XSETFASTINT (w->last_modified, 0);
1808 XSETFASTINT (w->last_overlay_modified, 0);
1809 windows_or_buffers_changed++;
1810 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
1812 XSETFASTINT (w->width, width);
1813 if (!NILP (w->vchild))
1815 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
1817 XWINDOW (child)->left = w->left;
1818 set_window_width (child, width, nodelete);
1821 else if (!NILP (w->hchild))
1823 lastright = left = XFASTINT (w->left);
1824 lastoright = 0;
1825 for (child = w->hchild; !NILP (child); child = c->next)
1827 c = XWINDOW (child);
1829 opos = lastoright + XFASTINT (c->width);
1831 XSETFASTINT (c->left, lastright);
1833 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
1835 /* Inhibit deletion for becoming too small */
1836 set_window_width (child, pos + left - lastright, 1);
1838 /* Now advance child to next window,
1839 and set lastright if child was not just deleted. */
1840 lastright = pos + left, lastoright = opos;
1842 /* Delete children that became too small */
1843 if (!nodelete)
1844 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
1846 set_window_width (child, XINT (XWINDOW (child)->width), 0);
1851 int window_select_count;
1853 Lisp_Object
1854 Fset_window_buffer_unwind (obuf)
1855 Lisp_Object obuf;
1857 Fset_buffer (obuf);
1858 return Qnil;
1861 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1862 "Make WINDOW display BUFFER as its contents.\n\
1863 BUFFER can be a buffer or buffer name.")
1864 (window, buffer)
1865 register Lisp_Object window, buffer;
1867 register Lisp_Object tem;
1868 register struct window *w = decode_window (window);
1869 int count = specpdl_ptr - specpdl;
1871 buffer = Fget_buffer (buffer);
1872 CHECK_BUFFER (buffer, 1);
1874 if (NILP (XBUFFER (buffer)->name))
1875 error ("Attempt to display deleted buffer");
1877 tem = w->buffer;
1878 if (NILP (tem))
1879 error ("Window is deleted");
1880 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
1881 is first being set up. */
1883 if (!NILP (w->dedicated) && !EQ (tem, buffer))
1884 error ("Window is dedicated to `%s'",
1885 XSTRING (XBUFFER (tem)->name)->data);
1887 unshow_buffer (w);
1890 w->buffer = buffer;
1892 if (EQ (window, selected_window))
1893 XBUFFER (w->buffer)->last_selected_window = window;
1894 if (INTEGERP (XBUFFER (buffer)->display_count))
1895 XSETINT (XBUFFER (buffer)->display_count,
1896 XINT (XBUFFER (buffer)->display_count) + 1);
1898 XSETFASTINT (w->window_end_pos, 0);
1899 w->window_end_valid = Qnil;
1900 XSETFASTINT (w->hscroll, 0);
1901 Fset_marker (w->pointm,
1902 make_number (BUF_PT (XBUFFER (buffer))),
1903 buffer);
1904 set_marker_restricted (w->start,
1905 make_number (XBUFFER (buffer)->last_window_start),
1906 buffer);
1907 w->start_at_line_beg = Qnil;
1908 w->force_start = Qnil;
1909 XSETFASTINT (w->last_modified, 0);
1910 XSETFASTINT (w->last_overlay_modified, 0);
1911 windows_or_buffers_changed++;
1913 /* We must select BUFFER for running the window-scroll-functions.
1914 If WINDOW is selected, switch permanently.
1915 Otherwise, switch but go back to the ambient buffer afterward. */
1916 if (EQ (window, selected_window))
1917 Fset_buffer (buffer);
1918 /* We can't check ! NILP (Vwindow_scroll_functions) here
1919 because that might itself be a local variable. */
1920 else if (window_initialized)
1922 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
1923 Fset_buffer (buffer);
1926 if (! NILP (Vwindow_scroll_functions))
1927 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1928 Fmarker_position (w->start));
1930 if (! NILP (Vwindow_configuration_change_hook)
1931 && ! NILP (Vrun_hooks))
1932 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1934 unbind_to (count, Qnil);
1936 return Qnil;
1939 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1940 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1941 The main editor command loop selects the buffer of the selected window\n\
1942 before each command.")
1943 (window)
1944 register Lisp_Object window;
1946 register struct window *w;
1947 register struct window *ow = XWINDOW (selected_window);
1949 CHECK_LIVE_WINDOW (window, 0);
1951 w = XWINDOW (window);
1953 if (NILP (w->buffer))
1954 error ("Trying to select deleted window or non-leaf window");
1956 XSETFASTINT (w->use_time, ++window_select_count);
1957 if (EQ (window, selected_window))
1958 return window;
1960 Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
1961 ow->buffer);
1963 selected_window = window;
1964 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
1966 XFRAME (WINDOW_FRAME (w))->selected_window = window;
1967 /* Use this rather than Fhandle_switch_frame
1968 so that FRAME_FOCUS_FRAME is moved appropriately as we
1969 move around in the state where a minibuffer in a separate
1970 frame is active. */
1971 Fselect_frame (WINDOW_FRAME (w), Qnil);
1973 else
1974 selected_frame->selected_window = window;
1976 record_buffer (w->buffer);
1977 Fset_buffer (w->buffer);
1979 XBUFFER (w->buffer)->last_selected_window = window;
1981 /* Go to the point recorded in the window.
1982 This is important when the buffer is in more
1983 than one window. It also matters when
1984 redisplay_window has altered point after scrolling,
1985 because it makes the change only in the window. */
1987 register int new_point = marker_position (w->pointm);
1988 if (new_point < BEGV)
1989 SET_PT (BEGV);
1990 else if (new_point > ZV)
1991 SET_PT (ZV);
1992 else
1993 SET_PT (new_point);
1996 windows_or_buffers_changed++;
1997 return window;
2000 /* Deiconify the frame containing the window WINDOW,
2001 unless it is the selected frame;
2002 then return WINDOW.
2004 The reason for the exception for the selected frame
2005 is that it seems better not to change the selected frames visibility
2006 merely because of displaying a different buffer in it.
2007 The deiconification is useful when a buffer gets shown in
2008 another frame that you were not using lately. */
2010 static Lisp_Object
2011 display_buffer_1 (window)
2012 Lisp_Object window;
2014 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
2015 FRAME_SAMPLE_VISIBILITY (f);
2016 if (f != selected_frame)
2018 if (FRAME_ICONIFIED_P (f))
2019 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
2020 else if (FRAME_VISIBLE_P (f))
2021 Fraise_frame (WINDOW_FRAME (XWINDOW (window)));
2023 return window;
2026 DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
2027 "Returns non-nil if a buffer named BUFFER-NAME would be created specially.\n\
2028 The value is actually t if the frame should be called with default frame\n\
2029 parameters, and a list of frame parameters if they were specified.\n\
2030 See `special-display-buffer-names', and `special-display-regexps'.")
2031 (buffer_name)
2032 Lisp_Object buffer_name;
2034 Lisp_Object tem;
2036 CHECK_STRING (buffer_name, 1);
2038 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2039 if (!NILP (tem))
2040 return Qt;
2042 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2043 if (!NILP (tem))
2044 return XCDR (tem);
2046 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2048 Lisp_Object car = XCAR (tem);
2049 if (STRINGP (car)
2050 && fast_string_match (car, buffer_name) >= 0)
2051 return Qt;
2052 else if (CONSP (car)
2053 && STRINGP (XCAR (car))
2054 && fast_string_match (XCAR (car), buffer_name) >= 0)
2055 return XCDR (tem);
2057 return Qnil;
2060 DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
2061 "Returns non-nil if a new buffer named BUFFER-NAME would use the same window.\n\
2062 See `same-window-buffer-names' and `same-window-regexps'.")
2063 (buffer_name)
2064 Lisp_Object buffer_name;
2066 Lisp_Object tem;
2068 CHECK_STRING (buffer_name, 1);
2070 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2071 if (!NILP (tem))
2072 return Qt;
2074 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2075 if (!NILP (tem))
2076 return Qt;
2078 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
2080 Lisp_Object car = XCAR (tem);
2081 if (STRINGP (car)
2082 && fast_string_match (car, buffer_name) >= 0)
2083 return Qt;
2084 else if (CONSP (car)
2085 && STRINGP (XCAR (car))
2086 && fast_string_match (XCAR (car), buffer_name) >= 0)
2087 return Qt;
2089 return Qnil;
2092 DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
2093 "BDisplay buffer: \nP", /* Use B so the default is (other-buffer). */
2094 "Make BUFFER appear in some window but don't select it.\n\
2095 BUFFER can be a buffer or a buffer name.\n\
2096 If BUFFER is shown already in some window, just use that one,\n\
2097 unless the window is the selected window and the optional second\n\
2098 argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
2099 If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
2100 Returns the window displaying BUFFER.\n\
2102 The variables `special-display-buffer-names', `special-display-regexps',\n\
2103 `same-window-buffer-names', and `same-window-regexps' customize how certain\n\
2104 buffer names are handled.")
2105 (buffer, not_this_window)
2106 register Lisp_Object buffer, not_this_window;
2108 register Lisp_Object window, tem;
2110 buffer = Fget_buffer (buffer);
2111 CHECK_BUFFER (buffer, 0);
2113 if (!NILP (Vdisplay_buffer_function))
2114 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
2116 if (NILP (not_this_window)
2117 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
2118 return display_buffer_1 (selected_window);
2120 /* See if the user has specified this buffer should appear
2121 in the selected window. */
2122 if (NILP (not_this_window))
2124 tem = Fsame_window_p (XBUFFER (buffer)->name);
2125 if (!NILP (tem))
2127 Fswitch_to_buffer (buffer, Qnil);
2128 return display_buffer_1 (selected_window);
2132 /* If pop_up_frames,
2133 look for a window showing BUFFER on any visible or iconified frame.
2134 Otherwise search only the current frame. */
2135 if (pop_up_frames || last_nonminibuf_frame == 0)
2136 XSETFASTINT (tem, 0);
2137 else
2138 XSETFRAME (tem, last_nonminibuf_frame);
2139 window = Fget_buffer_window (buffer, tem);
2140 if (!NILP (window)
2141 && (NILP (not_this_window) || !EQ (window, selected_window)))
2143 return display_buffer_1 (window);
2146 /* Certain buffer names get special handling. */
2147 if (!NILP (Vspecial_display_function))
2149 tem = Fspecial_display_p (XBUFFER (buffer)->name);
2150 if (EQ (tem, Qt))
2151 return call1 (Vspecial_display_function, buffer);
2152 if (CONSP (tem))
2153 return call2 (Vspecial_display_function, buffer, tem);
2156 /* If there are no frames open that have more than a minibuffer,
2157 we need to create a new frame. */
2158 if (pop_up_frames || last_nonminibuf_frame == 0)
2160 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2161 Fset_window_buffer (window, buffer);
2162 return display_buffer_1 (window);
2165 if (pop_up_windows
2166 || FRAME_MINIBUF_ONLY_P (selected_frame)
2167 /* If the current frame is a special display frame,
2168 don't try to reuse its windows. */
2169 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->dedicated)
2172 Lisp_Object frames;
2174 frames = Qnil;
2175 if (FRAME_MINIBUF_ONLY_P (selected_frame))
2176 XSETFRAME (frames, last_nonminibuf_frame);
2177 /* Don't try to create a window if would get an error */
2178 if (split_height_threshold < window_min_height << 1)
2179 split_height_threshold = window_min_height << 1;
2181 /* Note that both Fget_largest_window and Fget_lru_window
2182 ignore minibuffers and dedicated windows.
2183 This means they can return nil. */
2185 /* If the frame we would try to split cannot be split,
2186 try other frames. */
2187 if (FRAME_NO_SPLIT_P (NILP (frames) ? selected_frame
2188 : last_nonminibuf_frame))
2190 /* Try visible frames first. */
2191 window = Fget_largest_window (Qvisible);
2192 /* If that didn't work, try iconified frames. */
2193 if (NILP (window))
2194 window = Fget_largest_window (make_number (0));
2195 if (NILP (window))
2196 window = Fget_largest_window (Qt);
2198 else
2199 window = Fget_largest_window (frames);
2201 /* If we got a tall enough full-width window that can be split,
2202 split it. */
2203 if (!NILP (window)
2204 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2205 && window_height (window) >= split_height_threshold
2206 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
2207 window = Fsplit_window (window, Qnil, Qnil);
2208 else
2210 Lisp_Object upper, lower, other;
2212 window = Fget_lru_window (frames);
2213 /* If the LRU window is selected, and big enough,
2214 and can be split, split it. */
2215 if (!NILP (window)
2216 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
2217 && (EQ (window, selected_window)
2218 || EQ (XWINDOW (window)->parent, Qnil))
2219 && window_height (window) >= window_min_height << 1)
2220 window = Fsplit_window (window, Qnil, Qnil);
2221 /* If Fget_lru_window returned nil, try other approaches. */
2223 /* Try visible frames first. */
2224 if (NILP (window))
2225 window = Fget_buffer_window (buffer, Qvisible);
2226 if (NILP (window))
2227 window = Fget_largest_window (Qvisible);
2228 /* If that didn't work, try iconified frames. */
2229 if (NILP (window))
2230 window = Fget_buffer_window (buffer, make_number (0));
2231 if (NILP (window))
2232 window = Fget_largest_window (make_number (0));
2233 /* Try invisible frames. */
2234 if (NILP (window))
2235 window = Fget_buffer_window (buffer, Qt);
2236 if (NILP (window))
2237 window = Fget_largest_window (Qt);
2238 /* As a last resort, make a new frame. */
2239 if (NILP (window))
2240 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2241 /* If window appears above or below another,
2242 even out their heights. */
2243 other = upper = lower = Qnil;
2244 if (!NILP (XWINDOW (window)->prev))
2245 other = upper = XWINDOW (window)->prev, lower = window;
2246 if (!NILP (XWINDOW (window)->next))
2247 other = lower = XWINDOW (window)->next, upper = window;
2248 if (!NILP (other)
2249 /* Check that OTHER and WINDOW are vertically arrayed. */
2250 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
2251 && (XFASTINT (XWINDOW (other)->height)
2252 > XFASTINT (XWINDOW (window)->height)))
2254 int total = (XFASTINT (XWINDOW (other)->height)
2255 + XFASTINT (XWINDOW (window)->height));
2256 Lisp_Object old_selected_window;
2257 old_selected_window = selected_window;
2259 selected_window = upper;
2260 change_window_height ((total / 2
2261 - XFASTINT (XWINDOW (upper)->height)),
2263 selected_window = old_selected_window;
2267 else
2268 window = Fget_lru_window (Qnil);
2270 Fset_window_buffer (window, buffer);
2271 return display_buffer_1 (window);
2274 void
2275 temp_output_buffer_show (buf)
2276 register Lisp_Object buf;
2278 register struct buffer *old = current_buffer;
2279 register Lisp_Object window;
2280 register struct window *w;
2282 Fset_buffer (buf);
2283 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
2284 BEGV = BEG;
2285 ZV = Z;
2286 SET_PT (BEG);
2287 XBUFFER (buf)->clip_changed = 1;
2288 set_buffer_internal (old);
2290 if (!EQ (Vtemp_buffer_show_function, Qnil))
2291 call1 (Vtemp_buffer_show_function, buf);
2292 else
2294 window = Fdisplay_buffer (buf, Qnil);
2296 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
2297 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
2298 Vminibuf_scroll_window = window;
2299 w = XWINDOW (window);
2300 XSETFASTINT (w->hscroll, 0);
2301 set_marker_restricted (w->start, make_number (1), buf);
2302 set_marker_restricted (w->pointm, make_number (1), buf);
2304 /* Run temp-buffer-show-hook, with the chosen window selected. */
2305 if (!NILP (Vrun_hooks))
2307 Lisp_Object tem;
2308 tem = Fboundp (Qtemp_buffer_show_hook);
2309 if (!NILP (tem))
2311 tem = Fsymbol_value (Qtemp_buffer_show_hook);
2312 if (!NILP (tem))
2314 int count = specpdl_ptr - specpdl;
2316 /* Select the window that was chosen, for running the hook. */
2317 record_unwind_protect (Fset_window_configuration,
2318 Fcurrent_window_configuration (Qnil));
2320 Fselect_window (window);
2321 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
2322 unbind_to (count, Qnil);
2329 static
2330 make_dummy_parent (window)
2331 Lisp_Object window;
2333 Lisp_Object new;
2334 register struct window *o, *p;
2335 register struct Lisp_Vector *vec;
2336 int i;
2338 o = XWINDOW (window);
2339 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
2340 for (i = 0; i < VECSIZE (struct window); ++i)
2341 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
2342 vec->size = VECSIZE (struct window);
2343 p = (struct window *)vec;
2344 XSETWINDOW (new, p);
2346 XSETFASTINT (p->sequence_number, ++sequence_number);
2348 /* Put new into window structure in place of window */
2349 replace_window (window, new);
2351 o->next = Qnil;
2352 o->prev = Qnil;
2353 o->vchild = Qnil;
2354 o->hchild = Qnil;
2355 o->parent = new;
2357 p->start = Qnil;
2358 p->pointm = Qnil;
2359 p->buffer = Qnil;
2362 DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
2363 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
2364 WINDOW defaults to selected one and SIZE to half its size.\n\
2365 If optional third arg HORFLAG is non-nil, split side by side\n\
2366 and put SIZE columns in the first of the pair.")
2367 (window, size, horflag)
2368 Lisp_Object window, size, horflag;
2370 register Lisp_Object new;
2371 register struct window *o, *p;
2372 FRAME_PTR fo;
2373 register int size_int;
2375 if (NILP (window))
2376 window = selected_window;
2377 else
2378 CHECK_LIVE_WINDOW (window, 0);
2380 o = XWINDOW (window);
2381 fo = XFRAME (WINDOW_FRAME (o));
2383 if (NILP (size))
2385 if (!NILP (horflag))
2386 /* Calculate the size of the left-hand window, by dividing
2387 the usable space in columns by two. */
2388 size_int = XFASTINT (o->width) >> 1;
2389 else
2390 size_int = XFASTINT (o->height) >> 1;
2392 else
2394 CHECK_NUMBER (size, 1);
2395 size_int = XINT (size);
2398 if (MINI_WINDOW_P (o))
2399 error ("Attempt to split minibuffer window");
2401 check_min_window_sizes ();
2403 if (NILP (horflag))
2405 if (size_int < window_min_height)
2406 error ("Window height %d too small (after splitting)", size_int);
2407 if (size_int + window_min_height > XFASTINT (o->height))
2408 error ("Window height %d too small (after splitting)",
2409 XFASTINT (o->height) - size_int);
2410 if (NILP (o->parent)
2411 || NILP (XWINDOW (o->parent)->vchild))
2413 make_dummy_parent (window);
2414 new = o->parent;
2415 XWINDOW (new)->vchild = window;
2418 else
2420 if (size_int < window_min_width)
2421 error ("Window width %d too small (after splitting)", size_int);
2423 if (size_int + window_min_width > XFASTINT (o->width))
2424 error ("Window width %d too small (after splitting)",
2425 XFASTINT (o->width) - size_int);
2426 if (NILP (o->parent)
2427 || NILP (XWINDOW (o->parent)->hchild))
2429 make_dummy_parent (window);
2430 new = o->parent;
2431 XWINDOW (new)->hchild = window;
2435 /* Now we know that window's parent is a vertical combination
2436 if we are dividing vertically, or a horizontal combination
2437 if we are making side-by-side windows */
2439 windows_or_buffers_changed++;
2440 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
2441 new = make_window ();
2442 p = XWINDOW (new);
2444 p->frame = o->frame;
2445 p->next = o->next;
2446 if (!NILP (p->next))
2447 XWINDOW (p->next)->prev = new;
2448 p->prev = window;
2449 o->next = new;
2450 p->parent = o->parent;
2451 p->buffer = Qt;
2453 /* Apportion the available frame space among the two new windows */
2455 if (!NILP (horflag))
2457 p->height = o->height;
2458 p->top = o->top;
2459 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
2460 XSETFASTINT (o->width, size_int);
2461 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
2463 else
2465 p->left = o->left;
2466 p->width = o->width;
2467 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
2468 XSETFASTINT (o->height, size_int);
2469 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
2472 Fset_window_buffer (new, o->buffer);
2474 return new;
2477 DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
2478 "Make current window ARG lines bigger.\n\
2479 From program, optional second arg non-nil means grow sideways ARG columns.")
2480 (arg, side)
2481 register Lisp_Object arg, side;
2483 CHECK_NUMBER (arg, 0);
2484 change_window_height (XINT (arg), !NILP (side));
2486 if (! NILP (Vwindow_configuration_change_hook))
2487 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2489 return Qnil;
2492 DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
2493 "Make current window ARG lines smaller.\n\
2494 From program, optional second arg non-nil means shrink sideways arg columns.")
2495 (arg, side)
2496 register Lisp_Object arg, side;
2498 CHECK_NUMBER (arg, 0);
2499 change_window_height (-XINT (arg), !NILP (side));
2501 if (! NILP (Vwindow_configuration_change_hook))
2502 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2504 return Qnil;
2508 window_height (window)
2509 Lisp_Object window;
2511 register struct window *p = XWINDOW (window);
2512 return XFASTINT (p->height);
2516 window_width (window)
2517 Lisp_Object window;
2519 register struct window *p = XWINDOW (window);
2520 return XFASTINT (p->width);
2523 #define MINSIZE(w) \
2524 (widthflag \
2525 ? window_min_width \
2526 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
2528 #define CURBEG(w) \
2529 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
2531 #define CURSIZE(w) \
2532 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
2534 /* Unlike set_window_height, this function
2535 also changes the heights of the siblings so as to
2536 keep everything consistent. */
2538 change_window_height (delta, widthflag)
2539 register int delta;
2540 int widthflag;
2542 register Lisp_Object parent;
2543 Lisp_Object window;
2544 register struct window *p;
2545 int *sizep;
2546 int (*sizefun) () = widthflag ? window_width : window_height;
2547 register int (*setsizefun) () = (widthflag
2548 ? set_window_width
2549 : set_window_height);
2550 int maximum;
2551 Lisp_Object next, prev;
2553 check_min_window_sizes ();
2555 window = selected_window;
2556 while (1)
2558 p = XWINDOW (window);
2559 parent = p->parent;
2560 if (NILP (parent))
2562 if (widthflag)
2563 error ("No other window to side of this one");
2564 break;
2566 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
2567 : !NILP (XWINDOW (parent)->vchild))
2568 break;
2569 window = parent;
2572 sizep = &CURSIZE (window);
2575 register int maxdelta;
2577 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
2578 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
2579 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
2580 /* This is a frame with only one window, a minibuffer-only
2581 or a minibufferless frame. */
2582 : (delta = 0));
2584 if (delta > maxdelta)
2585 /* This case traps trying to make the minibuffer
2586 the full frame, or make the only window aside from the
2587 minibuffer the full frame. */
2588 delta = maxdelta;
2591 if (*sizep + delta < MINSIZE (window))
2593 delete_window (window);
2594 return;
2597 if (delta == 0)
2598 return;
2600 /* Find the total we can get from other siblings. */
2601 maximum = 0;
2602 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
2603 maximum += (*sizefun) (next) - MINSIZE (next);
2604 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
2605 maximum += (*sizefun) (prev) - MINSIZE (prev);
2607 /* If we can get it all from them, do so. */
2608 if (delta < maximum)
2610 Lisp_Object first_unaffected;
2611 Lisp_Object first_affected;
2613 next = p->next;
2614 prev = p->prev;
2615 first_affected = window;
2616 /* Look at one sibling at a time,
2617 moving away from this window in both directions alternately,
2618 and take as much as we can get without deleting that sibling. */
2619 while (delta != 0)
2621 if (delta == 0)
2622 break;
2623 if (! NILP (next))
2625 int this_one = (*sizefun) (next) - MINSIZE (next);
2626 if (this_one > delta)
2627 this_one = delta;
2629 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
2630 (*setsizefun) (window, *sizep + this_one, 0);
2632 delta -= this_one;
2633 next = XWINDOW (next)->next;
2635 if (delta == 0)
2636 break;
2637 if (! NILP (prev))
2639 int this_one = (*sizefun) (prev) - MINSIZE (prev);
2640 if (this_one > delta)
2641 this_one = delta;
2643 first_affected = prev;
2645 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
2646 (*setsizefun) (window, *sizep + this_one, 0);
2648 delta -= this_one;
2649 prev = XWINDOW (prev)->prev;
2653 /* Now recalculate the edge positions of all the windows affected,
2654 based on the new sizes. */
2655 first_unaffected = next;
2656 prev = first_affected;
2657 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
2658 prev = next, next = XWINDOW (next)->next)
2660 CURBEG (next) = CURBEG (prev) + (*sizefun) (prev);
2661 /* This does not change size of NEXT,
2662 but it propagates the new top edge to its children */
2663 (*setsizefun) (next, (*sizefun) (next), 0);
2666 else
2668 register int delta1;
2669 register int opht = (*sizefun) (parent);
2671 /* If trying to grow this window to or beyond size of the parent,
2672 make delta1 so big that, on shrinking back down,
2673 all the siblings end up with less than one line and are deleted. */
2674 if (opht <= *sizep + delta)
2675 delta1 = opht * opht * 2;
2676 /* Otherwise, make delta1 just right so that if we add delta1
2677 lines to this window and to the parent, and then shrink
2678 the parent back to its original size, the new proportional
2679 size of this window will increase by delta. */
2680 else
2681 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
2683 /* Add delta1 lines or columns to this window, and to the parent,
2684 keeping things consistent while not affecting siblings. */
2685 CURSIZE (parent) = opht + delta1;
2686 (*setsizefun) (window, *sizep + delta1, 0);
2688 /* Squeeze out delta1 lines or columns from our parent,
2689 shriking this window and siblings proportionately.
2690 This brings parent back to correct size.
2691 Delta1 was calculated so this makes this window the desired size,
2692 taking it all out of the siblings. */
2693 (*setsizefun) (parent, opht, 0);
2696 XSETFASTINT (p->last_modified, 0);
2697 XSETFASTINT (p->last_overlay_modified, 0);
2699 #undef MINSIZE
2700 #undef CURBEG
2701 #undef CURSIZE
2704 /* Return number of lines of text (not counting mode line) in W. */
2707 window_internal_height (w)
2708 struct window *w;
2710 int ht = XFASTINT (w->height);
2712 if (MINI_WINDOW_P (w))
2713 return ht;
2715 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2716 || !NILP (w->next) || !NILP (w->prev)
2717 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
2718 return ht - 1;
2720 return ht;
2724 /* Return the number of columns in W.
2725 Don't count columns occupied by scroll bars or the vertical bar
2726 separating W from the sibling to its right. */
2728 window_internal_width (w)
2729 struct window *w;
2731 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2732 int width = XINT (w->width);
2734 /* Scroll bars occupy a few columns. */
2735 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
2736 return width - FRAME_SCROLL_BAR_COLS (f);
2738 /* The column of `|' characters separating side-by-side windows
2739 occupies one column only. */
2740 if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
2741 return width - 1;
2743 return width;
2747 /* Scroll contents of window WINDOW up N lines.
2748 If WHOLE is nonzero, it means scroll N screenfuls instead. */
2750 static void
2751 window_scroll (window, n, whole, noerror)
2752 Lisp_Object window;
2753 int n;
2754 int whole;
2755 int noerror;
2757 register struct window *w = XWINDOW (window);
2758 register int opoint = PT;
2759 register int pos;
2760 register int ht = window_internal_height (w);
2761 register Lisp_Object tem;
2762 int lose;
2763 Lisp_Object bolp, nmoved;
2764 int startpos;
2765 struct position posit;
2766 int original_vpos;
2768 startpos = marker_position (w->start);
2770 posit = *compute_motion (startpos, 0, 0, 0,
2771 PT, ht, 0,
2772 window_internal_width (w), XINT (w->hscroll),
2773 0, w);
2774 original_vpos = posit.vpos;
2776 XSETFASTINT (tem, PT);
2777 tem = Fpos_visible_in_window_p (tem, window);
2779 if (NILP (tem))
2781 Fvertical_motion (make_number (- (ht / 2)), window);
2782 startpos = PT;
2785 SET_PT (startpos);
2786 lose = n < 0 && PT == BEGV;
2787 Fvertical_motion (make_number (n), window);
2788 pos = PT;
2789 bolp = Fbolp ();
2790 SET_PT (opoint);
2792 if (lose)
2794 if (noerror)
2795 return;
2796 else
2797 Fsignal (Qbeginning_of_buffer, Qnil);
2800 if (pos < ZV)
2802 int this_scroll_margin = scroll_margin;
2804 /* Don't use a scroll margin that is negative or too large. */
2805 if (this_scroll_margin < 0)
2806 this_scroll_margin = 0;
2808 if (XINT (w->height) < 4 * scroll_margin)
2809 this_scroll_margin = XINT (w->height) / 4;
2811 set_marker_restricted (w->start, make_number (pos), w->buffer);
2812 w->start_at_line_beg = bolp;
2813 w->update_mode_line = Qt;
2814 XSETFASTINT (w->last_modified, 0);
2815 XSETFASTINT (w->last_overlay_modified, 0);
2816 /* Set force_start so that redisplay_window will run
2817 the window-scroll-functions. */
2818 w->force_start = Qt;
2820 if (whole && scroll_preserve_screen_position)
2822 SET_PT (pos);
2823 Fvertical_motion (make_number (original_vpos), window);
2825 /* If we scrolled forward, put point enough lines down
2826 that it is outside the scroll margin. */
2827 else if (n > 0)
2829 int top_margin;
2831 if (this_scroll_margin > 0)
2833 SET_PT (pos);
2834 Fvertical_motion (make_number (this_scroll_margin), window);
2835 top_margin = PT;
2837 else
2838 top_margin = pos;
2840 if (top_margin <= opoint)
2841 SET_PT (opoint);
2842 else if (scroll_preserve_screen_position)
2844 SET_PT (pos);
2845 Fvertical_motion (make_number (original_vpos), window);
2847 else
2848 SET_PT (pos);
2850 else if (n < 0)
2852 int bottom_margin;
2854 /* If we scrolled backward, put point near the end of the window
2855 but not within the scroll margin. */
2856 SET_PT (pos);
2857 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
2858 if (XFASTINT (tem) == ht - this_scroll_margin)
2859 bottom_margin = PT;
2860 else
2861 bottom_margin = PT + 1;
2863 if (bottom_margin > opoint)
2864 SET_PT (opoint);
2865 else
2867 if (scroll_preserve_screen_position)
2869 SET_PT (pos);
2870 Fvertical_motion (make_number (original_vpos), window);
2872 else
2873 Fvertical_motion (make_number (-1), window);
2877 else
2879 if (noerror)
2880 return;
2881 else
2882 Fsignal (Qend_of_buffer, Qnil);
2886 /* This is the guts of Fscroll_up and Fscroll_down. */
2888 static void
2889 scroll_command (n, direction)
2890 register Lisp_Object n;
2891 int direction;
2893 register int defalt;
2894 int count = specpdl_ptr - specpdl;
2896 /* If selected window's buffer isn't current, make it current for the moment.
2897 But don't screw up if window_scroll gets an error. */
2898 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
2900 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2901 Fset_buffer (XWINDOW (selected_window)->buffer);
2904 defalt = (window_internal_height (XWINDOW (selected_window))
2905 - next_screen_context_lines);
2906 defalt = direction * (defalt < 1 ? 1 : defalt);
2908 if (NILP (n))
2909 window_scroll (selected_window, defalt, 1, 0);
2910 else if (EQ (n, Qminus))
2911 window_scroll (selected_window, - defalt, 1, 0);
2912 else
2914 n = Fprefix_numeric_value (n);
2915 window_scroll (selected_window, XINT (n) * direction, 0, 0);
2918 unbind_to (count, Qnil);
2921 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2922 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2923 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2924 Negative ARG means scroll downward.\n\
2925 When calling from a program, supply a number as argument or nil.")
2926 (arg)
2927 Lisp_Object arg;
2929 scroll_command (arg, 1);
2930 return Qnil;
2933 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2934 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2935 A near full screen is `next-screen-context-lines' less than a full screen.\n\
2936 Negative ARG means scroll upward.\n\
2937 When calling from a program, supply a number as argument or nil.")
2938 (arg)
2939 Lisp_Object arg;
2941 scroll_command (arg, -1);
2942 return Qnil;
2945 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
2946 "Return the other window for \"other window scroll\" commands.\n\
2947 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2948 specifies the window.\n\
2949 If `other-window-scroll-buffer' is non-nil, a window\n\
2950 showing that buffer is used.")
2953 Lisp_Object window;
2955 if (MINI_WINDOW_P (XWINDOW (selected_window))
2956 && !NILP (Vminibuf_scroll_window))
2957 window = Vminibuf_scroll_window;
2958 /* If buffer is specified, scroll that buffer. */
2959 else if (!NILP (Vother_window_scroll_buffer))
2961 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
2962 if (NILP (window))
2963 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2965 else
2967 /* Nothing specified; look for a neighboring window on the same
2968 frame. */
2969 window = Fnext_window (selected_window, Qnil, Qnil);
2971 if (EQ (window, selected_window))
2972 /* That didn't get us anywhere; look for a window on another
2973 visible frame. */
2975 window = Fnext_window (window, Qnil, Qt);
2976 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
2977 && ! EQ (window, selected_window));
2980 CHECK_LIVE_WINDOW (window, 0);
2982 if (EQ (window, selected_window))
2983 error ("There is no other window");
2985 return window;
2988 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
2989 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
2990 The next window is the one below the current one; or the one at the top\n\
2991 if the current one is at the bottom. Negative ARG means scroll downward.\n\
2992 When calling from a program, supply a number as argument or nil.\n\
2994 If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2995 specifies the window to scroll.\n\
2996 If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2997 showing that buffer, popping the buffer up if necessary.")
2998 (arg)
2999 register Lisp_Object arg;
3001 register Lisp_Object window;
3002 register int defalt;
3003 register struct window *w;
3004 register int count = specpdl_ptr - specpdl;
3006 window = Fother_window_for_scrolling ();
3008 w = XWINDOW (window);
3009 defalt = window_internal_height (w) - next_screen_context_lines;
3010 if (defalt < 1) defalt = 1;
3012 /* Don't screw up if window_scroll gets an error. */
3013 record_unwind_protect (save_excursion_restore, save_excursion_save ());
3015 Fset_buffer (w->buffer);
3016 SET_PT (marker_position (w->pointm));
3018 if (NILP (arg))
3019 window_scroll (window, defalt, 1, 1);
3020 else if (EQ (arg, Qminus))
3021 window_scroll (window, -defalt, 1, 1);
3022 else
3024 if (CONSP (arg))
3025 arg = Fcar (arg);
3026 CHECK_NUMBER (arg, 0);
3027 window_scroll (window, XINT (arg), 0, 1);
3030 Fset_marker (w->pointm, make_number (PT), Qnil);
3031 unbind_to (count, Qnil);
3033 return Qnil;
3036 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
3037 "Scroll selected window display ARG columns left.\n\
3038 Default for ARG is window width minus 2.")
3039 (arg)
3040 register Lisp_Object arg;
3043 if (NILP (arg))
3044 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
3045 else
3046 arg = Fprefix_numeric_value (arg);
3048 return
3049 Fset_window_hscroll (selected_window,
3050 make_number (XINT (XWINDOW (selected_window)->hscroll)
3051 + XINT (arg)));
3054 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
3055 "Scroll selected window display ARG columns right.\n\
3056 Default for ARG is window width minus 2.")
3057 (arg)
3058 register Lisp_Object arg;
3060 if (NILP (arg))
3061 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
3062 else
3063 arg = Fprefix_numeric_value (arg);
3065 return
3066 Fset_window_hscroll (selected_window,
3067 make_number (XINT (XWINDOW (selected_window)->hscroll)
3068 - XINT (arg)));
3071 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
3072 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
3073 The desired position of point is always relative to the current window.\n\
3074 Just C-u as prefix means put point in the center of the window.\n\
3075 If ARG is omitted or nil, erases the entire frame and then\n\
3076 redraws with point in the center of the current window.")
3077 (arg)
3078 register Lisp_Object arg;
3080 register struct window *w = XWINDOW (selected_window);
3081 register int ht = window_internal_height (w);
3082 struct position pos;
3084 if (NILP (arg))
3086 extern int frame_garbaged;
3088 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
3089 XSETFASTINT (arg, ht / 2);
3091 else if (CONSP (arg)) /* Just C-u. */
3093 XSETFASTINT (arg, ht / 2);
3095 else
3097 arg = Fprefix_numeric_value (arg);
3098 CHECK_NUMBER (arg, 0);
3101 if (XINT (arg) < 0)
3102 XSETINT (arg, XINT (arg) + ht);
3104 pos = *vmotion (PT, - XINT (arg), w);
3106 Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
3107 w->start_at_line_beg = ((pos.bufpos == BEGV
3108 || FETCH_BYTE (pos.bufpos - 1) == '\n')
3109 ? Qt : Qnil);
3110 w->force_start = Qt;
3112 return Qnil;
3115 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
3116 1, 1, "P",
3117 "Position point relative to window.\n\
3118 With no argument, position point at center of window.\n\
3119 An argument specifies frame line; zero means top of window,\n\
3120 negative means relative to bottom of window.")
3121 (arg)
3122 register Lisp_Object arg;
3124 register struct window *w = XWINDOW (selected_window);
3125 register int height = window_internal_height (w);
3126 register int start;
3127 Lisp_Object window;
3129 if (NILP (arg))
3130 XSETFASTINT (arg, height / 2);
3131 else
3133 arg = Fprefix_numeric_value (arg);
3134 if (XINT (arg) < 0)
3135 XSETINT (arg, XINT (arg) + height);
3138 start = marker_position (w->start);
3139 XSETWINDOW (window, w);
3140 if (start < BEGV || start > ZV)
3142 Fvertical_motion (make_number (- (height / 2)), window);
3143 Fset_marker (w->start, make_number (PT), w->buffer);
3144 w->start_at_line_beg = Fbolp ();
3145 w->force_start = Qt;
3147 else
3148 SET_PT (start);
3150 return Fvertical_motion (arg, window);
3153 struct save_window_data
3155 EMACS_INT size_from_Lisp_Vector_struct;
3156 struct Lisp_Vector *next_from_Lisp_Vector_struct;
3157 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
3158 Lisp_Object selected_frame;
3159 Lisp_Object current_window;
3160 Lisp_Object current_buffer;
3161 Lisp_Object minibuf_scroll_window;
3162 Lisp_Object root_window;
3163 Lisp_Object focus_frame;
3164 /* Record the values of window-min-width and window-min-height
3165 so that window sizes remain consistent with them. */
3166 Lisp_Object min_width, min_height;
3167 /* A vector, interpreted as a struct saved_window */
3168 Lisp_Object saved_windows;
3171 /* This is saved as a Lisp_Vector */
3172 struct saved_window
3174 /* these first two must agree with struct Lisp_Vector in lisp.h */
3175 EMACS_INT size_from_Lisp_Vector_struct;
3176 struct Lisp_Vector *next_from_Lisp_Vector_struct;
3178 Lisp_Object window;
3179 Lisp_Object buffer, start, pointm, mark;
3180 Lisp_Object left, top, width, height, hscroll;
3181 Lisp_Object parent, prev;
3182 Lisp_Object start_at_line_beg;
3183 Lisp_Object display_table;
3185 #define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
3187 #define SAVED_WINDOW_N(swv,n) \
3188 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
3190 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
3191 "T if OBJECT is a window-configuration object.")
3192 (object)
3193 Lisp_Object object;
3195 if (WINDOW_CONFIGURATIONP (object))
3196 return Qt;
3197 return Qnil;
3201 DEFUN ("set-window-configuration", Fset_window_configuration,
3202 Sset_window_configuration, 1, 1, 0,
3203 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
3204 CONFIGURATION must be a value previously returned\n\
3205 by `current-window-configuration' (which see).")
3206 (configuration)
3207 Lisp_Object configuration;
3209 register struct save_window_data *data;
3210 struct Lisp_Vector *saved_windows;
3211 Lisp_Object new_current_buffer;
3212 Lisp_Object frame;
3213 FRAME_PTR f;
3215 while (!WINDOW_CONFIGURATIONP (configuration))
3217 configuration = wrong_type_argument (intern ("window-configuration-p"),
3218 configuration);
3221 data = (struct save_window_data *) XVECTOR (configuration);
3222 saved_windows = XVECTOR (data->saved_windows);
3224 new_current_buffer = data->current_buffer;
3225 if (NILP (XBUFFER (new_current_buffer)->name))
3226 new_current_buffer = Qnil;
3228 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
3229 f = XFRAME (frame);
3231 /* If f is a dead frame, don't bother rebuilding its window tree.
3232 However, there is other stuff we should still try to do below. */
3233 if (FRAME_LIVE_P (f))
3235 register struct window *w;
3236 register struct saved_window *p;
3237 int k;
3239 /* If the frame has been resized since this window configuration was
3240 made, we change the frame to the size specified in the
3241 configuration, restore the configuration, and then resize it
3242 back. We keep track of the prevailing height in these variables. */
3243 int previous_frame_height = FRAME_HEIGHT (f);
3244 int previous_frame_width = FRAME_WIDTH (f);
3245 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
3247 if (XFASTINT (data->frame_height) != previous_frame_height
3248 || XFASTINT (data->frame_width) != previous_frame_width)
3249 change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
3250 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
3251 if (XFASTINT (data->frame_menu_bar_lines)
3252 != previous_frame_menu_bar_lines)
3253 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
3254 #endif
3256 windows_or_buffers_changed++;
3257 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3259 /* Temporarily avoid any problems with windows that are smaller
3260 than they are supposed to be. */
3261 window_min_height = 1;
3262 window_min_width = 1;
3264 /* Kludge Alert!
3265 Mark all windows now on frame as "deleted".
3266 Restoring the new configuration "undeletes" any that are in it.
3268 Save their current buffers in their height fields, since we may
3269 need it later, if a buffer saved in the configuration is now
3270 dead. */
3271 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
3273 for (k = 0; k < saved_windows->size; k++)
3275 p = SAVED_WINDOW_N (saved_windows, k);
3276 w = XWINDOW (p->window);
3277 w->next = Qnil;
3279 if (!NILP (p->parent))
3280 w->parent = SAVED_WINDOW_N (saved_windows,
3281 XFASTINT (p->parent))->window;
3282 else
3283 w->parent = Qnil;
3285 if (!NILP (p->prev))
3287 w->prev = SAVED_WINDOW_N (saved_windows,
3288 XFASTINT (p->prev))->window;
3289 XWINDOW (w->prev)->next = p->window;
3291 else
3293 w->prev = Qnil;
3294 if (!NILP (w->parent))
3296 if (EQ (p->width, XWINDOW (w->parent)->width))
3298 XWINDOW (w->parent)->vchild = p->window;
3299 XWINDOW (w->parent)->hchild = Qnil;
3301 else
3303 XWINDOW (w->parent)->hchild = p->window;
3304 XWINDOW (w->parent)->vchild = Qnil;
3309 /* If we squirreled away the buffer in the window's height,
3310 restore it now. */
3311 if (BUFFERP (w->height))
3312 w->buffer = w->height;
3313 w->left = p->left;
3314 w->top = p->top;
3315 w->width = p->width;
3316 w->height = p->height;
3317 w->hscroll = p->hscroll;
3318 w->display_table = p->display_table;
3319 XSETFASTINT (w->last_modified, 0);
3320 XSETFASTINT (w->last_overlay_modified, 0);
3322 /* Reinstall the saved buffer and pointers into it. */
3323 if (NILP (p->buffer))
3324 w->buffer = p->buffer;
3325 else
3327 if (!NILP (XBUFFER (p->buffer)->name))
3328 /* If saved buffer is alive, install it. */
3330 w->buffer = p->buffer;
3331 w->start_at_line_beg = p->start_at_line_beg;
3332 set_marker_restricted (w->start,
3333 Fmarker_position (p->start),
3334 w->buffer);
3335 set_marker_restricted (w->pointm,
3336 Fmarker_position (p->pointm),
3337 w->buffer);
3338 Fset_marker (XBUFFER (w->buffer)->mark,
3339 Fmarker_position (p->mark), w->buffer);
3341 /* As documented in Fcurrent_window_configuration, don't
3342 save the location of point in the buffer which was current
3343 when the window configuration was recorded. */
3344 if (!EQ (p->buffer, new_current_buffer)
3345 && XBUFFER (p->buffer) == current_buffer)
3346 Fgoto_char (w->pointm);
3348 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
3349 /* Else unless window has a live buffer, get one. */
3351 w->buffer = Fcdr (Fcar (Vbuffer_alist));
3352 /* This will set the markers to beginning of visible
3353 range. */
3354 set_marker_restricted (w->start, make_number (0), w->buffer);
3355 set_marker_restricted (w->pointm, make_number (0),w->buffer);
3356 w->start_at_line_beg = Qt;
3358 else
3359 /* Keeping window's old buffer; make sure the markers
3360 are real. */
3362 /* Set window markers at start of visible range. */
3363 if (XMARKER (w->start)->buffer == 0)
3364 set_marker_restricted (w->start, make_number (0),
3365 w->buffer);
3366 if (XMARKER (w->pointm)->buffer == 0)
3367 set_marker_restricted (w->pointm,
3368 (make_number
3369 (BUF_PT (XBUFFER (w->buffer)))),
3370 w->buffer);
3371 w->start_at_line_beg = Qt;
3376 FRAME_ROOT_WINDOW (f) = data->root_window;
3377 Fselect_window (data->current_window);
3378 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
3379 = selected_window;
3381 if (NILP (data->focus_frame)
3382 || (FRAMEP (data->focus_frame)
3383 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
3384 Fredirect_frame_focus (frame, data->focus_frame);
3386 #if 0 /* I don't understand why this is needed, and it causes problems
3387 when the frame's old selected window has been deleted. */
3388 if (f != selected_frame && FRAME_WINDOW_P (f))
3389 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
3390 Qnil, 0);
3391 #endif
3393 /* Set the screen height to the value it had before this function. */
3394 if (previous_frame_height != FRAME_HEIGHT (f)
3395 || previous_frame_width != FRAME_WIDTH (f))
3396 change_frame_size (f, previous_frame_height, previous_frame_width,
3397 0, 0);
3398 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
3399 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
3400 x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
3401 #endif
3404 /* Restore the minimum heights recorded in the configuration. */
3405 window_min_height = XINT (data->min_height);
3406 window_min_width = XINT (data->min_width);
3408 /* Fselect_window will have made f the selected frame, so we
3409 reselect the proper frame here. Fhandle_switch_frame will change the
3410 selected window too, but that doesn't make the call to
3411 Fselect_window above totally superfluous; it still sets f's
3412 selected window. */
3413 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
3414 do_switch_frame (data->selected_frame, Qnil, 0);
3416 if (!NILP (new_current_buffer))
3417 Fset_buffer (new_current_buffer);
3419 Vminibuf_scroll_window = data->minibuf_scroll_window;
3421 if (! NILP (Vwindow_configuration_change_hook)
3422 && ! NILP (Vrun_hooks))
3423 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3425 return (Qnil);
3428 /* Mark all windows now on frame as deleted
3429 by setting their buffers to nil. */
3431 void
3432 delete_all_subwindows (w)
3433 register struct window *w;
3435 if (!NILP (w->next))
3436 delete_all_subwindows (XWINDOW (w->next));
3437 if (!NILP (w->vchild))
3438 delete_all_subwindows (XWINDOW (w->vchild));
3439 if (!NILP (w->hchild))
3440 delete_all_subwindows (XWINDOW (w->hchild));
3442 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
3444 if (!NILP (w->buffer))
3445 unshow_buffer (w);
3447 /* We set all three of these fields to nil, to make sure that we can
3448 distinguish this dead window from any live window. Live leaf
3449 windows will have buffer set, and combination windows will have
3450 vchild or hchild set. */
3451 w->buffer = Qnil;
3452 w->vchild = Qnil;
3453 w->hchild = Qnil;
3456 static int
3457 count_windows (window)
3458 register struct window *window;
3460 register int count = 1;
3461 if (!NILP (window->next))
3462 count += count_windows (XWINDOW (window->next));
3463 if (!NILP (window->vchild))
3464 count += count_windows (XWINDOW (window->vchild));
3465 if (!NILP (window->hchild))
3466 count += count_windows (XWINDOW (window->hchild));
3467 return count;
3470 static int
3471 save_window_save (window, vector, i)
3472 Lisp_Object window;
3473 struct Lisp_Vector *vector;
3474 int i;
3476 register struct saved_window *p;
3477 register struct window *w;
3478 register Lisp_Object tem;
3480 for (;!NILP (window); window = w->next)
3482 p = SAVED_WINDOW_N (vector, i);
3483 w = XWINDOW (window);
3485 XSETFASTINT (w->temslot, i++);
3486 p->window = window;
3487 p->buffer = w->buffer;
3488 p->left = w->left;
3489 p->top = w->top;
3490 p->width = w->width;
3491 p->height = w->height;
3492 p->hscroll = w->hscroll;
3493 p->display_table = w->display_table;
3494 if (!NILP (w->buffer))
3496 /* Save w's value of point in the window configuration.
3497 If w is the selected window, then get the value of point
3498 from the buffer; pointm is garbage in the selected window. */
3499 if (EQ (window, selected_window))
3501 p->pointm = Fmake_marker ();
3502 Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
3503 w->buffer);
3505 else
3506 p->pointm = Fcopy_marker (w->pointm, Qnil);
3508 p->start = Fcopy_marker (w->start, Qnil);
3509 p->start_at_line_beg = w->start_at_line_beg;
3511 tem = XBUFFER (w->buffer)->mark;
3512 p->mark = Fcopy_marker (tem, Qnil);
3514 else
3516 p->pointm = Qnil;
3517 p->start = Qnil;
3518 p->mark = Qnil;
3519 p->start_at_line_beg = Qnil;
3522 if (NILP (w->parent))
3523 p->parent = Qnil;
3524 else
3525 p->parent = XWINDOW (w->parent)->temslot;
3527 if (NILP (w->prev))
3528 p->prev = Qnil;
3529 else
3530 p->prev = XWINDOW (w->prev)->temslot;
3532 if (!NILP (w->vchild))
3533 i = save_window_save (w->vchild, vector, i);
3534 if (!NILP (w->hchild))
3535 i = save_window_save (w->hchild, vector, i);
3538 return i;
3541 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
3542 Scurrent_window_configuration, 0, 1, 0,
3543 "Return an object representing the current window configuration of FRAME.\n\
3544 If FRAME is nil or omitted, use the selected frame.\n\
3545 This describes the number of windows, their sizes and current buffers,\n\
3546 and for each displayed buffer, where display starts, and the positions of\n\
3547 point and mark. An exception is made for point in the current buffer:\n\
3548 its value is -not- saved.\n\
3549 This also records the currently selected frame, and FRAME's focus\n\
3550 redirection (see `redirect-frame-focus').")
3551 (frame)
3552 Lisp_Object frame;
3554 register Lisp_Object tem;
3555 register int n_windows;
3556 register struct save_window_data *data;
3557 register struct Lisp_Vector *vec;
3558 register int i;
3559 FRAME_PTR f;
3561 if (NILP (frame))
3562 f = selected_frame;
3563 else
3565 CHECK_LIVE_FRAME (frame, 0);
3566 f = XFRAME (frame);
3569 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
3570 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
3571 for (i = 0; i < VECSIZE (struct save_window_data); i++)
3572 vec->contents[i] = Qnil;
3573 vec->size = VECSIZE (struct save_window_data);
3574 data = (struct save_window_data *)vec;
3576 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
3577 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
3578 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
3579 XSETFRAME (data->selected_frame, selected_frame);
3580 data->current_window = FRAME_SELECTED_WINDOW (f);
3581 XSETBUFFER (data->current_buffer, current_buffer);
3582 data->minibuf_scroll_window = Vminibuf_scroll_window;
3583 data->root_window = FRAME_ROOT_WINDOW (f);
3584 data->focus_frame = FRAME_FOCUS_FRAME (f);
3585 XSETINT (data->min_height, window_min_height);
3586 XSETINT (data->min_width, window_min_width);
3587 tem = Fmake_vector (make_number (n_windows), Qnil);
3588 data->saved_windows = tem;
3589 for (i = 0; i < n_windows; i++)
3590 XVECTOR (tem)->contents[i]
3591 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
3592 save_window_save (FRAME_ROOT_WINDOW (f),
3593 XVECTOR (tem), 0);
3594 XSETWINDOW_CONFIGURATION (tem, data);
3595 return (tem);
3598 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
3599 0, UNEVALLED, 0,
3600 "Execute body, preserving window sizes and contents.\n\
3601 Restore which buffer appears in which window, where display starts,\n\
3602 and the value of point and mark for each window.\n\
3603 Also restore which buffer is current.\n\
3604 But do not preserve point in the current buffer.\n\
3605 Does not restore the value of point in current buffer.")
3606 (args)
3607 Lisp_Object args;
3609 register Lisp_Object val;
3610 register int count = specpdl_ptr - specpdl;
3612 record_unwind_protect (Fset_window_configuration,
3613 Fcurrent_window_configuration (Qnil));
3614 val = Fprogn (args);
3615 return unbind_to (count, val);
3618 init_window_once ()
3620 selected_frame = make_terminal_frame ();
3621 XSETFRAME (Vterminal_frame, selected_frame);
3622 minibuf_window = selected_frame->minibuffer_window;
3623 selected_window = selected_frame->selected_window;
3624 last_nonminibuf_frame = selected_frame;
3626 window_initialized = 1;
3629 syms_of_window ()
3631 staticpro (&Qwindow_configuration_change_hook);
3632 Qwindow_configuration_change_hook
3633 = intern ("window-configuration-change-hook");
3635 Qwindowp = intern ("windowp");
3636 staticpro (&Qwindowp);
3638 Qwindow_live_p = intern ("window-live-p");
3639 staticpro (&Qwindow_live_p);
3641 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
3642 staticpro (&Qtemp_buffer_show_hook);
3644 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
3645 "Non-nil means call as function to display a help buffer.\n\
3646 The function is called with one argument, the buffer to be displayed.\n\
3647 Used by `with-output-to-temp-buffer'.\n\
3648 If this function is used, then it must do the entire job of showing\n\
3649 the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
3650 Vtemp_buffer_show_function = Qnil;
3652 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
3653 "If non-nil, function to call to handle `display-buffer'.\n\
3654 It will receive two args, the buffer and a flag which if non-nil means\n\
3655 that the currently selected window is not acceptable.\n\
3656 Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
3657 work using this function.");
3658 Vdisplay_buffer_function = Qnil;
3660 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
3661 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
3662 Vminibuf_scroll_window = Qnil;
3664 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
3665 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
3666 Vother_window_scroll_buffer = Qnil;
3668 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
3669 "*Non-nil means `display-buffer' should make a separate frame.");
3670 pop_up_frames = 0;
3672 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
3673 "Function to call to handle automatic new frame creation.\n\
3674 It is called with no arguments and should return a newly created frame.\n\
3676 A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
3677 where `pop-up-frame-alist' would hold the default frame parameters.");
3678 Vpop_up_frame_function = Qnil;
3680 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
3681 "*List of buffer names that should have their own special frames.\n\
3682 Displaying a buffer whose name is in this list makes a special frame for it\n\
3683 using `special-display-function'. See also `special-display-regexps'.\n\
3685 An element of the list can be a list instead of just a string.\n\
3686 There are two ways to use a list as an element:\n\
3687 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
3688 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
3689 In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
3690 followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
3691 All this is done by the function found in `special-display-function'.");
3692 Vspecial_display_buffer_names = Qnil;
3694 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
3695 "*List of regexps saying which buffers should have their own special frames.\n\
3696 If a buffer name matches one of these regexps, it gets its own frame.\n\
3697 Displaying a buffer whose name is in this list makes a special frame for it\n\
3698 using `special-display-function'.\n\
3700 An element of the list can be a list instead of just a string.\n\
3701 There are two ways to use a list as an element:\n\
3702 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
3703 In the first case, FRAME-PARAMETERS are used to create the frame.\n\
3704 In the latter case, FUNCTION is called with the buffer as first argument,\n\
3705 followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
3706 All this is done by the function found in `special-display-function'.");
3707 Vspecial_display_regexps = Qnil;
3709 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
3710 "Function to call to make a new frame for a special buffer.\n\
3711 It is called with two arguments, the buffer and optional buffer specific\n\
3712 data, and should return a window displaying that buffer.\n\
3713 The default value makes a separate frame for the buffer,\n\
3714 using `special-display-frame-alist' to specify the frame parameters.\n\
3716 A buffer is special if its is listed in `special-display-buffer-names'\n\
3717 or matches a regexp in `special-display-regexps'.");
3718 Vspecial_display_function = Qnil;
3720 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
3721 "*List of buffer names that should appear in the selected window.\n\
3722 Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
3723 switches to it in the selected window, rather than making it appear\n\
3724 in some other window.\n\
3726 An element of the list can be a cons cell instead of just a string.\n\
3727 Then the car must be a string, which specifies the buffer name.\n\
3728 This is for compatibility with `special-display-buffer-names';\n\
3729 the cdr of the cons cell is ignored.\n\
3731 See also `same-window-regexps'.");
3732 Vsame_window_buffer_names = Qnil;
3734 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
3735 "*List of regexps saying which buffers should appear in the selected window.\n\
3736 If a buffer name matches one of these regexps, then displaying it\n\
3737 using `display-buffer' or `pop-to-buffer' switches to it\n\
3738 in the selected window, rather than making it appear in some other window.\n\
3740 An element of the list can be a cons cell instead of just a string.\n\
3741 Then the car must be a string, which specifies the buffer name.\n\
3742 This is for compatibility with `special-display-buffer-names';\n\
3743 the cdr of the cons cell is ignored.\n\
3745 See also `same-window-buffer-names'.");
3746 Vsame_window_regexps = Qnil;
3748 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
3749 "*Non-nil means display-buffer should make new windows.");
3750 pop_up_windows = 1;
3752 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
3753 "*Number of lines of continuity when scrolling by screenfuls.");
3754 next_screen_context_lines = 2;
3756 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
3757 "*display-buffer would prefer to split the largest window if this large.\n\
3758 If there is only one window, it is split regardless of this value.");
3759 split_height_threshold = 500;
3761 DEFVAR_INT ("window-min-height", &window_min_height,
3762 "*Delete any window less than this tall (including its mode line).");
3763 window_min_height = 4;
3765 DEFVAR_INT ("window-min-width", &window_min_width,
3766 "*Delete any window less than this wide.");
3767 window_min_width = 10;
3769 DEFVAR_BOOL ("scroll-preserve-screen-position",
3770 &scroll_preserve_screen_position,
3771 "*Nonzero means scroll commands move point to keep its screen line unchanged.");
3772 scroll_preserve_screen_position = 0;
3774 DEFVAR_LISP ("window-configuration-change-hook",
3775 &Vwindow_configuration_change_hook,
3776 "Functions to call when window configuration changes.\n\
3777 The selected frae is the one whose configuration has changed.");
3778 Vwindow_configuration_change_hook = Qnil;
3780 defsubr (&Sselected_window);
3781 defsubr (&Sminibuffer_window);
3782 defsubr (&Swindow_minibuffer_p);
3783 defsubr (&Swindowp);
3784 defsubr (&Swindow_live_p);
3785 defsubr (&Spos_visible_in_window_p);
3786 defsubr (&Swindow_buffer);
3787 defsubr (&Swindow_height);
3788 defsubr (&Swindow_width);
3789 defsubr (&Swindow_hscroll);
3790 defsubr (&Sset_window_hscroll);
3791 defsubr (&Swindow_redisplay_end_trigger);
3792 defsubr (&Sset_window_redisplay_end_trigger);
3793 defsubr (&Swindow_edges);
3794 defsubr (&Scoordinates_in_window_p);
3795 defsubr (&Swindow_at);
3796 defsubr (&Swindow_point);
3797 defsubr (&Swindow_start);
3798 defsubr (&Swindow_end);
3799 defsubr (&Sset_window_point);
3800 defsubr (&Sset_window_start);
3801 defsubr (&Swindow_dedicated_p);
3802 defsubr (&Sset_window_dedicated_p);
3803 defsubr (&Swindow_display_table);
3804 defsubr (&Sset_window_display_table);
3805 defsubr (&Snext_window);
3806 defsubr (&Sprevious_window);
3807 defsubr (&Sother_window);
3808 defsubr (&Sget_lru_window);
3809 defsubr (&Sget_largest_window);
3810 defsubr (&Sget_buffer_window);
3811 defsubr (&Sdelete_other_windows);
3812 defsubr (&Sdelete_windows_on);
3813 defsubr (&Sreplace_buffer_in_windows);
3814 defsubr (&Sdelete_window);
3815 defsubr (&Sset_window_buffer);
3816 defsubr (&Sselect_window);
3817 defsubr (&Sspecial_display_p);
3818 defsubr (&Ssame_window_p);
3819 defsubr (&Sdisplay_buffer);
3820 defsubr (&Ssplit_window);
3821 defsubr (&Senlarge_window);
3822 defsubr (&Sshrink_window);
3823 defsubr (&Sscroll_up);
3824 defsubr (&Sscroll_down);
3825 defsubr (&Sscroll_left);
3826 defsubr (&Sscroll_right);
3827 defsubr (&Sother_window_for_scrolling);
3828 defsubr (&Sscroll_other_window);
3829 defsubr (&Srecenter);
3830 defsubr (&Smove_to_window_line);
3831 defsubr (&Swindow_configuration_p);
3832 defsubr (&Sset_window_configuration);
3833 defsubr (&Scurrent_window_configuration);
3834 defsubr (&Ssave_window_excursion);
3837 keys_of_window ()
3839 initial_define_key (control_x_map, '1', "delete-other-windows");
3840 initial_define_key (control_x_map, '2', "split-window");
3841 initial_define_key (control_x_map, '0', "delete-window");
3842 initial_define_key (control_x_map, 'o', "other-window");
3843 initial_define_key (control_x_map, '^', "enlarge-window");
3844 initial_define_key (control_x_map, '<', "scroll-left");
3845 initial_define_key (control_x_map, '>', "scroll-right");
3847 initial_define_key (global_map, Ctl ('V'), "scroll-up");
3848 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
3849 initial_define_key (meta_map, 'v', "scroll-down");
3851 initial_define_key (global_map, Ctl('L'), "recenter");
3852 initial_define_key (meta_map, 'r', "move-to-window-line");