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