* lisp/progmodes/cc-*.el: Fix up commenting style
[emacs.git] / src / window.c
blob863a7926a1e1964a364abaf84d8aa88ccfe44ce9
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 ptrdiff_t count_windows (struct window *);
49 static ptrdiff_t get_leaf_windows (struct window *, struct window **,
50 ptrdiff_t);
51 static void window_scroll_pixel_based (Lisp_Object, int, bool, bool);
52 static void window_scroll_line_based (Lisp_Object, int, bool, bool);
53 static void foreach_window (struct frame *,
54 bool (* fn) (struct window *, void *),
55 void *);
56 static bool foreach_window_1 (struct window *,
57 bool (* fn) (struct window *, void *),
58 void *);
59 static bool window_resize_check (struct window *, bool);
60 static void window_resize_apply (struct window *, bool);
61 static void select_window_1 (Lisp_Object, bool);
63 static struct window *set_window_fringes (struct window *, Lisp_Object,
64 Lisp_Object, Lisp_Object);
65 static struct window *set_window_margins (struct window *, Lisp_Object,
66 Lisp_Object);
67 static struct window *set_window_scroll_bars (struct window *, Lisp_Object,
68 Lisp_Object, Lisp_Object,
69 Lisp_Object);
70 static void apply_window_adjustment (struct window *);
72 /* This is the window in which the terminal's cursor should
73 be left when nothing is being done with it. This must
74 always be a leaf window, and its buffer is selected by
75 the top level editing loop at the end of each command.
77 This value is always the same as
78 FRAME_SELECTED_WINDOW (selected_frame). */
79 Lisp_Object selected_window;
81 /* A list of all windows for use by next_window and Fwindow_list.
82 Functions creating or deleting windows should invalidate this cache
83 by setting it to nil. */
84 Lisp_Object Vwindow_list;
86 /* The mini-buffer window of the selected frame.
87 Note that you cannot test for mini-bufferness of an arbitrary window
88 by comparing against this; but you can test for mini-bufferness of
89 the selected window. */
90 Lisp_Object minibuf_window;
92 /* Non-nil means it is the window whose mode line should be
93 shown as the selected window when the minibuffer is selected. */
94 Lisp_Object minibuf_selected_window;
96 /* Incremented for each window created. */
97 static EMACS_INT sequence_number;
99 /* Used by the function window_scroll_pixel_based. */
100 static int window_scroll_pixel_based_preserve_x;
101 static int window_scroll_pixel_based_preserve_y;
103 /* Same for window_scroll_line_based. */
104 static EMACS_INT window_scroll_preserve_hpos;
105 static EMACS_INT window_scroll_preserve_vpos;
107 static void
108 CHECK_WINDOW_CONFIGURATION (Lisp_Object x)
110 CHECK_TYPE (WINDOW_CONFIGURATIONP (x), Qwindow_configuration_p, x);
113 /* These setters are used only in this file, so they can be private. */
114 static void
115 wset_combination_limit (struct window *w, Lisp_Object val)
117 w->combination_limit = val;
120 static void
121 wset_dedicated (struct window *w, Lisp_Object val)
123 w->dedicated = val;
126 static void
127 wset_display_table (struct window *w, Lisp_Object val)
129 w->display_table = val;
132 static void
133 wset_new_normal (struct window *w, Lisp_Object val)
135 w->new_normal = val;
138 static void
139 wset_new_total (struct window *w, Lisp_Object val)
141 w->new_total = val;
144 static void
145 wset_normal_cols (struct window *w, Lisp_Object val)
147 w->normal_cols = val;
150 static void
151 wset_normal_lines (struct window *w, Lisp_Object val)
153 w->normal_lines = val;
156 static void
157 wset_parent (struct window *w, Lisp_Object val)
159 w->parent = val;
162 static void
163 wset_pointm (struct window *w, Lisp_Object val)
165 w->pointm = val;
168 static void
169 wset_old_pointm (struct window *w, Lisp_Object val)
171 w->old_pointm = val;
174 static void
175 wset_start (struct window *w, Lisp_Object val)
177 w->start = val;
180 static void
181 wset_temslot (struct window *w, Lisp_Object val)
183 w->temslot = val;
186 static void
187 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
189 w->vertical_scroll_bar_type = val;
192 static void
193 wset_window_parameters (struct window *w, Lisp_Object val)
195 w->window_parameters = val;
198 static void
199 wset_combination (struct window *w, bool horflag, Lisp_Object val)
201 /* Since leaf windows never becomes non-leaf, there should
202 be no buffer and markers in start and pointm fields of W. */
203 eassert (!BUFFERP (w->contents) && NILP (w->start) && NILP (w->pointm));
204 w->contents = val;
205 /* When an internal window is deleted and VAL is nil, HORFLAG
206 is meaningless. */
207 if (!NILP (val))
208 w->horizontal = horflag;
211 /* True if leaf window W doesn't reflect the actual state
212 of displayed buffer due to its text or overlays change. */
214 bool
215 window_outdated (struct window *w)
217 struct buffer *b = XBUFFER (w->contents);
218 return (w->last_modified < BUF_MODIFF (b)
219 || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b));
222 struct window *
223 decode_live_window (register Lisp_Object window)
225 if (NILP (window))
226 return XWINDOW (selected_window);
228 CHECK_LIVE_WINDOW (window);
229 return XWINDOW (window);
232 struct window *
233 decode_any_window (register Lisp_Object window)
235 struct window *w;
237 if (NILP (window))
238 return XWINDOW (selected_window);
240 CHECK_WINDOW (window);
241 w = XWINDOW (window);
242 return w;
245 static struct window *
246 decode_valid_window (register Lisp_Object window)
248 struct window *w;
250 if (NILP (window))
251 return XWINDOW (selected_window);
253 CHECK_VALID_WINDOW (window);
254 w = XWINDOW (window);
255 return w;
258 /* Called when W's buffer slot is changed. ARG -1 means that W is about to
259 cease its buffer, and 1 means that W is about to set up the new one. */
261 static void
262 adjust_window_count (struct window *w, int arg)
264 eassert (eabs (arg) == 1);
265 if (BUFFERP (w->contents))
267 struct buffer *b = XBUFFER (w->contents);
269 if (b->base_buffer)
270 b = b->base_buffer;
271 b->window_count += arg;
272 eassert (b->window_count >= 0);
273 /* These should be recalculated by redisplay code. */
274 w->window_end_valid = false;
275 w->base_line_pos = 0;
279 /* Set W's buffer slot to VAL and recompute number
280 of windows showing VAL if it is a buffer. */
282 void
283 wset_buffer (struct window *w, Lisp_Object val)
285 adjust_window_count (w, -1);
286 if (BUFFERP (val))
287 /* Make sure that we do not assign the buffer
288 to an internal window. */
289 eassert (MARKERP (w->start) && MARKERP (w->pointm));
290 w->contents = val;
291 adjust_window_count (w, 1);
294 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
295 doc: /* Return t if OBJECT is a window and nil otherwise. */)
296 (Lisp_Object object)
298 return WINDOWP (object) ? Qt : Qnil;
301 DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
302 doc: /* Return t if OBJECT is a valid window and nil otherwise.
303 A valid window is either a window that displays a buffer or an internal
304 window. Windows that have been deleted are not valid. */)
305 (Lisp_Object object)
307 return WINDOW_VALID_P (object) ? Qt : Qnil;
310 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
311 doc: /* Return t if OBJECT is a live window and nil otherwise.
312 A live window is a window that displays a buffer.
313 Internal windows and deleted windows are not live. */)
314 (Lisp_Object object)
316 return WINDOW_LIVE_P (object) ? Qt : Qnil;
319 /* Frames and windows. */
320 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 0, 1, 0,
321 doc: /* Return the frame that window WINDOW is on.
322 WINDOW must be a valid window and defaults to the selected one. */)
323 (Lisp_Object window)
325 return decode_valid_window (window)->frame;
328 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
329 doc: /* Return the root window of FRAME-OR-WINDOW.
330 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
331 With a frame argument, return that frame's root window.
332 With a window argument, return the root window of that window's frame. */)
333 (Lisp_Object frame_or_window)
335 Lisp_Object window;
337 if (NILP (frame_or_window))
338 window = SELECTED_FRAME ()->root_window;
339 else if (WINDOW_VALID_P (frame_or_window))
340 window = XFRAME (XWINDOW (frame_or_window)->frame)->root_window;
341 else
343 CHECK_LIVE_FRAME (frame_or_window);
344 window = XFRAME (frame_or_window)->root_window;
347 return window;
350 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
351 doc: /* Return the minibuffer window for frame FRAME.
352 If FRAME is omitted or nil, it defaults to the selected frame. */)
353 (Lisp_Object frame)
355 return FRAME_MINIBUF_WINDOW (decode_live_frame (frame));
358 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
359 Swindow_minibuffer_p, 0, 1, 0,
360 doc: /* Return non-nil if WINDOW is a minibuffer window.
361 WINDOW must be a valid window and defaults to the selected one. */)
362 (Lisp_Object window)
364 return MINI_WINDOW_P (decode_valid_window (window)) ? Qt : Qnil;
367 /* Don't move this to window.el - this must be a safe routine. */
368 DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
369 doc: /* Return the topmost, leftmost live window on FRAME-OR-WINDOW.
370 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
371 Else if FRAME-OR-WINDOW denotes a valid window, return the first window
372 of that window's frame. If FRAME-OR-WINDOW denotes a live frame, return
373 the first window of that frame. */)
374 (Lisp_Object frame_or_window)
376 Lisp_Object window;
378 if (NILP (frame_or_window))
379 window = SELECTED_FRAME ()->root_window;
380 else if (WINDOW_VALID_P (frame_or_window))
381 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
382 else
384 CHECK_LIVE_FRAME (frame_or_window);
385 window = XFRAME (frame_or_window)->root_window;
388 while (WINDOWP (XWINDOW (window)->contents))
389 window = XWINDOW (window)->contents;
391 return window;
394 DEFUN ("frame-selected-window", Fframe_selected_window,
395 Sframe_selected_window, 0, 1, 0,
396 doc: /* Return the selected window of FRAME-OR-WINDOW.
397 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
398 Else if FRAME-OR-WINDOW denotes a valid window, return the selected
399 window of that window's frame. If FRAME-OR-WINDOW denotes a live frame,
400 return the selected window of that frame. */)
401 (Lisp_Object frame_or_window)
403 Lisp_Object window;
405 if (NILP (frame_or_window))
406 window = SELECTED_FRAME ()->selected_window;
407 else if (WINDOW_VALID_P (frame_or_window))
408 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
409 else
411 CHECK_LIVE_FRAME (frame_or_window);
412 window = XFRAME (frame_or_window)->selected_window;
415 return window;
418 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
419 Sset_frame_selected_window, 2, 3, 0,
420 doc: /* Set selected window of FRAME to WINDOW.
421 FRAME must be a live frame and defaults to the selected one. If FRAME
422 is the selected frame, this makes WINDOW the selected window. Optional
423 argument NORECORD non-nil means to neither change the order of recently
424 selected windows nor the buffer list. WINDOW must denote a live window.
425 Return WINDOW. */)
426 (Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
428 if (NILP (frame))
429 frame = selected_frame;
431 CHECK_LIVE_FRAME (frame);
432 CHECK_LIVE_WINDOW (window);
434 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
435 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
437 if (EQ (frame, selected_frame))
438 return Fselect_window (window, norecord);
439 else
441 fset_selected_window (XFRAME (frame), window);
442 return window;
446 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
447 doc: /* Return the selected window.
448 The selected window is the window in which the standard cursor for
449 selected windows appears and to which many commands apply. */)
450 (void)
452 return selected_window;
455 EMACS_INT window_select_count;
457 /* If select_window is called with inhibit_point_swap true it will
458 not store point of the old selected window's buffer back into that
459 window's pointm slot. This is needed by Fset_window_configuration to
460 avoid that the display routine is called with selected_window set to
461 Qnil causing a subsequent crash. */
462 static Lisp_Object
463 select_window (Lisp_Object window, Lisp_Object norecord,
464 bool inhibit_point_swap)
466 struct window *w;
467 struct frame *sf;
469 CHECK_LIVE_WINDOW (window);
471 w = XWINDOW (window);
473 /* Make the selected window's buffer current. */
474 Fset_buffer (w->contents);
476 if (EQ (window, selected_window) && !inhibit_point_swap)
477 /* `switch-to-buffer' uses (select-window (selected-window)) as a "clever"
478 way to call record_buffer from Elisp, so it's important that we call
479 record_buffer before returning here. */
480 goto record_and_return;
482 if (NILP (norecord))
483 { /* Mark the window for redisplay since the selected-window has
484 a different mode-line. */
485 wset_redisplay (XWINDOW (selected_window));
486 wset_redisplay (w);
488 else
489 redisplay_other_windows ();
491 sf = SELECTED_FRAME ();
492 if (XFRAME (WINDOW_FRAME (w)) != sf)
494 fset_selected_window (XFRAME (WINDOW_FRAME (w)), window);
495 /* Use this rather than Fhandle_switch_frame
496 so that FRAME_FOCUS_FRAME is moved appropriately as we
497 move around in the state where a minibuffer in a separate
498 frame is active. */
499 Fselect_frame (WINDOW_FRAME (w), norecord);
500 /* Fselect_frame called us back so we've done all the work already. */
501 eassert (EQ (window, selected_window));
502 return window;
504 else
505 fset_selected_window (sf, window);
507 select_window_1 (window, inhibit_point_swap);
508 bset_last_selected_window (XBUFFER (w->contents), window);
510 record_and_return:
511 /* record_buffer can run QUIT, so make sure it is run only after we have
512 re-established the invariant between selected_window and selected_frame,
513 otherwise the temporary broken invariant might "escape" (bug#14161). */
514 if (NILP (norecord))
516 w->use_time = ++window_select_count;
517 record_buffer (w->contents);
520 return window;
523 /* Select window with a minimum of fuss, i.e. don't record the change anywhere
524 (not even for redisplay's benefit), and assume that the window's frame is
525 already selected. */
526 static void
527 select_window_1 (Lisp_Object window, bool inhibit_point_swap)
529 /* Store the old selected window's buffer's point in pointm of the old
530 selected window. It belongs to that window, and when the window is
531 not selected, must be in the window. */
532 if (!inhibit_point_swap)
534 struct window *ow = XWINDOW (selected_window);
535 if (BUFFERP (ow->contents))
536 set_marker_both (ow->pointm, ow->contents,
537 BUF_PT (XBUFFER (ow->contents)),
538 BUF_PT_BYTE (XBUFFER (ow->contents)));
541 selected_window = window;
543 /* Go to the point recorded in the window.
544 This is important when the buffer is in more
545 than one window. It also matters when
546 redisplay_window has altered point after scrolling,
547 because it makes the change only in the window. */
548 set_point_from_marker (XWINDOW (window)->pointm);
551 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
552 doc: /* Select WINDOW which must be a live window.
553 Also make WINDOW's frame the selected frame and WINDOW that frame's
554 selected window. In addition, make WINDOW's buffer current and set its
555 buffer's value of `point' to the value of WINDOW's `window-point'.
556 Return WINDOW.
558 Optional second arg NORECORD non-nil means do not put this buffer at the
559 front of the buffer list and do not make this window the most recently
560 selected one.
562 Run `buffer-list-update-hook' unless NORECORD is non-nil. Note that
563 applications and internal routines often select a window temporarily for
564 various purposes; mostly, to simplify coding. As a rule, such
565 selections should be not recorded and therefore will not pollute
566 `buffer-list-update-hook'. Selections that "really count" are those
567 causing a visible change in the next redisplay of WINDOW's frame and
568 should be always recorded. So if you think of running a function each
569 time a window gets selected put it on `buffer-list-update-hook'.
571 Also note that the main editor command loop sets the current buffer to
572 the buffer of the selected window before each command. */)
573 (Lisp_Object window, Lisp_Object norecord)
575 return select_window (window, norecord, false);
578 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
579 doc: /* Return the buffer displayed in window WINDOW.
580 If WINDOW is omitted or nil, it defaults to the selected window.
581 Return nil for an internal window or a deleted window. */)
582 (Lisp_Object window)
584 struct window *w = decode_any_window (window);
585 return WINDOW_LEAF_P (w) ? w->contents : Qnil;
588 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
589 doc: /* Return the parent window of window WINDOW.
590 WINDOW must be a valid window and defaults to the selected one.
591 Return nil for a window with no parent (e.g. a root window). */)
592 (Lisp_Object window)
594 return decode_valid_window (window)->parent;
597 DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 0, 1, 0,
598 doc: /* Return the topmost child window of window WINDOW.
599 WINDOW must be a valid window and defaults to the selected one.
600 Return nil if WINDOW is a live window (live windows have no children).
601 Return nil if WINDOW is an internal window whose children form a
602 horizontal combination. */)
603 (Lisp_Object window)
605 struct window *w = decode_valid_window (window);
606 return WINDOW_VERTICAL_COMBINATION_P (w) ? w->contents : Qnil;
609 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
610 doc: /* Return the leftmost child window of window WINDOW.
611 WINDOW must be a valid window and defaults to the selected one.
612 Return nil if WINDOW is a live window (live windows have no children).
613 Return nil if WINDOW is an internal window whose children form a
614 vertical combination. */)
615 (Lisp_Object window)
617 struct window *w = decode_valid_window (window);
618 return WINDOW_HORIZONTAL_COMBINATION_P (w) ? w->contents : Qnil;
621 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
622 doc: /* Return the next sibling window of window WINDOW.
623 WINDOW must be a valid window and defaults to the selected one.
624 Return nil if WINDOW has no next sibling. */)
625 (Lisp_Object window)
627 return decode_valid_window (window)->next;
630 DEFUN ("window-prev-sibling", Fwindow_prev_sibling, Swindow_prev_sibling, 0, 1, 0,
631 doc: /* Return the previous sibling window of window WINDOW.
632 WINDOW must be a valid window and defaults to the selected one.
633 Return nil if WINDOW has no previous sibling. */)
634 (Lisp_Object window)
636 return decode_valid_window (window)->prev;
639 DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
640 doc: /* Return combination limit of window WINDOW.
641 WINDOW must be a valid window used in horizontal or vertical combination.
642 If the return value is nil, child windows of WINDOW can be recombined with
643 WINDOW's siblings. A return value of t means that child windows of
644 WINDOW are never \(re-)combined with WINDOW's siblings. */)
645 (Lisp_Object window)
647 struct window *w;
649 CHECK_VALID_WINDOW (window);
650 w = XWINDOW (window);
651 if (WINDOW_LEAF_P (w))
652 error ("Combination limit is meaningful for internal windows only");
653 return w->combination_limit;
656 DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
657 doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
658 WINDOW must be a valid window used in horizontal or vertical combination.
659 If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
660 siblings. LIMIT t means that child windows of WINDOW are never
661 \(re-)combined with WINDOW's siblings. Other values are reserved for
662 future use. */)
663 (Lisp_Object window, Lisp_Object limit)
665 struct window *w;
667 CHECK_VALID_WINDOW (window);
668 w = XWINDOW (window);
669 if (WINDOW_LEAF_P (w))
670 error ("Combination limit is meaningful for internal windows only");
671 wset_combination_limit (w, limit);
672 return limit;
675 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
676 doc: /* Return the use time of window WINDOW.
677 WINDOW must be a live window and defaults to the selected one.
678 The window with the highest use time is the most recently selected
679 one. The window with the lowest use time is the least recently
680 selected one. */)
681 (Lisp_Object window)
683 return make_number (decode_live_window (window)->use_time);
686 DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0,
687 doc: /* Return the width of window WINDOW in pixels.
688 WINDOW must be a valid window and defaults to the selected one.
690 The return value includes the fringes and margins of WINDOW as well as
691 any vertical dividers or scroll bars belonging to WINDOW. If WINDOW is
692 an internal window, its pixel width is the width of the screen areas
693 spanned by its children. */)
694 (Lisp_Object window)
696 return make_number (decode_valid_window (window)->pixel_width);
699 DEFUN ("window-pixel-height", Fwindow_pixel_height, Swindow_pixel_height, 0, 1, 0,
700 doc: /* Return the height of window WINDOW in pixels.
701 WINDOW must be a valid window and defaults to the selected one.
703 The return value includes the mode line and header line and the bottom
704 divider, if any. If WINDOW is an internal window, its pixel height is
705 the height of the screen areas spanned by its children. */)
706 (Lisp_Object window)
708 return make_number (decode_valid_window (window)->pixel_height);
711 DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0,
712 doc: /* Return the height of window WINDOW in lines.
713 WINDOW must be a valid window and defaults to the selected one.
715 The return value includes the heights of WINDOW's mode and header line
716 and its bottom divider, if any. If WINDOW is an internal window, the
717 total height is the height of the screen areas spanned by its children.
719 If WINDOW's pixel height is not an integral multiple of its frame's
720 character height, the number of lines occupied by WINDOW is rounded
721 internally. This is done in a way such that, if WINDOW is a parent
722 window, the sum of the total heights of all its children internally
723 equals the total height of WINDOW.
725 If the optional argument ROUND is `ceiling', return the smallest integer
726 larger than WINDOW's pixel height divided by the character height of
727 WINDOW's frame. ROUND `floor' means to return the largest integer
728 smaller than WINDOW's pixel height divided by the character height of
729 WINDOW's frame. Any other value of ROUND means to return the internal
730 total height of WINDOW. */)
731 (Lisp_Object window, Lisp_Object round)
733 struct window *w = decode_valid_window (window);
735 if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
736 return make_number (w->total_lines);
737 else
739 int unit = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
741 return make_number (EQ (round, Qceiling)
742 ? ((w->pixel_height + unit - 1) /unit)
743 : (w->pixel_height / unit));
747 DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 2, 0,
748 doc: /* Return the total width of window WINDOW in columns.
749 WINDOW must be a valid window and defaults to the selected one.
751 The return value includes the widths of WINDOW's fringes, margins,
752 scroll bars and its right divider, if any. If WINDOW is an internal
753 window, the total width is the width of the screen areas spanned by its
754 children.
756 If WINDOW's pixel width is not an integral multiple of its frame's
757 character width, the number of lines occupied by WINDOW is rounded
758 internally. This is done in a way such that, if WINDOW is a parent
759 window, the sum of the total widths of all its children internally
760 equals the total width of WINDOW.
762 If the optional argument ROUND is `ceiling', return the smallest integer
763 larger than WINDOW's pixel width divided by the character width of
764 WINDOW's frame. ROUND `floor' means to return the largest integer
765 smaller than WINDOW's pixel width divided by the character width of
766 WINDOW's frame. Any other value of ROUND means to return the internal
767 total width of WINDOW. */)
768 (Lisp_Object window, Lisp_Object round)
770 struct window *w = decode_valid_window (window);
772 if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
773 return make_number (w->total_cols);
774 else
776 int unit = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
778 return make_number (EQ (round, Qceiling)
779 ? ((w->pixel_width + unit - 1) /unit)
780 : (w->pixel_width / unit));
784 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
785 doc: /* Return the new total size of window WINDOW.
786 WINDOW must be a valid window and defaults to the selected one.
788 The new total size of WINDOW is the value set by the last call of
789 `set-window-new-total' for WINDOW. If it is valid, it will be shortly
790 installed as WINDOW's total height (see `window-total-height') or total
791 width (see `window-total-width'). */)
792 (Lisp_Object window)
794 return decode_valid_window (window)->new_total;
797 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
798 doc: /* Return the normal height of window WINDOW.
799 WINDOW must be a valid window and defaults to the selected one.
800 If HORIZONTAL is non-nil, return the normal width of WINDOW.
802 The normal height of a frame's root window or a window that is
803 horizontally combined (a window that has a left or right sibling) is
804 1.0. The normal height of a window that is vertically combined (has a
805 sibling above or below) is the fraction of the window's height with
806 respect to its parent. The sum of the normal heights of all windows in a
807 vertical combination equals 1.0.
809 Similarly, the normal width of a frame's root window or a window that is
810 vertically combined equals 1.0. The normal width of a window that is
811 horizontally combined is the fraction of the window's width with respect
812 to its parent. The sum of the normal widths of all windows in a
813 horizontal combination equals 1.0.
815 The normal sizes of windows are used to restore the proportional sizes
816 of windows after they have been shrunk to their minimum sizes; for
817 example when a frame is temporarily made very small and afterwards gets
818 re-enlarged to its previous size. */)
819 (Lisp_Object window, Lisp_Object horizontal)
821 struct window *w = decode_valid_window (window);
823 return NILP (horizontal) ? w->normal_lines : w->normal_cols;
826 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
827 doc: /* Return new normal size of window WINDOW.
828 WINDOW must be a valid window and defaults to the selected one.
830 The new normal size of WINDOW is the value set by the last call of
831 `set-window-new-normal' for WINDOW. If valid, it will be shortly
832 installed as WINDOW's normal size (see `window-normal-size'). */)
833 (Lisp_Object window)
835 return decode_valid_window (window)->new_normal;
838 DEFUN ("window-new-pixel", Fwindow_new_pixel, Swindow_new_pixel, 0, 1, 0,
839 doc: /* Return new pixel size of window WINDOW.
840 WINDOW must be a valid window and defaults to the selected one.
842 The new pixel size of WINDOW is the value set by the last call of
843 `set-window-new-pixel' for WINDOW. If it is valid, it will be shortly
844 installed as WINDOW's pixel height (see `window-pixel-height') or pixel
845 width (see `window-pixel-width'). */)
846 (Lisp_Object window)
848 return decode_valid_window (window)->new_pixel;
851 DEFUN ("window-pixel-left", Fwindow_pixel_left, Swindow_pixel_left, 0, 1, 0,
852 doc: /* Return left pixel edge of window WINDOW.
853 WINDOW must be a valid window and defaults to the selected one. */)
854 (Lisp_Object window)
856 return make_number (decode_valid_window (window)->pixel_left);
859 DEFUN ("window-pixel-top", Fwindow_pixel_top, Swindow_pixel_top, 0, 1, 0,
860 doc: /* Return top pixel edge of window WINDOW.
861 WINDOW must be a valid window and defaults to the selected one. */)
862 (Lisp_Object window)
864 return make_number (decode_valid_window (window)->pixel_top);
867 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
868 doc: /* Return left column of window WINDOW.
869 This is the distance, in columns, between the left edge of WINDOW and
870 the left edge of the frame's window area. For instance, the return
871 value is 0 if there is no window to the left of WINDOW.
873 WINDOW must be a valid window and defaults to the selected one. */)
874 (Lisp_Object window)
876 return make_number (decode_valid_window (window)->left_col);
879 DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
880 doc: /* Return top line of window WINDOW.
881 This is the distance, in lines, between the top of WINDOW and the top
882 of the frame's window area. For instance, the return value is 0 if
883 there is no window above WINDOW.
885 WINDOW must be a valid window and defaults to the selected one. */)
886 (Lisp_Object window)
888 return make_number (decode_valid_window (window)->top_line);
891 /* Return the number of lines/pixels of W's body. Don't count any mode
892 or header line or horizontal divider of W. Rounds down to nearest
893 integer when not working pixelwise. */
894 static int
895 window_body_height (struct window *w, bool pixelwise)
897 int height = (w->pixel_height
898 - WINDOW_HEADER_LINE_HEIGHT (w)
899 - (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
900 ? WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
901 : 0)
902 - WINDOW_MODE_LINE_HEIGHT (w)
903 - WINDOW_BOTTOM_DIVIDER_WIDTH (w));
905 /* Don't return a negative value. */
906 return max (pixelwise
907 ? height
908 : height / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)),
912 /* Return the number of columns/pixels of W's body. Don't count columns
913 occupied by the scroll bar or the divider/vertical bar separating W
914 from its right sibling or margins. On window-systems don't count
915 fringes either. Round down to nearest integer when not working
916 pixelwise. */
918 window_body_width (struct window *w, bool pixelwise)
920 struct frame *f = XFRAME (WINDOW_FRAME (w));
922 int width = (w->pixel_width
923 - WINDOW_RIGHT_DIVIDER_WIDTH (w)
924 - (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
925 ? WINDOW_SCROLL_BAR_AREA_WIDTH (w)
926 : (/* A vertical bar is either 1 or 0. */
927 !FRAME_WINDOW_P (f)
928 && !WINDOW_RIGHTMOST_P (w)
929 && !WINDOW_RIGHT_DIVIDER_WIDTH (w)))
930 - WINDOW_MARGINS_WIDTH (w)
931 - (FRAME_WINDOW_P (f)
932 ? WINDOW_FRINGES_WIDTH (w)
933 : 0));
935 /* Don't return a negative value. */
936 return max (pixelwise
937 ? width
938 : width / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)),
942 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
943 doc: /* Return the height of WINDOW's text area.
944 WINDOW must be a live window and defaults to the selected one. Optional
945 argument PIXELWISE non-nil means return the height of WINDOW's text area
946 in pixels. The return value does not include the mode line or header
947 line or any horizontal divider.
949 If PIXELWISE is nil, return the largest integer smaller than WINDOW's
950 pixel height divided by the character height of WINDOW's frame. This
951 means that if a line at the bottom of the text area is only partially
952 visible, that line is not counted. */)
953 (Lisp_Object window, Lisp_Object pixelwise)
955 return make_number (window_body_height (decode_live_window (window),
956 !NILP (pixelwise)));
959 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
960 doc: /* Return the width of WINDOW's text area.
961 WINDOW must be a live window and defaults to the selected one. Optional
962 argument PIXELWISE non-nil means return the width in pixels. The return
963 value does not include any vertical dividers, fringes or marginal areas,
964 or scroll bars.
966 If PIXELWISE is nil, return the largest integer smaller than WINDOW's
967 pixel width divided by the character width of WINDOW's frame. This
968 means that if a column at the right of the text area is only partially
969 visible, that column is not counted.
971 Note that the returned value includes the column reserved for the
972 continuation glyph. */)
973 (Lisp_Object window, Lisp_Object pixelwise)
975 return make_number (window_body_width (decode_live_window (window),
976 !NILP (pixelwise)));
979 DEFUN ("window-mode-line-height", Fwindow_mode_line_height,
980 Swindow_mode_line_height, 0, 1, 0,
981 doc: /* Return the height in pixels of WINDOW's mode-line.
982 WINDOW must be a live window and defaults to the selected one. */)
983 (Lisp_Object window)
985 return (make_number (WINDOW_MODE_LINE_HEIGHT (decode_live_window (window))));
988 DEFUN ("window-header-line-height", Fwindow_header_line_height,
989 Swindow_header_line_height, 0, 1, 0,
990 doc: /* Return the height in pixels of WINDOW's header-line.
991 WINDOW must be a live window and defaults to the selected one. */)
992 (Lisp_Object window)
994 return (make_number (WINDOW_HEADER_LINE_HEIGHT (decode_live_window (window))));
997 DEFUN ("window-right-divider-width", Fwindow_right_divider_width,
998 Swindow_right_divider_width, 0, 1, 0,
999 doc: /* Return the width in pixels of WINDOW's right divider.
1000 WINDOW must be a live window and defaults to the selected one. */)
1001 (Lisp_Object window)
1003 return (make_number (WINDOW_RIGHT_DIVIDER_WIDTH (decode_live_window (window))));
1006 DEFUN ("window-bottom-divider-width", Fwindow_bottom_divider_width,
1007 Swindow_bottom_divider_width, 0, 1, 0,
1008 doc: /* Return the width in pixels of WINDOW's bottom divider.
1009 WINDOW must be a live window and defaults to the selected one. */)
1010 (Lisp_Object window)
1012 return (make_number (WINDOW_BOTTOM_DIVIDER_WIDTH (decode_live_window (window))));
1015 DEFUN ("window-scroll-bar-width", Fwindow_scroll_bar_width,
1016 Swindow_scroll_bar_width, 0, 1, 0,
1017 doc: /* Return the width in pixels of WINDOW's vertical scrollbar.
1018 WINDOW must be a live window and defaults to the selected one. */)
1019 (Lisp_Object window)
1021 return (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (decode_live_window (window))));
1024 DEFUN ("window-scroll-bar-height", Fwindow_scroll_bar_height,
1025 Swindow_scroll_bar_height, 0, 1, 0,
1026 doc: /* Return the height in pixels of WINDOW's horizontal scrollbar.
1027 WINDOW must be a live window and defaults to the selected one. */)
1028 (Lisp_Object window)
1030 return (make_number (WINDOW_SCROLL_BAR_AREA_HEIGHT (decode_live_window (window))));
1033 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
1034 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
1035 WINDOW must be a live window and defaults to the selected one. */)
1036 (Lisp_Object window)
1038 return make_number (decode_live_window (window)->hscroll);
1041 /* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
1042 range, returning the new amount as a fixnum. */
1043 static Lisp_Object
1044 set_window_hscroll (struct window *w, EMACS_INT hscroll)
1046 /* Horizontal scrolling has problems with large scroll amounts.
1047 It's too slow with long lines, and even with small lines the
1048 display can be messed up. For now, though, impose only the limits
1049 required by the internal representation: horizontal scrolling must
1050 fit in fixnum (since it's visible to Elisp) and into ptrdiff_t
1051 (since it's stored in a ptrdiff_t). */
1052 ptrdiff_t hscroll_max = min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX);
1053 ptrdiff_t new_hscroll = clip_to_bounds (0, hscroll, hscroll_max);
1055 /* Prevent redisplay shortcuts when changing the hscroll. */
1056 if (w->hscroll != new_hscroll)
1057 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
1059 w->hscroll = new_hscroll;
1060 w->suspend_auto_hscroll = true;
1062 return make_number (new_hscroll);
1065 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
1066 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
1067 WINDOW must be a live window and defaults to the selected one.
1068 Clip the number to a reasonable value if out of range.
1069 Return the new number. NCOL should be zero or positive.
1071 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
1072 window so that the location of point moves off-window. */)
1073 (Lisp_Object window, Lisp_Object ncol)
1075 CHECK_NUMBER (ncol);
1076 return set_window_hscroll (decode_live_window (window), XINT (ncol));
1079 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
1080 Swindow_redisplay_end_trigger, 0, 1, 0,
1081 doc: /* Return WINDOW's redisplay end trigger value.
1082 WINDOW must be a live window and defaults to the selected one.
1083 See `set-window-redisplay-end-trigger' for more information. */)
1084 (Lisp_Object window)
1086 return decode_live_window (window)->redisplay_end_trigger;
1089 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
1090 Sset_window_redisplay_end_trigger, 2, 2, 0,
1091 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
1092 WINDOW must be a live window and defaults to the selected one. VALUE
1093 should be a buffer position (typically a marker) or nil. If it is a
1094 buffer position, then if redisplay in WINDOW reaches a position beyond
1095 VALUE, the functions in `redisplay-end-trigger-functions' are called
1096 with two arguments: WINDOW, and the end trigger value. Afterwards the
1097 end-trigger value is reset to nil. */)
1098 (register Lisp_Object window, Lisp_Object value)
1100 wset_redisplay_end_trigger (decode_live_window (window), value);
1101 return value;
1104 /* Test if the character at column X, row Y is within window W.
1105 If it is not, return ON_NOTHING;
1106 if it is on the window's vertical divider, return
1107 ON_RIGHT_DIVIDER;
1108 if it is on the window's horizontal divider, return
1109 ON_BOTTOM_DIVIDER;
1110 if it is in the window's text area, return ON_TEXT;
1111 if it is on the window's modeline, return ON_MODE_LINE;
1112 if it is on the border between the window and its right sibling,
1113 return ON_VERTICAL_BORDER;
1114 if it is on a scroll bar, return ON_SCROLL_BAR;
1115 if it is on the window's top line, return ON_HEADER_LINE;
1116 if it is in left or right fringe of the window,
1117 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
1118 if it is in the marginal area to the left/right of the window,
1119 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
1121 X and Y are frame relative pixel coordinates. */
1123 static enum window_part
1124 coordinates_in_window (register struct window *w, int x, int y)
1126 struct frame *f = XFRAME (WINDOW_FRAME (w));
1127 enum window_part part;
1128 int ux = FRAME_COLUMN_WIDTH (f);
1129 int left_x = WINDOW_LEFT_EDGE_X (w);
1130 int right_x = WINDOW_RIGHT_EDGE_X (w);
1131 int top_y = WINDOW_TOP_EDGE_Y (w);
1132 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
1133 /* The width of the area where the vertical line can be dragged.
1134 (Between mode lines for instance. */
1135 int grabbable_width = ux;
1136 int lmargin_width, rmargin_width, text_left, text_right;
1138 /* Outside any interesting row or column? */
1139 if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
1140 return ON_NOTHING;
1142 /* On the horizontal window divider (which prevails the vertical
1143 divider)? */
1144 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w) > 0
1145 && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1146 && y <= bottom_y)
1147 return ON_BOTTOM_DIVIDER;
1148 /* On vertical window divider? */
1149 else if (!WINDOW_RIGHTMOST_P (w)
1150 && WINDOW_RIGHT_DIVIDER_WIDTH (w) > 0
1151 && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
1152 && x <= right_x)
1153 return ON_RIGHT_DIVIDER;
1154 /* On the horizontal scroll bar? (Including the empty space at its
1155 right!) */
1156 else if ((WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
1157 && y >= (bottom_y
1158 - WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
1159 - CURRENT_MODE_LINE_HEIGHT (w)
1160 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1161 && y <= (bottom_y
1162 - CURRENT_MODE_LINE_HEIGHT (w)
1163 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))))
1164 return ON_HORIZONTAL_SCROLL_BAR;
1165 /* On the mode or header line? */
1166 else if ((WINDOW_WANTS_MODELINE_P (w)
1167 && y >= (bottom_y
1168 - CURRENT_MODE_LINE_HEIGHT (w)
1169 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1170 && y <= bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
1171 && (part = ON_MODE_LINE))
1172 || (WINDOW_WANTS_HEADER_LINE_P (w)
1173 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
1174 && (part = ON_HEADER_LINE)))
1176 /* If it's under/over the scroll bar portion of the mode/header
1177 line, say it's on the vertical line. That's to be able to
1178 resize windows horizontally in case we're using toolkit scroll
1179 bars. Note: If scrollbars are on the left, the window that
1180 must be eventually resized is that on the left of WINDOW. */
1181 if ((WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0)
1182 && ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1183 && !WINDOW_LEFTMOST_P (w)
1184 && eabs (x - left_x) < grabbable_width)
1185 || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1186 && !WINDOW_RIGHTMOST_P (w)
1187 && eabs (x - right_x) < grabbable_width)))
1188 return ON_VERTICAL_BORDER;
1189 else
1190 return part;
1193 /* In what's below, we subtract 1 when computing right_x because we
1194 want the rightmost pixel, which is given by left_pixel+width-1. */
1195 if (w->pseudo_window_p)
1197 left_x = 0;
1198 right_x = WINDOW_PIXEL_WIDTH (w) - 1;
1200 else
1202 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
1203 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
1206 /* Outside any interesting column? */
1207 if (x < left_x || x > right_x)
1208 return ON_VERTICAL_SCROLL_BAR;
1210 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
1211 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
1213 text_left = window_box_left (w, TEXT_AREA);
1214 text_right = text_left + window_box_width (w, TEXT_AREA);
1216 if (FRAME_WINDOW_P (f))
1218 if (!w->pseudo_window_p
1219 && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
1220 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
1221 && !WINDOW_RIGHTMOST_P (w)
1222 && (eabs (x - right_x) < grabbable_width))
1223 return ON_VERTICAL_BORDER;
1225 /* Need to say "x > right_x" rather than >=, since on character
1226 terminals, the vertical line's x coordinate is right_x. */
1227 else if (!w->pseudo_window_p
1228 && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
1229 && !WINDOW_RIGHTMOST_P (w)
1230 /* Why check ux if we are not the rightmost window? Also
1231 shouldn't a pseudo window always be rightmost? */
1232 && x > right_x - ux)
1233 return ON_VERTICAL_BORDER;
1235 if (x < text_left)
1237 if (lmargin_width > 0
1238 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1239 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
1240 : (x < left_x + lmargin_width)))
1241 return ON_LEFT_MARGIN;
1242 else
1243 return ON_LEFT_FRINGE;
1246 if (x >= text_right)
1248 if (rmargin_width > 0
1249 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1250 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
1251 : (x >= right_x - rmargin_width)))
1252 return ON_RIGHT_MARGIN;
1253 else
1254 return ON_RIGHT_FRINGE;
1257 /* Everything special ruled out - must be on text area */
1258 return ON_TEXT;
1261 /* Take X is the frame-relative pixel x-coordinate, and return the
1262 x-coordinate relative to part PART of window W. */
1264 window_relative_x_coord (struct window *w, enum window_part part, int x)
1266 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
1268 switch (part)
1270 case ON_TEXT:
1271 return x - window_box_left (w, TEXT_AREA);
1273 case ON_HEADER_LINE:
1274 case ON_MODE_LINE:
1275 case ON_LEFT_FRINGE:
1276 return x - left_x;
1278 case ON_RIGHT_FRINGE:
1279 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
1281 case ON_LEFT_MARGIN:
1282 return (x - left_x
1283 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1284 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
1286 case ON_RIGHT_MARGIN:
1287 return (x + 1
1288 - ((w->pseudo_window_p)
1289 ? WINDOW_PIXEL_WIDTH (w)
1290 : WINDOW_BOX_RIGHT_EDGE_X (w))
1291 + window_box_width (w, RIGHT_MARGIN_AREA)
1292 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1293 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
1296 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
1297 return 0;
1301 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
1302 Scoordinates_in_window_p, 2, 2, 0,
1303 doc: /* Return non-nil if COORDINATES are in WINDOW.
1304 WINDOW must be a live window and defaults to the selected one.
1305 COORDINATES is a cons of the form (X . Y), X and Y being distances
1306 measured in characters from the upper-left corner of the frame.
1307 \(0 . 0) denotes the character in the upper left corner of the
1308 frame.
1309 If COORDINATES are in the text portion of WINDOW,
1310 the coordinates relative to the window are returned.
1311 If they are in the bottom divider of WINDOW, `bottom-divider' is returned.
1312 If they are in the right divider of WINDOW, `right-divider' is returned.
1313 If they are in the mode line of WINDOW, `mode-line' is returned.
1314 If they are in the header line of WINDOW, `header-line' is returned.
1315 If they are in the left fringe of WINDOW, `left-fringe' is returned.
1316 If they are in the right fringe of WINDOW, `right-fringe' is returned.
1317 If they are on the border between WINDOW and its right sibling,
1318 `vertical-line' is returned.
1319 If they are in the windows's left or right marginal areas, `left-margin'\n\
1320 or `right-margin' is returned. */)
1321 (register Lisp_Object coordinates, Lisp_Object window)
1323 struct window *w;
1324 struct frame *f;
1325 int x, y;
1326 Lisp_Object lx, ly;
1328 w = decode_live_window (window);
1329 f = XFRAME (w->frame);
1330 CHECK_CONS (coordinates);
1331 lx = Fcar (coordinates);
1332 ly = Fcdr (coordinates);
1333 CHECK_NUMBER_OR_FLOAT (lx);
1334 CHECK_NUMBER_OR_FLOAT (ly);
1335 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1336 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
1338 switch (coordinates_in_window (w, x, y))
1340 case ON_NOTHING:
1341 return Qnil;
1343 case ON_TEXT:
1344 /* Convert X and Y to window relative pixel coordinates, and
1345 return the canonical char units. */
1346 x -= window_box_left (w, TEXT_AREA);
1347 y -= WINDOW_TOP_EDGE_Y (w);
1348 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1349 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
1351 case ON_MODE_LINE:
1352 return Qmode_line;
1354 case ON_VERTICAL_BORDER:
1355 return Qvertical_line;
1357 case ON_HEADER_LINE:
1358 return Qheader_line;
1360 case ON_LEFT_FRINGE:
1361 return Qleft_fringe;
1363 case ON_RIGHT_FRINGE:
1364 return Qright_fringe;
1366 case ON_LEFT_MARGIN:
1367 return Qleft_margin;
1369 case ON_RIGHT_MARGIN:
1370 return Qright_margin;
1372 case ON_VERTICAL_SCROLL_BAR:
1373 /* Historically we are supposed to return nil in this case. */
1374 return Qnil;
1376 case ON_HORIZONTAL_SCROLL_BAR:
1377 return Qnil;
1379 case ON_RIGHT_DIVIDER:
1380 return Qright_divider;
1382 case ON_BOTTOM_DIVIDER:
1383 return Qbottom_divider;
1385 default:
1386 emacs_abort ();
1391 /* Callback for foreach_window, used in window_from_coordinates.
1392 Check if window W contains coordinates specified by USER_DATA which
1393 is actually a pointer to a struct check_window_data CW.
1395 Check if window W contains coordinates *CW->x and *CW->y. If it
1396 does, return W in *CW->window, as Lisp_Object, and return in
1397 *CW->part the part of the window under coordinates *X,*Y. Return
1398 false from this function to stop iterating over windows. */
1400 struct check_window_data
1402 Lisp_Object *window;
1403 int x, y;
1404 enum window_part *part;
1407 static bool
1408 check_window_containing (struct window *w, void *user_data)
1410 struct check_window_data *cw = user_data;
1411 enum window_part found = coordinates_in_window (w, cw->x, cw->y);
1412 if (found == ON_NOTHING)
1413 return true;
1414 else
1416 *cw->part = found;
1417 XSETWINDOW (*cw->window, w);
1418 return false;
1423 /* Find the window containing frame-relative pixel position X/Y and
1424 return it as a Lisp_Object.
1426 If X, Y is on one of the window's special `window_part' elements,
1427 set *PART to the id of that element.
1429 If there is no window under X, Y return nil and leave *PART
1430 unmodified. TOOL_BAR_P means detect tool-bar windows.
1432 This function was previously implemented with a loop cycling over
1433 windows with Fnext_window, and starting with the frame's selected
1434 window. It turned out that this doesn't work with an
1435 implementation of next_window using Vwindow_list, because
1436 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1437 tree of F when this function is called asynchronously from
1438 note_mouse_highlight. The original loop didn't terminate in this
1439 case. */
1441 Lisp_Object
1442 window_from_coordinates (struct frame *f, int x, int y,
1443 enum window_part *part, bool tool_bar_p)
1445 Lisp_Object window;
1446 struct check_window_data cw;
1447 enum window_part dummy;
1449 if (part == 0)
1450 part = &dummy;
1452 window = Qnil;
1453 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
1454 foreach_window (f, check_window_containing, &cw);
1456 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
1457 /* If not found above, see if it's in the tool bar window, if a tool
1458 bar exists. */
1459 if (NILP (window)
1460 && tool_bar_p
1461 && WINDOWP (f->tool_bar_window)
1462 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1463 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
1464 != ON_NOTHING))
1466 *part = ON_TEXT;
1467 window = f->tool_bar_window;
1469 #endif
1471 return window;
1474 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1475 doc: /* Return window containing coordinates X and Y on FRAME.
1476 FRAME must be a live frame and defaults to the selected one.
1477 The top left corner of the frame is considered to be row 0,
1478 column 0. */)
1479 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1481 struct frame *f = decode_live_frame (frame);
1483 /* Check that arguments are integers or floats. */
1484 CHECK_NUMBER_OR_FLOAT (x);
1485 CHECK_NUMBER_OR_FLOAT (y);
1487 return window_from_coordinates (f,
1488 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1489 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1490 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1491 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1492 0, false);
1495 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1496 doc: /* Return current value of point in WINDOW.
1497 WINDOW must be a live window and defaults to the selected one.
1499 For a nonselected window, this is the value point would have if that
1500 window were selected.
1502 Note that, when WINDOW is selected, the value returned is the same as
1503 that returned by `point' for WINDOW's buffer. It would be more strictly
1504 correct to return the top-level value of `point', outside of any
1505 `save-excursion' forms. But that is hard to define. */)
1506 (Lisp_Object window)
1508 register struct window *w = decode_live_window (window);
1510 if (w == XWINDOW (selected_window))
1511 return make_number (BUF_PT (XBUFFER (w->contents)));
1512 else
1513 return Fmarker_position (w->pointm);
1516 DEFUN ("window-old-point", Fwindow_old_point, Swindow_old_point, 0, 1, 0,
1517 doc: /* Return old value of point in WINDOW.
1518 WINDOW must be a live window and defaults to the selected one. */)
1519 (Lisp_Object window)
1521 return Fmarker_position (decode_live_window (window)->old_pointm);
1524 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1525 doc: /* Return position at which display currently starts in WINDOW.
1526 WINDOW must be a live window and defaults to the selected one.
1527 This is updated by redisplay or by calling `set-window-start'. */)
1528 (Lisp_Object window)
1530 return Fmarker_position (decode_live_window (window)->start);
1533 /* This is text temporarily removed from the doc string below.
1535 This function returns nil if the position is not currently known.
1536 That happens when redisplay is preempted and doesn't finish.
1537 If in that case you want to compute where the end of the window would
1538 have been if redisplay had finished, do this:
1539 (save-excursion
1540 (goto-char (window-start window))
1541 (vertical-motion (1- (window-height window)) window)
1542 (point))") */
1544 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1545 doc: /* Return position at which display currently ends in WINDOW.
1546 WINDOW must be a live window and defaults to the selected one.
1547 This is updated by redisplay, when it runs to completion.
1548 Simply changing the buffer text or setting `window-start'
1549 does not update this value.
1550 Return nil if there is no recorded value. (This can happen if the
1551 last redisplay of WINDOW was preempted, and did not finish.)
1552 If UPDATE is non-nil, compute the up-to-date position
1553 if it isn't already recorded. */)
1554 (Lisp_Object window, Lisp_Object update)
1556 Lisp_Object value;
1557 struct window *w = decode_live_window (window);
1558 Lisp_Object buf;
1559 struct buffer *b;
1561 buf = w->contents;
1562 CHECK_BUFFER (buf);
1563 b = XBUFFER (buf);
1565 if (! NILP (update)
1566 && (windows_or_buffers_changed
1567 || !w->window_end_valid
1568 || b->clip_changed
1569 || b->prevent_redisplay_optimizations_p
1570 || window_outdated (w))
1571 /* Don't call display routines if we didn't yet create any real
1572 frames, because the glyph matrices are not yet allocated in
1573 that case. This could happen in some code that runs in the
1574 daemon during initialization (e.g., see bug#20565). */
1575 && !(noninteractive || FRAME_INITIAL_P (WINDOW_XFRAME (w))))
1577 struct text_pos startp;
1578 struct it it;
1579 struct buffer *old_buffer = NULL;
1580 void *itdata = NULL;
1582 /* Cannot use Fvertical_motion because that function doesn't
1583 cope with variable-height lines. */
1584 if (b != current_buffer)
1586 old_buffer = current_buffer;
1587 set_buffer_internal (b);
1590 /* In case W->start is out of the range, use something
1591 reasonable. This situation occurred when loading a file with
1592 `-l' containing a call to `rmail' with subsequent other
1593 commands. At the end, W->start happened to be BEG, while
1594 rmail had already narrowed the buffer. */
1595 CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
1597 itdata = bidi_shelve_cache ();
1598 start_display (&it, w, startp);
1599 move_it_vertically (&it, window_box_height (w));
1600 if (it.current_y < it.last_visible_y)
1601 move_it_past_eol (&it);
1602 value = make_number (IT_CHARPOS (it));
1603 bidi_unshelve_cache (itdata, false);
1605 if (old_buffer)
1606 set_buffer_internal (old_buffer);
1608 else
1609 XSETINT (value, BUF_Z (b) - w->window_end_pos);
1611 return value;
1614 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1615 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1616 WINDOW must be a live window and defaults to the selected one.
1617 Return POS. */)
1618 (Lisp_Object window, Lisp_Object pos)
1620 register struct window *w = decode_live_window (window);
1622 /* Type of POS is checked by Fgoto_char or set_marker_restricted ... */
1624 if (w == XWINDOW (selected_window))
1626 if (XBUFFER (w->contents) == current_buffer)
1627 Fgoto_char (pos);
1628 else
1630 struct buffer *old_buffer = current_buffer;
1632 /* ... but here we want to catch type error before buffer change. */
1633 CHECK_NUMBER_COERCE_MARKER (pos);
1634 set_buffer_internal (XBUFFER (w->contents));
1635 Fgoto_char (pos);
1636 set_buffer_internal (old_buffer);
1639 else
1641 set_marker_restricted (w->pointm, pos, w->contents);
1642 /* We have to make sure that redisplay updates the window to show
1643 the new value of point. */
1644 wset_redisplay (w);
1647 return pos;
1650 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1651 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1652 WINDOW must be a live window and defaults to the selected one. Return
1653 POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
1654 overriding motion of point in order to display at this exact start. */)
1655 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1657 register struct window *w = decode_live_window (window);
1659 set_marker_restricted (w->start, pos, w->contents);
1660 /* This is not right, but much easier than doing what is right. */
1661 w->start_at_line_beg = false;
1662 if (NILP (noforce))
1663 w->force_start = true;
1664 w->update_mode_line = true;
1665 /* Bug#15957. */
1666 w->window_end_valid = false;
1667 wset_redisplay (w);
1669 return pos;
1672 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1673 Spos_visible_in_window_p, 0, 3, 0,
1674 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1675 WINDOW must be a live window and defaults to the selected one.
1677 Return nil if that position is scrolled vertically out of view. If a
1678 character is only partially visible, nil is returned, unless the
1679 optional argument PARTIALLY is non-nil. If POS is only out of view
1680 because of horizontal scrolling, return non-nil. If POS is t, it
1681 specifies the position of the last visible glyph in WINDOW. POS
1682 defaults to point in WINDOW; WINDOW defaults to the selected window.
1684 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
1685 the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
1686 where X and Y are the pixel coordinates relative to the top left corner
1687 of the window. The remaining elements are omitted if the character after
1688 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1689 off-window at the top and bottom of the screen line ("row") containing
1690 POS, ROWH is the visible height of that row, and VPOS is the row number
1691 \(zero-based). */)
1692 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1694 struct window *w;
1695 EMACS_INT posint;
1696 struct buffer *buf;
1697 struct text_pos top;
1698 Lisp_Object in_window = Qnil;
1699 int rtop, rbot, rowh, vpos;
1700 bool fully_p = true;
1701 int x, y;
1703 w = decode_live_window (window);
1704 buf = XBUFFER (w->contents);
1705 SET_TEXT_POS_FROM_MARKER (top, w->start);
1707 if (EQ (pos, Qt))
1708 posint = -1;
1709 else if (!NILP (pos))
1711 CHECK_NUMBER_COERCE_MARKER (pos);
1712 posint = XINT (pos);
1714 else if (w == XWINDOW (selected_window))
1715 posint = PT;
1716 else
1717 posint = marker_position (w->pointm);
1719 /* If position is above window start or outside buffer boundaries,
1720 or if window start is out of range, position is not visible. */
1721 if ((EQ (pos, Qt)
1722 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
1723 && CHARPOS (top) >= BUF_BEGV (buf)
1724 && CHARPOS (top) <= BUF_ZV (buf)
1725 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos))
1727 fully_p = !rtop && !rbot;
1728 if (!NILP (partially) || fully_p)
1729 in_window = Qt;
1732 if (!NILP (in_window) && !NILP (partially))
1734 Lisp_Object part = Qnil;
1735 if (!fully_p)
1736 part = list4i (rtop, rbot, rowh, vpos);
1737 in_window = Fcons (make_number (x),
1738 Fcons (make_number (y), part));
1741 return in_window;
1744 DEFUN ("window-line-height", Fwindow_line_height,
1745 Swindow_line_height, 0, 2, 0,
1746 doc: /* Return height in pixels of text line LINE in window WINDOW.
1747 WINDOW must be a live window and defaults to the selected one.
1749 Return height of current line if LINE is omitted or nil. Return height of
1750 header or mode line if LINE is `header-line' or `mode-line'.
1751 Otherwise, LINE is a text line number starting from 0. A negative number
1752 counts from the end of the window.
1754 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
1755 in pixels of the visible part of the line, VPOS and YPOS are the
1756 vertical position in lines and pixels of the line, relative to the top
1757 of the first text line, and OFFBOT is the number of off-window pixels at
1758 the bottom of the text line. If there are off-window pixels at the top
1759 of the (first) text line, YPOS is negative.
1761 Return nil if window display is not up-to-date. In that case, use
1762 `pos-visible-in-window-p' to obtain the information. */)
1763 (Lisp_Object line, Lisp_Object window)
1765 register struct window *w;
1766 register struct buffer *b;
1767 struct glyph_row *row, *end_row;
1768 int max_y, crop, i;
1769 EMACS_INT n;
1771 w = decode_live_window (window);
1773 if (noninteractive || w->pseudo_window_p)
1774 return Qnil;
1776 CHECK_BUFFER (w->contents);
1777 b = XBUFFER (w->contents);
1779 /* Fail if current matrix is not up-to-date. */
1780 if (!w->window_end_valid
1781 || windows_or_buffers_changed
1782 || b->clip_changed
1783 || b->prevent_redisplay_optimizations_p
1784 || window_outdated (w))
1785 return Qnil;
1787 if (NILP (line))
1789 i = w->cursor.vpos;
1790 if (i < 0 || i >= w->current_matrix->nrows
1791 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
1792 return Qnil;
1793 max_y = window_text_bottom_y (w);
1794 goto found_row;
1797 if (EQ (line, Qheader_line))
1799 if (!WINDOW_WANTS_HEADER_LINE_P (w))
1800 return Qnil;
1801 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1802 return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
1805 if (EQ (line, Qmode_line))
1807 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1808 return (row->enabled_p ?
1809 list4i (row->height,
1810 0, /* not accurate */
1811 (WINDOW_HEADER_LINE_HEIGHT (w)
1812 + window_text_bottom_y (w)),
1814 : Qnil);
1817 CHECK_NUMBER (line);
1818 n = XINT (line);
1820 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1821 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
1822 max_y = window_text_bottom_y (w);
1823 i = 0;
1825 while ((n < 0 || i < n)
1826 && row <= end_row && row->enabled_p
1827 && row->y + row->height < max_y)
1828 row++, i++;
1830 if (row > end_row || !row->enabled_p)
1831 return Qnil;
1833 if (++n < 0)
1835 if (-n > i)
1836 return Qnil;
1837 row += n;
1838 i += n;
1841 found_row:
1842 crop = max (0, (row->y + row->height) - max_y);
1843 return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
1846 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1847 0, 1, 0,
1848 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1849 More precisely, return the value assigned by the last call of
1850 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1851 never called with WINDOW as its argument, or the value set by that
1852 function was internally reset since its last call. WINDOW must be a
1853 live window and defaults to the selected one.
1855 When a window is dedicated to its buffer, `display-buffer' will refrain
1856 from displaying another buffer in it. `get-lru-window' and
1857 `get-largest-window' treat dedicated windows specially.
1858 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1859 `kill-buffer' can delete a dedicated window and the containing frame.
1861 Functions like `set-window-buffer' may change the buffer displayed by a
1862 window, unless that window is "strongly" dedicated to its buffer, that
1863 is the value returned by `window-dedicated-p' is t. */)
1864 (Lisp_Object window)
1866 return decode_live_window (window)->dedicated;
1869 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1870 Sset_window_dedicated_p, 2, 2, 0,
1871 doc: /* Mark WINDOW as dedicated according to FLAG.
1872 WINDOW must be a live window and defaults to the selected one. FLAG
1873 non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
1874 mark WINDOW as non-dedicated. Return FLAG.
1876 When a window is dedicated to its buffer, `display-buffer' will refrain
1877 from displaying another buffer in it. `get-lru-window' and
1878 `get-largest-window' treat dedicated windows specially.
1879 `delete-windows-on', `replace-buffer-in-windows', `quit-window',
1880 `quit-restore-window' and `kill-buffer' can delete a dedicated window
1881 and the containing frame.
1883 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1884 its buffer. Functions like `set-window-buffer' may change the buffer
1885 displayed by a window, unless that window is strongly dedicated to its
1886 buffer. If and when `set-window-buffer' displays another buffer in a
1887 window, it also makes sure that the window is no more dedicated. */)
1888 (Lisp_Object window, Lisp_Object flag)
1890 wset_dedicated (decode_live_window (window), flag);
1891 return flag;
1894 DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
1895 0, 1, 0,
1896 doc: /* Return buffers previously shown in WINDOW.
1897 WINDOW must be a live window and defaults to the selected one.
1899 The return value is a list of elements (BUFFER WINDOW-START POS),
1900 where BUFFER is a buffer, WINDOW-START is the start position of the
1901 window for that buffer, and POS is a window-specific point value. */)
1902 (Lisp_Object window)
1904 return decode_live_window (window)->prev_buffers;
1907 DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
1908 Sset_window_prev_buffers, 2, 2, 0,
1909 doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
1910 WINDOW must be a live window and defaults to the selected one.
1912 PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS),
1913 where BUFFER is a buffer, WINDOW-START is the start position of the
1914 window for that buffer, and POS is a window-specific point value. */)
1915 (Lisp_Object window, Lisp_Object prev_buffers)
1917 wset_prev_buffers (decode_live_window (window), prev_buffers);
1918 return prev_buffers;
1921 DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
1922 0, 1, 0,
1923 doc: /* Return list of buffers recently re-shown in WINDOW.
1924 WINDOW must be a live window and defaults to the selected one. */)
1925 (Lisp_Object window)
1927 return decode_live_window (window)->next_buffers;
1930 DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
1931 Sset_window_next_buffers, 2, 2, 0,
1932 doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
1933 WINDOW must be a live window and defaults to the selected one.
1934 NEXT-BUFFERS should be a list of buffers. */)
1935 (Lisp_Object window, Lisp_Object next_buffers)
1937 wset_next_buffers (decode_live_window (window), next_buffers);
1938 return next_buffers;
1941 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1942 0, 1, 0,
1943 doc: /* Return the parameters of WINDOW and their values.
1944 WINDOW must be a valid window and defaults to the selected one. The
1945 return value is a list of elements of the form (PARAMETER . VALUE). */)
1946 (Lisp_Object window)
1948 return Fcopy_alist (decode_valid_window (window)->window_parameters);
1951 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1952 2, 2, 0,
1953 doc: /* Return WINDOW's value for PARAMETER.
1954 WINDOW can be any window and defaults to the selected one. */)
1955 (Lisp_Object window, Lisp_Object parameter)
1957 Lisp_Object result;
1959 result = Fassq (parameter, decode_any_window (window)->window_parameters);
1960 return CDR_SAFE (result);
1963 DEFUN ("set-window-parameter", Fset_window_parameter,
1964 Sset_window_parameter, 3, 3, 0,
1965 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1966 WINDOW can be any window and defaults to the selected one.
1967 Return VALUE. */)
1968 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
1970 register struct window *w = decode_any_window (window);
1971 Lisp_Object old_alist_elt;
1973 old_alist_elt = Fassq (parameter, w->window_parameters);
1974 if (NILP (old_alist_elt))
1975 wset_window_parameters
1976 (w, Fcons (Fcons (parameter, value), w->window_parameters));
1977 else
1978 Fsetcdr (old_alist_elt, value);
1979 return value;
1982 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1983 0, 1, 0,
1984 doc: /* Return the display-table that WINDOW is using.
1985 WINDOW must be a live window and defaults to the selected one. */)
1986 (Lisp_Object window)
1988 return decode_live_window (window)->display_table;
1991 /* Get the display table for use on window W. This is either W's
1992 display table or W's buffer's display table. Ignore the specified
1993 tables if they are not valid; if no valid table is specified,
1994 return 0. */
1996 struct Lisp_Char_Table *
1997 window_display_table (struct window *w)
1999 struct Lisp_Char_Table *dp = NULL;
2001 if (DISP_TABLE_P (w->display_table))
2002 dp = XCHAR_TABLE (w->display_table);
2003 else if (BUFFERP (w->contents))
2005 struct buffer *b = XBUFFER (w->contents);
2007 if (DISP_TABLE_P (BVAR (b, display_table)))
2008 dp = XCHAR_TABLE (BVAR (b, display_table));
2009 else if (DISP_TABLE_P (Vstandard_display_table))
2010 dp = XCHAR_TABLE (Vstandard_display_table);
2013 return dp;
2016 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
2017 doc: /* Set WINDOW's display-table to TABLE.
2018 WINDOW must be a live window and defaults to the selected one. */)
2019 (register Lisp_Object window, Lisp_Object table)
2021 wset_display_table (decode_live_window (window), table);
2022 return table;
2025 /* Record info on buffer window W is displaying
2026 when it is about to cease to display that buffer. */
2027 static void
2028 unshow_buffer (register struct window *w)
2030 Lisp_Object buf = w->contents;
2031 struct buffer *b = XBUFFER (buf);
2033 eassert (b == XMARKER (w->pointm)->buffer);
2035 #if false
2036 if (w == XWINDOW (selected_window)
2037 || ! EQ (buf, XWINDOW (selected_window)->contents))
2038 /* Do this except when the selected window's buffer
2039 is being removed from some other window. */
2040 #endif
2041 /* last_window_start records the start position that this buffer
2042 had in the last window to be disconnected from it.
2043 Now that this statement is unconditional,
2044 it is possible for the buffer to be displayed in the
2045 selected window, while last_window_start reflects another
2046 window which was recently showing the same buffer.
2047 Some people might say that might be a good thing. Let's see. */
2048 b->last_window_start = marker_position (w->start);
2050 /* Point in the selected window's buffer
2051 is actually stored in that buffer, and the window's pointm isn't used.
2052 So don't clobber point in that buffer. */
2053 if (! EQ (buf, XWINDOW (selected_window)->contents)
2054 /* Don't clobber point in current buffer either (this could be
2055 useful in connection with bug#12208).
2056 && XBUFFER (buf) != current_buffer */
2057 /* This line helps to fix Horsley's testbug.el bug. */
2058 && !(WINDOWP (BVAR (b, last_selected_window))
2059 && w != XWINDOW (BVAR (b, last_selected_window))
2060 && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->contents)))
2061 temp_set_point_both (b,
2062 clip_to_bounds (BUF_BEGV (b),
2063 marker_position (w->pointm),
2064 BUF_ZV (b)),
2065 clip_to_bounds (BUF_BEGV_BYTE (b),
2066 marker_byte_position (w->pointm),
2067 BUF_ZV_BYTE (b)));
2069 if (WINDOWP (BVAR (b, last_selected_window))
2070 && w == XWINDOW (BVAR (b, last_selected_window)))
2071 bset_last_selected_window (b, Qnil);
2074 /* Put NEW into the window structure in place of OLD. SETFLAG false
2075 means change window structure only. Otherwise store geometry and
2076 other settings as well. */
2077 static void
2078 replace_window (Lisp_Object old, Lisp_Object new, bool setflag)
2080 Lisp_Object tem;
2081 struct window *o = XWINDOW (old), *n = XWINDOW (new);
2083 /* If OLD is its frame's root window, then NEW is the new
2084 root window for that frame. */
2085 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
2086 fset_root_window (XFRAME (o->frame), new);
2088 if (setflag)
2090 n->pixel_left = o->pixel_left;
2091 n->pixel_top = o->pixel_top;
2092 n->pixel_width = o->pixel_width;
2093 n->pixel_height = o->pixel_height;
2094 n->left_col = o->left_col;
2095 n->top_line = o->top_line;
2096 n->total_cols = o->total_cols;
2097 n->total_lines = o->total_lines;
2098 wset_normal_cols (n, o->normal_cols);
2099 wset_normal_cols (o, make_float (1.0));
2100 wset_normal_lines (n, o->normal_lines);
2101 wset_normal_lines (o, make_float (1.0));
2102 n->desired_matrix = n->current_matrix = 0;
2103 n->vscroll = 0;
2104 memset (&n->cursor, 0, sizeof (n->cursor));
2105 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
2106 n->last_cursor_vpos = 0;
2107 #ifdef HAVE_WINDOW_SYSTEM
2108 n->phys_cursor_type = NO_CURSOR;
2109 n->phys_cursor_width = -1;
2110 #endif
2111 n->must_be_updated_p = false;
2112 n->pseudo_window_p = false;
2113 n->window_end_vpos = 0;
2114 n->window_end_pos = 0;
2115 n->window_end_valid = false;
2118 tem = o->next;
2119 wset_next (n, tem);
2120 if (!NILP (tem))
2121 wset_prev (XWINDOW (tem), new);
2123 tem = o->prev;
2124 wset_prev (n, tem);
2125 if (!NILP (tem))
2126 wset_next (XWINDOW (tem), new);
2128 tem = o->parent;
2129 wset_parent (n, tem);
2130 if (!NILP (tem) && EQ (XWINDOW (tem)->contents, old))
2131 wset_combination (XWINDOW (tem), XWINDOW (tem)->horizontal, new);
2134 /* If window WINDOW and its parent window are iso-combined, merge
2135 WINDOW's children into those of its parent window and mark WINDOW as
2136 deleted. */
2138 static void
2139 recombine_windows (Lisp_Object window)
2141 struct window *w, *p, *c;
2142 Lisp_Object parent, child;
2143 bool horflag;
2145 w = XWINDOW (window);
2146 parent = w->parent;
2147 if (!NILP (parent) && NILP (w->combination_limit))
2149 p = XWINDOW (parent);
2150 if (WINDOWP (p->contents) && WINDOWP (w->contents)
2151 && p->horizontal == w->horizontal)
2152 /* WINDOW and PARENT are both either a vertical or a horizontal
2153 combination. */
2155 horflag = WINDOW_HORIZONTAL_COMBINATION_P (w);
2156 child = w->contents;
2157 c = XWINDOW (child);
2159 /* Splice WINDOW's children into its parent's children and
2160 assign new normal sizes. */
2161 if (NILP (w->prev))
2162 wset_combination (p, horflag, child);
2163 else
2165 wset_prev (c, w->prev);
2166 wset_next (XWINDOW (w->prev), child);
2169 while (c)
2171 wset_parent (c, parent);
2173 if (horflag)
2174 wset_normal_cols
2175 (c, make_float ((double) c->pixel_width
2176 / (double) p->pixel_width));
2177 else
2178 wset_normal_lines
2179 (c, make_float ((double) c->pixel_height
2180 / (double) p->pixel_height));
2182 if (NILP (c->next))
2184 if (!NILP (w->next))
2186 wset_next (c, w->next);
2187 wset_prev (XWINDOW (c->next), child);
2190 c = 0;
2192 else
2194 child = c->next;
2195 c = XWINDOW (child);
2199 /* WINDOW can be deleted now. */
2200 wset_combination (w, false, Qnil);
2205 /* If WINDOW can be deleted, delete it. */
2206 static void
2207 delete_deletable_window (Lisp_Object window)
2209 if (!NILP (call1 (Qwindow_deletable_p, window)))
2210 call1 (Qdelete_window, window);
2213 /***********************************************************************
2214 Window List
2215 ***********************************************************************/
2217 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
2218 pointer. This is a callback function for foreach_window, used in
2219 the window_list function. */
2221 static bool
2222 add_window_to_list (struct window *w, void *user_data)
2224 Lisp_Object *list = user_data;
2225 Lisp_Object window;
2226 XSETWINDOW (window, w);
2227 *list = Fcons (window, *list);
2228 return true;
2232 /* Return a list of all windows, for use by next_window. If
2233 Vwindow_list is a list, return that list. Otherwise, build a new
2234 list, cache it in Vwindow_list, and return that. */
2236 Lisp_Object
2237 window_list (void)
2239 if (!CONSP (Vwindow_list))
2241 Lisp_Object tail, frame;
2243 Vwindow_list = Qnil;
2244 FOR_EACH_FRAME (tail, frame)
2246 Lisp_Object arglist = Qnil;
2248 /* We are visiting windows in canonical order, and add
2249 new windows at the front of args[1], which means we
2250 have to reverse this list at the end. */
2251 foreach_window (XFRAME (frame), add_window_to_list, &arglist);
2252 arglist = Fnreverse (arglist);
2253 Vwindow_list = CALLN (Fnconc, Vwindow_list, arglist);
2257 return Vwindow_list;
2261 /* Value is true if WINDOW satisfies the constraints given by
2262 OWINDOW, MINIBUF and ALL_FRAMES.
2264 MINIBUF t means WINDOW may be minibuffer windows.
2265 `lambda' means WINDOW may not be a minibuffer window.
2266 a window means a specific minibuffer window
2268 ALL_FRAMES t means search all frames,
2269 nil means search just current frame,
2270 `visible' means search just visible frames on the
2271 current terminal,
2272 0 means search visible and iconified frames on the
2273 current terminal,
2274 a window means search the frame that window belongs to,
2275 a frame means consider windows on that frame, only. */
2277 static bool
2278 candidate_window_p (Lisp_Object window, Lisp_Object owindow,
2279 Lisp_Object minibuf, Lisp_Object all_frames)
2281 struct window *w = XWINDOW (window);
2282 struct frame *f = XFRAME (w->frame);
2283 bool candidate_p = true;
2285 if (!BUFFERP (w->contents))
2286 candidate_p = false;
2287 else if (MINI_WINDOW_P (w)
2288 && (EQ (minibuf, Qlambda)
2289 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
2291 /* If MINIBUF is `lambda' don't consider any mini-windows.
2292 If it is a window, consider only that one. */
2293 candidate_p = false;
2295 else if (EQ (all_frames, Qt))
2296 candidate_p = true;
2297 else if (NILP (all_frames))
2299 eassert (WINDOWP (owindow));
2300 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
2302 else if (EQ (all_frames, Qvisible))
2304 candidate_p = FRAME_VISIBLE_P (f)
2305 && (FRAME_TERMINAL (XFRAME (w->frame))
2306 == FRAME_TERMINAL (XFRAME (selected_frame)));
2309 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2311 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2312 #ifdef HAVE_X_WINDOWS
2313 /* Yuck!! If we've just created the frame and the
2314 window-manager requested the user to place it
2315 manually, the window may still not be considered
2316 `visible'. I'd argue it should be at least
2317 something like `iconified', but don't know how to do
2318 that yet. --Stef */
2319 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
2320 && !f->output_data.x->has_been_visible)
2321 #endif
2323 && (FRAME_TERMINAL (XFRAME (w->frame))
2324 == FRAME_TERMINAL (XFRAME (selected_frame)));
2326 else if (WINDOWP (all_frames))
2327 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
2328 || EQ (XWINDOW (all_frames)->frame, w->frame)
2329 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
2330 else if (FRAMEP (all_frames))
2331 candidate_p = EQ (all_frames, w->frame);
2333 return candidate_p;
2337 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
2338 Fwindow_list. See candidate_window_p for the meaning of WINDOW,
2339 MINIBUF, and ALL_FRAMES. */
2341 static void
2342 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
2344 struct window *w = decode_live_window (*window);
2346 XSETWINDOW (*window, w);
2347 /* MINIBUF nil may or may not include minibuffers. Decide if it
2348 does. */
2349 if (NILP (*minibuf))
2350 *minibuf = minibuf_level ? minibuf_window : Qlambda;
2351 else if (!EQ (*minibuf, Qt))
2352 *minibuf = Qlambda;
2354 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
2355 => count none of them, or a specific minibuffer window (the
2356 active one) to count. */
2358 /* ALL_FRAMES nil doesn't specify which frames to include. */
2359 if (NILP (*all_frames))
2360 *all_frames
2361 = (!EQ (*minibuf, Qlambda)
2362 ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame))
2363 : Qnil);
2364 else if (EQ (*all_frames, Qvisible))
2366 else if (EQ (*all_frames, make_number (0)))
2368 else if (FRAMEP (*all_frames))
2370 else if (!EQ (*all_frames, Qt))
2371 *all_frames = Qnil;
2375 /* Return the next or previous window of WINDOW in cyclic ordering
2376 of windows. NEXT_P means return the next window. See the
2377 documentation string of next-window for the meaning of MINIBUF and
2378 ALL_FRAMES. */
2380 static Lisp_Object
2381 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
2382 bool next_p)
2384 decode_next_window_args (&window, &minibuf, &all_frames);
2386 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
2387 return the first window on the frame. */
2388 if (FRAMEP (all_frames)
2389 && !EQ (all_frames, XWINDOW (window)->frame))
2390 return Fframe_first_window (all_frames);
2392 if (next_p)
2394 Lisp_Object list;
2396 /* Find WINDOW in the list of all windows. */
2397 list = Fmemq (window, window_list ());
2399 /* Scan forward from WINDOW to the end of the window list. */
2400 if (CONSP (list))
2401 for (list = XCDR (list); CONSP (list); list = XCDR (list))
2402 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2403 break;
2405 /* Scan from the start of the window list up to WINDOW. */
2406 if (!CONSP (list))
2407 for (list = Vwindow_list;
2408 CONSP (list) && !EQ (XCAR (list), window);
2409 list = XCDR (list))
2410 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2411 break;
2413 if (CONSP (list))
2414 window = XCAR (list);
2416 else
2418 Lisp_Object candidate, list;
2420 /* Scan through the list of windows for candidates. If there are
2421 candidate windows in front of WINDOW, the last one of these
2422 is the one we want. If there are candidates following WINDOW
2423 in the list, again the last one of these is the one we want. */
2424 candidate = Qnil;
2425 for (list = window_list (); CONSP (list); list = XCDR (list))
2427 if (EQ (XCAR (list), window))
2429 if (WINDOWP (candidate))
2430 break;
2432 else if (candidate_window_p (XCAR (list), window, minibuf,
2433 all_frames))
2434 candidate = XCAR (list);
2437 if (WINDOWP (candidate))
2438 window = candidate;
2441 return window;
2445 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2446 doc: /* Return live window after WINDOW in the cyclic ordering of windows.
2447 WINDOW must be a live window and defaults to the selected one. The
2448 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2449 consider.
2451 MINIBUF nil or omitted means consider the minibuffer window only if the
2452 minibuffer is active. MINIBUF t means consider the minibuffer window
2453 even if the minibuffer is not active. Any other value means do not
2454 consider the minibuffer window even if the minibuffer is active.
2456 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2457 plus the minibuffer window if specified by the MINIBUF argument. If the
2458 minibuffer counts, consider all windows on all frames that share that
2459 minibuffer too. The following non-nil values of ALL-FRAMES have special
2460 meanings:
2462 - t means consider all windows on all existing frames.
2464 - `visible' means consider all windows on all visible frames.
2466 - 0 (the number zero) means consider all windows on all visible and
2467 iconified frames.
2469 - A frame means consider all windows on that frame only.
2471 Anything else means consider all windows on WINDOW's frame and no
2472 others.
2474 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2475 `next-window' to iterate through the entire cycle of acceptable
2476 windows, eventually ending up back at the window you started with.
2477 `previous-window' traverses the same cycle, in the reverse order. */)
2478 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2480 return next_window (window, minibuf, all_frames, true);
2484 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2485 doc: /* Return live window before WINDOW in the cyclic ordering of windows.
2486 WINDOW must be a live window and defaults to the selected one. The
2487 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2488 consider.
2490 MINIBUF nil or omitted means consider the minibuffer window only if the
2491 minibuffer is active. MINIBUF t means consider the minibuffer window
2492 even if the minibuffer is not active. Any other value means do not
2493 consider the minibuffer window even if the minibuffer is active.
2495 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2496 plus the minibuffer window if specified by the MINIBUF argument. If the
2497 minibuffer counts, consider all windows on all frames that share that
2498 minibuffer too. The following non-nil values of ALL-FRAMES have special
2499 meanings:
2501 - t means consider all windows on all existing frames.
2503 - `visible' means consider all windows on all visible frames.
2505 - 0 (the number zero) means consider all windows on all visible and
2506 iconified frames.
2508 - A frame means consider all windows on that frame only.
2510 Anything else means consider all windows on WINDOW's frame and no
2511 others.
2513 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2514 use `previous-window' to iterate through the entire cycle of
2515 acceptable windows, eventually ending up back at the window you
2516 started with. `next-window' traverses the same cycle, in the
2517 reverse order. */)
2518 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2520 return next_window (window, minibuf, all_frames, false);
2524 /* Return a list of windows in cyclic ordering. Arguments are like
2525 for `next-window'. */
2527 static Lisp_Object
2528 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2530 Lisp_Object tail, list, rest;
2532 decode_next_window_args (&window, &minibuf, &all_frames);
2533 list = Qnil;
2535 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2536 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2537 list = Fcons (XCAR (tail), list);
2539 /* Rotate the list to start with WINDOW. */
2540 list = Fnreverse (list);
2541 rest = Fmemq (window, list);
2542 if (!NILP (rest) && !EQ (rest, list))
2544 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2546 XSETCDR (tail, Qnil);
2547 list = nconc2 (rest, list);
2549 return list;
2553 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2554 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2555 FRAME nil or omitted means use the selected frame.
2556 WINDOW nil or omitted means use the window selected within FRAME.
2557 MINIBUF t means include the minibuffer window, even if it isn't active.
2558 MINIBUF nil or omitted means include the minibuffer window only
2559 if it's active.
2560 MINIBUF neither nil nor t means never include the minibuffer window. */)
2561 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2563 if (NILP (window))
2564 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2565 CHECK_WINDOW (window);
2566 if (NILP (frame))
2567 frame = selected_frame;
2569 if (!EQ (frame, XWINDOW (window)->frame))
2570 error ("Window is on a different frame");
2572 return window_list_1 (window, minibuf, frame);
2576 DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2577 doc: /* Return a list of all live windows.
2578 WINDOW specifies the first window to list and defaults to the selected
2579 window.
2581 Optional argument MINIBUF nil or omitted means consider the minibuffer
2582 window only if the minibuffer is active. MINIBUF t means consider the
2583 minibuffer window even if the minibuffer is not active. Any other value
2584 means do not consider the minibuffer window even if the minibuffer is
2585 active.
2587 Optional argument ALL-FRAMES nil or omitted means consider all windows
2588 on WINDOW's frame, plus the minibuffer window if specified by the
2589 MINIBUF argument. If the minibuffer counts, consider all windows on all
2590 frames that share that minibuffer too. The following non-nil values of
2591 ALL-FRAMES have special meanings:
2593 - t means consider all windows on all existing frames.
2595 - `visible' means consider all windows on all visible frames.
2597 - 0 (the number zero) means consider all windows on all visible and
2598 iconified frames.
2600 - A frame means consider all windows on that frame only.
2602 Anything else means consider all windows on WINDOW's frame and no
2603 others.
2605 If WINDOW is not on the list of windows returned, some other window will
2606 be listed first but no error is signaled. */)
2607 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2609 return window_list_1 (window, minibuf, all_frames);
2612 /* Look at all windows, performing an operation specified by TYPE
2613 with argument OBJ.
2614 If FRAMES is Qt, look at all frames;
2615 Qnil, look at just the selected frame;
2616 Qvisible, look at visible frames;
2617 a frame, just look at windows on that frame.
2618 If MINI, perform the operation on minibuffer windows too. */
2620 enum window_loop
2622 WINDOW_LOOP_UNUSED,
2623 GET_BUFFER_WINDOW, /* Arg is buffer */
2624 REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
2625 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2626 CHECK_ALL_WINDOWS /* Arg is ignored */
2629 static Lisp_Object
2630 window_loop (enum window_loop type, Lisp_Object obj, bool mini,
2631 Lisp_Object frames)
2633 Lisp_Object window, windows, best_window, frame_arg;
2634 bool frame_best_window_flag = false;
2635 struct frame *f;
2636 struct gcpro gcpro1;
2638 /* If we're only looping through windows on a particular frame,
2639 frame points to that frame. If we're looping through windows
2640 on all frames, frame is 0. */
2641 if (FRAMEP (frames))
2642 f = XFRAME (frames);
2643 else if (NILP (frames))
2644 f = SELECTED_FRAME ();
2645 else
2646 f = NULL;
2648 if (f)
2649 frame_arg = Qlambda;
2650 else if (EQ (frames, make_number (0)))
2651 frame_arg = frames;
2652 else if (EQ (frames, Qvisible))
2653 frame_arg = frames;
2654 else
2655 frame_arg = Qt;
2657 /* frame_arg is Qlambda to stick to one frame,
2658 Qvisible to consider all visible frames,
2659 or Qt otherwise. */
2661 /* Pick a window to start with. */
2662 if (WINDOWP (obj))
2663 window = obj;
2664 else if (f)
2665 window = FRAME_SELECTED_WINDOW (f);
2666 else
2667 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2669 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2670 GCPRO1 (windows);
2671 best_window = Qnil;
2673 for (; CONSP (windows); windows = XCDR (windows))
2675 struct window *w;
2677 window = XCAR (windows);
2678 w = XWINDOW (window);
2680 /* Note that we do not pay attention here to whether the frame
2681 is visible, since Fwindow_list skips non-visible frames if
2682 that is desired, under the control of frame_arg. */
2683 if (!MINI_WINDOW_P (w)
2684 /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
2685 consider all windows. */
2686 || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
2687 || (mini && minibuf_level > 0))
2688 switch (type)
2690 case GET_BUFFER_WINDOW:
2691 if (EQ (w->contents, obj)
2692 /* Don't find any minibuffer window except the one that
2693 is currently in use. */
2694 && (!MINI_WINDOW_P (w) || EQ (window, minibuf_window)))
2696 if (EQ (window, selected_window))
2697 /* Preferably return the selected window. */
2698 RETURN_UNGCPRO (window);
2699 else if (EQ (XWINDOW (window)->frame, selected_frame)
2700 && !frame_best_window_flag)
2701 /* Prefer windows on the current frame (but don't
2702 choose another one if we have one already). */
2704 best_window = window;
2705 frame_best_window_flag = true;
2707 else if (NILP (best_window))
2708 best_window = window;
2710 break;
2712 case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
2713 /* We could simply check whether the buffer shown by window
2714 is live, and show another buffer in case it isn't. */
2715 if (EQ (w->contents, obj))
2717 /* Undedicate WINDOW. */
2718 wset_dedicated (w, Qnil);
2719 /* Make WINDOW show the buffer returned by
2720 other_buffer_safely, don't run any hooks. */
2721 set_window_buffer
2722 (window, other_buffer_safely (w->contents), false, false);
2723 /* If WINDOW is the selected window, make its buffer
2724 current. But do so only if the window shows the
2725 current buffer (Bug#6454). */
2726 if (EQ (window, selected_window)
2727 && XBUFFER (w->contents) == current_buffer)
2728 Fset_buffer (w->contents);
2730 break;
2732 case REDISPLAY_BUFFER_WINDOWS:
2733 if (EQ (w->contents, obj))
2735 mark_window_display_accurate (window, false);
2736 w->update_mode_line = true;
2737 XBUFFER (obj)->prevent_redisplay_optimizations_p = true;
2738 update_mode_lines = 27;
2739 best_window = window;
2741 break;
2743 /* Check for a leaf window that has a killed buffer
2744 or broken markers. */
2745 case CHECK_ALL_WINDOWS:
2746 if (BUFFERP (w->contents))
2748 struct buffer *b = XBUFFER (w->contents);
2750 if (!BUFFER_LIVE_P (b))
2751 emacs_abort ();
2752 if (!MARKERP (w->start) || XMARKER (w->start)->buffer != b)
2753 emacs_abort ();
2754 if (!MARKERP (w->pointm) || XMARKER (w->pointm)->buffer != b)
2755 emacs_abort ();
2757 break;
2759 case WINDOW_LOOP_UNUSED:
2760 break;
2764 UNGCPRO;
2765 return best_window;
2768 /* Used for debugging. Abort if any window has a dead buffer. */
2770 extern void check_all_windows (void) EXTERNALLY_VISIBLE;
2771 void
2772 check_all_windows (void)
2774 window_loop (CHECK_ALL_WINDOWS, Qnil, true, Qt);
2777 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2778 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2779 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
2780 the current buffer.
2782 The optional argument ALL-FRAMES specifies the frames to consider:
2784 - t means consider all windows on all existing frames.
2786 - `visible' means consider all windows on all visible frames.
2788 - 0 (the number zero) means consider all windows on all visible
2789 and iconified frames.
2791 - A frame means consider all windows on that frame only.
2793 Any other value of ALL-FRAMES means consider all windows on the
2794 selected frame and no others. */)
2795 (Lisp_Object buffer_or_name, Lisp_Object all_frames)
2797 Lisp_Object buffer;
2799 if (NILP (buffer_or_name))
2800 buffer = Fcurrent_buffer ();
2801 else
2802 buffer = Fget_buffer (buffer_or_name);
2804 if (BUFFERP (buffer))
2805 return window_loop (GET_BUFFER_WINDOW, buffer, true, all_frames);
2806 else
2807 return Qnil;
2811 static Lisp_Object
2812 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore, Lisp_Object pixelwise)
2814 return call5 (Qwindow_resize_root_window, window, delta, horizontal, ignore, pixelwise);
2817 /* Placeholder used by temacs -nw before window.el is loaded. */
2818 DEFUN ("window--sanitize-window-sizes", Fwindow__sanitize_window_sizes,
2819 Swindow__sanitize_window_sizes, 2, 2, 0,
2820 doc: /* */
2821 attributes: const)
2822 (Lisp_Object frame, Lisp_Object horizontal)
2824 return Qnil;
2827 Lisp_Object
2828 sanitize_window_sizes (Lisp_Object frame, Lisp_Object horizontal)
2830 return call2 (Qwindow_sanitize_window_sizes, frame, horizontal);
2834 static Lisp_Object
2835 window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal)
2837 return call2 (Qwindow_pixel_to_total, frame, horizontal);
2841 DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
2842 Sdelete_other_windows_internal, 0, 2, "",
2843 doc: /* Make WINDOW fill its frame.
2844 Only the frame WINDOW is on is affected. WINDOW must be a valid window
2845 and defaults to the selected one.
2847 Optional argument ROOT, if non-nil, must specify an internal window such
2848 that WINDOW is in its window subtree. If this is the case, replace ROOT
2849 by WINDOW and leave alone any windows not part of ROOT's subtree.
2851 When WINDOW is live try to reduce display jumps by keeping the text
2852 previously visible in WINDOW in the same place on the frame. Doing this
2853 depends on the value of (window-start WINDOW), so if calling this
2854 function in a program gives strange scrolling, make sure the
2855 window-start value is reasonable when this function is called. */)
2856 (Lisp_Object window, Lisp_Object root)
2858 struct window *w, *r, *s;
2859 struct frame *f;
2860 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
2861 ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0);
2862 int top IF_LINT (= 0), new_top;
2864 w = decode_valid_window (window);
2865 XSETWINDOW (window, w);
2866 f = XFRAME (w->frame);
2868 if (NILP (root))
2869 /* ROOT is the frame's root window. */
2871 root = FRAME_ROOT_WINDOW (f);
2872 r = XWINDOW (root);
2874 else
2875 /* ROOT must be an ancestor of WINDOW. */
2877 r = decode_valid_window (root);
2878 pwindow = XWINDOW (window)->parent;
2879 while (!NILP (pwindow))
2880 if (EQ (pwindow, root))
2881 break;
2882 else
2883 pwindow = XWINDOW (pwindow)->parent;
2884 if (!EQ (pwindow, root))
2885 error ("Specified root is not an ancestor of specified window");
2888 if (EQ (window, root))
2889 /* A noop. */
2890 return Qnil;
2891 /* I don't understand the "top > 0" part below. If we deal with a
2892 standalone minibuffer it would have been caught by the preceding
2893 test. */
2894 else if (MINI_WINDOW_P (w)) /* && top > 0) */
2895 error ("Can't expand minibuffer to full frame");
2897 if (BUFFERP (w->contents))
2899 startpos = marker_position (w->start);
2900 startbyte = marker_byte_position (w->start);
2901 top = (WINDOW_TOP_EDGE_LINE (w)
2902 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))));
2903 /* Make sure WINDOW is the frame's selected window. */
2904 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
2906 if (EQ (selected_frame, w->frame))
2907 Fselect_window (window, Qnil);
2908 else
2909 fset_selected_window (f, window);
2912 else
2914 /* See if the frame's selected window is a part of the window
2915 subtree rooted at WINDOW, by finding all the selected window's
2916 parents and comparing each one with WINDOW. If it isn't we
2917 need a new selected window for this frame. */
2918 swindow = FRAME_SELECTED_WINDOW (f);
2919 while (true)
2921 pwindow = swindow;
2922 while (!NILP (pwindow) && !EQ (window, pwindow))
2923 pwindow = XWINDOW (pwindow)->parent;
2925 if (EQ (window, pwindow))
2926 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
2927 as the new selected window. */
2928 break;
2929 else
2930 /* Else try the previous window of SWINDOW. */
2931 swindow = Fprevious_window (swindow, Qlambda, Qnil);
2934 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
2936 if (EQ (selected_frame, w->frame))
2937 Fselect_window (swindow, Qnil);
2938 else
2939 fset_selected_window (f, swindow);
2943 block_input ();
2944 if (!FRAME_INITIAL_P (f))
2946 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
2948 /* We are going to free the glyph matrices of WINDOW, and with
2949 that we might lose any information about glyph rows that have
2950 some of their glyphs highlighted in mouse face. (These rows
2951 are marked with a mouse_face_p flag.) If WINDOW
2952 indeed has some glyphs highlighted in mouse face, signal to
2953 frame's up-to-date hook that mouse highlight was overwritten,
2954 so that it will arrange for redisplaying the highlight. */
2955 if (EQ (hlinfo->mouse_face_window, window))
2956 reset_mouse_highlight (hlinfo);
2958 free_window_matrices (r);
2960 fset_redisplay (f);
2961 Vwindow_list = Qnil;
2962 FRAME_WINDOW_SIZES_CHANGED (f) = true;
2963 bool resize_failed = false;
2965 if (!WINDOW_LEAF_P (w))
2967 /* Resize child windows vertically. */
2968 XSETINT (delta, r->pixel_height - w->pixel_height);
2969 w->pixel_top = r->pixel_top;
2970 w->top_line = r->top_line;
2971 resize_root_window (window, delta, Qnil, Qnil, Qt);
2972 if (window_resize_check (w, false))
2974 window_resize_apply (w, false);
2975 window_pixel_to_total (w->frame, Qnil);
2977 else
2979 resize_root_window (window, delta, Qnil, Qt, Qt);
2980 if (window_resize_check (w, false))
2982 window_resize_apply (w, false);
2983 window_pixel_to_total (w->frame, Qnil);
2985 else
2986 resize_failed = true;
2989 /* Resize child windows horizontally. */
2990 if (!resize_failed)
2992 w->left_col = r->left_col;
2993 w->pixel_left = r->pixel_left;
2994 XSETINT (delta, r->pixel_width - w->pixel_width);
2995 resize_root_window (window, delta, Qt, Qnil, Qt);
2996 if (window_resize_check (w, true))
2998 window_resize_apply (w, true);
2999 window_pixel_to_total (w->frame, Qt);
3001 else
3003 resize_root_window (window, delta, Qt, Qt, Qt);
3004 if (window_resize_check (w, true))
3006 window_resize_apply (w, true);
3007 window_pixel_to_total (w->frame, Qt);
3009 else
3010 resize_failed = true;
3014 if (resize_failed)
3015 /* Play safe, if we still can ... */
3017 window = swindow;
3018 w = XWINDOW (window);
3022 /* Cleanly unlink WINDOW from window-tree. */
3023 if (!NILP (w->prev))
3024 /* Get SIBLING above (on the left of) WINDOW. */
3026 sibling = w->prev;
3027 s = XWINDOW (sibling);
3028 wset_next (s, w->next);
3029 if (!NILP (s->next))
3030 wset_prev (XWINDOW (s->next), sibling);
3032 else
3033 /* Get SIBLING below (on the right of) WINDOW. */
3035 sibling = w->next;
3036 s = XWINDOW (sibling);
3037 wset_prev (s, Qnil);
3038 wset_combination (XWINDOW (w->parent),
3039 XWINDOW (w->parent)->horizontal, sibling);
3042 /* Delete ROOT and all child windows of ROOT. */
3043 if (WINDOWP (r->contents))
3045 delete_all_child_windows (r->contents);
3046 wset_combination (r, false, Qnil);
3049 replace_window (root, window, true);
3051 /* This must become SWINDOW anyway ....... */
3052 if (BUFFERP (w->contents) && !resize_failed)
3054 /* Try to minimize scrolling, by setting the window start to the
3055 point will cause the text at the old window start to be at the
3056 same place on the frame. But don't try to do this if the
3057 window start is outside the visible portion (as might happen
3058 when the display is not current, due to typeahead). */
3059 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
3060 if (new_top != top
3061 && startpos >= BUF_BEGV (XBUFFER (w->contents))
3062 && startpos <= BUF_ZV (XBUFFER (w->contents)))
3064 struct position pos;
3065 struct buffer *obuf = current_buffer;
3067 Fset_buffer (w->contents);
3068 /* This computation used to temporarily move point, but that
3069 can have unwanted side effects due to text properties. */
3070 pos = *vmotion (startpos, startbyte, -top, w);
3072 set_marker_both (w->start, w->contents, pos.bufpos, pos.bytepos);
3073 w->window_end_valid = false;
3074 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
3075 || FETCH_BYTE (pos.bytepos - 1) == '\n');
3076 /* We need to do this, so that the window-scroll-functions
3077 get called. */
3078 w->optional_new_start = true;
3080 set_buffer_internal (obuf);
3084 adjust_frame_glyphs (f);
3085 unblock_input ();
3087 run_window_configuration_change_hook (f);
3089 return Qnil;
3093 void
3094 replace_buffer_in_windows (Lisp_Object buffer)
3096 call1 (Qreplace_buffer_in_windows, buffer);
3099 /* If BUFFER is shown in a window, safely replace it with some other
3100 buffer in all windows of all frames, even those on other keyboards. */
3102 void
3103 replace_buffer_in_windows_safely (Lisp_Object buffer)
3105 if (buffer_window_count (XBUFFER (buffer)))
3107 Lisp_Object tail, frame;
3109 /* A single call to window_loop won't do the job because it only
3110 considers frames on the current keyboard. So loop manually over
3111 frames, and handle each one. */
3112 FOR_EACH_FRAME (tail, frame)
3113 window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, true, frame);
3117 /* The following three routines are needed for running a window's
3118 configuration change hook. */
3119 static void
3120 run_funs (Lisp_Object funs)
3122 for (; CONSP (funs); funs = XCDR (funs))
3123 if (!EQ (XCAR (funs), Qt))
3124 call0 (XCAR (funs));
3127 static void
3128 select_window_norecord (Lisp_Object window)
3130 if (WINDOW_LIVE_P (window))
3131 Fselect_window (window, Qt);
3134 static void
3135 select_frame_norecord (Lisp_Object frame)
3137 if (FRAME_LIVE_P (XFRAME (frame)))
3138 Fselect_frame (frame, Qt);
3141 void
3142 run_window_configuration_change_hook (struct frame *f)
3144 ptrdiff_t count = SPECPDL_INDEX ();
3145 Lisp_Object frame, global_wcch
3146 = Fdefault_value (Qwindow_configuration_change_hook);
3147 XSETFRAME (frame, f);
3149 if (NILP (Vrun_hooks)
3150 || !(f->can_x_set_window_size)
3151 || !(f->after_make_frame))
3152 return;
3154 /* Use the right buffer. Matters when running the local hooks. */
3155 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3157 record_unwind_current_buffer ();
3158 Fset_buffer (Fwindow_buffer (Qnil));
3161 if (SELECTED_FRAME () != f)
3163 record_unwind_protect (select_frame_norecord, selected_frame);
3164 select_frame_norecord (frame);
3167 /* Look for buffer-local values. */
3169 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3170 for (; CONSP (windows); windows = XCDR (windows))
3172 Lisp_Object window = XCAR (windows);
3173 Lisp_Object buffer = Fwindow_buffer (window);
3174 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3175 buffer)))
3177 ptrdiff_t inner_count = SPECPDL_INDEX ();
3178 record_unwind_protect (select_window_norecord, selected_window);
3179 select_window_norecord (window);
3180 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3181 buffer));
3182 unbind_to (inner_count, Qnil);
3187 run_funs (global_wcch);
3188 unbind_to (count, Qnil);
3191 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
3192 Srun_window_configuration_change_hook, 0, 1, 0,
3193 doc: /* Run `window-configuration-change-hook' for FRAME.
3194 If FRAME is omitted or nil, it defaults to the selected frame. */)
3195 (Lisp_Object frame)
3197 run_window_configuration_change_hook (decode_live_frame (frame));
3198 return Qnil;
3201 DEFUN ("run-window-scroll-functions", Frun_window_scroll_functions,
3202 Srun_window_scroll_functions, 0, 1, 0,
3203 doc: /* Run `window-scroll-functions' for WINDOW.
3204 If WINDOW is omitted or nil, it defaults to the selected window. */)
3205 (Lisp_Object window)
3207 if (! NILP (Vwindow_scroll_functions))
3208 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3209 Fmarker_position (decode_live_window (window)->start));
3210 return Qnil;
3213 /* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed
3214 to run hooks. See make_frame for a case where it's not allowed.
3215 KEEP_MARGINS_P means that the current margins, fringes, and
3216 scroll-bar settings of the window are not reset from the buffer's
3217 local settings. */
3219 void
3220 set_window_buffer (Lisp_Object window, Lisp_Object buffer,
3221 bool run_hooks_p, bool keep_margins_p)
3223 struct window *w = XWINDOW (window);
3224 struct buffer *b = XBUFFER (buffer);
3225 ptrdiff_t count = SPECPDL_INDEX ();
3226 bool samebuf = EQ (buffer, w->contents);
3228 wset_buffer (w, buffer);
3230 if (EQ (window, selected_window))
3231 bset_last_selected_window (b, window);
3233 /* Let redisplay errors through. */
3234 b->display_error_modiff = 0;
3236 /* Update time stamps of buffer display. */
3237 if (INTEGERP (BVAR (b, display_count)))
3238 bset_display_count (b, make_number (XINT (BVAR (b, display_count)) + 1));
3239 bset_display_time (b, Fcurrent_time ());
3241 w->window_end_pos = 0;
3242 w->window_end_vpos = 0;
3243 w->last_cursor_vpos = 0;
3245 if (!(keep_margins_p && samebuf))
3246 { /* If we're not actually changing the buffer, don't reset hscroll
3247 and vscroll. This case happens for example when called from
3248 change_frame_size_1, where we use a dummy call to
3249 Fset_window_buffer on the frame's selected window (and no
3250 other) just in order to run window-configuration-change-hook
3251 (no longer true since change_frame_size_1 directly calls
3252 run_window_configuration_change_hook). Resetting hscroll and
3253 vscroll here is problematic for things like image-mode and
3254 doc-view-mode since it resets the image's position whenever we
3255 resize the frame. */
3256 w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
3257 w->suspend_auto_hscroll = false;
3258 w->vscroll = 0;
3259 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3260 set_marker_both (w->old_pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3261 set_marker_restricted (w->start,
3262 make_number (b->last_window_start),
3263 buffer);
3264 w->start_at_line_beg = false;
3265 w->force_start = false;
3267 /* Maybe we could move this into the `if' but it's not obviously safe and
3268 I doubt it's worth the trouble. */
3269 wset_redisplay (w);
3270 w->update_mode_line = true;
3272 /* We must select BUFFER to run the window-scroll-functions and to look up
3273 the buffer-local value of Vwindow_point_insertion_type. */
3274 record_unwind_current_buffer ();
3275 Fset_buffer (buffer);
3277 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3278 XMARKER (w->old_pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3280 if (!keep_margins_p)
3282 /* Set left and right marginal area width etc. from buffer. */
3283 set_window_fringes (w, BVAR (b, left_fringe_width),
3284 BVAR (b, right_fringe_width),
3285 BVAR (b, fringes_outside_margins));
3286 set_window_scroll_bars (w, BVAR (b, scroll_bar_width),
3287 BVAR (b, vertical_scroll_bar_type),
3288 BVAR (b, scroll_bar_height),
3289 BVAR (b, horizontal_scroll_bar_type));
3290 set_window_margins (w, BVAR (b, left_margin_cols),
3291 BVAR (b, right_margin_cols));
3292 apply_window_adjustment (w);
3295 if (run_hooks_p)
3297 if (! NILP (Vwindow_scroll_functions))
3298 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3299 Fmarker_position (w->start));
3300 if (!samebuf)
3301 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3304 unbind_to (count, Qnil);
3307 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3308 doc: /* Make WINDOW display BUFFER-OR-NAME.
3309 WINDOW must be a live window and defaults to the selected one.
3310 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
3312 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
3313 display margins, fringe widths, and scroll bar settings are preserved;
3314 the default is to reset these from the local settings for BUFFER-OR-NAME
3315 or the frame defaults. Return nil.
3317 This function throws an error when WINDOW is strongly dedicated to its
3318 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3319 already display BUFFER-OR-NAME.
3321 This function runs `window-scroll-functions' before running
3322 `window-configuration-change-hook'. */)
3323 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3325 register Lisp_Object tem, buffer;
3326 register struct window *w = decode_live_window (window);
3328 XSETWINDOW (window, w);
3329 buffer = Fget_buffer (buffer_or_name);
3330 CHECK_BUFFER (buffer);
3331 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3332 error ("Attempt to display deleted buffer");
3334 tem = w->contents;
3335 if (NILP (tem))
3336 error ("Window is deleted");
3337 else
3339 if (!EQ (tem, buffer))
3341 if (EQ (w->dedicated, Qt))
3342 /* WINDOW is strongly dedicated to its buffer, signal an
3343 error. */
3344 error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
3345 else
3346 /* WINDOW is weakly dedicated to its buffer, reset
3347 dedication. */
3348 wset_dedicated (w, Qnil);
3350 call1 (Qrecord_window_buffer, window);
3353 unshow_buffer (w);
3356 set_window_buffer (window, buffer, true, !NILP (keep_margins));
3358 return Qnil;
3361 static Lisp_Object
3362 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3364 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3367 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3368 0, 1, 0,
3369 doc: /* Force all windows to be updated on next redisplay.
3370 If optional arg OBJECT is a window, force redisplay of that window only.
3371 If OBJECT is a buffer or buffer name, force redisplay of all windows
3372 displaying that buffer. */)
3373 (Lisp_Object object)
3375 if (NILP (object))
3377 windows_or_buffers_changed = 29;
3378 update_mode_lines = 28;
3379 return Qt;
3382 if (WINDOWP (object))
3384 struct window *w = XWINDOW (object);
3385 mark_window_display_accurate (object, false);
3386 w->update_mode_line = true;
3387 if (BUFFERP (w->contents))
3388 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
3389 update_mode_lines = 29;
3390 return Qt;
3393 if (STRINGP (object))
3394 object = Fget_buffer (object);
3395 if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))
3396 && buffer_window_count (XBUFFER (object)))
3398 /* If buffer is live and shown in at least one window, find
3399 all windows showing this buffer and force update of them. */
3400 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, false, Qvisible);
3401 return NILP (object) ? Qnil : Qt;
3404 /* If nothing suitable was found, just return.
3405 We could signal an error, but this feature will typically be used
3406 asynchronously in timers or process sentinels, so we don't. */
3407 return Qnil;
3410 /* Obsolete since 24.3. */
3411 void
3412 temp_output_buffer_show (register Lisp_Object buf)
3414 register struct buffer *old = current_buffer;
3415 register Lisp_Object window;
3416 register struct window *w;
3418 bset_directory (XBUFFER (buf), BVAR (current_buffer, directory));
3420 Fset_buffer (buf);
3421 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3422 BEGV = BEG;
3423 ZV = Z;
3424 SET_PT (BEG);
3425 set_buffer_internal (old);
3427 if (!NILP (Vtemp_buffer_show_function))
3428 call1 (Vtemp_buffer_show_function, buf);
3429 else if (WINDOW_LIVE_P (window = display_buffer (buf, Qnil, Qnil)))
3431 if (!EQ (XWINDOW (window)->frame, selected_frame))
3432 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3433 Vminibuf_scroll_window = window;
3434 w = XWINDOW (window);
3435 w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
3436 w->suspend_auto_hscroll = false;
3437 set_marker_restricted_both (w->start, buf, BEG, BEG);
3438 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3439 set_marker_restricted_both (w->old_pointm, buf, BEG, BEG);
3441 /* Run temp-buffer-show-hook, with the chosen window selected
3442 and its buffer current. */
3444 ptrdiff_t count = SPECPDL_INDEX ();
3445 Lisp_Object prev_window, prev_buffer;
3446 prev_window = selected_window;
3447 XSETBUFFER (prev_buffer, old);
3449 /* Select the window that was chosen, for running the hook.
3450 Note: Both Fselect_window and select_window_norecord may
3451 set-buffer to the buffer displayed in the window,
3452 so we need to save the current buffer. --stef */
3453 record_unwind_protect (restore_buffer, prev_buffer);
3454 record_unwind_protect (select_window_norecord, prev_window);
3455 Fselect_window (window, Qt);
3456 Fset_buffer (w->contents);
3457 run_hook (Qtemp_buffer_show_hook);
3458 unbind_to (count, Qnil);
3463 /* Allocate basically initialized window. */
3465 static struct window *
3466 allocate_window (void)
3468 return ALLOCATE_ZEROED_PSEUDOVECTOR
3469 (struct window, current_matrix, PVEC_WINDOW);
3472 /* Make new window, have it replace WINDOW in window-tree, and make
3473 WINDOW its only vertical child (HORFLAG means make WINDOW its only
3474 horizontal child). */
3475 static void
3476 make_parent_window (Lisp_Object window, bool horflag)
3478 Lisp_Object parent;
3479 register struct window *o, *p;
3481 o = XWINDOW (window);
3482 p = allocate_window ();
3483 memcpy ((char *) p + sizeof (struct vectorlike_header),
3484 (char *) o + sizeof (struct vectorlike_header),
3485 word_size * VECSIZE (struct window));
3486 /* P's buffer slot may change from nil to a buffer... */
3487 adjust_window_count (p, 1);
3488 XSETWINDOW (parent, p);
3490 p->sequence_number = ++sequence_number;
3492 replace_window (window, parent, true);
3494 wset_next (o, Qnil);
3495 wset_prev (o, Qnil);
3496 wset_parent (o, parent);
3497 /* ...but now P becomes an internal window. */
3498 wset_start (p, Qnil);
3499 wset_pointm (p, Qnil);
3500 wset_old_pointm (p, Qnil);
3501 wset_buffer (p, Qnil);
3502 wset_combination (p, horflag, window);
3503 wset_combination_limit (p, Qnil);
3504 wset_window_parameters (p, Qnil);
3507 /* Make new window from scratch. */
3508 Lisp_Object
3509 make_window (void)
3511 Lisp_Object window;
3512 register struct window *w;
3514 w = allocate_window ();
3515 /* Initialize Lisp data. Note that allocate_window initializes all
3516 Lisp data to nil, so do it only for slots which should not be nil. */
3517 wset_normal_lines (w, make_float (1.0));
3518 wset_normal_cols (w, make_float (1.0));
3519 wset_new_total (w, make_number (0));
3520 wset_new_normal (w, make_number (0));
3521 wset_new_pixel (w, make_number (0));
3522 wset_start (w, Fmake_marker ());
3523 wset_pointm (w, Fmake_marker ());
3524 wset_old_pointm (w, Fmake_marker ());
3525 wset_vertical_scroll_bar_type (w, Qt);
3526 wset_horizontal_scroll_bar_type (w, Qt);
3527 /* These Lisp fields are marked specially so they're not set to nil by
3528 allocate_window. */
3529 wset_prev_buffers (w, Qnil);
3530 wset_next_buffers (w, Qnil);
3532 /* Initialize non-Lisp data. Note that allocate_window zeroes out all
3533 non-Lisp data, so do it only for slots which should not be zero. */
3534 w->nrows_scale_factor = w->ncols_scale_factor = 1;
3535 w->left_fringe_width = w->right_fringe_width = -1;
3536 w->mode_line_height = w->header_line_height = -1;
3537 #ifdef HAVE_WINDOW_SYSTEM
3538 w->phys_cursor_type = NO_CURSOR;
3539 w->phys_cursor_width = -1;
3540 #endif
3541 w->sequence_number = ++sequence_number;
3542 w->scroll_bar_width = -1;
3543 w->scroll_bar_height = -1;
3544 w->column_number_displayed = -1;
3545 /* Reset window_list. */
3546 Vwindow_list = Qnil;
3547 /* Return window. */
3548 XSETWINDOW (window, w);
3549 return window;
3552 DEFUN ("set-window-new-pixel", Fset_window_new_pixel, Sset_window_new_pixel, 2, 3, 0,
3553 doc: /* Set new pixel size of WINDOW to SIZE.
3554 WINDOW must be a valid window and defaults to the selected one.
3555 Return SIZE.
3557 Optional argument ADD non-nil means add SIZE to the new pixel size of
3558 WINDOW and return the sum.
3560 The new pixel size of WINDOW, if valid, will be shortly installed as
3561 WINDOW's pixel height (see `window-pixel-height') or pixel width (see
3562 `window-pixel-width').
3564 Note: This function does not operate on any child windows of WINDOW. */)
3565 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3567 struct window *w = decode_valid_window (window);
3568 EMACS_INT size_min = NILP (add) ? 0 : - XINT (w->new_pixel);
3569 EMACS_INT size_max = size_min + min (INT_MAX, MOST_POSITIVE_FIXNUM);
3571 CHECK_RANGED_INTEGER (size, size_min, size_max);
3572 if (NILP (add))
3573 wset_new_pixel (w, size);
3574 else
3575 wset_new_pixel (w, make_number (XINT (w->new_pixel) + XINT (size)));
3577 return w->new_pixel;
3580 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
3581 doc: /* Set new total size of WINDOW to SIZE.
3582 WINDOW must be a valid window and defaults to the selected one.
3583 Return SIZE.
3585 Optional argument ADD non-nil means add SIZE to the new total size of
3586 WINDOW and return the sum.
3588 The new total size of WINDOW, if valid, will be shortly installed as
3589 WINDOW's total height (see `window-total-height') or total width (see
3590 `window-total-width').
3592 Note: This function does not operate on any child windows of WINDOW. */)
3593 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3595 struct window *w = decode_valid_window (window);
3597 CHECK_NUMBER (size);
3598 if (NILP (add))
3599 wset_new_total (w, size);
3600 else
3601 wset_new_total (w, make_number (XINT (w->new_total) + XINT (size)));
3603 return w->new_total;
3606 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
3607 doc: /* Set new normal size of WINDOW to SIZE.
3608 WINDOW must be a valid window and defaults to the selected one.
3609 Return SIZE.
3611 The new normal size of WINDOW, if valid, will be shortly installed as
3612 WINDOW's normal size (see `window-normal-size').
3614 Note: This function does not operate on any child windows of WINDOW. */)
3615 (Lisp_Object window, Lisp_Object size)
3617 wset_new_normal (decode_valid_window (window), size);
3618 return size;
3621 /* Return true if setting w->pixel_height (w->pixel_width if HORFLAG)
3622 to w->new_pixel would result in correct heights (widths)
3623 for window W and recursively all child windows of W.
3625 Note: This function does not check any of `window-fixed-size-p',
3626 `window-min-height' or `window-min-width'. It does check that window
3627 sizes do not drop below one line (two columns). */
3628 static bool
3629 window_resize_check (struct window *w, bool horflag)
3631 struct frame *f = XFRAME (w->frame);
3632 struct window *c;
3634 if (WINDOW_VERTICAL_COMBINATION_P (w))
3635 /* W is a vertical combination. */
3637 c = XWINDOW (w->contents);
3638 if (horflag)
3639 /* All child windows of W must have the same width as W. */
3641 while (c)
3643 if (XINT (c->new_pixel) != XINT (w->new_pixel)
3644 || !window_resize_check (c, horflag))
3645 return false;
3647 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3650 return true;
3652 else
3653 /* The sum of the heights of the child windows of W must equal
3654 W's height. */
3656 int remaining_pixels = XINT (w->new_pixel);
3658 while (c)
3660 if (!window_resize_check (c, horflag))
3661 return false;
3663 remaining_pixels -= XINT (c->new_pixel);
3664 if (remaining_pixels < 0)
3665 return false;
3666 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3669 return remaining_pixels == 0;
3672 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3673 /* W is a horizontal combination. */
3675 c = XWINDOW (w->contents);
3676 if (horflag)
3677 /* The sum of the widths of the child windows of W must equal W's
3678 width. */
3680 int remaining_pixels = XINT (w->new_pixel);
3682 while (c)
3684 if (!window_resize_check (c, horflag))
3685 return false;
3687 remaining_pixels -= XINT (c->new_pixel);
3688 if (remaining_pixels < 0)
3689 return false;
3690 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3693 return remaining_pixels == 0;
3695 else
3696 /* All child windows of W must have the same height as W. */
3698 while (c)
3700 if (XINT (c->new_pixel) != XINT (w->new_pixel)
3701 || !window_resize_check (c, horflag))
3702 return false;
3704 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3707 return true;
3710 else
3711 /* A leaf window. Make sure it's not too small. The following
3712 hardcodes the values of `window-safe-min-width' (2) and
3713 `window-safe-min-height' (1) which are defined in window.el. */
3714 return (XINT (w->new_pixel) >= (horflag
3715 ? (2 * FRAME_COLUMN_WIDTH (f))
3716 : FRAME_LINE_HEIGHT (f)));
3720 /* Set w->pixel_height (w->pixel_width if HORFLAG) to
3721 w->new_pixel for window W and recursively all child windows of W.
3722 Also calculate and assign the new vertical (horizontal) pixel start
3723 positions of each of these windows.
3725 This function does not perform any error checks. Make sure you have
3726 run window_resize_check on W before applying this function. */
3727 static void
3728 window_resize_apply (struct window *w, bool horflag)
3730 struct window *c;
3731 int edge;
3732 int unit = (horflag
3733 ? FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w))
3734 : FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
3736 /* Note: Assigning new_normal requires that the new total size of the
3737 parent window has been set *before*. */
3738 if (horflag)
3740 w->pixel_width = XFASTINT (w->new_pixel);
3741 w->total_cols = w->pixel_width / unit;
3742 if (NUMBERP (w->new_normal))
3743 wset_normal_cols (w, w->new_normal);
3745 edge = w->pixel_left;
3747 else
3749 w->pixel_height = XFASTINT (w->new_pixel);
3750 w->total_lines = w->pixel_height / unit;
3751 if (NUMBERP (w->new_normal))
3752 wset_normal_lines (w, w->new_normal);
3754 edge = w->pixel_top;
3757 if (WINDOW_VERTICAL_COMBINATION_P (w))
3758 /* W is a vertical combination. */
3760 c = XWINDOW (w->contents);
3761 while (c)
3763 if (horflag)
3765 c->pixel_left = edge;
3766 c->left_col = edge / unit;
3768 else
3770 c->pixel_top = edge;
3771 c->top_line = edge / unit;
3773 window_resize_apply (c, horflag);
3774 if (!horflag)
3775 edge = edge + c->pixel_height;
3777 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3780 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3781 /* W is a horizontal combination. */
3783 c = XWINDOW (w->contents);
3784 while (c)
3786 if (horflag)
3788 c->pixel_left = edge;
3789 c->left_col = edge / unit;
3791 else
3793 c->pixel_top = edge;
3794 c->top_line = edge / unit;
3797 window_resize_apply (c, horflag);
3798 if (horflag)
3799 edge = edge + c->pixel_width;
3801 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3804 else
3805 /* Bug#15957. */
3806 w->window_end_valid = false;
3810 /* Set w->total_lines (w->total_cols if HORFLAG) to
3811 w->new_total for window W and recursively all child windows of W.
3812 Also calculate and assign the new vertical (horizontal) start
3813 positions of each of these windows. */
3814 static void
3815 window_resize_apply_total (struct window *w, bool horflag)
3817 struct window *c;
3818 int edge;
3820 /* Note: Assigning new_normal requires that the new total size of the
3821 parent window has been set *before*. */
3822 if (horflag)
3824 w->total_cols = XFASTINT (w->new_total);
3825 edge = w->left_col;
3827 else
3829 w->total_lines = XFASTINT (w->new_total);
3830 edge = w->top_line;
3833 if (WINDOW_VERTICAL_COMBINATION_P (w))
3834 /* W is a vertical combination. */
3836 c = XWINDOW (w->contents);
3837 while (c)
3839 if (horflag)
3840 c->left_col = edge;
3841 else
3842 c->top_line = edge;
3844 window_resize_apply_total (c, horflag);
3845 if (!horflag)
3846 edge = edge + c->total_lines;
3848 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3851 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3852 /* W is a horizontal combination. */
3854 c = XWINDOW (w->contents);
3855 while (c)
3857 if (horflag)
3858 c->left_col = edge;
3859 else
3860 c->top_line = edge;
3862 window_resize_apply_total (c, horflag);
3863 if (horflag)
3864 edge = edge + c->total_cols;
3866 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3871 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 0, 2, 0,
3872 doc: /* Apply requested size values for window-tree of FRAME.
3873 If FRAME is omitted or nil, it defaults to the selected frame.
3875 Optional argument HORIZONTAL omitted or nil means apply requested
3876 height values. HORIZONTAL non-nil means apply requested width values.
3878 The requested size values are those set by `set-window-new-pixel' and
3879 `set-window-new-normal'. This function checks whether the requested
3880 values sum up to a valid window layout, recursively assigns the new
3881 sizes of all child windows and calculates and assigns the new start
3882 positions of these windows.
3884 Return t if the requested values have been applied correctly, nil
3885 otherwise.
3887 Note: This function does not check any of `window-fixed-size-p',
3888 `window-min-height' or `window-min-width'. All these checks have to
3889 be applied on the Elisp level. */)
3890 (Lisp_Object frame, Lisp_Object horizontal)
3892 struct frame *f = decode_live_frame (frame);
3893 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
3894 bool horflag = !NILP (horizontal);
3896 if (!window_resize_check (r, horflag)
3897 || (XINT (r->new_pixel)
3898 != (horflag ? r->pixel_width : r->pixel_height)))
3899 return Qnil;
3901 block_input ();
3902 window_resize_apply (r, horflag);
3904 fset_redisplay (f);
3905 FRAME_WINDOW_SIZES_CHANGED (f) = true;
3907 adjust_frame_glyphs (f);
3908 unblock_input ();
3910 return Qt;
3914 DEFUN ("window-resize-apply-total", Fwindow_resize_apply_total, Swindow_resize_apply_total, 0, 2, 0,
3915 doc: /* Apply requested total size values for window-tree of FRAME.
3916 If FRAME is omitted or nil, it defaults to the selected frame.
3918 This function does not assign pixel or normal size values. You should
3919 have run `window-resize-apply' before running this.
3921 Optional argument HORIZONTAL omitted or nil means apply requested
3922 height values. HORIZONTAL non-nil means apply requested width
3923 values. */)
3924 (Lisp_Object frame, Lisp_Object horizontal)
3926 struct frame *f = decode_live_frame (frame);
3927 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
3929 block_input ();
3930 /* Necessary when deleting the top-/or leftmost window. */
3931 r->left_col = 0;
3932 r->top_line = FRAME_TOP_MARGIN (f);
3933 window_resize_apply_total (r, !NILP (horizontal));
3934 /* Handle the mini window. */
3935 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3937 struct window *m = XWINDOW (f->minibuffer_window);
3939 if (NILP (horizontal))
3941 m->top_line = r->top_line + r->total_lines;
3942 m->total_lines = XFASTINT (m->new_total);
3944 else
3945 m->total_cols = XFASTINT (m->new_total);
3948 unblock_input ();
3950 return Qt;
3954 /* Resize frame F's windows when number of lines of F is set to SIZE.
3955 HORFLAG means resize windows when number of columns of F is set to
3956 SIZE. PIXELWISE means to interpret SIZE as pixels. */
3957 void
3958 resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
3960 Lisp_Object root = f->root_window;
3961 struct window *r = XWINDOW (root);
3962 Lisp_Object mini = f->minibuffer_window;
3963 struct window *m;
3964 /* old_size is the old size of the frame's root window. */
3965 int old_size = horflag ? r->total_cols : r->total_lines;
3966 int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
3967 int old_pixel_top = r->pixel_top;
3968 /* new_size is the new size of the frame's root window. */
3969 int new_size, new_pixel_size;
3970 int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
3972 /* Don't let the size drop below one unit. This is more comforting
3973 when we are called from x_set_tool_bar_lines since the latter may
3974 have implicitly given us a zero or negative height. */
3975 if (pixelwise)
3977 /* Note: This does not include the size for internal borders
3978 since these are not part of the frame's text area. */
3979 new_pixel_size = max (horflag
3980 ? size
3981 : (size
3982 - ((FRAME_HAS_MINIBUF_P (f)
3983 && !FRAME_MINIBUF_ONLY_P (f))
3984 ? FRAME_LINE_HEIGHT (f) : 0)),
3985 unit);
3986 new_size = new_pixel_size / unit;
3988 else
3990 new_size = max (size - (!horflag
3991 && FRAME_HAS_MINIBUF_P (f)
3992 && !FRAME_MINIBUF_ONLY_P (f)),
3994 new_pixel_size = new_size * unit;
3997 r->top_line = FRAME_TOP_MARGIN (f);
3998 r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
4000 if (new_pixel_size == old_pixel_size
4001 && r->pixel_top == old_pixel_top)
4003 else if (WINDOW_LEAF_P (r))
4004 /* For a leaf root window just set the size. */
4005 if (horflag)
4007 r->total_cols = new_size;
4008 r->pixel_width = new_pixel_size;
4010 else
4012 r->total_lines = new_size;
4013 r->pixel_height = new_pixel_size;
4015 else
4017 Lisp_Object delta;
4019 if (pixelwise)
4020 XSETINT (delta, new_pixel_size - old_pixel_size);
4021 else
4022 XSETINT (delta, new_size - old_size);
4024 /* Try a "normal" resize first. */
4025 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil,
4026 pixelwise ? Qt : Qnil);
4027 if (window_resize_check (r, horflag)
4028 && new_pixel_size == XINT (r->new_pixel))
4030 window_resize_apply (r, horflag);
4031 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4033 else
4035 /* Try with "reasonable" minimum sizes next. */
4036 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt,
4037 pixelwise ? Qt : Qnil);
4038 if (window_resize_check (r, horflag)
4039 && new_pixel_size == XINT (r->new_pixel))
4041 window_resize_apply (r, horflag);
4042 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4043 #if false /* Let's try without safe sizes and/or killing other windows. */
4045 else
4047 /* Finally, try with "safe" minimum sizes. */
4048 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe,
4049 pixelwise ? Qt : Qnil);
4050 if (window_resize_check (r, horflag)
4051 && new_pixel_size == XINT (r->new_pixel))
4053 window_resize_apply (r, horflag);
4054 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4056 else
4058 /* We lost. Delete all windows but the frame's
4059 selected one. */
4060 root = f->selected_window;
4061 Fdelete_other_windows_internal (root, Qnil);
4062 if (horflag)
4064 XWINDOW (root)->total_cols = new_size;
4065 XWINDOW (root)->pixel_width = new_pixel_size;
4067 else
4069 XWINDOW (root)->total_lines = new_size;
4070 XWINDOW (root)->pixel_height = new_pixel_size;
4073 #endif /* false */
4078 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
4080 m = XWINDOW (mini);
4081 if (horflag)
4083 m->total_cols = size;
4084 m->pixel_width = new_pixel_size;
4086 else
4088 /* Are we sure we always want 1 line here? */
4089 m->total_lines = 1;
4090 m->pixel_height = FRAME_LINE_HEIGHT (f);
4091 m->top_line = r->top_line + r->total_lines;
4092 m->pixel_top = r->pixel_top + r->pixel_height;
4096 fset_redisplay (f);
4100 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
4101 doc: /* Split window OLD.
4102 Second argument PIXEL-SIZE specifies the number of pixels of the
4103 new window. It must be a positive integer.
4105 Third argument SIDE nil (or `below') specifies that the new window shall
4106 be located below WINDOW. SIDE `above' means the new window shall be
4107 located above WINDOW. In both cases PIXEL-SIZE specifies the pixel
4108 height of the new window including space reserved for the mode and/or
4109 header line.
4111 SIDE t (or `right') specifies that the new window shall be located on
4112 the right side of WINDOW. SIDE `left' means the new window shall be
4113 located on the left of WINDOW. In both cases PIXEL-SIZE specifies the
4114 width of the new window including space reserved for fringes and the
4115 scrollbar or a divider column.
4117 Fourth argument NORMAL-SIZE specifies the normal size of the new window
4118 according to the SIDE argument.
4120 The new pixel and normal sizes of all involved windows must have been
4121 set correctly. See the code of `split-window' for how this is done. */)
4122 (Lisp_Object old, Lisp_Object pixel_size, Lisp_Object side, Lisp_Object normal_size)
4124 /* OLD (*o) is the window we have to split. (*p) is either OLD's
4125 parent window or an internal window we have to install as OLD's new
4126 parent. REFERENCE (*r) must denote a live window, or is set to OLD
4127 provided OLD is a leaf window, or to the frame's selected window.
4128 NEW (*n) is the new window created with some parameters taken from
4129 REFERENCE (*r). */
4130 Lisp_Object new, frame, reference;
4131 struct window *o, *p, *n, *r, *c;
4132 struct frame *f;
4133 bool horflag
4134 /* HORFLAG is true when we split side-by-side, false otherwise. */
4135 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
4137 CHECK_WINDOW (old);
4138 o = XWINDOW (old);
4139 frame = WINDOW_FRAME (o);
4140 f = XFRAME (frame);
4142 CHECK_NUMBER (pixel_size);
4143 EMACS_INT total_size
4144 = XINT (pixel_size) / (horflag
4145 ? FRAME_COLUMN_WIDTH (f)
4146 : FRAME_LINE_HEIGHT (f));
4148 /* Set combination_limit if we have to make a new parent window.
4149 We do that if either `window-combination-limit' is t, or OLD has no
4150 parent, or OLD is ortho-combined. */
4151 bool combination_limit
4152 = (EQ (Vwindow_combination_limit, Qt)
4153 || NILP (o->parent)
4154 || (horflag
4155 ? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
4156 : WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent))));
4158 /* We need a live reference window to initialize some parameters. */
4159 if (WINDOW_LIVE_P (old))
4160 /* OLD is live, use it as reference window. */
4161 reference = old;
4162 else
4163 /* Use the frame's selected window as reference window. */
4164 reference = FRAME_SELECTED_WINDOW (f);
4165 r = XWINDOW (reference);
4167 /* The following bugs are caught by `split-window'. */
4168 if (MINI_WINDOW_P (o))
4169 error ("Attempt to split minibuffer window");
4170 else if (total_size < (horflag ? 2 : 1))
4171 error ("Size of new window too small (after split)");
4172 else if (!combination_limit && !NILP (Vwindow_combination_resize))
4173 /* `window-combination-resize' non-nil means try to resize OLD's siblings
4174 proportionally. */
4176 p = XWINDOW (o->parent);
4177 /* Temporarily pretend we split the parent window. */
4178 wset_new_pixel
4179 (p, make_number ((horflag ? p->pixel_width : p->pixel_height)
4180 - XINT (pixel_size)));
4181 if (!window_resize_check (p, horflag))
4182 error ("Window sizes don't fit");
4183 else
4184 /* Undo the temporary pretension. */
4185 wset_new_pixel (p, make_number (horflag ? p->pixel_width : p->pixel_height));
4187 else
4189 if (!window_resize_check (o, horflag))
4190 error ("Resizing old window failed");
4191 else if (XINT (pixel_size) + XINT (o->new_pixel)
4192 != (horflag ? o->pixel_width : o->pixel_height))
4193 error ("Sum of sizes of old and new window don't fit");
4196 /* This is our point of no return. */
4197 if (combination_limit)
4199 /* Save the old value of o->normal_cols/lines. It gets corrupted
4200 by make_parent_window and we need it below for assigning it to
4201 p->new_normal. */
4202 Lisp_Object new_normal
4203 = horflag ? o->normal_cols : o->normal_lines;
4205 make_parent_window (old, horflag);
4206 p = XWINDOW (o->parent);
4207 if (EQ (Vwindow_combination_limit, Qt))
4208 /* Store t in the new parent's combination_limit slot to avoid
4209 that its children get merged into another window. */
4210 wset_combination_limit (p, Qt);
4211 /* These get applied below. */
4212 wset_new_pixel
4213 (p, make_number (horflag ? o->pixel_width : o->pixel_height));
4214 wset_new_total
4215 (p, make_number (horflag ? o->total_cols : o->total_lines));
4216 wset_new_normal (p, new_normal);
4218 else
4219 p = XWINDOW (o->parent);
4221 fset_redisplay (f);
4222 FRAME_WINDOW_SIZES_CHANGED (f) = true;
4223 new = make_window ();
4224 n = XWINDOW (new);
4225 wset_frame (n, frame);
4226 wset_parent (n, o->parent);
4228 if (EQ (side, Qabove) || EQ (side, Qleft))
4230 wset_prev (n, o->prev);
4231 if (NILP (n->prev))
4232 wset_combination (p, horflag, new);
4233 else
4234 wset_next (XWINDOW (n->prev), new);
4235 wset_next (n, old);
4236 wset_prev (o, new);
4238 else
4240 wset_next (n, o->next);
4241 if (!NILP (n->next))
4242 wset_prev (XWINDOW (n->next), new);
4243 wset_prev (n, old);
4244 wset_next (o, new);
4247 n->window_end_valid = false;
4248 n->last_cursor_vpos = 0;
4250 /* Get special geometry settings from reference window. */
4251 n->left_margin_cols = r->left_margin_cols;
4252 n->right_margin_cols = r->right_margin_cols;
4253 n->left_fringe_width = r->left_fringe_width;
4254 n->right_fringe_width = r->right_fringe_width;
4255 n->fringes_outside_margins = r->fringes_outside_margins;
4256 n->scroll_bar_width = r->scroll_bar_width;
4257 n->scroll_bar_height = r->scroll_bar_height;
4258 wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
4259 wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type);
4261 /* Directly assign orthogonal coordinates and sizes. */
4262 if (horflag)
4264 n->pixel_top = o->pixel_top;
4265 n->top_line = o->top_line;
4266 n->pixel_height = o->pixel_height;
4267 n->total_lines = o->total_lines;
4269 else
4271 n->pixel_left = o->pixel_left;
4272 n->left_col = o->left_col;
4273 n->pixel_width = o->pixel_width;
4274 n->total_cols = o->total_cols;
4277 /* Iso-coordinates and sizes are assigned by window_resize_apply,
4278 get them ready here. */
4279 wset_new_pixel (n, pixel_size);
4280 EMACS_INT sum = 0;
4281 c = XWINDOW (p->contents);
4282 while (c)
4284 if (c != n)
4285 sum = sum + XINT (c->new_total);
4286 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4288 wset_new_total (n, make_number ((horflag
4289 ? p->total_cols
4290 : p->total_lines)
4291 - sum));
4292 wset_new_normal (n, normal_size);
4294 block_input ();
4295 window_resize_apply (p, horflag);
4296 adjust_frame_glyphs (f);
4297 /* Set buffer of NEW to buffer of reference window. Don't run
4298 any hooks. */
4299 set_window_buffer (new, r->contents, false, true);
4300 unblock_input ();
4302 /* Maybe we should run the scroll functions in Elisp (which already
4303 runs the configuration change hook). */
4304 if (! NILP (Vwindow_scroll_functions))
4305 run_hook_with_args_2 (Qwindow_scroll_functions, new,
4306 Fmarker_position (n->start));
4307 /* Return NEW. */
4308 return new;
4312 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
4313 doc: /* Remove WINDOW from its frame.
4314 WINDOW defaults to the selected window. Return nil.
4315 Signal an error when WINDOW is the only window on its frame. */)
4316 (Lisp_Object window)
4318 Lisp_Object parent, sibling, frame, root;
4319 struct window *w, *p, *s, *r;
4320 struct frame *f;
4321 bool horflag, before_sibling = false;
4323 w = decode_any_window (window);
4324 XSETWINDOW (window, w);
4325 if (NILP (w->contents))
4326 /* It's a no-op to delete an already deleted window. */
4327 return Qnil;
4329 parent = w->parent;
4330 if (NILP (parent))
4331 /* Never delete a minibuffer or frame root window. */
4332 error ("Attempt to delete minibuffer or sole ordinary window");
4333 else if (NILP (w->prev) && NILP (w->next))
4334 /* Rather bow out here, this case should be handled on the Elisp
4335 level. */
4336 error ("Attempt to delete sole window of parent");
4338 p = XWINDOW (parent);
4339 horflag = WINDOW_HORIZONTAL_COMBINATION_P (p);
4341 frame = WINDOW_FRAME (w);
4342 f = XFRAME (frame);
4344 root = FRAME_ROOT_WINDOW (f);
4345 r = XWINDOW (root);
4347 /* Unlink WINDOW from window tree. */
4348 if (NILP (w->prev))
4349 /* Get SIBLING below (on the right of) WINDOW. */
4351 /* before_sibling means WINDOW is the first child of its
4352 parent and thus before the sibling. */
4353 before_sibling = true;
4354 sibling = w->next;
4355 s = XWINDOW (sibling);
4356 wset_prev (s, Qnil);
4357 wset_combination (p, horflag, sibling);
4359 else
4360 /* Get SIBLING above (on the left of) WINDOW. */
4362 sibling = w->prev;
4363 s = XWINDOW (sibling);
4364 wset_next (s, w->next);
4365 if (!NILP (s->next))
4366 wset_prev (XWINDOW (s->next), sibling);
4369 if (window_resize_check (r, horflag)
4370 && (XINT (r->new_pixel)
4371 == (horflag ? r->pixel_width : r->pixel_height)))
4372 /* We can delete WINDOW now. */
4375 /* Block input. */
4376 block_input ();
4377 window_resize_apply (p, horflag);
4378 /* If this window is referred to by the dpyinfo's mouse
4379 highlight, invalidate that slot to be safe (Bug#9904). */
4380 if (!FRAME_INITIAL_P (f))
4382 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
4384 if (EQ (hlinfo->mouse_face_window, window))
4385 hlinfo->mouse_face_window = Qnil;
4388 fset_redisplay (f);
4389 Vwindow_list = Qnil;
4390 FRAME_WINDOW_SIZES_CHANGED (f) = true;
4392 wset_next (w, Qnil); /* Don't delete w->next too. */
4393 free_window_matrices (w);
4395 if (WINDOWP (w->contents))
4397 delete_all_child_windows (w->contents);
4398 wset_combination (w, false, Qnil);
4400 else
4402 unshow_buffer (w);
4403 unchain_marker (XMARKER (w->pointm));
4404 unchain_marker (XMARKER (w->old_pointm));
4405 unchain_marker (XMARKER (w->start));
4406 wset_buffer (w, Qnil);
4409 if (NILP (s->prev) && NILP (s->next))
4410 /* A matrjoshka where SIBLING has become the only child of
4411 PARENT. */
4413 /* Put SIBLING into PARENT's place. */
4414 replace_window (parent, sibling, false);
4415 /* Have SIBLING inherit the following three slot values from
4416 PARENT (the combination_limit slot is not inherited). */
4417 wset_normal_cols (s, p->normal_cols);
4418 wset_normal_lines (s, p->normal_lines);
4419 /* Mark PARENT as deleted. */
4420 wset_combination (p, false, Qnil);
4421 /* Try to merge SIBLING into its new parent. */
4422 recombine_windows (sibling);
4425 adjust_frame_glyphs (f);
4427 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
4428 /* We deleted the frame's selected window. */
4430 /* Use the frame's first window as fallback ... */
4431 Lisp_Object new_selected_window = Fframe_first_window (frame);
4432 /* ... but preferably use its most recently used window. */
4433 Lisp_Object mru_window;
4435 /* `get-mru-window' might fail for some reason so play it safe
4436 - promote the first window _without recording it_ first. */
4437 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4438 Fselect_window (new_selected_window, Qt);
4439 else
4440 fset_selected_window (f, new_selected_window);
4442 unblock_input ();
4444 /* Now look whether `get-mru-window' gets us something. */
4445 mru_window = call1 (Qget_mru_window, frame);
4446 if (WINDOW_LIVE_P (mru_window)
4447 && EQ (XWINDOW (mru_window)->frame, frame))
4448 new_selected_window = mru_window;
4450 /* If all ended up well, we now promote the mru window. */
4451 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4452 Fselect_window (new_selected_window, Qnil);
4453 else
4454 fset_selected_window (f, new_selected_window);
4456 else
4457 unblock_input ();
4459 /* Must be run by the caller:
4460 run_window_configuration_change_hook (f); */
4462 else
4463 /* We failed: Relink WINDOW into window tree. */
4465 if (before_sibling)
4467 wset_prev (s, window);
4468 wset_combination (p, horflag, window);
4470 else
4472 wset_next (s, window);
4473 if (!NILP (w->next))
4474 wset_prev (XWINDOW (w->next), window);
4476 error ("Deletion failed");
4479 return Qnil;
4482 /***********************************************************************
4483 Resizing Mini-Windows
4484 ***********************************************************************/
4486 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
4487 can. */
4488 void
4489 grow_mini_window (struct window *w, int delta, bool pixelwise)
4491 struct frame *f = XFRAME (w->frame);
4492 struct window *r;
4493 Lisp_Object root, height;
4494 int line_height, pixel_height;
4496 eassert (MINI_WINDOW_P (w));
4497 eassert (delta >= 0);
4499 if (delta > 0)
4501 root = FRAME_ROOT_WINDOW (f);
4502 r = XWINDOW (root);
4503 height = call3 (Qwindow_resize_root_window_vertically,
4504 root, make_number (- delta), pixelwise ? Qt : Qnil);
4505 if (INTEGERP (height) && window_resize_check (r, false))
4507 block_input ();
4508 window_resize_apply (r, false);
4510 if (pixelwise)
4512 pixel_height = min (-XINT (height), INT_MAX - w->pixel_height);
4513 line_height = pixel_height / FRAME_LINE_HEIGHT (f);
4515 else
4517 line_height = min (-XINT (height),
4518 ((INT_MAX - w->pixel_height)
4519 / FRAME_LINE_HEIGHT (f)));
4520 pixel_height = line_height * FRAME_LINE_HEIGHT (f);
4523 /* Grow the mini-window. */
4524 w->pixel_top = r->pixel_top + r->pixel_height;
4525 w->top_line = r->top_line + r->total_lines;
4526 /* Make sure the mini-window has always at least one line. */
4527 w->pixel_height = max (w->pixel_height + pixel_height,
4528 FRAME_LINE_HEIGHT (f));
4529 w->total_lines = max (w->total_lines + line_height, 1);
4531 /* Enforce full redisplay of the frame. */
4532 /* FIXME: Shouldn't window--resize-root-window-vertically do it? */
4533 fset_redisplay (f);
4534 adjust_frame_glyphs (f);
4535 unblock_input ();
4540 /* Shrink mini-window W to one line. */
4541 void
4542 shrink_mini_window (struct window *w, bool pixelwise)
4544 struct frame *f = XFRAME (w->frame);
4545 struct window *r;
4546 Lisp_Object root, delta;
4547 EMACS_INT height, unit;
4549 eassert (MINI_WINDOW_P (w));
4551 height = pixelwise ? w->pixel_height : w->total_lines;
4552 unit = pixelwise ? FRAME_LINE_HEIGHT (f) : 1;
4553 if (height > unit)
4555 root = FRAME_ROOT_WINDOW (f);
4556 r = XWINDOW (root);
4557 delta = call3 (Qwindow_resize_root_window_vertically,
4558 root, make_number (height - unit),
4559 pixelwise ? Qt : Qnil);
4560 if (INTEGERP (delta) && window_resize_check (r, false))
4562 block_input ();
4563 window_resize_apply (r, false);
4565 /* Shrink the mini-window. */
4566 w->top_line = r->top_line + r->total_lines;
4567 w->total_lines = 1;
4568 w->pixel_top = r->pixel_top + r->pixel_height;
4569 w->pixel_height = FRAME_LINE_HEIGHT (f);
4570 /* Enforce full redisplay of the frame. */
4571 /* FIXME: Shouldn't window--resize-root-window-vertically do it? */
4572 fset_redisplay (f);
4573 adjust_frame_glyphs (f);
4574 unblock_input ();
4576 /* If the above failed for whatever strange reason we must make a
4577 one window frame here. The same routine will be needed when
4578 shrinking the frame (and probably when making the initial
4579 *scratch* window). For the moment leave things as they are. */
4583 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
4584 doc: /* Resize minibuffer window WINDOW. */)
4585 (Lisp_Object window)
4587 struct window *w = XWINDOW (window);
4588 struct window *r;
4589 struct frame *f;
4590 int height;
4592 CHECK_WINDOW (window);
4593 f = XFRAME (w->frame);
4595 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
4596 error ("Not a valid minibuffer window");
4597 else if (FRAME_MINIBUF_ONLY_P (f))
4598 error ("Cannot resize a minibuffer-only frame");
4600 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4601 height = r->pixel_height + w->pixel_height;
4602 if (window_resize_check (r, false)
4603 && XINT (w->new_pixel) > 0
4604 && height == XINT (r->new_pixel) + XINT (w->new_pixel))
4606 block_input ();
4607 window_resize_apply (r, false);
4609 w->pixel_height = XFASTINT (w->new_pixel);
4610 w->total_lines = w->pixel_height / FRAME_LINE_HEIGHT (f);
4611 w->pixel_top = r->pixel_top + r->pixel_height;
4612 w->top_line = r->top_line + r->total_lines;
4614 fset_redisplay (f);
4615 FRAME_WINDOW_SIZES_CHANGED (f) = true;
4616 adjust_frame_glyphs (f);
4617 unblock_input ();
4618 return Qt;
4620 else
4621 error ("Failed to resize minibuffer window");
4624 /* Mark window cursors off for all windows in the window tree rooted
4625 at W by setting their phys_cursor_on_p flag to zero. Called from
4626 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4627 the frame are cleared. */
4629 void
4630 mark_window_cursors_off (struct window *w)
4632 while (w)
4634 if (WINDOWP (w->contents))
4635 mark_window_cursors_off (XWINDOW (w->contents));
4636 else
4637 w->phys_cursor_on_p = false;
4639 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4644 /* Return number of lines of text (not counting mode lines) in W. */
4647 window_internal_height (struct window *w)
4649 int ht = w->total_lines;
4651 if (!MINI_WINDOW_P (w))
4653 if (!NILP (w->parent)
4654 || WINDOWP (w->contents)
4655 || !NILP (w->next)
4656 || !NILP (w->prev)
4657 || WINDOW_WANTS_MODELINE_P (w))
4658 --ht;
4660 if (WINDOW_WANTS_HEADER_LINE_P (w))
4661 --ht;
4664 return ht;
4668 /************************************************************************
4669 Window Scrolling
4670 ***********************************************************************/
4672 /* Scroll contents of window WINDOW up. If WHOLE, scroll
4673 N screen-fulls, which is defined as the height of the window minus
4674 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4675 instead. Negative values of N mean scroll down. NOERROR
4676 means don't signal an error if we try to move over BEGV or ZV,
4677 respectively. */
4679 static void
4680 window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
4682 ptrdiff_t count = SPECPDL_INDEX ();
4684 immediate_quit = true;
4685 n = clip_to_bounds (INT_MIN, n, INT_MAX);
4687 wset_redisplay (XWINDOW (window));
4689 if (whole && Vfast_but_imprecise_scrolling)
4690 specbind (Qfontification_functions, Qnil);
4692 /* If we must, use the pixel-based version which is much slower than
4693 the line-based one but can handle varying line heights. */
4694 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4695 window_scroll_pixel_based (window, n, whole, noerror);
4696 else
4697 window_scroll_line_based (window, n, whole, noerror);
4699 unbind_to (count, Qnil);
4701 /* Bug#15957. */
4702 XWINDOW (window)->window_end_valid = false;
4703 immediate_quit = false;
4707 /* Implementation of window_scroll that works based on pixel line
4708 heights. See the comment of window_scroll for parameter
4709 descriptions. */
4711 static void
4712 window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
4714 struct it it;
4715 struct window *w = XWINDOW (window);
4716 struct text_pos start;
4717 int this_scroll_margin;
4718 /* True if we fiddled the window vscroll field without really scrolling. */
4719 bool vscrolled = false;
4720 int x, y, rtop, rbot, rowh, vpos;
4721 void *itdata = NULL;
4722 int window_total_lines;
4723 int frame_line_height = default_line_pixel_height (w);
4724 bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
4725 Fwindow_old_point (window)));
4727 SET_TEXT_POS_FROM_MARKER (start, w->start);
4728 /* Scrolling a minibuffer window via scroll bar when the echo area
4729 shows long text sometimes resets the minibuffer contents behind
4730 our backs. */
4731 if (CHARPOS (start) > ZV)
4732 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4734 /* If PT is not visible in WINDOW, move back one half of
4735 the screen. Allow PT to be partially visible, otherwise
4736 something like (scroll-down 1) with PT in the line before
4737 the partially visible one would recenter. */
4739 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4741 itdata = bidi_shelve_cache ();
4742 /* Move backward half the height of the window. Performance note:
4743 vmotion used here is about 10% faster, but would give wrong
4744 results for variable height lines. */
4745 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4746 it.current_y = it.last_visible_y;
4747 move_it_vertically_backward (&it, window_box_height (w) / 2);
4749 /* The function move_iterator_vertically may move over more than
4750 the specified y-distance. If it->w is small, e.g. a
4751 mini-buffer window, we may end up in front of the window's
4752 display area. Start displaying at the start of the line
4753 containing PT in this case. */
4754 if (it.current_y <= 0)
4756 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4757 move_it_vertically_backward (&it, 0);
4758 it.current_y = 0;
4761 start = it.current.pos;
4762 bidi_unshelve_cache (itdata, false);
4764 else if (auto_window_vscroll_p)
4766 if (rtop || rbot) /* Partially visible. */
4768 int px;
4769 int dy = frame_line_height;
4770 /* In the below we divide the window box height by the
4771 frame's line height to make the result predictable when
4772 the window box is not an integral multiple of the line
4773 height. This is important to ensure we get back to the
4774 same position when scrolling up, then down. */
4775 if (whole)
4776 dy = max ((window_box_height (w) / dy
4777 - next_screen_context_lines) * dy,
4778 dy);
4779 dy *= n;
4781 if (n < 0)
4783 /* Only vscroll backwards if already vscrolled forwards. */
4784 if (w->vscroll < 0 && rtop > 0)
4786 px = max (0, -w->vscroll - min (rtop, -dy));
4787 Fset_window_vscroll (window, make_number (px), Qt);
4788 return;
4791 if (n > 0)
4793 /* Do vscroll if already vscrolled or only display line. */
4794 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4796 px = max (0, -w->vscroll + min (rbot, dy));
4797 Fset_window_vscroll (window, make_number (px), Qt);
4798 return;
4801 /* Maybe modify window start instead of scrolling. */
4802 if (rbot > 0 || w->vscroll < 0)
4804 ptrdiff_t spos;
4806 Fset_window_vscroll (window, make_number (0), Qt);
4807 /* If there are other text lines above the current row,
4808 move window start to current row. Else to next row. */
4809 if (rbot > 0)
4810 spos = XINT (Fline_beginning_position (Qnil));
4811 else
4812 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4813 set_marker_restricted (w->start, make_number (spos),
4814 w->contents);
4815 w->start_at_line_beg = true;
4816 w->update_mode_line = true;
4817 /* Set force_start so that redisplay_window will run the
4818 window-scroll-functions. */
4819 w->force_start = true;
4820 return;
4824 /* Cancel previous vscroll. */
4825 Fset_window_vscroll (window, make_number (0), Qt);
4828 itdata = bidi_shelve_cache ();
4829 /* If scroll_preserve_screen_position is non-nil, we try to set
4830 point in the same window line as it is now, so get that line. */
4831 if (!NILP (Vscroll_preserve_screen_position))
4833 /* We preserve the goal pixel coordinate across consecutive
4834 calls to scroll-up, scroll-down and other commands that
4835 have the `scroll-command' property. This avoids the
4836 possibility of point becoming "stuck" on a tall line when
4837 scrolling by one line. */
4838 if (window_scroll_pixel_based_preserve_y < 0
4839 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4840 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4842 start_display (&it, w, start);
4843 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4844 window_scroll_pixel_based_preserve_y = it.current_y;
4845 window_scroll_pixel_based_preserve_x = it.current_x;
4848 else
4849 window_scroll_pixel_based_preserve_y
4850 = window_scroll_pixel_based_preserve_x = -1;
4852 /* Move iterator it from start the specified distance forward or
4853 backward. The result is the new window start. */
4854 start_display (&it, w, start);
4855 if (whole)
4857 ptrdiff_t start_pos = IT_CHARPOS (it);
4858 int dy = frame_line_height;
4859 /* In the below we divide the window box height by the frame's
4860 line height to make the result predictable when the window
4861 box is not an integral multiple of the line height. This is
4862 important to ensure we get back to the same position when
4863 scrolling up, then down. */
4864 dy = max ((window_box_height (w) / dy - next_screen_context_lines) * dy,
4865 dy) * n;
4867 /* Note that move_it_vertically always moves the iterator to the
4868 start of a line. So, if the last line doesn't have a newline,
4869 we would end up at the start of the line ending at ZV. */
4870 if (dy <= 0)
4872 move_it_vertically_backward (&it, -dy);
4873 /* Ensure we actually do move, e.g. in case we are currently
4874 looking at an image that is taller that the window height. */
4875 while (start_pos == IT_CHARPOS (it)
4876 && start_pos > BEGV)
4877 move_it_by_lines (&it, -1);
4879 else if (dy > 0)
4881 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4882 MOVE_TO_POS | MOVE_TO_Y);
4883 /* Ensure we actually do move, e.g. in case we are currently
4884 looking at an image that is taller that the window height. */
4885 while (start_pos == IT_CHARPOS (it)
4886 && start_pos < ZV)
4887 move_it_by_lines (&it, 1);
4890 else
4891 move_it_by_lines (&it, n);
4893 /* We failed if we find ZV is already on the screen (scrolling up,
4894 means there's nothing past the end), or if we can't start any
4895 earlier (scrolling down, means there's nothing past the top). */
4896 if ((n > 0 && IT_CHARPOS (it) == ZV)
4897 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4899 if (IT_CHARPOS (it) == ZV)
4901 if (it.current_y < it.last_visible_y
4902 && (it.current_y + it.max_ascent + it.max_descent
4903 > it.last_visible_y))
4905 /* The last line was only partially visible, make it fully
4906 visible. */
4907 w->vscroll = (it.last_visible_y
4908 - it.current_y + it.max_ascent + it.max_descent);
4909 adjust_frame_glyphs (it.f);
4911 else
4913 bidi_unshelve_cache (itdata, false);
4914 if (noerror)
4915 return;
4916 else if (n < 0) /* could happen with empty buffers */
4917 xsignal0 (Qbeginning_of_buffer);
4918 else
4919 xsignal0 (Qend_of_buffer);
4922 else
4924 if (w->vscroll != 0)
4925 /* The first line was only partially visible, make it fully
4926 visible. */
4927 w->vscroll = 0;
4928 else
4930 bidi_unshelve_cache (itdata, false);
4931 if (noerror)
4932 return;
4933 else
4934 xsignal0 (Qbeginning_of_buffer);
4938 /* If control gets here, then we vscrolled. */
4940 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
4942 /* Don't try to change the window start below. */
4943 vscrolled = true;
4946 if (! vscrolled)
4948 ptrdiff_t pos = IT_CHARPOS (it);
4949 ptrdiff_t bytepos;
4951 /* If in the middle of a multi-glyph character move forward to
4952 the next character. */
4953 if (in_display_vector_p (&it))
4955 ++pos;
4956 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4959 /* Set the window start, and set up the window for redisplay. */
4960 set_marker_restricted_both (w->start, w->contents, IT_CHARPOS (it),
4961 IT_BYTEPOS (it));
4962 bytepos = marker_byte_position (w->start);
4963 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
4964 w->update_mode_line = true;
4965 /* Set force_start so that redisplay_window will run the
4966 window-scroll-functions. */
4967 w->force_start = true;
4970 /* The rest of this function uses current_y in a nonstandard way,
4971 not including the height of the header line if any. */
4972 it.current_y = it.vpos = 0;
4974 /* Move PT out of scroll margins.
4975 This code wants current_y to be zero at the window start position
4976 even if there is a header line. */
4977 window_total_lines
4978 = w->total_lines * WINDOW_FRAME_LINE_HEIGHT (w) / frame_line_height;
4979 this_scroll_margin = max (0, scroll_margin);
4980 this_scroll_margin
4981 = min (this_scroll_margin, window_total_lines / 4);
4982 this_scroll_margin *= frame_line_height;
4984 if (n > 0)
4986 /* We moved the window start towards ZV, so PT may be now
4987 in the scroll margin at the top. */
4988 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4989 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
4990 && (NILP (Vscroll_preserve_screen_position)
4991 || EQ (Vscroll_preserve_screen_position, Qt)))
4992 /* We found PT at a legitimate height. Leave it alone. */
4994 else if (window_scroll_pixel_based_preserve_y >= 0)
4996 /* If we have a header line, take account of it.
4997 This is necessary because we set it.current_y to 0, above. */
4998 move_it_to (&it, -1,
4999 window_scroll_pixel_based_preserve_x,
5000 (window_scroll_pixel_based_preserve_y
5001 - WINDOW_WANTS_HEADER_LINE_P (w)),
5002 -1, MOVE_TO_Y | MOVE_TO_X);
5003 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5005 else
5007 while (it.current_y < this_scroll_margin)
5009 int prev = it.current_y;
5010 move_it_by_lines (&it, 1);
5011 if (prev == it.current_y)
5012 break;
5014 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5017 else if (n < 0)
5019 ptrdiff_t charpos, bytepos;
5020 bool partial_p;
5022 /* Save our position, for the
5023 window_scroll_pixel_based_preserve_y case. */
5024 charpos = IT_CHARPOS (it);
5025 bytepos = IT_BYTEPOS (it);
5027 /* We moved the window start towards BEGV, so PT may be now
5028 in the scroll margin at the bottom. */
5029 move_it_to (&it, PT, -1,
5030 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5031 - this_scroll_margin - 1),
5033 MOVE_TO_POS | MOVE_TO_Y);
5035 /* Save our position, in case it's correct. */
5036 charpos = IT_CHARPOS (it);
5037 bytepos = IT_BYTEPOS (it);
5039 /* If PT is in the screen line at the last fully visible line,
5040 move_it_to will stop at X = 0 in that line, because the
5041 required Y coordinate is reached there. See if we can get to
5042 PT without descending lower in Y, and if we can, it means we
5043 reached PT before the scroll margin. */
5044 if (charpos != PT)
5046 struct it it2;
5047 void *it_data;
5049 it2 = it;
5050 it_data = bidi_shelve_cache ();
5051 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5052 if (IT_CHARPOS (it) == PT && it.current_y == it2.current_y)
5054 charpos = IT_CHARPOS (it);
5055 bytepos = IT_BYTEPOS (it);
5056 bidi_unshelve_cache (it_data, true);
5058 else
5060 it = it2;
5061 bidi_unshelve_cache (it_data, false);
5065 /* See if point is on a partially visible line at the end. */
5066 if (it.what == IT_EOB)
5067 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5068 else
5070 move_it_by_lines (&it, 1);
5071 partial_p = it.current_y > it.last_visible_y;
5074 if (charpos == PT && !partial_p
5075 && (NILP (Vscroll_preserve_screen_position)
5076 || EQ (Vscroll_preserve_screen_position, Qt)))
5077 /* We found PT before we found the display margin, so PT is ok. */
5079 else if (window_scroll_pixel_based_preserve_y >= 0)
5081 SET_TEXT_POS_FROM_MARKER (start, w->start);
5082 start_display (&it, w, start);
5083 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5084 here because we called start_display again and did not
5085 alter it.current_y this time. */
5086 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
5087 window_scroll_pixel_based_preserve_y, -1,
5088 MOVE_TO_Y | MOVE_TO_X);
5089 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5091 else
5093 if (partial_p)
5094 /* The last line was only partially visible, so back up two
5095 lines to make sure we're on a fully visible line. */
5097 move_it_by_lines (&it, -2);
5098 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5100 else
5101 /* No, the position we saved is OK, so use it. */
5102 SET_PT_BOTH (charpos, bytepos);
5105 bidi_unshelve_cache (itdata, false);
5107 if (adjust_old_pointm)
5108 Fset_marker (w->old_pointm,
5109 ((w == XWINDOW (selected_window))
5110 ? make_number (BUF_PT (XBUFFER (w->contents)))
5111 : Fmarker_position (w->pointm)),
5112 w->contents);
5116 /* Implementation of window_scroll that works based on screen lines.
5117 See the comment of window_scroll for parameter descriptions. */
5119 static void
5120 window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
5122 struct window *w = XWINDOW (window);
5123 /* Fvertical_motion enters redisplay, which can trigger
5124 fontification, which in turn can modify buffer text (e.g., if the
5125 fontification functions replace escape sequences with faces, as
5126 in `grep-mode-font-lock-keywords'). So we use a marker to record
5127 the old point position, to prevent crashes in SET_PT_BOTH. */
5128 Lisp_Object opoint_marker = Fpoint_marker ();
5129 register ptrdiff_t pos, pos_byte;
5130 register int ht = window_internal_height (w);
5131 register Lisp_Object tem;
5132 bool lose;
5133 Lisp_Object bolp;
5134 ptrdiff_t startpos = marker_position (w->start);
5135 ptrdiff_t startbyte = marker_byte_position (w->start);
5136 Lisp_Object original_pos = Qnil;
5137 bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
5138 Fwindow_old_point (window)));
5140 /* If scrolling screen-fulls, compute the number of lines to
5141 scroll from the window's height. */
5142 if (whole)
5143 n *= max (1, ht - next_screen_context_lines);
5145 if (!NILP (Vscroll_preserve_screen_position))
5147 if (window_scroll_preserve_vpos <= 0
5148 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
5149 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
5151 struct position posit
5152 = *compute_motion (startpos, startbyte, 0, 0, false,
5153 PT, ht, 0, -1, w->hscroll, 0, w);
5155 window_scroll_preserve_vpos = posit.vpos;
5156 window_scroll_preserve_hpos = posit.hpos + w->hscroll;
5159 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
5160 make_number (window_scroll_preserve_vpos));
5163 XSETFASTINT (tem, PT);
5164 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5166 if (NILP (tem))
5168 Fvertical_motion (make_number (- (ht / 2)), window, Qnil);
5169 startpos = PT;
5170 startbyte = PT_BYTE;
5173 SET_PT_BOTH (startpos, startbyte);
5174 lose = n < 0 && PT == BEGV;
5175 Fvertical_motion (make_number (n), window, Qnil);
5176 pos = PT;
5177 pos_byte = PT_BYTE;
5178 bolp = Fbolp ();
5179 SET_PT_BOTH (marker_position (opoint_marker),
5180 marker_byte_position (opoint_marker));
5182 if (lose)
5184 if (noerror)
5185 return;
5186 else
5187 xsignal0 (Qbeginning_of_buffer);
5190 if (pos < ZV)
5192 /* Don't use a scroll margin that is negative or too large. */
5193 int this_scroll_margin =
5194 max (0, min (scroll_margin, w->total_lines / 4));
5196 set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
5197 w->start_at_line_beg = !NILP (bolp);
5198 w->update_mode_line = true;
5199 /* Set force_start so that redisplay_window will run
5200 the window-scroll-functions. */
5201 w->force_start = true;
5203 if (!NILP (Vscroll_preserve_screen_position)
5204 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5206 SET_PT_BOTH (pos, pos_byte);
5207 Fvertical_motion (original_pos, window, Qnil);
5209 /* If we scrolled forward, put point enough lines down
5210 that it is outside the scroll margin. */
5211 else if (n > 0)
5213 int top_margin;
5215 if (this_scroll_margin > 0)
5217 SET_PT_BOTH (pos, pos_byte);
5218 Fvertical_motion (make_number (this_scroll_margin), window, Qnil);
5219 top_margin = PT;
5221 else
5222 top_margin = pos;
5224 if (top_margin <= marker_position (opoint_marker))
5225 SET_PT_BOTH (marker_position (opoint_marker),
5226 marker_byte_position (opoint_marker));
5227 else if (!NILP (Vscroll_preserve_screen_position))
5229 SET_PT_BOTH (pos, pos_byte);
5230 Fvertical_motion (original_pos, window, Qnil);
5232 else
5233 SET_PT (top_margin);
5235 else if (n < 0)
5237 int bottom_margin;
5239 /* If we scrolled backward, put point near the end of the window
5240 but not within the scroll margin. */
5241 SET_PT_BOTH (pos, pos_byte);
5242 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window,
5243 Qnil);
5244 if (XFASTINT (tem) == ht - this_scroll_margin)
5245 bottom_margin = PT;
5246 else
5247 bottom_margin = PT + 1;
5249 if (bottom_margin > marker_position (opoint_marker))
5250 SET_PT_BOTH (marker_position (opoint_marker),
5251 marker_byte_position (opoint_marker));
5252 else
5254 if (!NILP (Vscroll_preserve_screen_position))
5256 SET_PT_BOTH (pos, pos_byte);
5257 Fvertical_motion (original_pos, window, Qnil);
5259 else
5260 Fvertical_motion (make_number (-1), window, Qnil);
5264 else
5266 if (noerror)
5267 return;
5268 else
5269 xsignal0 (Qend_of_buffer);
5272 if (adjust_old_pointm)
5273 Fset_marker (w->old_pointm,
5274 ((w == XWINDOW (selected_window))
5275 ? make_number (BUF_PT (XBUFFER (w->contents)))
5276 : Fmarker_position (w->pointm)),
5277 w->contents);
5281 /* Scroll selected_window up or down. If N is nil, scroll a
5282 screen-full which is defined as the height of the window minus
5283 next_screen_context_lines. If N is the symbol `-', scroll.
5284 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5285 up. This is the guts of Fscroll_up and Fscroll_down. */
5287 static void
5288 scroll_command (Lisp_Object n, int direction)
5290 ptrdiff_t count = SPECPDL_INDEX ();
5292 eassert (eabs (direction) == 1);
5294 /* If selected window's buffer isn't current, make it current for
5295 the moment. But don't screw up if window_scroll gets an error. */
5296 if (XBUFFER (XWINDOW (selected_window)->contents) != current_buffer)
5298 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5299 Fset_buffer (XWINDOW (selected_window)->contents);
5302 if (NILP (n))
5303 window_scroll (selected_window, direction, true, false);
5304 else if (EQ (n, Qminus))
5305 window_scroll (selected_window, -direction, true, false);
5306 else
5308 n = Fprefix_numeric_value (n);
5309 window_scroll (selected_window, XINT (n) * direction, false, false);
5312 unbind_to (count, Qnil);
5315 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
5316 doc: /* Scroll text of selected window upward ARG lines.
5317 If ARG is omitted or nil, scroll upward by a near full screen.
5318 A near full screen is `next-screen-context-lines' less than a full screen.
5319 Negative ARG means scroll downward.
5320 If ARG is the atom `-', scroll downward by nearly full screen.
5321 When calling from a program, supply as argument a number, nil, or `-'. */)
5322 (Lisp_Object arg)
5324 scroll_command (arg, 1);
5325 return Qnil;
5328 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
5329 doc: /* Scroll text of selected window down ARG lines.
5330 If ARG is omitted or nil, scroll down by a near full screen.
5331 A near full screen is `next-screen-context-lines' less than a full screen.
5332 Negative ARG means scroll upward.
5333 If ARG is the atom `-', scroll upward by nearly full screen.
5334 When calling from a program, supply as argument a number, nil, or `-'. */)
5335 (Lisp_Object arg)
5337 scroll_command (arg, -1);
5338 return Qnil;
5341 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5342 doc: /* Return the other window for \"other window scroll\" commands.
5343 If `other-window-scroll-buffer' is non-nil, a window
5344 showing that buffer is used.
5345 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5346 specifies the window. This takes precedence over
5347 `other-window-scroll-buffer'. */)
5348 (void)
5350 Lisp_Object window;
5352 if (MINI_WINDOW_P (XWINDOW (selected_window))
5353 && !NILP (Vminibuf_scroll_window))
5354 window = Vminibuf_scroll_window;
5355 /* If buffer is specified and live, scroll that buffer. */
5356 else if (!NILP (Vother_window_scroll_buffer)
5357 && BUFFERP (Vother_window_scroll_buffer)
5358 && BUFFER_LIVE_P (XBUFFER (Vother_window_scroll_buffer)))
5360 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5361 if (NILP (window))
5362 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5364 else
5366 /* Nothing specified; look for a neighboring window on the same
5367 frame. */
5368 window = Fnext_window (selected_window, Qnil, Qnil);
5370 if (EQ (window, selected_window))
5371 /* That didn't get us anywhere; look for a window on another
5372 visible frame. */
5374 window = Fnext_window (window, Qnil, Qt);
5375 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5376 && ! EQ (window, selected_window));
5379 CHECK_LIVE_WINDOW (window);
5381 if (EQ (window, selected_window))
5382 error ("There is no other window");
5384 return window;
5387 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5388 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5389 A near full screen is `next-screen-context-lines' less than a full screen.
5390 The next window is the one below the current one; or the one at the top
5391 if the current one is at the bottom. Negative ARG means scroll downward.
5392 If ARG is the atom `-', scroll downward by nearly full screen.
5393 When calling from a program, supply as argument a number, nil, or `-'.
5395 If `other-window-scroll-buffer' is non-nil, scroll the window
5396 showing that buffer, popping the buffer up if necessary.
5397 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5398 specifies the window to scroll. This takes precedence over
5399 `other-window-scroll-buffer'. */)
5400 (Lisp_Object arg)
5402 Lisp_Object window;
5403 struct window *w;
5404 ptrdiff_t count = SPECPDL_INDEX ();
5406 window = Fother_window_for_scrolling ();
5407 w = XWINDOW (window);
5409 /* Don't screw up if window_scroll gets an error. */
5410 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5412 Fset_buffer (w->contents);
5413 SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
5414 SET_PT_BOTH (marker_position (w->old_pointm), marker_byte_position (w->old_pointm));
5416 if (NILP (arg))
5417 window_scroll (window, 1, true, true);
5418 else if (EQ (arg, Qminus))
5419 window_scroll (window, -1, true, true);
5420 else
5422 if (CONSP (arg))
5423 arg = XCAR (arg);
5424 CHECK_NUMBER (arg);
5425 window_scroll (window, XINT (arg), false, true);
5428 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5429 set_marker_both (w->old_pointm, Qnil, PT, PT_BYTE);
5430 unbind_to (count, Qnil);
5432 return Qnil;
5435 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5436 doc: /* Scroll selected window display ARG columns left.
5437 Default for ARG is window width minus 2.
5438 Value is the total amount of leftward horizontal scrolling in
5439 effect after the change.
5440 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5441 lower bound for automatic scrolling, i.e. automatic scrolling
5442 will not scroll a window to a column less than the value returned
5443 by this function. This happens in an interactive call. */)
5444 (register Lisp_Object arg, Lisp_Object set_minimum)
5446 struct window *w = XWINDOW (selected_window);
5447 EMACS_INT requested_arg = (NILP (arg)
5448 ? window_body_width (w, 0) - 2
5449 : XINT (Fprefix_numeric_value (arg)));
5450 Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
5452 if (!NILP (set_minimum))
5453 w->min_hscroll = w->hscroll;
5455 w->suspend_auto_hscroll = true;
5457 return result;
5460 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5461 doc: /* Scroll selected window display ARG columns right.
5462 Default for ARG is window width minus 2.
5463 Value is the total amount of leftward horizontal scrolling in
5464 effect after the change.
5465 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5466 lower bound for automatic scrolling, i.e. automatic scrolling
5467 will not scroll a window to a column less than the value returned
5468 by this function. This happens in an interactive call. */)
5469 (register Lisp_Object arg, Lisp_Object set_minimum)
5471 struct window *w = XWINDOW (selected_window);
5472 EMACS_INT requested_arg = (NILP (arg)
5473 ? window_body_width (w, 0) - 2
5474 : XINT (Fprefix_numeric_value (arg)));
5475 Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
5477 if (!NILP (set_minimum))
5478 w->min_hscroll = w->hscroll;
5480 w->suspend_auto_hscroll = true;
5482 return result;
5485 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5486 doc: /* Return the window which was selected when entering the minibuffer.
5487 Returns nil, if selected window is not a minibuffer window. */)
5488 (void)
5490 if (minibuf_level > 0
5491 && MINI_WINDOW_P (XWINDOW (selected_window))
5492 && WINDOW_LIVE_P (minibuf_selected_window))
5493 return minibuf_selected_window;
5495 return Qnil;
5498 /* Value is the number of lines actually displayed in window W,
5499 as opposed to its height. */
5501 static int
5502 displayed_window_lines (struct window *w)
5504 struct it it;
5505 struct text_pos start;
5506 int height = window_box_height (w);
5507 struct buffer *old_buffer;
5508 int bottom_y;
5509 void *itdata = NULL;
5511 if (XBUFFER (w->contents) != current_buffer)
5513 old_buffer = current_buffer;
5514 set_buffer_internal (XBUFFER (w->contents));
5516 else
5517 old_buffer = NULL;
5519 /* In case W->start is out of the accessible range, do something
5520 reasonable. This happens in Info mode when Info-scroll-down
5521 calls (recenter -1) while W->start is 1. */
5522 CLIP_TEXT_POS_FROM_MARKER (start, w->start);
5524 itdata = bidi_shelve_cache ();
5525 start_display (&it, w, start);
5526 move_it_vertically (&it, height);
5527 bottom_y = line_bottom_y (&it);
5528 bidi_unshelve_cache (itdata, false);
5530 /* rms: On a non-window display,
5531 the value of it.vpos at the bottom of the screen
5532 seems to be 1 larger than window_box_height (w).
5533 This kludge fixes a bug whereby (move-to-window-line -1)
5534 when ZV is on the last screen line
5535 moves to the previous screen line instead of the last one. */
5536 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5537 height++;
5539 /* Add in empty lines at the bottom of the window. */
5540 if (bottom_y < height)
5542 int uy = FRAME_LINE_HEIGHT (it.f);
5543 it.vpos += (height - bottom_y + uy - 1) / uy;
5546 if (old_buffer)
5547 set_buffer_internal (old_buffer);
5549 return it.vpos;
5553 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5554 doc: /* Center point in selected window and maybe redisplay frame.
5555 With a numeric prefix argument ARG, recenter putting point on screen line ARG
5556 relative to the selected window. If ARG is negative, it counts up from the
5557 bottom of the window. (ARG should be less than the height of the window.)
5559 If ARG is omitted or nil, then recenter with point on the middle line of
5560 the selected window; if the variable `recenter-redisplay' is non-nil,
5561 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5562 is set to `grow-only', this resets the tool-bar's height to the minimum
5563 height needed); if `recenter-redisplay' has the special value `tty',
5564 then only tty frames are redrawn.
5566 Just C-u as prefix means put point in the center of the window
5567 and redisplay normally--don't erase and redraw the frame. */)
5568 (register Lisp_Object arg)
5570 struct window *w = XWINDOW (selected_window);
5571 struct buffer *buf = XBUFFER (w->contents);
5572 bool center_p = false;
5573 ptrdiff_t charpos, bytepos;
5574 EMACS_INT iarg IF_LINT (= 0);
5575 int this_scroll_margin;
5577 if (buf != current_buffer)
5578 error ("`recenter'ing a window that does not display current-buffer.");
5580 /* If redisplay is suppressed due to an error, try again. */
5581 buf->display_error_modiff = 0;
5583 if (NILP (arg))
5585 if (!NILP (Vrecenter_redisplay)
5586 && (!EQ (Vrecenter_redisplay, Qtty)
5587 || !NILP (Ftty_type (selected_frame))))
5589 ptrdiff_t i;
5591 /* Invalidate pixel data calculated for all compositions. */
5592 for (i = 0; i < n_compositions; i++)
5593 composition_table[i]->font = NULL;
5594 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
5595 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5596 #endif
5597 Fredraw_frame (WINDOW_FRAME (w));
5598 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5601 center_p = true;
5603 else if (CONSP (arg)) /* Just C-u. */
5604 center_p = true;
5605 else
5607 arg = Fprefix_numeric_value (arg);
5608 CHECK_NUMBER (arg);
5609 iarg = XINT (arg);
5612 /* Do this after making BUF current
5613 in case scroll_margin is buffer-local. */
5614 this_scroll_margin
5615 = max (0, min (scroll_margin, w->total_lines / 4));
5617 /* Don't use redisplay code for initial frames, as the necessary
5618 data structures might not be set up yet then. */
5619 if (!FRAME_INITIAL_P (XFRAME (w->frame)))
5621 if (center_p)
5623 struct it it;
5624 struct text_pos pt;
5625 void *itdata = bidi_shelve_cache ();
5627 SET_TEXT_POS (pt, PT, PT_BYTE);
5628 start_display (&it, w, pt);
5629 move_it_vertically_backward (&it, window_box_height (w) / 2);
5630 charpos = IT_CHARPOS (it);
5631 bytepos = IT_BYTEPOS (it);
5632 bidi_unshelve_cache (itdata, false);
5634 else if (iarg < 0)
5636 struct it it;
5637 struct text_pos pt;
5638 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
5639 int extra_line_spacing;
5640 int h = window_box_height (w);
5641 int ht = window_internal_height (w);
5642 void *itdata = bidi_shelve_cache ();
5644 nlines = clip_to_bounds (this_scroll_margin + 1, nlines,
5645 ht - this_scroll_margin);
5647 SET_TEXT_POS (pt, PT, PT_BYTE);
5648 start_display (&it, w, pt);
5650 /* Be sure we have the exact height of the full line containing PT. */
5651 move_it_by_lines (&it, 0);
5653 /* The amount of pixels we have to move back is the window
5654 height minus what's displayed in the line containing PT,
5655 and the lines below. */
5656 it.current_y = 0;
5657 it.vpos = 0;
5658 move_it_by_lines (&it, nlines);
5660 if (it.vpos == nlines)
5661 h -= it.current_y;
5662 else
5664 /* Last line has no newline. */
5665 h -= line_bottom_y (&it);
5666 it.vpos++;
5669 /* Don't reserve space for extra line spacing of last line. */
5670 extra_line_spacing = it.max_extra_line_spacing;
5672 /* If we can't move down NLINES lines because we hit
5673 the end of the buffer, count in some empty lines. */
5674 if (it.vpos < nlines)
5676 nlines -= it.vpos;
5677 extra_line_spacing = it.extra_line_spacing;
5678 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5680 if (h <= 0)
5682 bidi_unshelve_cache (itdata, false);
5683 return Qnil;
5686 /* Now find the new top line (starting position) of the window. */
5687 start_display (&it, w, pt);
5688 it.current_y = 0;
5689 move_it_vertically_backward (&it, h);
5691 /* If extra line spacing is present, we may move too far
5692 back. This causes the last line to be only partially
5693 visible (which triggers redisplay to recenter that line
5694 in the middle), so move forward.
5695 But ignore extra line spacing on last line, as it is not
5696 considered to be part of the visible height of the line.
5698 h += extra_line_spacing;
5699 while (-it.current_y > h)
5700 move_it_by_lines (&it, 1);
5702 charpos = IT_CHARPOS (it);
5703 bytepos = IT_BYTEPOS (it);
5705 bidi_unshelve_cache (itdata, false);
5707 else
5709 struct it it;
5710 struct text_pos pt;
5711 ptrdiff_t nlines = min (PTRDIFF_MAX, iarg);
5712 int ht = window_internal_height (w);
5713 void *itdata = bidi_shelve_cache ();
5715 nlines = clip_to_bounds (this_scroll_margin, nlines,
5716 ht - this_scroll_margin - 1);
5718 SET_TEXT_POS (pt, PT, PT_BYTE);
5719 start_display (&it, w, pt);
5721 /* Move to the beginning of screen line containing PT. */
5722 move_it_by_lines (&it, 0);
5724 /* Move back to find the point which is ARG screen lines above PT. */
5725 if (nlines > 0)
5727 it.current_y = 0;
5728 it.vpos = 0;
5729 move_it_by_lines (&it, -nlines);
5732 charpos = IT_CHARPOS (it);
5733 bytepos = IT_BYTEPOS (it);
5735 bidi_unshelve_cache (itdata, false);
5738 else
5740 struct position pos;
5741 int ht = window_internal_height (w);
5743 if (center_p)
5744 iarg = ht / 2;
5745 else if (iarg < 0)
5746 iarg += ht;
5748 /* Don't let it get into the margin at either top or bottom. */
5749 iarg = clip_to_bounds (this_scroll_margin, iarg,
5750 ht - this_scroll_margin - 1);
5752 pos = *vmotion (PT, PT_BYTE, - iarg, w);
5753 charpos = pos.bufpos;
5754 bytepos = pos.bytepos;
5757 /* Set the new window start. */
5758 set_marker_both (w->start, w->contents, charpos, bytepos);
5759 w->window_end_valid = false;
5761 w->optional_new_start = true;
5763 w->start_at_line_beg = (bytepos == BEGV_BYTE
5764 || FETCH_BYTE (bytepos - 1) == '\n');
5766 wset_redisplay (w);
5768 return Qnil;
5771 DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
5772 0, 2, 0,
5773 doc: /* Return the width in columns of the text display area of WINDOW.
5774 WINDOW must be a live window and defaults to the selected one.
5776 The returned width does not include dividers, scrollbars, margins,
5777 fringes, nor any partial-width columns at the right of the text
5778 area.
5780 Optional argument PIXELWISE non-nil, means to return the width in
5781 pixels. */)
5782 (Lisp_Object window, Lisp_Object pixelwise)
5784 struct window *w = decode_live_window (window);
5786 if (NILP (pixelwise))
5787 return make_number (window_box_width (w, TEXT_AREA)
5788 / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
5789 else
5790 return make_number (window_box_width (w, TEXT_AREA));
5793 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5794 0, 2, 0,
5795 doc: /* Return the height in lines of the text display area of WINDOW.
5796 WINDOW must be a live window and defaults to the selected one.
5798 The returned height does not include dividers, the mode line, any header
5799 line, nor any partial-height lines at the bottom of the text area.
5801 Optional argument PIXELWISE non-nil, means to return the height in
5802 pixels. */)
5803 (Lisp_Object window, Lisp_Object pixelwise)
5805 struct window *w = decode_live_window (window);
5807 if (NILP (pixelwise))
5808 return make_number (window_box_height (w)
5809 / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
5810 else
5811 return make_number (window_box_height (w));
5814 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5815 1, 1, "P",
5816 doc: /* Position point relative to window.
5817 ARG nil means position point at center of window.
5818 Else, ARG specifies vertical position within the window;
5819 zero means top of window, negative means relative to bottom of window. */)
5820 (Lisp_Object arg)
5822 struct window *w = XWINDOW (selected_window);
5823 int lines, start;
5824 Lisp_Object window;
5825 #if false
5826 int this_scroll_margin;
5827 #endif
5829 if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer))
5830 /* This test is needed to make sure PT/PT_BYTE make sense in w->contents
5831 when passed below to set_marker_both. */
5832 error ("move-to-window-line called from unrelated buffer");
5834 window = selected_window;
5835 start = marker_position (w->start);
5836 if (start < BEGV || start > ZV)
5838 int height = window_internal_height (w);
5839 Fvertical_motion (make_number (- (height / 2)), window, Qnil);
5840 set_marker_both (w->start, w->contents, PT, PT_BYTE);
5841 w->start_at_line_beg = !NILP (Fbolp ());
5842 w->force_start = true;
5844 else
5845 Fgoto_char (w->start);
5847 lines = displayed_window_lines (w);
5849 #if false
5850 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
5851 #endif
5853 if (NILP (arg))
5854 XSETFASTINT (arg, lines / 2);
5855 else
5857 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
5859 if (iarg < 0)
5860 iarg = iarg + lines;
5862 #if false /* This code would prevent move-to-window-line from moving point
5863 to a place inside the scroll margins (which would cause the
5864 next redisplay to scroll). I wrote this code, but then concluded
5865 it is probably better not to install it. However, it is here
5866 inside #if false so as not to lose it. -- rms. */
5868 /* Don't let it get into the margin at either top or bottom. */
5869 iarg = max (iarg, this_scroll_margin);
5870 iarg = min (iarg, lines - this_scroll_margin - 1);
5871 #endif
5873 arg = make_number (iarg);
5876 /* Skip past a partially visible first line. */
5877 if (w->vscroll)
5878 XSETINT (arg, XINT (arg) + 1);
5880 return Fvertical_motion (arg, window, Qnil);
5885 /***********************************************************************
5886 Window Configuration
5887 ***********************************************************************/
5889 struct save_window_data
5891 struct vectorlike_header header;
5892 Lisp_Object selected_frame;
5893 Lisp_Object current_window;
5894 Lisp_Object current_buffer;
5895 Lisp_Object minibuf_scroll_window;
5896 Lisp_Object minibuf_selected_window;
5897 Lisp_Object root_window;
5898 Lisp_Object focus_frame;
5899 /* A vector, each of whose elements is a struct saved_window
5900 for one window. */
5901 Lisp_Object saved_windows;
5903 /* All fields above are traced by the GC.
5904 From `frame-cols' down, the fields are ignored by the GC. */
5905 /* We should be able to do without the following two. */
5906 int frame_cols, frame_lines;
5907 /* These two should get eventually replaced by their pixel
5908 counterparts. */
5909 int frame_menu_bar_lines, frame_tool_bar_lines;
5910 int frame_text_width, frame_text_height;
5911 /* These are currently unused. We need them as soon as we convert
5912 to pixels. */
5913 int frame_menu_bar_height, frame_tool_bar_height;
5916 /* This is saved as a Lisp_Vector. */
5917 struct saved_window
5919 struct vectorlike_header header;
5921 Lisp_Object window, buffer, start, pointm, old_pointm;
5922 Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
5923 Lisp_Object left_col, top_line, total_cols, total_lines;
5924 Lisp_Object normal_cols, normal_lines;
5925 Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll;
5926 Lisp_Object parent, prev;
5927 Lisp_Object start_at_line_beg;
5928 Lisp_Object display_table;
5929 Lisp_Object left_margin_cols, right_margin_cols;
5930 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5931 Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
5932 Lisp_Object scroll_bar_height, horizontal_scroll_bar_type;
5933 Lisp_Object combination_limit, window_parameters;
5936 #define SAVED_WINDOW_N(swv,n) \
5937 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5939 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5940 doc: /* Return t if OBJECT is a window-configuration object. */)
5941 (Lisp_Object object)
5943 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5946 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5947 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5948 (Lisp_Object config)
5950 register struct save_window_data *data;
5951 struct Lisp_Vector *saved_windows;
5953 CHECK_WINDOW_CONFIGURATION (config);
5955 data = (struct save_window_data *) XVECTOR (config);
5956 saved_windows = XVECTOR (data->saved_windows);
5957 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5960 DEFUN ("set-window-configuration", Fset_window_configuration,
5961 Sset_window_configuration, 1, 1, 0,
5962 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5963 CONFIGURATION must be a value previously returned
5964 by `current-window-configuration' (which see).
5965 If CONFIGURATION was made from a frame that is now deleted,
5966 only frame-independent values can be restored. In this case,
5967 the return value is nil. Otherwise the value is t. */)
5968 (Lisp_Object configuration)
5970 register struct save_window_data *data;
5971 struct Lisp_Vector *saved_windows;
5972 Lisp_Object new_current_buffer;
5973 Lisp_Object frame;
5974 struct frame *f;
5975 ptrdiff_t old_point = -1;
5976 USE_SAFE_ALLOCA;
5978 CHECK_WINDOW_CONFIGURATION (configuration);
5980 data = (struct save_window_data *) XVECTOR (configuration);
5981 saved_windows = XVECTOR (data->saved_windows);
5983 new_current_buffer = data->current_buffer;
5984 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5985 new_current_buffer = Qnil;
5986 else
5988 if (XBUFFER (new_current_buffer) == current_buffer)
5989 /* The code further down "preserves point" by saving here PT in
5990 old_point and then setting it later back into PT. When the
5991 current-selected-window and the final-selected-window both show
5992 the current buffer, this suffers from the problem that the
5993 current PT is the window-point of the current-selected-window,
5994 while the final PT is the point of the final-selected-window, so
5995 this copy from one PT to the other would end up moving the
5996 window-point of the final-selected-window to the window-point of
5997 the current-selected-window. So we have to be careful which
5998 point of the current-buffer we copy into old_point. */
5999 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
6000 && WINDOWP (selected_window)
6001 && EQ (XWINDOW (selected_window)->contents, new_current_buffer)
6002 && !EQ (selected_window, data->current_window))
6003 old_point = marker_position (XWINDOW (data->current_window)->pointm);
6004 else
6005 old_point = PT;
6006 else
6007 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6008 point in new_current_buffer as of the last time this buffer was
6009 used. This can be non-deterministic since it can be changed by
6010 things like jit-lock by mere temporary selection of some random
6011 window that happens to show this buffer.
6012 So if possible we want this arbitrary choice of "which point" to
6013 be the one from the to-be-selected-window so as to prevent this
6014 window's cursor from being copied from another window. */
6015 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
6016 /* If current_window = selected_window, its point is in BUF_PT. */
6017 && !EQ (selected_window, data->current_window))
6018 old_point = marker_position (XWINDOW (data->current_window)->pointm);
6019 else
6020 old_point = BUF_PT (XBUFFER (new_current_buffer));
6023 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6024 f = XFRAME (frame);
6026 /* If f is a dead frame, don't bother rebuilding its window tree.
6027 However, there is other stuff we should still try to do below. */
6028 if (FRAME_LIVE_P (f))
6030 Lisp_Object window;
6031 Lisp_Object dead_windows = Qnil;
6032 Lisp_Object tem, par, pers;
6033 struct window *w;
6034 struct saved_window *p;
6035 struct window *root_window;
6036 struct window **leaf_windows;
6037 ptrdiff_t i, k, n_leaf_windows;
6039 /* Don't do this within the main loop below: This may call Lisp
6040 code and is thus potentially unsafe while input is blocked. */
6041 for (k = 0; k < saved_windows->header.size; k++)
6043 p = SAVED_WINDOW_N (saved_windows, k);
6044 window = p->window;
6045 w = XWINDOW (window);
6046 if (BUFFERP (w->contents)
6047 && !EQ (w->contents, p->buffer)
6048 && BUFFER_LIVE_P (XBUFFER (p->buffer)))
6049 /* If a window we restore gets another buffer, record the
6050 window's old buffer. */
6051 call1 (Qrecord_window_buffer, window);
6054 /* Disallow x_set_window_size, temporarily. */
6055 f->can_x_set_window_size = false;
6056 /* The mouse highlighting code could get screwed up
6057 if it runs during this. */
6058 block_input ();
6060 /* "Swap out" point from the selected window's buffer
6061 into the window itself. (Normally the pointm of the selected
6062 window holds garbage.) We do this now, before
6063 restoring the window contents, and prevent it from
6064 being done later on when we select a new window. */
6065 if (! NILP (XWINDOW (selected_window)->contents))
6067 w = XWINDOW (selected_window);
6068 set_marker_both (w->pointm,
6069 w->contents,
6070 BUF_PT (XBUFFER (w->contents)),
6071 BUF_PT_BYTE (XBUFFER (w->contents)));
6074 fset_redisplay (f);
6075 FRAME_WINDOW_SIZES_CHANGED (f) = true;
6077 /* Problem: Freeing all matrices and later allocating them again
6078 is a serious redisplay flickering problem. What we would
6079 really like to do is to free only those matrices not reused
6080 below. */
6081 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6082 ptrdiff_t nwindows = count_windows (root_window);
6083 SAFE_NALLOCA (leaf_windows, 1, nwindows);
6084 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6086 /* Kludge Alert!
6087 Mark all windows now on frame as "deleted".
6088 Restoring the new configuration "undeletes" any that are in it.
6090 Save their current buffers in their height fields, since we may
6091 need it later, if a buffer saved in the configuration is now
6092 dead. */
6093 delete_all_child_windows (FRAME_ROOT_WINDOW (f));
6095 for (k = 0; k < saved_windows->header.size; k++)
6097 p = SAVED_WINDOW_N (saved_windows, k);
6098 window = p->window;
6099 w = XWINDOW (window);
6100 wset_next (w, Qnil);
6102 if (!NILP (p->parent))
6103 wset_parent
6104 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window);
6105 else
6106 wset_parent (w, Qnil);
6108 if (!NILP (p->prev))
6110 wset_prev
6111 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window);
6112 wset_next (XWINDOW (w->prev), p->window);
6114 else
6116 wset_prev (w, Qnil);
6117 if (!NILP (w->parent))
6118 wset_combination (XWINDOW (w->parent),
6119 (XINT (p->total_cols)
6120 != XWINDOW (w->parent)->total_cols),
6121 p->window);
6124 /* If we squirreled away the buffer, restore it now. */
6125 if (BUFFERP (w->combination_limit))
6126 wset_buffer (w, w->combination_limit);
6127 w->pixel_left = XFASTINT (p->pixel_left);
6128 w->pixel_top = XFASTINT (p->pixel_top);
6129 w->pixel_width = XFASTINT (p->pixel_width);
6130 w->pixel_height = XFASTINT (p->pixel_height);
6131 w->left_col = XFASTINT (p->left_col);
6132 w->top_line = XFASTINT (p->top_line);
6133 w->total_cols = XFASTINT (p->total_cols);
6134 w->total_lines = XFASTINT (p->total_lines);
6135 wset_normal_cols (w, p->normal_cols);
6136 wset_normal_lines (w, p->normal_lines);
6137 w->hscroll = XFASTINT (p->hscroll);
6138 w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll);
6139 w->min_hscroll = XFASTINT (p->min_hscroll);
6140 w->hscroll_whole = XFASTINT (p->hscroll_whole);
6141 wset_display_table (w, p->display_table);
6142 w->left_margin_cols = XINT (p->left_margin_cols);
6143 w->right_margin_cols = XINT (p->right_margin_cols);
6144 w->left_fringe_width = XINT (p->left_fringe_width);
6145 w->right_fringe_width = XINT (p->right_fringe_width);
6146 w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
6147 w->scroll_bar_width = XINT (p->scroll_bar_width);
6148 w->scroll_bar_height = XINT (p->scroll_bar_height);
6149 wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
6150 wset_horizontal_scroll_bar_type (w, p->horizontal_scroll_bar_type);
6151 wset_dedicated (w, p->dedicated);
6152 wset_combination_limit (w, p->combination_limit);
6153 /* Restore any window parameters that have been saved.
6154 Parameters that have not been saved are left alone. */
6155 for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
6157 pers = XCAR (tem);
6158 if (CONSP (pers))
6160 if (NILP (XCDR (pers)))
6162 par = Fassq (XCAR (pers), w->window_parameters);
6163 if (CONSP (par) && !NILP (XCDR (par)))
6164 /* Reset a parameter to nil if and only if it
6165 has a non-nil association. Don't make new
6166 associations. */
6167 Fsetcdr (par, Qnil);
6169 else
6170 /* Always restore a non-nil value. */
6171 Fset_window_parameter (window, XCAR (pers), XCDR (pers));
6175 if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
6176 /* If saved buffer is alive, install it. */
6178 wset_buffer (w, p->buffer);
6179 w->start_at_line_beg = !NILP (p->start_at_line_beg);
6180 set_marker_restricted (w->start, p->start, w->contents);
6181 set_marker_restricted (w->pointm, p->pointm, w->contents);
6182 set_marker_restricted (w->old_pointm, p->old_pointm, w->contents);
6183 /* As documented in Fcurrent_window_configuration, don't
6184 restore the location of point in the buffer which was
6185 current when the window configuration was recorded. */
6186 if (!EQ (p->buffer, new_current_buffer)
6187 && XBUFFER (p->buffer) == current_buffer)
6188 Fgoto_char (w->pointm);
6190 else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
6191 /* Keep window's old buffer; make sure the markers are real. */
6193 /* Set window markers at start of visible range. */
6194 if (XMARKER (w->start)->buffer == 0)
6195 set_marker_restricted_both (w->start, w->contents, 0, 0);
6196 if (XMARKER (w->pointm)->buffer == 0)
6197 set_marker_restricted_both
6198 (w->pointm, w->contents,
6199 BUF_PT (XBUFFER (w->contents)),
6200 BUF_PT_BYTE (XBUFFER (w->contents)));
6201 if (XMARKER (w->old_pointm)->buffer == 0)
6202 set_marker_restricted_both
6203 (w->old_pointm, w->contents,
6204 BUF_PT (XBUFFER (w->contents)),
6205 BUF_PT_BYTE (XBUFFER (w->contents)));
6206 w->start_at_line_beg = true;
6208 else if (!NILP (w->start))
6209 /* Leaf window has no live buffer, get one. */
6211 /* Get the buffer via other_buffer_safely in order to
6212 avoid showing an unimportant buffer and, if necessary, to
6213 recreate *scratch* in the course (part of Juanma's bs-show
6214 scenario from March 2011). */
6215 wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
6216 /* This will set the markers to beginning of visible
6217 range. */
6218 set_marker_restricted_both (w->start, w->contents, 0, 0);
6219 set_marker_restricted_both (w->pointm, w->contents, 0, 0);
6220 set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
6221 w->start_at_line_beg = true;
6222 if (!NILP (w->dedicated))
6223 /* Record this window as dead. */
6224 dead_windows = Fcons (window, dead_windows);
6225 /* Make sure window is no more dedicated. */
6226 wset_dedicated (w, Qnil);
6230 fset_root_window (f, data->root_window);
6231 /* Arrange *not* to restore point in the buffer that was
6232 current when the window configuration was saved. */
6233 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
6234 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6235 make_number (old_point),
6236 XWINDOW (data->current_window)->contents);
6238 /* In the following call to `select-window', prevent "swapping out
6239 point" in the old selected window using the buffer that has
6240 been restored into it. We already swapped out that point from
6241 that window's old buffer.
6243 Do not record the buffer here. We do that in a separate call
6244 to select_window below. See also Bug#16207. */
6245 select_window (data->current_window, Qt, true);
6246 BVAR (XBUFFER (XWINDOW (selected_window)->contents),
6247 last_selected_window)
6248 = selected_window;
6250 if (NILP (data->focus_frame)
6251 || (FRAMEP (data->focus_frame)
6252 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6253 Fredirect_frame_focus (frame, data->focus_frame);
6255 /* Now, free glyph matrices in windows that were not reused. */
6256 for (i = 0; i < n_leaf_windows; i++)
6257 if (NILP (leaf_windows[i]->contents))
6258 free_window_matrices (leaf_windows[i]);
6260 /* Allow x_set_window_size again and apply frame size changes if
6261 needed. */
6262 f->can_x_set_window_size = true;
6263 adjust_frame_size (f, -1, -1, 1, false, Qset_window_configuration);
6265 adjust_frame_glyphs (f);
6266 unblock_input ();
6268 /* Scan dead buffer windows. */
6269 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
6271 window = XCAR (dead_windows);
6272 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
6273 delete_deletable_window (window);
6276 /* Record the selected window's buffer here. The window should
6277 already be the selected one from the call above. */
6278 select_window (data->current_window, Qnil, false);
6280 /* Fselect_window will have made f the selected frame, so we
6281 reselect the proper frame here. Fhandle_switch_frame will change the
6282 selected window too, but that doesn't make the call to
6283 Fselect_window above totally superfluous; it still sets f's
6284 selected window. */
6285 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6286 do_switch_frame (data->selected_frame, 0, 0, Qnil);
6288 run_window_configuration_change_hook (f);
6291 if (!NILP (new_current_buffer))
6293 Fset_buffer (new_current_buffer);
6294 /* If the new current buffer doesn't appear in the selected
6295 window, go to its old point (see bug#12208). */
6296 if (!EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
6297 Fgoto_char (make_number (old_point));
6300 Vminibuf_scroll_window = data->minibuf_scroll_window;
6301 minibuf_selected_window = data->minibuf_selected_window;
6303 SAFE_FREE ();
6304 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6308 void
6309 restore_window_configuration (Lisp_Object configuration)
6311 Fset_window_configuration (configuration);
6315 /* If WINDOW is an internal window, recursively delete all child windows
6316 reachable via the next and contents slots of WINDOW. Otherwise setup
6317 WINDOW to not show any buffer. */
6319 void
6320 delete_all_child_windows (Lisp_Object window)
6322 register struct window *w;
6324 w = XWINDOW (window);
6326 if (!NILP (w->next))
6327 /* Delete WINDOW's siblings (we traverse postorderly). */
6328 delete_all_child_windows (w->next);
6330 if (WINDOWP (w->contents))
6332 delete_all_child_windows (w->contents);
6333 wset_combination (w, false, Qnil);
6335 else if (BUFFERP (w->contents))
6337 unshow_buffer (w);
6338 unchain_marker (XMARKER (w->pointm));
6339 unchain_marker (XMARKER (w->old_pointm));
6340 unchain_marker (XMARKER (w->start));
6341 /* Since combination limit makes sense for an internal windows
6342 only, we use this slot to save the buffer for the sake of
6343 possible resurrection in Fset_window_configuration. */
6344 wset_combination_limit (w, w->contents);
6345 wset_buffer (w, Qnil);
6348 Vwindow_list = Qnil;
6351 static ptrdiff_t
6352 count_windows (struct window *window)
6354 ptrdiff_t count = 1;
6355 if (!NILP (window->next))
6356 count += count_windows (XWINDOW (window->next));
6357 if (WINDOWP (window->contents))
6358 count += count_windows (XWINDOW (window->contents));
6359 return count;
6363 /* Fill vector FLAT with leaf windows under W, starting at index I.
6364 Value is last index + 1. */
6365 static ptrdiff_t
6366 get_leaf_windows (struct window *w, struct window **flat, ptrdiff_t i)
6368 while (w)
6370 if (WINDOWP (w->contents))
6371 i = get_leaf_windows (XWINDOW (w->contents), flat, i);
6372 else
6373 flat[i++] = w;
6375 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6378 return i;
6382 /* Return a pointer to the glyph W's physical cursor is on. Value is
6383 null if W's current matrix is invalid, so that no meaningful glyph
6384 can be returned. */
6385 struct glyph *
6386 get_phys_cursor_glyph (struct window *w)
6388 struct glyph_row *row;
6389 struct glyph *glyph;
6390 int hpos = w->phys_cursor.hpos;
6392 if (!(w->phys_cursor.vpos >= 0
6393 && w->phys_cursor.vpos < w->current_matrix->nrows))
6394 return NULL;
6396 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
6397 if (!row->enabled_p)
6398 return NULL;
6400 if (w->hscroll)
6402 /* When the window is hscrolled, cursor hpos can legitimately be
6403 out of bounds, but we draw the cursor at the corresponding
6404 window margin in that case. */
6405 if (!row->reversed_p && hpos < 0)
6406 hpos = 0;
6407 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
6408 hpos = row->used[TEXT_AREA] - 1;
6411 if (0 <= hpos && hpos < row->used[TEXT_AREA])
6412 glyph = row->glyphs[TEXT_AREA] + hpos;
6413 else
6414 glyph = NULL;
6416 return glyph;
6420 static ptrdiff_t
6421 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i)
6423 struct saved_window *p;
6424 struct window *w;
6425 Lisp_Object tem, pers, par;
6427 for (; !NILP (window); window = w->next)
6429 p = SAVED_WINDOW_N (vector, i);
6430 w = XWINDOW (window);
6432 wset_temslot (w, make_number (i)); i++;
6433 p->window = window;
6434 p->buffer = (WINDOW_LEAF_P (w) ? w->contents : Qnil);
6435 p->pixel_left = make_number (w->pixel_left);
6436 p->pixel_top = make_number (w->pixel_top);
6437 p->pixel_width = make_number (w->pixel_width);
6438 p->pixel_height = make_number (w->pixel_height);
6439 p->left_col = make_number (w->left_col);
6440 p->top_line = make_number (w->top_line);
6441 p->total_cols = make_number (w->total_cols);
6442 p->total_lines = make_number (w->total_lines);
6443 p->normal_cols = w->normal_cols;
6444 p->normal_lines = w->normal_lines;
6445 XSETFASTINT (p->hscroll, w->hscroll);
6446 p->suspend_auto_hscroll = w->suspend_auto_hscroll ? Qt : Qnil;
6447 XSETFASTINT (p->min_hscroll, w->min_hscroll);
6448 XSETFASTINT (p->hscroll_whole, w->hscroll_whole);
6449 p->display_table = w->display_table;
6450 p->left_margin_cols = make_number (w->left_margin_cols);
6451 p->right_margin_cols = make_number (w->right_margin_cols);
6452 p->left_fringe_width = make_number (w->left_fringe_width);
6453 p->right_fringe_width = make_number (w->right_fringe_width);
6454 p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
6455 p->scroll_bar_width = make_number (w->scroll_bar_width);
6456 p->scroll_bar_height = make_number (w->scroll_bar_height);
6457 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6458 p->horizontal_scroll_bar_type = w->horizontal_scroll_bar_type;
6459 p->dedicated = w->dedicated;
6460 p->combination_limit = w->combination_limit;
6461 p->window_parameters = Qnil;
6463 if (!NILP (Vwindow_persistent_parameters))
6465 /* Run cycle detection on Vwindow_persistent_parameters. */
6466 Lisp_Object tortoise, hare;
6468 hare = tortoise = Vwindow_persistent_parameters;
6469 while (CONSP (hare))
6471 hare = XCDR (hare);
6472 if (!CONSP (hare))
6473 break;
6475 hare = XCDR (hare);
6476 tortoise = XCDR (tortoise);
6478 if (EQ (hare, tortoise))
6479 /* Reset Vwindow_persistent_parameters to Qnil. */
6481 Vwindow_persistent_parameters = Qnil;
6482 break;
6486 for (tem = Vwindow_persistent_parameters; CONSP (tem);
6487 tem = XCDR (tem))
6489 pers = XCAR (tem);
6490 /* Save values for persistent window parameters. */
6491 if (CONSP (pers) && !NILP (XCDR (pers)))
6493 par = Fassq (XCAR (pers), w->window_parameters);
6494 if (NILP (par))
6495 /* If the window has no value for the parameter,
6496 make one. */
6497 p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
6498 p->window_parameters);
6499 else
6500 /* If the window has a value for the parameter,
6501 save it. */
6502 p->window_parameters = Fcons (Fcons (XCAR (par),
6503 XCDR (par)),
6504 p->window_parameters);
6509 if (BUFFERP (w->contents))
6511 /* Save w's value of point in the window configuration. If w
6512 is the selected window, then get the value of point from
6513 the buffer; pointm is garbage in the selected window. */
6514 if (EQ (window, selected_window))
6515 p->pointm = build_marker (XBUFFER (w->contents),
6516 BUF_PT (XBUFFER (w->contents)),
6517 BUF_PT_BYTE (XBUFFER (w->contents)));
6518 else
6519 p->pointm = Fcopy_marker (w->pointm, Qnil);
6520 p->old_pointm = Fcopy_marker (w->old_pointm, Qnil);
6521 XMARKER (p->pointm)->insertion_type
6522 = !NILP (buffer_local_value /* Don't signal error if void. */
6523 (Qwindow_point_insertion_type, w->contents));
6524 XMARKER (p->old_pointm)->insertion_type
6525 = !NILP (buffer_local_value /* Don't signal error if void. */
6526 (Qwindow_point_insertion_type, w->contents));
6528 p->start = Fcopy_marker (w->start, Qnil);
6529 p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
6531 else
6533 p->pointm = Qnil;
6534 p->old_pointm = Qnil;
6535 p->start = Qnil;
6536 p->start_at_line_beg = Qnil;
6539 p->parent = NILP (w->parent) ? Qnil : XWINDOW (w->parent)->temslot;
6540 p->prev = NILP (w->prev) ? Qnil : XWINDOW (w->prev)->temslot;
6542 if (WINDOWP (w->contents))
6543 i = save_window_save (w->contents, vector, i);
6546 return i;
6549 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6550 Scurrent_window_configuration, 0, 1, 0,
6551 doc: /* Return an object representing the current window configuration of FRAME.
6552 If FRAME is nil or omitted, use the selected frame.
6553 This describes the number of windows, their sizes and current buffers,
6554 and for each displayed buffer, where display starts, and the position of
6555 point. An exception is made for point in the current buffer:
6556 its value is -not- saved.
6557 This also records the currently selected frame, and FRAME's focus
6558 redirection (see `redirect-frame-focus'). The variable
6559 `window-persistent-parameters' specifies which window parameters are
6560 saved by this function. */)
6561 (Lisp_Object frame)
6563 Lisp_Object tem;
6564 ptrdiff_t i, n_windows;
6565 struct save_window_data *data;
6566 struct frame *f = decode_live_frame (frame);
6568 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6569 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6570 PVEC_WINDOW_CONFIGURATION);
6572 data->frame_cols = FRAME_COLS (f);
6573 data->frame_lines = FRAME_LINES (f);
6574 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6575 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6576 data->frame_text_width = FRAME_TEXT_WIDTH (f);
6577 data->frame_text_height = FRAME_TEXT_HEIGHT (f);
6578 data->frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
6579 data->frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
6580 data->selected_frame = selected_frame;
6581 data->current_window = FRAME_SELECTED_WINDOW (f);
6582 XSETBUFFER (data->current_buffer, current_buffer);
6583 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6584 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6585 data->root_window = FRAME_ROOT_WINDOW (f);
6586 data->focus_frame = FRAME_FOCUS_FRAME (f);
6587 tem = make_uninit_vector (n_windows);
6588 data->saved_windows = tem;
6589 for (i = 0; i < n_windows; i++)
6590 ASET (tem, i,
6591 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil));
6592 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6593 XSETWINDOW_CONFIGURATION (tem, data);
6594 return (tem);
6597 /* Called after W's margins, fringes or scroll bars was adjusted. */
6599 static void
6600 apply_window_adjustment (struct window *w)
6602 eassert (w);
6603 clear_glyph_matrix (w->current_matrix);
6604 w->window_end_valid = false;
6605 windows_or_buffers_changed = 30;
6606 wset_redisplay (w);
6607 adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
6611 /***********************************************************************
6612 Marginal Areas
6613 ***********************************************************************/
6615 static int
6616 extract_dimension (Lisp_Object dimension)
6618 if (NILP (dimension))
6619 return -1;
6620 CHECK_RANGED_INTEGER (dimension, 0, INT_MAX);
6621 return XINT (dimension);
6624 static struct window *
6625 set_window_margins (struct window *w, Lisp_Object left_width,
6626 Lisp_Object right_width)
6628 int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
6629 int left = NILP (left_width) ? 0 : extract_dimension (left_width);
6630 int right = NILP (right_width) ? 0 : extract_dimension (right_width);
6632 if (w->left_margin_cols != left || w->right_margin_cols != right)
6634 /* Don't change anything if new margins won't fit. */
6635 if ((WINDOW_PIXEL_WIDTH (w)
6636 - WINDOW_FRINGES_WIDTH (w)
6637 - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
6638 - (left + right) * unit)
6639 >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
6641 w->left_margin_cols = left;
6642 w->right_margin_cols = right;
6644 return w;
6646 else
6647 return NULL;
6649 else
6650 return NULL;
6653 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6654 2, 3, 0,
6655 doc: /* Set width of marginal areas of window WINDOW.
6656 WINDOW must be a live window and defaults to the selected one.
6658 Second arg LEFT-WIDTH specifies the number of character cells to
6659 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6660 does the same for the right marginal area. A nil width parameter
6661 means no margin.
6663 Return t if any margin was actually changed and nil otherwise. */)
6664 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6666 struct window *w = set_window_margins (decode_live_window (window),
6667 left_width, right_width);
6668 return w ? (apply_window_adjustment (w), Qt) : Qnil;
6672 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6673 0, 1, 0,
6674 doc: /* Get width of marginal areas of window WINDOW.
6675 WINDOW must be a live window and defaults to the selected one.
6677 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6678 If a marginal area does not exist, its width will be returned
6679 as nil. */)
6680 (Lisp_Object window)
6682 struct window *w = decode_live_window (window);
6683 return Fcons (w->left_margin_cols
6684 ? make_number (w->left_margin_cols) : Qnil,
6685 w->right_margin_cols
6686 ? make_number (w->right_margin_cols) : Qnil);
6691 /***********************************************************************
6692 Fringes
6693 ***********************************************************************/
6695 static struct window *
6696 set_window_fringes (struct window *w, Lisp_Object left_width,
6697 Lisp_Object right_width, Lisp_Object outside_margins)
6699 bool outside = !NILP (outside_margins);
6700 int left = extract_dimension (left_width);
6701 int right = extract_dimension (right_width);
6703 /* Do nothing on a tty or if nothing to actually change. */
6704 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6705 && (w->left_fringe_width != left
6706 || w->right_fringe_width != right
6707 || w->fringes_outside_margins != outside))
6709 if (left > 0 || right > 0)
6711 /* Don't change anything if new fringes don't fit. */
6712 if ((WINDOW_PIXEL_WIDTH (w)
6713 - WINDOW_MARGINS_WIDTH (w)
6714 - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
6715 - max (left, 0) - max (right, 0))
6716 < MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
6717 return NULL;
6720 w->left_fringe_width = left;
6721 w->right_fringe_width = right;
6722 w->fringes_outside_margins = outside;
6724 return w;
6726 else
6727 return NULL;
6730 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6731 2, 4, 0,
6732 doc: /* Set the fringe widths of window WINDOW.
6733 WINDOW must be a live window and defaults to the selected one.
6735 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6736 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6737 fringe width. If a fringe width arg is nil, that means to use the
6738 frame's default fringe width. Default fringe widths can be set with
6739 the command `set-fringe-style'.
6740 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6741 outside of the display margins. By default, fringes are drawn between
6742 display marginal areas and the text area.
6744 Return t if any fringe was actually changed and nil otherwise. */)
6745 (Lisp_Object window, Lisp_Object left_width,
6746 Lisp_Object right_width, Lisp_Object outside_margins)
6748 struct window *w
6749 = set_window_fringes (decode_live_window (window),
6750 left_width, right_width, outside_margins);
6751 return w ? (apply_window_adjustment (w), Qt) : Qnil;
6755 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6756 0, 1, 0,
6757 doc: /* Get width of fringes of window WINDOW.
6758 WINDOW must be a live window and defaults to the selected one.
6760 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6761 (Lisp_Object window)
6763 struct window *w = decode_live_window (window);
6765 return list3 (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6766 make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6767 WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil);
6772 /***********************************************************************
6773 Scroll bars
6774 ***********************************************************************/
6776 static struct window *
6777 set_window_scroll_bars (struct window *w, Lisp_Object width,
6778 Lisp_Object vertical_type, Lisp_Object height,
6779 Lisp_Object horizontal_type)
6781 int iwidth = extract_dimension (width);
6782 bool changed = false;
6784 if (iwidth == 0)
6785 vertical_type = Qnil;
6787 if (!(NILP (vertical_type)
6788 || EQ (vertical_type, Qleft)
6789 || EQ (vertical_type, Qright)
6790 || EQ (vertical_type, Qt)))
6791 error ("Invalid type of vertical scroll bar");
6793 if (w->scroll_bar_width != iwidth
6794 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6796 /* Don't change anything if new scroll bar won't fit. */
6797 if ((WINDOW_PIXEL_WIDTH (w)
6798 - WINDOW_MARGINS_WIDTH (w)
6799 - WINDOW_FRINGES_WIDTH (w)
6800 - max (iwidth, 0))
6801 >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
6803 w->scroll_bar_width = iwidth;
6804 wset_vertical_scroll_bar_type (w, vertical_type);
6805 changed = true;
6809 #if USE_HORIZONTAL_SCROLL_BARS
6811 int iheight = extract_dimension (height);
6813 if (MINI_WINDOW_P (w) || iheight == 0)
6814 horizontal_type = Qnil;
6816 if (!(NILP (horizontal_type)
6817 || EQ (horizontal_type, Qbottom)
6818 || EQ (horizontal_type, Qt)))
6819 error ("Invalid type of horizontal scroll bar");
6821 if (w->scroll_bar_height != iheight
6822 || !EQ (w->horizontal_scroll_bar_type, horizontal_type))
6824 /* Don't change anything if new scroll bar won't fit. */
6825 if ((WINDOW_PIXEL_HEIGHT (w)
6826 - WINDOW_HEADER_LINE_HEIGHT (w)
6827 - WINDOW_MODE_LINE_HEIGHT (w)
6828 - max (iheight, 0))
6829 >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w))
6831 w->scroll_bar_height = iheight;
6832 wset_horizontal_scroll_bar_type (w, horizontal_type);
6833 changed = true;
6837 #else
6838 wset_horizontal_scroll_bar_type (w, Qnil);
6839 #endif
6841 return changed ? w : NULL;
6844 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
6845 Sset_window_scroll_bars, 1, 5, 0,
6846 doc: /* Set width and type of scroll bars of window WINDOW.
6847 WINDOW must be a live window and defaults to the selected one.
6849 Second parameter WIDTH specifies the pixel width for the vertical scroll
6850 bar. If WIDTH is nil, use the scroll-bar width of WINDOW's frame.
6851 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6852 bar: left, right, or nil. If VERTICAL-TYPE is t, this means use the
6853 frame's scroll-bar type.
6855 Fourth parameter HEIGHT specifies the pixel height for the horizontal
6856 scroll bar. If HEIGHT is nil, use the scroll-bar height of WINDOW's
6857 frame. Fifth parameter HORIZONTAL-TYPE specifies the type of the
6858 horizontal scroll bar: nil, bottom, or t. If HORIZONTAL-TYPE is t, this
6859 means to use the frame's horizontal scroll-bar type.
6861 Return t if scroll bars were actually changed and nil otherwise. */)
6862 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type,
6863 Lisp_Object height, Lisp_Object horizontal_type)
6865 struct window *w
6866 = set_window_scroll_bars (decode_live_window (window),
6867 width, vertical_type, height, horizontal_type);
6868 return w ? (apply_window_adjustment (w), Qt) : Qnil;
6872 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6873 0, 1, 0,
6874 doc: /* Get width and type of scroll bars of window WINDOW.
6875 WINDOW must be a live window and defaults to the selected one.
6877 Value is a list of the form (WIDTH COLUMNS VERTICAL-TYPE HEIGHT LINES
6878 HORIZONTAL-TYPE). If WIDTH or HEIGHT is nil or VERTICAL-TYPE or
6879 HORIZONTAL-TYPE is t, the window is using the frame's corresponding
6880 value. */)
6881 (Lisp_Object window)
6883 struct window *w = decode_live_window (window);
6885 return Fcons (((w->scroll_bar_width >= 0)
6886 ? make_number (w->scroll_bar_width)
6887 : Qnil),
6888 list5 (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6889 w->vertical_scroll_bar_type,
6890 ((w->scroll_bar_height >= 0)
6891 ? make_number (w->scroll_bar_height)
6892 : Qnil),
6893 make_number (WINDOW_SCROLL_BAR_LINES (w)),
6894 w->horizontal_scroll_bar_type));
6897 /***********************************************************************
6898 Smooth scrolling
6899 ***********************************************************************/
6901 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6902 doc: /* Return the amount by which WINDOW is scrolled vertically.
6903 If WINDOW is omitted or nil, it defaults to the selected window.
6904 Normally, value is a multiple of the canonical character height of WINDOW;
6905 optional second arg PIXELS-P means value is measured in pixels. */)
6906 (Lisp_Object window, Lisp_Object pixels_p)
6908 Lisp_Object result;
6909 struct window *w = decode_live_window (window);
6910 struct frame *f = XFRAME (w->frame);
6912 if (FRAME_WINDOW_P (f))
6913 result = (NILP (pixels_p)
6914 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6915 : make_number (-w->vscroll));
6916 else
6917 result = make_number (0);
6918 return result;
6922 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6923 2, 3, 0,
6924 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6925 WINDOW nil means use the selected window. Normally, VSCROLL is a
6926 non-negative multiple of the canonical character height of WINDOW;
6927 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6928 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6929 corresponds to an integral number of pixels. The return value is the
6930 result of this rounding.
6931 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6932 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
6934 struct window *w = decode_live_window (window);
6935 struct frame *f = XFRAME (w->frame);
6937 CHECK_NUMBER_OR_FLOAT (vscroll);
6939 if (FRAME_WINDOW_P (f))
6941 int old_dy = w->vscroll;
6943 w->vscroll = - (NILP (pixels_p)
6944 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6945 : XFLOATINT (vscroll));
6946 w->vscroll = min (w->vscroll, 0);
6948 if (w->vscroll != old_dy)
6950 /* Adjust glyph matrix of the frame if the virtual display
6951 area becomes larger than before. */
6952 if (w->vscroll < 0 && w->vscroll < old_dy)
6953 adjust_frame_glyphs (f);
6955 /* Prevent redisplay shortcuts. */
6956 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
6960 return Fwindow_vscroll (window, pixels_p);
6964 /* Call FN for all leaf windows on frame F. FN is called with the
6965 first argument being a pointer to the leaf window, and with
6966 additional argument USER_DATA. Stops when FN returns 0. */
6968 static void
6969 foreach_window (struct frame *f, bool (*fn) (struct window *, void *),
6970 void *user_data)
6972 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6973 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6974 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6978 /* Helper function for foreach_window. Call FN for all leaf windows
6979 reachable from W. FN is called with the first argument being a
6980 pointer to the leaf window, and with additional argument USER_DATA.
6981 Stop when FN returns false. Value is false if stopped by FN. */
6983 static bool
6984 foreach_window_1 (struct window *w, bool (*fn) (struct window *, void *),
6985 void *user_data)
6987 bool cont;
6989 for (cont = true; w && cont;)
6991 if (WINDOWP (w->contents))
6992 cont = foreach_window_1 (XWINDOW (w->contents), fn, user_data);
6993 else
6994 cont = fn (w, user_data);
6996 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6999 return cont;
7002 /***********************************************************************
7003 Initialization
7004 ***********************************************************************/
7006 /* Return true if window configurations CONFIGURATION1 and CONFIGURATION2
7007 describe the same state of affairs. This is used by Fequal.
7009 IGNORE_POSITIONS means ignore non-matching scroll positions
7010 and the like.
7012 This ignores a couple of things like the dedication status of
7013 window, combination_limit and the like. This might have to be
7014 fixed. */
7016 bool
7017 compare_window_configurations (Lisp_Object configuration1,
7018 Lisp_Object configuration2,
7019 bool ignore_positions)
7021 register struct save_window_data *d1, *d2;
7022 struct Lisp_Vector *sws1, *sws2;
7023 ptrdiff_t i;
7025 CHECK_WINDOW_CONFIGURATION (configuration1);
7026 CHECK_WINDOW_CONFIGURATION (configuration2);
7028 d1 = (struct save_window_data *) XVECTOR (configuration1);
7029 d2 = (struct save_window_data *) XVECTOR (configuration2);
7030 sws1 = XVECTOR (d1->saved_windows);
7031 sws2 = XVECTOR (d2->saved_windows);
7033 /* Frame settings must match. */
7034 if (d1->frame_cols != d2->frame_cols
7035 || d1->frame_lines != d2->frame_lines
7036 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
7037 || !EQ (d1->selected_frame, d2->selected_frame)
7038 || !EQ (d1->current_buffer, d2->current_buffer)
7039 || (!ignore_positions
7040 && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
7041 || !EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)))
7042 || !EQ (d1->focus_frame, d2->focus_frame)
7043 /* Verify that the two configurations have the same number of windows. */
7044 || sws1->header.size != sws2->header.size)
7045 return false;
7047 for (i = 0; i < sws1->header.size; i++)
7049 struct saved_window *sw1, *sw2;
7051 sw1 = SAVED_WINDOW_N (sws1, i);
7052 sw2 = SAVED_WINDOW_N (sws2, i);
7054 if (
7055 /* The "current" windows in the two configurations must
7056 correspond to each other. */
7057 EQ (d1->current_window, sw1->window)
7058 != EQ (d2->current_window, sw2->window)
7059 /* Windows' buffers must match. */
7060 || !EQ (sw1->buffer, sw2->buffer)
7061 || !EQ (sw1->pixel_left, sw2->pixel_left)
7062 || !EQ (sw1->pixel_top, sw2->pixel_top)
7063 || !EQ (sw1->pixel_height, sw2->pixel_height)
7064 || !EQ (sw1->pixel_width, sw2->pixel_width)
7065 || !EQ (sw1->left_col, sw2->left_col)
7066 || !EQ (sw1->top_line, sw2->top_line)
7067 || !EQ (sw1->total_cols, sw2->total_cols)
7068 || !EQ (sw1->total_lines, sw2->total_lines)
7069 || !EQ (sw1->display_table, sw2->display_table)
7070 /* The next two disjuncts check the window structure for
7071 equality. */
7072 || !EQ (sw1->parent, sw2->parent)
7073 || !EQ (sw1->prev, sw2->prev)
7074 || (!ignore_positions
7075 && (!EQ (sw1->hscroll, sw2->hscroll)
7076 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
7077 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
7078 || NILP (Fequal (sw1->start, sw2->start))
7079 || NILP (Fequal (sw1->pointm, sw2->pointm))))
7080 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
7081 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
7082 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
7083 || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
7084 || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
7085 || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
7086 || !EQ (sw1->scroll_bar_height, sw2->scroll_bar_height)
7087 || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type)
7088 || !EQ (sw1->horizontal_scroll_bar_type, sw2->horizontal_scroll_bar_type))
7089 return false;
7092 return true;
7095 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7096 Scompare_window_configurations, 2, 2, 0,
7097 doc: /* Compare two window configurations as regards the structure of windows.
7098 This function ignores details such as the values of point
7099 and scrolling positions. */)
7100 (Lisp_Object x, Lisp_Object y)
7102 if (compare_window_configurations (x, y, true))
7103 return Qt;
7104 return Qnil;
7107 void
7108 init_window_once (void)
7110 struct frame *f = make_initial_frame ();
7111 XSETFRAME (selected_frame, f);
7112 Vterminal_frame = selected_frame;
7113 minibuf_window = f->minibuffer_window;
7114 selected_window = f->selected_window;
7117 void
7118 init_window (void)
7120 Vwindow_list = Qnil;
7123 void
7124 syms_of_window (void)
7126 DEFSYM (Qscroll_up, "scroll-up");
7127 DEFSYM (Qscroll_down, "scroll-down");
7128 DEFSYM (Qscroll_command, "scroll-command");
7130 Fput (Qscroll_up, Qscroll_command, Qt);
7131 Fput (Qscroll_down, Qscroll_command, Qt);
7133 DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
7134 DEFSYM (Qwindowp, "windowp");
7135 DEFSYM (Qwindow_configuration_p, "window-configuration-p");
7136 DEFSYM (Qwindow_live_p, "window-live-p");
7137 DEFSYM (Qwindow_valid_p, "window-valid-p");
7138 DEFSYM (Qwindow_deletable_p, "window-deletable-p");
7139 DEFSYM (Qdelete_window, "delete-window");
7140 DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
7141 DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
7142 DEFSYM (Qwindow_sanitize_window_sizes, "window--sanitize-window-sizes");
7143 DEFSYM (Qwindow_pixel_to_total, "window--pixel-to-total");
7144 DEFSYM (Qsafe, "safe");
7145 DEFSYM (Qdisplay_buffer, "display-buffer");
7146 DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
7147 DEFSYM (Qrecord_window_buffer, "record-window-buffer");
7148 DEFSYM (Qget_mru_window, "get-mru-window");
7149 DEFSYM (Qwindow_size, "window-size");
7150 DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
7151 DEFSYM (Qabove, "above");
7152 DEFSYM (Qclone_of, "clone-of");
7153 DEFSYM (Qfloor, "floor");
7154 DEFSYM (Qceiling, "ceiling");
7156 staticpro (&Vwindow_list);
7158 minibuf_selected_window = Qnil;
7159 staticpro (&minibuf_selected_window);
7161 window_scroll_pixel_based_preserve_x = -1;
7162 window_scroll_pixel_based_preserve_y = -1;
7163 window_scroll_preserve_hpos = -1;
7164 window_scroll_preserve_vpos = -1;
7166 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
7167 doc: /* Non-nil means call as function to display a help buffer.
7168 The function is called with one argument, the buffer to be displayed.
7169 Used by `with-output-to-temp-buffer'.
7170 If this function is used, then it must do the entire job of showing
7171 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7172 Vtemp_buffer_show_function = Qnil;
7174 DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
7175 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7176 Vminibuf_scroll_window = Qnil;
7178 DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
7179 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7180 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7181 is displayed in the `mode-line' face. */);
7182 mode_line_in_non_selected_windows = true;
7184 DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
7185 doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window. */);
7186 Vother_window_scroll_buffer = Qnil;
7188 DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
7189 doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7190 auto_window_vscroll_p = true;
7192 DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
7193 doc: /* Number of lines of continuity when scrolling by screenfuls. */);
7194 next_screen_context_lines = 2;
7196 DEFVAR_LISP ("scroll-preserve-screen-position",
7197 Vscroll_preserve_screen_position,
7198 doc: /* Controls if scroll commands move point to keep its screen position unchanged.
7199 A value of nil means point does not keep its screen position except
7200 at the scroll margin or window boundary respectively.
7201 A value of t means point keeps its screen position if the scroll
7202 command moved it vertically out of the window, e.g. when scrolling
7203 by full screens.
7204 Any other value means point always keeps its screen position.
7205 Scroll commands should have the `scroll-command' property
7206 on their symbols to be controlled by this variable. */);
7207 Vscroll_preserve_screen_position = Qnil;
7209 DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
7210 doc: /* Type of marker to use for `window-point'. */);
7211 Vwindow_point_insertion_type = Qnil;
7212 DEFSYM (Qwindow_point_insertion_type, "window_point_insertion_type");
7214 DEFVAR_LISP ("window-configuration-change-hook",
7215 Vwindow_configuration_change_hook,
7216 doc: /* Functions to call when window configuration changes.
7217 The buffer-local part is run once per window, with the relevant window
7218 selected; while the global part is run only once for the modified frame,
7219 with the relevant frame selected. */);
7220 Vwindow_configuration_change_hook = Qnil;
7222 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
7223 doc: /* Non-nil means `recenter' redraws entire frame.
7224 If this option is non-nil, then the `recenter' command with a nil
7225 argument will redraw the entire frame; the special value `tty' causes
7226 the frame to be redrawn only if it is a tty frame. */);
7227 Vrecenter_redisplay = Qtty;
7229 DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
7230 doc: /* If t, resize window combinations proportionally.
7231 If this variable is nil, splitting a window gets the entire screen space
7232 for displaying the new window from the window to split. Deleting and
7233 resizing a window preferably resizes one adjacent window only.
7235 If this variable is t, splitting a window tries to get the space
7236 proportionally from all windows in the same combination. This also
7237 allows to split a window that is otherwise too small or of fixed size.
7238 Resizing and deleting a window proportionally resize all windows in the
7239 same combination.
7241 Other values are reserved for future use.
7243 This variable takes no effect if the variable `window-combination-limit' is
7244 non-nil. */);
7245 Vwindow_combination_resize = Qnil;
7247 DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
7248 doc: /* If non-nil, splitting a window makes a new parent window.
7249 The following values are recognized:
7251 nil means splitting a window will create a new parent window only if the
7252 window has no parent window or the window shall become part of a
7253 combination orthogonal to the one it is part of.
7255 `window-size' means that splitting a window for displaying a buffer
7256 makes a new parent window provided `display-buffer' is supposed to
7257 explicitly set the window's size due to the presence of a
7258 `window-height' or `window-width' entry in the alist used by
7259 `display-buffer'. Otherwise, this value is handled like nil.
7261 `temp-buffer' means that splitting a window for displaying a temporary
7262 buffer always makes a new parent window. Otherwise, this value is
7263 handled like nil.
7265 `display-buffer' means that splitting a window for displaying a buffer
7266 always makes a new parent window. Since temporary buffers are
7267 displayed by the function `display-buffer', this value is stronger
7268 than `temp-buffer'. Splitting a window for other purpose makes a
7269 new parent window only if needed.
7271 t means that splitting a window always creates a new parent window. If
7272 all splits behave this way, each frame's window tree is a binary
7273 tree and every window but the frame's root window has exactly one
7274 sibling.
7276 Other values are reserved for future use. */);
7277 Vwindow_combination_limit = Qwindow_size;
7279 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
7280 doc: /* Alist of persistent window parameters.
7281 This alist specifies which window parameters shall get saved by
7282 `current-window-configuration' and `window-state-get' and subsequently
7283 restored to their previous values by `set-window-configuration' and
7284 `window-state-put'.
7286 The car of each entry of this alist is the symbol specifying the
7287 parameter. The cdr is one of the following:
7289 nil means the parameter is neither saved by `window-state-get' nor by
7290 `current-window-configuration'.
7292 t means the parameter is saved by `current-window-configuration' and,
7293 provided its WRITABLE argument is nil, by `window-state-get'.
7295 The symbol `writable' means the parameter is saved unconditionally by
7296 both `current-window-configuration' and `window-state-get'. Do not use
7297 this value for parameters without read syntax (like windows or frames).
7299 Parameters not saved by `current-window-configuration' or
7300 `window-state-get' are left alone by `set-window-configuration'
7301 respectively are not installed by `window-state-put'. */);
7302 Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
7304 DEFVAR_BOOL ("window-resize-pixelwise", window_resize_pixelwise,
7305 doc: /* Non-nil means resize windows pixelwise.
7306 This currently affects the functions: `split-window', `maximize-window',
7307 `minimize-window', `fit-window-to-buffer' and `fit-frame-to-buffer', and
7308 all functions that symmetrically resize a parent window.
7310 Note that when a frame's pixel size is not a multiple of the
7311 frame's character size, at least one window may get resized
7312 pixelwise even if this option is nil. */);
7313 window_resize_pixelwise = false;
7315 DEFVAR_BOOL ("fast-but-imprecise-scrolling",
7316 Vfast_but_imprecise_scrolling,
7317 doc: /* When non-nil, accelerate scrolling operations.
7318 This comes into play when scrolling rapidly over previously
7319 unfontified buffer regions. Only those portions of the buffer which
7320 are actually going to be displayed get fontified.
7322 Note that this optimization can cause the portion of the buffer
7323 displayed after a scrolling operation to be somewhat inaccurate. */);
7324 Vfast_but_imprecise_scrolling = false;
7326 defsubr (&Sselected_window);
7327 defsubr (&Sminibuffer_window);
7328 defsubr (&Swindow_minibuffer_p);
7329 defsubr (&Swindowp);
7330 defsubr (&Swindow_valid_p);
7331 defsubr (&Swindow_live_p);
7332 defsubr (&Swindow_frame);
7333 defsubr (&Sframe_root_window);
7334 defsubr (&Sframe_first_window);
7335 defsubr (&Sframe_selected_window);
7336 defsubr (&Sset_frame_selected_window);
7337 defsubr (&Spos_visible_in_window_p);
7338 defsubr (&Swindow_line_height);
7339 defsubr (&Swindow_buffer);
7340 defsubr (&Swindow_parent);
7341 defsubr (&Swindow_top_child);
7342 defsubr (&Swindow_left_child);
7343 defsubr (&Swindow_next_sibling);
7344 defsubr (&Swindow_prev_sibling);
7345 defsubr (&Swindow_combination_limit);
7346 defsubr (&Sset_window_combination_limit);
7347 defsubr (&Swindow_use_time);
7348 defsubr (&Swindow_pixel_width);
7349 defsubr (&Swindow_pixel_height);
7350 defsubr (&Swindow_total_width);
7351 defsubr (&Swindow_total_height);
7352 defsubr (&Swindow_normal_size);
7353 defsubr (&Swindow_new_pixel);
7354 defsubr (&Swindow_new_total);
7355 defsubr (&Swindow_new_normal);
7356 defsubr (&Swindow_pixel_left);
7357 defsubr (&Swindow_pixel_top);
7358 defsubr (&Swindow_left_column);
7359 defsubr (&Swindow_top_line);
7360 defsubr (&Sset_window_new_pixel);
7361 defsubr (&Sset_window_new_total);
7362 defsubr (&Sset_window_new_normal);
7363 defsubr (&Swindow_resize_apply);
7364 defsubr (&Swindow_resize_apply_total);
7365 defsubr (&Swindow_body_height);
7366 defsubr (&Swindow_body_width);
7367 defsubr (&Swindow_hscroll);
7368 defsubr (&Sset_window_hscroll);
7369 defsubr (&Swindow_redisplay_end_trigger);
7370 defsubr (&Sset_window_redisplay_end_trigger);
7371 defsubr (&Swindow_mode_line_height);
7372 defsubr (&Swindow_header_line_height);
7373 defsubr (&Swindow_right_divider_width);
7374 defsubr (&Swindow_bottom_divider_width);
7375 defsubr (&Swindow_scroll_bar_width);
7376 defsubr (&Swindow_scroll_bar_height);
7377 defsubr (&Scoordinates_in_window_p);
7378 defsubr (&Swindow_at);
7379 defsubr (&Swindow_point);
7380 defsubr (&Swindow_old_point);
7381 defsubr (&Swindow_start);
7382 defsubr (&Swindow_end);
7383 defsubr (&Sset_window_point);
7384 defsubr (&Sset_window_start);
7385 defsubr (&Swindow_dedicated_p);
7386 defsubr (&Sset_window_dedicated_p);
7387 defsubr (&Swindow_display_table);
7388 defsubr (&Sset_window_display_table);
7389 defsubr (&Snext_window);
7390 defsubr (&Sprevious_window);
7391 defsubr (&Swindow__sanitize_window_sizes);
7392 defsubr (&Sget_buffer_window);
7393 defsubr (&Sdelete_other_windows_internal);
7394 defsubr (&Sdelete_window_internal);
7395 defsubr (&Sresize_mini_window_internal);
7396 defsubr (&Sset_window_buffer);
7397 defsubr (&Srun_window_configuration_change_hook);
7398 defsubr (&Srun_window_scroll_functions);
7399 defsubr (&Sselect_window);
7400 defsubr (&Sforce_window_update);
7401 defsubr (&Ssplit_window_internal);
7402 defsubr (&Sscroll_up);
7403 defsubr (&Sscroll_down);
7404 defsubr (&Sscroll_left);
7405 defsubr (&Sscroll_right);
7406 defsubr (&Sother_window_for_scrolling);
7407 defsubr (&Sscroll_other_window);
7408 defsubr (&Sminibuffer_selected_window);
7409 defsubr (&Srecenter);
7410 defsubr (&Swindow_text_width);
7411 defsubr (&Swindow_text_height);
7412 defsubr (&Smove_to_window_line);
7413 defsubr (&Swindow_configuration_p);
7414 defsubr (&Swindow_configuration_frame);
7415 defsubr (&Sset_window_configuration);
7416 defsubr (&Scurrent_window_configuration);
7417 defsubr (&Sset_window_margins);
7418 defsubr (&Swindow_margins);
7419 defsubr (&Sset_window_fringes);
7420 defsubr (&Swindow_fringes);
7421 defsubr (&Sset_window_scroll_bars);
7422 defsubr (&Swindow_scroll_bars);
7423 defsubr (&Swindow_vscroll);
7424 defsubr (&Sset_window_vscroll);
7425 defsubr (&Scompare_window_configurations);
7426 defsubr (&Swindow_list);
7427 defsubr (&Swindow_list_1);
7428 defsubr (&Swindow_prev_buffers);
7429 defsubr (&Sset_window_prev_buffers);
7430 defsubr (&Swindow_next_buffers);
7431 defsubr (&Sset_window_next_buffers);
7432 defsubr (&Swindow_parameters);
7433 defsubr (&Swindow_parameter);
7434 defsubr (&Sset_window_parameter);
7437 void
7438 keys_of_window (void)
7440 initial_define_key (control_x_map, '<', "scroll-left");
7441 initial_define_key (control_x_map, '>', "scroll-right");
7443 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
7444 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7445 initial_define_key (meta_map, 'v', "scroll-down-command");