(Fexpand_abbrev): Remove unused variables.
[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"
dfcf069d 32#include "dispextern.h"
5500c422
GM
33#include "blockinput.h"
34#include "intervals.h"
35
6d55d620 36#ifdef HAVE_X_WINDOWS
dfcf069d 37#include "xterm.h"
5500c422
GM
38#endif /* HAVE_X_WINDOWS */
39
40#ifndef max
41#define max(a, b) ((a) < (b) ? (b) : (a))
dfcf069d 42#endif
7ab12479 43
5500c422 44
3f8ab7bd 45Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
8a37516b 46Lisp_Object Qwindow_size_fixed, Qleft_bitmap_area, Qright_bitmap_area;
233a4a2c 47extern Lisp_Object Qheight, Qwidth;
7ab12479 48
5e14b1fc 49static struct window *decode_window P_ ((Lisp_Object));
b7354ddf 50static Lisp_Object select_window_1 P_ ((Lisp_Object, int));
5500c422
GM
51static int count_windows P_ ((struct window *));
52static int get_leaf_windows P_ ((struct window *, struct window **, int));
53static void window_scroll P_ ((Lisp_Object, int, int, int));
54static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
55static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
233a4a2c
GM
56static int window_min_size_1 P_ ((struct window *, int));
57static int window_min_size P_ ((struct window *, int, int *));
58static int window_fixed_size_p P_ ((struct window *, int, int));
59static void size_window P_ ((Lisp_Object, int, int, int));
7bbb5782
GM
60static void foreach_window_1 P_ ((struct window *, void (*fn) (), int, int,
61 int, int));
62static void freeze_window_start P_ ((struct window *, int));
5500c422 63
b7354ddf 64
7ab12479
JB
65/* This is the window in which the terminal's cursor should
66 be left when nothing is being done with it. This must
67 always be a leaf window, and its buffer is selected by
68 the top level editing loop at the end of each command.
69
70 This value is always the same as
44fa5b1e 71 FRAME_SELECTED_WINDOW (selected_frame). */
7ab12479
JB
72
73Lisp_Object selected_window;
74
5500c422
GM
75/* The mini-buffer window of the selected frame.
76 Note that you cannot test for mini-bufferness of an arbitrary window
77 by comparing against this; but you can test for mini-bufferness of
7ab12479 78 the selected window. */
5500c422 79
7ab12479
JB
80Lisp_Object minibuf_window;
81
82/* Non-nil means it is the window for C-M-v to scroll
5500c422
GM
83 when the mini-buffer is selected. */
84
7ab12479
JB
85Lisp_Object Vminibuf_scroll_window;
86
87/* Non-nil means this is the buffer whose window C-M-v should scroll. */
5500c422 88
7ab12479
JB
89Lisp_Object Vother_window_scroll_buffer;
90
7ab12479 91/* Non-nil means it's function to call to display temp buffers. */
5500c422 92
7ab12479
JB
93Lisp_Object Vtemp_buffer_show_function;
94
95/* If a window gets smaller than either of these, it is removed. */
5500c422 96
7ab12479
JB
97int window_min_height;
98int window_min_width;
99
100/* Nonzero implies Fdisplay_buffer should create windows. */
5500c422 101
7ab12479
JB
102int pop_up_windows;
103
44fa5b1e 104/* Nonzero implies make new frames for Fdisplay_buffer. */
5500c422 105
44fa5b1e 106int pop_up_frames;
7ab12479
JB
107
108/* Non-nil means use this function instead of default */
5500c422 109
44fa5b1e 110Lisp_Object Vpop_up_frame_function;
7ab12479
JB
111
112/* Function to call to handle Fdisplay_buffer. */
5500c422 113
7ab12479
JB
114Lisp_Object Vdisplay_buffer_function;
115
a90712c2 116/* List of buffer *names* for buffers that should have their own frames. */
5500c422 117
a90712c2
RS
118Lisp_Object Vspecial_display_buffer_names;
119
120/* List of regexps for buffer names that should have their own frames. */
5500c422 121
a90712c2
RS
122Lisp_Object Vspecial_display_regexps;
123
124/* Function to pop up a special frame. */
5500c422 125
a90712c2
RS
126Lisp_Object Vspecial_display_function;
127
855d8627 128/* List of buffer *names* for buffers to appear in selected window. */
5500c422 129
855d8627
RS
130Lisp_Object Vsame_window_buffer_names;
131
132/* List of regexps for buffer names to appear in selected window. */
5500c422 133
855d8627
RS
134Lisp_Object Vsame_window_regexps;
135
a58ec57d 136/* Hook run at end of temp_output_buffer_show. */
5500c422 137
a58ec57d
RS
138Lisp_Object Qtemp_buffer_show_hook;
139
37962e60 140/* Fdisplay_buffer always splits the largest window
7ab12479 141 if that window is more than this high. */
5500c422 142
7ab12479
JB
143int split_height_threshold;
144
145/* Number of lines of continuity in scrolling by screenfuls. */
5500c422 146
7ab12479
JB
147int next_screen_context_lines;
148
149/* Incremented for each window created. */
5500c422 150
7ab12479
JB
151static int sequence_number;
152
5b03d3c0 153/* Nonzero after init_window_once has finished. */
5500c422 154
5b03d3c0
RS
155static int window_initialized;
156
543f5fb1 157/* Hook to run when window config changes. */
5500c422 158
543f5fb1
RS
159Lisp_Object Qwindow_configuration_change_hook;
160Lisp_Object Vwindow_configuration_change_hook;
161
9317a85d
RS
162/* Nonzero means scroll commands try to put point
163 at the same screen height as previously. */
9317a85d 164
5500c422
GM
165Lisp_Object Vscroll_preserve_screen_position;
166
167#if 0 /* This isn't used anywhere. */
91a78190 168/* Nonzero means we can split a frame even if it is "unsplittable". */
eddd51c2 169static int inhibit_frame_unsplittable;
5500c422 170#endif /* 0 */
7d601aaa 171
7ab12479 172#define min(a, b) ((a) < (b) ? (a) : (b))
dba06815 173
9317a85d
RS
174extern int scroll_margin;
175
dba06815 176extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
7ab12479
JB
177\f
178DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
413430c5
EN
179 "Returns t if OBJECT is a window.")
180 (object)
181 Lisp_Object object;
7ab12479 182{
413430c5 183 return WINDOWP (object) ? Qt : Qnil;
7ab12479
JB
184}
185
806b4d9b 186DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
413430c5
EN
187 "Returns t if OBJECT is a window which is currently visible.")
188 (object)
189 Lisp_Object object;
605be8af 190{
413430c5 191 return (WINDOWP (object) && ! NILP (XWINDOW (object)->buffer) ? Qt : Qnil);
605be8af
JB
192}
193
7ab12479
JB
194Lisp_Object
195make_window ()
196{
cffec418 197 Lisp_Object val;
7ab12479 198 register struct window *p;
cffec418
KH
199 register struct Lisp_Vector *vec;
200 int i;
201
202 vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct window));
203 for (i = 0; i < VECSIZE (struct window); i++)
204 vec->contents[i] = Qnil;
205 vec->size = VECSIZE (struct window);
5500c422 206 p = (struct window *) vec;
d834a2e9
KH
207 XSETFASTINT (p->sequence_number, ++sequence_number);
208 XSETFASTINT (p->left, 0);
209 XSETFASTINT (p->top, 0);
210 XSETFASTINT (p->height, 0);
211 XSETFASTINT (p->width, 0);
212 XSETFASTINT (p->hscroll, 0);
7ab12479
JB
213 p->start = Fmake_marker ();
214 p->pointm = Fmake_marker ();
d834a2e9 215 XSETFASTINT (p->use_time, 0);
44fa5b1e 216 p->frame = Qnil;
7ab12479
JB
217 p->display_table = Qnil;
218 p->dedicated = Qnil;
5500c422
GM
219 p->pseudo_window_p = 0;
220 bzero (&p->cursor, sizeof (p->cursor));
221 bzero (&p->last_cursor, sizeof (p->last_cursor));
222 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
223 p->desired_matrix = p->current_matrix = 0;
224 p->phys_cursor_type = -1;
225 p->must_be_updated_p = 0;
226 XSETFASTINT (p->window_end_vpos, 0);
227 XSETFASTINT (p->window_end_pos, 0);
228 p->window_end_valid = Qnil;
229 p->vscroll = 0;
cffec418 230 XSETWINDOW (val, p);
5500c422 231 XSETFASTINT (p->last_point, 0);
7bbb5782 232 p->frozen_window_start_p = 0;
7ab12479
JB
233 return val;
234}
235
236DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
237 "Return the window that the cursor now appears in and commands apply to.")
238 ()
239{
240 return selected_window;
241}
242
83762ba4
JB
243DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
244 "Return the window used now for minibuffers.\n\
245If the optional argument FRAME is specified, return the minibuffer window\n\
246used by that frame.")
247 (frame)
248 Lisp_Object frame;
7ab12479 249{
83762ba4 250 if (NILP (frame))
1ae1a37d
GM
251 frame = selected_frame;
252 CHECK_LIVE_FRAME (frame, 0);
83762ba4 253 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
7ab12479
JB
254}
255
605be8af 256DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
7ab12479
JB
257 "Returns non-nil if WINDOW is a minibuffer window.")
258 (window)
259 Lisp_Object window;
260{
261 struct window *w = decode_window (window);
262 return (MINI_WINDOW_P (w) ? Qt : Qnil);
263}
264
265DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
266 Spos_visible_in_window_p, 0, 2, 0,
44fa5b1e 267 "Return t if position POS is currently on the frame in WINDOW.\n\
7ab12479
JB
268Returns nil if that position is scrolled vertically out of view.\n\
269POS defaults to point; WINDOW, to the selected window.")
270 (pos, window)
271 Lisp_Object pos, window;
272{
273 register struct window *w;
7ab12479
JB
274 register int posint;
275 register struct buffer *buf;
9a132b1f
GM
276 struct text_pos top;
277 Lisp_Object in_window;
7ab12479 278
265a9e55 279 if (NILP (pos))
5ce7b543 280 posint = PT;
7ab12479
JB
281 else
282 {
283 CHECK_NUMBER_COERCE_MARKER (pos, 0);
284 posint = XINT (pos);
285 }
286
605be8af 287 w = decode_window (window);
9a132b1f 288 buf = XBUFFER (w->buffer);
5500c422 289 SET_TEXT_POS_FROM_MARKER (top, w->start);
7ab12479 290
5500c422
GM
291 /* If position above window, it's not visible. */
292 if (posint < CHARPOS (top))
9a132b1f
GM
293 in_window = Qnil;
294 else if (XFASTINT (w->last_modified) >= BUF_MODIFF (buf)
295 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (buf)
296 && posint < BUF_Z (buf) - XFASTINT (w->window_end_pos))
297 /* If frame is up to date, and POSINT is < window end pos, use
298 that info. This doesn't work for POSINT == end pos, because
299 the window end pos is actually the position _after_ the last
300 char in the window. */
301 in_window = Qt;
302 else if (posint > BUF_ZV (buf))
303 in_window = Qnil;
304 else if (CHARPOS (top) < BUF_BEGV (buf) || CHARPOS (top) > BUF_ZV (buf))
305 /* If window start is out of range, do something reasonable. */
306 in_window = Qnil;
7ab12479
JB
307 else
308 {
5500c422 309 struct it it;
5500c422
GM
310 start_display (&it, w, top);
311 move_it_to (&it, posint, 0, it.last_visible_y, -1,
9a132b1f
GM
312 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
313 in_window = IT_CHARPOS (it) == posint ? Qt : Qnil;
7ab12479 314 }
9a132b1f
GM
315
316 return in_window;
7ab12479
JB
317}
318\f
319static struct window *
320decode_window (window)
321 register Lisp_Object window;
322{
265a9e55 323 if (NILP (window))
7ab12479
JB
324 return XWINDOW (selected_window);
325
605be8af 326 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
327 return XWINDOW (window);
328}
329
330DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
331 "Return the buffer that WINDOW is displaying.")
332 (window)
333 Lisp_Object window;
334{
335 return decode_window (window)->buffer;
336}
337
338DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
339 "Return the number of lines in WINDOW (including its mode line).")
340 (window)
341 Lisp_Object window;
342{
343 return decode_window (window)->height;
344}
345
346DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
3b5908ef
RS
347 "Return the number of display columns in WINDOW.\n\
348This is the width that is usable columns available for text in WINDOW.\n\
349If you want to find out how many columns WINDOW takes up,\n\
350use (let ((edges (window-edges))) (- (nth 2 edges) (nth 0 edges))).")
7ab12479
JB
351 (window)
352 Lisp_Object window;
353{
ee61d94e 354 return make_number (window_internal_width (decode_window (window)));
7ab12479
JB
355}
356
357DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
358 "Return the number of columns by which WINDOW is scrolled from left margin.")
359 (window)
360 Lisp_Object window;
361{
362 return decode_window (window)->hscroll;
363}
364
365DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
366 "Set number of columns WINDOW is scrolled from left margin to NCOL.\n\
367NCOL should be zero or positive.")
368 (window, ncol)
369 register Lisp_Object window, ncol;
370{
371 register struct window *w;
372
373 CHECK_NUMBER (ncol, 1);
d834a2e9 374 if (XINT (ncol) < 0) XSETFASTINT (ncol, 0);
7ab12479 375 w = decode_window (window);
7f4161e0 376 if (XINT (w->hscroll) != XINT (ncol))
b1599b4c
GM
377 /* Prevent redisplay shortcuts */
378 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
7ab12479
JB
379 w->hscroll = ncol;
380 return ncol;
381}
382
190eb263
RS
383DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
384 Swindow_redisplay_end_trigger, 0, 1, 0,
385 "Return WINDOW's redisplay end trigger value.\n\
386See `set-window-redisplay-end-trigger' for more information.")
387 (window)
388 Lisp_Object window;
389{
390 return decode_window (window)->redisplay_end_trigger;
391}
392
393DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
394 Sset_window_redisplay_end_trigger, 2, 2, 0,
395 "Set WINDOW's redisplay end trigger value to VALUE.\n\
396VALUE should be a buffer position (typically a marker) or nil.\n\
76854cf2
RS
397If it is a buffer position, then if redisplay in WINDOW reaches a position\n\
398beyond VALUE, the functions in `redisplay-end-trigger-functions' are called\n\
399with two arguments: WINDOW, and the end trigger value.\n\
400Afterwards the end-trigger value is reset to nil.")
190eb263
RS
401 (window, value)
402 register Lisp_Object window, value;
403{
404 register struct window *w;
405
406 w = decode_window (window);
407 w->redisplay_end_trigger = value;
408 return value;
409}
410
7ab12479
JB
411DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
412 "Return a list of the edge coordinates of WINDOW.\n\
44fa5b1e 413\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.\n\
7ab12479
JB
414RIGHT is one more than the rightmost column used by WINDOW,\n\
415and BOTTOM is one more than the bottommost row used by WINDOW\n\
416 and its mode-line.")
417 (window)
418 Lisp_Object window;
419{
420 register struct window *w = decode_window (window);
421
422 return Fcons (w->left, Fcons (w->top,
111e5992 423 Fcons (make_number (WINDOW_RIGHT_EDGE (w)),
7ab12479
JB
424 Fcons (make_number (XFASTINT (w->top)
425 + XFASTINT (w->height)),
426 Qnil))));
427}
428
fbad6f9a 429/* Test if the character at column *X, row *Y is within window W.
d5783c40
JB
430 If it is not, return 0;
431 if it is in the window's text area,
432 set *x and *y to its location relative to the upper left corner
433 of the window, and
434 return 1;
435 if it is on the window's modeline, return 2;
436 if it is on the border between the window and its right sibling,
5500c422
GM
437 return 3.
438 if it is on the window's top line, return 4;
fbad6f9a
GM
439 if it is in the bitmap area to the left/right of the window,
440 return 5 or 6, and convert *X and *Y to window-relative corrdinates.
5500c422
GM
441
442 X and Y are frame relative pixel coordinates. */
443
d5783c40
JB
444static int
445coordinates_in_window (w, x, y)
446 register struct window *w;
447 register int *x, *y;
448{
5500c422
GM
449 struct frame *f = XFRAME (WINDOW_FRAME (w));
450 int left_x, right_x, top_y, bottom_y;
b46dfc64 451 int flags_area_width = FRAME_LEFT_FLAGS_AREA_WIDTH (f);
d5783c40 452
5500c422
GM
453 if (w->pseudo_window_p)
454 {
455 left_x = 0;
456 right_x = XFASTINT (w->width) * CANON_Y_UNIT (f);
457 top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
458 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
459 }
460 else
461 {
462 left_x = WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
463 right_x = WINDOW_DISPLAY_RIGHT_EDGE_PIXEL_X (w);
464 top_y = WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
465 bottom_y = WINDOW_DISPLAY_BOTTOM_EDGE_PIXEL_Y (w);
466 }
37962e60 467
5500c422
GM
468 if (*y < top_y
469 || *y >= bottom_y
470 || *x < (left_x
471 - flags_area_width
472 - (FRAME_LEFT_SCROLL_BAR_WIDTH (f)
473 * CANON_X_UNIT (f)))
474 || *x > right_x + flags_area_width)
475 /* Completely outside anything interesting. */
476 return 0;
477 else if (WINDOW_WANTS_MODELINE_P (w)
478 && *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
479 /* On the mode line. */
480 return 2;
045dee35
GM
481 else if (WINDOW_WANTS_HEADER_LINE_P (w)
482 && *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
5500c422
GM
483 /* On the top line. */
484 return 4;
485 else if (*x < left_x || *x >= right_x)
fbad6f9a
GM
486 {
487 /* Other lines than the mode line don't include flags areas and
488 scroll bars on the left. */
489
490 /* Convert X and Y to window-relative pixel coordinates. */
491 *x -= left_x;
492 *y -= top_y;
493 return *x < left_x ? 5 : 6;
494 }
5500c422
GM
495 else if (!w->pseudo_window_p
496 && !WINDOW_RIGHTMOST_P (w)
497 && *x >= right_x - CANON_X_UNIT (f))
498 /* On the border on the right side of the window? Assume that
499 this area begins at RIGHT_X minus a canonical char width. */
500 return 3;
501 else
502 {
503 /* Convert X and Y to window-relative pixel coordinates. */
504 *x -= left_x;
505 *y -= top_y;
506 return 1;
507 }
d5783c40
JB
508}
509
510DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
511 Scoordinates_in_window_p, 2, 2, 0,
512 "Return non-nil if COORDINATES are in WINDOW.\n\
1113d9db 513COORDINATES is a cons of the form (X . Y), X and Y being distances\n\
44fa5b1e 514measured in characters from the upper-left corner of the frame.\n\
1113d9db 515(0 . 0) denotes the character in the upper left corner of the\n\
44fa5b1e 516frame.\n\
d5783c40
JB
517If COORDINATES are in the text portion of WINDOW,\n\
518 the coordinates relative to the window are returned.\n\
e5d77022 519If they are in the mode line of WINDOW, `mode-line' is returned.\n\
045dee35 520If they are in the top mode line of WINDOW, `header-line' is returned.\n\
fbad6f9a
GM
521If they are in the bitmap-area to the left of the window,\n\
522 `left-bitmap-area' is returned, if they are in the area on the right of\n\
523 the window, `right-bitmap-area' is returned.\n\
d5783c40 524If they are on the border between WINDOW and its right sibling,\n\
e5d77022 525 `vertical-line' is returned.")
d5783c40
JB
526 (coordinates, window)
527 register Lisp_Object coordinates, window;
528{
5500c422
GM
529 struct window *w;
530 struct frame *f;
d5783c40 531 int x, y;
5500c422 532 Lisp_Object lx, ly;
d5783c40 533
605be8af 534 CHECK_LIVE_WINDOW (window, 0);
5500c422
GM
535 w = XWINDOW (window);
536 f = XFRAME (w->frame);
d5783c40 537 CHECK_CONS (coordinates, 1);
5500c422
GM
538 lx = Fcar (coordinates);
539 ly = Fcdr (coordinates);
540 CHECK_NUMBER_OR_FLOAT (lx, 1);
541 CHECK_NUMBER_OR_FLOAT (ly, 1);
542 x = PIXEL_X_FROM_CANON_X (f, lx);
543 y = PIXEL_Y_FROM_CANON_Y (f, ly);
544
545 switch (coordinates_in_window (w, &x, &y))
d5783c40
JB
546 {
547 case 0: /* NOT in window at all. */
548 return Qnil;
549
550 case 1: /* In text part of window. */
5500c422
GM
551 /* X and Y are now window relative pixel coordinates.
552 Convert them to canonical char units before returning
553 them. */
554 return Fcons (CANON_X_FROM_PIXEL_X (f, x),
555 CANON_Y_FROM_PIXEL_Y (f, y));
d5783c40
JB
556
557 case 2: /* In mode line of window. */
558 return Qmode_line;
37962e60 559
d5783c40 560 case 3: /* On right border of window. */
e5d77022 561 return Qvertical_line;
d5783c40 562
5500c422 563 case 4:
045dee35 564 return Qheader_line;
5500c422 565
fbad6f9a
GM
566 case 5:
567 return Qleft_bitmap_area;
568
569 case 6:
570 return Qright_bitmap_area;
571
d5783c40
JB
572 default:
573 abort ();
574 }
575}
576
5500c422
GM
577/* Find the window containing frame-relative pixel position X/Y and
578 return it as a Lisp_Object. If X, Y is on the window's modeline,
579 set *PART to 1; if it is on the separating line between the window
580 and its right sibling, set it to 2; otherwise set it to 0. If
581 there is no window under X, Y return nil and leave *PART
9ea173e8 582 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows. */
5500c422 583
7ab12479 584Lisp_Object
9ea173e8 585window_from_coordinates (frame, x, y, part, tool_bar_p)
44fa5b1e 586 FRAME_PTR frame;
7ab12479 587 int x, y;
d5783c40 588 int *part;
9ea173e8 589 int tool_bar_p;
7ab12479
JB
590{
591 register Lisp_Object tem, first;
5500c422 592 int found;
7ab12479 593
44fa5b1e 594 tem = first = FRAME_SELECTED_WINDOW (frame);
7ab12479 595
d5783c40 596 do
7ab12479 597 {
5500c422 598 found = coordinates_in_window (XWINDOW (tem), &x, &y);
7ab12479
JB
599
600 if (found)
601 {
d5783c40 602 *part = found - 1;
7ab12479
JB
603 return tem;
604 }
605
d5783c40 606 tem = Fnext_window (tem, Qt, Qlambda);
7ab12479 607 }
5500c422
GM
608 while (!EQ (tem, first));
609
9ea173e8
GM
610 /* See if it's in the tool bar window, if a tool bar exists. */
611 if (tool_bar_p
612 && WINDOWP (frame->tool_bar_window)
613 && XFASTINT (XWINDOW (frame->tool_bar_window)->height)
614 && coordinates_in_window (XWINDOW (frame->tool_bar_window), &x, &y))
5500c422
GM
615 {
616 *part = 0;
9ea173e8 617 return frame->tool_bar_window;
5500c422 618 }
37962e60 619
d5783c40 620 return Qnil;
7ab12479
JB
621}
622
ab17c3f2 623DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
b0c33a94 624 "Return window containing coordinates X and Y on FRAME.\n\
44fa5b1e
JB
625If omitted, FRAME defaults to the currently selected frame.\n\
626The top left corner of the frame is considered to be row 0,\n\
95605e15 627column 0.")
b0c33a94
RS
628 (x, y, frame)
629 Lisp_Object x, y, frame;
7ab12479
JB
630{
631 int part;
5500c422 632 struct frame *f;
7ab12479 633
44fa5b1e 634 if (NILP (frame))
1ae1a37d
GM
635 frame = selected_frame;
636 CHECK_LIVE_FRAME (frame, 2);
5500c422 637 f = XFRAME (frame);
7ab12479 638
5500c422
GM
639 /* Check that arguments are integers or floats. */
640 CHECK_NUMBER_OR_FLOAT (x, 0);
641 CHECK_NUMBER_OR_FLOAT (y, 1);
642
643 return window_from_coordinates (f,
644 PIXEL_X_FROM_CANON_X (f, x),
645 PIXEL_Y_FROM_CANON_Y (f, y),
646 &part, 0);
7ab12479
JB
647}
648
649DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
650 "Return current value of point in WINDOW.\n\
651For a nonselected window, this is the value point would have\n\
652if that window were selected.\n\
653\n\
654Note that, when WINDOW is the selected window and its buffer\n\
655is also currently selected, the value returned is the same as (point).\n\
656It would be more strictly correct to return the `top-level' value\n\
657of point, outside of any save-excursion forms.\n\
658But that is hard to define.")
659 (window)
660 Lisp_Object window;
661{
662 register struct window *w = decode_window (window);
663
664 if (w == XWINDOW (selected_window)
665 && current_buffer == XBUFFER (w->buffer))
666 return Fpoint ();
667 return Fmarker_position (w->pointm);
668}
669
670DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
0fea6c40
RS
671 "Return position at which display currently starts in WINDOW.\n\
672This is updated by redisplay or by calling `set-window-start'.")
7ab12479
JB
673 (window)
674 Lisp_Object window;
675{
676 return Fmarker_position (decode_window (window)->start);
677}
678
8646118f
RS
679/* This is text temporarily removed from the doc string below.
680
7250968e
RS
681This function returns nil if the position is not currently known.\n\
682That happens when redisplay is preempted and doesn't finish.\n\
683If in that case you want to compute where the end of the window would\n\
684have been if redisplay had finished, do this:\n\
685 (save-excursion\n\
686 (goto-char (window-start window))\n\
687 (vertical-motion (1- (window-height window)) window)\n\
8646118f
RS
688 (point))") */
689
478292ed 690DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
8646118f
RS
691 "Return position at which display currently ends in WINDOW.\n\
692This is updated by redisplay, when it runs to completion.\n\
693Simply changing the buffer text or setting `window-start'\n\
478292ed
RS
694does not update this value.\n\
695If UP-TO-DATE is non-nil, compute the up-to-date position\n\
696if it isn't already recorded.")
697 (window, update)
698 Lisp_Object window, update;
7ab12479
JB
699{
700 Lisp_Object value;
701 struct window *w = decode_window (window);
5a41ab94
RS
702 Lisp_Object buf;
703
704 buf = w->buffer;
705 CHECK_BUFFER (buf, 0);
706
8646118f 707#if 0 /* This change broke some things. We should make it later. */
7250968e
RS
708 /* If we don't know the end position, return nil.
709 The user can compute it with vertical-motion if he wants to.
710 It would be nicer to do it automatically,
711 but that's so slow that it would probably bother people. */
712 if (NILP (w->window_end_valid))
713 return Qnil;
8646118f 714#endif
7250968e 715
478292ed
RS
716 if (! NILP (update)
717 && ! (! NILP (w->window_end_valid)
718 && XFASTINT (w->last_modified) >= MODIFF))
719 {
720 int opoint = PT, opoint_byte = PT_BYTE;
721 TEMP_SET_PT_BOTH (XMARKER (w->start)->charpos,
722 XMARKER (w->start)->bytepos);
723 Fvertical_motion (make_number (window_internal_height (w)), Qnil);
724 XSETINT (value, PT);
725 TEMP_SET_PT_BOTH (opoint, opoint_byte);
726 }
727 else
728 XSETINT (value,
729 BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
7ab12479
JB
730
731 return value;
732}
733
734DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
735 "Make point value in WINDOW be at position POS in WINDOW's buffer.")
736 (window, pos)
737 Lisp_Object window, pos;
738{
739 register struct window *w = decode_window (window);
740
741 CHECK_NUMBER_COERCE_MARKER (pos, 1);
e90c4fe6
RS
742 if (w == XWINDOW (selected_window)
743 && XBUFFER (w->buffer) == current_buffer)
7ab12479
JB
744 Fgoto_char (pos);
745 else
746 set_marker_restricted (w->pointm, pos, w->buffer);
ce7fae7d 747
7ab12479
JB
748 return pos;
749}
750
751DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
752 "Make display in WINDOW start at position POS in WINDOW's buffer.\n\
753Optional third arg NOFORCE non-nil inhibits next redisplay\n\
754from overriding motion of point in order to display at this exact start.")
755 (window, pos, noforce)
756 Lisp_Object window, pos, noforce;
757{
758 register struct window *w = decode_window (window);
759
760 CHECK_NUMBER_COERCE_MARKER (pos, 1);
761 set_marker_restricted (w->start, pos, w->buffer);
762 /* this is not right, but much easier than doing what is right. */
763 w->start_at_line_beg = Qnil;
265a9e55 764 if (NILP (noforce))
7ab12479
JB
765 w->force_start = Qt;
766 w->update_mode_line = Qt;
d834a2e9 767 XSETFASTINT (w->last_modified, 0);
3cd21523 768 XSETFASTINT (w->last_overlay_modified, 0);
62c07cc7
JB
769 if (!EQ (window, selected_window))
770 windows_or_buffers_changed++;
ce7fae7d 771
7ab12479
JB
772 return pos;
773}
774
775DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
776 1, 1, 0,
777 "Return WINDOW's dedicated object, usually t or nil.\n\
1f18c48f 778See also `set-window-dedicated-p'.")
7ab12479
JB
779 (window)
780 Lisp_Object window;
781{
782 return decode_window (window)->dedicated;
783}
784
d207b766
RS
785DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
786 Sset_window_dedicated_p, 2, 2, 0,
787 "Control whether WINDOW is dedicated to the buffer it displays.\n\
788If it is dedicated, Emacs will not automatically change\n\
789which buffer appears in it.\n\
790The second argument is the new value for the dedication flag;\n\
791non-nil means yes.")
7ab12479
JB
792 (window, arg)
793 Lisp_Object window, arg;
794{
795 register struct window *w = decode_window (window);
796
265a9e55 797 if (NILP (arg))
7ab12479
JB
798 w->dedicated = Qnil;
799 else
d207b766 800 w->dedicated = Qt;
7ab12479
JB
801
802 return w->dedicated;
803}
804
805DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
806 0, 1, 0,
807 "Return the display-table that WINDOW is using.")
808 (window)
809 Lisp_Object window;
810{
811 return decode_window (window)->display_table;
812}
813
5500c422
GM
814/* Get the display table for use on window W. This is either W's
815 display table or W's buffer's display table. Ignore the specified
816 tables if they are not valid; if no valid table is specified,
817 return 0. */
7ab12479 818
319315f1 819struct Lisp_Char_Table *
7ab12479
JB
820window_display_table (w)
821 struct window *w;
822{
823 Lisp_Object tem;
824 tem = w->display_table;
319315f1
RS
825 if (DISP_TABLE_P (tem))
826 return XCHAR_TABLE (tem);
171d003c
RS
827 if (NILP (w->buffer))
828 return 0;
829
7ab12479 830 tem = XBUFFER (w->buffer)->display_table;
319315f1
RS
831 if (DISP_TABLE_P (tem))
832 return XCHAR_TABLE (tem);
7ab12479 833 tem = Vstandard_display_table;
319315f1
RS
834 if (DISP_TABLE_P (tem))
835 return XCHAR_TABLE (tem);
7ab12479
JB
836 return 0;
837}
838
3a2712f9 839DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
7ab12479
JB
840 "Set WINDOW's display-table to TABLE.")
841 (window, table)
842 register Lisp_Object window, table;
843{
844 register struct window *w;
7ab12479
JB
845
846 w = decode_window (window);
847 w->display_table = table;
848 return table;
849}
850\f
851/* Record info on buffer window w is displaying
852 when it is about to cease to display that buffer. */
dfcf069d 853static void
7ab12479
JB
854unshow_buffer (w)
855 register struct window *w;
856{
12cae7c0 857 Lisp_Object buf;
b73ea88e 858 struct buffer *b;
7ab12479 859
12cae7c0 860 buf = w->buffer;
b73ea88e
RS
861 b = XBUFFER (buf);
862 if (b != XMARKER (w->pointm)->buffer)
7ab12479
JB
863 abort ();
864
b73ea88e
RS
865 if (w == XWINDOW (b->last_selected_window))
866 b->last_selected_window = Qnil;
86e48436 867
573f41ab 868#if 0
7ab12479
JB
869 if (w == XWINDOW (selected_window)
870 || ! EQ (buf, XWINDOW (selected_window)->buffer))
871 /* Do this except when the selected window's buffer
872 is being removed from some other window. */
573f41ab
RS
873#endif
874 /* last_window_start records the start position that this buffer
875 had in the last window to be disconnected from it.
876 Now that this statement is unconditional,
877 it is possible for the buffer to be displayed in the
878 selected window, while last_window_start reflects another
879 window which was recently showing the same buffer.
880 Some people might say that might be a good thing. Let's see. */
b73ea88e 881 b->last_window_start = marker_position (w->start);
7ab12479
JB
882
883 /* Point in the selected window's buffer
884 is actually stored in that buffer, and the window's pointm isn't used.
885 So don't clobber point in that buffer. */
886 if (! EQ (buf, XWINDOW (selected_window)->buffer))
b73ea88e
RS
887 temp_set_point_both (b,
888 clip_to_bounds (BUF_BEGV (b),
889 XMARKER (w->pointm)->charpos,
890 BUF_ZV (b)),
891 clip_to_bounds (BUF_BEGV_BYTE (b),
892 marker_byte_position (w->pointm),
893 BUF_ZV_BYTE (b)));
7ab12479
JB
894}
895
896/* Put replacement into the window structure in place of old. */
dfcf069d 897static void
7ab12479
JB
898replace_window (old, replacement)
899 Lisp_Object old, replacement;
900{
901 register Lisp_Object tem;
902 register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
903
44fa5b1e
JB
904 /* If OLD is its frame's root_window, then replacement is the new
905 root_window for that frame. */
7ab12479 906
7f4161e0 907 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
44fa5b1e 908 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
7ab12479
JB
909
910 p->left = o->left;
911 p->top = o->top;
912 p->width = o->width;
913 p->height = o->height;
5500c422
GM
914 p->desired_matrix = p->current_matrix = 0;
915 p->vscroll = 0;
916 bzero (&p->cursor, sizeof (p->cursor));
917 bzero (&p->last_cursor, sizeof (p->last_cursor));
918 bzero (&p->phys_cursor, sizeof (p->phys_cursor));
919 p->phys_cursor_type = -1;
920 p->must_be_updated_p = 0;
921 p->pseudo_window_p = 0;
922 XSETFASTINT (p->window_end_vpos, 0);
923 XSETFASTINT (p->window_end_pos, 0);
924 p->window_end_valid = Qnil;
7bbb5782 925 p->frozen_window_start_p = 0;
7ab12479
JB
926
927 p->next = tem = o->next;
265a9e55 928 if (!NILP (tem))
7ab12479
JB
929 XWINDOW (tem)->prev = replacement;
930
931 p->prev = tem = o->prev;
265a9e55 932 if (!NILP (tem))
7ab12479
JB
933 XWINDOW (tem)->next = replacement;
934
935 p->parent = tem = o->parent;
265a9e55 936 if (!NILP (tem))
7ab12479
JB
937 {
938 if (EQ (XWINDOW (tem)->vchild, old))
939 XWINDOW (tem)->vchild = replacement;
940 if (EQ (XWINDOW (tem)->hchild, old))
941 XWINDOW (tem)->hchild = replacement;
942 }
943
944/*** Here, if replacement is a vertical combination
945and so is its new parent, we should make replacement's
946children be children of that parent instead. ***/
947}
948
949DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
950 "Remove WINDOW from the display. Default is selected window.")
951 (window)
952 register Lisp_Object window;
543f5fb1
RS
953{
954 delete_window (window);
955
956 if (! NILP (Vwindow_configuration_change_hook)
957 && ! NILP (Vrun_hooks))
958 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
959
960 return Qnil;
961}
962
5e14b1fc 963void
543f5fb1
RS
964delete_window (window)
965 register Lisp_Object window;
7ab12479
JB
966{
967 register Lisp_Object tem, parent, sib;
968 register struct window *p;
969 register struct window *par;
5500c422 970 FRAME_PTR frame;
7ab12479 971
605be8af
JB
972 /* Because this function is called by other C code on non-leaf
973 windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
974 so we can't decode_window here. */
265a9e55 975 if (NILP (window))
7ab12479
JB
976 window = selected_window;
977 else
978 CHECK_WINDOW (window, 0);
7ab12479 979 p = XWINDOW (window);
605be8af
JB
980
981 /* It's okay to delete an already-deleted window. */
982 if (NILP (p->buffer)
983 && NILP (p->hchild)
984 && NILP (p->vchild))
296b535c 985 return;
605be8af 986
7ab12479 987 parent = p->parent;
265a9e55 988 if (NILP (parent))
7ab12479
JB
989 error ("Attempt to delete minibuffer or sole ordinary window");
990 par = XWINDOW (parent);
991
992 windows_or_buffers_changed++;
5500c422
GM
993 frame = XFRAME (WINDOW_FRAME (p));
994 FRAME_WINDOW_SIZES_CHANGED (frame) = 1;
7ab12479 995
605be8af
JB
996 /* Are we trying to delete any frame's selected window? */
997 {
0def0403 998 Lisp_Object frame, pwindow;
605be8af 999
0def0403
RS
1000 /* See if the frame's selected window is either WINDOW
1001 or any subwindow of it, by finding all that window's parents
1002 and comparing each one with WINDOW. */
1003 frame = WINDOW_FRAME (XWINDOW (window));
1004 pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
1005
1006 while (!NILP (pwindow))
1007 {
1008 if (EQ (window, pwindow))
1009 break;
1010 pwindow = XWINDOW (pwindow)->parent;
1011 }
1012
1013 if (EQ (window, pwindow))
605be8af 1014 {
89bca612
RS
1015 Lisp_Object alternative;
1016 alternative = Fnext_window (window, Qlambda, Qnil);
605be8af
JB
1017
1018 /* If we're about to delete the selected window on the
1019 selected frame, then we should use Fselect_window to select
1020 the new window. On the other hand, if we're about to
1021 delete the selected window on any other frame, we shouldn't do
1022 anything but set the frame's selected_window slot. */
1023 if (EQ (window, selected_window))
1024 Fselect_window (alternative);
1025 else
0def0403 1026 FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
605be8af
JB
1027 }
1028 }
7ab12479
JB
1029
1030 tem = p->buffer;
1031 /* tem is null for dummy parent windows
1032 (which have inferiors but not any contents themselves) */
265a9e55 1033 if (!NILP (tem))
7ab12479
JB
1034 {
1035 unshow_buffer (p);
1036 unchain_marker (p->pointm);
1037 unchain_marker (p->start);
7ab12479
JB
1038 }
1039
5500c422
GM
1040 /* Free window glyph matrices.
1041 It is sure that they are allocated again when ADJUST_GLYPHS
1042 is called. */
1043 free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (frame)));
1044
7ab12479 1045 tem = p->next;
265a9e55 1046 if (!NILP (tem))
7ab12479
JB
1047 XWINDOW (tem)->prev = p->prev;
1048
1049 tem = p->prev;
265a9e55 1050 if (!NILP (tem))
7ab12479
JB
1051 XWINDOW (tem)->next = p->next;
1052
1053 if (EQ (window, par->hchild))
1054 par->hchild = p->next;
1055 if (EQ (window, par->vchild))
1056 par->vchild = p->next;
1057
1058 /* Find one of our siblings to give our space to. */
1059 sib = p->prev;
265a9e55 1060 if (NILP (sib))
7ab12479
JB
1061 {
1062 /* If p gives its space to its next sibling, that sibling needs
1063 to have its top/left side pulled back to where p's is.
1064 set_window_{height,width} will re-position the sibling's
1065 children. */
1066 sib = p->next;
7f4161e0
JB
1067 XWINDOW (sib)->top = p->top;
1068 XWINDOW (sib)->left = p->left;
7ab12479
JB
1069 }
1070
1071 /* Stretch that sibling. */
265a9e55 1072 if (!NILP (par->vchild))
7ab12479
JB
1073 set_window_height (sib,
1074 XFASTINT (XWINDOW (sib)->height) + XFASTINT (p->height),
1075 1);
265a9e55 1076 if (!NILP (par->hchild))
7ab12479
JB
1077 set_window_width (sib,
1078 XFASTINT (XWINDOW (sib)->width) + XFASTINT (p->width),
1079 1);
1080
1081 /* If parent now has only one child,
1082 put the child into the parent's place. */
7ab12479 1083 tem = par->hchild;
265a9e55 1084 if (NILP (tem))
7ab12479 1085 tem = par->vchild;
265a9e55 1086 if (NILP (XWINDOW (tem)->next))
7ab12479 1087 replace_window (parent, tem);
605be8af
JB
1088
1089 /* Since we may be deleting combination windows, we must make sure that
1090 not only p but all its children have been marked as deleted. */
1091 if (! NILP (p->hchild))
1092 delete_all_subwindows (XWINDOW (p->hchild));
1093 else if (! NILP (p->vchild))
1094 delete_all_subwindows (XWINDOW (p->vchild));
1095
1096 /* Mark this window as deleted. */
1097 p->buffer = p->hchild = p->vchild = Qnil;
5500c422
GM
1098
1099 /* Adjust glyph matrices. */
1100 adjust_glyphs (frame);
7ab12479
JB
1101}
1102\f
7ab12479 1103
44fa5b1e 1104extern Lisp_Object next_frame (), prev_frame ();
7ab12479 1105
26f6279d
JB
1106/* This comment supplies the doc string for `next-window',
1107 for make-docfile to see. We cannot put this in the real DEFUN
1108 due to limits in the Unix cpp.
1109
1110DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
7ab12479 1111 "Return next window after WINDOW in canonical ordering of windows.\n\
d5783c40
JB
1112If omitted, WINDOW defaults to the selected window.\n\
1113\n\
1114Optional second arg MINIBUF t means count the minibuffer window even\n\
1115if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1116it is active. MINIBUF neither t nor nil means not to count the\n\
1117minibuffer even if it is active.\n\
1118\n\
44fa5b1e
JB
1119Several frames may share a single minibuffer; if the minibuffer\n\
1120counts, all windows on all frames that share that minibuffer count\n\
ed160f1f 1121too. Therefore, `next-window' can be used to iterate through the\n\
44fa5b1e
JB
1122set of windows even when the minibuffer is on another frame. If the\n\
1123minibuffer does not count, only windows from WINDOW's frame count.\n\
d5783c40 1124\n\
44fa5b1e
JB
1125Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1126ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
89bca612 1127above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
f812f9c6 1128ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1f4c5d09 1129If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
89bca612 1130Anything else means restrict to WINDOW's frame.\n\
dbc4e1c1
JB
1131\n\
1132If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1133`next-window' to iterate through the entire cycle of acceptable\n\
1134windows, eventually ending up back at the window you started with.\n\
1135`previous-window' traverses the same cycle, in the reverse order.")
26f6279d
JB
1136 (window, minibuf, all_frames) */
1137
1138DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
1139 0)
44fa5b1e
JB
1140 (window, minibuf, all_frames)
1141 register Lisp_Object window, minibuf, all_frames;
7ab12479
JB
1142{
1143 register Lisp_Object tem;
d5783c40 1144 Lisp_Object start_window;
7ab12479 1145
265a9e55 1146 if (NILP (window))
7ab12479
JB
1147 window = selected_window;
1148 else
605be8af 1149 CHECK_LIVE_WINDOW (window, 0);
7ab12479 1150
d5783c40
JB
1151 start_window = window;
1152
1153 /* minibuf == nil may or may not include minibuffers.
1154 Decide if it does. */
265a9e55 1155 if (NILP (minibuf))
fbdc1545
RS
1156 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1157 else if (! EQ (minibuf, Qt))
1158 minibuf = Qlambda;
1159 /* Now minibuf can be t => count all minibuffer windows,
1160 lambda => count none of them,
1161 or a specific minibuffer window (the active one) to count. */
d5783c40 1162
1bb80f72 1163 /* all_frames == nil doesn't specify which frames to include. */
44fa5b1e 1164 if (NILP (all_frames))
fbdc1545 1165 all_frames = (! EQ (minibuf, Qlambda)
1bb80f72
RS
1166 ? (FRAME_MINIBUF_WINDOW
1167 (XFRAME
1168 (WINDOW_FRAME
1169 (XWINDOW (window)))))
1170 : Qnil);
89bca612
RS
1171 else if (EQ (all_frames, Qvisible))
1172 ;
f812f9c6
RS
1173 else if (XFASTINT (all_frames) == 0)
1174 ;
1f4c5d09
RS
1175 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1176 /* If all_frames is a frame and window arg isn't on that frame, just
1177 return the first window on the frame. */
1178 return Fframe_first_window (all_frames);
44fa5b1e
JB
1179 else if (! EQ (all_frames, Qt))
1180 all_frames = Qnil;
644b477c
RS
1181 /* Now all_frames is t meaning search all frames,
1182 nil meaning search just current frame,
f812f9c6
RS
1183 visible meaning search just visible frames,
1184 0 meaning search visible and iconified frames,
644b477c 1185 or a window, meaning search the frame that window belongs to. */
7ab12479
JB
1186
1187 /* Do this loop at least once, to get the next window, and perhaps
1188 again, if we hit the minibuffer and that is not acceptable. */
1189 do
1190 {
1191 /* Find a window that actually has a next one. This loop
1192 climbs up the tree. */
265a9e55
JB
1193 while (tem = XWINDOW (window)->next, NILP (tem))
1194 if (tem = XWINDOW (window)->parent, !NILP (tem))
7ab12479 1195 window = tem;
d5783c40 1196 else
7ab12479 1197 {
44fa5b1e
JB
1198 /* We've reached the end of this frame.
1199 Which other frames are acceptable? */
1200 tem = WINDOW_FRAME (XWINDOW (window));
44fa5b1e 1201 if (! NILP (all_frames))
1bb80f72
RS
1202 {
1203 Lisp_Object tem1;
1204
1205 tem1 = tem;
1206 tem = next_frame (tem, all_frames);
1207 /* In the case where the minibuffer is active,
1208 and we include its frame as well as the selected one,
1209 next_frame may get stuck in that frame.
1210 If that happens, go back to the selected frame
1211 so we can complete the cycle. */
1212 if (EQ (tem, tem1))
1ae1a37d 1213 tem = selected_frame;
1bb80f72 1214 }
44fa5b1e 1215 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
d5783c40 1216
7ab12479
JB
1217 break;
1218 }
1219
1220 window = tem;
d5783c40 1221
7ab12479
JB
1222 /* If we're in a combination window, find its first child and
1223 recurse on that. Otherwise, we've found the window we want. */
1224 while (1)
1225 {
265a9e55 1226 if (!NILP (XWINDOW (window)->hchild))
7ab12479 1227 window = XWINDOW (window)->hchild;
265a9e55 1228 else if (!NILP (XWINDOW (window)->vchild))
7ab12479
JB
1229 window = XWINDOW (window)->vchild;
1230 else break;
1231 }
1232 }
5c4d25a6 1233 /* Which windows are acceptable?
d5783c40 1234 Exit the loop and accept this window if
fbdc1545
RS
1235 this isn't a minibuffer window,
1236 or we're accepting all minibuffer windows,
1237 or this is the active minibuffer and we are accepting that one, or
d5783c40 1238 we've come all the way around and we're back at the original window. */
7ab12479 1239 while (MINI_WINDOW_P (XWINDOW (window))
d5783c40 1240 && ! EQ (minibuf, Qt)
fbdc1545 1241 && ! EQ (minibuf, window)
7f4161e0 1242 && ! EQ (window, start_window));
7ab12479
JB
1243
1244 return window;
1245}
1246
26f6279d
JB
1247/* This comment supplies the doc string for `previous-window',
1248 for make-docfile to see. We cannot put this in the real DEFUN
1249 due to limits in the Unix cpp.
1250
1251DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
5c4d25a6 1252 "Return the window preceding WINDOW in canonical ordering of windows.\n\
d5783c40
JB
1253If omitted, WINDOW defaults to the selected window.\n\
1254\n\
1255Optional second arg MINIBUF t means count the minibuffer window even\n\
1256if not active. MINIBUF nil or omitted means count the minibuffer iff\n\
1257it is active. MINIBUF neither t nor nil means not to count the\n\
1258minibuffer even if it is active.\n\
1259\n\
44fa5b1e
JB
1260Several frames may share a single minibuffer; if the minibuffer\n\
1261counts, all windows on all frames that share that minibuffer count\n\
ed160f1f 1262too. Therefore, `previous-window' can be used to iterate through\n\
44fa5b1e 1263the set of windows even when the minibuffer is on another frame. If\n\
ed160f1f 1264the minibuffer does not count, only windows from WINDOW's frame count\n\
d5783c40 1265\n\
44fa5b1e
JB
1266Optional third arg ALL-FRAMES t means include windows on all frames.\n\
1267ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
89bca612 1268above. ALL-FRAMES = `visible' means include windows on all visible frames.\n\
f812f9c6 1269ALL-FRAMES = 0 means include windows on all visible and iconified frames.\n\
1f4c5d09 1270If ALL-FRAMES is a frame, restrict search to windows on that frame.\n\
89bca612 1271Anything else means restrict to WINDOW's frame.\n\
dbc4e1c1
JB
1272\n\
1273If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
1274`previous-window' to iterate through the entire cycle of acceptable\n\
1275windows, eventually ending up back at the window you started with.\n\
1276`next-window' traverses the same cycle, in the reverse order.")
26f6279d
JB
1277 (window, minibuf, all_frames) */
1278
1279
1280DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
1281 0)
44fa5b1e
JB
1282 (window, minibuf, all_frames)
1283 register Lisp_Object window, minibuf, all_frames;
7ab12479
JB
1284{
1285 register Lisp_Object tem;
d5783c40 1286 Lisp_Object start_window;
7ab12479 1287
265a9e55 1288 if (NILP (window))
7ab12479
JB
1289 window = selected_window;
1290 else
605be8af 1291 CHECK_LIVE_WINDOW (window, 0);
7ab12479 1292
d5783c40
JB
1293 start_window = window;
1294
1295 /* minibuf == nil may or may not include minibuffers.
1296 Decide if it does. */
265a9e55 1297 if (NILP (minibuf))
fbdc1545
RS
1298 minibuf = (minibuf_level ? minibuf_window : Qlambda);
1299 else if (! EQ (minibuf, Qt))
1300 minibuf = Qlambda;
1301 /* Now minibuf can be t => count all minibuffer windows,
1302 lambda => count none of them,
1303 or a specific minibuffer window (the active one) to count. */
d5783c40 1304
44fa5b1e
JB
1305 /* all_frames == nil doesn't specify which frames to include.
1306 Decide which frames it includes. */
1307 if (NILP (all_frames))
fbdc1545 1308 all_frames = (! EQ (minibuf, Qlambda)
44fa5b1e
JB
1309 ? (FRAME_MINIBUF_WINDOW
1310 (XFRAME
1311 (WINDOW_FRAME
d5783c40
JB
1312 (XWINDOW (window)))))
1313 : Qnil);
89bca612
RS
1314 else if (EQ (all_frames, Qvisible))
1315 ;
f812f9c6
RS
1316 else if (XFASTINT (all_frames) == 0)
1317 ;
1f4c5d09
RS
1318 else if (FRAMEP (all_frames) && ! EQ (all_frames, Fwindow_frame (window)))
1319 /* If all_frames is a frame and window arg isn't on that frame, just
1320 return the first window on the frame. */
1321 return Fframe_first_window (all_frames);
44fa5b1e
JB
1322 else if (! EQ (all_frames, Qt))
1323 all_frames = Qnil;
644b477c
RS
1324 /* Now all_frames is t meaning search all frames,
1325 nil meaning search just current frame,
f812f9c6
RS
1326 visible meaning search just visible frames,
1327 0 meaning search visible and iconified frames,
644b477c 1328 or a window, meaning search the frame that window belongs to. */
7ab12479
JB
1329
1330 /* Do this loop at least once, to get the previous window, and perhaps
1331 again, if we hit the minibuffer and that is not acceptable. */
1332 do
1333 {
1334 /* Find a window that actually has a previous one. This loop
1335 climbs up the tree. */
265a9e55
JB
1336 while (tem = XWINDOW (window)->prev, NILP (tem))
1337 if (tem = XWINDOW (window)->parent, !NILP (tem))
7ab12479 1338 window = tem;
d5783c40 1339 else
7ab12479 1340 {
44fa5b1e
JB
1341 /* We have found the top window on the frame.
1342 Which frames are acceptable? */
1343 tem = WINDOW_FRAME (XWINDOW (window));
44fa5b1e 1344 if (! NILP (all_frames))
dbc4e1c1
JB
1345 /* It's actually important that we use prev_frame here,
1346 rather than next_frame. All the windows acceptable
1347 according to the given parameters should form a ring;
1348 Fnext_window and Fprevious_window should go back and
1349 forth around the ring. If we use next_frame here,
1350 then Fnext_window and Fprevious_window take different
1351 paths through the set of acceptable windows.
1352 window_loop assumes that these `ring' requirement are
1353 met. */
1bb80f72
RS
1354 {
1355 Lisp_Object tem1;
1356
1357 tem1 = tem;
1358 tem = prev_frame (tem, all_frames);
1359 /* In the case where the minibuffer is active,
1360 and we include its frame as well as the selected one,
1361 next_frame may get stuck in that frame.
1362 If that happens, go back to the selected frame
1363 so we can complete the cycle. */
1364 if (EQ (tem, tem1))
1ae1a37d 1365 tem = selected_frame;
1bb80f72 1366 }
644b477c
RS
1367 /* If this frame has a minibuffer, find that window first,
1368 because it is conceptually the last window in that frame. */
5e12e32f
JB
1369 if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
1370 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
1371 else
644b477c 1372 tem = FRAME_ROOT_WINDOW (XFRAME (tem));
d5783c40 1373
7ab12479
JB
1374 break;
1375 }
1376
1377 window = tem;
1378 /* If we're in a combination window, find its last child and
1379 recurse on that. Otherwise, we've found the window we want. */
1380 while (1)
1381 {
265a9e55 1382 if (!NILP (XWINDOW (window)->hchild))
7ab12479 1383 window = XWINDOW (window)->hchild;
265a9e55 1384 else if (!NILP (XWINDOW (window)->vchild))
7ab12479
JB
1385 window = XWINDOW (window)->vchild;
1386 else break;
265a9e55 1387 while (tem = XWINDOW (window)->next, !NILP (tem))
7ab12479
JB
1388 window = tem;
1389 }
1390 }
5c4d25a6 1391 /* Which windows are acceptable?
d5783c40 1392 Exit the loop and accept this window if
fbdc1545
RS
1393 this isn't a minibuffer window,
1394 or we're accepting all minibuffer windows,
1395 or this is the active minibuffer and we are accepting that one, or
d5783c40 1396 we've come all the way around and we're back at the original window. */
7ab12479 1397 while (MINI_WINDOW_P (XWINDOW (window))
fbdc1545
RS
1398 && ! EQ (minibuf, Qt)
1399 && ! EQ (minibuf, window)
1400 && ! EQ (window, start_window));
7ab12479
JB
1401
1402 return window;
1403}
1404
62c07cc7 1405DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
44fa5b1e
JB
1406 "Select the ARG'th different window on this frame.\n\
1407All windows on current frame are arranged in a cyclic order.\n\
7ab12479
JB
1408This command selects the window ARG steps away in that order.\n\
1409A negative ARG moves in the opposite order. If the optional second\n\
44fa5b1e 1410argument ALL_FRAMES is non-nil, cycle through all frames.")
413430c5
EN
1411 (arg, all_frames)
1412 register Lisp_Object arg, all_frames;
7ab12479
JB
1413{
1414 register int i;
1415 register Lisp_Object w;
1416
413430c5 1417 CHECK_NUMBER (arg, 0);
7ab12479 1418 w = selected_window;
413430c5 1419 i = XINT (arg);
7ab12479
JB
1420
1421 while (i > 0)
1422 {
44fa5b1e 1423 w = Fnext_window (w, Qnil, all_frames);
7ab12479
JB
1424 i--;
1425 }
1426 while (i < 0)
1427 {
44fa5b1e 1428 w = Fprevious_window (w, Qnil, all_frames);
7ab12479
JB
1429 i++;
1430 }
1431 Fselect_window (w);
1432 return Qnil;
1433}
1434\f
1435/* Look at all windows, performing an operation specified by TYPE
1436 with argument OBJ.
75d8f668 1437 If FRAMES is Qt, look at all frames;
75d8f668 1438 Qnil, look at just the selected frame;
89bca612 1439 Qvisible, look at visible frames;
75d8f668 1440 a frame, just look at windows on that frame.
7ab12479
JB
1441 If MINI is non-zero, perform the operation on minibuffer windows too.
1442*/
1443
1444enum window_loop
1445{
1446 WINDOW_LOOP_UNUSED,
1447 GET_BUFFER_WINDOW, /* Arg is buffer */
1448 GET_LRU_WINDOW, /* Arg is t for full-width windows only */
1449 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
1450 DELETE_BUFFER_WINDOWS, /* Arg is buffer */
1451 GET_LARGEST_WINDOW,
3f8ab7bd
RS
1452 UNSHOW_BUFFER, /* Arg is buffer */
1453 CHECK_ALL_WINDOWS
7ab12479
JB
1454};
1455
1456static Lisp_Object
44fa5b1e 1457window_loop (type, obj, mini, frames)
7ab12479 1458 enum window_loop type;
44fa5b1e 1459 register Lisp_Object obj, frames;
7ab12479
JB
1460 int mini;
1461{
1462 register Lisp_Object w;
1463 register Lisp_Object best_window;
1464 register Lisp_Object next_window;
4b206065 1465 register Lisp_Object last_window;
44fa5b1e 1466 FRAME_PTR frame;
89bca612
RS
1467 Lisp_Object frame_arg;
1468 frame_arg = Qt;
44fa5b1e
JB
1469
1470 /* If we're only looping through windows on a particular frame,
1471 frame points to that frame. If we're looping through windows
1472 on all frames, frame is 0. */
1473 if (FRAMEP (frames))
1474 frame = XFRAME (frames);
1475 else if (NILP (frames))
1ae1a37d 1476 frame = SELECTED_FRAME ();
7ab12479 1477 else
44fa5b1e 1478 frame = 0;
89bca612
RS
1479 if (frame)
1480 frame_arg = Qlambda;
f812f9c6
RS
1481 else if (XFASTINT (frames) == 0)
1482 frame_arg = frames;
89bca612
RS
1483 else if (EQ (frames, Qvisible))
1484 frame_arg = frames;
7ab12479 1485
89bca612
RS
1486 /* frame_arg is Qlambda to stick to one frame,
1487 Qvisible to consider all visible frames,
1488 or Qt otherwise. */
1489
7ab12479 1490 /* Pick a window to start with. */
017b2bad 1491 if (WINDOWP (obj))
4b206065 1492 w = obj;
44fa5b1e 1493 else if (frame)
4b206065 1494 w = FRAME_SELECTED_WINDOW (frame);
7ab12479 1495 else
1ae1a37d 1496 w = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
4b206065
JB
1497
1498 /* Figure out the last window we're going to mess with. Since
1499 Fnext_window, given the same options, is guaranteed to go in a
1500 ring, we can just use Fprevious_window to find the last one.
1501
1502 We can't just wait until we hit the first window again, because
1503 it might be deleted. */
1504
89bca612 1505 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg);
7ab12479 1506
7ab12479 1507 best_window = Qnil;
4b206065 1508 for (;;)
7ab12479
JB
1509 {
1510 /* Pick the next window now, since some operations will delete
1511 the current window. */
89bca612 1512 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg);
7ab12479 1513
d29a5631
RS
1514 /* Note that we do not pay attention here to whether
1515 the frame is visible, since Fnext_window skips non-visible frames
1516 if that is desired, under the control of frame_arg. */
75d8f668 1517 if (! MINI_WINDOW_P (XWINDOW (w))
65a04b96
RS
1518 /* For UNSHOW_BUFFER, we must always consider all windows. */
1519 || type == UNSHOW_BUFFER
7ab12479
JB
1520 || (mini && minibuf_level > 0))
1521 switch (type)
1522 {
1523 case GET_BUFFER_WINDOW:
5c204627
RS
1524 if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj)
1525 /* Don't find any minibuffer window
1526 except the one that is currently in use. */
1527 && (MINI_WINDOW_P (XWINDOW (w))
1528 ? EQ (w, minibuf_window) : 1))
7ab12479
JB
1529 return w;
1530 break;
1531
1532 case GET_LRU_WINDOW:
1533 /* t as arg means consider only full-width windows */
111e5992 1534 if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (XWINDOW (w)))
7ab12479 1535 break;
7ab12479
JB
1536 /* Ignore dedicated windows and minibuffers. */
1537 if (MINI_WINDOW_P (XWINDOW (w))
265a9e55 1538 || !NILP (XWINDOW (w)->dedicated))
7ab12479 1539 break;
265a9e55 1540 if (NILP (best_window)
7ab12479
JB
1541 || (XFASTINT (XWINDOW (best_window)->use_time)
1542 > XFASTINT (XWINDOW (w)->use_time)))
1543 best_window = w;
1544 break;
1545
1546 case DELETE_OTHER_WINDOWS:
1547 if (XWINDOW (w) != XWINDOW (obj))
1548 Fdelete_window (w);
1549 break;
1550
1551 case DELETE_BUFFER_WINDOWS:
1552 if (EQ (XWINDOW (w)->buffer, obj))
1553 {
3548e138
RS
1554 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
1555
1556 /* If this window is dedicated, and in a frame of its own,
1557 kill the frame. */
1558 if (EQ (w, FRAME_ROOT_WINDOW (f))
1559 && !NILP (XWINDOW (w)->dedicated)
1560 && other_visible_frames (f))
7ab12479 1561 {
3548e138
RS
1562 /* Skip the other windows on this frame.
1563 There might be one, the minibuffer! */
1564 if (! EQ (w, last_window))
1565 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1566 {
1567 /* As we go, check for the end of the loop.
1568 We mustn't start going around a second time. */
1569 if (EQ (next_window, last_window))
1570 {
1571 last_window = w;
1572 break;
1573 }
1574 next_window = Fnext_window (next_window,
1575 mini ? Qt : Qnil,
1576 frame_arg);
1577 }
1578 /* Now we can safely delete the frame. */
1579 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
7ab12479
JB
1580 }
1581 else
3548e138
RS
1582 /* If we're deleting the buffer displayed in the only window
1583 on the frame, find a new buffer to display there. */
1584 if (NILP (XWINDOW (w)->parent))
1585 {
1586 Lisp_Object new_buffer;
b7354ddf
RS
1587 new_buffer = Fother_buffer (obj, Qnil,
1588 XWINDOW (w)->frame);
3548e138
RS
1589 if (NILP (new_buffer))
1590 new_buffer
1591 = Fget_buffer_create (build_string ("*scratch*"));
1592 Fset_window_buffer (w, new_buffer);
1593 if (EQ (w, selected_window))
1594 Fset_buffer (XWINDOW (w)->buffer);
1595 }
1596 else
1597 Fdelete_window (w);
7ab12479
JB
1598 }
1599 break;
1600
1601 case GET_LARGEST_WINDOW:
7ab12479
JB
1602 /* Ignore dedicated windows and minibuffers. */
1603 if (MINI_WINDOW_P (XWINDOW (w))
265a9e55 1604 || !NILP (XWINDOW (w)->dedicated))
7ab12479
JB
1605 break;
1606 {
1607 struct window *best_window_ptr = XWINDOW (best_window);
1608 struct window *w_ptr = XWINDOW (w);
6b54027b
RS
1609 if (NILP (best_window)
1610 || (XFASTINT (w_ptr->height) * XFASTINT (w_ptr->width)
1611 > (XFASTINT (best_window_ptr->height)
1612 * XFASTINT (best_window_ptr->width))))
7ab12479
JB
1613 best_window = w;
1614 }
1615 break;
1616
1617 case UNSHOW_BUFFER:
1618 if (EQ (XWINDOW (w)->buffer, obj))
1619 {
1620 /* Find another buffer to show in this window. */
12cae7c0 1621 Lisp_Object another_buffer;
38ab08d1 1622 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (w)));
b7354ddf 1623 another_buffer = Fother_buffer (obj, Qnil, XWINDOW (w)->frame);
265a9e55 1624 if (NILP (another_buffer))
7ab12479
JB
1625 another_buffer
1626 = Fget_buffer_create (build_string ("*scratch*"));
38ab08d1
RS
1627 /* If this window is dedicated, and in a frame of its own,
1628 kill the frame. */
1629 if (EQ (w, FRAME_ROOT_WINDOW (f))
596122a7 1630 && !NILP (XWINDOW (w)->dedicated)
38ab08d1 1631 && other_visible_frames (f))
45945a7b
RS
1632 {
1633 /* Skip the other windows on this frame.
1634 There might be one, the minibuffer! */
1635 if (! EQ (w, last_window))
1636 while (f == XFRAME (WINDOW_FRAME (XWINDOW (next_window))))
1637 {
1638 /* As we go, check for the end of the loop.
1639 We mustn't start going around a second time. */
1640 if (EQ (next_window, last_window))
1641 {
1642 last_window = w;
1643 break;
1644 }
1645 next_window = Fnext_window (next_window,
1646 mini ? Qt : Qnil,
1647 frame_arg);
1648 }
1649 /* Now we can safely delete the frame. */
1650 Fdelete_frame (WINDOW_FRAME (XWINDOW (w)), Qnil);
1651 }
38ab08d1 1652 else
38ab08d1
RS
1653 {
1654 /* Otherwise show a different buffer in the window. */
1655 XWINDOW (w)->dedicated = Qnil;
1656 Fset_window_buffer (w, another_buffer);
1657 if (EQ (w, selected_window))
1658 Fset_buffer (XWINDOW (w)->buffer);
1659 }
7ab12479
JB
1660 }
1661 break;
3f8ab7bd
RS
1662
1663 /* Check for a window that has a killed buffer. */
1664 case CHECK_ALL_WINDOWS:
1665 if (! NILP (XWINDOW (w)->buffer)
1666 && NILP (XBUFFER (XWINDOW (w)->buffer)->name))
1667 abort ();
7ab12479 1668 }
4b206065
JB
1669
1670 if (EQ (w, last_window))
1671 break;
1672
7ab12479
JB
1673 w = next_window;
1674 }
7ab12479
JB
1675
1676 return best_window;
37962e60 1677}
605be8af 1678
3f8ab7bd
RS
1679/* Used for debugging. Abort if any window has a dead buffer. */
1680
233a4a2c 1681void
3f8ab7bd
RS
1682check_all_windows ()
1683{
1684 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
1685}
1686
7ab12479
JB
1687DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
1688 "Return the window least recently selected or used for display.\n\
89bca612 1689If optional argument FRAME is `visible', search all visible frames.\n\
cee67da9 1690If FRAME is 0, search all visible and iconified frames.\n\
89bca612
RS
1691If FRAME is t, search all frames.\n\
1692If FRAME is nil, search only the selected frame.\n\
1693If FRAME is a frame, search only that frame.")
1694 (frame)
1695 Lisp_Object frame;
7ab12479
JB
1696{
1697 register Lisp_Object w;
1698 /* First try for a window that is full-width */
89bca612 1699 w = window_loop (GET_LRU_WINDOW, Qt, 0, frame);
265a9e55 1700 if (!NILP (w) && !EQ (w, selected_window))
7ab12479
JB
1701 return w;
1702 /* If none of them, try the rest */
89bca612 1703 return window_loop (GET_LRU_WINDOW, Qnil, 0, frame);
7ab12479
JB
1704}
1705
1706DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
1707 "Return the largest window in area.\n\
89bca612 1708If optional argument FRAME is `visible', search all visible frames.\n\
cee67da9 1709If FRAME is 0, search all visible and iconified frames.\n\
89bca612
RS
1710If FRAME is t, search all frames.\n\
1711If FRAME is nil, search only the selected frame.\n\
1712If FRAME is a frame, search only that frame.")
44fa5b1e
JB
1713 (frame)
1714 Lisp_Object frame;
7ab12479
JB
1715{
1716 return window_loop (GET_LARGEST_WINDOW, Qnil, 0,
44fa5b1e 1717 frame);
7ab12479
JB
1718}
1719
1720DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
1721 "Return a window currently displaying BUFFER, or nil if none.\n\
89bca612 1722If optional argument FRAME is `visible', search all visible frames.\n\
f812f9c6 1723If optional argument FRAME is 0, search all visible and iconified frames.\n\
89bca612 1724If FRAME is t, search all frames.\n\
1bc981d2 1725If FRAME is nil, search only the selected frame.\n\
89bca612 1726If FRAME is a frame, search only that frame.")
44fa5b1e
JB
1727 (buffer, frame)
1728 Lisp_Object buffer, frame;
7ab12479
JB
1729{
1730 buffer = Fget_buffer (buffer);
017b2bad 1731 if (BUFFERP (buffer))
44fa5b1e 1732 return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
7ab12479
JB
1733 else
1734 return Qnil;
1735}
1736
1737DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
1738 0, 1, "",
44fa5b1e 1739 "Make WINDOW (or the selected window) fill its frame.\n\
f16a1ed3
RS
1740Only the frame WINDOW is on is affected.\n\
1741This function tries to reduce display jumps\n\
1742by keeping the text previously visible in WINDOW\n\
1743in the same place on the frame. Doing this depends on\n\
1744the value of (window-start WINDOW), so if calling this function\n\
1745in a program gives strange scrolling, make sure the window-start\n\
1746value is reasonable when this function is called.")
7ab12479
JB
1747 (window)
1748 Lisp_Object window;
1749{
1750 struct window *w;
00d3d838 1751 int startpos;
7ab12479
JB
1752 int top;
1753
265a9e55 1754 if (NILP (window))
7ab12479
JB
1755 window = selected_window;
1756 else
605be8af 1757 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
1758
1759 w = XWINDOW (window);
a2b38b3c 1760
00d3d838 1761 startpos = marker_position (w->start);
5500c422 1762 top = XFASTINT (w->top) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
7ab12479 1763
a2b38b3c
RS
1764 if (MINI_WINDOW_P (w) && top > 0)
1765 error ("Can't expand minibuffer to full frame");
1766
70728a80 1767 window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
7ab12479 1768
00d3d838
KH
1769 /* Try to minimize scrolling, by setting the window start to the point
1770 will cause the text at the old window start to be at the same place
1771 on the frame. But don't try to do this if the window start is
1772 outside the visible portion (as might happen when the display is
1773 not current, due to typeahead). */
1774 if (startpos >= BUF_BEGV (XBUFFER (w->buffer))
1775 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
1776 {
1777 struct position pos;
1778 struct buffer *obuf = current_buffer;
1779
1780 Fset_buffer (w->buffer);
1781 /* This computation used to temporarily move point, but that can
1782 have unwanted side effects due to text properties. */
0383eb57 1783 pos = *vmotion (startpos, -top, w);
4d047f50 1784
b73ea88e
RS
1785 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
1786 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
1787 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
00d3d838 1788 : Qnil);
80622eec
RS
1789 /* We need to do this, so that the window-scroll-functions
1790 get called. */
4d047f50 1791 w->optional_new_start = Qt;
00d3d838
KH
1792
1793 set_buffer_internal (obuf);
1794 }
5500c422 1795
7ab12479
JB
1796 return Qnil;
1797}
1798
1799DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
3cbbb729 1800 1, 2, "bDelete windows on (buffer): ",
26f6279d
JB
1801 "Delete all windows showing BUFFER.\n\
1802Optional second argument FRAME controls which frames are affected.\n\
c520265e
RS
1803If optional argument FRAME is `visible', search all visible frames.\n\
1804If FRAME is 0, search all visible and iconified frames.\n\
1805If FRAME is nil, search all frames.\n\
1806If FRAME is t, search only the selected frame.\n\
1807If FRAME is a frame, search only that frame.")
26f6279d
JB
1808 (buffer, frame)
1809 Lisp_Object buffer, frame;
7ab12479 1810{
26f6279d
JB
1811 /* FRAME uses t and nil to mean the opposite of what window_loop
1812 expects. */
c520265e
RS
1813 if (NILP (frame))
1814 frame = Qt;
1815 else if (EQ (frame, Qt))
1816 frame = Qnil;
26f6279d 1817
265a9e55 1818 if (!NILP (buffer))
7ab12479
JB
1819 {
1820 buffer = Fget_buffer (buffer);
1821 CHECK_BUFFER (buffer, 0);
26f6279d 1822 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
7ab12479 1823 }
5500c422 1824
7ab12479
JB
1825 return Qnil;
1826}
1827
1828DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
1829 Sreplace_buffer_in_windows,
1830 1, 1, "bReplace buffer in windows: ",
1831 "Replace BUFFER with some other buffer in all windows showing it.")
1832 (buffer)
1833 Lisp_Object buffer;
1834{
265a9e55 1835 if (!NILP (buffer))
7ab12479
JB
1836 {
1837 buffer = Fget_buffer (buffer);
1838 CHECK_BUFFER (buffer, 0);
1839 window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
1840 }
1841 return Qnil;
1842}
ff58478b
RS
1843
1844/* Replace BUFFER with some other buffer in all windows
1845 of all frames, even those on other keyboards. */
1846
1847void
1848replace_buffer_in_all_windows (buffer)
1849 Lisp_Object buffer;
1850{
27abb84f 1851#ifdef MULTI_KBOARD
ff58478b
RS
1852 Lisp_Object tail, frame;
1853
ff58478b
RS
1854 /* A single call to window_loop won't do the job
1855 because it only considers frames on the current keyboard.
1856 So loop manually over frames, and handle each one. */
1857 FOR_EACH_FRAME (tail, frame)
db7f721d 1858 window_loop (UNSHOW_BUFFER, buffer, 1, frame);
ff58478b 1859#else
db7f721d 1860 window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
ff58478b
RS
1861#endif
1862}
7ab12479
JB
1863\f
1864/* Set the height of WINDOW and all its inferiors. */
a481b3ea
JB
1865
1866/* The smallest acceptable dimensions for a window. Anything smaller
1867 might crash Emacs. */
5500c422 1868
a481b3ea
JB
1869#define MIN_SAFE_WINDOW_WIDTH (2)
1870#define MIN_SAFE_WINDOW_HEIGHT (2)
1871
1872/* Make sure that window_min_height and window_min_width are
1873 not too small; if they are, set them to safe minima. */
1874
1875static void
1876check_min_window_sizes ()
1877{
1878 /* Smaller values might permit a crash. */
1879 if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
1880 window_min_width = MIN_SAFE_WINDOW_WIDTH;
1881 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
1882 window_min_height = MIN_SAFE_WINDOW_HEIGHT;
1883}
1884
1885/* If *ROWS or *COLS are too small a size for FRAME, set them to the
1886 minimum allowable size. */
5500c422 1887
605be8af 1888void
a481b3ea 1889check_frame_size (frame, rows, cols)
605be8af
JB
1890 FRAME_PTR frame;
1891 int *rows, *cols;
a481b3ea 1892{
628df3bf 1893 /* For height, we have to see:
37962e60 1894 whether the frame has a minibuffer,
628df3bf
JB
1895 whether it wants a mode line, and
1896 whether it has a menu bar. */
a481b3ea 1897 int min_height =
79f92720
JB
1898 (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
1899 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
a481b3ea 1900 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
5500c422
GM
1901
1902 if (FRAME_TOP_MARGIN (frame) > 0)
1903 min_height += FRAME_TOP_MARGIN (frame);
a481b3ea
JB
1904
1905 if (*rows < min_height)
1906 *rows = min_height;
1907 if (*cols < MIN_SAFE_WINDOW_WIDTH)
1908 *cols = MIN_SAFE_WINDOW_WIDTH;
1909}
1910
c1636aa6 1911
233a4a2c
GM
1912/* Value is non-zero if window W is fixed-size. WIDTH_P non-zero means
1913 check if W's width can be changed, otherwise check W's height.
1914 CHECK_SIBLINGS_P non-zero means check resizablity of WINDOW's
1915 siblings, too. If none of the siblings is resizable, WINDOW isn't
1916 either. */
c1636aa6 1917
233a4a2c
GM
1918static int
1919window_fixed_size_p (w, width_p, check_siblings_p)
1920 struct window *w;
1921 int width_p, check_siblings_p;
1922{
1923 int fixed_p;
1924 struct window *c;
1925
1926 if (!NILP (w->hchild))
1927 {
1928 c = XWINDOW (w->hchild);
1929
1930 if (width_p)
1931 {
1932 /* A horiz. combination is fixed-width if all of if its
1933 children are. */
1934 while (c && window_fixed_size_p (c, width_p, 0))
1935 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1936 fixed_p = c == NULL;
1937 }
1938 else
1939 {
1940 /* A horiz. combination is fixed-height if one of if its
1941 children is. */
1942 while (c && !window_fixed_size_p (c, width_p, 0))
1943 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1944 fixed_p = c != NULL;
1945 }
1946 }
1947 else if (!NILP (w->vchild))
1948 {
1949 c = XWINDOW (w->vchild);
1950
1951 if (width_p)
1952 {
1953 /* A vert. combination is fixed-width if one of if its
1954 children is. */
1955 while (c && !window_fixed_size_p (c, width_p, 0))
1956 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1957 fixed_p = c != NULL;
1958 }
1959 else
1960 {
1961 /* A vert. combination is fixed-height if all of if its
1962 children are. */
1963 while (c && window_fixed_size_p (c, width_p, 0))
1964 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
1965 fixed_p = c == NULL;
1966 }
1967 }
1968 else if (BUFFERP (w->buffer))
1969 {
a34dfd12
GM
1970 if (w->height_fixed_p && !width_p)
1971 fixed_p = 1;
1972 else
233a4a2c 1973 {
a34dfd12
GM
1974 struct buffer *old = current_buffer;
1975 Lisp_Object val;
1976
1977 current_buffer = XBUFFER (w->buffer);
1978 val = find_symbol_value (Qwindow_size_fixed);
1979 current_buffer = old;
1980
1981 fixed_p = 0;
1982 if (!EQ (val, Qunbound))
1983 {
1984 fixed_p = !NILP (val);
1985
1986 if (fixed_p
1987 && ((EQ (val, Qheight) && width_p)
1988 || (EQ (val, Qwidth) && !width_p)))
1989 fixed_p = 0;
1990 }
233a4a2c
GM
1991 }
1992
1993 /* Can't tell if this one is resizable without looking at
1994 siblings. If all siblings are fixed-size this one is too. */
1995 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
1996 {
1997 Lisp_Object child;
1998
1999 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
2000 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2001 break;
2002
2003 if (NILP (child))
2004 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2005 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2006 break;
2007
2008 if (NILP (child))
2009 fixed_p = 1;
2010 }
2011 }
2012 else
2013 fixed_p = 1;
2014
2015 return fixed_p;
2016}
2017
2018
2019/* Return the minimum size of window W, not taking fixed-width windows
2020 into account. WIDTH_P non-zero means return the minimum width,
2021 otherwise return the minimum height. If W is a combination window,
2022 compute the minimum size from the minimum sizes of W's children. */
2023
2024static int
2025window_min_size_1 (w, width_p)
c1636aa6
GM
2026 struct window *w;
2027 int width_p;
2028{
233a4a2c 2029 struct window *c;
c1636aa6
GM
2030 int size;
2031
233a4a2c
GM
2032 if (!NILP (w->hchild))
2033 {
2034 c = XWINDOW (w->hchild);
2035 size = 0;
2036
2037 if (width_p)
2038 {
2039 /* The min width of a horizontal combination is
2040 the sum of the min widths of its children. */
2041 while (c)
2042 {
2043 size += window_min_size_1 (c, width_p);
2044 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2045 }
2046 }
2047 else
2048 {
2049 /* The min height a horizontal combination equals
2050 the maximum of all min height of its children. */
2051 while (c)
2052 {
2053 int min_size = window_min_size_1 (c, width_p);
2054 size = max (min_size, size);
2055 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2056 }
2057 }
2058 }
2059 else if (!NILP (w->vchild))
2060 {
2061 c = XWINDOW (w->vchild);
2062 size = 0;
2063
2064 if (width_p)
2065 {
2066 /* The min width of a vertical combination is
2067 the maximum of the min widths of its children. */
2068 while (c)
2069 {
2070 int min_size = window_min_size_1 (c, width_p);
2071 size = max (min_size, size);
2072 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2073 }
2074 }
2075 else
2076 {
2077 /* The min height of a vertical combination equals
2078 the sum of the min height of its children. */
2079 while (c)
2080 {
2081 size += window_min_size_1 (c, width_p);
2082 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2083 }
2084 }
2085 }
c1636aa6
GM
2086 else
2087 {
233a4a2c
GM
2088 if (width_p)
2089 size = window_min_width;
c1636aa6 2090 else
233a4a2c
GM
2091 {
2092 if (MINI_WINDOW_P (w)
2093 || (!WINDOW_WANTS_MODELINE_P (w)
045dee35 2094 && !WINDOW_WANTS_HEADER_LINE_P (w)))
233a4a2c
GM
2095 size = 1;
2096 else
2097 size = window_min_height;
2098 }
c1636aa6
GM
2099 }
2100
2101 return size;
2102}
2103
2104
233a4a2c
GM
2105/* Return the minimum size of window W, taking fixed-size windows into
2106 account. WIDTH_P non-zero means return the minimum width,
2107 otherwise return the minimum height. Set *FIXED to 1 if W is
2108 fixed-size unless FIXED is null. */
7ab12479 2109
233a4a2c
GM
2110static int
2111window_min_size (w, width_p, fixed)
2112 struct window *w;
2113 int width_p, *fixed;
2114{
2115 int size, fixed_p;
2116
2117 fixed_p = window_fixed_size_p (w, width_p, 1);
2118 if (fixed)
2119 *fixed = fixed_p;
2120
2121 if (fixed_p)
2122 size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
2123 else
2124 size = window_min_size_1 (w, width_p);
2125
2126 return size;
2127}
2128
2129
2130/* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2131 WINDOW's width. Resize WINDOW's children, if any, so that they
2132 keep their proportionate size relative to WINDOW. Propagate
2133 WINDOW's top or left edge position to children. Delete windows
2134 that become too small unless NODELETE_P is non-zero. */
2135
2136static void
2137size_window (window, size, width_p, nodelete_p)
7ab12479 2138 Lisp_Object window;
233a4a2c 2139 int size, width_p, nodelete_p;
7ab12479 2140{
233a4a2c
GM
2141 struct window *w = XWINDOW (window);
2142 struct window *c;
2143 Lisp_Object child, *forward, *sideward;
2144 int old_size, min_size;
7ab12479 2145
a481b3ea 2146 check_min_window_sizes ();
233a4a2c 2147
b5f05b50
GM
2148 /* If the window has been "too small" at one point,
2149 don't delete it for being "too small" in the future.
2150 Preserve it as long as that is at all possible. */
233a4a2c
GM
2151 if (width_p)
2152 {
2153 old_size = XFASTINT (w->width);
2154 min_size = window_min_width;
2155 }
2156 else
2157 {
2158 old_size = XFASTINT (w->height);
2159 min_size = window_min_height;
2160 }
2161
2162 if (old_size < window_min_width)
b5f05b50
GM
2163 w->too_small_ok = Qt;
2164
233a4a2c
GM
2165 /* Maybe delete WINDOW if it's too small. */
2166 if (!nodelete_p && !NILP (w->parent))
7ab12479 2167 {
233a4a2c 2168 int min_size;
b5f05b50
GM
2169
2170 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
233a4a2c 2171 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
b5f05b50 2172 else
233a4a2c 2173 min_size = width_p ? window_min_width : window_min_height;
b5f05b50 2174
233a4a2c 2175 if (size < min_size)
c1636aa6
GM
2176 {
2177 delete_window (window);
2178 return;
2179 }
7ab12479
JB
2180 }
2181
233a4a2c 2182 /* Set redisplay hints. */
d834a2e9 2183 XSETFASTINT (w->last_modified, 0);
3cd21523 2184 XSETFASTINT (w->last_overlay_modified, 0);
7ab12479 2185 windows_or_buffers_changed++;
29aeee73
RS
2186 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
2187
233a4a2c
GM
2188 if (width_p)
2189 {
2190 sideward = &w->vchild;
2191 forward = &w->hchild;
2192 XSETFASTINT (w->width, size);
2193 }
2194 else
2195 {
2196 sideward = &w->hchild;
2197 forward = &w->vchild;
2198 XSETFASTINT (w->height, size);
2199 }
2200
2201 if (!NILP (*sideward))
7ab12479 2202 {
233a4a2c 2203 for (child = *sideward; !NILP (child); child = c->next)
7ab12479 2204 {
233a4a2c
GM
2205 c = XWINDOW (child);
2206 if (width_p)
2207 c->left = w->left;
2208 else
2209 c->top = w->top;
2210 size_window (child, size, width_p, nodelete_p);
7ab12479
JB
2211 }
2212 }
233a4a2c 2213 else if (!NILP (*forward))
7ab12479 2214 {
233a4a2c
GM
2215 int fixed_size, each, extra, n;
2216 int resize_fixed_p, nfixed;
2217 int last_pos, first_pos, nchildren;
2218
2219 /* Determine the fixed-size portion of the this window, and the
2220 number of child windows. */
2221 fixed_size = nchildren = nfixed = 0;
2222 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
7ab12479
JB
2223 {
2224 c = XWINDOW (child);
233a4a2c
GM
2225 if (window_fixed_size_p (c, width_p, 0))
2226 {
2227 fixed_size += (width_p
2228 ? XFASTINT (c->width) : XFASTINT (c->height));
2229 ++nfixed;
2230 }
2231 }
7ab12479 2232
233a4a2c
GM
2233 /* If the new size is smaller than fixed_size, or if there
2234 aren't any resizable windows, allow resizing fixed-size
2235 windows. */
2236 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2237
2238 /* Compute how many lines/columns to add to each child. The
2239 value of extra takes care of rounding errors. */
2240 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2241 each = (size - old_size) / n;
2242 extra = (size - old_size) - n * each;
2243
2244 /* Compute new children heights and edge positions. */
2245 first_pos = width_p ? XFASTINT (w->left) : XFASTINT (w->top);
2246 last_pos = first_pos;
2247 for (child = *forward; !NILP (child); child = c->next)
2248 {
2249 int new_size, old_size;
2250
2251 c = XWINDOW (child);
2252 old_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2253 new_size = old_size;
7ab12479 2254
233a4a2c
GM
2255 /* The top or left edge position of this child equals the
2256 bottom or right edge of its predecessor. */
2257 if (width_p)
2258 c->left = make_number (last_pos);
2259 else
2260 c->top = make_number (last_pos);
7ab12479 2261
233a4a2c
GM
2262 /* If this child can be resized, do it. */
2263 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2264 {
2265 new_size = old_size + each + extra;
2266 extra = 0;
2267 }
2268
2269 /* Set new height. Note that size_window also propagates
2270 edge positions to children, so it's not a no-op if we
2271 didn't change the child's size. */
2272 size_window (child, new_size, width_p, 1);
2273
2274 /* Remember the bottom/right edge position of this child; it
2275 will be used to set the top/left edge of the next child. */
2276 last_pos += new_size;
7ab12479 2277 }
233a4a2c
GM
2278
2279 /* We should have covered the parent exactly with child windows. */
2280 xassert (size == last_pos - first_pos);
2281
7ab12479 2282 /* Now delete any children that became too small. */
233a4a2c
GM
2283 if (!nodelete_p)
2284 for (child = *forward; !NILP (child); child = c->next)
7ab12479 2285 {
233a4a2c
GM
2286 int child_size;
2287 c = XWINDOW (child);
2288 child_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2289 size_window (child, child_size, width_p, 0);
7ab12479
JB
2290 }
2291 }
2292}
2293
233a4a2c
GM
2294/* Set WINDOW's height to HEIGHT, and recursively change the height of
2295 WINDOW's children. NODELETE non-zero means don't delete windows
2296 that become too small in the process. (The caller should check
2297 later and do so if appropriate.) */
7ab12479 2298
5e14b1fc 2299void
233a4a2c 2300set_window_height (window, height, nodelete)
7ab12479 2301 Lisp_Object window;
233a4a2c 2302 int height;
7ab12479
JB
2303 int nodelete;
2304{
233a4a2c
GM
2305 size_window (window, height, 0, nodelete);
2306}
7ab12479 2307
7ab12479 2308
233a4a2c
GM
2309/* Set WINDOW's width to WIDTH, and recursively change the width of
2310 WINDOW's children. NODELETE non-zero means don't delete windows
2311 that become too small in the process. (The caller should check
2312 later and do so if appropriate.) */
7ab12479 2313
233a4a2c
GM
2314void
2315set_window_width (window, width, nodelete)
2316 Lisp_Object window;
2317 int width;
2318 int nodelete;
2319{
2320 size_window (window, width, 1, nodelete);
7ab12479 2321}
233a4a2c 2322
7ab12479 2323\f
1d8d96fa 2324int window_select_count;
7ab12479 2325
5b03d3c0
RS
2326Lisp_Object
2327Fset_window_buffer_unwind (obuf)
2328 Lisp_Object obuf;
2329{
2330 Fset_buffer (obuf);
2331 return Qnil;
2332}
2333
7ab12479 2334
5500c422
GM
2335/* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2336 means it's allowed to run hooks. See make_frame for a case where
2337 it's not allowed. */
7ab12479 2338
5500c422
GM
2339void
2340set_window_buffer (window, buffer, run_hooks_p)
2341 Lisp_Object window, buffer;
2342 int run_hooks_p;
2343{
2344 struct window *w = XWINDOW (window);
2345 struct buffer *b = XBUFFER (buffer);
2346 int count = specpdl_ptr - specpdl;
7ab12479
JB
2347
2348 w->buffer = buffer;
86e48436
RS
2349
2350 if (EQ (window, selected_window))
5500c422 2351 b->last_selected_window = window;
beb4e312
RS
2352
2353 /* Update time stamps of buffer display. */
5500c422
GM
2354 if (INTEGERP (b->display_count))
2355 XSETINT (b->display_count, XINT (b->display_count) + 1);
2356 b->display_time = Fcurrent_time ();
86e48436 2357
d834a2e9 2358 XSETFASTINT (w->window_end_pos, 0);
5500c422
GM
2359 XSETFASTINT (w->window_end_vpos, 0);
2360 bzero (&w->last_cursor, sizeof w->last_cursor);
5a41ab94 2361 w->window_end_valid = Qnil;
dba06815 2362 XSETFASTINT (w->hscroll, 0);
5500c422 2363 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
7ab12479 2364 set_marker_restricted (w->start,
5500c422 2365 make_number (b->last_window_start),
7ab12479
JB
2366 buffer);
2367 w->start_at_line_beg = Qnil;
e36ab06b 2368 w->force_start = Qnil;
d834a2e9 2369 XSETFASTINT (w->last_modified, 0);
3cd21523 2370 XSETFASTINT (w->last_overlay_modified, 0);
7ab12479 2371 windows_or_buffers_changed++;
5b03d3c0
RS
2372
2373 /* We must select BUFFER for running the window-scroll-functions.
2374 If WINDOW is selected, switch permanently.
2375 Otherwise, switch but go back to the ambient buffer afterward. */
7ab12479
JB
2376 if (EQ (window, selected_window))
2377 Fset_buffer (buffer);
5b03d3c0
RS
2378 /* We can't check ! NILP (Vwindow_scroll_functions) here
2379 because that might itself be a local variable. */
2380 else if (window_initialized)
2381 {
2382 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2383 Fset_buffer (buffer);
2384 }
2385
5500c422 2386 /* Set left and right marginal area width from buffer. */
cfa22082 2387 Fset_window_margins (window, b->left_margin_width, b->right_margin_width);
7ab12479 2388
5500c422
GM
2389 if (run_hooks_p)
2390 {
2391 if (! NILP (Vwindow_scroll_functions))
2392 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2393 Fmarker_position (w->start));
2394
2395 if (! NILP (Vwindow_configuration_change_hook)
2396 && ! NILP (Vrun_hooks))
2397 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2398 }
543f5fb1 2399
5b03d3c0 2400 unbind_to (count, Qnil);
5500c422 2401}
5b03d3c0 2402
5500c422
GM
2403
2404DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
2405 "Make WINDOW display BUFFER as its contents.\n\
2406BUFFER can be a buffer or buffer name.")
2407 (window, buffer)
2408 register Lisp_Object window, buffer;
2409{
2410 register Lisp_Object tem;
2411 register struct window *w = decode_window (window);
5500c422
GM
2412
2413 buffer = Fget_buffer (buffer);
2414 CHECK_BUFFER (buffer, 1);
2415
2416 if (NILP (XBUFFER (buffer)->name))
2417 error ("Attempt to display deleted buffer");
2418
2419 tem = w->buffer;
2420 if (NILP (tem))
2421 error ("Window is deleted");
2422 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
2423 is first being set up. */
2424 {
2425 if (!NILP (w->dedicated) && !EQ (tem, buffer))
2426 error ("Window is dedicated to `%s'",
2427 XSTRING (XBUFFER (tem)->name)->data);
2428
2429 unshow_buffer (w);
2430 }
2431
2432 set_window_buffer (window, buffer, 1);
7ab12479
JB
2433 return Qnil;
2434}
2435
2436DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
2437 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
beb4e312
RS
2438If WINDOW is not already selected, also make WINDOW's buffer current.\n\
2439Note that the main editor command loop\n\
2440selects the buffer of the selected window before each command.")
7ab12479
JB
2441 (window)
2442 register Lisp_Object window;
b7354ddf
RS
2443{
2444 return select_window_1 (window, 1);
2445}
2446\f
2447static Lisp_Object
2448select_window_1 (window, recordflag)
2449 register Lisp_Object window;
2450 int recordflag;
7ab12479
JB
2451{
2452 register struct window *w;
2453 register struct window *ow = XWINDOW (selected_window);
1ae1a37d 2454 struct frame *sf;
7ab12479 2455
605be8af 2456 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2457
2458 w = XWINDOW (window);
2459
265a9e55 2460 if (NILP (w->buffer))
7ab12479
JB
2461 error ("Trying to select deleted window or non-leaf window");
2462
d834a2e9 2463 XSETFASTINT (w->use_time, ++window_select_count);
7ab12479
JB
2464 if (EQ (window, selected_window))
2465 return window;
2466
596ae0cf
RS
2467 if (! NILP (ow->buffer))
2468 set_marker_both (ow->pointm, ow->buffer,
2469 BUF_PT (XBUFFER (ow->buffer)),
2470 BUF_PT_BYTE (XBUFFER (ow->buffer)));
7ab12479
JB
2471
2472 selected_window = window;
1ae1a37d
GM
2473 sf = SELECTED_FRAME ();
2474 if (XFRAME (WINDOW_FRAME (w)) != sf)
7ab12479 2475 {
44fa5b1e 2476 XFRAME (WINDOW_FRAME (w))->selected_window = window;
147a6615
RS
2477 /* Use this rather than Fhandle_switch_frame
2478 so that FRAME_FOCUS_FRAME is moved appropriately as we
2479 move around in the state where a minibuffer in a separate
2480 frame is active. */
2481 Fselect_frame (WINDOW_FRAME (w), Qnil);
7ab12479
JB
2482 }
2483 else
1ae1a37d 2484 sf->selected_window = window;
7ab12479 2485
b7354ddf
RS
2486 if (recordflag)
2487 record_buffer (w->buffer);
7ab12479
JB
2488 Fset_buffer (w->buffer);
2489
86e48436
RS
2490 XBUFFER (w->buffer)->last_selected_window = window;
2491
7ab12479
JB
2492 /* Go to the point recorded in the window.
2493 This is important when the buffer is in more
2494 than one window. It also matters when
2495 redisplay_window has altered point after scrolling,
2496 because it makes the change only in the window. */
2497 {
2498 register int new_point = marker_position (w->pointm);
2499 if (new_point < BEGV)
2500 SET_PT (BEGV);
a9c95e08 2501 else if (new_point > ZV)
7ab12479
JB
2502 SET_PT (ZV);
2503 else
2504 SET_PT (new_point);
2505 }
2506
2507 windows_or_buffers_changed++;
2508 return window;
2509}
b7354ddf 2510\f
441a127e
RS
2511/* Deiconify the frame containing the window WINDOW,
2512 unless it is the selected frame;
2513 then return WINDOW.
2514
2515 The reason for the exception for the selected frame
2516 is that it seems better not to change the selected frames visibility
2517 merely because of displaying a different buffer in it.
2518 The deiconification is useful when a buffer gets shown in
2519 another frame that you were not using lately. */
d07f802a
RS
2520
2521static Lisp_Object
2522display_buffer_1 (window)
2523 Lisp_Object window;
2524{
1ae1a37d
GM
2525 Lisp_Object frame = XWINDOW (window)->frame;
2526 FRAME_PTR f = XFRAME (frame);
2527
d07f802a 2528 FRAME_SAMPLE_VISIBILITY (f);
1ae1a37d
GM
2529
2530 if (!EQ (frame, selected_frame))
60117126
RS
2531 {
2532 if (FRAME_ICONIFIED_P (f))
1ae1a37d 2533 Fmake_frame_visible (frame);
37962e60 2534 else if (FRAME_VISIBLE_P (f))
1ae1a37d 2535 Fraise_frame (frame);
60117126 2536 }
1ae1a37d 2537
d07f802a
RS
2538 return window;
2539}
2540
4628f7a4 2541DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
0f7d64d2
GV
2542 "Returns non-nil if a buffer named BUFFER-NAME would be created specially.\n\
2543The value is actually t if the frame should be called with default frame\n\
2544parameters, and a list of frame parameters if they were specified.\n\
4628f7a4
EN
2545See `special-display-buffer-names', and `special-display-regexps'.")
2546 (buffer_name)
2547 Lisp_Object buffer_name;
2548{
2549 Lisp_Object tem;
2550
2551 CHECK_STRING (buffer_name, 1);
2552
2553 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2554 if (!NILP (tem))
2555 return Qt;
2556
2557 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2558 if (!NILP (tem))
2559 return XCDR (tem);
2560
2561 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2562 {
2563 Lisp_Object car = XCAR (tem);
2564 if (STRINGP (car)
2565 && fast_string_match (car, buffer_name) >= 0)
2566 return Qt;
2567 else if (CONSP (car)
2568 && STRINGP (XCAR (car))
2569 && fast_string_match (XCAR (car), buffer_name) >= 0)
0057b00a 2570 return XCDR (car);
4628f7a4
EN
2571 }
2572 return Qnil;
2573}
2574
2575DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
0f7d64d2 2576 "Returns non-nil if a new buffer named BUFFER-NAME would use the same window.\n\
4628f7a4
EN
2577See `same-window-buffer-names' and `same-window-regexps'.")
2578 (buffer_name)
2579 Lisp_Object buffer_name;
2580{
2581 Lisp_Object tem;
2582
2583 CHECK_STRING (buffer_name, 1);
2584
2585 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2586 if (!NILP (tem))
2587 return Qt;
2588
2589 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2590 if (!NILP (tem))
2591 return Qt;
2592
2593 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
2594 {
2595 Lisp_Object car = XCAR (tem);
2596 if (STRINGP (car)
2597 && fast_string_match (car, buffer_name) >= 0)
2598 return Qt;
2599 else if (CONSP (car)
2600 && STRINGP (XCAR (car))
2601 && fast_string_match (XCAR (car), buffer_name) >= 0)
2602 return Qt;
2603 }
2604 return Qnil;
2605}
2606
53f76081
RS
2607 /* Use B so the default is (other-buffer). */
2608DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
2609 "BDisplay buffer: \nP",
7ab12479
JB
2610 "Make BUFFER appear in some window but don't select it.\n\
2611BUFFER can be a buffer or a buffer name.\n\
2612If BUFFER is shown already in some window, just use that one,\n\
2613unless the window is the selected window and the optional second\n\
46d3268a 2614argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
5141b901 2615If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
5abcf432
RS
2616Returns the window displaying BUFFER.\n\
2617\n\
2618The variables `special-display-buffer-names', `special-display-regexps',\n\
2619`same-window-buffer-names', and `same-window-regexps' customize how certain\n\
53f76081
RS
2620buffer names are handled.\n\
2621\n\
2622If optional argument FRAME is `visible', search all visible frames.\n\
2623If FRAME is 0, search all visible and iconified frames.\n\
2624If FRAME is t, search all frames.\n\
2625If FRAME is a frame, search only that frame.\n\
2626If FRAME is nil, search only the selected frame\n\
2627 (actually the last nonminibuffer frame),\n\
2628 unless `pop-up-frames' is non-nil,\n\
2629 which means search visible and iconified frames.")
2630 (buffer, not_this_window, frame)
2631 register Lisp_Object buffer, not_this_window, frame;
7ab12479 2632{
aee631c2 2633 register Lisp_Object window, tem, swp;
1ae1a37d 2634 struct frame *f;
7ab12479 2635
aee631c2 2636 swp = Qnil;
7ab12479
JB
2637 buffer = Fget_buffer (buffer);
2638 CHECK_BUFFER (buffer, 0);
2639
265a9e55 2640 if (!NILP (Vdisplay_buffer_function))
7ab12479
JB
2641 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
2642
265a9e55 2643 if (NILP (not_this_window)
7ab12479 2644 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
d07f802a 2645 return display_buffer_1 (selected_window);
7ab12479 2646
855d8627
RS
2647 /* See if the user has specified this buffer should appear
2648 in the selected window. */
2649 if (NILP (not_this_window))
2650 {
aee631c2
RS
2651 swp = Fsame_window_p (XBUFFER (buffer)->name);
2652 if (!NILP (swp) && !no_switch_window (selected_window))
c63dc4a2
RS
2653 {
2654 Fswitch_to_buffer (buffer, Qnil);
d07f802a 2655 return display_buffer_1 (selected_window);
c63dc4a2 2656 }
855d8627
RS
2657 }
2658
e8edb3ae 2659 /* If pop_up_frames,
73dc5198
KH
2660 look for a window showing BUFFER on any visible or iconified frame.
2661 Otherwise search only the current frame. */
53f76081
RS
2662 if (! NILP (frame))
2663 tem = frame;
2664 else if (pop_up_frames || last_nonminibuf_frame == 0)
73dc5198
KH
2665 XSETFASTINT (tem, 0);
2666 else
73dc5198
KH
2667 XSETFRAME (tem, last_nonminibuf_frame);
2668 window = Fget_buffer_window (buffer, tem);
265a9e55
JB
2669 if (!NILP (window)
2670 && (NILP (not_this_window) || !EQ (window, selected_window)))
f812f9c6 2671 {
d07f802a 2672 return display_buffer_1 (window);
f812f9c6 2673 }
7ab12479 2674
a90712c2 2675 /* Certain buffer names get special handling. */
aee631c2 2676 if (!NILP (Vspecial_display_function) && NILP (swp))
a90712c2 2677 {
4628f7a4
EN
2678 tem = Fspecial_display_p (XBUFFER (buffer)->name);
2679 if (EQ (tem, Qt))
a90712c2 2680 return call1 (Vspecial_display_function, buffer);
4628f7a4
EN
2681 if (CONSP (tem))
2682 return call2 (Vspecial_display_function, buffer, tem);
a90712c2
RS
2683 }
2684
44fa5b1e
JB
2685 /* If there are no frames open that have more than a minibuffer,
2686 we need to create a new frame. */
2687 if (pop_up_frames || last_nonminibuf_frame == 0)
7ab12479 2688 {
a90712c2 2689 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
7ab12479 2690 Fset_window_buffer (window, buffer);
d07f802a 2691 return display_buffer_1 (window);
7ab12479 2692 }
7ab12479 2693
1ae1a37d 2694 f = SELECTED_FRAME ();
43bad991 2695 if (pop_up_windows
1ae1a37d 2696 || FRAME_MINIBUF_ONLY_P (f)
cee67da9
RS
2697 /* If the current frame is a special display frame,
2698 don't try to reuse its windows. */
1ae1a37d 2699 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
7ab12479 2700 {
12cae7c0
KH
2701 Lisp_Object frames;
2702
37962e60 2703 frames = Qnil;
1ae1a37d 2704 if (FRAME_MINIBUF_ONLY_P (f))
74112613 2705 XSETFRAME (frames, last_nonminibuf_frame);
7ab12479
JB
2706 /* Don't try to create a window if would get an error */
2707 if (split_height_threshold < window_min_height << 1)
2708 split_height_threshold = window_min_height << 1;
2709
cee67da9
RS
2710 /* Note that both Fget_largest_window and Fget_lru_window
2711 ignore minibuffers and dedicated windows.
2712 This means they can return nil. */
7ab12479 2713
cee67da9
RS
2714 /* If the frame we would try to split cannot be split,
2715 try other frames. */
1ae1a37d 2716 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
cee67da9
RS
2717 {
2718 /* Try visible frames first. */
2719 window = Fget_largest_window (Qvisible);
2720 /* If that didn't work, try iconified frames. */
2721 if (NILP (window))
2722 window = Fget_largest_window (make_number (0));
2723 if (NILP (window))
2724 window = Fget_largest_window (Qt);
2725 }
2726 else
2727 window = Fget_largest_window (frames);
2728
92cca945
RS
2729 /* If we got a tall enough full-width window that can be split,
2730 split it. */
265a9e55 2731 if (!NILP (window)
92cca945 2732 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
7ab12479 2733 && window_height (window) >= split_height_threshold
111e5992 2734 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
7ab12479
JB
2735 window = Fsplit_window (window, Qnil, Qnil);
2736 else
2737 {
1942f68f
RS
2738 Lisp_Object upper, lower, other;
2739
44fa5b1e 2740 window = Fget_lru_window (frames);
92cca945
RS
2741 /* If the LRU window is selected, and big enough,
2742 and can be split, split it. */
cee67da9 2743 if (!NILP (window)
92cca945 2744 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
cee67da9
RS
2745 && (EQ (window, selected_window)
2746 || EQ (XWINDOW (window)->parent, Qnil))
7ab12479
JB
2747 && window_height (window) >= window_min_height << 1)
2748 window = Fsplit_window (window, Qnil, Qnil);
cee67da9 2749 /* If Fget_lru_window returned nil, try other approaches. */
48d9379d 2750
cee67da9 2751 /* Try visible frames first. */
48d9379d
RS
2752 if (NILP (window))
2753 window = Fget_buffer_window (buffer, Qvisible);
cee67da9
RS
2754 if (NILP (window))
2755 window = Fget_largest_window (Qvisible);
2756 /* If that didn't work, try iconified frames. */
48d9379d
RS
2757 if (NILP (window))
2758 window = Fget_buffer_window (buffer, make_number (0));
cee67da9
RS
2759 if (NILP (window))
2760 window = Fget_largest_window (make_number (0));
2761 /* Try invisible frames. */
48d9379d
RS
2762 if (NILP (window))
2763 window = Fget_buffer_window (buffer, Qt);
cee67da9
RS
2764 if (NILP (window))
2765 window = Fget_largest_window (Qt);
2766 /* As a last resort, make a new frame. */
2767 if (NILP (window))
2768 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
1942f68f
RS
2769 /* If window appears above or below another,
2770 even out their heights. */
cac66e4f 2771 other = upper = lower = Qnil;
1942f68f
RS
2772 if (!NILP (XWINDOW (window)->prev))
2773 other = upper = XWINDOW (window)->prev, lower = window;
2774 if (!NILP (XWINDOW (window)->next))
2775 other = lower = XWINDOW (window)->next, upper = window;
2776 if (!NILP (other)
2777 /* Check that OTHER and WINDOW are vertically arrayed. */
296b535c
KH
2778 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
2779 && (XFASTINT (XWINDOW (other)->height)
2780 > XFASTINT (XWINDOW (window)->height)))
1942f68f 2781 {
296b535c
KH
2782 int total = (XFASTINT (XWINDOW (other)->height)
2783 + XFASTINT (XWINDOW (window)->height));
8d77c0c8
KH
2784 Lisp_Object old_selected_window;
2785 old_selected_window = selected_window;
1942f68f 2786
8d77c0c8 2787 selected_window = upper;
296b535c
KH
2788 change_window_height ((total / 2
2789 - XFASTINT (XWINDOW (upper)->height)),
2790 0);
1942f68f
RS
2791 selected_window = old_selected_window;
2792 }
7ab12479
JB
2793 }
2794 }
2795 else
2796 window = Fget_lru_window (Qnil);
2797
2798 Fset_window_buffer (window, buffer);
d07f802a 2799 return display_buffer_1 (window);
7ab12479
JB
2800}
2801
2802void
2803temp_output_buffer_show (buf)
2804 register Lisp_Object buf;
2805{
2806 register struct buffer *old = current_buffer;
2807 register Lisp_Object window;
2808 register struct window *w;
2809
bccd3dd1
RS
2810 XBUFFER (buf)->directory = current_buffer->directory;
2811
7ab12479 2812 Fset_buffer (buf);
c6367666 2813 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
7ab12479
JB
2814 BEGV = BEG;
2815 ZV = Z;
2816 SET_PT (BEG);
b1599b4c 2817 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
7ab12479
JB
2818 set_buffer_internal (old);
2819
2820 if (!EQ (Vtemp_buffer_show_function, Qnil))
2821 call1 (Vtemp_buffer_show_function, buf);
2822 else
2823 {
53f76081 2824 window = Fdisplay_buffer (buf, Qnil, Qnil);
7ab12479 2825
1ae1a37d 2826 if (!EQ (XWINDOW (window)->frame, selected_frame))
44fa5b1e 2827 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
7ab12479
JB
2828 Vminibuf_scroll_window = window;
2829 w = XWINDOW (window);
d834a2e9 2830 XSETFASTINT (w->hscroll, 0);
b73ea88e
RS
2831 set_marker_restricted_both (w->start, buf, 1, 1);
2832 set_marker_restricted_both (w->pointm, buf, 1, 1);
a58ec57d 2833
beb4e312
RS
2834 /* Run temp-buffer-show-hook, with the chosen window selected
2835 and it sbuffer current. */
f52cca03 2836 if (!NILP (Vrun_hooks))
2cccc823 2837 {
f52cca03
RS
2838 Lisp_Object tem;
2839 tem = Fboundp (Qtemp_buffer_show_hook);
2cccc823
RS
2840 if (!NILP (tem))
2841 {
f52cca03
RS
2842 tem = Fsymbol_value (Qtemp_buffer_show_hook);
2843 if (!NILP (tem))
2844 {
2845 int count = specpdl_ptr - specpdl;
b7354ddf
RS
2846 Lisp_Object prev_window;
2847 prev_window = selected_window;
2cccc823 2848
f52cca03 2849 /* Select the window that was chosen, for running the hook. */
65a04b96 2850 record_unwind_protect (Fselect_window, prev_window);
b7354ddf 2851 select_window_1 (window, 0);
beb4e312 2852 Fset_buffer (w->buffer);
f52cca03 2853 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
b7354ddf 2854 select_window_1 (prev_window, 0);
f52cca03
RS
2855 unbind_to (count, Qnil);
2856 }
2cccc823
RS
2857 }
2858 }
2859 }
7ab12479
JB
2860}
2861\f
dfcf069d 2862static void
7ab12479
JB
2863make_dummy_parent (window)
2864 Lisp_Object window;
2865{
cffec418 2866 Lisp_Object new;
7ab12479 2867 register struct window *o, *p;
cffec418
KH
2868 register struct Lisp_Vector *vec;
2869 int i;
7ab12479 2870
cffec418
KH
2871 o = XWINDOW (window);
2872 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
2873 for (i = 0; i < VECSIZE (struct window); ++i)
2874 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
2875 vec->size = VECSIZE (struct window);
2876 p = (struct window *)vec;
2877 XSETWINDOW (new, p);
7ab12479 2878
d834a2e9 2879 XSETFASTINT (p->sequence_number, ++sequence_number);
7ab12479
JB
2880
2881 /* Put new into window structure in place of window */
2882 replace_window (window, new);
2883
2884 o->next = Qnil;
2885 o->prev = Qnil;
2886 o->vchild = Qnil;
2887 o->hchild = Qnil;
2888 o->parent = new;
2889
2890 p->start = Qnil;
2891 p->pointm = Qnil;
2892 p->buffer = Qnil;
2893}
2894
2895DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
2896 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
2897WINDOW defaults to selected one and SIZE to half its size.\n\
77ae0fe3 2898If optional third arg HORFLAG is non-nil, split side by side\n\
10f96191
RS
2899and put SIZE columns in the first of the pair. In that case,\n\
2900SIZE includes that window's scroll bar, or the divider column to its right.")
77ae0fe3
KH
2901 (window, size, horflag)
2902 Lisp_Object window, size, horflag;
7ab12479
JB
2903{
2904 register Lisp_Object new;
2905 register struct window *o, *p;
c0807608 2906 FRAME_PTR fo;
77ae0fe3 2907 register int size_int;
7ab12479 2908
265a9e55 2909 if (NILP (window))
7ab12479
JB
2910 window = selected_window;
2911 else
605be8af 2912 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2913
2914 o = XWINDOW (window);
c0807608 2915 fo = XFRAME (WINDOW_FRAME (o));
7ab12479 2916
77ae0fe3 2917 if (NILP (size))
7ab12479 2918 {
265a9e55 2919 if (!NILP (horflag))
c0807608 2920 /* Calculate the size of the left-hand window, by dividing
25b33244
KH
2921 the usable space in columns by two.
2922 We round up, since the left-hand window may include
2923 a dividing line, while the right-hand may not. */
2924 size_int = (XFASTINT (o->width) + 1) >> 1;
7ab12479 2925 else
77ae0fe3 2926 size_int = XFASTINT (o->height) >> 1;
7ab12479
JB
2927 }
2928 else
2929 {
77ae0fe3
KH
2930 CHECK_NUMBER (size, 1);
2931 size_int = XINT (size);
7ab12479
JB
2932 }
2933
2934 if (MINI_WINDOW_P (o))
2935 error ("Attempt to split minibuffer window");
233a4a2c
GM
2936 else if (window_fixed_size_p (o, !NILP (horflag), 0))
2937 error ("Attempt to split fixed-size window");
7ab12479 2938
a481b3ea 2939 check_min_window_sizes ();
7ab12479 2940
265a9e55 2941 if (NILP (horflag))
7ab12479 2942 {
77ae0fe3
KH
2943 if (size_int < window_min_height)
2944 error ("Window height %d too small (after splitting)", size_int);
2945 if (size_int + window_min_height > XFASTINT (o->height))
37962e60 2946 error ("Window height %d too small (after splitting)",
77ae0fe3 2947 XFASTINT (o->height) - size_int);
265a9e55
JB
2948 if (NILP (o->parent)
2949 || NILP (XWINDOW (o->parent)->vchild))
7ab12479
JB
2950 {
2951 make_dummy_parent (window);
2952 new = o->parent;
2953 XWINDOW (new)->vchild = window;
2954 }
2955 }
2956 else
2957 {
77ae0fe3
KH
2958 if (size_int < window_min_width)
2959 error ("Window width %d too small (after splitting)", size_int);
a59fed7e
RS
2960
2961 if (size_int + window_min_width > XFASTINT (o->width))
37962e60 2962 error ("Window width %d too small (after splitting)",
a59fed7e 2963 XFASTINT (o->width) - size_int);
265a9e55
JB
2964 if (NILP (o->parent)
2965 || NILP (XWINDOW (o->parent)->hchild))
7ab12479
JB
2966 {
2967 make_dummy_parent (window);
2968 new = o->parent;
2969 XWINDOW (new)->hchild = window;
2970 }
2971 }
2972
2973 /* Now we know that window's parent is a vertical combination
2974 if we are dividing vertically, or a horizontal combination
2975 if we are making side-by-side windows */
2976
2977 windows_or_buffers_changed++;
c0807608 2978 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
7ab12479
JB
2979 new = make_window ();
2980 p = XWINDOW (new);
2981
44fa5b1e 2982 p->frame = o->frame;
7ab12479 2983 p->next = o->next;
265a9e55 2984 if (!NILP (p->next))
7ab12479
JB
2985 XWINDOW (p->next)->prev = new;
2986 p->prev = window;
2987 o->next = new;
2988 p->parent = o->parent;
2989 p->buffer = Qt;
5500c422
GM
2990 p->window_end_valid = Qnil;
2991 bzero (&p->last_cursor, sizeof p->last_cursor);
7ab12479 2992
44fa5b1e 2993 /* Apportion the available frame space among the two new windows */
7ab12479 2994
265a9e55 2995 if (!NILP (horflag))
7ab12479
JB
2996 {
2997 p->height = o->height;
2998 p->top = o->top;
a59fed7e 2999 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
77ae0fe3
KH
3000 XSETFASTINT (o->width, size_int);
3001 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
7ab12479
JB
3002 }
3003 else
3004 {
3005 p->left = o->left;
3006 p->width = o->width;
77ae0fe3
KH
3007 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
3008 XSETFASTINT (o->height, size_int);
3009 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
7ab12479
JB
3010 }
3011
5500c422
GM
3012 /* Adjust glyph matrices. */
3013 adjust_glyphs (fo);
543f5fb1 3014 Fset_window_buffer (new, o->buffer);
7ab12479
JB
3015 return new;
3016}
3017\f
3018DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3019 "Make current window ARG lines bigger.\n\
3020From program, optional second arg non-nil means grow sideways ARG columns.")
413430c5
EN
3021 (arg, side)
3022 register Lisp_Object arg, side;
7ab12479 3023{
413430c5
EN
3024 CHECK_NUMBER (arg, 0);
3025 change_window_height (XINT (arg), !NILP (side));
543f5fb1
RS
3026
3027 if (! NILP (Vwindow_configuration_change_hook))
3028 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3029
7ab12479
JB
3030 return Qnil;
3031}
3032
3033DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3034 "Make current window ARG lines smaller.\n\
413430c5
EN
3035From program, optional second arg non-nil means shrink sideways arg columns.")
3036 (arg, side)
3037 register Lisp_Object arg, side;
7ab12479 3038{
413430c5
EN
3039 CHECK_NUMBER (arg, 0);
3040 change_window_height (-XINT (arg), !NILP (side));
543f5fb1
RS
3041
3042 if (! NILP (Vwindow_configuration_change_hook))
3043 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3044
7ab12479
JB
3045 return Qnil;
3046}
3047
3048int
3049window_height (window)
3050 Lisp_Object window;
3051{
3052 register struct window *p = XWINDOW (window);
3053 return XFASTINT (p->height);
3054}
3055
3056int
3057window_width (window)
3058 Lisp_Object window;
3059{
3060 register struct window *p = XWINDOW (window);
3061 return XFASTINT (p->width);
3062}
3063
c1636aa6 3064
7ab12479 3065#define CURBEG(w) \
05c2896a 3066 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
7ab12479
JB
3067
3068#define CURSIZE(w) \
05c2896a 3069 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
7ab12479 3070
233a4a2c
GM
3071
3072/* Enlarge selected_window by DELTA. WIDTHFLAG non-zero means
3073 increase its width. Siblings of the selected window are resized to
3074 fullfil the size request. If they become too small in the process,
3075 they will be deleted. */
7ab12479 3076
5e14b1fc 3077void
7ab12479 3078change_window_height (delta, widthflag)
233a4a2c 3079 int delta, widthflag;
7ab12479 3080{
233a4a2c
GM
3081 Lisp_Object parent, window, next, prev;
3082 struct window *p;
3083 int *sizep, maximum;
5e14b1fc
AS
3084 int (*sizefun) P_ ((Lisp_Object))
3085 = widthflag ? window_width : window_height;
233a4a2c 3086 void (*setsizefun) P_ ((Lisp_Object, int, int))
5e14b1fc 3087 = (widthflag ? set_window_width : set_window_height);
7ab12479 3088
233a4a2c
GM
3089 /* Check values of window_min_width and window_min_height for
3090 validity. */
a481b3ea 3091 check_min_window_sizes ();
7ab12479 3092
233a4a2c 3093 /* Give up if this window cannot be resized. */
7ab12479 3094 window = selected_window;
233a4a2c
GM
3095 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3096 error ("Window is not resizable");
3097
3098 /* Find the parent of the selected window. */
7ab12479
JB
3099 while (1)
3100 {
3101 p = XWINDOW (window);
3102 parent = p->parent;
233a4a2c 3103
265a9e55 3104 if (NILP (parent))
7ab12479
JB
3105 {
3106 if (widthflag)
3107 error ("No other window to side of this one");
3108 break;
3109 }
233a4a2c
GM
3110
3111 if (widthflag
3112 ? !NILP (XWINDOW (parent)->hchild)
265a9e55 3113 : !NILP (XWINDOW (parent)->vchild))
7ab12479 3114 break;
233a4a2c 3115
7ab12479
JB
3116 window = parent;
3117 }
3118
05c2896a 3119 sizep = &CURSIZE (window);
7ab12479 3120
7ab12479
JB
3121 {
3122 register int maxdelta;
7ab12479 3123
265a9e55 3124 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
c1636aa6
GM
3125 : !NILP (p->next) ? ((*sizefun) (p->next)
3126 - window_min_size (XWINDOW (p->next),
233a4a2c 3127 widthflag, 0))
c1636aa6
GM
3128 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3129 - window_min_size (XWINDOW (p->prev),
233a4a2c 3130 widthflag, 0))
44fa5b1e
JB
3131 /* This is a frame with only one window, a minibuffer-only
3132 or a minibufferless frame. */
d5783c40 3133 : (delta = 0));
7ab12479
JB
3134
3135 if (delta > maxdelta)
3136 /* This case traps trying to make the minibuffer
44fa5b1e
JB
3137 the full frame, or make the only window aside from the
3138 minibuffer the full frame. */
7ab12479 3139 delta = maxdelta;
6b54027b 3140 }
d5783c40 3141
233a4a2c 3142 if (*sizep + delta < window_min_size (XWINDOW (window), widthflag, 0))
6b54027b 3143 {
543f5fb1 3144 delete_window (window);
d5783c40 3145 return;
6b54027b
RS
3146 }
3147
3148 if (delta == 0)
3149 return;
7ab12479 3150
db98a733
RS
3151 /* Find the total we can get from other siblings. */
3152 maximum = 0;
3153 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
c1636aa6 3154 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
233a4a2c 3155 widthflag, 0);
db98a733 3156 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
c1636aa6 3157 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
233a4a2c 3158 widthflag, 0);
db98a733
RS
3159
3160 /* If we can get it all from them, do so. */
c6b530ed 3161 if (delta <= maximum)
7ab12479 3162 {
db98a733
RS
3163 Lisp_Object first_unaffected;
3164 Lisp_Object first_affected;
233a4a2c 3165 int fixed_p;
db98a733
RS
3166
3167 next = p->next;
3168 prev = p->prev;
3169 first_affected = window;
3170 /* Look at one sibling at a time,
3171 moving away from this window in both directions alternately,
3172 and take as much as we can get without deleting that sibling. */
233a4a2c 3173 while (delta != 0 && (!NILP (next) || !NILP (prev)))
db98a733 3174 {
db98a733
RS
3175 if (! NILP (next))
3176 {
c1636aa6 3177 int this_one = ((*sizefun) (next)
233a4a2c
GM
3178 - window_min_size (XWINDOW (next),
3179 widthflag, &fixed_p));
3180 if (!fixed_p)
3181 {
3182 if (this_one > delta)
3183 this_one = delta;
3184
3185 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3186 (*setsizefun) (window, *sizep + this_one, 0);
db98a733 3187
233a4a2c
GM
3188 delta -= this_one;
3189 }
3190
db98a733
RS
3191 next = XWINDOW (next)->next;
3192 }
233a4a2c 3193
db98a733
RS
3194 if (delta == 0)
3195 break;
233a4a2c 3196
db98a733
RS
3197 if (! NILP (prev))
3198 {
c1636aa6 3199 int this_one = ((*sizefun) (prev)
233a4a2c
GM
3200 - window_min_size (XWINDOW (prev),
3201 widthflag, &fixed_p));
3202 if (!fixed_p)
3203 {
3204 if (this_one > delta)
3205 this_one = delta;
3206
3207 first_affected = prev;
3208
3209 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3210 (*setsizefun) (window, *sizep + this_one, 0);
3211
3212 delta -= this_one;
3213 }
3214
db98a733
RS
3215 prev = XWINDOW (prev)->prev;
3216 }
3217 }
3218
233a4a2c
GM
3219 xassert (delta == 0);
3220
db98a733
RS
3221 /* Now recalculate the edge positions of all the windows affected,
3222 based on the new sizes. */
3223 first_unaffected = next;
3224 prev = first_affected;
3225 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3226 prev = next, next = XWINDOW (next)->next)
3227 {
3228 CURBEG (next) = CURBEG (prev) + (*sizefun) (prev);
3229 /* This does not change size of NEXT,
3230 but it propagates the new top edge to its children */
3231 (*setsizefun) (next, (*sizefun) (next), 0);
3232 }
7ab12479
JB
3233 }
3234 else
3235 {
3236 register int delta1;
3237 register int opht = (*sizefun) (parent);
3238
3239 /* If trying to grow this window to or beyond size of the parent,
3240 make delta1 so big that, on shrinking back down,
3241 all the siblings end up with less than one line and are deleted. */
3242 if (opht <= *sizep + delta)
3243 delta1 = opht * opht * 2;
7ab12479 3244 else
233a4a2c
GM
3245 {
3246 /* Otherwise, make delta1 just right so that if we add
3247 delta1 lines to this window and to the parent, and then
3248 shrink the parent back to its original size, the new
3249 proportional size of this window will increase by delta.
3250
3251 The function size_window will compute the new height h'
3252 of the window from delta1 as:
3253
3254 e = delta1/n
3255 x = delta1 - delta1/n * n for the 1st resizable child
3256 h' = h + e + x
3257
3258 where n is the number of children that can be resized.
3259 We can ignore x by choosing a delta1 that is a multiple of
3260 n. We want the height of this window to come out as
3261
3262 h' = h + delta
3263
3264 So, delta1 must be
3265
3266 h + e = h + delta
3267 delta1/n = delta
3268 delta1 = n * delta.
3269
3270 The number of children n rquals the number of resizable
3271 children of this window + 1 because we know window itself
3272 is resizable (otherwise we would have signalled an error. */
3273
3274 struct window *w = XWINDOW (window);
3275 Lisp_Object s;
3276 int n = 1;
3277
3278 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3279 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3280 ++n;
3281 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3282 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3283 ++n;
3284
3285 delta1 = n * delta;
3286 }
7ab12479
JB
3287
3288 /* Add delta1 lines or columns to this window, and to the parent,
3289 keeping things consistent while not affecting siblings. */
05c2896a 3290 CURSIZE (parent) = opht + delta1;
7ab12479
JB
3291 (*setsizefun) (window, *sizep + delta1, 0);
3292
3293 /* Squeeze out delta1 lines or columns from our parent,
3294 shriking this window and siblings proportionately.
3295 This brings parent back to correct size.
3296 Delta1 was calculated so this makes this window the desired size,
3297 taking it all out of the siblings. */
3298 (*setsizefun) (parent, opht, 0);
3299 }
3300
d834a2e9 3301 XSETFASTINT (p->last_modified, 0);
3cd21523 3302 XSETFASTINT (p->last_overlay_modified, 0);
5500c422
GM
3303
3304 /* Adjust glyph matrices. */
3305 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
7ab12479 3306}
c1636aa6 3307
7ab12479
JB
3308#undef CURBEG
3309#undef CURSIZE
3310
5500c422
GM
3311
3312/* Mark window cursors off for all windows in the window tree rooted
3313 at W by setting their phys_cursor_on_p flag to zero. Called from
3314 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3315 the frame are cleared. */
3316
3317void
3318mark_window_cursors_off (w)
3319 struct window *w;
3320{
3321 while (w)
3322 {
3323 if (!NILP (w->hchild))
3324 mark_window_cursors_off (XWINDOW (w->hchild));
3325 else if (!NILP (w->vchild))
3326 mark_window_cursors_off (XWINDOW (w->vchild));
3327 else
3328 w->phys_cursor_on_p = 0;
3329
3330 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3331 }
3332}
3333
3334
7ab12479
JB
3335/* Return number of lines of text (not counting mode line) in W. */
3336
3337int
3338window_internal_height (w)
3339 struct window *w;
3340{
3341 int ht = XFASTINT (w->height);
3342
3343 if (MINI_WINDOW_P (w))
3344 return ht;
3345
265a9e55
JB
3346 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
3347 || !NILP (w->next) || !NILP (w->prev)
44fa5b1e 3348 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
7ab12479
JB
3349 return ht - 1;
3350
3351 return ht;
3352}
3353
535e0b8e
JB
3354
3355/* Return the number of columns in W.
a3c87d4e 3356 Don't count columns occupied by scroll bars or the vertical bar
535e0b8e 3357 separating W from the sibling to its right. */
5500c422 3358
535e0b8e
JB
3359int
3360window_internal_width (w)
3361 struct window *w;
3362{
5500c422 3363 struct frame *f = XFRAME (WINDOW_FRAME (w));
535e0b8e
JB
3364 int width = XINT (w->width);
3365
a3c87d4e 3366 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5500c422
GM
3367 /* Scroll bars occupy a few columns. */
3368 width -= FRAME_SCROLL_BAR_COLS (f);
3369 else if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
3370 /* The column of `|' characters separating side-by-side windows
3371 occupies one column only. */
3372 width -= 1;
3373
3374 /* On window-systems, areas to the left and right of the window
3375 are used to display bitmaps there. */
3376 if (FRAME_WINDOW_P (f))
b46dfc64 3377 width -= FRAME_FLAGS_AREA_COLS (f);
111e5992
RS
3378
3379 return width;
535e0b8e
JB
3380}
3381
5500c422
GM
3382\f
3383/************************************************************************
3384 Window Scrolling
3385 ***********************************************************************/
535e0b8e 3386
5500c422
GM
3387/* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
3388 one screen-full, which is defined as the height of the window minus
3389 next_screen_context_lines. If WHOLE is zero, scroll up N lines
3390 instead. Negative values of N mean scroll down. NOERROR non-zero
3391 means don't signal an error if we try to move over BEGV or ZV,
3392 respectively. */
7ab12479 3393
101d1605
RS
3394static void
3395window_scroll (window, n, whole, noerror)
7ab12479
JB
3396 Lisp_Object window;
3397 int n;
101d1605 3398 int whole;
f8026fd8 3399 int noerror;
5500c422
GM
3400{
3401 /* If we must, use the pixel-based version which is much slower than
3402 the line-based one but can handle varying line heights. */
3403 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
3404 window_scroll_pixel_based (window, n, whole, noerror);
3405 else
3406 window_scroll_line_based (window, n, whole, noerror);
3407}
3408
3409
3410/* Implementation of window_scroll that works based on pixel line
3411 heights. See the comment of window_scroll for parameter
3412 descriptions. */
3413
3414static void
3415window_scroll_pixel_based (window, n, whole, noerror)
3416 Lisp_Object window;
3417 int n;
3418 int whole;
3419 int noerror;
3420{
3421 struct it it;
3422 struct window *w = XWINDOW (window);
3423 struct text_pos start;
3424 Lisp_Object tem;
3425 int this_scroll_margin;
3426 int preserve_y;
3427
3428 SET_TEXT_POS_FROM_MARKER (start, w->start);
3429
3430 /* If PT is not visible in WINDOW, move back one half of
3431 the screen. */
3432 XSETFASTINT (tem, PT);
3433 tem = Fpos_visible_in_window_p (tem, window);
3434 if (NILP (tem))
3435 {
3436 /* Move backward half the height of the window. Performance note:
3437 vmotion used here is about 10% faster, but would give wrong
3438 results for variable height lines. */
3439 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3440 it.current_y = it.last_visible_y;
3441 move_it_vertically (&it, -it.last_visible_y / 2);
3442
3443 /* The function move_iterator_vertically may move over more than
3444 the specified y-distance. If it->w is small, e.g. a
3445 mini-buffer window, we may end up in front of the window's
3446 display area. This is the case when Start displaying at the
3447 start of the line containing PT in this case. */
3448 if (it.current_y <= 0)
3449 {
3450 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3451 move_it_vertically (&it, 0);
3452 it.current_y = 0;
3453 }
3454
3455 start = it.current.pos;
3456 }
3457
3458 /* If scroll_preserve_screen_position is non-zero, we try to set
3459 point in the same window line as it is now, so get that line. */
3460 if (!NILP (Vscroll_preserve_screen_position))
3461 {
3462 start_display (&it, w, start);
3463 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3464 preserve_y = it.current_y;
3465 }
3466 else
3467 preserve_y = -1;
3468
3469 /* Move iterator it from start the specified distance forward or
3470 backward. The result is the new window start. */
3471 start_display (&it, w, start);
3472 if (whole)
3473 {
3474 int screen_full = (it.last_visible_y
3475 - next_screen_context_lines * CANON_Y_UNIT (it.f));
3476 int direction = n < 0 ? -1 : 1;
3477 move_it_vertically (&it, direction * screen_full);
3478 }
3479 else
3480 move_it_by_lines (&it, n, 1);
3481
3482 /* End if we end up at ZV or BEGV. */
3483 if ((n > 0 && IT_CHARPOS (it) == ZV)
3484 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
3485 {
3486 if (noerror)
3487 return;
3488 else if (IT_CHARPOS (it) == ZV)
3489 Fsignal (Qend_of_buffer, Qnil);
3490 else
3491 Fsignal (Qbeginning_of_buffer, Qnil);
3492 }
3493
3494 /* Set the window start, and set up the window for redisplay. */
3495 set_marker_restricted (w->start, make_number (IT_CHARPOS (it)), w->buffer);
3496 w->start_at_line_beg = Fbolp ();
3497 w->update_mode_line = Qt;
3498 XSETFASTINT (w->last_modified, 0);
3499 XSETFASTINT (w->last_overlay_modified, 0);
3500 /* Set force_start so that redisplay_window will run the
3501 window-scroll-functions. */
3502 w->force_start = Qt;
3503
3504 it.current_y = it.vpos = 0;
3505
3506 /* Preserve the screen position if we must. */
3507 if (preserve_y >= 0)
3508 {
3509 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
3510 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3511 }
3512 else
3513 {
3514 /* Move PT out of scroll margins. */
3515 this_scroll_margin = max (0, scroll_margin);
3516 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
3517 this_scroll_margin *= CANON_Y_UNIT (it.f);
3518
3519 if (n > 0)
3520 {
3521 /* We moved the window start towards ZV, so PT may be now
3522 in the scroll margin at the top. */
3523 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3524 while (it.current_y < this_scroll_margin)
3525 move_it_by_lines (&it, 1, 1);
3526 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3527 }
3528 else if (n < 0)
3529 {
3530 /* We moved the window start towards BEGV, so PT may be now
3531 in the scroll margin at the bottom. */
3532 move_it_to (&it, PT, -1,
3533 it.last_visible_y - this_scroll_margin - 1, -1,
3534 MOVE_TO_POS | MOVE_TO_Y);
3535
3536 /* Don't put point on a partially visible line at the end. */
3537 if (it.current_y + it.max_ascent + it.max_descent
3538 > it.last_visible_y)
3539 move_it_by_lines (&it, -1, 0);
3540
3541 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3542 }
3543 }
3544}
3545
3546
3547/* Implementation of window_scroll that works based on screen lines.
3548 See the comment of window_scroll for parameter descriptions. */
3549
3550static void
3551window_scroll_line_based (window, n, whole, noerror)
3552 Lisp_Object window;
3553 int n;
3554 int whole;
3555 int noerror;
7ab12479
JB
3556{
3557 register struct window *w = XWINDOW (window);
5500c422 3558 register int opoint = PT, opoint_byte = PT_BYTE;
b73ea88e 3559 register int pos, pos_byte;
7ab12479
JB
3560 register int ht = window_internal_height (w);
3561 register Lisp_Object tem;
3562 int lose;
5500c422 3563 Lisp_Object bolp;
345d45b2 3564 int startpos;
101d1605
RS
3565 struct position posit;
3566 int original_vpos;
3567
3568 startpos = marker_position (w->start);
3569
3570 posit = *compute_motion (startpos, 0, 0, 0,
3571 PT, ht, 0,
3572 window_internal_width (w), XINT (w->hscroll),
3573 0, w);
3574 original_vpos = posit.vpos;
0a1f771a 3575
d834a2e9 3576 XSETFASTINT (tem, PT);
7ab12479
JB
3577 tem = Fpos_visible_in_window_p (tem, window);
3578
265a9e55 3579 if (NILP (tem))
7ab12479 3580 {
cd2be1dd 3581 Fvertical_motion (make_number (- (ht / 2)), window);
345d45b2 3582 startpos = PT;
7ab12479
JB
3583 }
3584
345d45b2 3585 SET_PT (startpos);
5ce7b543 3586 lose = n < 0 && PT == BEGV;
540b6aa0 3587 Fvertical_motion (make_number (n), window);
5ce7b543 3588 pos = PT;
b73ea88e 3589 pos_byte = PT_BYTE;
7ab12479 3590 bolp = Fbolp ();
b73ea88e 3591 SET_PT_BOTH (opoint, opoint_byte);
7ab12479
JB
3592
3593 if (lose)
f8026fd8
JB
3594 {
3595 if (noerror)
3596 return;
3597 else
3598 Fsignal (Qbeginning_of_buffer, Qnil);
3599 }
7ab12479
JB
3600
3601 if (pos < ZV)
7ab12479 3602 {
0c7da84e
RS
3603 int this_scroll_margin = scroll_margin;
3604
3605 /* Don't use a scroll margin that is negative or too large. */
3606 if (this_scroll_margin < 0)
3607 this_scroll_margin = 0;
3608
3609 if (XINT (w->height) < 4 * scroll_margin)
3610 this_scroll_margin = XINT (w->height) / 4;
3611
b73ea88e 3612 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
7ab12479
JB
3613 w->start_at_line_beg = bolp;
3614 w->update_mode_line = Qt;
d834a2e9 3615 XSETFASTINT (w->last_modified, 0);
3cd21523 3616 XSETFASTINT (w->last_overlay_modified, 0);
345d45b2
RS
3617 /* Set force_start so that redisplay_window will run
3618 the window-scroll-functions. */
3619 w->force_start = Qt;
0c7da84e 3620
5500c422 3621 if (whole && !NILP (Vscroll_preserve_screen_position))
0c7da84e 3622 {
b73ea88e 3623 SET_PT_BOTH (pos, pos_byte);
101d1605 3624 Fvertical_motion (make_number (original_vpos), window);
0c7da84e 3625 }
101d1605
RS
3626 /* If we scrolled forward, put point enough lines down
3627 that it is outside the scroll margin. */
3628 else if (n > 0)
0c7da84e 3629 {
101d1605
RS
3630 int top_margin;
3631
3632 if (this_scroll_margin > 0)
3633 {
b73ea88e 3634 SET_PT_BOTH (pos, pos_byte);
101d1605
RS
3635 Fvertical_motion (make_number (this_scroll_margin), window);
3636 top_margin = PT;
3637 }
3638 else
3639 top_margin = pos;
3640
3641 if (top_margin <= opoint)
b73ea88e 3642 SET_PT_BOTH (opoint, opoint_byte);
5500c422 3643 else if (!NILP (Vscroll_preserve_screen_position))
101d1605 3644 {
b73ea88e 3645 SET_PT_BOTH (pos, pos_byte);
101d1605
RS
3646 Fvertical_motion (make_number (original_vpos), window);
3647 }
9317a85d 3648 else
335406fc 3649 SET_PT (top_margin);
0c7da84e 3650 }
101d1605 3651 else if (n < 0)
7ab12479 3652 {
101d1605
RS
3653 int bottom_margin;
3654
0c7da84e
RS
3655 /* If we scrolled backward, put point near the end of the window
3656 but not within the scroll margin. */
b73ea88e 3657 SET_PT_BOTH (pos, pos_byte);
0c7da84e 3658 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
101d1605
RS
3659 if (XFASTINT (tem) == ht - this_scroll_margin)
3660 bottom_margin = PT;
3661 else
3662 bottom_margin = PT + 1;
3663
3664 if (bottom_margin > opoint)
b73ea88e 3665 SET_PT_BOTH (opoint, opoint_byte);
7ab12479 3666 else
101d1605 3667 {
5500c422 3668 if (!NILP (Vscroll_preserve_screen_position))
9317a85d 3669 {
b73ea88e 3670 SET_PT_BOTH (pos, pos_byte);
9317a85d
RS
3671 Fvertical_motion (make_number (original_vpos), window);
3672 }
3673 else
3674 Fvertical_motion (make_number (-1), window);
101d1605 3675 }
7ab12479
JB
3676 }
3677 }
3678 else
f8026fd8
JB
3679 {
3680 if (noerror)
3681 return;
3682 else
3683 Fsignal (Qend_of_buffer, Qnil);
3684 }
7ab12479 3685}
5500c422
GM
3686
3687
3688/* Scroll selected_window up or down. If N is nil, scroll a
3689 screen-full which is defined as the height of the window minus
3690 next_screen_context_lines. If N is the symbol `-', scroll.
3691 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
3692 up. This is the guts of Fscroll_up and Fscroll_down. */
7ab12479
JB
3693
3694static void
3695scroll_command (n, direction)
5500c422 3696 Lisp_Object n;
7ab12479
JB
3697 int direction;
3698{
3699 register int defalt;
3700 int count = specpdl_ptr - specpdl;
3701
5500c422
GM
3702 xassert (abs (direction) == 1);
3703
3704 /* If selected window's buffer isn't current, make it current for
3705 the moment. But don't screw up if window_scroll gets an error. */
7ab12479 3706 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
95605e15
JB
3707 {
3708 record_unwind_protect (save_excursion_restore, save_excursion_save ());
3709 Fset_buffer (XWINDOW (selected_window)->buffer);
5500c422
GM
3710
3711 /* Make redisplay consider other windows than just selected_window. */
3712 ++windows_or_buffers_changed;
95605e15 3713 }
7ab12479
JB
3714
3715 defalt = (window_internal_height (XWINDOW (selected_window))
3716 - next_screen_context_lines);
3717 defalt = direction * (defalt < 1 ? 1 : defalt);
3718
265a9e55 3719 if (NILP (n))
101d1605 3720 window_scroll (selected_window, defalt, 1, 0);
7ab12479 3721 else if (EQ (n, Qminus))
101d1605 3722 window_scroll (selected_window, - defalt, 1, 0);
7ab12479
JB
3723 else
3724 {
3725 n = Fprefix_numeric_value (n);
101d1605 3726 window_scroll (selected_window, XINT (n) * direction, 0, 0);
7ab12479 3727 }
95605e15
JB
3728
3729 unbind_to (count, Qnil);
7ab12479
JB
3730}
3731
3732DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
3733 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
3734A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 3735Negative ARG means scroll downward.\n\
dd394ff9
KH
3736If ARG is the atom `-', scroll downward by nearly full screen.\n\
3737When calling from a program, supply as argument a number, nil, or `-'.")
413430c5
EN
3738 (arg)
3739 Lisp_Object arg;
7ab12479 3740{
413430c5 3741 scroll_command (arg, 1);
7ab12479
JB
3742 return Qnil;
3743}
3744
3745DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
a5fcbc4e 3746 "Scroll text of current window down ARG lines; or near full screen if no ARG.\n\
7ab12479 3747A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 3748Negative ARG means scroll upward.\n\
dd394ff9
KH
3749If ARG is the atom `-', scroll upward by nearly full screen.\n\
3750When calling from a program, supply as argument a number, nil, or `-'.")
413430c5
EN
3751 (arg)
3752 Lisp_Object arg;
7ab12479 3753{
413430c5 3754 scroll_command (arg, -1);
7ab12479
JB
3755 return Qnil;
3756}
ccd0664b
RS
3757\f
3758DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
3759 "Return the other window for \"other window scroll\" commands.\n\
77b24de6 3760If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
ccd0664b
RS
3761specifies the window.\n\
3762If `other-window-scroll-buffer' is non-nil, a window\n\
3763showing that buffer is used.")
eb16ec06 3764 ()
7ab12479 3765{
ccd0664b 3766 Lisp_Object window;
7ab12479
JB
3767
3768 if (MINI_WINDOW_P (XWINDOW (selected_window))
265a9e55 3769 && !NILP (Vminibuf_scroll_window))
7ab12479
JB
3770 window = Vminibuf_scroll_window;
3771 /* If buffer is specified, scroll that buffer. */
265a9e55 3772 else if (!NILP (Vother_window_scroll_buffer))
7ab12479
JB
3773 {
3774 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
265a9e55 3775 if (NILP (window))
53f76081 3776 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
7ab12479
JB
3777 }
3778 else
dbc4e1c1
JB
3779 {
3780 /* Nothing specified; look for a neighboring window on the same
3781 frame. */
3782 window = Fnext_window (selected_window, Qnil, Qnil);
3783
3784 if (EQ (window, selected_window))
3785 /* That didn't get us anywhere; look for a window on another
3786 visible frame. */
3787 do
3788 window = Fnext_window (window, Qnil, Qt);
3789 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
3790 && ! EQ (window, selected_window));
3791 }
3792
605be8af 3793 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
3794
3795 if (EQ (window, selected_window))
3796 error ("There is no other window");
3797
ccd0664b
RS
3798 return window;
3799}
3800
3801DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
3802 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
dd394ff9 3803A near full screen is `next-screen-context-lines' less than a full screen.\n\
ccd0664b
RS
3804The next window is the one below the current one; or the one at the top\n\
3805if the current one is at the bottom. Negative ARG means scroll downward.\n\
dd394ff9
KH
3806If ARG is the atom `-', scroll downward by nearly full screen.\n\
3807When calling from a program, supply as argument a number, nil, or `-'.\n\
ccd0664b
RS
3808\n\
3809If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
3810specifies the window to scroll.\n\
3811If `other-window-scroll-buffer' is non-nil, scroll the window\n\
3812showing that buffer, popping the buffer up if necessary.")
413430c5
EN
3813 (arg)
3814 register Lisp_Object arg;
ccd0664b
RS
3815{
3816 register Lisp_Object window;
2f787aa3 3817 register int defalt;
ccd0664b
RS
3818 register struct window *w;
3819 register int count = specpdl_ptr - specpdl;
3820
3821 window = Fother_window_for_scrolling ();
3822
7ab12479 3823 w = XWINDOW (window);
2f787aa3
KH
3824 defalt = window_internal_height (w) - next_screen_context_lines;
3825 if (defalt < 1) defalt = 1;
7ab12479
JB
3826
3827 /* Don't screw up if window_scroll gets an error. */
3828 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5500c422 3829 ++windows_or_buffers_changed;
7ab12479
JB
3830
3831 Fset_buffer (w->buffer);
3832 SET_PT (marker_position (w->pointm));
3833
413430c5 3834 if (NILP (arg))
101d1605 3835 window_scroll (window, defalt, 1, 1);
413430c5 3836 else if (EQ (arg, Qminus))
101d1605 3837 window_scroll (window, -defalt, 1, 1);
7ab12479
JB
3838 else
3839 {
413430c5
EN
3840 if (CONSP (arg))
3841 arg = Fcar (arg);
3842 CHECK_NUMBER (arg, 0);
101d1605 3843 window_scroll (window, XINT (arg), 0, 1);
7ab12479
JB
3844 }
3845
b73ea88e 3846 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
f4e7b2c2 3847 unbind_to (count, Qnil);
7ab12479
JB
3848
3849 return Qnil;
3850}
3851\f
644b477c 3852DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
7ab12479
JB
3853 "Scroll selected window display ARG columns left.\n\
3854Default for ARG is window width minus 2.")
3855 (arg)
3856 register Lisp_Object arg;
3857{
3858
265a9e55 3859 if (NILP (arg))
d834a2e9 3860 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
7ab12479
JB
3861 else
3862 arg = Fprefix_numeric_value (arg);
3863
3864 return
3865 Fset_window_hscroll (selected_window,
3866 make_number (XINT (XWINDOW (selected_window)->hscroll)
3867 + XINT (arg)));
3868}
3869
644b477c 3870DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
7ab12479
JB
3871 "Scroll selected window display ARG columns right.\n\
3872Default for ARG is window width minus 2.")
3873 (arg)
3874 register Lisp_Object arg;
3875{
265a9e55 3876 if (NILP (arg))
d834a2e9 3877 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
7ab12479
JB
3878 else
3879 arg = Fprefix_numeric_value (arg);
3880
3881 return
3882 Fset_window_hscroll (selected_window,
3883 make_number (XINT (XWINDOW (selected_window)->hscroll)
3884 - XINT (arg)));
3885}
3886
3887DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
44fa5b1e 3888 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
7ab12479 3889The desired position of point is always relative to the current window.\n\
44fa5b1e 3890Just C-u as prefix means put point in the center of the window.\n\
413430c5 3891If ARG is omitted or nil, erases the entire frame and then\n\
44fa5b1e 3892redraws with point in the center of the current window.")
413430c5
EN
3893 (arg)
3894 register Lisp_Object arg;
7ab12479
JB
3895{
3896 register struct window *w = XWINDOW (selected_window);
3897 register int ht = window_internal_height (w);
113d9015 3898 struct position pos;
478292ed
RS
3899 struct buffer *buf = XBUFFER (w->buffer);
3900 struct buffer *obuf = current_buffer;
7ab12479 3901
413430c5 3902 if (NILP (arg))
7ab12479 3903 {
44fa5b1e 3904 extern int frame_garbaged;
7ab12479 3905
527b6458 3906 Fredraw_frame (w->frame);
44fa5b1e 3907 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
413430c5 3908 XSETFASTINT (arg, ht / 2);
7ab12479 3909 }
413430c5 3910 else if (CONSP (arg)) /* Just C-u. */
7ab12479 3911 {
413430c5 3912 XSETFASTINT (arg, ht / 2);
7ab12479
JB
3913 }
3914 else
3915 {
413430c5
EN
3916 arg = Fprefix_numeric_value (arg);
3917 CHECK_NUMBER (arg, 0);
7ab12479
JB
3918 }
3919
413430c5
EN
3920 if (XINT (arg) < 0)
3921 XSETINT (arg, XINT (arg) + ht);
7ab12479 3922
478292ed 3923 set_buffer_internal (buf);
6ec8bbd2 3924 pos = *vmotion (PT, - XINT (arg), w);
7ab12479 3925
b73ea88e
RS
3926 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
3927 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
3928 || FETCH_BYTE (pos.bytepos - 1) == '\n')
113d9015 3929 ? Qt : Qnil);
7ab12479 3930 w->force_start = Qt;
478292ed 3931 set_buffer_internal (obuf);
7ab12479
JB
3932
3933 return Qnil;
3934}
3935\f
3936DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
3937 1, 1, "P",
3938 "Position point relative to window.\n\
19e3bf0a 3939With no argument, position point at center of window.\n\
d81724c7
RS
3940An argument specifies vertical position within the window;\n\
3941zero means top of window, negative means relative to bottom of window.")
7ab12479
JB
3942 (arg)
3943 register Lisp_Object arg;
3944{
3945 register struct window *w = XWINDOW (selected_window);
3946 register int height = window_internal_height (w);
3947 register int start;
540b6aa0 3948 Lisp_Object window;
7ab12479 3949
265a9e55 3950 if (NILP (arg))
d834a2e9 3951 XSETFASTINT (arg, height / 2);
7ab12479
JB
3952 else
3953 {
3954 arg = Fprefix_numeric_value (arg);
3955 if (XINT (arg) < 0)
3956 XSETINT (arg, XINT (arg) + height);
3957 }
3958
3959 start = marker_position (w->start);
74112613 3960 XSETWINDOW (window, w);
7ab12479
JB
3961 if (start < BEGV || start > ZV)
3962 {
cd2be1dd 3963 Fvertical_motion (make_number (- (height / 2)), window);
b73ea88e 3964 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
7ab12479
JB
3965 w->start_at_line_beg = Fbolp ();
3966 w->force_start = Qt;
3967 }
3968 else
b73ea88e 3969 Fgoto_char (w->start);
7ab12479 3970
540b6aa0 3971 return Fvertical_motion (arg, window);
7ab12479 3972}
5500c422
GM
3973
3974
7ab12479 3975\f
5500c422
GM
3976/***********************************************************************
3977 Window Configuration
3978 ***********************************************************************/
3979
7ab12479
JB
3980struct save_window_data
3981 {
f5ccc0cc 3982 EMACS_INT size_from_Lisp_Vector_struct;
7ab12479 3983 struct Lisp_Vector *next_from_Lisp_Vector_struct;
8f6ea2e9 3984 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
9ea173e8 3985 Lisp_Object frame_tool_bar_lines;
bdc727bf 3986 Lisp_Object selected_frame;
7ab12479
JB
3987 Lisp_Object current_window;
3988 Lisp_Object current_buffer;
3989 Lisp_Object minibuf_scroll_window;
3990 Lisp_Object root_window;
bdc727bf 3991 Lisp_Object focus_frame;
756b6edc
RS
3992 /* Record the values of window-min-width and window-min-height
3993 so that window sizes remain consistent with them. */
3994 Lisp_Object min_width, min_height;
cbff28e8
RS
3995 /* A vector, each of whose elements is a struct saved_window
3996 for one window. */
7ab12479
JB
3997 Lisp_Object saved_windows;
3998 };
ff06df24 3999
cbff28e8 4000/* This is saved as a Lisp_Vector */
7ab12479
JB
4001struct saved_window
4002 {
4003 /* these first two must agree with struct Lisp_Vector in lisp.h */
f5ccc0cc 4004 EMACS_INT size_from_Lisp_Vector_struct;
7ab12479
JB
4005 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4006
4007 Lisp_Object window;
4008 Lisp_Object buffer, start, pointm, mark;
4009 Lisp_Object left, top, width, height, hscroll;
4010 Lisp_Object parent, prev;
4011 Lisp_Object start_at_line_beg;
4012 Lisp_Object display_table;
4013 };
4014#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
4015
4016#define SAVED_WINDOW_N(swv,n) \
4017 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4018
4019DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
cbff28e8 4020 "Return t if OBJECT is a window-configuration object.")
413430c5
EN
4021 (object)
4022 Lisp_Object object;
7ab12479 4023{
413430c5 4024 if (WINDOW_CONFIGURATIONP (object))
7ab12479
JB
4025 return Qt;
4026 return Qnil;
4027}
4028
3f8ab7bd
RS
4029DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
4030 "Return the frame that CONFIG, a window-configuration object, is about.")
4031 (config)
4032 Lisp_Object config;
4033{
4034 register struct save_window_data *data;
4035 struct Lisp_Vector *saved_windows;
4036
4037 if (! WINDOW_CONFIGURATIONP (config))
4038 wrong_type_argument (Qwindow_configuration_p, config);
4039
4040 data = (struct save_window_data *) XVECTOR (config);
4041 saved_windows = XVECTOR (data->saved_windows);
4042 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4043}
4044
d5b2799e
RS
4045DEFUN ("set-window-configuration", Fset_window_configuration,
4046 Sset_window_configuration, 1, 1, 0,
7ab12479
JB
4047 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
4048CONFIGURATION must be a value previously returned\n\
3f8ab7bd
RS
4049by `current-window-configuration' (which see).\n\
4050If CONFIGURATION was made from a frame that is now deleted,\n\
4051only frame-independent values can be restored. In this case,\n\
4052the return value is nil. Otherwise the value is t.")
4053 (configuration)
2f83aebe 4054 Lisp_Object configuration;
7ab12479 4055{
7ab12479
JB
4056 register struct save_window_data *data;
4057 struct Lisp_Vector *saved_windows;
7ab12479 4058 Lisp_Object new_current_buffer;
fd482be5 4059 Lisp_Object frame;
44fa5b1e 4060 FRAME_PTR f;
d2b35234 4061 int old_point = -1;
7ab12479 4062
017b2bad 4063 while (!WINDOW_CONFIGURATIONP (configuration))
3f8ab7bd 4064 wrong_type_argument (Qwindow_configuration_p, configuration);
7ab12479 4065
2f83aebe 4066 data = (struct save_window_data *) XVECTOR (configuration);
7ab12479
JB
4067 saved_windows = XVECTOR (data->saved_windows);
4068
7ab12479 4069 new_current_buffer = data->current_buffer;
265a9e55 4070 if (NILP (XBUFFER (new_current_buffer)->name))
7ab12479 4071 new_current_buffer = Qnil;
d2b35234
RS
4072 else
4073 {
4074 if (XBUFFER (new_current_buffer) == current_buffer)
4075 old_point = PT;
cbff28e8 4076
d2b35234 4077 }
7ab12479 4078
fd482be5
JB
4079 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4080 f = XFRAME (frame);
9ace597f 4081
fd482be5
JB
4082 /* If f is a dead frame, don't bother rebuilding its window tree.
4083 However, there is other stuff we should still try to do below. */
4084 if (FRAME_LIVE_P (f))
7ab12479 4085 {
fd482be5
JB
4086 register struct window *w;
4087 register struct saved_window *p;
5500c422
GM
4088 struct window *root_window;
4089 struct window **leaf_windows;
4090 int n_leaf_windows;
4091 int k, i;
fd482be5
JB
4092
4093 /* If the frame has been resized since this window configuration was
4094 made, we change the frame to the size specified in the
4095 configuration, restore the configuration, and then resize it
4096 back. We keep track of the prevailing height in these variables. */
4097 int previous_frame_height = FRAME_HEIGHT (f);
4098 int previous_frame_width = FRAME_WIDTH (f);
8f6ea2e9 4099 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
9ea173e8 4100 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
fd482be5 4101
d2b35234
RS
4102 /* The mouse highlighting code could get screwed up
4103 if it runs during this. */
4104 BLOCK_INPUT;
4105
fd482be5
JB
4106 if (XFASTINT (data->frame_height) != previous_frame_height
4107 || XFASTINT (data->frame_width) != previous_frame_width)
f8ad443a 4108 change_frame_size (f, XFASTINT (data->frame_height),
2b653806 4109 XFASTINT (data->frame_width), 0, 0, 0);
e3678b64 4110#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
8f6ea2e9
KH
4111 if (XFASTINT (data->frame_menu_bar_lines)
4112 != previous_frame_menu_bar_lines)
f8ad443a 4113 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
4314246f 4114#ifdef HAVE_WINDOW_SYSTEM
9ea173e8
GM
4115 if (XFASTINT (data->frame_tool_bar_lines)
4116 != previous_frame_tool_bar_lines)
4117 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
4314246f 4118#endif
217f2871 4119#endif
fd482be5 4120
596ae0cf
RS
4121 if (! NILP (XWINDOW (selected_window)->buffer))
4122 {
4123 w = XWINDOW (selected_window);
4124 set_marker_both (w->pointm,
4125 w->buffer,
4126 BUF_PT (XBUFFER (w->buffer)),
4127 BUF_PT_BYTE (XBUFFER (w->buffer)));
4128 }
4129
fd482be5 4130 windows_or_buffers_changed++;
29aeee73 4131 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
fd482be5 4132
5500c422
GM
4133 /* Problem: Freeing all matrices and later allocating them again
4134 is a serious redisplay flickering problem. What we would
4135 really like to do is to free only those matrices not reused
4136 below. */
4137 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
4138 leaf_windows
4139 = (struct window **) alloca (count_windows (root_window)
4140 * sizeof (struct window *));
4141 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
4142
756b6edc
RS
4143 /* Temporarily avoid any problems with windows that are smaller
4144 than they are supposed to be. */
4145 window_min_height = 1;
4146 window_min_width = 1;
4147
fd482be5
JB
4148 /* Kludge Alert!
4149 Mark all windows now on frame as "deleted".
4150 Restoring the new configuration "undeletes" any that are in it.
37962e60 4151
fd482be5
JB
4152 Save their current buffers in their height fields, since we may
4153 need it later, if a buffer saved in the configuration is now
4154 dead. */
4155 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4156
4157 for (k = 0; k < saved_windows->size; k++)
4158 {
4159 p = SAVED_WINDOW_N (saved_windows, k);
4160 w = XWINDOW (p->window);
4161 w->next = Qnil;
7ab12479 4162
fd482be5
JB
4163 if (!NILP (p->parent))
4164 w->parent = SAVED_WINDOW_N (saved_windows,
4165 XFASTINT (p->parent))->window;
4166 else
4167 w->parent = Qnil;
7ab12479 4168
fd482be5 4169 if (!NILP (p->prev))
7ab12479 4170 {
fd482be5
JB
4171 w->prev = SAVED_WINDOW_N (saved_windows,
4172 XFASTINT (p->prev))->window;
4173 XWINDOW (w->prev)->next = p->window;
4174 }
4175 else
4176 {
4177 w->prev = Qnil;
4178 if (!NILP (w->parent))
4179 {
4180 if (EQ (p->width, XWINDOW (w->parent)->width))
4181 {
4182 XWINDOW (w->parent)->vchild = p->window;
4183 XWINDOW (w->parent)->hchild = Qnil;
4184 }
4185 else
4186 {
4187 XWINDOW (w->parent)->hchild = p->window;
4188 XWINDOW (w->parent)->vchild = Qnil;
4189 }
4190 }
4191 }
4192
4193 /* If we squirreled away the buffer in the window's height,
4194 restore it now. */
017b2bad 4195 if (BUFFERP (w->height))
fd482be5
JB
4196 w->buffer = w->height;
4197 w->left = p->left;
4198 w->top = p->top;
4199 w->width = p->width;
4200 w->height = p->height;
4201 w->hscroll = p->hscroll;
4202 w->display_table = p->display_table;
d834a2e9 4203 XSETFASTINT (w->last_modified, 0);
3cd21523 4204 XSETFASTINT (w->last_overlay_modified, 0);
fd482be5
JB
4205
4206 /* Reinstall the saved buffer and pointers into it. */
4207 if (NILP (p->buffer))
4208 w->buffer = p->buffer;
4209 else
4210 {
4211 if (!NILP (XBUFFER (p->buffer)->name))
4212 /* If saved buffer is alive, install it. */
4213 {
4214 w->buffer = p->buffer;
4215 w->start_at_line_beg = p->start_at_line_beg;
b73ea88e
RS
4216 set_marker_restricted (w->start, p->start, w->buffer);
4217 set_marker_restricted (w->pointm, p->pointm, w->buffer);
fd482be5 4218 Fset_marker (XBUFFER (w->buffer)->mark,
b73ea88e 4219 p->mark, w->buffer);
fd482be5
JB
4220
4221 /* As documented in Fcurrent_window_configuration, don't
4222 save the location of point in the buffer which was current
4223 when the window configuration was recorded. */
6b54027b
RS
4224 if (!EQ (p->buffer, new_current_buffer)
4225 && XBUFFER (p->buffer) == current_buffer)
fd482be5
JB
4226 Fgoto_char (w->pointm);
4227 }
52a68e98
RS
4228 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
4229 /* Else unless window has a live buffer, get one. */
7ab12479 4230 {
fd482be5
JB
4231 w->buffer = Fcdr (Fcar (Vbuffer_alist));
4232 /* This will set the markers to beginning of visible
4233 range. */
4234 set_marker_restricted (w->start, make_number (0), w->buffer);
4235 set_marker_restricted (w->pointm, make_number (0),w->buffer);
4236 w->start_at_line_beg = Qt;
7ab12479
JB
4237 }
4238 else
fd482be5 4239 /* Keeping window's old buffer; make sure the markers
52a68e98 4240 are real. */
7ab12479 4241 {
fd482be5
JB
4242 /* Set window markers at start of visible range. */
4243 if (XMARKER (w->start)->buffer == 0)
4244 set_marker_restricted (w->start, make_number (0),
4245 w->buffer);
4246 if (XMARKER (w->pointm)->buffer == 0)
b73ea88e
RS
4247 set_marker_restricted_both (w->pointm, w->buffer,
4248 BUF_PT (XBUFFER (w->buffer)),
4249 BUF_PT_BYTE (XBUFFER (w->buffer)));
fd482be5 4250 w->start_at_line_beg = Qt;
7ab12479
JB
4251 }
4252 }
4253 }
9ace597f 4254
fd482be5
JB
4255 FRAME_ROOT_WINDOW (f) = data->root_window;
4256 Fselect_window (data->current_window);
396a830c
RS
4257 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
4258 = selected_window;
7ab12479 4259
db269683 4260 if (NILP (data->focus_frame)
017b2bad 4261 || (FRAMEP (data->focus_frame)
db269683
JB
4262 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
4263 Fredirect_frame_focus (frame, data->focus_frame);
7ab12479 4264
fd482be5
JB
4265#if 0 /* I don't understand why this is needed, and it causes problems
4266 when the frame's old selected window has been deleted. */
e4e59717 4267 if (f != selected_frame && FRAME_WINDOW_P (f))
9a7c6fc3
RS
4268 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
4269 Qnil, 0);
fd482be5
JB
4270#endif
4271
4272 /* Set the screen height to the value it had before this function. */
4273 if (previous_frame_height != FRAME_HEIGHT (f)
4274 || previous_frame_width != FRAME_WIDTH (f))
4275 change_frame_size (f, previous_frame_height, previous_frame_width,
2b653806 4276 0, 0, 0);
e3678b64 4277#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
8f6ea2e9 4278 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
f8ad443a
AS
4279 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
4280 make_number (0));
4314246f 4281#ifdef HAVE_WINDOW_SYSTEM
9ea173e8
GM
4282 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
4283 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
4284 make_number (0));
4314246f 4285#endif
217f2871 4286#endif
d2b35234 4287
5500c422
GM
4288 /* Now, free glyph matrices in windows that were not reused. */
4289 for (i = 0; i < n_leaf_windows; ++i)
4290 if (NILP (leaf_windows[i]->buffer))
4291 {
4292 /* Assert it's not reused as a combination. */
4293 xassert (NILP (leaf_windows[i]->hchild)
4294 && NILP (leaf_windows[i]->vchild));
4295 free_window_matrices (leaf_windows[i]);
4296 SET_FRAME_GARBAGED (f);
4297 }
4298
4299 adjust_glyphs (f);
4300
d2b35234 4301 UNBLOCK_INPUT;
756b6edc 4302
478292ed
RS
4303 /* Fselect_window will have made f the selected frame, so we
4304 reselect the proper frame here. Fhandle_switch_frame will change the
4305 selected window too, but that doesn't make the call to
4306 Fselect_window above totally superfluous; it still sets f's
4307 selected window. */
4308 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
4309 do_switch_frame (data->selected_frame, Qnil, 0);
4310
4311 if (! NILP (Vwindow_configuration_change_hook)
4312 && ! NILP (Vrun_hooks))
4313 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4314 }
bdc727bf
JB
4315
4316 if (!NILP (new_current_buffer))
d2b35234
RS
4317 {
4318 Fset_buffer (new_current_buffer);
4319
4320 /* If the buffer that is current now is the same
4321 that was current before setting the window configuration,
4322 don't alter its PT. */
4323 if (old_point >= 0)
4324 SET_PT (old_point);
4325 }
bdc727bf 4326
478292ed
RS
4327 /* Restore the minimum heights recorded in the configuration. */
4328 window_min_height = XINT (data->min_height);
4329 window_min_width = XINT (data->min_width);
543f5fb1 4330
478292ed 4331 Vminibuf_scroll_window = data->minibuf_scroll_window;
543f5fb1 4332
3f8ab7bd 4333 return (FRAME_LIVE_P (f) ? Qt : Qnil);
7ab12479
JB
4334}
4335
44fa5b1e 4336/* Mark all windows now on frame as deleted
7ab12479
JB
4337 by setting their buffers to nil. */
4338
fd482be5 4339void
7ab12479
JB
4340delete_all_subwindows (w)
4341 register struct window *w;
4342{
265a9e55 4343 if (!NILP (w->next))
7ab12479 4344 delete_all_subwindows (XWINDOW (w->next));
265a9e55 4345 if (!NILP (w->vchild))
7ab12479 4346 delete_all_subwindows (XWINDOW (w->vchild));
265a9e55 4347 if (!NILP (w->hchild))
7ab12479 4348 delete_all_subwindows (XWINDOW (w->hchild));
605be8af
JB
4349
4350 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
4351
86e48436
RS
4352 if (!NILP (w->buffer))
4353 unshow_buffer (w);
4354
605be8af
JB
4355 /* We set all three of these fields to nil, to make sure that we can
4356 distinguish this dead window from any live window. Live leaf
4357 windows will have buffer set, and combination windows will have
4358 vchild or hchild set. */
4359 w->buffer = Qnil;
4360 w->vchild = Qnil;
4361 w->hchild = Qnil;
7ab12479
JB
4362}
4363\f
4364static int
4365count_windows (window)
4366 register struct window *window;
4367{
4368 register int count = 1;
265a9e55 4369 if (!NILP (window->next))
7ab12479 4370 count += count_windows (XWINDOW (window->next));
265a9e55 4371 if (!NILP (window->vchild))
7ab12479 4372 count += count_windows (XWINDOW (window->vchild));
265a9e55 4373 if (!NILP (window->hchild))
7ab12479
JB
4374 count += count_windows (XWINDOW (window->hchild));
4375 return count;
4376}
4377
5500c422
GM
4378
4379/* Fill vector FLAT with leaf windows under W, starting at index I.
4380 Value is last index + 1. */
4381
4382static int
4383get_leaf_windows (w, flat, i)
4384 struct window *w;
4385 struct window **flat;
4386 int i;
4387{
4388 while (w)
4389 {
4390 if (!NILP (w->hchild))
4391 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
4392 else if (!NILP (w->vchild))
4393 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
4394 else
4395 flat[i++] = w;
4396
4397 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4398 }
4399
4400 return i;
4401}
4402
4403
4404/* Return a pointer to the glyph W's physical cursor is on. Value is
4405 null if W's current matrix is invalid, so that no meaningfull glyph
4406 can be returned. */
4407
4408struct glyph *
4409get_phys_cursor_glyph (w)
4410 struct window *w;
4411{
4412 struct glyph_row *row;
4413 struct glyph *glyph;
4414
4415 if (w->phys_cursor.vpos >= 0
4416 && w->phys_cursor.vpos < w->current_matrix->nrows
4417 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
4418 row->enabled_p)
4419 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
4420 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
4421 else
4422 glyph = NULL;
4423
4424 return glyph;
4425}
4426
4427
7ab12479
JB
4428static int
4429save_window_save (window, vector, i)
4430 Lisp_Object window;
4431 struct Lisp_Vector *vector;
4432 int i;
4433{
4434 register struct saved_window *p;
4435 register struct window *w;
4436 register Lisp_Object tem;
4437
265a9e55 4438 for (;!NILP (window); window = w->next)
7ab12479
JB
4439 {
4440 p = SAVED_WINDOW_N (vector, i);
4441 w = XWINDOW (window);
4442
d834a2e9 4443 XSETFASTINT (w->temslot, i++);
7ab12479
JB
4444 p->window = window;
4445 p->buffer = w->buffer;
4446 p->left = w->left;
4447 p->top = w->top;
4448 p->width = w->width;
4449 p->height = w->height;
4450 p->hscroll = w->hscroll;
4451 p->display_table = w->display_table;
265a9e55 4452 if (!NILP (w->buffer))
7ab12479
JB
4453 {
4454 /* Save w's value of point in the window configuration.
4455 If w is the selected window, then get the value of point
4456 from the buffer; pointm is garbage in the selected window. */
4457 if (EQ (window, selected_window))
4458 {
4459 p->pointm = Fmake_marker ();
b73ea88e
RS
4460 set_marker_both (p->pointm, w->buffer,
4461 BUF_PT (XBUFFER (w->buffer)),
4462 BUF_PT_BYTE (XBUFFER (w->buffer)));
7ab12479
JB
4463 }
4464 else
eeb82665 4465 p->pointm = Fcopy_marker (w->pointm, Qnil);
7ab12479 4466
eeb82665 4467 p->start = Fcopy_marker (w->start, Qnil);
7ab12479
JB
4468 p->start_at_line_beg = w->start_at_line_beg;
4469
4470 tem = XBUFFER (w->buffer)->mark;
eeb82665 4471 p->mark = Fcopy_marker (tem, Qnil);
7ab12479
JB
4472 }
4473 else
4474 {
4475 p->pointm = Qnil;
4476 p->start = Qnil;
4477 p->mark = Qnil;
4478 p->start_at_line_beg = Qnil;
4479 }
4480
265a9e55 4481 if (NILP (w->parent))
7ab12479
JB
4482 p->parent = Qnil;
4483 else
4484 p->parent = XWINDOW (w->parent)->temslot;
4485
265a9e55 4486 if (NILP (w->prev))
7ab12479
JB
4487 p->prev = Qnil;
4488 else
4489 p->prev = XWINDOW (w->prev)->temslot;
4490
265a9e55 4491 if (!NILP (w->vchild))
7ab12479 4492 i = save_window_save (w->vchild, vector, i);
265a9e55 4493 if (!NILP (w->hchild))
7ab12479
JB
4494 i = save_window_save (w->hchild, vector, i);
4495 }
4496
4497 return i;
4498}
4499
a0d76c27
EN
4500DEFUN ("current-window-configuration", Fcurrent_window_configuration,
4501 Scurrent_window_configuration, 0, 1, 0,
44fa5b1e
JB
4502 "Return an object representing the current window configuration of FRAME.\n\
4503If FRAME is nil or omitted, use the selected frame.\n\
7ab12479
JB
4504This describes the number of windows, their sizes and current buffers,\n\
4505and for each displayed buffer, where display starts, and the positions of\n\
4506point and mark. An exception is made for point in the current buffer:\n\
bdc727bf
JB
4507its value is -not- saved.\n\
4508This also records the currently selected frame, and FRAME's focus\n\
4509redirection (see `redirect-frame-focus').")
44fa5b1e
JB
4510 (frame)
4511 Lisp_Object frame;
7ab12479
JB
4512{
4513 register Lisp_Object tem;
4514 register int n_windows;
4515 register struct save_window_data *data;
da2792e0 4516 register struct Lisp_Vector *vec;
7ab12479 4517 register int i;
44fa5b1e 4518 FRAME_PTR f;
43bad991 4519
44fa5b1e 4520 if (NILP (frame))
1ae1a37d
GM
4521 frame = selected_frame;
4522 CHECK_LIVE_FRAME (frame, 0);
4523 f = XFRAME (frame);
7ab12479 4524
44fa5b1e 4525 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
da2792e0
KH
4526 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
4527 for (i = 0; i < VECSIZE (struct save_window_data); i++)
4528 vec->contents[i] = Qnil;
4529 vec->size = VECSIZE (struct save_window_data);
4530 data = (struct save_window_data *)vec;
4531
d834a2e9
KH
4532 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
4533 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
4534 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
9ea173e8 4535 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
1ae1a37d 4536 data->selected_frame = selected_frame;
44fa5b1e 4537 data->current_window = FRAME_SELECTED_WINDOW (f);
74112613 4538 XSETBUFFER (data->current_buffer, current_buffer);
7ab12479 4539 data->minibuf_scroll_window = Vminibuf_scroll_window;
44fa5b1e 4540 data->root_window = FRAME_ROOT_WINDOW (f);
bdc727bf 4541 data->focus_frame = FRAME_FOCUS_FRAME (f);
74112613
KH
4542 XSETINT (data->min_height, window_min_height);
4543 XSETINT (data->min_width, window_min_width);
7ab12479
JB
4544 tem = Fmake_vector (make_number (n_windows), Qnil);
4545 data->saved_windows = tem;
4546 for (i = 0; i < n_windows; i++)
4547 XVECTOR (tem)->contents[i]
4548 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
44fa5b1e 4549 save_window_save (FRAME_ROOT_WINDOW (f),
7ab12479 4550 XVECTOR (tem), 0);
74112613 4551 XSETWINDOW_CONFIGURATION (tem, data);
7ab12479
JB
4552 return (tem);
4553}
4554
4555DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
4556 0, UNEVALLED, 0,
4557 "Execute body, preserving window sizes and contents.\n\
eb16ec06
RS
4558Restore which buffer appears in which window, where display starts,\n\
4559and the value of point and mark for each window.\n\
4560Also restore which buffer is current.\n\
4561But do not preserve point in the current buffer.\n\
7ab12479
JB
4562Does not restore the value of point in current buffer.")
4563 (args)
4564 Lisp_Object args;
4565{
4566 register Lisp_Object val;
4567 register int count = specpdl_ptr - specpdl;
4568
4569 record_unwind_protect (Fset_window_configuration,
43bad991 4570 Fcurrent_window_configuration (Qnil));
7ab12479
JB
4571 val = Fprogn (args);
4572 return unbind_to (count, val);
4573}
5500c422
GM
4574
4575\f
4576/***********************************************************************
4577 Marginal Areas
4578 ***********************************************************************/
4579
4580DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
4581 2, 3, "",
4582 "Set width of marginal areas of window WINDOW.\n\
4583If window is nil or omitted, set margins of the currently selected window.\n\
4584First parameter LEFT-WIDTH specifies the number of character\n\
4585cells to reserve for the left marginal area. Second parameter\n\
4586RIGHT-WIDTH does the same for the right marginal area.\n\
4587A nil width parameter means no margin.")
cfa22082 4588 (window, left, right)
5500c422
GM
4589 Lisp_Object window, left, right;
4590{
4591 struct window *w = decode_window (window);
5500c422
GM
4592
4593 if (!NILP (left))
cfa22082 4594 CHECK_NUMBER_OR_FLOAT (left, 1);
5500c422 4595 if (!NILP (right))
cfa22082 4596 CHECK_NUMBER_OR_FLOAT (right, 2);
5500c422
GM
4597
4598 /* Check widths < 0 and translate a zero width to nil.
4599 Margins that are too wide have to be checked elsewhere. */
4600 if ((INTEGERP (left) && XINT (left) < 0)
4601 || (FLOATP (left) && XFLOAT (left)->data <= 0))
4602 XSETFASTINT (left, 0);
4603 if (INTEGERP (left) && XFASTINT (left) == 0)
4604 left = Qnil;
4605
4606 if ((INTEGERP (right) && XINT (right) < 0)
4607 || (FLOATP (right) && XFLOAT (right)->data <= 0))
4608 XSETFASTINT (right, 0);
4609 if (INTEGERP (right) && XFASTINT (right) == 0)
4610 right = Qnil;
4611
4612 w->left_margin_width = left;
4613 w->right_margin_width = right;
4614
4615 ++windows_or_buffers_changed;
4616 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
4617 return Qnil;
4618}
4619
4620
4621DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
4622 0, 1, 0,
4623 "Get width of marginal areas of window WINDOW.\n\
4624If WINDOW is omitted or nil, use the currently selected window.\n\
4625Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).\n\
4626If a marginal area does not exist, its width will be returned\n\
4627as nil.")
4628 (window)
4629 Lisp_Object window;
4630{
4631 struct window *w = decode_window (window);
4632 return Fcons (w->left_margin_width, w->right_margin_width);
4633}
4634
4635
7ab12479 4636\f
5500c422
GM
4637/***********************************************************************
4638 Smooth scrolling
4639 ***********************************************************************/
4640
4641DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
4642 "Return the amount by which WINDOW is scrolled vertically.\n\
4643Use the selected window if WINDOW is nil or omitted.\n\
4644Value is a multiple of the canonical character height of WINDOW.")
4645 (window)
4646 Lisp_Object window;
4647{
47004952 4648 Lisp_Object result;
5500c422
GM
4649 struct frame *f;
4650 struct window *w;
4651
4652 if (NILP (window))
4653 window = selected_window;
47004952
GM
4654 else
4655 CHECK_WINDOW (window, 0);
5500c422
GM
4656 w = XWINDOW (window);
4657 f = XFRAME (w->frame);
4658
4659 if (FRAME_WINDOW_P (f))
47004952 4660 result = CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
5500c422 4661 else
47004952
GM
4662 result = make_number (0);
4663 return result;
5500c422
GM
4664}
4665
4666
4667DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
47004952
GM
4668 2, 2, 0,
4669 "Set amount by which WINDOW should be scrolled vertically to VSCROLL.\n\
5500c422 4670WINDOW nil or omitted means use the selected window. VSCROLL is a\n\
47004952
GM
4671non-negative multiple of the canonical character height of WINDOW.")
4672 (window, vscroll)
4673 Lisp_Object window, vscroll;
5500c422
GM
4674{
4675 struct window *w;
4676 struct frame *f;
4677
5500c422
GM
4678 if (NILP (window))
4679 window = selected_window;
47004952
GM
4680 else
4681 CHECK_WINDOW (window, 0);
4682 CHECK_NUMBER_OR_FLOAT (vscroll, 1);
4683
5500c422
GM
4684 w = XWINDOW (window);
4685 f = XFRAME (w->frame);
4686
4687 if (FRAME_WINDOW_P (f))
4688 {
4689 int old_dy = w->vscroll;
47004952
GM
4690
4691 w->vscroll = - CANON_Y_UNIT (f) * XFLOATINT (vscroll);
4692 w->vscroll = min (w->vscroll, 0);
5500c422
GM
4693
4694 /* Adjust glyph matrix of the frame if the virtual display
4695 area becomes larger than before. */
4696 if (w->vscroll < 0 && w->vscroll < old_dy)
4697 adjust_glyphs (f);
4698
4699 /* Prevent redisplay shortcuts. */
b1599b4c 4700 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5500c422
GM
4701 }
4702
47004952 4703 return Fwindow_vscroll (window);
5500c422
GM
4704}
4705
7bbb5782
GM
4706\f
4707/* Call FN for all leaf windows on frame F. FN is called with the
4708 first argument being a pointer to the leaf window, and with
4709 additional arguments A1..A4. */
4710
4711void
4712foreach_window (f, fn, a1, a2, a3, a4)
4713 struct frame *f;
4714 void (* fn) ();
4715 int a1, a2, a3, a4;
4716{
4717 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, a1, a2, a3, a4);
4718}
4719
4720
4721/* Helper function for foreach_window. Call FN for all leaf windows
4722 reachable from W. FN is called with the first argument being a
4723 pointer to the leaf window, and with additional arguments A1..A4. */
4724
4725static void
4726foreach_window_1 (w, fn, a1, a2, a3, a4)
4727 struct window *w;
4728 void (* fn) ();
4729 int a1, a2, a3, a4;
4730{
4731 while (w)
4732 {
4733 if (!NILP (w->hchild))
4734 foreach_window_1 (XWINDOW (w->hchild), fn, a1, a2, a3, a4);
4735 else if (!NILP (w->vchild))
4736 foreach_window_1 (XWINDOW (w->vchild), fn, a1, a2, a3, a4);
4737 else
4738 fn (w, a1, a2, a3, a4);
4739
4740 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4741 }
4742}
4743
4744
4745/* Freeze or unfreeze the window start of W if unless it is a
4746 mini-window or the selected window. FREEZE_P non-zero means freeze
4747 the window start. */
4748
4749static void
4750freeze_window_start (w, freeze_p)
4751 struct window *w;
4752 int freeze_p;
4753{
4754 if (w == XWINDOW (selected_window)
4755 || MINI_WINDOW_P (w)
4756 || (MINI_WINDOW_P (XWINDOW (selected_window))
4757 && w == XWINDOW (Vminibuf_scroll_window)))
4758 freeze_p = 0;
4759
4760 w->frozen_window_start_p = freeze_p;
4761}
4762
4763
4764/* Freeze or unfreeze the window starts of all leaf windows on frame
4765 F, except the selected window and a mini-window. FREEZE_P non-zero
4766 means freeze the window start. */
4767
4768void
4769freeze_window_starts (f, freeze_p)
4770 struct frame *f;
4771 int freeze_p;
4772{
4773 foreach_window (f, freeze_window_start, freeze_p);
4774}
5500c422
GM
4775
4776\f
4777/***********************************************************************
4778 Initialization
4779 ***********************************************************************/
4780
cbff28e8
RS
4781/* Return 1 if window configurations C1 and C2
4782 describe the same state of affairs. This is used by Fequal. */
4783
4784int
2f8274be 4785compare_window_configurations (c1, c2, ignore_positions)
cbff28e8 4786 Lisp_Object c1, c2;
2f8274be 4787 int ignore_positions;
cbff28e8
RS
4788{
4789 register struct save_window_data *d1, *d2;
4790 struct Lisp_Vector *sw1, *sw2;
4791 int i;
4792
4793 d1 = (struct save_window_data *) XVECTOR (c1);
4794 d2 = (struct save_window_data *) XVECTOR (c2);
4795 sw1 = XVECTOR (d1->saved_windows);
4796 sw2 = XVECTOR (d2->saved_windows);
4797
4798 if (! EQ (d1->frame_width, d2->frame_width))
4799 return 0;
4800 if (! EQ (d1->frame_height, d2->frame_height))
4801 return 0;
4802 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
4803 return 0;
4804 if (! EQ (d1->selected_frame, d2->selected_frame))
4805 return 0;
4806 /* Don't compare the current_window field directly.
4807 Instead see w1_is_current and w2_is_current, below. */
4808 if (! EQ (d1->current_buffer, d2->current_buffer))
4809 return 0;
2f8274be
RS
4810 if (! ignore_positions)
4811 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
4812 return 0;
cbff28e8
RS
4813 /* Don't compare the root_window field.
4814 We don't require the two configurations
4815 to use the same window object,
4816 and the two root windows must be equivalent
4817 if everything else compares equal. */
4818 if (! EQ (d1->focus_frame, d2->focus_frame))
4819 return 0;
4820 if (! EQ (d1->min_width, d2->min_width))
4821 return 0;
4822 if (! EQ (d1->min_height, d2->min_height))
4823 return 0;
4824
4825 /* Verify that the two confis have the same number of windows. */
4826 if (sw1->size != sw2->size)
4827 return 0;
4828
4829 for (i = 0; i < sw1->size; i++)
4830 {
4831 struct saved_window *p1, *p2;
4832 int w1_is_current, w2_is_current;
4833
4834 p1 = SAVED_WINDOW_N (sw1, i);
4835 p2 = SAVED_WINDOW_N (sw2, i);
4836
4837 /* Verify that the current windows in the two
4838 configurations correspond to each other. */
4839 w1_is_current = EQ (d1->current_window, p1->window);
4840 w2_is_current = EQ (d2->current_window, p2->window);
4841
4842 if (w1_is_current != w2_is_current)
4843 return 0;
4844
4845 /* Verify that the corresponding windows do match. */
4846 if (! EQ (p1->buffer, p2->buffer))
4847 return 0;
4848 if (! EQ (p1->left, p2->left))
4849 return 0;
4850 if (! EQ (p1->top, p2->top))
4851 return 0;
4852 if (! EQ (p1->width, p2->width))
4853 return 0;
4854 if (! EQ (p1->height, p2->height))
4855 return 0;
cbff28e8
RS
4856 if (! EQ (p1->display_table, p2->display_table))
4857 return 0;
4858 if (! EQ (p1->parent, p2->parent))
4859 return 0;
4860 if (! EQ (p1->prev, p2->prev))
4861 return 0;
2f8274be
RS
4862 if (! ignore_positions)
4863 {
4864 if (! EQ (p1->hscroll, p2->hscroll))
4865 return 0;
4866 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
4867 return 0;
4868 if (NILP (Fequal (p1->start, p2->start)))
4869 return 0;
4870 if (NILP (Fequal (p1->pointm, p2->pointm)))
4871 return 0;
4872 if (NILP (Fequal (p1->mark, p2->mark)))
4873 return 0;
4874 }
cbff28e8
RS
4875 }
4876
4877 return 1;
4878}
2f8274be
RS
4879
4880DEFUN ("compare-window-configurations", Fcompare_window_configurations,
4881 Scompare_window_configurations, 2, 2, 0,
4882 "Compare two window configurations as regards the structure of windows.\n\
4883This function ignores details such as the values of point and mark\n\
4884and scrolling positions.")
4885 (x, y)
4886 Lisp_Object x, y;
4887{
4888 if (compare_window_configurations (x, y, 1))
4889 return Qt;
4890 return Qnil;
4891}
cbff28e8 4892\f
dfcf069d 4893void
7ab12479
JB
4894init_window_once ()
4895{
1ae1a37d
GM
4896 struct frame *f = make_terminal_frame ();
4897 XSETFRAME (selected_frame, f);
4898 Vterminal_frame = selected_frame;
4899 minibuf_window = f->minibuffer_window;
4900 selected_window = f->selected_window;
4901 last_nonminibuf_frame = f;
5b03d3c0
RS
4902
4903 window_initialized = 1;
7ab12479
JB
4904}
4905
dfcf069d 4906void
7ab12479
JB
4907syms_of_window ()
4908{
fbad6f9a
GM
4909 Qleft_bitmap_area = intern ("left-bitmap-area");
4910 staticpro (&Qleft_bitmap_area);
4911 Qright_bitmap_area = intern ("right-bitmap-area");
4912 staticpro (&Qright_bitmap_area);
4913
8a37516b
GM
4914 Qwindow_size_fixed = intern ("window-size-fixed");
4915 staticpro (&Qwindow_size_fixed);
233a4a2c 4916
543f5fb1
RS
4917 staticpro (&Qwindow_configuration_change_hook);
4918 Qwindow_configuration_change_hook
4919 = intern ("window-configuration-change-hook");
4920
7ab12479
JB
4921 Qwindowp = intern ("windowp");
4922 staticpro (&Qwindowp);
4923
3f8ab7bd
RS
4924 Qwindow_configuration_p = intern ("window-configuration-p");
4925 staticpro (&Qwindow_configuration_p);
4926
806b4d9b
JB
4927 Qwindow_live_p = intern ("window-live-p");
4928 staticpro (&Qwindow_live_p);
605be8af 4929
2cccc823 4930 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
a58ec57d
RS
4931 staticpro (&Qtemp_buffer_show_hook);
4932
7ab12479
JB
4933 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
4934 "Non-nil means call as function to display a help buffer.\n\
c3ef6b1d 4935The function is called with one argument, the buffer to be displayed.\n\
f52cca03
RS
4936Used by `with-output-to-temp-buffer'.\n\
4937If this function is used, then it must do the entire job of showing\n\
4938the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
7ab12479
JB
4939 Vtemp_buffer_show_function = Qnil;
4940
4941 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
4942 "If non-nil, function to call to handle `display-buffer'.\n\
4943It will receive two args, the buffer and a flag which if non-nil means\n\
4944 that the currently selected window is not acceptable.\n\
4945Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
4946work using this function.");
4947 Vdisplay_buffer_function = Qnil;
4948
7ab12479
JB
4949 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
4950 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
4951 Vminibuf_scroll_window = Qnil;
4952
4953 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
4954 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
4955 Vother_window_scroll_buffer = Qnil;
4956
44fa5b1e 4957 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
700f75a4 4958 "*Non-nil means `display-buffer' should make a separate frame.");
44fa5b1e 4959 pop_up_frames = 0;
7ab12479 4960
44fa5b1e 4961 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
a90712c2 4962 "Function to call to handle automatic new frame creation.\n\
44fa5b1e 4963It is called with no arguments and should return a newly created frame.\n\
7ab12479 4964\n\
44fa5b1e
JB
4965A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
4966where `pop-up-frame-alist' would hold the default frame parameters.");
4967 Vpop_up_frame_function = Qnil;
7ab12479 4968
a90712c2
RS
4969 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
4970 "*List of buffer names that should have their own special frames.\n\
4971Displaying a buffer whose name is in this list makes a special frame for it\n\
524580a4 4972using `special-display-function'. See also `special-display-regexps'.\n\
3548e138 4973\n\
524580a4
RS
4974An element of the list can be a list instead of just a string.\n\
4975There are two ways to use a list as an element:\n\
4976 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
4977In the first case, FRAME-PARAMETERS are used to create the frame.\n\
4978In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
4979followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
4caa7448
RS
4980All this is done by the function found in `special-display-function'.\n\
4981\n\
4982If this variable appears \"not to work\", because you add a name to it\n\
4983but that buffer still appears in the selected window, look at the\n\
4984values of `same-window-buffer-names' and `same-window-regexps'.\n\
4985Those variables take precedence over this one.");
a90712c2
RS
4986 Vspecial_display_buffer_names = Qnil;
4987
4988 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
4989 "*List of regexps saying which buffers should have their own special frames.\n\
4990If a buffer name matches one of these regexps, it gets its own frame.\n\
4991Displaying a buffer whose name is in this list makes a special frame for it\n\
0a952b57 4992using `special-display-function'.\n\
3548e138 4993\n\
524580a4
RS
4994An element of the list can be a list instead of just a string.\n\
4995There are two ways to use a list as an element:\n\
4996 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
4997In the first case, FRAME-PARAMETERS are used to create the frame.\n\
4998In the latter case, FUNCTION is called with the buffer as first argument,\n\
4999followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
4caa7448
RS
5000All this is done by the function found in `special-display-function'.\n\
5001\n\
5002If this variable appears \"not to work\", because you add a regexp to it\n\
5003but the matching buffers still appear in the selected window, look at the\n\
5004values of `same-window-buffer-names' and `same-window-regexps'.\n\
5005Those variables take precedence over this one.");
a90712c2
RS
5006 Vspecial_display_regexps = Qnil;
5007
5008 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
5009 "Function to call to make a new frame for a special buffer.\n\
0a952b57
RS
5010It is called with two arguments, the buffer and optional buffer specific\n\
5011data, and should return a window displaying that buffer.\n\
a90712c2 5012The default value makes a separate frame for the buffer,\n\
bdd3a802 5013using `special-display-frame-alist' to specify the frame parameters.\n\
a90712c2
RS
5014\n\
5015A buffer is special if its is listed in `special-display-buffer-names'\n\
5016or matches a regexp in `special-display-regexps'.");
5017 Vspecial_display_function = Qnil;
5018
855d8627
RS
5019 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
5020 "*List of buffer names that should appear in the selected window.\n\
5021Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
5022switches to it in the selected window, rather than making it appear\n\
2e5ce1a0 5023in some other window.\n\
855d8627
RS
5024\n\
5025An element of the list can be a cons cell instead of just a string.\n\
5026Then the car must be a string, which specifies the buffer name.\n\
5027This is for compatibility with `special-display-buffer-names';\n\
5028the cdr of the cons cell is ignored.\n\
5029\n\
5030See also `same-window-regexps'.");
5031 Vsame_window_buffer_names = Qnil;
5032
5033 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
5034 "*List of regexps saying which buffers should appear in the selected window.\n\
5035If a buffer name matches one of these regexps, then displaying it\n\
5036using `display-buffer' or `pop-to-buffer' switches to it\n\
5037in the selected window, rather than making it appear in some other window.\n\
5038\n\
5039An element of the list can be a cons cell instead of just a string.\n\
5040Then the car must be a string, which specifies the buffer name.\n\
5041This is for compatibility with `special-display-buffer-names';\n\
5042the cdr of the cons cell is ignored.\n\
5043\n\
5044See also `same-window-buffer-names'.");
5045 Vsame_window_regexps = Qnil;
5046
7ab12479
JB
5047 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
5048 "*Non-nil means display-buffer should make new windows.");
5049 pop_up_windows = 1;
5050
5051 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
5052 "*Number of lines of continuity when scrolling by screenfuls.");
5053 next_screen_context_lines = 2;
5054
5055 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
5056 "*display-buffer would prefer to split the largest window if this large.\n\
5057If there is only one window, it is split regardless of this value.");
5058 split_height_threshold = 500;
5059
5060 DEFVAR_INT ("window-min-height", &window_min_height,
5061 "*Delete any window less than this tall (including its mode line).");
5062 window_min_height = 4;
5063
5064 DEFVAR_INT ("window-min-width", &window_min_width,
5065 "*Delete any window less than this wide.");
5066 window_min_width = 10;
5067
5500c422
GM
5068 DEFVAR_LISP ("scroll-preserve-screen-position",
5069 &Vscroll_preserve_screen_position,
9317a85d 5070 "*Nonzero means scroll commands move point to keep its screen line unchanged.");
5500c422 5071 Vscroll_preserve_screen_position = Qnil;
9317a85d 5072
543f5fb1
RS
5073 DEFVAR_LISP ("window-configuration-change-hook",
5074 &Vwindow_configuration_change_hook,
5075 "Functions to call when window configuration changes.\n\
e3e041eb 5076The selected frame is the one whose configuration has changed.");
543f5fb1
RS
5077 Vwindow_configuration_change_hook = Qnil;
5078
7ab12479
JB
5079 defsubr (&Sselected_window);
5080 defsubr (&Sminibuffer_window);
5081 defsubr (&Swindow_minibuffer_p);
5082 defsubr (&Swindowp);
806b4d9b 5083 defsubr (&Swindow_live_p);
7ab12479
JB
5084 defsubr (&Spos_visible_in_window_p);
5085 defsubr (&Swindow_buffer);
5086 defsubr (&Swindow_height);
5087 defsubr (&Swindow_width);
5088 defsubr (&Swindow_hscroll);
5089 defsubr (&Sset_window_hscroll);
190eb263
RS
5090 defsubr (&Swindow_redisplay_end_trigger);
5091 defsubr (&Sset_window_redisplay_end_trigger);
7ab12479 5092 defsubr (&Swindow_edges);
d5783c40
JB
5093 defsubr (&Scoordinates_in_window_p);
5094 defsubr (&Swindow_at);
7ab12479
JB
5095 defsubr (&Swindow_point);
5096 defsubr (&Swindow_start);
5097 defsubr (&Swindow_end);
5098 defsubr (&Sset_window_point);
5099 defsubr (&Sset_window_start);
5100 defsubr (&Swindow_dedicated_p);
d207b766 5101 defsubr (&Sset_window_dedicated_p);
7ab12479
JB
5102 defsubr (&Swindow_display_table);
5103 defsubr (&Sset_window_display_table);
5104 defsubr (&Snext_window);
5105 defsubr (&Sprevious_window);
5106 defsubr (&Sother_window);
5107 defsubr (&Sget_lru_window);
5108 defsubr (&Sget_largest_window);
5109 defsubr (&Sget_buffer_window);
5110 defsubr (&Sdelete_other_windows);
5111 defsubr (&Sdelete_windows_on);
5112 defsubr (&Sreplace_buffer_in_windows);
5113 defsubr (&Sdelete_window);
5114 defsubr (&Sset_window_buffer);
5115 defsubr (&Sselect_window);
4628f7a4
EN
5116 defsubr (&Sspecial_display_p);
5117 defsubr (&Ssame_window_p);
7ab12479
JB
5118 defsubr (&Sdisplay_buffer);
5119 defsubr (&Ssplit_window);
5120 defsubr (&Senlarge_window);
5121 defsubr (&Sshrink_window);
5122 defsubr (&Sscroll_up);
5123 defsubr (&Sscroll_down);
5124 defsubr (&Sscroll_left);
5125 defsubr (&Sscroll_right);
ccd0664b 5126 defsubr (&Sother_window_for_scrolling);
7ab12479
JB
5127 defsubr (&Sscroll_other_window);
5128 defsubr (&Srecenter);
5129 defsubr (&Smove_to_window_line);
5130 defsubr (&Swindow_configuration_p);
3f8ab7bd 5131 defsubr (&Swindow_configuration_frame);
7ab12479
JB
5132 defsubr (&Sset_window_configuration);
5133 defsubr (&Scurrent_window_configuration);
5134 defsubr (&Ssave_window_excursion);
5500c422
GM
5135 defsubr (&Sset_window_margins);
5136 defsubr (&Swindow_margins);
5137 defsubr (&Swindow_vscroll);
5138 defsubr (&Sset_window_vscroll);
2f8274be 5139 defsubr (&Scompare_window_configurations);
7ab12479
JB
5140}
5141
dfcf069d 5142void
7ab12479
JB
5143keys_of_window ()
5144{
5145 initial_define_key (control_x_map, '1', "delete-other-windows");
5146 initial_define_key (control_x_map, '2', "split-window");
5147 initial_define_key (control_x_map, '0', "delete-window");
5148 initial_define_key (control_x_map, 'o', "other-window");
5149 initial_define_key (control_x_map, '^', "enlarge-window");
5150 initial_define_key (control_x_map, '<', "scroll-left");
5151 initial_define_key (control_x_map, '>', "scroll-right");
5152
5153 initial_define_key (global_map, Ctl ('V'), "scroll-up");
5154 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
5155 initial_define_key (meta_map, 'v', "scroll-down");
5156
5157 initial_define_key (global_map, Ctl('L'), "recenter");
5158 initial_define_key (meta_map, 'r', "move-to-window-line");
5159}