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