(sgml-font-lock-keywords-1): Accept upper case like lower case.
[bpt/emacs.git] / src / window.c
CommitLineData
7ab12479
JB
1/* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
4a2f9c6a 3 Copyright (C) 1985,86,87,93,94,95,96,97,1998 Free Software Foundation, Inc.
7ab12479
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
1113d9db 9the Free Software Foundation; either version 2, or (at your option)
7ab12479
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
7ab12479 21
18160b98 22#include <config.h>
7ab12479
JB
23#include "lisp.h"
24#include "buffer.h"
44fa5b1e 25#include "frame.h"
7ab12479
JB
26#include "window.h"
27#include "commands.h"
28#include "indent.h"
29#include "termchar.h"
30#include "disptab.h"
f8026fd8 31#include "keyboard.h"
d2b35234 32#include "blockinput.h"
dfcf069d 33#include "dispextern.h"
6d55d620 34#ifdef HAVE_X_WINDOWS
dfcf069d
AS
35#include "xterm.h"
36#endif
7ab12479 37
806b4d9b 38Lisp_Object Qwindowp, Qwindow_live_p;
7ab12479 39
5e14b1fc 40static struct window *decode_window P_ ((Lisp_Object));
7ab12479 41
b7354ddf
RS
42static Lisp_Object select_window_1 P_ ((Lisp_Object, int));
43
7ab12479
JB
44/* This is the window in which the terminal's cursor should
45 be left when nothing is being done with it. This must
46 always be a leaf window, and its buffer is selected by
47 the top level editing loop at the end of each command.
48
49 This value is always the same as
44fa5b1e 50 FRAME_SELECTED_WINDOW (selected_frame). */
7ab12479
JB
51
52Lisp_Object selected_window;
53
44fa5b1e 54/* The minibuffer window of the selected frame.
7ab12479
JB
55 Note that you cannot test for minibufferness of an arbitrary window
56 by comparing against this; but you can test for minibufferness of
57 the selected window. */
58Lisp_Object minibuf_window;
59
60/* Non-nil means it is the window for C-M-v to scroll
61 when the minibuffer is selected. */
62Lisp_Object Vminibuf_scroll_window;
63
64/* Non-nil means this is the buffer whose window C-M-v should scroll. */
65Lisp_Object Vother_window_scroll_buffer;
66
7ab12479
JB
67/* Non-nil means it's function to call to display temp buffers. */
68Lisp_Object Vtemp_buffer_show_function;
69
70/* If a window gets smaller than either of these, it is removed. */
71int window_min_height;
72int window_min_width;
73
74/* Nonzero implies Fdisplay_buffer should create windows. */
75int pop_up_windows;
76
44fa5b1e
JB
77/* Nonzero implies make new frames for Fdisplay_buffer. */
78int pop_up_frames;
7ab12479
JB
79
80/* Non-nil means use this function instead of default */
44fa5b1e 81Lisp_Object Vpop_up_frame_function;
7ab12479
JB
82
83/* Function to call to handle Fdisplay_buffer. */
84Lisp_Object Vdisplay_buffer_function;
85
a90712c2
RS
86/* List of buffer *names* for buffers that should have their own frames. */
87Lisp_Object Vspecial_display_buffer_names;
88
89/* List of regexps for buffer names that should have their own frames. */
90Lisp_Object Vspecial_display_regexps;
91
92/* Function to pop up a special frame. */
93Lisp_Object Vspecial_display_function;
94
855d8627
RS
95/* List of buffer *names* for buffers to appear in selected window. */
96Lisp_Object Vsame_window_buffer_names;
97
98/* List of regexps for buffer names to appear in selected window. */
99Lisp_Object Vsame_window_regexps;
100
a58ec57d
RS
101/* Hook run at end of temp_output_buffer_show. */
102Lisp_Object Qtemp_buffer_show_hook;
103
37962e60 104/* Fdisplay_buffer always splits the largest window
7ab12479
JB
105 if that window is more than this high. */
106int split_height_threshold;
107
108/* Number of lines of continuity in scrolling by screenfuls. */
109int next_screen_context_lines;
110
111/* Incremented for each window created. */
112static int sequence_number;
113
5b03d3c0
RS
114/* Nonzero after init_window_once has finished. */
115static int window_initialized;
116
543f5fb1
RS
117/* Hook to run when window config changes. */
118Lisp_Object Qwindow_configuration_change_hook;
119Lisp_Object Vwindow_configuration_change_hook;
120
9317a85d
RS
121/* Nonzero means scroll commands try to put point
122 at the same screen height as previously. */
123static int scroll_preserve_screen_position;
124
91a78190 125/* Nonzero means we can split a frame even if it is "unsplittable". */
eddd51c2 126static int inhibit_frame_unsplittable;
7d601aaa 127
7ab12479 128#define min(a, b) ((a) < (b) ? (a) : (b))
dba06815 129
9317a85d
RS
130extern int scroll_margin;
131
dba06815 132extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
7ab12479
JB
133\f
134DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
413430c5
EN
135 "Returns t if OBJECT is a window.")
136 (object)
137 Lisp_Object object;
7ab12479 138{
413430c5 139 return WINDOWP (object) ? Qt : Qnil;
7ab12479
JB
140}
141
806b4d9b 142DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
413430c5
EN
143 "Returns t if OBJECT is a window which is currently visible.")
144 (object)
145 Lisp_Object object;
605be8af 146{
413430c5 147 return (WINDOWP (object) && ! NILP (XWINDOW (object)->buffer) ? Qt : Qnil);
605be8af
JB
148}
149
7ab12479
JB
150Lisp_Object
151make_window ()
152{
cffec418 153 Lisp_Object val;
7ab12479 154 register struct window *p;
cffec418
KH
155 register struct Lisp_Vector *vec;
156 int i;
157
158 vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
159 for (i = 0; i < VECSIZE (struct window); i++)
160 vec->contents[i] = Qnil;
161 vec->size = VECSIZE (struct window);
162 p = (struct window *)vec;
d834a2e9
KH
163 XSETFASTINT (p->sequence_number, ++sequence_number);
164 XSETFASTINT (p->left, 0);
165 XSETFASTINT (p->top, 0);
166 XSETFASTINT (p->height, 0);
167 XSETFASTINT (p->width, 0);
168 XSETFASTINT (p->hscroll, 0);
9d1ec831 169 XSETFASTINT (p->last_point, 0);
d834a2e9
KH
170 XSETFASTINT (p->last_point_x, 0);
171 XSETFASTINT (p->last_point_y, 0);
7ab12479
JB
172 p->start = Fmake_marker ();
173 p->pointm = Fmake_marker ();
d834a2e9 174 XSETFASTINT (p->use_time, 0);
44fa5b1e 175 p->frame = Qnil;
7ab12479
JB
176 p->display_table = Qnil;
177 p->dedicated = Qnil;
cffec418 178 XSETWINDOW (val, p);
7ab12479
JB
179 return val;
180}
181
182DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
183 "Return the window that the cursor now appears in and commands apply to.")
184 ()
185{
186 return selected_window;
187}
188
83762ba4
JB
189DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
190 "Return the window used now for minibuffers.\n\
191If the optional argument FRAME is specified, return the minibuffer window\n\
192used by that frame.")
193 (frame)
194 Lisp_Object frame;
7ab12479 195{
83762ba4 196 if (NILP (frame))
74112613 197 XSETFRAME (frame, selected_frame);
83762ba4
JB
198 else
199 CHECK_LIVE_FRAME (frame, 0);
83762ba4
JB
200
201 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
7ab12479
JB
202}
203
605be8af 204DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
7ab12479
JB
205 "Returns non-nil if WINDOW is a minibuffer window.")
206 (window)
207 Lisp_Object window;
208{
209 struct window *w = decode_window (window);
210 return (MINI_WINDOW_P (w) ? Qt : Qnil);
211}
212
213DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
214 Spos_visible_in_window_p, 0, 2, 0,
44fa5b1e 215 "Return t if position POS is currently on the frame in WINDOW.\n\
7ab12479
JB
216Returns nil if that position is scrolled vertically out of view.\n\
217POS defaults to point; WINDOW, to the selected window.")
218 (pos, window)
219 Lisp_Object pos, window;
220{
221 register struct window *w;
222 register int top;
223 register int height;
224 register int posint;
225 register struct buffer *buf;
226 struct position posval;
afdb2485 227 int hscroll;
7ab12479 228
265a9e55 229 if (NILP (pos))
5ce7b543 230 posint = PT;
7ab12479
JB
231 else
232 {
233 CHECK_NUMBER_COERCE_MARKER (pos, 0);
234 posint = XINT (pos);
235 }
236
605be8af 237 w = decode_window (window);
7ab12479 238 top = marker_position (w->start);
afdb2485 239 hscroll = XINT (w->hscroll);
7ab12479
JB
240
241 if (posint < top)
242 return Qnil;
243
244 height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
245
246 buf = XBUFFER (w->buffer);
3cd21523
RS
247 if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
248 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf))
7ab12479 249 {
44fa5b1e 250 /* If frame is up to date,
7ab12479
JB
251 use the info recorded about how much text fit on it. */
252 if (posint < BUF_Z (buf) - XFASTINT (w->window_end_pos)
253 || (XFASTINT (w->window_end_vpos) < height))
254 return Qt;
255 return Qnil;
256 }
257 else
258 {
33eb4ede 259 if (posint > BUF_ZV (buf))
7ab12479
JB
260 return Qnil;
261
61b5322b
RS
262 /* w->start can be out of range. If it is, do something reasonable. */
263 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf))
264 return Qnil;
265
7ab12479 266 /* If that info is not correct, calculate afresh */
5a255667
KH
267 /* BUG FIX for the 7th arg (TOHPOS).
268
269 '0' is harmless, however, ' - (1 << (BITS_PER_SHORT - 1))' is
270 more appropriate here. In case of HSCROLL > 0, this can avoid
271 needless calculation done until (HPOS == 0).
272
273 We want to determine if the position POSINT is in HEIGHT or
274 not. We don't have to do calculation until (HPOS == 0). We
275 can stop it when VPOS goes beyond HEIGHT. */
4efffd80 276 posval = *compute_motion (top, 0, (hscroll ? 1 - hscroll : 0), 0,
5a255667 277 posint, height, - (1 << (BITS_PER_SHORT - 1)),
535e0b8e 278 window_internal_width (w) - 1,
e37f06d7 279 hscroll, 0, w);
7ab12479
JB
280
281 return posval.vpos < height ? Qt : Qnil;
282 }
283}
284\f
285static struct window *
286decode_window (window)
287 register Lisp_Object window;
288{
265a9e55 289 if (NILP (window))
7ab12479
JB
290 return XWINDOW (selected_window);
291
605be8af 292 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
293 return XWINDOW (window);
294}
295
296DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
297 "Return the buffer that WINDOW is displaying.")
298 (window)
299 Lisp_Object window;
300{
301 return decode_window (window)->buffer;
302}
303
304DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
305 "Return the number of lines in WINDOW (including its mode line).")
306 (window)
307 Lisp_Object window;
308{
309 return decode_window (window)->height;
310}
311
312DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
3b5908ef
RS
313 "Return the number of display columns in WINDOW.\n\
314This is the width that is usable columns available for text in WINDOW.\n\
315If you want to find out how many columns WINDOW takes up,\n\
316use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
7ab12479
JB
317 (window)
318 Lisp_Object window;
319{
ee61d94e 320 return make_number (window_internal_width (decode_window (window)));
7ab12479
JB
321}
322
323DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
324 "Return the number of columns by which WINDOW is scrolled from left margin.")
325 (window)
326 Lisp_Object window;
327{
328 return decode_window (window)->hscroll;
329}
330
331DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
332 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
333NCOL should be zero or positive.")
334 (window, ncol)
335 register Lisp_Object window, ncol;
336{
337 register struct window *w;
338
339 CHECK_NUMBER (ncol, 1);
d834a2e9 340 if (XINT (ncol) < 0) XSETFASTINT (ncol, 0);
7ab12479 341 w = decode_window (window);
7f4161e0 342 if (XINT (w->hscroll) != XINT (ncol))
1479ef51 343 XBUFFER (w->buffer)->clip_changed = 1; /* Prevent redisplay shortcuts */
7ab12479
JB
344 w->hscroll = ncol;
345 return ncol;
346}
347
190eb263
RS
348DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
349 Swindow_redisplay_end_trigger, 0, 1, 0,
350 "Return WINDOW's redisplay end trigger value.\n\
351See `set-window-redisplay-end-trigger' for more information.")
352 (window)
353 Lisp_Object window;
354{
355 return decode_window (window)->redisplay_end_trigger;
356}
357
358DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
359 Sset_window_redisplay_end_trigger, 2, 2, 0,
360 "Set WINDOW's redisplay end trigger value to VALUE.\n\
361VALUE should be a buffer position (typically a marker) or nil.\n\
76854cf2
RS
362If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
363beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
364with two arguments: WINDOW, and the end trigger value.\n\
365Afterwards the end-trigger value is reset to nil.")
190eb263
RS
366 (window, value)
367 register Lisp_Object window, value;
368{
369 register struct window *w;
370
371 w = decode_window (window);
372 w->redisplay_end_trigger = value;
373 return value;
374}
375
7ab12479
JB
376DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
377 "Return a list of the edge coordinates of WINDOW.\n\
44fa5b1e 378\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
7ab12479
JB
379RIGHT is one more than the rightmost column used by WINDOW,\n\
380and BOTTOM is one more than the bottommost row used by WINDOW\n\
381 and its mode-line.")
382 (window)
383 Lisp_Object window;
384{
385 register struct window *w = decode_window (window);
386
387 return Fcons (w->left, Fcons (w->top,
111e5992 388 Fcons (make_number (WINDOW_RIGHT_EDGE (w)),
7ab12479
JB
389 Fcons (make_number (XFASTINT (w->top)
390 + XFASTINT (w->height)),
391 Qnil))));
392}
393
d5783c40
JB
394/* Test if the character at column *x, row *y is within window *w.
395 If it is not, return 0;
396 if it is in the window's text area,
397 set *x and *y to its location relative to the upper left corner
398 of the window, and
399 return 1;
400 if it is on the window's modeline, return 2;
401 if it is on the border between the window and its right sibling,
402 return 3. */
403static int
404coordinates_in_window (w, x, y)
405 register struct window *w;
406 register int *x, *y;
407{
408 register int left = XINT (w->left);
111e5992
RS
409 register int right_edge = WINDOW_RIGHT_EDGE (w);
410 register int left_margin = WINDOW_LEFT_MARGIN (w);
411 register int right_margin = WINDOW_RIGHT_MARGIN (w);
d5783c40
JB
412 register int window_height = XINT (w->height);
413 register int top = XFASTINT (w->top);
111e5992
RS
414
415 if ( *x < left || *x >= right_edge
d5783c40
JB
416 || *y < top || *y >= top + window_height)
417 return 0;
418
111e5992
RS
419 if (left_margin != left && *x < left_margin && *x >= left)
420 return 3;
421
422 if (right_margin != right_edge && *x >= right_margin && *x < right_edge)
423 return 3;
424
d5783c40
JB
425 /* Is the character is the mode line? */
426 if (*y == top + window_height - 1
05c2896a 427 && ! MINI_WINDOW_P (w))
d5783c40 428 return 2;
37962e60 429
111e5992 430 *x -= WINDOW_LEFT_MARGIN (w);
d5783c40
JB
431 *y -= top;
432 return 1;
433}
434
435DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
436 Scoordinates_in_window_p, 2, 2, 0,
437 "Return non-nil if COORDINATES are in WINDOW.\n\
1113d9db 438COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
44fa5b1e 439measured in characters from the upper-left corner of the frame.\n\
1113d9db 440(0 . 0) denotes the character in the upper left corner of the\n\
44fa5b1e 441frame.\n\
d5783c40
JB
442If COORDINATES are in the text portion of WINDOW,\n\
443 the coordinates relative to the window are returned.\n\
e5d77022 444If they are in the mode line of WINDOW, `mode-line' is returned.\n\
d5783c40 445If they are on the border between WINDOW and its right sibling,\n\
e5d77022 446 `vertical-line' is returned.")
d5783c40
JB
447 (coordinates, window)
448 register Lisp_Object coordinates, window;
449{
450 int x, y;
451
605be8af 452 CHECK_LIVE_WINDOW (window, 0);
d5783c40
JB
453 CHECK_CONS (coordinates, 1);
454 x = XINT (Fcar (coordinates));
455 y = XINT (Fcdr (coordinates));
456
457 switch (coordinates_in_window (XWINDOW (window), &x, &y))
458 {
459 case 0: /* NOT in window at all. */
460 return Qnil;
461
462 case 1: /* In text part of window. */
34c0dab2 463 return Fcons (make_number (x), make_number (y));
d5783c40
JB
464
465 case 2: /* In mode line of window. */
466 return Qmode_line;
37962e60 467
d5783c40 468 case 3: /* On right border of window. */
e5d77022 469 return Qvertical_line;
d5783c40
JB
470
471 default:
472 abort ();
473 }
474}
475
7ab12479 476/* Find the window containing column x, row y, and return it as a
d5783c40
JB
477 Lisp_Object. If x, y is on the window's modeline, set *part
478 to 1; if it is on the separating line between the window and its
479 right sibling, set it to 2; otherwise set it to 0. If there is no
480 window under x, y return nil and leave *part unmodified. */
7ab12479 481Lisp_Object
44fa5b1e
JB
482window_from_coordinates (frame, x, y, part)
483 FRAME_PTR frame;
7ab12479 484 int x, y;
d5783c40 485 int *part;
7ab12479
JB
486{
487 register Lisp_Object tem, first;
488
44fa5b1e 489 tem = first = FRAME_SELECTED_WINDOW (frame);
7ab12479 490
d5783c40 491 do
7ab12479
JB
492 {
493 int found = coordinates_in_window (XWINDOW (tem), &x, &y);
494
495 if (found)
496 {
d5783c40 497 *part = found - 1;
7ab12479
JB
498 return tem;
499 }
500
d5783c40 501 tem = Fnext_window (tem, Qt, Qlambda);
7ab12479 502 }
d5783c40 503 while (! EQ (tem, first));
37962e60 504
d5783c40 505 return Qnil;
7ab12479
JB
506}
507
ab17c3f2 508DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
b0c33a94 509 "Return window containing coordinates X and Y on FRAME.\n\
44fa5b1e
JB
510If omitted, FRAME defaults to the currently selected frame.\n\
511The top left corner of the frame is considered to be row 0,\n\
95605e15 512column 0.")
b0c33a94
RS
513 (x, y, frame)
514 Lisp_Object x, y, frame;
7ab12479
JB
515{
516 int part;
517
44fa5b1e 518 if (NILP (frame))
74112613 519 XSETFRAME (frame, selected_frame);
d5783c40 520 else
44fa5b1e 521 CHECK_LIVE_FRAME (frame, 2);
b0c33a94
RS
522 CHECK_NUMBER (x, 0);
523 CHECK_NUMBER (y, 1);
7ab12479 524
44fa5b1e 525 return window_from_coordinates (XFRAME (frame),
b0c33a94 526 XINT (x), XINT (y),
7ab12479
JB
527 &part);
528}
529
530DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
531 "Return current value of point in WINDOW.\n\
532For a nonselected window, this is the value point would have\n\
533if that window were selected.\n\
534\n\
535Note that, when WINDOW is the selected window and its buffer\n\
536is also currently selected, the value returned is the same as (point).\n\
537It would be more strictly correct to return the `top-level' value\n\
538of point, outside of any save-excursion forms.\n\
539But that is hard to define.")
540 (window)
541 Lisp_Object window;
542{
543 register struct window *w = decode_window (window);
544
545 if (w == XWINDOW (selected_window)
546 && current_buffer == XBUFFER (w->buffer))
547 return Fpoint ();
548 return Fmarker_position (w->pointm);
549}
550
551DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
0fea6c40
RS
552 "Return position at which display currently starts in WINDOW.\n\
553This is updated by redisplay or by calling `set-window-start'.")
7ab12479
JB
554 (window)
555 Lisp_Object window;
556{
557 return Fmarker_position (decode_window (window)->start);
558}
559
8646118f
RS
560/* This is text temporarily removed from the doc string below.
561
7250968e
RS
562This function returns nil if the position is not currently known.\n\
563That happens when redisplay is preempted and doesn't finish.\n\
564If in that case you want to compute where the end of the window would\n\
565have been if redisplay had finished, do this:\n\
566 (save-excursion\n\
567 (goto-char (window-start window))\n\
568 (vertical-motion (1- (window-height window)) window)\n\
8646118f
RS
569 (point))") */
570
478292ed 571DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
8646118f
RS
572 "Return position at which display currently ends in WINDOW.\n\
573This is updated by redisplay, when it runs to completion.\n\
574Simply changing the buffer text or setting `window-start'\n\
478292ed
RS
575does not update this value.\n\
576If UP-TO-DATE is non-nil, compute the up-to-date position\n\
577if it isn't already recorded.")
578 (window, update)
579 Lisp_Object window, update;
7ab12479
JB
580{
581 Lisp_Object value;
582 struct window *w = decode_window (window);
5a41ab94
RS
583 Lisp_Object buf;
584
585 buf = w->buffer;
586 CHECK_BUFFER (buf, 0);
587
8646118f 588#if 0 /* This change broke some things. We should make it later. */
7250968e
RS
589 /* If we don't know the end position, return nil.
590 The user can compute it with vertical-motion if he wants to.
591 It would be nicer to do it automatically,
592 but that's so slow that it would probably bother people. */
593 if (NILP (w->window_end_valid))
594 return Qnil;
8646118f 595#endif
7250968e 596
478292ed
RS
597 if (! NILP (update)
598 && ! (! NILP (w->window_end_valid)
599 && XFASTINT (w->last_modified) >= MODIFF))
600 {
601 int opoint = PT, opoint_byte = PT_BYTE;
602 TEMP_SET_PT_BOTH (XMARKER (w->start)->charpos,
603 XMARKER (w->start)->bytepos);
604 Fvertical_motion (make_number (window_internal_height (w)), Qnil);
605 XSETINT (value, PT);
606 TEMP_SET_PT_BOTH (opoint, opoint_byte);
607 }
608 else
609 XSETINT (value,
610 BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
7ab12479
JB
611
612 return value;
613}
614
615DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
616 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
617 (window, pos)
618 Lisp_Object window, pos;
619{
620 register struct window *w = decode_window (window);
621
622 CHECK_NUMBER_COERCE_MARKER (pos, 1);
623 if (w == XWINDOW (selected_window))
624 Fgoto_char (pos);
625 else
626 set_marker_restricted (w->pointm, pos, w->buffer);
627
628 return pos;
629}
630
631DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
632 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
633Optional third arg NOFORCE non-nil inhibits next redisplay\n\
634from overriding motion of point in order to display at this exact start.")
635 (window, pos, noforce)
636 Lisp_Object window, pos, noforce;
637{
638 register struct window *w = decode_window (window);
639
640 CHECK_NUMBER_COERCE_MARKER (pos, 1);
641 set_marker_restricted (w->start, pos, w->buffer);
642 /* this is not right, but much easier than doing what is right. */
643 w->start_at_line_beg = Qnil;
265a9e55 644 if (NILP (noforce))
7ab12479
JB
645 w->force_start = Qt;
646 w->update_mode_line = Qt;
d834a2e9 647 XSETFASTINT (w->last_modified, 0);
3cd21523 648 XSETFASTINT (w->last_overlay_modified, 0);
62c07cc7
JB
649 if (!EQ (window, selected_window))
650 windows_or_buffers_changed++;
7ab12479
JB
651 return pos;
652}
653
654DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
655 1, 1, 0,
656 "Return WINDOW's dedicated object, usually t or nil.\n\
1f18c48f 657See also `set-window-dedicated-p'.")
7ab12479
JB
658 (window)
659 Lisp_Object window;
660{
661 return decode_window (window)->dedicated;
662}
663
d207b766
RS
664DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
665 Sset_window_dedicated_p, 2, 2, 0,
666 "Control whether WINDOW is dedicated to the buffer it displays.\n\
667If it is dedicated, Emacs will not automatically change\n\
668which buffer appears in it.\n\
669The second argument is the new value for the dedication flag;\n\
670non-nil means yes.")
7ab12479
JB
671 (window, arg)
672 Lisp_Object window, arg;
673{
674 register struct window *w = decode_window (window);
675
265a9e55 676 if (NILP (arg))
7ab12479
JB
677 w->dedicated = Qnil;
678 else
d207b766 679 w->dedicated = Qt;
7ab12479
JB
680
681 return w->dedicated;
682}
683
684DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
685 0, 1, 0,
686 "Return the display-table that WINDOW is using.")
687 (window)
688 Lisp_Object window;
689{
690 return decode_window (window)->display_table;
691}
692
693/* Get the display table for use currently on window W.
694 This is either W's display table or W's buffer's display table.
695 Ignore the specified tables if they are not valid;
696 if no valid table is specified, return 0. */
697
319315f1 698struct Lisp_Char_Table *
7ab12479
JB
699window_display_table (w)
700 struct window *w;
701{
702 Lisp_Object tem;
703 tem = w->display_table;
319315f1
RS
704 if (DISP_TABLE_P (tem))
705 return XCHAR_TABLE (tem);
171d003c
RS
706 if (NILP (w->buffer))
707 return 0;
708
7ab12479 709 tem = XBUFFER (w->buffer)->display_table;
319315f1
RS
710 if (DISP_TABLE_P (tem))
711 return XCHAR_TABLE (tem);
7ab12479 712 tem = Vstandard_display_table;
319315f1
RS
713 if (DISP_TABLE_P (tem))
714 return XCHAR_TABLE (tem);
7ab12479
JB
715 return 0;
716}
717
3a2712f9 718DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
7ab12479
JB
719 "Set WINDOW's display-table to TABLE.")
720 (window, table)
721 register Lisp_Object window, table;
722{
723 register struct window *w;
724 register Lisp_Object z; /* Return value. */
725
726 w = decode_window (window);
727 w->display_table = table;
728 return table;
729}
730\f
731/* Record info on buffer window w is displaying
732 when it is about to cease to display that buffer. */
dfcf069d 733static void
7ab12479
JB
734unshow_buffer (w)
735 register struct window *w;
736{
12cae7c0 737 Lisp_Object buf;
b73ea88e 738 struct buffer *b;
7ab12479 739
12cae7c0 740 buf = w->buffer;
b73ea88e
RS
741 b = XBUFFER (buf);
742 if (b != XMARKER (w->pointm)->buffer)
7ab12479
JB
743 abort ();
744
b73ea88e
RS
745 if (w == XWINDOW (b->last_selected_window))
746 b->last_selected_window = Qnil;
86e48436 747
573f41ab 748#if 0
7ab12479
JB
749 if (w == XWINDOW (selected_window)
750 || ! EQ (buf, XWINDOW (selected_window)->buffer))
751 /* Do this except when the selected window's buffer
752 is being removed from some other window. */
573f41ab
RS
753#endif
754 /* last_window_start records the start position that this buffer
755 had in the last window to be disconnected from it.
756 Now that this statement is unconditional,
757 it is possible for the buffer to be displayed in the
758 selected window, while last_window_start reflects another
759 window which was recently showing the same buffer.
760 Some people might say that might be a good thing. Let's see. */
b73ea88e 761 b->last_window_start = marker_position (w->start);
7ab12479
JB
762
763 /* Point in the selected window's buffer
764 is actually stored in that buffer, and the window's pointm isn't used.
765 So don't clobber point in that buffer. */
766 if (! EQ (buf, XWINDOW (selected_window)->buffer))
b73ea88e
RS
767 temp_set_point_both (b,
768 clip_to_bounds (BUF_BEGV (b),
769 XMARKER (w->pointm)->charpos,
770 BUF_ZV (b)),
771 clip_to_bounds (BUF_BEGV_BYTE (b),
772 marker_byte_position (w->pointm),
773 BUF_ZV_BYTE (b)));
7ab12479
JB
774}
775
776/* Put replacement into the window structure in place of old. */
dfcf069d 777static void
7ab12479
JB
778replace_window (old, replacement)
779 Lisp_Object old, replacement;
780{
781 register Lisp_Object tem;
782 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
783
44fa5b1e
JB
784 /* If OLD is its frame's root_window, then replacement is the new
785 root_window for that frame. */
7ab12479 786
7f4161e0 787 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
44fa5b1e 788 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
7ab12479
JB
789
790 p->left = o->left;
791 p->top = o->top;
792 p->width = o->width;
793 p->height = o->height;
794
795 p->next = tem = o->next;
265a9e55 796 if (!NILP (tem))
7ab12479
JB
797 XWINDOW (tem)->prev = replacement;
798
799 p->prev = tem = o->prev;
265a9e55 800 if (!NILP (tem))
7ab12479
JB
801 XWINDOW (tem)->next = replacement;
802
803 p->parent = tem = o->parent;
265a9e55 804 if (!NILP (tem))
7ab12479
JB
805 {
806 if (EQ (XWINDOW (tem)->vchild, old))
807 XWINDOW (tem)->vchild = replacement;
808 if (EQ (XWINDOW (tem)->hchild, old))
809 XWINDOW (tem)->hchild = replacement;
810 }
811
812/*** Here, if replacement is a vertical combination
813and so is its new parent, we should make replacement's
814children be children of that parent instead. ***/
815}
816
817DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
818 "Remove WINDOW from the display. Default is selected window.")
819 (window)
820 register Lisp_Object window;
543f5fb1
RS
821{
822 delete_window (window);
823
824 if (! NILP (Vwindow_configuration_change_hook)
825 && ! NILP (Vrun_hooks))
826 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
827
828 return Qnil;
829}
830
5e14b1fc 831void
543f5fb1
RS
832delete_window (window)
833 register Lisp_Object window;
7ab12479
JB
834{
835 register Lisp_Object tem, parent, sib;
836 register struct window *p;
837 register struct window *par;
838
605be8af
JB
839 /* Because this function is called by other C code on non-leaf
840 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
841 so we can't decode_window here. */
265a9e55 842 if (NILP (window))
7ab12479
JB
843 window = selected_window;
844 else
845 CHECK_WINDOW (window, 0);
7ab12479 846 p = XWINDOW (window);
605be8af
JB
847
848 /* It's okay to delete an already-deleted window. */
849 if (NILP (p->buffer)
850 && NILP (p->hchild)
851 && NILP (p->vchild))
296b535c 852 return;
605be8af 853
7ab12479 854 parent = p->parent;
265a9e55 855 if (NILP (parent))
7ab12479
JB
856 error ("Attempt to delete minibuffer or sole ordinary window");
857 par = XWINDOW (parent);
858
859 windows_or_buffers_changed++;
29aeee73 860 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (p))) = 1;
7ab12479 861
605be8af
JB
862 /* Are we trying to delete any frame's selected window? */
863 {
0def0403 864 Lisp_Object frame, pwindow;
605be8af 865
0def0403
RS
866 /* See if the frame's selected window is either WINDOW
867 or any subwindow of it, by finding all that window's parents
868 and comparing each one with WINDOW. */
869 frame = WINDOW_FRAME (XWINDOW (window));
870 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
871
872 while (!NILP (pwindow))
873 {
874 if (EQ (window, pwindow))
875 break;
876 pwindow = XWINDOW (pwindow)->parent;
877 }
878
879 if (EQ (window, pwindow))
605be8af 880 {
89bca612
RS
881 Lisp_Object alternative;
882 alternative = Fnext_window (window, Qlambda, Qnil);
605be8af
JB
883
884 /* If we're about to delete the selected window on the
885 selected frame, then we should use Fselect_window to select
886 the new window. On the other hand, if we're about to
887 delete the selected window on any other frame, we shouldn't do
888 anything but set the frame's selected_window slot. */
889 if (EQ (window, selected_window))
890 Fselect_window (alternative);
891 else
0def0403 892 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
605be8af
JB
893 }
894 }
7ab12479
JB
895
896 tem = p->buffer;
897 /* tem is null for dummy parent windows
898 (which have inferiors but not any contents themselves) */
265a9e55 899 if (!NILP (tem))
7ab12479
JB
900 {
901 unshow_buffer (p);
902 unchain_marker (p->pointm);
903 unchain_marker (p->start);
7ab12479
JB
904 }
905
906 tem = p->next;
265a9e55 907 if (!NILP (tem))
7ab12479
JB
908 XWINDOW (tem)->prev = p->prev;
909
910 tem = p->prev;
265a9e55 911 if (!NILP (tem))
7ab12479
JB
912 XWINDOW (tem)->next = p->next;
913
914 if (EQ (window, par->hchild))
915 par->hchild = p->next;
916 if (EQ (window, par->vchild))
917 par->vchild = p->next;
918
919 /* Find one of our siblings to give our space to. */
920 sib = p->prev;
265a9e55 921 if (NILP (sib))
7ab12479
JB
922 {
923 /* If p gives its space to its next sibling, that sibling needs
924 to have its top/left side pulled back to where p's is.
925 set_window_{height,width} will re-position the sibling's
926 children. */
927 sib = p->next;
7f4161e0
JB
928 XWINDOW (sib)->top = p->top;
929 XWINDOW (sib)->left = p->left;
7ab12479
JB
930 }
931
932 /* Stretch that sibling. */
265a9e55 933 if (!NILP (par->vchild))
7ab12479
JB
934 set_window_height (sib,
935 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
936 1);
265a9e55 937 if (!NILP (par->hchild))
7ab12479
JB
938 set_window_width (sib,
939 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
940 1);
941
942 /* If parent now has only one child,
943 put the child into the parent's place. */
7ab12479 944 tem = par->hchild;
265a9e55 945 if (NILP (tem))
7ab12479 946 tem = par->vchild;
265a9e55 947 if (NILP (XWINDOW (tem)->next))
7ab12479 948 replace_window (parent, tem);
605be8af
JB
949
950 /* Since we may be deleting combination windows, we must make sure that
951 not only p but all its children have been marked as deleted. */
952 if (! NILP (p->hchild))
953 delete_all_subwindows (XWINDOW (p->hchild));
954 else if (! NILP (p->vchild))
955 delete_all_subwindows (XWINDOW (p->vchild));
956
957 /* Mark this window as deleted. */
958 p->buffer = p->hchild = p->vchild = Qnil;
7ab12479
JB
959}
960\f
7ab12479 961
44fa5b1e 962extern Lisp_Object next_frame (), prev_frame ();
7ab12479 963
26f6279d
JB
964/* This comment supplies the doc string for `next-window',
965 for make-docfile to see. We cannot put this in the real DEFUN
966 due to limits in the Unix cpp.
967
968DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
7ab12479 969 "Return next window after WINDOW in canonical ordering of windows.\n\
d5783c40
JB
970If omitted, WINDOW defaults to the selected window.\n\
971\n\
972Optional second arg MINIBUF t means count the minibuffer window even\n\
973if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
974it is active. MINIBUF neither t nor nil means not to count the\n\
975minibuffer even if it is active.\n\
976\n\
44fa5b1e
JB
977Several frames may share a single minibuffer; if the minibuffer\n\
978counts, all windows on all frames that share that minibuffer count\n\
ed160f1f 979too. Therefore, `next-window' can be used to iterate through the\n\
44fa5b1e
JB
980set of windows even when the minibuffer is on another frame. If the\n\
981minibuffer does not count, only windows from WINDOW's frame count.\n\
d5783c40 982\n\
44fa5b1e
JB
983Optional third arg ALL-FRAMES t means include windows on all frames.\n\
984ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
89bca612 985above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
f812f9c6 986ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1f4c5d09 987If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
89bca612 988Anything else means restrict to WINDOW's frame.\n\
dbc4e1c1
JB
989\n\
990If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
991`next-window' to iterate through the entire cycle of acceptable\n\
992windows, eventually ending up back at the window you started with.\n\
993`previous-window' traverses the same cycle, in the reverse order.")
26f6279d
JB
994 (window, minibuf, all_frames) */
995
996DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
997 0)
44fa5b1e
JB
998 (window, minibuf, all_frames)
999 register Lisp_Object window, minibuf, all_frames;
7ab12479
JB
1000{
1001 register Lisp_Object tem;
d5783c40 1002 Lisp_Object start_window;
7ab12479 1003
265a9e55 1004 if (NILP (window))
7ab12479
JB
1005 window = selected_window;
1006 else
605be8af 1007 CHECK_LIVE_WINDOW (window, 0);
7ab12479 1008
d5783c40
JB
1009 start_window = window;
1010
1011 /* minibuf == nil may or may not include minibuffers.
1012 Decide if it does. */
265a9e55 1013 if (NILP (minibuf))
fbdc1545
RS
1014 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1015 else if (! EQ (minibuf, Qt))
1016 minibuf = Qlambda;
1017 /* Now minibuf can be t => count all minibuffer windows,
1018 lambda => count none of them,
1019 or a specific minibuffer window (the active one) to count. */
d5783c40 1020
1bb80f72 1021 /* all_frames == nil doesn't specify which frames to include. */
44fa5b1e 1022 if (NILP (all_frames))
fbdc1545 1023 all_frames = (! EQ (minibuf, Qlambda)
1bb80f72
RS
1024 ? (FRAME_MINIBUF_WINDOW
1025 (XFRAME
1026 (WINDOW_FRAME
1027 (XWINDOW (window)))))
1028 : Qnil);
89bca612
RS
1029 else if (EQ (all_frames, Qvisible))
1030 ;
f812f9c6
RS
1031 else if (XFASTINT (all_frames) == 0)
1032 ;
1f4c5d09
RS
1033 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1034 /* If all_frames is a frame and window arg isn't on that frame, just
1035 return the first window on the frame. */
1036 return Fframe_first_window (all_frames);
44fa5b1e
JB
1037 else if (! EQ (all_frames, Qt))
1038 all_frames = Qnil;
644b477c
RS
1039 /* Now all_frames is t meaning search all frames,
1040 nil meaning search just current frame,
f812f9c6
RS
1041 visible meaning search just visible frames,
1042 0 meaning search visible and iconified frames,
644b477c 1043 or a window, meaning search the frame that window belongs to. */
7ab12479
JB
1044
1045 /* Do this loop at least once, to get the next window, and perhaps
1046 again, if we hit the minibuffer and that is not acceptable. */
1047 do
1048 {
1049 /* Find a window that actually has a next one. This loop
1050 climbs up the tree. */
265a9e55
JB
1051 while (tem = XWINDOW (window)->next, NILP (tem))
1052 if (tem = XWINDOW (window)->parent, !NILP (tem))
7ab12479 1053 window = tem;
d5783c40 1054 else
7ab12479 1055 {
44fa5b1e
JB
1056 /* We've reached the end of this frame.
1057 Which other frames are acceptable? */
1058 tem = WINDOW_FRAME (XWINDOW (window));
44fa5b1e 1059 if (! NILP (all_frames))
1bb80f72
RS
1060 {
1061 Lisp_Object tem1;
1062
1063 tem1 = tem;
1064 tem = next_frame (tem, all_frames);
1065 /* In the case where the minibuffer is active,
1066 and we include its frame as well as the selected one,
1067 next_frame may get stuck in that frame.
1068 If that happens, go back to the selected frame
1069 so we can complete the cycle. */
1070 if (EQ (tem, tem1))
74112613 1071 XSETFRAME (tem, selected_frame);
1bb80f72 1072 }
44fa5b1e 1073 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
d5783c40 1074
7ab12479
JB
1075 break;
1076 }
1077
1078 window = tem;
d5783c40 1079
7ab12479
JB
1080 /* If we're in a combination window, find its first child and
1081 recurse on that. Otherwise, we've found the window we want. */
1082 while (1)
1083 {
265a9e55 1084 if (!NILP (XWINDOW (window)->hchild))
7ab12479 1085 window = XWINDOW (window)->hchild;
265a9e55 1086 else if (!NILP (XWINDOW (window)->vchild))
7ab12479
JB
1087 window = XWINDOW (window)->vchild;
1088 else break;
1089 }
1090 }
5c4d25a6 1091 /* Which windows are acceptable?
d5783c40 1092 Exit the loop and accept this window if
fbdc1545
RS
1093 this isn't a minibuffer window,
1094 or we're accepting all minibuffer windows,
1095 or this is the active minibuffer and we are accepting that one, or
d5783c40 1096 we've come all the way around and we're back at the original window. */
7ab12479 1097 while (MINI_WINDOW_P (XWINDOW (window))
d5783c40 1098 && ! EQ (minibuf, Qt)
fbdc1545 1099 && ! EQ (minibuf, window)
7f4161e0 1100 && ! EQ (window, start_window));
7ab12479
JB
1101
1102 return window;
1103}
1104
26f6279d
JB
1105/* This comment supplies the doc string for `previous-window',
1106 for make-docfile to see. We cannot put this in the real DEFUN
1107 due to limits in the Unix cpp.
1108
1109DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
5c4d25a6 1110 "Return the window preceding WINDOW in canonical ordering of windows.\n\
d5783c40
JB
1111If omitted, WINDOW defaults to the selected window.\n\
1112\n\
1113Optional second arg MINIBUF t means count the minibuffer window even\n\
1114if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1115it is active. MINIBUF neither t nor nil means not to count the\n\
1116minibuffer even if it is active.\n\
1117\n\
44fa5b1e
JB
1118Several frames may share a single minibuffer; if the minibuffer\n\
1119counts, all windows on all frames that share that minibuffer count\n\
ed160f1f 1120too. Therefore, `previous-window' can be used to iterate through\n\
44fa5b1e 1121the set of windows even when the minibuffer is on another frame. If\n\
ed160f1f 1122the minibuffer does not count, only windows from WINDOW's frame count\n\
d5783c40 1123\n\
44fa5b1e
JB
1124Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1125ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
89bca612 1126above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
f812f9c6 1127ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1f4c5d09 1128If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
89bca612 1129Anything else means restrict to WINDOW's frame.\n\
dbc4e1c1
JB
1130\n\
1131If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1132`previous-window' to iterate through the entire cycle of acceptable\n\
1133windows, eventually ending up back at the window you started with.\n\
1134`next-window' traverses the same cycle, in the reverse order.")
26f6279d
JB
1135 (window, minibuf, all_frames) */
1136
1137
1138DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1139 0)
44fa5b1e
JB
1140 (window, minibuf, all_frames)
1141 register Lisp_Object window, minibuf, all_frames;
7ab12479
JB
1142{
1143 register Lisp_Object tem;
d5783c40 1144 Lisp_Object start_window;
7ab12479 1145
265a9e55 1146 if (NILP (window))
7ab12479
JB
1147 window = selected_window;
1148 else
605be8af 1149 CHECK_LIVE_WINDOW (window, 0);
7ab12479 1150
d5783c40
JB
1151 start_window = window;
1152
1153 /* minibuf == nil may or may not include minibuffers.
1154 Decide if it does. */
265a9e55 1155 if (NILP (minibuf))
fbdc1545
RS
1156 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1157 else if (! EQ (minibuf, Qt))
1158 minibuf = Qlambda;
1159 /* Now minibuf can be t => count all minibuffer windows,
1160 lambda => count none of them,
1161 or a specific minibuffer window (the active one) to count. */
d5783c40 1162
44fa5b1e
JB
1163 /* all_frames == nil doesn't specify which frames to include.
1164 Decide which frames it includes. */
1165 if (NILP (all_frames))
fbdc1545 1166 all_frames = (! EQ (minibuf, Qlambda)
44fa5b1e
JB
1167 ? (FRAME_MINIBUF_WINDOW
1168 (XFRAME
1169 (WINDOW_FRAME
d5783c40
JB
1170 (XWINDOW (window)))))
1171 : Qnil);
89bca612
RS
1172 else if (EQ (all_frames, Qvisible))
1173 ;
f812f9c6
RS
1174 else if (XFASTINT (all_frames) == 0)
1175 ;
1f4c5d09
RS
1176 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1177 /* If all_frames is a frame and window arg isn't on that frame, just
1178 return the first window on the frame. */
1179 return Fframe_first_window (all_frames);
44fa5b1e
JB
1180 else if (! EQ (all_frames, Qt))
1181 all_frames = Qnil;
644b477c
RS
1182 /* Now all_frames is t meaning search all frames,
1183 nil meaning search just current frame,
f812f9c6
RS
1184 visible meaning search just visible frames,
1185 0 meaning search visible and iconified frames,
644b477c 1186 or a window, meaning search the frame that window belongs to. */
7ab12479
JB
1187
1188 /* Do this loop at least once, to get the previous window, and perhaps
1189 again, if we hit the minibuffer and that is not acceptable. */
1190 do
1191 {
1192 /* Find a window that actually has a previous one. This loop
1193 climbs up the tree. */
265a9e55
JB
1194 while (tem = XWINDOW (window)->prev, NILP (tem))
1195 if (tem = XWINDOW (window)->parent, !NILP (tem))
7ab12479 1196 window = tem;
d5783c40 1197 else
7ab12479 1198 {
44fa5b1e
JB
1199 /* We have found the top window on the frame.
1200 Which frames are acceptable? */
1201 tem = WINDOW_FRAME (XWINDOW (window));
44fa5b1e 1202 if (! NILP (all_frames))
dbc4e1c1
JB
1203 /* It's actually important that we use prev_frame here,
1204 rather than next_frame. All the windows acceptable
1205 according to the given parameters should form a ring;
1206 Fnext_window and Fprevious_window should go back and
1207 forth around the ring. If we use next_frame here,
1208 then Fnext_window and Fprevious_window take different
1209 paths through the set of acceptable windows.
1210 window_loop assumes that these `ring' requirement are
1211 met. */
1bb80f72
RS
1212 {
1213 Lisp_Object tem1;
1214
1215 tem1 = tem;
1216 tem = prev_frame (tem, all_frames);
1217 /* In the case where the minibuffer is active,
1218 and we include its frame as well as the selected one,
1219 next_frame may get stuck in that frame.
1220 If that happens, go back to the selected frame
1221 so we can complete the cycle. */
1222 if (EQ (tem, tem1))
74112613 1223 XSETFRAME (tem, selected_frame);
1bb80f72 1224 }
644b477c
RS
1225 /* If this frame has a minibuffer, find that window first,
1226 because it is conceptually the last window in that frame. */
5e12e32f
JB
1227 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
1228 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
1229 else
644b477c 1230 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
d5783c40 1231
7ab12479
JB
1232 break;
1233 }
1234
1235 window = tem;
1236 /* If we're in a combination window, find its last child and
1237 recurse on that. Otherwise, we've found the window we want. */
1238 while (1)
1239 {
265a9e55 1240 if (!NILP (XWINDOW (window)->hchild))
7ab12479 1241 window = XWINDOW (window)->hchild;
265a9e55 1242 else if (!NILP (XWINDOW (window)->vchild))
7ab12479
JB
1243 window = XWINDOW (window)->vchild;
1244 else break;
265a9e55 1245 while (tem = XWINDOW (window)->next, !NILP (tem))
7ab12479
JB
1246 window = tem;
1247 }
1248 }
5c4d25a6 1249 /* Which windows are acceptable?
d5783c40 1250 Exit the loop and accept this window if
fbdc1545
RS
1251 this isn't a minibuffer window,
1252 or we're accepting all minibuffer windows,
1253 or this is the active minibuffer and we are accepting that one, or
d5783c40 1254 we've come all the way around and we're back at the original window. */
7ab12479 1255 while (MINI_WINDOW_P (XWINDOW (window))
fbdc1545
RS
1256 && ! EQ (minibuf, Qt)
1257 && ! EQ (minibuf, window)
1258 && ! EQ (window, start_window));
7ab12479
JB
1259
1260 return window;
1261}
1262
62c07cc7 1263DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
44fa5b1e
JB
1264 "Select the ARG'th different window on this frame.\n\
1265All windows on current frame are arranged in a cyclic order.\n\
7ab12479
JB
1266This command selects the window ARG steps away in that order.\n\
1267A negative ARG moves in the opposite order. If the optional second\n\
44fa5b1e 1268argument ALL_FRAMES is non-nil, cycle through all frames.")
413430c5
EN
1269 (arg, all_frames)
1270 register Lisp_Object arg, all_frames;
7ab12479
JB
1271{
1272 register int i;
1273 register Lisp_Object w;
1274
413430c5 1275 CHECK_NUMBER (arg, 0);
7ab12479 1276 w = selected_window;
413430c5 1277 i = XINT (arg);
7ab12479
JB
1278
1279 while (i > 0)
1280 {
44fa5b1e 1281 w = Fnext_window (w, Qnil, all_frames);
7ab12479
JB
1282 i--;
1283 }
1284 while (i < 0)
1285 {
44fa5b1e 1286 w = Fprevious_window (w, Qnil, all_frames);
7ab12479
JB
1287 i++;
1288 }
1289 Fselect_window (w);
1290 return Qnil;
1291}
1292\f
1293/* Look at all windows, performing an operation specified by TYPE
1294 with argument OBJ.
75d8f668 1295 If FRAMES is Qt, look at all frames;
75d8f668 1296 Qnil, look at just the selected frame;
89bca612 1297 Qvisible, look at visible frames;
75d8f668 1298 a frame, just look at windows on that frame.
7ab12479
JB
1299 If MINI is non-zero, perform the operation on minibuffer windows too.
1300*/
1301
1302enum window_loop
1303{
1304 WINDOW_LOOP_UNUSED,
1305 GET_BUFFER_WINDOW, /* Arg is buffer */
1306 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1307 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1308 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1309 GET_LARGEST_WINDOW,
a68c0d3b 1310 UNSHOW_BUFFER /* Arg is buffer */
7ab12479
JB
1311};
1312
1313static Lisp_Object
44fa5b1e 1314window_loop (type, obj, mini, frames)
7ab12479 1315 enum window_loop type;
44fa5b1e 1316 register Lisp_Object obj, frames;
7ab12479
JB
1317 int mini;
1318{
1319 register Lisp_Object w;
1320 register Lisp_Object best_window;
1321 register Lisp_Object next_window;
4b206065 1322 register Lisp_Object last_window;
44fa5b1e 1323 FRAME_PTR frame;
89bca612
RS
1324 Lisp_Object frame_arg;
1325 frame_arg = Qt;
44fa5b1e
JB
1326
1327 /* If we're only looping through windows on a particular frame,
1328 frame points to that frame. If we're looping through windows
1329 on all frames, frame is 0. */
1330 if (FRAMEP (frames))
1331 frame = XFRAME (frames);
1332 else if (NILP (frames))
1333 frame = selected_frame;
7ab12479 1334 else
44fa5b1e 1335 frame = 0;
89bca612
RS
1336 if (frame)
1337 frame_arg = Qlambda;
f812f9c6
RS
1338 else if (XFASTINT (frames) == 0)
1339 frame_arg = frames;
89bca612
RS
1340 else if (EQ (frames, Qvisible))
1341 frame_arg = frames;
7ab12479 1342
89bca612
RS
1343 /* frame_arg is Qlambda to stick to one frame,
1344 Qvisible to consider all visible frames,
1345 or Qt otherwise. */
1346
7ab12479 1347 /* Pick a window to start with. */
017b2bad 1348 if (WINDOWP (obj))
4b206065 1349 w = obj;
44fa5b1e 1350 else if (frame)
4b206065 1351 w = FRAME_SELECTED_WINDOW (frame);
7ab12479 1352 else
4b206065
JB
1353 w = FRAME_SELECTED_WINDOW (selected_frame);
1354
1355 /* Figure out the last window we're going to mess with. Since
1356 Fnext_window, given the same options, is guaranteed to go in a
1357 ring, we can just use Fprevious_window to find the last one.
1358
1359 We can't just wait until we hit the first window again, because
1360 it might be deleted. */
1361
89bca612 1362 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
7ab12479 1363
7ab12479 1364 best_window = Qnil;
4b206065 1365 for (;;)
7ab12479 1366 {
75d8f668
JB
1367 FRAME_PTR w_frame = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1368
7ab12479
JB
1369 /* Pick the next window now, since some operations will delete
1370 the current window. */
89bca612 1371 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
7ab12479 1372
d29a5631
RS
1373 /* Note that we do not pay attention here to whether
1374 the frame is visible, since Fnext_window skips non-visible frames
1375 if that is desired, under the control of frame_arg. */
75d8f668 1376 if (! MINI_WINDOW_P (XWINDOW (w))
7ab12479
JB
1377 || (mini && minibuf_level > 0))
1378 switch (type)
1379 {
1380 case GET_BUFFER_WINDOW:
5c204627
RS
1381 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj)
1382 /* Don't find any minibuffer window
1383 except the one that is currently in use. */
1384 && (MINI_WINDOW_P (XWINDOW (w))
1385 ? EQ (w, minibuf_window) : 1))
7ab12479
JB
1386 return w;
1387 break;
1388
1389 case GET_LRU_WINDOW:
1390 /* t as arg means consider only full-width windows */
111e5992 1391 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (XWINDOW (w)))
7ab12479 1392 break;
7ab12479
JB
1393 /* Ignore dedicated windows and minibuffers. */
1394 if (MINI_WINDOW_P (XWINDOW (w))
265a9e55 1395 || !NILP (XWINDOW (w)->dedicated))
7ab12479 1396 break;
265a9e55 1397 if (NILP (best_window)
7ab12479
JB
1398 || (XFASTINT (XWINDOW (best_window)->use_time)
1399 > XFASTINT (XWINDOW (w)->use_time)))
1400 best_window = w;
1401 break;
1402
1403 case DELETE_OTHER_WINDOWS:
1404 if (XWINDOW (w) != XWINDOW (obj))
1405 Fdelete_window (w);
1406 break;
1407
1408 case DELETE_BUFFER_WINDOWS:
1409 if (EQ (XWINDOW (w)->buffer, obj))
1410 {
3548e138
RS
1411 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1412
1413 /* If this window is dedicated, and in a frame of its own,
1414 kill the frame. */
1415 if (EQ (w, FRAME_ROOT_WINDOW (f))
1416 && !NILP (XWINDOW (w)->dedicated)
1417 && other_visible_frames (f))
7ab12479 1418 {
3548e138
RS
1419 /* Skip the other windows on this frame.
1420 There might be one, the minibuffer! */
1421 if (! EQ (w, last_window))
1422 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1423 {
1424 /* As we go, check for the end of the loop.
1425 We mustn't start going around a second time. */
1426 if (EQ (next_window, last_window))
1427 {
1428 last_window = w;
1429 break;
1430 }
1431 next_window = Fnext_window (next_window,
1432 mini ? Qt : Qnil,
1433 frame_arg);
1434 }
1435 /* Now we can safely delete the frame. */
1436 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
7ab12479
JB
1437 }
1438 else
3548e138
RS
1439 /* If we're deleting the buffer displayed in the only window
1440 on the frame, find a new buffer to display there. */
1441 if (NILP (XWINDOW (w)->parent))
1442 {
1443 Lisp_Object new_buffer;
b7354ddf
RS
1444 new_buffer = Fother_buffer (obj, Qnil,
1445 XWINDOW (w)->frame);
3548e138
RS
1446 if (NILP (new_buffer))
1447 new_buffer
1448 = Fget_buffer_create (build_string ("*scratch*"));
1449 Fset_window_buffer (w, new_buffer);
1450 if (EQ (w, selected_window))
1451 Fset_buffer (XWINDOW (w)->buffer);
1452 }
1453 else
1454 Fdelete_window (w);
7ab12479
JB
1455 }
1456 break;
1457
1458 case GET_LARGEST_WINDOW:
7ab12479
JB
1459 /* Ignore dedicated windows and minibuffers. */
1460 if (MINI_WINDOW_P (XWINDOW (w))
265a9e55 1461 || !NILP (XWINDOW (w)->dedicated))
7ab12479
JB
1462 break;
1463 {
1464 struct window *best_window_ptr = XWINDOW (best_window);
1465 struct window *w_ptr = XWINDOW (w);
6b54027b
RS
1466 if (NILP (best_window)
1467 || (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width)
1468 > (XFASTINT (best_window_ptr->height)
1469 * XFASTINT (best_window_ptr->width))))
7ab12479
JB
1470 best_window = w;
1471 }
1472 break;
1473
1474 case UNSHOW_BUFFER:
1475 if (EQ (XWINDOW (w)->buffer, obj))
1476 {
1477 /* Find another buffer to show in this window. */
12cae7c0 1478 Lisp_Object another_buffer;
38ab08d1 1479 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
b7354ddf 1480 another_buffer = Fother_buffer (obj, Qnil, XWINDOW (w)->frame);
265a9e55 1481 if (NILP (another_buffer))
7ab12479
JB
1482 another_buffer
1483 = Fget_buffer_create (build_string ("*scratch*"));
38ab08d1
RS
1484 /* If this window is dedicated, and in a frame of its own,
1485 kill the frame. */
1486 if (EQ (w, FRAME_ROOT_WINDOW (f))
596122a7 1487 && !NILP (XWINDOW (w)->dedicated)
38ab08d1 1488 && other_visible_frames (f))
45945a7b
RS
1489 {
1490 /* Skip the other windows on this frame.
1491 There might be one, the minibuffer! */
1492 if (! EQ (w, last_window))
1493 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1494 {
1495 /* As we go, check for the end of the loop.
1496 We mustn't start going around a second time. */
1497 if (EQ (next_window, last_window))
1498 {
1499 last_window = w;
1500 break;
1501 }
1502 next_window = Fnext_window (next_window,
1503 mini ? Qt : Qnil,
1504 frame_arg);
1505 }
1506 /* Now we can safely delete the frame. */
1507 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
1508 }
38ab08d1 1509 else
38ab08d1
RS
1510 {
1511 /* Otherwise show a different buffer in the window. */
1512 XWINDOW (w)->dedicated = Qnil;
1513 Fset_window_buffer (w, another_buffer);
1514 if (EQ (w, selected_window))
1515 Fset_buffer (XWINDOW (w)->buffer);
1516 }
7ab12479
JB
1517 }
1518 break;
1519 }
4b206065
JB
1520
1521 if (EQ (w, last_window))
1522 break;
1523
7ab12479
JB
1524 w = next_window;
1525 }
7ab12479
JB
1526
1527 return best_window;
37962e60 1528}
605be8af 1529
7ab12479
JB
1530DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1531 "Return the window least recently selected or used for display.\n\
89bca612 1532If optional argument FRAME is `visible', search all visible frames.\n\
cee67da9 1533If FRAME is 0, search all visible and iconified frames.\n\
89bca612
RS
1534If FRAME is t, search all frames.\n\
1535If FRAME is nil, search only the selected frame.\n\
1536If FRAME is a frame, search only that frame.")
1537 (frame)
1538 Lisp_Object frame;
7ab12479
JB
1539{
1540 register Lisp_Object w;
1541 /* First try for a window that is full-width */
89bca612 1542 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
265a9e55 1543 if (!NILP (w) && !EQ (w, selected_window))
7ab12479
JB
1544 return w;
1545 /* If none of them, try the rest */
89bca612 1546 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
7ab12479
JB
1547}
1548
1549DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1550 "Return the largest window in area.\n\
89bca612 1551If optional argument FRAME is `visible', search all visible frames.\n\
cee67da9 1552If FRAME is 0, search all visible and iconified frames.\n\
89bca612
RS
1553If FRAME is t, search all frames.\n\
1554If FRAME is nil, search only the selected frame.\n\
1555If FRAME is a frame, search only that frame.")
44fa5b1e
JB
1556 (frame)
1557 Lisp_Object frame;
7ab12479
JB
1558{
1559 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
44fa5b1e 1560 frame);
7ab12479
JB
1561}
1562
1563DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1564 "Return a window currently displaying BUFFER, or nil if none.\n\
89bca612 1565If optional argument FRAME is `visible', search all visible frames.\n\
f812f9c6 1566If optional argument FRAME is 0, search all visible and iconified frames.\n\
89bca612 1567If FRAME is t, search all frames.\n\
1bc981d2 1568If FRAME is nil, search only the selected frame.\n\
89bca612 1569If FRAME is a frame, search only that frame.")
44fa5b1e
JB
1570 (buffer, frame)
1571 Lisp_Object buffer, frame;
7ab12479
JB
1572{
1573 buffer = Fget_buffer (buffer);
017b2bad 1574 if (BUFFERP (buffer))
44fa5b1e 1575 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
7ab12479
JB
1576 else
1577 return Qnil;
1578}
1579
1580DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1581 0, 1, "",
44fa5b1e 1582 "Make WINDOW (or the selected window) fill its frame.\n\
f16a1ed3
RS
1583Only the frame WINDOW is on is affected.\n\
1584This function tries to reduce display jumps\n\
1585by keeping the text previously visible in WINDOW\n\
1586in the same place on the frame. Doing this depends on\n\
1587the value of (window-start WINDOW), so if calling this function\n\
1588in a program gives strange scrolling, make sure the window-start\n\
1589value is reasonable when this function is called.")
7ab12479
JB
1590 (window)
1591 Lisp_Object window;
1592{
1593 struct window *w;
00d3d838 1594 int startpos;
7ab12479
JB
1595 int top;
1596
265a9e55 1597 if (NILP (window))
7ab12479
JB
1598 window = selected_window;
1599 else
605be8af 1600 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1601
1602 w = XWINDOW (window);
a2b38b3c 1603
00d3d838
KH
1604 startpos = marker_position (w->start);
1605 top = XFASTINT (w->top) - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w)));
7ab12479 1606
a2b38b3c
RS
1607 if (MINI_WINDOW_P (w) && top > 0)
1608 error ("Can't expand minibuffer to full frame");
1609
70728a80 1610 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
7ab12479 1611
00d3d838
KH
1612 /* Try to minimize scrolling, by setting the window start to the point
1613 will cause the text at the old window start to be at the same place
1614 on the frame. But don't try to do this if the window start is
1615 outside the visible portion (as might happen when the display is
1616 not current, due to typeahead). */
1617 if (startpos >= BUF_BEGV (XBUFFER (w->buffer))
1618 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
1619 {
1620 struct position pos;
1621 struct buffer *obuf = current_buffer;
1622
1623 Fset_buffer (w->buffer);
1624 /* This computation used to temporarily move point, but that can
1625 have unwanted side effects due to text properties. */
0383eb57 1626 pos = *vmotion (startpos, -top, w);
4d047f50 1627
b73ea88e
RS
1628 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
1629 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
1630 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
00d3d838 1631 : Qnil);
80622eec
RS
1632 /* We need to do this, so that the window-scroll-functions
1633 get called. */
4d047f50 1634 w->optional_new_start = Qt;
00d3d838
KH
1635
1636 set_buffer_internal (obuf);
1637 }
7ab12479
JB
1638 return Qnil;
1639}
1640
1641DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
3cbbb729 1642 1, 2, "bDelete windows on (buffer): ",
26f6279d
JB
1643 "Delete all windows showing BUFFER.\n\
1644Optional second argument FRAME controls which frames are affected.\n\
1645If nil or omitted, delete all windows showing BUFFER in any frame.\n\
1646If t, delete only windows showing BUFFER in the selected frame.\n\
89bca612 1647If `visible', delete all windows showing BUFFER in any visible frame.\n\
26f6279d
JB
1648If a frame, delete only windows showing BUFFER in that frame.")
1649 (buffer, frame)
1650 Lisp_Object buffer, frame;
7ab12479 1651{
26f6279d
JB
1652 /* FRAME uses t and nil to mean the opposite of what window_loop
1653 expects. */
1654 if (! FRAMEP (frame))
1655 frame = NILP (frame) ? Qt : Qnil;
26f6279d 1656
265a9e55 1657 if (!NILP (buffer))
7ab12479
JB
1658 {
1659 buffer = Fget_buffer (buffer);
1660 CHECK_BUFFER (buffer, 0);
26f6279d 1661 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
7ab12479
JB
1662 }
1663 return Qnil;
1664}
1665
1666DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1667 Sreplace_buffer_in_windows,
1668 1, 1, "bReplace buffer in windows: ",
1669 "Replace BUFFER with some other buffer in all windows showing it.")
1670 (buffer)
1671 Lisp_Object buffer;
1672{
265a9e55 1673 if (!NILP (buffer))
7ab12479
JB
1674 {
1675 buffer = Fget_buffer (buffer);
1676 CHECK_BUFFER (buffer, 0);
1677 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1678 }
1679 return Qnil;
1680}
ff58478b
RS
1681
1682/* Replace BUFFER with some other buffer in all windows
1683 of all frames, even those on other keyboards. */
1684
1685void
1686replace_buffer_in_all_windows (buffer)
1687 Lisp_Object buffer;
1688{
27abb84f 1689#ifdef MULTI_KBOARD
ff58478b
RS
1690 Lisp_Object tail, frame;
1691
ff58478b
RS
1692 /* A single call to window_loop won't do the job
1693 because it only considers frames on the current keyboard.
1694 So loop manually over frames, and handle each one. */
1695 FOR_EACH_FRAME (tail, frame)
db7f721d 1696 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
ff58478b 1697#else
db7f721d 1698 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
ff58478b
RS
1699#endif
1700}
7ab12479
JB
1701\f
1702/* Set the height of WINDOW and all its inferiors. */
a481b3ea
JB
1703
1704/* The smallest acceptable dimensions for a window. Anything smaller
1705 might crash Emacs. */
1706#define MIN_SAFE_WINDOW_WIDTH (2)
1707#define MIN_SAFE_WINDOW_HEIGHT (2)
1708
1709/* Make sure that window_min_height and window_min_width are
1710 not too small; if they are, set them to safe minima. */
1711
1712static void
1713check_min_window_sizes ()
1714{
1715 /* Smaller values might permit a crash. */
1716 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1717 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1718 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1719 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1720}
1721
1722/* If *ROWS or *COLS are too small a size for FRAME, set them to the
1723 minimum allowable size. */
605be8af 1724void
a481b3ea 1725check_frame_size (frame, rows, cols)
605be8af
JB
1726 FRAME_PTR frame;
1727 int *rows, *cols;
a481b3ea 1728{
628df3bf 1729 /* For height, we have to see:
37962e60 1730 whether the frame has a minibuffer,
628df3bf
JB
1731 whether it wants a mode line, and
1732 whether it has a menu bar. */
a481b3ea 1733 int min_height =
79f92720
JB
1734 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
1735 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
a481b3ea 1736 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
628df3bf
JB
1737 if (FRAME_MENU_BAR_LINES (frame) > 0)
1738 min_height += FRAME_MENU_BAR_LINES (frame);
a481b3ea
JB
1739
1740 if (*rows < min_height)
1741 *rows = min_height;
1742 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1743 *cols = MIN_SAFE_WINDOW_WIDTH;
1744}
1745
7ab12479
JB
1746/* Normally the window is deleted if it gets too small.
1747 nodelete nonzero means do not do this.
1748 (The caller should check later and do so if appropriate) */
1749
5e14b1fc 1750void
7ab12479
JB
1751set_window_height (window, height, nodelete)
1752 Lisp_Object window;
1753 int height;
1754 int nodelete;
1755{
1756 register struct window *w = XWINDOW (window);
1757 register struct window *c;
1758 int oheight = XFASTINT (w->height);
1759 int top, pos, lastbot, opos, lastobot;
1760 Lisp_Object child;
1761
a481b3ea
JB
1762 check_min_window_sizes ();
1763
7ab12479 1764 if (!nodelete
265a9e55 1765 && ! NILP (w->parent)
c6b530ed
RS
1766 && (MINI_WINDOW_P (w)
1767 ? height < 1
1768 : height < window_min_height))
7ab12479 1769 {
543f5fb1 1770 delete_window (window);
7ab12479
JB
1771 return;
1772 }
1773
d834a2e9 1774 XSETFASTINT (w->last_modified, 0);
3cd21523 1775 XSETFASTINT (w->last_overlay_modified, 0);
7ab12479 1776 windows_or_buffers_changed++;
29aeee73
RS
1777 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
1778
d834a2e9 1779 XSETFASTINT (w->height, height);
265a9e55 1780 if (!NILP (w->hchild))
7ab12479 1781 {
265a9e55 1782 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1783 {
1784 XWINDOW (child)->top = w->top;
1785 set_window_height (child, height, nodelete);
1786 }
1787 }
265a9e55 1788 else if (!NILP (w->vchild))
7ab12479
JB
1789 {
1790 lastbot = top = XFASTINT (w->top);
1791 lastobot = 0;
265a9e55 1792 for (child = w->vchild; !NILP (child); child = c->next)
7ab12479
JB
1793 {
1794 c = XWINDOW (child);
1795
1796 opos = lastobot + XFASTINT (c->height);
1797
d834a2e9 1798 XSETFASTINT (c->top, lastbot);
7ab12479
JB
1799
1800 pos = (((opos * height) << 1) + oheight) / (oheight << 1);
1801
1802 /* Avoid confusion: inhibit deletion of child if becomes too small */
1803 set_window_height (child, pos + top - lastbot, 1);
1804
1805 /* Now advance child to next window,
1806 and set lastbot if child was not just deleted. */
1807 lastbot = pos + top;
1808 lastobot = opos;
1809 }
1810 /* Now delete any children that became too small. */
1811 if (!nodelete)
265a9e55 1812 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1813 {
1814 set_window_height (child, XINT (XWINDOW (child)->height), 0);
1815 }
1816 }
1817}
1818
1819/* Recursively set width of WINDOW and its inferiors. */
1820
5e14b1fc 1821void
7ab12479
JB
1822set_window_width (window, width, nodelete)
1823 Lisp_Object window;
1824 int width;
1825 int nodelete;
1826{
1827 register struct window *w = XWINDOW (window);
1828 register struct window *c;
1829 int owidth = XFASTINT (w->width);
1830 int left, pos, lastright, opos, lastoright;
1831 Lisp_Object child;
1832
abdced83 1833 if (!nodelete && width < window_min_width && !NILP (w->parent))
7ab12479 1834 {
543f5fb1 1835 delete_window (window);
7ab12479
JB
1836 return;
1837 }
1838
d834a2e9 1839 XSETFASTINT (w->last_modified, 0);
3cd21523 1840 XSETFASTINT (w->last_overlay_modified, 0);
7ab12479 1841 windows_or_buffers_changed++;
29aeee73
RS
1842 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
1843
d834a2e9 1844 XSETFASTINT (w->width, width);
265a9e55 1845 if (!NILP (w->vchild))
7ab12479 1846 {
265a9e55 1847 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1848 {
1849 XWINDOW (child)->left = w->left;
1850 set_window_width (child, width, nodelete);
1851 }
1852 }
265a9e55 1853 else if (!NILP (w->hchild))
7ab12479
JB
1854 {
1855 lastright = left = XFASTINT (w->left);
1856 lastoright = 0;
265a9e55 1857 for (child = w->hchild; !NILP (child); child = c->next)
7ab12479
JB
1858 {
1859 c = XWINDOW (child);
1860
1861 opos = lastoright + XFASTINT (c->width);
1862
d834a2e9 1863 XSETFASTINT (c->left, lastright);
7ab12479
JB
1864
1865 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
1866
1867 /* Inhibit deletion for becoming too small */
1868 set_window_width (child, pos + left - lastright, 1);
1869
1870 /* Now advance child to next window,
1871 and set lastright if child was not just deleted. */
1872 lastright = pos + left, lastoright = opos;
1873 }
1874 /* Delete children that became too small */
1875 if (!nodelete)
265a9e55 1876 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1877 {
1878 set_window_width (child, XINT (XWINDOW (child)->width), 0);
1879 }
1880 }
1881}
1882\f
1d8d96fa 1883int window_select_count;
7ab12479 1884
5b03d3c0
RS
1885Lisp_Object
1886Fset_window_buffer_unwind (obuf)
1887 Lisp_Object obuf;
1888{
1889 Fset_buffer (obuf);
1890 return Qnil;
1891}
1892
7ab12479
JB
1893DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1894 "Make WINDOW display BUFFER as its contents.\n\
1895BUFFER can be a buffer or buffer name.")
1896 (window, buffer)
1897 register Lisp_Object window, buffer;
1898{
1899 register Lisp_Object tem;
1900 register struct window *w = decode_window (window);
5b03d3c0 1901 int count = specpdl_ptr - specpdl;
7ab12479
JB
1902
1903 buffer = Fget_buffer (buffer);
1904 CHECK_BUFFER (buffer, 1);
1905
265a9e55 1906 if (NILP (XBUFFER (buffer)->name))
7ab12479
JB
1907 error ("Attempt to display deleted buffer");
1908
1909 tem = w->buffer;
265a9e55 1910 if (NILP (tem))
7ab12479
JB
1911 error ("Window is deleted");
1912 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
1913 is first being set up. */
1914 {
265a9e55 1915 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3cf85532
RS
1916 error ("Window is dedicated to `%s'",
1917 XSTRING (XBUFFER (tem)->name)->data);
7ab12479
JB
1918
1919 unshow_buffer (w);
1920 }
1921
1922 w->buffer = buffer;
86e48436
RS
1923
1924 if (EQ (window, selected_window))
1925 XBUFFER (w->buffer)->last_selected_window = window;
beb4e312
RS
1926
1927 /* Update time stamps of buffer display. */
850ebd4f
RS
1928 if (INTEGERP (XBUFFER (buffer)->display_count))
1929 XSETINT (XBUFFER (buffer)->display_count,
296b535c 1930 XINT (XBUFFER (buffer)->display_count) + 1);
beb4e312 1931 XBUFFER (buffer)->display_time = Fcurrent_time ();
86e48436 1932
d834a2e9 1933 XSETFASTINT (w->window_end_pos, 0);
5a41ab94 1934 w->window_end_valid = Qnil;
dba06815 1935 XSETFASTINT (w->hscroll, 0);
b73ea88e
RS
1936 set_marker_both (w->pointm, buffer,
1937 BUF_PT (XBUFFER (buffer)), BUF_PT_BYTE (XBUFFER (buffer)));
7ab12479
JB
1938 set_marker_restricted (w->start,
1939 make_number (XBUFFER (buffer)->last_window_start),
1940 buffer);
1941 w->start_at_line_beg = Qnil;
e36ab06b 1942 w->force_start = Qnil;
d834a2e9 1943 XSETFASTINT (w->last_modified, 0);
3cd21523 1944 XSETFASTINT (w->last_overlay_modified, 0);
7ab12479 1945 windows_or_buffers_changed++;
5b03d3c0
RS
1946
1947 /* We must select BUFFER for running the window-scroll-functions.
1948 If WINDOW is selected, switch permanently.
1949 Otherwise, switch but go back to the ambient buffer afterward. */
7ab12479
JB
1950 if (EQ (window, selected_window))
1951 Fset_buffer (buffer);
5b03d3c0
RS
1952 /* We can't check ! NILP (Vwindow_scroll_functions) here
1953 because that might itself be a local variable. */
1954 else if (window_initialized)
1955 {
1956 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
1957 Fset_buffer (buffer);
1958 }
1959
dba06815
RS
1960 if (! NILP (Vwindow_scroll_functions))
1961 run_hook_with_args_2 (Qwindow_scroll_functions, window,
1962 Fmarker_position (w->start));
7ab12479 1963
543f5fb1
RS
1964 if (! NILP (Vwindow_configuration_change_hook)
1965 && ! NILP (Vrun_hooks))
1966 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
1967
5b03d3c0
RS
1968 unbind_to (count, Qnil);
1969
7ab12479
JB
1970 return Qnil;
1971}
1972
1973DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1974 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
beb4e312
RS
1975If WINDOW is not already selected, also make WINDOW's buffer current.\n\
1976Note that the main editor command loop\n\
1977selects the buffer of the selected window before each command.")
7ab12479
JB
1978 (window)
1979 register Lisp_Object window;
b7354ddf
RS
1980{
1981 return select_window_1 (window, 1);
1982}
1983\f
1984static Lisp_Object
1985select_window_1 (window, recordflag)
1986 register Lisp_Object window;
1987 int recordflag;
7ab12479
JB
1988{
1989 register struct window *w;
1990 register struct window *ow = XWINDOW (selected_window);
1991
605be8af 1992 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1993
1994 w = XWINDOW (window);
1995
265a9e55 1996 if (NILP (w->buffer))
7ab12479
JB
1997 error ("Trying to select deleted window or non-leaf window");
1998
d834a2e9 1999 XSETFASTINT (w->use_time, ++window_select_count);
7ab12479
JB
2000 if (EQ (window, selected_window))
2001 return window;
2002
596ae0cf
RS
2003 if (! NILP (ow->buffer))
2004 set_marker_both (ow->pointm, ow->buffer,
2005 BUF_PT (XBUFFER (ow->buffer)),
2006 BUF_PT_BYTE (XBUFFER (ow->buffer)));
7ab12479
JB
2007
2008 selected_window = window;
44fa5b1e 2009 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
7ab12479 2010 {
44fa5b1e 2011 XFRAME (WINDOW_FRAME (w))->selected_window = window;
147a6615
RS
2012 /* Use this rather than Fhandle_switch_frame
2013 so that FRAME_FOCUS_FRAME is moved appropriately as we
2014 move around in the state where a minibuffer in a separate
2015 frame is active. */
2016 Fselect_frame (WINDOW_FRAME (w), Qnil);
7ab12479
JB
2017 }
2018 else
44fa5b1e 2019 selected_frame->selected_window = window;
7ab12479 2020
b7354ddf
RS
2021 if (recordflag)
2022 record_buffer (w->buffer);
7ab12479
JB
2023 Fset_buffer (w->buffer);
2024
86e48436
RS
2025 XBUFFER (w->buffer)->last_selected_window = window;
2026
7ab12479
JB
2027 /* Go to the point recorded in the window.
2028 This is important when the buffer is in more
2029 than one window. It also matters when
2030 redisplay_window has altered point after scrolling,
2031 because it makes the change only in the window. */
2032 {
2033 register int new_point = marker_position (w->pointm);
2034 if (new_point < BEGV)
2035 SET_PT (BEGV);
a9c95e08 2036 else if (new_point > ZV)
7ab12479
JB
2037 SET_PT (ZV);
2038 else
2039 SET_PT (new_point);
2040 }
2041
2042 windows_or_buffers_changed++;
2043 return window;
2044}
b7354ddf 2045\f
441a127e
RS
2046/* Deiconify the frame containing the window WINDOW,
2047 unless it is the selected frame;
2048 then return WINDOW.
2049
2050 The reason for the exception for the selected frame
2051 is that it seems better not to change the selected frames visibility
2052 merely because of displaying a different buffer in it.
2053 The deiconification is useful when a buffer gets shown in
2054 another frame that you were not using lately. */
d07f802a
RS
2055
2056static Lisp_Object
2057display_buffer_1 (window)
2058 Lisp_Object window;
2059{
d07f802a
RS
2060 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
2061 FRAME_SAMPLE_VISIBILITY (f);
60117126
RS
2062 if (f != selected_frame)
2063 {
2064 if (FRAME_ICONIFIED_P (f))
2065 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
37962e60 2066 else if (FRAME_VISIBLE_P (f))
60117126
RS
2067 Fraise_frame (WINDOW_FRAME (XWINDOW (window)));
2068 }
d07f802a
RS
2069 return window;
2070}
2071
4628f7a4 2072DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
0f7d64d2
GV
2073 "Returns non-nil if a buffer named BUFFER-NAME would be created specially.\n\
2074The value is actually t if the frame should be called with default frame\n\
2075parameters, and a list of frame parameters if they were specified.\n\
4628f7a4
EN
2076See `special-display-buffer-names', and `special-display-regexps'.")
2077 (buffer_name)
2078 Lisp_Object buffer_name;
2079{
2080 Lisp_Object tem;
2081
2082 CHECK_STRING (buffer_name, 1);
2083
2084 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2085 if (!NILP (tem))
2086 return Qt;
2087
2088 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2089 if (!NILP (tem))
2090 return XCDR (tem);
2091
2092 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2093 {
2094 Lisp_Object car = XCAR (tem);
2095 if (STRINGP (car)
2096 && fast_string_match (car, buffer_name) >= 0)
2097 return Qt;
2098 else if (CONSP (car)
2099 && STRINGP (XCAR (car))
2100 && fast_string_match (XCAR (car), buffer_name) >= 0)
0057b00a 2101 return XCDR (car);
4628f7a4
EN
2102 }
2103 return Qnil;
2104}
2105
2106DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
0f7d64d2 2107 "Returns non-nil if a new buffer named BUFFER-NAME would use the same window.\n\
4628f7a4
EN
2108See `same-window-buffer-names' and `same-window-regexps'.")
2109 (buffer_name)
2110 Lisp_Object buffer_name;
2111{
2112 Lisp_Object tem;
2113
2114 CHECK_STRING (buffer_name, 1);
2115
2116 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2117 if (!NILP (tem))
2118 return Qt;
2119
2120 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2121 if (!NILP (tem))
2122 return Qt;
2123
2124 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
2125 {
2126 Lisp_Object car = XCAR (tem);
2127 if (STRINGP (car)
2128 && fast_string_match (car, buffer_name) >= 0)
2129 return Qt;
2130 else if (CONSP (car)
2131 && STRINGP (XCAR (car))
2132 && fast_string_match (XCAR (car), buffer_name) >= 0)
2133 return Qt;
2134 }
2135 return Qnil;
2136}
2137
53f76081
RS
2138 /* Use B so the default is (other-buffer). */
2139DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
2140 "BDisplay buffer: \nP",
7ab12479
JB
2141 "Make BUFFER appear in some window but don't select it.\n\
2142BUFFER can be a buffer or a buffer name.\n\
2143If BUFFER is shown already in some window, just use that one,\n\
2144unless the window is the selected window and the optional second\n\
46d3268a 2145argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
5141b901 2146If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
5abcf432
RS
2147Returns the window displaying BUFFER.\n\
2148\n\
2149The variables `special-display-buffer-names', `special-display-regexps',\n\
2150`same-window-buffer-names', and `same-window-regexps' customize how certain\n\
53f76081
RS
2151buffer names are handled.\n\
2152\n\
2153If optional argument FRAME is `visible', search all visible frames.\n\
2154If FRAME is 0, search all visible and iconified frames.\n\
2155If FRAME is t, search all frames.\n\
2156If FRAME is a frame, search only that frame.\n\
2157If FRAME is nil, search only the selected frame\n\
2158 (actually the last nonminibuffer frame),\n\
2159 unless `pop-up-frames' is non-nil,\n\
2160 which means search visible and iconified frames.")
2161 (buffer, not_this_window, frame)
2162 register Lisp_Object buffer, not_this_window, frame;
7ab12479 2163{
a90712c2 2164 register Lisp_Object window, tem;
7ab12479
JB
2165
2166 buffer = Fget_buffer (buffer);
2167 CHECK_BUFFER (buffer, 0);
2168
265a9e55 2169 if (!NILP (Vdisplay_buffer_function))
7ab12479
JB
2170 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
2171
265a9e55 2172 if (NILP (not_this_window)
7ab12479 2173 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
d07f802a 2174 return display_buffer_1 (selected_window);
7ab12479 2175
855d8627
RS
2176 /* See if the user has specified this buffer should appear
2177 in the selected window. */
2178 if (NILP (not_this_window))
2179 {
4628f7a4 2180 tem = Fsame_window_p (XBUFFER (buffer)->name);
855d8627 2181 if (!NILP (tem))
c63dc4a2
RS
2182 {
2183 Fswitch_to_buffer (buffer, Qnil);
d07f802a 2184 return display_buffer_1 (selected_window);
c63dc4a2 2185 }
855d8627
RS
2186 }
2187
e8edb3ae 2188 /* If pop_up_frames,
73dc5198
KH
2189 look for a window showing BUFFER on any visible or iconified frame.
2190 Otherwise search only the current frame. */
53f76081
RS
2191 if (! NILP (frame))
2192 tem = frame;
2193 else if (pop_up_frames || last_nonminibuf_frame == 0)
73dc5198
KH
2194 XSETFASTINT (tem, 0);
2195 else
73dc5198
KH
2196 XSETFRAME (tem, last_nonminibuf_frame);
2197 window = Fget_buffer_window (buffer, tem);
265a9e55
JB
2198 if (!NILP (window)
2199 && (NILP (not_this_window) || !EQ (window, selected_window)))
f812f9c6 2200 {
d07f802a 2201 return display_buffer_1 (window);
f812f9c6 2202 }
7ab12479 2203
a90712c2 2204 /* Certain buffer names get special handling. */
4628f7a4 2205 if (!NILP (Vspecial_display_function))
a90712c2 2206 {
4628f7a4
EN
2207 tem = Fspecial_display_p (XBUFFER (buffer)->name);
2208 if (EQ (tem, Qt))
a90712c2 2209 return call1 (Vspecial_display_function, buffer);
4628f7a4
EN
2210 if (CONSP (tem))
2211 return call2 (Vspecial_display_function, buffer, tem);
a90712c2
RS
2212 }
2213
44fa5b1e
JB
2214 /* If there are no frames open that have more than a minibuffer,
2215 we need to create a new frame. */
2216 if (pop_up_frames || last_nonminibuf_frame == 0)
7ab12479 2217 {
a90712c2 2218 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
7ab12479 2219 Fset_window_buffer (window, buffer);
d07f802a 2220 return display_buffer_1 (window);
7ab12479 2221 }
7ab12479 2222
43bad991 2223 if (pop_up_windows
44fa5b1e 2224 || FRAME_MINIBUF_ONLY_P (selected_frame)
cee67da9
RS
2225 /* If the current frame is a special display frame,
2226 don't try to reuse its windows. */
2227 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->dedicated)
43bad991 2228 )
7ab12479 2229 {
12cae7c0
KH
2230 Lisp_Object frames;
2231
37962e60 2232 frames = Qnil;
44fa5b1e 2233 if (FRAME_MINIBUF_ONLY_P (selected_frame))
74112613 2234 XSETFRAME (frames, last_nonminibuf_frame);
7ab12479
JB
2235 /* Don't try to create a window if would get an error */
2236 if (split_height_threshold < window_min_height << 1)
2237 split_height_threshold = window_min_height << 1;
2238
cee67da9
RS
2239 /* Note that both Fget_largest_window and Fget_lru_window
2240 ignore minibuffers and dedicated windows.
2241 This means they can return nil. */
7ab12479 2242
cee67da9
RS
2243 /* If the frame we would try to split cannot be split,
2244 try other frames. */
2245 if (FRAME_NO_SPLIT_P (NILP (frames) ? selected_frame
2246 : last_nonminibuf_frame))
2247 {
2248 /* Try visible frames first. */
2249 window = Fget_largest_window (Qvisible);
2250 /* If that didn't work, try iconified frames. */
2251 if (NILP (window))
2252 window = Fget_largest_window (make_number (0));
2253 if (NILP (window))
2254 window = Fget_largest_window (Qt);
2255 }
2256 else
2257 window = Fget_largest_window (frames);
2258
92cca945
RS
2259 /* If we got a tall enough full-width window that can be split,
2260 split it. */
265a9e55 2261 if (!NILP (window)
92cca945 2262 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
7ab12479 2263 && window_height (window) >= split_height_threshold
111e5992 2264 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
7ab12479
JB
2265 window = Fsplit_window (window, Qnil, Qnil);
2266 else
2267 {
1942f68f
RS
2268 Lisp_Object upper, lower, other;
2269
44fa5b1e 2270 window = Fget_lru_window (frames);
92cca945
RS
2271 /* If the LRU window is selected, and big enough,
2272 and can be split, split it. */
cee67da9 2273 if (!NILP (window)
92cca945 2274 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
cee67da9
RS
2275 && (EQ (window, selected_window)
2276 || EQ (XWINDOW (window)->parent, Qnil))
7ab12479
JB
2277 && window_height (window) >= window_min_height << 1)
2278 window = Fsplit_window (window, Qnil, Qnil);
cee67da9 2279 /* If Fget_lru_window returned nil, try other approaches. */
48d9379d 2280
cee67da9 2281 /* Try visible frames first. */
48d9379d
RS
2282 if (NILP (window))
2283 window = Fget_buffer_window (buffer, Qvisible);
cee67da9
RS
2284 if (NILP (window))
2285 window = Fget_largest_window (Qvisible);
2286 /* If that didn't work, try iconified frames. */
48d9379d
RS
2287 if (NILP (window))
2288 window = Fget_buffer_window (buffer, make_number (0));
cee67da9
RS
2289 if (NILP (window))
2290 window = Fget_largest_window (make_number (0));
2291 /* Try invisible frames. */
48d9379d
RS
2292 if (NILP (window))
2293 window = Fget_buffer_window (buffer, Qt);
cee67da9
RS
2294 if (NILP (window))
2295 window = Fget_largest_window (Qt);
2296 /* As a last resort, make a new frame. */
2297 if (NILP (window))
2298 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
1942f68f
RS
2299 /* If window appears above or below another,
2300 even out their heights. */
cac66e4f 2301 other = upper = lower = Qnil;
1942f68f
RS
2302 if (!NILP (XWINDOW (window)->prev))
2303 other = upper = XWINDOW (window)->prev, lower = window;
2304 if (!NILP (XWINDOW (window)->next))
2305 other = lower = XWINDOW (window)->next, upper = window;
2306 if (!NILP (other)
2307 /* Check that OTHER and WINDOW are vertically arrayed. */
296b535c
KH
2308 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
2309 && (XFASTINT (XWINDOW (other)->height)
2310 > XFASTINT (XWINDOW (window)->height)))
1942f68f 2311 {
296b535c
KH
2312 int total = (XFASTINT (XWINDOW (other)->height)
2313 + XFASTINT (XWINDOW (window)->height));
8d77c0c8
KH
2314 Lisp_Object old_selected_window;
2315 old_selected_window = selected_window;
1942f68f 2316
8d77c0c8 2317 selected_window = upper;
296b535c
KH
2318 change_window_height ((total / 2
2319 - XFASTINT (XWINDOW (upper)->height)),
2320 0);
1942f68f
RS
2321 selected_window = old_selected_window;
2322 }
7ab12479
JB
2323 }
2324 }
2325 else
2326 window = Fget_lru_window (Qnil);
2327
2328 Fset_window_buffer (window, buffer);
d07f802a 2329 return display_buffer_1 (window);
7ab12479
JB
2330}
2331
2332void
2333temp_output_buffer_show (buf)
2334 register Lisp_Object buf;
2335{
2336 register struct buffer *old = current_buffer;
2337 register Lisp_Object window;
2338 register struct window *w;
2339
bccd3dd1
RS
2340 XBUFFER (buf)->directory = current_buffer->directory;
2341
7ab12479 2342 Fset_buffer (buf);
c6367666 2343 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
7ab12479
JB
2344 BEGV = BEG;
2345 ZV = Z;
2346 SET_PT (BEG);
1479ef51 2347 XBUFFER (buf)->clip_changed = 1;
7ab12479
JB
2348 set_buffer_internal (old);
2349
2350 if (!EQ (Vtemp_buffer_show_function, Qnil))
2351 call1 (Vtemp_buffer_show_function, buf);
2352 else
2353 {
53f76081 2354 window = Fdisplay_buffer (buf, Qnil, Qnil);
7ab12479 2355
44fa5b1e
JB
2356 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
2357 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
7ab12479
JB
2358 Vminibuf_scroll_window = window;
2359 w = XWINDOW (window);
d834a2e9 2360 XSETFASTINT (w->hscroll, 0);
b73ea88e
RS
2361 set_marker_restricted_both (w->start, buf, 1, 1);
2362 set_marker_restricted_both (w->pointm, buf, 1, 1);
a58ec57d 2363
beb4e312
RS
2364 /* Run temp-buffer-show-hook, with the chosen window selected
2365 and it sbuffer current. */
f52cca03 2366 if (!NILP (Vrun_hooks))
2cccc823 2367 {
f52cca03
RS
2368 Lisp_Object tem;
2369 tem = Fboundp (Qtemp_buffer_show_hook);
2cccc823
RS
2370 if (!NILP (tem))
2371 {
f52cca03
RS
2372 tem = Fsymbol_value (Qtemp_buffer_show_hook);
2373 if (!NILP (tem))
2374 {
2375 int count = specpdl_ptr - specpdl;
b7354ddf
RS
2376 Lisp_Object prev_window;
2377 prev_window = selected_window;
2cccc823 2378
f52cca03
RS
2379 /* Select the window that was chosen, for running the hook. */
2380 record_unwind_protect (Fset_window_configuration,
2381 Fcurrent_window_configuration (Qnil));
2cccc823 2382
b7354ddf 2383 select_window_1 (window, 0);
beb4e312 2384 Fset_buffer (w->buffer);
f52cca03 2385 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
b7354ddf 2386 select_window_1 (prev_window, 0);
f52cca03
RS
2387 unbind_to (count, Qnil);
2388 }
2cccc823
RS
2389 }
2390 }
2391 }
7ab12479
JB
2392}
2393\f
dfcf069d 2394static void
7ab12479
JB
2395make_dummy_parent (window)
2396 Lisp_Object window;
2397{
cffec418 2398 Lisp_Object new;
7ab12479 2399 register struct window *o, *p;
cffec418
KH
2400 register struct Lisp_Vector *vec;
2401 int i;
7ab12479 2402
cffec418
KH
2403 o = XWINDOW (window);
2404 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
2405 for (i = 0; i < VECSIZE (struct window); ++i)
2406 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
2407 vec->size = VECSIZE (struct window);
2408 p = (struct window *)vec;
2409 XSETWINDOW (new, p);
7ab12479 2410
d834a2e9 2411 XSETFASTINT (p->sequence_number, ++sequence_number);
7ab12479
JB
2412
2413 /* Put new into window structure in place of window */
2414 replace_window (window, new);
2415
2416 o->next = Qnil;
2417 o->prev = Qnil;
2418 o->vchild = Qnil;
2419 o->hchild = Qnil;
2420 o->parent = new;
2421
2422 p->start = Qnil;
2423 p->pointm = Qnil;
2424 p->buffer = Qnil;
2425}
2426
2427DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
2428 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
2429WINDOW defaults to selected one and SIZE to half its size.\n\
77ae0fe3 2430If optional third arg HORFLAG is non-nil, split side by side\n\
7ab12479 2431and put SIZE columns in the first of the pair.")
77ae0fe3
KH
2432 (window, size, horflag)
2433 Lisp_Object window, size, horflag;
7ab12479
JB
2434{
2435 register Lisp_Object new;
2436 register struct window *o, *p;
c0807608 2437 FRAME_PTR fo;
77ae0fe3 2438 register int size_int;
7ab12479 2439
265a9e55 2440 if (NILP (window))
7ab12479
JB
2441 window = selected_window;
2442 else
605be8af 2443 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2444
2445 o = XWINDOW (window);
c0807608 2446 fo = XFRAME (WINDOW_FRAME (o));
7ab12479 2447
77ae0fe3 2448 if (NILP (size))
7ab12479 2449 {
265a9e55 2450 if (!NILP (horflag))
c0807608
KH
2451 /* Calculate the size of the left-hand window, by dividing
2452 the usable space in columns by two. */
a59fed7e 2453 size_int = XFASTINT (o->width) >> 1;
7ab12479 2454 else
77ae0fe3 2455 size_int = XFASTINT (o->height) >> 1;
7ab12479
JB
2456 }
2457 else
2458 {
77ae0fe3
KH
2459 CHECK_NUMBER (size, 1);
2460 size_int = XINT (size);
7ab12479
JB
2461 }
2462
2463 if (MINI_WINDOW_P (o))
2464 error ("Attempt to split minibuffer window");
7ab12479 2465
a481b3ea 2466 check_min_window_sizes ();
7ab12479 2467
265a9e55 2468 if (NILP (horflag))
7ab12479 2469 {
77ae0fe3
KH
2470 if (size_int < window_min_height)
2471 error ("Window height %d too small (after splitting)", size_int);
2472 if (size_int + window_min_height > XFASTINT (o->height))
37962e60 2473 error ("Window height %d too small (after splitting)",
77ae0fe3 2474 XFASTINT (o->height) - size_int);
265a9e55
JB
2475 if (NILP (o->parent)
2476 || NILP (XWINDOW (o->parent)->vchild))
7ab12479
JB
2477 {
2478 make_dummy_parent (window);
2479 new = o->parent;
2480 XWINDOW (new)->vchild = window;
2481 }
2482 }
2483 else
2484 {
77ae0fe3
KH
2485 if (size_int < window_min_width)
2486 error ("Window width %d too small (after splitting)", size_int);
a59fed7e
RS
2487
2488 if (size_int + window_min_width > XFASTINT (o->width))
37962e60 2489 error ("Window width %d too small (after splitting)",
a59fed7e 2490 XFASTINT (o->width) - size_int);
265a9e55
JB
2491 if (NILP (o->parent)
2492 || NILP (XWINDOW (o->parent)->hchild))
7ab12479
JB
2493 {
2494 make_dummy_parent (window);
2495 new = o->parent;
2496 XWINDOW (new)->hchild = window;
2497 }
2498 }
2499
2500 /* Now we know that window's parent is a vertical combination
2501 if we are dividing vertically, or a horizontal combination
2502 if we are making side-by-side windows */
2503
2504 windows_or_buffers_changed++;
c0807608 2505 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
7ab12479
JB
2506 new = make_window ();
2507 p = XWINDOW (new);
2508
44fa5b1e 2509 p->frame = o->frame;
7ab12479 2510 p->next = o->next;
265a9e55 2511 if (!NILP (p->next))
7ab12479
JB
2512 XWINDOW (p->next)->prev = new;
2513 p->prev = window;
2514 o->next = new;
2515 p->parent = o->parent;
2516 p->buffer = Qt;
2517
44fa5b1e 2518 /* Apportion the available frame space among the two new windows */
7ab12479 2519
265a9e55 2520 if (!NILP (horflag))
7ab12479
JB
2521 {
2522 p->height = o->height;
2523 p->top = o->top;
a59fed7e 2524 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
77ae0fe3
KH
2525 XSETFASTINT (o->width, size_int);
2526 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
7ab12479
JB
2527 }
2528 else
2529 {
2530 p->left = o->left;
2531 p->width = o->width;
77ae0fe3
KH
2532 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
2533 XSETFASTINT (o->height, size_int);
2534 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
7ab12479
JB
2535 }
2536
543f5fb1
RS
2537 Fset_window_buffer (new, o->buffer);
2538
7ab12479
JB
2539 return new;
2540}
2541\f
2542DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
2543 "Make current window ARG lines bigger.\n\
2544From program, optional second arg non-nil means grow sideways ARG columns.")
413430c5
EN
2545 (arg, side)
2546 register Lisp_Object arg, side;
7ab12479 2547{
413430c5
EN
2548 CHECK_NUMBER (arg, 0);
2549 change_window_height (XINT (arg), !NILP (side));
543f5fb1
RS
2550
2551 if (! NILP (Vwindow_configuration_change_hook))
2552 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2553
7ab12479
JB
2554 return Qnil;
2555}
2556
2557DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
2558 "Make current window ARG lines smaller.\n\
413430c5
EN
2559From program, optional second arg non-nil means shrink sideways arg columns.")
2560 (arg, side)
2561 register Lisp_Object arg, side;
7ab12479 2562{
413430c5
EN
2563 CHECK_NUMBER (arg, 0);
2564 change_window_height (-XINT (arg), !NILP (side));
543f5fb1
RS
2565
2566 if (! NILP (Vwindow_configuration_change_hook))
2567 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2568
7ab12479
JB
2569 return Qnil;
2570}
2571
2572int
2573window_height (window)
2574 Lisp_Object window;
2575{
2576 register struct window *p = XWINDOW (window);
2577 return XFASTINT (p->height);
2578}
2579
2580int
2581window_width (window)
2582 Lisp_Object window;
2583{
2584 register struct window *p = XWINDOW (window);
2585 return XFASTINT (p->width);
2586}
2587
05c2896a
JB
2588#define MINSIZE(w) \
2589 (widthflag \
2590 ? window_min_width \
2591 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
7ab12479
JB
2592
2593#define CURBEG(w) \
05c2896a 2594 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
7ab12479
JB
2595
2596#define CURSIZE(w) \
05c2896a 2597 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
7ab12479
JB
2598
2599/* Unlike set_window_height, this function
2600 also changes the heights of the siblings so as to
2601 keep everything consistent. */
2602
5e14b1fc 2603void
7ab12479
JB
2604change_window_height (delta, widthflag)
2605 register int delta;
2606 int widthflag;
2607{
2608 register Lisp_Object parent;
2609 Lisp_Object window;
2610 register struct window *p;
2611 int *sizep;
5e14b1fc
AS
2612 int (*sizefun) P_ ((Lisp_Object))
2613 = widthflag ? window_width : window_height;
2614 register void (*setsizefun) P_ ((Lisp_Object, int, int))
2615 = (widthflag ? set_window_width : set_window_height);
db98a733
RS
2616 int maximum;
2617 Lisp_Object next, prev;
7ab12479 2618
a481b3ea 2619 check_min_window_sizes ();
7ab12479
JB
2620
2621 window = selected_window;
2622 while (1)
2623 {
2624 p = XWINDOW (window);
2625 parent = p->parent;
265a9e55 2626 if (NILP (parent))
7ab12479
JB
2627 {
2628 if (widthflag)
2629 error ("No other window to side of this one");
2630 break;
2631 }
265a9e55
JB
2632 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
2633 : !NILP (XWINDOW (parent)->vchild))
7ab12479
JB
2634 break;
2635 window = parent;
2636 }
2637
05c2896a 2638 sizep = &CURSIZE (window);
7ab12479 2639
7ab12479
JB
2640 {
2641 register int maxdelta;
7ab12479 2642
265a9e55
JB
2643 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
2644 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
2645 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
44fa5b1e
JB
2646 /* This is a frame with only one window, a minibuffer-only
2647 or a minibufferless frame. */
d5783c40 2648 : (delta = 0));
7ab12479
JB
2649
2650 if (delta > maxdelta)
2651 /* This case traps trying to make the minibuffer
44fa5b1e
JB
2652 the full frame, or make the only window aside from the
2653 minibuffer the full frame. */
7ab12479 2654 delta = maxdelta;
6b54027b 2655 }
d5783c40 2656
6b54027b
RS
2657 if (*sizep + delta < MINSIZE (window))
2658 {
543f5fb1 2659 delete_window (window);
d5783c40 2660 return;
6b54027b
RS
2661 }
2662
2663 if (delta == 0)
2664 return;
7ab12479 2665
db98a733
RS
2666 /* Find the total we can get from other siblings. */
2667 maximum = 0;
2668 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
2669 maximum += (*sizefun) (next) - MINSIZE (next);
2670 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
2671 maximum += (*sizefun) (prev) - MINSIZE (prev);
2672
2673 /* If we can get it all from them, do so. */
c6b530ed 2674 if (delta <= maximum)
7ab12479 2675 {
db98a733
RS
2676 Lisp_Object first_unaffected;
2677 Lisp_Object first_affected;
2678
2679 next = p->next;
2680 prev = p->prev;
2681 first_affected = window;
2682 /* Look at one sibling at a time,
2683 moving away from this window in both directions alternately,
2684 and take as much as we can get without deleting that sibling. */
dc91fb5d 2685 while (delta != 0)
db98a733
RS
2686 {
2687 if (delta == 0)
2688 break;
2689 if (! NILP (next))
2690 {
2691 int this_one = (*sizefun) (next) - MINSIZE (next);
2692 if (this_one > delta)
2693 this_one = delta;
2694
2695 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
2696 (*setsizefun) (window, *sizep + this_one, 0);
2697
2698 delta -= this_one;
2699 next = XWINDOW (next)->next;
2700 }
2701 if (delta == 0)
2702 break;
2703 if (! NILP (prev))
2704 {
2705 int this_one = (*sizefun) (prev) - MINSIZE (prev);
2706 if (this_one > delta)
2707 this_one = delta;
2708
2709 first_affected = prev;
2710
2711 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
2712 (*setsizefun) (window, *sizep + this_one, 0);
2713
2714 delta -= this_one;
2715 prev = XWINDOW (prev)->prev;
2716 }
2717 }
2718
2719 /* Now recalculate the edge positions of all the windows affected,
2720 based on the new sizes. */
2721 first_unaffected = next;
2722 prev = first_affected;
2723 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
2724 prev = next, next = XWINDOW (next)->next)
2725 {
2726 CURBEG (next) = CURBEG (prev) + (*sizefun) (prev);
2727 /* This does not change size of NEXT,
2728 but it propagates the new top edge to its children */
2729 (*setsizefun) (next, (*sizefun) (next), 0);
2730 }
7ab12479
JB
2731 }
2732 else
2733 {
2734 register int delta1;
2735 register int opht = (*sizefun) (parent);
2736
2737 /* If trying to grow this window to or beyond size of the parent,
2738 make delta1 so big that, on shrinking back down,
2739 all the siblings end up with less than one line and are deleted. */
2740 if (opht <= *sizep + delta)
2741 delta1 = opht * opht * 2;
2742 /* Otherwise, make delta1 just right so that if we add delta1
2743 lines to this window and to the parent, and then shrink
2744 the parent back to its original size, the new proportional
2745 size of this window will increase by delta. */
2746 else
2747 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
2748
2749 /* Add delta1 lines or columns to this window, and to the parent,
2750 keeping things consistent while not affecting siblings. */
05c2896a 2751 CURSIZE (parent) = opht + delta1;
7ab12479
JB
2752 (*setsizefun) (window, *sizep + delta1, 0);
2753
2754 /* Squeeze out delta1 lines or columns from our parent,
2755 shriking this window and siblings proportionately.
2756 This brings parent back to correct size.
2757 Delta1 was calculated so this makes this window the desired size,
2758 taking it all out of the siblings. */
2759 (*setsizefun) (parent, opht, 0);
2760 }
2761
d834a2e9 2762 XSETFASTINT (p->last_modified, 0);
3cd21523 2763 XSETFASTINT (p->last_overlay_modified, 0);
7ab12479
JB
2764}
2765#undef MINSIZE
2766#undef CURBEG
2767#undef CURSIZE
2768
2769\f
2770/* Return number of lines of text (not counting mode line) in W. */
2771
2772int
2773window_internal_height (w)
2774 struct window *w;
2775{
2776 int ht = XFASTINT (w->height);
2777
2778 if (MINI_WINDOW_P (w))
2779 return ht;
2780
265a9e55
JB
2781 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2782 || !NILP (w->next) || !NILP (w->prev)
44fa5b1e 2783 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
7ab12479
JB
2784 return ht - 1;
2785
2786 return ht;
2787}
2788
535e0b8e
JB
2789
2790/* Return the number of columns in W.
a3c87d4e 2791 Don't count columns occupied by scroll bars or the vertical bar
535e0b8e
JB
2792 separating W from the sibling to its right. */
2793int
2794window_internal_width (w)
2795 struct window *w;
2796{
2797 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
535e0b8e
JB
2798 int width = XINT (w->width);
2799
a3c87d4e
JB
2800 /* Scroll bars occupy a few columns. */
2801 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
ca0d0bb9 2802 return width - FRAME_SCROLL_BAR_COLS (f);
535e0b8e
JB
2803
2804 /* The column of `|' characters separating side-by-side windows
2805 occupies one column only. */
111e5992
RS
2806 if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
2807 return width - 1;
2808
2809 return width;
535e0b8e
JB
2810}
2811
2812
101d1605 2813/* Scroll contents of window WINDOW up N lines.
9317a85d 2814 If WHOLE is nonzero, it means scroll N screenfuls instead. */
7ab12479 2815
101d1605
RS
2816static void
2817window_scroll (window, n, whole, noerror)
7ab12479
JB
2818 Lisp_Object window;
2819 int n;
101d1605 2820 int whole;
f8026fd8 2821 int noerror;
7ab12479
JB
2822{
2823 register struct window *w = XWINDOW (window);
5ce7b543 2824 register int opoint = PT;
cb8419b5 2825 register int opoint_byte = PT_BYTE;
b73ea88e 2826 register int pos, pos_byte;
7ab12479
JB
2827 register int ht = window_internal_height (w);
2828 register Lisp_Object tem;
2829 int lose;
2830 Lisp_Object bolp, nmoved;
345d45b2 2831 int startpos;
101d1605
RS
2832 struct position posit;
2833 int original_vpos;
2834
2835 startpos = marker_position (w->start);
2836
2837 posit = *compute_motion (startpos, 0, 0, 0,
2838 PT, ht, 0,
2839 window_internal_width (w), XINT (w->hscroll),
2840 0, w);
2841 original_vpos = posit.vpos;
0a1f771a 2842
d834a2e9 2843 XSETFASTINT (tem, PT);
7ab12479
JB
2844 tem = Fpos_visible_in_window_p (tem, window);
2845
265a9e55 2846 if (NILP (tem))
7ab12479 2847 {
cd2be1dd 2848 Fvertical_motion (make_number (- (ht / 2)), window);
345d45b2 2849 startpos = PT;
7ab12479
JB
2850 }
2851
345d45b2 2852 SET_PT (startpos);
5ce7b543 2853 lose = n < 0 && PT == BEGV;
540b6aa0 2854 Fvertical_motion (make_number (n), window);
5ce7b543 2855 pos = PT;
b73ea88e 2856 pos_byte = PT_BYTE;
7ab12479 2857 bolp = Fbolp ();
b73ea88e 2858 SET_PT_BOTH (opoint, opoint_byte);
7ab12479
JB
2859
2860 if (lose)
f8026fd8
JB
2861 {
2862 if (noerror)
2863 return;
2864 else
2865 Fsignal (Qbeginning_of_buffer, Qnil);
2866 }
7ab12479
JB
2867
2868 if (pos < ZV)
7ab12479 2869 {
0c7da84e
RS
2870 int this_scroll_margin = scroll_margin;
2871
2872 /* Don't use a scroll margin that is negative or too large. */
2873 if (this_scroll_margin < 0)
2874 this_scroll_margin = 0;
2875
2876 if (XINT (w->height) < 4 * scroll_margin)
2877 this_scroll_margin = XINT (w->height) / 4;
2878
b73ea88e 2879 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
7ab12479
JB
2880 w->start_at_line_beg = bolp;
2881 w->update_mode_line = Qt;
d834a2e9 2882 XSETFASTINT (w->last_modified, 0);
3cd21523 2883 XSETFASTINT (w->last_overlay_modified, 0);
345d45b2
RS
2884 /* Set force_start so that redisplay_window will run
2885 the window-scroll-functions. */
2886 w->force_start = Qt;
0c7da84e 2887
9317a85d 2888 if (whole && scroll_preserve_screen_position)
0c7da84e 2889 {
b73ea88e 2890 SET_PT_BOTH (pos, pos_byte);
101d1605 2891 Fvertical_motion (make_number (original_vpos), window);
0c7da84e 2892 }
101d1605
RS
2893 /* If we scrolled forward, put point enough lines down
2894 that it is outside the scroll margin. */
2895 else if (n > 0)
0c7da84e 2896 {
101d1605
RS
2897 int top_margin;
2898
2899 if (this_scroll_margin > 0)
2900 {
b73ea88e 2901 SET_PT_BOTH (pos, pos_byte);
101d1605
RS
2902 Fvertical_motion (make_number (this_scroll_margin), window);
2903 top_margin = PT;
2904 }
2905 else
2906 top_margin = pos;
2907
2908 if (top_margin <= opoint)
b73ea88e 2909 SET_PT_BOTH (opoint, opoint_byte);
9317a85d 2910 else if (scroll_preserve_screen_position)
101d1605 2911 {
b73ea88e 2912 SET_PT_BOTH (pos, pos_byte);
101d1605
RS
2913 Fvertical_motion (make_number (original_vpos), window);
2914 }
9317a85d 2915 else
335406fc 2916 SET_PT (top_margin);
0c7da84e 2917 }
101d1605 2918 else if (n < 0)
7ab12479 2919 {
101d1605
RS
2920 int bottom_margin;
2921
0c7da84e
RS
2922 /* If we scrolled backward, put point near the end of the window
2923 but not within the scroll margin. */
b73ea88e 2924 SET_PT_BOTH (pos, pos_byte);
0c7da84e 2925 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
101d1605
RS
2926 if (XFASTINT (tem) == ht - this_scroll_margin)
2927 bottom_margin = PT;
2928 else
2929 bottom_margin = PT + 1;
2930
2931 if (bottom_margin > opoint)
b73ea88e 2932 SET_PT_BOTH (opoint, opoint_byte);
7ab12479 2933 else
101d1605 2934 {
9317a85d
RS
2935 if (scroll_preserve_screen_position)
2936 {
b73ea88e 2937 SET_PT_BOTH (pos, pos_byte);
9317a85d
RS
2938 Fvertical_motion (make_number (original_vpos), window);
2939 }
2940 else
2941 Fvertical_motion (make_number (-1), window);
101d1605 2942 }
7ab12479
JB
2943 }
2944 }
2945 else
f8026fd8
JB
2946 {
2947 if (noerror)
2948 return;
2949 else
2950 Fsignal (Qend_of_buffer, Qnil);
2951 }
7ab12479
JB
2952}
2953\f
2954/* This is the guts of Fscroll_up and Fscroll_down. */
2955
2956static void
2957scroll_command (n, direction)
2958 register Lisp_Object n;
2959 int direction;
2960{
2961 register int defalt;
2962 int count = specpdl_ptr - specpdl;
2963
95605e15
JB
2964 /* If selected window's buffer isn't current, make it current for the moment.
2965 But don't screw up if window_scroll gets an error. */
7ab12479 2966 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
95605e15
JB
2967 {
2968 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2969 Fset_buffer (XWINDOW (selected_window)->buffer);
2970 }
7ab12479
JB
2971
2972 defalt = (window_internal_height (XWINDOW (selected_window))
2973 - next_screen_context_lines);
2974 defalt = direction * (defalt < 1 ? 1 : defalt);
2975
265a9e55 2976 if (NILP (n))
101d1605 2977 window_scroll (selected_window, defalt, 1, 0);
7ab12479 2978 else if (EQ (n, Qminus))
101d1605 2979 window_scroll (selected_window, - defalt, 1, 0);
7ab12479
JB
2980 else
2981 {
2982 n = Fprefix_numeric_value (n);
101d1605 2983 window_scroll (selected_window, XINT (n) * direction, 0, 0);
7ab12479 2984 }
95605e15
JB
2985
2986 unbind_to (count, Qnil);
7ab12479
JB
2987}
2988
2989DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2990 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2991A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 2992Negative ARG means scroll downward.\n\
a5fcbc4e
RS
2993If ARG is the atom `-', scroll downward by nearly full screen.
2994When calling from a program, supply as argument a number, nil, or '-.")
413430c5
EN
2995 (arg)
2996 Lisp_Object arg;
7ab12479 2997{
413430c5 2998 scroll_command (arg, 1);
7ab12479
JB
2999 return Qnil;
3000}
3001
3002DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
a5fcbc4e 3003 "Scroll text of current window down ARG lines; or near full screen if no ARG.\n\
7ab12479 3004A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 3005Negative ARG means scroll upward.\n\
a5fcbc4e
RS
3006If ARG is the atom `-', scroll upward by nearly full screen.
3007When calling from a program, supply as argument a number, nil, or '-.")
413430c5
EN
3008 (arg)
3009 Lisp_Object arg;
7ab12479 3010{
413430c5 3011 scroll_command (arg, -1);
7ab12479
JB
3012 return Qnil;
3013}
ccd0664b
RS
3014\f
3015DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
3016 "Return the other window for \"other window scroll\" commands.\n\
77b24de6 3017If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
ccd0664b
RS
3018specifies the window.\n\
3019If `other-window-scroll-buffer' is non-nil, a window\n\
3020showing that buffer is used.")
eb16ec06 3021 ()
7ab12479 3022{
ccd0664b 3023 Lisp_Object window;
7ab12479
JB
3024
3025 if (MINI_WINDOW_P (XWINDOW (selected_window))
265a9e55 3026 && !NILP (Vminibuf_scroll_window))
7ab12479
JB
3027 window = Vminibuf_scroll_window;
3028 /* If buffer is specified, scroll that buffer. */
265a9e55 3029 else if (!NILP (Vother_window_scroll_buffer))
7ab12479
JB
3030 {
3031 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
265a9e55 3032 if (NILP (window))
53f76081 3033 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
7ab12479
JB
3034 }
3035 else
dbc4e1c1
JB
3036 {
3037 /* Nothing specified; look for a neighboring window on the same
3038 frame. */
3039 window = Fnext_window (selected_window, Qnil, Qnil);
3040
3041 if (EQ (window, selected_window))
3042 /* That didn't get us anywhere; look for a window on another
3043 visible frame. */
3044 do
3045 window = Fnext_window (window, Qnil, Qt);
3046 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
3047 && ! EQ (window, selected_window));
3048 }
3049
605be8af 3050 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
3051
3052 if (EQ (window, selected_window))
3053 error ("There is no other window");
3054
ccd0664b
RS
3055 return window;
3056}
3057
3058DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
3059 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
a5fcbc4e 3060A near full screen is `next-screen-context-lines' less than a full screen.
ccd0664b
RS
3061The next window is the one below the current one; or the one at the top\n\
3062if the current one is at the bottom. Negative ARG means scroll downward.\n\
a5fcbc4e
RS
3063If ARG is the atom `-', scroll downward by nearly full screen.
3064When calling from a program, supply as argument a number, nil, or '-.\n\
ccd0664b
RS
3065\n\
3066If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
3067specifies the window to scroll.\n\
3068If `other-window-scroll-buffer' is non-nil, scroll the window\n\
3069showing that buffer, popping the buffer up if necessary.")
413430c5
EN
3070 (arg)
3071 register Lisp_Object arg;
ccd0664b
RS
3072{
3073 register Lisp_Object window;
2f787aa3 3074 register int defalt;
ccd0664b
RS
3075 register struct window *w;
3076 register int count = specpdl_ptr - specpdl;
3077
3078 window = Fother_window_for_scrolling ();
3079
7ab12479 3080 w = XWINDOW (window);
2f787aa3
KH
3081 defalt = window_internal_height (w) - next_screen_context_lines;
3082 if (defalt < 1) defalt = 1;
7ab12479
JB
3083
3084 /* Don't screw up if window_scroll gets an error. */
3085 record_unwind_protect (save_excursion_restore, save_excursion_save ());
3086
3087 Fset_buffer (w->buffer);
3088 SET_PT (marker_position (w->pointm));
3089
413430c5 3090 if (NILP (arg))
101d1605 3091 window_scroll (window, defalt, 1, 1);
413430c5 3092 else if (EQ (arg, Qminus))
101d1605 3093 window_scroll (window, -defalt, 1, 1);
7ab12479
JB
3094 else
3095 {
413430c5
EN
3096 if (CONSP (arg))
3097 arg = Fcar (arg);
3098 CHECK_NUMBER (arg, 0);
101d1605 3099 window_scroll (window, XINT (arg), 0, 1);
7ab12479
JB
3100 }
3101
b73ea88e 3102 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
f4e7b2c2 3103 unbind_to (count, Qnil);
7ab12479
JB
3104
3105 return Qnil;
3106}
3107\f
644b477c 3108DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
7ab12479
JB
3109 "Scroll selected window display ARG columns left.\n\
3110Default for ARG is window width minus 2.")
3111 (arg)
3112 register Lisp_Object arg;
3113{
3114
265a9e55 3115 if (NILP (arg))
d834a2e9 3116 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
7ab12479
JB
3117 else
3118 arg = Fprefix_numeric_value (arg);
3119
3120 return
3121 Fset_window_hscroll (selected_window,
3122 make_number (XINT (XWINDOW (selected_window)->hscroll)
3123 + XINT (arg)));
3124}
3125
644b477c 3126DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
7ab12479
JB
3127 "Scroll selected window display ARG columns right.\n\
3128Default for ARG is window width minus 2.")
3129 (arg)
3130 register Lisp_Object arg;
3131{
265a9e55 3132 if (NILP (arg))
d834a2e9 3133 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
7ab12479
JB
3134 else
3135 arg = Fprefix_numeric_value (arg);
3136
3137 return
3138 Fset_window_hscroll (selected_window,
3139 make_number (XINT (XWINDOW (selected_window)->hscroll)
3140 - XINT (arg)));
3141}
3142
3143DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
44fa5b1e 3144 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
7ab12479 3145The desired position of point is always relative to the current window.\n\
44fa5b1e 3146Just C-u as prefix means put point in the center of the window.\n\
413430c5 3147If ARG is omitted or nil, erases the entire frame and then\n\
44fa5b1e 3148redraws with point in the center of the current window.")
413430c5
EN
3149 (arg)
3150 register Lisp_Object arg;
7ab12479
JB
3151{
3152 register struct window *w = XWINDOW (selected_window);
3153 register int ht = window_internal_height (w);
113d9015 3154 struct position pos;
478292ed
RS
3155 struct buffer *buf = XBUFFER (w->buffer);
3156 struct buffer *obuf = current_buffer;
7ab12479 3157
413430c5 3158 if (NILP (arg))
7ab12479 3159 {
44fa5b1e 3160 extern int frame_garbaged;
7ab12479 3161
44fa5b1e 3162 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
413430c5 3163 XSETFASTINT (arg, ht / 2);
7ab12479 3164 }
413430c5 3165 else if (CONSP (arg)) /* Just C-u. */
7ab12479 3166 {
413430c5 3167 XSETFASTINT (arg, ht / 2);
7ab12479
JB
3168 }
3169 else
3170 {
413430c5
EN
3171 arg = Fprefix_numeric_value (arg);
3172 CHECK_NUMBER (arg, 0);
7ab12479
JB
3173 }
3174
413430c5
EN
3175 if (XINT (arg) < 0)
3176 XSETINT (arg, XINT (arg) + ht);
7ab12479 3177
478292ed 3178 set_buffer_internal (buf);
6ec8bbd2 3179 pos = *vmotion (PT, - XINT (arg), w);
7ab12479 3180
b73ea88e
RS
3181 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
3182 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
3183 || FETCH_BYTE (pos.bytepos - 1) == '\n')
113d9015 3184 ? Qt : Qnil);
7ab12479 3185 w->force_start = Qt;
478292ed 3186 set_buffer_internal (obuf);
7ab12479
JB
3187
3188 return Qnil;
3189}
3190\f
3191DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
3192 1, 1, "P",
3193 "Position point relative to window.\n\
19e3bf0a 3194With no argument, position point at center of window.\n\
44fa5b1e 3195An argument specifies frame line; zero means top of window,\n\
7ab12479
JB
3196negative means relative to bottom of window.")
3197 (arg)
3198 register Lisp_Object arg;
3199{
3200 register struct window *w = XWINDOW (selected_window);
3201 register int height = window_internal_height (w);
3202 register int start;
540b6aa0 3203 Lisp_Object window;
7ab12479 3204
265a9e55 3205 if (NILP (arg))
d834a2e9 3206 XSETFASTINT (arg, height / 2);
7ab12479
JB
3207 else
3208 {
3209 arg = Fprefix_numeric_value (arg);
3210 if (XINT (arg) < 0)
3211 XSETINT (arg, XINT (arg) + height);
3212 }
3213
3214 start = marker_position (w->start);
74112613 3215 XSETWINDOW (window, w);
7ab12479
JB
3216 if (start < BEGV || start > ZV)
3217 {
cd2be1dd 3218 Fvertical_motion (make_number (- (height / 2)), window);
b73ea88e 3219 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
7ab12479
JB
3220 w->start_at_line_beg = Fbolp ();
3221 w->force_start = Qt;
3222 }
3223 else
b73ea88e 3224 Fgoto_char (w->start);
7ab12479 3225
540b6aa0 3226 return Fvertical_motion (arg, window);
7ab12479
JB
3227}
3228\f
3229struct save_window_data
3230 {
f5ccc0cc 3231 EMACS_INT size_from_Lisp_Vector_struct;
7ab12479 3232 struct Lisp_Vector *next_from_Lisp_Vector_struct;
8f6ea2e9 3233 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
bdc727bf 3234 Lisp_Object selected_frame;
7ab12479
JB
3235 Lisp_Object current_window;
3236 Lisp_Object current_buffer;
3237 Lisp_Object minibuf_scroll_window;
3238 Lisp_Object root_window;
bdc727bf 3239 Lisp_Object focus_frame;
756b6edc
RS
3240 /* Record the values of window-min-width and window-min-height
3241 so that window sizes remain consistent with them. */
3242 Lisp_Object min_width, min_height;
cbff28e8
RS
3243 /* A vector, each of whose elements is a struct saved_window
3244 for one window. */
7ab12479
JB
3245 Lisp_Object saved_windows;
3246 };
ff06df24 3247
cbff28e8 3248/* This is saved as a Lisp_Vector */
7ab12479
JB
3249struct saved_window
3250 {
3251 /* these first two must agree with struct Lisp_Vector in lisp.h */
f5ccc0cc 3252 EMACS_INT size_from_Lisp_Vector_struct;
7ab12479
JB
3253 struct Lisp_Vector *next_from_Lisp_Vector_struct;
3254
3255 Lisp_Object window;
3256 Lisp_Object buffer, start, pointm, mark;
3257 Lisp_Object left, top, width, height, hscroll;
3258 Lisp_Object parent, prev;
3259 Lisp_Object start_at_line_beg;
3260 Lisp_Object display_table;
3261 };
3262#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
3263
3264#define SAVED_WINDOW_N(swv,n) \
3265 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
3266
3267DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
cbff28e8 3268 "Return t if OBJECT is a window-configuration object.")
413430c5
EN
3269 (object)
3270 Lisp_Object object;
7ab12479 3271{
413430c5 3272 if (WINDOW_CONFIGURATIONP (object))
7ab12479
JB
3273 return Qt;
3274 return Qnil;
3275}
3276
d5b2799e
RS
3277DEFUN ("set-window-configuration", Fset_window_configuration,
3278 Sset_window_configuration, 1, 1, 0,
7ab12479
JB
3279 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
3280CONFIGURATION must be a value previously returned\n\
3281by `current-window-configuration' (which see).")
2f83aebe
JB
3282 (configuration)
3283 Lisp_Object configuration;
7ab12479 3284{
7ab12479
JB
3285 register struct save_window_data *data;
3286 struct Lisp_Vector *saved_windows;
7ab12479 3287 Lisp_Object new_current_buffer;
fd482be5 3288 Lisp_Object frame;
44fa5b1e 3289 FRAME_PTR f;
d2b35234 3290 int old_point = -1;
7ab12479 3291
017b2bad 3292 while (!WINDOW_CONFIGURATIONP (configuration))
7ab12479 3293 {
2f83aebe
JB
3294 configuration = wrong_type_argument (intern ("window-configuration-p"),
3295 configuration);
7ab12479
JB
3296 }
3297
2f83aebe 3298 data = (struct save_window_data *) XVECTOR (configuration);
7ab12479
JB
3299 saved_windows = XVECTOR (data->saved_windows);
3300
7ab12479 3301 new_current_buffer = data->current_buffer;
265a9e55 3302 if (NILP (XBUFFER (new_current_buffer)->name))
7ab12479 3303 new_current_buffer = Qnil;
d2b35234
RS
3304 else
3305 {
3306 if (XBUFFER (new_current_buffer) == current_buffer)
3307 old_point = PT;
cbff28e8 3308
d2b35234 3309 }
7ab12479 3310
fd482be5
JB
3311 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
3312 f = XFRAME (frame);
9ace597f 3313
fd482be5
JB
3314 /* If f is a dead frame, don't bother rebuilding its window tree.
3315 However, there is other stuff we should still try to do below. */
3316 if (FRAME_LIVE_P (f))
7ab12479 3317 {
fd482be5
JB
3318 register struct window *w;
3319 register struct saved_window *p;
3320 int k;
3321
3322 /* If the frame has been resized since this window configuration was
3323 made, we change the frame to the size specified in the
3324 configuration, restore the configuration, and then resize it
3325 back. We keep track of the prevailing height in these variables. */
3326 int previous_frame_height = FRAME_HEIGHT (f);
3327 int previous_frame_width = FRAME_WIDTH (f);
8f6ea2e9 3328 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
fd482be5 3329
d2b35234
RS
3330 /* The mouse highlighting code could get screwed up
3331 if it runs during this. */
3332 BLOCK_INPUT;
3333
fd482be5
JB
3334 if (XFASTINT (data->frame_height) != previous_frame_height
3335 || XFASTINT (data->frame_width) != previous_frame_width)
f8ad443a
AS
3336 change_frame_size (f, XFASTINT (data->frame_height),
3337 XFASTINT (data->frame_width), 0, 0);
e3678b64 3338#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
8f6ea2e9
KH
3339 if (XFASTINT (data->frame_menu_bar_lines)
3340 != previous_frame_menu_bar_lines)
f8ad443a 3341 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
217f2871 3342#endif
fd482be5 3343
596ae0cf
RS
3344 if (! NILP (XWINDOW (selected_window)->buffer))
3345 {
3346 w = XWINDOW (selected_window);
3347 set_marker_both (w->pointm,
3348 w->buffer,
3349 BUF_PT (XBUFFER (w->buffer)),
3350 BUF_PT_BYTE (XBUFFER (w->buffer)));
3351 }
3352
fd482be5 3353 windows_or_buffers_changed++;
29aeee73 3354 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
fd482be5 3355
756b6edc
RS
3356 /* Temporarily avoid any problems with windows that are smaller
3357 than they are supposed to be. */
3358 window_min_height = 1;
3359 window_min_width = 1;
3360
fd482be5
JB
3361 /* Kludge Alert!
3362 Mark all windows now on frame as "deleted".
3363 Restoring the new configuration "undeletes" any that are in it.
37962e60 3364
fd482be5
JB
3365 Save their current buffers in their height fields, since we may
3366 need it later, if a buffer saved in the configuration is now
3367 dead. */
3368 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
3369
3370 for (k = 0; k < saved_windows->size; k++)
3371 {
3372 p = SAVED_WINDOW_N (saved_windows, k);
3373 w = XWINDOW (p->window);
3374 w->next = Qnil;
7ab12479 3375
fd482be5
JB
3376 if (!NILP (p->parent))
3377 w->parent = SAVED_WINDOW_N (saved_windows,
3378 XFASTINT (p->parent))->window;
3379 else
3380 w->parent = Qnil;
7ab12479 3381
fd482be5 3382 if (!NILP (p->prev))
7ab12479 3383 {
fd482be5
JB
3384 w->prev = SAVED_WINDOW_N (saved_windows,
3385 XFASTINT (p->prev))->window;
3386 XWINDOW (w->prev)->next = p->window;
3387 }
3388 else
3389 {
3390 w->prev = Qnil;
3391 if (!NILP (w->parent))
3392 {
3393 if (EQ (p->width, XWINDOW (w->parent)->width))
3394 {
3395 XWINDOW (w->parent)->vchild = p->window;
3396 XWINDOW (w->parent)->hchild = Qnil;
3397 }
3398 else
3399 {
3400 XWINDOW (w->parent)->hchild = p->window;
3401 XWINDOW (w->parent)->vchild = Qnil;
3402 }
3403 }
3404 }
3405
3406 /* If we squirreled away the buffer in the window's height,
3407 restore it now. */
017b2bad 3408 if (BUFFERP (w->height))
fd482be5
JB
3409 w->buffer = w->height;
3410 w->left = p->left;
3411 w->top = p->top;
3412 w->width = p->width;
3413 w->height = p->height;
3414 w->hscroll = p->hscroll;
3415 w->display_table = p->display_table;
d834a2e9 3416 XSETFASTINT (w->last_modified, 0);
3cd21523 3417 XSETFASTINT (w->last_overlay_modified, 0);
fd482be5
JB
3418
3419 /* Reinstall the saved buffer and pointers into it. */
3420 if (NILP (p->buffer))
3421 w->buffer = p->buffer;
3422 else
3423 {
3424 if (!NILP (XBUFFER (p->buffer)->name))
3425 /* If saved buffer is alive, install it. */
3426 {
3427 w->buffer = p->buffer;
3428 w->start_at_line_beg = p->start_at_line_beg;
b73ea88e
RS
3429 set_marker_restricted (w->start, p->start, w->buffer);
3430 set_marker_restricted (w->pointm, p->pointm, w->buffer);
fd482be5 3431 Fset_marker (XBUFFER (w->buffer)->mark,
b73ea88e 3432 p->mark, w->buffer);
fd482be5
JB
3433
3434 /* As documented in Fcurrent_window_configuration, don't
3435 save the location of point in the buffer which was current
3436 when the window configuration was recorded. */
6b54027b
RS
3437 if (!EQ (p->buffer, new_current_buffer)
3438 && XBUFFER (p->buffer) == current_buffer)
fd482be5
JB
3439 Fgoto_char (w->pointm);
3440 }
52a68e98
RS
3441 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
3442 /* Else unless window has a live buffer, get one. */
7ab12479 3443 {
fd482be5
JB
3444 w->buffer = Fcdr (Fcar (Vbuffer_alist));
3445 /* This will set the markers to beginning of visible
3446 range. */
3447 set_marker_restricted (w->start, make_number (0), w->buffer);
3448 set_marker_restricted (w->pointm, make_number (0),w->buffer);
3449 w->start_at_line_beg = Qt;
7ab12479
JB
3450 }
3451 else
fd482be5 3452 /* Keeping window's old buffer; make sure the markers
52a68e98 3453 are real. */
7ab12479 3454 {
fd482be5
JB
3455 /* Set window markers at start of visible range. */
3456 if (XMARKER (w->start)->buffer == 0)
3457 set_marker_restricted (w->start, make_number (0),
3458 w->buffer);
3459 if (XMARKER (w->pointm)->buffer == 0)
b73ea88e
RS
3460 set_marker_restricted_both (w->pointm, w->buffer,
3461 BUF_PT (XBUFFER (w->buffer)),
3462 BUF_PT_BYTE (XBUFFER (w->buffer)));
fd482be5 3463 w->start_at_line_beg = Qt;
7ab12479
JB
3464 }
3465 }
3466 }
9ace597f 3467
fd482be5
JB
3468 FRAME_ROOT_WINDOW (f) = data->root_window;
3469 Fselect_window (data->current_window);
396a830c
RS
3470 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
3471 = selected_window;
7ab12479 3472
db269683 3473 if (NILP (data->focus_frame)
017b2bad 3474 || (FRAMEP (data->focus_frame)
db269683
JB
3475 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
3476 Fredirect_frame_focus (frame, data->focus_frame);
7ab12479 3477
fd482be5
JB
3478#if 0 /* I don't understand why this is needed, and it causes problems
3479 when the frame's old selected window has been deleted. */
e4e59717 3480 if (f != selected_frame && FRAME_WINDOW_P (f))
9a7c6fc3
RS
3481 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
3482 Qnil, 0);
fd482be5
JB
3483#endif
3484
3485 /* Set the screen height to the value it had before this function. */
3486 if (previous_frame_height != FRAME_HEIGHT (f)
3487 || previous_frame_width != FRAME_WIDTH (f))
3488 change_frame_size (f, previous_frame_height, previous_frame_width,
3489 0, 0);
e3678b64 3490#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
8f6ea2e9 3491 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
f8ad443a
AS
3492 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
3493 make_number (0));
217f2871 3494#endif
d2b35234
RS
3495
3496 UNBLOCK_INPUT;
756b6edc 3497
478292ed
RS
3498 /* Fselect_window will have made f the selected frame, so we
3499 reselect the proper frame here. Fhandle_switch_frame will change the
3500 selected window too, but that doesn't make the call to
3501 Fselect_window above totally superfluous; it still sets f's
3502 selected window. */
3503 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
3504 do_switch_frame (data->selected_frame, Qnil, 0);
3505
3506 if (! NILP (Vwindow_configuration_change_hook)
3507 && ! NILP (Vrun_hooks))
3508 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3509 }
bdc727bf
JB
3510
3511 if (!NILP (new_current_buffer))
d2b35234
RS
3512 {
3513 Fset_buffer (new_current_buffer);
3514
3515 /* If the buffer that is current now is the same
3516 that was current before setting the window configuration,
3517 don't alter its PT. */
3518 if (old_point >= 0)
3519 SET_PT (old_point);
3520 }
bdc727bf 3521
478292ed
RS
3522 /* Restore the minimum heights recorded in the configuration. */
3523 window_min_height = XINT (data->min_height);
3524 window_min_width = XINT (data->min_width);
543f5fb1 3525
478292ed 3526 Vminibuf_scroll_window = data->minibuf_scroll_window;
543f5fb1 3527
478292ed 3528 return Qnil;
7ab12479
JB
3529}
3530
44fa5b1e 3531/* Mark all windows now on frame as deleted
7ab12479
JB
3532 by setting their buffers to nil. */
3533
fd482be5 3534void
7ab12479
JB
3535delete_all_subwindows (w)
3536 register struct window *w;
3537{
265a9e55 3538 if (!NILP (w->next))
7ab12479 3539 delete_all_subwindows (XWINDOW (w->next));
265a9e55 3540 if (!NILP (w->vchild))
7ab12479 3541 delete_all_subwindows (XWINDOW (w->vchild));
265a9e55 3542 if (!NILP (w->hchild))
7ab12479 3543 delete_all_subwindows (XWINDOW (w->hchild));
605be8af
JB
3544
3545 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
3546
86e48436
RS
3547 if (!NILP (w->buffer))
3548 unshow_buffer (w);
3549
605be8af
JB
3550 /* We set all three of these fields to nil, to make sure that we can
3551 distinguish this dead window from any live window. Live leaf
3552 windows will have buffer set, and combination windows will have
3553 vchild or hchild set. */
3554 w->buffer = Qnil;
3555 w->vchild = Qnil;
3556 w->hchild = Qnil;
7ab12479
JB
3557}
3558\f
3559static int
3560count_windows (window)
3561 register struct window *window;
3562{
3563 register int count = 1;
265a9e55 3564 if (!NILP (window->next))
7ab12479 3565 count += count_windows (XWINDOW (window->next));
265a9e55 3566 if (!NILP (window->vchild))
7ab12479 3567 count += count_windows (XWINDOW (window->vchild));
265a9e55 3568 if (!NILP (window->hchild))
7ab12479
JB
3569 count += count_windows (XWINDOW (window->hchild));
3570 return count;
3571}
3572
3573static int
3574save_window_save (window, vector, i)
3575 Lisp_Object window;
3576 struct Lisp_Vector *vector;
3577 int i;
3578{
3579 register struct saved_window *p;
3580 register struct window *w;
3581 register Lisp_Object tem;
3582
265a9e55 3583 for (;!NILP (window); window = w->next)
7ab12479
JB
3584 {
3585 p = SAVED_WINDOW_N (vector, i);
3586 w = XWINDOW (window);
3587
d834a2e9 3588 XSETFASTINT (w->temslot, i++);
7ab12479
JB
3589 p->window = window;
3590 p->buffer = w->buffer;
3591 p->left = w->left;
3592 p->top = w->top;
3593 p->width = w->width;
3594 p->height = w->height;
3595 p->hscroll = w->hscroll;
3596 p->display_table = w->display_table;
265a9e55 3597 if (!NILP (w->buffer))
7ab12479
JB
3598 {
3599 /* Save w's value of point in the window configuration.
3600 If w is the selected window, then get the value of point
3601 from the buffer; pointm is garbage in the selected window. */
3602 if (EQ (window, selected_window))
3603 {
3604 p->pointm = Fmake_marker ();
b73ea88e
RS
3605 set_marker_both (p->pointm, w->buffer,
3606 BUF_PT (XBUFFER (w->buffer)),
3607 BUF_PT_BYTE (XBUFFER (w->buffer)));
7ab12479
JB
3608 }
3609 else
eeb82665 3610 p->pointm = Fcopy_marker (w->pointm, Qnil);
7ab12479 3611
eeb82665 3612 p->start = Fcopy_marker (w->start, Qnil);
7ab12479
JB
3613 p->start_at_line_beg = w->start_at_line_beg;
3614
3615 tem = XBUFFER (w->buffer)->mark;
eeb82665 3616 p->mark = Fcopy_marker (tem, Qnil);
7ab12479
JB
3617 }
3618 else
3619 {
3620 p->pointm = Qnil;
3621 p->start = Qnil;
3622 p->mark = Qnil;
3623 p->start_at_line_beg = Qnil;
3624 }
3625
265a9e55 3626 if (NILP (w->parent))
7ab12479
JB
3627 p->parent = Qnil;
3628 else
3629 p->parent = XWINDOW (w->parent)->temslot;
3630
265a9e55 3631 if (NILP (w->prev))
7ab12479
JB
3632 p->prev = Qnil;
3633 else
3634 p->prev = XWINDOW (w->prev)->temslot;
3635
265a9e55 3636 if (!NILP (w->vchild))
7ab12479 3637 i = save_window_save (w->vchild, vector, i);
265a9e55 3638 if (!NILP (w->hchild))
7ab12479
JB
3639 i = save_window_save (w->hchild, vector, i);
3640 }
3641
3642 return i;
3643}
3644
a0d76c27
EN
3645DEFUN ("current-window-configuration", Fcurrent_window_configuration,
3646 Scurrent_window_configuration, 0, 1, 0,
44fa5b1e
JB
3647 "Return an object representing the current window configuration of FRAME.\n\
3648If FRAME is nil or omitted, use the selected frame.\n\
7ab12479
JB
3649This describes the number of windows, their sizes and current buffers,\n\
3650and for each displayed buffer, where display starts, and the positions of\n\
3651point and mark. An exception is made for point in the current buffer:\n\
bdc727bf
JB
3652its value is -not- saved.\n\
3653This also records the currently selected frame, and FRAME's focus\n\
3654redirection (see `redirect-frame-focus').")
44fa5b1e
JB
3655 (frame)
3656 Lisp_Object frame;
7ab12479
JB
3657{
3658 register Lisp_Object tem;
3659 register int n_windows;
3660 register struct save_window_data *data;
da2792e0 3661 register struct Lisp_Vector *vec;
7ab12479 3662 register int i;
44fa5b1e 3663 FRAME_PTR f;
43bad991 3664
44fa5b1e
JB
3665 if (NILP (frame))
3666 f = selected_frame;
43bad991
JB
3667 else
3668 {
44fa5b1e
JB
3669 CHECK_LIVE_FRAME (frame, 0);
3670 f = XFRAME (frame);
43bad991 3671 }
7ab12479 3672
44fa5b1e 3673 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
da2792e0
KH
3674 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
3675 for (i = 0; i < VECSIZE (struct save_window_data); i++)
3676 vec->contents[i] = Qnil;
3677 vec->size = VECSIZE (struct save_window_data);
3678 data = (struct save_window_data *)vec;
3679
d834a2e9
KH
3680 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
3681 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
3682 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
74112613 3683 XSETFRAME (data->selected_frame, selected_frame);
44fa5b1e 3684 data->current_window = FRAME_SELECTED_WINDOW (f);
74112613 3685 XSETBUFFER (data->current_buffer, current_buffer);
7ab12479 3686 data->minibuf_scroll_window = Vminibuf_scroll_window;
44fa5b1e 3687 data->root_window = FRAME_ROOT_WINDOW (f);
bdc727bf 3688 data->focus_frame = FRAME_FOCUS_FRAME (f);
74112613
KH
3689 XSETINT (data->min_height, window_min_height);
3690 XSETINT (data->min_width, window_min_width);
7ab12479
JB
3691 tem = Fmake_vector (make_number (n_windows), Qnil);
3692 data->saved_windows = tem;
3693 for (i = 0; i < n_windows; i++)
3694 XVECTOR (tem)->contents[i]
3695 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
44fa5b1e 3696 save_window_save (FRAME_ROOT_WINDOW (f),
7ab12479 3697 XVECTOR (tem), 0);
74112613 3698 XSETWINDOW_CONFIGURATION (tem, data);
7ab12479
JB
3699 return (tem);
3700}
3701
3702DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
3703 0, UNEVALLED, 0,
3704 "Execute body, preserving window sizes and contents.\n\
eb16ec06
RS
3705Restore which buffer appears in which window, where display starts,\n\
3706and the value of point and mark for each window.\n\
3707Also restore which buffer is current.\n\
3708But do not preserve point in the current buffer.\n\
7ab12479
JB
3709Does not restore the value of point in current buffer.")
3710 (args)
3711 Lisp_Object args;
3712{
3713 register Lisp_Object val;
3714 register int count = specpdl_ptr - specpdl;
3715
3716 record_unwind_protect (Fset_window_configuration,
43bad991 3717 Fcurrent_window_configuration (Qnil));
7ab12479
JB
3718 val = Fprogn (args);
3719 return unbind_to (count, val);
3720}
3721\f
cbff28e8
RS
3722/* Return 1 if window configurations C1 and C2
3723 describe the same state of affairs. This is used by Fequal. */
3724
3725int
2f8274be 3726compare_window_configurations (c1, c2, ignore_positions)
cbff28e8 3727 Lisp_Object c1, c2;
2f8274be 3728 int ignore_positions;
cbff28e8
RS
3729{
3730 register struct save_window_data *d1, *d2;
3731 struct Lisp_Vector *sw1, *sw2;
3732 int i;
3733
3734 d1 = (struct save_window_data *) XVECTOR (c1);
3735 d2 = (struct save_window_data *) XVECTOR (c2);
3736 sw1 = XVECTOR (d1->saved_windows);
3737 sw2 = XVECTOR (d2->saved_windows);
3738
3739 if (! EQ (d1->frame_width, d2->frame_width))
3740 return 0;
3741 if (! EQ (d1->frame_height, d2->frame_height))
3742 return 0;
3743 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
3744 return 0;
3745 if (! EQ (d1->selected_frame, d2->selected_frame))
3746 return 0;
3747 /* Don't compare the current_window field directly.
3748 Instead see w1_is_current and w2_is_current, below. */
3749 if (! EQ (d1->current_buffer, d2->current_buffer))
3750 return 0;
2f8274be
RS
3751 if (! ignore_positions)
3752 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
3753 return 0;
cbff28e8
RS
3754 /* Don't compare the root_window field.
3755 We don't require the two configurations
3756 to use the same window object,
3757 and the two root windows must be equivalent
3758 if everything else compares equal. */
3759 if (! EQ (d1->focus_frame, d2->focus_frame))
3760 return 0;
3761 if (! EQ (d1->min_width, d2->min_width))
3762 return 0;
3763 if (! EQ (d1->min_height, d2->min_height))
3764 return 0;
3765
3766 /* Verify that the two confis have the same number of windows. */
3767 if (sw1->size != sw2->size)
3768 return 0;
3769
3770 for (i = 0; i < sw1->size; i++)
3771 {
3772 struct saved_window *p1, *p2;
3773 int w1_is_current, w2_is_current;
3774
3775 p1 = SAVED_WINDOW_N (sw1, i);
3776 p2 = SAVED_WINDOW_N (sw2, i);
3777
3778 /* Verify that the current windows in the two
3779 configurations correspond to each other. */
3780 w1_is_current = EQ (d1->current_window, p1->window);
3781 w2_is_current = EQ (d2->current_window, p2->window);
3782
3783 if (w1_is_current != w2_is_current)
3784 return 0;
3785
3786 /* Verify that the corresponding windows do match. */
3787 if (! EQ (p1->buffer, p2->buffer))
3788 return 0;
3789 if (! EQ (p1->left, p2->left))
3790 return 0;
3791 if (! EQ (p1->top, p2->top))
3792 return 0;
3793 if (! EQ (p1->width, p2->width))
3794 return 0;
3795 if (! EQ (p1->height, p2->height))
3796 return 0;
cbff28e8
RS
3797 if (! EQ (p1->display_table, p2->display_table))
3798 return 0;
3799 if (! EQ (p1->parent, p2->parent))
3800 return 0;
3801 if (! EQ (p1->prev, p2->prev))
3802 return 0;
2f8274be
RS
3803 if (! ignore_positions)
3804 {
3805 if (! EQ (p1->hscroll, p2->hscroll))
3806 return 0;
3807 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
3808 return 0;
3809 if (NILP (Fequal (p1->start, p2->start)))
3810 return 0;
3811 if (NILP (Fequal (p1->pointm, p2->pointm)))
3812 return 0;
3813 if (NILP (Fequal (p1->mark, p2->mark)))
3814 return 0;
3815 }
cbff28e8
RS
3816 }
3817
3818 return 1;
3819}
2f8274be
RS
3820
3821DEFUN ("compare-window-configurations", Fcompare_window_configurations,
3822 Scompare_window_configurations, 2, 2, 0,
3823 "Compare two window configurations as regards the structure of windows.\n\
3824This function ignores details such as the values of point and mark\n\
3825and scrolling positions.")
3826 (x, y)
3827 Lisp_Object x, y;
3828{
3829 if (compare_window_configurations (x, y, 1))
3830 return Qt;
3831 return Qnil;
3832}
cbff28e8 3833\f
dfcf069d 3834void
7ab12479
JB
3835init_window_once ()
3836{
44fa5b1e 3837 selected_frame = make_terminal_frame ();
bc6c324f 3838 XSETFRAME (Vterminal_frame, selected_frame);
44fa5b1e
JB
3839 minibuf_window = selected_frame->minibuffer_window;
3840 selected_window = selected_frame->selected_window;
3841 last_nonminibuf_frame = selected_frame;
5b03d3c0
RS
3842
3843 window_initialized = 1;
7ab12479
JB
3844}
3845
dfcf069d 3846void
7ab12479
JB
3847syms_of_window ()
3848{
543f5fb1
RS
3849 staticpro (&Qwindow_configuration_change_hook);
3850 Qwindow_configuration_change_hook
3851 = intern ("window-configuration-change-hook");
3852
7ab12479
JB
3853 Qwindowp = intern ("windowp");
3854 staticpro (&Qwindowp);
3855
806b4d9b
JB
3856 Qwindow_live_p = intern ("window-live-p");
3857 staticpro (&Qwindow_live_p);
605be8af 3858
2cccc823 3859 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
a58ec57d
RS
3860 staticpro (&Qtemp_buffer_show_hook);
3861
7ab12479
JB
3862 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
3863 "Non-nil means call as function to display a help buffer.\n\
c3ef6b1d 3864The function is called with one argument, the buffer to be displayed.\n\
f52cca03
RS
3865Used by `with-output-to-temp-buffer'.\n\
3866If this function is used, then it must do the entire job of showing\n\
3867the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
7ab12479
JB
3868 Vtemp_buffer_show_function = Qnil;
3869
3870 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
3871 "If non-nil, function to call to handle `display-buffer'.\n\
3872It will receive two args, the buffer and a flag which if non-nil means\n\
3873 that the currently selected window is not acceptable.\n\
3874Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
3875work using this function.");
3876 Vdisplay_buffer_function = Qnil;
3877
7ab12479
JB
3878 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
3879 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
3880 Vminibuf_scroll_window = Qnil;
3881
3882 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
3883 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
3884 Vother_window_scroll_buffer = Qnil;
3885
44fa5b1e 3886 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
700f75a4 3887 "*Non-nil means `display-buffer' should make a separate frame.");
44fa5b1e 3888 pop_up_frames = 0;
7ab12479 3889
44fa5b1e 3890 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
a90712c2 3891 "Function to call to handle automatic new frame creation.\n\
44fa5b1e 3892It is called with no arguments and should return a newly created frame.\n\
7ab12479 3893\n\
44fa5b1e
JB
3894A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
3895where `pop-up-frame-alist' would hold the default frame parameters.");
3896 Vpop_up_frame_function = Qnil;
7ab12479 3897
a90712c2
RS
3898 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
3899 "*List of buffer names that should have their own special frames.\n\
3900Displaying a buffer whose name is in this list makes a special frame for it\n\
524580a4 3901using `special-display-function'. See also `special-display-regexps'.\n\
3548e138 3902\n\
524580a4
RS
3903An element of the list can be a list instead of just a string.\n\
3904There are two ways to use a list as an element:\n\
3905 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
3906In the first case, FRAME-PARAMETERS are used to create the frame.\n\
3907In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
3908followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
4caa7448
RS
3909All this is done by the function found in `special-display-function'.\n\
3910\n\
3911If this variable appears \"not to work\", because you add a name to it\n\
3912but that buffer still appears in the selected window, look at the\n\
3913values of `same-window-buffer-names' and `same-window-regexps'.\n\
3914Those variables take precedence over this one.");
a90712c2
RS
3915 Vspecial_display_buffer_names = Qnil;
3916
3917 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
3918 "*List of regexps saying which buffers should have their own special frames.\n\
3919If a buffer name matches one of these regexps, it gets its own frame.\n\
3920Displaying a buffer whose name is in this list makes a special frame for it\n\
0a952b57 3921using `special-display-function'.\n\
3548e138 3922\n\
524580a4
RS
3923An element of the list can be a list instead of just a string.\n\
3924There are two ways to use a list as an element:\n\
3925 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
3926In the first case, FRAME-PARAMETERS are used to create the frame.\n\
3927In the latter case, FUNCTION is called with the buffer as first argument,\n\
3928followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
4caa7448
RS
3929All this is done by the function found in `special-display-function'.\n\
3930\n\
3931If this variable appears \"not to work\", because you add a regexp to it\n\
3932but the matching buffers still appear in the selected window, look at the\n\
3933values of `same-window-buffer-names' and `same-window-regexps'.\n\
3934Those variables take precedence over this one.");
a90712c2
RS
3935 Vspecial_display_regexps = Qnil;
3936
3937 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
3938 "Function to call to make a new frame for a special buffer.\n\
0a952b57
RS
3939It is called with two arguments, the buffer and optional buffer specific\n\
3940data, and should return a window displaying that buffer.\n\
a90712c2 3941The default value makes a separate frame for the buffer,\n\
bdd3a802 3942using `special-display-frame-alist' to specify the frame parameters.\n\
a90712c2
RS
3943\n\
3944A buffer is special if its is listed in `special-display-buffer-names'\n\
3945or matches a regexp in `special-display-regexps'.");
3946 Vspecial_display_function = Qnil;
3947
855d8627
RS
3948 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
3949 "*List of buffer names that should appear in the selected window.\n\
3950Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
3951switches to it in the selected window, rather than making it appear\n\
2e5ce1a0 3952in some other window.\n\
855d8627
RS
3953\n\
3954An element of the list can be a cons cell instead of just a string.\n\
3955Then the car must be a string, which specifies the buffer name.\n\
3956This is for compatibility with `special-display-buffer-names';\n\
3957the cdr of the cons cell is ignored.\n\
3958\n\
3959See also `same-window-regexps'.");
3960 Vsame_window_buffer_names = Qnil;
3961
3962 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
3963 "*List of regexps saying which buffers should appear in the selected window.\n\
3964If a buffer name matches one of these regexps, then displaying it\n\
3965using `display-buffer' or `pop-to-buffer' switches to it\n\
3966in the selected window, rather than making it appear in some other window.\n\
3967\n\
3968An element of the list can be a cons cell instead of just a string.\n\
3969Then the car must be a string, which specifies the buffer name.\n\
3970This is for compatibility with `special-display-buffer-names';\n\
3971the cdr of the cons cell is ignored.\n\
3972\n\
3973See also `same-window-buffer-names'.");
3974 Vsame_window_regexps = Qnil;
3975
7ab12479
JB
3976 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
3977 "*Non-nil means display-buffer should make new windows.");
3978 pop_up_windows = 1;
3979
3980 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
3981 "*Number of lines of continuity when scrolling by screenfuls.");
3982 next_screen_context_lines = 2;
3983
3984 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
3985 "*display-buffer would prefer to split the largest window if this large.\n\
3986If there is only one window, it is split regardless of this value.");
3987 split_height_threshold = 500;
3988
3989 DEFVAR_INT ("window-min-height", &window_min_height,
3990 "*Delete any window less than this tall (including its mode line).");
3991 window_min_height = 4;
3992
3993 DEFVAR_INT ("window-min-width", &window_min_width,
3994 "*Delete any window less than this wide.");
3995 window_min_width = 10;
3996
9317a85d
RS
3997 DEFVAR_BOOL ("scroll-preserve-screen-position",
3998 &scroll_preserve_screen_position,
3999 "*Nonzero means scroll commands move point to keep its screen line unchanged.");
4000 scroll_preserve_screen_position = 0;
4001
543f5fb1
RS
4002 DEFVAR_LISP ("window-configuration-change-hook",
4003 &Vwindow_configuration_change_hook,
4004 "Functions to call when window configuration changes.\n\
e3e041eb 4005The selected frame is the one whose configuration has changed.");
543f5fb1
RS
4006 Vwindow_configuration_change_hook = Qnil;
4007
7ab12479
JB
4008 defsubr (&Sselected_window);
4009 defsubr (&Sminibuffer_window);
4010 defsubr (&Swindow_minibuffer_p);
4011 defsubr (&Swindowp);
806b4d9b 4012 defsubr (&Swindow_live_p);
7ab12479
JB
4013 defsubr (&Spos_visible_in_window_p);
4014 defsubr (&Swindow_buffer);
4015 defsubr (&Swindow_height);
4016 defsubr (&Swindow_width);
4017 defsubr (&Swindow_hscroll);
4018 defsubr (&Sset_window_hscroll);
190eb263
RS
4019 defsubr (&Swindow_redisplay_end_trigger);
4020 defsubr (&Sset_window_redisplay_end_trigger);
7ab12479 4021 defsubr (&Swindow_edges);
d5783c40
JB
4022 defsubr (&Scoordinates_in_window_p);
4023 defsubr (&Swindow_at);
7ab12479
JB
4024 defsubr (&Swindow_point);
4025 defsubr (&Swindow_start);
4026 defsubr (&Swindow_end);
4027 defsubr (&Sset_window_point);
4028 defsubr (&Sset_window_start);
4029 defsubr (&Swindow_dedicated_p);
d207b766 4030 defsubr (&Sset_window_dedicated_p);
7ab12479
JB
4031 defsubr (&Swindow_display_table);
4032 defsubr (&Sset_window_display_table);
4033 defsubr (&Snext_window);
4034 defsubr (&Sprevious_window);
4035 defsubr (&Sother_window);
4036 defsubr (&Sget_lru_window);
4037 defsubr (&Sget_largest_window);
4038 defsubr (&Sget_buffer_window);
4039 defsubr (&Sdelete_other_windows);
4040 defsubr (&Sdelete_windows_on);
4041 defsubr (&Sreplace_buffer_in_windows);
4042 defsubr (&Sdelete_window);
4043 defsubr (&Sset_window_buffer);
4044 defsubr (&Sselect_window);
4628f7a4
EN
4045 defsubr (&Sspecial_display_p);
4046 defsubr (&Ssame_window_p);
7ab12479
JB
4047 defsubr (&Sdisplay_buffer);
4048 defsubr (&Ssplit_window);
4049 defsubr (&Senlarge_window);
4050 defsubr (&Sshrink_window);
4051 defsubr (&Sscroll_up);
4052 defsubr (&Sscroll_down);
4053 defsubr (&Sscroll_left);
4054 defsubr (&Sscroll_right);
ccd0664b 4055 defsubr (&Sother_window_for_scrolling);
7ab12479
JB
4056 defsubr (&Sscroll_other_window);
4057 defsubr (&Srecenter);
4058 defsubr (&Smove_to_window_line);
4059 defsubr (&Swindow_configuration_p);
4060 defsubr (&Sset_window_configuration);
4061 defsubr (&Scurrent_window_configuration);
4062 defsubr (&Ssave_window_excursion);
2f8274be 4063 defsubr (&Scompare_window_configurations);
7ab12479
JB
4064}
4065
dfcf069d 4066void
7ab12479
JB
4067keys_of_window ()
4068{
4069 initial_define_key (control_x_map, '1', "delete-other-windows");
4070 initial_define_key (control_x_map, '2', "split-window");
4071 initial_define_key (control_x_map, '0', "delete-window");
4072 initial_define_key (control_x_map, 'o', "other-window");
4073 initial_define_key (control_x_map, '^', "enlarge-window");
4074 initial_define_key (control_x_map, '<', "scroll-left");
4075 initial_define_key (control_x_map, '>', "scroll-right");
4076
4077 initial_define_key (global_map, Ctl ('V'), "scroll-up");
4078 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
4079 initial_define_key (meta_map, 'v', "scroll-down");
4080
4081 initial_define_key (global_map, Ctl('L'), "recenter");
4082 initial_define_key (meta_map, 'r', "move-to-window-line");
4083}