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