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