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