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