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