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