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