Always load case-table, latin-1, latin-2, latin-3, latin-4.
[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 2221 /* If Fget_lru_window returned nil, try other approaches. */
48d9379d 2222
cee67da9 2223 /* Try visible frames first. */
48d9379d
RS
2224 if (NILP (window))
2225 window = Fget_buffer_window (buffer, Qvisible);
cee67da9
RS
2226 if (NILP (window))
2227 window = Fget_largest_window (Qvisible);
2228 /* If that didn't work, try iconified frames. */
48d9379d
RS
2229 if (NILP (window))
2230 window = Fget_buffer_window (buffer, make_number (0));
cee67da9
RS
2231 if (NILP (window))
2232 window = Fget_largest_window (make_number (0));
2233 /* Try invisible frames. */
48d9379d
RS
2234 if (NILP (window))
2235 window = Fget_buffer_window (buffer, Qt);
cee67da9
RS
2236 if (NILP (window))
2237 window = Fget_largest_window (Qt);
2238 /* As a last resort, make a new frame. */
2239 if (NILP (window))
2240 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
1942f68f
RS
2241 /* If window appears above or below another,
2242 even out their heights. */
cac66e4f 2243 other = upper = lower = Qnil;
1942f68f
RS
2244 if (!NILP (XWINDOW (window)->prev))
2245 other = upper = XWINDOW (window)->prev, lower = window;
2246 if (!NILP (XWINDOW (window)->next))
2247 other = lower = XWINDOW (window)->next, upper = window;
2248 if (!NILP (other)
2249 /* Check that OTHER and WINDOW are vertically arrayed. */
296b535c
KH
2250 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
2251 && (XFASTINT (XWINDOW (other)->height)
2252 > XFASTINT (XWINDOW (window)->height)))
1942f68f 2253 {
296b535c
KH
2254 int total = (XFASTINT (XWINDOW (other)->height)
2255 + XFASTINT (XWINDOW (window)->height));
8d77c0c8
KH
2256 Lisp_Object old_selected_window;
2257 old_selected_window = selected_window;
1942f68f 2258
8d77c0c8 2259 selected_window = upper;
296b535c
KH
2260 change_window_height ((total / 2
2261 - XFASTINT (XWINDOW (upper)->height)),
2262 0);
1942f68f
RS
2263 selected_window = old_selected_window;
2264 }
7ab12479
JB
2265 }
2266 }
2267 else
2268 window = Fget_lru_window (Qnil);
2269
2270 Fset_window_buffer (window, buffer);
d07f802a 2271 return display_buffer_1 (window);
7ab12479
JB
2272}
2273
2274void
2275temp_output_buffer_show (buf)
2276 register Lisp_Object buf;
2277{
2278 register struct buffer *old = current_buffer;
2279 register Lisp_Object window;
2280 register struct window *w;
2281
2282 Fset_buffer (buf);
c6367666 2283 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
7ab12479
JB
2284 BEGV = BEG;
2285 ZV = Z;
2286 SET_PT (BEG);
1479ef51 2287 XBUFFER (buf)->clip_changed = 1;
7ab12479
JB
2288 set_buffer_internal (old);
2289
2290 if (!EQ (Vtemp_buffer_show_function, Qnil))
2291 call1 (Vtemp_buffer_show_function, buf);
2292 else
2293 {
2294 window = Fdisplay_buffer (buf, Qnil);
2295
44fa5b1e
JB
2296 if (XFRAME (XWINDOW (window)->frame) != selected_frame)
2297 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
7ab12479
JB
2298 Vminibuf_scroll_window = window;
2299 w = XWINDOW (window);
d834a2e9 2300 XSETFASTINT (w->hscroll, 0);
7ab12479
JB
2301 set_marker_restricted (w->start, make_number (1), buf);
2302 set_marker_restricted (w->pointm, make_number (1), buf);
a58ec57d 2303
37962e60 2304 /* Run temp-buffer-show-hook, with the chosen window selected. */
f52cca03 2305 if (!NILP (Vrun_hooks))
2cccc823 2306 {
f52cca03
RS
2307 Lisp_Object tem;
2308 tem = Fboundp (Qtemp_buffer_show_hook);
2cccc823
RS
2309 if (!NILP (tem))
2310 {
f52cca03
RS
2311 tem = Fsymbol_value (Qtemp_buffer_show_hook);
2312 if (!NILP (tem))
2313 {
2314 int count = specpdl_ptr - specpdl;
2cccc823 2315
f52cca03
RS
2316 /* Select the window that was chosen, for running the hook. */
2317 record_unwind_protect (Fset_window_configuration,
2318 Fcurrent_window_configuration (Qnil));
2cccc823 2319
f52cca03
RS
2320 Fselect_window (window);
2321 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
2322 unbind_to (count, Qnil);
2323 }
2cccc823
RS
2324 }
2325 }
2326 }
7ab12479
JB
2327}
2328\f
2329static
2330make_dummy_parent (window)
2331 Lisp_Object window;
2332{
cffec418 2333 Lisp_Object new;
7ab12479 2334 register struct window *o, *p;
cffec418
KH
2335 register struct Lisp_Vector *vec;
2336 int i;
7ab12479 2337
cffec418
KH
2338 o = XWINDOW (window);
2339 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
2340 for (i = 0; i < VECSIZE (struct window); ++i)
2341 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
2342 vec->size = VECSIZE (struct window);
2343 p = (struct window *)vec;
2344 XSETWINDOW (new, p);
7ab12479 2345
d834a2e9 2346 XSETFASTINT (p->sequence_number, ++sequence_number);
7ab12479
JB
2347
2348 /* Put new into window structure in place of window */
2349 replace_window (window, new);
2350
2351 o->next = Qnil;
2352 o->prev = Qnil;
2353 o->vchild = Qnil;
2354 o->hchild = Qnil;
2355 o->parent = new;
2356
2357 p->start = Qnil;
2358 p->pointm = Qnil;
2359 p->buffer = Qnil;
2360}
2361
2362DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
2363 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
2364WINDOW defaults to selected one and SIZE to half its size.\n\
77ae0fe3 2365If optional third arg HORFLAG is non-nil, split side by side\n\
7ab12479 2366and put SIZE columns in the first of the pair.")
77ae0fe3
KH
2367 (window, size, horflag)
2368 Lisp_Object window, size, horflag;
7ab12479
JB
2369{
2370 register Lisp_Object new;
2371 register struct window *o, *p;
c0807608 2372 FRAME_PTR fo;
77ae0fe3 2373 register int size_int;
7ab12479 2374
265a9e55 2375 if (NILP (window))
7ab12479
JB
2376 window = selected_window;
2377 else
605be8af 2378 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2379
2380 o = XWINDOW (window);
c0807608 2381 fo = XFRAME (WINDOW_FRAME (o));
7ab12479 2382
77ae0fe3 2383 if (NILP (size))
7ab12479 2384 {
265a9e55 2385 if (!NILP (horflag))
c0807608
KH
2386 /* Calculate the size of the left-hand window, by dividing
2387 the usable space in columns by two. */
a59fed7e 2388 size_int = XFASTINT (o->width) >> 1;
7ab12479 2389 else
77ae0fe3 2390 size_int = XFASTINT (o->height) >> 1;
7ab12479
JB
2391 }
2392 else
2393 {
77ae0fe3
KH
2394 CHECK_NUMBER (size, 1);
2395 size_int = XINT (size);
7ab12479
JB
2396 }
2397
2398 if (MINI_WINDOW_P (o))
2399 error ("Attempt to split minibuffer window");
7d601aaa 2400 else if (FRAME_NO_SPLIT_P (fo) && ! frame_override_unsplittable)
44fa5b1e 2401 error ("Attempt to split unsplittable frame");
7ab12479 2402
a481b3ea 2403 check_min_window_sizes ();
7ab12479 2404
265a9e55 2405 if (NILP (horflag))
7ab12479 2406 {
77ae0fe3
KH
2407 if (size_int < window_min_height)
2408 error ("Window height %d too small (after splitting)", size_int);
2409 if (size_int + window_min_height > XFASTINT (o->height))
37962e60 2410 error ("Window height %d too small (after splitting)",
77ae0fe3 2411 XFASTINT (o->height) - size_int);
265a9e55
JB
2412 if (NILP (o->parent)
2413 || NILP (XWINDOW (o->parent)->vchild))
7ab12479
JB
2414 {
2415 make_dummy_parent (window);
2416 new = o->parent;
2417 XWINDOW (new)->vchild = window;
2418 }
2419 }
2420 else
2421 {
77ae0fe3
KH
2422 if (size_int < window_min_width)
2423 error ("Window width %d too small (after splitting)", size_int);
a59fed7e
RS
2424
2425 if (size_int + window_min_width > XFASTINT (o->width))
37962e60 2426 error ("Window width %d too small (after splitting)",
a59fed7e 2427 XFASTINT (o->width) - size_int);
265a9e55
JB
2428 if (NILP (o->parent)
2429 || NILP (XWINDOW (o->parent)->hchild))
7ab12479
JB
2430 {
2431 make_dummy_parent (window);
2432 new = o->parent;
2433 XWINDOW (new)->hchild = window;
2434 }
2435 }
2436
2437 /* Now we know that window's parent is a vertical combination
2438 if we are dividing vertically, or a horizontal combination
2439 if we are making side-by-side windows */
2440
2441 windows_or_buffers_changed++;
c0807608 2442 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
7ab12479
JB
2443 new = make_window ();
2444 p = XWINDOW (new);
2445
44fa5b1e 2446 p->frame = o->frame;
7ab12479 2447 p->next = o->next;
265a9e55 2448 if (!NILP (p->next))
7ab12479
JB
2449 XWINDOW (p->next)->prev = new;
2450 p->prev = window;
2451 o->next = new;
2452 p->parent = o->parent;
2453 p->buffer = Qt;
2454
44fa5b1e 2455 /* Apportion the available frame space among the two new windows */
7ab12479 2456
265a9e55 2457 if (!NILP (horflag))
7ab12479
JB
2458 {
2459 p->height = o->height;
2460 p->top = o->top;
a59fed7e 2461 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
77ae0fe3
KH
2462 XSETFASTINT (o->width, size_int);
2463 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
7ab12479
JB
2464 }
2465 else
2466 {
2467 p->left = o->left;
2468 p->width = o->width;
77ae0fe3
KH
2469 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
2470 XSETFASTINT (o->height, size_int);
2471 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
7ab12479
JB
2472 }
2473
543f5fb1
RS
2474 Fset_window_buffer (new, o->buffer);
2475
7ab12479
JB
2476 return new;
2477}
2478\f
2479DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
2480 "Make current window ARG lines bigger.\n\
2481From program, optional second arg non-nil means grow sideways ARG columns.")
413430c5
EN
2482 (arg, side)
2483 register Lisp_Object arg, side;
7ab12479 2484{
413430c5
EN
2485 CHECK_NUMBER (arg, 0);
2486 change_window_height (XINT (arg), !NILP (side));
543f5fb1
RS
2487
2488 if (! NILP (Vwindow_configuration_change_hook))
2489 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2490
7ab12479
JB
2491 return Qnil;
2492}
2493
2494DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
2495 "Make current window ARG lines smaller.\n\
413430c5
EN
2496From program, optional second arg non-nil means shrink sideways arg columns.")
2497 (arg, side)
2498 register Lisp_Object arg, side;
7ab12479 2499{
413430c5
EN
2500 CHECK_NUMBER (arg, 0);
2501 change_window_height (-XINT (arg), !NILP (side));
543f5fb1
RS
2502
2503 if (! NILP (Vwindow_configuration_change_hook))
2504 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2505
7ab12479
JB
2506 return Qnil;
2507}
2508
2509int
2510window_height (window)
2511 Lisp_Object window;
2512{
2513 register struct window *p = XWINDOW (window);
2514 return XFASTINT (p->height);
2515}
2516
2517int
2518window_width (window)
2519 Lisp_Object window;
2520{
2521 register struct window *p = XWINDOW (window);
2522 return XFASTINT (p->width);
2523}
2524
05c2896a
JB
2525#define MINSIZE(w) \
2526 (widthflag \
2527 ? window_min_width \
2528 : (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))
7ab12479
JB
2529
2530#define CURBEG(w) \
05c2896a 2531 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
7ab12479
JB
2532
2533#define CURSIZE(w) \
05c2896a 2534 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
7ab12479
JB
2535
2536/* Unlike set_window_height, this function
2537 also changes the heights of the siblings so as to
2538 keep everything consistent. */
2539
2540change_window_height (delta, widthflag)
2541 register int delta;
2542 int widthflag;
2543{
2544 register Lisp_Object parent;
2545 Lisp_Object window;
2546 register struct window *p;
2547 int *sizep;
2548 int (*sizefun) () = widthflag ? window_width : window_height;
2549 register int (*setsizefun) () = (widthflag
2550 ? set_window_width
2551 : set_window_height);
db98a733
RS
2552 int maximum;
2553 Lisp_Object next, prev;
7ab12479 2554
a481b3ea 2555 check_min_window_sizes ();
7ab12479
JB
2556
2557 window = selected_window;
2558 while (1)
2559 {
2560 p = XWINDOW (window);
2561 parent = p->parent;
265a9e55 2562 if (NILP (parent))
7ab12479
JB
2563 {
2564 if (widthflag)
2565 error ("No other window to side of this one");
2566 break;
2567 }
265a9e55
JB
2568 if (widthflag ? !NILP (XWINDOW (parent)->hchild)
2569 : !NILP (XWINDOW (parent)->vchild))
7ab12479
JB
2570 break;
2571 window = parent;
2572 }
2573
05c2896a 2574 sizep = &CURSIZE (window);
7ab12479 2575
7ab12479
JB
2576 {
2577 register int maxdelta;
7ab12479 2578
265a9e55
JB
2579 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
2580 : !NILP (p->next) ? (*sizefun) (p->next) - MINSIZE (p->next)
2581 : !NILP (p->prev) ? (*sizefun) (p->prev) - MINSIZE (p->prev)
44fa5b1e
JB
2582 /* This is a frame with only one window, a minibuffer-only
2583 or a minibufferless frame. */
d5783c40 2584 : (delta = 0));
7ab12479
JB
2585
2586 if (delta > maxdelta)
2587 /* This case traps trying to make the minibuffer
44fa5b1e
JB
2588 the full frame, or make the only window aside from the
2589 minibuffer the full frame. */
7ab12479 2590 delta = maxdelta;
6b54027b 2591 }
d5783c40 2592
6b54027b
RS
2593 if (*sizep + delta < MINSIZE (window))
2594 {
543f5fb1 2595 delete_window (window);
d5783c40 2596 return;
6b54027b
RS
2597 }
2598
2599 if (delta == 0)
2600 return;
7ab12479 2601
db98a733
RS
2602 /* Find the total we can get from other siblings. */
2603 maximum = 0;
2604 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
2605 maximum += (*sizefun) (next) - MINSIZE (next);
2606 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
2607 maximum += (*sizefun) (prev) - MINSIZE (prev);
2608
2609 /* If we can get it all from them, do so. */
2610 if (delta < maximum)
7ab12479 2611 {
db98a733
RS
2612 Lisp_Object first_unaffected;
2613 Lisp_Object first_affected;
2614
2615 next = p->next;
2616 prev = p->prev;
2617 first_affected = window;
2618 /* Look at one sibling at a time,
2619 moving away from this window in both directions alternately,
2620 and take as much as we can get without deleting that sibling. */
dc91fb5d 2621 while (delta != 0)
db98a733
RS
2622 {
2623 if (delta == 0)
2624 break;
2625 if (! NILP (next))
2626 {
2627 int this_one = (*sizefun) (next) - MINSIZE (next);
2628 if (this_one > delta)
2629 this_one = delta;
2630
2631 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
2632 (*setsizefun) (window, *sizep + this_one, 0);
2633
2634 delta -= this_one;
2635 next = XWINDOW (next)->next;
2636 }
2637 if (delta == 0)
2638 break;
2639 if (! NILP (prev))
2640 {
2641 int this_one = (*sizefun) (prev) - MINSIZE (prev);
2642 if (this_one > delta)
2643 this_one = delta;
2644
2645 first_affected = prev;
2646
2647 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
2648 (*setsizefun) (window, *sizep + this_one, 0);
2649
2650 delta -= this_one;
2651 prev = XWINDOW (prev)->prev;
2652 }
2653 }
2654
2655 /* Now recalculate the edge positions of all the windows affected,
2656 based on the new sizes. */
2657 first_unaffected = next;
2658 prev = first_affected;
2659 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
2660 prev = next, next = XWINDOW (next)->next)
2661 {
2662 CURBEG (next) = CURBEG (prev) + (*sizefun) (prev);
2663 /* This does not change size of NEXT,
2664 but it propagates the new top edge to its children */
2665 (*setsizefun) (next, (*sizefun) (next), 0);
2666 }
7ab12479
JB
2667 }
2668 else
2669 {
2670 register int delta1;
2671 register int opht = (*sizefun) (parent);
2672
2673 /* If trying to grow this window to or beyond size of the parent,
2674 make delta1 so big that, on shrinking back down,
2675 all the siblings end up with less than one line and are deleted. */
2676 if (opht <= *sizep + delta)
2677 delta1 = opht * opht * 2;
2678 /* Otherwise, make delta1 just right so that if we add delta1
2679 lines to this window and to the parent, and then shrink
2680 the parent back to its original size, the new proportional
2681 size of this window will increase by delta. */
2682 else
2683 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100);
2684
2685 /* Add delta1 lines or columns to this window, and to the parent,
2686 keeping things consistent while not affecting siblings. */
05c2896a 2687 CURSIZE (parent) = opht + delta1;
7ab12479
JB
2688 (*setsizefun) (window, *sizep + delta1, 0);
2689
2690 /* Squeeze out delta1 lines or columns from our parent,
2691 shriking this window and siblings proportionately.
2692 This brings parent back to correct size.
2693 Delta1 was calculated so this makes this window the desired size,
2694 taking it all out of the siblings. */
2695 (*setsizefun) (parent, opht, 0);
2696 }
2697
d834a2e9 2698 XSETFASTINT (p->last_modified, 0);
3cd21523 2699 XSETFASTINT (p->last_overlay_modified, 0);
7ab12479
JB
2700}
2701#undef MINSIZE
2702#undef CURBEG
2703#undef CURSIZE
2704
2705\f
2706/* Return number of lines of text (not counting mode line) in W. */
2707
2708int
2709window_internal_height (w)
2710 struct window *w;
2711{
2712 int ht = XFASTINT (w->height);
2713
2714 if (MINI_WINDOW_P (w))
2715 return ht;
2716
265a9e55
JB
2717 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
2718 || !NILP (w->next) || !NILP (w->prev)
44fa5b1e 2719 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
7ab12479
JB
2720 return ht - 1;
2721
2722 return ht;
2723}
2724
535e0b8e
JB
2725
2726/* Return the number of columns in W.
a3c87d4e 2727 Don't count columns occupied by scroll bars or the vertical bar
535e0b8e
JB
2728 separating W from the sibling to its right. */
2729int
2730window_internal_width (w)
2731 struct window *w;
2732{
2733 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
535e0b8e
JB
2734 int width = XINT (w->width);
2735
a3c87d4e
JB
2736 /* Scroll bars occupy a few columns. */
2737 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
ca0d0bb9 2738 return width - FRAME_SCROLL_BAR_COLS (f);
535e0b8e
JB
2739
2740 /* The column of `|' characters separating side-by-side windows
2741 occupies one column only. */
111e5992
RS
2742 if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
2743 return width - 1;
2744
2745 return width;
535e0b8e
JB
2746}
2747
2748
101d1605 2749/* Scroll contents of window WINDOW up N lines.
9317a85d 2750 If WHOLE is nonzero, it means scroll N screenfuls instead. */
7ab12479 2751
101d1605
RS
2752static void
2753window_scroll (window, n, whole, noerror)
7ab12479
JB
2754 Lisp_Object window;
2755 int n;
101d1605 2756 int whole;
f8026fd8 2757 int noerror;
7ab12479
JB
2758{
2759 register struct window *w = XWINDOW (window);
5ce7b543 2760 register int opoint = PT;
7ab12479
JB
2761 register int pos;
2762 register int ht = window_internal_height (w);
2763 register Lisp_Object tem;
2764 int lose;
2765 Lisp_Object bolp, nmoved;
345d45b2 2766 int startpos;
101d1605
RS
2767 struct position posit;
2768 int original_vpos;
2769
2770 startpos = marker_position (w->start);
2771
2772 posit = *compute_motion (startpos, 0, 0, 0,
2773 PT, ht, 0,
2774 window_internal_width (w), XINT (w->hscroll),
2775 0, w);
2776 original_vpos = posit.vpos;
0a1f771a 2777
d834a2e9 2778 XSETFASTINT (tem, PT);
7ab12479
JB
2779 tem = Fpos_visible_in_window_p (tem, window);
2780
265a9e55 2781 if (NILP (tem))
7ab12479 2782 {
cd2be1dd 2783 Fvertical_motion (make_number (- (ht / 2)), window);
345d45b2 2784 startpos = PT;
7ab12479
JB
2785 }
2786
345d45b2 2787 SET_PT (startpos);
5ce7b543 2788 lose = n < 0 && PT == BEGV;
540b6aa0 2789 Fvertical_motion (make_number (n), window);
5ce7b543 2790 pos = PT;
7ab12479
JB
2791 bolp = Fbolp ();
2792 SET_PT (opoint);
2793
2794 if (lose)
f8026fd8
JB
2795 {
2796 if (noerror)
2797 return;
2798 else
2799 Fsignal (Qbeginning_of_buffer, Qnil);
2800 }
7ab12479
JB
2801
2802 if (pos < ZV)
7ab12479 2803 {
0c7da84e
RS
2804 int this_scroll_margin = scroll_margin;
2805
2806 /* Don't use a scroll margin that is negative or too large. */
2807 if (this_scroll_margin < 0)
2808 this_scroll_margin = 0;
2809
2810 if (XINT (w->height) < 4 * scroll_margin)
2811 this_scroll_margin = XINT (w->height) / 4;
2812
7ab12479
JB
2813 set_marker_restricted (w->start, make_number (pos), w->buffer);
2814 w->start_at_line_beg = bolp;
2815 w->update_mode_line = Qt;
d834a2e9 2816 XSETFASTINT (w->last_modified, 0);
3cd21523 2817 XSETFASTINT (w->last_overlay_modified, 0);
345d45b2
RS
2818 /* Set force_start so that redisplay_window will run
2819 the window-scroll-functions. */
2820 w->force_start = Qt;
0c7da84e 2821
9317a85d 2822 if (whole && scroll_preserve_screen_position)
0c7da84e
RS
2823 {
2824 SET_PT (pos);
101d1605 2825 Fvertical_motion (make_number (original_vpos), window);
0c7da84e 2826 }
101d1605
RS
2827 /* If we scrolled forward, put point enough lines down
2828 that it is outside the scroll margin. */
2829 else if (n > 0)
0c7da84e 2830 {
101d1605
RS
2831 int top_margin;
2832
2833 if (this_scroll_margin > 0)
2834 {
2835 SET_PT (pos);
2836 Fvertical_motion (make_number (this_scroll_margin), window);
2837 top_margin = PT;
2838 }
2839 else
2840 top_margin = pos;
2841
2842 if (top_margin <= opoint)
2843 SET_PT (opoint);
9317a85d 2844 else if (scroll_preserve_screen_position)
101d1605
RS
2845 {
2846 SET_PT (pos);
2847 Fvertical_motion (make_number (original_vpos), window);
2848 }
9317a85d
RS
2849 else
2850 SET_PT (pos);
0c7da84e 2851 }
101d1605 2852 else if (n < 0)
7ab12479 2853 {
101d1605
RS
2854 int bottom_margin;
2855
0c7da84e
RS
2856 /* If we scrolled backward, put point near the end of the window
2857 but not within the scroll margin. */
7ab12479 2858 SET_PT (pos);
0c7da84e 2859 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
101d1605
RS
2860 if (XFASTINT (tem) == ht - this_scroll_margin)
2861 bottom_margin = PT;
2862 else
2863 bottom_margin = PT + 1;
2864
2865 if (bottom_margin > opoint)
7ab12479
JB
2866 SET_PT (opoint);
2867 else
101d1605 2868 {
9317a85d
RS
2869 if (scroll_preserve_screen_position)
2870 {
2871 SET_PT (pos);
2872 Fvertical_motion (make_number (original_vpos), window);
2873 }
2874 else
2875 Fvertical_motion (make_number (-1), window);
101d1605 2876 }
7ab12479
JB
2877 }
2878 }
2879 else
f8026fd8
JB
2880 {
2881 if (noerror)
2882 return;
2883 else
2884 Fsignal (Qend_of_buffer, Qnil);
2885 }
7ab12479
JB
2886}
2887\f
2888/* This is the guts of Fscroll_up and Fscroll_down. */
2889
2890static void
2891scroll_command (n, direction)
2892 register Lisp_Object n;
2893 int direction;
2894{
2895 register int defalt;
2896 int count = specpdl_ptr - specpdl;
2897
95605e15
JB
2898 /* If selected window's buffer isn't current, make it current for the moment.
2899 But don't screw up if window_scroll gets an error. */
7ab12479 2900 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
95605e15
JB
2901 {
2902 record_unwind_protect (save_excursion_restore, save_excursion_save ());
2903 Fset_buffer (XWINDOW (selected_window)->buffer);
2904 }
7ab12479
JB
2905
2906 defalt = (window_internal_height (XWINDOW (selected_window))
2907 - next_screen_context_lines);
2908 defalt = direction * (defalt < 1 ? 1 : defalt);
2909
265a9e55 2910 if (NILP (n))
101d1605 2911 window_scroll (selected_window, defalt, 1, 0);
7ab12479 2912 else if (EQ (n, Qminus))
101d1605 2913 window_scroll (selected_window, - defalt, 1, 0);
7ab12479
JB
2914 else
2915 {
2916 n = Fprefix_numeric_value (n);
101d1605 2917 window_scroll (selected_window, XINT (n) * direction, 0, 0);
7ab12479 2918 }
95605e15
JB
2919
2920 unbind_to (count, Qnil);
7ab12479
JB
2921}
2922
2923DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
2924 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
2925A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 2926Negative ARG means scroll downward.\n\
7ab12479 2927When calling from a program, supply a number as argument or nil.")
413430c5
EN
2928 (arg)
2929 Lisp_Object arg;
7ab12479 2930{
413430c5 2931 scroll_command (arg, 1);
7ab12479
JB
2932 return Qnil;
2933}
2934
2935DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
2936 "Scroll text of current window downward ARG lines; or near full screen if no ARG.\n\
2937A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 2938Negative ARG means scroll upward.\n\
7ab12479 2939When calling from a program, supply a number as argument or nil.")
413430c5
EN
2940 (arg)
2941 Lisp_Object arg;
7ab12479 2942{
413430c5 2943 scroll_command (arg, -1);
7ab12479
JB
2944 return Qnil;
2945}
ccd0664b
RS
2946\f
2947DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
2948 "Return the other window for \"other window scroll\" commands.\n\
77b24de6 2949If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
ccd0664b
RS
2950specifies the window.\n\
2951If `other-window-scroll-buffer' is non-nil, a window\n\
2952showing that buffer is used.")
eb16ec06 2953 ()
7ab12479 2954{
ccd0664b 2955 Lisp_Object window;
7ab12479
JB
2956
2957 if (MINI_WINDOW_P (XWINDOW (selected_window))
265a9e55 2958 && !NILP (Vminibuf_scroll_window))
7ab12479
JB
2959 window = Vminibuf_scroll_window;
2960 /* If buffer is specified, scroll that buffer. */
265a9e55 2961 else if (!NILP (Vother_window_scroll_buffer))
7ab12479
JB
2962 {
2963 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
265a9e55 2964 if (NILP (window))
7ab12479
JB
2965 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
2966 }
2967 else
dbc4e1c1
JB
2968 {
2969 /* Nothing specified; look for a neighboring window on the same
2970 frame. */
2971 window = Fnext_window (selected_window, Qnil, Qnil);
2972
2973 if (EQ (window, selected_window))
2974 /* That didn't get us anywhere; look for a window on another
2975 visible frame. */
2976 do
2977 window = Fnext_window (window, Qnil, Qt);
2978 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
2979 && ! EQ (window, selected_window));
2980 }
2981
605be8af 2982 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2983
2984 if (EQ (window, selected_window))
2985 error ("There is no other window");
2986
ccd0664b
RS
2987 return window;
2988}
2989
2990DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
2991 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
2992The next window is the one below the current one; or the one at the top\n\
2993if the current one is at the bottom. Negative ARG means scroll downward.\n\
2994When calling from a program, supply a number as argument or nil.\n\
2995\n\
2996If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
2997specifies the window to scroll.\n\
2998If `other-window-scroll-buffer' is non-nil, scroll the window\n\
2999showing that buffer, popping the buffer up if necessary.")
413430c5
EN
3000 (arg)
3001 register Lisp_Object arg;
ccd0664b
RS
3002{
3003 register Lisp_Object window;
2f787aa3 3004 register int defalt;
ccd0664b
RS
3005 register struct window *w;
3006 register int count = specpdl_ptr - specpdl;
3007
3008 window = Fother_window_for_scrolling ();
3009
7ab12479 3010 w = XWINDOW (window);
2f787aa3
KH
3011 defalt = window_internal_height (w) - next_screen_context_lines;
3012 if (defalt < 1) defalt = 1;
7ab12479
JB
3013
3014 /* Don't screw up if window_scroll gets an error. */
3015 record_unwind_protect (save_excursion_restore, save_excursion_save ());
3016
3017 Fset_buffer (w->buffer);
3018 SET_PT (marker_position (w->pointm));
3019
413430c5 3020 if (NILP (arg))
101d1605 3021 window_scroll (window, defalt, 1, 1);
413430c5 3022 else if (EQ (arg, Qminus))
101d1605 3023 window_scroll (window, -defalt, 1, 1);
7ab12479
JB
3024 else
3025 {
413430c5
EN
3026 if (CONSP (arg))
3027 arg = Fcar (arg);
3028 CHECK_NUMBER (arg, 0);
101d1605 3029 window_scroll (window, XINT (arg), 0, 1);
7ab12479
JB
3030 }
3031
5ce7b543 3032 Fset_marker (w->pointm, make_number (PT), Qnil);
f4e7b2c2 3033 unbind_to (count, Qnil);
7ab12479
JB
3034
3035 return Qnil;
3036}
3037\f
644b477c 3038DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
7ab12479
JB
3039 "Scroll selected window display ARG columns left.\n\
3040Default for ARG is window width minus 2.")
3041 (arg)
3042 register Lisp_Object arg;
3043{
3044
265a9e55 3045 if (NILP (arg))
d834a2e9 3046 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
7ab12479
JB
3047 else
3048 arg = Fprefix_numeric_value (arg);
3049
3050 return
3051 Fset_window_hscroll (selected_window,
3052 make_number (XINT (XWINDOW (selected_window)->hscroll)
3053 + XINT (arg)));
3054}
3055
644b477c 3056DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
7ab12479
JB
3057 "Scroll selected window display ARG columns right.\n\
3058Default for ARG is window width minus 2.")
3059 (arg)
3060 register Lisp_Object arg;
3061{
265a9e55 3062 if (NILP (arg))
d834a2e9 3063 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
7ab12479
JB
3064 else
3065 arg = Fprefix_numeric_value (arg);
3066
3067 return
3068 Fset_window_hscroll (selected_window,
3069 make_number (XINT (XWINDOW (selected_window)->hscroll)
3070 - XINT (arg)));
3071}
3072
3073DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
44fa5b1e 3074 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
7ab12479 3075The desired position of point is always relative to the current window.\n\
44fa5b1e 3076Just C-u as prefix means put point in the center of the window.\n\
413430c5 3077If ARG is omitted or nil, erases the entire frame and then\n\
44fa5b1e 3078redraws with point in the center of the current window.")
413430c5
EN
3079 (arg)
3080 register Lisp_Object arg;
7ab12479
JB
3081{
3082 register struct window *w = XWINDOW (selected_window);
3083 register int ht = window_internal_height (w);
113d9015 3084 struct position pos;
7ab12479 3085
413430c5 3086 if (NILP (arg))
7ab12479 3087 {
44fa5b1e 3088 extern int frame_garbaged;
7ab12479 3089
44fa5b1e 3090 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
413430c5 3091 XSETFASTINT (arg, ht / 2);
7ab12479 3092 }
413430c5 3093 else if (CONSP (arg)) /* Just C-u. */
7ab12479 3094 {
413430c5 3095 XSETFASTINT (arg, ht / 2);
7ab12479
JB
3096 }
3097 else
3098 {
413430c5
EN
3099 arg = Fprefix_numeric_value (arg);
3100 CHECK_NUMBER (arg, 0);
7ab12479
JB
3101 }
3102
413430c5
EN
3103 if (XINT (arg) < 0)
3104 XSETINT (arg, XINT (arg) + ht);
7ab12479 3105
6ec8bbd2 3106 pos = *vmotion (PT, - XINT (arg), w);
7ab12479 3107
113d9015
KH
3108 Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
3109 w->start_at_line_beg = ((pos.bufpos == BEGV
5a255667 3110 || FETCH_BYTE (pos.bufpos - 1) == '\n')
113d9015 3111 ? Qt : Qnil);
7ab12479
JB
3112 w->force_start = Qt;
3113
3114 return Qnil;
3115}
3116\f
3117DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
3118 1, 1, "P",
3119 "Position point relative to window.\n\
19e3bf0a 3120With no argument, position point at center of window.\n\
44fa5b1e 3121An argument specifies frame line; zero means top of window,\n\
7ab12479
JB
3122negative means relative to bottom of window.")
3123 (arg)
3124 register Lisp_Object arg;
3125{
3126 register struct window *w = XWINDOW (selected_window);
3127 register int height = window_internal_height (w);
3128 register int start;
540b6aa0 3129 Lisp_Object window;
7ab12479 3130
265a9e55 3131 if (NILP (arg))
d834a2e9 3132 XSETFASTINT (arg, height / 2);
7ab12479
JB
3133 else
3134 {
3135 arg = Fprefix_numeric_value (arg);
3136 if (XINT (arg) < 0)
3137 XSETINT (arg, XINT (arg) + height);
3138 }
3139
3140 start = marker_position (w->start);
74112613 3141 XSETWINDOW (window, w);
7ab12479
JB
3142 if (start < BEGV || start > ZV)
3143 {
cd2be1dd 3144 Fvertical_motion (make_number (- (height / 2)), window);
5ce7b543 3145 Fset_marker (w->start, make_number (PT), w->buffer);
7ab12479
JB
3146 w->start_at_line_beg = Fbolp ();
3147 w->force_start = Qt;
3148 }
3149 else
3150 SET_PT (start);
3151
540b6aa0 3152 return Fvertical_motion (arg, window);
7ab12479
JB
3153}
3154\f
3155struct save_window_data
3156 {
f5ccc0cc 3157 EMACS_INT size_from_Lisp_Vector_struct;
7ab12479 3158 struct Lisp_Vector *next_from_Lisp_Vector_struct;
8f6ea2e9 3159 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
bdc727bf 3160 Lisp_Object selected_frame;
7ab12479
JB
3161 Lisp_Object current_window;
3162 Lisp_Object current_buffer;
3163 Lisp_Object minibuf_scroll_window;
3164 Lisp_Object root_window;
bdc727bf 3165 Lisp_Object focus_frame;
756b6edc
RS
3166 /* Record the values of window-min-width and window-min-height
3167 so that window sizes remain consistent with them. */
3168 Lisp_Object min_width, min_height;
7ab12479
JB
3169 /* A vector, interpreted as a struct saved_window */
3170 Lisp_Object saved_windows;
3171 };
ff06df24 3172
7ab12479
JB
3173/* This is saved as a Lisp_Vector */
3174struct saved_window
3175 {
3176 /* these first two must agree with struct Lisp_Vector in lisp.h */
f5ccc0cc 3177 EMACS_INT size_from_Lisp_Vector_struct;
7ab12479
JB
3178 struct Lisp_Vector *next_from_Lisp_Vector_struct;
3179
3180 Lisp_Object window;
3181 Lisp_Object buffer, start, pointm, mark;
3182 Lisp_Object left, top, width, height, hscroll;
3183 Lisp_Object parent, prev;
3184 Lisp_Object start_at_line_beg;
3185 Lisp_Object display_table;
3186 };
3187#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
3188
3189#define SAVED_WINDOW_N(swv,n) \
3190 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
3191
3192DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5c4d25a6 3193 "T if OBJECT is a window-configuration object.")
413430c5
EN
3194 (object)
3195 Lisp_Object object;
7ab12479 3196{
413430c5 3197 if (WINDOW_CONFIGURATIONP (object))
7ab12479
JB
3198 return Qt;
3199 return Qnil;
3200}
3201
3202
d5b2799e
RS
3203DEFUN ("set-window-configuration", Fset_window_configuration,
3204 Sset_window_configuration, 1, 1, 0,
7ab12479
JB
3205 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
3206CONFIGURATION must be a value previously returned\n\
3207by `current-window-configuration' (which see).")
2f83aebe
JB
3208 (configuration)
3209 Lisp_Object configuration;
7ab12479 3210{
7ab12479
JB
3211 register struct save_window_data *data;
3212 struct Lisp_Vector *saved_windows;
7ab12479 3213 Lisp_Object new_current_buffer;
fd482be5 3214 Lisp_Object frame;
44fa5b1e 3215 FRAME_PTR f;
7ab12479 3216
017b2bad 3217 while (!WINDOW_CONFIGURATIONP (configuration))
7ab12479 3218 {
2f83aebe
JB
3219 configuration = wrong_type_argument (intern ("window-configuration-p"),
3220 configuration);
7ab12479
JB
3221 }
3222
2f83aebe 3223 data = (struct save_window_data *) XVECTOR (configuration);
7ab12479
JB
3224 saved_windows = XVECTOR (data->saved_windows);
3225
7ab12479 3226 new_current_buffer = data->current_buffer;
265a9e55 3227 if (NILP (XBUFFER (new_current_buffer)->name))
7ab12479
JB
3228 new_current_buffer = Qnil;
3229
fd482be5
JB
3230 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
3231 f = XFRAME (frame);
9ace597f 3232
fd482be5
JB
3233 /* If f is a dead frame, don't bother rebuilding its window tree.
3234 However, there is other stuff we should still try to do below. */
3235 if (FRAME_LIVE_P (f))
7ab12479 3236 {
fd482be5
JB
3237 register struct window *w;
3238 register struct saved_window *p;
3239 int k;
3240
3241 /* If the frame has been resized since this window configuration was
3242 made, we change the frame to the size specified in the
3243 configuration, restore the configuration, and then resize it
3244 back. We keep track of the prevailing height in these variables. */
3245 int previous_frame_height = FRAME_HEIGHT (f);
3246 int previous_frame_width = FRAME_WIDTH (f);
8f6ea2e9 3247 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
fd482be5
JB
3248
3249 if (XFASTINT (data->frame_height) != previous_frame_height
3250 || XFASTINT (data->frame_width) != previous_frame_width)
3251 change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
e3678b64 3252#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
8f6ea2e9
KH
3253 if (XFASTINT (data->frame_menu_bar_lines)
3254 != previous_frame_menu_bar_lines)
3255 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, 0);
217f2871 3256#endif
fd482be5
JB
3257
3258 windows_or_buffers_changed++;
29aeee73 3259 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
fd482be5 3260
756b6edc
RS
3261 /* Temporarily avoid any problems with windows that are smaller
3262 than they are supposed to be. */
3263 window_min_height = 1;
3264 window_min_width = 1;
3265
fd482be5
JB
3266 /* Kludge Alert!
3267 Mark all windows now on frame as "deleted".
3268 Restoring the new configuration "undeletes" any that are in it.
37962e60 3269
fd482be5
JB
3270 Save their current buffers in their height fields, since we may
3271 need it later, if a buffer saved in the configuration is now
3272 dead. */
3273 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
3274
3275 for (k = 0; k < saved_windows->size; k++)
3276 {
3277 p = SAVED_WINDOW_N (saved_windows, k);
3278 w = XWINDOW (p->window);
3279 w->next = Qnil;
7ab12479 3280
fd482be5
JB
3281 if (!NILP (p->parent))
3282 w->parent = SAVED_WINDOW_N (saved_windows,
3283 XFASTINT (p->parent))->window;
3284 else
3285 w->parent = Qnil;
7ab12479 3286
fd482be5 3287 if (!NILP (p->prev))
7ab12479 3288 {
fd482be5
JB
3289 w->prev = SAVED_WINDOW_N (saved_windows,
3290 XFASTINT (p->prev))->window;
3291 XWINDOW (w->prev)->next = p->window;
3292 }
3293 else
3294 {
3295 w->prev = Qnil;
3296 if (!NILP (w->parent))
3297 {
3298 if (EQ (p->width, XWINDOW (w->parent)->width))
3299 {
3300 XWINDOW (w->parent)->vchild = p->window;
3301 XWINDOW (w->parent)->hchild = Qnil;
3302 }
3303 else
3304 {
3305 XWINDOW (w->parent)->hchild = p->window;
3306 XWINDOW (w->parent)->vchild = Qnil;
3307 }
3308 }
3309 }
3310
3311 /* If we squirreled away the buffer in the window's height,
3312 restore it now. */
017b2bad 3313 if (BUFFERP (w->height))
fd482be5
JB
3314 w->buffer = w->height;
3315 w->left = p->left;
3316 w->top = p->top;
3317 w->width = p->width;
3318 w->height = p->height;
3319 w->hscroll = p->hscroll;
3320 w->display_table = p->display_table;
d834a2e9 3321 XSETFASTINT (w->last_modified, 0);
3cd21523 3322 XSETFASTINT (w->last_overlay_modified, 0);
fd482be5
JB
3323
3324 /* Reinstall the saved buffer and pointers into it. */
3325 if (NILP (p->buffer))
3326 w->buffer = p->buffer;
3327 else
3328 {
3329 if (!NILP (XBUFFER (p->buffer)->name))
3330 /* If saved buffer is alive, install it. */
3331 {
3332 w->buffer = p->buffer;
3333 w->start_at_line_beg = p->start_at_line_beg;
3334 set_marker_restricted (w->start,
3335 Fmarker_position (p->start),
3336 w->buffer);
3337 set_marker_restricted (w->pointm,
3338 Fmarker_position (p->pointm),
3339 w->buffer);
3340 Fset_marker (XBUFFER (w->buffer)->mark,
3341 Fmarker_position (p->mark), w->buffer);
3342
3343 /* As documented in Fcurrent_window_configuration, don't
3344 save the location of point in the buffer which was current
3345 when the window configuration was recorded. */
6b54027b
RS
3346 if (!EQ (p->buffer, new_current_buffer)
3347 && XBUFFER (p->buffer) == current_buffer)
fd482be5
JB
3348 Fgoto_char (w->pointm);
3349 }
52a68e98
RS
3350 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
3351 /* Else unless window has a live buffer, get one. */
7ab12479 3352 {
fd482be5
JB
3353 w->buffer = Fcdr (Fcar (Vbuffer_alist));
3354 /* This will set the markers to beginning of visible
3355 range. */
3356 set_marker_restricted (w->start, make_number (0), w->buffer);
3357 set_marker_restricted (w->pointm, make_number (0),w->buffer);
3358 w->start_at_line_beg = Qt;
7ab12479
JB
3359 }
3360 else
fd482be5 3361 /* Keeping window's old buffer; make sure the markers
52a68e98 3362 are real. */
7ab12479 3363 {
fd482be5
JB
3364 /* Set window markers at start of visible range. */
3365 if (XMARKER (w->start)->buffer == 0)
3366 set_marker_restricted (w->start, make_number (0),
3367 w->buffer);
3368 if (XMARKER (w->pointm)->buffer == 0)
3369 set_marker_restricted (w->pointm,
3370 (make_number
3371 (BUF_PT (XBUFFER (w->buffer)))),
3372 w->buffer);
3373 w->start_at_line_beg = Qt;
7ab12479
JB
3374 }
3375 }
3376 }
9ace597f 3377
fd482be5
JB
3378 FRAME_ROOT_WINDOW (f) = data->root_window;
3379 Fselect_window (data->current_window);
396a830c
RS
3380 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
3381 = selected_window;
7ab12479 3382
db269683 3383 if (NILP (data->focus_frame)
017b2bad 3384 || (FRAMEP (data->focus_frame)
db269683
JB
3385 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
3386 Fredirect_frame_focus (frame, data->focus_frame);
7ab12479 3387
fd482be5
JB
3388#if 0 /* I don't understand why this is needed, and it causes problems
3389 when the frame's old selected window has been deleted. */
e4e59717 3390 if (f != selected_frame && FRAME_WINDOW_P (f))
9a7c6fc3
RS
3391 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
3392 Qnil, 0);
fd482be5
JB
3393#endif
3394
3395 /* Set the screen height to the value it had before this function. */
3396 if (previous_frame_height != FRAME_HEIGHT (f)
3397 || previous_frame_width != FRAME_WIDTH (f))
3398 change_frame_size (f, previous_frame_height, previous_frame_width,
3399 0, 0);
e3678b64 3400#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
8f6ea2e9
KH
3401 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
3402 x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
217f2871 3403#endif
fd482be5 3404 }
bdc727bf 3405
756b6edc
RS
3406 /* Restore the minimum heights recorded in the configuration. */
3407 window_min_height = XINT (data->min_height);
3408 window_min_width = XINT (data->min_width);
3409
bdc727bf 3410 /* Fselect_window will have made f the selected frame, so we
d5b2799e 3411 reselect the proper frame here. Fhandle_switch_frame will change the
bdc727bf
JB
3412 selected window too, but that doesn't make the call to
3413 Fselect_window above totally superfluous; it still sets f's
3414 selected window. */
fd482be5 3415 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
9a7c6fc3 3416 do_switch_frame (data->selected_frame, Qnil, 0);
bdc727bf
JB
3417
3418 if (!NILP (new_current_buffer))
3419 Fset_buffer (new_current_buffer);
3420
7ab12479 3421 Vminibuf_scroll_window = data->minibuf_scroll_window;
543f5fb1
RS
3422
3423 if (! NILP (Vwindow_configuration_change_hook)
3424 && ! NILP (Vrun_hooks))
3425 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3426
7ab12479
JB
3427 return (Qnil);
3428}
3429
44fa5b1e 3430/* Mark all windows now on frame as deleted
7ab12479
JB
3431 by setting their buffers to nil. */
3432
fd482be5 3433void
7ab12479
JB
3434delete_all_subwindows (w)
3435 register struct window *w;
3436{
265a9e55 3437 if (!NILP (w->next))
7ab12479 3438 delete_all_subwindows (XWINDOW (w->next));
265a9e55 3439 if (!NILP (w->vchild))
7ab12479 3440 delete_all_subwindows (XWINDOW (w->vchild));
265a9e55 3441 if (!NILP (w->hchild))
7ab12479 3442 delete_all_subwindows (XWINDOW (w->hchild));
605be8af
JB
3443
3444 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
3445
86e48436
RS
3446 if (!NILP (w->buffer))
3447 unshow_buffer (w);
3448
605be8af
JB
3449 /* We set all three of these fields to nil, to make sure that we can
3450 distinguish this dead window from any live window. Live leaf
3451 windows will have buffer set, and combination windows will have
3452 vchild or hchild set. */
3453 w->buffer = Qnil;
3454 w->vchild = Qnil;
3455 w->hchild = Qnil;
7ab12479
JB
3456}
3457\f
3458static int
3459count_windows (window)
3460 register struct window *window;
3461{
3462 register int count = 1;
265a9e55 3463 if (!NILP (window->next))
7ab12479 3464 count += count_windows (XWINDOW (window->next));
265a9e55 3465 if (!NILP (window->vchild))
7ab12479 3466 count += count_windows (XWINDOW (window->vchild));
265a9e55 3467 if (!NILP (window->hchild))
7ab12479
JB
3468 count += count_windows (XWINDOW (window->hchild));
3469 return count;
3470}
3471
3472static int
3473save_window_save (window, vector, i)
3474 Lisp_Object window;
3475 struct Lisp_Vector *vector;
3476 int i;
3477{
3478 register struct saved_window *p;
3479 register struct window *w;
3480 register Lisp_Object tem;
3481
265a9e55 3482 for (;!NILP (window); window = w->next)
7ab12479
JB
3483 {
3484 p = SAVED_WINDOW_N (vector, i);
3485 w = XWINDOW (window);
3486
d834a2e9 3487 XSETFASTINT (w->temslot, i++);
7ab12479
JB
3488 p->window = window;
3489 p->buffer = w->buffer;
3490 p->left = w->left;
3491 p->top = w->top;
3492 p->width = w->width;
3493 p->height = w->height;
3494 p->hscroll = w->hscroll;
3495 p->display_table = w->display_table;
265a9e55 3496 if (!NILP (w->buffer))
7ab12479
JB
3497 {
3498 /* Save w's value of point in the window configuration.
3499 If w is the selected window, then get the value of point
3500 from the buffer; pointm is garbage in the selected window. */
3501 if (EQ (window, selected_window))
3502 {
3503 p->pointm = Fmake_marker ();
3504 Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
3505 w->buffer);
3506 }
3507 else
eeb82665 3508 p->pointm = Fcopy_marker (w->pointm, Qnil);
7ab12479 3509
eeb82665 3510 p->start = Fcopy_marker (w->start, Qnil);
7ab12479
JB
3511 p->start_at_line_beg = w->start_at_line_beg;
3512
3513 tem = XBUFFER (w->buffer)->mark;
eeb82665 3514 p->mark = Fcopy_marker (tem, Qnil);
7ab12479
JB
3515 }
3516 else
3517 {
3518 p->pointm = Qnil;
3519 p->start = Qnil;
3520 p->mark = Qnil;
3521 p->start_at_line_beg = Qnil;
3522 }
3523
265a9e55 3524 if (NILP (w->parent))
7ab12479
JB
3525 p->parent = Qnil;
3526 else
3527 p->parent = XWINDOW (w->parent)->temslot;
3528
265a9e55 3529 if (NILP (w->prev))
7ab12479
JB
3530 p->prev = Qnil;
3531 else
3532 p->prev = XWINDOW (w->prev)->temslot;
3533
265a9e55 3534 if (!NILP (w->vchild))
7ab12479 3535 i = save_window_save (w->vchild, vector, i);
265a9e55 3536 if (!NILP (w->hchild))
7ab12479
JB
3537 i = save_window_save (w->hchild, vector, i);
3538 }
3539
3540 return i;
3541}
3542
a0d76c27
EN
3543DEFUN ("current-window-configuration", Fcurrent_window_configuration,
3544 Scurrent_window_configuration, 0, 1, 0,
44fa5b1e
JB
3545 "Return an object representing the current window configuration of FRAME.\n\
3546If FRAME is nil or omitted, use the selected frame.\n\
7ab12479
JB
3547This describes the number of windows, their sizes and current buffers,\n\
3548and for each displayed buffer, where display starts, and the positions of\n\
3549point and mark. An exception is made for point in the current buffer:\n\
bdc727bf
JB
3550its value is -not- saved.\n\
3551This also records the currently selected frame, and FRAME's focus\n\
3552redirection (see `redirect-frame-focus').")
44fa5b1e
JB
3553 (frame)
3554 Lisp_Object frame;
7ab12479
JB
3555{
3556 register Lisp_Object tem;
3557 register int n_windows;
3558 register struct save_window_data *data;
da2792e0 3559 register struct Lisp_Vector *vec;
7ab12479 3560 register int i;
44fa5b1e 3561 FRAME_PTR f;
43bad991 3562
44fa5b1e
JB
3563 if (NILP (frame))
3564 f = selected_frame;
43bad991
JB
3565 else
3566 {
44fa5b1e
JB
3567 CHECK_LIVE_FRAME (frame, 0);
3568 f = XFRAME (frame);
43bad991 3569 }
7ab12479 3570
44fa5b1e 3571 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
da2792e0
KH
3572 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
3573 for (i = 0; i < VECSIZE (struct save_window_data); i++)
3574 vec->contents[i] = Qnil;
3575 vec->size = VECSIZE (struct save_window_data);
3576 data = (struct save_window_data *)vec;
3577
d834a2e9
KH
3578 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
3579 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
3580 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
74112613 3581 XSETFRAME (data->selected_frame, selected_frame);
44fa5b1e 3582 data->current_window = FRAME_SELECTED_WINDOW (f);
74112613 3583 XSETBUFFER (data->current_buffer, current_buffer);
7ab12479 3584 data->minibuf_scroll_window = Vminibuf_scroll_window;
44fa5b1e 3585 data->root_window = FRAME_ROOT_WINDOW (f);
bdc727bf 3586 data->focus_frame = FRAME_FOCUS_FRAME (f);
74112613
KH
3587 XSETINT (data->min_height, window_min_height);
3588 XSETINT (data->min_width, window_min_width);
7ab12479
JB
3589 tem = Fmake_vector (make_number (n_windows), Qnil);
3590 data->saved_windows = tem;
3591 for (i = 0; i < n_windows; i++)
3592 XVECTOR (tem)->contents[i]
3593 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
44fa5b1e 3594 save_window_save (FRAME_ROOT_WINDOW (f),
7ab12479 3595 XVECTOR (tem), 0);
74112613 3596 XSETWINDOW_CONFIGURATION (tem, data);
7ab12479
JB
3597 return (tem);
3598}
3599
3600DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
3601 0, UNEVALLED, 0,
3602 "Execute body, preserving window sizes and contents.\n\
eb16ec06
RS
3603Restore which buffer appears in which window, where display starts,\n\
3604and the value of point and mark for each window.\n\
3605Also restore which buffer is current.\n\
3606But do not preserve point in the current buffer.\n\
7ab12479
JB
3607Does not restore the value of point in current buffer.")
3608 (args)
3609 Lisp_Object args;
3610{
3611 register Lisp_Object val;
3612 register int count = specpdl_ptr - specpdl;
3613
3614 record_unwind_protect (Fset_window_configuration,
43bad991 3615 Fcurrent_window_configuration (Qnil));
7ab12479
JB
3616 val = Fprogn (args);
3617 return unbind_to (count, val);
3618}
3619\f
3620init_window_once ()
3621{
44fa5b1e 3622 selected_frame = make_terminal_frame ();
bc6c324f 3623 XSETFRAME (Vterminal_frame, selected_frame);
44fa5b1e
JB
3624 minibuf_window = selected_frame->minibuffer_window;
3625 selected_window = selected_frame->selected_window;
3626 last_nonminibuf_frame = selected_frame;
5b03d3c0
RS
3627
3628 window_initialized = 1;
7ab12479
JB
3629}
3630
3631syms_of_window ()
3632{
543f5fb1
RS
3633 staticpro (&Qwindow_configuration_change_hook);
3634 Qwindow_configuration_change_hook
3635 = intern ("window-configuration-change-hook");
3636
7ab12479
JB
3637 Qwindowp = intern ("windowp");
3638 staticpro (&Qwindowp);
3639
806b4d9b
JB
3640 Qwindow_live_p = intern ("window-live-p");
3641 staticpro (&Qwindow_live_p);
605be8af 3642
2cccc823 3643 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
a58ec57d
RS
3644 staticpro (&Qtemp_buffer_show_hook);
3645
7ab12479
JB
3646 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
3647 "Non-nil means call as function to display a help buffer.\n\
c3ef6b1d 3648The function is called with one argument, the buffer to be displayed.\n\
f52cca03
RS
3649Used by `with-output-to-temp-buffer'.\n\
3650If this function is used, then it must do the entire job of showing\n\
3651the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
7ab12479
JB
3652 Vtemp_buffer_show_function = Qnil;
3653
3654 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
3655 "If non-nil, function to call to handle `display-buffer'.\n\
3656It will receive two args, the buffer and a flag which if non-nil means\n\
3657 that the currently selected window is not acceptable.\n\
3658Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
3659work using this function.");
3660 Vdisplay_buffer_function = Qnil;
3661
7ab12479
JB
3662 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
3663 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
3664 Vminibuf_scroll_window = Qnil;
3665
3666 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
3667 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
3668 Vother_window_scroll_buffer = Qnil;
3669
44fa5b1e 3670 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
700f75a4 3671 "*Non-nil means `display-buffer' should make a separate frame.");
44fa5b1e 3672 pop_up_frames = 0;
7ab12479 3673
44fa5b1e 3674 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
a90712c2 3675 "Function to call to handle automatic new frame creation.\n\
44fa5b1e 3676It is called with no arguments and should return a newly created frame.\n\
7ab12479 3677\n\
44fa5b1e
JB
3678A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
3679where `pop-up-frame-alist' would hold the default frame parameters.");
3680 Vpop_up_frame_function = Qnil;
7ab12479 3681
a90712c2
RS
3682 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
3683 "*List of buffer names that should have their own special frames.\n\
3684Displaying a buffer whose name is in this list makes a special frame for it\n\
524580a4 3685using `special-display-function'. See also `special-display-regexps'.\n\
3548e138 3686\n\
524580a4
RS
3687An element of the list can be a list instead of just a string.\n\
3688There are two ways to use a list as an element:\n\
3689 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
3690In the first case, FRAME-PARAMETERS are used to create the frame.\n\
3691In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
3692followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
3693All this is done by the function found in `special-display-function'.");
a90712c2
RS
3694 Vspecial_display_buffer_names = Qnil;
3695
3696 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
3697 "*List of regexps saying which buffers should have their own special frames.\n\
3698If a buffer name matches one of these regexps, it gets its own frame.\n\
3699Displaying a buffer whose name is in this list makes a special frame for it\n\
0a952b57 3700using `special-display-function'.\n\
3548e138 3701\n\
524580a4
RS
3702An element of the list can be a list instead of just a string.\n\
3703There are two ways to use a list as an element:\n\
3704 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
3705In the first case, FRAME-PARAMETERS are used to create the frame.\n\
3706In the latter case, FUNCTION is called with the buffer as first argument,\n\
3707followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
3708All this is done by the function found in `special-display-function'.");
a90712c2
RS
3709 Vspecial_display_regexps = Qnil;
3710
3711 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
3712 "Function to call to make a new frame for a special buffer.\n\
0a952b57
RS
3713It is called with two arguments, the buffer and optional buffer specific\n\
3714data, and should return a window displaying that buffer.\n\
a90712c2 3715The default value makes a separate frame for the buffer,\n\
bdd3a802 3716using `special-display-frame-alist' to specify the frame parameters.\n\
a90712c2
RS
3717\n\
3718A buffer is special if its is listed in `special-display-buffer-names'\n\
3719or matches a regexp in `special-display-regexps'.");
3720 Vspecial_display_function = Qnil;
3721
855d8627
RS
3722 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
3723 "*List of buffer names that should appear in the selected window.\n\
3724Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
3725switches to it in the selected window, rather than making it appear\n\
2e5ce1a0 3726in some other window.\n\
855d8627
RS
3727\n\
3728An element of the list can be a cons cell instead of just a string.\n\
3729Then the car must be a string, which specifies the buffer name.\n\
3730This is for compatibility with `special-display-buffer-names';\n\
3731the cdr of the cons cell is ignored.\n\
3732\n\
3733See also `same-window-regexps'.");
3734 Vsame_window_buffer_names = Qnil;
3735
3736 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
3737 "*List of regexps saying which buffers should appear in the selected window.\n\
3738If a buffer name matches one of these regexps, then displaying it\n\
3739using `display-buffer' or `pop-to-buffer' switches to it\n\
3740in the selected window, rather than making it appear in some other window.\n\
3741\n\
3742An element of the list can be a cons cell instead of just a string.\n\
3743Then the car must be a string, which specifies the buffer name.\n\
3744This is for compatibility with `special-display-buffer-names';\n\
3745the cdr of the cons cell is ignored.\n\
3746\n\
3747See also `same-window-buffer-names'.");
3748 Vsame_window_regexps = Qnil;
3749
7ab12479
JB
3750 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
3751 "*Non-nil means display-buffer should make new windows.");
3752 pop_up_windows = 1;
3753
3754 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
3755 "*Number of lines of continuity when scrolling by screenfuls.");
3756 next_screen_context_lines = 2;
3757
3758 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
3759 "*display-buffer would prefer to split the largest window if this large.\n\
3760If there is only one window, it is split regardless of this value.");
3761 split_height_threshold = 500;
3762
3763 DEFVAR_INT ("window-min-height", &window_min_height,
3764 "*Delete any window less than this tall (including its mode line).");
3765 window_min_height = 4;
3766
3767 DEFVAR_INT ("window-min-width", &window_min_width,
3768 "*Delete any window less than this wide.");
3769 window_min_width = 10;
3770
9317a85d
RS
3771 DEFVAR_BOOL ("scroll-preserve-screen-position",
3772 &scroll_preserve_screen_position,
3773 "*Nonzero means scroll commands move point to keep its screen line unchanged.");
3774 scroll_preserve_screen_position = 0;
3775
543f5fb1
RS
3776 DEFVAR_LISP ("window-configuration-change-hook",
3777 &Vwindow_configuration_change_hook,
3778 "Functions to call when window configuration changes.\n\
3779The selected frae is the one whose configuration has changed.");
3780 Vwindow_configuration_change_hook = Qnil;
3781
7d601aaa
RS
3782 DEFVAR_BOOL ("frame-override-unsplittable", &frame_override_unsplittable,
3783 "Non-nil means allow splitting an `unsplittable' frame.\n\
3784\(That means, a frame whise `unsplittable' parameter is non-nil.)\n\
3785Packages such as Ispell that work by splitting the selected frame\n\
3786can bind this, so that they will work when used in an unsplittable frame.");
3787
7ab12479
JB
3788 defsubr (&Sselected_window);
3789 defsubr (&Sminibuffer_window);
3790 defsubr (&Swindow_minibuffer_p);
3791 defsubr (&Swindowp);
806b4d9b 3792 defsubr (&Swindow_live_p);
7ab12479
JB
3793 defsubr (&Spos_visible_in_window_p);
3794 defsubr (&Swindow_buffer);
3795 defsubr (&Swindow_height);
3796 defsubr (&Swindow_width);
3797 defsubr (&Swindow_hscroll);
3798 defsubr (&Sset_window_hscroll);
190eb263
RS
3799 defsubr (&Swindow_redisplay_end_trigger);
3800 defsubr (&Sset_window_redisplay_end_trigger);
7ab12479 3801 defsubr (&Swindow_edges);
d5783c40
JB
3802 defsubr (&Scoordinates_in_window_p);
3803 defsubr (&Swindow_at);
7ab12479
JB
3804 defsubr (&Swindow_point);
3805 defsubr (&Swindow_start);
3806 defsubr (&Swindow_end);
3807 defsubr (&Sset_window_point);
3808 defsubr (&Sset_window_start);
3809 defsubr (&Swindow_dedicated_p);
d207b766 3810 defsubr (&Sset_window_dedicated_p);
7ab12479
JB
3811 defsubr (&Swindow_display_table);
3812 defsubr (&Sset_window_display_table);
3813 defsubr (&Snext_window);
3814 defsubr (&Sprevious_window);
3815 defsubr (&Sother_window);
3816 defsubr (&Sget_lru_window);
3817 defsubr (&Sget_largest_window);
3818 defsubr (&Sget_buffer_window);
3819 defsubr (&Sdelete_other_windows);
3820 defsubr (&Sdelete_windows_on);
3821 defsubr (&Sreplace_buffer_in_windows);
3822 defsubr (&Sdelete_window);
3823 defsubr (&Sset_window_buffer);
3824 defsubr (&Sselect_window);
4628f7a4
EN
3825 defsubr (&Sspecial_display_p);
3826 defsubr (&Ssame_window_p);
7ab12479
JB
3827 defsubr (&Sdisplay_buffer);
3828 defsubr (&Ssplit_window);
3829 defsubr (&Senlarge_window);
3830 defsubr (&Sshrink_window);
3831 defsubr (&Sscroll_up);
3832 defsubr (&Sscroll_down);
3833 defsubr (&Sscroll_left);
3834 defsubr (&Sscroll_right);
ccd0664b 3835 defsubr (&Sother_window_for_scrolling);
7ab12479
JB
3836 defsubr (&Sscroll_other_window);
3837 defsubr (&Srecenter);
3838 defsubr (&Smove_to_window_line);
3839 defsubr (&Swindow_configuration_p);
3840 defsubr (&Sset_window_configuration);
3841 defsubr (&Scurrent_window_configuration);
3842 defsubr (&Ssave_window_excursion);
3843}
3844
3845keys_of_window ()
3846{
3847 initial_define_key (control_x_map, '1', "delete-other-windows");
3848 initial_define_key (control_x_map, '2', "split-window");
3849 initial_define_key (control_x_map, '0', "delete-window");
3850 initial_define_key (control_x_map, 'o', "other-window");
3851 initial_define_key (control_x_map, '^', "enlarge-window");
3852 initial_define_key (control_x_map, '<', "scroll-left");
3853 initial_define_key (control_x_map, '>', "scroll-right");
3854
3855 initial_define_key (global_map, Ctl ('V'), "scroll-up");
3856 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
3857 initial_define_key (meta_map, 'v', "scroll-down");
3858
3859 initial_define_key (global_map, Ctl('L'), "recenter");
3860 initial_define_key (meta_map, 'r', "move-to-window-line");
3861}