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