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