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