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