(AT_WORD_BOUNDARY): Disable macro.
[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,
113 "Returns t if OBJ is a window.")
114 (obj)
115 Lisp_Object obj;
116{
017b2bad 117 return WINDOWP (obj) ? Qt : Qnil;
7ab12479
JB
118}
119
806b4d9b 120DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
605be8af
JB
121 "Returns t if OBJ is a window which is currently visible.")
122 (obj)
123 Lisp_Object obj;
124{
017b2bad 125 return (WINDOWP (obj) && ! NILP (XWINDOW (obj)->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 }
d5783c40
JB
1026 /* Which windows are acceptible?
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,
d5783c40
JB
1045 "Return the window preceeding WINDOW in canonical ordering of windows.\n\
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 }
fbdc1545 1188 /* Which windows are acceptible?
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
JB
1207argument ALL_FRAMES is non-nil, cycle through all frames.")
1208 (n, all_frames)
1209 register Lisp_Object n, all_frames;
7ab12479
JB
1210{
1211 register int i;
1212 register Lisp_Object w;
1213
1214 CHECK_NUMBER (n, 0);
1215 w = selected_window;
1216 i = XINT (n);
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}
1627\f
1628/* Set the height of WINDOW and all its inferiors. */
a481b3ea
JB
1629
1630/* The smallest acceptable dimensions for a window. Anything smaller
1631 might crash Emacs. */
1632#define MIN_SAFE_WINDOW_WIDTH (2)
1633#define MIN_SAFE_WINDOW_HEIGHT (2)
1634
1635/* Make sure that window_min_height and window_min_width are
1636 not too small; if they are, set them to safe minima. */
1637
1638static void
1639check_min_window_sizes ()
1640{
1641 /* Smaller values might permit a crash. */
1642 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1643 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1644 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1645 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1646}
1647
1648/* If *ROWS or *COLS are too small a size for FRAME, set them to the
1649 minimum allowable size. */
605be8af 1650void
a481b3ea 1651check_frame_size (frame, rows, cols)
605be8af
JB
1652 FRAME_PTR frame;
1653 int *rows, *cols;
a481b3ea 1654{
628df3bf
JB
1655 /* For height, we have to see:
1656 whether the frame has a minibuffer,
1657 whether it wants a mode line, and
1658 whether it has a menu bar. */
a481b3ea 1659 int min_height =
79f92720
JB
1660 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
1661 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
a481b3ea 1662 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
628df3bf
JB
1663 if (FRAME_MENU_BAR_LINES (frame) > 0)
1664 min_height += FRAME_MENU_BAR_LINES (frame);
a481b3ea
JB
1665
1666 if (*rows < min_height)
1667 *rows = min_height;
1668 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1669 *cols = MIN_SAFE_WINDOW_WIDTH;
1670}
1671
7ab12479
JB
1672/* Normally the window is deleted if it gets too small.
1673 nodelete nonzero means do not do this.
1674 (The caller should check later and do so if appropriate) */
1675
1676set_window_height (window, height, nodelete)
1677 Lisp_Object window;
1678 int height;
1679 int nodelete;
1680{
1681 register struct window *w = XWINDOW (window);
1682 register struct window *c;
1683 int oheight = XFASTINT (w->height);
1684 int top, pos, lastbot, opos, lastobot;
1685 Lisp_Object child;
1686
a481b3ea
JB
1687 check_min_window_sizes ();
1688
7ab12479 1689 if (!nodelete
265a9e55 1690 && ! NILP (w->parent)
7ab12479
JB
1691 && height < window_min_height)
1692 {
1693 Fdelete_window (window);
1694 return;
1695 }
1696
d834a2e9 1697 XSETFASTINT (w->last_modified, 0);
7ab12479 1698 windows_or_buffers_changed++;
29aeee73
RS
1699 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
1700
d834a2e9 1701 XSETFASTINT (w->height, height);
265a9e55 1702 if (!NILP (w->hchild))
7ab12479 1703 {
265a9e55 1704 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1705 {
1706 XWINDOW (child)->top = w->top;
1707 set_window_height (child, height, nodelete);
1708 }
1709 }
265a9e55 1710 else if (!NILP (w->vchild))
7ab12479
JB
1711 {
1712 lastbot = top = XFASTINT (w->top);
1713 lastobot = 0;
265a9e55 1714 for (child = w->vchild; !NILP (child); child = c->next)
7ab12479
JB
1715 {
1716 c = XWINDOW (child);
1717
1718 opos = lastobot + XFASTINT (c->height);
1719
d834a2e9 1720 XSETFASTINT (c->top, lastbot);
7ab12479
JB
1721
1722 pos = (((opos * height) << 1) + oheight) / (oheight << 1);
1723
1724 /* Avoid confusion: inhibit deletion of child if becomes too small */
1725 set_window_height (child, pos + top - lastbot, 1);
1726
1727 /* Now advance child to next window,
1728 and set lastbot if child was not just deleted. */
1729 lastbot = pos + top;
1730 lastobot = opos;
1731 }
1732 /* Now delete any children that became too small. */
1733 if (!nodelete)
265a9e55 1734 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1735 {
1736 set_window_height (child, XINT (XWINDOW (child)->height), 0);
1737 }
1738 }
1739}
1740
1741/* Recursively set width of WINDOW and its inferiors. */
1742
1743set_window_width (window, width, nodelete)
1744 Lisp_Object window;
1745 int width;
1746 int nodelete;
1747{
1748 register struct window *w = XWINDOW (window);
1749 register struct window *c;
1750 int owidth = XFASTINT (w->width);
1751 int left, pos, lastright, opos, lastoright;
1752 Lisp_Object child;
1753
abdced83 1754 if (!nodelete && width < window_min_width && !NILP (w->parent))
7ab12479
JB
1755 {
1756 Fdelete_window (window);
1757 return;
1758 }
1759
d834a2e9 1760 XSETFASTINT (w->last_modified, 0);
7ab12479 1761 windows_or_buffers_changed++;
29aeee73
RS
1762 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
1763
d834a2e9 1764 XSETFASTINT (w->width, width);
265a9e55 1765 if (!NILP (w->vchild))
7ab12479 1766 {
265a9e55 1767 for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1768 {
1769 XWINDOW (child)->left = w->left;
1770 set_window_width (child, width, nodelete);
1771 }
1772 }
265a9e55 1773 else if (!NILP (w->hchild))
7ab12479
JB
1774 {
1775 lastright = left = XFASTINT (w->left);
1776 lastoright = 0;
265a9e55 1777 for (child = w->hchild; !NILP (child); child = c->next)
7ab12479
JB
1778 {
1779 c = XWINDOW (child);
1780
1781 opos = lastoright + XFASTINT (c->width);
1782
d834a2e9 1783 XSETFASTINT (c->left, lastright);
7ab12479
JB
1784
1785 pos = (((opos * width) << 1) + owidth) / (owidth << 1);
1786
1787 /* Inhibit deletion for becoming too small */
1788 set_window_width (child, pos + left - lastright, 1);
1789
1790 /* Now advance child to next window,
1791 and set lastright if child was not just deleted. */
1792 lastright = pos + left, lastoright = opos;
1793 }
1794 /* Delete children that became too small */
1795 if (!nodelete)
265a9e55 1796 for (child = w->hchild; !NILP (child); child = XWINDOW (child)->next)
7ab12479
JB
1797 {
1798 set_window_width (child, XINT (XWINDOW (child)->width), 0);
1799 }
1800 }
1801}
1802\f
1d8d96fa 1803int window_select_count;
7ab12479
JB
1804
1805DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
1806 "Make WINDOW display BUFFER as its contents.\n\
1807BUFFER can be a buffer or buffer name.")
1808 (window, buffer)
1809 register Lisp_Object window, buffer;
1810{
1811 register Lisp_Object tem;
1812 register struct window *w = decode_window (window);
1813
1814 buffer = Fget_buffer (buffer);
1815 CHECK_BUFFER (buffer, 1);
1816
265a9e55 1817 if (NILP (XBUFFER (buffer)->name))
7ab12479
JB
1818 error ("Attempt to display deleted buffer");
1819
1820 tem = w->buffer;
265a9e55 1821 if (NILP (tem))
7ab12479
JB
1822 error ("Window is deleted");
1823 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
1824 is first being set up. */
1825 {
265a9e55 1826 if (!NILP (w->dedicated) && !EQ (tem, buffer))
3cf85532
RS
1827 error ("Window is dedicated to `%s'",
1828 XSTRING (XBUFFER (tem)->name)->data);
7ab12479
JB
1829
1830 unshow_buffer (w);
1831 }
1832
1833 w->buffer = buffer;
d834a2e9 1834 XSETFASTINT (w->window_end_pos, 0);
5a41ab94 1835 w->window_end_valid = Qnil;
d834a2e9 1836 XSETFASTINT(w->hscroll, 0);
7ab12479
JB
1837 Fset_marker (w->pointm,
1838 make_number (BUF_PT (XBUFFER (buffer))),
1839 buffer);
1840 set_marker_restricted (w->start,
1841 make_number (XBUFFER (buffer)->last_window_start),
1842 buffer);
1843 w->start_at_line_beg = Qnil;
e36ab06b 1844 w->force_start = Qnil;
d834a2e9 1845 XSETFASTINT (w->last_modified, 0);
7ab12479
JB
1846 windows_or_buffers_changed++;
1847 if (EQ (window, selected_window))
1848 Fset_buffer (buffer);
1849
1850 return Qnil;
1851}
1852
1853DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
1854 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
1855The main editor command loop selects the buffer of the selected window\n\
1856before each command.")
1857 (window)
1858 register Lisp_Object window;
1859{
1860 register struct window *w;
1861 register struct window *ow = XWINDOW (selected_window);
1862
605be8af 1863 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1864
1865 w = XWINDOW (window);
1866
265a9e55 1867 if (NILP (w->buffer))
7ab12479
JB
1868 error ("Trying to select deleted window or non-leaf window");
1869
d834a2e9 1870 XSETFASTINT (w->use_time, ++window_select_count);
7ab12479
JB
1871 if (EQ (window, selected_window))
1872 return window;
1873
1874 Fset_marker (ow->pointm, make_number (BUF_PT (XBUFFER (ow->buffer))),
1875 ow->buffer);
1876
1877 selected_window = window;
44fa5b1e
JB
1878#ifdef MULTI_FRAME
1879 if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
7ab12479 1880 {
44fa5b1e 1881 XFRAME (WINDOW_FRAME (w))->selected_window = window;
147a6615
RS
1882 /* Use this rather than Fhandle_switch_frame
1883 so that FRAME_FOCUS_FRAME is moved appropriately as we
1884 move around in the state where a minibuffer in a separate
1885 frame is active. */
1886 Fselect_frame (WINDOW_FRAME (w), Qnil);
7ab12479
JB
1887 }
1888 else
44fa5b1e 1889 selected_frame->selected_window = window;
7ab12479
JB
1890#endif
1891
1892 record_buffer (w->buffer);
1893 Fset_buffer (w->buffer);
1894
1895 /* Go to the point recorded in the window.
1896 This is important when the buffer is in more
1897 than one window. It also matters when
1898 redisplay_window has altered point after scrolling,
1899 because it makes the change only in the window. */
1900 {
1901 register int new_point = marker_position (w->pointm);
1902 if (new_point < BEGV)
1903 SET_PT (BEGV);
a9c95e08 1904 else if (new_point > ZV)
7ab12479
JB
1905 SET_PT (ZV);
1906 else
1907 SET_PT (new_point);
1908 }
1909
1910 windows_or_buffers_changed++;
1911 return window;
1912}
1913
d07f802a
RS
1914/* Deiconify the frame containing the window WINDOW, then return WINDOW. */
1915
1916static Lisp_Object
1917display_buffer_1 (window)
1918 Lisp_Object window;
1919{
1920#ifdef MULTI_FRAME
1921 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1922 FRAME_SAMPLE_VISIBILITY (f);
1923 if (FRAME_ICONIFIED_P (f))
1924 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
1925#endif
1926 return window;
1927}
1928
35aaf00c 1929DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
869e65bb 1930 "bDisplay buffer: \nP",
7ab12479
JB
1931 "Make BUFFER appear in some window but don't select it.\n\
1932BUFFER can be a buffer or a buffer name.\n\
1933If BUFFER is shown already in some window, just use that one,\n\
1934unless the window is the selected window and the optional second\n\
46d3268a 1935argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
5141b901 1936If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
7ab12479
JB
1937Returns the window displaying BUFFER.")
1938 (buffer, not_this_window)
1939 register Lisp_Object buffer, not_this_window;
1940{
a90712c2 1941 register Lisp_Object window, tem;
7ab12479
JB
1942
1943 buffer = Fget_buffer (buffer);
1944 CHECK_BUFFER (buffer, 0);
1945
265a9e55 1946 if (!NILP (Vdisplay_buffer_function))
7ab12479
JB
1947 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
1948
265a9e55 1949 if (NILP (not_this_window)
7ab12479 1950 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
d07f802a 1951 return display_buffer_1 (selected_window);
7ab12479 1952
855d8627
RS
1953 /* See if the user has specified this buffer should appear
1954 in the selected window. */
1955 if (NILP (not_this_window))
1956 {
1957 tem = Fmember (XBUFFER (buffer)->name, Vsame_window_buffer_names);
1958 if (!NILP (tem))
c63dc4a2
RS
1959 {
1960 Fswitch_to_buffer (buffer, Qnil);
d07f802a 1961 return display_buffer_1 (selected_window);
c63dc4a2 1962 }
855d8627
RS
1963
1964 tem = Fassoc (XBUFFER (buffer)->name, Vsame_window_buffer_names);
1965 if (!NILP (tem))
c63dc4a2
RS
1966 {
1967 Fswitch_to_buffer (buffer, Qnil);
d07f802a 1968 return display_buffer_1 (selected_window);
c63dc4a2 1969 }
855d8627
RS
1970
1971 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCONS (tem)->cdr)
1972 {
1973 Lisp_Object car = XCONS (tem)->car;
1974 if (STRINGP (car)
1975 && fast_string_match (car, XBUFFER (buffer)->name) >= 0)
c63dc4a2
RS
1976 {
1977 Fswitch_to_buffer (buffer, Qnil);
d07f802a 1978 return display_buffer_1 (selected_window);
c63dc4a2 1979 }
855d8627
RS
1980 else if (CONSP (car)
1981 && STRINGP (XCONS (car)->car)
1982 && fast_string_match (XCONS (car)->car,
1983 XBUFFER (buffer)->name) >= 0)
c63dc4a2
RS
1984 {
1985 Fswitch_to_buffer (buffer, Qnil);
d07f802a 1986 return display_buffer_1 (selected_window);
c63dc4a2 1987 }
855d8627
RS
1988 }
1989 }
1990
c6e73093 1991#ifdef MULTI_FRAME
e8edb3ae 1992 /* If pop_up_frames,
73dc5198
KH
1993 look for a window showing BUFFER on any visible or iconified frame.
1994 Otherwise search only the current frame. */
1995 if (pop_up_frames || last_nonminibuf_frame == 0)
1996 XSETFASTINT (tem, 0);
1997 else
c6e73093 1998#endif
73dc5198
KH
1999 XSETFRAME (tem, last_nonminibuf_frame);
2000 window = Fget_buffer_window (buffer, tem);
265a9e55
JB
2001 if (!NILP (window)
2002 && (NILP (not_this_window) || !EQ (window, selected_window)))
f812f9c6 2003 {
d07f802a 2004 return display_buffer_1 (window);
f812f9c6 2005 }
7ab12479 2006
a90712c2
RS
2007 /* Certain buffer names get special handling. */
2008 if (! NILP (Vspecial_display_function))
2009 {
2010 tem = Fmember (XBUFFER (buffer)->name, Vspecial_display_buffer_names);
2011 if (!NILP (tem))
2012 return call1 (Vspecial_display_function, buffer);
2013
0a952b57
RS
2014 tem = Fassoc (XBUFFER (buffer)->name, Vspecial_display_buffer_names);
2015 if (!NILP (tem))
2016 return call2 (Vspecial_display_function, buffer, XCONS (tem)->cdr);
2017
a90712c2 2018 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCONS (tem)->cdr)
0a952b57
RS
2019 {
2020 Lisp_Object car = XCONS (tem)->car;
2021 if (STRINGP (car)
2022 && fast_string_match (car, XBUFFER (buffer)->name) >= 0)
2023 return call1 (Vspecial_display_function, buffer);
2024 else if (CONSP (car)
2025 && STRINGP (XCONS (car)->car)
2026 && fast_string_match (XCONS (car)->car,
2027 XBUFFER (buffer)->name) >= 0)
2028 return call2 (Vspecial_display_function,
2029 buffer,
2030 XCONS (car)->cdr);
2031 }
a90712c2
RS
2032 }
2033
44fa5b1e
JB
2034#ifdef MULTI_FRAME
2035 /* If there are no frames open that have more than a minibuffer,
2036 we need to create a new frame. */
2037 if (pop_up_frames || last_nonminibuf_frame == 0)
7ab12479 2038 {
a90712c2 2039 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
7ab12479 2040 Fset_window_buffer (window, buffer);
d07f802a 2041 return display_buffer_1 (window);
7ab12479 2042 }
44fa5b1e 2043#endif /* MULTI_FRAME */
7ab12479 2044
43bad991 2045 if (pop_up_windows
44fa5b1e
JB
2046#ifdef MULTI_FRAME
2047 || FRAME_MINIBUF_ONLY_P (selected_frame)
cee67da9
RS
2048 /* If the current frame is a special display frame,
2049 don't try to reuse its windows. */
2050 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->dedicated)
43bad991
JB
2051#endif
2052 )
7ab12479 2053 {
12cae7c0
KH
2054 Lisp_Object frames;
2055
2056 frames = Qnil;
44fa5b1e
JB
2057#ifdef MULTI_FRAME
2058 if (FRAME_MINIBUF_ONLY_P (selected_frame))
74112613 2059 XSETFRAME (frames, last_nonminibuf_frame);
7ab12479
JB
2060#endif
2061 /* Don't try to create a window if would get an error */
2062 if (split_height_threshold < window_min_height << 1)
2063 split_height_threshold = window_min_height << 1;
2064
cee67da9
RS
2065 /* Note that both Fget_largest_window and Fget_lru_window
2066 ignore minibuffers and dedicated windows.
2067 This means they can return nil. */
7ab12479 2068
9f7a8b5d 2069#ifdef MULTI_FRAME
cee67da9
RS
2070 /* If the frame we would try to split cannot be split,
2071 try other frames. */
2072 if (FRAME_NO_SPLIT_P (NILP (frames) ? selected_frame
2073 : last_nonminibuf_frame))
2074 {
2075 /* Try visible frames first. */
2076 window = Fget_largest_window (Qvisible);
2077 /* If that didn't work, try iconified frames. */
2078 if (NILP (window))
2079 window = Fget_largest_window (make_number (0));
2080 if (NILP (window))
2081 window = Fget_largest_window (Qt);
2082 }
2083 else
9f7a8b5d 2084#endif
cee67da9
RS
2085 window = Fget_largest_window (frames);
2086
92cca945
RS
2087 /* If we got a tall enough full-width window that can be split,
2088 split it. */
265a9e55 2089 if (!NILP (window)
92cca945 2090 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
7ab12479 2091 && window_height (window) >= split_height_threshold
535e0b8e
JB
2092 && (XFASTINT (XWINDOW (window)->width)
2093 == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
7ab12479
JB
2094 window = Fsplit_window (window, Qnil, Qnil);
2095 else
2096 {
1942f68f
RS
2097 Lisp_Object upper, lower, other;
2098
44fa5b1e 2099 window = Fget_lru_window (frames);
92cca945
RS
2100 /* If the LRU window is selected, and big enough,
2101 and can be split, split it. */
cee67da9 2102 if (!NILP (window)
92cca945 2103 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
cee67da9
RS
2104 && (EQ (window, selected_window)
2105 || EQ (XWINDOW (window)->parent, Qnil))
7ab12479
JB
2106 && window_height (window) >= window_min_height << 1)
2107 window = Fsplit_window (window, Qnil, Qnil);
cee67da9
RS
2108#ifdef MULTI_FRAME
2109 /* If Fget_lru_window returned nil, try other approaches. */
2110 /* Try visible frames first. */
2111 if (NILP (window))
2112 window = Fget_largest_window (Qvisible);
2113 /* If that didn't work, try iconified frames. */
2114 if (NILP (window))
2115 window = Fget_largest_window (make_number (0));
2116 /* Try invisible frames. */
2117 if (NILP (window))
2118 window = Fget_largest_window (Qt);
2119 /* As a last resort, make a new frame. */
2120 if (NILP (window))
2121 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
2122#else
2123 /* As a last resort, use a non minibuffer window. */
2124 if (NILP (window))
2125 window = Fframe_first_window (Fselected_frame ());
2126#endif
1942f68f
RS
2127 /* If window appears above or below another,
2128 even out their heights. */
cac66e4f 2129 other = upper = lower = Qnil;
1942f68f
RS
2130 if (!NILP (XWINDOW (window)->prev))
2131 other = upper = XWINDOW (window)->prev, lower = window;
2132 if (!NILP (XWINDOW (window)->next))
2133 other = lower = XWINDOW (window)->next, upper = window;
2134 if (!NILP (other)
2135 /* Check that OTHER and WINDOW are vertically arrayed. */
2136 && XWINDOW (other)->top != XWINDOW (window)->top
2137 && XWINDOW (other)->height > XWINDOW (window)->height)
2138 {
2139 int total = XWINDOW (other)->height + XWINDOW (window)->height;
8d77c0c8
KH
2140 Lisp_Object old_selected_window;
2141 old_selected_window = selected_window;
1942f68f 2142
8d77c0c8 2143 selected_window = upper;
1942f68f
RS
2144 change_window_height (total / 2 - XWINDOW (upper)->height, 0);
2145 selected_window = old_selected_window;
2146 }
7ab12479
JB
2147 }
2148 }
2149 else
2150 window = Fget_lru_window (Qnil);
2151
2152 Fset_window_buffer (window, buffer);
d07f802a 2153 return display_buffer_1 (window);
7ab12479
JB
2154}
2155
2156void
2157temp_output_buffer_show (buf)
2158 register Lisp_Object buf;
2159{
2160 register struct buffer *old = current_buffer;
2161 register Lisp_Object window;
2162 register struct window *w;
2163
2164 Fset_buffer (buf);
c6367666 2165 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
7ab12479
JB
2166 BEGV = BEG;
2167 ZV = Z;
2168 SET_PT (BEG);
1479ef51 2169 XBUFFER (buf)->clip_changed = 1;
7ab12479
JB
2170 set_buffer_internal (old);
2171
2172 if (!EQ (Vtemp_buffer_show_function, Qnil))
2173 call1 (Vtemp_buffer_show_function, buf);
2174 else
2175 {
2176 window = Fdisplay_buffer (buf, Qnil);
2177
44fa5b1e
JB
2178#ifdef MULTI_FRAME
2179 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
2180 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
2181#endif /* MULTI_FRAME */
7ab12479
JB
2182 Vminibuf_scroll_window = window;
2183 w = XWINDOW (window);
d834a2e9 2184 XSETFASTINT (w->hscroll, 0);
7ab12479
JB
2185 set_marker_restricted (w->start, make_number (1), buf);
2186 set_marker_restricted (w->pointm, make_number (1), buf);
a58ec57d 2187
f52cca03
RS
2188 /* Run temp-buffer-show-hook, with the chosen window selected. */
2189 if (!NILP (Vrun_hooks))
2cccc823 2190 {
f52cca03
RS
2191 Lisp_Object tem;
2192 tem = Fboundp (Qtemp_buffer_show_hook);
2cccc823
RS
2193 if (!NILP (tem))
2194 {
f52cca03
RS
2195 tem = Fsymbol_value (Qtemp_buffer_show_hook);
2196 if (!NILP (tem))
2197 {
2198 int count = specpdl_ptr - specpdl;
2cccc823 2199
f52cca03
RS
2200 /* Select the window that was chosen, for running the hook. */
2201 record_unwind_protect (Fset_window_configuration,
2202 Fcurrent_window_configuration (Qnil));
2cccc823 2203
f52cca03
RS
2204 Fselect_window (window);
2205 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
2206 unbind_to (count, Qnil);
2207 }
2cccc823
RS
2208 }
2209 }
2210 }
7ab12479
JB
2211}
2212\f
2213static
2214make_dummy_parent (window)
2215 Lisp_Object window;
2216{
cffec418 2217 Lisp_Object new;
7ab12479 2218 register struct window *o, *p;
cffec418
KH
2219 register struct Lisp_Vector *vec;
2220 int i;
7ab12479 2221
cffec418
KH
2222 o = XWINDOW (window);
2223 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
2224 for (i = 0; i < VECSIZE (struct window); ++i)
2225 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
2226 vec->size = VECSIZE (struct window);
2227 p = (struct window *)vec;
2228 XSETWINDOW (new, p);
7ab12479 2229
d834a2e9 2230 XSETFASTINT (p->sequence_number, ++sequence_number);
7ab12479
JB
2231
2232 /* Put new into window structure in place of window */
2233 replace_window (window, new);
2234
2235 o->next = Qnil;
2236 o->prev = Qnil;
2237 o->vchild = Qnil;
2238 o->hchild = Qnil;
2239 o->parent = new;
2240
2241 p->start = Qnil;
2242 p->pointm = Qnil;
2243 p->buffer = Qnil;
2244}
2245
2246DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
2247 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
2248WINDOW defaults to selected one and SIZE to half its size.\n\
2249If optional third arg HOR-FLAG is non-nil, split side by side\n\
2250and put SIZE columns in the first of the pair.")
2251 (window, chsize, horflag)
2252 Lisp_Object window, chsize, horflag;
2253{
2254 register Lisp_Object new;
2255 register struct window *o, *p;
2256 register int size;
2257
265a9e55 2258 if (NILP (window))
7ab12479
JB
2259 window = selected_window;
2260 else
605be8af 2261 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2262
2263 o = XWINDOW (window);
2264
265a9e55 2265 if (NILP (chsize))
7ab12479 2266 {
265a9e55 2267 if (!NILP (horflag))
7ab12479
JB
2268 /* Round odd size up, since this is for the left-hand window,
2269 and it will lose a column for the separators. */
2270 size = ((XFASTINT (o->width) + 1) & -2) >> 1;
2271 else
2272 size = XFASTINT (o->height) >> 1;
2273 }
2274 else
2275 {
2276 CHECK_NUMBER (chsize, 1);
2277 size = XINT (chsize);
2278 }
2279
2280 if (MINI_WINDOW_P (o))
2281 error ("Attempt to split minibuffer window");
44fa5b1e
JB
2282 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o))))
2283 error ("Attempt to split unsplittable frame");
7ab12479 2284
a481b3ea 2285 check_min_window_sizes ();
7ab12479 2286
265a9e55 2287 if (NILP (horflag))
7ab12479 2288 {
3d22c388
RS
2289 if (size < window_min_height)
2290 error ("Window height %d too small (after splitting)", size);
2291 if (size + window_min_height > XFASTINT (o->height))
2292 error ("Window height %d too small (after splitting)",
2293 XFASTINT (o->height) - size);
265a9e55
JB
2294 if (NILP (o->parent)
2295 || NILP (XWINDOW (o->parent)->vchild))
7ab12479
JB
2296 {
2297 make_dummy_parent (window);
2298 new = o->parent;
2299 XWINDOW (new)->vchild = window;
2300 }
2301 }
2302 else
2303 {
3d22c388
RS
2304 if (size < window_min_width)
2305 error ("Window width %d too small (after splitting)", size);
2306 if (size + window_min_width > XFASTINT (o->width))
2307 error ("Window width %d too small (after splitting)",
2308 XFASTINT (o->width) - size);
265a9e55
JB
2309 if (NILP (o->parent)
2310 || NILP (XWINDOW (o->parent)->hchild))
7ab12479
JB
2311 {
2312 make_dummy_parent (window);
2313 new = o->parent;
2314 XWINDOW (new)->hchild = window;
2315 }
2316 }
2317
2318 /* Now we know that window's parent is a vertical combination
2319 if we are dividing vertically, or a horizontal combination
2320 if we are making side-by-side windows */
2321
2322 windows_or_buffers_changed++;
29aeee73 2323 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (o))) = 1;
7ab12479
JB
2324 new = make_window ();
2325 p = XWINDOW (new);
2326
44fa5b1e 2327 p->frame = o->frame;
7ab12479 2328 p->next = o->next;
265a9e55 2329 if (!NILP (p->next))
7ab12479
JB
2330 XWINDOW (p->next)->prev = new;
2331 p->prev = window;
2332 o->next = new;
2333 p->parent = o->parent;
2334 p->buffer = Qt;
2335
2336 Fset_window_buffer (new, o->buffer);
2337
44fa5b1e 2338 /* Apportion the available frame space among the two new windows */
7ab12479 2339
265a9e55 2340 if (!NILP (horflag))
7ab12479
JB
2341 {
2342 p->height = o->height;
2343 p->top = o->top;
d834a2e9
KH
2344 XSETFASTINT (p->width, XFASTINT (o->width) - size);
2345 XSETFASTINT (o->width, size);
2346 XSETFASTINT (p->left, XFASTINT (o->left) + size);
7ab12479
JB
2347 }
2348 else
2349 {
2350 p->left = o->left;
2351 p->width = o->width;
d834a2e9
KH
2352 XSETFASTINT (p->height, XFASTINT (o->height) - size);
2353 XSETFASTINT (o->height, size);
2354 XSETFASTINT (p->top, XFASTINT (o->top) + size);
7ab12479
JB
2355 }
2356
2357 return new;
2358}
2359\f
2360DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
2361 "Make current window ARG lines bigger.\n\
2362From program, optional second arg non-nil means grow sideways ARG columns.")
2363 (n, side)
2364 register Lisp_Object n, side;
2365{
2366 CHECK_NUMBER (n, 0);
265a9e55 2367 change_window_height (XINT (n), !NILP (side));
7ab12479
JB
2368 return Qnil;
2369}
2370
2371DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
2372 "Make current window ARG lines smaller.\n\
2373From program, optional second arg non-nil means shrink sideways ARG columns.")
2374 (n, side)
2375 register Lisp_Object n, side;
2376{
2377 CHECK_NUMBER (n, 0);
265a9e55 2378 change_window_height (-XINT (n), !NILP (side));
7ab12479
JB
2379 return Qnil;
2380}
2381
2382int
2383window_height (window)
2384 Lisp_Object window;
2385{
2386 register struct window *p = XWINDOW (window);
2387 return XFASTINT (p->height);
2388}
2389
2390int
2391window_width (window)
2392 Lisp_Object window;
2393{
2394 register struct window *p = XWINDOW (window);
2395 return XFASTINT (p->width);
2396}
2397
05c2896a
JB
2398#define MINSIZE(w) \
2399 (widthflag \
2400 ? window_min_width \
2401 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
7ab12479
JB
2402
2403#define CURBEG(w) \
05c2896a 2404 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
7ab12479
JB
2405
2406#define CURSIZE(w) \
05c2896a 2407 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
7ab12479
JB
2408
2409/* Unlike set_window_height, this function
2410 also changes the heights of the siblings so as to
2411 keep everything consistent. */
2412
2413change_window_height (delta, widthflag)
2414 register int delta;
2415 int widthflag;
2416{
2417 register Lisp_Object parent;
2418 Lisp_Object window;
2419 register struct window *p;
2420 int *sizep;
2421 int (*sizefun) () = widthflag ? window_width : window_height;
2422 register int (*setsizefun) () = (widthflag
2423 ? set_window_width
2424 : set_window_height);
2425
a481b3ea 2426 check_min_window_sizes ();
7ab12479
JB
2427
2428 window = selected_window;
2429 while (1)
2430 {
2431 p = XWINDOW (window);
2432 parent = p->parent;
265a9e55 2433 if (NILP (parent))
7ab12479
JB
2434 {
2435 if (widthflag)
2436 error ("No other window to side of this one");
2437 break;
2438 }
265a9e55
JB
2439 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
2440 : !NILP (XWINDOW (parent)->vchild))
7ab12479
JB
2441 break;
2442 window = parent;
2443 }
2444
05c2896a 2445 sizep = &CURSIZE (window);
7ab12479 2446
7ab12479
JB
2447 {
2448 register int maxdelta;
7ab12479 2449
265a9e55
JB
2450 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
2451 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
2452 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
44fa5b1e
JB
2453 /* This is a frame with only one window, a minibuffer-only
2454 or a minibufferless frame. */
d5783c40 2455 : (delta = 0));
7ab12479
JB
2456
2457 if (delta > maxdelta)
2458 /* This case traps trying to make the minibuffer
44fa5b1e
JB
2459 the full frame, or make the only window aside from the
2460 minibuffer the full frame. */
7ab12479 2461 delta = maxdelta;
6b54027b 2462 }
d5783c40 2463
6b54027b
RS
2464 if (*sizep + delta < MINSIZE (window))
2465 {
2466 Fdelete_window (window);
d5783c40 2467 return;
6b54027b
RS
2468 }
2469
2470 if (delta == 0)
2471 return;
7ab12479 2472
6b54027b
RS
2473 if (!NILP (p->next)
2474 && (*sizefun) (p->next) - delta >= MINSIZE (p->next))
7ab12479
JB
2475 {
2476 (*setsizefun) (p->next, (*sizefun) (p->next) - delta, 0);
2477 (*setsizefun) (window, *sizep + delta, 0);
05c2896a 2478 CURBEG (p->next) += delta;
7ab12479
JB
2479 /* This does not change size of p->next,
2480 but it propagates the new top edge to its children */
2481 (*setsizefun) (p->next, (*sizefun) (p->next), 0);
2482 }
6b54027b
RS
2483 else if (!NILP (p->prev)
2484 && (*sizefun) (p->prev) - delta >= MINSIZE (p->prev))
7ab12479
JB
2485 {
2486 (*setsizefun) (p->prev, (*sizefun) (p->prev) - delta, 0);
05c2896a 2487 CURBEG (window) -= delta;
7ab12479
JB
2488 (*setsizefun) (window, *sizep + delta, 0);
2489 }
2490 else
2491 {
2492 register int delta1;
2493 register int opht = (*sizefun) (parent);
2494
2495 /* If trying to grow this window to or beyond size of the parent,
2496 make delta1 so big that, on shrinking back down,
2497 all the siblings end up with less than one line and are deleted. */
2498 if (opht <= *sizep + delta)
2499 delta1 = opht * opht * 2;
2500 /* Otherwise, make delta1 just right so that if we add delta1
2501 lines to this window and to the parent, and then shrink
2502 the parent back to its original size, the new proportional
2503 size of this window will increase by delta. */
2504 else
2505 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
2506
2507 /* Add delta1 lines or columns to this window, and to the parent,
2508 keeping things consistent while not affecting siblings. */
05c2896a 2509 CURSIZE (parent) = opht + delta1;
7ab12479
JB
2510 (*setsizefun) (window, *sizep + delta1, 0);
2511
2512 /* Squeeze out delta1 lines or columns from our parent,
2513 shriking this window and siblings proportionately.
2514 This brings parent back to correct size.
2515 Delta1 was calculated so this makes this window the desired size,
2516 taking it all out of the siblings. */
2517 (*setsizefun) (parent, opht, 0);
2518 }
2519
d834a2e9 2520 XSETFASTINT (p->last_modified, 0);
7ab12479
JB
2521}
2522#undef MINSIZE
2523#undef CURBEG
2524#undef CURSIZE
2525
2526\f
2527/* Return number of lines of text (not counting mode line) in W. */
2528
2529int
2530window_internal_height (w)
2531 struct window *w;
2532{
2533 int ht = XFASTINT (w->height);
2534
2535 if (MINI_WINDOW_P (w))
2536 return ht;
2537
265a9e55
JB
2538 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2539 || !NILP (w->next) || !NILP (w->prev)
44fa5b1e 2540 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
7ab12479
JB
2541 return ht - 1;
2542
2543 return ht;
2544}
2545
535e0b8e
JB
2546
2547/* Return the number of columns in W.
a3c87d4e 2548 Don't count columns occupied by scroll bars or the vertical bar
535e0b8e
JB
2549 separating W from the sibling to its right. */
2550int
2551window_internal_width (w)
2552 struct window *w;
2553{
2554 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2555 int left = XINT (w->left);
2556 int width = XINT (w->width);
2557
2558 /* If this window is flush against the right edge of the frame, its
2559 internal width is its full width. */
2560 if (left + width >= FRAME_WIDTH (f))
2561 return width;
2562
2563 /* If we are not flush right, then our rightmost columns are
2564 occupied by some sort of separator. */
2565
a3c87d4e
JB
2566 /* Scroll bars occupy a few columns. */
2567 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
ca0d0bb9 2568 return width - FRAME_SCROLL_BAR_COLS (f);
535e0b8e
JB
2569
2570 /* The column of `|' characters separating side-by-side windows
2571 occupies one column only. */
2572 return width - 1;
2573}
2574
2575
7ab12479
JB
2576/* Scroll contents of window WINDOW up N lines. */
2577
2578void
f8026fd8 2579window_scroll (window, n, noerror)
7ab12479
JB
2580 Lisp_Object window;
2581 int n;
f8026fd8 2582 int noerror;
7ab12479
JB
2583{
2584 register struct window *w = XWINDOW (window);
5ce7b543 2585 register int opoint = PT;
7ab12479
JB
2586 register int pos;
2587 register int ht = window_internal_height (w);
2588 register Lisp_Object tem;
2589 int lose;
2590 Lisp_Object bolp, nmoved;
2591
0a1f771a 2592 /* Always set force_start so that redisplay_window will run
80622eec 2593 thw window-scroll-functions. */
0a1f771a
RS
2594 w->force_start = Qt;
2595
d834a2e9 2596 XSETFASTINT (tem, PT);
7ab12479
JB
2597 tem = Fpos_visible_in_window_p (tem, window);
2598
265a9e55 2599 if (NILP (tem))
7ab12479 2600 {
cd2be1dd 2601 Fvertical_motion (make_number (- (ht / 2)), window);
d834a2e9 2602 XSETFASTINT (tem, PT);
7ab12479 2603 Fset_marker (w->start, tem, w->buffer);
7ab12479
JB
2604 }
2605
2606 SET_PT (marker_position (w->start));
5ce7b543 2607 lose = n < 0 && PT == BEGV;
540b6aa0 2608 Fvertical_motion (make_number (n), window);
5ce7b543 2609 pos = PT;
7ab12479
JB
2610 bolp = Fbolp ();
2611 SET_PT (opoint);
2612
2613 if (lose)
f8026fd8
JB
2614 {
2615 if (noerror)
2616 return;
2617 else
2618 Fsignal (Qbeginning_of_buffer, Qnil);
2619 }
7ab12479
JB
2620
2621 if (pos < ZV)
7ab12479
JB
2622 {
2623 set_marker_restricted (w->start, make_number (pos), w->buffer);
2624 w->start_at_line_beg = bolp;
2625 w->update_mode_line = Qt;
d834a2e9 2626 XSETFASTINT (w->last_modified, 0);
7ab12479
JB
2627 if (pos > opoint)
2628 SET_PT (pos);
2629 if (n < 0)
2630 {
2631 SET_PT (pos);
540b6aa0 2632 tem = Fvertical_motion (make_number (ht), window);
5ce7b543 2633 if (PT > opoint || XFASTINT (tem) < ht)
7ab12479
JB
2634 SET_PT (opoint);
2635 else
540b6aa0 2636 Fvertical_motion (make_number (-1), window);
7ab12479
JB
2637 }
2638 }
2639 else
f8026fd8
JB
2640 {
2641 if (noerror)
2642 return;
2643 else
2644 Fsignal (Qend_of_buffer, Qnil);
2645 }
7ab12479
JB
2646}
2647\f
2648/* This is the guts of Fscroll_up and Fscroll_down. */
2649
2650static void
2651scroll_command (n, direction)
2652 register Lisp_Object n;
2653 int direction;
2654{
2655 register int defalt;
2656 int count = specpdl_ptr - specpdl;
2657
95605e15
JB
2658 /* If selected window's buffer isn't current, make it current for the moment.
2659 But don't screw up if window_scroll gets an error. */
7ab12479 2660 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
95605e15
JB
2661 {
2662 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2663 Fset_buffer (XWINDOW (selected_window)->buffer);
2664 }
7ab12479
JB
2665
2666 defalt = (window_internal_height (XWINDOW (selected_window))
2667 - next_screen_context_lines);
2668 defalt = direction * (defalt < 1 ? 1 : defalt);
2669
265a9e55 2670 if (NILP (n))
f8026fd8 2671 window_scroll (selected_window, defalt, 0);
7ab12479 2672 else if (EQ (n, Qminus))
f8026fd8 2673 window_scroll (selected_window, - defalt, 0);
7ab12479
JB
2674 else
2675 {
2676 n = Fprefix_numeric_value (n);
f8026fd8 2677 window_scroll (selected_window, XINT (n) * direction, 0);
7ab12479 2678 }
95605e15
JB
2679
2680 unbind_to (count, Qnil);
7ab12479
JB
2681}
2682
2683DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2684 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2685A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 2686Negative ARG means scroll downward.\n\
7ab12479
JB
2687When calling from a program, supply a number as argument or nil.")
2688 (n)
2689 Lisp_Object n;
2690{
2691 scroll_command (n, 1);
2692 return Qnil;
2693}
2694
2695DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2696 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2697A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 2698Negative ARG means scroll upward.\n\
7ab12479
JB
2699When calling from a program, supply a number as argument or nil.")
2700 (n)
2701 Lisp_Object n;
2702{
2703 scroll_command (n, -1);
2704 return Qnil;
2705}
ccd0664b
RS
2706\f
2707DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
2708 "Return the other window for \"other window scroll\" commands.\n\
77b24de6 2709If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
ccd0664b
RS
2710specifies the window.\n\
2711If `other-window-scroll-buffer' is non-nil, a window\n\
2712showing that buffer is used.")
eb16ec06 2713 ()
7ab12479 2714{
ccd0664b 2715 Lisp_Object window;
7ab12479
JB
2716
2717 if (MINI_WINDOW_P (XWINDOW (selected_window))
265a9e55 2718 && !NILP (Vminibuf_scroll_window))
7ab12479
JB
2719 window = Vminibuf_scroll_window;
2720 /* If buffer is specified, scroll that buffer. */
265a9e55 2721 else if (!NILP (Vother_window_scroll_buffer))
7ab12479
JB
2722 {
2723 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
265a9e55 2724 if (NILP (window))
7ab12479
JB
2725 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2726 }
2727 else
dbc4e1c1
JB
2728 {
2729 /* Nothing specified; look for a neighboring window on the same
2730 frame. */
2731 window = Fnext_window (selected_window, Qnil, Qnil);
2732
2733 if (EQ (window, selected_window))
2734 /* That didn't get us anywhere; look for a window on another
2735 visible frame. */
2736 do
2737 window = Fnext_window (window, Qnil, Qt);
2738 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
2739 && ! EQ (window, selected_window));
2740 }
2741
605be8af 2742 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2743
2744 if (EQ (window, selected_window))
2745 error ("There is no other window");
2746
ccd0664b
RS
2747 return window;
2748}
2749
2750DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
2751 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
2752The next window is the one below the current one; or the one at the top\n\
2753if the current one is at the bottom. Negative ARG means scroll downward.\n\
2754When calling from a program, supply a number as argument or nil.\n\
2755\n\
2756If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2757specifies the window to scroll.\n\
2758If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2759showing that buffer, popping the buffer up if necessary.")
2760 (n)
2761 register Lisp_Object n;
2762{
2763 register Lisp_Object window;
2f787aa3 2764 register int defalt;
ccd0664b
RS
2765 register struct window *w;
2766 register int count = specpdl_ptr - specpdl;
2767
2768 window = Fother_window_for_scrolling ();
2769
7ab12479 2770 w = XWINDOW (window);
2f787aa3
KH
2771 defalt = window_internal_height (w) - next_screen_context_lines;
2772 if (defalt < 1) defalt = 1;
7ab12479
JB
2773
2774 /* Don't screw up if window_scroll gets an error. */
2775 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2776
2777 Fset_buffer (w->buffer);
2778 SET_PT (marker_position (w->pointm));
2779
265a9e55 2780 if (NILP (n))
2f787aa3 2781 window_scroll (window, defalt, 1);
7ab12479 2782 else if (EQ (n, Qminus))
2f787aa3 2783 window_scroll (window, -defalt, 1);
7ab12479
JB
2784 else
2785 {
017b2bad 2786 if (CONSP (n))
7ab12479
JB
2787 n = Fcar (n);
2788 CHECK_NUMBER (n, 0);
f8026fd8 2789 window_scroll (window, XINT (n), 1);
7ab12479
JB
2790 }
2791
5ce7b543 2792 Fset_marker (w->pointm, make_number (PT), Qnil);
f4e7b2c2 2793 unbind_to (count, Qnil);
7ab12479
JB
2794
2795 return Qnil;
2796}
2797\f
644b477c 2798DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
7ab12479
JB
2799 "Scroll selected window display ARG columns left.\n\
2800Default for ARG is window width minus 2.")
2801 (arg)
2802 register Lisp_Object arg;
2803{
2804
265a9e55 2805 if (NILP (arg))
d834a2e9 2806 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
7ab12479
JB
2807 else
2808 arg = Fprefix_numeric_value (arg);
2809
2810 return
2811 Fset_window_hscroll (selected_window,
2812 make_number (XINT (XWINDOW (selected_window)->hscroll)
2813 + XINT (arg)));
2814}
2815
644b477c 2816DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
7ab12479
JB
2817 "Scroll selected window display ARG columns right.\n\
2818Default for ARG is window width minus 2.")
2819 (arg)
2820 register Lisp_Object arg;
2821{
265a9e55 2822 if (NILP (arg))
d834a2e9 2823 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
7ab12479
JB
2824 else
2825 arg = Fprefix_numeric_value (arg);
2826
2827 return
2828 Fset_window_hscroll (selected_window,
2829 make_number (XINT (XWINDOW (selected_window)->hscroll)
2830 - XINT (arg)));
2831}
2832
2833DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
44fa5b1e 2834 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
7ab12479 2835The desired position of point is always relative to the current window.\n\
44fa5b1e
JB
2836Just C-u as prefix means put point in the center of the window.\n\
2837No arg (i.e., it is nil) erases the entire frame and then\n\
2838redraws with point in the center of the current window.")
7ab12479
JB
2839 (n)
2840 register Lisp_Object n;
2841{
2842 register struct window *w = XWINDOW (selected_window);
2843 register int ht = window_internal_height (w);
113d9015 2844 struct position pos;
7ab12479 2845
265a9e55 2846 if (NILP (n))
7ab12479 2847 {
44fa5b1e 2848 extern int frame_garbaged;
7ab12479 2849
44fa5b1e 2850 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
d834a2e9 2851 XSETFASTINT (n, ht / 2);
7ab12479 2852 }
017b2bad 2853 else if (CONSP (n)) /* Just C-u. */
7ab12479 2854 {
d834a2e9 2855 XSETFASTINT (n, ht / 2);
7ab12479
JB
2856 }
2857 else
2858 {
2859 n = Fprefix_numeric_value (n);
2860 CHECK_NUMBER (n, 0);
2861 }
2862
2863 if (XINT (n) < 0)
2864 XSETINT (n, XINT (n) + ht);
2865
6e55cbc2 2866 pos = *vmotion (point, - XINT (n), w);
7ab12479 2867
113d9015
KH
2868 Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
2869 w->start_at_line_beg = ((pos.bufpos == BEGV
2870 || FETCH_CHAR (pos.bufpos - 1) == '\n')
2871 ? Qt : Qnil);
7ab12479
JB
2872 w->force_start = Qt;
2873
2874 return Qnil;
2875}
2876\f
2877DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
2878 1, 1, "P",
2879 "Position point relative to window.\n\
19e3bf0a 2880With no argument, position point at center of window.\n\
44fa5b1e 2881An argument specifies frame line; zero means top of window,\n\
7ab12479
JB
2882negative means relative to bottom of window.")
2883 (arg)
2884 register Lisp_Object arg;
2885{
2886 register struct window *w = XWINDOW (selected_window);
2887 register int height = window_internal_height (w);
2888 register int start;
540b6aa0 2889 Lisp_Object window;
7ab12479 2890
265a9e55 2891 if (NILP (arg))
d834a2e9 2892 XSETFASTINT (arg, height / 2);
7ab12479
JB
2893 else
2894 {
2895 arg = Fprefix_numeric_value (arg);
2896 if (XINT (arg) < 0)
2897 XSETINT (arg, XINT (arg) + height);
2898 }
2899
2900 start = marker_position (w->start);
74112613 2901 XSETWINDOW (window, w);
7ab12479
JB
2902 if (start < BEGV || start > ZV)
2903 {
cd2be1dd 2904 Fvertical_motion (make_number (- (height / 2)), window);
5ce7b543 2905 Fset_marker (w->start, make_number (PT), w->buffer);
7ab12479
JB
2906 w->start_at_line_beg = Fbolp ();
2907 w->force_start = Qt;
2908 }
2909 else
2910 SET_PT (start);
2911
540b6aa0 2912 return Fvertical_motion (arg, window);
7ab12479
JB
2913}
2914\f
2915struct save_window_data
2916 {
2917 int size_from_Lisp_Vector_struct;
2918 struct Lisp_Vector *next_from_Lisp_Vector_struct;
8f6ea2e9 2919 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
bdc727bf 2920 Lisp_Object selected_frame;
7ab12479
JB
2921 Lisp_Object current_window;
2922 Lisp_Object current_buffer;
2923 Lisp_Object minibuf_scroll_window;
2924 Lisp_Object root_window;
bdc727bf 2925 Lisp_Object focus_frame;
756b6edc
RS
2926 /* Record the values of window-min-width and window-min-height
2927 so that window sizes remain consistent with them. */
2928 Lisp_Object min_width, min_height;
7ab12479
JB
2929 /* A vector, interpreted as a struct saved_window */
2930 Lisp_Object saved_windows;
2931 };
ff06df24 2932
7ab12479
JB
2933/* This is saved as a Lisp_Vector */
2934struct saved_window
2935 {
2936 /* these first two must agree with struct Lisp_Vector in lisp.h */
2937 int size_from_Lisp_Vector_struct;
2938 struct Lisp_Vector *next_from_Lisp_Vector_struct;
2939
2940 Lisp_Object window;
2941 Lisp_Object buffer, start, pointm, mark;
2942 Lisp_Object left, top, width, height, hscroll;
2943 Lisp_Object parent, prev;
2944 Lisp_Object start_at_line_beg;
2945 Lisp_Object display_table;
2946 };
2947#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
2948
2949#define SAVED_WINDOW_N(swv,n) \
2950 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
2951
2952DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
2953 "T if OBJECT is a window-configration object.")
2954 (obj)
2955 Lisp_Object obj;
2956{
017b2bad 2957 if (WINDOW_CONFIGURATIONP (obj))
7ab12479
JB
2958 return Qt;
2959 return Qnil;
2960}
2961
2962
d5b2799e
RS
2963DEFUN ("set-window-configuration", Fset_window_configuration,
2964 Sset_window_configuration, 1, 1, 0,
7ab12479
JB
2965 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
2966CONFIGURATION must be a value previously returned\n\
2967by `current-window-configuration' (which see).")
2f83aebe
JB
2968 (configuration)
2969 Lisp_Object configuration;
7ab12479 2970{
7ab12479
JB
2971 register struct save_window_data *data;
2972 struct Lisp_Vector *saved_windows;
7ab12479 2973 Lisp_Object new_current_buffer;
fd482be5 2974 Lisp_Object frame;
44fa5b1e 2975 FRAME_PTR f;
7ab12479 2976
017b2bad 2977 while (!WINDOW_CONFIGURATIONP (configuration))
7ab12479 2978 {
2f83aebe
JB
2979 configuration = wrong_type_argument (intern ("window-configuration-p"),
2980 configuration);
7ab12479
JB
2981 }
2982
2f83aebe 2983 data = (struct save_window_data *) XVECTOR (configuration);
7ab12479
JB
2984 saved_windows = XVECTOR (data->saved_windows);
2985
7ab12479 2986 new_current_buffer = data->current_buffer;
265a9e55 2987 if (NILP (XBUFFER (new_current_buffer)->name))
7ab12479
JB
2988 new_current_buffer = Qnil;
2989
fd482be5
JB
2990 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
2991 f = XFRAME (frame);
9ace597f 2992
fd482be5
JB
2993 /* If f is a dead frame, don't bother rebuilding its window tree.
2994 However, there is other stuff we should still try to do below. */
2995 if (FRAME_LIVE_P (f))
7ab12479 2996 {
fd482be5
JB
2997 register struct window *w;
2998 register struct saved_window *p;
2999 int k;
3000
3001 /* If the frame has been resized since this window configuration was
3002 made, we change the frame to the size specified in the
3003 configuration, restore the configuration, and then resize it
3004 back. We keep track of the prevailing height in these variables. */
3005 int previous_frame_height = FRAME_HEIGHT (f);
3006 int previous_frame_width = FRAME_WIDTH (f);
8f6ea2e9 3007 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
fd482be5
JB
3008
3009 if (XFASTINT (data->frame_height) != previous_frame_height
3010 || XFASTINT (data->frame_width) != previous_frame_width)
3011 change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
1f853940 3012#ifdef HAVE_WINDOW_SYSTEM
8f6ea2e9
KH
3013 if (XFASTINT (data->frame_menu_bar_lines)
3014 != previous_frame_menu_bar_lines)
3015 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
217f2871 3016#endif
fd482be5
JB
3017
3018 windows_or_buffers_changed++;
29aeee73 3019 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
fd482be5 3020
756b6edc
RS
3021 /* Temporarily avoid any problems with windows that are smaller
3022 than they are supposed to be. */
3023 window_min_height = 1;
3024 window_min_width = 1;
3025
fd482be5
JB
3026 /* Kludge Alert!
3027 Mark all windows now on frame as "deleted".
3028 Restoring the new configuration "undeletes" any that are in it.
3029
3030 Save their current buffers in their height fields, since we may
3031 need it later, if a buffer saved in the configuration is now
3032 dead. */
3033 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
3034
3035 for (k = 0; k < saved_windows->size; k++)
3036 {
3037 p = SAVED_WINDOW_N (saved_windows, k);
3038 w = XWINDOW (p->window);
3039 w->next = Qnil;
7ab12479 3040
fd482be5
JB
3041 if (!NILP (p->parent))
3042 w->parent = SAVED_WINDOW_N (saved_windows,
3043 XFASTINT (p->parent))->window;
3044 else
3045 w->parent = Qnil;
7ab12479 3046
fd482be5 3047 if (!NILP (p->prev))
7ab12479 3048 {
fd482be5
JB
3049 w->prev = SAVED_WINDOW_N (saved_windows,
3050 XFASTINT (p->prev))->window;
3051 XWINDOW (w->prev)->next = p->window;
3052 }
3053 else
3054 {
3055 w->prev = Qnil;
3056 if (!NILP (w->parent))
3057 {
3058 if (EQ (p->width, XWINDOW (w->parent)->width))
3059 {
3060 XWINDOW (w->parent)->vchild = p->window;
3061 XWINDOW (w->parent)->hchild = Qnil;
3062 }
3063 else
3064 {
3065 XWINDOW (w->parent)->hchild = p->window;
3066 XWINDOW (w->parent)->vchild = Qnil;
3067 }
3068 }
3069 }
3070
3071 /* If we squirreled away the buffer in the window's height,
3072 restore it now. */
017b2bad 3073 if (BUFFERP (w->height))
fd482be5
JB
3074 w->buffer = w->height;
3075 w->left = p->left;
3076 w->top = p->top;
3077 w->width = p->width;
3078 w->height = p->height;
3079 w->hscroll = p->hscroll;
3080 w->display_table = p->display_table;
d834a2e9 3081 XSETFASTINT (w->last_modified, 0);
fd482be5
JB
3082
3083 /* Reinstall the saved buffer and pointers into it. */
3084 if (NILP (p->buffer))
3085 w->buffer = p->buffer;
3086 else
3087 {
3088 if (!NILP (XBUFFER (p->buffer)->name))
3089 /* If saved buffer is alive, install it. */
3090 {
3091 w->buffer = p->buffer;
3092 w->start_at_line_beg = p->start_at_line_beg;
3093 set_marker_restricted (w->start,
3094 Fmarker_position (p->start),
3095 w->buffer);
3096 set_marker_restricted (w->pointm,
3097 Fmarker_position (p->pointm),
3098 w->buffer);
3099 Fset_marker (XBUFFER (w->buffer)->mark,
3100 Fmarker_position (p->mark), w->buffer);
3101
3102 /* As documented in Fcurrent_window_configuration, don't
3103 save the location of point in the buffer which was current
3104 when the window configuration was recorded. */
6b54027b
RS
3105 if (!EQ (p->buffer, new_current_buffer)
3106 && XBUFFER (p->buffer) == current_buffer)
fd482be5
JB
3107 Fgoto_char (w->pointm);
3108 }
52a68e98
RS
3109 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
3110 /* Else unless window has a live buffer, get one. */
7ab12479 3111 {
fd482be5
JB
3112 w->buffer = Fcdr (Fcar (Vbuffer_alist));
3113 /* This will set the markers to beginning of visible
3114 range. */
3115 set_marker_restricted (w->start, make_number (0), w->buffer);
3116 set_marker_restricted (w->pointm, make_number (0),w->buffer);
3117 w->start_at_line_beg = Qt;
7ab12479
JB
3118 }
3119 else
fd482be5 3120 /* Keeping window's old buffer; make sure the markers
52a68e98 3121 are real. */
7ab12479 3122 {
fd482be5
JB
3123 /* Set window markers at start of visible range. */
3124 if (XMARKER (w->start)->buffer == 0)
3125 set_marker_restricted (w->start, make_number (0),
3126 w->buffer);
3127 if (XMARKER (w->pointm)->buffer == 0)
3128 set_marker_restricted (w->pointm,
3129 (make_number
3130 (BUF_PT (XBUFFER (w->buffer)))),
3131 w->buffer);
3132 w->start_at_line_beg = Qt;
7ab12479
JB
3133 }
3134 }
3135 }
9ace597f 3136
fd482be5
JB
3137 FRAME_ROOT_WINDOW (f) = data->root_window;
3138 Fselect_window (data->current_window);
7ab12479 3139
fd482be5 3140#ifdef MULTI_FRAME
db269683 3141 if (NILP (data->focus_frame)
017b2bad 3142 || (FRAMEP (data->focus_frame)
db269683
JB
3143 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
3144 Fredirect_frame_focus (frame, data->focus_frame);
fd482be5 3145#endif
7ab12479 3146
fd482be5
JB
3147#if 0 /* I don't understand why this is needed, and it causes problems
3148 when the frame's old selected window has been deleted. */
3149#ifdef MULTI_FRAME
3150 if (f != selected_frame && ! FRAME_TERMCAP_P (f))
9a7c6fc3
RS
3151 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
3152 Qnil, 0);
fd482be5
JB
3153#endif
3154#endif
3155
3156 /* Set the screen height to the value it had before this function. */
3157 if (previous_frame_height != FRAME_HEIGHT (f)
3158 || previous_frame_width != FRAME_WIDTH (f))
3159 change_frame_size (f, previous_frame_height, previous_frame_width,
3160 0, 0);
1f853940 3161#ifdef HAVE_WINDOW_SYSTEM
8f6ea2e9
KH
3162 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
3163 x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
217f2871 3164#endif
fd482be5 3165 }
bdc727bf 3166
756b6edc
RS
3167 /* Restore the minimum heights recorded in the configuration. */
3168 window_min_height = XINT (data->min_height);
3169 window_min_width = XINT (data->min_width);
3170
ad854249 3171#ifdef MULTI_FRAME
bdc727bf 3172 /* Fselect_window will have made f the selected frame, so we
d5b2799e 3173 reselect the proper frame here. Fhandle_switch_frame will change the
bdc727bf
JB
3174 selected window too, but that doesn't make the call to
3175 Fselect_window above totally superfluous; it still sets f's
3176 selected window. */
fd482be5 3177 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
9a7c6fc3 3178 do_switch_frame (data->selected_frame, Qnil, 0);
ad854249 3179#endif
bdc727bf
JB
3180
3181 if (!NILP (new_current_buffer))
3182 Fset_buffer (new_current_buffer);
3183
7ab12479
JB
3184 Vminibuf_scroll_window = data->minibuf_scroll_window;
3185 return (Qnil);
3186}
3187
44fa5b1e 3188/* Mark all windows now on frame as deleted
7ab12479
JB
3189 by setting their buffers to nil. */
3190
fd482be5 3191void
7ab12479
JB
3192delete_all_subwindows (w)
3193 register struct window *w;
3194{
265a9e55 3195 if (!NILP (w->next))
7ab12479 3196 delete_all_subwindows (XWINDOW (w->next));
265a9e55 3197 if (!NILP (w->vchild))
7ab12479 3198 delete_all_subwindows (XWINDOW (w->vchild));
265a9e55 3199 if (!NILP (w->hchild))
7ab12479 3200 delete_all_subwindows (XWINDOW (w->hchild));
605be8af
JB
3201
3202 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
3203
3204 /* We set all three of these fields to nil, to make sure that we can
3205 distinguish this dead window from any live window. Live leaf
3206 windows will have buffer set, and combination windows will have
3207 vchild or hchild set. */
3208 w->buffer = Qnil;
3209 w->vchild = Qnil;
3210 w->hchild = Qnil;
7ab12479
JB
3211}
3212\f
3213static int
3214count_windows (window)
3215 register struct window *window;
3216{
3217 register int count = 1;
265a9e55 3218 if (!NILP (window->next))
7ab12479 3219 count += count_windows (XWINDOW (window->next));
265a9e55 3220 if (!NILP (window->vchild))
7ab12479 3221 count += count_windows (XWINDOW (window->vchild));
265a9e55 3222 if (!NILP (window->hchild))
7ab12479
JB
3223 count += count_windows (XWINDOW (window->hchild));
3224 return count;
3225}
3226
3227static int
3228save_window_save (window, vector, i)
3229 Lisp_Object window;
3230 struct Lisp_Vector *vector;
3231 int i;
3232{
3233 register struct saved_window *p;
3234 register struct window *w;
3235 register Lisp_Object tem;
3236
265a9e55 3237 for (;!NILP (window); window = w->next)
7ab12479
JB
3238 {
3239 p = SAVED_WINDOW_N (vector, i);
3240 w = XWINDOW (window);
3241
d834a2e9 3242 XSETFASTINT (w->temslot, i++);
7ab12479
JB
3243 p->window = window;
3244 p->buffer = w->buffer;
3245 p->left = w->left;
3246 p->top = w->top;
3247 p->width = w->width;
3248 p->height = w->height;
3249 p->hscroll = w->hscroll;
3250 p->display_table = w->display_table;
265a9e55 3251 if (!NILP (w->buffer))
7ab12479
JB
3252 {
3253 /* Save w's value of point in the window configuration.
3254 If w is the selected window, then get the value of point
3255 from the buffer; pointm is garbage in the selected window. */
3256 if (EQ (window, selected_window))
3257 {
3258 p->pointm = Fmake_marker ();
3259 Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
3260 w->buffer);
3261 }
3262 else
eeb82665 3263 p->pointm = Fcopy_marker (w->pointm, Qnil);
7ab12479 3264
eeb82665 3265 p->start = Fcopy_marker (w->start, Qnil);
7ab12479
JB
3266 p->start_at_line_beg = w->start_at_line_beg;
3267
3268 tem = XBUFFER (w->buffer)->mark;
eeb82665 3269 p->mark = Fcopy_marker (tem, Qnil);
7ab12479
JB
3270 }
3271 else
3272 {
3273 p->pointm = Qnil;
3274 p->start = Qnil;
3275 p->mark = Qnil;
3276 p->start_at_line_beg = Qnil;
3277 }
3278
265a9e55 3279 if (NILP (w->parent))
7ab12479
JB
3280 p->parent = Qnil;
3281 else
3282 p->parent = XWINDOW (w->parent)->temslot;
3283
265a9e55 3284 if (NILP (w->prev))
7ab12479
JB
3285 p->prev = Qnil;
3286 else
3287 p->prev = XWINDOW (w->prev)->temslot;
3288
265a9e55 3289 if (!NILP (w->vchild))
7ab12479 3290 i = save_window_save (w->vchild, vector, i);
265a9e55 3291 if (!NILP (w->hchild))
7ab12479
JB
3292 i = save_window_save (w->hchild, vector, i);
3293 }
3294
3295 return i;
3296}
3297
3298DEFUN ("current-window-configuration",
43bad991 3299 Fcurrent_window_configuration, Scurrent_window_configuration, 0, 1, 0,
44fa5b1e
JB
3300 "Return an object representing the current window configuration of FRAME.\n\
3301If FRAME is nil or omitted, use the selected frame.\n\
7ab12479
JB
3302This describes the number of windows, their sizes and current buffers,\n\
3303and for each displayed buffer, where display starts, and the positions of\n\
3304point and mark. An exception is made for point in the current buffer:\n\
bdc727bf
JB
3305its value is -not- saved.\n\
3306This also records the currently selected frame, and FRAME's focus\n\
3307redirection (see `redirect-frame-focus').")
44fa5b1e
JB
3308 (frame)
3309 Lisp_Object frame;
7ab12479
JB
3310{
3311 register Lisp_Object tem;
3312 register int n_windows;
3313 register struct save_window_data *data;
da2792e0 3314 register struct Lisp_Vector *vec;
7ab12479 3315 register int i;
44fa5b1e 3316 FRAME_PTR f;
43bad991 3317
44fa5b1e
JB
3318 if (NILP (frame))
3319 f = selected_frame;
43bad991
JB
3320 else
3321 {
44fa5b1e
JB
3322 CHECK_LIVE_FRAME (frame, 0);
3323 f = XFRAME (frame);
43bad991 3324 }
7ab12479 3325
44fa5b1e 3326 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
da2792e0
KH
3327 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
3328 for (i = 0; i < VECSIZE (struct save_window_data); i++)
3329 vec->contents[i] = Qnil;
3330 vec->size = VECSIZE (struct save_window_data);
3331 data = (struct save_window_data *)vec;
3332
d834a2e9
KH
3333 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
3334 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
3335 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
ad854249 3336#ifdef MULTI_FRAME
74112613 3337 XSETFRAME (data->selected_frame, selected_frame);
ad854249 3338#endif
44fa5b1e 3339 data->current_window = FRAME_SELECTED_WINDOW (f);
74112613 3340 XSETBUFFER (data->current_buffer, current_buffer);
7ab12479 3341 data->minibuf_scroll_window = Vminibuf_scroll_window;
44fa5b1e 3342 data->root_window = FRAME_ROOT_WINDOW (f);
bdc727bf 3343 data->focus_frame = FRAME_FOCUS_FRAME (f);
74112613
KH
3344 XSETINT (data->min_height, window_min_height);
3345 XSETINT (data->min_width, window_min_width);
7ab12479
JB
3346 tem = Fmake_vector (make_number (n_windows), Qnil);
3347 data->saved_windows = tem;
3348 for (i = 0; i < n_windows; i++)
3349 XVECTOR (tem)->contents[i]
3350 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
44fa5b1e 3351 save_window_save (FRAME_ROOT_WINDOW (f),
7ab12479 3352 XVECTOR (tem), 0);
74112613 3353 XSETWINDOW_CONFIGURATION (tem, data);
7ab12479
JB
3354 return (tem);
3355}
3356
3357DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
3358 0, UNEVALLED, 0,
3359 "Execute body, preserving window sizes and contents.\n\
eb16ec06
RS
3360Restore which buffer appears in which window, where display starts,\n\
3361and the value of point and mark for each window.\n\
3362Also restore which buffer is current.\n\
3363But do not preserve point in the current buffer.\n\
7ab12479
JB
3364Does not restore the value of point in current buffer.")
3365 (args)
3366 Lisp_Object args;
3367{
3368 register Lisp_Object val;
3369 register int count = specpdl_ptr - specpdl;
3370
3371 record_unwind_protect (Fset_window_configuration,
43bad991 3372 Fcurrent_window_configuration (Qnil));
7ab12479
JB
3373 val = Fprogn (args);
3374 return unbind_to (count, val);
3375}
3376\f
3377init_window_once ()
3378{
44fa5b1e
JB
3379#ifdef MULTI_FRAME
3380 selected_frame = make_terminal_frame ();
bc6c324f 3381 XSETFRAME (Vterminal_frame, selected_frame);
44fa5b1e
JB
3382 minibuf_window = selected_frame->minibuffer_window;
3383 selected_window = selected_frame->selected_window;
3384 last_nonminibuf_frame = selected_frame;
3385#else /* not MULTI_FRAME */
7ab12479
JB
3386 extern Lisp_Object get_minibuffer ();
3387
87485d6f
MW
3388 selected_frame = last_nonminibuf_frame = &the_only_frame;
3389
95605e15 3390 minibuf_window = make_window ();
4b206065 3391 FRAME_ROOT_WINDOW (selected_frame) = make_window ();
7ab12479 3392
44fa5b1e
JB
3393 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->next = minibuf_window;
3394 XWINDOW (minibuf_window)->prev = FRAME_ROOT_WINDOW (selected_frame);
4b206065 3395 XWINDOW (minibuf_window)->mini_p = Qt;
7ab12479
JB
3396
3397 /* These values 9 and 10 are arbitrary,
3398 just so that there is "something there."
3399 Correct values are put in in init_xdisp */
3400
d834a2e9
KH
3401 XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->width, 10);
3402 XSETFASTINT (XWINDOW (minibuf_window)->width, 10);
7ab12479 3403
d834a2e9
KH
3404 XSETFASTINT (XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->height, 9);
3405 XSETFASTINT (XWINDOW (minibuf_window)->top, 9);
3406 XSETFASTINT (XWINDOW (minibuf_window)->height, 1);
7ab12479
JB
3407
3408 /* Prevent error in Fset_window_buffer. */
44fa5b1e 3409 XWINDOW (FRAME_ROOT_WINDOW (selected_frame))->buffer = Qt;
7ab12479
JB
3410 XWINDOW (minibuf_window)->buffer = Qt;
3411
3412 /* Now set them up for real. */
44fa5b1e 3413 Fset_window_buffer (FRAME_ROOT_WINDOW (selected_frame),
e5d77022 3414 Fcurrent_buffer ());
7ab12479
JB
3415 Fset_window_buffer (minibuf_window, get_minibuffer (0));
3416
44fa5b1e 3417 selected_window = FRAME_ROOT_WINDOW (selected_frame);
1d8d96fa
JB
3418 /* Make sure this window seems more recently used than
3419 a newly-created, never-selected window. Increment
3420 window_select_count so the first selection ever will get
3421 something newer than this. */
d834a2e9 3422 XSETFASTINT (XWINDOW (selected_window)->use_time, ++window_select_count);
44fa5b1e 3423#endif /* not MULTI_FRAME */
7ab12479
JB
3424}
3425
3426syms_of_window ()
3427{
3428 Qwindowp = intern ("windowp");
3429 staticpro (&Qwindowp);
3430
806b4d9b
JB
3431 Qwindow_live_p = intern ("window-live-p");
3432 staticpro (&Qwindow_live_p);
605be8af 3433
2cccc823 3434 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
a58ec57d
RS
3435 staticpro (&Qtemp_buffer_show_hook);
3436
2f83aebe 3437#ifndef MULTI_FRAME
7ab12479
JB
3438 /* Make sure all windows get marked */
3439 staticpro (&minibuf_window);
2f83aebe 3440#endif
7ab12479
JB
3441
3442 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
3443 "Non-nil means call as function to display a help buffer.\n\
c3ef6b1d 3444The function is called with one argument, the buffer to be displayed.\n\
f52cca03
RS
3445Used by `with-output-to-temp-buffer'.\n\
3446If this function is used, then it must do the entire job of showing\n\
3447the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
7ab12479
JB
3448 Vtemp_buffer_show_function = Qnil;
3449
3450 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
3451 "If non-nil, function to call to handle `display-buffer'.\n\
3452It will receive two args, the buffer and a flag which if non-nil means\n\
3453 that the currently selected window is not acceptable.\n\
3454Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
3455work using this function.");
3456 Vdisplay_buffer_function = Qnil;
3457
7ab12479
JB
3458 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
3459 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
3460 Vminibuf_scroll_window = Qnil;
3461
3462 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
3463 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
3464 Vother_window_scroll_buffer = Qnil;
3465
44fa5b1e 3466 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
700f75a4 3467 "*Non-nil means `display-buffer' should make a separate frame.");
44fa5b1e 3468 pop_up_frames = 0;
7ab12479 3469
44fa5b1e 3470 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
a90712c2 3471 "Function to call to handle automatic new frame creation.\n\
44fa5b1e 3472It is called with no arguments and should return a newly created frame.\n\
7ab12479 3473\n\
44fa5b1e
JB
3474A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
3475where `pop-up-frame-alist' would hold the default frame parameters.");
3476 Vpop_up_frame_function = Qnil;
7ab12479 3477
a90712c2
RS
3478 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
3479 "*List of buffer names that should have their own special frames.\n\
3480Displaying a buffer whose name is in this list makes a special frame for it\n\
0a952b57 3481using `special-display-function'.\n\
3548e138
RS
3482\n\
3483An element of the list can be a cons cell instead of just a string.\n\
3484Then the car should be a buffer name, and the cdr specifies frame\n\
3485parameters for creating the frame for that buffer.\n\
3486More precisely, the cdr is passed as the second argument to\n\
3487the function found in `special-display-function', when making that frame.\n\
0a952b57 3488See also `special-display-regexps'.");
a90712c2
RS
3489 Vspecial_display_buffer_names = Qnil;
3490
3491 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
3492 "*List of regexps saying which buffers should have their own special frames.\n\
3493If a buffer name matches one of these regexps, it gets its own frame.\n\
3494Displaying a buffer whose name is in this list makes a special frame for it\n\
0a952b57 3495using `special-display-function'.\n\
3548e138
RS
3496\n\
3497An element of the list can be a cons cell instead of just a string.\n\
3498Then the car should be the regexp, and the cdr specifies frame\n\
3499parameters for creating the frame for buffers that match.\n\
3500More precisely, the cdr is passed as the second argument to\n\
3501the function found in `special-display-function', when making that frame.\n\
0a952b57 3502See also `special-display-buffer-names'.");
a90712c2
RS
3503 Vspecial_display_regexps = Qnil;
3504
3505 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
3506 "Function to call to make a new frame for a special buffer.\n\
0a952b57
RS
3507It is called with two arguments, the buffer and optional buffer specific\n\
3508data, and should return a window displaying that buffer.\n\
a90712c2 3509The default value makes a separate frame for the buffer,\n\
bdd3a802 3510using `special-display-frame-alist' to specify the frame parameters.\n\
a90712c2
RS
3511\n\
3512A buffer is special if its is listed in `special-display-buffer-names'\n\
3513or matches a regexp in `special-display-regexps'.");
3514 Vspecial_display_function = Qnil;
3515
855d8627
RS
3516 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
3517 "*List of buffer names that should appear in the selected window.\n\
3518Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
3519switches to it in the selected window, rather than making it appear\n\
2e5ce1a0 3520in some other window.\n\
855d8627
RS
3521\n\
3522An element of the list can be a cons cell instead of just a string.\n\
3523Then the car must be a string, which specifies the buffer name.\n\
3524This is for compatibility with `special-display-buffer-names';\n\
3525the cdr of the cons cell is ignored.\n\
3526\n\
3527See also `same-window-regexps'.");
3528 Vsame_window_buffer_names = Qnil;
3529
3530 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
3531 "*List of regexps saying which buffers should appear in the selected window.\n\
3532If a buffer name matches one of these regexps, then displaying it\n\
3533using `display-buffer' or `pop-to-buffer' switches to it\n\
3534in the selected window, rather than making it appear in some other window.\n\
3535\n\
3536An element of the list can be a cons cell instead of just a string.\n\
3537Then the car must be a string, which specifies the buffer name.\n\
3538This is for compatibility with `special-display-buffer-names';\n\
3539the cdr of the cons cell is ignored.\n\
3540\n\
3541See also `same-window-buffer-names'.");
3542 Vsame_window_regexps = Qnil;
3543
7ab12479
JB
3544 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
3545 "*Non-nil means display-buffer should make new windows.");
3546 pop_up_windows = 1;
3547
3548 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
3549 "*Number of lines of continuity when scrolling by screenfuls.");
3550 next_screen_context_lines = 2;
3551
3552 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
3553 "*display-buffer would prefer to split the largest window if this large.\n\
3554If there is only one window, it is split regardless of this value.");
3555 split_height_threshold = 500;
3556
3557 DEFVAR_INT ("window-min-height", &window_min_height,
3558 "*Delete any window less than this tall (including its mode line).");
3559 window_min_height = 4;
3560
3561 DEFVAR_INT ("window-min-width", &window_min_width,
3562 "*Delete any window less than this wide.");
3563 window_min_width = 10;
3564
3565 defsubr (&Sselected_window);
3566 defsubr (&Sminibuffer_window);
3567 defsubr (&Swindow_minibuffer_p);
3568 defsubr (&Swindowp);
806b4d9b 3569 defsubr (&Swindow_live_p);
7ab12479
JB
3570 defsubr (&Spos_visible_in_window_p);
3571 defsubr (&Swindow_buffer);
3572 defsubr (&Swindow_height);
3573 defsubr (&Swindow_width);
3574 defsubr (&Swindow_hscroll);
3575 defsubr (&Sset_window_hscroll);
190eb263
RS
3576 defsubr (&Swindow_redisplay_end_trigger);
3577 defsubr (&Sset_window_redisplay_end_trigger);
7ab12479 3578 defsubr (&Swindow_edges);
d5783c40
JB
3579 defsubr (&Scoordinates_in_window_p);
3580 defsubr (&Swindow_at);
7ab12479
JB
3581 defsubr (&Swindow_point);
3582 defsubr (&Swindow_start);
3583 defsubr (&Swindow_end);
3584 defsubr (&Sset_window_point);
3585 defsubr (&Sset_window_start);
3586 defsubr (&Swindow_dedicated_p);
d207b766 3587 defsubr (&Sset_window_dedicated_p);
7ab12479
JB
3588 defsubr (&Swindow_display_table);
3589 defsubr (&Sset_window_display_table);
3590 defsubr (&Snext_window);
3591 defsubr (&Sprevious_window);
3592 defsubr (&Sother_window);
3593 defsubr (&Sget_lru_window);
3594 defsubr (&Sget_largest_window);
3595 defsubr (&Sget_buffer_window);
3596 defsubr (&Sdelete_other_windows);
3597 defsubr (&Sdelete_windows_on);
3598 defsubr (&Sreplace_buffer_in_windows);
3599 defsubr (&Sdelete_window);
3600 defsubr (&Sset_window_buffer);
3601 defsubr (&Sselect_window);
3602 defsubr (&Sdisplay_buffer);
3603 defsubr (&Ssplit_window);
3604 defsubr (&Senlarge_window);
3605 defsubr (&Sshrink_window);
3606 defsubr (&Sscroll_up);
3607 defsubr (&Sscroll_down);
3608 defsubr (&Sscroll_left);
3609 defsubr (&Sscroll_right);
ccd0664b 3610 defsubr (&Sother_window_for_scrolling);
7ab12479
JB
3611 defsubr (&Sscroll_other_window);
3612 defsubr (&Srecenter);
3613 defsubr (&Smove_to_window_line);
3614 defsubr (&Swindow_configuration_p);
3615 defsubr (&Sset_window_configuration);
3616 defsubr (&Scurrent_window_configuration);
3617 defsubr (&Ssave_window_excursion);
3618}
3619
3620keys_of_window ()
3621{
3622 initial_define_key (control_x_map, '1', "delete-other-windows");
3623 initial_define_key (control_x_map, '2', "split-window");
3624 initial_define_key (control_x_map, '0', "delete-window");
3625 initial_define_key (control_x_map, 'o', "other-window");
3626 initial_define_key (control_x_map, '^', "enlarge-window");
3627 initial_define_key (control_x_map, '<', "scroll-left");
3628 initial_define_key (control_x_map, '>', "scroll-right");
3629
3630 initial_define_key (global_map, Ctl ('V'), "scroll-up");
3631 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
3632 initial_define_key (meta_map, 'v', "scroll-down");
3633
3634 initial_define_key (global_map, Ctl('L'), "recenter");
3635 initial_define_key (meta_map, 'r', "move-to-window-line");
3636}