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