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