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