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