(read_minibuf): 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 {
1970 Lisp_Object val;
1971 struct buffer *old = current_buffer;
1972
1973 current_buffer = XBUFFER (w->buffer);
8a37516b 1974 val = find_symbol_value (Qwindow_size_fixed);
233a4a2c
GM
1975 current_buffer = old;
1976
1977 fixed_p = 0;
1978 if (!EQ (val, Qunbound))
1979 {
1980 fixed_p = !NILP (val);
1981
1982 if (fixed_p
1983 && ((EQ (val, Qheight) && width_p)
1984 || (EQ (val, Qwidth) && !width_p)))
1985 fixed_p = 0;
1986 }
1987
1988 /* Can't tell if this one is resizable without looking at
1989 siblings. If all siblings are fixed-size this one is too. */
1990 if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
1991 {
1992 Lisp_Object child;
1993
1994 for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
1995 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
1996 break;
1997
1998 if (NILP (child))
1999 for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
2000 if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
2001 break;
2002
2003 if (NILP (child))
2004 fixed_p = 1;
2005 }
2006 }
2007 else
2008 fixed_p = 1;
2009
2010 return fixed_p;
2011}
2012
2013
2014/* Return the minimum size of window W, not taking fixed-width windows
2015 into account. WIDTH_P non-zero means return the minimum width,
2016 otherwise return the minimum height. If W is a combination window,
2017 compute the minimum size from the minimum sizes of W's children. */
2018
2019static int
2020window_min_size_1 (w, width_p)
c1636aa6
GM
2021 struct window *w;
2022 int width_p;
2023{
233a4a2c 2024 struct window *c;
c1636aa6
GM
2025 int size;
2026
233a4a2c
GM
2027 if (!NILP (w->hchild))
2028 {
2029 c = XWINDOW (w->hchild);
2030 size = 0;
2031
2032 if (width_p)
2033 {
2034 /* The min width of a horizontal combination is
2035 the sum of the min widths of its children. */
2036 while (c)
2037 {
2038 size += window_min_size_1 (c, width_p);
2039 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2040 }
2041 }
2042 else
2043 {
2044 /* The min height a horizontal combination equals
2045 the maximum of all min height of its children. */
2046 while (c)
2047 {
2048 int min_size = window_min_size_1 (c, width_p);
2049 size = max (min_size, size);
2050 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2051 }
2052 }
2053 }
2054 else if (!NILP (w->vchild))
2055 {
2056 c = XWINDOW (w->vchild);
2057 size = 0;
2058
2059 if (width_p)
2060 {
2061 /* The min width of a vertical combination is
2062 the maximum of the min widths of its children. */
2063 while (c)
2064 {
2065 int min_size = window_min_size_1 (c, width_p);
2066 size = max (min_size, size);
2067 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2068 }
2069 }
2070 else
2071 {
2072 /* The min height of a vertical combination equals
2073 the sum of the min height of its children. */
2074 while (c)
2075 {
2076 size += window_min_size_1 (c, width_p);
2077 c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
2078 }
2079 }
2080 }
c1636aa6
GM
2081 else
2082 {
233a4a2c
GM
2083 if (width_p)
2084 size = window_min_width;
c1636aa6 2085 else
233a4a2c
GM
2086 {
2087 if (MINI_WINDOW_P (w)
2088 || (!WINDOW_WANTS_MODELINE_P (w)
045dee35 2089 && !WINDOW_WANTS_HEADER_LINE_P (w)))
233a4a2c
GM
2090 size = 1;
2091 else
2092 size = window_min_height;
2093 }
c1636aa6
GM
2094 }
2095
2096 return size;
2097}
2098
2099
233a4a2c
GM
2100/* Return the minimum size of window W, taking fixed-size windows into
2101 account. WIDTH_P non-zero means return the minimum width,
2102 otherwise return the minimum height. Set *FIXED to 1 if W is
2103 fixed-size unless FIXED is null. */
7ab12479 2104
233a4a2c
GM
2105static int
2106window_min_size (w, width_p, fixed)
2107 struct window *w;
2108 int width_p, *fixed;
2109{
2110 int size, fixed_p;
2111
2112 fixed_p = window_fixed_size_p (w, width_p, 1);
2113 if (fixed)
2114 *fixed = fixed_p;
2115
2116 if (fixed_p)
2117 size = width_p ? XFASTINT (w->width) : XFASTINT (w->height);
2118 else
2119 size = window_min_size_1 (w, width_p);
2120
2121 return size;
2122}
2123
2124
2125/* Set WINDOW's height or width to SIZE. WIDTH_P non-zero means set
2126 WINDOW's width. Resize WINDOW's children, if any, so that they
2127 keep their proportionate size relative to WINDOW. Propagate
2128 WINDOW's top or left edge position to children. Delete windows
2129 that become too small unless NODELETE_P is non-zero. */
2130
2131static void
2132size_window (window, size, width_p, nodelete_p)
7ab12479 2133 Lisp_Object window;
233a4a2c 2134 int size, width_p, nodelete_p;
7ab12479 2135{
233a4a2c
GM
2136 struct window *w = XWINDOW (window);
2137 struct window *c;
2138 Lisp_Object child, *forward, *sideward;
2139 int old_size, min_size;
7ab12479 2140
a481b3ea 2141 check_min_window_sizes ();
233a4a2c 2142
b5f05b50
GM
2143 /* If the window has been "too small" at one point,
2144 don't delete it for being "too small" in the future.
2145 Preserve it as long as that is at all possible. */
233a4a2c
GM
2146 if (width_p)
2147 {
2148 old_size = XFASTINT (w->width);
2149 min_size = window_min_width;
2150 }
2151 else
2152 {
2153 old_size = XFASTINT (w->height);
2154 min_size = window_min_height;
2155 }
2156
2157 if (old_size < window_min_width)
b5f05b50
GM
2158 w->too_small_ok = Qt;
2159
233a4a2c
GM
2160 /* Maybe delete WINDOW if it's too small. */
2161 if (!nodelete_p && !NILP (w->parent))
7ab12479 2162 {
233a4a2c 2163 int min_size;
b5f05b50
GM
2164
2165 if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
233a4a2c 2166 min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
b5f05b50 2167 else
233a4a2c 2168 min_size = width_p ? window_min_width : window_min_height;
b5f05b50 2169
233a4a2c 2170 if (size < min_size)
c1636aa6
GM
2171 {
2172 delete_window (window);
2173 return;
2174 }
7ab12479
JB
2175 }
2176
233a4a2c 2177 /* Set redisplay hints. */
d834a2e9 2178 XSETFASTINT (w->last_modified, 0);
3cd21523 2179 XSETFASTINT (w->last_overlay_modified, 0);
7ab12479 2180 windows_or_buffers_changed++;
29aeee73
RS
2181 FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
2182
233a4a2c
GM
2183 if (width_p)
2184 {
2185 sideward = &w->vchild;
2186 forward = &w->hchild;
2187 XSETFASTINT (w->width, size);
2188 }
2189 else
2190 {
2191 sideward = &w->hchild;
2192 forward = &w->vchild;
2193 XSETFASTINT (w->height, size);
2194 }
2195
2196 if (!NILP (*sideward))
7ab12479 2197 {
233a4a2c 2198 for (child = *sideward; !NILP (child); child = c->next)
7ab12479 2199 {
233a4a2c
GM
2200 c = XWINDOW (child);
2201 if (width_p)
2202 c->left = w->left;
2203 else
2204 c->top = w->top;
2205 size_window (child, size, width_p, nodelete_p);
7ab12479
JB
2206 }
2207 }
233a4a2c 2208 else if (!NILP (*forward))
7ab12479 2209 {
233a4a2c
GM
2210 int fixed_size, each, extra, n;
2211 int resize_fixed_p, nfixed;
2212 int last_pos, first_pos, nchildren;
2213
2214 /* Determine the fixed-size portion of the this window, and the
2215 number of child windows. */
2216 fixed_size = nchildren = nfixed = 0;
2217 for (child = *forward; !NILP (child); child = c->next, ++nchildren)
7ab12479
JB
2218 {
2219 c = XWINDOW (child);
233a4a2c
GM
2220 if (window_fixed_size_p (c, width_p, 0))
2221 {
2222 fixed_size += (width_p
2223 ? XFASTINT (c->width) : XFASTINT (c->height));
2224 ++nfixed;
2225 }
2226 }
7ab12479 2227
233a4a2c
GM
2228 /* If the new size is smaller than fixed_size, or if there
2229 aren't any resizable windows, allow resizing fixed-size
2230 windows. */
2231 resize_fixed_p = nfixed == nchildren || size < fixed_size;
2232
2233 /* Compute how many lines/columns to add to each child. The
2234 value of extra takes care of rounding errors. */
2235 n = resize_fixed_p ? nchildren : nchildren - nfixed;
2236 each = (size - old_size) / n;
2237 extra = (size - old_size) - n * each;
2238
2239 /* Compute new children heights and edge positions. */
2240 first_pos = width_p ? XFASTINT (w->left) : XFASTINT (w->top);
2241 last_pos = first_pos;
2242 for (child = *forward; !NILP (child); child = c->next)
2243 {
2244 int new_size, old_size;
2245
2246 c = XWINDOW (child);
2247 old_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2248 new_size = old_size;
7ab12479 2249
233a4a2c
GM
2250 /* The top or left edge position of this child equals the
2251 bottom or right edge of its predecessor. */
2252 if (width_p)
2253 c->left = make_number (last_pos);
2254 else
2255 c->top = make_number (last_pos);
7ab12479 2256
233a4a2c
GM
2257 /* If this child can be resized, do it. */
2258 if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
2259 {
2260 new_size = old_size + each + extra;
2261 extra = 0;
2262 }
2263
2264 /* Set new height. Note that size_window also propagates
2265 edge positions to children, so it's not a no-op if we
2266 didn't change the child's size. */
2267 size_window (child, new_size, width_p, 1);
2268
2269 /* Remember the bottom/right edge position of this child; it
2270 will be used to set the top/left edge of the next child. */
2271 last_pos += new_size;
7ab12479 2272 }
233a4a2c
GM
2273
2274 /* We should have covered the parent exactly with child windows. */
2275 xassert (size == last_pos - first_pos);
2276
7ab12479 2277 /* Now delete any children that became too small. */
233a4a2c
GM
2278 if (!nodelete_p)
2279 for (child = *forward; !NILP (child); child = c->next)
7ab12479 2280 {
233a4a2c
GM
2281 int child_size;
2282 c = XWINDOW (child);
2283 child_size = width_p ? XFASTINT (c->width) : XFASTINT (c->height);
2284 size_window (child, child_size, width_p, 0);
7ab12479
JB
2285 }
2286 }
2287}
2288
233a4a2c
GM
2289/* Set WINDOW's height to HEIGHT, and recursively change the height of
2290 WINDOW's children. NODELETE non-zero means don't delete windows
2291 that become too small in the process. (The caller should check
2292 later and do so if appropriate.) */
7ab12479 2293
5e14b1fc 2294void
233a4a2c 2295set_window_height (window, height, nodelete)
7ab12479 2296 Lisp_Object window;
233a4a2c 2297 int height;
7ab12479
JB
2298 int nodelete;
2299{
233a4a2c
GM
2300 size_window (window, height, 0, nodelete);
2301}
7ab12479 2302
7ab12479 2303
233a4a2c
GM
2304/* Set WINDOW's width to WIDTH, and recursively change the width of
2305 WINDOW's children. NODELETE non-zero means don't delete windows
2306 that become too small in the process. (The caller should check
2307 later and do so if appropriate.) */
7ab12479 2308
233a4a2c
GM
2309void
2310set_window_width (window, width, nodelete)
2311 Lisp_Object window;
2312 int width;
2313 int nodelete;
2314{
2315 size_window (window, width, 1, nodelete);
7ab12479 2316}
233a4a2c 2317
7ab12479 2318\f
1d8d96fa 2319int window_select_count;
7ab12479 2320
5b03d3c0
RS
2321Lisp_Object
2322Fset_window_buffer_unwind (obuf)
2323 Lisp_Object obuf;
2324{
2325 Fset_buffer (obuf);
2326 return Qnil;
2327}
2328
7ab12479 2329
5500c422
GM
2330/* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2331 means it's allowed to run hooks. See make_frame for a case where
2332 it's not allowed. */
7ab12479 2333
5500c422
GM
2334void
2335set_window_buffer (window, buffer, run_hooks_p)
2336 Lisp_Object window, buffer;
2337 int run_hooks_p;
2338{
2339 struct window *w = XWINDOW (window);
2340 struct buffer *b = XBUFFER (buffer);
2341 int count = specpdl_ptr - specpdl;
7ab12479
JB
2342
2343 w->buffer = buffer;
86e48436
RS
2344
2345 if (EQ (window, selected_window))
5500c422 2346 b->last_selected_window = window;
beb4e312
RS
2347
2348 /* Update time stamps of buffer display. */
5500c422
GM
2349 if (INTEGERP (b->display_count))
2350 XSETINT (b->display_count, XINT (b->display_count) + 1);
2351 b->display_time = Fcurrent_time ();
86e48436 2352
d834a2e9 2353 XSETFASTINT (w->window_end_pos, 0);
5500c422
GM
2354 XSETFASTINT (w->window_end_vpos, 0);
2355 bzero (&w->last_cursor, sizeof w->last_cursor);
5a41ab94 2356 w->window_end_valid = Qnil;
dba06815 2357 XSETFASTINT (w->hscroll, 0);
5500c422 2358 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
7ab12479 2359 set_marker_restricted (w->start,
5500c422 2360 make_number (b->last_window_start),
7ab12479
JB
2361 buffer);
2362 w->start_at_line_beg = Qnil;
e36ab06b 2363 w->force_start = Qnil;
d834a2e9 2364 XSETFASTINT (w->last_modified, 0);
3cd21523 2365 XSETFASTINT (w->last_overlay_modified, 0);
7ab12479 2366 windows_or_buffers_changed++;
5b03d3c0
RS
2367
2368 /* We must select BUFFER for running the window-scroll-functions.
2369 If WINDOW is selected, switch permanently.
2370 Otherwise, switch but go back to the ambient buffer afterward. */
7ab12479
JB
2371 if (EQ (window, selected_window))
2372 Fset_buffer (buffer);
5b03d3c0
RS
2373 /* We can't check ! NILP (Vwindow_scroll_functions) here
2374 because that might itself be a local variable. */
2375 else if (window_initialized)
2376 {
2377 record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
2378 Fset_buffer (buffer);
2379 }
2380
5500c422 2381 /* Set left and right marginal area width from buffer. */
cfa22082 2382 Fset_window_margins (window, b->left_margin_width, b->right_margin_width);
7ab12479 2383
5500c422
GM
2384 if (run_hooks_p)
2385 {
2386 if (! NILP (Vwindow_scroll_functions))
2387 run_hook_with_args_2 (Qwindow_scroll_functions, window,
2388 Fmarker_position (w->start));
2389
2390 if (! NILP (Vwindow_configuration_change_hook)
2391 && ! NILP (Vrun_hooks))
2392 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
2393 }
543f5fb1 2394
5b03d3c0 2395 unbind_to (count, Qnil);
5500c422 2396}
5b03d3c0 2397
5500c422
GM
2398
2399DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 2, 0,
2400 "Make WINDOW display BUFFER as its contents.\n\
2401BUFFER can be a buffer or buffer name.")
2402 (window, buffer)
2403 register Lisp_Object window, buffer;
2404{
2405 register Lisp_Object tem;
2406 register struct window *w = decode_window (window);
2407 struct buffer *b;
2408
2409 buffer = Fget_buffer (buffer);
2410 CHECK_BUFFER (buffer, 1);
2411
2412 if (NILP (XBUFFER (buffer)->name))
2413 error ("Attempt to display deleted buffer");
2414
2415 tem = w->buffer;
2416 if (NILP (tem))
2417 error ("Window is deleted");
2418 else if (! EQ (tem, Qt)) /* w->buffer is t when the window
2419 is first being set up. */
2420 {
2421 if (!NILP (w->dedicated) && !EQ (tem, buffer))
2422 error ("Window is dedicated to `%s'",
2423 XSTRING (XBUFFER (tem)->name)->data);
2424
2425 unshow_buffer (w);
2426 }
2427
2428 set_window_buffer (window, buffer, 1);
7ab12479
JB
2429 return Qnil;
2430}
2431
2432DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
2433 "Select WINDOW. Most editing will apply to WINDOW's buffer.\n\
beb4e312
RS
2434If WINDOW is not already selected, also make WINDOW's buffer current.\n\
2435Note that the main editor command loop\n\
2436selects the buffer of the selected window before each command.")
7ab12479
JB
2437 (window)
2438 register Lisp_Object window;
b7354ddf
RS
2439{
2440 return select_window_1 (window, 1);
2441}
2442\f
2443static Lisp_Object
2444select_window_1 (window, recordflag)
2445 register Lisp_Object window;
2446 int recordflag;
7ab12479
JB
2447{
2448 register struct window *w;
2449 register struct window *ow = XWINDOW (selected_window);
1ae1a37d 2450 struct frame *sf;
7ab12479 2451
605be8af 2452 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2453
2454 w = XWINDOW (window);
2455
265a9e55 2456 if (NILP (w->buffer))
7ab12479
JB
2457 error ("Trying to select deleted window or non-leaf window");
2458
d834a2e9 2459 XSETFASTINT (w->use_time, ++window_select_count);
7ab12479
JB
2460 if (EQ (window, selected_window))
2461 return window;
2462
596ae0cf
RS
2463 if (! NILP (ow->buffer))
2464 set_marker_both (ow->pointm, ow->buffer,
2465 BUF_PT (XBUFFER (ow->buffer)),
2466 BUF_PT_BYTE (XBUFFER (ow->buffer)));
7ab12479
JB
2467
2468 selected_window = window;
1ae1a37d
GM
2469 sf = SELECTED_FRAME ();
2470 if (XFRAME (WINDOW_FRAME (w)) != sf)
7ab12479 2471 {
44fa5b1e 2472 XFRAME (WINDOW_FRAME (w))->selected_window = window;
147a6615
RS
2473 /* Use this rather than Fhandle_switch_frame
2474 so that FRAME_FOCUS_FRAME is moved appropriately as we
2475 move around in the state where a minibuffer in a separate
2476 frame is active. */
2477 Fselect_frame (WINDOW_FRAME (w), Qnil);
7ab12479
JB
2478 }
2479 else
1ae1a37d 2480 sf->selected_window = window;
7ab12479 2481
b7354ddf
RS
2482 if (recordflag)
2483 record_buffer (w->buffer);
7ab12479
JB
2484 Fset_buffer (w->buffer);
2485
86e48436
RS
2486 XBUFFER (w->buffer)->last_selected_window = window;
2487
7ab12479
JB
2488 /* Go to the point recorded in the window.
2489 This is important when the buffer is in more
2490 than one window. It also matters when
2491 redisplay_window has altered point after scrolling,
2492 because it makes the change only in the window. */
2493 {
2494 register int new_point = marker_position (w->pointm);
2495 if (new_point < BEGV)
2496 SET_PT (BEGV);
a9c95e08 2497 else if (new_point > ZV)
7ab12479
JB
2498 SET_PT (ZV);
2499 else
2500 SET_PT (new_point);
2501 }
2502
2503 windows_or_buffers_changed++;
2504 return window;
2505}
b7354ddf 2506\f
441a127e
RS
2507/* Deiconify the frame containing the window WINDOW,
2508 unless it is the selected frame;
2509 then return WINDOW.
2510
2511 The reason for the exception for the selected frame
2512 is that it seems better not to change the selected frames visibility
2513 merely because of displaying a different buffer in it.
2514 The deiconification is useful when a buffer gets shown in
2515 another frame that you were not using lately. */
d07f802a
RS
2516
2517static Lisp_Object
2518display_buffer_1 (window)
2519 Lisp_Object window;
2520{
1ae1a37d
GM
2521 Lisp_Object frame = XWINDOW (window)->frame;
2522 FRAME_PTR f = XFRAME (frame);
2523
d07f802a 2524 FRAME_SAMPLE_VISIBILITY (f);
1ae1a37d
GM
2525
2526 if (!EQ (frame, selected_frame))
60117126
RS
2527 {
2528 if (FRAME_ICONIFIED_P (f))
1ae1a37d 2529 Fmake_frame_visible (frame);
37962e60 2530 else if (FRAME_VISIBLE_P (f))
1ae1a37d 2531 Fraise_frame (frame);
60117126 2532 }
1ae1a37d 2533
d07f802a
RS
2534 return window;
2535}
2536
4628f7a4 2537DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
0f7d64d2
GV
2538 "Returns non-nil if a buffer named BUFFER-NAME would be created specially.\n\
2539The value is actually t if the frame should be called with default frame\n\
2540parameters, and a list of frame parameters if they were specified.\n\
4628f7a4
EN
2541See `special-display-buffer-names', and `special-display-regexps'.")
2542 (buffer_name)
2543 Lisp_Object buffer_name;
2544{
2545 Lisp_Object tem;
2546
2547 CHECK_STRING (buffer_name, 1);
2548
2549 tem = Fmember (buffer_name, Vspecial_display_buffer_names);
2550 if (!NILP (tem))
2551 return Qt;
2552
2553 tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
2554 if (!NILP (tem))
2555 return XCDR (tem);
2556
2557 for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
2558 {
2559 Lisp_Object car = XCAR (tem);
2560 if (STRINGP (car)
2561 && fast_string_match (car, buffer_name) >= 0)
2562 return Qt;
2563 else if (CONSP (car)
2564 && STRINGP (XCAR (car))
2565 && fast_string_match (XCAR (car), buffer_name) >= 0)
0057b00a 2566 return XCDR (car);
4628f7a4
EN
2567 }
2568 return Qnil;
2569}
2570
2571DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
0f7d64d2 2572 "Returns non-nil if a new buffer named BUFFER-NAME would use the same window.\n\
4628f7a4
EN
2573See `same-window-buffer-names' and `same-window-regexps'.")
2574 (buffer_name)
2575 Lisp_Object buffer_name;
2576{
2577 Lisp_Object tem;
2578
2579 CHECK_STRING (buffer_name, 1);
2580
2581 tem = Fmember (buffer_name, Vsame_window_buffer_names);
2582 if (!NILP (tem))
2583 return Qt;
2584
2585 tem = Fassoc (buffer_name, Vsame_window_buffer_names);
2586 if (!NILP (tem))
2587 return Qt;
2588
2589 for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
2590 {
2591 Lisp_Object car = XCAR (tem);
2592 if (STRINGP (car)
2593 && fast_string_match (car, buffer_name) >= 0)
2594 return Qt;
2595 else if (CONSP (car)
2596 && STRINGP (XCAR (car))
2597 && fast_string_match (XCAR (car), buffer_name) >= 0)
2598 return Qt;
2599 }
2600 return Qnil;
2601}
2602
53f76081
RS
2603 /* Use B so the default is (other-buffer). */
2604DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
2605 "BDisplay buffer: \nP",
7ab12479
JB
2606 "Make BUFFER appear in some window but don't select it.\n\
2607BUFFER can be a buffer or a buffer name.\n\
2608If BUFFER is shown already in some window, just use that one,\n\
2609unless the window is the selected window and the optional second\n\
46d3268a 2610argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
5141b901 2611If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.\n\
5abcf432
RS
2612Returns the window displaying BUFFER.\n\
2613\n\
2614The variables `special-display-buffer-names', `special-display-regexps',\n\
2615`same-window-buffer-names', and `same-window-regexps' customize how certain\n\
53f76081
RS
2616buffer names are handled.\n\
2617\n\
2618If optional argument FRAME is `visible', search all visible frames.\n\
2619If FRAME is 0, search all visible and iconified frames.\n\
2620If FRAME is t, search all frames.\n\
2621If FRAME is a frame, search only that frame.\n\
2622If FRAME is nil, search only the selected frame\n\
2623 (actually the last nonminibuffer frame),\n\
2624 unless `pop-up-frames' is non-nil,\n\
2625 which means search visible and iconified frames.")
2626 (buffer, not_this_window, frame)
2627 register Lisp_Object buffer, not_this_window, frame;
7ab12479 2628{
aee631c2 2629 register Lisp_Object window, tem, swp;
1ae1a37d 2630 struct frame *f;
7ab12479 2631
aee631c2 2632 swp = Qnil;
7ab12479
JB
2633 buffer = Fget_buffer (buffer);
2634 CHECK_BUFFER (buffer, 0);
2635
265a9e55 2636 if (!NILP (Vdisplay_buffer_function))
7ab12479
JB
2637 return call2 (Vdisplay_buffer_function, buffer, not_this_window);
2638
265a9e55 2639 if (NILP (not_this_window)
7ab12479 2640 && XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
d07f802a 2641 return display_buffer_1 (selected_window);
7ab12479 2642
855d8627
RS
2643 /* See if the user has specified this buffer should appear
2644 in the selected window. */
2645 if (NILP (not_this_window))
2646 {
aee631c2
RS
2647 swp = Fsame_window_p (XBUFFER (buffer)->name);
2648 if (!NILP (swp) && !no_switch_window (selected_window))
c63dc4a2
RS
2649 {
2650 Fswitch_to_buffer (buffer, Qnil);
d07f802a 2651 return display_buffer_1 (selected_window);
c63dc4a2 2652 }
855d8627
RS
2653 }
2654
e8edb3ae 2655 /* If pop_up_frames,
73dc5198
KH
2656 look for a window showing BUFFER on any visible or iconified frame.
2657 Otherwise search only the current frame. */
53f76081
RS
2658 if (! NILP (frame))
2659 tem = frame;
2660 else if (pop_up_frames || last_nonminibuf_frame == 0)
73dc5198
KH
2661 XSETFASTINT (tem, 0);
2662 else
73dc5198
KH
2663 XSETFRAME (tem, last_nonminibuf_frame);
2664 window = Fget_buffer_window (buffer, tem);
265a9e55
JB
2665 if (!NILP (window)
2666 && (NILP (not_this_window) || !EQ (window, selected_window)))
f812f9c6 2667 {
d07f802a 2668 return display_buffer_1 (window);
f812f9c6 2669 }
7ab12479 2670
a90712c2 2671 /* Certain buffer names get special handling. */
aee631c2 2672 if (!NILP (Vspecial_display_function) && NILP (swp))
a90712c2 2673 {
4628f7a4
EN
2674 tem = Fspecial_display_p (XBUFFER (buffer)->name);
2675 if (EQ (tem, Qt))
a90712c2 2676 return call1 (Vspecial_display_function, buffer);
4628f7a4
EN
2677 if (CONSP (tem))
2678 return call2 (Vspecial_display_function, buffer, tem);
a90712c2
RS
2679 }
2680
44fa5b1e
JB
2681 /* If there are no frames open that have more than a minibuffer,
2682 we need to create a new frame. */
2683 if (pop_up_frames || last_nonminibuf_frame == 0)
7ab12479 2684 {
a90712c2 2685 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
7ab12479 2686 Fset_window_buffer (window, buffer);
d07f802a 2687 return display_buffer_1 (window);
7ab12479 2688 }
7ab12479 2689
1ae1a37d 2690 f = SELECTED_FRAME ();
43bad991 2691 if (pop_up_windows
1ae1a37d 2692 || FRAME_MINIBUF_ONLY_P (f)
cee67da9
RS
2693 /* If the current frame is a special display frame,
2694 don't try to reuse its windows. */
1ae1a37d 2695 || !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
7ab12479 2696 {
12cae7c0
KH
2697 Lisp_Object frames;
2698
37962e60 2699 frames = Qnil;
1ae1a37d 2700 if (FRAME_MINIBUF_ONLY_P (f))
74112613 2701 XSETFRAME (frames, last_nonminibuf_frame);
7ab12479
JB
2702 /* Don't try to create a window if would get an error */
2703 if (split_height_threshold < window_min_height << 1)
2704 split_height_threshold = window_min_height << 1;
2705
cee67da9
RS
2706 /* Note that both Fget_largest_window and Fget_lru_window
2707 ignore minibuffers and dedicated windows.
2708 This means they can return nil. */
7ab12479 2709
cee67da9
RS
2710 /* If the frame we would try to split cannot be split,
2711 try other frames. */
1ae1a37d 2712 if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
cee67da9
RS
2713 {
2714 /* Try visible frames first. */
2715 window = Fget_largest_window (Qvisible);
2716 /* If that didn't work, try iconified frames. */
2717 if (NILP (window))
2718 window = Fget_largest_window (make_number (0));
2719 if (NILP (window))
2720 window = Fget_largest_window (Qt);
2721 }
2722 else
2723 window = Fget_largest_window (frames);
2724
92cca945
RS
2725 /* If we got a tall enough full-width window that can be split,
2726 split it. */
265a9e55 2727 if (!NILP (window)
92cca945 2728 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
7ab12479 2729 && window_height (window) >= split_height_threshold
111e5992 2730 && WINDOW_FULL_WIDTH_P (XWINDOW (window)))
7ab12479
JB
2731 window = Fsplit_window (window, Qnil, Qnil);
2732 else
2733 {
1942f68f
RS
2734 Lisp_Object upper, lower, other;
2735
44fa5b1e 2736 window = Fget_lru_window (frames);
92cca945
RS
2737 /* If the LRU window is selected, and big enough,
2738 and can be split, split it. */
cee67da9 2739 if (!NILP (window)
92cca945 2740 && ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
cee67da9
RS
2741 && (EQ (window, selected_window)
2742 || EQ (XWINDOW (window)->parent, Qnil))
7ab12479
JB
2743 && window_height (window) >= window_min_height << 1)
2744 window = Fsplit_window (window, Qnil, Qnil);
cee67da9 2745 /* If Fget_lru_window returned nil, try other approaches. */
48d9379d 2746
cee67da9 2747 /* Try visible frames first. */
48d9379d
RS
2748 if (NILP (window))
2749 window = Fget_buffer_window (buffer, Qvisible);
cee67da9
RS
2750 if (NILP (window))
2751 window = Fget_largest_window (Qvisible);
2752 /* If that didn't work, try iconified frames. */
48d9379d
RS
2753 if (NILP (window))
2754 window = Fget_buffer_window (buffer, make_number (0));
cee67da9
RS
2755 if (NILP (window))
2756 window = Fget_largest_window (make_number (0));
2757 /* Try invisible frames. */
48d9379d
RS
2758 if (NILP (window))
2759 window = Fget_buffer_window (buffer, Qt);
cee67da9
RS
2760 if (NILP (window))
2761 window = Fget_largest_window (Qt);
2762 /* As a last resort, make a new frame. */
2763 if (NILP (window))
2764 window = Fframe_selected_window (call0 (Vpop_up_frame_function));
1942f68f
RS
2765 /* If window appears above or below another,
2766 even out their heights. */
cac66e4f 2767 other = upper = lower = Qnil;
1942f68f
RS
2768 if (!NILP (XWINDOW (window)->prev))
2769 other = upper = XWINDOW (window)->prev, lower = window;
2770 if (!NILP (XWINDOW (window)->next))
2771 other = lower = XWINDOW (window)->next, upper = window;
2772 if (!NILP (other)
2773 /* Check that OTHER and WINDOW are vertically arrayed. */
296b535c
KH
2774 && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
2775 && (XFASTINT (XWINDOW (other)->height)
2776 > XFASTINT (XWINDOW (window)->height)))
1942f68f 2777 {
296b535c
KH
2778 int total = (XFASTINT (XWINDOW (other)->height)
2779 + XFASTINT (XWINDOW (window)->height));
8d77c0c8
KH
2780 Lisp_Object old_selected_window;
2781 old_selected_window = selected_window;
1942f68f 2782
8d77c0c8 2783 selected_window = upper;
296b535c
KH
2784 change_window_height ((total / 2
2785 - XFASTINT (XWINDOW (upper)->height)),
2786 0);
1942f68f
RS
2787 selected_window = old_selected_window;
2788 }
7ab12479
JB
2789 }
2790 }
2791 else
2792 window = Fget_lru_window (Qnil);
2793
2794 Fset_window_buffer (window, buffer);
d07f802a 2795 return display_buffer_1 (window);
7ab12479
JB
2796}
2797
2798void
2799temp_output_buffer_show (buf)
2800 register Lisp_Object buf;
2801{
2802 register struct buffer *old = current_buffer;
2803 register Lisp_Object window;
2804 register struct window *w;
2805
bccd3dd1
RS
2806 XBUFFER (buf)->directory = current_buffer->directory;
2807
7ab12479 2808 Fset_buffer (buf);
c6367666 2809 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
7ab12479
JB
2810 BEGV = BEG;
2811 ZV = Z;
2812 SET_PT (BEG);
b1599b4c 2813 XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
7ab12479
JB
2814 set_buffer_internal (old);
2815
2816 if (!EQ (Vtemp_buffer_show_function, Qnil))
2817 call1 (Vtemp_buffer_show_function, buf);
2818 else
2819 {
53f76081 2820 window = Fdisplay_buffer (buf, Qnil, Qnil);
7ab12479 2821
1ae1a37d 2822 if (!EQ (XWINDOW (window)->frame, selected_frame))
44fa5b1e 2823 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
7ab12479
JB
2824 Vminibuf_scroll_window = window;
2825 w = XWINDOW (window);
d834a2e9 2826 XSETFASTINT (w->hscroll, 0);
b73ea88e
RS
2827 set_marker_restricted_both (w->start, buf, 1, 1);
2828 set_marker_restricted_both (w->pointm, buf, 1, 1);
a58ec57d 2829
beb4e312
RS
2830 /* Run temp-buffer-show-hook, with the chosen window selected
2831 and it sbuffer current. */
f52cca03 2832 if (!NILP (Vrun_hooks))
2cccc823 2833 {
f52cca03
RS
2834 Lisp_Object tem;
2835 tem = Fboundp (Qtemp_buffer_show_hook);
2cccc823
RS
2836 if (!NILP (tem))
2837 {
f52cca03
RS
2838 tem = Fsymbol_value (Qtemp_buffer_show_hook);
2839 if (!NILP (tem))
2840 {
2841 int count = specpdl_ptr - specpdl;
b7354ddf
RS
2842 Lisp_Object prev_window;
2843 prev_window = selected_window;
2cccc823 2844
f52cca03 2845 /* Select the window that was chosen, for running the hook. */
65a04b96 2846 record_unwind_protect (Fselect_window, prev_window);
b7354ddf 2847 select_window_1 (window, 0);
beb4e312 2848 Fset_buffer (w->buffer);
f52cca03 2849 call1 (Vrun_hooks, Qtemp_buffer_show_hook);
b7354ddf 2850 select_window_1 (prev_window, 0);
f52cca03
RS
2851 unbind_to (count, Qnil);
2852 }
2cccc823
RS
2853 }
2854 }
2855 }
7ab12479
JB
2856}
2857\f
dfcf069d 2858static void
7ab12479
JB
2859make_dummy_parent (window)
2860 Lisp_Object window;
2861{
cffec418 2862 Lisp_Object new;
7ab12479 2863 register struct window *o, *p;
cffec418
KH
2864 register struct Lisp_Vector *vec;
2865 int i;
7ab12479 2866
cffec418
KH
2867 o = XWINDOW (window);
2868 vec = allocate_vectorlike ((EMACS_INT)VECSIZE (struct window));
2869 for (i = 0; i < VECSIZE (struct window); ++i)
2870 vec->contents[i] = ((struct Lisp_Vector *)o)->contents[i];
2871 vec->size = VECSIZE (struct window);
2872 p = (struct window *)vec;
2873 XSETWINDOW (new, p);
7ab12479 2874
d834a2e9 2875 XSETFASTINT (p->sequence_number, ++sequence_number);
7ab12479
JB
2876
2877 /* Put new into window structure in place of window */
2878 replace_window (window, new);
2879
2880 o->next = Qnil;
2881 o->prev = Qnil;
2882 o->vchild = Qnil;
2883 o->hchild = Qnil;
2884 o->parent = new;
2885
2886 p->start = Qnil;
2887 p->pointm = Qnil;
2888 p->buffer = Qnil;
2889}
2890
2891DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
2892 "Split WINDOW, putting SIZE lines in the first of the pair.\n\
2893WINDOW defaults to selected one and SIZE to half its size.\n\
77ae0fe3 2894If optional third arg HORFLAG is non-nil, split side by side\n\
10f96191
RS
2895and put SIZE columns in the first of the pair. In that case,\n\
2896SIZE includes that window's scroll bar, or the divider column to its right.")
77ae0fe3
KH
2897 (window, size, horflag)
2898 Lisp_Object window, size, horflag;
7ab12479
JB
2899{
2900 register Lisp_Object new;
2901 register struct window *o, *p;
c0807608 2902 FRAME_PTR fo;
77ae0fe3 2903 register int size_int;
7ab12479 2904
265a9e55 2905 if (NILP (window))
7ab12479
JB
2906 window = selected_window;
2907 else
605be8af 2908 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
2909
2910 o = XWINDOW (window);
c0807608 2911 fo = XFRAME (WINDOW_FRAME (o));
7ab12479 2912
77ae0fe3 2913 if (NILP (size))
7ab12479 2914 {
265a9e55 2915 if (!NILP (horflag))
c0807608 2916 /* Calculate the size of the left-hand window, by dividing
25b33244
KH
2917 the usable space in columns by two.
2918 We round up, since the left-hand window may include
2919 a dividing line, while the right-hand may not. */
2920 size_int = (XFASTINT (o->width) + 1) >> 1;
7ab12479 2921 else
77ae0fe3 2922 size_int = XFASTINT (o->height) >> 1;
7ab12479
JB
2923 }
2924 else
2925 {
77ae0fe3
KH
2926 CHECK_NUMBER (size, 1);
2927 size_int = XINT (size);
7ab12479
JB
2928 }
2929
2930 if (MINI_WINDOW_P (o))
2931 error ("Attempt to split minibuffer window");
233a4a2c
GM
2932 else if (window_fixed_size_p (o, !NILP (horflag), 0))
2933 error ("Attempt to split fixed-size window");
7ab12479 2934
a481b3ea 2935 check_min_window_sizes ();
7ab12479 2936
265a9e55 2937 if (NILP (horflag))
7ab12479 2938 {
77ae0fe3
KH
2939 if (size_int < window_min_height)
2940 error ("Window height %d too small (after splitting)", size_int);
2941 if (size_int + window_min_height > XFASTINT (o->height))
37962e60 2942 error ("Window height %d too small (after splitting)",
77ae0fe3 2943 XFASTINT (o->height) - size_int);
265a9e55
JB
2944 if (NILP (o->parent)
2945 || NILP (XWINDOW (o->parent)->vchild))
7ab12479
JB
2946 {
2947 make_dummy_parent (window);
2948 new = o->parent;
2949 XWINDOW (new)->vchild = window;
2950 }
2951 }
2952 else
2953 {
77ae0fe3
KH
2954 if (size_int < window_min_width)
2955 error ("Window width %d too small (after splitting)", size_int);
a59fed7e
RS
2956
2957 if (size_int + window_min_width > XFASTINT (o->width))
37962e60 2958 error ("Window width %d too small (after splitting)",
a59fed7e 2959 XFASTINT (o->width) - size_int);
265a9e55
JB
2960 if (NILP (o->parent)
2961 || NILP (XWINDOW (o->parent)->hchild))
7ab12479
JB
2962 {
2963 make_dummy_parent (window);
2964 new = o->parent;
2965 XWINDOW (new)->hchild = window;
2966 }
2967 }
2968
2969 /* Now we know that window's parent is a vertical combination
2970 if we are dividing vertically, or a horizontal combination
2971 if we are making side-by-side windows */
2972
2973 windows_or_buffers_changed++;
c0807608 2974 FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
7ab12479
JB
2975 new = make_window ();
2976 p = XWINDOW (new);
2977
44fa5b1e 2978 p->frame = o->frame;
7ab12479 2979 p->next = o->next;
265a9e55 2980 if (!NILP (p->next))
7ab12479
JB
2981 XWINDOW (p->next)->prev = new;
2982 p->prev = window;
2983 o->next = new;
2984 p->parent = o->parent;
2985 p->buffer = Qt;
5500c422
GM
2986 p->window_end_valid = Qnil;
2987 bzero (&p->last_cursor, sizeof p->last_cursor);
7ab12479 2988
44fa5b1e 2989 /* Apportion the available frame space among the two new windows */
7ab12479 2990
265a9e55 2991 if (!NILP (horflag))
7ab12479
JB
2992 {
2993 p->height = o->height;
2994 p->top = o->top;
a59fed7e 2995 XSETFASTINT (p->width, XFASTINT (o->width) - size_int);
77ae0fe3
KH
2996 XSETFASTINT (o->width, size_int);
2997 XSETFASTINT (p->left, XFASTINT (o->left) + size_int);
7ab12479
JB
2998 }
2999 else
3000 {
3001 p->left = o->left;
3002 p->width = o->width;
77ae0fe3
KH
3003 XSETFASTINT (p->height, XFASTINT (o->height) - size_int);
3004 XSETFASTINT (o->height, size_int);
3005 XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
7ab12479
JB
3006 }
3007
5500c422
GM
3008 /* Adjust glyph matrices. */
3009 adjust_glyphs (fo);
543f5fb1 3010 Fset_window_buffer (new, o->buffer);
7ab12479
JB
3011 return new;
3012}
3013\f
3014DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
3015 "Make current window ARG lines bigger.\n\
3016From program, optional second arg non-nil means grow sideways ARG columns.")
413430c5
EN
3017 (arg, side)
3018 register Lisp_Object arg, side;
7ab12479 3019{
413430c5
EN
3020 CHECK_NUMBER (arg, 0);
3021 change_window_height (XINT (arg), !NILP (side));
543f5fb1
RS
3022
3023 if (! NILP (Vwindow_configuration_change_hook))
3024 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3025
7ab12479
JB
3026 return Qnil;
3027}
3028
3029DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
3030 "Make current window ARG lines smaller.\n\
413430c5
EN
3031From program, optional second arg non-nil means shrink sideways arg columns.")
3032 (arg, side)
3033 register Lisp_Object arg, side;
7ab12479 3034{
413430c5
EN
3035 CHECK_NUMBER (arg, 0);
3036 change_window_height (-XINT (arg), !NILP (side));
543f5fb1
RS
3037
3038 if (! NILP (Vwindow_configuration_change_hook))
3039 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
3040
7ab12479
JB
3041 return Qnil;
3042}
3043
3044int
3045window_height (window)
3046 Lisp_Object window;
3047{
3048 register struct window *p = XWINDOW (window);
3049 return XFASTINT (p->height);
3050}
3051
3052int
3053window_width (window)
3054 Lisp_Object window;
3055{
3056 register struct window *p = XWINDOW (window);
3057 return XFASTINT (p->width);
3058}
3059
c1636aa6 3060
7ab12479 3061#define CURBEG(w) \
05c2896a 3062 *(widthflag ? (int *) &(XWINDOW (w)->left) : (int *) &(XWINDOW (w)->top))
7ab12479
JB
3063
3064#define CURSIZE(w) \
05c2896a 3065 *(widthflag ? (int *) &(XWINDOW (w)->width) : (int *) &(XWINDOW (w)->height))
7ab12479 3066
233a4a2c
GM
3067
3068/* Enlarge selected_window by DELTA. WIDTHFLAG non-zero means
3069 increase its width. Siblings of the selected window are resized to
3070 fullfil the size request. If they become too small in the process,
3071 they will be deleted. */
7ab12479 3072
5e14b1fc 3073void
7ab12479 3074change_window_height (delta, widthflag)
233a4a2c 3075 int delta, widthflag;
7ab12479 3076{
233a4a2c
GM
3077 Lisp_Object parent, window, next, prev;
3078 struct window *p;
3079 int *sizep, maximum;
5e14b1fc
AS
3080 int (*sizefun) P_ ((Lisp_Object))
3081 = widthflag ? window_width : window_height;
233a4a2c 3082 void (*setsizefun) P_ ((Lisp_Object, int, int))
5e14b1fc 3083 = (widthflag ? set_window_width : set_window_height);
7ab12479 3084
233a4a2c
GM
3085 /* Check values of window_min_width and window_min_height for
3086 validity. */
a481b3ea 3087 check_min_window_sizes ();
7ab12479 3088
233a4a2c 3089 /* Give up if this window cannot be resized. */
7ab12479 3090 window = selected_window;
233a4a2c
GM
3091 if (window_fixed_size_p (XWINDOW (window), widthflag, 1))
3092 error ("Window is not resizable");
3093
3094 /* Find the parent of the selected window. */
7ab12479
JB
3095 while (1)
3096 {
3097 p = XWINDOW (window);
3098 parent = p->parent;
233a4a2c 3099
265a9e55 3100 if (NILP (parent))
7ab12479
JB
3101 {
3102 if (widthflag)
3103 error ("No other window to side of this one");
3104 break;
3105 }
233a4a2c
GM
3106
3107 if (widthflag
3108 ? !NILP (XWINDOW (parent)->hchild)
265a9e55 3109 : !NILP (XWINDOW (parent)->vchild))
7ab12479 3110 break;
233a4a2c 3111
7ab12479
JB
3112 window = parent;
3113 }
3114
05c2896a 3115 sizep = &CURSIZE (window);
7ab12479 3116
7ab12479
JB
3117 {
3118 register int maxdelta;
7ab12479 3119
265a9e55 3120 maxdelta = (!NILP (parent) ? (*sizefun) (parent) - *sizep
c1636aa6
GM
3121 : !NILP (p->next) ? ((*sizefun) (p->next)
3122 - window_min_size (XWINDOW (p->next),
233a4a2c 3123 widthflag, 0))
c1636aa6
GM
3124 : !NILP (p->prev) ? ((*sizefun) (p->prev)
3125 - window_min_size (XWINDOW (p->prev),
233a4a2c 3126 widthflag, 0))
44fa5b1e
JB
3127 /* This is a frame with only one window, a minibuffer-only
3128 or a minibufferless frame. */
d5783c40 3129 : (delta = 0));
7ab12479
JB
3130
3131 if (delta > maxdelta)
3132 /* This case traps trying to make the minibuffer
44fa5b1e
JB
3133 the full frame, or make the only window aside from the
3134 minibuffer the full frame. */
7ab12479 3135 delta = maxdelta;
6b54027b 3136 }
d5783c40 3137
233a4a2c 3138 if (*sizep + delta < window_min_size (XWINDOW (window), widthflag, 0))
6b54027b 3139 {
543f5fb1 3140 delete_window (window);
d5783c40 3141 return;
6b54027b
RS
3142 }
3143
3144 if (delta == 0)
3145 return;
7ab12479 3146
db98a733
RS
3147 /* Find the total we can get from other siblings. */
3148 maximum = 0;
3149 for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
c1636aa6 3150 maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
233a4a2c 3151 widthflag, 0);
db98a733 3152 for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
c1636aa6 3153 maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
233a4a2c 3154 widthflag, 0);
db98a733
RS
3155
3156 /* If we can get it all from them, do so. */
c6b530ed 3157 if (delta <= maximum)
7ab12479 3158 {
db98a733
RS
3159 Lisp_Object first_unaffected;
3160 Lisp_Object first_affected;
233a4a2c 3161 int fixed_p;
db98a733
RS
3162
3163 next = p->next;
3164 prev = p->prev;
3165 first_affected = window;
3166 /* Look at one sibling at a time,
3167 moving away from this window in both directions alternately,
3168 and take as much as we can get without deleting that sibling. */
233a4a2c 3169 while (delta != 0 && (!NILP (next) || !NILP (prev)))
db98a733 3170 {
db98a733
RS
3171 if (! NILP (next))
3172 {
c1636aa6 3173 int this_one = ((*sizefun) (next)
233a4a2c
GM
3174 - window_min_size (XWINDOW (next),
3175 widthflag, &fixed_p));
3176 if (!fixed_p)
3177 {
3178 if (this_one > delta)
3179 this_one = delta;
3180
3181 (*setsizefun) (next, (*sizefun) (next) - this_one, 0);
3182 (*setsizefun) (window, *sizep + this_one, 0);
db98a733 3183
233a4a2c
GM
3184 delta -= this_one;
3185 }
3186
db98a733
RS
3187 next = XWINDOW (next)->next;
3188 }
233a4a2c 3189
db98a733
RS
3190 if (delta == 0)
3191 break;
233a4a2c 3192
db98a733
RS
3193 if (! NILP (prev))
3194 {
c1636aa6 3195 int this_one = ((*sizefun) (prev)
233a4a2c
GM
3196 - window_min_size (XWINDOW (prev),
3197 widthflag, &fixed_p));
3198 if (!fixed_p)
3199 {
3200 if (this_one > delta)
3201 this_one = delta;
3202
3203 first_affected = prev;
3204
3205 (*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
3206 (*setsizefun) (window, *sizep + this_one, 0);
3207
3208 delta -= this_one;
3209 }
3210
db98a733
RS
3211 prev = XWINDOW (prev)->prev;
3212 }
3213 }
3214
233a4a2c
GM
3215 xassert (delta == 0);
3216
db98a733
RS
3217 /* Now recalculate the edge positions of all the windows affected,
3218 based on the new sizes. */
3219 first_unaffected = next;
3220 prev = first_affected;
3221 for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
3222 prev = next, next = XWINDOW (next)->next)
3223 {
3224 CURBEG (next) = CURBEG (prev) + (*sizefun) (prev);
3225 /* This does not change size of NEXT,
3226 but it propagates the new top edge to its children */
3227 (*setsizefun) (next, (*sizefun) (next), 0);
3228 }
7ab12479
JB
3229 }
3230 else
3231 {
3232 register int delta1;
3233 register int opht = (*sizefun) (parent);
3234
3235 /* If trying to grow this window to or beyond size of the parent,
3236 make delta1 so big that, on shrinking back down,
3237 all the siblings end up with less than one line and are deleted. */
3238 if (opht <= *sizep + delta)
3239 delta1 = opht * opht * 2;
7ab12479 3240 else
233a4a2c
GM
3241 {
3242 /* Otherwise, make delta1 just right so that if we add
3243 delta1 lines to this window and to the parent, and then
3244 shrink the parent back to its original size, the new
3245 proportional size of this window will increase by delta.
3246
3247 The function size_window will compute the new height h'
3248 of the window from delta1 as:
3249
3250 e = delta1/n
3251 x = delta1 - delta1/n * n for the 1st resizable child
3252 h' = h + e + x
3253
3254 where n is the number of children that can be resized.
3255 We can ignore x by choosing a delta1 that is a multiple of
3256 n. We want the height of this window to come out as
3257
3258 h' = h + delta
3259
3260 So, delta1 must be
3261
3262 h + e = h + delta
3263 delta1/n = delta
3264 delta1 = n * delta.
3265
3266 The number of children n rquals the number of resizable
3267 children of this window + 1 because we know window itself
3268 is resizable (otherwise we would have signalled an error. */
3269
3270 struct window *w = XWINDOW (window);
3271 Lisp_Object s;
3272 int n = 1;
3273
3274 for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
3275 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3276 ++n;
3277 for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
3278 if (!window_fixed_size_p (XWINDOW (s), widthflag, 0))
3279 ++n;
3280
3281 delta1 = n * delta;
3282 }
7ab12479
JB
3283
3284 /* Add delta1 lines or columns to this window, and to the parent,
3285 keeping things consistent while not affecting siblings. */
05c2896a 3286 CURSIZE (parent) = opht + delta1;
7ab12479
JB
3287 (*setsizefun) (window, *sizep + delta1, 0);
3288
3289 /* Squeeze out delta1 lines or columns from our parent,
3290 shriking this window and siblings proportionately.
3291 This brings parent back to correct size.
3292 Delta1 was calculated so this makes this window the desired size,
3293 taking it all out of the siblings. */
3294 (*setsizefun) (parent, opht, 0);
3295 }
3296
d834a2e9 3297 XSETFASTINT (p->last_modified, 0);
3cd21523 3298 XSETFASTINT (p->last_overlay_modified, 0);
5500c422
GM
3299
3300 /* Adjust glyph matrices. */
3301 adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
7ab12479 3302}
c1636aa6 3303
7ab12479
JB
3304#undef CURBEG
3305#undef CURSIZE
3306
5500c422
GM
3307
3308/* Mark window cursors off for all windows in the window tree rooted
3309 at W by setting their phys_cursor_on_p flag to zero. Called from
3310 xterm.c, e.g. when a frame is cleared and thereby all cursors on
3311 the frame are cleared. */
3312
3313void
3314mark_window_cursors_off (w)
3315 struct window *w;
3316{
3317 while (w)
3318 {
3319 if (!NILP (w->hchild))
3320 mark_window_cursors_off (XWINDOW (w->hchild));
3321 else if (!NILP (w->vchild))
3322 mark_window_cursors_off (XWINDOW (w->vchild));
3323 else
3324 w->phys_cursor_on_p = 0;
3325
3326 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3327 }
3328}
3329
3330
7ab12479
JB
3331/* Return number of lines of text (not counting mode line) in W. */
3332
3333int
3334window_internal_height (w)
3335 struct window *w;
3336{
3337 int ht = XFASTINT (w->height);
3338
3339 if (MINI_WINDOW_P (w))
3340 return ht;
3341
265a9e55
JB
3342 if (!NILP (w->parent) || !NILP (w->vchild) || !NILP (w->hchild)
3343 || !NILP (w->next) || !NILP (w->prev)
44fa5b1e 3344 || FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (w))))
7ab12479
JB
3345 return ht - 1;
3346
3347 return ht;
3348}
3349
535e0b8e
JB
3350
3351/* Return the number of columns in W.
a3c87d4e 3352 Don't count columns occupied by scroll bars or the vertical bar
535e0b8e 3353 separating W from the sibling to its right. */
5500c422 3354
535e0b8e
JB
3355int
3356window_internal_width (w)
3357 struct window *w;
3358{
5500c422 3359 struct frame *f = XFRAME (WINDOW_FRAME (w));
535e0b8e
JB
3360 int width = XINT (w->width);
3361
a3c87d4e 3362 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5500c422
GM
3363 /* Scroll bars occupy a few columns. */
3364 width -= FRAME_SCROLL_BAR_COLS (f);
3365 else if (!WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
3366 /* The column of `|' characters separating side-by-side windows
3367 occupies one column only. */
3368 width -= 1;
3369
3370 /* On window-systems, areas to the left and right of the window
3371 are used to display bitmaps there. */
3372 if (FRAME_WINDOW_P (f))
b46dfc64 3373 width -= FRAME_FLAGS_AREA_COLS (f);
111e5992
RS
3374
3375 return width;
535e0b8e
JB
3376}
3377
5500c422
GM
3378\f
3379/************************************************************************
3380 Window Scrolling
3381 ***********************************************************************/
535e0b8e 3382
5500c422
GM
3383/* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
3384 one screen-full, which is defined as the height of the window minus
3385 next_screen_context_lines. If WHOLE is zero, scroll up N lines
3386 instead. Negative values of N mean scroll down. NOERROR non-zero
3387 means don't signal an error if we try to move over BEGV or ZV,
3388 respectively. */
7ab12479 3389
101d1605
RS
3390static void
3391window_scroll (window, n, whole, noerror)
7ab12479
JB
3392 Lisp_Object window;
3393 int n;
101d1605 3394 int whole;
f8026fd8 3395 int noerror;
5500c422
GM
3396{
3397 /* If we must, use the pixel-based version which is much slower than
3398 the line-based one but can handle varying line heights. */
3399 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
3400 window_scroll_pixel_based (window, n, whole, noerror);
3401 else
3402 window_scroll_line_based (window, n, whole, noerror);
3403}
3404
3405
3406/* Implementation of window_scroll that works based on pixel line
3407 heights. See the comment of window_scroll for parameter
3408 descriptions. */
3409
3410static void
3411window_scroll_pixel_based (window, n, whole, noerror)
3412 Lisp_Object window;
3413 int n;
3414 int whole;
3415 int noerror;
3416{
3417 struct it it;
3418 struct window *w = XWINDOW (window);
3419 struct text_pos start;
3420 Lisp_Object tem;
3421 int this_scroll_margin;
3422 int preserve_y;
3423
3424 SET_TEXT_POS_FROM_MARKER (start, w->start);
3425
3426 /* If PT is not visible in WINDOW, move back one half of
3427 the screen. */
3428 XSETFASTINT (tem, PT);
3429 tem = Fpos_visible_in_window_p (tem, window);
3430 if (NILP (tem))
3431 {
3432 /* Move backward half the height of the window. Performance note:
3433 vmotion used here is about 10% faster, but would give wrong
3434 results for variable height lines. */
3435 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3436 it.current_y = it.last_visible_y;
3437 move_it_vertically (&it, -it.last_visible_y / 2);
3438
3439 /* The function move_iterator_vertically may move over more than
3440 the specified y-distance. If it->w is small, e.g. a
3441 mini-buffer window, we may end up in front of the window's
3442 display area. This is the case when Start displaying at the
3443 start of the line containing PT in this case. */
3444 if (it.current_y <= 0)
3445 {
3446 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
3447 move_it_vertically (&it, 0);
3448 it.current_y = 0;
3449 }
3450
3451 start = it.current.pos;
3452 }
3453
3454 /* If scroll_preserve_screen_position is non-zero, we try to set
3455 point in the same window line as it is now, so get that line. */
3456 if (!NILP (Vscroll_preserve_screen_position))
3457 {
3458 start_display (&it, w, start);
3459 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3460 preserve_y = it.current_y;
3461 }
3462 else
3463 preserve_y = -1;
3464
3465 /* Move iterator it from start the specified distance forward or
3466 backward. The result is the new window start. */
3467 start_display (&it, w, start);
3468 if (whole)
3469 {
3470 int screen_full = (it.last_visible_y
3471 - next_screen_context_lines * CANON_Y_UNIT (it.f));
3472 int direction = n < 0 ? -1 : 1;
3473 move_it_vertically (&it, direction * screen_full);
3474 }
3475 else
3476 move_it_by_lines (&it, n, 1);
3477
3478 /* End if we end up at ZV or BEGV. */
3479 if ((n > 0 && IT_CHARPOS (it) == ZV)
3480 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
3481 {
3482 if (noerror)
3483 return;
3484 else if (IT_CHARPOS (it) == ZV)
3485 Fsignal (Qend_of_buffer, Qnil);
3486 else
3487 Fsignal (Qbeginning_of_buffer, Qnil);
3488 }
3489
3490 /* Set the window start, and set up the window for redisplay. */
3491 set_marker_restricted (w->start, make_number (IT_CHARPOS (it)), w->buffer);
3492 w->start_at_line_beg = Fbolp ();
3493 w->update_mode_line = Qt;
3494 XSETFASTINT (w->last_modified, 0);
3495 XSETFASTINT (w->last_overlay_modified, 0);
3496 /* Set force_start so that redisplay_window will run the
3497 window-scroll-functions. */
3498 w->force_start = Qt;
3499
3500 it.current_y = it.vpos = 0;
3501
3502 /* Preserve the screen position if we must. */
3503 if (preserve_y >= 0)
3504 {
3505 move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
3506 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3507 }
3508 else
3509 {
3510 /* Move PT out of scroll margins. */
3511 this_scroll_margin = max (0, scroll_margin);
3512 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
3513 this_scroll_margin *= CANON_Y_UNIT (it.f);
3514
3515 if (n > 0)
3516 {
3517 /* We moved the window start towards ZV, so PT may be now
3518 in the scroll margin at the top. */
3519 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
3520 while (it.current_y < this_scroll_margin)
3521 move_it_by_lines (&it, 1, 1);
3522 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3523 }
3524 else if (n < 0)
3525 {
3526 /* We moved the window start towards BEGV, so PT may be now
3527 in the scroll margin at the bottom. */
3528 move_it_to (&it, PT, -1,
3529 it.last_visible_y - this_scroll_margin - 1, -1,
3530 MOVE_TO_POS | MOVE_TO_Y);
3531
3532 /* Don't put point on a partially visible line at the end. */
3533 if (it.current_y + it.max_ascent + it.max_descent
3534 > it.last_visible_y)
3535 move_it_by_lines (&it, -1, 0);
3536
3537 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
3538 }
3539 }
3540}
3541
3542
3543/* Implementation of window_scroll that works based on screen lines.
3544 See the comment of window_scroll for parameter descriptions. */
3545
3546static void
3547window_scroll_line_based (window, n, whole, noerror)
3548 Lisp_Object window;
3549 int n;
3550 int whole;
3551 int noerror;
7ab12479
JB
3552{
3553 register struct window *w = XWINDOW (window);
5500c422 3554 register int opoint = PT, opoint_byte = PT_BYTE;
b73ea88e 3555 register int pos, pos_byte;
7ab12479
JB
3556 register int ht = window_internal_height (w);
3557 register Lisp_Object tem;
3558 int lose;
5500c422 3559 Lisp_Object bolp;
345d45b2 3560 int startpos;
101d1605
RS
3561 struct position posit;
3562 int original_vpos;
3563
3564 startpos = marker_position (w->start);
3565
3566 posit = *compute_motion (startpos, 0, 0, 0,
3567 PT, ht, 0,
3568 window_internal_width (w), XINT (w->hscroll),
3569 0, w);
3570 original_vpos = posit.vpos;
0a1f771a 3571
d834a2e9 3572 XSETFASTINT (tem, PT);
7ab12479
JB
3573 tem = Fpos_visible_in_window_p (tem, window);
3574
265a9e55 3575 if (NILP (tem))
7ab12479 3576 {
cd2be1dd 3577 Fvertical_motion (make_number (- (ht / 2)), window);
345d45b2 3578 startpos = PT;
7ab12479
JB
3579 }
3580
345d45b2 3581 SET_PT (startpos);
5ce7b543 3582 lose = n < 0 && PT == BEGV;
540b6aa0 3583 Fvertical_motion (make_number (n), window);
5ce7b543 3584 pos = PT;
b73ea88e 3585 pos_byte = PT_BYTE;
7ab12479 3586 bolp = Fbolp ();
b73ea88e 3587 SET_PT_BOTH (opoint, opoint_byte);
7ab12479
JB
3588
3589 if (lose)
f8026fd8
JB
3590 {
3591 if (noerror)
3592 return;
3593 else
3594 Fsignal (Qbeginning_of_buffer, Qnil);
3595 }
7ab12479
JB
3596
3597 if (pos < ZV)
7ab12479 3598 {
0c7da84e
RS
3599 int this_scroll_margin = scroll_margin;
3600
3601 /* Don't use a scroll margin that is negative or too large. */
3602 if (this_scroll_margin < 0)
3603 this_scroll_margin = 0;
3604
3605 if (XINT (w->height) < 4 * scroll_margin)
3606 this_scroll_margin = XINT (w->height) / 4;
3607
b73ea88e 3608 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
7ab12479
JB
3609 w->start_at_line_beg = bolp;
3610 w->update_mode_line = Qt;
d834a2e9 3611 XSETFASTINT (w->last_modified, 0);
3cd21523 3612 XSETFASTINT (w->last_overlay_modified, 0);
345d45b2
RS
3613 /* Set force_start so that redisplay_window will run
3614 the window-scroll-functions. */
3615 w->force_start = Qt;
0c7da84e 3616
5500c422 3617 if (whole && !NILP (Vscroll_preserve_screen_position))
0c7da84e 3618 {
b73ea88e 3619 SET_PT_BOTH (pos, pos_byte);
101d1605 3620 Fvertical_motion (make_number (original_vpos), window);
0c7da84e 3621 }
101d1605
RS
3622 /* If we scrolled forward, put point enough lines down
3623 that it is outside the scroll margin. */
3624 else if (n > 0)
0c7da84e 3625 {
101d1605
RS
3626 int top_margin;
3627
3628 if (this_scroll_margin > 0)
3629 {
b73ea88e 3630 SET_PT_BOTH (pos, pos_byte);
101d1605
RS
3631 Fvertical_motion (make_number (this_scroll_margin), window);
3632 top_margin = PT;
3633 }
3634 else
3635 top_margin = pos;
3636
3637 if (top_margin <= opoint)
b73ea88e 3638 SET_PT_BOTH (opoint, opoint_byte);
5500c422 3639 else if (!NILP (Vscroll_preserve_screen_position))
101d1605 3640 {
b73ea88e 3641 SET_PT_BOTH (pos, pos_byte);
101d1605
RS
3642 Fvertical_motion (make_number (original_vpos), window);
3643 }
9317a85d 3644 else
335406fc 3645 SET_PT (top_margin);
0c7da84e 3646 }
101d1605 3647 else if (n < 0)
7ab12479 3648 {
101d1605
RS
3649 int bottom_margin;
3650
0c7da84e
RS
3651 /* If we scrolled backward, put point near the end of the window
3652 but not within the scroll margin. */
b73ea88e 3653 SET_PT_BOTH (pos, pos_byte);
0c7da84e 3654 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
101d1605
RS
3655 if (XFASTINT (tem) == ht - this_scroll_margin)
3656 bottom_margin = PT;
3657 else
3658 bottom_margin = PT + 1;
3659
3660 if (bottom_margin > opoint)
b73ea88e 3661 SET_PT_BOTH (opoint, opoint_byte);
7ab12479 3662 else
101d1605 3663 {
5500c422 3664 if (!NILP (Vscroll_preserve_screen_position))
9317a85d 3665 {
b73ea88e 3666 SET_PT_BOTH (pos, pos_byte);
9317a85d
RS
3667 Fvertical_motion (make_number (original_vpos), window);
3668 }
3669 else
3670 Fvertical_motion (make_number (-1), window);
101d1605 3671 }
7ab12479
JB
3672 }
3673 }
3674 else
f8026fd8
JB
3675 {
3676 if (noerror)
3677 return;
3678 else
3679 Fsignal (Qend_of_buffer, Qnil);
3680 }
7ab12479 3681}
5500c422
GM
3682
3683
3684/* Scroll selected_window up or down. If N is nil, scroll a
3685 screen-full which is defined as the height of the window minus
3686 next_screen_context_lines. If N is the symbol `-', scroll.
3687 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
3688 up. This is the guts of Fscroll_up and Fscroll_down. */
7ab12479
JB
3689
3690static void
3691scroll_command (n, direction)
5500c422 3692 Lisp_Object n;
7ab12479
JB
3693 int direction;
3694{
3695 register int defalt;
3696 int count = specpdl_ptr - specpdl;
3697
5500c422
GM
3698 xassert (abs (direction) == 1);
3699
3700 /* If selected window's buffer isn't current, make it current for
3701 the moment. But don't screw up if window_scroll gets an error. */
7ab12479 3702 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
95605e15
JB
3703 {
3704 record_unwind_protect (save_excursion_restore, save_excursion_save ());
3705 Fset_buffer (XWINDOW (selected_window)->buffer);
5500c422
GM
3706
3707 /* Make redisplay consider other windows than just selected_window. */
3708 ++windows_or_buffers_changed;
95605e15 3709 }
7ab12479
JB
3710
3711 defalt = (window_internal_height (XWINDOW (selected_window))
3712 - next_screen_context_lines);
3713 defalt = direction * (defalt < 1 ? 1 : defalt);
3714
265a9e55 3715 if (NILP (n))
101d1605 3716 window_scroll (selected_window, defalt, 1, 0);
7ab12479 3717 else if (EQ (n, Qminus))
101d1605 3718 window_scroll (selected_window, - defalt, 1, 0);
7ab12479
JB
3719 else
3720 {
3721 n = Fprefix_numeric_value (n);
101d1605 3722 window_scroll (selected_window, XINT (n) * direction, 0, 0);
7ab12479 3723 }
95605e15
JB
3724
3725 unbind_to (count, Qnil);
7ab12479
JB
3726}
3727
3728DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
3729 "Scroll text of current window upward ARG lines; or near full screen if no ARG.\n\
3730A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 3731Negative ARG means scroll downward.\n\
dd394ff9
KH
3732If ARG is the atom `-', scroll downward by nearly full screen.\n\
3733When calling from a program, supply as argument a number, nil, or `-'.")
413430c5
EN
3734 (arg)
3735 Lisp_Object arg;
7ab12479 3736{
413430c5 3737 scroll_command (arg, 1);
7ab12479
JB
3738 return Qnil;
3739}
3740
3741DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
a5fcbc4e 3742 "Scroll text of current window down ARG lines; or near full screen if no ARG.\n\
7ab12479 3743A near full screen is `next-screen-context-lines' less than a full screen.\n\
279e0e0c 3744Negative ARG means scroll upward.\n\
dd394ff9
KH
3745If ARG is the atom `-', scroll upward by nearly full screen.\n\
3746When calling from a program, supply as argument a number, nil, or `-'.")
413430c5
EN
3747 (arg)
3748 Lisp_Object arg;
7ab12479 3749{
413430c5 3750 scroll_command (arg, -1);
7ab12479
JB
3751 return Qnil;
3752}
ccd0664b
RS
3753\f
3754DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
3755 "Return the other window for \"other window scroll\" commands.\n\
77b24de6 3756If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
ccd0664b
RS
3757specifies the window.\n\
3758If `other-window-scroll-buffer' is non-nil, a window\n\
3759showing that buffer is used.")
eb16ec06 3760 ()
7ab12479 3761{
ccd0664b 3762 Lisp_Object window;
7ab12479
JB
3763
3764 if (MINI_WINDOW_P (XWINDOW (selected_window))
265a9e55 3765 && !NILP (Vminibuf_scroll_window))
7ab12479
JB
3766 window = Vminibuf_scroll_window;
3767 /* If buffer is specified, scroll that buffer. */
265a9e55 3768 else if (!NILP (Vother_window_scroll_buffer))
7ab12479
JB
3769 {
3770 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
265a9e55 3771 if (NILP (window))
53f76081 3772 window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
7ab12479
JB
3773 }
3774 else
dbc4e1c1
JB
3775 {
3776 /* Nothing specified; look for a neighboring window on the same
3777 frame. */
3778 window = Fnext_window (selected_window, Qnil, Qnil);
3779
3780 if (EQ (window, selected_window))
3781 /* That didn't get us anywhere; look for a window on another
3782 visible frame. */
3783 do
3784 window = Fnext_window (window, Qnil, Qt);
3785 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
3786 && ! EQ (window, selected_window));
3787 }
3788
605be8af 3789 CHECK_LIVE_WINDOW (window, 0);
7ab12479
JB
3790
3791 if (EQ (window, selected_window))
3792 error ("There is no other window");
3793
ccd0664b
RS
3794 return window;
3795}
3796
3797DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
3798 "Scroll next window upward ARG lines; or near full screen if no ARG.\n\
dd394ff9 3799A near full screen is `next-screen-context-lines' less than a full screen.\n\
ccd0664b
RS
3800The next window is the one below the current one; or the one at the top\n\
3801if the current one is at the bottom. Negative ARG means scroll downward.\n\
dd394ff9
KH
3802If ARG is the atom `-', scroll downward by nearly full screen.\n\
3803When calling from a program, supply as argument a number, nil, or `-'.\n\
ccd0664b
RS
3804\n\
3805If in the minibuffer, `minibuffer-scroll-window' if non-nil\n\
3806specifies the window to scroll.\n\
3807If `other-window-scroll-buffer' is non-nil, scroll the window\n\
3808showing that buffer, popping the buffer up if necessary.")
413430c5
EN
3809 (arg)
3810 register Lisp_Object arg;
ccd0664b
RS
3811{
3812 register Lisp_Object window;
2f787aa3 3813 register int defalt;
ccd0664b
RS
3814 register struct window *w;
3815 register int count = specpdl_ptr - specpdl;
3816
3817 window = Fother_window_for_scrolling ();
3818
7ab12479 3819 w = XWINDOW (window);
2f787aa3
KH
3820 defalt = window_internal_height (w) - next_screen_context_lines;
3821 if (defalt < 1) defalt = 1;
7ab12479
JB
3822
3823 /* Don't screw up if window_scroll gets an error. */
3824 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5500c422 3825 ++windows_or_buffers_changed;
7ab12479
JB
3826
3827 Fset_buffer (w->buffer);
3828 SET_PT (marker_position (w->pointm));
3829
413430c5 3830 if (NILP (arg))
101d1605 3831 window_scroll (window, defalt, 1, 1);
413430c5 3832 else if (EQ (arg, Qminus))
101d1605 3833 window_scroll (window, -defalt, 1, 1);
7ab12479
JB
3834 else
3835 {
413430c5
EN
3836 if (CONSP (arg))
3837 arg = Fcar (arg);
3838 CHECK_NUMBER (arg, 0);
101d1605 3839 window_scroll (window, XINT (arg), 0, 1);
7ab12479
JB
3840 }
3841
b73ea88e 3842 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
f4e7b2c2 3843 unbind_to (count, Qnil);
7ab12479
JB
3844
3845 return Qnil;
3846}
3847\f
644b477c 3848DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
7ab12479
JB
3849 "Scroll selected window display ARG columns left.\n\
3850Default for ARG is window width minus 2.")
3851 (arg)
3852 register Lisp_Object arg;
3853{
3854
265a9e55 3855 if (NILP (arg))
d834a2e9 3856 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
7ab12479
JB
3857 else
3858 arg = Fprefix_numeric_value (arg);
3859
3860 return
3861 Fset_window_hscroll (selected_window,
3862 make_number (XINT (XWINDOW (selected_window)->hscroll)
3863 + XINT (arg)));
3864}
3865
644b477c 3866DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
7ab12479
JB
3867 "Scroll selected window display ARG columns right.\n\
3868Default for ARG is window width minus 2.")
3869 (arg)
3870 register Lisp_Object arg;
3871{
265a9e55 3872 if (NILP (arg))
d834a2e9 3873 XSETFASTINT (arg, window_internal_width (XWINDOW (selected_window)) - 2);
7ab12479
JB
3874 else
3875 arg = Fprefix_numeric_value (arg);
3876
3877 return
3878 Fset_window_hscroll (selected_window,
3879 make_number (XINT (XWINDOW (selected_window)->hscroll)
3880 - XINT (arg)));
3881}
3882
3883DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
44fa5b1e 3884 "Center point in window and redisplay frame. With ARG, put point on line ARG.\n\
7ab12479 3885The desired position of point is always relative to the current window.\n\
44fa5b1e 3886Just C-u as prefix means put point in the center of the window.\n\
413430c5 3887If ARG is omitted or nil, erases the entire frame and then\n\
44fa5b1e 3888redraws with point in the center of the current window.")
413430c5
EN
3889 (arg)
3890 register Lisp_Object arg;
7ab12479
JB
3891{
3892 register struct window *w = XWINDOW (selected_window);
3893 register int ht = window_internal_height (w);
113d9015 3894 struct position pos;
478292ed
RS
3895 struct buffer *buf = XBUFFER (w->buffer);
3896 struct buffer *obuf = current_buffer;
7ab12479 3897
413430c5 3898 if (NILP (arg))
7ab12479 3899 {
44fa5b1e 3900 extern int frame_garbaged;
7ab12479 3901
527b6458 3902 Fredraw_frame (w->frame);
44fa5b1e 3903 SET_FRAME_GARBAGED (XFRAME (WINDOW_FRAME (w)));
413430c5 3904 XSETFASTINT (arg, ht / 2);
7ab12479 3905 }
413430c5 3906 else if (CONSP (arg)) /* Just C-u. */
7ab12479 3907 {
413430c5 3908 XSETFASTINT (arg, ht / 2);
7ab12479
JB
3909 }
3910 else
3911 {
413430c5
EN
3912 arg = Fprefix_numeric_value (arg);
3913 CHECK_NUMBER (arg, 0);
7ab12479
JB
3914 }
3915
413430c5
EN
3916 if (XINT (arg) < 0)
3917 XSETINT (arg, XINT (arg) + ht);
7ab12479 3918
478292ed 3919 set_buffer_internal (buf);
6ec8bbd2 3920 pos = *vmotion (PT, - XINT (arg), w);
7ab12479 3921
b73ea88e
RS
3922 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
3923 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
3924 || FETCH_BYTE (pos.bytepos - 1) == '\n')
113d9015 3925 ? Qt : Qnil);
7ab12479 3926 w->force_start = Qt;
478292ed 3927 set_buffer_internal (obuf);
7ab12479
JB
3928
3929 return Qnil;
3930}
3931\f
3932DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
3933 1, 1, "P",
3934 "Position point relative to window.\n\
19e3bf0a 3935With no argument, position point at center of window.\n\
d81724c7
RS
3936An argument specifies vertical position within the window;\n\
3937zero means top of window, negative means relative to bottom of window.")
7ab12479
JB
3938 (arg)
3939 register Lisp_Object arg;
3940{
3941 register struct window *w = XWINDOW (selected_window);
3942 register int height = window_internal_height (w);
3943 register int start;
540b6aa0 3944 Lisp_Object window;
7ab12479 3945
265a9e55 3946 if (NILP (arg))
d834a2e9 3947 XSETFASTINT (arg, height / 2);
7ab12479
JB
3948 else
3949 {
3950 arg = Fprefix_numeric_value (arg);
3951 if (XINT (arg) < 0)
3952 XSETINT (arg, XINT (arg) + height);
3953 }
3954
3955 start = marker_position (w->start);
74112613 3956 XSETWINDOW (window, w);
7ab12479
JB
3957 if (start < BEGV || start > ZV)
3958 {
cd2be1dd 3959 Fvertical_motion (make_number (- (height / 2)), window);
b73ea88e 3960 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
7ab12479
JB
3961 w->start_at_line_beg = Fbolp ();
3962 w->force_start = Qt;
3963 }
3964 else
b73ea88e 3965 Fgoto_char (w->start);
7ab12479 3966
540b6aa0 3967 return Fvertical_motion (arg, window);
7ab12479 3968}
5500c422
GM
3969
3970
7ab12479 3971\f
5500c422
GM
3972/***********************************************************************
3973 Window Configuration
3974 ***********************************************************************/
3975
7ab12479
JB
3976struct save_window_data
3977 {
f5ccc0cc 3978 EMACS_INT size_from_Lisp_Vector_struct;
7ab12479 3979 struct Lisp_Vector *next_from_Lisp_Vector_struct;
8f6ea2e9 3980 Lisp_Object frame_width, frame_height, frame_menu_bar_lines;
9ea173e8 3981 Lisp_Object frame_tool_bar_lines;
bdc727bf 3982 Lisp_Object selected_frame;
7ab12479
JB
3983 Lisp_Object current_window;
3984 Lisp_Object current_buffer;
3985 Lisp_Object minibuf_scroll_window;
3986 Lisp_Object root_window;
bdc727bf 3987 Lisp_Object focus_frame;
756b6edc
RS
3988 /* Record the values of window-min-width and window-min-height
3989 so that window sizes remain consistent with them. */
3990 Lisp_Object min_width, min_height;
cbff28e8
RS
3991 /* A vector, each of whose elements is a struct saved_window
3992 for one window. */
7ab12479
JB
3993 Lisp_Object saved_windows;
3994 };
ff06df24 3995
cbff28e8 3996/* This is saved as a Lisp_Vector */
7ab12479
JB
3997struct saved_window
3998 {
3999 /* these first two must agree with struct Lisp_Vector in lisp.h */
f5ccc0cc 4000 EMACS_INT size_from_Lisp_Vector_struct;
7ab12479
JB
4001 struct Lisp_Vector *next_from_Lisp_Vector_struct;
4002
4003 Lisp_Object window;
4004 Lisp_Object buffer, start, pointm, mark;
4005 Lisp_Object left, top, width, height, hscroll;
4006 Lisp_Object parent, prev;
4007 Lisp_Object start_at_line_beg;
4008 Lisp_Object display_table;
4009 };
4010#define SAVED_WINDOW_VECTOR_SIZE 14 /* Arg to Fmake_vector */
4011
4012#define SAVED_WINDOW_N(swv,n) \
4013 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
4014
4015DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
cbff28e8 4016 "Return t if OBJECT is a window-configuration object.")
413430c5
EN
4017 (object)
4018 Lisp_Object object;
7ab12479 4019{
413430c5 4020 if (WINDOW_CONFIGURATIONP (object))
7ab12479
JB
4021 return Qt;
4022 return Qnil;
4023}
4024
3f8ab7bd
RS
4025DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
4026 "Return the frame that CONFIG, a window-configuration object, is about.")
4027 (config)
4028 Lisp_Object config;
4029{
4030 register struct save_window_data *data;
4031 struct Lisp_Vector *saved_windows;
4032
4033 if (! WINDOW_CONFIGURATIONP (config))
4034 wrong_type_argument (Qwindow_configuration_p, config);
4035
4036 data = (struct save_window_data *) XVECTOR (config);
4037 saved_windows = XVECTOR (data->saved_windows);
4038 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4039}
4040
d5b2799e
RS
4041DEFUN ("set-window-configuration", Fset_window_configuration,
4042 Sset_window_configuration, 1, 1, 0,
7ab12479
JB
4043 "Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
4044CONFIGURATION must be a value previously returned\n\
3f8ab7bd
RS
4045by `current-window-configuration' (which see).\n\
4046If CONFIGURATION was made from a frame that is now deleted,\n\
4047only frame-independent values can be restored. In this case,\n\
4048the return value is nil. Otherwise the value is t.")
4049 (configuration)
2f83aebe 4050 Lisp_Object configuration;
7ab12479 4051{
7ab12479
JB
4052 register struct save_window_data *data;
4053 struct Lisp_Vector *saved_windows;
7ab12479 4054 Lisp_Object new_current_buffer;
fd482be5 4055 Lisp_Object frame;
44fa5b1e 4056 FRAME_PTR f;
d2b35234 4057 int old_point = -1;
7ab12479 4058
017b2bad 4059 while (!WINDOW_CONFIGURATIONP (configuration))
3f8ab7bd 4060 wrong_type_argument (Qwindow_configuration_p, configuration);
7ab12479 4061
2f83aebe 4062 data = (struct save_window_data *) XVECTOR (configuration);
7ab12479
JB
4063 saved_windows = XVECTOR (data->saved_windows);
4064
7ab12479 4065 new_current_buffer = data->current_buffer;
265a9e55 4066 if (NILP (XBUFFER (new_current_buffer)->name))
7ab12479 4067 new_current_buffer = Qnil;
d2b35234
RS
4068 else
4069 {
4070 if (XBUFFER (new_current_buffer) == current_buffer)
4071 old_point = PT;
cbff28e8 4072
d2b35234 4073 }
7ab12479 4074
fd482be5
JB
4075 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
4076 f = XFRAME (frame);
9ace597f 4077
fd482be5
JB
4078 /* If f is a dead frame, don't bother rebuilding its window tree.
4079 However, there is other stuff we should still try to do below. */
4080 if (FRAME_LIVE_P (f))
7ab12479 4081 {
fd482be5
JB
4082 register struct window *w;
4083 register struct saved_window *p;
5500c422
GM
4084 struct window *root_window;
4085 struct window **leaf_windows;
4086 int n_leaf_windows;
4087 int k, i;
fd482be5
JB
4088
4089 /* If the frame has been resized since this window configuration was
4090 made, we change the frame to the size specified in the
4091 configuration, restore the configuration, and then resize it
4092 back. We keep track of the prevailing height in these variables. */
4093 int previous_frame_height = FRAME_HEIGHT (f);
4094 int previous_frame_width = FRAME_WIDTH (f);
8f6ea2e9 4095 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
9ea173e8 4096 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
fd482be5 4097
d2b35234
RS
4098 /* The mouse highlighting code could get screwed up
4099 if it runs during this. */
4100 BLOCK_INPUT;
4101
fd482be5
JB
4102 if (XFASTINT (data->frame_height) != previous_frame_height
4103 || XFASTINT (data->frame_width) != previous_frame_width)
f8ad443a 4104 change_frame_size (f, XFASTINT (data->frame_height),
2b653806 4105 XFASTINT (data->frame_width), 0, 0, 0);
e3678b64 4106#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
8f6ea2e9
KH
4107 if (XFASTINT (data->frame_menu_bar_lines)
4108 != previous_frame_menu_bar_lines)
f8ad443a 4109 x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
4314246f 4110#ifdef HAVE_WINDOW_SYSTEM
9ea173e8
GM
4111 if (XFASTINT (data->frame_tool_bar_lines)
4112 != previous_frame_tool_bar_lines)
4113 x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
4314246f 4114#endif
217f2871 4115#endif
fd482be5 4116
596ae0cf
RS
4117 if (! NILP (XWINDOW (selected_window)->buffer))
4118 {
4119 w = XWINDOW (selected_window);
4120 set_marker_both (w->pointm,
4121 w->buffer,
4122 BUF_PT (XBUFFER (w->buffer)),
4123 BUF_PT_BYTE (XBUFFER (w->buffer)));
4124 }
4125
fd482be5 4126 windows_or_buffers_changed++;
29aeee73 4127 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
fd482be5 4128
5500c422
GM
4129 /* Problem: Freeing all matrices and later allocating them again
4130 is a serious redisplay flickering problem. What we would
4131 really like to do is to free only those matrices not reused
4132 below. */
4133 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
4134 leaf_windows
4135 = (struct window **) alloca (count_windows (root_window)
4136 * sizeof (struct window *));
4137 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
4138
756b6edc
RS
4139 /* Temporarily avoid any problems with windows that are smaller
4140 than they are supposed to be. */
4141 window_min_height = 1;
4142 window_min_width = 1;
4143
fd482be5
JB
4144 /* Kludge Alert!
4145 Mark all windows now on frame as "deleted".
4146 Restoring the new configuration "undeletes" any that are in it.
37962e60 4147
fd482be5
JB
4148 Save their current buffers in their height fields, since we may
4149 need it later, if a buffer saved in the configuration is now
4150 dead. */
4151 delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
4152
4153 for (k = 0; k < saved_windows->size; k++)
4154 {
4155 p = SAVED_WINDOW_N (saved_windows, k);
4156 w = XWINDOW (p->window);
4157 w->next = Qnil;
7ab12479 4158
fd482be5
JB
4159 if (!NILP (p->parent))
4160 w->parent = SAVED_WINDOW_N (saved_windows,
4161 XFASTINT (p->parent))->window;
4162 else
4163 w->parent = Qnil;
7ab12479 4164
fd482be5 4165 if (!NILP (p->prev))
7ab12479 4166 {
fd482be5
JB
4167 w->prev = SAVED_WINDOW_N (saved_windows,
4168 XFASTINT (p->prev))->window;
4169 XWINDOW (w->prev)->next = p->window;
4170 }
4171 else
4172 {
4173 w->prev = Qnil;
4174 if (!NILP (w->parent))
4175 {
4176 if (EQ (p->width, XWINDOW (w->parent)->width))
4177 {
4178 XWINDOW (w->parent)->vchild = p->window;
4179 XWINDOW (w->parent)->hchild = Qnil;
4180 }
4181 else
4182 {
4183 XWINDOW (w->parent)->hchild = p->window;
4184 XWINDOW (w->parent)->vchild = Qnil;
4185 }
4186 }
4187 }
4188
4189 /* If we squirreled away the buffer in the window's height,
4190 restore it now. */
017b2bad 4191 if (BUFFERP (w->height))
fd482be5
JB
4192 w->buffer = w->height;
4193 w->left = p->left;
4194 w->top = p->top;
4195 w->width = p->width;
4196 w->height = p->height;
4197 w->hscroll = p->hscroll;
4198 w->display_table = p->display_table;
d834a2e9 4199 XSETFASTINT (w->last_modified, 0);
3cd21523 4200 XSETFASTINT (w->last_overlay_modified, 0);
fd482be5
JB
4201
4202 /* Reinstall the saved buffer and pointers into it. */
4203 if (NILP (p->buffer))
4204 w->buffer = p->buffer;
4205 else
4206 {
4207 if (!NILP (XBUFFER (p->buffer)->name))
4208 /* If saved buffer is alive, install it. */
4209 {
4210 w->buffer = p->buffer;
4211 w->start_at_line_beg = p->start_at_line_beg;
b73ea88e
RS
4212 set_marker_restricted (w->start, p->start, w->buffer);
4213 set_marker_restricted (w->pointm, p->pointm, w->buffer);
fd482be5 4214 Fset_marker (XBUFFER (w->buffer)->mark,
b73ea88e 4215 p->mark, w->buffer);
fd482be5
JB
4216
4217 /* As documented in Fcurrent_window_configuration, don't
4218 save the location of point in the buffer which was current
4219 when the window configuration was recorded. */
6b54027b
RS
4220 if (!EQ (p->buffer, new_current_buffer)
4221 && XBUFFER (p->buffer) == current_buffer)
fd482be5
JB
4222 Fgoto_char (w->pointm);
4223 }
52a68e98
RS
4224 else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
4225 /* Else unless window has a live buffer, get one. */
7ab12479 4226 {
fd482be5
JB
4227 w->buffer = Fcdr (Fcar (Vbuffer_alist));
4228 /* This will set the markers to beginning of visible
4229 range. */
4230 set_marker_restricted (w->start, make_number (0), w->buffer);
4231 set_marker_restricted (w->pointm, make_number (0),w->buffer);
4232 w->start_at_line_beg = Qt;
7ab12479
JB
4233 }
4234 else
fd482be5 4235 /* Keeping window's old buffer; make sure the markers
52a68e98 4236 are real. */
7ab12479 4237 {
fd482be5
JB
4238 /* Set window markers at start of visible range. */
4239 if (XMARKER (w->start)->buffer == 0)
4240 set_marker_restricted (w->start, make_number (0),
4241 w->buffer);
4242 if (XMARKER (w->pointm)->buffer == 0)
b73ea88e
RS
4243 set_marker_restricted_both (w->pointm, w->buffer,
4244 BUF_PT (XBUFFER (w->buffer)),
4245 BUF_PT_BYTE (XBUFFER (w->buffer)));
fd482be5 4246 w->start_at_line_beg = Qt;
7ab12479
JB
4247 }
4248 }
4249 }
9ace597f 4250
fd482be5
JB
4251 FRAME_ROOT_WINDOW (f) = data->root_window;
4252 Fselect_window (data->current_window);
396a830c
RS
4253 XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
4254 = selected_window;
7ab12479 4255
db269683 4256 if (NILP (data->focus_frame)
017b2bad 4257 || (FRAMEP (data->focus_frame)
db269683
JB
4258 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
4259 Fredirect_frame_focus (frame, data->focus_frame);
7ab12479 4260
fd482be5
JB
4261#if 0 /* I don't understand why this is needed, and it causes problems
4262 when the frame's old selected window has been deleted. */
e4e59717 4263 if (f != selected_frame && FRAME_WINDOW_P (f))
9a7c6fc3
RS
4264 do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
4265 Qnil, 0);
fd482be5
JB
4266#endif
4267
4268 /* Set the screen height to the value it had before this function. */
4269 if (previous_frame_height != FRAME_HEIGHT (f)
4270 || previous_frame_width != FRAME_WIDTH (f))
4271 change_frame_size (f, previous_frame_height, previous_frame_width,
2b653806 4272 0, 0, 0);
e3678b64 4273#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
8f6ea2e9 4274 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
f8ad443a
AS
4275 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
4276 make_number (0));
4314246f 4277#ifdef HAVE_WINDOW_SYSTEM
9ea173e8
GM
4278 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
4279 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
4280 make_number (0));
4314246f 4281#endif
217f2871 4282#endif
d2b35234 4283
5500c422
GM
4284 /* Now, free glyph matrices in windows that were not reused. */
4285 for (i = 0; i < n_leaf_windows; ++i)
4286 if (NILP (leaf_windows[i]->buffer))
4287 {
4288 /* Assert it's not reused as a combination. */
4289 xassert (NILP (leaf_windows[i]->hchild)
4290 && NILP (leaf_windows[i]->vchild));
4291 free_window_matrices (leaf_windows[i]);
4292 SET_FRAME_GARBAGED (f);
4293 }
4294
4295 adjust_glyphs (f);
4296
d2b35234 4297 UNBLOCK_INPUT;
756b6edc 4298
478292ed
RS
4299 /* Fselect_window will have made f the selected frame, so we
4300 reselect the proper frame here. Fhandle_switch_frame will change the
4301 selected window too, but that doesn't make the call to
4302 Fselect_window above totally superfluous; it still sets f's
4303 selected window. */
4304 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
4305 do_switch_frame (data->selected_frame, Qnil, 0);
4306
4307 if (! NILP (Vwindow_configuration_change_hook)
4308 && ! NILP (Vrun_hooks))
4309 call1 (Vrun_hooks, Qwindow_configuration_change_hook);
4310 }
bdc727bf
JB
4311
4312 if (!NILP (new_current_buffer))
d2b35234
RS
4313 {
4314 Fset_buffer (new_current_buffer);
4315
4316 /* If the buffer that is current now is the same
4317 that was current before setting the window configuration,
4318 don't alter its PT. */
4319 if (old_point >= 0)
4320 SET_PT (old_point);
4321 }
bdc727bf 4322
478292ed
RS
4323 /* Restore the minimum heights recorded in the configuration. */
4324 window_min_height = XINT (data->min_height);
4325 window_min_width = XINT (data->min_width);
543f5fb1 4326
478292ed 4327 Vminibuf_scroll_window = data->minibuf_scroll_window;
543f5fb1 4328
3f8ab7bd 4329 return (FRAME_LIVE_P (f) ? Qt : Qnil);
7ab12479
JB
4330}
4331
44fa5b1e 4332/* Mark all windows now on frame as deleted
7ab12479
JB
4333 by setting their buffers to nil. */
4334
fd482be5 4335void
7ab12479
JB
4336delete_all_subwindows (w)
4337 register struct window *w;
4338{
265a9e55 4339 if (!NILP (w->next))
7ab12479 4340 delete_all_subwindows (XWINDOW (w->next));
265a9e55 4341 if (!NILP (w->vchild))
7ab12479 4342 delete_all_subwindows (XWINDOW (w->vchild));
265a9e55 4343 if (!NILP (w->hchild))
7ab12479 4344 delete_all_subwindows (XWINDOW (w->hchild));
605be8af
JB
4345
4346 w->height = w->buffer; /* See Fset_window_configuration for excuse. */
4347
86e48436
RS
4348 if (!NILP (w->buffer))
4349 unshow_buffer (w);
4350
605be8af
JB
4351 /* We set all three of these fields to nil, to make sure that we can
4352 distinguish this dead window from any live window. Live leaf
4353 windows will have buffer set, and combination windows will have
4354 vchild or hchild set. */
4355 w->buffer = Qnil;
4356 w->vchild = Qnil;
4357 w->hchild = Qnil;
7ab12479
JB
4358}
4359\f
4360static int
4361count_windows (window)
4362 register struct window *window;
4363{
4364 register int count = 1;
265a9e55 4365 if (!NILP (window->next))
7ab12479 4366 count += count_windows (XWINDOW (window->next));
265a9e55 4367 if (!NILP (window->vchild))
7ab12479 4368 count += count_windows (XWINDOW (window->vchild));
265a9e55 4369 if (!NILP (window->hchild))
7ab12479
JB
4370 count += count_windows (XWINDOW (window->hchild));
4371 return count;
4372}
4373
5500c422
GM
4374
4375/* Fill vector FLAT with leaf windows under W, starting at index I.
4376 Value is last index + 1. */
4377
4378static int
4379get_leaf_windows (w, flat, i)
4380 struct window *w;
4381 struct window **flat;
4382 int i;
4383{
4384 while (w)
4385 {
4386 if (!NILP (w->hchild))
4387 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
4388 else if (!NILP (w->vchild))
4389 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
4390 else
4391 flat[i++] = w;
4392
4393 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4394 }
4395
4396 return i;
4397}
4398
4399
4400/* Return a pointer to the glyph W's physical cursor is on. Value is
4401 null if W's current matrix is invalid, so that no meaningfull glyph
4402 can be returned. */
4403
4404struct glyph *
4405get_phys_cursor_glyph (w)
4406 struct window *w;
4407{
4408 struct glyph_row *row;
4409 struct glyph *glyph;
4410
4411 if (w->phys_cursor.vpos >= 0
4412 && w->phys_cursor.vpos < w->current_matrix->nrows
4413 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
4414 row->enabled_p)
4415 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
4416 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
4417 else
4418 glyph = NULL;
4419
4420 return glyph;
4421}
4422
4423
7ab12479
JB
4424static int
4425save_window_save (window, vector, i)
4426 Lisp_Object window;
4427 struct Lisp_Vector *vector;
4428 int i;
4429{
4430 register struct saved_window *p;
4431 register struct window *w;
4432 register Lisp_Object tem;
4433
265a9e55 4434 for (;!NILP (window); window = w->next)
7ab12479
JB
4435 {
4436 p = SAVED_WINDOW_N (vector, i);
4437 w = XWINDOW (window);
4438
d834a2e9 4439 XSETFASTINT (w->temslot, i++);
7ab12479
JB
4440 p->window = window;
4441 p->buffer = w->buffer;
4442 p->left = w->left;
4443 p->top = w->top;
4444 p->width = w->width;
4445 p->height = w->height;
4446 p->hscroll = w->hscroll;
4447 p->display_table = w->display_table;
265a9e55 4448 if (!NILP (w->buffer))
7ab12479
JB
4449 {
4450 /* Save w's value of point in the window configuration.
4451 If w is the selected window, then get the value of point
4452 from the buffer; pointm is garbage in the selected window. */
4453 if (EQ (window, selected_window))
4454 {
4455 p->pointm = Fmake_marker ();
b73ea88e
RS
4456 set_marker_both (p->pointm, w->buffer,
4457 BUF_PT (XBUFFER (w->buffer)),
4458 BUF_PT_BYTE (XBUFFER (w->buffer)));
7ab12479
JB
4459 }
4460 else
eeb82665 4461 p->pointm = Fcopy_marker (w->pointm, Qnil);
7ab12479 4462
eeb82665 4463 p->start = Fcopy_marker (w->start, Qnil);
7ab12479
JB
4464 p->start_at_line_beg = w->start_at_line_beg;
4465
4466 tem = XBUFFER (w->buffer)->mark;
eeb82665 4467 p->mark = Fcopy_marker (tem, Qnil);
7ab12479
JB
4468 }
4469 else
4470 {
4471 p->pointm = Qnil;
4472 p->start = Qnil;
4473 p->mark = Qnil;
4474 p->start_at_line_beg = Qnil;
4475 }
4476
265a9e55 4477 if (NILP (w->parent))
7ab12479
JB
4478 p->parent = Qnil;
4479 else
4480 p->parent = XWINDOW (w->parent)->temslot;
4481
265a9e55 4482 if (NILP (w->prev))
7ab12479
JB
4483 p->prev = Qnil;
4484 else
4485 p->prev = XWINDOW (w->prev)->temslot;
4486
265a9e55 4487 if (!NILP (w->vchild))
7ab12479 4488 i = save_window_save (w->vchild, vector, i);
265a9e55 4489 if (!NILP (w->hchild))
7ab12479
JB
4490 i = save_window_save (w->hchild, vector, i);
4491 }
4492
4493 return i;
4494}
4495
a0d76c27
EN
4496DEFUN ("current-window-configuration", Fcurrent_window_configuration,
4497 Scurrent_window_configuration, 0, 1, 0,
44fa5b1e
JB
4498 "Return an object representing the current window configuration of FRAME.\n\
4499If FRAME is nil or omitted, use the selected frame.\n\
7ab12479
JB
4500This describes the number of windows, their sizes and current buffers,\n\
4501and for each displayed buffer, where display starts, and the positions of\n\
4502point and mark. An exception is made for point in the current buffer:\n\
bdc727bf
JB
4503its value is -not- saved.\n\
4504This also records the currently selected frame, and FRAME's focus\n\
4505redirection (see `redirect-frame-focus').")
44fa5b1e
JB
4506 (frame)
4507 Lisp_Object frame;
7ab12479
JB
4508{
4509 register Lisp_Object tem;
4510 register int n_windows;
4511 register struct save_window_data *data;
da2792e0 4512 register struct Lisp_Vector *vec;
7ab12479 4513 register int i;
44fa5b1e 4514 FRAME_PTR f;
43bad991 4515
44fa5b1e 4516 if (NILP (frame))
1ae1a37d
GM
4517 frame = selected_frame;
4518 CHECK_LIVE_FRAME (frame, 0);
4519 f = XFRAME (frame);
7ab12479 4520
44fa5b1e 4521 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
da2792e0
KH
4522 vec = allocate_vectorlike (VECSIZE (struct save_window_data));
4523 for (i = 0; i < VECSIZE (struct save_window_data); i++)
4524 vec->contents[i] = Qnil;
4525 vec->size = VECSIZE (struct save_window_data);
4526 data = (struct save_window_data *)vec;
4527
d834a2e9
KH
4528 XSETFASTINT (data->frame_width, FRAME_WIDTH (f));
4529 XSETFASTINT (data->frame_height, FRAME_HEIGHT (f));
4530 XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
9ea173e8 4531 XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
1ae1a37d 4532 data->selected_frame = selected_frame;
44fa5b1e 4533 data->current_window = FRAME_SELECTED_WINDOW (f);
74112613 4534 XSETBUFFER (data->current_buffer, current_buffer);
7ab12479 4535 data->minibuf_scroll_window = Vminibuf_scroll_window;
44fa5b1e 4536 data->root_window = FRAME_ROOT_WINDOW (f);
bdc727bf 4537 data->focus_frame = FRAME_FOCUS_FRAME (f);
74112613
KH
4538 XSETINT (data->min_height, window_min_height);
4539 XSETINT (data->min_width, window_min_width);
7ab12479
JB
4540 tem = Fmake_vector (make_number (n_windows), Qnil);
4541 data->saved_windows = tem;
4542 for (i = 0; i < n_windows; i++)
4543 XVECTOR (tem)->contents[i]
4544 = Fmake_vector (make_number (SAVED_WINDOW_VECTOR_SIZE), Qnil);
44fa5b1e 4545 save_window_save (FRAME_ROOT_WINDOW (f),
7ab12479 4546 XVECTOR (tem), 0);
74112613 4547 XSETWINDOW_CONFIGURATION (tem, data);
7ab12479
JB
4548 return (tem);
4549}
4550
4551DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
4552 0, UNEVALLED, 0,
4553 "Execute body, preserving window sizes and contents.\n\
eb16ec06
RS
4554Restore which buffer appears in which window, where display starts,\n\
4555and the value of point and mark for each window.\n\
4556Also restore which buffer is current.\n\
4557But do not preserve point in the current buffer.\n\
7ab12479
JB
4558Does not restore the value of point in current buffer.")
4559 (args)
4560 Lisp_Object args;
4561{
4562 register Lisp_Object val;
4563 register int count = specpdl_ptr - specpdl;
4564
4565 record_unwind_protect (Fset_window_configuration,
43bad991 4566 Fcurrent_window_configuration (Qnil));
7ab12479
JB
4567 val = Fprogn (args);
4568 return unbind_to (count, val);
4569}
5500c422
GM
4570
4571\f
4572/***********************************************************************
4573 Marginal Areas
4574 ***********************************************************************/
4575
4576DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
4577 2, 3, "",
4578 "Set width of marginal areas of window WINDOW.\n\
4579If window is nil or omitted, set margins of the currently selected window.\n\
4580First parameter LEFT-WIDTH specifies the number of character\n\
4581cells to reserve for the left marginal area. Second parameter\n\
4582RIGHT-WIDTH does the same for the right marginal area.\n\
4583A nil width parameter means no margin.")
cfa22082 4584 (window, left, right)
5500c422
GM
4585 Lisp_Object window, left, right;
4586{
4587 struct window *w = decode_window (window);
4588 struct frame *f = XFRAME (w->frame);
4589
4590 if (!NILP (left))
cfa22082 4591 CHECK_NUMBER_OR_FLOAT (left, 1);
5500c422 4592 if (!NILP (right))
cfa22082 4593 CHECK_NUMBER_OR_FLOAT (right, 2);
5500c422
GM
4594
4595 /* Check widths < 0 and translate a zero width to nil.
4596 Margins that are too wide have to be checked elsewhere. */
4597 if ((INTEGERP (left) && XINT (left) < 0)
4598 || (FLOATP (left) && XFLOAT (left)->data <= 0))
4599 XSETFASTINT (left, 0);
4600 if (INTEGERP (left) && XFASTINT (left) == 0)
4601 left = Qnil;
4602
4603 if ((INTEGERP (right) && XINT (right) < 0)
4604 || (FLOATP (right) && XFLOAT (right)->data <= 0))
4605 XSETFASTINT (right, 0);
4606 if (INTEGERP (right) && XFASTINT (right) == 0)
4607 right = Qnil;
4608
4609 w->left_margin_width = left;
4610 w->right_margin_width = right;
4611
4612 ++windows_or_buffers_changed;
4613 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
4614 return Qnil;
4615}
4616
4617
4618DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
4619 0, 1, 0,
4620 "Get width of marginal areas of window WINDOW.\n\
4621If WINDOW is omitted or nil, use the currently selected window.\n\
4622Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).\n\
4623If a marginal area does not exist, its width will be returned\n\
4624as nil.")
4625 (window)
4626 Lisp_Object window;
4627{
4628 struct window *w = decode_window (window);
4629 return Fcons (w->left_margin_width, w->right_margin_width);
4630}
4631
4632
7ab12479 4633\f
5500c422
GM
4634/***********************************************************************
4635 Smooth scrolling
4636 ***********************************************************************/
4637
4638DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 1, 0,
4639 "Return the amount by which WINDOW is scrolled vertically.\n\
4640Use the selected window if WINDOW is nil or omitted.\n\
4641Value is a multiple of the canonical character height of WINDOW.")
4642 (window)
4643 Lisp_Object window;
4644{
47004952 4645 Lisp_Object result;
5500c422
GM
4646 struct frame *f;
4647 struct window *w;
4648
4649 if (NILP (window))
4650 window = selected_window;
47004952
GM
4651 else
4652 CHECK_WINDOW (window, 0);
5500c422
GM
4653 w = XWINDOW (window);
4654 f = XFRAME (w->frame);
4655
4656 if (FRAME_WINDOW_P (f))
47004952 4657 result = CANON_Y_FROM_PIXEL_Y (f, -w->vscroll);
5500c422 4658 else
47004952
GM
4659 result = make_number (0);
4660 return result;
5500c422
GM
4661}
4662
4663
4664DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
47004952
GM
4665 2, 2, 0,
4666 "Set amount by which WINDOW should be scrolled vertically to VSCROLL.\n\
5500c422 4667WINDOW nil or omitted means use the selected window. VSCROLL is a\n\
47004952
GM
4668non-negative multiple of the canonical character height of WINDOW.")
4669 (window, vscroll)
4670 Lisp_Object window, vscroll;
5500c422
GM
4671{
4672 struct window *w;
4673 struct frame *f;
4674
5500c422
GM
4675 if (NILP (window))
4676 window = selected_window;
47004952
GM
4677 else
4678 CHECK_WINDOW (window, 0);
4679 CHECK_NUMBER_OR_FLOAT (vscroll, 1);
4680
5500c422
GM
4681 w = XWINDOW (window);
4682 f = XFRAME (w->frame);
4683
4684 if (FRAME_WINDOW_P (f))
4685 {
4686 int old_dy = w->vscroll;
47004952
GM
4687
4688 w->vscroll = - CANON_Y_UNIT (f) * XFLOATINT (vscroll);
4689 w->vscroll = min (w->vscroll, 0);
5500c422
GM
4690
4691 /* Adjust glyph matrix of the frame if the virtual display
4692 area becomes larger than before. */
4693 if (w->vscroll < 0 && w->vscroll < old_dy)
4694 adjust_glyphs (f);
4695
4696 /* Prevent redisplay shortcuts. */
b1599b4c 4697 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
5500c422
GM
4698 }
4699
47004952 4700 return Fwindow_vscroll (window);
5500c422
GM
4701}
4702
7bbb5782
GM
4703\f
4704/* Call FN for all leaf windows on frame F. FN is called with the
4705 first argument being a pointer to the leaf window, and with
4706 additional arguments A1..A4. */
4707
4708void
4709foreach_window (f, fn, a1, a2, a3, a4)
4710 struct frame *f;
4711 void (* fn) ();
4712 int a1, a2, a3, a4;
4713{
4714 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, a1, a2, a3, a4);
4715}
4716
4717
4718/* Helper function for foreach_window. Call FN for all leaf windows
4719 reachable from W. FN is called with the first argument being a
4720 pointer to the leaf window, and with additional arguments A1..A4. */
4721
4722static void
4723foreach_window_1 (w, fn, a1, a2, a3, a4)
4724 struct window *w;
4725 void (* fn) ();
4726 int a1, a2, a3, a4;
4727{
4728 while (w)
4729 {
4730 if (!NILP (w->hchild))
4731 foreach_window_1 (XWINDOW (w->hchild), fn, a1, a2, a3, a4);
4732 else if (!NILP (w->vchild))
4733 foreach_window_1 (XWINDOW (w->vchild), fn, a1, a2, a3, a4);
4734 else
4735 fn (w, a1, a2, a3, a4);
4736
4737 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4738 }
4739}
4740
4741
4742/* Freeze or unfreeze the window start of W if unless it is a
4743 mini-window or the selected window. FREEZE_P non-zero means freeze
4744 the window start. */
4745
4746static void
4747freeze_window_start (w, freeze_p)
4748 struct window *w;
4749 int freeze_p;
4750{
4751 if (w == XWINDOW (selected_window)
4752 || MINI_WINDOW_P (w)
4753 || (MINI_WINDOW_P (XWINDOW (selected_window))
4754 && w == XWINDOW (Vminibuf_scroll_window)))
4755 freeze_p = 0;
4756
4757 w->frozen_window_start_p = freeze_p;
4758}
4759
4760
4761/* Freeze or unfreeze the window starts of all leaf windows on frame
4762 F, except the selected window and a mini-window. FREEZE_P non-zero
4763 means freeze the window start. */
4764
4765void
4766freeze_window_starts (f, freeze_p)
4767 struct frame *f;
4768 int freeze_p;
4769{
4770 foreach_window (f, freeze_window_start, freeze_p);
4771}
5500c422
GM
4772
4773\f
4774/***********************************************************************
4775 Initialization
4776 ***********************************************************************/
4777
cbff28e8
RS
4778/* Return 1 if window configurations C1 and C2
4779 describe the same state of affairs. This is used by Fequal. */
4780
4781int
2f8274be 4782compare_window_configurations (c1, c2, ignore_positions)
cbff28e8 4783 Lisp_Object c1, c2;
2f8274be 4784 int ignore_positions;
cbff28e8
RS
4785{
4786 register struct save_window_data *d1, *d2;
4787 struct Lisp_Vector *sw1, *sw2;
4788 int i;
4789
4790 d1 = (struct save_window_data *) XVECTOR (c1);
4791 d2 = (struct save_window_data *) XVECTOR (c2);
4792 sw1 = XVECTOR (d1->saved_windows);
4793 sw2 = XVECTOR (d2->saved_windows);
4794
4795 if (! EQ (d1->frame_width, d2->frame_width))
4796 return 0;
4797 if (! EQ (d1->frame_height, d2->frame_height))
4798 return 0;
4799 if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
4800 return 0;
4801 if (! EQ (d1->selected_frame, d2->selected_frame))
4802 return 0;
4803 /* Don't compare the current_window field directly.
4804 Instead see w1_is_current and w2_is_current, below. */
4805 if (! EQ (d1->current_buffer, d2->current_buffer))
4806 return 0;
2f8274be
RS
4807 if (! ignore_positions)
4808 if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
4809 return 0;
cbff28e8
RS
4810 /* Don't compare the root_window field.
4811 We don't require the two configurations
4812 to use the same window object,
4813 and the two root windows must be equivalent
4814 if everything else compares equal. */
4815 if (! EQ (d1->focus_frame, d2->focus_frame))
4816 return 0;
4817 if (! EQ (d1->min_width, d2->min_width))
4818 return 0;
4819 if (! EQ (d1->min_height, d2->min_height))
4820 return 0;
4821
4822 /* Verify that the two confis have the same number of windows. */
4823 if (sw1->size != sw2->size)
4824 return 0;
4825
4826 for (i = 0; i < sw1->size; i++)
4827 {
4828 struct saved_window *p1, *p2;
4829 int w1_is_current, w2_is_current;
4830
4831 p1 = SAVED_WINDOW_N (sw1, i);
4832 p2 = SAVED_WINDOW_N (sw2, i);
4833
4834 /* Verify that the current windows in the two
4835 configurations correspond to each other. */
4836 w1_is_current = EQ (d1->current_window, p1->window);
4837 w2_is_current = EQ (d2->current_window, p2->window);
4838
4839 if (w1_is_current != w2_is_current)
4840 return 0;
4841
4842 /* Verify that the corresponding windows do match. */
4843 if (! EQ (p1->buffer, p2->buffer))
4844 return 0;
4845 if (! EQ (p1->left, p2->left))
4846 return 0;
4847 if (! EQ (p1->top, p2->top))
4848 return 0;
4849 if (! EQ (p1->width, p2->width))
4850 return 0;
4851 if (! EQ (p1->height, p2->height))
4852 return 0;
cbff28e8
RS
4853 if (! EQ (p1->display_table, p2->display_table))
4854 return 0;
4855 if (! EQ (p1->parent, p2->parent))
4856 return 0;
4857 if (! EQ (p1->prev, p2->prev))
4858 return 0;
2f8274be
RS
4859 if (! ignore_positions)
4860 {
4861 if (! EQ (p1->hscroll, p2->hscroll))
4862 return 0;
4863 if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
4864 return 0;
4865 if (NILP (Fequal (p1->start, p2->start)))
4866 return 0;
4867 if (NILP (Fequal (p1->pointm, p2->pointm)))
4868 return 0;
4869 if (NILP (Fequal (p1->mark, p2->mark)))
4870 return 0;
4871 }
cbff28e8
RS
4872 }
4873
4874 return 1;
4875}
2f8274be
RS
4876
4877DEFUN ("compare-window-configurations", Fcompare_window_configurations,
4878 Scompare_window_configurations, 2, 2, 0,
4879 "Compare two window configurations as regards the structure of windows.\n\
4880This function ignores details such as the values of point and mark\n\
4881and scrolling positions.")
4882 (x, y)
4883 Lisp_Object x, y;
4884{
4885 if (compare_window_configurations (x, y, 1))
4886 return Qt;
4887 return Qnil;
4888}
cbff28e8 4889\f
dfcf069d 4890void
7ab12479
JB
4891init_window_once ()
4892{
1ae1a37d
GM
4893 struct frame *f = make_terminal_frame ();
4894 XSETFRAME (selected_frame, f);
4895 Vterminal_frame = selected_frame;
4896 minibuf_window = f->minibuffer_window;
4897 selected_window = f->selected_window;
4898 last_nonminibuf_frame = f;
5b03d3c0
RS
4899
4900 window_initialized = 1;
7ab12479
JB
4901}
4902
dfcf069d 4903void
7ab12479
JB
4904syms_of_window ()
4905{
fbad6f9a
GM
4906 Qleft_bitmap_area = intern ("left-bitmap-area");
4907 staticpro (&Qleft_bitmap_area);
4908 Qright_bitmap_area = intern ("right-bitmap-area");
4909 staticpro (&Qright_bitmap_area);
4910
8a37516b
GM
4911 Qwindow_size_fixed = intern ("window-size-fixed");
4912 staticpro (&Qwindow_size_fixed);
233a4a2c 4913
543f5fb1
RS
4914 staticpro (&Qwindow_configuration_change_hook);
4915 Qwindow_configuration_change_hook
4916 = intern ("window-configuration-change-hook");
4917
7ab12479
JB
4918 Qwindowp = intern ("windowp");
4919 staticpro (&Qwindowp);
4920
3f8ab7bd
RS
4921 Qwindow_configuration_p = intern ("window-configuration-p");
4922 staticpro (&Qwindow_configuration_p);
4923
806b4d9b
JB
4924 Qwindow_live_p = intern ("window-live-p");
4925 staticpro (&Qwindow_live_p);
605be8af 4926
2cccc823 4927 Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
a58ec57d
RS
4928 staticpro (&Qtemp_buffer_show_hook);
4929
7ab12479
JB
4930 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
4931 "Non-nil means call as function to display a help buffer.\n\
c3ef6b1d 4932The function is called with one argument, the buffer to be displayed.\n\
f52cca03
RS
4933Used by `with-output-to-temp-buffer'.\n\
4934If this function is used, then it must do the entire job of showing\n\
4935the buffer; `temp-buffer-show-hook' is not run unless this function runs it.");
7ab12479
JB
4936 Vtemp_buffer_show_function = Qnil;
4937
4938 DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
4939 "If non-nil, function to call to handle `display-buffer'.\n\
4940It will receive two args, the buffer and a flag which if non-nil means\n\
4941 that the currently selected window is not acceptable.\n\
4942Commands such as `switch-to-buffer-other-window' and `find-file-other-window'\n\
4943work using this function.");
4944 Vdisplay_buffer_function = Qnil;
4945
7ab12479
JB
4946 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
4947 "Non-nil means it is the window that C-M-v in minibuffer should scroll.");
4948 Vminibuf_scroll_window = Qnil;
4949
4950 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
4951 "If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
4952 Vother_window_scroll_buffer = Qnil;
4953
44fa5b1e 4954 DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
700f75a4 4955 "*Non-nil means `display-buffer' should make a separate frame.");
44fa5b1e 4956 pop_up_frames = 0;
7ab12479 4957
44fa5b1e 4958 DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
a90712c2 4959 "Function to call to handle automatic new frame creation.\n\
44fa5b1e 4960It is called with no arguments and should return a newly created frame.\n\
7ab12479 4961\n\
44fa5b1e
JB
4962A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
4963where `pop-up-frame-alist' would hold the default frame parameters.");
4964 Vpop_up_frame_function = Qnil;
7ab12479 4965
a90712c2
RS
4966 DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
4967 "*List of buffer names that should have their own special frames.\n\
4968Displaying a buffer whose name is in this list makes a special frame for it\n\
524580a4 4969using `special-display-function'. See also `special-display-regexps'.\n\
3548e138 4970\n\
524580a4
RS
4971An element of the list can be a list instead of just a string.\n\
4972There are two ways to use a list as an element:\n\
4973 (BUFFER FRAME-PARAMETERS...) (BUFFER FUNCTION OTHER-ARGS...)\n\
4974In the first case, FRAME-PARAMETERS are used to create the frame.\n\
4975In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
4976followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
4caa7448
RS
4977All this is done by the function found in `special-display-function'.\n\
4978\n\
4979If this variable appears \"not to work\", because you add a name to it\n\
4980but that buffer still appears in the selected window, look at the\n\
4981values of `same-window-buffer-names' and `same-window-regexps'.\n\
4982Those variables take precedence over this one.");
a90712c2
RS
4983 Vspecial_display_buffer_names = Qnil;
4984
4985 DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
4986 "*List of regexps saying which buffers should have their own special frames.\n\
4987If a buffer name matches one of these regexps, it gets its own frame.\n\
4988Displaying a buffer whose name is in this list makes a special frame for it\n\
0a952b57 4989using `special-display-function'.\n\
3548e138 4990\n\
524580a4
RS
4991An element of the list can be a list instead of just a string.\n\
4992There are two ways to use a list as an element:\n\
4993 (REGEXP FRAME-PARAMETERS...) (REGEXP FUNCTION OTHER-ARGS...)\n\
4994In the first case, FRAME-PARAMETERS are used to create the frame.\n\
4995In the latter case, FUNCTION is called with the buffer as first argument,\n\
4996followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
4caa7448
RS
4997All this is done by the function found in `special-display-function'.\n\
4998\n\
4999If this variable appears \"not to work\", because you add a regexp to it\n\
5000but the matching buffers still appear in the selected window, look at the\n\
5001values of `same-window-buffer-names' and `same-window-regexps'.\n\
5002Those variables take precedence over this one.");
a90712c2
RS
5003 Vspecial_display_regexps = Qnil;
5004
5005 DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
5006 "Function to call to make a new frame for a special buffer.\n\
0a952b57
RS
5007It is called with two arguments, the buffer and optional buffer specific\n\
5008data, and should return a window displaying that buffer.\n\
a90712c2 5009The default value makes a separate frame for the buffer,\n\
bdd3a802 5010using `special-display-frame-alist' to specify the frame parameters.\n\
a90712c2
RS
5011\n\
5012A buffer is special if its is listed in `special-display-buffer-names'\n\
5013or matches a regexp in `special-display-regexps'.");
5014 Vspecial_display_function = Qnil;
5015
855d8627
RS
5016 DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
5017 "*List of buffer names that should appear in the selected window.\n\
5018Displaying one of these buffers using `display-buffer' or `pop-to-buffer'\n\
5019switches to it in the selected window, rather than making it appear\n\
2e5ce1a0 5020in some other window.\n\
855d8627
RS
5021\n\
5022An element of the list can be a cons cell instead of just a string.\n\
5023Then the car must be a string, which specifies the buffer name.\n\
5024This is for compatibility with `special-display-buffer-names';\n\
5025the cdr of the cons cell is ignored.\n\
5026\n\
5027See also `same-window-regexps'.");
5028 Vsame_window_buffer_names = Qnil;
5029
5030 DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
5031 "*List of regexps saying which buffers should appear in the selected window.\n\
5032If a buffer name matches one of these regexps, then displaying it\n\
5033using `display-buffer' or `pop-to-buffer' switches to it\n\
5034in the selected window, rather than making it appear in some other window.\n\
5035\n\
5036An element of the list can be a cons cell instead of just a string.\n\
5037Then the car must be a string, which specifies the buffer name.\n\
5038This is for compatibility with `special-display-buffer-names';\n\
5039the cdr of the cons cell is ignored.\n\
5040\n\
5041See also `same-window-buffer-names'.");
5042 Vsame_window_regexps = Qnil;
5043
7ab12479
JB
5044 DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
5045 "*Non-nil means display-buffer should make new windows.");
5046 pop_up_windows = 1;
5047
5048 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
5049 "*Number of lines of continuity when scrolling by screenfuls.");
5050 next_screen_context_lines = 2;
5051
5052 DEFVAR_INT ("split-height-threshold", &split_height_threshold,
5053 "*display-buffer would prefer to split the largest window if this large.\n\
5054If there is only one window, it is split regardless of this value.");
5055 split_height_threshold = 500;
5056
5057 DEFVAR_INT ("window-min-height", &window_min_height,
5058 "*Delete any window less than this tall (including its mode line).");
5059 window_min_height = 4;
5060
5061 DEFVAR_INT ("window-min-width", &window_min_width,
5062 "*Delete any window less than this wide.");
5063 window_min_width = 10;
5064
5500c422
GM
5065 DEFVAR_LISP ("scroll-preserve-screen-position",
5066 &Vscroll_preserve_screen_position,
9317a85d 5067 "*Nonzero means scroll commands move point to keep its screen line unchanged.");
5500c422 5068 Vscroll_preserve_screen_position = Qnil;
9317a85d 5069
543f5fb1
RS
5070 DEFVAR_LISP ("window-configuration-change-hook",
5071 &Vwindow_configuration_change_hook,
5072 "Functions to call when window configuration changes.\n\
e3e041eb 5073The selected frame is the one whose configuration has changed.");
543f5fb1
RS
5074 Vwindow_configuration_change_hook = Qnil;
5075
7ab12479
JB
5076 defsubr (&Sselected_window);
5077 defsubr (&Sminibuffer_window);
5078 defsubr (&Swindow_minibuffer_p);
5079 defsubr (&Swindowp);
806b4d9b 5080 defsubr (&Swindow_live_p);
7ab12479
JB
5081 defsubr (&Spos_visible_in_window_p);
5082 defsubr (&Swindow_buffer);
5083 defsubr (&Swindow_height);
5084 defsubr (&Swindow_width);
5085 defsubr (&Swindow_hscroll);
5086 defsubr (&Sset_window_hscroll);
190eb263
RS
5087 defsubr (&Swindow_redisplay_end_trigger);
5088 defsubr (&Sset_window_redisplay_end_trigger);
7ab12479 5089 defsubr (&Swindow_edges);
d5783c40
JB
5090 defsubr (&Scoordinates_in_window_p);
5091 defsubr (&Swindow_at);
7ab12479
JB
5092 defsubr (&Swindow_point);
5093 defsubr (&Swindow_start);
5094 defsubr (&Swindow_end);
5095 defsubr (&Sset_window_point);
5096 defsubr (&Sset_window_start);
5097 defsubr (&Swindow_dedicated_p);
d207b766 5098 defsubr (&Sset_window_dedicated_p);
7ab12479
JB
5099 defsubr (&Swindow_display_table);
5100 defsubr (&Sset_window_display_table);
5101 defsubr (&Snext_window);
5102 defsubr (&Sprevious_window);
5103 defsubr (&Sother_window);
5104 defsubr (&Sget_lru_window);
5105 defsubr (&Sget_largest_window);
5106 defsubr (&Sget_buffer_window);
5107 defsubr (&Sdelete_other_windows);
5108 defsubr (&Sdelete_windows_on);
5109 defsubr (&Sreplace_buffer_in_windows);
5110 defsubr (&Sdelete_window);
5111 defsubr (&Sset_window_buffer);
5112 defsubr (&Sselect_window);
4628f7a4
EN
5113 defsubr (&Sspecial_display_p);
5114 defsubr (&Ssame_window_p);
7ab12479
JB
5115 defsubr (&Sdisplay_buffer);
5116 defsubr (&Ssplit_window);
5117 defsubr (&Senlarge_window);
5118 defsubr (&Sshrink_window);
5119 defsubr (&Sscroll_up);
5120 defsubr (&Sscroll_down);
5121 defsubr (&Sscroll_left);
5122 defsubr (&Sscroll_right);
ccd0664b 5123 defsubr (&Sother_window_for_scrolling);
7ab12479
JB
5124 defsubr (&Sscroll_other_window);
5125 defsubr (&Srecenter);
5126 defsubr (&Smove_to_window_line);
5127 defsubr (&Swindow_configuration_p);
3f8ab7bd 5128 defsubr (&Swindow_configuration_frame);
7ab12479
JB
5129 defsubr (&Sset_window_configuration);
5130 defsubr (&Scurrent_window_configuration);
5131 defsubr (&Ssave_window_excursion);
5500c422
GM
5132 defsubr (&Sset_window_margins);
5133 defsubr (&Swindow_margins);
5134 defsubr (&Swindow_vscroll);
5135 defsubr (&Sset_window_vscroll);
2f8274be 5136 defsubr (&Scompare_window_configurations);
7ab12479
JB
5137}
5138
dfcf069d 5139void
7ab12479
JB
5140keys_of_window ()
5141{
5142 initial_define_key (control_x_map, '1', "delete-other-windows");
5143 initial_define_key (control_x_map, '2', "split-window");
5144 initial_define_key (control_x_map, '0', "delete-window");
5145 initial_define_key (control_x_map, 'o', "other-window");
5146 initial_define_key (control_x_map, '^', "enlarge-window");
5147 initial_define_key (control_x_map, '<', "scroll-left");
5148 initial_define_key (control_x_map, '>', "scroll-right");
5149
5150 initial_define_key (global_map, Ctl ('V'), "scroll-up");
5151 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
5152 initial_define_key (meta_map, 'v', "scroll-down");
5153
5154 initial_define_key (global_map, Ctl('L'), "recenter");
5155 initial_define_key (meta_map, 'r', "move-to-window-line");
5156}