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