Support debug declarations in pcase macros
[emacs.git] / src / window.c
blobeb68672e2e0fc7458a8303fa604b25984fb1daf8
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985-1987, 1993-1998, 2000-2015 Free Software
4 Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 #include <config.h>
23 #include <stdio.h>
25 #include "lisp.h"
26 #include "character.h"
27 #include "buffer.h"
28 #include "keyboard.h"
29 #include "keymap.h"
30 #include "menu.h"
31 #include "frame.h"
32 #include "window.h"
33 #include "commands.h"
34 #include "indent.h"
35 #include "termchar.h"
36 #include "disptab.h"
37 #include "dispextern.h"
38 #include "blockinput.h"
39 #include "intervals.h"
40 #include "termhooks.h" /* For FRAME_TERMINAL. */
41 #ifdef HAVE_WINDOW_SYSTEM
42 #include TERM_HEADER
43 #endif /* HAVE_WINDOW_SYSTEM */
44 #ifdef MSDOS
45 #include "msdos.h"
46 #endif
48 static int count_windows (struct window *);
49 static int get_leaf_windows (struct window *, struct window **, int);
50 static void window_scroll_pixel_based (Lisp_Object, int, bool, bool);
51 static void window_scroll_line_based (Lisp_Object, int, bool, bool);
52 static void foreach_window (struct frame *,
53 bool (* fn) (struct window *, void *),
54 void *);
55 static bool foreach_window_1 (struct window *,
56 bool (* fn) (struct window *, void *),
57 void *);
58 static bool window_resize_check (struct window *, bool);
59 static void window_resize_apply (struct window *, bool);
60 static void select_window_1 (Lisp_Object, bool);
62 static struct window *set_window_fringes (struct window *, Lisp_Object,
63 Lisp_Object, Lisp_Object);
64 static struct window *set_window_margins (struct window *, Lisp_Object,
65 Lisp_Object);
66 static struct window *set_window_scroll_bars (struct window *, Lisp_Object,
67 Lisp_Object, Lisp_Object,
68 Lisp_Object);
69 static void apply_window_adjustment (struct window *);
71 /* This is the window in which the terminal's cursor should
72 be left when nothing is being done with it. This must
73 always be a leaf window, and its buffer is selected by
74 the top level editing loop at the end of each command.
76 This value is always the same as
77 FRAME_SELECTED_WINDOW (selected_frame). */
78 Lisp_Object selected_window;
80 /* A list of all windows for use by next_window and Fwindow_list.
81 Functions creating or deleting windows should invalidate this cache
82 by setting it to nil. */
83 Lisp_Object Vwindow_list;
85 /* The mini-buffer window of the selected frame.
86 Note that you cannot test for mini-bufferness of an arbitrary window
87 by comparing against this; but you can test for mini-bufferness of
88 the selected window. */
89 Lisp_Object minibuf_window;
91 /* Non-nil means it is the window whose mode line should be
92 shown as the selected window when the minibuffer is selected. */
93 Lisp_Object minibuf_selected_window;
95 /* Incremented for each window created. */
96 static int sequence_number;
98 /* Used by the function window_scroll_pixel_based. */
99 static int window_scroll_pixel_based_preserve_x;
100 static int window_scroll_pixel_based_preserve_y;
102 /* Same for window_scroll_line_based. */
103 static EMACS_INT window_scroll_preserve_hpos;
104 static EMACS_INT window_scroll_preserve_vpos;
106 static void
107 CHECK_WINDOW_CONFIGURATION (Lisp_Object x)
109 CHECK_TYPE (WINDOW_CONFIGURATIONP (x), Qwindow_configuration_p, x);
112 /* These setters are used only in this file, so they can be private. */
113 static void
114 wset_combination_limit (struct window *w, Lisp_Object val)
116 w->combination_limit = val;
119 static void
120 wset_dedicated (struct window *w, Lisp_Object val)
122 w->dedicated = val;
125 static void
126 wset_display_table (struct window *w, Lisp_Object val)
128 w->display_table = val;
131 static void
132 wset_new_normal (struct window *w, Lisp_Object val)
134 w->new_normal = val;
137 static void
138 wset_new_total (struct window *w, Lisp_Object val)
140 w->new_total = val;
143 static void
144 wset_normal_cols (struct window *w, Lisp_Object val)
146 w->normal_cols = val;
149 static void
150 wset_normal_lines (struct window *w, Lisp_Object val)
152 w->normal_lines = val;
155 static void
156 wset_parent (struct window *w, Lisp_Object val)
158 w->parent = val;
161 static void
162 wset_pointm (struct window *w, Lisp_Object val)
164 w->pointm = val;
167 static void
168 wset_old_pointm (struct window *w, Lisp_Object val)
170 w->old_pointm = val;
173 static void
174 wset_start (struct window *w, Lisp_Object val)
176 w->start = val;
179 static void
180 wset_temslot (struct window *w, Lisp_Object val)
182 w->temslot = val;
185 static void
186 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
188 w->vertical_scroll_bar_type = val;
191 static void
192 wset_window_parameters (struct window *w, Lisp_Object val)
194 w->window_parameters = val;
197 static void
198 wset_combination (struct window *w, bool horflag, Lisp_Object val)
200 /* Since leaf windows never becomes non-leaf, there should
201 be no buffer and markers in start and pointm fields of W. */
202 eassert (!BUFFERP (w->contents) && NILP (w->start) && NILP (w->pointm));
203 w->contents = val;
204 /* When an internal window is deleted and VAL is nil, HORFLAG
205 is meaningless. */
206 if (!NILP (val))
207 w->horizontal = horflag;
210 /* True if leaf window W doesn't reflect the actual state
211 of displayed buffer due to its text or overlays change. */
213 bool
214 window_outdated (struct window *w)
216 struct buffer *b = XBUFFER (w->contents);
217 return (w->last_modified < BUF_MODIFF (b)
218 || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b));
221 struct window *
222 decode_live_window (register Lisp_Object window)
224 if (NILP (window))
225 return XWINDOW (selected_window);
227 CHECK_LIVE_WINDOW (window);
228 return XWINDOW (window);
231 struct window *
232 decode_any_window (register Lisp_Object window)
234 struct window *w;
236 if (NILP (window))
237 return XWINDOW (selected_window);
239 CHECK_WINDOW (window);
240 w = XWINDOW (window);
241 return w;
244 static struct window *
245 decode_valid_window (register Lisp_Object window)
247 struct window *w;
249 if (NILP (window))
250 return XWINDOW (selected_window);
252 CHECK_VALID_WINDOW (window);
253 w = XWINDOW (window);
254 return w;
257 /* Called when W's buffer slot is changed. ARG -1 means that W is about to
258 cease its buffer, and 1 means that W is about to set up the new one. */
260 static void
261 adjust_window_count (struct window *w, int arg)
263 eassert (eabs (arg) == 1);
264 if (BUFFERP (w->contents))
266 struct buffer *b = XBUFFER (w->contents);
268 if (b->base_buffer)
269 b = b->base_buffer;
270 b->window_count += arg;
271 eassert (b->window_count >= 0);
272 /* These should be recalculated by redisplay code. */
273 w->window_end_valid = false;
274 w->base_line_pos = 0;
278 /* Set W's buffer slot to VAL and recompute number
279 of windows showing VAL if it is a buffer. */
281 void
282 wset_buffer (struct window *w, Lisp_Object val)
284 adjust_window_count (w, -1);
285 if (BUFFERP (val))
286 /* Make sure that we do not assign the buffer
287 to an internal window. */
288 eassert (MARKERP (w->start) && MARKERP (w->pointm));
289 w->contents = val;
290 adjust_window_count (w, 1);
293 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
294 doc: /* Return t if OBJECT is a window and nil otherwise. */)
295 (Lisp_Object object)
297 return WINDOWP (object) ? Qt : Qnil;
300 DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
301 doc: /* Return t if OBJECT is a valid window and nil otherwise.
302 A valid window is either a window that displays a buffer or an internal
303 window. Windows that have been deleted are not valid. */)
304 (Lisp_Object object)
306 return WINDOW_VALID_P (object) ? Qt : Qnil;
309 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
310 doc: /* Return t if OBJECT is a live window and nil otherwise.
311 A live window is a window that displays a buffer.
312 Internal windows and deleted windows are not live. */)
313 (Lisp_Object object)
315 return WINDOW_LIVE_P (object) ? Qt : Qnil;
318 /* Frames and windows. */
319 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 0, 1, 0,
320 doc: /* Return the frame that window WINDOW is on.
321 WINDOW must be a valid window and defaults to the selected one. */)
322 (Lisp_Object window)
324 return decode_valid_window (window)->frame;
327 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
328 doc: /* Return the root window of FRAME-OR-WINDOW.
329 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
330 With a frame argument, return that frame's root window.
331 With a window argument, return the root window of that window's frame. */)
332 (Lisp_Object frame_or_window)
334 Lisp_Object window;
336 if (NILP (frame_or_window))
337 window = SELECTED_FRAME ()->root_window;
338 else if (WINDOW_VALID_P (frame_or_window))
339 window = XFRAME (XWINDOW (frame_or_window)->frame)->root_window;
340 else
342 CHECK_LIVE_FRAME (frame_or_window);
343 window = XFRAME (frame_or_window)->root_window;
346 return window;
349 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
350 doc: /* Return the minibuffer window for frame FRAME.
351 If FRAME is omitted or nil, it defaults to the selected frame. */)
352 (Lisp_Object frame)
354 return FRAME_MINIBUF_WINDOW (decode_live_frame (frame));
357 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
358 Swindow_minibuffer_p, 0, 1, 0,
359 doc: /* Return non-nil if WINDOW is a minibuffer window.
360 WINDOW must be a valid window and defaults to the selected one. */)
361 (Lisp_Object window)
363 return MINI_WINDOW_P (decode_valid_window (window)) ? Qt : Qnil;
366 /* Don't move this to window.el - this must be a safe routine. */
367 DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
368 doc: /* Return the topmost, leftmost live window on FRAME-OR-WINDOW.
369 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
370 Else if FRAME-OR-WINDOW denotes a valid window, return the first window
371 of that window's frame. If FRAME-OR-WINDOW denotes a live frame, return
372 the first window of that frame. */)
373 (Lisp_Object frame_or_window)
375 Lisp_Object window;
377 if (NILP (frame_or_window))
378 window = SELECTED_FRAME ()->root_window;
379 else if (WINDOW_VALID_P (frame_or_window))
380 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
381 else
383 CHECK_LIVE_FRAME (frame_or_window);
384 window = XFRAME (frame_or_window)->root_window;
387 while (WINDOWP (XWINDOW (window)->contents))
388 window = XWINDOW (window)->contents;
390 return window;
393 DEFUN ("frame-selected-window", Fframe_selected_window,
394 Sframe_selected_window, 0, 1, 0,
395 doc: /* Return the selected window of FRAME-OR-WINDOW.
396 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
397 Else if FRAME-OR-WINDOW denotes a valid window, return the selected
398 window of that window's frame. If FRAME-OR-WINDOW denotes a live frame,
399 return the selected window of that frame. */)
400 (Lisp_Object frame_or_window)
402 Lisp_Object window;
404 if (NILP (frame_or_window))
405 window = SELECTED_FRAME ()->selected_window;
406 else if (WINDOW_VALID_P (frame_or_window))
407 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
408 else
410 CHECK_LIVE_FRAME (frame_or_window);
411 window = XFRAME (frame_or_window)->selected_window;
414 return window;
417 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
418 Sset_frame_selected_window, 2, 3, 0,
419 doc: /* Set selected window of FRAME to WINDOW.
420 FRAME must be a live frame and defaults to the selected one. If FRAME
421 is the selected frame, this makes WINDOW the selected window. Optional
422 argument NORECORD non-nil means to neither change the order of recently
423 selected windows nor the buffer list. WINDOW must denote a live window.
424 Return WINDOW. */)
425 (Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
427 if (NILP (frame))
428 frame = selected_frame;
430 CHECK_LIVE_FRAME (frame);
431 CHECK_LIVE_WINDOW (window);
433 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
434 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
436 if (EQ (frame, selected_frame))
437 return Fselect_window (window, norecord);
438 else
440 fset_selected_window (XFRAME (frame), window);
441 return window;
445 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
446 doc: /* Return the selected window.
447 The selected window is the window in which the standard cursor for
448 selected windows appears and to which many commands apply. */)
449 (void)
451 return selected_window;
454 int window_select_count;
456 /* If select_window is called with inhibit_point_swap true it will
457 not store point of the old selected window's buffer back into that
458 window's pointm slot. This is needed by Fset_window_configuration to
459 avoid that the display routine is called with selected_window set to
460 Qnil causing a subsequent crash. */
461 static Lisp_Object
462 select_window (Lisp_Object window, Lisp_Object norecord,
463 bool inhibit_point_swap)
465 struct window *w;
466 struct frame *sf;
468 CHECK_LIVE_WINDOW (window);
470 w = XWINDOW (window);
472 /* Make the selected window's buffer current. */
473 Fset_buffer (w->contents);
475 if (EQ (window, selected_window) && !inhibit_point_swap)
476 /* `switch-to-buffer' uses (select-window (selected-window)) as a "clever"
477 way to call record_buffer from Elisp, so it's important that we call
478 record_buffer before returning here. */
479 goto record_and_return;
481 if (NILP (norecord))
482 { /* Mark the window for redisplay since the selected-window has
483 a different mode-line. */
484 wset_redisplay (XWINDOW (selected_window));
485 wset_redisplay (w);
487 else
488 redisplay_other_windows ();
490 sf = SELECTED_FRAME ();
491 if (XFRAME (WINDOW_FRAME (w)) != sf)
493 fset_selected_window (XFRAME (WINDOW_FRAME (w)), window);
494 /* Use this rather than Fhandle_switch_frame
495 so that FRAME_FOCUS_FRAME is moved appropriately as we
496 move around in the state where a minibuffer in a separate
497 frame is active. */
498 Fselect_frame (WINDOW_FRAME (w), norecord);
499 /* Fselect_frame called us back so we've done all the work already. */
500 eassert (EQ (window, selected_window));
501 return window;
503 else
504 fset_selected_window (sf, window);
506 select_window_1 (window, inhibit_point_swap);
507 bset_last_selected_window (XBUFFER (w->contents), window);
509 record_and_return:
510 /* record_buffer can run QUIT, so make sure it is run only after we have
511 re-established the invariant between selected_window and selected_frame,
512 otherwise the temporary broken invariant might "escape" (bug#14161). */
513 if (NILP (norecord))
515 w->use_time = ++window_select_count;
516 record_buffer (w->contents);
519 return window;
522 /* Select window with a minimum of fuss, i.e. don't record the change anywhere
523 (not even for redisplay's benefit), and assume that the window's frame is
524 already selected. */
525 static void
526 select_window_1 (Lisp_Object window, bool inhibit_point_swap)
528 /* Store the old selected window's buffer's point in pointm of the old
529 selected window. It belongs to that window, and when the window is
530 not selected, must be in the window. */
531 if (!inhibit_point_swap)
533 struct window *ow = XWINDOW (selected_window);
534 if (BUFFERP (ow->contents))
535 set_marker_both (ow->pointm, ow->contents,
536 BUF_PT (XBUFFER (ow->contents)),
537 BUF_PT_BYTE (XBUFFER (ow->contents)));
540 selected_window = window;
542 /* Go to the point recorded in the window.
543 This is important when the buffer is in more
544 than one window. It also matters when
545 redisplay_window has altered point after scrolling,
546 because it makes the change only in the window. */
547 set_point_from_marker (XWINDOW (window)->pointm);
550 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
551 doc: /* Select WINDOW which must be a live window.
552 Also make WINDOW's frame the selected frame and WINDOW that frame's
553 selected window. In addition, make WINDOW's buffer current and set its
554 buffer's value of `point' to the value of WINDOW's `window-point'.
555 Return WINDOW.
557 Optional second arg NORECORD non-nil means do not put this buffer at the
558 front of the buffer list and do not make this window the most recently
559 selected one.
561 Run `buffer-list-update-hook' unless NORECORD is non-nil. Note that
562 applications and internal routines often select a window temporarily for
563 various purposes; mostly, to simplify coding. As a rule, such
564 selections should be not recorded and therefore will not pollute
565 `buffer-list-update-hook'. Selections that "really count" are those
566 causing a visible change in the next redisplay of WINDOW's frame and
567 should be always recorded. So if you think of running a function each
568 time a window gets selected put it on `buffer-list-update-hook'.
570 Also note that the main editor command loop sets the current buffer to
571 the buffer of the selected window before each command. */)
572 (Lisp_Object window, Lisp_Object norecord)
574 return select_window (window, norecord, false);
577 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
578 doc: /* Return the buffer displayed in window WINDOW.
579 If WINDOW is omitted or nil, it defaults to the selected window.
580 Return nil for an internal window or a deleted window. */)
581 (Lisp_Object window)
583 struct window *w = decode_any_window (window);
584 return WINDOW_LEAF_P (w) ? w->contents : Qnil;
587 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
588 doc: /* Return the parent window of window WINDOW.
589 WINDOW must be a valid window and defaults to the selected one.
590 Return nil for a window with no parent (e.g. a root window). */)
591 (Lisp_Object window)
593 return decode_valid_window (window)->parent;
596 DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 0, 1, 0,
597 doc: /* Return the topmost child window of window WINDOW.
598 WINDOW must be a valid window and defaults to the selected one.
599 Return nil if WINDOW is a live window (live windows have no children).
600 Return nil if WINDOW is an internal window whose children form a
601 horizontal combination. */)
602 (Lisp_Object window)
604 struct window *w = decode_valid_window (window);
605 return WINDOW_VERTICAL_COMBINATION_P (w) ? w->contents : Qnil;
608 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
609 doc: /* Return the leftmost child window of window WINDOW.
610 WINDOW must be a valid window and defaults to the selected one.
611 Return nil if WINDOW is a live window (live windows have no children).
612 Return nil if WINDOW is an internal window whose children form a
613 vertical combination. */)
614 (Lisp_Object window)
616 struct window *w = decode_valid_window (window);
617 return WINDOW_HORIZONTAL_COMBINATION_P (w) ? w->contents : Qnil;
620 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
621 doc: /* Return the next sibling window of window WINDOW.
622 WINDOW must be a valid window and defaults to the selected one.
623 Return nil if WINDOW has no next sibling. */)
624 (Lisp_Object window)
626 return decode_valid_window (window)->next;
629 DEFUN ("window-prev-sibling", Fwindow_prev_sibling, Swindow_prev_sibling, 0, 1, 0,
630 doc: /* Return the previous sibling window of window WINDOW.
631 WINDOW must be a valid window and defaults to the selected one.
632 Return nil if WINDOW has no previous sibling. */)
633 (Lisp_Object window)
635 return decode_valid_window (window)->prev;
638 DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
639 doc: /* Return combination limit of window WINDOW.
640 WINDOW must be a valid window used in horizontal or vertical combination.
641 If the return value is nil, child windows of WINDOW can be recombined with
642 WINDOW's siblings. A return value of t means that child windows of
643 WINDOW are never \(re-)combined with WINDOW's siblings. */)
644 (Lisp_Object window)
646 struct window *w;
648 CHECK_VALID_WINDOW (window);
649 w = XWINDOW (window);
650 if (WINDOW_LEAF_P (w))
651 error ("Combination limit is meaningful for internal windows only");
652 return w->combination_limit;
655 DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
656 doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
657 WINDOW must be a valid window used in horizontal or vertical combination.
658 If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
659 siblings. LIMIT t means that child windows of WINDOW are never
660 \(re-)combined with WINDOW's siblings. Other values are reserved for
661 future use. */)
662 (Lisp_Object window, Lisp_Object limit)
664 struct window *w;
666 CHECK_VALID_WINDOW (window);
667 w = XWINDOW (window);
668 if (WINDOW_LEAF_P (w))
669 error ("Combination limit is meaningful for internal windows only");
670 wset_combination_limit (w, limit);
671 return limit;
674 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
675 doc: /* Return the use time of window WINDOW.
676 WINDOW must be a live window and defaults to the selected one.
677 The window with the highest use time is the most recently selected
678 one. The window with the lowest use time is the least recently
679 selected one. */)
680 (Lisp_Object window)
682 return make_number (decode_live_window (window)->use_time);
685 DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0,
686 doc: /* Return the width of window WINDOW in pixels.
687 WINDOW must be a valid window and defaults to the selected one.
689 The return value includes the fringes and margins of WINDOW as well as
690 any vertical dividers or scroll bars belonging to WINDOW. If WINDOW is
691 an internal window, its pixel width is the width of the screen areas
692 spanned by its children. */)
693 (Lisp_Object window)
695 return make_number (decode_valid_window (window)->pixel_width);
698 DEFUN ("window-pixel-height", Fwindow_pixel_height, Swindow_pixel_height, 0, 1, 0,
699 doc: /* Return the height of window WINDOW in pixels.
700 WINDOW must be a valid window and defaults to the selected one.
702 The return value includes the mode line and header line and the bottom
703 divider, if any. If WINDOW is an internal window, its pixel height is
704 the height of the screen areas spanned by its children. */)
705 (Lisp_Object window)
707 return make_number (decode_valid_window (window)->pixel_height);
710 DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0,
711 doc: /* Return the height of window WINDOW in lines.
712 WINDOW must be a valid window and defaults to the selected one.
714 The return value includes the heights of WINDOW's mode and header line
715 and its bottom divider, if any. If WINDOW is an internal window, the
716 total height is the height of the screen areas spanned by its children.
718 If WINDOW's pixel height is not an integral multiple of its frame's
719 character height, the number of lines occupied by WINDOW is rounded
720 internally. This is done in a way such that, if WINDOW is a parent
721 window, the sum of the total heights of all its children internally
722 equals the total height of WINDOW.
724 If the optional argument ROUND is `ceiling', return the smallest integer
725 larger than WINDOW's pixel height divided by the character height of
726 WINDOW's frame. ROUND `floor' means to return the largest integer
727 smaller than WINDOW's pixel height divided by the character height of
728 WINDOW's frame. Any other value of ROUND means to return the internal
729 total height of WINDOW. */)
730 (Lisp_Object window, Lisp_Object round)
732 struct window *w = decode_valid_window (window);
734 if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
735 return make_number (w->total_lines);
736 else
738 int unit = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
740 return make_number (EQ (round, Qceiling)
741 ? ((w->pixel_height + unit - 1) /unit)
742 : (w->pixel_height / unit));
746 DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 2, 0,
747 doc: /* Return the total width of window WINDOW in columns.
748 WINDOW must be a valid window and defaults to the selected one.
750 The return value includes the widths of WINDOW's fringes, margins,
751 scroll bars and its right divider, if any. If WINDOW is an internal
752 window, the total width is the width of the screen areas spanned by its
753 children.
755 If WINDOW's pixel width is not an integral multiple of its frame's
756 character width, the number of lines occupied by WINDOW is rounded
757 internally. This is done in a way such that, if WINDOW is a parent
758 window, the sum of the total widths of all its children internally
759 equals the total width of WINDOW.
761 If the optional argument ROUND is `ceiling', return the smallest integer
762 larger than WINDOW's pixel width divided by the character width of
763 WINDOW's frame. ROUND `floor' means to return the largest integer
764 smaller than WINDOW's pixel width divided by the character width of
765 WINDOW's frame. Any other value of ROUND means to return the internal
766 total width of WINDOW. */)
767 (Lisp_Object window, Lisp_Object round)
769 struct window *w = decode_valid_window (window);
771 if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
772 return make_number (w->total_cols);
773 else
775 int unit = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
777 return make_number (EQ (round, Qceiling)
778 ? ((w->pixel_width + unit - 1) /unit)
779 : (w->pixel_width / unit));
783 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
784 doc: /* Return the new total size of window WINDOW.
785 WINDOW must be a valid window and defaults to the selected one.
787 The new total size of WINDOW is the value set by the last call of
788 `set-window-new-total' for WINDOW. If it is valid, it will be shortly
789 installed as WINDOW's total height (see `window-total-height') or total
790 width (see `window-total-width'). */)
791 (Lisp_Object window)
793 return decode_valid_window (window)->new_total;
796 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
797 doc: /* Return the normal height of window WINDOW.
798 WINDOW must be a valid window and defaults to the selected one.
799 If HORIZONTAL is non-nil, return the normal width of WINDOW.
801 The normal height of a frame's root window or a window that is
802 horizontally combined (a window that has a left or right sibling) is
803 1.0. The normal height of a window that is vertically combined (has a
804 sibling above or below) is the fraction of the window's height with
805 respect to its parent. The sum of the normal heights of all windows in a
806 vertical combination equals 1.0.
808 Similarly, the normal width of a frame's root window or a window that is
809 vertically combined equals 1.0. The normal width of a window that is
810 horizontally combined is the fraction of the window's width with respect
811 to its parent. The sum of the normal widths of all windows in a
812 horizontal combination equals 1.0.
814 The normal sizes of windows are used to restore the proportional sizes
815 of windows after they have been shrunk to their minimum sizes; for
816 example when a frame is temporarily made very small and afterwards gets
817 re-enlarged to its previous size. */)
818 (Lisp_Object window, Lisp_Object horizontal)
820 struct window *w = decode_valid_window (window);
822 return NILP (horizontal) ? w->normal_lines : w->normal_cols;
825 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
826 doc: /* Return new normal size of window WINDOW.
827 WINDOW must be a valid window and defaults to the selected one.
829 The new normal size of WINDOW is the value set by the last call of
830 `set-window-new-normal' for WINDOW. If valid, it will be shortly
831 installed as WINDOW's normal size (see `window-normal-size'). */)
832 (Lisp_Object window)
834 return decode_valid_window (window)->new_normal;
837 DEFUN ("window-new-pixel", Fwindow_new_pixel, Swindow_new_pixel, 0, 1, 0,
838 doc: /* Return new pixel size of window WINDOW.
839 WINDOW must be a valid window and defaults to the selected one.
841 The new pixel size of WINDOW is the value set by the last call of
842 `set-window-new-pixel' for WINDOW. If it is valid, it will be shortly
843 installed as WINDOW's pixel height (see `window-pixel-height') or pixel
844 width (see `window-pixel-width'). */)
845 (Lisp_Object window)
847 return decode_valid_window (window)->new_pixel;
850 DEFUN ("window-pixel-left", Fwindow_pixel_left, Swindow_pixel_left, 0, 1, 0,
851 doc: /* Return left pixel edge of window WINDOW.
852 WINDOW must be a valid window and defaults to the selected one. */)
853 (Lisp_Object window)
855 return make_number (decode_valid_window (window)->pixel_left);
858 DEFUN ("window-pixel-top", Fwindow_pixel_top, Swindow_pixel_top, 0, 1, 0,
859 doc: /* Return top pixel edge of window WINDOW.
860 WINDOW must be a valid window and defaults to the selected one. */)
861 (Lisp_Object window)
863 return make_number (decode_valid_window (window)->pixel_top);
866 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
867 doc: /* Return left column of window WINDOW.
868 This is the distance, in columns, between the left edge of WINDOW and
869 the left edge of the frame's window area. For instance, the return
870 value is 0 if there is no window to the left of WINDOW.
872 WINDOW must be a valid window and defaults to the selected one. */)
873 (Lisp_Object window)
875 return make_number (decode_valid_window (window)->left_col);
878 DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
879 doc: /* Return top line of window WINDOW.
880 This is the distance, in lines, between the top of WINDOW and the top
881 of the frame's window area. For instance, the return value is 0 if
882 there is no window above WINDOW.
884 WINDOW must be a valid window and defaults to the selected one. */)
885 (Lisp_Object window)
887 return make_number (decode_valid_window (window)->top_line);
890 /* Return the number of lines/pixels of W's body. Don't count any mode
891 or header line or horizontal divider of W. Rounds down to nearest
892 integer when not working pixelwise. */
893 static int
894 window_body_height (struct window *w, bool pixelwise)
896 int height = (w->pixel_height
897 - WINDOW_HEADER_LINE_HEIGHT (w)
898 - (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
899 ? WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
900 : 0)
901 - WINDOW_MODE_LINE_HEIGHT (w)
902 - WINDOW_BOTTOM_DIVIDER_WIDTH (w));
904 /* Don't return a negative value. */
905 return max (pixelwise
906 ? height
907 : height / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)),
911 /* Return the number of columns/pixels of W's body. Don't count columns
912 occupied by the scroll bar or the divider/vertical bar separating W
913 from its right sibling or margins. On window-systems don't count
914 fringes either. Round down to nearest integer when not working
915 pixelwise. */
917 window_body_width (struct window *w, bool pixelwise)
919 struct frame *f = XFRAME (WINDOW_FRAME (w));
921 int width = (w->pixel_width
922 - WINDOW_RIGHT_DIVIDER_WIDTH (w)
923 - (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
924 ? WINDOW_SCROLL_BAR_AREA_WIDTH (w)
925 : (/* A vertical bar is either 1 or 0. */
926 !FRAME_WINDOW_P (f)
927 && !WINDOW_RIGHTMOST_P (w)
928 && !WINDOW_RIGHT_DIVIDER_WIDTH (w)))
929 - WINDOW_MARGINS_WIDTH (w)
930 - (FRAME_WINDOW_P (f)
931 ? WINDOW_FRINGES_WIDTH (w)
932 : 0));
934 /* Don't return a negative value. */
935 return max (pixelwise
936 ? width
937 : width / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)),
941 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
942 doc: /* Return the height of WINDOW's text area.
943 WINDOW must be a live window and defaults to the selected one. Optional
944 argument PIXELWISE non-nil means return the height of WINDOW's text area
945 in pixels. The return value does not include the mode line or header
946 line or any horizontal divider.
948 If PIXELWISE is nil, return the largest integer smaller than WINDOW's
949 pixel height divided by the character height of WINDOW's frame. This
950 means that if a line at the bottom of the text area is only partially
951 visible, that line is not counted. */)
952 (Lisp_Object window, Lisp_Object pixelwise)
954 return make_number (window_body_height (decode_live_window (window),
955 !NILP (pixelwise)));
958 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
959 doc: /* Return the width of WINDOW's text area.
960 WINDOW must be a live window and defaults to the selected one. Optional
961 argument PIXELWISE non-nil means return the width in pixels. The return
962 value does not include any vertical dividers, fringes or marginal areas,
963 or scroll bars.
965 If PIXELWISE is nil, return the largest integer smaller than WINDOW's
966 pixel width divided by the character width of WINDOW's frame. This
967 means that if a column at the right of the text area is only partially
968 visible, that column is not counted.
970 Note that the returned value includes the column reserved for the
971 continuation glyph. */)
972 (Lisp_Object window, Lisp_Object pixelwise)
974 return make_number (window_body_width (decode_live_window (window),
975 !NILP (pixelwise)));
978 DEFUN ("window-mode-line-height", Fwindow_mode_line_height,
979 Swindow_mode_line_height, 0, 1, 0,
980 doc: /* Return the height in pixels of WINDOW's mode-line.
981 WINDOW must be a live window and defaults to the selected one. */)
982 (Lisp_Object window)
984 return (make_number (WINDOW_MODE_LINE_HEIGHT (decode_live_window (window))));
987 DEFUN ("window-header-line-height", Fwindow_header_line_height,
988 Swindow_header_line_height, 0, 1, 0,
989 doc: /* Return the height in pixels of WINDOW's header-line.
990 WINDOW must be a live window and defaults to the selected one. */)
991 (Lisp_Object window)
993 return (make_number (WINDOW_HEADER_LINE_HEIGHT (decode_live_window (window))));
996 DEFUN ("window-right-divider-width", Fwindow_right_divider_width,
997 Swindow_right_divider_width, 0, 1, 0,
998 doc: /* Return the width in pixels of WINDOW's right divider.
999 WINDOW must be a live window and defaults to the selected one. */)
1000 (Lisp_Object window)
1002 return (make_number (WINDOW_RIGHT_DIVIDER_WIDTH (decode_live_window (window))));
1005 DEFUN ("window-bottom-divider-width", Fwindow_bottom_divider_width,
1006 Swindow_bottom_divider_width, 0, 1, 0,
1007 doc: /* Return the width in pixels of WINDOW's bottom divider.
1008 WINDOW must be a live window and defaults to the selected one. */)
1009 (Lisp_Object window)
1011 return (make_number (WINDOW_BOTTOM_DIVIDER_WIDTH (decode_live_window (window))));
1014 DEFUN ("window-scroll-bar-width", Fwindow_scroll_bar_width,
1015 Swindow_scroll_bar_width, 0, 1, 0,
1016 doc: /* Return the width in pixels of WINDOW's vertical scrollbar.
1017 WINDOW must be a live window and defaults to the selected one. */)
1018 (Lisp_Object window)
1020 return (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (decode_live_window (window))));
1023 DEFUN ("window-scroll-bar-height", Fwindow_scroll_bar_height,
1024 Swindow_scroll_bar_height, 0, 1, 0,
1025 doc: /* Return the height in pixels of WINDOW's horizontal scrollbar.
1026 WINDOW must be a live window and defaults to the selected one. */)
1027 (Lisp_Object window)
1029 return (make_number (WINDOW_SCROLL_BAR_AREA_HEIGHT (decode_live_window (window))));
1032 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
1033 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
1034 WINDOW must be a live window and defaults to the selected one. */)
1035 (Lisp_Object window)
1037 return make_number (decode_live_window (window)->hscroll);
1040 /* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
1041 range, returning the new amount as a fixnum. */
1042 static Lisp_Object
1043 set_window_hscroll (struct window *w, EMACS_INT hscroll)
1045 /* Horizontal scrolling has problems with large scroll amounts.
1046 It's too slow with long lines, and even with small lines the
1047 display can be messed up. For now, though, impose only the limits
1048 required by the internal representation: horizontal scrolling must
1049 fit in fixnum (since it's visible to Elisp) and into ptrdiff_t
1050 (since it's stored in a ptrdiff_t). */
1051 ptrdiff_t hscroll_max = min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX);
1052 ptrdiff_t new_hscroll = clip_to_bounds (0, hscroll, hscroll_max);
1054 /* Prevent redisplay shortcuts when changing the hscroll. */
1055 if (w->hscroll != new_hscroll)
1056 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
1058 w->hscroll = new_hscroll;
1059 w->suspend_auto_hscroll = true;
1061 return make_number (new_hscroll);
1064 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
1065 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
1066 WINDOW must be a live window and defaults to the selected one.
1067 Clip the number to a reasonable value if out of range.
1068 Return the new number. NCOL should be zero or positive.
1070 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
1071 window so that the location of point moves off-window. */)
1072 (Lisp_Object window, Lisp_Object ncol)
1074 CHECK_NUMBER (ncol);
1075 return set_window_hscroll (decode_live_window (window), XINT (ncol));
1078 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
1079 Swindow_redisplay_end_trigger, 0, 1, 0,
1080 doc: /* Return WINDOW's redisplay end trigger value.
1081 WINDOW must be a live window and defaults to the selected one.
1082 See `set-window-redisplay-end-trigger' for more information. */)
1083 (Lisp_Object window)
1085 return decode_live_window (window)->redisplay_end_trigger;
1088 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
1089 Sset_window_redisplay_end_trigger, 2, 2, 0,
1090 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
1091 WINDOW must be a live window and defaults to the selected one. VALUE
1092 should be a buffer position (typically a marker) or nil. If it is a
1093 buffer position, then if redisplay in WINDOW reaches a position beyond
1094 VALUE, the functions in `redisplay-end-trigger-functions' are called
1095 with two arguments: WINDOW, and the end trigger value. Afterwards the
1096 end-trigger value is reset to nil. */)
1097 (register Lisp_Object window, Lisp_Object value)
1099 wset_redisplay_end_trigger (decode_live_window (window), value);
1100 return value;
1103 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
1104 doc: /* Return a list of the edge coordinates of WINDOW.
1105 WINDOW must be a valid window and defaults to the selected one.
1107 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
1108 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
1109 0 at top left corner of frame.
1111 RIGHT is one more than the rightmost column occupied by WINDOW. BOTTOM
1112 is one more than the bottommost row occupied by WINDOW. The edges
1113 include the space used by WINDOW's scroll bar, display margins, fringes,
1114 header line, and/or mode line. For the edges of just the text area, use
1115 `window-inside-edges'. */)
1116 (Lisp_Object window)
1118 register struct window *w = decode_valid_window (window);
1120 return list4i (WINDOW_LEFT_EDGE_COL (w), WINDOW_TOP_EDGE_LINE (w),
1121 WINDOW_RIGHT_EDGE_COL (w), WINDOW_BOTTOM_EDGE_LINE (w));
1124 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
1125 doc: /* Return a list of the edge pixel coordinates of WINDOW.
1126 WINDOW must be a valid window and defaults to the selected one.
1128 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1129 0, 0 at the top left corner of the frame.
1131 RIGHT is one more than the rightmost x position occupied by WINDOW.
1132 BOTTOM is one more than the bottommost y position occupied by WINDOW.
1133 The pixel edges include the space used by WINDOW's scroll bar, display
1134 margins, fringes, header line, and/or mode line. For the pixel edges
1135 of just the text area, use `window-inside-pixel-edges'. */)
1136 (Lisp_Object window)
1138 register struct window *w = decode_valid_window (window);
1140 return list4i (WINDOW_LEFT_EDGE_X (w), WINDOW_TOP_EDGE_Y (w),
1141 WINDOW_RIGHT_EDGE_X (w), WINDOW_BOTTOM_EDGE_Y (w));
1144 static void
1145 calc_absolute_offset (struct window *w, int *add_x, int *add_y)
1147 struct frame *f = XFRAME (w->frame);
1148 *add_y = f->top_pos;
1149 #ifdef FRAME_MENUBAR_HEIGHT
1150 *add_y += FRAME_MENUBAR_HEIGHT (f);
1151 #endif
1152 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
1153 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
1154 #elif defined (FRAME_TOOLBAR_HEIGHT)
1155 *add_y += FRAME_TOOLBAR_HEIGHT (f);
1156 #endif
1157 #ifdef FRAME_NS_TITLEBAR_HEIGHT
1158 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
1159 #endif
1160 *add_x = f->left_pos;
1161 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
1162 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
1163 #endif
1166 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
1167 Swindow_absolute_pixel_edges, 0, 1, 0,
1168 doc: /* Return a list of the edge pixel coordinates of WINDOW.
1169 WINDOW must be a valid window and defaults to the selected one.
1171 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1172 0, 0 at the top left corner of the display.
1174 RIGHT is one more than the rightmost x position occupied by WINDOW.
1175 BOTTOM is one more than the bottommost y position occupied by WINDOW.
1176 The pixel edges include the space used by WINDOW's scroll bar, display
1177 margins, fringes, header line, and/or mode line. For the pixel edges
1178 of just the text area, use `window-inside-absolute-pixel-edges'. */)
1179 (Lisp_Object window)
1181 register struct window *w = decode_valid_window (window);
1182 int add_x, add_y;
1184 calc_absolute_offset (w, &add_x, &add_y);
1186 return list4i (WINDOW_LEFT_EDGE_X (w) + add_x,
1187 WINDOW_TOP_EDGE_Y (w) + add_y,
1188 WINDOW_RIGHT_EDGE_X (w) + add_x,
1189 WINDOW_BOTTOM_EDGE_Y (w) + add_y);
1192 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
1193 doc: /* Return a list of the edge coordinates of WINDOW.
1194 WINDOW must be a live window and defaults to the selected one.
1196 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
1197 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
1198 0 at top left corner of frame.
1200 RIGHT is one more than the rightmost column of WINDOW's text area.
1201 BOTTOM is one more than the bottommost row of WINDOW's text area. The
1202 inside edges do not include the space used by the WINDOW's scroll bar,
1203 display margins, fringes, header line, and/or mode line. */)
1204 (Lisp_Object window)
1206 register struct window *w = decode_live_window (window);
1208 return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w)
1209 + WINDOW_LEFT_MARGIN_COLS (w)
1210 + ((WINDOW_LEFT_FRINGE_WIDTH (w)
1211 + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
1212 / WINDOW_FRAME_COLUMN_WIDTH (w))),
1213 (WINDOW_TOP_EDGE_LINE (w)
1214 + WINDOW_HEADER_LINE_LINES (w)),
1215 (WINDOW_BOX_RIGHT_EDGE_COL (w)
1216 - WINDOW_RIGHT_MARGIN_COLS (w)
1217 - ((WINDOW_RIGHT_FRINGE_WIDTH (w)
1218 + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
1219 / WINDOW_FRAME_COLUMN_WIDTH (w))),
1220 (WINDOW_BOTTOM_EDGE_LINE (w)
1221 - WINDOW_MODE_LINE_LINES (w)));
1224 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
1225 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1226 WINDOW must be a live window and defaults to the selected one.
1228 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1229 (0,0) at the top left corner of the frame's window area.
1231 RIGHT is one more than the rightmost x position of WINDOW's text area.
1232 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1233 The inside edges do not include the space used by WINDOW's scroll bar,
1234 display margins, fringes, header line, and/or mode line. */)
1235 (Lisp_Object window)
1237 register struct window *w = decode_live_window (window);
1239 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1240 + WINDOW_LEFT_MARGIN_WIDTH (w)
1241 + WINDOW_LEFT_FRINGE_WIDTH (w)),
1242 (WINDOW_TOP_EDGE_Y (w)
1243 + WINDOW_HEADER_LINE_HEIGHT (w)),
1244 (WINDOW_BOX_RIGHT_EDGE_X (w)
1245 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1246 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
1247 (WINDOW_BOTTOM_EDGE_Y (w)
1248 - WINDOW_MODE_LINE_HEIGHT (w)));
1251 DEFUN ("window-inside-absolute-pixel-edges",
1252 Fwindow_inside_absolute_pixel_edges,
1253 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
1254 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1255 WINDOW must be a live window and defaults to the selected one.
1257 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1258 (0,0) at the top left corner of the frame's window area.
1260 RIGHT is one more than the rightmost x position of WINDOW's text area.
1261 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1262 The inside edges do not include the space used by WINDOW's scroll bar,
1263 display margins, fringes, header line, and/or mode line. */)
1264 (Lisp_Object window)
1266 register struct window *w = decode_live_window (window);
1267 int add_x, add_y;
1269 calc_absolute_offset (w, &add_x, &add_y);
1271 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1272 + WINDOW_LEFT_MARGIN_WIDTH (w)
1273 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
1274 (WINDOW_TOP_EDGE_Y (w)
1275 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
1276 (WINDOW_BOX_RIGHT_EDGE_X (w)
1277 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1278 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
1279 (WINDOW_BOTTOM_EDGE_Y (w)
1280 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
1283 /* Test if the character at column X, row Y is within window W.
1284 If it is not, return ON_NOTHING;
1285 if it is on the window's vertical divider, return
1286 ON_RIGHT_DIVIDER;
1287 if it is on the window's horizontal divider, return
1288 ON_BOTTOM_DIVIDER;
1289 if it is in the window's text area, return ON_TEXT;
1290 if it is on the window's modeline, return ON_MODE_LINE;
1291 if it is on the border between the window and its right sibling,
1292 return ON_VERTICAL_BORDER;
1293 if it is on a scroll bar, return ON_SCROLL_BAR;
1294 if it is on the window's top line, return ON_HEADER_LINE;
1295 if it is in left or right fringe of the window,
1296 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
1297 if it is in the marginal area to the left/right of the window,
1298 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
1300 X and Y are frame relative pixel coordinates. */
1302 static enum window_part
1303 coordinates_in_window (register struct window *w, int x, int y)
1305 struct frame *f = XFRAME (WINDOW_FRAME (w));
1306 enum window_part part;
1307 int ux = FRAME_COLUMN_WIDTH (f);
1308 int left_x = WINDOW_LEFT_EDGE_X (w);
1309 int right_x = WINDOW_RIGHT_EDGE_X (w);
1310 int top_y = WINDOW_TOP_EDGE_Y (w);
1311 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
1312 /* The width of the area where the vertical line can be dragged.
1313 (Between mode lines for instance. */
1314 int grabbable_width = ux;
1315 int lmargin_width, rmargin_width, text_left, text_right;
1317 /* Outside any interesting row or column? */
1318 if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
1319 return ON_NOTHING;
1321 /* On the horizontal window divider (which prevails the vertical
1322 divider)? */
1323 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w) > 0
1324 && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1325 && y <= bottom_y)
1326 return ON_BOTTOM_DIVIDER;
1327 /* On vertical window divider? */
1328 else if (!WINDOW_RIGHTMOST_P (w)
1329 && WINDOW_RIGHT_DIVIDER_WIDTH (w) > 0
1330 && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
1331 && x <= right_x)
1332 return ON_RIGHT_DIVIDER;
1333 /* On the horizontal scroll bar? (Including the empty space at its
1334 right!) */
1335 else if ((WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
1336 && y >= (bottom_y
1337 - WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
1338 - CURRENT_MODE_LINE_HEIGHT (w)
1339 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1340 && y <= (bottom_y
1341 - CURRENT_MODE_LINE_HEIGHT (w)
1342 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))))
1343 return ON_HORIZONTAL_SCROLL_BAR;
1344 /* On the mode or header line? */
1345 else if ((WINDOW_WANTS_MODELINE_P (w)
1346 && y >= (bottom_y
1347 - CURRENT_MODE_LINE_HEIGHT (w)
1348 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1349 && y <= bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
1350 && (part = ON_MODE_LINE))
1351 || (WINDOW_WANTS_HEADER_LINE_P (w)
1352 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
1353 && (part = ON_HEADER_LINE)))
1355 /* If it's under/over the scroll bar portion of the mode/header
1356 line, say it's on the vertical line. That's to be able to
1357 resize windows horizontally in case we're using toolkit scroll
1358 bars. Note: If scrollbars are on the left, the window that
1359 must be eventually resized is that on the left of WINDOW. */
1360 if ((WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0)
1361 && ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1362 && !WINDOW_LEFTMOST_P (w)
1363 && eabs (x - left_x) < grabbable_width)
1364 || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1365 && !WINDOW_RIGHTMOST_P (w)
1366 && eabs (x - right_x) < grabbable_width)))
1367 return ON_VERTICAL_BORDER;
1368 else
1369 return part;
1372 /* In what's below, we subtract 1 when computing right_x because we
1373 want the rightmost pixel, which is given by left_pixel+width-1. */
1374 if (w->pseudo_window_p)
1376 left_x = 0;
1377 right_x = WINDOW_PIXEL_WIDTH (w) - 1;
1379 else
1381 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
1382 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
1385 /* Outside any interesting column? */
1386 if (x < left_x || x > right_x)
1387 return ON_VERTICAL_SCROLL_BAR;
1389 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
1390 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
1392 text_left = window_box_left (w, TEXT_AREA);
1393 text_right = text_left + window_box_width (w, TEXT_AREA);
1395 if (FRAME_WINDOW_P (f))
1397 if (!w->pseudo_window_p
1398 && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
1399 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
1400 && !WINDOW_RIGHTMOST_P (w)
1401 && (eabs (x - right_x) < grabbable_width))
1402 return ON_VERTICAL_BORDER;
1404 /* Need to say "x > right_x" rather than >=, since on character
1405 terminals, the vertical line's x coordinate is right_x. */
1406 else if (!w->pseudo_window_p
1407 && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
1408 && !WINDOW_RIGHTMOST_P (w)
1409 /* Why check ux if we are not the rightmost window? Also
1410 shouldn't a pseudo window always be rightmost? */
1411 && x > right_x - ux)
1412 return ON_VERTICAL_BORDER;
1414 if (x < text_left)
1416 if (lmargin_width > 0
1417 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1418 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
1419 : (x < left_x + lmargin_width)))
1420 return ON_LEFT_MARGIN;
1421 else
1422 return ON_LEFT_FRINGE;
1425 if (x >= text_right)
1427 if (rmargin_width > 0
1428 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1429 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
1430 : (x >= right_x - rmargin_width)))
1431 return ON_RIGHT_MARGIN;
1432 else
1433 return ON_RIGHT_FRINGE;
1436 /* Everything special ruled out - must be on text area */
1437 return ON_TEXT;
1440 /* Take X is the frame-relative pixel x-coordinate, and return the
1441 x-coordinate relative to part PART of window W. */
1443 window_relative_x_coord (struct window *w, enum window_part part, int x)
1445 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
1447 switch (part)
1449 case ON_TEXT:
1450 return x - window_box_left (w, TEXT_AREA);
1452 case ON_HEADER_LINE:
1453 case ON_MODE_LINE:
1454 case ON_LEFT_FRINGE:
1455 return x - left_x;
1457 case ON_RIGHT_FRINGE:
1458 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
1460 case ON_LEFT_MARGIN:
1461 return (x - left_x
1462 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1463 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
1465 case ON_RIGHT_MARGIN:
1466 return (x + 1
1467 - ((w->pseudo_window_p)
1468 ? WINDOW_PIXEL_WIDTH (w)
1469 : WINDOW_BOX_RIGHT_EDGE_X (w))
1470 + window_box_width (w, RIGHT_MARGIN_AREA)
1471 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1472 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
1475 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
1476 return 0;
1480 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
1481 Scoordinates_in_window_p, 2, 2, 0,
1482 doc: /* Return non-nil if COORDINATES are in WINDOW.
1483 WINDOW must be a live window and defaults to the selected one.
1484 COORDINATES is a cons of the form (X . Y), X and Y being distances
1485 measured in characters from the upper-left corner of the frame.
1486 \(0 . 0) denotes the character in the upper left corner of the
1487 frame.
1488 If COORDINATES are in the text portion of WINDOW,
1489 the coordinates relative to the window are returned.
1490 If they are in the bottom divider of WINDOW, `bottom-divider' is returned.
1491 If they are in the right divider of WINDOW, `right-divider' is returned.
1492 If they are in the mode line of WINDOW, `mode-line' is returned.
1493 If they are in the header line of WINDOW, `header-line' is returned.
1494 If they are in the left fringe of WINDOW, `left-fringe' is returned.
1495 If they are in the right fringe of WINDOW, `right-fringe' is returned.
1496 If they are on the border between WINDOW and its right sibling,
1497 `vertical-line' is returned.
1498 If they are in the windows's left or right marginal areas, `left-margin'\n\
1499 or `right-margin' is returned. */)
1500 (register Lisp_Object coordinates, Lisp_Object window)
1502 struct window *w;
1503 struct frame *f;
1504 int x, y;
1505 Lisp_Object lx, ly;
1507 w = decode_live_window (window);
1508 f = XFRAME (w->frame);
1509 CHECK_CONS (coordinates);
1510 lx = Fcar (coordinates);
1511 ly = Fcdr (coordinates);
1512 CHECK_NUMBER_OR_FLOAT (lx);
1513 CHECK_NUMBER_OR_FLOAT (ly);
1514 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1515 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
1517 switch (coordinates_in_window (w, x, y))
1519 case ON_NOTHING:
1520 return Qnil;
1522 case ON_TEXT:
1523 /* Convert X and Y to window relative pixel coordinates, and
1524 return the canonical char units. */
1525 x -= window_box_left (w, TEXT_AREA);
1526 y -= WINDOW_TOP_EDGE_Y (w);
1527 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1528 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
1530 case ON_MODE_LINE:
1531 return Qmode_line;
1533 case ON_VERTICAL_BORDER:
1534 return Qvertical_line;
1536 case ON_HEADER_LINE:
1537 return Qheader_line;
1539 case ON_LEFT_FRINGE:
1540 return Qleft_fringe;
1542 case ON_RIGHT_FRINGE:
1543 return Qright_fringe;
1545 case ON_LEFT_MARGIN:
1546 return Qleft_margin;
1548 case ON_RIGHT_MARGIN:
1549 return Qright_margin;
1551 case ON_VERTICAL_SCROLL_BAR:
1552 /* Historically we are supposed to return nil in this case. */
1553 return Qnil;
1555 case ON_HORIZONTAL_SCROLL_BAR:
1556 return Qnil;
1558 case ON_RIGHT_DIVIDER:
1559 return Qright_divider;
1561 case ON_BOTTOM_DIVIDER:
1562 return Qbottom_divider;
1564 default:
1565 emacs_abort ();
1570 /* Callback for foreach_window, used in window_from_coordinates.
1571 Check if window W contains coordinates specified by USER_DATA which
1572 is actually a pointer to a struct check_window_data CW.
1574 Check if window W contains coordinates *CW->x and *CW->y. If it
1575 does, return W in *CW->window, as Lisp_Object, and return in
1576 *CW->part the part of the window under coordinates *X,*Y. Return
1577 false from this function to stop iterating over windows. */
1579 struct check_window_data
1581 Lisp_Object *window;
1582 int x, y;
1583 enum window_part *part;
1586 static bool
1587 check_window_containing (struct window *w, void *user_data)
1589 struct check_window_data *cw = user_data;
1590 enum window_part found = coordinates_in_window (w, cw->x, cw->y);
1591 if (found == ON_NOTHING)
1592 return true;
1593 else
1595 *cw->part = found;
1596 XSETWINDOW (*cw->window, w);
1597 return false;
1602 /* Find the window containing frame-relative pixel position X/Y and
1603 return it as a Lisp_Object.
1605 If X, Y is on one of the window's special `window_part' elements,
1606 set *PART to the id of that element.
1608 If there is no window under X, Y return nil and leave *PART
1609 unmodified. TOOL_BAR_P means detect tool-bar windows.
1611 This function was previously implemented with a loop cycling over
1612 windows with Fnext_window, and starting with the frame's selected
1613 window. It turned out that this doesn't work with an
1614 implementation of next_window using Vwindow_list, because
1615 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1616 tree of F when this function is called asynchronously from
1617 note_mouse_highlight. The original loop didn't terminate in this
1618 case. */
1620 Lisp_Object
1621 window_from_coordinates (struct frame *f, int x, int y,
1622 enum window_part *part, bool tool_bar_p)
1624 Lisp_Object window;
1625 struct check_window_data cw;
1626 enum window_part dummy;
1628 if (part == 0)
1629 part = &dummy;
1631 window = Qnil;
1632 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
1633 foreach_window (f, check_window_containing, &cw);
1635 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
1636 /* If not found above, see if it's in the tool bar window, if a tool
1637 bar exists. */
1638 if (NILP (window)
1639 && tool_bar_p
1640 && WINDOWP (f->tool_bar_window)
1641 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1642 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
1643 != ON_NOTHING))
1645 *part = ON_TEXT;
1646 window = f->tool_bar_window;
1648 #endif
1650 return window;
1653 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1654 doc: /* Return window containing coordinates X and Y on FRAME.
1655 FRAME must be a live frame and defaults to the selected one.
1656 The top left corner of the frame is considered to be row 0,
1657 column 0. */)
1658 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1660 struct frame *f = decode_live_frame (frame);
1662 /* Check that arguments are integers or floats. */
1663 CHECK_NUMBER_OR_FLOAT (x);
1664 CHECK_NUMBER_OR_FLOAT (y);
1666 return window_from_coordinates (f,
1667 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1668 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1669 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1670 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1671 0, false);
1674 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1675 doc: /* Return current value of point in WINDOW.
1676 WINDOW must be a live window and defaults to the selected one.
1678 For a nonselected window, this is the value point would have if that
1679 window were selected.
1681 Note that, when WINDOW is selected, the value returned is the same as
1682 that returned by `point' for WINDOW's buffer. It would be more strictly
1683 correct to return the top-level value of `point', outside of any
1684 `save-excursion' forms. But that is hard to define. */)
1685 (Lisp_Object window)
1687 register struct window *w = decode_live_window (window);
1689 if (w == XWINDOW (selected_window))
1690 return make_number (BUF_PT (XBUFFER (w->contents)));
1691 else
1692 return Fmarker_position (w->pointm);
1695 DEFUN ("window-old-point", Fwindow_old_point, Swindow_old_point, 0, 1, 0,
1696 doc: /* Return old value of point in WINDOW.
1697 WINDOW must be a live window and defaults to the selected one. */)
1698 (Lisp_Object window)
1700 return Fmarker_position (decode_live_window (window)->old_pointm);
1703 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1704 doc: /* Return position at which display currently starts in WINDOW.
1705 WINDOW must be a live window and defaults to the selected one.
1706 This is updated by redisplay or by calling `set-window-start'. */)
1707 (Lisp_Object window)
1709 return Fmarker_position (decode_live_window (window)->start);
1712 /* This is text temporarily removed from the doc string below.
1714 This function returns nil if the position is not currently known.
1715 That happens when redisplay is preempted and doesn't finish.
1716 If in that case you want to compute where the end of the window would
1717 have been if redisplay had finished, do this:
1718 (save-excursion
1719 (goto-char (window-start window))
1720 (vertical-motion (1- (window-height window)) window)
1721 (point))") */
1723 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1724 doc: /* Return position at which display currently ends in WINDOW.
1725 WINDOW must be a live window and defaults to the selected one.
1726 This is updated by redisplay, when it runs to completion.
1727 Simply changing the buffer text or setting `window-start'
1728 does not update this value.
1729 Return nil if there is no recorded value. (This can happen if the
1730 last redisplay of WINDOW was preempted, and did not finish.)
1731 If UPDATE is non-nil, compute the up-to-date position
1732 if it isn't already recorded. */)
1733 (Lisp_Object window, Lisp_Object update)
1735 Lisp_Object value;
1736 struct window *w = decode_live_window (window);
1737 Lisp_Object buf;
1738 struct buffer *b;
1740 buf = w->contents;
1741 CHECK_BUFFER (buf);
1742 b = XBUFFER (buf);
1744 if (! NILP (update)
1745 && (windows_or_buffers_changed
1746 || !w->window_end_valid
1747 || b->clip_changed
1748 || b->prevent_redisplay_optimizations_p
1749 || window_outdated (w))
1750 && !noninteractive)
1752 struct text_pos startp;
1753 struct it it;
1754 struct buffer *old_buffer = NULL;
1755 void *itdata = NULL;
1757 /* Cannot use Fvertical_motion because that function doesn't
1758 cope with variable-height lines. */
1759 if (b != current_buffer)
1761 old_buffer = current_buffer;
1762 set_buffer_internal (b);
1765 /* In case W->start is out of the range, use something
1766 reasonable. This situation occurred when loading a file with
1767 `-l' containing a call to `rmail' with subsequent other
1768 commands. At the end, W->start happened to be BEG, while
1769 rmail had already narrowed the buffer. */
1770 CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
1772 itdata = bidi_shelve_cache ();
1773 start_display (&it, w, startp);
1774 move_it_vertically (&it, window_box_height (w));
1775 if (it.current_y < it.last_visible_y)
1776 move_it_past_eol (&it);
1777 value = make_number (IT_CHARPOS (it));
1778 bidi_unshelve_cache (itdata, false);
1780 if (old_buffer)
1781 set_buffer_internal (old_buffer);
1783 else
1784 XSETINT (value, BUF_Z (b) - w->window_end_pos);
1786 return value;
1789 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1790 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1791 WINDOW must be a live window and defaults to the selected one.
1792 Return POS. */)
1793 (Lisp_Object window, Lisp_Object pos)
1795 register struct window *w = decode_live_window (window);
1797 /* Type of POS is checked by Fgoto_char or set_marker_restricted ... */
1799 if (w == XWINDOW (selected_window))
1801 if (XBUFFER (w->contents) == current_buffer)
1802 Fgoto_char (pos);
1803 else
1805 struct buffer *old_buffer = current_buffer;
1807 /* ... but here we want to catch type error before buffer change. */
1808 CHECK_NUMBER_COERCE_MARKER (pos);
1809 set_buffer_internal (XBUFFER (w->contents));
1810 Fgoto_char (pos);
1811 set_buffer_internal (old_buffer);
1814 else
1816 set_marker_restricted (w->pointm, pos, w->contents);
1817 /* We have to make sure that redisplay updates the window to show
1818 the new value of point. */
1819 wset_redisplay (w);
1822 return pos;
1825 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1826 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1827 WINDOW must be a live window and defaults to the selected one. Return
1828 POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
1829 overriding motion of point in order to display at this exact start. */)
1830 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1832 register struct window *w = decode_live_window (window);
1834 set_marker_restricted (w->start, pos, w->contents);
1835 /* This is not right, but much easier than doing what is right. */
1836 w->start_at_line_beg = false;
1837 if (NILP (noforce))
1838 w->force_start = true;
1839 w->update_mode_line = true;
1840 /* Bug#15957. */
1841 w->window_end_valid = false;
1842 wset_redisplay (w);
1844 return pos;
1847 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1848 Spos_visible_in_window_p, 0, 3, 0,
1849 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1850 WINDOW must be a live window and defaults to the selected one.
1852 Return nil if that position is scrolled vertically out of view. If a
1853 character is only partially visible, nil is returned, unless the
1854 optional argument PARTIALLY is non-nil. If POS is only out of view
1855 because of horizontal scrolling, return non-nil. If POS is t, it
1856 specifies the position of the last visible glyph in WINDOW. POS
1857 defaults to point in WINDOW; WINDOW defaults to the selected window.
1859 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
1860 the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
1861 where X and Y are the pixel coordinates relative to the top left corner
1862 of the window. The remaining elements are omitted if the character after
1863 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1864 off-window at the top and bottom of the screen line ("row") containing
1865 POS, ROWH is the visible height of that row, and VPOS is the row number
1866 \(zero-based). */)
1867 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1869 struct window *w;
1870 EMACS_INT posint;
1871 struct buffer *buf;
1872 struct text_pos top;
1873 Lisp_Object in_window = Qnil;
1874 int rtop, rbot, rowh, vpos;
1875 bool fully_p = true;
1876 int x, y;
1878 w = decode_live_window (window);
1879 buf = XBUFFER (w->contents);
1880 SET_TEXT_POS_FROM_MARKER (top, w->start);
1882 if (EQ (pos, Qt))
1883 posint = -1;
1884 else if (!NILP (pos))
1886 CHECK_NUMBER_COERCE_MARKER (pos);
1887 posint = XINT (pos);
1889 else if (w == XWINDOW (selected_window))
1890 posint = PT;
1891 else
1892 posint = marker_position (w->pointm);
1894 /* If position is above window start or outside buffer boundaries,
1895 or if window start is out of range, position is not visible. */
1896 if ((EQ (pos, Qt)
1897 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
1898 && CHARPOS (top) >= BUF_BEGV (buf)
1899 && CHARPOS (top) <= BUF_ZV (buf)
1900 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos))
1902 fully_p = !rtop && !rbot;
1903 if (!NILP (partially) || fully_p)
1904 in_window = Qt;
1907 if (!NILP (in_window) && !NILP (partially))
1909 Lisp_Object part = Qnil;
1910 if (!fully_p)
1911 part = list4i (rtop, rbot, rowh, vpos);
1912 in_window = Fcons (make_number (x),
1913 Fcons (make_number (y), part));
1916 return in_window;
1919 DEFUN ("window-line-height", Fwindow_line_height,
1920 Swindow_line_height, 0, 2, 0,
1921 doc: /* Return height in pixels of text line LINE in window WINDOW.
1922 WINDOW must be a live window and defaults to the selected one.
1924 Return height of current line if LINE is omitted or nil. Return height of
1925 header or mode line if LINE is `header-line' or `mode-line'.
1926 Otherwise, LINE is a text line number starting from 0. A negative number
1927 counts from the end of the window.
1929 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
1930 in pixels of the visible part of the line, VPOS and YPOS are the
1931 vertical position in lines and pixels of the line, relative to the top
1932 of the first text line, and OFFBOT is the number of off-window pixels at
1933 the bottom of the text line. If there are off-window pixels at the top
1934 of the (first) text line, YPOS is negative.
1936 Return nil if window display is not up-to-date. In that case, use
1937 `pos-visible-in-window-p' to obtain the information. */)
1938 (Lisp_Object line, Lisp_Object window)
1940 register struct window *w;
1941 register struct buffer *b;
1942 struct glyph_row *row, *end_row;
1943 int max_y, crop, i;
1944 EMACS_INT n;
1946 w = decode_live_window (window);
1948 if (noninteractive || w->pseudo_window_p)
1949 return Qnil;
1951 CHECK_BUFFER (w->contents);
1952 b = XBUFFER (w->contents);
1954 /* Fail if current matrix is not up-to-date. */
1955 if (!w->window_end_valid
1956 || windows_or_buffers_changed
1957 || b->clip_changed
1958 || b->prevent_redisplay_optimizations_p
1959 || window_outdated (w))
1960 return Qnil;
1962 if (NILP (line))
1964 i = w->cursor.vpos;
1965 if (i < 0 || i >= w->current_matrix->nrows
1966 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
1967 return Qnil;
1968 max_y = window_text_bottom_y (w);
1969 goto found_row;
1972 if (EQ (line, Qheader_line))
1974 if (!WINDOW_WANTS_HEADER_LINE_P (w))
1975 return Qnil;
1976 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1977 return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
1980 if (EQ (line, Qmode_line))
1982 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1983 return (row->enabled_p ?
1984 list4i (row->height,
1985 0, /* not accurate */
1986 (WINDOW_HEADER_LINE_HEIGHT (w)
1987 + window_text_bottom_y (w)),
1989 : Qnil);
1992 CHECK_NUMBER (line);
1993 n = XINT (line);
1995 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1996 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
1997 max_y = window_text_bottom_y (w);
1998 i = 0;
2000 while ((n < 0 || i < n)
2001 && row <= end_row && row->enabled_p
2002 && row->y + row->height < max_y)
2003 row++, i++;
2005 if (row > end_row || !row->enabled_p)
2006 return Qnil;
2008 if (++n < 0)
2010 if (-n > i)
2011 return Qnil;
2012 row += n;
2013 i += n;
2016 found_row:
2017 crop = max (0, (row->y + row->height) - max_y);
2018 return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
2021 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
2022 0, 1, 0,
2023 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
2024 More precisely, return the value assigned by the last call of
2025 `set-window-dedicated-p' for WINDOW. Return nil if that function was
2026 never called with WINDOW as its argument, or the value set by that
2027 function was internally reset since its last call. WINDOW must be a
2028 live window and defaults to the selected one.
2030 When a window is dedicated to its buffer, `display-buffer' will refrain
2031 from displaying another buffer in it. `get-lru-window' and
2032 `get-largest-window' treat dedicated windows specially.
2033 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
2034 `kill-buffer' can delete a dedicated window and the containing frame.
2036 Functions like `set-window-buffer' may change the buffer displayed by a
2037 window, unless that window is "strongly" dedicated to its buffer, that
2038 is the value returned by `window-dedicated-p' is t. */)
2039 (Lisp_Object window)
2041 return decode_live_window (window)->dedicated;
2044 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
2045 Sset_window_dedicated_p, 2, 2, 0,
2046 doc: /* Mark WINDOW as dedicated according to FLAG.
2047 WINDOW must be a live window and defaults to the selected one. FLAG
2048 non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
2049 mark WINDOW as non-dedicated. Return FLAG.
2051 When a window is dedicated to its buffer, `display-buffer' will refrain
2052 from displaying another buffer in it. `get-lru-window' and
2053 `get-largest-window' treat dedicated windows specially.
2054 `delete-windows-on', `replace-buffer-in-windows', `quit-window',
2055 `quit-restore-window' and `kill-buffer' can delete a dedicated window
2056 and the containing frame.
2058 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
2059 its buffer. Functions like `set-window-buffer' may change the buffer
2060 displayed by a window, unless that window is strongly dedicated to its
2061 buffer. If and when `set-window-buffer' displays another buffer in a
2062 window, it also makes sure that the window is no more dedicated. */)
2063 (Lisp_Object window, Lisp_Object flag)
2065 wset_dedicated (decode_live_window (window), flag);
2066 return flag;
2069 DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
2070 0, 1, 0,
2071 doc: /* Return buffers previously shown in WINDOW.
2072 WINDOW must be a live window and defaults to the selected one.
2074 The return value is a list of elements (BUFFER WINDOW-START POS),
2075 where BUFFER is a buffer, WINDOW-START is the start position of the
2076 window for that buffer, and POS is a window-specific point value. */)
2077 (Lisp_Object window)
2079 return decode_live_window (window)->prev_buffers;
2082 DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
2083 Sset_window_prev_buffers, 2, 2, 0,
2084 doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
2085 WINDOW must be a live window and defaults to the selected one.
2087 PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS),
2088 where BUFFER is a buffer, WINDOW-START is the start position of the
2089 window for that buffer, and POS is a window-specific point value. */)
2090 (Lisp_Object window, Lisp_Object prev_buffers)
2092 wset_prev_buffers (decode_live_window (window), prev_buffers);
2093 return prev_buffers;
2096 DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
2097 0, 1, 0,
2098 doc: /* Return list of buffers recently re-shown in WINDOW.
2099 WINDOW must be a live window and defaults to the selected one. */)
2100 (Lisp_Object window)
2102 return decode_live_window (window)->next_buffers;
2105 DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
2106 Sset_window_next_buffers, 2, 2, 0,
2107 doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
2108 WINDOW must be a live window and defaults to the selected one.
2109 NEXT-BUFFERS should be a list of buffers. */)
2110 (Lisp_Object window, Lisp_Object next_buffers)
2112 wset_next_buffers (decode_live_window (window), next_buffers);
2113 return next_buffers;
2116 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
2117 0, 1, 0,
2118 doc: /* Return the parameters of WINDOW and their values.
2119 WINDOW must be a valid window and defaults to the selected one. The
2120 return value is a list of elements of the form (PARAMETER . VALUE). */)
2121 (Lisp_Object window)
2123 return Fcopy_alist (decode_valid_window (window)->window_parameters);
2126 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
2127 2, 2, 0,
2128 doc: /* Return WINDOW's value for PARAMETER.
2129 WINDOW can be any window and defaults to the selected one. */)
2130 (Lisp_Object window, Lisp_Object parameter)
2132 Lisp_Object result;
2134 result = Fassq (parameter, decode_any_window (window)->window_parameters);
2135 return CDR_SAFE (result);
2138 DEFUN ("set-window-parameter", Fset_window_parameter,
2139 Sset_window_parameter, 3, 3, 0,
2140 doc: /* Set WINDOW's value of PARAMETER to VALUE.
2141 WINDOW can be any window and defaults to the selected one.
2142 Return VALUE. */)
2143 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
2145 register struct window *w = decode_any_window (window);
2146 Lisp_Object old_alist_elt;
2148 old_alist_elt = Fassq (parameter, w->window_parameters);
2149 if (NILP (old_alist_elt))
2150 wset_window_parameters
2151 (w, Fcons (Fcons (parameter, value), w->window_parameters));
2152 else
2153 Fsetcdr (old_alist_elt, value);
2154 return value;
2157 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
2158 0, 1, 0,
2159 doc: /* Return the display-table that WINDOW is using.
2160 WINDOW must be a live window and defaults to the selected one. */)
2161 (Lisp_Object window)
2163 return decode_live_window (window)->display_table;
2166 /* Get the display table for use on window W. This is either W's
2167 display table or W's buffer's display table. Ignore the specified
2168 tables if they are not valid; if no valid table is specified,
2169 return 0. */
2171 struct Lisp_Char_Table *
2172 window_display_table (struct window *w)
2174 struct Lisp_Char_Table *dp = NULL;
2176 if (DISP_TABLE_P (w->display_table))
2177 dp = XCHAR_TABLE (w->display_table);
2178 else if (BUFFERP (w->contents))
2180 struct buffer *b = XBUFFER (w->contents);
2182 if (DISP_TABLE_P (BVAR (b, display_table)))
2183 dp = XCHAR_TABLE (BVAR (b, display_table));
2184 else if (DISP_TABLE_P (Vstandard_display_table))
2185 dp = XCHAR_TABLE (Vstandard_display_table);
2188 return dp;
2191 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
2192 doc: /* Set WINDOW's display-table to TABLE.
2193 WINDOW must be a live window and defaults to the selected one. */)
2194 (register Lisp_Object window, Lisp_Object table)
2196 wset_display_table (decode_live_window (window), table);
2197 return table;
2200 /* Record info on buffer window W is displaying
2201 when it is about to cease to display that buffer. */
2202 static void
2203 unshow_buffer (register struct window *w)
2205 Lisp_Object buf = w->contents;
2206 struct buffer *b = XBUFFER (buf);
2208 eassert (b == XMARKER (w->pointm)->buffer);
2210 #if false
2211 if (w == XWINDOW (selected_window)
2212 || ! EQ (buf, XWINDOW (selected_window)->contents))
2213 /* Do this except when the selected window's buffer
2214 is being removed from some other window. */
2215 #endif
2216 /* last_window_start records the start position that this buffer
2217 had in the last window to be disconnected from it.
2218 Now that this statement is unconditional,
2219 it is possible for the buffer to be displayed in the
2220 selected window, while last_window_start reflects another
2221 window which was recently showing the same buffer.
2222 Some people might say that might be a good thing. Let's see. */
2223 b->last_window_start = marker_position (w->start);
2225 /* Point in the selected window's buffer
2226 is actually stored in that buffer, and the window's pointm isn't used.
2227 So don't clobber point in that buffer. */
2228 if (! EQ (buf, XWINDOW (selected_window)->contents)
2229 /* Don't clobber point in current buffer either (this could be
2230 useful in connection with bug#12208).
2231 && XBUFFER (buf) != current_buffer */
2232 /* This line helps to fix Horsley's testbug.el bug. */
2233 && !(WINDOWP (BVAR (b, last_selected_window))
2234 && w != XWINDOW (BVAR (b, last_selected_window))
2235 && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->contents)))
2236 temp_set_point_both (b,
2237 clip_to_bounds (BUF_BEGV (b),
2238 marker_position (w->pointm),
2239 BUF_ZV (b)),
2240 clip_to_bounds (BUF_BEGV_BYTE (b),
2241 marker_byte_position (w->pointm),
2242 BUF_ZV_BYTE (b)));
2244 if (WINDOWP (BVAR (b, last_selected_window))
2245 && w == XWINDOW (BVAR (b, last_selected_window)))
2246 bset_last_selected_window (b, Qnil);
2249 /* Put NEW into the window structure in place of OLD. SETFLAG false
2250 means change window structure only. Otherwise store geometry and
2251 other settings as well. */
2252 static void
2253 replace_window (Lisp_Object old, Lisp_Object new, bool setflag)
2255 Lisp_Object tem;
2256 struct window *o = XWINDOW (old), *n = XWINDOW (new);
2258 /* If OLD is its frame's root window, then NEW is the new
2259 root window for that frame. */
2260 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
2261 fset_root_window (XFRAME (o->frame), new);
2263 if (setflag)
2265 n->pixel_left = o->pixel_left;
2266 n->pixel_top = o->pixel_top;
2267 n->pixel_width = o->pixel_width;
2268 n->pixel_height = o->pixel_height;
2269 n->left_col = o->left_col;
2270 n->top_line = o->top_line;
2271 n->total_cols = o->total_cols;
2272 n->total_lines = o->total_lines;
2273 wset_normal_cols (n, o->normal_cols);
2274 wset_normal_cols (o, make_float (1.0));
2275 wset_normal_lines (n, o->normal_lines);
2276 wset_normal_lines (o, make_float (1.0));
2277 n->desired_matrix = n->current_matrix = 0;
2278 n->vscroll = 0;
2279 memset (&n->cursor, 0, sizeof (n->cursor));
2280 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
2281 n->last_cursor_vpos = 0;
2282 #ifdef HAVE_WINDOW_SYSTEM
2283 n->phys_cursor_type = NO_CURSOR;
2284 n->phys_cursor_width = -1;
2285 #endif
2286 n->must_be_updated_p = false;
2287 n->pseudo_window_p = false;
2288 n->window_end_vpos = 0;
2289 n->window_end_pos = 0;
2290 n->window_end_valid = false;
2293 tem = o->next;
2294 wset_next (n, tem);
2295 if (!NILP (tem))
2296 wset_prev (XWINDOW (tem), new);
2298 tem = o->prev;
2299 wset_prev (n, tem);
2300 if (!NILP (tem))
2301 wset_next (XWINDOW (tem), new);
2303 tem = o->parent;
2304 wset_parent (n, tem);
2305 if (!NILP (tem) && EQ (XWINDOW (tem)->contents, old))
2306 wset_combination (XWINDOW (tem), XWINDOW (tem)->horizontal, new);
2309 /* If window WINDOW and its parent window are iso-combined, merge
2310 WINDOW's children into those of its parent window and mark WINDOW as
2311 deleted. */
2313 static void
2314 recombine_windows (Lisp_Object window)
2316 struct window *w, *p, *c;
2317 Lisp_Object parent, child;
2318 bool horflag;
2320 w = XWINDOW (window);
2321 parent = w->parent;
2322 if (!NILP (parent) && NILP (w->combination_limit))
2324 p = XWINDOW (parent);
2325 if (WINDOWP (p->contents) && WINDOWP (w->contents)
2326 && p->horizontal == w->horizontal)
2327 /* WINDOW and PARENT are both either a vertical or a horizontal
2328 combination. */
2330 horflag = WINDOW_HORIZONTAL_COMBINATION_P (w);
2331 child = w->contents;
2332 c = XWINDOW (child);
2334 /* Splice WINDOW's children into its parent's children and
2335 assign new normal sizes. */
2336 if (NILP (w->prev))
2337 wset_combination (p, horflag, child);
2338 else
2340 wset_prev (c, w->prev);
2341 wset_next (XWINDOW (w->prev), child);
2344 while (c)
2346 wset_parent (c, parent);
2348 if (horflag)
2349 wset_normal_cols
2350 (c, make_float ((double) c->pixel_width
2351 / (double) p->pixel_width));
2352 else
2353 wset_normal_lines
2354 (c, make_float ((double) c->pixel_height
2355 / (double) p->pixel_height));
2357 if (NILP (c->next))
2359 if (!NILP (w->next))
2361 wset_next (c, w->next);
2362 wset_prev (XWINDOW (c->next), child);
2365 c = 0;
2367 else
2369 child = c->next;
2370 c = XWINDOW (child);
2374 /* WINDOW can be deleted now. */
2375 wset_combination (w, false, Qnil);
2380 /* If WINDOW can be deleted, delete it. */
2381 static void
2382 delete_deletable_window (Lisp_Object window)
2384 if (!NILP (call1 (Qwindow_deletable_p, window)))
2385 call1 (Qdelete_window, window);
2388 /***********************************************************************
2389 Window List
2390 ***********************************************************************/
2392 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
2393 pointer. This is a callback function for foreach_window, used in
2394 the window_list function. */
2396 static bool
2397 add_window_to_list (struct window *w, void *user_data)
2399 Lisp_Object *list = user_data;
2400 Lisp_Object window;
2401 XSETWINDOW (window, w);
2402 *list = Fcons (window, *list);
2403 return true;
2407 /* Return a list of all windows, for use by next_window. If
2408 Vwindow_list is a list, return that list. Otherwise, build a new
2409 list, cache it in Vwindow_list, and return that. */
2411 Lisp_Object
2412 window_list (void)
2414 if (!CONSP (Vwindow_list))
2416 Lisp_Object tail, frame;
2418 Vwindow_list = Qnil;
2419 FOR_EACH_FRAME (tail, frame)
2421 Lisp_Object arglist = Qnil;
2423 /* We are visiting windows in canonical order, and add
2424 new windows at the front of args[1], which means we
2425 have to reverse this list at the end. */
2426 foreach_window (XFRAME (frame), add_window_to_list, &arglist);
2427 arglist = Fnreverse (arglist);
2428 Vwindow_list = CALLN (Fnconc, Vwindow_list, arglist);
2432 return Vwindow_list;
2436 /* Value is true if WINDOW satisfies the constraints given by
2437 OWINDOW, MINIBUF and ALL_FRAMES.
2439 MINIBUF t means WINDOW may be minibuffer windows.
2440 `lambda' means WINDOW may not be a minibuffer window.
2441 a window means a specific minibuffer window
2443 ALL_FRAMES t means search all frames,
2444 nil means search just current frame,
2445 `visible' means search just visible frames on the
2446 current terminal,
2447 0 means search visible and iconified frames on the
2448 current terminal,
2449 a window means search the frame that window belongs to,
2450 a frame means consider windows on that frame, only. */
2452 static bool
2453 candidate_window_p (Lisp_Object window, Lisp_Object owindow,
2454 Lisp_Object minibuf, Lisp_Object all_frames)
2456 struct window *w = XWINDOW (window);
2457 struct frame *f = XFRAME (w->frame);
2458 bool candidate_p = true;
2460 if (!BUFFERP (w->contents))
2461 candidate_p = false;
2462 else if (MINI_WINDOW_P (w)
2463 && (EQ (minibuf, Qlambda)
2464 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
2466 /* If MINIBUF is `lambda' don't consider any mini-windows.
2467 If it is a window, consider only that one. */
2468 candidate_p = false;
2470 else if (EQ (all_frames, Qt))
2471 candidate_p = true;
2472 else if (NILP (all_frames))
2474 eassert (WINDOWP (owindow));
2475 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
2477 else if (EQ (all_frames, Qvisible))
2479 candidate_p = FRAME_VISIBLE_P (f)
2480 && (FRAME_TERMINAL (XFRAME (w->frame))
2481 == FRAME_TERMINAL (XFRAME (selected_frame)));
2484 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2486 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2487 #ifdef HAVE_X_WINDOWS
2488 /* Yuck!! If we've just created the frame and the
2489 window-manager requested the user to place it
2490 manually, the window may still not be considered
2491 `visible'. I'd argue it should be at least
2492 something like `iconified', but don't know how to do
2493 that yet. --Stef */
2494 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
2495 && !f->output_data.x->has_been_visible)
2496 #endif
2498 && (FRAME_TERMINAL (XFRAME (w->frame))
2499 == FRAME_TERMINAL (XFRAME (selected_frame)));
2501 else if (WINDOWP (all_frames))
2502 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
2503 || EQ (XWINDOW (all_frames)->frame, w->frame)
2504 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
2505 else if (FRAMEP (all_frames))
2506 candidate_p = EQ (all_frames, w->frame);
2508 return candidate_p;
2512 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
2513 Fwindow_list. See candidate_window_p for the meaning of WINDOW,
2514 MINIBUF, and ALL_FRAMES. */
2516 static void
2517 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
2519 struct window *w = decode_live_window (*window);
2521 XSETWINDOW (*window, w);
2522 /* MINIBUF nil may or may not include minibuffers. Decide if it
2523 does. */
2524 if (NILP (*minibuf))
2525 *minibuf = minibuf_level ? minibuf_window : Qlambda;
2526 else if (!EQ (*minibuf, Qt))
2527 *minibuf = Qlambda;
2529 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
2530 => count none of them, or a specific minibuffer window (the
2531 active one) to count. */
2533 /* ALL_FRAMES nil doesn't specify which frames to include. */
2534 if (NILP (*all_frames))
2535 *all_frames
2536 = (!EQ (*minibuf, Qlambda)
2537 ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame))
2538 : Qnil);
2539 else if (EQ (*all_frames, Qvisible))
2541 else if (EQ (*all_frames, make_number (0)))
2543 else if (FRAMEP (*all_frames))
2545 else if (!EQ (*all_frames, Qt))
2546 *all_frames = Qnil;
2550 /* Return the next or previous window of WINDOW in cyclic ordering
2551 of windows. NEXT_P means return the next window. See the
2552 documentation string of next-window for the meaning of MINIBUF and
2553 ALL_FRAMES. */
2555 static Lisp_Object
2556 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
2557 bool next_p)
2559 decode_next_window_args (&window, &minibuf, &all_frames);
2561 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
2562 return the first window on the frame. */
2563 if (FRAMEP (all_frames)
2564 && !EQ (all_frames, XWINDOW (window)->frame))
2565 return Fframe_first_window (all_frames);
2567 if (next_p)
2569 Lisp_Object list;
2571 /* Find WINDOW in the list of all windows. */
2572 list = Fmemq (window, window_list ());
2574 /* Scan forward from WINDOW to the end of the window list. */
2575 if (CONSP (list))
2576 for (list = XCDR (list); CONSP (list); list = XCDR (list))
2577 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2578 break;
2580 /* Scan from the start of the window list up to WINDOW. */
2581 if (!CONSP (list))
2582 for (list = Vwindow_list;
2583 CONSP (list) && !EQ (XCAR (list), window);
2584 list = XCDR (list))
2585 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2586 break;
2588 if (CONSP (list))
2589 window = XCAR (list);
2591 else
2593 Lisp_Object candidate, list;
2595 /* Scan through the list of windows for candidates. If there are
2596 candidate windows in front of WINDOW, the last one of these
2597 is the one we want. If there are candidates following WINDOW
2598 in the list, again the last one of these is the one we want. */
2599 candidate = Qnil;
2600 for (list = window_list (); CONSP (list); list = XCDR (list))
2602 if (EQ (XCAR (list), window))
2604 if (WINDOWP (candidate))
2605 break;
2607 else if (candidate_window_p (XCAR (list), window, minibuf,
2608 all_frames))
2609 candidate = XCAR (list);
2612 if (WINDOWP (candidate))
2613 window = candidate;
2616 return window;
2620 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2621 doc: /* Return live window after WINDOW in the cyclic ordering of windows.
2622 WINDOW must be a live window and defaults to the selected one. The
2623 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2624 consider.
2626 MINIBUF nil or omitted means consider the minibuffer window only if the
2627 minibuffer is active. MINIBUF t means consider the minibuffer window
2628 even if the minibuffer is not active. Any other value means do not
2629 consider the minibuffer window even if the minibuffer is active.
2631 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2632 plus the minibuffer window if specified by the MINIBUF argument. If the
2633 minibuffer counts, consider all windows on all frames that share that
2634 minibuffer too. The following non-nil values of ALL-FRAMES have special
2635 meanings:
2637 - t means consider all windows on all existing frames.
2639 - `visible' means consider all windows on all visible frames.
2641 - 0 (the number zero) means consider all windows on all visible and
2642 iconified frames.
2644 - A frame means consider all windows on that frame only.
2646 Anything else means consider all windows on WINDOW's frame and no
2647 others.
2649 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2650 `next-window' to iterate through the entire cycle of acceptable
2651 windows, eventually ending up back at the window you started with.
2652 `previous-window' traverses the same cycle, in the reverse order. */)
2653 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2655 return next_window (window, minibuf, all_frames, true);
2659 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2660 doc: /* Return live window before WINDOW in the cyclic ordering of windows.
2661 WINDOW must be a live window and defaults to the selected one. The
2662 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2663 consider.
2665 MINIBUF nil or omitted means consider the minibuffer window only if the
2666 minibuffer is active. MINIBUF t means consider the minibuffer window
2667 even if the minibuffer is not active. Any other value means do not
2668 consider the minibuffer window even if the minibuffer is active.
2670 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2671 plus the minibuffer window if specified by the MINIBUF argument. If the
2672 minibuffer counts, consider all windows on all frames that share that
2673 minibuffer too. The following non-nil values of ALL-FRAMES have special
2674 meanings:
2676 - t means consider all windows on all existing frames.
2678 - `visible' means consider all windows on all visible frames.
2680 - 0 (the number zero) means consider all windows on all visible and
2681 iconified frames.
2683 - A frame means consider all windows on that frame only.
2685 Anything else means consider all windows on WINDOW's frame and no
2686 others.
2688 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2689 use `previous-window' to iterate through the entire cycle of
2690 acceptable windows, eventually ending up back at the window you
2691 started with. `next-window' traverses the same cycle, in the
2692 reverse order. */)
2693 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2695 return next_window (window, minibuf, all_frames, false);
2699 /* Return a list of windows in cyclic ordering. Arguments are like
2700 for `next-window'. */
2702 static Lisp_Object
2703 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2705 Lisp_Object tail, list, rest;
2707 decode_next_window_args (&window, &minibuf, &all_frames);
2708 list = Qnil;
2710 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2711 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2712 list = Fcons (XCAR (tail), list);
2714 /* Rotate the list to start with WINDOW. */
2715 list = Fnreverse (list);
2716 rest = Fmemq (window, list);
2717 if (!NILP (rest) && !EQ (rest, list))
2719 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2721 XSETCDR (tail, Qnil);
2722 list = nconc2 (rest, list);
2724 return list;
2728 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2729 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2730 FRAME nil or omitted means use the selected frame.
2731 WINDOW nil or omitted means use the window selected within FRAME.
2732 MINIBUF t means include the minibuffer window, even if it isn't active.
2733 MINIBUF nil or omitted means include the minibuffer window only
2734 if it's active.
2735 MINIBUF neither nil nor t means never include the minibuffer window. */)
2736 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2738 if (NILP (window))
2739 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2740 CHECK_WINDOW (window);
2741 if (NILP (frame))
2742 frame = selected_frame;
2744 if (!EQ (frame, XWINDOW (window)->frame))
2745 error ("Window is on a different frame");
2747 return window_list_1 (window, minibuf, frame);
2751 DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2752 doc: /* Return a list of all live windows.
2753 WINDOW specifies the first window to list and defaults to the selected
2754 window.
2756 Optional argument MINIBUF nil or omitted means consider the minibuffer
2757 window only if the minibuffer is active. MINIBUF t means consider the
2758 minibuffer window even if the minibuffer is not active. Any other value
2759 means do not consider the minibuffer window even if the minibuffer is
2760 active.
2762 Optional argument ALL-FRAMES nil or omitted means consider all windows
2763 on WINDOW's frame, plus the minibuffer window if specified by the
2764 MINIBUF argument. If the minibuffer counts, consider all windows on all
2765 frames that share that minibuffer too. The following non-nil values of
2766 ALL-FRAMES have special meanings:
2768 - t means consider all windows on all existing frames.
2770 - `visible' means consider all windows on all visible frames.
2772 - 0 (the number zero) means consider all windows on all visible and
2773 iconified frames.
2775 - A frame means consider all windows on that frame only.
2777 Anything else means consider all windows on WINDOW's frame and no
2778 others.
2780 If WINDOW is not on the list of windows returned, some other window will
2781 be listed first but no error is signaled. */)
2782 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2784 return window_list_1 (window, minibuf, all_frames);
2787 /* Look at all windows, performing an operation specified by TYPE
2788 with argument OBJ.
2789 If FRAMES is Qt, look at all frames;
2790 Qnil, look at just the selected frame;
2791 Qvisible, look at visible frames;
2792 a frame, just look at windows on that frame.
2793 If MINI, perform the operation on minibuffer windows too. */
2795 enum window_loop
2797 WINDOW_LOOP_UNUSED,
2798 GET_BUFFER_WINDOW, /* Arg is buffer */
2799 REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
2800 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2801 CHECK_ALL_WINDOWS /* Arg is ignored */
2804 static Lisp_Object
2805 window_loop (enum window_loop type, Lisp_Object obj, bool mini,
2806 Lisp_Object frames)
2808 Lisp_Object window, windows, best_window, frame_arg;
2809 bool frame_best_window_flag = false;
2810 struct frame *f;
2811 struct gcpro gcpro1;
2813 /* If we're only looping through windows on a particular frame,
2814 frame points to that frame. If we're looping through windows
2815 on all frames, frame is 0. */
2816 if (FRAMEP (frames))
2817 f = XFRAME (frames);
2818 else if (NILP (frames))
2819 f = SELECTED_FRAME ();
2820 else
2821 f = NULL;
2823 if (f)
2824 frame_arg = Qlambda;
2825 else if (EQ (frames, make_number (0)))
2826 frame_arg = frames;
2827 else if (EQ (frames, Qvisible))
2828 frame_arg = frames;
2829 else
2830 frame_arg = Qt;
2832 /* frame_arg is Qlambda to stick to one frame,
2833 Qvisible to consider all visible frames,
2834 or Qt otherwise. */
2836 /* Pick a window to start with. */
2837 if (WINDOWP (obj))
2838 window = obj;
2839 else if (f)
2840 window = FRAME_SELECTED_WINDOW (f);
2841 else
2842 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2844 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2845 GCPRO1 (windows);
2846 best_window = Qnil;
2848 for (; CONSP (windows); windows = XCDR (windows))
2850 struct window *w;
2852 window = XCAR (windows);
2853 w = XWINDOW (window);
2855 /* Note that we do not pay attention here to whether the frame
2856 is visible, since Fwindow_list skips non-visible frames if
2857 that is desired, under the control of frame_arg. */
2858 if (!MINI_WINDOW_P (w)
2859 /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
2860 consider all windows. */
2861 || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
2862 || (mini && minibuf_level > 0))
2863 switch (type)
2865 case GET_BUFFER_WINDOW:
2866 if (EQ (w->contents, obj)
2867 /* Don't find any minibuffer window except the one that
2868 is currently in use. */
2869 && (!MINI_WINDOW_P (w) || EQ (window, minibuf_window)))
2871 if (EQ (window, selected_window))
2872 /* Preferably return the selected window. */
2873 RETURN_UNGCPRO (window);
2874 else if (EQ (XWINDOW (window)->frame, selected_frame)
2875 && !frame_best_window_flag)
2876 /* Prefer windows on the current frame (but don't
2877 choose another one if we have one already). */
2879 best_window = window;
2880 frame_best_window_flag = true;
2882 else if (NILP (best_window))
2883 best_window = window;
2885 break;
2887 case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
2888 /* We could simply check whether the buffer shown by window
2889 is live, and show another buffer in case it isn't. */
2890 if (EQ (w->contents, obj))
2892 /* Undedicate WINDOW. */
2893 wset_dedicated (w, Qnil);
2894 /* Make WINDOW show the buffer returned by
2895 other_buffer_safely, don't run any hooks. */
2896 set_window_buffer
2897 (window, other_buffer_safely (w->contents), false, false);
2898 /* If WINDOW is the selected window, make its buffer
2899 current. But do so only if the window shows the
2900 current buffer (Bug#6454). */
2901 if (EQ (window, selected_window)
2902 && XBUFFER (w->contents) == current_buffer)
2903 Fset_buffer (w->contents);
2905 break;
2907 case REDISPLAY_BUFFER_WINDOWS:
2908 if (EQ (w->contents, obj))
2910 mark_window_display_accurate (window, false);
2911 w->update_mode_line = true;
2912 XBUFFER (obj)->prevent_redisplay_optimizations_p = true;
2913 update_mode_lines = 27;
2914 best_window = window;
2916 break;
2918 /* Check for a leaf window that has a killed buffer
2919 or broken markers. */
2920 case CHECK_ALL_WINDOWS:
2921 if (BUFFERP (w->contents))
2923 struct buffer *b = XBUFFER (w->contents);
2925 if (!BUFFER_LIVE_P (b))
2926 emacs_abort ();
2927 if (!MARKERP (w->start) || XMARKER (w->start)->buffer != b)
2928 emacs_abort ();
2929 if (!MARKERP (w->pointm) || XMARKER (w->pointm)->buffer != b)
2930 emacs_abort ();
2932 break;
2934 case WINDOW_LOOP_UNUSED:
2935 break;
2939 UNGCPRO;
2940 return best_window;
2943 /* Used for debugging. Abort if any window has a dead buffer. */
2945 extern void check_all_windows (void) EXTERNALLY_VISIBLE;
2946 void
2947 check_all_windows (void)
2949 window_loop (CHECK_ALL_WINDOWS, Qnil, true, Qt);
2952 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2953 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2954 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
2955 the current buffer.
2957 The optional argument ALL-FRAMES specifies the frames to consider:
2959 - t means consider all windows on all existing frames.
2961 - `visible' means consider all windows on all visible frames.
2963 - 0 (the number zero) means consider all windows on all visible
2964 and iconified frames.
2966 - A frame means consider all windows on that frame only.
2968 Any other value of ALL-FRAMES means consider all windows on the
2969 selected frame and no others. */)
2970 (Lisp_Object buffer_or_name, Lisp_Object all_frames)
2972 Lisp_Object buffer;
2974 if (NILP (buffer_or_name))
2975 buffer = Fcurrent_buffer ();
2976 else
2977 buffer = Fget_buffer (buffer_or_name);
2979 if (BUFFERP (buffer))
2980 return window_loop (GET_BUFFER_WINDOW, buffer, true, all_frames);
2981 else
2982 return Qnil;
2986 static Lisp_Object
2987 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore, Lisp_Object pixelwise)
2989 return call5 (Qwindow_resize_root_window, window, delta, horizontal, ignore, pixelwise);
2992 /* Placeholder used by temacs -nw before window.el is loaded. */
2993 DEFUN ("window--sanitize-window-sizes", Fwindow__sanitize_window_sizes,
2994 Swindow__sanitize_window_sizes, 2, 2, 0,
2995 doc: /* */
2996 attributes: const)
2997 (Lisp_Object frame, Lisp_Object horizontal)
2999 return Qnil;
3002 Lisp_Object
3003 sanitize_window_sizes (Lisp_Object frame, Lisp_Object horizontal)
3005 return call2 (Qwindow_sanitize_window_sizes, frame, horizontal);
3009 static Lisp_Object
3010 window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal)
3012 return call2 (Qwindow_pixel_to_total, frame, horizontal);
3016 DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
3017 Sdelete_other_windows_internal, 0, 2, "",
3018 doc: /* Make WINDOW fill its frame.
3019 Only the frame WINDOW is on is affected. WINDOW must be a valid window
3020 and defaults to the selected one.
3022 Optional argument ROOT, if non-nil, must specify an internal window such
3023 that WINDOW is in its window subtree. If this is the case, replace ROOT
3024 by WINDOW and leave alone any windows not part of ROOT's subtree.
3026 When WINDOW is live try to reduce display jumps by keeping the text
3027 previously visible in WINDOW in the same place on the frame. Doing this
3028 depends on the value of (window-start WINDOW), so if calling this
3029 function in a program gives strange scrolling, make sure the
3030 window-start value is reasonable when this function is called. */)
3031 (Lisp_Object window, Lisp_Object root)
3033 struct window *w, *r, *s;
3034 struct frame *f;
3035 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
3036 ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0);
3037 int top IF_LINT (= 0), new_top;
3039 w = decode_valid_window (window);
3040 XSETWINDOW (window, w);
3041 f = XFRAME (w->frame);
3043 if (NILP (root))
3044 /* ROOT is the frame's root window. */
3046 root = FRAME_ROOT_WINDOW (f);
3047 r = XWINDOW (root);
3049 else
3050 /* ROOT must be an ancestor of WINDOW. */
3052 r = decode_valid_window (root);
3053 pwindow = XWINDOW (window)->parent;
3054 while (!NILP (pwindow))
3055 if (EQ (pwindow, root))
3056 break;
3057 else
3058 pwindow = XWINDOW (pwindow)->parent;
3059 if (!EQ (pwindow, root))
3060 error ("Specified root is not an ancestor of specified window");
3063 if (EQ (window, root))
3064 /* A noop. */
3065 return Qnil;
3066 /* I don't understand the "top > 0" part below. If we deal with a
3067 standalone minibuffer it would have been caught by the preceding
3068 test. */
3069 else if (MINI_WINDOW_P (w)) /* && top > 0) */
3070 error ("Can't expand minibuffer to full frame");
3072 if (BUFFERP (w->contents))
3074 startpos = marker_position (w->start);
3075 startbyte = marker_byte_position (w->start);
3076 top = (WINDOW_TOP_EDGE_LINE (w)
3077 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))));
3078 /* Make sure WINDOW is the frame's selected window. */
3079 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
3081 if (EQ (selected_frame, w->frame))
3082 Fselect_window (window, Qnil);
3083 else
3084 fset_selected_window (f, window);
3087 else
3089 /* See if the frame's selected window is a part of the window
3090 subtree rooted at WINDOW, by finding all the selected window's
3091 parents and comparing each one with WINDOW. If it isn't we
3092 need a new selected window for this frame. */
3093 swindow = FRAME_SELECTED_WINDOW (f);
3094 while (true)
3096 pwindow = swindow;
3097 while (!NILP (pwindow) && !EQ (window, pwindow))
3098 pwindow = XWINDOW (pwindow)->parent;
3100 if (EQ (window, pwindow))
3101 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
3102 as the new selected window. */
3103 break;
3104 else
3105 /* Else try the previous window of SWINDOW. */
3106 swindow = Fprevious_window (swindow, Qlambda, Qnil);
3109 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
3111 if (EQ (selected_frame, w->frame))
3112 Fselect_window (swindow, Qnil);
3113 else
3114 fset_selected_window (f, swindow);
3118 block_input ();
3119 if (!FRAME_INITIAL_P (f))
3121 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
3123 /* We are going to free the glyph matrices of WINDOW, and with
3124 that we might lose any information about glyph rows that have
3125 some of their glyphs highlighted in mouse face. (These rows
3126 are marked with a mouse_face_p flag.) If WINDOW
3127 indeed has some glyphs highlighted in mouse face, signal to
3128 frame's up-to-date hook that mouse highlight was overwritten,
3129 so that it will arrange for redisplaying the highlight. */
3130 if (EQ (hlinfo->mouse_face_window, window))
3131 reset_mouse_highlight (hlinfo);
3133 free_window_matrices (r);
3135 fset_redisplay (f);
3136 Vwindow_list = Qnil;
3137 FRAME_WINDOW_SIZES_CHANGED (f) = true;
3138 bool resize_failed = false;
3140 if (!WINDOW_LEAF_P (w))
3142 /* Resize child windows vertically. */
3143 XSETINT (delta, r->pixel_height - w->pixel_height);
3144 w->pixel_top = r->pixel_top;
3145 w->top_line = r->top_line;
3146 resize_root_window (window, delta, Qnil, Qnil, Qt);
3147 if (window_resize_check (w, false))
3149 window_resize_apply (w, false);
3150 window_pixel_to_total (w->frame, Qnil);
3152 else
3154 resize_root_window (window, delta, Qnil, Qt, Qt);
3155 if (window_resize_check (w, false))
3157 window_resize_apply (w, false);
3158 window_pixel_to_total (w->frame, Qnil);
3160 else
3161 resize_failed = true;
3164 /* Resize child windows horizontally. */
3165 if (!resize_failed)
3167 w->left_col = r->left_col;
3168 w->pixel_left = r->pixel_left;
3169 XSETINT (delta, r->pixel_width - w->pixel_width);
3170 resize_root_window (window, delta, Qt, Qnil, Qt);
3171 if (window_resize_check (w, true))
3173 window_resize_apply (w, true);
3174 window_pixel_to_total (w->frame, Qt);
3176 else
3178 resize_root_window (window, delta, Qt, Qt, Qt);
3179 if (window_resize_check (w, true))
3181 window_resize_apply (w, true);
3182 window_pixel_to_total (w->frame, Qt);
3184 else
3185 resize_failed = true;
3189 if (resize_failed)
3190 /* Play safe, if we still can ... */
3192 window = swindow;
3193 w = XWINDOW (window);
3197 /* Cleanly unlink WINDOW from window-tree. */
3198 if (!NILP (w->prev))
3199 /* Get SIBLING above (on the left of) WINDOW. */
3201 sibling = w->prev;
3202 s = XWINDOW (sibling);
3203 wset_next (s, w->next);
3204 if (!NILP (s->next))
3205 wset_prev (XWINDOW (s->next), sibling);
3207 else
3208 /* Get SIBLING below (on the right of) WINDOW. */
3210 sibling = w->next;
3211 s = XWINDOW (sibling);
3212 wset_prev (s, Qnil);
3213 wset_combination (XWINDOW (w->parent),
3214 XWINDOW (w->parent)->horizontal, sibling);
3217 /* Delete ROOT and all child windows of ROOT. */
3218 if (WINDOWP (r->contents))
3220 delete_all_child_windows (r->contents);
3221 wset_combination (r, false, Qnil);
3224 replace_window (root, window, true);
3226 /* This must become SWINDOW anyway ....... */
3227 if (BUFFERP (w->contents) && !resize_failed)
3229 /* Try to minimize scrolling, by setting the window start to the
3230 point will cause the text at the old window start to be at the
3231 same place on the frame. But don't try to do this if the
3232 window start is outside the visible portion (as might happen
3233 when the display is not current, due to typeahead). */
3234 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
3235 if (new_top != top
3236 && startpos >= BUF_BEGV (XBUFFER (w->contents))
3237 && startpos <= BUF_ZV (XBUFFER (w->contents)))
3239 struct position pos;
3240 struct buffer *obuf = current_buffer;
3242 Fset_buffer (w->contents);
3243 /* This computation used to temporarily move point, but that
3244 can have unwanted side effects due to text properties. */
3245 pos = *vmotion (startpos, startbyte, -top, w);
3247 set_marker_both (w->start, w->contents, pos.bufpos, pos.bytepos);
3248 w->window_end_valid = false;
3249 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
3250 || FETCH_BYTE (pos.bytepos - 1) == '\n');
3251 /* We need to do this, so that the window-scroll-functions
3252 get called. */
3253 w->optional_new_start = true;
3255 set_buffer_internal (obuf);
3259 adjust_frame_glyphs (f);
3260 unblock_input ();
3262 run_window_configuration_change_hook (f);
3264 return Qnil;
3268 void
3269 replace_buffer_in_windows (Lisp_Object buffer)
3271 call1 (Qreplace_buffer_in_windows, buffer);
3274 /* If BUFFER is shown in a window, safely replace it with some other
3275 buffer in all windows of all frames, even those on other keyboards. */
3277 void
3278 replace_buffer_in_windows_safely (Lisp_Object buffer)
3280 if (buffer_window_count (XBUFFER (buffer)))
3282 Lisp_Object tail, frame;
3284 /* A single call to window_loop won't do the job because it only
3285 considers frames on the current keyboard. So loop manually over
3286 frames, and handle each one. */
3287 FOR_EACH_FRAME (tail, frame)
3288 window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, true, frame);
3292 /* The following three routines are needed for running a window's
3293 configuration change hook. */
3294 static void
3295 run_funs (Lisp_Object funs)
3297 for (; CONSP (funs); funs = XCDR (funs))
3298 if (!EQ (XCAR (funs), Qt))
3299 call0 (XCAR (funs));
3302 static void
3303 select_window_norecord (Lisp_Object window)
3305 if (WINDOW_LIVE_P (window))
3306 Fselect_window (window, Qt);
3309 static void
3310 select_frame_norecord (Lisp_Object frame)
3312 if (FRAME_LIVE_P (XFRAME (frame)))
3313 Fselect_frame (frame, Qt);
3316 void
3317 run_window_configuration_change_hook (struct frame *f)
3319 ptrdiff_t count = SPECPDL_INDEX ();
3320 Lisp_Object frame, global_wcch
3321 = Fdefault_value (Qwindow_configuration_change_hook);
3322 XSETFRAME (frame, f);
3324 if (NILP (Vrun_hooks)
3325 || !(f->can_x_set_window_size)
3326 || !(f->after_make_frame))
3327 return;
3329 /* Use the right buffer. Matters when running the local hooks. */
3330 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3332 record_unwind_current_buffer ();
3333 Fset_buffer (Fwindow_buffer (Qnil));
3336 if (SELECTED_FRAME () != f)
3338 record_unwind_protect (select_frame_norecord, selected_frame);
3339 select_frame_norecord (frame);
3342 /* Look for buffer-local values. */
3344 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3345 for (; CONSP (windows); windows = XCDR (windows))
3347 Lisp_Object window = XCAR (windows);
3348 Lisp_Object buffer = Fwindow_buffer (window);
3349 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3350 buffer)))
3352 ptrdiff_t inner_count = SPECPDL_INDEX ();
3353 record_unwind_protect (select_window_norecord, selected_window);
3354 select_window_norecord (window);
3355 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3356 buffer));
3357 unbind_to (inner_count, Qnil);
3362 run_funs (global_wcch);
3363 unbind_to (count, Qnil);
3366 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
3367 Srun_window_configuration_change_hook, 0, 1, 0,
3368 doc: /* Run `window-configuration-change-hook' for FRAME.
3369 If FRAME is omitted or nil, it defaults to the selected frame. */)
3370 (Lisp_Object frame)
3372 run_window_configuration_change_hook (decode_live_frame (frame));
3373 return Qnil;
3376 DEFUN ("run-window-scroll-functions", Frun_window_scroll_functions,
3377 Srun_window_scroll_functions, 0, 1, 0,
3378 doc: /* Run `window-scroll-functions' for WINDOW.
3379 If WINDOW is omitted or nil, it defaults to the selected window. */)
3380 (Lisp_Object window)
3382 if (! NILP (Vwindow_scroll_functions))
3383 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3384 Fmarker_position (decode_live_window (window)->start));
3385 return Qnil;
3388 /* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed
3389 to run hooks. See make_frame for a case where it's not allowed.
3390 KEEP_MARGINS_P means that the current margins, fringes, and
3391 scroll-bar settings of the window are not reset from the buffer's
3392 local settings. */
3394 void
3395 set_window_buffer (Lisp_Object window, Lisp_Object buffer,
3396 bool run_hooks_p, bool keep_margins_p)
3398 struct window *w = XWINDOW (window);
3399 struct buffer *b = XBUFFER (buffer);
3400 ptrdiff_t count = SPECPDL_INDEX ();
3401 bool samebuf = EQ (buffer, w->contents);
3403 wset_buffer (w, buffer);
3405 if (EQ (window, selected_window))
3406 bset_last_selected_window (b, window);
3408 /* Let redisplay errors through. */
3409 b->display_error_modiff = 0;
3411 /* Update time stamps of buffer display. */
3412 if (INTEGERP (BVAR (b, display_count)))
3413 bset_display_count (b, make_number (XINT (BVAR (b, display_count)) + 1));
3414 bset_display_time (b, Fcurrent_time ());
3416 w->window_end_pos = 0;
3417 w->window_end_vpos = 0;
3418 w->last_cursor_vpos = 0;
3420 if (!(keep_margins_p && samebuf))
3421 { /* If we're not actually changing the buffer, don't reset hscroll
3422 and vscroll. This case happens for example when called from
3423 change_frame_size_1, where we use a dummy call to
3424 Fset_window_buffer on the frame's selected window (and no
3425 other) just in order to run window-configuration-change-hook
3426 (no longer true since change_frame_size_1 directly calls
3427 run_window_configuration_change_hook). Resetting hscroll and
3428 vscroll here is problematic for things like image-mode and
3429 doc-view-mode since it resets the image's position whenever we
3430 resize the frame. */
3431 w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
3432 w->suspend_auto_hscroll = false;
3433 w->vscroll = 0;
3434 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3435 set_marker_both (w->old_pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3436 set_marker_restricted (w->start,
3437 make_number (b->last_window_start),
3438 buffer);
3439 w->start_at_line_beg = false;
3440 w->force_start = false;
3442 /* Maybe we could move this into the `if' but it's not obviously safe and
3443 I doubt it's worth the trouble. */
3444 wset_redisplay (w);
3445 w->update_mode_line = true;
3447 /* We must select BUFFER to run the window-scroll-functions and to look up
3448 the buffer-local value of Vwindow_point_insertion_type. */
3449 record_unwind_current_buffer ();
3450 Fset_buffer (buffer);
3452 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3453 XMARKER (w->old_pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3455 if (!keep_margins_p)
3457 /* Set left and right marginal area width etc. from buffer. */
3458 set_window_fringes (w, BVAR (b, left_fringe_width),
3459 BVAR (b, right_fringe_width),
3460 BVAR (b, fringes_outside_margins));
3461 set_window_scroll_bars (w, BVAR (b, scroll_bar_width),
3462 BVAR (b, vertical_scroll_bar_type),
3463 BVAR (b, scroll_bar_height),
3464 BVAR (b, horizontal_scroll_bar_type));
3465 set_window_margins (w, BVAR (b, left_margin_cols),
3466 BVAR (b, right_margin_cols));
3467 apply_window_adjustment (w);
3470 if (run_hooks_p)
3472 if (! NILP (Vwindow_scroll_functions))
3473 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3474 Fmarker_position (w->start));
3475 if (!samebuf)
3476 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3479 unbind_to (count, Qnil);
3482 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3483 doc: /* Make WINDOW display BUFFER-OR-NAME.
3484 WINDOW must be a live window and defaults to the selected one.
3485 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
3487 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
3488 display margins, fringe widths, and scroll bar settings are preserved;
3489 the default is to reset these from the local settings for BUFFER-OR-NAME
3490 or the frame defaults. Return nil.
3492 This function throws an error when WINDOW is strongly dedicated to its
3493 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3494 already display BUFFER-OR-NAME.
3496 This function runs `window-scroll-functions' before running
3497 `window-configuration-change-hook'. */)
3498 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3500 register Lisp_Object tem, buffer;
3501 register struct window *w = decode_live_window (window);
3503 XSETWINDOW (window, w);
3504 buffer = Fget_buffer (buffer_or_name);
3505 CHECK_BUFFER (buffer);
3506 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3507 error ("Attempt to display deleted buffer");
3509 tem = w->contents;
3510 if (NILP (tem))
3511 error ("Window is deleted");
3512 else
3514 if (!EQ (tem, buffer))
3516 if (EQ (w->dedicated, Qt))
3517 /* WINDOW is strongly dedicated to its buffer, signal an
3518 error. */
3519 error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
3520 else
3521 /* WINDOW is weakly dedicated to its buffer, reset
3522 dedication. */
3523 wset_dedicated (w, Qnil);
3525 call1 (Qrecord_window_buffer, window);
3528 unshow_buffer (w);
3531 set_window_buffer (window, buffer, true, !NILP (keep_margins));
3533 return Qnil;
3536 static Lisp_Object
3537 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3539 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3542 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3543 0, 1, 0,
3544 doc: /* Force all windows to be updated on next redisplay.
3545 If optional arg OBJECT is a window, force redisplay of that window only.
3546 If OBJECT is a buffer or buffer name, force redisplay of all windows
3547 displaying that buffer. */)
3548 (Lisp_Object object)
3550 if (NILP (object))
3552 windows_or_buffers_changed = 29;
3553 update_mode_lines = 28;
3554 return Qt;
3557 if (WINDOWP (object))
3559 struct window *w = XWINDOW (object);
3560 mark_window_display_accurate (object, false);
3561 w->update_mode_line = true;
3562 if (BUFFERP (w->contents))
3563 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
3564 update_mode_lines = 29;
3565 return Qt;
3568 if (STRINGP (object))
3569 object = Fget_buffer (object);
3570 if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))
3571 && buffer_window_count (XBUFFER (object)))
3573 /* If buffer is live and shown in at least one window, find
3574 all windows showing this buffer and force update of them. */
3575 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, false, Qvisible);
3576 return NILP (object) ? Qnil : Qt;
3579 /* If nothing suitable was found, just return.
3580 We could signal an error, but this feature will typically be used
3581 asynchronously in timers or process sentinels, so we don't. */
3582 return Qnil;
3585 /* Obsolete since 24.3. */
3586 void
3587 temp_output_buffer_show (register Lisp_Object buf)
3589 register struct buffer *old = current_buffer;
3590 register Lisp_Object window;
3591 register struct window *w;
3593 bset_directory (XBUFFER (buf), BVAR (current_buffer, directory));
3595 Fset_buffer (buf);
3596 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3597 BEGV = BEG;
3598 ZV = Z;
3599 SET_PT (BEG);
3600 set_buffer_internal (old);
3602 if (!NILP (Vtemp_buffer_show_function))
3603 call1 (Vtemp_buffer_show_function, buf);
3604 else if (WINDOW_LIVE_P (window = display_buffer (buf, Qnil, Qnil)))
3606 if (!EQ (XWINDOW (window)->frame, selected_frame))
3607 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3608 Vminibuf_scroll_window = window;
3609 w = XWINDOW (window);
3610 w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
3611 w->suspend_auto_hscroll = false;
3612 set_marker_restricted_both (w->start, buf, BEG, BEG);
3613 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3614 set_marker_restricted_both (w->old_pointm, buf, BEG, BEG);
3616 /* Run temp-buffer-show-hook, with the chosen window selected
3617 and its buffer current. */
3619 ptrdiff_t count = SPECPDL_INDEX ();
3620 Lisp_Object prev_window, prev_buffer;
3621 prev_window = selected_window;
3622 XSETBUFFER (prev_buffer, old);
3624 /* Select the window that was chosen, for running the hook.
3625 Note: Both Fselect_window and select_window_norecord may
3626 set-buffer to the buffer displayed in the window,
3627 so we need to save the current buffer. --stef */
3628 record_unwind_protect (restore_buffer, prev_buffer);
3629 record_unwind_protect (select_window_norecord, prev_window);
3630 Fselect_window (window, Qt);
3631 Fset_buffer (w->contents);
3632 run_hook (Qtemp_buffer_show_hook);
3633 unbind_to (count, Qnil);
3638 /* Allocate basically initialized window. */
3640 static struct window *
3641 allocate_window (void)
3643 return ALLOCATE_ZEROED_PSEUDOVECTOR
3644 (struct window, current_matrix, PVEC_WINDOW);
3647 /* Make new window, have it replace WINDOW in window-tree, and make
3648 WINDOW its only vertical child (HORFLAG means make WINDOW its only
3649 horizontal child). */
3650 static void
3651 make_parent_window (Lisp_Object window, bool horflag)
3653 Lisp_Object parent;
3654 register struct window *o, *p;
3656 o = XWINDOW (window);
3657 p = allocate_window ();
3658 memcpy ((char *) p + sizeof (struct vectorlike_header),
3659 (char *) o + sizeof (struct vectorlike_header),
3660 word_size * VECSIZE (struct window));
3661 /* P's buffer slot may change from nil to a buffer... */
3662 adjust_window_count (p, 1);
3663 XSETWINDOW (parent, p);
3665 p->sequence_number = ++sequence_number;
3667 replace_window (window, parent, true);
3669 wset_next (o, Qnil);
3670 wset_prev (o, Qnil);
3671 wset_parent (o, parent);
3672 /* ...but now P becomes an internal window. */
3673 wset_start (p, Qnil);
3674 wset_pointm (p, Qnil);
3675 wset_old_pointm (p, Qnil);
3676 wset_buffer (p, Qnil);
3677 wset_combination (p, horflag, window);
3678 wset_combination_limit (p, Qnil);
3679 wset_window_parameters (p, Qnil);
3682 /* Make new window from scratch. */
3683 Lisp_Object
3684 make_window (void)
3686 Lisp_Object window;
3687 register struct window *w;
3689 w = allocate_window ();
3690 /* Initialize Lisp data. Note that allocate_window initializes all
3691 Lisp data to nil, so do it only for slots which should not be nil. */
3692 wset_normal_lines (w, make_float (1.0));
3693 wset_normal_cols (w, make_float (1.0));
3694 wset_new_total (w, make_number (0));
3695 wset_new_normal (w, make_number (0));
3696 wset_new_pixel (w, make_number (0));
3697 wset_start (w, Fmake_marker ());
3698 wset_pointm (w, Fmake_marker ());
3699 wset_old_pointm (w, Fmake_marker ());
3700 wset_vertical_scroll_bar_type (w, Qt);
3701 wset_horizontal_scroll_bar_type (w, Qt);
3702 /* These Lisp fields are marked specially so they're not set to nil by
3703 allocate_window. */
3704 wset_prev_buffers (w, Qnil);
3705 wset_next_buffers (w, Qnil);
3707 /* Initialize non-Lisp data. Note that allocate_window zeroes out all
3708 non-Lisp data, so do it only for slots which should not be zero. */
3709 w->nrows_scale_factor = w->ncols_scale_factor = 1;
3710 w->left_fringe_width = w->right_fringe_width = -1;
3711 w->mode_line_height = w->header_line_height = -1;
3712 #ifdef HAVE_WINDOW_SYSTEM
3713 w->phys_cursor_type = NO_CURSOR;
3714 w->phys_cursor_width = -1;
3715 #endif
3716 w->sequence_number = ++sequence_number;
3717 w->scroll_bar_width = -1;
3718 w->scroll_bar_height = -1;
3719 w->column_number_displayed = -1;
3720 /* Reset window_list. */
3721 Vwindow_list = Qnil;
3722 /* Return window. */
3723 XSETWINDOW (window, w);
3724 return window;
3727 DEFUN ("set-window-new-pixel", Fset_window_new_pixel, Sset_window_new_pixel, 2, 3, 0,
3728 doc: /* Set new pixel size of WINDOW to SIZE.
3729 WINDOW must be a valid window and defaults to the selected one.
3730 Return SIZE.
3732 Optional argument ADD non-nil means add SIZE to the new pixel size of
3733 WINDOW and return the sum.
3735 The new pixel size of WINDOW, if valid, will be shortly installed as
3736 WINDOW's pixel height (see `window-pixel-height') or pixel width (see
3737 `window-pixel-width').
3739 Note: This function does not operate on any child windows of WINDOW. */)
3740 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3742 struct window *w = decode_valid_window (window);
3743 EMACS_INT size_min = NILP (add) ? 0 : - XINT (w->new_pixel);
3744 EMACS_INT size_max = size_min + min (INT_MAX, MOST_POSITIVE_FIXNUM);
3746 CHECK_RANGED_INTEGER (size, size_min, size_max);
3747 if (NILP (add))
3748 wset_new_pixel (w, size);
3749 else
3750 wset_new_pixel (w, make_number (XINT (w->new_pixel) + XINT (size)));
3752 return w->new_pixel;
3755 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
3756 doc: /* Set new total size of WINDOW to SIZE.
3757 WINDOW must be a valid window and defaults to the selected one.
3758 Return SIZE.
3760 Optional argument ADD non-nil means add SIZE to the new total size of
3761 WINDOW and return the sum.
3763 The new total size of WINDOW, if valid, will be shortly installed as
3764 WINDOW's total height (see `window-total-height') or total width (see
3765 `window-total-width').
3767 Note: This function does not operate on any child windows of WINDOW. */)
3768 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3770 struct window *w = decode_valid_window (window);
3772 CHECK_NUMBER (size);
3773 if (NILP (add))
3774 wset_new_total (w, size);
3775 else
3776 wset_new_total (w, make_number (XINT (w->new_total) + XINT (size)));
3778 return w->new_total;
3781 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
3782 doc: /* Set new normal size of WINDOW to SIZE.
3783 WINDOW must be a valid window and defaults to the selected one.
3784 Return SIZE.
3786 The new normal size of WINDOW, if valid, will be shortly installed as
3787 WINDOW's normal size (see `window-normal-size').
3789 Note: This function does not operate on any child windows of WINDOW. */)
3790 (Lisp_Object window, Lisp_Object size)
3792 wset_new_normal (decode_valid_window (window), size);
3793 return size;
3796 /* Return true if setting w->pixel_height (w->pixel_width if HORFLAG)
3797 to w->new_pixel would result in correct heights (widths)
3798 for window W and recursively all child windows of W.
3800 Note: This function does not check any of `window-fixed-size-p',
3801 `window-min-height' or `window-min-width'. It does check that window
3802 sizes do not drop below one line (two columns). */
3803 static bool
3804 window_resize_check (struct window *w, bool horflag)
3806 struct frame *f = XFRAME (w->frame);
3807 struct window *c;
3809 if (WINDOW_VERTICAL_COMBINATION_P (w))
3810 /* W is a vertical combination. */
3812 c = XWINDOW (w->contents);
3813 if (horflag)
3814 /* All child windows of W must have the same width as W. */
3816 while (c)
3818 if (XINT (c->new_pixel) != XINT (w->new_pixel)
3819 || !window_resize_check (c, horflag))
3820 return false;
3822 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3825 return true;
3827 else
3828 /* The sum of the heights of the child windows of W must equal
3829 W's height. */
3831 int remaining_pixels = XINT (w->new_pixel);
3833 while (c)
3835 if (!window_resize_check (c, horflag))
3836 return false;
3838 remaining_pixels -= XINT (c->new_pixel);
3839 if (remaining_pixels < 0)
3840 return false;
3841 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3844 return remaining_pixels == 0;
3847 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3848 /* W is a horizontal combination. */
3850 c = XWINDOW (w->contents);
3851 if (horflag)
3852 /* The sum of the widths of the child windows of W must equal W's
3853 width. */
3855 int remaining_pixels = XINT (w->new_pixel);
3857 while (c)
3859 if (!window_resize_check (c, horflag))
3860 return false;
3862 remaining_pixels -= XINT (c->new_pixel);
3863 if (remaining_pixels < 0)
3864 return false;
3865 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3868 return remaining_pixels == 0;
3870 else
3871 /* All child windows of W must have the same height as W. */
3873 while (c)
3875 if (XINT (c->new_pixel) != XINT (w->new_pixel)
3876 || !window_resize_check (c, horflag))
3877 return false;
3879 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3882 return true;
3885 else
3886 /* A leaf window. Make sure it's not too small. The following
3887 hardcodes the values of `window-safe-min-width' (2) and
3888 `window-safe-min-height' (1) which are defined in window.el. */
3889 return (XINT (w->new_pixel) >= (horflag
3890 ? (2 * FRAME_COLUMN_WIDTH (f))
3891 : FRAME_LINE_HEIGHT (f)));
3895 /* Set w->pixel_height (w->pixel_width if HORFLAG) to
3896 w->new_pixel for window W and recursively all child windows of W.
3897 Also calculate and assign the new vertical (horizontal) pixel start
3898 positions of each of these windows.
3900 This function does not perform any error checks. Make sure you have
3901 run window_resize_check on W before applying this function. */
3902 static void
3903 window_resize_apply (struct window *w, bool horflag)
3905 struct window *c;
3906 int edge;
3907 int unit = (horflag
3908 ? FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w))
3909 : FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
3911 /* Note: Assigning new_normal requires that the new total size of the
3912 parent window has been set *before*. */
3913 if (horflag)
3915 w->pixel_width = XFASTINT (w->new_pixel);
3916 w->total_cols = w->pixel_width / unit;
3917 if (NUMBERP (w->new_normal))
3918 wset_normal_cols (w, w->new_normal);
3920 edge = w->pixel_left;
3922 else
3924 w->pixel_height = XFASTINT (w->new_pixel);
3925 w->total_lines = w->pixel_height / unit;
3926 if (NUMBERP (w->new_normal))
3927 wset_normal_lines (w, w->new_normal);
3929 edge = w->pixel_top;
3932 if (WINDOW_VERTICAL_COMBINATION_P (w))
3933 /* W is a vertical combination. */
3935 c = XWINDOW (w->contents);
3936 while (c)
3938 if (horflag)
3940 c->pixel_left = edge;
3941 c->left_col = edge / unit;
3943 else
3945 c->pixel_top = edge;
3946 c->top_line = edge / unit;
3948 window_resize_apply (c, horflag);
3949 if (!horflag)
3950 edge = edge + c->pixel_height;
3952 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3955 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3956 /* W is a horizontal combination. */
3958 c = XWINDOW (w->contents);
3959 while (c)
3961 if (horflag)
3963 c->pixel_left = edge;
3964 c->left_col = edge / unit;
3966 else
3968 c->pixel_top = edge;
3969 c->top_line = edge / unit;
3972 window_resize_apply (c, horflag);
3973 if (horflag)
3974 edge = edge + c->pixel_width;
3976 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3979 else
3980 /* Bug#15957. */
3981 w->window_end_valid = false;
3985 /* Set w->total_lines (w->total_cols if HORFLAG) to
3986 w->new_total for window W and recursively all child windows of W.
3987 Also calculate and assign the new vertical (horizontal) start
3988 positions of each of these windows. */
3989 static void
3990 window_resize_apply_total (struct window *w, bool horflag)
3992 struct window *c;
3993 int edge;
3995 /* Note: Assigning new_normal requires that the new total size of the
3996 parent window has been set *before*. */
3997 if (horflag)
3999 w->total_cols = XFASTINT (w->new_total);
4000 edge = w->left_col;
4002 else
4004 w->total_lines = XFASTINT (w->new_total);
4005 edge = w->top_line;
4008 if (WINDOW_VERTICAL_COMBINATION_P (w))
4009 /* W is a vertical combination. */
4011 c = XWINDOW (w->contents);
4012 while (c)
4014 if (horflag)
4015 c->left_col = edge;
4016 else
4017 c->top_line = edge;
4019 window_resize_apply_total (c, horflag);
4020 if (!horflag)
4021 edge = edge + c->total_lines;
4023 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4026 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
4027 /* W is a horizontal combination. */
4029 c = XWINDOW (w->contents);
4030 while (c)
4032 if (horflag)
4033 c->left_col = edge;
4034 else
4035 c->top_line = edge;
4037 window_resize_apply_total (c, horflag);
4038 if (horflag)
4039 edge = edge + c->total_cols;
4041 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4046 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 0, 2, 0,
4047 doc: /* Apply requested size values for window-tree of FRAME.
4048 If FRAME is omitted or nil, it defaults to the selected frame.
4050 Optional argument HORIZONTAL omitted or nil means apply requested
4051 height values. HORIZONTAL non-nil means apply requested width values.
4053 The requested size values are those set by `set-window-new-pixel' and
4054 `set-window-new-normal'. This function checks whether the requested
4055 values sum up to a valid window layout, recursively assigns the new
4056 sizes of all child windows and calculates and assigns the new start
4057 positions of these windows.
4059 Return t if the requested values have been applied correctly, nil
4060 otherwise.
4062 Note: This function does not check any of `window-fixed-size-p',
4063 `window-min-height' or `window-min-width'. All these checks have to
4064 be applied on the Elisp level. */)
4065 (Lisp_Object frame, Lisp_Object horizontal)
4067 struct frame *f = decode_live_frame (frame);
4068 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
4069 bool horflag = !NILP (horizontal);
4071 if (!window_resize_check (r, horflag)
4072 || (XINT (r->new_pixel)
4073 != (horflag ? r->pixel_width : r->pixel_height)))
4074 return Qnil;
4076 block_input ();
4077 window_resize_apply (r, horflag);
4079 fset_redisplay (f);
4080 FRAME_WINDOW_SIZES_CHANGED (f) = true;
4082 adjust_frame_glyphs (f);
4083 unblock_input ();
4085 return Qt;
4089 DEFUN ("window-resize-apply-total", Fwindow_resize_apply_total, Swindow_resize_apply_total, 0, 2, 0,
4090 doc: /* Apply requested total size values for window-tree of FRAME.
4091 If FRAME is omitted or nil, it defaults to the selected frame.
4093 This function does not assign pixel or normal size values. You should
4094 have run `window-resize-apply' before running this.
4096 Optional argument HORIZONTAL omitted or nil means apply requested
4097 height values. HORIZONTAL non-nil means apply requested width
4098 values. */)
4099 (Lisp_Object frame, Lisp_Object horizontal)
4101 struct frame *f = decode_live_frame (frame);
4102 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
4104 block_input ();
4105 /* Necessary when deleting the top-/or leftmost window. */
4106 r->left_col = 0;
4107 r->top_line = FRAME_TOP_MARGIN (f);
4108 window_resize_apply_total (r, !NILP (horizontal));
4109 /* Handle the mini window. */
4110 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
4112 struct window *m = XWINDOW (f->minibuffer_window);
4114 if (NILP (horizontal))
4116 m->top_line = r->top_line + r->total_lines;
4117 m->total_lines = XFASTINT (m->new_total);
4119 else
4120 m->total_cols = XFASTINT (m->new_total);
4123 unblock_input ();
4125 return Qt;
4129 /* Resize frame F's windows when number of lines of F is set to SIZE.
4130 HORFLAG means resize windows when number of columns of F is set to
4131 SIZE. PIXELWISE means to interpret SIZE as pixels. */
4132 void
4133 resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
4135 Lisp_Object root = f->root_window;
4136 struct window *r = XWINDOW (root);
4137 Lisp_Object mini = f->minibuffer_window;
4138 struct window *m;
4139 /* old_size is the old size of the frame's root window. */
4140 int old_size = horflag ? r->total_cols : r->total_lines;
4141 int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
4142 int old_pixel_top = r->pixel_top;
4143 /* new_size is the new size of the frame's root window. */
4144 int new_size, new_pixel_size;
4145 int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
4147 /* Don't let the size drop below one unit. This is more comforting
4148 when we are called from x_set_tool_bar_lines since the latter may
4149 have implicitly given us a zero or negative height. */
4150 if (pixelwise)
4152 /* Note: This does not include the size for internal borders
4153 since these are not part of the frame's text area. */
4154 new_pixel_size = max (horflag
4155 ? size
4156 : (size
4157 - ((FRAME_HAS_MINIBUF_P (f)
4158 && !FRAME_MINIBUF_ONLY_P (f))
4159 ? FRAME_LINE_HEIGHT (f) : 0)),
4160 unit);
4161 new_size = new_pixel_size / unit;
4163 else
4165 new_size = max (size - (!horflag
4166 && FRAME_HAS_MINIBUF_P (f)
4167 && !FRAME_MINIBUF_ONLY_P (f)),
4169 new_pixel_size = new_size * unit;
4172 r->top_line = FRAME_TOP_MARGIN (f);
4173 r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
4175 if (new_pixel_size == old_pixel_size
4176 && r->pixel_top == old_pixel_top)
4178 else if (WINDOW_LEAF_P (r))
4179 /* For a leaf root window just set the size. */
4180 if (horflag)
4182 r->total_cols = new_size;
4183 r->pixel_width = new_pixel_size;
4185 else
4187 r->total_lines = new_size;
4188 r->pixel_height = new_pixel_size;
4190 else
4192 Lisp_Object delta;
4194 if (pixelwise)
4195 XSETINT (delta, new_pixel_size - old_pixel_size);
4196 else
4197 XSETINT (delta, new_size - old_size);
4199 /* Try a "normal" resize first. */
4200 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil,
4201 pixelwise ? Qt : Qnil);
4202 if (window_resize_check (r, horflag)
4203 && new_pixel_size == XINT (r->new_pixel))
4205 window_resize_apply (r, horflag);
4206 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4208 else
4210 /* Try with "reasonable" minimum sizes next. */
4211 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt,
4212 pixelwise ? Qt : Qnil);
4213 if (window_resize_check (r, horflag)
4214 && new_pixel_size == XINT (r->new_pixel))
4216 window_resize_apply (r, horflag);
4217 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4218 #if false /* Let's try without safe sizes and/or killing other windows. */
4220 else
4222 /* Finally, try with "safe" minimum sizes. */
4223 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe,
4224 pixelwise ? Qt : Qnil);
4225 if (window_resize_check (r, horflag)
4226 && new_pixel_size == XINT (r->new_pixel))
4228 window_resize_apply (r, horflag);
4229 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4231 else
4233 /* We lost. Delete all windows but the frame's
4234 selected one. */
4235 root = f->selected_window;
4236 Fdelete_other_windows_internal (root, Qnil);
4237 if (horflag)
4239 XWINDOW (root)->total_cols = new_size;
4240 XWINDOW (root)->pixel_width = new_pixel_size;
4242 else
4244 XWINDOW (root)->total_lines = new_size;
4245 XWINDOW (root)->pixel_height = new_pixel_size;
4248 #endif /* false */
4253 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
4255 m = XWINDOW (mini);
4256 if (horflag)
4258 m->total_cols = size;
4259 m->pixel_width = new_pixel_size;
4261 else
4263 /* Are we sure we always want 1 line here? */
4264 m->total_lines = 1;
4265 m->pixel_height = FRAME_LINE_HEIGHT (f);
4266 m->top_line = r->top_line + r->total_lines;
4267 m->pixel_top = r->pixel_top + r->pixel_height;
4271 fset_redisplay (f);
4275 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
4276 doc: /* Split window OLD.
4277 Second argument PIXEL-SIZE specifies the number of pixels of the
4278 new window. In any case TOTAL-SIZE must be a positive integer.
4280 Third argument SIDE nil (or `below') specifies that the new window shall
4281 be located below WINDOW. SIDE `above' means the new window shall be
4282 located above WINDOW. In both cases PIXEL-SIZE specifies the pixel
4283 height of the new window including space reserved for the mode and/or
4284 header line.
4286 SIDE t (or `right') specifies that the new window shall be located on
4287 the right side of WINDOW. SIDE `left' means the new window shall be
4288 located on the left of WINDOW. In both cases PIXEL-SIZE specifies the
4289 width of the new window including space reserved for fringes and the
4290 scrollbar or a divider column.
4292 Fourth argument NORMAL-SIZE specifies the normal size of the new window
4293 according to the SIDE argument.
4295 The new pixel and normal sizes of all involved windows must have been
4296 set correctly. See the code of `split-window' for how this is done. */)
4297 (Lisp_Object old, Lisp_Object pixel_size, Lisp_Object side, Lisp_Object normal_size)
4299 /* OLD (*o) is the window we have to split. (*p) is either OLD's
4300 parent window or an internal window we have to install as OLD's new
4301 parent. REFERENCE (*r) must denote a live window, or is set to OLD
4302 provided OLD is a leaf window, or to the frame's selected window.
4303 NEW (*n) is the new window created with some parameters taken from
4304 REFERENCE (*r). */
4305 Lisp_Object new, frame, reference;
4306 struct window *o, *p, *n, *r, *c;
4307 struct frame *f;
4308 bool horflag
4309 /* HORFLAG is true when we split side-by-side, false otherwise. */
4310 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
4312 CHECK_WINDOW (old);
4313 o = XWINDOW (old);
4314 frame = WINDOW_FRAME (o);
4315 f = XFRAME (frame);
4317 CHECK_NUMBER (pixel_size);
4318 int total_size
4319 = XINT (pixel_size) / (horflag
4320 ? FRAME_COLUMN_WIDTH (f)
4321 : FRAME_LINE_HEIGHT (f));
4323 /* Set combination_limit if we have to make a new parent window.
4324 We do that if either `window-combination-limit' is t, or OLD has no
4325 parent, or OLD is ortho-combined. */
4326 bool combination_limit
4327 = (EQ (Vwindow_combination_limit, Qt)
4328 || NILP (o->parent)
4329 || (horflag
4330 ? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
4331 : WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent))));
4333 /* We need a live reference window to initialize some parameters. */
4334 if (WINDOW_LIVE_P (old))
4335 /* OLD is live, use it as reference window. */
4336 reference = old;
4337 else
4338 /* Use the frame's selected window as reference window. */
4339 reference = FRAME_SELECTED_WINDOW (f);
4340 r = XWINDOW (reference);
4342 /* The following bugs are caught by `split-window'. */
4343 if (MINI_WINDOW_P (o))
4344 error ("Attempt to split minibuffer window");
4345 else if (total_size < (horflag ? 2 : 1))
4346 error ("Size of new window too small (after split)");
4347 else if (!combination_limit && !NILP (Vwindow_combination_resize))
4348 /* `window-combination-resize' non-nil means try to resize OLD's siblings
4349 proportionally. */
4351 p = XWINDOW (o->parent);
4352 /* Temporarily pretend we split the parent window. */
4353 wset_new_pixel
4354 (p, make_number ((horflag ? p->pixel_width : p->pixel_height)
4355 - XINT (pixel_size)));
4356 if (!window_resize_check (p, horflag))
4357 error ("Window sizes don't fit");
4358 else
4359 /* Undo the temporary pretension. */
4360 wset_new_pixel (p, make_number (horflag ? p->pixel_width : p->pixel_height));
4362 else
4364 if (!window_resize_check (o, horflag))
4365 error ("Resizing old window failed");
4366 else if (XINT (pixel_size) + XINT (o->new_pixel)
4367 != (horflag ? o->pixel_width : o->pixel_height))
4368 error ("Sum of sizes of old and new window don't fit");
4371 /* This is our point of no return. */
4372 if (combination_limit)
4374 /* Save the old value of o->normal_cols/lines. It gets corrupted
4375 by make_parent_window and we need it below for assigning it to
4376 p->new_normal. */
4377 Lisp_Object new_normal
4378 = horflag ? o->normal_cols : o->normal_lines;
4380 make_parent_window (old, horflag);
4381 p = XWINDOW (o->parent);
4382 if (EQ (Vwindow_combination_limit, Qt))
4383 /* Store t in the new parent's combination_limit slot to avoid
4384 that its children get merged into another window. */
4385 wset_combination_limit (p, Qt);
4386 /* These get applied below. */
4387 wset_new_pixel
4388 (p, make_number (horflag ? o->pixel_width : o->pixel_height));
4389 wset_new_total
4390 (p, make_number (horflag ? o->total_cols : o->total_lines));
4391 wset_new_normal (p, new_normal);
4393 else
4394 p = XWINDOW (o->parent);
4396 fset_redisplay (f);
4397 FRAME_WINDOW_SIZES_CHANGED (f) = true;
4398 new = make_window ();
4399 n = XWINDOW (new);
4400 wset_frame (n, frame);
4401 wset_parent (n, o->parent);
4403 if (EQ (side, Qabove) || EQ (side, Qleft))
4405 wset_prev (n, o->prev);
4406 if (NILP (n->prev))
4407 wset_combination (p, horflag, new);
4408 else
4409 wset_next (XWINDOW (n->prev), new);
4410 wset_next (n, old);
4411 wset_prev (o, new);
4413 else
4415 wset_next (n, o->next);
4416 if (!NILP (n->next))
4417 wset_prev (XWINDOW (n->next), new);
4418 wset_prev (n, old);
4419 wset_next (o, new);
4422 n->window_end_valid = false;
4423 n->last_cursor_vpos = 0;
4425 /* Get special geometry settings from reference window. */
4426 n->left_margin_cols = r->left_margin_cols;
4427 n->right_margin_cols = r->right_margin_cols;
4428 n->left_fringe_width = r->left_fringe_width;
4429 n->right_fringe_width = r->right_fringe_width;
4430 n->fringes_outside_margins = r->fringes_outside_margins;
4431 n->scroll_bar_width = r->scroll_bar_width;
4432 n->scroll_bar_height = r->scroll_bar_height;
4433 wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
4434 wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type);
4436 /* Directly assign orthogonal coordinates and sizes. */
4437 if (horflag)
4439 n->pixel_top = o->pixel_top;
4440 n->top_line = o->top_line;
4441 n->pixel_height = o->pixel_height;
4442 n->total_lines = o->total_lines;
4444 else
4446 n->pixel_left = o->pixel_left;
4447 n->left_col = o->left_col;
4448 n->pixel_width = o->pixel_width;
4449 n->total_cols = o->total_cols;
4452 /* Iso-coordinates and sizes are assigned by window_resize_apply,
4453 get them ready here. */
4454 wset_new_pixel (n, pixel_size);
4455 int sum = 0;
4456 c = XWINDOW (p->contents);
4457 while (c)
4459 if (c != n)
4460 sum = sum + XINT (c->new_total);
4461 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4463 wset_new_total (n, make_number ((horflag
4464 ? p->total_cols
4465 : p->total_lines)
4466 - sum));
4467 wset_new_normal (n, normal_size);
4469 block_input ();
4470 window_resize_apply (p, horflag);
4471 adjust_frame_glyphs (f);
4472 /* Set buffer of NEW to buffer of reference window. Don't run
4473 any hooks. */
4474 set_window_buffer (new, r->contents, false, true);
4475 unblock_input ();
4477 /* Maybe we should run the scroll functions in Elisp (which already
4478 runs the configuration change hook). */
4479 if (! NILP (Vwindow_scroll_functions))
4480 run_hook_with_args_2 (Qwindow_scroll_functions, new,
4481 Fmarker_position (n->start));
4482 /* Return NEW. */
4483 return new;
4487 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
4488 doc: /* Remove WINDOW from its frame.
4489 WINDOW defaults to the selected window. Return nil.
4490 Signal an error when WINDOW is the only window on its frame. */)
4491 (Lisp_Object window)
4493 Lisp_Object parent, sibling, frame, root;
4494 struct window *w, *p, *s, *r;
4495 struct frame *f;
4496 bool horflag, before_sibling = false;
4498 w = decode_any_window (window);
4499 XSETWINDOW (window, w);
4500 if (NILP (w->contents))
4501 /* It's a no-op to delete an already deleted window. */
4502 return Qnil;
4504 parent = w->parent;
4505 if (NILP (parent))
4506 /* Never delete a minibuffer or frame root window. */
4507 error ("Attempt to delete minibuffer or sole ordinary window");
4508 else if (NILP (w->prev) && NILP (w->next))
4509 /* Rather bow out here, this case should be handled on the Elisp
4510 level. */
4511 error ("Attempt to delete sole window of parent");
4513 p = XWINDOW (parent);
4514 horflag = WINDOW_HORIZONTAL_COMBINATION_P (p);
4516 frame = WINDOW_FRAME (w);
4517 f = XFRAME (frame);
4519 root = FRAME_ROOT_WINDOW (f);
4520 r = XWINDOW (root);
4522 /* Unlink WINDOW from window tree. */
4523 if (NILP (w->prev))
4524 /* Get SIBLING below (on the right of) WINDOW. */
4526 /* before_sibling means WINDOW is the first child of its
4527 parent and thus before the sibling. */
4528 before_sibling = true;
4529 sibling = w->next;
4530 s = XWINDOW (sibling);
4531 wset_prev (s, Qnil);
4532 wset_combination (p, horflag, sibling);
4534 else
4535 /* Get SIBLING above (on the left of) WINDOW. */
4537 sibling = w->prev;
4538 s = XWINDOW (sibling);
4539 wset_next (s, w->next);
4540 if (!NILP (s->next))
4541 wset_prev (XWINDOW (s->next), sibling);
4544 if (window_resize_check (r, horflag)
4545 && (XINT (r->new_pixel)
4546 == (horflag ? r->pixel_width : r->pixel_height)))
4547 /* We can delete WINDOW now. */
4550 /* Block input. */
4551 block_input ();
4552 window_resize_apply (p, horflag);
4553 /* If this window is referred to by the dpyinfo's mouse
4554 highlight, invalidate that slot to be safe (Bug#9904). */
4555 if (!FRAME_INITIAL_P (f))
4557 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
4559 if (EQ (hlinfo->mouse_face_window, window))
4560 hlinfo->mouse_face_window = Qnil;
4563 fset_redisplay (f);
4564 Vwindow_list = Qnil;
4565 FRAME_WINDOW_SIZES_CHANGED (f) = true;
4567 wset_next (w, Qnil); /* Don't delete w->next too. */
4568 free_window_matrices (w);
4570 if (WINDOWP (w->contents))
4572 delete_all_child_windows (w->contents);
4573 wset_combination (w, false, Qnil);
4575 else
4577 unshow_buffer (w);
4578 unchain_marker (XMARKER (w->pointm));
4579 unchain_marker (XMARKER (w->old_pointm));
4580 unchain_marker (XMARKER (w->start));
4581 wset_buffer (w, Qnil);
4584 if (NILP (s->prev) && NILP (s->next))
4585 /* A matrjoshka where SIBLING has become the only child of
4586 PARENT. */
4588 /* Put SIBLING into PARENT's place. */
4589 replace_window (parent, sibling, false);
4590 /* Have SIBLING inherit the following three slot values from
4591 PARENT (the combination_limit slot is not inherited). */
4592 wset_normal_cols (s, p->normal_cols);
4593 wset_normal_lines (s, p->normal_lines);
4594 /* Mark PARENT as deleted. */
4595 wset_combination (p, false, Qnil);
4596 /* Try to merge SIBLING into its new parent. */
4597 recombine_windows (sibling);
4600 adjust_frame_glyphs (f);
4602 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
4603 /* We deleted the frame's selected window. */
4605 /* Use the frame's first window as fallback ... */
4606 Lisp_Object new_selected_window = Fframe_first_window (frame);
4607 /* ... but preferably use its most recently used window. */
4608 Lisp_Object mru_window;
4610 /* `get-mru-window' might fail for some reason so play it safe
4611 - promote the first window _without recording it_ first. */
4612 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4613 Fselect_window (new_selected_window, Qt);
4614 else
4615 fset_selected_window (f, new_selected_window);
4617 unblock_input ();
4619 /* Now look whether `get-mru-window' gets us something. */
4620 mru_window = call1 (Qget_mru_window, frame);
4621 if (WINDOW_LIVE_P (mru_window)
4622 && EQ (XWINDOW (mru_window)->frame, frame))
4623 new_selected_window = mru_window;
4625 /* If all ended up well, we now promote the mru window. */
4626 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4627 Fselect_window (new_selected_window, Qnil);
4628 else
4629 fset_selected_window (f, new_selected_window);
4631 else
4632 unblock_input ();
4634 /* Must be run by the caller:
4635 run_window_configuration_change_hook (f); */
4637 else
4638 /* We failed: Relink WINDOW into window tree. */
4640 if (before_sibling)
4642 wset_prev (s, window);
4643 wset_combination (p, horflag, window);
4645 else
4647 wset_next (s, window);
4648 if (!NILP (w->next))
4649 wset_prev (XWINDOW (w->next), window);
4651 error ("Deletion failed");
4654 return Qnil;
4657 /***********************************************************************
4658 Resizing Mini-Windows
4659 ***********************************************************************/
4661 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
4662 can. */
4663 void
4664 grow_mini_window (struct window *w, int delta, bool pixelwise)
4666 struct frame *f = XFRAME (w->frame);
4667 struct window *r;
4668 Lisp_Object root, height;
4669 int line_height, pixel_height;
4671 eassert (MINI_WINDOW_P (w));
4672 eassert (delta >= 0);
4674 if (delta > 0)
4676 root = FRAME_ROOT_WINDOW (f);
4677 r = XWINDOW (root);
4678 height = call3 (Qwindow_resize_root_window_vertically,
4679 root, make_number (- delta), pixelwise ? Qt : Qnil);
4680 if (INTEGERP (height) && window_resize_check (r, false))
4682 block_input ();
4683 window_resize_apply (r, false);
4685 if (pixelwise)
4687 pixel_height = min (-XINT (height), INT_MAX - w->pixel_height);
4688 line_height = pixel_height / FRAME_LINE_HEIGHT (f);
4690 else
4692 line_height = min (-XINT (height),
4693 ((INT_MAX - w->pixel_height)
4694 / FRAME_LINE_HEIGHT (f)));
4695 pixel_height = line_height * FRAME_LINE_HEIGHT (f);
4698 /* Grow the mini-window. */
4699 w->pixel_top = r->pixel_top + r->pixel_height;
4700 w->top_line = r->top_line + r->total_lines;
4701 /* Make sure the mini-window has always at least one line. */
4702 w->pixel_height = max (w->pixel_height + pixel_height,
4703 FRAME_LINE_HEIGHT (f));
4704 w->total_lines = max (w->total_lines + line_height, 1);
4706 /* Enforce full redisplay of the frame. */
4707 /* FIXME: Shouldn't window--resize-root-window-vertically do it? */
4708 fset_redisplay (f);
4709 adjust_frame_glyphs (f);
4710 unblock_input ();
4715 /* Shrink mini-window W to one line. */
4716 void
4717 shrink_mini_window (struct window *w, bool pixelwise)
4719 struct frame *f = XFRAME (w->frame);
4720 struct window *r;
4721 Lisp_Object root, delta;
4722 EMACS_INT height, unit;
4724 eassert (MINI_WINDOW_P (w));
4726 height = pixelwise ? w->pixel_height : w->total_lines;
4727 unit = pixelwise ? FRAME_LINE_HEIGHT (f) : 1;
4728 if (height > unit)
4730 root = FRAME_ROOT_WINDOW (f);
4731 r = XWINDOW (root);
4732 delta = call3 (Qwindow_resize_root_window_vertically,
4733 root, make_number (height - unit),
4734 pixelwise ? Qt : Qnil);
4735 if (INTEGERP (delta) && window_resize_check (r, false))
4737 block_input ();
4738 window_resize_apply (r, false);
4740 /* Shrink the mini-window. */
4741 w->top_line = r->top_line + r->total_lines;
4742 w->total_lines = 1;
4743 w->pixel_top = r->pixel_top + r->pixel_height;
4744 w->pixel_height = FRAME_LINE_HEIGHT (f);
4745 /* Enforce full redisplay of the frame. */
4746 /* FIXME: Shouldn't window--resize-root-window-vertically do it? */
4747 fset_redisplay (f);
4748 adjust_frame_glyphs (f);
4749 unblock_input ();
4751 /* If the above failed for whatever strange reason we must make a
4752 one window frame here. The same routine will be needed when
4753 shrinking the frame (and probably when making the initial
4754 *scratch* window). For the moment leave things as they are. */
4758 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
4759 doc: /* Resize minibuffer window WINDOW. */)
4760 (Lisp_Object window)
4762 struct window *w = XWINDOW (window);
4763 struct window *r;
4764 struct frame *f;
4765 int height;
4767 CHECK_WINDOW (window);
4768 f = XFRAME (w->frame);
4770 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
4771 error ("Not a valid minibuffer window");
4772 else if (FRAME_MINIBUF_ONLY_P (f))
4773 error ("Cannot resize a minibuffer-only frame");
4775 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4776 height = r->pixel_height + w->pixel_height;
4777 if (window_resize_check (r, false)
4778 && XINT (w->new_pixel) > 0
4779 && height == XINT (r->new_pixel) + XINT (w->new_pixel))
4781 block_input ();
4782 window_resize_apply (r, false);
4784 w->pixel_height = XFASTINT (w->new_pixel);
4785 w->total_lines = w->pixel_height / FRAME_LINE_HEIGHT (f);
4786 w->pixel_top = r->pixel_top + r->pixel_height;
4787 w->top_line = r->top_line + r->total_lines;
4789 fset_redisplay (f);
4790 FRAME_WINDOW_SIZES_CHANGED (f) = true;
4791 adjust_frame_glyphs (f);
4792 unblock_input ();
4793 return Qt;
4795 else
4796 error ("Failed to resize minibuffer window");
4799 /* Mark window cursors off for all windows in the window tree rooted
4800 at W by setting their phys_cursor_on_p flag to zero. Called from
4801 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4802 the frame are cleared. */
4804 void
4805 mark_window_cursors_off (struct window *w)
4807 while (w)
4809 if (WINDOWP (w->contents))
4810 mark_window_cursors_off (XWINDOW (w->contents));
4811 else
4812 w->phys_cursor_on_p = false;
4814 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4819 /* Return number of lines of text (not counting mode lines) in W. */
4822 window_internal_height (struct window *w)
4824 int ht = w->total_lines;
4826 if (!MINI_WINDOW_P (w))
4828 if (!NILP (w->parent)
4829 || WINDOWP (w->contents)
4830 || !NILP (w->next)
4831 || !NILP (w->prev)
4832 || WINDOW_WANTS_MODELINE_P (w))
4833 --ht;
4835 if (WINDOW_WANTS_HEADER_LINE_P (w))
4836 --ht;
4839 return ht;
4843 /************************************************************************
4844 Window Scrolling
4845 ***********************************************************************/
4847 /* Scroll contents of window WINDOW up. If WHOLE, scroll
4848 N screen-fulls, which is defined as the height of the window minus
4849 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4850 instead. Negative values of N mean scroll down. NOERROR
4851 means don't signal an error if we try to move over BEGV or ZV,
4852 respectively. */
4854 static void
4855 window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
4857 ptrdiff_t count = SPECPDL_INDEX ();
4859 immediate_quit = true;
4860 n = clip_to_bounds (INT_MIN, n, INT_MAX);
4862 wset_redisplay (XWINDOW (window));
4864 if (whole && Vfast_but_imprecise_scrolling)
4865 specbind (Qfontification_functions, Qnil);
4867 /* If we must, use the pixel-based version which is much slower than
4868 the line-based one but can handle varying line heights. */
4869 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4870 window_scroll_pixel_based (window, n, whole, noerror);
4871 else
4872 window_scroll_line_based (window, n, whole, noerror);
4874 unbind_to (count, Qnil);
4876 /* Bug#15957. */
4877 XWINDOW (window)->window_end_valid = false;
4878 immediate_quit = false;
4882 /* Implementation of window_scroll that works based on pixel line
4883 heights. See the comment of window_scroll for parameter
4884 descriptions. */
4886 static void
4887 window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
4889 struct it it;
4890 struct window *w = XWINDOW (window);
4891 struct text_pos start;
4892 int this_scroll_margin;
4893 /* True if we fiddled the window vscroll field without really scrolling. */
4894 bool vscrolled = false;
4895 int x, y, rtop, rbot, rowh, vpos;
4896 void *itdata = NULL;
4897 int window_total_lines;
4898 int frame_line_height = default_line_pixel_height (w);
4899 bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
4900 Fwindow_old_point (window)));
4902 SET_TEXT_POS_FROM_MARKER (start, w->start);
4903 /* Scrolling a minibuffer window via scroll bar when the echo area
4904 shows long text sometimes resets the minibuffer contents behind
4905 our backs. */
4906 if (CHARPOS (start) > ZV)
4907 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4909 /* If PT is not visible in WINDOW, move back one half of
4910 the screen. Allow PT to be partially visible, otherwise
4911 something like (scroll-down 1) with PT in the line before
4912 the partially visible one would recenter. */
4914 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4916 itdata = bidi_shelve_cache ();
4917 /* Move backward half the height of the window. Performance note:
4918 vmotion used here is about 10% faster, but would give wrong
4919 results for variable height lines. */
4920 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4921 it.current_y = it.last_visible_y;
4922 move_it_vertically_backward (&it, window_box_height (w) / 2);
4924 /* The function move_iterator_vertically may move over more than
4925 the specified y-distance. If it->w is small, e.g. a
4926 mini-buffer window, we may end up in front of the window's
4927 display area. Start displaying at the start of the line
4928 containing PT in this case. */
4929 if (it.current_y <= 0)
4931 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4932 move_it_vertically_backward (&it, 0);
4933 it.current_y = 0;
4936 start = it.current.pos;
4937 bidi_unshelve_cache (itdata, false);
4939 else if (auto_window_vscroll_p)
4941 if (rtop || rbot) /* Partially visible. */
4943 int px;
4944 int dy = frame_line_height;
4945 /* In the below we divide the window box height by the
4946 frame's line height to make the result predictable when
4947 the window box is not an integral multiple of the line
4948 height. This is important to ensure we get back to the
4949 same position when scrolling up, then down. */
4950 if (whole)
4951 dy = max ((window_box_height (w) / dy
4952 - next_screen_context_lines) * dy,
4953 dy);
4954 dy *= n;
4956 if (n < 0)
4958 /* Only vscroll backwards if already vscrolled forwards. */
4959 if (w->vscroll < 0 && rtop > 0)
4961 px = max (0, -w->vscroll - min (rtop, -dy));
4962 Fset_window_vscroll (window, make_number (px), Qt);
4963 return;
4966 if (n > 0)
4968 /* Do vscroll if already vscrolled or only display line. */
4969 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4971 px = max (0, -w->vscroll + min (rbot, dy));
4972 Fset_window_vscroll (window, make_number (px), Qt);
4973 return;
4976 /* Maybe modify window start instead of scrolling. */
4977 if (rbot > 0 || w->vscroll < 0)
4979 ptrdiff_t spos;
4981 Fset_window_vscroll (window, make_number (0), Qt);
4982 /* If there are other text lines above the current row,
4983 move window start to current row. Else to next row. */
4984 if (rbot > 0)
4985 spos = XINT (Fline_beginning_position (Qnil));
4986 else
4987 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4988 set_marker_restricted (w->start, make_number (spos),
4989 w->contents);
4990 w->start_at_line_beg = true;
4991 w->update_mode_line = true;
4992 /* Set force_start so that redisplay_window will run the
4993 window-scroll-functions. */
4994 w->force_start = true;
4995 return;
4999 /* Cancel previous vscroll. */
5000 Fset_window_vscroll (window, make_number (0), Qt);
5003 itdata = bidi_shelve_cache ();
5004 /* If scroll_preserve_screen_position is non-nil, we try to set
5005 point in the same window line as it is now, so get that line. */
5006 if (!NILP (Vscroll_preserve_screen_position))
5008 /* We preserve the goal pixel coordinate across consecutive
5009 calls to scroll-up, scroll-down and other commands that
5010 have the `scroll-command' property. This avoids the
5011 possibility of point becoming "stuck" on a tall line when
5012 scrolling by one line. */
5013 if (window_scroll_pixel_based_preserve_y < 0
5014 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
5015 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
5017 start_display (&it, w, start);
5018 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5019 window_scroll_pixel_based_preserve_y = it.current_y;
5020 window_scroll_pixel_based_preserve_x = it.current_x;
5023 else
5024 window_scroll_pixel_based_preserve_y
5025 = window_scroll_pixel_based_preserve_x = -1;
5027 /* Move iterator it from start the specified distance forward or
5028 backward. The result is the new window start. */
5029 start_display (&it, w, start);
5030 if (whole)
5032 ptrdiff_t start_pos = IT_CHARPOS (it);
5033 int dy = frame_line_height;
5034 /* In the below we divide the window box height by the frame's
5035 line height to make the result predictable when the window
5036 box is not an integral multiple of the line height. This is
5037 important to ensure we get back to the same position when
5038 scrolling up, then down. */
5039 dy = max ((window_box_height (w) / dy - next_screen_context_lines) * dy,
5040 dy) * n;
5042 /* Note that move_it_vertically always moves the iterator to the
5043 start of a line. So, if the last line doesn't have a newline,
5044 we would end up at the start of the line ending at ZV. */
5045 if (dy <= 0)
5047 move_it_vertically_backward (&it, -dy);
5048 /* Ensure we actually do move, e.g. in case we are currently
5049 looking at an image that is taller that the window height. */
5050 while (start_pos == IT_CHARPOS (it)
5051 && start_pos > BEGV)
5052 move_it_by_lines (&it, -1);
5054 else if (dy > 0)
5056 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
5057 MOVE_TO_POS | MOVE_TO_Y);
5058 /* Ensure we actually do move, e.g. in case we are currently
5059 looking at an image that is taller that the window height. */
5060 while (start_pos == IT_CHARPOS (it)
5061 && start_pos < ZV)
5062 move_it_by_lines (&it, 1);
5065 else
5066 move_it_by_lines (&it, n);
5068 /* We failed if we find ZV is already on the screen (scrolling up,
5069 means there's nothing past the end), or if we can't start any
5070 earlier (scrolling down, means there's nothing past the top). */
5071 if ((n > 0 && IT_CHARPOS (it) == ZV)
5072 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
5074 if (IT_CHARPOS (it) == ZV)
5076 if (it.current_y < it.last_visible_y
5077 && (it.current_y + it.max_ascent + it.max_descent
5078 > it.last_visible_y))
5080 /* The last line was only partially visible, make it fully
5081 visible. */
5082 w->vscroll = (it.last_visible_y
5083 - it.current_y + it.max_ascent + it.max_descent);
5084 adjust_frame_glyphs (it.f);
5086 else
5088 bidi_unshelve_cache (itdata, false);
5089 if (noerror)
5090 return;
5091 else if (n < 0) /* could happen with empty buffers */
5092 xsignal0 (Qbeginning_of_buffer);
5093 else
5094 xsignal0 (Qend_of_buffer);
5097 else
5099 if (w->vscroll != 0)
5100 /* The first line was only partially visible, make it fully
5101 visible. */
5102 w->vscroll = 0;
5103 else
5105 bidi_unshelve_cache (itdata, false);
5106 if (noerror)
5107 return;
5108 else
5109 xsignal0 (Qbeginning_of_buffer);
5113 /* If control gets here, then we vscrolled. */
5115 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
5117 /* Don't try to change the window start below. */
5118 vscrolled = true;
5121 if (! vscrolled)
5123 ptrdiff_t pos = IT_CHARPOS (it);
5124 ptrdiff_t bytepos;
5126 /* If in the middle of a multi-glyph character move forward to
5127 the next character. */
5128 if (in_display_vector_p (&it))
5130 ++pos;
5131 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
5134 /* Set the window start, and set up the window for redisplay. */
5135 set_marker_restricted_both (w->start, w->contents, IT_CHARPOS (it),
5136 IT_BYTEPOS (it));
5137 bytepos = marker_byte_position (w->start);
5138 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
5139 w->update_mode_line = true;
5140 /* Set force_start so that redisplay_window will run the
5141 window-scroll-functions. */
5142 w->force_start = true;
5145 /* The rest of this function uses current_y in a nonstandard way,
5146 not including the height of the header line if any. */
5147 it.current_y = it.vpos = 0;
5149 /* Move PT out of scroll margins.
5150 This code wants current_y to be zero at the window start position
5151 even if there is a header line. */
5152 window_total_lines
5153 = w->total_lines * WINDOW_FRAME_LINE_HEIGHT (w) / frame_line_height;
5154 this_scroll_margin = max (0, scroll_margin);
5155 this_scroll_margin
5156 = min (this_scroll_margin, window_total_lines / 4);
5157 this_scroll_margin *= frame_line_height;
5159 if (n > 0)
5161 /* We moved the window start towards ZV, so PT may be now
5162 in the scroll margin at the top. */
5163 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5164 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5165 && (NILP (Vscroll_preserve_screen_position)
5166 || EQ (Vscroll_preserve_screen_position, Qt)))
5167 /* We found PT at a legitimate height. Leave it alone. */
5169 else if (window_scroll_pixel_based_preserve_y >= 0)
5171 /* If we have a header line, take account of it.
5172 This is necessary because we set it.current_y to 0, above. */
5173 move_it_to (&it, -1,
5174 window_scroll_pixel_based_preserve_x,
5175 (window_scroll_pixel_based_preserve_y
5176 - WINDOW_WANTS_HEADER_LINE_P (w)),
5177 -1, MOVE_TO_Y | MOVE_TO_X);
5178 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5180 else
5182 while (it.current_y < this_scroll_margin)
5184 int prev = it.current_y;
5185 move_it_by_lines (&it, 1);
5186 if (prev == it.current_y)
5187 break;
5189 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5192 else if (n < 0)
5194 ptrdiff_t charpos, bytepos;
5195 bool partial_p;
5197 /* Save our position, for the
5198 window_scroll_pixel_based_preserve_y case. */
5199 charpos = IT_CHARPOS (it);
5200 bytepos = IT_BYTEPOS (it);
5202 /* We moved the window start towards BEGV, so PT may be now
5203 in the scroll margin at the bottom. */
5204 move_it_to (&it, PT, -1,
5205 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5206 - this_scroll_margin - 1),
5208 MOVE_TO_POS | MOVE_TO_Y);
5210 /* Save our position, in case it's correct. */
5211 charpos = IT_CHARPOS (it);
5212 bytepos = IT_BYTEPOS (it);
5214 /* If PT is in the screen line at the last fully visible line,
5215 move_it_to will stop at X = 0 in that line, because the
5216 required Y coordinate is reached there. See if we can get to
5217 PT without descending lower in Y, and if we can, it means we
5218 reached PT before the scroll margin. */
5219 if (charpos != PT)
5221 struct it it2;
5222 void *it_data;
5224 it2 = it;
5225 it_data = bidi_shelve_cache ();
5226 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5227 if (IT_CHARPOS (it) == PT && it.current_y == it2.current_y)
5229 charpos = IT_CHARPOS (it);
5230 bytepos = IT_BYTEPOS (it);
5231 bidi_unshelve_cache (it_data, true);
5233 else
5235 it = it2;
5236 bidi_unshelve_cache (it_data, false);
5240 /* See if point is on a partially visible line at the end. */
5241 if (it.what == IT_EOB)
5242 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5243 else
5245 move_it_by_lines (&it, 1);
5246 partial_p = it.current_y > it.last_visible_y;
5249 if (charpos == PT && !partial_p
5250 && (NILP (Vscroll_preserve_screen_position)
5251 || EQ (Vscroll_preserve_screen_position, Qt)))
5252 /* We found PT before we found the display margin, so PT is ok. */
5254 else if (window_scroll_pixel_based_preserve_y >= 0)
5256 SET_TEXT_POS_FROM_MARKER (start, w->start);
5257 start_display (&it, w, start);
5258 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5259 here because we called start_display again and did not
5260 alter it.current_y this time. */
5261 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
5262 window_scroll_pixel_based_preserve_y, -1,
5263 MOVE_TO_Y | MOVE_TO_X);
5264 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5266 else
5268 if (partial_p)
5269 /* The last line was only partially visible, so back up two
5270 lines to make sure we're on a fully visible line. */
5272 move_it_by_lines (&it, -2);
5273 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5275 else
5276 /* No, the position we saved is OK, so use it. */
5277 SET_PT_BOTH (charpos, bytepos);
5280 bidi_unshelve_cache (itdata, false);
5282 if (adjust_old_pointm)
5283 Fset_marker (w->old_pointm,
5284 ((w == XWINDOW (selected_window))
5285 ? make_number (BUF_PT (XBUFFER (w->contents)))
5286 : Fmarker_position (w->pointm)),
5287 w->contents);
5291 /* Implementation of window_scroll that works based on screen lines.
5292 See the comment of window_scroll for parameter descriptions. */
5294 static void
5295 window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
5297 struct window *w = XWINDOW (window);
5298 /* Fvertical_motion enters redisplay, which can trigger
5299 fontification, which in turn can modify buffer text (e.g., if the
5300 fontification functions replace escape sequences with faces, as
5301 in `grep-mode-font-lock-keywords'). So we use a marker to record
5302 the old point position, to prevent crashes in SET_PT_BOTH. */
5303 Lisp_Object opoint_marker = Fpoint_marker ();
5304 register ptrdiff_t pos, pos_byte;
5305 register int ht = window_internal_height (w);
5306 register Lisp_Object tem;
5307 bool lose;
5308 Lisp_Object bolp;
5309 ptrdiff_t startpos = marker_position (w->start);
5310 ptrdiff_t startbyte = marker_byte_position (w->start);
5311 Lisp_Object original_pos = Qnil;
5312 bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
5313 Fwindow_old_point (window)));
5315 /* If scrolling screen-fulls, compute the number of lines to
5316 scroll from the window's height. */
5317 if (whole)
5318 n *= max (1, ht - next_screen_context_lines);
5320 if (!NILP (Vscroll_preserve_screen_position))
5322 if (window_scroll_preserve_vpos <= 0
5323 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
5324 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
5326 struct position posit
5327 = *compute_motion (startpos, startbyte, 0, 0, false,
5328 PT, ht, 0, -1, w->hscroll, 0, w);
5330 window_scroll_preserve_vpos = posit.vpos;
5331 window_scroll_preserve_hpos = posit.hpos + w->hscroll;
5334 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
5335 make_number (window_scroll_preserve_vpos));
5338 XSETFASTINT (tem, PT);
5339 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5341 if (NILP (tem))
5343 Fvertical_motion (make_number (- (ht / 2)), window, Qnil);
5344 startpos = PT;
5345 startbyte = PT_BYTE;
5348 SET_PT_BOTH (startpos, startbyte);
5349 lose = n < 0 && PT == BEGV;
5350 Fvertical_motion (make_number (n), window, Qnil);
5351 pos = PT;
5352 pos_byte = PT_BYTE;
5353 bolp = Fbolp ();
5354 SET_PT_BOTH (marker_position (opoint_marker),
5355 marker_byte_position (opoint_marker));
5357 if (lose)
5359 if (noerror)
5360 return;
5361 else
5362 xsignal0 (Qbeginning_of_buffer);
5365 if (pos < ZV)
5367 /* Don't use a scroll margin that is negative or too large. */
5368 int this_scroll_margin =
5369 max (0, min (scroll_margin, w->total_lines / 4));
5371 set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
5372 w->start_at_line_beg = !NILP (bolp);
5373 w->update_mode_line = true;
5374 /* Set force_start so that redisplay_window will run
5375 the window-scroll-functions. */
5376 w->force_start = true;
5378 if (!NILP (Vscroll_preserve_screen_position)
5379 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5381 SET_PT_BOTH (pos, pos_byte);
5382 Fvertical_motion (original_pos, window, Qnil);
5384 /* If we scrolled forward, put point enough lines down
5385 that it is outside the scroll margin. */
5386 else if (n > 0)
5388 int top_margin;
5390 if (this_scroll_margin > 0)
5392 SET_PT_BOTH (pos, pos_byte);
5393 Fvertical_motion (make_number (this_scroll_margin), window, Qnil);
5394 top_margin = PT;
5396 else
5397 top_margin = pos;
5399 if (top_margin <= marker_position (opoint_marker))
5400 SET_PT_BOTH (marker_position (opoint_marker),
5401 marker_byte_position (opoint_marker));
5402 else if (!NILP (Vscroll_preserve_screen_position))
5404 SET_PT_BOTH (pos, pos_byte);
5405 Fvertical_motion (original_pos, window, Qnil);
5407 else
5408 SET_PT (top_margin);
5410 else if (n < 0)
5412 int bottom_margin;
5414 /* If we scrolled backward, put point near the end of the window
5415 but not within the scroll margin. */
5416 SET_PT_BOTH (pos, pos_byte);
5417 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window,
5418 Qnil);
5419 if (XFASTINT (tem) == ht - this_scroll_margin)
5420 bottom_margin = PT;
5421 else
5422 bottom_margin = PT + 1;
5424 if (bottom_margin > marker_position (opoint_marker))
5425 SET_PT_BOTH (marker_position (opoint_marker),
5426 marker_byte_position (opoint_marker));
5427 else
5429 if (!NILP (Vscroll_preserve_screen_position))
5431 SET_PT_BOTH (pos, pos_byte);
5432 Fvertical_motion (original_pos, window, Qnil);
5434 else
5435 Fvertical_motion (make_number (-1), window, Qnil);
5439 else
5441 if (noerror)
5442 return;
5443 else
5444 xsignal0 (Qend_of_buffer);
5447 if (adjust_old_pointm)
5448 Fset_marker (w->old_pointm,
5449 ((w == XWINDOW (selected_window))
5450 ? make_number (BUF_PT (XBUFFER (w->contents)))
5451 : Fmarker_position (w->pointm)),
5452 w->contents);
5456 /* Scroll selected_window up or down. If N is nil, scroll a
5457 screen-full which is defined as the height of the window minus
5458 next_screen_context_lines. If N is the symbol `-', scroll.
5459 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5460 up. This is the guts of Fscroll_up and Fscroll_down. */
5462 static void
5463 scroll_command (Lisp_Object n, int direction)
5465 ptrdiff_t count = SPECPDL_INDEX ();
5467 eassert (eabs (direction) == 1);
5469 /* If selected window's buffer isn't current, make it current for
5470 the moment. But don't screw up if window_scroll gets an error. */
5471 if (XBUFFER (XWINDOW (selected_window)->contents) != current_buffer)
5473 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5474 Fset_buffer (XWINDOW (selected_window)->contents);
5477 if (NILP (n))
5478 window_scroll (selected_window, direction, true, false);
5479 else if (EQ (n, Qminus))
5480 window_scroll (selected_window, -direction, true, false);
5481 else
5483 n = Fprefix_numeric_value (n);
5484 window_scroll (selected_window, XINT (n) * direction, false, false);
5487 unbind_to (count, Qnil);
5490 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
5491 doc: /* Scroll text of selected window upward ARG lines.
5492 If ARG is omitted or nil, scroll upward by a near full screen.
5493 A near full screen is `next-screen-context-lines' less than a full screen.
5494 Negative ARG means scroll downward.
5495 If ARG is the atom `-', scroll downward by nearly full screen.
5496 When calling from a program, supply as argument a number, nil, or `-'. */)
5497 (Lisp_Object arg)
5499 scroll_command (arg, 1);
5500 return Qnil;
5503 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
5504 doc: /* Scroll text of selected window down ARG lines.
5505 If ARG is omitted or nil, scroll down by a near full screen.
5506 A near full screen is `next-screen-context-lines' less than a full screen.
5507 Negative ARG means scroll upward.
5508 If ARG is the atom `-', scroll upward by nearly full screen.
5509 When calling from a program, supply as argument a number, nil, or `-'. */)
5510 (Lisp_Object arg)
5512 scroll_command (arg, -1);
5513 return Qnil;
5516 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5517 doc: /* Return the other window for \"other window scroll\" commands.
5518 If `other-window-scroll-buffer' is non-nil, a window
5519 showing that buffer is used.
5520 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5521 specifies the window. This takes precedence over
5522 `other-window-scroll-buffer'. */)
5523 (void)
5525 Lisp_Object window;
5527 if (MINI_WINDOW_P (XWINDOW (selected_window))
5528 && !NILP (Vminibuf_scroll_window))
5529 window = Vminibuf_scroll_window;
5530 /* If buffer is specified and live, scroll that buffer. */
5531 else if (!NILP (Vother_window_scroll_buffer)
5532 && BUFFERP (Vother_window_scroll_buffer)
5533 && BUFFER_LIVE_P (XBUFFER (Vother_window_scroll_buffer)))
5535 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5536 if (NILP (window))
5537 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5539 else
5541 /* Nothing specified; look for a neighboring window on the same
5542 frame. */
5543 window = Fnext_window (selected_window, Qnil, Qnil);
5545 if (EQ (window, selected_window))
5546 /* That didn't get us anywhere; look for a window on another
5547 visible frame. */
5549 window = Fnext_window (window, Qnil, Qt);
5550 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5551 && ! EQ (window, selected_window));
5554 CHECK_LIVE_WINDOW (window);
5556 if (EQ (window, selected_window))
5557 error ("There is no other window");
5559 return window;
5562 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5563 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5564 A near full screen is `next-screen-context-lines' less than a full screen.
5565 The next window is the one below the current one; or the one at the top
5566 if the current one is at the bottom. Negative ARG means scroll downward.
5567 If ARG is the atom `-', scroll downward by nearly full screen.
5568 When calling from a program, supply as argument a number, nil, or `-'.
5570 If `other-window-scroll-buffer' is non-nil, scroll the window
5571 showing that buffer, popping the buffer up if necessary.
5572 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5573 specifies the window to scroll. This takes precedence over
5574 `other-window-scroll-buffer'. */)
5575 (Lisp_Object arg)
5577 Lisp_Object window;
5578 struct window *w;
5579 ptrdiff_t count = SPECPDL_INDEX ();
5581 window = Fother_window_for_scrolling ();
5582 w = XWINDOW (window);
5584 /* Don't screw up if window_scroll gets an error. */
5585 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5587 Fset_buffer (w->contents);
5588 SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
5589 SET_PT_BOTH (marker_position (w->old_pointm), marker_byte_position (w->old_pointm));
5591 if (NILP (arg))
5592 window_scroll (window, 1, true, true);
5593 else if (EQ (arg, Qminus))
5594 window_scroll (window, -1, true, true);
5595 else
5597 if (CONSP (arg))
5598 arg = XCAR (arg);
5599 CHECK_NUMBER (arg);
5600 window_scroll (window, XINT (arg), false, true);
5603 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5604 set_marker_both (w->old_pointm, Qnil, PT, PT_BYTE);
5605 unbind_to (count, Qnil);
5607 return Qnil;
5610 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5611 doc: /* Scroll selected window display ARG columns left.
5612 Default for ARG is window width minus 2.
5613 Value is the total amount of leftward horizontal scrolling in
5614 effect after the change.
5615 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5616 lower bound for automatic scrolling, i.e. automatic scrolling
5617 will not scroll a window to a column less than the value returned
5618 by this function. This happens in an interactive call. */)
5619 (register Lisp_Object arg, Lisp_Object set_minimum)
5621 struct window *w = XWINDOW (selected_window);
5622 EMACS_INT requested_arg = (NILP (arg)
5623 ? window_body_width (w, 0) - 2
5624 : XINT (Fprefix_numeric_value (arg)));
5625 Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
5627 if (!NILP (set_minimum))
5628 w->min_hscroll = w->hscroll;
5630 w->suspend_auto_hscroll = true;
5632 return result;
5635 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5636 doc: /* Scroll selected window display ARG columns right.
5637 Default for ARG is window width minus 2.
5638 Value is the total amount of leftward horizontal scrolling in
5639 effect after the change.
5640 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5641 lower bound for automatic scrolling, i.e. automatic scrolling
5642 will not scroll a window to a column less than the value returned
5643 by this function. This happens in an interactive call. */)
5644 (register Lisp_Object arg, Lisp_Object set_minimum)
5646 struct window *w = XWINDOW (selected_window);
5647 EMACS_INT requested_arg = (NILP (arg)
5648 ? window_body_width (w, 0) - 2
5649 : XINT (Fprefix_numeric_value (arg)));
5650 Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
5652 if (!NILP (set_minimum))
5653 w->min_hscroll = w->hscroll;
5655 w->suspend_auto_hscroll = true;
5657 return result;
5660 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5661 doc: /* Return the window which was selected when entering the minibuffer.
5662 Returns nil, if selected window is not a minibuffer window. */)
5663 (void)
5665 if (minibuf_level > 0
5666 && MINI_WINDOW_P (XWINDOW (selected_window))
5667 && WINDOW_LIVE_P (minibuf_selected_window))
5668 return minibuf_selected_window;
5670 return Qnil;
5673 /* Value is the number of lines actually displayed in window W,
5674 as opposed to its height. */
5676 static int
5677 displayed_window_lines (struct window *w)
5679 struct it it;
5680 struct text_pos start;
5681 int height = window_box_height (w);
5682 struct buffer *old_buffer;
5683 int bottom_y;
5684 void *itdata = NULL;
5686 if (XBUFFER (w->contents) != current_buffer)
5688 old_buffer = current_buffer;
5689 set_buffer_internal (XBUFFER (w->contents));
5691 else
5692 old_buffer = NULL;
5694 /* In case W->start is out of the accessible range, do something
5695 reasonable. This happens in Info mode when Info-scroll-down
5696 calls (recenter -1) while W->start is 1. */
5697 CLIP_TEXT_POS_FROM_MARKER (start, w->start);
5699 itdata = bidi_shelve_cache ();
5700 start_display (&it, w, start);
5701 move_it_vertically (&it, height);
5702 bottom_y = line_bottom_y (&it);
5703 bidi_unshelve_cache (itdata, false);
5705 /* rms: On a non-window display,
5706 the value of it.vpos at the bottom of the screen
5707 seems to be 1 larger than window_box_height (w).
5708 This kludge fixes a bug whereby (move-to-window-line -1)
5709 when ZV is on the last screen line
5710 moves to the previous screen line instead of the last one. */
5711 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5712 height++;
5714 /* Add in empty lines at the bottom of the window. */
5715 if (bottom_y < height)
5717 int uy = FRAME_LINE_HEIGHT (it.f);
5718 it.vpos += (height - bottom_y + uy - 1) / uy;
5721 if (old_buffer)
5722 set_buffer_internal (old_buffer);
5724 return it.vpos;
5728 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5729 doc: /* Center point in selected window and maybe redisplay frame.
5730 With a numeric prefix argument ARG, recenter putting point on screen line ARG
5731 relative to the selected window. If ARG is negative, it counts up from the
5732 bottom of the window. (ARG should be less than the height of the window.)
5734 If ARG is omitted or nil, then recenter with point on the middle line of
5735 the selected window; if the variable `recenter-redisplay' is non-nil,
5736 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5737 is set to `grow-only', this resets the tool-bar's height to the minimum
5738 height needed); if `recenter-redisplay' has the special value `tty',
5739 then only tty frames are redrawn.
5741 Just C-u as prefix means put point in the center of the window
5742 and redisplay normally--don't erase and redraw the frame. */)
5743 (register Lisp_Object arg)
5745 struct window *w = XWINDOW (selected_window);
5746 struct buffer *buf = XBUFFER (w->contents);
5747 bool center_p = false;
5748 ptrdiff_t charpos, bytepos;
5749 EMACS_INT iarg IF_LINT (= 0);
5750 int this_scroll_margin;
5752 if (buf != current_buffer)
5753 error ("`recenter'ing a window that does not display current-buffer.");
5755 /* If redisplay is suppressed due to an error, try again. */
5756 buf->display_error_modiff = 0;
5758 if (NILP (arg))
5760 if (!NILP (Vrecenter_redisplay)
5761 && (!EQ (Vrecenter_redisplay, Qtty)
5762 || !NILP (Ftty_type (selected_frame))))
5764 ptrdiff_t i;
5766 /* Invalidate pixel data calculated for all compositions. */
5767 for (i = 0; i < n_compositions; i++)
5768 composition_table[i]->font = NULL;
5769 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
5770 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5771 #endif
5772 Fredraw_frame (WINDOW_FRAME (w));
5773 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5776 center_p = true;
5778 else if (CONSP (arg)) /* Just C-u. */
5779 center_p = true;
5780 else
5782 arg = Fprefix_numeric_value (arg);
5783 CHECK_NUMBER (arg);
5784 iarg = XINT (arg);
5787 /* Do this after making BUF current
5788 in case scroll_margin is buffer-local. */
5789 this_scroll_margin
5790 = max (0, min (scroll_margin, w->total_lines / 4));
5792 /* Don't use redisplay code for initial frames, as the necessary
5793 data structures might not be set up yet then. */
5794 if (!FRAME_INITIAL_P (XFRAME (w->frame)))
5796 if (center_p)
5798 struct it it;
5799 struct text_pos pt;
5800 void *itdata = bidi_shelve_cache ();
5802 SET_TEXT_POS (pt, PT, PT_BYTE);
5803 start_display (&it, w, pt);
5804 move_it_vertically_backward (&it, window_box_height (w) / 2);
5805 charpos = IT_CHARPOS (it);
5806 bytepos = IT_BYTEPOS (it);
5807 bidi_unshelve_cache (itdata, false);
5809 else if (iarg < 0)
5811 struct it it;
5812 struct text_pos pt;
5813 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
5814 int extra_line_spacing;
5815 int h = window_box_height (w);
5816 int ht = window_internal_height (w);
5817 void *itdata = bidi_shelve_cache ();
5819 nlines = clip_to_bounds (this_scroll_margin + 1, nlines,
5820 ht - this_scroll_margin);
5822 SET_TEXT_POS (pt, PT, PT_BYTE);
5823 start_display (&it, w, pt);
5825 /* Be sure we have the exact height of the full line containing PT. */
5826 move_it_by_lines (&it, 0);
5828 /* The amount of pixels we have to move back is the window
5829 height minus what's displayed in the line containing PT,
5830 and the lines below. */
5831 it.current_y = 0;
5832 it.vpos = 0;
5833 move_it_by_lines (&it, nlines);
5835 if (it.vpos == nlines)
5836 h -= it.current_y;
5837 else
5839 /* Last line has no newline. */
5840 h -= line_bottom_y (&it);
5841 it.vpos++;
5844 /* Don't reserve space for extra line spacing of last line. */
5845 extra_line_spacing = it.max_extra_line_spacing;
5847 /* If we can't move down NLINES lines because we hit
5848 the end of the buffer, count in some empty lines. */
5849 if (it.vpos < nlines)
5851 nlines -= it.vpos;
5852 extra_line_spacing = it.extra_line_spacing;
5853 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5855 if (h <= 0)
5857 bidi_unshelve_cache (itdata, false);
5858 return Qnil;
5861 /* Now find the new top line (starting position) of the window. */
5862 start_display (&it, w, pt);
5863 it.current_y = 0;
5864 move_it_vertically_backward (&it, h);
5866 /* If extra line spacing is present, we may move too far
5867 back. This causes the last line to be only partially
5868 visible (which triggers redisplay to recenter that line
5869 in the middle), so move forward.
5870 But ignore extra line spacing on last line, as it is not
5871 considered to be part of the visible height of the line.
5873 h += extra_line_spacing;
5874 while (-it.current_y > h)
5875 move_it_by_lines (&it, 1);
5877 charpos = IT_CHARPOS (it);
5878 bytepos = IT_BYTEPOS (it);
5880 bidi_unshelve_cache (itdata, false);
5882 else
5884 struct it it;
5885 struct text_pos pt;
5886 ptrdiff_t nlines = min (PTRDIFF_MAX, iarg);
5887 int ht = window_internal_height (w);
5888 void *itdata = bidi_shelve_cache ();
5890 nlines = clip_to_bounds (this_scroll_margin, nlines,
5891 ht - this_scroll_margin - 1);
5893 SET_TEXT_POS (pt, PT, PT_BYTE);
5894 start_display (&it, w, pt);
5896 /* Move to the beginning of screen line containing PT. */
5897 move_it_by_lines (&it, 0);
5899 /* Move back to find the point which is ARG screen lines above PT. */
5900 if (nlines > 0)
5902 it.current_y = 0;
5903 it.vpos = 0;
5904 move_it_by_lines (&it, -nlines);
5907 charpos = IT_CHARPOS (it);
5908 bytepos = IT_BYTEPOS (it);
5910 bidi_unshelve_cache (itdata, false);
5913 else
5915 struct position pos;
5916 int ht = window_internal_height (w);
5918 if (center_p)
5919 iarg = ht / 2;
5920 else if (iarg < 0)
5921 iarg += ht;
5923 /* Don't let it get into the margin at either top or bottom. */
5924 iarg = clip_to_bounds (this_scroll_margin, iarg,
5925 ht - this_scroll_margin - 1);
5927 pos = *vmotion (PT, PT_BYTE, - iarg, w);
5928 charpos = pos.bufpos;
5929 bytepos = pos.bytepos;
5932 /* Set the new window start. */
5933 set_marker_both (w->start, w->contents, charpos, bytepos);
5934 w->window_end_valid = false;
5936 w->optional_new_start = true;
5938 w->start_at_line_beg = (bytepos == BEGV_BYTE
5939 || FETCH_BYTE (bytepos - 1) == '\n');
5941 wset_redisplay (w);
5943 return Qnil;
5946 DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
5947 0, 2, 0,
5948 doc: /* Return the width in columns of the text display area of WINDOW.
5949 WINDOW must be a live window and defaults to the selected one.
5951 The returned width does not include dividers, scrollbars, margins,
5952 fringes, nor any partial-width columns at the right of the text
5953 area.
5955 Optional argument PIXELWISE non-nil, means to return the width in
5956 pixels. */)
5957 (Lisp_Object window, Lisp_Object pixelwise)
5959 struct window *w = decode_live_window (window);
5961 if (NILP (pixelwise))
5962 return make_number (window_box_width (w, TEXT_AREA)
5963 / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
5964 else
5965 return make_number (window_box_width (w, TEXT_AREA));
5968 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5969 0, 2, 0,
5970 doc: /* Return the height in lines of the text display area of WINDOW.
5971 WINDOW must be a live window and defaults to the selected one.
5973 The returned height does not include dividers, the mode line, any header
5974 line, nor any partial-height lines at the bottom of the text area.
5976 Optional argument PIXELWISE non-nil, means to return the height in
5977 pixels. */)
5978 (Lisp_Object window, Lisp_Object pixelwise)
5980 struct window *w = decode_live_window (window);
5982 if (NILP (pixelwise))
5983 return make_number (window_box_height (w)
5984 / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
5985 else
5986 return make_number (window_box_height (w));
5989 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5990 1, 1, "P",
5991 doc: /* Position point relative to window.
5992 ARG nil means position point at center of window.
5993 Else, ARG specifies vertical position within the window;
5994 zero means top of window, negative means relative to bottom of window. */)
5995 (Lisp_Object arg)
5997 struct window *w = XWINDOW (selected_window);
5998 int lines, start;
5999 Lisp_Object window;
6000 #if false
6001 int this_scroll_margin;
6002 #endif
6004 if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer))
6005 /* This test is needed to make sure PT/PT_BYTE make sense in w->contents
6006 when passed below to set_marker_both. */
6007 error ("move-to-window-line called from unrelated buffer");
6009 window = selected_window;
6010 start = marker_position (w->start);
6011 if (start < BEGV || start > ZV)
6013 int height = window_internal_height (w);
6014 Fvertical_motion (make_number (- (height / 2)), window, Qnil);
6015 set_marker_both (w->start, w->contents, PT, PT_BYTE);
6016 w->start_at_line_beg = !NILP (Fbolp ());
6017 w->force_start = true;
6019 else
6020 Fgoto_char (w->start);
6022 lines = displayed_window_lines (w);
6024 #if false
6025 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
6026 #endif
6028 if (NILP (arg))
6029 XSETFASTINT (arg, lines / 2);
6030 else
6032 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
6034 if (iarg < 0)
6035 iarg = iarg + lines;
6037 #if false /* This code would prevent move-to-window-line from moving point
6038 to a place inside the scroll margins (which would cause the
6039 next redisplay to scroll). I wrote this code, but then concluded
6040 it is probably better not to install it. However, it is here
6041 inside #if false so as not to lose it. -- rms. */
6043 /* Don't let it get into the margin at either top or bottom. */
6044 iarg = max (iarg, this_scroll_margin);
6045 iarg = min (iarg, lines - this_scroll_margin - 1);
6046 #endif
6048 arg = make_number (iarg);
6051 /* Skip past a partially visible first line. */
6052 if (w->vscroll)
6053 XSETINT (arg, XINT (arg) + 1);
6055 return Fvertical_motion (arg, window, Qnil);
6060 /***********************************************************************
6061 Window Configuration
6062 ***********************************************************************/
6064 struct save_window_data
6066 struct vectorlike_header header;
6067 Lisp_Object selected_frame;
6068 Lisp_Object current_window;
6069 Lisp_Object current_buffer;
6070 Lisp_Object minibuf_scroll_window;
6071 Lisp_Object minibuf_selected_window;
6072 Lisp_Object root_window;
6073 Lisp_Object focus_frame;
6074 /* A vector, each of whose elements is a struct saved_window
6075 for one window. */
6076 Lisp_Object saved_windows;
6078 /* All fields above are traced by the GC.
6079 From `frame-cols' down, the fields are ignored by the GC. */
6080 /* We should be able to do without the following two. */
6081 int frame_cols, frame_lines;
6082 /* These two should get eventually replaced by their pixel
6083 counterparts. */
6084 int frame_menu_bar_lines, frame_tool_bar_lines;
6085 int frame_text_width, frame_text_height;
6086 /* These are currently unused. We need them as soon as we convert
6087 to pixels. */
6088 int frame_menu_bar_height, frame_tool_bar_height;
6091 /* This is saved as a Lisp_Vector. */
6092 struct saved_window
6094 struct vectorlike_header header;
6096 Lisp_Object window, buffer, start, pointm, old_pointm;
6097 Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
6098 Lisp_Object left_col, top_line, total_cols, total_lines;
6099 Lisp_Object normal_cols, normal_lines;
6100 Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll;
6101 Lisp_Object parent, prev;
6102 Lisp_Object start_at_line_beg;
6103 Lisp_Object display_table;
6104 Lisp_Object left_margin_cols, right_margin_cols;
6105 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
6106 Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
6107 Lisp_Object scroll_bar_height, horizontal_scroll_bar_type;
6108 Lisp_Object combination_limit, window_parameters;
6111 #define SAVED_WINDOW_N(swv,n) \
6112 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
6114 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
6115 doc: /* Return t if OBJECT is a window-configuration object. */)
6116 (Lisp_Object object)
6118 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
6121 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
6122 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
6123 (Lisp_Object config)
6125 register struct save_window_data *data;
6126 struct Lisp_Vector *saved_windows;
6128 CHECK_WINDOW_CONFIGURATION (config);
6130 data = (struct save_window_data *) XVECTOR (config);
6131 saved_windows = XVECTOR (data->saved_windows);
6132 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6135 DEFUN ("set-window-configuration", Fset_window_configuration,
6136 Sset_window_configuration, 1, 1, 0,
6137 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
6138 CONFIGURATION must be a value previously returned
6139 by `current-window-configuration' (which see).
6140 If CONFIGURATION was made from a frame that is now deleted,
6141 only frame-independent values can be restored. In this case,
6142 the return value is nil. Otherwise the value is t. */)
6143 (Lisp_Object configuration)
6145 register struct save_window_data *data;
6146 struct Lisp_Vector *saved_windows;
6147 Lisp_Object new_current_buffer;
6148 Lisp_Object frame;
6149 struct frame *f;
6150 ptrdiff_t old_point = -1;
6151 USE_SAFE_ALLOCA;
6153 CHECK_WINDOW_CONFIGURATION (configuration);
6155 data = (struct save_window_data *) XVECTOR (configuration);
6156 saved_windows = XVECTOR (data->saved_windows);
6158 new_current_buffer = data->current_buffer;
6159 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
6160 new_current_buffer = Qnil;
6161 else
6163 if (XBUFFER (new_current_buffer) == current_buffer)
6164 /* The code further down "preserves point" by saving here PT in
6165 old_point and then setting it later back into PT. When the
6166 current-selected-window and the final-selected-window both show
6167 the current buffer, this suffers from the problem that the
6168 current PT is the window-point of the current-selected-window,
6169 while the final PT is the point of the final-selected-window, so
6170 this copy from one PT to the other would end up moving the
6171 window-point of the final-selected-window to the window-point of
6172 the current-selected-window. So we have to be careful which
6173 point of the current-buffer we copy into old_point. */
6174 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
6175 && WINDOWP (selected_window)
6176 && EQ (XWINDOW (selected_window)->contents, new_current_buffer)
6177 && !EQ (selected_window, data->current_window))
6178 old_point = marker_position (XWINDOW (data->current_window)->pointm);
6179 else
6180 old_point = PT;
6181 else
6182 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6183 point in new_current_buffer as of the last time this buffer was
6184 used. This can be non-deterministic since it can be changed by
6185 things like jit-lock by mere temporary selection of some random
6186 window that happens to show this buffer.
6187 So if possible we want this arbitrary choice of "which point" to
6188 be the one from the to-be-selected-window so as to prevent this
6189 window's cursor from being copied from another window. */
6190 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
6191 /* If current_window = selected_window, its point is in BUF_PT. */
6192 && !EQ (selected_window, data->current_window))
6193 old_point = marker_position (XWINDOW (data->current_window)->pointm);
6194 else
6195 old_point = BUF_PT (XBUFFER (new_current_buffer));
6198 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6199 f = XFRAME (frame);
6201 /* If f is a dead frame, don't bother rebuilding its window tree.
6202 However, there is other stuff we should still try to do below. */
6203 if (FRAME_LIVE_P (f))
6205 Lisp_Object window;
6206 Lisp_Object dead_windows = Qnil;
6207 register Lisp_Object tem, par, pers;
6208 register struct window *w;
6209 register struct saved_window *p;
6210 struct window *root_window;
6211 struct window **leaf_windows;
6212 int n_leaf_windows;
6213 ptrdiff_t k;
6214 int i, n;
6216 /* Don't do this within the main loop below: This may call Lisp
6217 code and is thus potentially unsafe while input is blocked. */
6218 for (k = 0; k < saved_windows->header.size; k++)
6220 p = SAVED_WINDOW_N (saved_windows, k);
6221 window = p->window;
6222 w = XWINDOW (window);
6223 if (BUFFERP (w->contents)
6224 && !EQ (w->contents, p->buffer)
6225 && BUFFER_LIVE_P (XBUFFER (p->buffer)))
6226 /* If a window we restore gets another buffer, record the
6227 window's old buffer. */
6228 call1 (Qrecord_window_buffer, window);
6231 /* Disallow x_set_window_size, temporarily. */
6232 f->can_x_set_window_size = false;
6233 /* The mouse highlighting code could get screwed up
6234 if it runs during this. */
6235 block_input ();
6237 /* "Swap out" point from the selected window's buffer
6238 into the window itself. (Normally the pointm of the selected
6239 window holds garbage.) We do this now, before
6240 restoring the window contents, and prevent it from
6241 being done later on when we select a new window. */
6242 if (! NILP (XWINDOW (selected_window)->contents))
6244 w = XWINDOW (selected_window);
6245 set_marker_both (w->pointm,
6246 w->contents,
6247 BUF_PT (XBUFFER (w->contents)),
6248 BUF_PT_BYTE (XBUFFER (w->contents)));
6251 fset_redisplay (f);
6252 FRAME_WINDOW_SIZES_CHANGED (f) = true;
6254 /* Problem: Freeing all matrices and later allocating them again
6255 is a serious redisplay flickering problem. What we would
6256 really like to do is to free only those matrices not reused
6257 below. */
6258 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6259 int nwindows = count_windows (root_window);
6260 SAFE_NALLOCA (leaf_windows, 1, nwindows);
6261 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6263 /* Kludge Alert!
6264 Mark all windows now on frame as "deleted".
6265 Restoring the new configuration "undeletes" any that are in it.
6267 Save their current buffers in their height fields, since we may
6268 need it later, if a buffer saved in the configuration is now
6269 dead. */
6270 delete_all_child_windows (FRAME_ROOT_WINDOW (f));
6272 for (k = 0; k < saved_windows->header.size; k++)
6274 p = SAVED_WINDOW_N (saved_windows, k);
6275 window = p->window;
6276 w = XWINDOW (window);
6277 wset_next (w, Qnil);
6279 if (!NILP (p->parent))
6280 wset_parent
6281 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window);
6282 else
6283 wset_parent (w, Qnil);
6285 if (!NILP (p->prev))
6287 wset_prev
6288 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window);
6289 wset_next (XWINDOW (w->prev), p->window);
6291 else
6293 wset_prev (w, Qnil);
6294 if (!NILP (w->parent))
6295 wset_combination (XWINDOW (w->parent),
6296 (XINT (p->total_cols)
6297 != XWINDOW (w->parent)->total_cols),
6298 p->window);
6301 /* If we squirreled away the buffer, restore it now. */
6302 if (BUFFERP (w->combination_limit))
6303 wset_buffer (w, w->combination_limit);
6304 w->pixel_left = XFASTINT (p->pixel_left);
6305 w->pixel_top = XFASTINT (p->pixel_top);
6306 w->pixel_width = XFASTINT (p->pixel_width);
6307 w->pixel_height = XFASTINT (p->pixel_height);
6308 w->left_col = XFASTINT (p->left_col);
6309 w->top_line = XFASTINT (p->top_line);
6310 w->total_cols = XFASTINT (p->total_cols);
6311 w->total_lines = XFASTINT (p->total_lines);
6312 wset_normal_cols (w, p->normal_cols);
6313 wset_normal_lines (w, p->normal_lines);
6314 w->hscroll = XFASTINT (p->hscroll);
6315 w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll);
6316 w->min_hscroll = XFASTINT (p->min_hscroll);
6317 w->hscroll_whole = XFASTINT (p->hscroll_whole);
6318 wset_display_table (w, p->display_table);
6319 w->left_margin_cols = XINT (p->left_margin_cols);
6320 w->right_margin_cols = XINT (p->right_margin_cols);
6321 w->left_fringe_width = XINT (p->left_fringe_width);
6322 w->right_fringe_width = XINT (p->right_fringe_width);
6323 w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
6324 w->scroll_bar_width = XINT (p->scroll_bar_width);
6325 w->scroll_bar_height = XINT (p->scroll_bar_height);
6326 wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
6327 wset_horizontal_scroll_bar_type (w, p->horizontal_scroll_bar_type);
6328 wset_dedicated (w, p->dedicated);
6329 wset_combination_limit (w, p->combination_limit);
6330 /* Restore any window parameters that have been saved.
6331 Parameters that have not been saved are left alone. */
6332 for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
6334 pers = XCAR (tem);
6335 if (CONSP (pers))
6337 if (NILP (XCDR (pers)))
6339 par = Fassq (XCAR (pers), w->window_parameters);
6340 if (CONSP (par) && !NILP (XCDR (par)))
6341 /* Reset a parameter to nil if and only if it
6342 has a non-nil association. Don't make new
6343 associations. */
6344 Fsetcdr (par, Qnil);
6346 else
6347 /* Always restore a non-nil value. */
6348 Fset_window_parameter (window, XCAR (pers), XCDR (pers));
6352 if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
6353 /* If saved buffer is alive, install it. */
6355 wset_buffer (w, p->buffer);
6356 w->start_at_line_beg = !NILP (p->start_at_line_beg);
6357 set_marker_restricted (w->start, p->start, w->contents);
6358 set_marker_restricted (w->pointm, p->pointm, w->contents);
6359 set_marker_restricted (w->old_pointm, p->old_pointm, w->contents);
6360 /* As documented in Fcurrent_window_configuration, don't
6361 restore the location of point in the buffer which was
6362 current when the window configuration was recorded. */
6363 if (!EQ (p->buffer, new_current_buffer)
6364 && XBUFFER (p->buffer) == current_buffer)
6365 Fgoto_char (w->pointm);
6367 else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
6368 /* Keep window's old buffer; make sure the markers are real. */
6370 /* Set window markers at start of visible range. */
6371 if (XMARKER (w->start)->buffer == 0)
6372 set_marker_restricted_both (w->start, w->contents, 0, 0);
6373 if (XMARKER (w->pointm)->buffer == 0)
6374 set_marker_restricted_both
6375 (w->pointm, w->contents,
6376 BUF_PT (XBUFFER (w->contents)),
6377 BUF_PT_BYTE (XBUFFER (w->contents)));
6378 if (XMARKER (w->old_pointm)->buffer == 0)
6379 set_marker_restricted_both
6380 (w->old_pointm, w->contents,
6381 BUF_PT (XBUFFER (w->contents)),
6382 BUF_PT_BYTE (XBUFFER (w->contents)));
6383 w->start_at_line_beg = true;
6385 else if (!NILP (w->start))
6386 /* Leaf window has no live buffer, get one. */
6388 /* Get the buffer via other_buffer_safely in order to
6389 avoid showing an unimportant buffer and, if necessary, to
6390 recreate *scratch* in the course (part of Juanma's bs-show
6391 scenario from March 2011). */
6392 wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
6393 /* This will set the markers to beginning of visible
6394 range. */
6395 set_marker_restricted_both (w->start, w->contents, 0, 0);
6396 set_marker_restricted_both (w->pointm, w->contents, 0, 0);
6397 set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
6398 w->start_at_line_beg = true;
6399 if (!NILP (w->dedicated))
6400 /* Record this window as dead. */
6401 dead_windows = Fcons (window, dead_windows);
6402 /* Make sure window is no more dedicated. */
6403 wset_dedicated (w, Qnil);
6407 fset_root_window (f, data->root_window);
6408 /* Arrange *not* to restore point in the buffer that was
6409 current when the window configuration was saved. */
6410 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
6411 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6412 make_number (old_point),
6413 XWINDOW (data->current_window)->contents);
6415 /* In the following call to `select-window', prevent "swapping out
6416 point" in the old selected window using the buffer that has
6417 been restored into it. We already swapped out that point from
6418 that window's old buffer.
6420 Do not record the buffer here. We do that in a separate call
6421 to select_window below. See also Bug#16207. */
6422 select_window (data->current_window, Qt, true);
6423 BVAR (XBUFFER (XWINDOW (selected_window)->contents),
6424 last_selected_window)
6425 = selected_window;
6427 if (NILP (data->focus_frame)
6428 || (FRAMEP (data->focus_frame)
6429 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6430 Fredirect_frame_focus (frame, data->focus_frame);
6432 /* Now, free glyph matrices in windows that were not reused. */
6433 for (i = n = 0; i < n_leaf_windows; ++i)
6435 if (NILP (leaf_windows[i]->contents))
6436 free_window_matrices (leaf_windows[i]);
6437 else if (EQ (leaf_windows[i]->contents, new_current_buffer))
6438 ++n;
6441 /* Allow x_set_window_size again and apply frame size changes if
6442 needed. */
6443 f->can_x_set_window_size = true;
6444 adjust_frame_size (f, -1, -1, 1, false, Qset_window_configuration);
6446 adjust_frame_glyphs (f);
6447 unblock_input ();
6449 /* Scan dead buffer windows. */
6450 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
6452 window = XCAR (dead_windows);
6453 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
6454 delete_deletable_window (window);
6457 /* Record the selected window's buffer here. The window should
6458 already be the selected one from the call above. */
6459 select_window (data->current_window, Qnil, false);
6461 /* Fselect_window will have made f the selected frame, so we
6462 reselect the proper frame here. Fhandle_switch_frame will change the
6463 selected window too, but that doesn't make the call to
6464 Fselect_window above totally superfluous; it still sets f's
6465 selected window. */
6466 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6467 do_switch_frame (data->selected_frame, 0, 0, Qnil);
6469 run_window_configuration_change_hook (f);
6472 if (!NILP (new_current_buffer))
6474 Fset_buffer (new_current_buffer);
6475 /* If the new current buffer doesn't appear in the selected
6476 window, go to its old point (see bug#12208). */
6477 if (!EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
6478 Fgoto_char (make_number (old_point));
6481 Vminibuf_scroll_window = data->minibuf_scroll_window;
6482 minibuf_selected_window = data->minibuf_selected_window;
6484 SAFE_FREE ();
6485 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6489 void
6490 restore_window_configuration (Lisp_Object configuration)
6492 Fset_window_configuration (configuration);
6496 /* If WINDOW is an internal window, recursively delete all child windows
6497 reachable via the next and contents slots of WINDOW. Otherwise setup
6498 WINDOW to not show any buffer. */
6500 void
6501 delete_all_child_windows (Lisp_Object window)
6503 register struct window *w;
6505 w = XWINDOW (window);
6507 if (!NILP (w->next))
6508 /* Delete WINDOW's siblings (we traverse postorderly). */
6509 delete_all_child_windows (w->next);
6511 if (WINDOWP (w->contents))
6513 delete_all_child_windows (w->contents);
6514 wset_combination (w, false, Qnil);
6516 else if (BUFFERP (w->contents))
6518 unshow_buffer (w);
6519 unchain_marker (XMARKER (w->pointm));
6520 unchain_marker (XMARKER (w->old_pointm));
6521 unchain_marker (XMARKER (w->start));
6522 /* Since combination limit makes sense for an internal windows
6523 only, we use this slot to save the buffer for the sake of
6524 possible resurrection in Fset_window_configuration. */
6525 wset_combination_limit (w, w->contents);
6526 wset_buffer (w, Qnil);
6529 Vwindow_list = Qnil;
6532 static int
6533 count_windows (register struct window *window)
6535 register int count = 1;
6536 if (!NILP (window->next))
6537 count += count_windows (XWINDOW (window->next));
6538 if (WINDOWP (window->contents))
6539 count += count_windows (XWINDOW (window->contents));
6540 return count;
6544 /* Fill vector FLAT with leaf windows under W, starting at index I.
6545 Value is last index + 1. */
6546 static int
6547 get_leaf_windows (struct window *w, struct window **flat, int i)
6549 while (w)
6551 if (WINDOWP (w->contents))
6552 i = get_leaf_windows (XWINDOW (w->contents), flat, i);
6553 else
6554 flat[i++] = w;
6556 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6559 return i;
6563 /* Return a pointer to the glyph W's physical cursor is on. Value is
6564 null if W's current matrix is invalid, so that no meaningful glyph
6565 can be returned. */
6566 struct glyph *
6567 get_phys_cursor_glyph (struct window *w)
6569 struct glyph_row *row;
6570 struct glyph *glyph;
6571 int hpos = w->phys_cursor.hpos;
6573 if (!(w->phys_cursor.vpos >= 0
6574 && w->phys_cursor.vpos < w->current_matrix->nrows))
6575 return NULL;
6577 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
6578 if (!row->enabled_p)
6579 return NULL;
6581 if (w->hscroll)
6583 /* When the window is hscrolled, cursor hpos can legitimately be
6584 out of bounds, but we draw the cursor at the corresponding
6585 window margin in that case. */
6586 if (!row->reversed_p && hpos < 0)
6587 hpos = 0;
6588 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
6589 hpos = row->used[TEXT_AREA] - 1;
6592 if (0 <= hpos && hpos < row->used[TEXT_AREA])
6593 glyph = row->glyphs[TEXT_AREA] + hpos;
6594 else
6595 glyph = NULL;
6597 return glyph;
6601 static int
6602 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
6604 register struct saved_window *p;
6605 register struct window *w;
6606 register Lisp_Object tem, pers, par;
6608 for (; !NILP (window); window = w->next)
6610 p = SAVED_WINDOW_N (vector, i);
6611 w = XWINDOW (window);
6613 wset_temslot (w, make_number (i)); i++;
6614 p->window = window;
6615 p->buffer = (WINDOW_LEAF_P (w) ? w->contents : Qnil);
6616 p->pixel_left = make_number (w->pixel_left);
6617 p->pixel_top = make_number (w->pixel_top);
6618 p->pixel_width = make_number (w->pixel_width);
6619 p->pixel_height = make_number (w->pixel_height);
6620 p->left_col = make_number (w->left_col);
6621 p->top_line = make_number (w->top_line);
6622 p->total_cols = make_number (w->total_cols);
6623 p->total_lines = make_number (w->total_lines);
6624 p->normal_cols = w->normal_cols;
6625 p->normal_lines = w->normal_lines;
6626 XSETFASTINT (p->hscroll, w->hscroll);
6627 p->suspend_auto_hscroll = w->suspend_auto_hscroll ? Qt : Qnil;
6628 XSETFASTINT (p->min_hscroll, w->min_hscroll);
6629 XSETFASTINT (p->hscroll_whole, w->hscroll_whole);
6630 p->display_table = w->display_table;
6631 p->left_margin_cols = make_number (w->left_margin_cols);
6632 p->right_margin_cols = make_number (w->right_margin_cols);
6633 p->left_fringe_width = make_number (w->left_fringe_width);
6634 p->right_fringe_width = make_number (w->right_fringe_width);
6635 p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
6636 p->scroll_bar_width = make_number (w->scroll_bar_width);
6637 p->scroll_bar_height = make_number (w->scroll_bar_height);
6638 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6639 p->horizontal_scroll_bar_type = w->horizontal_scroll_bar_type;
6640 p->dedicated = w->dedicated;
6641 p->combination_limit = w->combination_limit;
6642 p->window_parameters = Qnil;
6644 if (!NILP (Vwindow_persistent_parameters))
6646 /* Run cycle detection on Vwindow_persistent_parameters. */
6647 Lisp_Object tortoise, hare;
6649 hare = tortoise = Vwindow_persistent_parameters;
6650 while (CONSP (hare))
6652 hare = XCDR (hare);
6653 if (!CONSP (hare))
6654 break;
6656 hare = XCDR (hare);
6657 tortoise = XCDR (tortoise);
6659 if (EQ (hare, tortoise))
6660 /* Reset Vwindow_persistent_parameters to Qnil. */
6662 Vwindow_persistent_parameters = Qnil;
6663 break;
6667 for (tem = Vwindow_persistent_parameters; CONSP (tem);
6668 tem = XCDR (tem))
6670 pers = XCAR (tem);
6671 /* Save values for persistent window parameters. */
6672 if (CONSP (pers) && !NILP (XCDR (pers)))
6674 par = Fassq (XCAR (pers), w->window_parameters);
6675 if (NILP (par))
6676 /* If the window has no value for the parameter,
6677 make one. */
6678 p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
6679 p->window_parameters);
6680 else
6681 /* If the window has a value for the parameter,
6682 save it. */
6683 p->window_parameters = Fcons (Fcons (XCAR (par),
6684 XCDR (par)),
6685 p->window_parameters);
6690 if (BUFFERP (w->contents))
6692 /* Save w's value of point in the window configuration. If w
6693 is the selected window, then get the value of point from
6694 the buffer; pointm is garbage in the selected window. */
6695 if (EQ (window, selected_window))
6696 p->pointm = build_marker (XBUFFER (w->contents),
6697 BUF_PT (XBUFFER (w->contents)),
6698 BUF_PT_BYTE (XBUFFER (w->contents)));
6699 else
6700 p->pointm = Fcopy_marker (w->pointm, Qnil);
6701 p->old_pointm = Fcopy_marker (w->old_pointm, Qnil);
6702 XMARKER (p->pointm)->insertion_type
6703 = !NILP (buffer_local_value /* Don't signal error if void. */
6704 (Qwindow_point_insertion_type, w->contents));
6705 XMARKER (p->old_pointm)->insertion_type
6706 = !NILP (buffer_local_value /* Don't signal error if void. */
6707 (Qwindow_point_insertion_type, w->contents));
6709 p->start = Fcopy_marker (w->start, Qnil);
6710 p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
6712 else
6714 p->pointm = Qnil;
6715 p->old_pointm = Qnil;
6716 p->start = Qnil;
6717 p->start_at_line_beg = Qnil;
6720 p->parent = NILP (w->parent) ? Qnil : XWINDOW (w->parent)->temslot;
6721 p->prev = NILP (w->prev) ? Qnil : XWINDOW (w->prev)->temslot;
6723 if (WINDOWP (w->contents))
6724 i = save_window_save (w->contents, vector, i);
6727 return i;
6730 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6731 Scurrent_window_configuration, 0, 1, 0,
6732 doc: /* Return an object representing the current window configuration of FRAME.
6733 If FRAME is nil or omitted, use the selected frame.
6734 This describes the number of windows, their sizes and current buffers,
6735 and for each displayed buffer, where display starts, and the position of
6736 point. An exception is made for point in the current buffer:
6737 its value is -not- saved.
6738 This also records the currently selected frame, and FRAME's focus
6739 redirection (see `redirect-frame-focus'). The variable
6740 `window-persistent-parameters' specifies which window parameters are
6741 saved by this function. */)
6742 (Lisp_Object frame)
6744 register Lisp_Object tem;
6745 register int n_windows;
6746 register struct save_window_data *data;
6747 register int i;
6748 struct frame *f = decode_live_frame (frame);
6750 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6751 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6752 PVEC_WINDOW_CONFIGURATION);
6754 data->frame_cols = FRAME_COLS (f);
6755 data->frame_lines = FRAME_LINES (f);
6756 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6757 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6758 data->frame_text_width = FRAME_TEXT_WIDTH (f);
6759 data->frame_text_height = FRAME_TEXT_HEIGHT (f);
6760 data->frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
6761 data->frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
6762 data->selected_frame = selected_frame;
6763 data->current_window = FRAME_SELECTED_WINDOW (f);
6764 XSETBUFFER (data->current_buffer, current_buffer);
6765 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6766 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6767 data->root_window = FRAME_ROOT_WINDOW (f);
6768 data->focus_frame = FRAME_FOCUS_FRAME (f);
6769 tem = make_uninit_vector (n_windows);
6770 data->saved_windows = tem;
6771 for (i = 0; i < n_windows; i++)
6772 ASET (tem, i,
6773 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil));
6774 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6775 XSETWINDOW_CONFIGURATION (tem, data);
6776 return (tem);
6779 /* Called after W's margins, fringes or scroll bars was adjusted. */
6781 static void
6782 apply_window_adjustment (struct window *w)
6784 eassert (w);
6785 clear_glyph_matrix (w->current_matrix);
6786 w->window_end_valid = false;
6787 windows_or_buffers_changed = 30;
6788 wset_redisplay (w);
6789 adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
6793 /***********************************************************************
6794 Marginal Areas
6795 ***********************************************************************/
6797 static struct window *
6798 set_window_margins (struct window *w, Lisp_Object left_width,
6799 Lisp_Object right_width)
6801 int left, right;
6802 int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
6804 left = (NILP (left_width) ? 0
6805 : (CHECK_NATNUM (left_width), XINT (left_width)));
6806 right = (NILP (right_width) ? 0
6807 : (CHECK_NATNUM (right_width), XINT (right_width)));
6809 if (w->left_margin_cols != left || w->right_margin_cols != right)
6811 /* Don't change anything if new margins won't fit. */
6812 if ((WINDOW_PIXEL_WIDTH (w)
6813 - WINDOW_FRINGES_WIDTH (w)
6814 - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
6815 - (left + right) * unit)
6816 >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
6818 w->left_margin_cols = left;
6819 w->right_margin_cols = right;
6821 return w;
6823 else
6824 return NULL;
6826 else
6827 return NULL;
6830 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6831 2, 3, 0,
6832 doc: /* Set width of marginal areas of window WINDOW.
6833 WINDOW must be a live window and defaults to the selected one.
6835 Second arg LEFT-WIDTH specifies the number of character cells to
6836 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6837 does the same for the right marginal area. A nil width parameter
6838 means no margin.
6840 Return t if any margin was actually changed and nil otherwise. */)
6841 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6843 struct window *w = set_window_margins (decode_live_window (window),
6844 left_width, right_width);
6845 return w ? (apply_window_adjustment (w), Qt) : Qnil;
6849 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6850 0, 1, 0,
6851 doc: /* Get width of marginal areas of window WINDOW.
6852 WINDOW must be a live window and defaults to the selected one.
6854 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6855 If a marginal area does not exist, its width will be returned
6856 as nil. */)
6857 (Lisp_Object window)
6859 struct window *w = decode_live_window (window);
6860 return Fcons (w->left_margin_cols
6861 ? make_number (w->left_margin_cols) : Qnil,
6862 w->right_margin_cols
6863 ? make_number (w->right_margin_cols) : Qnil);
6868 /***********************************************************************
6869 Fringes
6870 ***********************************************************************/
6872 static struct window *
6873 set_window_fringes (struct window *w, Lisp_Object left_width,
6874 Lisp_Object right_width, Lisp_Object outside_margins)
6876 int left, right;
6877 bool outside = !NILP (outside_margins);
6879 left = (NILP (left_width) ? -1
6880 : (CHECK_NATNUM (left_width), XINT (left_width)));
6881 right = (NILP (right_width) ? -1
6882 : (CHECK_NATNUM (right_width), XINT (right_width)));
6884 /* Do nothing on a tty or if nothing to actually change. */
6885 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6886 && (w->left_fringe_width != left
6887 || w->right_fringe_width != right
6888 || w->fringes_outside_margins != outside))
6890 if (left > 0 || right > 0)
6892 /* Don't change anything if new fringes don't fit. */
6893 if ((WINDOW_PIXEL_WIDTH (w)
6894 - WINDOW_MARGINS_WIDTH (w)
6895 - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
6896 - max (left, 0) - max (right, 0))
6897 < MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
6898 return NULL;
6901 w->left_fringe_width = left;
6902 w->right_fringe_width = right;
6903 w->fringes_outside_margins = outside;
6905 return w;
6907 else
6908 return NULL;
6911 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6912 2, 4, 0,
6913 doc: /* Set the fringe widths of window WINDOW.
6914 WINDOW must be a live window and defaults to the selected one.
6916 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6917 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6918 fringe width. If a fringe width arg is nil, that means to use the
6919 frame's default fringe width. Default fringe widths can be set with
6920 the command `set-fringe-style'.
6921 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6922 outside of the display margins. By default, fringes are drawn between
6923 display marginal areas and the text area.
6925 Return t if any fringe was actually changed and nil otherwise. */)
6926 (Lisp_Object window, Lisp_Object left_width,
6927 Lisp_Object right_width, Lisp_Object outside_margins)
6929 struct window *w
6930 = set_window_fringes (decode_live_window (window),
6931 left_width, right_width, outside_margins);
6932 return w ? (apply_window_adjustment (w), Qt) : Qnil;
6936 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6937 0, 1, 0,
6938 doc: /* Get width of fringes of window WINDOW.
6939 WINDOW must be a live window and defaults to the selected one.
6941 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6942 (Lisp_Object window)
6944 struct window *w = decode_live_window (window);
6946 return list3 (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6947 make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6948 WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil);
6953 /***********************************************************************
6954 Scroll bars
6955 ***********************************************************************/
6957 static struct window *
6958 set_window_scroll_bars (struct window *w, Lisp_Object width,
6959 Lisp_Object vertical_type, Lisp_Object height,
6960 Lisp_Object horizontal_type)
6962 int iwidth = (NILP (width) ? -1 : (CHECK_NATNUM (width), XINT (width)));
6963 bool changed = false;
6965 if (iwidth == 0)
6966 vertical_type = Qnil;
6968 if (!(NILP (vertical_type)
6969 || EQ (vertical_type, Qleft)
6970 || EQ (vertical_type, Qright)
6971 || EQ (vertical_type, Qt)))
6972 error ("Invalid type of vertical scroll bar");
6974 if (w->scroll_bar_width != iwidth
6975 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6977 /* Don't change anything if new scroll bar won't fit. */
6978 if ((WINDOW_PIXEL_WIDTH (w)
6979 - WINDOW_MARGINS_WIDTH (w)
6980 - WINDOW_FRINGES_WIDTH (w)
6981 - max (iwidth, 0))
6982 >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
6984 w->scroll_bar_width = iwidth;
6985 wset_vertical_scroll_bar_type (w, vertical_type);
6986 changed = true;
6990 #if USE_HORIZONTAL_SCROLL_BARS
6992 int iheight = (NILP (height) ? -1 : (CHECK_NATNUM (height), XINT (height)));
6994 if (MINI_WINDOW_P (w) || iheight == 0)
6995 horizontal_type = Qnil;
6997 if (!(NILP (horizontal_type)
6998 || EQ (horizontal_type, Qbottom)
6999 || EQ (horizontal_type, Qt)))
7000 error ("Invalid type of horizontal scroll bar");
7002 if (w->scroll_bar_height != iheight
7003 || !EQ (w->horizontal_scroll_bar_type, horizontal_type))
7005 /* Don't change anything if new scroll bar won't fit. */
7006 if ((WINDOW_PIXEL_HEIGHT (w)
7007 - WINDOW_HEADER_LINE_HEIGHT (w)
7008 - WINDOW_MODE_LINE_HEIGHT (w)
7009 - max (iheight, 0))
7010 >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w))
7012 w->scroll_bar_height = iheight;
7013 wset_horizontal_scroll_bar_type (w, horizontal_type);
7014 changed = true;
7018 #else
7019 wset_horizontal_scroll_bar_type (w, Qnil);
7020 #endif
7022 return changed ? w : NULL;
7025 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
7026 Sset_window_scroll_bars, 1, 5, 0,
7027 doc: /* Set width and type of scroll bars of window WINDOW.
7028 WINDOW must be a live window and defaults to the selected one.
7030 Second parameter WIDTH specifies the pixel width for the vertical scroll
7031 bar. If WIDTH is nil, use the scroll-bar width of WINDOW's frame.
7032 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
7033 bar: left, right, or nil. If VERTICAL-TYPE is t, this means use the
7034 frame's scroll-bar type.
7036 Fourth parameter HEIGHT specifies the pixel height for the horizontal
7037 scroll bar. If HEIGHT is nil, use the scroll-bar height of WINDOW's
7038 frame. Fifth parameter HORIZONTAL-TYPE specifies the type of the
7039 horizontal scroll bar: nil, bottom, or t. If HORIZONTAL-TYPE is t, this
7040 means to use the frame's horizontal scroll-bar type.
7042 Return t if scroll bars were actually changed and nil otherwise. */)
7043 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type,
7044 Lisp_Object height, Lisp_Object horizontal_type)
7046 struct window *w
7047 = set_window_scroll_bars (decode_live_window (window),
7048 width, vertical_type, height, horizontal_type);
7049 return w ? (apply_window_adjustment (w), Qt) : Qnil;
7053 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
7054 0, 1, 0,
7055 doc: /* Get width and type of scroll bars of window WINDOW.
7056 WINDOW must be a live window and defaults to the selected one.
7058 Value is a list of the form (WIDTH COLUMNS VERTICAL-TYPE HEIGHT LINES
7059 HORIZONTAL-TYPE). If WIDTH or HEIGHT is nil or VERTICAL-TYPE or
7060 HORIZONTAL-TYPE is t, the window is using the frame's corresponding
7061 value. */)
7062 (Lisp_Object window)
7064 struct window *w = decode_live_window (window);
7066 return Fcons (((w->scroll_bar_width >= 0)
7067 ? make_number (w->scroll_bar_width)
7068 : Qnil),
7069 list5 (make_number (WINDOW_SCROLL_BAR_COLS (w)),
7070 w->vertical_scroll_bar_type,
7071 ((w->scroll_bar_height >= 0)
7072 ? make_number (w->scroll_bar_height)
7073 : Qnil),
7074 make_number (WINDOW_SCROLL_BAR_LINES (w)),
7075 w->horizontal_scroll_bar_type));
7078 /***********************************************************************
7079 Smooth scrolling
7080 ***********************************************************************/
7082 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
7083 doc: /* Return the amount by which WINDOW is scrolled vertically.
7084 If WINDOW is omitted or nil, it defaults to the selected window.
7085 Normally, value is a multiple of the canonical character height of WINDOW;
7086 optional second arg PIXELS-P means value is measured in pixels. */)
7087 (Lisp_Object window, Lisp_Object pixels_p)
7089 Lisp_Object result;
7090 struct window *w = decode_live_window (window);
7091 struct frame *f = XFRAME (w->frame);
7093 if (FRAME_WINDOW_P (f))
7094 result = (NILP (pixels_p)
7095 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
7096 : make_number (-w->vscroll));
7097 else
7098 result = make_number (0);
7099 return result;
7103 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
7104 2, 3, 0,
7105 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
7106 WINDOW nil means use the selected window. Normally, VSCROLL is a
7107 non-negative multiple of the canonical character height of WINDOW;
7108 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
7109 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
7110 corresponds to an integral number of pixels. The return value is the
7111 result of this rounding.
7112 If PIXELS-P is non-nil, the return value is VSCROLL. */)
7113 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
7115 struct window *w = decode_live_window (window);
7116 struct frame *f = XFRAME (w->frame);
7118 CHECK_NUMBER_OR_FLOAT (vscroll);
7120 if (FRAME_WINDOW_P (f))
7122 int old_dy = w->vscroll;
7124 w->vscroll = - (NILP (pixels_p)
7125 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
7126 : XFLOATINT (vscroll));
7127 w->vscroll = min (w->vscroll, 0);
7129 if (w->vscroll != old_dy)
7131 /* Adjust glyph matrix of the frame if the virtual display
7132 area becomes larger than before. */
7133 if (w->vscroll < 0 && w->vscroll < old_dy)
7134 adjust_frame_glyphs (f);
7136 /* Prevent redisplay shortcuts. */
7137 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
7141 return Fwindow_vscroll (window, pixels_p);
7145 /* Call FN for all leaf windows on frame F. FN is called with the
7146 first argument being a pointer to the leaf window, and with
7147 additional argument USER_DATA. Stops when FN returns 0. */
7149 static void
7150 foreach_window (struct frame *f, bool (*fn) (struct window *, void *),
7151 void *user_data)
7153 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
7154 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
7155 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
7159 /* Helper function for foreach_window. Call FN for all leaf windows
7160 reachable from W. FN is called with the first argument being a
7161 pointer to the leaf window, and with additional argument USER_DATA.
7162 Stop when FN returns false. Value is false if stopped by FN. */
7164 static bool
7165 foreach_window_1 (struct window *w, bool (*fn) (struct window *, void *),
7166 void *user_data)
7168 bool cont;
7170 for (cont = true; w && cont;)
7172 if (WINDOWP (w->contents))
7173 cont = foreach_window_1 (XWINDOW (w->contents), fn, user_data);
7174 else
7175 cont = fn (w, user_data);
7177 w = NILP (w->next) ? 0 : XWINDOW (w->next);
7180 return cont;
7183 /***********************************************************************
7184 Initialization
7185 ***********************************************************************/
7187 /* Return true if window configurations CONFIGURATION1 and CONFIGURATION2
7188 describe the same state of affairs. This is used by Fequal.
7190 IGNORE_POSITIONS means ignore non-matching scroll positions
7191 and the like.
7193 This ignores a couple of things like the dedication status of
7194 window, combination_limit and the like. This might have to be
7195 fixed. */
7197 bool
7198 compare_window_configurations (Lisp_Object configuration1,
7199 Lisp_Object configuration2,
7200 bool ignore_positions)
7202 register struct save_window_data *d1, *d2;
7203 struct Lisp_Vector *sws1, *sws2;
7204 ptrdiff_t i;
7206 CHECK_WINDOW_CONFIGURATION (configuration1);
7207 CHECK_WINDOW_CONFIGURATION (configuration2);
7209 d1 = (struct save_window_data *) XVECTOR (configuration1);
7210 d2 = (struct save_window_data *) XVECTOR (configuration2);
7211 sws1 = XVECTOR (d1->saved_windows);
7212 sws2 = XVECTOR (d2->saved_windows);
7214 /* Frame settings must match. */
7215 if (d1->frame_cols != d2->frame_cols
7216 || d1->frame_lines != d2->frame_lines
7217 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
7218 || !EQ (d1->selected_frame, d2->selected_frame)
7219 || !EQ (d1->current_buffer, d2->current_buffer)
7220 || (!ignore_positions
7221 && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
7222 || !EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)))
7223 || !EQ (d1->focus_frame, d2->focus_frame)
7224 /* Verify that the two configurations have the same number of windows. */
7225 || sws1->header.size != sws2->header.size)
7226 return false;
7228 for (i = 0; i < sws1->header.size; i++)
7230 struct saved_window *sw1, *sw2;
7232 sw1 = SAVED_WINDOW_N (sws1, i);
7233 sw2 = SAVED_WINDOW_N (sws2, i);
7235 if (
7236 /* The "current" windows in the two configurations must
7237 correspond to each other. */
7238 EQ (d1->current_window, sw1->window)
7239 != EQ (d2->current_window, sw2->window)
7240 /* Windows' buffers must match. */
7241 || !EQ (sw1->buffer, sw2->buffer)
7242 || !EQ (sw1->pixel_left, sw2->pixel_left)
7243 || !EQ (sw1->pixel_top, sw2->pixel_top)
7244 || !EQ (sw1->pixel_height, sw2->pixel_height)
7245 || !EQ (sw1->pixel_width, sw2->pixel_width)
7246 || !EQ (sw1->left_col, sw2->left_col)
7247 || !EQ (sw1->top_line, sw2->top_line)
7248 || !EQ (sw1->total_cols, sw2->total_cols)
7249 || !EQ (sw1->total_lines, sw2->total_lines)
7250 || !EQ (sw1->display_table, sw2->display_table)
7251 /* The next two disjuncts check the window structure for
7252 equality. */
7253 || !EQ (sw1->parent, sw2->parent)
7254 || !EQ (sw1->prev, sw2->prev)
7255 || (!ignore_positions
7256 && (!EQ (sw1->hscroll, sw2->hscroll)
7257 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
7258 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
7259 || NILP (Fequal (sw1->start, sw2->start))
7260 || NILP (Fequal (sw1->pointm, sw2->pointm))))
7261 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
7262 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
7263 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
7264 || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
7265 || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
7266 || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
7267 || !EQ (sw1->scroll_bar_height, sw2->scroll_bar_height)
7268 || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type)
7269 || !EQ (sw1->horizontal_scroll_bar_type, sw2->horizontal_scroll_bar_type))
7270 return false;
7273 return true;
7276 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7277 Scompare_window_configurations, 2, 2, 0,
7278 doc: /* Compare two window configurations as regards the structure of windows.
7279 This function ignores details such as the values of point
7280 and scrolling positions. */)
7281 (Lisp_Object x, Lisp_Object y)
7283 if (compare_window_configurations (x, y, true))
7284 return Qt;
7285 return Qnil;
7288 void
7289 init_window_once (void)
7291 struct frame *f = make_initial_frame ();
7292 XSETFRAME (selected_frame, f);
7293 Vterminal_frame = selected_frame;
7294 minibuf_window = f->minibuffer_window;
7295 selected_window = f->selected_window;
7298 void
7299 init_window (void)
7301 Vwindow_list = Qnil;
7304 void
7305 syms_of_window (void)
7307 DEFSYM (Qscroll_up, "scroll-up");
7308 DEFSYM (Qscroll_down, "scroll-down");
7309 DEFSYM (Qscroll_command, "scroll-command");
7311 Fput (Qscroll_up, Qscroll_command, Qt);
7312 Fput (Qscroll_down, Qscroll_command, Qt);
7314 DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
7315 DEFSYM (Qwindowp, "windowp");
7316 DEFSYM (Qwindow_configuration_p, "window-configuration-p");
7317 DEFSYM (Qwindow_live_p, "window-live-p");
7318 DEFSYM (Qwindow_valid_p, "window-valid-p");
7319 DEFSYM (Qwindow_deletable_p, "window-deletable-p");
7320 DEFSYM (Qdelete_window, "delete-window");
7321 DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
7322 DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
7323 DEFSYM (Qwindow_sanitize_window_sizes, "window--sanitize-window-sizes");
7324 DEFSYM (Qwindow_pixel_to_total, "window--pixel-to-total");
7325 DEFSYM (Qsafe, "safe");
7326 DEFSYM (Qdisplay_buffer, "display-buffer");
7327 DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
7328 DEFSYM (Qrecord_window_buffer, "record-window-buffer");
7329 DEFSYM (Qget_mru_window, "get-mru-window");
7330 DEFSYM (Qwindow_size, "window-size");
7331 DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
7332 DEFSYM (Qabove, "above");
7333 DEFSYM (Qbelow, "below");
7334 DEFSYM (Qclone_of, "clone-of");
7335 DEFSYM (Qfloor, "floor");
7336 DEFSYM (Qceiling, "ceiling");
7338 staticpro (&Vwindow_list);
7340 minibuf_selected_window = Qnil;
7341 staticpro (&minibuf_selected_window);
7343 window_scroll_pixel_based_preserve_x = -1;
7344 window_scroll_pixel_based_preserve_y = -1;
7345 window_scroll_preserve_hpos = -1;
7346 window_scroll_preserve_vpos = -1;
7348 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
7349 doc: /* Non-nil means call as function to display a help buffer.
7350 The function is called with one argument, the buffer to be displayed.
7351 Used by `with-output-to-temp-buffer'.
7352 If this function is used, then it must do the entire job of showing
7353 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7354 Vtemp_buffer_show_function = Qnil;
7356 DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
7357 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7358 Vminibuf_scroll_window = Qnil;
7360 DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
7361 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7362 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7363 is displayed in the `mode-line' face. */);
7364 mode_line_in_non_selected_windows = true;
7366 DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
7367 doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window. */);
7368 Vother_window_scroll_buffer = Qnil;
7370 DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
7371 doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7372 auto_window_vscroll_p = true;
7374 DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
7375 doc: /* Number of lines of continuity when scrolling by screenfuls. */);
7376 next_screen_context_lines = 2;
7378 DEFVAR_LISP ("scroll-preserve-screen-position",
7379 Vscroll_preserve_screen_position,
7380 doc: /* Controls if scroll commands move point to keep its screen position unchanged.
7381 A value of nil means point does not keep its screen position except
7382 at the scroll margin or window boundary respectively.
7383 A value of t means point keeps its screen position if the scroll
7384 command moved it vertically out of the window, e.g. when scrolling
7385 by full screens.
7386 Any other value means point always keeps its screen position.
7387 Scroll commands should have the `scroll-command' property
7388 on their symbols to be controlled by this variable. */);
7389 Vscroll_preserve_screen_position = Qnil;
7391 DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
7392 doc: /* Type of marker to use for `window-point'. */);
7393 Vwindow_point_insertion_type = Qnil;
7394 DEFSYM (Qwindow_point_insertion_type, "window_point_insertion_type");
7396 DEFVAR_LISP ("window-configuration-change-hook",
7397 Vwindow_configuration_change_hook,
7398 doc: /* Functions to call when window configuration changes.
7399 The buffer-local part is run once per window, with the relevant window
7400 selected; while the global part is run only once for the modified frame,
7401 with the relevant frame selected. */);
7402 Vwindow_configuration_change_hook = Qnil;
7404 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
7405 doc: /* Non-nil means `recenter' redraws entire frame.
7406 If this option is non-nil, then the `recenter' command with a nil
7407 argument will redraw the entire frame; the special value `tty' causes
7408 the frame to be redrawn only if it is a tty frame. */);
7409 Vrecenter_redisplay = Qtty;
7411 DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
7412 doc: /* If t, resize window combinations proportionally.
7413 If this variable is nil, splitting a window gets the entire screen space
7414 for displaying the new window from the window to split. Deleting and
7415 resizing a window preferably resizes one adjacent window only.
7417 If this variable is t, splitting a window tries to get the space
7418 proportionally from all windows in the same combination. This also
7419 allows to split a window that is otherwise too small or of fixed size.
7420 Resizing and deleting a window proportionally resize all windows in the
7421 same combination.
7423 Other values are reserved for future use.
7425 This variable takes no effect if the variable `window-combination-limit' is
7426 non-nil. */);
7427 Vwindow_combination_resize = Qnil;
7429 DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
7430 doc: /* If non-nil, splitting a window makes a new parent window.
7431 The following values are recognized:
7433 nil means splitting a window will create a new parent window only if the
7434 window has no parent window or the window shall become part of a
7435 combination orthogonal to the one it is part of.
7437 `window-size' means that splitting a window for displaying a buffer
7438 makes a new parent window provided `display-buffer' is supposed to
7439 explicitly set the window's size due to the presence of a
7440 `window-height' or `window-width' entry in the alist used by
7441 `display-buffer'. Otherwise, this value is handled like nil.
7443 `temp-buffer' means that splitting a window for displaying a temporary
7444 buffer always makes a new parent window. Otherwise, this value is
7445 handled like nil.
7447 `display-buffer' means that splitting a window for displaying a buffer
7448 always makes a new parent window. Since temporary buffers are
7449 displayed by the function `display-buffer', this value is stronger
7450 than `temp-buffer'. Splitting a window for other purpose makes a
7451 new parent window only if needed.
7453 t means that splitting a window always creates a new parent window. If
7454 all splits behave this way, each frame's window tree is a binary
7455 tree and every window but the frame's root window has exactly one
7456 sibling.
7458 Other values are reserved for future use. */);
7459 Vwindow_combination_limit = Qwindow_size;
7461 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
7462 doc: /* Alist of persistent window parameters.
7463 This alist specifies which window parameters shall get saved by
7464 `current-window-configuration' and `window-state-get' and subsequently
7465 restored to their previous values by `set-window-configuration' and
7466 `window-state-put'.
7468 The car of each entry of this alist is the symbol specifying the
7469 parameter. The cdr is one of the following:
7471 nil means the parameter is neither saved by `window-state-get' nor by
7472 `current-window-configuration'.
7474 t means the parameter is saved by `current-window-configuration' and,
7475 provided its WRITABLE argument is nil, by `window-state-get'.
7477 The symbol `writable' means the parameter is saved unconditionally by
7478 both `current-window-configuration' and `window-state-get'. Do not use
7479 this value for parameters without read syntax (like windows or frames).
7481 Parameters not saved by `current-window-configuration' or
7482 `window-state-get' are left alone by `set-window-configuration'
7483 respectively are not installed by `window-state-put'. */);
7484 Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
7486 DEFVAR_BOOL ("window-resize-pixelwise", window_resize_pixelwise,
7487 doc: /* Non-nil means resize windows pixelwise.
7488 This currently affects the functions: `split-window', `maximize-window',
7489 `minimize-window', `fit-window-to-buffer' and `fit-frame-to-buffer', and
7490 all functions that symmetrically resize a parent window.
7492 Note that when a frame's pixel size is not a multiple of the
7493 frame's character size, at least one window may get resized
7494 pixelwise even if this option is nil. */);
7495 window_resize_pixelwise = false;
7497 DEFVAR_BOOL ("fast-but-imprecise-scrolling",
7498 Vfast_but_imprecise_scrolling,
7499 doc: /* When non-nil, accelerate scrolling operations.
7500 This comes into play when scrolling rapidly over previously
7501 unfontified buffer regions. Only those portions of the buffer which
7502 are actually going to be displayed get fontified.
7504 Note that this optimization can cause the portion of the buffer
7505 displayed after a scrolling operation to be somewhat inaccurate. */);
7506 Vfast_but_imprecise_scrolling = false;
7508 defsubr (&Sselected_window);
7509 defsubr (&Sminibuffer_window);
7510 defsubr (&Swindow_minibuffer_p);
7511 defsubr (&Swindowp);
7512 defsubr (&Swindow_valid_p);
7513 defsubr (&Swindow_live_p);
7514 defsubr (&Swindow_frame);
7515 defsubr (&Sframe_root_window);
7516 defsubr (&Sframe_first_window);
7517 defsubr (&Sframe_selected_window);
7518 defsubr (&Sset_frame_selected_window);
7519 defsubr (&Spos_visible_in_window_p);
7520 defsubr (&Swindow_line_height);
7521 defsubr (&Swindow_buffer);
7522 defsubr (&Swindow_parent);
7523 defsubr (&Swindow_top_child);
7524 defsubr (&Swindow_left_child);
7525 defsubr (&Swindow_next_sibling);
7526 defsubr (&Swindow_prev_sibling);
7527 defsubr (&Swindow_combination_limit);
7528 defsubr (&Sset_window_combination_limit);
7529 defsubr (&Swindow_use_time);
7530 defsubr (&Swindow_pixel_width);
7531 defsubr (&Swindow_pixel_height);
7532 defsubr (&Swindow_total_width);
7533 defsubr (&Swindow_total_height);
7534 defsubr (&Swindow_normal_size);
7535 defsubr (&Swindow_new_pixel);
7536 defsubr (&Swindow_new_total);
7537 defsubr (&Swindow_new_normal);
7538 defsubr (&Swindow_pixel_left);
7539 defsubr (&Swindow_pixel_top);
7540 defsubr (&Swindow_left_column);
7541 defsubr (&Swindow_top_line);
7542 defsubr (&Sset_window_new_pixel);
7543 defsubr (&Sset_window_new_total);
7544 defsubr (&Sset_window_new_normal);
7545 defsubr (&Swindow_resize_apply);
7546 defsubr (&Swindow_resize_apply_total);
7547 defsubr (&Swindow_body_height);
7548 defsubr (&Swindow_body_width);
7549 defsubr (&Swindow_hscroll);
7550 defsubr (&Sset_window_hscroll);
7551 defsubr (&Swindow_redisplay_end_trigger);
7552 defsubr (&Sset_window_redisplay_end_trigger);
7553 defsubr (&Swindow_edges);
7554 defsubr (&Swindow_pixel_edges);
7555 defsubr (&Swindow_absolute_pixel_edges);
7556 defsubr (&Swindow_mode_line_height);
7557 defsubr (&Swindow_header_line_height);
7558 defsubr (&Swindow_right_divider_width);
7559 defsubr (&Swindow_bottom_divider_width);
7560 defsubr (&Swindow_scroll_bar_width);
7561 defsubr (&Swindow_scroll_bar_height);
7562 defsubr (&Swindow_inside_edges);
7563 defsubr (&Swindow_inside_pixel_edges);
7564 defsubr (&Swindow_inside_absolute_pixel_edges);
7565 defsubr (&Scoordinates_in_window_p);
7566 defsubr (&Swindow_at);
7567 defsubr (&Swindow_point);
7568 defsubr (&Swindow_old_point);
7569 defsubr (&Swindow_start);
7570 defsubr (&Swindow_end);
7571 defsubr (&Sset_window_point);
7572 defsubr (&Sset_window_start);
7573 defsubr (&Swindow_dedicated_p);
7574 defsubr (&Sset_window_dedicated_p);
7575 defsubr (&Swindow_display_table);
7576 defsubr (&Sset_window_display_table);
7577 defsubr (&Snext_window);
7578 defsubr (&Sprevious_window);
7579 defsubr (&Swindow__sanitize_window_sizes);
7580 defsubr (&Sget_buffer_window);
7581 defsubr (&Sdelete_other_windows_internal);
7582 defsubr (&Sdelete_window_internal);
7583 defsubr (&Sresize_mini_window_internal);
7584 defsubr (&Sset_window_buffer);
7585 defsubr (&Srun_window_configuration_change_hook);
7586 defsubr (&Srun_window_scroll_functions);
7587 defsubr (&Sselect_window);
7588 defsubr (&Sforce_window_update);
7589 defsubr (&Ssplit_window_internal);
7590 defsubr (&Sscroll_up);
7591 defsubr (&Sscroll_down);
7592 defsubr (&Sscroll_left);
7593 defsubr (&Sscroll_right);
7594 defsubr (&Sother_window_for_scrolling);
7595 defsubr (&Sscroll_other_window);
7596 defsubr (&Sminibuffer_selected_window);
7597 defsubr (&Srecenter);
7598 defsubr (&Swindow_text_width);
7599 defsubr (&Swindow_text_height);
7600 defsubr (&Smove_to_window_line);
7601 defsubr (&Swindow_configuration_p);
7602 defsubr (&Swindow_configuration_frame);
7603 defsubr (&Sset_window_configuration);
7604 defsubr (&Scurrent_window_configuration);
7605 defsubr (&Sset_window_margins);
7606 defsubr (&Swindow_margins);
7607 defsubr (&Sset_window_fringes);
7608 defsubr (&Swindow_fringes);
7609 defsubr (&Sset_window_scroll_bars);
7610 defsubr (&Swindow_scroll_bars);
7611 defsubr (&Swindow_vscroll);
7612 defsubr (&Sset_window_vscroll);
7613 defsubr (&Scompare_window_configurations);
7614 defsubr (&Swindow_list);
7615 defsubr (&Swindow_list_1);
7616 defsubr (&Swindow_prev_buffers);
7617 defsubr (&Sset_window_prev_buffers);
7618 defsubr (&Swindow_next_buffers);
7619 defsubr (&Sset_window_next_buffers);
7620 defsubr (&Swindow_parameters);
7621 defsubr (&Swindow_parameter);
7622 defsubr (&Sset_window_parameter);
7625 void
7626 keys_of_window (void)
7628 initial_define_key (control_x_map, '<', "scroll-left");
7629 initial_define_key (control_x_map, '>', "scroll-right");
7631 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
7632 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7633 initial_define_key (meta_map, 'v', "scroll-down-command");