CEDET (srecode-insert-fcn): Fix use of oref on a class
[emacs.git] / src / window.c
blob0fcf82d43f4a93e62e54ae9d6bd72b1c95f68772
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 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
1105 doc: /* Return a list of the edge coordinates of WINDOW.
1106 WINDOW must be a valid window and defaults to the selected one.
1108 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
1109 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
1110 0 at top left corner of frame.
1112 RIGHT is one more than the rightmost column occupied by WINDOW. BOTTOM
1113 is one more than the bottommost row occupied by WINDOW. The edges
1114 include the space used by WINDOW's scroll bar, display margins, fringes,
1115 header line, and/or mode line. For the edges of just the text area, use
1116 `window-inside-edges'. */)
1117 (Lisp_Object window)
1119 register struct window *w = decode_valid_window (window);
1121 return list4i (WINDOW_LEFT_EDGE_COL (w), WINDOW_TOP_EDGE_LINE (w),
1122 WINDOW_RIGHT_EDGE_COL (w), WINDOW_BOTTOM_EDGE_LINE (w));
1125 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
1126 doc: /* Return a list of the edge pixel coordinates of WINDOW.
1127 WINDOW must be a valid window and defaults to the selected one.
1129 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1130 0, 0 at the top left corner of the frame.
1132 RIGHT is one more than the rightmost x position occupied by WINDOW.
1133 BOTTOM is one more than the bottommost y position occupied by WINDOW.
1134 The pixel edges include the space used by WINDOW's scroll bar, display
1135 margins, fringes, header line, and/or mode line. For the pixel edges
1136 of just the text area, use `window-inside-pixel-edges'. */)
1137 (Lisp_Object window)
1139 register struct window *w = decode_valid_window (window);
1141 return list4i (WINDOW_LEFT_EDGE_X (w), WINDOW_TOP_EDGE_Y (w),
1142 WINDOW_RIGHT_EDGE_X (w), WINDOW_BOTTOM_EDGE_Y (w));
1145 static void
1146 calc_absolute_offset (struct window *w, int *add_x, int *add_y)
1148 struct frame *f = XFRAME (w->frame);
1149 *add_y = f->top_pos;
1150 #ifdef FRAME_MENUBAR_HEIGHT
1151 *add_y += FRAME_MENUBAR_HEIGHT (f);
1152 #endif
1153 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
1154 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
1155 #elif defined (FRAME_TOOLBAR_HEIGHT)
1156 *add_y += FRAME_TOOLBAR_HEIGHT (f);
1157 #endif
1158 #ifdef FRAME_NS_TITLEBAR_HEIGHT
1159 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
1160 #endif
1161 *add_x = f->left_pos;
1162 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
1163 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
1164 #endif
1167 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
1168 Swindow_absolute_pixel_edges, 0, 1, 0,
1169 doc: /* Return a list of the edge pixel coordinates of WINDOW.
1170 WINDOW must be a valid window and defaults to the selected one.
1172 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1173 0, 0 at the top left corner of the display.
1175 RIGHT is one more than the rightmost x position occupied by WINDOW.
1176 BOTTOM is one more than the bottommost y position occupied by WINDOW.
1177 The pixel edges include the space used by WINDOW's scroll bar, display
1178 margins, fringes, header line, and/or mode line. For the pixel edges
1179 of just the text area, use `window-inside-absolute-pixel-edges'. */)
1180 (Lisp_Object window)
1182 register struct window *w = decode_valid_window (window);
1183 int add_x, add_y;
1185 calc_absolute_offset (w, &add_x, &add_y);
1187 return list4i (WINDOW_LEFT_EDGE_X (w) + add_x,
1188 WINDOW_TOP_EDGE_Y (w) + add_y,
1189 WINDOW_RIGHT_EDGE_X (w) + add_x,
1190 WINDOW_BOTTOM_EDGE_Y (w) + add_y);
1193 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
1194 doc: /* Return a list of the edge coordinates of WINDOW.
1195 WINDOW must be a live window and defaults to the selected one.
1197 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
1198 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
1199 0 at top left corner of frame.
1201 RIGHT is one more than the rightmost column of WINDOW's text area.
1202 BOTTOM is one more than the bottommost row of WINDOW's text area. The
1203 inside edges do not include the space used by the WINDOW's scroll bar,
1204 display margins, fringes, header line, and/or mode line. */)
1205 (Lisp_Object window)
1207 register struct window *w = decode_live_window (window);
1209 return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w)
1210 + WINDOW_LEFT_MARGIN_COLS (w)
1211 + ((WINDOW_LEFT_FRINGE_WIDTH (w)
1212 + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
1213 / WINDOW_FRAME_COLUMN_WIDTH (w))),
1214 (WINDOW_TOP_EDGE_LINE (w)
1215 + WINDOW_HEADER_LINE_LINES (w)),
1216 (WINDOW_BOX_RIGHT_EDGE_COL (w)
1217 - WINDOW_RIGHT_MARGIN_COLS (w)
1218 - ((WINDOW_RIGHT_FRINGE_WIDTH (w)
1219 + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
1220 / WINDOW_FRAME_COLUMN_WIDTH (w))),
1221 (WINDOW_BOTTOM_EDGE_LINE (w)
1222 - WINDOW_MODE_LINE_LINES (w)));
1225 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
1226 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1227 WINDOW must be a live window and defaults to the selected one.
1229 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1230 (0,0) at the top left corner of the frame's window area.
1232 RIGHT is one more than the rightmost x position of WINDOW's text area.
1233 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1234 The inside edges do not include the space used by WINDOW's scroll bar,
1235 display margins, fringes, header line, and/or mode line. */)
1236 (Lisp_Object window)
1238 register struct window *w = decode_live_window (window);
1240 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1241 + WINDOW_LEFT_MARGIN_WIDTH (w)
1242 + WINDOW_LEFT_FRINGE_WIDTH (w)),
1243 (WINDOW_TOP_EDGE_Y (w)
1244 + WINDOW_HEADER_LINE_HEIGHT (w)),
1245 (WINDOW_BOX_RIGHT_EDGE_X (w)
1246 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1247 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
1248 (WINDOW_BOTTOM_EDGE_Y (w)
1249 - WINDOW_MODE_LINE_HEIGHT (w)));
1252 DEFUN ("window-inside-absolute-pixel-edges",
1253 Fwindow_inside_absolute_pixel_edges,
1254 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
1255 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1256 WINDOW must be a live window and defaults to the selected one.
1258 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1259 (0,0) at the top left corner of the frame's window area.
1261 RIGHT is one more than the rightmost x position of WINDOW's text area.
1262 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1263 The inside edges do not include the space used by WINDOW's scroll bar,
1264 display margins, fringes, header line, and/or mode line. */)
1265 (Lisp_Object window)
1267 register struct window *w = decode_live_window (window);
1268 int add_x, add_y;
1270 calc_absolute_offset (w, &add_x, &add_y);
1272 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1273 + WINDOW_LEFT_MARGIN_WIDTH (w)
1274 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
1275 (WINDOW_TOP_EDGE_Y (w)
1276 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
1277 (WINDOW_BOX_RIGHT_EDGE_X (w)
1278 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1279 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
1280 (WINDOW_BOTTOM_EDGE_Y (w)
1281 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
1284 /* Test if the character at column X, row Y is within window W.
1285 If it is not, return ON_NOTHING;
1286 if it is on the window's vertical divider, return
1287 ON_RIGHT_DIVIDER;
1288 if it is on the window's horizontal divider, return
1289 ON_BOTTOM_DIVIDER;
1290 if it is in the window's text area, return ON_TEXT;
1291 if it is on the window's modeline, return ON_MODE_LINE;
1292 if it is on the border between the window and its right sibling,
1293 return ON_VERTICAL_BORDER;
1294 if it is on a scroll bar, return ON_SCROLL_BAR;
1295 if it is on the window's top line, return ON_HEADER_LINE;
1296 if it is in left or right fringe of the window,
1297 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
1298 if it is in the marginal area to the left/right of the window,
1299 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
1301 X and Y are frame relative pixel coordinates. */
1303 static enum window_part
1304 coordinates_in_window (register struct window *w, int x, int y)
1306 struct frame *f = XFRAME (WINDOW_FRAME (w));
1307 enum window_part part;
1308 int ux = FRAME_COLUMN_WIDTH (f);
1309 int left_x = WINDOW_LEFT_EDGE_X (w);
1310 int right_x = WINDOW_RIGHT_EDGE_X (w);
1311 int top_y = WINDOW_TOP_EDGE_Y (w);
1312 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
1313 /* The width of the area where the vertical line can be dragged.
1314 (Between mode lines for instance. */
1315 int grabbable_width = ux;
1316 int lmargin_width, rmargin_width, text_left, text_right;
1318 /* Outside any interesting row or column? */
1319 if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
1320 return ON_NOTHING;
1322 /* On the horizontal window divider (which prevails the vertical
1323 divider)? */
1324 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w) > 0
1325 && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1326 && y <= bottom_y)
1327 return ON_BOTTOM_DIVIDER;
1328 /* On vertical window divider? */
1329 else if (!WINDOW_RIGHTMOST_P (w)
1330 && WINDOW_RIGHT_DIVIDER_WIDTH (w) > 0
1331 && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
1332 && x <= right_x)
1333 return ON_RIGHT_DIVIDER;
1334 /* On the horizontal scroll bar? (Including the empty space at its
1335 right!) */
1336 else if ((WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
1337 && y >= (bottom_y
1338 - WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
1339 - CURRENT_MODE_LINE_HEIGHT (w)
1340 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1341 && y <= (bottom_y
1342 - CURRENT_MODE_LINE_HEIGHT (w)
1343 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))))
1344 return ON_HORIZONTAL_SCROLL_BAR;
1345 /* On the mode or header line? */
1346 else if ((WINDOW_WANTS_MODELINE_P (w)
1347 && y >= (bottom_y
1348 - CURRENT_MODE_LINE_HEIGHT (w)
1349 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1350 && y <= bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
1351 && (part = ON_MODE_LINE))
1352 || (WINDOW_WANTS_HEADER_LINE_P (w)
1353 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
1354 && (part = ON_HEADER_LINE)))
1356 /* If it's under/over the scroll bar portion of the mode/header
1357 line, say it's on the vertical line. That's to be able to
1358 resize windows horizontally in case we're using toolkit scroll
1359 bars. Note: If scrollbars are on the left, the window that
1360 must be eventually resized is that on the left of WINDOW. */
1361 if ((WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0)
1362 && ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1363 && !WINDOW_LEFTMOST_P (w)
1364 && eabs (x - left_x) < grabbable_width)
1365 || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1366 && !WINDOW_RIGHTMOST_P (w)
1367 && eabs (x - right_x) < grabbable_width)))
1368 return ON_VERTICAL_BORDER;
1369 else
1370 return part;
1373 /* In what's below, we subtract 1 when computing right_x because we
1374 want the rightmost pixel, which is given by left_pixel+width-1. */
1375 if (w->pseudo_window_p)
1377 left_x = 0;
1378 right_x = WINDOW_PIXEL_WIDTH (w) - 1;
1380 else
1382 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
1383 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
1386 /* Outside any interesting column? */
1387 if (x < left_x || x > right_x)
1388 return ON_VERTICAL_SCROLL_BAR;
1390 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
1391 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
1393 text_left = window_box_left (w, TEXT_AREA);
1394 text_right = text_left + window_box_width (w, TEXT_AREA);
1396 if (FRAME_WINDOW_P (f))
1398 if (!w->pseudo_window_p
1399 && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
1400 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
1401 && !WINDOW_RIGHTMOST_P (w)
1402 && (eabs (x - right_x) < grabbable_width))
1403 return ON_VERTICAL_BORDER;
1405 /* Need to say "x > right_x" rather than >=, since on character
1406 terminals, the vertical line's x coordinate is right_x. */
1407 else if (!w->pseudo_window_p
1408 && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
1409 && !WINDOW_RIGHTMOST_P (w)
1410 /* Why check ux if we are not the rightmost window? Also
1411 shouldn't a pseudo window always be rightmost? */
1412 && x > right_x - ux)
1413 return ON_VERTICAL_BORDER;
1415 if (x < text_left)
1417 if (lmargin_width > 0
1418 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1419 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
1420 : (x < left_x + lmargin_width)))
1421 return ON_LEFT_MARGIN;
1422 else
1423 return ON_LEFT_FRINGE;
1426 if (x >= text_right)
1428 if (rmargin_width > 0
1429 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1430 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
1431 : (x >= right_x - rmargin_width)))
1432 return ON_RIGHT_MARGIN;
1433 else
1434 return ON_RIGHT_FRINGE;
1437 /* Everything special ruled out - must be on text area */
1438 return ON_TEXT;
1441 /* Take X is the frame-relative pixel x-coordinate, and return the
1442 x-coordinate relative to part PART of window W. */
1444 window_relative_x_coord (struct window *w, enum window_part part, int x)
1446 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
1448 switch (part)
1450 case ON_TEXT:
1451 return x - window_box_left (w, TEXT_AREA);
1453 case ON_HEADER_LINE:
1454 case ON_MODE_LINE:
1455 case ON_LEFT_FRINGE:
1456 return x - left_x;
1458 case ON_RIGHT_FRINGE:
1459 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
1461 case ON_LEFT_MARGIN:
1462 return (x - left_x
1463 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1464 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
1466 case ON_RIGHT_MARGIN:
1467 return (x + 1
1468 - ((w->pseudo_window_p)
1469 ? WINDOW_PIXEL_WIDTH (w)
1470 : WINDOW_BOX_RIGHT_EDGE_X (w))
1471 + window_box_width (w, RIGHT_MARGIN_AREA)
1472 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1473 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
1476 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
1477 return 0;
1481 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
1482 Scoordinates_in_window_p, 2, 2, 0,
1483 doc: /* Return non-nil if COORDINATES are in WINDOW.
1484 WINDOW must be a live window and defaults to the selected one.
1485 COORDINATES is a cons of the form (X . Y), X and Y being distances
1486 measured in characters from the upper-left corner of the frame.
1487 \(0 . 0) denotes the character in the upper left corner of the
1488 frame.
1489 If COORDINATES are in the text portion of WINDOW,
1490 the coordinates relative to the window are returned.
1491 If they are in the bottom divider of WINDOW, `bottom-divider' is returned.
1492 If they are in the right divider of WINDOW, `right-divider' is returned.
1493 If they are in the mode line of WINDOW, `mode-line' is returned.
1494 If they are in the header line of WINDOW, `header-line' is returned.
1495 If they are in the left fringe of WINDOW, `left-fringe' is returned.
1496 If they are in the right fringe of WINDOW, `right-fringe' is returned.
1497 If they are on the border between WINDOW and its right sibling,
1498 `vertical-line' is returned.
1499 If they are in the windows's left or right marginal areas, `left-margin'\n\
1500 or `right-margin' is returned. */)
1501 (register Lisp_Object coordinates, Lisp_Object window)
1503 struct window *w;
1504 struct frame *f;
1505 int x, y;
1506 Lisp_Object lx, ly;
1508 w = decode_live_window (window);
1509 f = XFRAME (w->frame);
1510 CHECK_CONS (coordinates);
1511 lx = Fcar (coordinates);
1512 ly = Fcdr (coordinates);
1513 CHECK_NUMBER_OR_FLOAT (lx);
1514 CHECK_NUMBER_OR_FLOAT (ly);
1515 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1516 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
1518 switch (coordinates_in_window (w, x, y))
1520 case ON_NOTHING:
1521 return Qnil;
1523 case ON_TEXT:
1524 /* Convert X and Y to window relative pixel coordinates, and
1525 return the canonical char units. */
1526 x -= window_box_left (w, TEXT_AREA);
1527 y -= WINDOW_TOP_EDGE_Y (w);
1528 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1529 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
1531 case ON_MODE_LINE:
1532 return Qmode_line;
1534 case ON_VERTICAL_BORDER:
1535 return Qvertical_line;
1537 case ON_HEADER_LINE:
1538 return Qheader_line;
1540 case ON_LEFT_FRINGE:
1541 return Qleft_fringe;
1543 case ON_RIGHT_FRINGE:
1544 return Qright_fringe;
1546 case ON_LEFT_MARGIN:
1547 return Qleft_margin;
1549 case ON_RIGHT_MARGIN:
1550 return Qright_margin;
1552 case ON_VERTICAL_SCROLL_BAR:
1553 /* Historically we are supposed to return nil in this case. */
1554 return Qnil;
1556 case ON_HORIZONTAL_SCROLL_BAR:
1557 return Qnil;
1559 case ON_RIGHT_DIVIDER:
1560 return Qright_divider;
1562 case ON_BOTTOM_DIVIDER:
1563 return Qbottom_divider;
1565 default:
1566 emacs_abort ();
1571 /* Callback for foreach_window, used in window_from_coordinates.
1572 Check if window W contains coordinates specified by USER_DATA which
1573 is actually a pointer to a struct check_window_data CW.
1575 Check if window W contains coordinates *CW->x and *CW->y. If it
1576 does, return W in *CW->window, as Lisp_Object, and return in
1577 *CW->part the part of the window under coordinates *X,*Y. Return
1578 false from this function to stop iterating over windows. */
1580 struct check_window_data
1582 Lisp_Object *window;
1583 int x, y;
1584 enum window_part *part;
1587 static bool
1588 check_window_containing (struct window *w, void *user_data)
1590 struct check_window_data *cw = user_data;
1591 enum window_part found = coordinates_in_window (w, cw->x, cw->y);
1592 if (found == ON_NOTHING)
1593 return true;
1594 else
1596 *cw->part = found;
1597 XSETWINDOW (*cw->window, w);
1598 return false;
1603 /* Find the window containing frame-relative pixel position X/Y and
1604 return it as a Lisp_Object.
1606 If X, Y is on one of the window's special `window_part' elements,
1607 set *PART to the id of that element.
1609 If there is no window under X, Y return nil and leave *PART
1610 unmodified. TOOL_BAR_P means detect tool-bar windows.
1612 This function was previously implemented with a loop cycling over
1613 windows with Fnext_window, and starting with the frame's selected
1614 window. It turned out that this doesn't work with an
1615 implementation of next_window using Vwindow_list, because
1616 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1617 tree of F when this function is called asynchronously from
1618 note_mouse_highlight. The original loop didn't terminate in this
1619 case. */
1621 Lisp_Object
1622 window_from_coordinates (struct frame *f, int x, int y,
1623 enum window_part *part, bool tool_bar_p)
1625 Lisp_Object window;
1626 struct check_window_data cw;
1627 enum window_part dummy;
1629 if (part == 0)
1630 part = &dummy;
1632 window = Qnil;
1633 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
1634 foreach_window (f, check_window_containing, &cw);
1636 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
1637 /* If not found above, see if it's in the tool bar window, if a tool
1638 bar exists. */
1639 if (NILP (window)
1640 && tool_bar_p
1641 && WINDOWP (f->tool_bar_window)
1642 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1643 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
1644 != ON_NOTHING))
1646 *part = ON_TEXT;
1647 window = f->tool_bar_window;
1649 #endif
1651 return window;
1654 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1655 doc: /* Return window containing coordinates X and Y on FRAME.
1656 FRAME must be a live frame and defaults to the selected one.
1657 The top left corner of the frame is considered to be row 0,
1658 column 0. */)
1659 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1661 struct frame *f = decode_live_frame (frame);
1663 /* Check that arguments are integers or floats. */
1664 CHECK_NUMBER_OR_FLOAT (x);
1665 CHECK_NUMBER_OR_FLOAT (y);
1667 return window_from_coordinates (f,
1668 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1669 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1670 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1671 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1672 0, false);
1675 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1676 doc: /* Return current value of point in WINDOW.
1677 WINDOW must be a live window and defaults to the selected one.
1679 For a nonselected window, this is the value point would have if that
1680 window were selected.
1682 Note that, when WINDOW is selected, the value returned is the same as
1683 that returned by `point' for WINDOW's buffer. It would be more strictly
1684 correct to return the top-level value of `point', outside of any
1685 `save-excursion' forms. But that is hard to define. */)
1686 (Lisp_Object window)
1688 register struct window *w = decode_live_window (window);
1690 if (w == XWINDOW (selected_window))
1691 return make_number (BUF_PT (XBUFFER (w->contents)));
1692 else
1693 return Fmarker_position (w->pointm);
1696 DEFUN ("window-old-point", Fwindow_old_point, Swindow_old_point, 0, 1, 0,
1697 doc: /* Return old value of point in WINDOW.
1698 WINDOW must be a live window and defaults to the selected one. */)
1699 (Lisp_Object window)
1701 return Fmarker_position (decode_live_window (window)->old_pointm);
1704 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1705 doc: /* Return position at which display currently starts in WINDOW.
1706 WINDOW must be a live window and defaults to the selected one.
1707 This is updated by redisplay or by calling `set-window-start'. */)
1708 (Lisp_Object window)
1710 return Fmarker_position (decode_live_window (window)->start);
1713 /* This is text temporarily removed from the doc string below.
1715 This function returns nil if the position is not currently known.
1716 That happens when redisplay is preempted and doesn't finish.
1717 If in that case you want to compute where the end of the window would
1718 have been if redisplay had finished, do this:
1719 (save-excursion
1720 (goto-char (window-start window))
1721 (vertical-motion (1- (window-height window)) window)
1722 (point))") */
1724 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1725 doc: /* Return position at which display currently ends in WINDOW.
1726 WINDOW must be a live window and defaults to the selected one.
1727 This is updated by redisplay, when it runs to completion.
1728 Simply changing the buffer text or setting `window-start'
1729 does not update this value.
1730 Return nil if there is no recorded value. (This can happen if the
1731 last redisplay of WINDOW was preempted, and did not finish.)
1732 If UPDATE is non-nil, compute the up-to-date position
1733 if it isn't already recorded. */)
1734 (Lisp_Object window, Lisp_Object update)
1736 Lisp_Object value;
1737 struct window *w = decode_live_window (window);
1738 Lisp_Object buf;
1739 struct buffer *b;
1741 buf = w->contents;
1742 CHECK_BUFFER (buf);
1743 b = XBUFFER (buf);
1745 if (! NILP (update)
1746 && (windows_or_buffers_changed
1747 || !w->window_end_valid
1748 || b->clip_changed
1749 || b->prevent_redisplay_optimizations_p
1750 || window_outdated (w))
1751 && !noninteractive)
1753 struct text_pos startp;
1754 struct it it;
1755 struct buffer *old_buffer = NULL;
1756 void *itdata = NULL;
1758 /* Cannot use Fvertical_motion because that function doesn't
1759 cope with variable-height lines. */
1760 if (b != current_buffer)
1762 old_buffer = current_buffer;
1763 set_buffer_internal (b);
1766 /* In case W->start is out of the range, use something
1767 reasonable. This situation occurred when loading a file with
1768 `-l' containing a call to `rmail' with subsequent other
1769 commands. At the end, W->start happened to be BEG, while
1770 rmail had already narrowed the buffer. */
1771 CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
1773 itdata = bidi_shelve_cache ();
1774 start_display (&it, w, startp);
1775 move_it_vertically (&it, window_box_height (w));
1776 if (it.current_y < it.last_visible_y)
1777 move_it_past_eol (&it);
1778 value = make_number (IT_CHARPOS (it));
1779 bidi_unshelve_cache (itdata, false);
1781 if (old_buffer)
1782 set_buffer_internal (old_buffer);
1784 else
1785 XSETINT (value, BUF_Z (b) - w->window_end_pos);
1787 return value;
1790 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1791 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1792 WINDOW must be a live window and defaults to the selected one.
1793 Return POS. */)
1794 (Lisp_Object window, Lisp_Object pos)
1796 register struct window *w = decode_live_window (window);
1798 /* Type of POS is checked by Fgoto_char or set_marker_restricted ... */
1800 if (w == XWINDOW (selected_window))
1802 if (XBUFFER (w->contents) == current_buffer)
1803 Fgoto_char (pos);
1804 else
1806 struct buffer *old_buffer = current_buffer;
1808 /* ... but here we want to catch type error before buffer change. */
1809 CHECK_NUMBER_COERCE_MARKER (pos);
1810 set_buffer_internal (XBUFFER (w->contents));
1811 Fgoto_char (pos);
1812 set_buffer_internal (old_buffer);
1815 else
1817 set_marker_restricted (w->pointm, pos, w->contents);
1818 /* We have to make sure that redisplay updates the window to show
1819 the new value of point. */
1820 wset_redisplay (w);
1823 return pos;
1826 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1827 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1828 WINDOW must be a live window and defaults to the selected one. Return
1829 POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
1830 overriding motion of point in order to display at this exact start. */)
1831 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1833 register struct window *w = decode_live_window (window);
1835 set_marker_restricted (w->start, pos, w->contents);
1836 /* This is not right, but much easier than doing what is right. */
1837 w->start_at_line_beg = false;
1838 if (NILP (noforce))
1839 w->force_start = true;
1840 w->update_mode_line = true;
1841 /* Bug#15957. */
1842 w->window_end_valid = false;
1843 wset_redisplay (w);
1845 return pos;
1848 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1849 Spos_visible_in_window_p, 0, 3, 0,
1850 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1851 WINDOW must be a live window and defaults to the selected one.
1853 Return nil if that position is scrolled vertically out of view. If a
1854 character is only partially visible, nil is returned, unless the
1855 optional argument PARTIALLY is non-nil. If POS is only out of view
1856 because of horizontal scrolling, return non-nil. If POS is t, it
1857 specifies the position of the last visible glyph in WINDOW. POS
1858 defaults to point in WINDOW; WINDOW defaults to the selected window.
1860 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
1861 the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
1862 where X and Y are the pixel coordinates relative to the top left corner
1863 of the window. The remaining elements are omitted if the character after
1864 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1865 off-window at the top and bottom of the screen line ("row") containing
1866 POS, ROWH is the visible height of that row, and VPOS is the row number
1867 \(zero-based). */)
1868 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1870 struct window *w;
1871 EMACS_INT posint;
1872 struct buffer *buf;
1873 struct text_pos top;
1874 Lisp_Object in_window = Qnil;
1875 int rtop, rbot, rowh, vpos;
1876 bool fully_p = true;
1877 int x, y;
1879 w = decode_live_window (window);
1880 buf = XBUFFER (w->contents);
1881 SET_TEXT_POS_FROM_MARKER (top, w->start);
1883 if (EQ (pos, Qt))
1884 posint = -1;
1885 else if (!NILP (pos))
1887 CHECK_NUMBER_COERCE_MARKER (pos);
1888 posint = XINT (pos);
1890 else if (w == XWINDOW (selected_window))
1891 posint = PT;
1892 else
1893 posint = marker_position (w->pointm);
1895 /* If position is above window start or outside buffer boundaries,
1896 or if window start is out of range, position is not visible. */
1897 if ((EQ (pos, Qt)
1898 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
1899 && CHARPOS (top) >= BUF_BEGV (buf)
1900 && CHARPOS (top) <= BUF_ZV (buf)
1901 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos))
1903 fully_p = !rtop && !rbot;
1904 if (!NILP (partially) || fully_p)
1905 in_window = Qt;
1908 if (!NILP (in_window) && !NILP (partially))
1910 Lisp_Object part = Qnil;
1911 if (!fully_p)
1912 part = list4i (rtop, rbot, rowh, vpos);
1913 in_window = Fcons (make_number (x),
1914 Fcons (make_number (y), part));
1917 return in_window;
1920 DEFUN ("window-line-height", Fwindow_line_height,
1921 Swindow_line_height, 0, 2, 0,
1922 doc: /* Return height in pixels of text line LINE in window WINDOW.
1923 WINDOW must be a live window and defaults to the selected one.
1925 Return height of current line if LINE is omitted or nil. Return height of
1926 header or mode line if LINE is `header-line' or `mode-line'.
1927 Otherwise, LINE is a text line number starting from 0. A negative number
1928 counts from the end of the window.
1930 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
1931 in pixels of the visible part of the line, VPOS and YPOS are the
1932 vertical position in lines and pixels of the line, relative to the top
1933 of the first text line, and OFFBOT is the number of off-window pixels at
1934 the bottom of the text line. If there are off-window pixels at the top
1935 of the (first) text line, YPOS is negative.
1937 Return nil if window display is not up-to-date. In that case, use
1938 `pos-visible-in-window-p' to obtain the information. */)
1939 (Lisp_Object line, Lisp_Object window)
1941 register struct window *w;
1942 register struct buffer *b;
1943 struct glyph_row *row, *end_row;
1944 int max_y, crop, i;
1945 EMACS_INT n;
1947 w = decode_live_window (window);
1949 if (noninteractive || w->pseudo_window_p)
1950 return Qnil;
1952 CHECK_BUFFER (w->contents);
1953 b = XBUFFER (w->contents);
1955 /* Fail if current matrix is not up-to-date. */
1956 if (!w->window_end_valid
1957 || windows_or_buffers_changed
1958 || b->clip_changed
1959 || b->prevent_redisplay_optimizations_p
1960 || window_outdated (w))
1961 return Qnil;
1963 if (NILP (line))
1965 i = w->cursor.vpos;
1966 if (i < 0 || i >= w->current_matrix->nrows
1967 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
1968 return Qnil;
1969 max_y = window_text_bottom_y (w);
1970 goto found_row;
1973 if (EQ (line, Qheader_line))
1975 if (!WINDOW_WANTS_HEADER_LINE_P (w))
1976 return Qnil;
1977 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1978 return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
1981 if (EQ (line, Qmode_line))
1983 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1984 return (row->enabled_p ?
1985 list4i (row->height,
1986 0, /* not accurate */
1987 (WINDOW_HEADER_LINE_HEIGHT (w)
1988 + window_text_bottom_y (w)),
1990 : Qnil);
1993 CHECK_NUMBER (line);
1994 n = XINT (line);
1996 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1997 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
1998 max_y = window_text_bottom_y (w);
1999 i = 0;
2001 while ((n < 0 || i < n)
2002 && row <= end_row && row->enabled_p
2003 && row->y + row->height < max_y)
2004 row++, i++;
2006 if (row > end_row || !row->enabled_p)
2007 return Qnil;
2009 if (++n < 0)
2011 if (-n > i)
2012 return Qnil;
2013 row += n;
2014 i += n;
2017 found_row:
2018 crop = max (0, (row->y + row->height) - max_y);
2019 return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
2022 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
2023 0, 1, 0,
2024 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
2025 More precisely, return the value assigned by the last call of
2026 `set-window-dedicated-p' for WINDOW. Return nil if that function was
2027 never called with WINDOW as its argument, or the value set by that
2028 function was internally reset since its last call. WINDOW must be a
2029 live window and defaults to the selected one.
2031 When a window is dedicated to its buffer, `display-buffer' will refrain
2032 from displaying another buffer in it. `get-lru-window' and
2033 `get-largest-window' treat dedicated windows specially.
2034 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
2035 `kill-buffer' can delete a dedicated window and the containing frame.
2037 Functions like `set-window-buffer' may change the buffer displayed by a
2038 window, unless that window is "strongly" dedicated to its buffer, that
2039 is the value returned by `window-dedicated-p' is t. */)
2040 (Lisp_Object window)
2042 return decode_live_window (window)->dedicated;
2045 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
2046 Sset_window_dedicated_p, 2, 2, 0,
2047 doc: /* Mark WINDOW as dedicated according to FLAG.
2048 WINDOW must be a live window and defaults to the selected one. FLAG
2049 non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
2050 mark WINDOW as non-dedicated. Return FLAG.
2052 When a window is dedicated to its buffer, `display-buffer' will refrain
2053 from displaying another buffer in it. `get-lru-window' and
2054 `get-largest-window' treat dedicated windows specially.
2055 `delete-windows-on', `replace-buffer-in-windows', `quit-window',
2056 `quit-restore-window' and `kill-buffer' can delete a dedicated window
2057 and the containing frame.
2059 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
2060 its buffer. Functions like `set-window-buffer' may change the buffer
2061 displayed by a window, unless that window is strongly dedicated to its
2062 buffer. If and when `set-window-buffer' displays another buffer in a
2063 window, it also makes sure that the window is no more dedicated. */)
2064 (Lisp_Object window, Lisp_Object flag)
2066 wset_dedicated (decode_live_window (window), flag);
2067 return flag;
2070 DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
2071 0, 1, 0,
2072 doc: /* Return buffers previously shown in WINDOW.
2073 WINDOW must be a live window and defaults to the selected one.
2075 The return value is a list of elements (BUFFER WINDOW-START POS),
2076 where BUFFER is a buffer, WINDOW-START is the start position of the
2077 window for that buffer, and POS is a window-specific point value. */)
2078 (Lisp_Object window)
2080 return decode_live_window (window)->prev_buffers;
2083 DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
2084 Sset_window_prev_buffers, 2, 2, 0,
2085 doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
2086 WINDOW must be a live window and defaults to the selected one.
2088 PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS),
2089 where BUFFER is a buffer, WINDOW-START is the start position of the
2090 window for that buffer, and POS is a window-specific point value. */)
2091 (Lisp_Object window, Lisp_Object prev_buffers)
2093 wset_prev_buffers (decode_live_window (window), prev_buffers);
2094 return prev_buffers;
2097 DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
2098 0, 1, 0,
2099 doc: /* Return list of buffers recently re-shown in WINDOW.
2100 WINDOW must be a live window and defaults to the selected one. */)
2101 (Lisp_Object window)
2103 return decode_live_window (window)->next_buffers;
2106 DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
2107 Sset_window_next_buffers, 2, 2, 0,
2108 doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
2109 WINDOW must be a live window and defaults to the selected one.
2110 NEXT-BUFFERS should be a list of buffers. */)
2111 (Lisp_Object window, Lisp_Object next_buffers)
2113 wset_next_buffers (decode_live_window (window), next_buffers);
2114 return next_buffers;
2117 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
2118 0, 1, 0,
2119 doc: /* Return the parameters of WINDOW and their values.
2120 WINDOW must be a valid window and defaults to the selected one. The
2121 return value is a list of elements of the form (PARAMETER . VALUE). */)
2122 (Lisp_Object window)
2124 return Fcopy_alist (decode_valid_window (window)->window_parameters);
2127 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
2128 2, 2, 0,
2129 doc: /* Return WINDOW's value for PARAMETER.
2130 WINDOW can be any window and defaults to the selected one. */)
2131 (Lisp_Object window, Lisp_Object parameter)
2133 Lisp_Object result;
2135 result = Fassq (parameter, decode_any_window (window)->window_parameters);
2136 return CDR_SAFE (result);
2139 DEFUN ("set-window-parameter", Fset_window_parameter,
2140 Sset_window_parameter, 3, 3, 0,
2141 doc: /* Set WINDOW's value of PARAMETER to VALUE.
2142 WINDOW can be any window and defaults to the selected one.
2143 Return VALUE. */)
2144 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
2146 register struct window *w = decode_any_window (window);
2147 Lisp_Object old_alist_elt;
2149 old_alist_elt = Fassq (parameter, w->window_parameters);
2150 if (NILP (old_alist_elt))
2151 wset_window_parameters
2152 (w, Fcons (Fcons (parameter, value), w->window_parameters));
2153 else
2154 Fsetcdr (old_alist_elt, value);
2155 return value;
2158 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
2159 0, 1, 0,
2160 doc: /* Return the display-table that WINDOW is using.
2161 WINDOW must be a live window and defaults to the selected one. */)
2162 (Lisp_Object window)
2164 return decode_live_window (window)->display_table;
2167 /* Get the display table for use on window W. This is either W's
2168 display table or W's buffer's display table. Ignore the specified
2169 tables if they are not valid; if no valid table is specified,
2170 return 0. */
2172 struct Lisp_Char_Table *
2173 window_display_table (struct window *w)
2175 struct Lisp_Char_Table *dp = NULL;
2177 if (DISP_TABLE_P (w->display_table))
2178 dp = XCHAR_TABLE (w->display_table);
2179 else if (BUFFERP (w->contents))
2181 struct buffer *b = XBUFFER (w->contents);
2183 if (DISP_TABLE_P (BVAR (b, display_table)))
2184 dp = XCHAR_TABLE (BVAR (b, display_table));
2185 else if (DISP_TABLE_P (Vstandard_display_table))
2186 dp = XCHAR_TABLE (Vstandard_display_table);
2189 return dp;
2192 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
2193 doc: /* Set WINDOW's display-table to TABLE.
2194 WINDOW must be a live window and defaults to the selected one. */)
2195 (register Lisp_Object window, Lisp_Object table)
2197 wset_display_table (decode_live_window (window), table);
2198 return table;
2201 /* Record info on buffer window W is displaying
2202 when it is about to cease to display that buffer. */
2203 static void
2204 unshow_buffer (register struct window *w)
2206 Lisp_Object buf = w->contents;
2207 struct buffer *b = XBUFFER (buf);
2209 eassert (b == XMARKER (w->pointm)->buffer);
2211 #if false
2212 if (w == XWINDOW (selected_window)
2213 || ! EQ (buf, XWINDOW (selected_window)->contents))
2214 /* Do this except when the selected window's buffer
2215 is being removed from some other window. */
2216 #endif
2217 /* last_window_start records the start position that this buffer
2218 had in the last window to be disconnected from it.
2219 Now that this statement is unconditional,
2220 it is possible for the buffer to be displayed in the
2221 selected window, while last_window_start reflects another
2222 window which was recently showing the same buffer.
2223 Some people might say that might be a good thing. Let's see. */
2224 b->last_window_start = marker_position (w->start);
2226 /* Point in the selected window's buffer
2227 is actually stored in that buffer, and the window's pointm isn't used.
2228 So don't clobber point in that buffer. */
2229 if (! EQ (buf, XWINDOW (selected_window)->contents)
2230 /* Don't clobber point in current buffer either (this could be
2231 useful in connection with bug#12208).
2232 && XBUFFER (buf) != current_buffer */
2233 /* This line helps to fix Horsley's testbug.el bug. */
2234 && !(WINDOWP (BVAR (b, last_selected_window))
2235 && w != XWINDOW (BVAR (b, last_selected_window))
2236 && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->contents)))
2237 temp_set_point_both (b,
2238 clip_to_bounds (BUF_BEGV (b),
2239 marker_position (w->pointm),
2240 BUF_ZV (b)),
2241 clip_to_bounds (BUF_BEGV_BYTE (b),
2242 marker_byte_position (w->pointm),
2243 BUF_ZV_BYTE (b)));
2245 if (WINDOWP (BVAR (b, last_selected_window))
2246 && w == XWINDOW (BVAR (b, last_selected_window)))
2247 bset_last_selected_window (b, Qnil);
2250 /* Put NEW into the window structure in place of OLD. SETFLAG false
2251 means change window structure only. Otherwise store geometry and
2252 other settings as well. */
2253 static void
2254 replace_window (Lisp_Object old, Lisp_Object new, bool setflag)
2256 Lisp_Object tem;
2257 struct window *o = XWINDOW (old), *n = XWINDOW (new);
2259 /* If OLD is its frame's root window, then NEW is the new
2260 root window for that frame. */
2261 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
2262 fset_root_window (XFRAME (o->frame), new);
2264 if (setflag)
2266 n->pixel_left = o->pixel_left;
2267 n->pixel_top = o->pixel_top;
2268 n->pixel_width = o->pixel_width;
2269 n->pixel_height = o->pixel_height;
2270 n->left_col = o->left_col;
2271 n->top_line = o->top_line;
2272 n->total_cols = o->total_cols;
2273 n->total_lines = o->total_lines;
2274 wset_normal_cols (n, o->normal_cols);
2275 wset_normal_cols (o, make_float (1.0));
2276 wset_normal_lines (n, o->normal_lines);
2277 wset_normal_lines (o, make_float (1.0));
2278 n->desired_matrix = n->current_matrix = 0;
2279 n->vscroll = 0;
2280 memset (&n->cursor, 0, sizeof (n->cursor));
2281 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
2282 n->last_cursor_vpos = 0;
2283 #ifdef HAVE_WINDOW_SYSTEM
2284 n->phys_cursor_type = NO_CURSOR;
2285 n->phys_cursor_width = -1;
2286 #endif
2287 n->must_be_updated_p = false;
2288 n->pseudo_window_p = false;
2289 n->window_end_vpos = 0;
2290 n->window_end_pos = 0;
2291 n->window_end_valid = false;
2294 tem = o->next;
2295 wset_next (n, tem);
2296 if (!NILP (tem))
2297 wset_prev (XWINDOW (tem), new);
2299 tem = o->prev;
2300 wset_prev (n, tem);
2301 if (!NILP (tem))
2302 wset_next (XWINDOW (tem), new);
2304 tem = o->parent;
2305 wset_parent (n, tem);
2306 if (!NILP (tem) && EQ (XWINDOW (tem)->contents, old))
2307 wset_combination (XWINDOW (tem), XWINDOW (tem)->horizontal, new);
2310 /* If window WINDOW and its parent window are iso-combined, merge
2311 WINDOW's children into those of its parent window and mark WINDOW as
2312 deleted. */
2314 static void
2315 recombine_windows (Lisp_Object window)
2317 struct window *w, *p, *c;
2318 Lisp_Object parent, child;
2319 bool horflag;
2321 w = XWINDOW (window);
2322 parent = w->parent;
2323 if (!NILP (parent) && NILP (w->combination_limit))
2325 p = XWINDOW (parent);
2326 if (WINDOWP (p->contents) && WINDOWP (w->contents)
2327 && p->horizontal == w->horizontal)
2328 /* WINDOW and PARENT are both either a vertical or a horizontal
2329 combination. */
2331 horflag = WINDOW_HORIZONTAL_COMBINATION_P (w);
2332 child = w->contents;
2333 c = XWINDOW (child);
2335 /* Splice WINDOW's children into its parent's children and
2336 assign new normal sizes. */
2337 if (NILP (w->prev))
2338 wset_combination (p, horflag, child);
2339 else
2341 wset_prev (c, w->prev);
2342 wset_next (XWINDOW (w->prev), child);
2345 while (c)
2347 wset_parent (c, parent);
2349 if (horflag)
2350 wset_normal_cols
2351 (c, make_float ((double) c->pixel_width
2352 / (double) p->pixel_width));
2353 else
2354 wset_normal_lines
2355 (c, make_float ((double) c->pixel_height
2356 / (double) p->pixel_height));
2358 if (NILP (c->next))
2360 if (!NILP (w->next))
2362 wset_next (c, w->next);
2363 wset_prev (XWINDOW (c->next), child);
2366 c = 0;
2368 else
2370 child = c->next;
2371 c = XWINDOW (child);
2375 /* WINDOW can be deleted now. */
2376 wset_combination (w, false, Qnil);
2381 /* If WINDOW can be deleted, delete it. */
2382 static void
2383 delete_deletable_window (Lisp_Object window)
2385 if (!NILP (call1 (Qwindow_deletable_p, window)))
2386 call1 (Qdelete_window, window);
2389 /***********************************************************************
2390 Window List
2391 ***********************************************************************/
2393 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
2394 pointer. This is a callback function for foreach_window, used in
2395 the window_list function. */
2397 static bool
2398 add_window_to_list (struct window *w, void *user_data)
2400 Lisp_Object *list = user_data;
2401 Lisp_Object window;
2402 XSETWINDOW (window, w);
2403 *list = Fcons (window, *list);
2404 return true;
2408 /* Return a list of all windows, for use by next_window. If
2409 Vwindow_list is a list, return that list. Otherwise, build a new
2410 list, cache it in Vwindow_list, and return that. */
2412 Lisp_Object
2413 window_list (void)
2415 if (!CONSP (Vwindow_list))
2417 Lisp_Object tail, frame;
2419 Vwindow_list = Qnil;
2420 FOR_EACH_FRAME (tail, frame)
2422 Lisp_Object arglist = Qnil;
2424 /* We are visiting windows in canonical order, and add
2425 new windows at the front of args[1], which means we
2426 have to reverse this list at the end. */
2427 foreach_window (XFRAME (frame), add_window_to_list, &arglist);
2428 arglist = Fnreverse (arglist);
2429 Vwindow_list = CALLN (Fnconc, Vwindow_list, arglist);
2433 return Vwindow_list;
2437 /* Value is true if WINDOW satisfies the constraints given by
2438 OWINDOW, MINIBUF and ALL_FRAMES.
2440 MINIBUF t means WINDOW may be minibuffer windows.
2441 `lambda' means WINDOW may not be a minibuffer window.
2442 a window means a specific minibuffer window
2444 ALL_FRAMES t means search all frames,
2445 nil means search just current frame,
2446 `visible' means search just visible frames on the
2447 current terminal,
2448 0 means search visible and iconified frames on the
2449 current terminal,
2450 a window means search the frame that window belongs to,
2451 a frame means consider windows on that frame, only. */
2453 static bool
2454 candidate_window_p (Lisp_Object window, Lisp_Object owindow,
2455 Lisp_Object minibuf, Lisp_Object all_frames)
2457 struct window *w = XWINDOW (window);
2458 struct frame *f = XFRAME (w->frame);
2459 bool candidate_p = true;
2461 if (!BUFFERP (w->contents))
2462 candidate_p = false;
2463 else if (MINI_WINDOW_P (w)
2464 && (EQ (minibuf, Qlambda)
2465 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
2467 /* If MINIBUF is `lambda' don't consider any mini-windows.
2468 If it is a window, consider only that one. */
2469 candidate_p = false;
2471 else if (EQ (all_frames, Qt))
2472 candidate_p = true;
2473 else if (NILP (all_frames))
2475 eassert (WINDOWP (owindow));
2476 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
2478 else if (EQ (all_frames, Qvisible))
2480 candidate_p = FRAME_VISIBLE_P (f)
2481 && (FRAME_TERMINAL (XFRAME (w->frame))
2482 == FRAME_TERMINAL (XFRAME (selected_frame)));
2485 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2487 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2488 #ifdef HAVE_X_WINDOWS
2489 /* Yuck!! If we've just created the frame and the
2490 window-manager requested the user to place it
2491 manually, the window may still not be considered
2492 `visible'. I'd argue it should be at least
2493 something like `iconified', but don't know how to do
2494 that yet. --Stef */
2495 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
2496 && !f->output_data.x->has_been_visible)
2497 #endif
2499 && (FRAME_TERMINAL (XFRAME (w->frame))
2500 == FRAME_TERMINAL (XFRAME (selected_frame)));
2502 else if (WINDOWP (all_frames))
2503 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
2504 || EQ (XWINDOW (all_frames)->frame, w->frame)
2505 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
2506 else if (FRAMEP (all_frames))
2507 candidate_p = EQ (all_frames, w->frame);
2509 return candidate_p;
2513 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
2514 Fwindow_list. See candidate_window_p for the meaning of WINDOW,
2515 MINIBUF, and ALL_FRAMES. */
2517 static void
2518 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
2520 struct window *w = decode_live_window (*window);
2522 XSETWINDOW (*window, w);
2523 /* MINIBUF nil may or may not include minibuffers. Decide if it
2524 does. */
2525 if (NILP (*minibuf))
2526 *minibuf = minibuf_level ? minibuf_window : Qlambda;
2527 else if (!EQ (*minibuf, Qt))
2528 *minibuf = Qlambda;
2530 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
2531 => count none of them, or a specific minibuffer window (the
2532 active one) to count. */
2534 /* ALL_FRAMES nil doesn't specify which frames to include. */
2535 if (NILP (*all_frames))
2536 *all_frames
2537 = (!EQ (*minibuf, Qlambda)
2538 ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame))
2539 : Qnil);
2540 else if (EQ (*all_frames, Qvisible))
2542 else if (EQ (*all_frames, make_number (0)))
2544 else if (FRAMEP (*all_frames))
2546 else if (!EQ (*all_frames, Qt))
2547 *all_frames = Qnil;
2551 /* Return the next or previous window of WINDOW in cyclic ordering
2552 of windows. NEXT_P means return the next window. See the
2553 documentation string of next-window for the meaning of MINIBUF and
2554 ALL_FRAMES. */
2556 static Lisp_Object
2557 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames,
2558 bool next_p)
2560 decode_next_window_args (&window, &minibuf, &all_frames);
2562 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
2563 return the first window on the frame. */
2564 if (FRAMEP (all_frames)
2565 && !EQ (all_frames, XWINDOW (window)->frame))
2566 return Fframe_first_window (all_frames);
2568 if (next_p)
2570 Lisp_Object list;
2572 /* Find WINDOW in the list of all windows. */
2573 list = Fmemq (window, window_list ());
2575 /* Scan forward from WINDOW to the end of the window list. */
2576 if (CONSP (list))
2577 for (list = XCDR (list); CONSP (list); list = XCDR (list))
2578 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2579 break;
2581 /* Scan from the start of the window list up to WINDOW. */
2582 if (!CONSP (list))
2583 for (list = Vwindow_list;
2584 CONSP (list) && !EQ (XCAR (list), window);
2585 list = XCDR (list))
2586 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2587 break;
2589 if (CONSP (list))
2590 window = XCAR (list);
2592 else
2594 Lisp_Object candidate, list;
2596 /* Scan through the list of windows for candidates. If there are
2597 candidate windows in front of WINDOW, the last one of these
2598 is the one we want. If there are candidates following WINDOW
2599 in the list, again the last one of these is the one we want. */
2600 candidate = Qnil;
2601 for (list = window_list (); CONSP (list); list = XCDR (list))
2603 if (EQ (XCAR (list), window))
2605 if (WINDOWP (candidate))
2606 break;
2608 else if (candidate_window_p (XCAR (list), window, minibuf,
2609 all_frames))
2610 candidate = XCAR (list);
2613 if (WINDOWP (candidate))
2614 window = candidate;
2617 return window;
2621 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2622 doc: /* Return live window after WINDOW in the cyclic ordering of windows.
2623 WINDOW must be a live window and defaults to the selected one. The
2624 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2625 consider.
2627 MINIBUF nil or omitted means consider the minibuffer window only if the
2628 minibuffer is active. MINIBUF t means consider the minibuffer window
2629 even if the minibuffer is not active. Any other value means do not
2630 consider the minibuffer window even if the minibuffer is active.
2632 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2633 plus the minibuffer window if specified by the MINIBUF argument. If the
2634 minibuffer counts, consider all windows on all frames that share that
2635 minibuffer too. The following non-nil values of ALL-FRAMES have special
2636 meanings:
2638 - t means consider all windows on all existing frames.
2640 - `visible' means consider all windows on all visible frames.
2642 - 0 (the number zero) means consider all windows on all visible and
2643 iconified frames.
2645 - A frame means consider all windows on that frame only.
2647 Anything else means consider all windows on WINDOW's frame and no
2648 others.
2650 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2651 `next-window' to iterate through the entire cycle of acceptable
2652 windows, eventually ending up back at the window you started with.
2653 `previous-window' traverses the same cycle, in the reverse order. */)
2654 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2656 return next_window (window, minibuf, all_frames, true);
2660 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2661 doc: /* Return live window before WINDOW in the cyclic ordering of windows.
2662 WINDOW must be a live window and defaults to the selected one. The
2663 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2664 consider.
2666 MINIBUF nil or omitted means consider the minibuffer window only if the
2667 minibuffer is active. MINIBUF t means consider the minibuffer window
2668 even if the minibuffer is not active. Any other value means do not
2669 consider the minibuffer window even if the minibuffer is active.
2671 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2672 plus the minibuffer window if specified by the MINIBUF argument. If the
2673 minibuffer counts, consider all windows on all frames that share that
2674 minibuffer too. The following non-nil values of ALL-FRAMES have special
2675 meanings:
2677 - t means consider all windows on all existing frames.
2679 - `visible' means consider all windows on all visible frames.
2681 - 0 (the number zero) means consider all windows on all visible and
2682 iconified frames.
2684 - A frame means consider all windows on that frame only.
2686 Anything else means consider all windows on WINDOW's frame and no
2687 others.
2689 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2690 use `previous-window' to iterate through the entire cycle of
2691 acceptable windows, eventually ending up back at the window you
2692 started with. `next-window' traverses the same cycle, in the
2693 reverse order. */)
2694 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2696 return next_window (window, minibuf, all_frames, false);
2700 /* Return a list of windows in cyclic ordering. Arguments are like
2701 for `next-window'. */
2703 static Lisp_Object
2704 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2706 Lisp_Object tail, list, rest;
2708 decode_next_window_args (&window, &minibuf, &all_frames);
2709 list = Qnil;
2711 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2712 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2713 list = Fcons (XCAR (tail), list);
2715 /* Rotate the list to start with WINDOW. */
2716 list = Fnreverse (list);
2717 rest = Fmemq (window, list);
2718 if (!NILP (rest) && !EQ (rest, list))
2720 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2722 XSETCDR (tail, Qnil);
2723 list = nconc2 (rest, list);
2725 return list;
2729 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2730 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2731 FRAME nil or omitted means use the selected frame.
2732 WINDOW nil or omitted means use the window selected within FRAME.
2733 MINIBUF t means include the minibuffer window, even if it isn't active.
2734 MINIBUF nil or omitted means include the minibuffer window only
2735 if it's active.
2736 MINIBUF neither nil nor t means never include the minibuffer window. */)
2737 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2739 if (NILP (window))
2740 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2741 CHECK_WINDOW (window);
2742 if (NILP (frame))
2743 frame = selected_frame;
2745 if (!EQ (frame, XWINDOW (window)->frame))
2746 error ("Window is on a different frame");
2748 return window_list_1 (window, minibuf, frame);
2752 DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2753 doc: /* Return a list of all live windows.
2754 WINDOW specifies the first window to list and defaults to the selected
2755 window.
2757 Optional argument MINIBUF nil or omitted means consider the minibuffer
2758 window only if the minibuffer is active. MINIBUF t means consider the
2759 minibuffer window even if the minibuffer is not active. Any other value
2760 means do not consider the minibuffer window even if the minibuffer is
2761 active.
2763 Optional argument ALL-FRAMES nil or omitted means consider all windows
2764 on WINDOW's frame, plus the minibuffer window if specified by the
2765 MINIBUF argument. If the minibuffer counts, consider all windows on all
2766 frames that share that minibuffer too. The following non-nil values of
2767 ALL-FRAMES have special meanings:
2769 - t means consider all windows on all existing frames.
2771 - `visible' means consider all windows on all visible frames.
2773 - 0 (the number zero) means consider all windows on all visible and
2774 iconified frames.
2776 - A frame means consider all windows on that frame only.
2778 Anything else means consider all windows on WINDOW's frame and no
2779 others.
2781 If WINDOW is not on the list of windows returned, some other window will
2782 be listed first but no error is signaled. */)
2783 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2785 return window_list_1 (window, minibuf, all_frames);
2788 /* Look at all windows, performing an operation specified by TYPE
2789 with argument OBJ.
2790 If FRAMES is Qt, look at all frames;
2791 Qnil, look at just the selected frame;
2792 Qvisible, look at visible frames;
2793 a frame, just look at windows on that frame.
2794 If MINI, perform the operation on minibuffer windows too. */
2796 enum window_loop
2798 WINDOW_LOOP_UNUSED,
2799 GET_BUFFER_WINDOW, /* Arg is buffer */
2800 REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
2801 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2802 CHECK_ALL_WINDOWS /* Arg is ignored */
2805 static Lisp_Object
2806 window_loop (enum window_loop type, Lisp_Object obj, bool mini,
2807 Lisp_Object frames)
2809 Lisp_Object window, windows, best_window, frame_arg;
2810 bool frame_best_window_flag = false;
2811 struct frame *f;
2812 struct gcpro gcpro1;
2814 /* If we're only looping through windows on a particular frame,
2815 frame points to that frame. If we're looping through windows
2816 on all frames, frame is 0. */
2817 if (FRAMEP (frames))
2818 f = XFRAME (frames);
2819 else if (NILP (frames))
2820 f = SELECTED_FRAME ();
2821 else
2822 f = NULL;
2824 if (f)
2825 frame_arg = Qlambda;
2826 else if (EQ (frames, make_number (0)))
2827 frame_arg = frames;
2828 else if (EQ (frames, Qvisible))
2829 frame_arg = frames;
2830 else
2831 frame_arg = Qt;
2833 /* frame_arg is Qlambda to stick to one frame,
2834 Qvisible to consider all visible frames,
2835 or Qt otherwise. */
2837 /* Pick a window to start with. */
2838 if (WINDOWP (obj))
2839 window = obj;
2840 else if (f)
2841 window = FRAME_SELECTED_WINDOW (f);
2842 else
2843 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2845 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2846 GCPRO1 (windows);
2847 best_window = Qnil;
2849 for (; CONSP (windows); windows = XCDR (windows))
2851 struct window *w;
2853 window = XCAR (windows);
2854 w = XWINDOW (window);
2856 /* Note that we do not pay attention here to whether the frame
2857 is visible, since Fwindow_list skips non-visible frames if
2858 that is desired, under the control of frame_arg. */
2859 if (!MINI_WINDOW_P (w)
2860 /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
2861 consider all windows. */
2862 || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
2863 || (mini && minibuf_level > 0))
2864 switch (type)
2866 case GET_BUFFER_WINDOW:
2867 if (EQ (w->contents, obj)
2868 /* Don't find any minibuffer window except the one that
2869 is currently in use. */
2870 && (!MINI_WINDOW_P (w) || EQ (window, minibuf_window)))
2872 if (EQ (window, selected_window))
2873 /* Preferably return the selected window. */
2874 RETURN_UNGCPRO (window);
2875 else if (EQ (XWINDOW (window)->frame, selected_frame)
2876 && !frame_best_window_flag)
2877 /* Prefer windows on the current frame (but don't
2878 choose another one if we have one already). */
2880 best_window = window;
2881 frame_best_window_flag = true;
2883 else if (NILP (best_window))
2884 best_window = window;
2886 break;
2888 case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
2889 /* We could simply check whether the buffer shown by window
2890 is live, and show another buffer in case it isn't. */
2891 if (EQ (w->contents, obj))
2893 /* Undedicate WINDOW. */
2894 wset_dedicated (w, Qnil);
2895 /* Make WINDOW show the buffer returned by
2896 other_buffer_safely, don't run any hooks. */
2897 set_window_buffer
2898 (window, other_buffer_safely (w->contents), false, false);
2899 /* If WINDOW is the selected window, make its buffer
2900 current. But do so only if the window shows the
2901 current buffer (Bug#6454). */
2902 if (EQ (window, selected_window)
2903 && XBUFFER (w->contents) == current_buffer)
2904 Fset_buffer (w->contents);
2906 break;
2908 case REDISPLAY_BUFFER_WINDOWS:
2909 if (EQ (w->contents, obj))
2911 mark_window_display_accurate (window, false);
2912 w->update_mode_line = true;
2913 XBUFFER (obj)->prevent_redisplay_optimizations_p = true;
2914 update_mode_lines = 27;
2915 best_window = window;
2917 break;
2919 /* Check for a leaf window that has a killed buffer
2920 or broken markers. */
2921 case CHECK_ALL_WINDOWS:
2922 if (BUFFERP (w->contents))
2924 struct buffer *b = XBUFFER (w->contents);
2926 if (!BUFFER_LIVE_P (b))
2927 emacs_abort ();
2928 if (!MARKERP (w->start) || XMARKER (w->start)->buffer != b)
2929 emacs_abort ();
2930 if (!MARKERP (w->pointm) || XMARKER (w->pointm)->buffer != b)
2931 emacs_abort ();
2933 break;
2935 case WINDOW_LOOP_UNUSED:
2936 break;
2940 UNGCPRO;
2941 return best_window;
2944 /* Used for debugging. Abort if any window has a dead buffer. */
2946 extern void check_all_windows (void) EXTERNALLY_VISIBLE;
2947 void
2948 check_all_windows (void)
2950 window_loop (CHECK_ALL_WINDOWS, Qnil, true, Qt);
2953 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2954 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2955 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
2956 the current buffer.
2958 The optional argument ALL-FRAMES specifies the frames to consider:
2960 - t means consider all windows on all existing frames.
2962 - `visible' means consider all windows on all visible frames.
2964 - 0 (the number zero) means consider all windows on all visible
2965 and iconified frames.
2967 - A frame means consider all windows on that frame only.
2969 Any other value of ALL-FRAMES means consider all windows on the
2970 selected frame and no others. */)
2971 (Lisp_Object buffer_or_name, Lisp_Object all_frames)
2973 Lisp_Object buffer;
2975 if (NILP (buffer_or_name))
2976 buffer = Fcurrent_buffer ();
2977 else
2978 buffer = Fget_buffer (buffer_or_name);
2980 if (BUFFERP (buffer))
2981 return window_loop (GET_BUFFER_WINDOW, buffer, true, all_frames);
2982 else
2983 return Qnil;
2987 static Lisp_Object
2988 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore, Lisp_Object pixelwise)
2990 return call5 (Qwindow_resize_root_window, window, delta, horizontal, ignore, pixelwise);
2993 /* Placeholder used by temacs -nw before window.el is loaded. */
2994 DEFUN ("window--sanitize-window-sizes", Fwindow__sanitize_window_sizes,
2995 Swindow__sanitize_window_sizes, 2, 2, 0,
2996 doc: /* */
2997 attributes: const)
2998 (Lisp_Object frame, Lisp_Object horizontal)
3000 return Qnil;
3003 Lisp_Object
3004 sanitize_window_sizes (Lisp_Object frame, Lisp_Object horizontal)
3006 return call2 (Qwindow_sanitize_window_sizes, frame, horizontal);
3010 static Lisp_Object
3011 window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal)
3013 return call2 (Qwindow_pixel_to_total, frame, horizontal);
3017 DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
3018 Sdelete_other_windows_internal, 0, 2, "",
3019 doc: /* Make WINDOW fill its frame.
3020 Only the frame WINDOW is on is affected. WINDOW must be a valid window
3021 and defaults to the selected one.
3023 Optional argument ROOT, if non-nil, must specify an internal window such
3024 that WINDOW is in its window subtree. If this is the case, replace ROOT
3025 by WINDOW and leave alone any windows not part of ROOT's subtree.
3027 When WINDOW is live try to reduce display jumps by keeping the text
3028 previously visible in WINDOW in the same place on the frame. Doing this
3029 depends on the value of (window-start WINDOW), so if calling this
3030 function in a program gives strange scrolling, make sure the
3031 window-start value is reasonable when this function is called. */)
3032 (Lisp_Object window, Lisp_Object root)
3034 struct window *w, *r, *s;
3035 struct frame *f;
3036 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
3037 ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0);
3038 int top IF_LINT (= 0), new_top;
3040 w = decode_valid_window (window);
3041 XSETWINDOW (window, w);
3042 f = XFRAME (w->frame);
3044 if (NILP (root))
3045 /* ROOT is the frame's root window. */
3047 root = FRAME_ROOT_WINDOW (f);
3048 r = XWINDOW (root);
3050 else
3051 /* ROOT must be an ancestor of WINDOW. */
3053 r = decode_valid_window (root);
3054 pwindow = XWINDOW (window)->parent;
3055 while (!NILP (pwindow))
3056 if (EQ (pwindow, root))
3057 break;
3058 else
3059 pwindow = XWINDOW (pwindow)->parent;
3060 if (!EQ (pwindow, root))
3061 error ("Specified root is not an ancestor of specified window");
3064 if (EQ (window, root))
3065 /* A noop. */
3066 return Qnil;
3067 /* I don't understand the "top > 0" part below. If we deal with a
3068 standalone minibuffer it would have been caught by the preceding
3069 test. */
3070 else if (MINI_WINDOW_P (w)) /* && top > 0) */
3071 error ("Can't expand minibuffer to full frame");
3073 if (BUFFERP (w->contents))
3075 startpos = marker_position (w->start);
3076 startbyte = marker_byte_position (w->start);
3077 top = (WINDOW_TOP_EDGE_LINE (w)
3078 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))));
3079 /* Make sure WINDOW is the frame's selected window. */
3080 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
3082 if (EQ (selected_frame, w->frame))
3083 Fselect_window (window, Qnil);
3084 else
3085 fset_selected_window (f, window);
3088 else
3090 /* See if the frame's selected window is a part of the window
3091 subtree rooted at WINDOW, by finding all the selected window's
3092 parents and comparing each one with WINDOW. If it isn't we
3093 need a new selected window for this frame. */
3094 swindow = FRAME_SELECTED_WINDOW (f);
3095 while (true)
3097 pwindow = swindow;
3098 while (!NILP (pwindow) && !EQ (window, pwindow))
3099 pwindow = XWINDOW (pwindow)->parent;
3101 if (EQ (window, pwindow))
3102 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
3103 as the new selected window. */
3104 break;
3105 else
3106 /* Else try the previous window of SWINDOW. */
3107 swindow = Fprevious_window (swindow, Qlambda, Qnil);
3110 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
3112 if (EQ (selected_frame, w->frame))
3113 Fselect_window (swindow, Qnil);
3114 else
3115 fset_selected_window (f, swindow);
3119 block_input ();
3120 if (!FRAME_INITIAL_P (f))
3122 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
3124 /* We are going to free the glyph matrices of WINDOW, and with
3125 that we might lose any information about glyph rows that have
3126 some of their glyphs highlighted in mouse face. (These rows
3127 are marked with a mouse_face_p flag.) If WINDOW
3128 indeed has some glyphs highlighted in mouse face, signal to
3129 frame's up-to-date hook that mouse highlight was overwritten,
3130 so that it will arrange for redisplaying the highlight. */
3131 if (EQ (hlinfo->mouse_face_window, window))
3132 reset_mouse_highlight (hlinfo);
3134 free_window_matrices (r);
3136 fset_redisplay (f);
3137 Vwindow_list = Qnil;
3138 FRAME_WINDOW_SIZES_CHANGED (f) = true;
3139 bool resize_failed = false;
3141 if (!WINDOW_LEAF_P (w))
3143 /* Resize child windows vertically. */
3144 XSETINT (delta, r->pixel_height - w->pixel_height);
3145 w->pixel_top = r->pixel_top;
3146 w->top_line = r->top_line;
3147 resize_root_window (window, delta, Qnil, Qnil, Qt);
3148 if (window_resize_check (w, false))
3150 window_resize_apply (w, false);
3151 window_pixel_to_total (w->frame, Qnil);
3153 else
3155 resize_root_window (window, delta, Qnil, Qt, Qt);
3156 if (window_resize_check (w, false))
3158 window_resize_apply (w, false);
3159 window_pixel_to_total (w->frame, Qnil);
3161 else
3162 resize_failed = true;
3165 /* Resize child windows horizontally. */
3166 if (!resize_failed)
3168 w->left_col = r->left_col;
3169 w->pixel_left = r->pixel_left;
3170 XSETINT (delta, r->pixel_width - w->pixel_width);
3171 resize_root_window (window, delta, Qt, Qnil, Qt);
3172 if (window_resize_check (w, true))
3174 window_resize_apply (w, true);
3175 window_pixel_to_total (w->frame, Qt);
3177 else
3179 resize_root_window (window, delta, Qt, Qt, Qt);
3180 if (window_resize_check (w, true))
3182 window_resize_apply (w, true);
3183 window_pixel_to_total (w->frame, Qt);
3185 else
3186 resize_failed = true;
3190 if (resize_failed)
3191 /* Play safe, if we still can ... */
3193 window = swindow;
3194 w = XWINDOW (window);
3198 /* Cleanly unlink WINDOW from window-tree. */
3199 if (!NILP (w->prev))
3200 /* Get SIBLING above (on the left of) WINDOW. */
3202 sibling = w->prev;
3203 s = XWINDOW (sibling);
3204 wset_next (s, w->next);
3205 if (!NILP (s->next))
3206 wset_prev (XWINDOW (s->next), sibling);
3208 else
3209 /* Get SIBLING below (on the right of) WINDOW. */
3211 sibling = w->next;
3212 s = XWINDOW (sibling);
3213 wset_prev (s, Qnil);
3214 wset_combination (XWINDOW (w->parent),
3215 XWINDOW (w->parent)->horizontal, sibling);
3218 /* Delete ROOT and all child windows of ROOT. */
3219 if (WINDOWP (r->contents))
3221 delete_all_child_windows (r->contents);
3222 wset_combination (r, false, Qnil);
3225 replace_window (root, window, true);
3227 /* This must become SWINDOW anyway ....... */
3228 if (BUFFERP (w->contents) && !resize_failed)
3230 /* Try to minimize scrolling, by setting the window start to the
3231 point will cause the text at the old window start to be at the
3232 same place on the frame. But don't try to do this if the
3233 window start is outside the visible portion (as might happen
3234 when the display is not current, due to typeahead). */
3235 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
3236 if (new_top != top
3237 && startpos >= BUF_BEGV (XBUFFER (w->contents))
3238 && startpos <= BUF_ZV (XBUFFER (w->contents)))
3240 struct position pos;
3241 struct buffer *obuf = current_buffer;
3243 Fset_buffer (w->contents);
3244 /* This computation used to temporarily move point, but that
3245 can have unwanted side effects due to text properties. */
3246 pos = *vmotion (startpos, startbyte, -top, w);
3248 set_marker_both (w->start, w->contents, pos.bufpos, pos.bytepos);
3249 w->window_end_valid = false;
3250 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
3251 || FETCH_BYTE (pos.bytepos - 1) == '\n');
3252 /* We need to do this, so that the window-scroll-functions
3253 get called. */
3254 w->optional_new_start = true;
3256 set_buffer_internal (obuf);
3260 adjust_frame_glyphs (f);
3261 unblock_input ();
3263 run_window_configuration_change_hook (f);
3265 return Qnil;
3269 void
3270 replace_buffer_in_windows (Lisp_Object buffer)
3272 call1 (Qreplace_buffer_in_windows, buffer);
3275 /* If BUFFER is shown in a window, safely replace it with some other
3276 buffer in all windows of all frames, even those on other keyboards. */
3278 void
3279 replace_buffer_in_windows_safely (Lisp_Object buffer)
3281 if (buffer_window_count (XBUFFER (buffer)))
3283 Lisp_Object tail, frame;
3285 /* A single call to window_loop won't do the job because it only
3286 considers frames on the current keyboard. So loop manually over
3287 frames, and handle each one. */
3288 FOR_EACH_FRAME (tail, frame)
3289 window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, true, frame);
3293 /* The following three routines are needed for running a window's
3294 configuration change hook. */
3295 static void
3296 run_funs (Lisp_Object funs)
3298 for (; CONSP (funs); funs = XCDR (funs))
3299 if (!EQ (XCAR (funs), Qt))
3300 call0 (XCAR (funs));
3303 static void
3304 select_window_norecord (Lisp_Object window)
3306 if (WINDOW_LIVE_P (window))
3307 Fselect_window (window, Qt);
3310 static void
3311 select_frame_norecord (Lisp_Object frame)
3313 if (FRAME_LIVE_P (XFRAME (frame)))
3314 Fselect_frame (frame, Qt);
3317 void
3318 run_window_configuration_change_hook (struct frame *f)
3320 ptrdiff_t count = SPECPDL_INDEX ();
3321 Lisp_Object frame, global_wcch
3322 = Fdefault_value (Qwindow_configuration_change_hook);
3323 XSETFRAME (frame, f);
3325 if (NILP (Vrun_hooks)
3326 || !(f->can_x_set_window_size)
3327 || !(f->after_make_frame))
3328 return;
3330 /* Use the right buffer. Matters when running the local hooks. */
3331 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3333 record_unwind_current_buffer ();
3334 Fset_buffer (Fwindow_buffer (Qnil));
3337 if (SELECTED_FRAME () != f)
3339 record_unwind_protect (select_frame_norecord, selected_frame);
3340 select_frame_norecord (frame);
3343 /* Look for buffer-local values. */
3345 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3346 for (; CONSP (windows); windows = XCDR (windows))
3348 Lisp_Object window = XCAR (windows);
3349 Lisp_Object buffer = Fwindow_buffer (window);
3350 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3351 buffer)))
3353 ptrdiff_t inner_count = SPECPDL_INDEX ();
3354 record_unwind_protect (select_window_norecord, selected_window);
3355 select_window_norecord (window);
3356 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3357 buffer));
3358 unbind_to (inner_count, Qnil);
3363 run_funs (global_wcch);
3364 unbind_to (count, Qnil);
3367 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
3368 Srun_window_configuration_change_hook, 0, 1, 0,
3369 doc: /* Run `window-configuration-change-hook' for FRAME.
3370 If FRAME is omitted or nil, it defaults to the selected frame. */)
3371 (Lisp_Object frame)
3373 run_window_configuration_change_hook (decode_live_frame (frame));
3374 return Qnil;
3377 DEFUN ("run-window-scroll-functions", Frun_window_scroll_functions,
3378 Srun_window_scroll_functions, 0, 1, 0,
3379 doc: /* Run `window-scroll-functions' for WINDOW.
3380 If WINDOW is omitted or nil, it defaults to the selected window. */)
3381 (Lisp_Object window)
3383 if (! NILP (Vwindow_scroll_functions))
3384 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3385 Fmarker_position (decode_live_window (window)->start));
3386 return Qnil;
3389 /* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed
3390 to run hooks. See make_frame for a case where it's not allowed.
3391 KEEP_MARGINS_P means that the current margins, fringes, and
3392 scroll-bar settings of the window are not reset from the buffer's
3393 local settings. */
3395 void
3396 set_window_buffer (Lisp_Object window, Lisp_Object buffer,
3397 bool run_hooks_p, bool keep_margins_p)
3399 struct window *w = XWINDOW (window);
3400 struct buffer *b = XBUFFER (buffer);
3401 ptrdiff_t count = SPECPDL_INDEX ();
3402 bool samebuf = EQ (buffer, w->contents);
3404 wset_buffer (w, buffer);
3406 if (EQ (window, selected_window))
3407 bset_last_selected_window (b, window);
3409 /* Let redisplay errors through. */
3410 b->display_error_modiff = 0;
3412 /* Update time stamps of buffer display. */
3413 if (INTEGERP (BVAR (b, display_count)))
3414 bset_display_count (b, make_number (XINT (BVAR (b, display_count)) + 1));
3415 bset_display_time (b, Fcurrent_time ());
3417 w->window_end_pos = 0;
3418 w->window_end_vpos = 0;
3419 w->last_cursor_vpos = 0;
3421 if (!(keep_margins_p && samebuf))
3422 { /* If we're not actually changing the buffer, don't reset hscroll
3423 and vscroll. This case happens for example when called from
3424 change_frame_size_1, where we use a dummy call to
3425 Fset_window_buffer on the frame's selected window (and no
3426 other) just in order to run window-configuration-change-hook
3427 (no longer true since change_frame_size_1 directly calls
3428 run_window_configuration_change_hook). Resetting hscroll and
3429 vscroll here is problematic for things like image-mode and
3430 doc-view-mode since it resets the image's position whenever we
3431 resize the frame. */
3432 w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
3433 w->suspend_auto_hscroll = false;
3434 w->vscroll = 0;
3435 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3436 set_marker_both (w->old_pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3437 set_marker_restricted (w->start,
3438 make_number (b->last_window_start),
3439 buffer);
3440 w->start_at_line_beg = false;
3441 w->force_start = false;
3443 /* Maybe we could move this into the `if' but it's not obviously safe and
3444 I doubt it's worth the trouble. */
3445 wset_redisplay (w);
3446 w->update_mode_line = true;
3448 /* We must select BUFFER to run the window-scroll-functions and to look up
3449 the buffer-local value of Vwindow_point_insertion_type. */
3450 record_unwind_current_buffer ();
3451 Fset_buffer (buffer);
3453 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3454 XMARKER (w->old_pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3456 if (!keep_margins_p)
3458 /* Set left and right marginal area width etc. from buffer. */
3459 set_window_fringes (w, BVAR (b, left_fringe_width),
3460 BVAR (b, right_fringe_width),
3461 BVAR (b, fringes_outside_margins));
3462 set_window_scroll_bars (w, BVAR (b, scroll_bar_width),
3463 BVAR (b, vertical_scroll_bar_type),
3464 BVAR (b, scroll_bar_height),
3465 BVAR (b, horizontal_scroll_bar_type));
3466 set_window_margins (w, BVAR (b, left_margin_cols),
3467 BVAR (b, right_margin_cols));
3468 apply_window_adjustment (w);
3471 if (run_hooks_p)
3473 if (! NILP (Vwindow_scroll_functions))
3474 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3475 Fmarker_position (w->start));
3476 if (!samebuf)
3477 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3480 unbind_to (count, Qnil);
3483 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3484 doc: /* Make WINDOW display BUFFER-OR-NAME.
3485 WINDOW must be a live window and defaults to the selected one.
3486 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
3488 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
3489 display margins, fringe widths, and scroll bar settings are preserved;
3490 the default is to reset these from the local settings for BUFFER-OR-NAME
3491 or the frame defaults. Return nil.
3493 This function throws an error when WINDOW is strongly dedicated to its
3494 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3495 already display BUFFER-OR-NAME.
3497 This function runs `window-scroll-functions' before running
3498 `window-configuration-change-hook'. */)
3499 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3501 register Lisp_Object tem, buffer;
3502 register struct window *w = decode_live_window (window);
3504 XSETWINDOW (window, w);
3505 buffer = Fget_buffer (buffer_or_name);
3506 CHECK_BUFFER (buffer);
3507 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3508 error ("Attempt to display deleted buffer");
3510 tem = w->contents;
3511 if (NILP (tem))
3512 error ("Window is deleted");
3513 else
3515 if (!EQ (tem, buffer))
3517 if (EQ (w->dedicated, Qt))
3518 /* WINDOW is strongly dedicated to its buffer, signal an
3519 error. */
3520 error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
3521 else
3522 /* WINDOW is weakly dedicated to its buffer, reset
3523 dedication. */
3524 wset_dedicated (w, Qnil);
3526 call1 (Qrecord_window_buffer, window);
3529 unshow_buffer (w);
3532 set_window_buffer (window, buffer, true, !NILP (keep_margins));
3534 return Qnil;
3537 static Lisp_Object
3538 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3540 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3543 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3544 0, 1, 0,
3545 doc: /* Force all windows to be updated on next redisplay.
3546 If optional arg OBJECT is a window, force redisplay of that window only.
3547 If OBJECT is a buffer or buffer name, force redisplay of all windows
3548 displaying that buffer. */)
3549 (Lisp_Object object)
3551 if (NILP (object))
3553 windows_or_buffers_changed = 29;
3554 update_mode_lines = 28;
3555 return Qt;
3558 if (WINDOWP (object))
3560 struct window *w = XWINDOW (object);
3561 mark_window_display_accurate (object, false);
3562 w->update_mode_line = true;
3563 if (BUFFERP (w->contents))
3564 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
3565 update_mode_lines = 29;
3566 return Qt;
3569 if (STRINGP (object))
3570 object = Fget_buffer (object);
3571 if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))
3572 && buffer_window_count (XBUFFER (object)))
3574 /* If buffer is live and shown in at least one window, find
3575 all windows showing this buffer and force update of them. */
3576 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, false, Qvisible);
3577 return NILP (object) ? Qnil : Qt;
3580 /* If nothing suitable was found, just return.
3581 We could signal an error, but this feature will typically be used
3582 asynchronously in timers or process sentinels, so we don't. */
3583 return Qnil;
3586 /* Obsolete since 24.3. */
3587 void
3588 temp_output_buffer_show (register Lisp_Object buf)
3590 register struct buffer *old = current_buffer;
3591 register Lisp_Object window;
3592 register struct window *w;
3594 bset_directory (XBUFFER (buf), BVAR (current_buffer, directory));
3596 Fset_buffer (buf);
3597 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3598 BEGV = BEG;
3599 ZV = Z;
3600 SET_PT (BEG);
3601 set_buffer_internal (old);
3603 if (!NILP (Vtemp_buffer_show_function))
3604 call1 (Vtemp_buffer_show_function, buf);
3605 else if (WINDOW_LIVE_P (window = display_buffer (buf, Qnil, Qnil)))
3607 if (!EQ (XWINDOW (window)->frame, selected_frame))
3608 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3609 Vminibuf_scroll_window = window;
3610 w = XWINDOW (window);
3611 w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
3612 w->suspend_auto_hscroll = false;
3613 set_marker_restricted_both (w->start, buf, BEG, BEG);
3614 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3615 set_marker_restricted_both (w->old_pointm, buf, BEG, BEG);
3617 /* Run temp-buffer-show-hook, with the chosen window selected
3618 and its buffer current. */
3620 ptrdiff_t count = SPECPDL_INDEX ();
3621 Lisp_Object prev_window, prev_buffer;
3622 prev_window = selected_window;
3623 XSETBUFFER (prev_buffer, old);
3625 /* Select the window that was chosen, for running the hook.
3626 Note: Both Fselect_window and select_window_norecord may
3627 set-buffer to the buffer displayed in the window,
3628 so we need to save the current buffer. --stef */
3629 record_unwind_protect (restore_buffer, prev_buffer);
3630 record_unwind_protect (select_window_norecord, prev_window);
3631 Fselect_window (window, Qt);
3632 Fset_buffer (w->contents);
3633 run_hook (Qtemp_buffer_show_hook);
3634 unbind_to (count, Qnil);
3639 /* Allocate basically initialized window. */
3641 static struct window *
3642 allocate_window (void)
3644 return ALLOCATE_ZEROED_PSEUDOVECTOR
3645 (struct window, current_matrix, PVEC_WINDOW);
3648 /* Make new window, have it replace WINDOW in window-tree, and make
3649 WINDOW its only vertical child (HORFLAG means make WINDOW its only
3650 horizontal child). */
3651 static void
3652 make_parent_window (Lisp_Object window, bool horflag)
3654 Lisp_Object parent;
3655 register struct window *o, *p;
3657 o = XWINDOW (window);
3658 p = allocate_window ();
3659 memcpy ((char *) p + sizeof (struct vectorlike_header),
3660 (char *) o + sizeof (struct vectorlike_header),
3661 word_size * VECSIZE (struct window));
3662 /* P's buffer slot may change from nil to a buffer... */
3663 adjust_window_count (p, 1);
3664 XSETWINDOW (parent, p);
3666 p->sequence_number = ++sequence_number;
3668 replace_window (window, parent, true);
3670 wset_next (o, Qnil);
3671 wset_prev (o, Qnil);
3672 wset_parent (o, parent);
3673 /* ...but now P becomes an internal window. */
3674 wset_start (p, Qnil);
3675 wset_pointm (p, Qnil);
3676 wset_old_pointm (p, Qnil);
3677 wset_buffer (p, Qnil);
3678 wset_combination (p, horflag, window);
3679 wset_combination_limit (p, Qnil);
3680 wset_window_parameters (p, Qnil);
3683 /* Make new window from scratch. */
3684 Lisp_Object
3685 make_window (void)
3687 Lisp_Object window;
3688 register struct window *w;
3690 w = allocate_window ();
3691 /* Initialize Lisp data. Note that allocate_window initializes all
3692 Lisp data to nil, so do it only for slots which should not be nil. */
3693 wset_normal_lines (w, make_float (1.0));
3694 wset_normal_cols (w, make_float (1.0));
3695 wset_new_total (w, make_number (0));
3696 wset_new_normal (w, make_number (0));
3697 wset_new_pixel (w, make_number (0));
3698 wset_start (w, Fmake_marker ());
3699 wset_pointm (w, Fmake_marker ());
3700 wset_old_pointm (w, Fmake_marker ());
3701 wset_vertical_scroll_bar_type (w, Qt);
3702 wset_horizontal_scroll_bar_type (w, Qt);
3703 /* These Lisp fields are marked specially so they're not set to nil by
3704 allocate_window. */
3705 wset_prev_buffers (w, Qnil);
3706 wset_next_buffers (w, Qnil);
3708 /* Initialize non-Lisp data. Note that allocate_window zeroes out all
3709 non-Lisp data, so do it only for slots which should not be zero. */
3710 w->nrows_scale_factor = w->ncols_scale_factor = 1;
3711 w->left_fringe_width = w->right_fringe_width = -1;
3712 w->mode_line_height = w->header_line_height = -1;
3713 #ifdef HAVE_WINDOW_SYSTEM
3714 w->phys_cursor_type = NO_CURSOR;
3715 w->phys_cursor_width = -1;
3716 #endif
3717 w->sequence_number = ++sequence_number;
3718 w->scroll_bar_width = -1;
3719 w->scroll_bar_height = -1;
3720 w->column_number_displayed = -1;
3721 /* Reset window_list. */
3722 Vwindow_list = Qnil;
3723 /* Return window. */
3724 XSETWINDOW (window, w);
3725 return window;
3728 DEFUN ("set-window-new-pixel", Fset_window_new_pixel, Sset_window_new_pixel, 2, 3, 0,
3729 doc: /* Set new pixel size of WINDOW to SIZE.
3730 WINDOW must be a valid window and defaults to the selected one.
3731 Return SIZE.
3733 Optional argument ADD non-nil means add SIZE to the new pixel size of
3734 WINDOW and return the sum.
3736 The new pixel size of WINDOW, if valid, will be shortly installed as
3737 WINDOW's pixel height (see `window-pixel-height') or pixel width (see
3738 `window-pixel-width').
3740 Note: This function does not operate on any child windows of WINDOW. */)
3741 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3743 struct window *w = decode_valid_window (window);
3744 EMACS_INT size_min = NILP (add) ? 0 : - XINT (w->new_pixel);
3745 EMACS_INT size_max = size_min + min (INT_MAX, MOST_POSITIVE_FIXNUM);
3747 CHECK_RANGED_INTEGER (size, size_min, size_max);
3748 if (NILP (add))
3749 wset_new_pixel (w, size);
3750 else
3751 wset_new_pixel (w, make_number (XINT (w->new_pixel) + XINT (size)));
3753 return w->new_pixel;
3756 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
3757 doc: /* Set new total size of WINDOW to SIZE.
3758 WINDOW must be a valid window and defaults to the selected one.
3759 Return SIZE.
3761 Optional argument ADD non-nil means add SIZE to the new total size of
3762 WINDOW and return the sum.
3764 The new total size of WINDOW, if valid, will be shortly installed as
3765 WINDOW's total height (see `window-total-height') or total width (see
3766 `window-total-width').
3768 Note: This function does not operate on any child windows of WINDOW. */)
3769 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3771 struct window *w = decode_valid_window (window);
3773 CHECK_NUMBER (size);
3774 if (NILP (add))
3775 wset_new_total (w, size);
3776 else
3777 wset_new_total (w, make_number (XINT (w->new_total) + XINT (size)));
3779 return w->new_total;
3782 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
3783 doc: /* Set new normal size of WINDOW to SIZE.
3784 WINDOW must be a valid window and defaults to the selected one.
3785 Return SIZE.
3787 The new normal size of WINDOW, if valid, will be shortly installed as
3788 WINDOW's normal size (see `window-normal-size').
3790 Note: This function does not operate on any child windows of WINDOW. */)
3791 (Lisp_Object window, Lisp_Object size)
3793 wset_new_normal (decode_valid_window (window), size);
3794 return size;
3797 /* Return true if setting w->pixel_height (w->pixel_width if HORFLAG)
3798 to w->new_pixel would result in correct heights (widths)
3799 for window W and recursively all child windows of W.
3801 Note: This function does not check any of `window-fixed-size-p',
3802 `window-min-height' or `window-min-width'. It does check that window
3803 sizes do not drop below one line (two columns). */
3804 static bool
3805 window_resize_check (struct window *w, bool horflag)
3807 struct frame *f = XFRAME (w->frame);
3808 struct window *c;
3810 if (WINDOW_VERTICAL_COMBINATION_P (w))
3811 /* W is a vertical combination. */
3813 c = XWINDOW (w->contents);
3814 if (horflag)
3815 /* All child windows of W must have the same width as W. */
3817 while (c)
3819 if (XINT (c->new_pixel) != XINT (w->new_pixel)
3820 || !window_resize_check (c, horflag))
3821 return false;
3823 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3826 return true;
3828 else
3829 /* The sum of the heights of the child windows of W must equal
3830 W's height. */
3832 int remaining_pixels = XINT (w->new_pixel);
3834 while (c)
3836 if (!window_resize_check (c, horflag))
3837 return false;
3839 remaining_pixels -= XINT (c->new_pixel);
3840 if (remaining_pixels < 0)
3841 return false;
3842 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3845 return remaining_pixels == 0;
3848 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3849 /* W is a horizontal combination. */
3851 c = XWINDOW (w->contents);
3852 if (horflag)
3853 /* The sum of the widths of the child windows of W must equal W's
3854 width. */
3856 int remaining_pixels = XINT (w->new_pixel);
3858 while (c)
3860 if (!window_resize_check (c, horflag))
3861 return false;
3863 remaining_pixels -= XINT (c->new_pixel);
3864 if (remaining_pixels < 0)
3865 return false;
3866 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3869 return remaining_pixels == 0;
3871 else
3872 /* All child windows of W must have the same height as W. */
3874 while (c)
3876 if (XINT (c->new_pixel) != XINT (w->new_pixel)
3877 || !window_resize_check (c, horflag))
3878 return false;
3880 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3883 return true;
3886 else
3887 /* A leaf window. Make sure it's not too small. The following
3888 hardcodes the values of `window-safe-min-width' (2) and
3889 `window-safe-min-height' (1) which are defined in window.el. */
3890 return (XINT (w->new_pixel) >= (horflag
3891 ? (2 * FRAME_COLUMN_WIDTH (f))
3892 : FRAME_LINE_HEIGHT (f)));
3896 /* Set w->pixel_height (w->pixel_width if HORFLAG) to
3897 w->new_pixel for window W and recursively all child windows of W.
3898 Also calculate and assign the new vertical (horizontal) pixel start
3899 positions of each of these windows.
3901 This function does not perform any error checks. Make sure you have
3902 run window_resize_check on W before applying this function. */
3903 static void
3904 window_resize_apply (struct window *w, bool horflag)
3906 struct window *c;
3907 int edge;
3908 int unit = (horflag
3909 ? FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w))
3910 : FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
3912 /* Note: Assigning new_normal requires that the new total size of the
3913 parent window has been set *before*. */
3914 if (horflag)
3916 w->pixel_width = XFASTINT (w->new_pixel);
3917 w->total_cols = w->pixel_width / unit;
3918 if (NUMBERP (w->new_normal))
3919 wset_normal_cols (w, w->new_normal);
3921 edge = w->pixel_left;
3923 else
3925 w->pixel_height = XFASTINT (w->new_pixel);
3926 w->total_lines = w->pixel_height / unit;
3927 if (NUMBERP (w->new_normal))
3928 wset_normal_lines (w, w->new_normal);
3930 edge = w->pixel_top;
3933 if (WINDOW_VERTICAL_COMBINATION_P (w))
3934 /* W is a vertical combination. */
3936 c = XWINDOW (w->contents);
3937 while (c)
3939 if (horflag)
3941 c->pixel_left = edge;
3942 c->left_col = edge / unit;
3944 else
3946 c->pixel_top = edge;
3947 c->top_line = edge / unit;
3949 window_resize_apply (c, horflag);
3950 if (!horflag)
3951 edge = edge + c->pixel_height;
3953 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3956 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3957 /* W is a horizontal combination. */
3959 c = XWINDOW (w->contents);
3960 while (c)
3962 if (horflag)
3964 c->pixel_left = edge;
3965 c->left_col = edge / unit;
3967 else
3969 c->pixel_top = edge;
3970 c->top_line = edge / unit;
3973 window_resize_apply (c, horflag);
3974 if (horflag)
3975 edge = edge + c->pixel_width;
3977 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3980 else
3981 /* Bug#15957. */
3982 w->window_end_valid = false;
3986 /* Set w->total_lines (w->total_cols if HORFLAG) to
3987 w->new_total for window W and recursively all child windows of W.
3988 Also calculate and assign the new vertical (horizontal) start
3989 positions of each of these windows. */
3990 static void
3991 window_resize_apply_total (struct window *w, bool horflag)
3993 struct window *c;
3994 int edge;
3996 /* Note: Assigning new_normal requires that the new total size of the
3997 parent window has been set *before*. */
3998 if (horflag)
4000 w->total_cols = XFASTINT (w->new_total);
4001 edge = w->left_col;
4003 else
4005 w->total_lines = XFASTINT (w->new_total);
4006 edge = w->top_line;
4009 if (WINDOW_VERTICAL_COMBINATION_P (w))
4010 /* W is a vertical combination. */
4012 c = XWINDOW (w->contents);
4013 while (c)
4015 if (horflag)
4016 c->left_col = edge;
4017 else
4018 c->top_line = edge;
4020 window_resize_apply_total (c, horflag);
4021 if (!horflag)
4022 edge = edge + c->total_lines;
4024 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4027 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
4028 /* W is a horizontal combination. */
4030 c = XWINDOW (w->contents);
4031 while (c)
4033 if (horflag)
4034 c->left_col = edge;
4035 else
4036 c->top_line = edge;
4038 window_resize_apply_total (c, horflag);
4039 if (horflag)
4040 edge = edge + c->total_cols;
4042 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4047 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 0, 2, 0,
4048 doc: /* Apply requested size values for window-tree of FRAME.
4049 If FRAME is omitted or nil, it defaults to the selected frame.
4051 Optional argument HORIZONTAL omitted or nil means apply requested
4052 height values. HORIZONTAL non-nil means apply requested width values.
4054 The requested size values are those set by `set-window-new-pixel' and
4055 `set-window-new-normal'. This function checks whether the requested
4056 values sum up to a valid window layout, recursively assigns the new
4057 sizes of all child windows and calculates and assigns the new start
4058 positions of these windows.
4060 Return t if the requested values have been applied correctly, nil
4061 otherwise.
4063 Note: This function does not check any of `window-fixed-size-p',
4064 `window-min-height' or `window-min-width'. All these checks have to
4065 be applied on the Elisp level. */)
4066 (Lisp_Object frame, Lisp_Object horizontal)
4068 struct frame *f = decode_live_frame (frame);
4069 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
4070 bool horflag = !NILP (horizontal);
4072 if (!window_resize_check (r, horflag)
4073 || (XINT (r->new_pixel)
4074 != (horflag ? r->pixel_width : r->pixel_height)))
4075 return Qnil;
4077 block_input ();
4078 window_resize_apply (r, horflag);
4080 fset_redisplay (f);
4081 FRAME_WINDOW_SIZES_CHANGED (f) = true;
4083 adjust_frame_glyphs (f);
4084 unblock_input ();
4086 return Qt;
4090 DEFUN ("window-resize-apply-total", Fwindow_resize_apply_total, Swindow_resize_apply_total, 0, 2, 0,
4091 doc: /* Apply requested total size values for window-tree of FRAME.
4092 If FRAME is omitted or nil, it defaults to the selected frame.
4094 This function does not assign pixel or normal size values. You should
4095 have run `window-resize-apply' before running this.
4097 Optional argument HORIZONTAL omitted or nil means apply requested
4098 height values. HORIZONTAL non-nil means apply requested width
4099 values. */)
4100 (Lisp_Object frame, Lisp_Object horizontal)
4102 struct frame *f = decode_live_frame (frame);
4103 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
4105 block_input ();
4106 /* Necessary when deleting the top-/or leftmost window. */
4107 r->left_col = 0;
4108 r->top_line = FRAME_TOP_MARGIN (f);
4109 window_resize_apply_total (r, !NILP (horizontal));
4110 /* Handle the mini window. */
4111 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
4113 struct window *m = XWINDOW (f->minibuffer_window);
4115 if (NILP (horizontal))
4117 m->top_line = r->top_line + r->total_lines;
4118 m->total_lines = XFASTINT (m->new_total);
4120 else
4121 m->total_cols = XFASTINT (m->new_total);
4124 unblock_input ();
4126 return Qt;
4130 /* Resize frame F's windows when number of lines of F is set to SIZE.
4131 HORFLAG means resize windows when number of columns of F is set to
4132 SIZE. PIXELWISE means to interpret SIZE as pixels. */
4133 void
4134 resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
4136 Lisp_Object root = f->root_window;
4137 struct window *r = XWINDOW (root);
4138 Lisp_Object mini = f->minibuffer_window;
4139 struct window *m;
4140 /* old_size is the old size of the frame's root window. */
4141 int old_size = horflag ? r->total_cols : r->total_lines;
4142 int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
4143 int old_pixel_top = r->pixel_top;
4144 /* new_size is the new size of the frame's root window. */
4145 int new_size, new_pixel_size;
4146 int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
4148 /* Don't let the size drop below one unit. This is more comforting
4149 when we are called from x_set_tool_bar_lines since the latter may
4150 have implicitly given us a zero or negative height. */
4151 if (pixelwise)
4153 /* Note: This does not include the size for internal borders
4154 since these are not part of the frame's text area. */
4155 new_pixel_size = max (horflag
4156 ? size
4157 : (size
4158 - ((FRAME_HAS_MINIBUF_P (f)
4159 && !FRAME_MINIBUF_ONLY_P (f))
4160 ? FRAME_LINE_HEIGHT (f) : 0)),
4161 unit);
4162 new_size = new_pixel_size / unit;
4164 else
4166 new_size = max (size - (!horflag
4167 && FRAME_HAS_MINIBUF_P (f)
4168 && !FRAME_MINIBUF_ONLY_P (f)),
4170 new_pixel_size = new_size * unit;
4173 r->top_line = FRAME_TOP_MARGIN (f);
4174 r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
4176 if (new_pixel_size == old_pixel_size
4177 && r->pixel_top == old_pixel_top)
4179 else if (WINDOW_LEAF_P (r))
4180 /* For a leaf root window just set the size. */
4181 if (horflag)
4183 r->total_cols = new_size;
4184 r->pixel_width = new_pixel_size;
4186 else
4188 r->total_lines = new_size;
4189 r->pixel_height = new_pixel_size;
4191 else
4193 Lisp_Object delta;
4195 if (pixelwise)
4196 XSETINT (delta, new_pixel_size - old_pixel_size);
4197 else
4198 XSETINT (delta, new_size - old_size);
4200 /* Try a "normal" resize first. */
4201 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil,
4202 pixelwise ? Qt : Qnil);
4203 if (window_resize_check (r, horflag)
4204 && new_pixel_size == XINT (r->new_pixel))
4206 window_resize_apply (r, horflag);
4207 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4209 else
4211 /* Try with "reasonable" minimum sizes next. */
4212 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt,
4213 pixelwise ? Qt : Qnil);
4214 if (window_resize_check (r, horflag)
4215 && new_pixel_size == XINT (r->new_pixel))
4217 window_resize_apply (r, horflag);
4218 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4219 #if false /* Let's try without safe sizes and/or killing other windows. */
4221 else
4223 /* Finally, try with "safe" minimum sizes. */
4224 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe,
4225 pixelwise ? Qt : Qnil);
4226 if (window_resize_check (r, horflag)
4227 && new_pixel_size == XINT (r->new_pixel))
4229 window_resize_apply (r, horflag);
4230 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4232 else
4234 /* We lost. Delete all windows but the frame's
4235 selected one. */
4236 root = f->selected_window;
4237 Fdelete_other_windows_internal (root, Qnil);
4238 if (horflag)
4240 XWINDOW (root)->total_cols = new_size;
4241 XWINDOW (root)->pixel_width = new_pixel_size;
4243 else
4245 XWINDOW (root)->total_lines = new_size;
4246 XWINDOW (root)->pixel_height = new_pixel_size;
4249 #endif /* false */
4254 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
4256 m = XWINDOW (mini);
4257 if (horflag)
4259 m->total_cols = size;
4260 m->pixel_width = new_pixel_size;
4262 else
4264 /* Are we sure we always want 1 line here? */
4265 m->total_lines = 1;
4266 m->pixel_height = FRAME_LINE_HEIGHT (f);
4267 m->top_line = r->top_line + r->total_lines;
4268 m->pixel_top = r->pixel_top + r->pixel_height;
4272 fset_redisplay (f);
4276 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
4277 doc: /* Split window OLD.
4278 Second argument PIXEL-SIZE specifies the number of pixels of the
4279 new window. It must be a positive integer.
4281 Third argument SIDE nil (or `below') specifies that the new window shall
4282 be located below WINDOW. SIDE `above' means the new window shall be
4283 located above WINDOW. In both cases PIXEL-SIZE specifies the pixel
4284 height of the new window including space reserved for the mode and/or
4285 header line.
4287 SIDE t (or `right') specifies that the new window shall be located on
4288 the right side of WINDOW. SIDE `left' means the new window shall be
4289 located on the left of WINDOW. In both cases PIXEL-SIZE specifies the
4290 width of the new window including space reserved for fringes and the
4291 scrollbar or a divider column.
4293 Fourth argument NORMAL-SIZE specifies the normal size of the new window
4294 according to the SIDE argument.
4296 The new pixel and normal sizes of all involved windows must have been
4297 set correctly. See the code of `split-window' for how this is done. */)
4298 (Lisp_Object old, Lisp_Object pixel_size, Lisp_Object side, Lisp_Object normal_size)
4300 /* OLD (*o) is the window we have to split. (*p) is either OLD's
4301 parent window or an internal window we have to install as OLD's new
4302 parent. REFERENCE (*r) must denote a live window, or is set to OLD
4303 provided OLD is a leaf window, or to the frame's selected window.
4304 NEW (*n) is the new window created with some parameters taken from
4305 REFERENCE (*r). */
4306 Lisp_Object new, frame, reference;
4307 struct window *o, *p, *n, *r, *c;
4308 struct frame *f;
4309 bool horflag
4310 /* HORFLAG is true when we split side-by-side, false otherwise. */
4311 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
4313 CHECK_WINDOW (old);
4314 o = XWINDOW (old);
4315 frame = WINDOW_FRAME (o);
4316 f = XFRAME (frame);
4318 CHECK_NUMBER (pixel_size);
4319 EMACS_INT total_size
4320 = XINT (pixel_size) / (horflag
4321 ? FRAME_COLUMN_WIDTH (f)
4322 : FRAME_LINE_HEIGHT (f));
4324 /* Set combination_limit if we have to make a new parent window.
4325 We do that if either `window-combination-limit' is t, or OLD has no
4326 parent, or OLD is ortho-combined. */
4327 bool combination_limit
4328 = (EQ (Vwindow_combination_limit, Qt)
4329 || NILP (o->parent)
4330 || (horflag
4331 ? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
4332 : WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent))));
4334 /* We need a live reference window to initialize some parameters. */
4335 if (WINDOW_LIVE_P (old))
4336 /* OLD is live, use it as reference window. */
4337 reference = old;
4338 else
4339 /* Use the frame's selected window as reference window. */
4340 reference = FRAME_SELECTED_WINDOW (f);
4341 r = XWINDOW (reference);
4343 /* The following bugs are caught by `split-window'. */
4344 if (MINI_WINDOW_P (o))
4345 error ("Attempt to split minibuffer window");
4346 else if (total_size < (horflag ? 2 : 1))
4347 error ("Size of new window too small (after split)");
4348 else if (!combination_limit && !NILP (Vwindow_combination_resize))
4349 /* `window-combination-resize' non-nil means try to resize OLD's siblings
4350 proportionally. */
4352 p = XWINDOW (o->parent);
4353 /* Temporarily pretend we split the parent window. */
4354 wset_new_pixel
4355 (p, make_number ((horflag ? p->pixel_width : p->pixel_height)
4356 - XINT (pixel_size)));
4357 if (!window_resize_check (p, horflag))
4358 error ("Window sizes don't fit");
4359 else
4360 /* Undo the temporary pretension. */
4361 wset_new_pixel (p, make_number (horflag ? p->pixel_width : p->pixel_height));
4363 else
4365 if (!window_resize_check (o, horflag))
4366 error ("Resizing old window failed");
4367 else if (XINT (pixel_size) + XINT (o->new_pixel)
4368 != (horflag ? o->pixel_width : o->pixel_height))
4369 error ("Sum of sizes of old and new window don't fit");
4372 /* This is our point of no return. */
4373 if (combination_limit)
4375 /* Save the old value of o->normal_cols/lines. It gets corrupted
4376 by make_parent_window and we need it below for assigning it to
4377 p->new_normal. */
4378 Lisp_Object new_normal
4379 = horflag ? o->normal_cols : o->normal_lines;
4381 make_parent_window (old, horflag);
4382 p = XWINDOW (o->parent);
4383 if (EQ (Vwindow_combination_limit, Qt))
4384 /* Store t in the new parent's combination_limit slot to avoid
4385 that its children get merged into another window. */
4386 wset_combination_limit (p, Qt);
4387 /* These get applied below. */
4388 wset_new_pixel
4389 (p, make_number (horflag ? o->pixel_width : o->pixel_height));
4390 wset_new_total
4391 (p, make_number (horflag ? o->total_cols : o->total_lines));
4392 wset_new_normal (p, new_normal);
4394 else
4395 p = XWINDOW (o->parent);
4397 fset_redisplay (f);
4398 FRAME_WINDOW_SIZES_CHANGED (f) = true;
4399 new = make_window ();
4400 n = XWINDOW (new);
4401 wset_frame (n, frame);
4402 wset_parent (n, o->parent);
4404 if (EQ (side, Qabove) || EQ (side, Qleft))
4406 wset_prev (n, o->prev);
4407 if (NILP (n->prev))
4408 wset_combination (p, horflag, new);
4409 else
4410 wset_next (XWINDOW (n->prev), new);
4411 wset_next (n, old);
4412 wset_prev (o, new);
4414 else
4416 wset_next (n, o->next);
4417 if (!NILP (n->next))
4418 wset_prev (XWINDOW (n->next), new);
4419 wset_prev (n, old);
4420 wset_next (o, new);
4423 n->window_end_valid = false;
4424 n->last_cursor_vpos = 0;
4426 /* Get special geometry settings from reference window. */
4427 n->left_margin_cols = r->left_margin_cols;
4428 n->right_margin_cols = r->right_margin_cols;
4429 n->left_fringe_width = r->left_fringe_width;
4430 n->right_fringe_width = r->right_fringe_width;
4431 n->fringes_outside_margins = r->fringes_outside_margins;
4432 n->scroll_bar_width = r->scroll_bar_width;
4433 n->scroll_bar_height = r->scroll_bar_height;
4434 wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
4435 wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type);
4437 /* Directly assign orthogonal coordinates and sizes. */
4438 if (horflag)
4440 n->pixel_top = o->pixel_top;
4441 n->top_line = o->top_line;
4442 n->pixel_height = o->pixel_height;
4443 n->total_lines = o->total_lines;
4445 else
4447 n->pixel_left = o->pixel_left;
4448 n->left_col = o->left_col;
4449 n->pixel_width = o->pixel_width;
4450 n->total_cols = o->total_cols;
4453 /* Iso-coordinates and sizes are assigned by window_resize_apply,
4454 get them ready here. */
4455 wset_new_pixel (n, pixel_size);
4456 EMACS_INT sum = 0;
4457 c = XWINDOW (p->contents);
4458 while (c)
4460 if (c != n)
4461 sum = sum + XINT (c->new_total);
4462 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4464 wset_new_total (n, make_number ((horflag
4465 ? p->total_cols
4466 : p->total_lines)
4467 - sum));
4468 wset_new_normal (n, normal_size);
4470 block_input ();
4471 window_resize_apply (p, horflag);
4472 adjust_frame_glyphs (f);
4473 /* Set buffer of NEW to buffer of reference window. Don't run
4474 any hooks. */
4475 set_window_buffer (new, r->contents, false, true);
4476 unblock_input ();
4478 /* Maybe we should run the scroll functions in Elisp (which already
4479 runs the configuration change hook). */
4480 if (! NILP (Vwindow_scroll_functions))
4481 run_hook_with_args_2 (Qwindow_scroll_functions, new,
4482 Fmarker_position (n->start));
4483 /* Return NEW. */
4484 return new;
4488 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
4489 doc: /* Remove WINDOW from its frame.
4490 WINDOW defaults to the selected window. Return nil.
4491 Signal an error when WINDOW is the only window on its frame. */)
4492 (Lisp_Object window)
4494 Lisp_Object parent, sibling, frame, root;
4495 struct window *w, *p, *s, *r;
4496 struct frame *f;
4497 bool horflag, before_sibling = false;
4499 w = decode_any_window (window);
4500 XSETWINDOW (window, w);
4501 if (NILP (w->contents))
4502 /* It's a no-op to delete an already deleted window. */
4503 return Qnil;
4505 parent = w->parent;
4506 if (NILP (parent))
4507 /* Never delete a minibuffer or frame root window. */
4508 error ("Attempt to delete minibuffer or sole ordinary window");
4509 else if (NILP (w->prev) && NILP (w->next))
4510 /* Rather bow out here, this case should be handled on the Elisp
4511 level. */
4512 error ("Attempt to delete sole window of parent");
4514 p = XWINDOW (parent);
4515 horflag = WINDOW_HORIZONTAL_COMBINATION_P (p);
4517 frame = WINDOW_FRAME (w);
4518 f = XFRAME (frame);
4520 root = FRAME_ROOT_WINDOW (f);
4521 r = XWINDOW (root);
4523 /* Unlink WINDOW from window tree. */
4524 if (NILP (w->prev))
4525 /* Get SIBLING below (on the right of) WINDOW. */
4527 /* before_sibling means WINDOW is the first child of its
4528 parent and thus before the sibling. */
4529 before_sibling = true;
4530 sibling = w->next;
4531 s = XWINDOW (sibling);
4532 wset_prev (s, Qnil);
4533 wset_combination (p, horflag, sibling);
4535 else
4536 /* Get SIBLING above (on the left of) WINDOW. */
4538 sibling = w->prev;
4539 s = XWINDOW (sibling);
4540 wset_next (s, w->next);
4541 if (!NILP (s->next))
4542 wset_prev (XWINDOW (s->next), sibling);
4545 if (window_resize_check (r, horflag)
4546 && (XINT (r->new_pixel)
4547 == (horflag ? r->pixel_width : r->pixel_height)))
4548 /* We can delete WINDOW now. */
4551 /* Block input. */
4552 block_input ();
4553 window_resize_apply (p, horflag);
4554 /* If this window is referred to by the dpyinfo's mouse
4555 highlight, invalidate that slot to be safe (Bug#9904). */
4556 if (!FRAME_INITIAL_P (f))
4558 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
4560 if (EQ (hlinfo->mouse_face_window, window))
4561 hlinfo->mouse_face_window = Qnil;
4564 fset_redisplay (f);
4565 Vwindow_list = Qnil;
4566 FRAME_WINDOW_SIZES_CHANGED (f) = true;
4568 wset_next (w, Qnil); /* Don't delete w->next too. */
4569 free_window_matrices (w);
4571 if (WINDOWP (w->contents))
4573 delete_all_child_windows (w->contents);
4574 wset_combination (w, false, Qnil);
4576 else
4578 unshow_buffer (w);
4579 unchain_marker (XMARKER (w->pointm));
4580 unchain_marker (XMARKER (w->old_pointm));
4581 unchain_marker (XMARKER (w->start));
4582 wset_buffer (w, Qnil);
4585 if (NILP (s->prev) && NILP (s->next))
4586 /* A matrjoshka where SIBLING has become the only child of
4587 PARENT. */
4589 /* Put SIBLING into PARENT's place. */
4590 replace_window (parent, sibling, false);
4591 /* Have SIBLING inherit the following three slot values from
4592 PARENT (the combination_limit slot is not inherited). */
4593 wset_normal_cols (s, p->normal_cols);
4594 wset_normal_lines (s, p->normal_lines);
4595 /* Mark PARENT as deleted. */
4596 wset_combination (p, false, Qnil);
4597 /* Try to merge SIBLING into its new parent. */
4598 recombine_windows (sibling);
4601 adjust_frame_glyphs (f);
4603 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
4604 /* We deleted the frame's selected window. */
4606 /* Use the frame's first window as fallback ... */
4607 Lisp_Object new_selected_window = Fframe_first_window (frame);
4608 /* ... but preferably use its most recently used window. */
4609 Lisp_Object mru_window;
4611 /* `get-mru-window' might fail for some reason so play it safe
4612 - promote the first window _without recording it_ first. */
4613 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4614 Fselect_window (new_selected_window, Qt);
4615 else
4616 fset_selected_window (f, new_selected_window);
4618 unblock_input ();
4620 /* Now look whether `get-mru-window' gets us something. */
4621 mru_window = call1 (Qget_mru_window, frame);
4622 if (WINDOW_LIVE_P (mru_window)
4623 && EQ (XWINDOW (mru_window)->frame, frame))
4624 new_selected_window = mru_window;
4626 /* If all ended up well, we now promote the mru window. */
4627 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4628 Fselect_window (new_selected_window, Qnil);
4629 else
4630 fset_selected_window (f, new_selected_window);
4632 else
4633 unblock_input ();
4635 /* Must be run by the caller:
4636 run_window_configuration_change_hook (f); */
4638 else
4639 /* We failed: Relink WINDOW into window tree. */
4641 if (before_sibling)
4643 wset_prev (s, window);
4644 wset_combination (p, horflag, window);
4646 else
4648 wset_next (s, window);
4649 if (!NILP (w->next))
4650 wset_prev (XWINDOW (w->next), window);
4652 error ("Deletion failed");
4655 return Qnil;
4658 /***********************************************************************
4659 Resizing Mini-Windows
4660 ***********************************************************************/
4662 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
4663 can. */
4664 void
4665 grow_mini_window (struct window *w, int delta, bool pixelwise)
4667 struct frame *f = XFRAME (w->frame);
4668 struct window *r;
4669 Lisp_Object root, height;
4670 int line_height, pixel_height;
4672 eassert (MINI_WINDOW_P (w));
4673 eassert (delta >= 0);
4675 if (delta > 0)
4677 root = FRAME_ROOT_WINDOW (f);
4678 r = XWINDOW (root);
4679 height = call3 (Qwindow_resize_root_window_vertically,
4680 root, make_number (- delta), pixelwise ? Qt : Qnil);
4681 if (INTEGERP (height) && window_resize_check (r, false))
4683 block_input ();
4684 window_resize_apply (r, false);
4686 if (pixelwise)
4688 pixel_height = min (-XINT (height), INT_MAX - w->pixel_height);
4689 line_height = pixel_height / FRAME_LINE_HEIGHT (f);
4691 else
4693 line_height = min (-XINT (height),
4694 ((INT_MAX - w->pixel_height)
4695 / FRAME_LINE_HEIGHT (f)));
4696 pixel_height = line_height * FRAME_LINE_HEIGHT (f);
4699 /* Grow the mini-window. */
4700 w->pixel_top = r->pixel_top + r->pixel_height;
4701 w->top_line = r->top_line + r->total_lines;
4702 /* Make sure the mini-window has always at least one line. */
4703 w->pixel_height = max (w->pixel_height + pixel_height,
4704 FRAME_LINE_HEIGHT (f));
4705 w->total_lines = max (w->total_lines + line_height, 1);
4707 /* Enforce full redisplay of the frame. */
4708 /* FIXME: Shouldn't window--resize-root-window-vertically do it? */
4709 fset_redisplay (f);
4710 adjust_frame_glyphs (f);
4711 unblock_input ();
4716 /* Shrink mini-window W to one line. */
4717 void
4718 shrink_mini_window (struct window *w, bool pixelwise)
4720 struct frame *f = XFRAME (w->frame);
4721 struct window *r;
4722 Lisp_Object root, delta;
4723 EMACS_INT height, unit;
4725 eassert (MINI_WINDOW_P (w));
4727 height = pixelwise ? w->pixel_height : w->total_lines;
4728 unit = pixelwise ? FRAME_LINE_HEIGHT (f) : 1;
4729 if (height > unit)
4731 root = FRAME_ROOT_WINDOW (f);
4732 r = XWINDOW (root);
4733 delta = call3 (Qwindow_resize_root_window_vertically,
4734 root, make_number (height - unit),
4735 pixelwise ? Qt : Qnil);
4736 if (INTEGERP (delta) && window_resize_check (r, false))
4738 block_input ();
4739 window_resize_apply (r, false);
4741 /* Shrink the mini-window. */
4742 w->top_line = r->top_line + r->total_lines;
4743 w->total_lines = 1;
4744 w->pixel_top = r->pixel_top + r->pixel_height;
4745 w->pixel_height = FRAME_LINE_HEIGHT (f);
4746 /* Enforce full redisplay of the frame. */
4747 /* FIXME: Shouldn't window--resize-root-window-vertically do it? */
4748 fset_redisplay (f);
4749 adjust_frame_glyphs (f);
4750 unblock_input ();
4752 /* If the above failed for whatever strange reason we must make a
4753 one window frame here. The same routine will be needed when
4754 shrinking the frame (and probably when making the initial
4755 *scratch* window). For the moment leave things as they are. */
4759 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
4760 doc: /* Resize minibuffer window WINDOW. */)
4761 (Lisp_Object window)
4763 struct window *w = XWINDOW (window);
4764 struct window *r;
4765 struct frame *f;
4766 int height;
4768 CHECK_WINDOW (window);
4769 f = XFRAME (w->frame);
4771 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
4772 error ("Not a valid minibuffer window");
4773 else if (FRAME_MINIBUF_ONLY_P (f))
4774 error ("Cannot resize a minibuffer-only frame");
4776 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4777 height = r->pixel_height + w->pixel_height;
4778 if (window_resize_check (r, false)
4779 && XINT (w->new_pixel) > 0
4780 && height == XINT (r->new_pixel) + XINT (w->new_pixel))
4782 block_input ();
4783 window_resize_apply (r, false);
4785 w->pixel_height = XFASTINT (w->new_pixel);
4786 w->total_lines = w->pixel_height / FRAME_LINE_HEIGHT (f);
4787 w->pixel_top = r->pixel_top + r->pixel_height;
4788 w->top_line = r->top_line + r->total_lines;
4790 fset_redisplay (f);
4791 FRAME_WINDOW_SIZES_CHANGED (f) = true;
4792 adjust_frame_glyphs (f);
4793 unblock_input ();
4794 return Qt;
4796 else
4797 error ("Failed to resize minibuffer window");
4800 /* Mark window cursors off for all windows in the window tree rooted
4801 at W by setting their phys_cursor_on_p flag to zero. Called from
4802 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4803 the frame are cleared. */
4805 void
4806 mark_window_cursors_off (struct window *w)
4808 while (w)
4810 if (WINDOWP (w->contents))
4811 mark_window_cursors_off (XWINDOW (w->contents));
4812 else
4813 w->phys_cursor_on_p = false;
4815 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4820 /* Return number of lines of text (not counting mode lines) in W. */
4823 window_internal_height (struct window *w)
4825 int ht = w->total_lines;
4827 if (!MINI_WINDOW_P (w))
4829 if (!NILP (w->parent)
4830 || WINDOWP (w->contents)
4831 || !NILP (w->next)
4832 || !NILP (w->prev)
4833 || WINDOW_WANTS_MODELINE_P (w))
4834 --ht;
4836 if (WINDOW_WANTS_HEADER_LINE_P (w))
4837 --ht;
4840 return ht;
4844 /************************************************************************
4845 Window Scrolling
4846 ***********************************************************************/
4848 /* Scroll contents of window WINDOW up. If WHOLE, scroll
4849 N screen-fulls, which is defined as the height of the window minus
4850 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4851 instead. Negative values of N mean scroll down. NOERROR
4852 means don't signal an error if we try to move over BEGV or ZV,
4853 respectively. */
4855 static void
4856 window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
4858 ptrdiff_t count = SPECPDL_INDEX ();
4860 immediate_quit = true;
4861 n = clip_to_bounds (INT_MIN, n, INT_MAX);
4863 wset_redisplay (XWINDOW (window));
4865 if (whole && Vfast_but_imprecise_scrolling)
4866 specbind (Qfontification_functions, Qnil);
4868 /* If we must, use the pixel-based version which is much slower than
4869 the line-based one but can handle varying line heights. */
4870 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4871 window_scroll_pixel_based (window, n, whole, noerror);
4872 else
4873 window_scroll_line_based (window, n, whole, noerror);
4875 unbind_to (count, Qnil);
4877 /* Bug#15957. */
4878 XWINDOW (window)->window_end_valid = false;
4879 immediate_quit = false;
4883 /* Implementation of window_scroll that works based on pixel line
4884 heights. See the comment of window_scroll for parameter
4885 descriptions. */
4887 static void
4888 window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror)
4890 struct it it;
4891 struct window *w = XWINDOW (window);
4892 struct text_pos start;
4893 int this_scroll_margin;
4894 /* True if we fiddled the window vscroll field without really scrolling. */
4895 bool vscrolled = false;
4896 int x, y, rtop, rbot, rowh, vpos;
4897 void *itdata = NULL;
4898 int window_total_lines;
4899 int frame_line_height = default_line_pixel_height (w);
4900 bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
4901 Fwindow_old_point (window)));
4903 SET_TEXT_POS_FROM_MARKER (start, w->start);
4904 /* Scrolling a minibuffer window via scroll bar when the echo area
4905 shows long text sometimes resets the minibuffer contents behind
4906 our backs. */
4907 if (CHARPOS (start) > ZV)
4908 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4910 /* If PT is not visible in WINDOW, move back one half of
4911 the screen. Allow PT to be partially visible, otherwise
4912 something like (scroll-down 1) with PT in the line before
4913 the partially visible one would recenter. */
4915 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4917 itdata = bidi_shelve_cache ();
4918 /* Move backward half the height of the window. Performance note:
4919 vmotion used here is about 10% faster, but would give wrong
4920 results for variable height lines. */
4921 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4922 it.current_y = it.last_visible_y;
4923 move_it_vertically_backward (&it, window_box_height (w) / 2);
4925 /* The function move_iterator_vertically may move over more than
4926 the specified y-distance. If it->w is small, e.g. a
4927 mini-buffer window, we may end up in front of the window's
4928 display area. Start displaying at the start of the line
4929 containing PT in this case. */
4930 if (it.current_y <= 0)
4932 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4933 move_it_vertically_backward (&it, 0);
4934 it.current_y = 0;
4937 start = it.current.pos;
4938 bidi_unshelve_cache (itdata, false);
4940 else if (auto_window_vscroll_p)
4942 if (rtop || rbot) /* Partially visible. */
4944 int px;
4945 int dy = frame_line_height;
4946 /* In the below we divide the window box height by the
4947 frame's line height to make the result predictable when
4948 the window box is not an integral multiple of the line
4949 height. This is important to ensure we get back to the
4950 same position when scrolling up, then down. */
4951 if (whole)
4952 dy = max ((window_box_height (w) / dy
4953 - next_screen_context_lines) * dy,
4954 dy);
4955 dy *= n;
4957 if (n < 0)
4959 /* Only vscroll backwards if already vscrolled forwards. */
4960 if (w->vscroll < 0 && rtop > 0)
4962 px = max (0, -w->vscroll - min (rtop, -dy));
4963 Fset_window_vscroll (window, make_number (px), Qt);
4964 return;
4967 if (n > 0)
4969 /* Do vscroll if already vscrolled or only display line. */
4970 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4972 px = max (0, -w->vscroll + min (rbot, dy));
4973 Fset_window_vscroll (window, make_number (px), Qt);
4974 return;
4977 /* Maybe modify window start instead of scrolling. */
4978 if (rbot > 0 || w->vscroll < 0)
4980 ptrdiff_t spos;
4982 Fset_window_vscroll (window, make_number (0), Qt);
4983 /* If there are other text lines above the current row,
4984 move window start to current row. Else to next row. */
4985 if (rbot > 0)
4986 spos = XINT (Fline_beginning_position (Qnil));
4987 else
4988 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4989 set_marker_restricted (w->start, make_number (spos),
4990 w->contents);
4991 w->start_at_line_beg = true;
4992 w->update_mode_line = true;
4993 /* Set force_start so that redisplay_window will run the
4994 window-scroll-functions. */
4995 w->force_start = true;
4996 return;
5000 /* Cancel previous vscroll. */
5001 Fset_window_vscroll (window, make_number (0), Qt);
5004 itdata = bidi_shelve_cache ();
5005 /* If scroll_preserve_screen_position is non-nil, we try to set
5006 point in the same window line as it is now, so get that line. */
5007 if (!NILP (Vscroll_preserve_screen_position))
5009 /* We preserve the goal pixel coordinate across consecutive
5010 calls to scroll-up, scroll-down and other commands that
5011 have the `scroll-command' property. This avoids the
5012 possibility of point becoming "stuck" on a tall line when
5013 scrolling by one line. */
5014 if (window_scroll_pixel_based_preserve_y < 0
5015 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
5016 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
5018 start_display (&it, w, start);
5019 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5020 window_scroll_pixel_based_preserve_y = it.current_y;
5021 window_scroll_pixel_based_preserve_x = it.current_x;
5024 else
5025 window_scroll_pixel_based_preserve_y
5026 = window_scroll_pixel_based_preserve_x = -1;
5028 /* Move iterator it from start the specified distance forward or
5029 backward. The result is the new window start. */
5030 start_display (&it, w, start);
5031 if (whole)
5033 ptrdiff_t start_pos = IT_CHARPOS (it);
5034 int dy = frame_line_height;
5035 /* In the below we divide the window box height by the frame's
5036 line height to make the result predictable when the window
5037 box is not an integral multiple of the line height. This is
5038 important to ensure we get back to the same position when
5039 scrolling up, then down. */
5040 dy = max ((window_box_height (w) / dy - next_screen_context_lines) * dy,
5041 dy) * n;
5043 /* Note that move_it_vertically always moves the iterator to the
5044 start of a line. So, if the last line doesn't have a newline,
5045 we would end up at the start of the line ending at ZV. */
5046 if (dy <= 0)
5048 move_it_vertically_backward (&it, -dy);
5049 /* Ensure we actually do move, e.g. in case we are currently
5050 looking at an image that is taller that the window height. */
5051 while (start_pos == IT_CHARPOS (it)
5052 && start_pos > BEGV)
5053 move_it_by_lines (&it, -1);
5055 else if (dy > 0)
5057 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
5058 MOVE_TO_POS | MOVE_TO_Y);
5059 /* Ensure we actually do move, e.g. in case we are currently
5060 looking at an image that is taller that the window height. */
5061 while (start_pos == IT_CHARPOS (it)
5062 && start_pos < ZV)
5063 move_it_by_lines (&it, 1);
5066 else
5067 move_it_by_lines (&it, n);
5069 /* We failed if we find ZV is already on the screen (scrolling up,
5070 means there's nothing past the end), or if we can't start any
5071 earlier (scrolling down, means there's nothing past the top). */
5072 if ((n > 0 && IT_CHARPOS (it) == ZV)
5073 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
5075 if (IT_CHARPOS (it) == ZV)
5077 if (it.current_y < it.last_visible_y
5078 && (it.current_y + it.max_ascent + it.max_descent
5079 > it.last_visible_y))
5081 /* The last line was only partially visible, make it fully
5082 visible. */
5083 w->vscroll = (it.last_visible_y
5084 - it.current_y + it.max_ascent + it.max_descent);
5085 adjust_frame_glyphs (it.f);
5087 else
5089 bidi_unshelve_cache (itdata, false);
5090 if (noerror)
5091 return;
5092 else if (n < 0) /* could happen with empty buffers */
5093 xsignal0 (Qbeginning_of_buffer);
5094 else
5095 xsignal0 (Qend_of_buffer);
5098 else
5100 if (w->vscroll != 0)
5101 /* The first line was only partially visible, make it fully
5102 visible. */
5103 w->vscroll = 0;
5104 else
5106 bidi_unshelve_cache (itdata, false);
5107 if (noerror)
5108 return;
5109 else
5110 xsignal0 (Qbeginning_of_buffer);
5114 /* If control gets here, then we vscrolled. */
5116 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
5118 /* Don't try to change the window start below. */
5119 vscrolled = true;
5122 if (! vscrolled)
5124 ptrdiff_t pos = IT_CHARPOS (it);
5125 ptrdiff_t bytepos;
5127 /* If in the middle of a multi-glyph character move forward to
5128 the next character. */
5129 if (in_display_vector_p (&it))
5131 ++pos;
5132 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
5135 /* Set the window start, and set up the window for redisplay. */
5136 set_marker_restricted_both (w->start, w->contents, IT_CHARPOS (it),
5137 IT_BYTEPOS (it));
5138 bytepos = marker_byte_position (w->start);
5139 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
5140 w->update_mode_line = true;
5141 /* Set force_start so that redisplay_window will run the
5142 window-scroll-functions. */
5143 w->force_start = true;
5146 /* The rest of this function uses current_y in a nonstandard way,
5147 not including the height of the header line if any. */
5148 it.current_y = it.vpos = 0;
5150 /* Move PT out of scroll margins.
5151 This code wants current_y to be zero at the window start position
5152 even if there is a header line. */
5153 window_total_lines
5154 = w->total_lines * WINDOW_FRAME_LINE_HEIGHT (w) / frame_line_height;
5155 this_scroll_margin = max (0, scroll_margin);
5156 this_scroll_margin
5157 = min (this_scroll_margin, window_total_lines / 4);
5158 this_scroll_margin *= frame_line_height;
5160 if (n > 0)
5162 /* We moved the window start towards ZV, so PT may be now
5163 in the scroll margin at the top. */
5164 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5165 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5166 && (NILP (Vscroll_preserve_screen_position)
5167 || EQ (Vscroll_preserve_screen_position, Qt)))
5168 /* We found PT at a legitimate height. Leave it alone. */
5170 else if (window_scroll_pixel_based_preserve_y >= 0)
5172 /* If we have a header line, take account of it.
5173 This is necessary because we set it.current_y to 0, above. */
5174 move_it_to (&it, -1,
5175 window_scroll_pixel_based_preserve_x,
5176 (window_scroll_pixel_based_preserve_y
5177 - WINDOW_WANTS_HEADER_LINE_P (w)),
5178 -1, MOVE_TO_Y | MOVE_TO_X);
5179 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5181 else
5183 while (it.current_y < this_scroll_margin)
5185 int prev = it.current_y;
5186 move_it_by_lines (&it, 1);
5187 if (prev == it.current_y)
5188 break;
5190 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5193 else if (n < 0)
5195 ptrdiff_t charpos, bytepos;
5196 bool partial_p;
5198 /* Save our position, for the
5199 window_scroll_pixel_based_preserve_y case. */
5200 charpos = IT_CHARPOS (it);
5201 bytepos = IT_BYTEPOS (it);
5203 /* We moved the window start towards BEGV, so PT may be now
5204 in the scroll margin at the bottom. */
5205 move_it_to (&it, PT, -1,
5206 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5207 - this_scroll_margin - 1),
5209 MOVE_TO_POS | MOVE_TO_Y);
5211 /* Save our position, in case it's correct. */
5212 charpos = IT_CHARPOS (it);
5213 bytepos = IT_BYTEPOS (it);
5215 /* If PT is in the screen line at the last fully visible line,
5216 move_it_to will stop at X = 0 in that line, because the
5217 required Y coordinate is reached there. See if we can get to
5218 PT without descending lower in Y, and if we can, it means we
5219 reached PT before the scroll margin. */
5220 if (charpos != PT)
5222 struct it it2;
5223 void *it_data;
5225 it2 = it;
5226 it_data = bidi_shelve_cache ();
5227 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5228 if (IT_CHARPOS (it) == PT && it.current_y == it2.current_y)
5230 charpos = IT_CHARPOS (it);
5231 bytepos = IT_BYTEPOS (it);
5232 bidi_unshelve_cache (it_data, true);
5234 else
5236 it = it2;
5237 bidi_unshelve_cache (it_data, false);
5241 /* See if point is on a partially visible line at the end. */
5242 if (it.what == IT_EOB)
5243 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5244 else
5246 move_it_by_lines (&it, 1);
5247 partial_p = it.current_y > it.last_visible_y;
5250 if (charpos == PT && !partial_p
5251 && (NILP (Vscroll_preserve_screen_position)
5252 || EQ (Vscroll_preserve_screen_position, Qt)))
5253 /* We found PT before we found the display margin, so PT is ok. */
5255 else if (window_scroll_pixel_based_preserve_y >= 0)
5257 SET_TEXT_POS_FROM_MARKER (start, w->start);
5258 start_display (&it, w, start);
5259 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5260 here because we called start_display again and did not
5261 alter it.current_y this time. */
5262 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
5263 window_scroll_pixel_based_preserve_y, -1,
5264 MOVE_TO_Y | MOVE_TO_X);
5265 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5267 else
5269 if (partial_p)
5270 /* The last line was only partially visible, so back up two
5271 lines to make sure we're on a fully visible line. */
5273 move_it_by_lines (&it, -2);
5274 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5276 else
5277 /* No, the position we saved is OK, so use it. */
5278 SET_PT_BOTH (charpos, bytepos);
5281 bidi_unshelve_cache (itdata, false);
5283 if (adjust_old_pointm)
5284 Fset_marker (w->old_pointm,
5285 ((w == XWINDOW (selected_window))
5286 ? make_number (BUF_PT (XBUFFER (w->contents)))
5287 : Fmarker_position (w->pointm)),
5288 w->contents);
5292 /* Implementation of window_scroll that works based on screen lines.
5293 See the comment of window_scroll for parameter descriptions. */
5295 static void
5296 window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
5298 struct window *w = XWINDOW (window);
5299 /* Fvertical_motion enters redisplay, which can trigger
5300 fontification, which in turn can modify buffer text (e.g., if the
5301 fontification functions replace escape sequences with faces, as
5302 in `grep-mode-font-lock-keywords'). So we use a marker to record
5303 the old point position, to prevent crashes in SET_PT_BOTH. */
5304 Lisp_Object opoint_marker = Fpoint_marker ();
5305 register ptrdiff_t pos, pos_byte;
5306 register int ht = window_internal_height (w);
5307 register Lisp_Object tem;
5308 bool lose;
5309 Lisp_Object bolp;
5310 ptrdiff_t startpos = marker_position (w->start);
5311 ptrdiff_t startbyte = marker_byte_position (w->start);
5312 Lisp_Object original_pos = Qnil;
5313 bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
5314 Fwindow_old_point (window)));
5316 /* If scrolling screen-fulls, compute the number of lines to
5317 scroll from the window's height. */
5318 if (whole)
5319 n *= max (1, ht - next_screen_context_lines);
5321 if (!NILP (Vscroll_preserve_screen_position))
5323 if (window_scroll_preserve_vpos <= 0
5324 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
5325 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
5327 struct position posit
5328 = *compute_motion (startpos, startbyte, 0, 0, false,
5329 PT, ht, 0, -1, w->hscroll, 0, w);
5331 window_scroll_preserve_vpos = posit.vpos;
5332 window_scroll_preserve_hpos = posit.hpos + w->hscroll;
5335 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
5336 make_number (window_scroll_preserve_vpos));
5339 XSETFASTINT (tem, PT);
5340 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5342 if (NILP (tem))
5344 Fvertical_motion (make_number (- (ht / 2)), window, Qnil);
5345 startpos = PT;
5346 startbyte = PT_BYTE;
5349 SET_PT_BOTH (startpos, startbyte);
5350 lose = n < 0 && PT == BEGV;
5351 Fvertical_motion (make_number (n), window, Qnil);
5352 pos = PT;
5353 pos_byte = PT_BYTE;
5354 bolp = Fbolp ();
5355 SET_PT_BOTH (marker_position (opoint_marker),
5356 marker_byte_position (opoint_marker));
5358 if (lose)
5360 if (noerror)
5361 return;
5362 else
5363 xsignal0 (Qbeginning_of_buffer);
5366 if (pos < ZV)
5368 /* Don't use a scroll margin that is negative or too large. */
5369 int this_scroll_margin =
5370 max (0, min (scroll_margin, w->total_lines / 4));
5372 set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
5373 w->start_at_line_beg = !NILP (bolp);
5374 w->update_mode_line = true;
5375 /* Set force_start so that redisplay_window will run
5376 the window-scroll-functions. */
5377 w->force_start = true;
5379 if (!NILP (Vscroll_preserve_screen_position)
5380 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5382 SET_PT_BOTH (pos, pos_byte);
5383 Fvertical_motion (original_pos, window, Qnil);
5385 /* If we scrolled forward, put point enough lines down
5386 that it is outside the scroll margin. */
5387 else if (n > 0)
5389 int top_margin;
5391 if (this_scroll_margin > 0)
5393 SET_PT_BOTH (pos, pos_byte);
5394 Fvertical_motion (make_number (this_scroll_margin), window, Qnil);
5395 top_margin = PT;
5397 else
5398 top_margin = pos;
5400 if (top_margin <= marker_position (opoint_marker))
5401 SET_PT_BOTH (marker_position (opoint_marker),
5402 marker_byte_position (opoint_marker));
5403 else if (!NILP (Vscroll_preserve_screen_position))
5405 SET_PT_BOTH (pos, pos_byte);
5406 Fvertical_motion (original_pos, window, Qnil);
5408 else
5409 SET_PT (top_margin);
5411 else if (n < 0)
5413 int bottom_margin;
5415 /* If we scrolled backward, put point near the end of the window
5416 but not within the scroll margin. */
5417 SET_PT_BOTH (pos, pos_byte);
5418 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window,
5419 Qnil);
5420 if (XFASTINT (tem) == ht - this_scroll_margin)
5421 bottom_margin = PT;
5422 else
5423 bottom_margin = PT + 1;
5425 if (bottom_margin > marker_position (opoint_marker))
5426 SET_PT_BOTH (marker_position (opoint_marker),
5427 marker_byte_position (opoint_marker));
5428 else
5430 if (!NILP (Vscroll_preserve_screen_position))
5432 SET_PT_BOTH (pos, pos_byte);
5433 Fvertical_motion (original_pos, window, Qnil);
5435 else
5436 Fvertical_motion (make_number (-1), window, Qnil);
5440 else
5442 if (noerror)
5443 return;
5444 else
5445 xsignal0 (Qend_of_buffer);
5448 if (adjust_old_pointm)
5449 Fset_marker (w->old_pointm,
5450 ((w == XWINDOW (selected_window))
5451 ? make_number (BUF_PT (XBUFFER (w->contents)))
5452 : Fmarker_position (w->pointm)),
5453 w->contents);
5457 /* Scroll selected_window up or down. If N is nil, scroll a
5458 screen-full which is defined as the height of the window minus
5459 next_screen_context_lines. If N is the symbol `-', scroll.
5460 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5461 up. This is the guts of Fscroll_up and Fscroll_down. */
5463 static void
5464 scroll_command (Lisp_Object n, int direction)
5466 ptrdiff_t count = SPECPDL_INDEX ();
5468 eassert (eabs (direction) == 1);
5470 /* If selected window's buffer isn't current, make it current for
5471 the moment. But don't screw up if window_scroll gets an error. */
5472 if (XBUFFER (XWINDOW (selected_window)->contents) != current_buffer)
5474 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5475 Fset_buffer (XWINDOW (selected_window)->contents);
5478 if (NILP (n))
5479 window_scroll (selected_window, direction, true, false);
5480 else if (EQ (n, Qminus))
5481 window_scroll (selected_window, -direction, true, false);
5482 else
5484 n = Fprefix_numeric_value (n);
5485 window_scroll (selected_window, XINT (n) * direction, false, false);
5488 unbind_to (count, Qnil);
5491 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
5492 doc: /* Scroll text of selected window upward ARG lines.
5493 If ARG is omitted or nil, scroll upward by a near full screen.
5494 A near full screen is `next-screen-context-lines' less than a full screen.
5495 Negative ARG means scroll downward.
5496 If ARG is the atom `-', scroll downward by nearly full screen.
5497 When calling from a program, supply as argument a number, nil, or `-'. */)
5498 (Lisp_Object arg)
5500 scroll_command (arg, 1);
5501 return Qnil;
5504 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
5505 doc: /* Scroll text of selected window down ARG lines.
5506 If ARG is omitted or nil, scroll down by a near full screen.
5507 A near full screen is `next-screen-context-lines' less than a full screen.
5508 Negative ARG means scroll upward.
5509 If ARG is the atom `-', scroll upward by nearly full screen.
5510 When calling from a program, supply as argument a number, nil, or `-'. */)
5511 (Lisp_Object arg)
5513 scroll_command (arg, -1);
5514 return Qnil;
5517 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5518 doc: /* Return the other window for \"other window scroll\" commands.
5519 If `other-window-scroll-buffer' is non-nil, a window
5520 showing that buffer is used.
5521 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5522 specifies the window. This takes precedence over
5523 `other-window-scroll-buffer'. */)
5524 (void)
5526 Lisp_Object window;
5528 if (MINI_WINDOW_P (XWINDOW (selected_window))
5529 && !NILP (Vminibuf_scroll_window))
5530 window = Vminibuf_scroll_window;
5531 /* If buffer is specified and live, scroll that buffer. */
5532 else if (!NILP (Vother_window_scroll_buffer)
5533 && BUFFERP (Vother_window_scroll_buffer)
5534 && BUFFER_LIVE_P (XBUFFER (Vother_window_scroll_buffer)))
5536 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5537 if (NILP (window))
5538 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5540 else
5542 /* Nothing specified; look for a neighboring window on the same
5543 frame. */
5544 window = Fnext_window (selected_window, Qnil, Qnil);
5546 if (EQ (window, selected_window))
5547 /* That didn't get us anywhere; look for a window on another
5548 visible frame. */
5550 window = Fnext_window (window, Qnil, Qt);
5551 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5552 && ! EQ (window, selected_window));
5555 CHECK_LIVE_WINDOW (window);
5557 if (EQ (window, selected_window))
5558 error ("There is no other window");
5560 return window;
5563 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5564 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5565 A near full screen is `next-screen-context-lines' less than a full screen.
5566 The next window is the one below the current one; or the one at the top
5567 if the current one is at the bottom. Negative ARG means scroll downward.
5568 If ARG is the atom `-', scroll downward by nearly full screen.
5569 When calling from a program, supply as argument a number, nil, or `-'.
5571 If `other-window-scroll-buffer' is non-nil, scroll the window
5572 showing that buffer, popping the buffer up if necessary.
5573 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5574 specifies the window to scroll. This takes precedence over
5575 `other-window-scroll-buffer'. */)
5576 (Lisp_Object arg)
5578 Lisp_Object window;
5579 struct window *w;
5580 ptrdiff_t count = SPECPDL_INDEX ();
5582 window = Fother_window_for_scrolling ();
5583 w = XWINDOW (window);
5585 /* Don't screw up if window_scroll gets an error. */
5586 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5588 Fset_buffer (w->contents);
5589 SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
5590 SET_PT_BOTH (marker_position (w->old_pointm), marker_byte_position (w->old_pointm));
5592 if (NILP (arg))
5593 window_scroll (window, 1, true, true);
5594 else if (EQ (arg, Qminus))
5595 window_scroll (window, -1, true, true);
5596 else
5598 if (CONSP (arg))
5599 arg = XCAR (arg);
5600 CHECK_NUMBER (arg);
5601 window_scroll (window, XINT (arg), false, true);
5604 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5605 set_marker_both (w->old_pointm, Qnil, PT, PT_BYTE);
5606 unbind_to (count, Qnil);
5608 return Qnil;
5611 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5612 doc: /* Scroll selected window display ARG columns left.
5613 Default for ARG is window width minus 2.
5614 Value is the total amount of leftward horizontal scrolling in
5615 effect after the change.
5616 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5617 lower bound for automatic scrolling, i.e. automatic scrolling
5618 will not scroll a window to a column less than the value returned
5619 by this function. This happens in an interactive call. */)
5620 (register Lisp_Object arg, Lisp_Object set_minimum)
5622 struct window *w = XWINDOW (selected_window);
5623 EMACS_INT requested_arg = (NILP (arg)
5624 ? window_body_width (w, 0) - 2
5625 : XINT (Fprefix_numeric_value (arg)));
5626 Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
5628 if (!NILP (set_minimum))
5629 w->min_hscroll = w->hscroll;
5631 w->suspend_auto_hscroll = true;
5633 return result;
5636 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5637 doc: /* Scroll selected window display ARG columns right.
5638 Default for ARG is window width minus 2.
5639 Value is the total amount of leftward horizontal scrolling in
5640 effect after the change.
5641 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5642 lower bound for automatic scrolling, i.e. automatic scrolling
5643 will not scroll a window to a column less than the value returned
5644 by this function. This happens in an interactive call. */)
5645 (register Lisp_Object arg, Lisp_Object set_minimum)
5647 struct window *w = XWINDOW (selected_window);
5648 EMACS_INT requested_arg = (NILP (arg)
5649 ? window_body_width (w, 0) - 2
5650 : XINT (Fprefix_numeric_value (arg)));
5651 Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
5653 if (!NILP (set_minimum))
5654 w->min_hscroll = w->hscroll;
5656 w->suspend_auto_hscroll = true;
5658 return result;
5661 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5662 doc: /* Return the window which was selected when entering the minibuffer.
5663 Returns nil, if selected window is not a minibuffer window. */)
5664 (void)
5666 if (minibuf_level > 0
5667 && MINI_WINDOW_P (XWINDOW (selected_window))
5668 && WINDOW_LIVE_P (minibuf_selected_window))
5669 return minibuf_selected_window;
5671 return Qnil;
5674 /* Value is the number of lines actually displayed in window W,
5675 as opposed to its height. */
5677 static int
5678 displayed_window_lines (struct window *w)
5680 struct it it;
5681 struct text_pos start;
5682 int height = window_box_height (w);
5683 struct buffer *old_buffer;
5684 int bottom_y;
5685 void *itdata = NULL;
5687 if (XBUFFER (w->contents) != current_buffer)
5689 old_buffer = current_buffer;
5690 set_buffer_internal (XBUFFER (w->contents));
5692 else
5693 old_buffer = NULL;
5695 /* In case W->start is out of the accessible range, do something
5696 reasonable. This happens in Info mode when Info-scroll-down
5697 calls (recenter -1) while W->start is 1. */
5698 CLIP_TEXT_POS_FROM_MARKER (start, w->start);
5700 itdata = bidi_shelve_cache ();
5701 start_display (&it, w, start);
5702 move_it_vertically (&it, height);
5703 bottom_y = line_bottom_y (&it);
5704 bidi_unshelve_cache (itdata, false);
5706 /* rms: On a non-window display,
5707 the value of it.vpos at the bottom of the screen
5708 seems to be 1 larger than window_box_height (w).
5709 This kludge fixes a bug whereby (move-to-window-line -1)
5710 when ZV is on the last screen line
5711 moves to the previous screen line instead of the last one. */
5712 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5713 height++;
5715 /* Add in empty lines at the bottom of the window. */
5716 if (bottom_y < height)
5718 int uy = FRAME_LINE_HEIGHT (it.f);
5719 it.vpos += (height - bottom_y + uy - 1) / uy;
5722 if (old_buffer)
5723 set_buffer_internal (old_buffer);
5725 return it.vpos;
5729 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5730 doc: /* Center point in selected window and maybe redisplay frame.
5731 With a numeric prefix argument ARG, recenter putting point on screen line ARG
5732 relative to the selected window. If ARG is negative, it counts up from the
5733 bottom of the window. (ARG should be less than the height of the window.)
5735 If ARG is omitted or nil, then recenter with point on the middle line of
5736 the selected window; if the variable `recenter-redisplay' is non-nil,
5737 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5738 is set to `grow-only', this resets the tool-bar's height to the minimum
5739 height needed); if `recenter-redisplay' has the special value `tty',
5740 then only tty frames are redrawn.
5742 Just C-u as prefix means put point in the center of the window
5743 and redisplay normally--don't erase and redraw the frame. */)
5744 (register Lisp_Object arg)
5746 struct window *w = XWINDOW (selected_window);
5747 struct buffer *buf = XBUFFER (w->contents);
5748 bool center_p = false;
5749 ptrdiff_t charpos, bytepos;
5750 EMACS_INT iarg IF_LINT (= 0);
5751 int this_scroll_margin;
5753 if (buf != current_buffer)
5754 error ("`recenter'ing a window that does not display current-buffer.");
5756 /* If redisplay is suppressed due to an error, try again. */
5757 buf->display_error_modiff = 0;
5759 if (NILP (arg))
5761 if (!NILP (Vrecenter_redisplay)
5762 && (!EQ (Vrecenter_redisplay, Qtty)
5763 || !NILP (Ftty_type (selected_frame))))
5765 ptrdiff_t i;
5767 /* Invalidate pixel data calculated for all compositions. */
5768 for (i = 0; i < n_compositions; i++)
5769 composition_table[i]->font = NULL;
5770 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
5771 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5772 #endif
5773 Fredraw_frame (WINDOW_FRAME (w));
5774 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5777 center_p = true;
5779 else if (CONSP (arg)) /* Just C-u. */
5780 center_p = true;
5781 else
5783 arg = Fprefix_numeric_value (arg);
5784 CHECK_NUMBER (arg);
5785 iarg = XINT (arg);
5788 /* Do this after making BUF current
5789 in case scroll_margin is buffer-local. */
5790 this_scroll_margin
5791 = max (0, min (scroll_margin, w->total_lines / 4));
5793 /* Don't use redisplay code for initial frames, as the necessary
5794 data structures might not be set up yet then. */
5795 if (!FRAME_INITIAL_P (XFRAME (w->frame)))
5797 if (center_p)
5799 struct it it;
5800 struct text_pos pt;
5801 void *itdata = bidi_shelve_cache ();
5803 SET_TEXT_POS (pt, PT, PT_BYTE);
5804 start_display (&it, w, pt);
5805 move_it_vertically_backward (&it, window_box_height (w) / 2);
5806 charpos = IT_CHARPOS (it);
5807 bytepos = IT_BYTEPOS (it);
5808 bidi_unshelve_cache (itdata, false);
5810 else if (iarg < 0)
5812 struct it it;
5813 struct text_pos pt;
5814 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
5815 int extra_line_spacing;
5816 int h = window_box_height (w);
5817 int ht = window_internal_height (w);
5818 void *itdata = bidi_shelve_cache ();
5820 nlines = clip_to_bounds (this_scroll_margin + 1, nlines,
5821 ht - this_scroll_margin);
5823 SET_TEXT_POS (pt, PT, PT_BYTE);
5824 start_display (&it, w, pt);
5826 /* Be sure we have the exact height of the full line containing PT. */
5827 move_it_by_lines (&it, 0);
5829 /* The amount of pixels we have to move back is the window
5830 height minus what's displayed in the line containing PT,
5831 and the lines below. */
5832 it.current_y = 0;
5833 it.vpos = 0;
5834 move_it_by_lines (&it, nlines);
5836 if (it.vpos == nlines)
5837 h -= it.current_y;
5838 else
5840 /* Last line has no newline. */
5841 h -= line_bottom_y (&it);
5842 it.vpos++;
5845 /* Don't reserve space for extra line spacing of last line. */
5846 extra_line_spacing = it.max_extra_line_spacing;
5848 /* If we can't move down NLINES lines because we hit
5849 the end of the buffer, count in some empty lines. */
5850 if (it.vpos < nlines)
5852 nlines -= it.vpos;
5853 extra_line_spacing = it.extra_line_spacing;
5854 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5856 if (h <= 0)
5858 bidi_unshelve_cache (itdata, false);
5859 return Qnil;
5862 /* Now find the new top line (starting position) of the window. */
5863 start_display (&it, w, pt);
5864 it.current_y = 0;
5865 move_it_vertically_backward (&it, h);
5867 /* If extra line spacing is present, we may move too far
5868 back. This causes the last line to be only partially
5869 visible (which triggers redisplay to recenter that line
5870 in the middle), so move forward.
5871 But ignore extra line spacing on last line, as it is not
5872 considered to be part of the visible height of the line.
5874 h += extra_line_spacing;
5875 while (-it.current_y > h)
5876 move_it_by_lines (&it, 1);
5878 charpos = IT_CHARPOS (it);
5879 bytepos = IT_BYTEPOS (it);
5881 bidi_unshelve_cache (itdata, false);
5883 else
5885 struct it it;
5886 struct text_pos pt;
5887 ptrdiff_t nlines = min (PTRDIFF_MAX, iarg);
5888 int ht = window_internal_height (w);
5889 void *itdata = bidi_shelve_cache ();
5891 nlines = clip_to_bounds (this_scroll_margin, nlines,
5892 ht - this_scroll_margin - 1);
5894 SET_TEXT_POS (pt, PT, PT_BYTE);
5895 start_display (&it, w, pt);
5897 /* Move to the beginning of screen line containing PT. */
5898 move_it_by_lines (&it, 0);
5900 /* Move back to find the point which is ARG screen lines above PT. */
5901 if (nlines > 0)
5903 it.current_y = 0;
5904 it.vpos = 0;
5905 move_it_by_lines (&it, -nlines);
5908 charpos = IT_CHARPOS (it);
5909 bytepos = IT_BYTEPOS (it);
5911 bidi_unshelve_cache (itdata, false);
5914 else
5916 struct position pos;
5917 int ht = window_internal_height (w);
5919 if (center_p)
5920 iarg = ht / 2;
5921 else if (iarg < 0)
5922 iarg += ht;
5924 /* Don't let it get into the margin at either top or bottom. */
5925 iarg = clip_to_bounds (this_scroll_margin, iarg,
5926 ht - this_scroll_margin - 1);
5928 pos = *vmotion (PT, PT_BYTE, - iarg, w);
5929 charpos = pos.bufpos;
5930 bytepos = pos.bytepos;
5933 /* Set the new window start. */
5934 set_marker_both (w->start, w->contents, charpos, bytepos);
5935 w->window_end_valid = false;
5937 w->optional_new_start = true;
5939 w->start_at_line_beg = (bytepos == BEGV_BYTE
5940 || FETCH_BYTE (bytepos - 1) == '\n');
5942 wset_redisplay (w);
5944 return Qnil;
5947 DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
5948 0, 2, 0,
5949 doc: /* Return the width in columns of the text display area of WINDOW.
5950 WINDOW must be a live window and defaults to the selected one.
5952 The returned width does not include dividers, scrollbars, margins,
5953 fringes, nor any partial-width columns at the right of the text
5954 area.
5956 Optional argument PIXELWISE non-nil, means to return the width in
5957 pixels. */)
5958 (Lisp_Object window, Lisp_Object pixelwise)
5960 struct window *w = decode_live_window (window);
5962 if (NILP (pixelwise))
5963 return make_number (window_box_width (w, TEXT_AREA)
5964 / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
5965 else
5966 return make_number (window_box_width (w, TEXT_AREA));
5969 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5970 0, 2, 0,
5971 doc: /* Return the height in lines of the text display area of WINDOW.
5972 WINDOW must be a live window and defaults to the selected one.
5974 The returned height does not include dividers, the mode line, any header
5975 line, nor any partial-height lines at the bottom of the text area.
5977 Optional argument PIXELWISE non-nil, means to return the height in
5978 pixels. */)
5979 (Lisp_Object window, Lisp_Object pixelwise)
5981 struct window *w = decode_live_window (window);
5983 if (NILP (pixelwise))
5984 return make_number (window_box_height (w)
5985 / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
5986 else
5987 return make_number (window_box_height (w));
5990 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5991 1, 1, "P",
5992 doc: /* Position point relative to window.
5993 ARG nil means position point at center of window.
5994 Else, ARG specifies vertical position within the window;
5995 zero means top of window, negative means relative to bottom of window. */)
5996 (Lisp_Object arg)
5998 struct window *w = XWINDOW (selected_window);
5999 int lines, start;
6000 Lisp_Object window;
6001 #if false
6002 int this_scroll_margin;
6003 #endif
6005 if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer))
6006 /* This test is needed to make sure PT/PT_BYTE make sense in w->contents
6007 when passed below to set_marker_both. */
6008 error ("move-to-window-line called from unrelated buffer");
6010 window = selected_window;
6011 start = marker_position (w->start);
6012 if (start < BEGV || start > ZV)
6014 int height = window_internal_height (w);
6015 Fvertical_motion (make_number (- (height / 2)), window, Qnil);
6016 set_marker_both (w->start, w->contents, PT, PT_BYTE);
6017 w->start_at_line_beg = !NILP (Fbolp ());
6018 w->force_start = true;
6020 else
6021 Fgoto_char (w->start);
6023 lines = displayed_window_lines (w);
6025 #if false
6026 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
6027 #endif
6029 if (NILP (arg))
6030 XSETFASTINT (arg, lines / 2);
6031 else
6033 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
6035 if (iarg < 0)
6036 iarg = iarg + lines;
6038 #if false /* This code would prevent move-to-window-line from moving point
6039 to a place inside the scroll margins (which would cause the
6040 next redisplay to scroll). I wrote this code, but then concluded
6041 it is probably better not to install it. However, it is here
6042 inside #if false so as not to lose it. -- rms. */
6044 /* Don't let it get into the margin at either top or bottom. */
6045 iarg = max (iarg, this_scroll_margin);
6046 iarg = min (iarg, lines - this_scroll_margin - 1);
6047 #endif
6049 arg = make_number (iarg);
6052 /* Skip past a partially visible first line. */
6053 if (w->vscroll)
6054 XSETINT (arg, XINT (arg) + 1);
6056 return Fvertical_motion (arg, window, Qnil);
6061 /***********************************************************************
6062 Window Configuration
6063 ***********************************************************************/
6065 struct save_window_data
6067 struct vectorlike_header header;
6068 Lisp_Object selected_frame;
6069 Lisp_Object current_window;
6070 Lisp_Object current_buffer;
6071 Lisp_Object minibuf_scroll_window;
6072 Lisp_Object minibuf_selected_window;
6073 Lisp_Object root_window;
6074 Lisp_Object focus_frame;
6075 /* A vector, each of whose elements is a struct saved_window
6076 for one window. */
6077 Lisp_Object saved_windows;
6079 /* All fields above are traced by the GC.
6080 From `frame-cols' down, the fields are ignored by the GC. */
6081 /* We should be able to do without the following two. */
6082 int frame_cols, frame_lines;
6083 /* These two should get eventually replaced by their pixel
6084 counterparts. */
6085 int frame_menu_bar_lines, frame_tool_bar_lines;
6086 int frame_text_width, frame_text_height;
6087 /* These are currently unused. We need them as soon as we convert
6088 to pixels. */
6089 int frame_menu_bar_height, frame_tool_bar_height;
6092 /* This is saved as a Lisp_Vector. */
6093 struct saved_window
6095 struct vectorlike_header header;
6097 Lisp_Object window, buffer, start, pointm, old_pointm;
6098 Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
6099 Lisp_Object left_col, top_line, total_cols, total_lines;
6100 Lisp_Object normal_cols, normal_lines;
6101 Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll;
6102 Lisp_Object parent, prev;
6103 Lisp_Object start_at_line_beg;
6104 Lisp_Object display_table;
6105 Lisp_Object left_margin_cols, right_margin_cols;
6106 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
6107 Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
6108 Lisp_Object scroll_bar_height, horizontal_scroll_bar_type;
6109 Lisp_Object combination_limit, window_parameters;
6112 #define SAVED_WINDOW_N(swv,n) \
6113 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
6115 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
6116 doc: /* Return t if OBJECT is a window-configuration object. */)
6117 (Lisp_Object object)
6119 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
6122 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
6123 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
6124 (Lisp_Object config)
6126 register struct save_window_data *data;
6127 struct Lisp_Vector *saved_windows;
6129 CHECK_WINDOW_CONFIGURATION (config);
6131 data = (struct save_window_data *) XVECTOR (config);
6132 saved_windows = XVECTOR (data->saved_windows);
6133 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6136 DEFUN ("set-window-configuration", Fset_window_configuration,
6137 Sset_window_configuration, 1, 1, 0,
6138 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
6139 CONFIGURATION must be a value previously returned
6140 by `current-window-configuration' (which see).
6141 If CONFIGURATION was made from a frame that is now deleted,
6142 only frame-independent values can be restored. In this case,
6143 the return value is nil. Otherwise the value is t. */)
6144 (Lisp_Object configuration)
6146 register struct save_window_data *data;
6147 struct Lisp_Vector *saved_windows;
6148 Lisp_Object new_current_buffer;
6149 Lisp_Object frame;
6150 struct frame *f;
6151 ptrdiff_t old_point = -1;
6152 USE_SAFE_ALLOCA;
6154 CHECK_WINDOW_CONFIGURATION (configuration);
6156 data = (struct save_window_data *) XVECTOR (configuration);
6157 saved_windows = XVECTOR (data->saved_windows);
6159 new_current_buffer = data->current_buffer;
6160 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
6161 new_current_buffer = Qnil;
6162 else
6164 if (XBUFFER (new_current_buffer) == current_buffer)
6165 /* The code further down "preserves point" by saving here PT in
6166 old_point and then setting it later back into PT. When the
6167 current-selected-window and the final-selected-window both show
6168 the current buffer, this suffers from the problem that the
6169 current PT is the window-point of the current-selected-window,
6170 while the final PT is the point of the final-selected-window, so
6171 this copy from one PT to the other would end up moving the
6172 window-point of the final-selected-window to the window-point of
6173 the current-selected-window. So we have to be careful which
6174 point of the current-buffer we copy into old_point. */
6175 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
6176 && WINDOWP (selected_window)
6177 && EQ (XWINDOW (selected_window)->contents, new_current_buffer)
6178 && !EQ (selected_window, data->current_window))
6179 old_point = marker_position (XWINDOW (data->current_window)->pointm);
6180 else
6181 old_point = PT;
6182 else
6183 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6184 point in new_current_buffer as of the last time this buffer was
6185 used. This can be non-deterministic since it can be changed by
6186 things like jit-lock by mere temporary selection of some random
6187 window that happens to show this buffer.
6188 So if possible we want this arbitrary choice of "which point" to
6189 be the one from the to-be-selected-window so as to prevent this
6190 window's cursor from being copied from another window. */
6191 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
6192 /* If current_window = selected_window, its point is in BUF_PT. */
6193 && !EQ (selected_window, data->current_window))
6194 old_point = marker_position (XWINDOW (data->current_window)->pointm);
6195 else
6196 old_point = BUF_PT (XBUFFER (new_current_buffer));
6199 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6200 f = XFRAME (frame);
6202 /* If f is a dead frame, don't bother rebuilding its window tree.
6203 However, there is other stuff we should still try to do below. */
6204 if (FRAME_LIVE_P (f))
6206 Lisp_Object window;
6207 Lisp_Object dead_windows = Qnil;
6208 Lisp_Object tem, par, pers;
6209 struct window *w;
6210 struct saved_window *p;
6211 struct window *root_window;
6212 struct window **leaf_windows;
6213 ptrdiff_t i, k, n_leaf_windows;
6215 /* Don't do this within the main loop below: This may call Lisp
6216 code and is thus potentially unsafe while input is blocked. */
6217 for (k = 0; k < saved_windows->header.size; k++)
6219 p = SAVED_WINDOW_N (saved_windows, k);
6220 window = p->window;
6221 w = XWINDOW (window);
6222 if (BUFFERP (w->contents)
6223 && !EQ (w->contents, p->buffer)
6224 && BUFFER_LIVE_P (XBUFFER (p->buffer)))
6225 /* If a window we restore gets another buffer, record the
6226 window's old buffer. */
6227 call1 (Qrecord_window_buffer, window);
6230 /* Disallow x_set_window_size, temporarily. */
6231 f->can_x_set_window_size = false;
6232 /* The mouse highlighting code could get screwed up
6233 if it runs during this. */
6234 block_input ();
6236 /* "Swap out" point from the selected window's buffer
6237 into the window itself. (Normally the pointm of the selected
6238 window holds garbage.) We do this now, before
6239 restoring the window contents, and prevent it from
6240 being done later on when we select a new window. */
6241 if (! NILP (XWINDOW (selected_window)->contents))
6243 w = XWINDOW (selected_window);
6244 set_marker_both (w->pointm,
6245 w->contents,
6246 BUF_PT (XBUFFER (w->contents)),
6247 BUF_PT_BYTE (XBUFFER (w->contents)));
6250 fset_redisplay (f);
6251 FRAME_WINDOW_SIZES_CHANGED (f) = true;
6253 /* Problem: Freeing all matrices and later allocating them again
6254 is a serious redisplay flickering problem. What we would
6255 really like to do is to free only those matrices not reused
6256 below. */
6257 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6258 ptrdiff_t nwindows = count_windows (root_window);
6259 SAFE_NALLOCA (leaf_windows, 1, nwindows);
6260 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6262 /* Kludge Alert!
6263 Mark all windows now on frame as "deleted".
6264 Restoring the new configuration "undeletes" any that are in it.
6266 Save their current buffers in their height fields, since we may
6267 need it later, if a buffer saved in the configuration is now
6268 dead. */
6269 delete_all_child_windows (FRAME_ROOT_WINDOW (f));
6271 for (k = 0; k < saved_windows->header.size; k++)
6273 p = SAVED_WINDOW_N (saved_windows, k);
6274 window = p->window;
6275 w = XWINDOW (window);
6276 wset_next (w, Qnil);
6278 if (!NILP (p->parent))
6279 wset_parent
6280 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window);
6281 else
6282 wset_parent (w, Qnil);
6284 if (!NILP (p->prev))
6286 wset_prev
6287 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window);
6288 wset_next (XWINDOW (w->prev), p->window);
6290 else
6292 wset_prev (w, Qnil);
6293 if (!NILP (w->parent))
6294 wset_combination (XWINDOW (w->parent),
6295 (XINT (p->total_cols)
6296 != XWINDOW (w->parent)->total_cols),
6297 p->window);
6300 /* If we squirreled away the buffer, restore it now. */
6301 if (BUFFERP (w->combination_limit))
6302 wset_buffer (w, w->combination_limit);
6303 w->pixel_left = XFASTINT (p->pixel_left);
6304 w->pixel_top = XFASTINT (p->pixel_top);
6305 w->pixel_width = XFASTINT (p->pixel_width);
6306 w->pixel_height = XFASTINT (p->pixel_height);
6307 w->left_col = XFASTINT (p->left_col);
6308 w->top_line = XFASTINT (p->top_line);
6309 w->total_cols = XFASTINT (p->total_cols);
6310 w->total_lines = XFASTINT (p->total_lines);
6311 wset_normal_cols (w, p->normal_cols);
6312 wset_normal_lines (w, p->normal_lines);
6313 w->hscroll = XFASTINT (p->hscroll);
6314 w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll);
6315 w->min_hscroll = XFASTINT (p->min_hscroll);
6316 w->hscroll_whole = XFASTINT (p->hscroll_whole);
6317 wset_display_table (w, p->display_table);
6318 w->left_margin_cols = XINT (p->left_margin_cols);
6319 w->right_margin_cols = XINT (p->right_margin_cols);
6320 w->left_fringe_width = XINT (p->left_fringe_width);
6321 w->right_fringe_width = XINT (p->right_fringe_width);
6322 w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
6323 w->scroll_bar_width = XINT (p->scroll_bar_width);
6324 w->scroll_bar_height = XINT (p->scroll_bar_height);
6325 wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
6326 wset_horizontal_scroll_bar_type (w, p->horizontal_scroll_bar_type);
6327 wset_dedicated (w, p->dedicated);
6328 wset_combination_limit (w, p->combination_limit);
6329 /* Restore any window parameters that have been saved.
6330 Parameters that have not been saved are left alone. */
6331 for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
6333 pers = XCAR (tem);
6334 if (CONSP (pers))
6336 if (NILP (XCDR (pers)))
6338 par = Fassq (XCAR (pers), w->window_parameters);
6339 if (CONSP (par) && !NILP (XCDR (par)))
6340 /* Reset a parameter to nil if and only if it
6341 has a non-nil association. Don't make new
6342 associations. */
6343 Fsetcdr (par, Qnil);
6345 else
6346 /* Always restore a non-nil value. */
6347 Fset_window_parameter (window, XCAR (pers), XCDR (pers));
6351 if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
6352 /* If saved buffer is alive, install it. */
6354 wset_buffer (w, p->buffer);
6355 w->start_at_line_beg = !NILP (p->start_at_line_beg);
6356 set_marker_restricted (w->start, p->start, w->contents);
6357 set_marker_restricted (w->pointm, p->pointm, w->contents);
6358 set_marker_restricted (w->old_pointm, p->old_pointm, w->contents);
6359 /* As documented in Fcurrent_window_configuration, don't
6360 restore the location of point in the buffer which was
6361 current when the window configuration was recorded. */
6362 if (!EQ (p->buffer, new_current_buffer)
6363 && XBUFFER (p->buffer) == current_buffer)
6364 Fgoto_char (w->pointm);
6366 else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
6367 /* Keep window's old buffer; make sure the markers are real. */
6369 /* Set window markers at start of visible range. */
6370 if (XMARKER (w->start)->buffer == 0)
6371 set_marker_restricted_both (w->start, w->contents, 0, 0);
6372 if (XMARKER (w->pointm)->buffer == 0)
6373 set_marker_restricted_both
6374 (w->pointm, w->contents,
6375 BUF_PT (XBUFFER (w->contents)),
6376 BUF_PT_BYTE (XBUFFER (w->contents)));
6377 if (XMARKER (w->old_pointm)->buffer == 0)
6378 set_marker_restricted_both
6379 (w->old_pointm, w->contents,
6380 BUF_PT (XBUFFER (w->contents)),
6381 BUF_PT_BYTE (XBUFFER (w->contents)));
6382 w->start_at_line_beg = true;
6384 else if (!NILP (w->start))
6385 /* Leaf window has no live buffer, get one. */
6387 /* Get the buffer via other_buffer_safely in order to
6388 avoid showing an unimportant buffer and, if necessary, to
6389 recreate *scratch* in the course (part of Juanma's bs-show
6390 scenario from March 2011). */
6391 wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
6392 /* This will set the markers to beginning of visible
6393 range. */
6394 set_marker_restricted_both (w->start, w->contents, 0, 0);
6395 set_marker_restricted_both (w->pointm, w->contents, 0, 0);
6396 set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
6397 w->start_at_line_beg = true;
6398 if (!NILP (w->dedicated))
6399 /* Record this window as dead. */
6400 dead_windows = Fcons (window, dead_windows);
6401 /* Make sure window is no more dedicated. */
6402 wset_dedicated (w, Qnil);
6406 fset_root_window (f, data->root_window);
6407 /* Arrange *not* to restore point in the buffer that was
6408 current when the window configuration was saved. */
6409 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
6410 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6411 make_number (old_point),
6412 XWINDOW (data->current_window)->contents);
6414 /* In the following call to `select-window', prevent "swapping out
6415 point" in the old selected window using the buffer that has
6416 been restored into it. We already swapped out that point from
6417 that window's old buffer.
6419 Do not record the buffer here. We do that in a separate call
6420 to select_window below. See also Bug#16207. */
6421 select_window (data->current_window, Qt, true);
6422 BVAR (XBUFFER (XWINDOW (selected_window)->contents),
6423 last_selected_window)
6424 = selected_window;
6426 if (NILP (data->focus_frame)
6427 || (FRAMEP (data->focus_frame)
6428 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6429 Fredirect_frame_focus (frame, data->focus_frame);
6431 /* Now, free glyph matrices in windows that were not reused. */
6432 for (i = 0; i < n_leaf_windows; i++)
6433 if (NILP (leaf_windows[i]->contents))
6434 free_window_matrices (leaf_windows[i]);
6436 /* Allow x_set_window_size again and apply frame size changes if
6437 needed. */
6438 f->can_x_set_window_size = true;
6439 adjust_frame_size (f, -1, -1, 1, false, Qset_window_configuration);
6441 adjust_frame_glyphs (f);
6442 unblock_input ();
6444 /* Scan dead buffer windows. */
6445 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
6447 window = XCAR (dead_windows);
6448 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
6449 delete_deletable_window (window);
6452 /* Record the selected window's buffer here. The window should
6453 already be the selected one from the call above. */
6454 select_window (data->current_window, Qnil, false);
6456 /* Fselect_window will have made f the selected frame, so we
6457 reselect the proper frame here. Fhandle_switch_frame will change the
6458 selected window too, but that doesn't make the call to
6459 Fselect_window above totally superfluous; it still sets f's
6460 selected window. */
6461 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6462 do_switch_frame (data->selected_frame, 0, 0, Qnil);
6464 run_window_configuration_change_hook (f);
6467 if (!NILP (new_current_buffer))
6469 Fset_buffer (new_current_buffer);
6470 /* If the new current buffer doesn't appear in the selected
6471 window, go to its old point (see bug#12208). */
6472 if (!EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
6473 Fgoto_char (make_number (old_point));
6476 Vminibuf_scroll_window = data->minibuf_scroll_window;
6477 minibuf_selected_window = data->minibuf_selected_window;
6479 SAFE_FREE ();
6480 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6484 void
6485 restore_window_configuration (Lisp_Object configuration)
6487 Fset_window_configuration (configuration);
6491 /* If WINDOW is an internal window, recursively delete all child windows
6492 reachable via the next and contents slots of WINDOW. Otherwise setup
6493 WINDOW to not show any buffer. */
6495 void
6496 delete_all_child_windows (Lisp_Object window)
6498 register struct window *w;
6500 w = XWINDOW (window);
6502 if (!NILP (w->next))
6503 /* Delete WINDOW's siblings (we traverse postorderly). */
6504 delete_all_child_windows (w->next);
6506 if (WINDOWP (w->contents))
6508 delete_all_child_windows (w->contents);
6509 wset_combination (w, false, Qnil);
6511 else if (BUFFERP (w->contents))
6513 unshow_buffer (w);
6514 unchain_marker (XMARKER (w->pointm));
6515 unchain_marker (XMARKER (w->old_pointm));
6516 unchain_marker (XMARKER (w->start));
6517 /* Since combination limit makes sense for an internal windows
6518 only, we use this slot to save the buffer for the sake of
6519 possible resurrection in Fset_window_configuration. */
6520 wset_combination_limit (w, w->contents);
6521 wset_buffer (w, Qnil);
6524 Vwindow_list = Qnil;
6527 static ptrdiff_t
6528 count_windows (struct window *window)
6530 ptrdiff_t count = 1;
6531 if (!NILP (window->next))
6532 count += count_windows (XWINDOW (window->next));
6533 if (WINDOWP (window->contents))
6534 count += count_windows (XWINDOW (window->contents));
6535 return count;
6539 /* Fill vector FLAT with leaf windows under W, starting at index I.
6540 Value is last index + 1. */
6541 static ptrdiff_t
6542 get_leaf_windows (struct window *w, struct window **flat, ptrdiff_t i)
6544 while (w)
6546 if (WINDOWP (w->contents))
6547 i = get_leaf_windows (XWINDOW (w->contents), flat, i);
6548 else
6549 flat[i++] = w;
6551 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6554 return i;
6558 /* Return a pointer to the glyph W's physical cursor is on. Value is
6559 null if W's current matrix is invalid, so that no meaningful glyph
6560 can be returned. */
6561 struct glyph *
6562 get_phys_cursor_glyph (struct window *w)
6564 struct glyph_row *row;
6565 struct glyph *glyph;
6566 int hpos = w->phys_cursor.hpos;
6568 if (!(w->phys_cursor.vpos >= 0
6569 && w->phys_cursor.vpos < w->current_matrix->nrows))
6570 return NULL;
6572 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
6573 if (!row->enabled_p)
6574 return NULL;
6576 if (w->hscroll)
6578 /* When the window is hscrolled, cursor hpos can legitimately be
6579 out of bounds, but we draw the cursor at the corresponding
6580 window margin in that case. */
6581 if (!row->reversed_p && hpos < 0)
6582 hpos = 0;
6583 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
6584 hpos = row->used[TEXT_AREA] - 1;
6587 if (0 <= hpos && hpos < row->used[TEXT_AREA])
6588 glyph = row->glyphs[TEXT_AREA] + hpos;
6589 else
6590 glyph = NULL;
6592 return glyph;
6596 static ptrdiff_t
6597 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i)
6599 struct saved_window *p;
6600 struct window *w;
6601 Lisp_Object tem, pers, par;
6603 for (; !NILP (window); window = w->next)
6605 p = SAVED_WINDOW_N (vector, i);
6606 w = XWINDOW (window);
6608 wset_temslot (w, make_number (i)); i++;
6609 p->window = window;
6610 p->buffer = (WINDOW_LEAF_P (w) ? w->contents : Qnil);
6611 p->pixel_left = make_number (w->pixel_left);
6612 p->pixel_top = make_number (w->pixel_top);
6613 p->pixel_width = make_number (w->pixel_width);
6614 p->pixel_height = make_number (w->pixel_height);
6615 p->left_col = make_number (w->left_col);
6616 p->top_line = make_number (w->top_line);
6617 p->total_cols = make_number (w->total_cols);
6618 p->total_lines = make_number (w->total_lines);
6619 p->normal_cols = w->normal_cols;
6620 p->normal_lines = w->normal_lines;
6621 XSETFASTINT (p->hscroll, w->hscroll);
6622 p->suspend_auto_hscroll = w->suspend_auto_hscroll ? Qt : Qnil;
6623 XSETFASTINT (p->min_hscroll, w->min_hscroll);
6624 XSETFASTINT (p->hscroll_whole, w->hscroll_whole);
6625 p->display_table = w->display_table;
6626 p->left_margin_cols = make_number (w->left_margin_cols);
6627 p->right_margin_cols = make_number (w->right_margin_cols);
6628 p->left_fringe_width = make_number (w->left_fringe_width);
6629 p->right_fringe_width = make_number (w->right_fringe_width);
6630 p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
6631 p->scroll_bar_width = make_number (w->scroll_bar_width);
6632 p->scroll_bar_height = make_number (w->scroll_bar_height);
6633 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6634 p->horizontal_scroll_bar_type = w->horizontal_scroll_bar_type;
6635 p->dedicated = w->dedicated;
6636 p->combination_limit = w->combination_limit;
6637 p->window_parameters = Qnil;
6639 if (!NILP (Vwindow_persistent_parameters))
6641 /* Run cycle detection on Vwindow_persistent_parameters. */
6642 Lisp_Object tortoise, hare;
6644 hare = tortoise = Vwindow_persistent_parameters;
6645 while (CONSP (hare))
6647 hare = XCDR (hare);
6648 if (!CONSP (hare))
6649 break;
6651 hare = XCDR (hare);
6652 tortoise = XCDR (tortoise);
6654 if (EQ (hare, tortoise))
6655 /* Reset Vwindow_persistent_parameters to Qnil. */
6657 Vwindow_persistent_parameters = Qnil;
6658 break;
6662 for (tem = Vwindow_persistent_parameters; CONSP (tem);
6663 tem = XCDR (tem))
6665 pers = XCAR (tem);
6666 /* Save values for persistent window parameters. */
6667 if (CONSP (pers) && !NILP (XCDR (pers)))
6669 par = Fassq (XCAR (pers), w->window_parameters);
6670 if (NILP (par))
6671 /* If the window has no value for the parameter,
6672 make one. */
6673 p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
6674 p->window_parameters);
6675 else
6676 /* If the window has a value for the parameter,
6677 save it. */
6678 p->window_parameters = Fcons (Fcons (XCAR (par),
6679 XCDR (par)),
6680 p->window_parameters);
6685 if (BUFFERP (w->contents))
6687 /* Save w's value of point in the window configuration. If w
6688 is the selected window, then get the value of point from
6689 the buffer; pointm is garbage in the selected window. */
6690 if (EQ (window, selected_window))
6691 p->pointm = build_marker (XBUFFER (w->contents),
6692 BUF_PT (XBUFFER (w->contents)),
6693 BUF_PT_BYTE (XBUFFER (w->contents)));
6694 else
6695 p->pointm = Fcopy_marker (w->pointm, Qnil);
6696 p->old_pointm = Fcopy_marker (w->old_pointm, Qnil);
6697 XMARKER (p->pointm)->insertion_type
6698 = !NILP (buffer_local_value /* Don't signal error if void. */
6699 (Qwindow_point_insertion_type, w->contents));
6700 XMARKER (p->old_pointm)->insertion_type
6701 = !NILP (buffer_local_value /* Don't signal error if void. */
6702 (Qwindow_point_insertion_type, w->contents));
6704 p->start = Fcopy_marker (w->start, Qnil);
6705 p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
6707 else
6709 p->pointm = Qnil;
6710 p->old_pointm = Qnil;
6711 p->start = Qnil;
6712 p->start_at_line_beg = Qnil;
6715 p->parent = NILP (w->parent) ? Qnil : XWINDOW (w->parent)->temslot;
6716 p->prev = NILP (w->prev) ? Qnil : XWINDOW (w->prev)->temslot;
6718 if (WINDOWP (w->contents))
6719 i = save_window_save (w->contents, vector, i);
6722 return i;
6725 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6726 Scurrent_window_configuration, 0, 1, 0,
6727 doc: /* Return an object representing the current window configuration of FRAME.
6728 If FRAME is nil or omitted, use the selected frame.
6729 This describes the number of windows, their sizes and current buffers,
6730 and for each displayed buffer, where display starts, and the position of
6731 point. An exception is made for point in the current buffer:
6732 its value is -not- saved.
6733 This also records the currently selected frame, and FRAME's focus
6734 redirection (see `redirect-frame-focus'). The variable
6735 `window-persistent-parameters' specifies which window parameters are
6736 saved by this function. */)
6737 (Lisp_Object frame)
6739 Lisp_Object tem;
6740 ptrdiff_t i, n_windows;
6741 struct save_window_data *data;
6742 struct frame *f = decode_live_frame (frame);
6744 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6745 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6746 PVEC_WINDOW_CONFIGURATION);
6748 data->frame_cols = FRAME_COLS (f);
6749 data->frame_lines = FRAME_LINES (f);
6750 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6751 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6752 data->frame_text_width = FRAME_TEXT_WIDTH (f);
6753 data->frame_text_height = FRAME_TEXT_HEIGHT (f);
6754 data->frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
6755 data->frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
6756 data->selected_frame = selected_frame;
6757 data->current_window = FRAME_SELECTED_WINDOW (f);
6758 XSETBUFFER (data->current_buffer, current_buffer);
6759 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6760 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6761 data->root_window = FRAME_ROOT_WINDOW (f);
6762 data->focus_frame = FRAME_FOCUS_FRAME (f);
6763 tem = make_uninit_vector (n_windows);
6764 data->saved_windows = tem;
6765 for (i = 0; i < n_windows; i++)
6766 ASET (tem, i,
6767 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil));
6768 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6769 XSETWINDOW_CONFIGURATION (tem, data);
6770 return (tem);
6773 /* Called after W's margins, fringes or scroll bars was adjusted. */
6775 static void
6776 apply_window_adjustment (struct window *w)
6778 eassert (w);
6779 clear_glyph_matrix (w->current_matrix);
6780 w->window_end_valid = false;
6781 windows_or_buffers_changed = 30;
6782 wset_redisplay (w);
6783 adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
6787 /***********************************************************************
6788 Marginal Areas
6789 ***********************************************************************/
6791 static int
6792 extract_dimension (Lisp_Object dimension)
6794 if (NILP (dimension))
6795 return -1;
6796 CHECK_RANGED_INTEGER (dimension, 0, INT_MAX);
6797 return XINT (dimension);
6800 static struct window *
6801 set_window_margins (struct window *w, Lisp_Object left_width,
6802 Lisp_Object right_width)
6804 int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
6805 int left = NILP (left_width) ? 0 : extract_dimension (left_width);
6806 int right = NILP (right_width) ? 0 : extract_dimension (right_width);
6808 if (w->left_margin_cols != left || w->right_margin_cols != right)
6810 /* Don't change anything if new margins won't fit. */
6811 if ((WINDOW_PIXEL_WIDTH (w)
6812 - WINDOW_FRINGES_WIDTH (w)
6813 - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
6814 - (left + right) * unit)
6815 >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
6817 w->left_margin_cols = left;
6818 w->right_margin_cols = right;
6820 return w;
6822 else
6823 return NULL;
6825 else
6826 return NULL;
6829 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6830 2, 3, 0,
6831 doc: /* Set width of marginal areas of window WINDOW.
6832 WINDOW must be a live window and defaults to the selected one.
6834 Second arg LEFT-WIDTH specifies the number of character cells to
6835 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6836 does the same for the right marginal area. A nil width parameter
6837 means no margin.
6839 Return t if any margin was actually changed and nil otherwise. */)
6840 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6842 struct window *w = set_window_margins (decode_live_window (window),
6843 left_width, right_width);
6844 return w ? (apply_window_adjustment (w), Qt) : Qnil;
6848 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6849 0, 1, 0,
6850 doc: /* Get width of marginal areas of window WINDOW.
6851 WINDOW must be a live window and defaults to the selected one.
6853 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6854 If a marginal area does not exist, its width will be returned
6855 as nil. */)
6856 (Lisp_Object window)
6858 struct window *w = decode_live_window (window);
6859 return Fcons (w->left_margin_cols
6860 ? make_number (w->left_margin_cols) : Qnil,
6861 w->right_margin_cols
6862 ? make_number (w->right_margin_cols) : Qnil);
6867 /***********************************************************************
6868 Fringes
6869 ***********************************************************************/
6871 static struct window *
6872 set_window_fringes (struct window *w, Lisp_Object left_width,
6873 Lisp_Object right_width, Lisp_Object outside_margins)
6875 bool outside = !NILP (outside_margins);
6876 int left = extract_dimension (left_width);
6877 int right = extract_dimension (right_width);
6879 /* Do nothing on a tty or if nothing to actually change. */
6880 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6881 && (w->left_fringe_width != left
6882 || w->right_fringe_width != right
6883 || w->fringes_outside_margins != outside))
6885 if (left > 0 || right > 0)
6887 /* Don't change anything if new fringes don't fit. */
6888 if ((WINDOW_PIXEL_WIDTH (w)
6889 - WINDOW_MARGINS_WIDTH (w)
6890 - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
6891 - max (left, 0) - max (right, 0))
6892 < MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
6893 return NULL;
6896 w->left_fringe_width = left;
6897 w->right_fringe_width = right;
6898 w->fringes_outside_margins = outside;
6900 return w;
6902 else
6903 return NULL;
6906 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6907 2, 4, 0,
6908 doc: /* Set the fringe widths of window WINDOW.
6909 WINDOW must be a live window and defaults to the selected one.
6911 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6912 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6913 fringe width. If a fringe width arg is nil, that means to use the
6914 frame's default fringe width. Default fringe widths can be set with
6915 the command `set-fringe-style'.
6916 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6917 outside of the display margins. By default, fringes are drawn between
6918 display marginal areas and the text area.
6920 Return t if any fringe was actually changed and nil otherwise. */)
6921 (Lisp_Object window, Lisp_Object left_width,
6922 Lisp_Object right_width, Lisp_Object outside_margins)
6924 struct window *w
6925 = set_window_fringes (decode_live_window (window),
6926 left_width, right_width, outside_margins);
6927 return w ? (apply_window_adjustment (w), Qt) : Qnil;
6931 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6932 0, 1, 0,
6933 doc: /* Get width of fringes of window WINDOW.
6934 WINDOW must be a live window and defaults to the selected one.
6936 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6937 (Lisp_Object window)
6939 struct window *w = decode_live_window (window);
6941 return list3 (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6942 make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6943 WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil);
6948 /***********************************************************************
6949 Scroll bars
6950 ***********************************************************************/
6952 static struct window *
6953 set_window_scroll_bars (struct window *w, Lisp_Object width,
6954 Lisp_Object vertical_type, Lisp_Object height,
6955 Lisp_Object horizontal_type)
6957 int iwidth = extract_dimension (width);
6958 bool changed = false;
6960 if (iwidth == 0)
6961 vertical_type = Qnil;
6963 if (!(NILP (vertical_type)
6964 || EQ (vertical_type, Qleft)
6965 || EQ (vertical_type, Qright)
6966 || EQ (vertical_type, Qt)))
6967 error ("Invalid type of vertical scroll bar");
6969 if (w->scroll_bar_width != iwidth
6970 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6972 /* Don't change anything if new scroll bar won't fit. */
6973 if ((WINDOW_PIXEL_WIDTH (w)
6974 - WINDOW_MARGINS_WIDTH (w)
6975 - WINDOW_FRINGES_WIDTH (w)
6976 - max (iwidth, 0))
6977 >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
6979 w->scroll_bar_width = iwidth;
6980 wset_vertical_scroll_bar_type (w, vertical_type);
6981 changed = true;
6985 #if USE_HORIZONTAL_SCROLL_BARS
6987 int iheight = extract_dimension (height);
6989 if (MINI_WINDOW_P (w) || iheight == 0)
6990 horizontal_type = Qnil;
6992 if (!(NILP (horizontal_type)
6993 || EQ (horizontal_type, Qbottom)
6994 || EQ (horizontal_type, Qt)))
6995 error ("Invalid type of horizontal scroll bar");
6997 if (w->scroll_bar_height != iheight
6998 || !EQ (w->horizontal_scroll_bar_type, horizontal_type))
7000 /* Don't change anything if new scroll bar won't fit. */
7001 if ((WINDOW_PIXEL_HEIGHT (w)
7002 - WINDOW_HEADER_LINE_HEIGHT (w)
7003 - WINDOW_MODE_LINE_HEIGHT (w)
7004 - max (iheight, 0))
7005 >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w))
7007 w->scroll_bar_height = iheight;
7008 wset_horizontal_scroll_bar_type (w, horizontal_type);
7009 changed = true;
7013 #else
7014 wset_horizontal_scroll_bar_type (w, Qnil);
7015 #endif
7017 return changed ? w : NULL;
7020 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
7021 Sset_window_scroll_bars, 1, 5, 0,
7022 doc: /* Set width and type of scroll bars of window WINDOW.
7023 WINDOW must be a live window and defaults to the selected one.
7025 Second parameter WIDTH specifies the pixel width for the vertical scroll
7026 bar. If WIDTH is nil, use the scroll-bar width of WINDOW's frame.
7027 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
7028 bar: left, right, or nil. If VERTICAL-TYPE is t, this means use the
7029 frame's scroll-bar type.
7031 Fourth parameter HEIGHT specifies the pixel height for the horizontal
7032 scroll bar. If HEIGHT is nil, use the scroll-bar height of WINDOW's
7033 frame. Fifth parameter HORIZONTAL-TYPE specifies the type of the
7034 horizontal scroll bar: nil, bottom, or t. If HORIZONTAL-TYPE is t, this
7035 means to use the frame's horizontal scroll-bar type.
7037 Return t if scroll bars were actually changed and nil otherwise. */)
7038 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type,
7039 Lisp_Object height, Lisp_Object horizontal_type)
7041 struct window *w
7042 = set_window_scroll_bars (decode_live_window (window),
7043 width, vertical_type, height, horizontal_type);
7044 return w ? (apply_window_adjustment (w), Qt) : Qnil;
7048 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
7049 0, 1, 0,
7050 doc: /* Get width and type of scroll bars of window WINDOW.
7051 WINDOW must be a live window and defaults to the selected one.
7053 Value is a list of the form (WIDTH COLUMNS VERTICAL-TYPE HEIGHT LINES
7054 HORIZONTAL-TYPE). If WIDTH or HEIGHT is nil or VERTICAL-TYPE or
7055 HORIZONTAL-TYPE is t, the window is using the frame's corresponding
7056 value. */)
7057 (Lisp_Object window)
7059 struct window *w = decode_live_window (window);
7061 return Fcons (((w->scroll_bar_width >= 0)
7062 ? make_number (w->scroll_bar_width)
7063 : Qnil),
7064 list5 (make_number (WINDOW_SCROLL_BAR_COLS (w)),
7065 w->vertical_scroll_bar_type,
7066 ((w->scroll_bar_height >= 0)
7067 ? make_number (w->scroll_bar_height)
7068 : Qnil),
7069 make_number (WINDOW_SCROLL_BAR_LINES (w)),
7070 w->horizontal_scroll_bar_type));
7073 /***********************************************************************
7074 Smooth scrolling
7075 ***********************************************************************/
7077 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
7078 doc: /* Return the amount by which WINDOW is scrolled vertically.
7079 If WINDOW is omitted or nil, it defaults to the selected window.
7080 Normally, value is a multiple of the canonical character height of WINDOW;
7081 optional second arg PIXELS-P means value is measured in pixels. */)
7082 (Lisp_Object window, Lisp_Object pixels_p)
7084 Lisp_Object result;
7085 struct window *w = decode_live_window (window);
7086 struct frame *f = XFRAME (w->frame);
7088 if (FRAME_WINDOW_P (f))
7089 result = (NILP (pixels_p)
7090 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
7091 : make_number (-w->vscroll));
7092 else
7093 result = make_number (0);
7094 return result;
7098 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
7099 2, 3, 0,
7100 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
7101 WINDOW nil means use the selected window. Normally, VSCROLL is a
7102 non-negative multiple of the canonical character height of WINDOW;
7103 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
7104 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
7105 corresponds to an integral number of pixels. The return value is the
7106 result of this rounding.
7107 If PIXELS-P is non-nil, the return value is VSCROLL. */)
7108 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
7110 struct window *w = decode_live_window (window);
7111 struct frame *f = XFRAME (w->frame);
7113 CHECK_NUMBER_OR_FLOAT (vscroll);
7115 if (FRAME_WINDOW_P (f))
7117 int old_dy = w->vscroll;
7119 w->vscroll = - (NILP (pixels_p)
7120 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
7121 : XFLOATINT (vscroll));
7122 w->vscroll = min (w->vscroll, 0);
7124 if (w->vscroll != old_dy)
7126 /* Adjust glyph matrix of the frame if the virtual display
7127 area becomes larger than before. */
7128 if (w->vscroll < 0 && w->vscroll < old_dy)
7129 adjust_frame_glyphs (f);
7131 /* Prevent redisplay shortcuts. */
7132 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = true;
7136 return Fwindow_vscroll (window, pixels_p);
7140 /* Call FN for all leaf windows on frame F. FN is called with the
7141 first argument being a pointer to the leaf window, and with
7142 additional argument USER_DATA. Stops when FN returns 0. */
7144 static void
7145 foreach_window (struct frame *f, bool (*fn) (struct window *, void *),
7146 void *user_data)
7148 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
7149 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
7150 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
7154 /* Helper function for foreach_window. Call FN for all leaf windows
7155 reachable from W. FN is called with the first argument being a
7156 pointer to the leaf window, and with additional argument USER_DATA.
7157 Stop when FN returns false. Value is false if stopped by FN. */
7159 static bool
7160 foreach_window_1 (struct window *w, bool (*fn) (struct window *, void *),
7161 void *user_data)
7163 bool cont;
7165 for (cont = true; w && cont;)
7167 if (WINDOWP (w->contents))
7168 cont = foreach_window_1 (XWINDOW (w->contents), fn, user_data);
7169 else
7170 cont = fn (w, user_data);
7172 w = NILP (w->next) ? 0 : XWINDOW (w->next);
7175 return cont;
7178 /***********************************************************************
7179 Initialization
7180 ***********************************************************************/
7182 /* Return true if window configurations CONFIGURATION1 and CONFIGURATION2
7183 describe the same state of affairs. This is used by Fequal.
7185 IGNORE_POSITIONS means ignore non-matching scroll positions
7186 and the like.
7188 This ignores a couple of things like the dedication status of
7189 window, combination_limit and the like. This might have to be
7190 fixed. */
7192 bool
7193 compare_window_configurations (Lisp_Object configuration1,
7194 Lisp_Object configuration2,
7195 bool ignore_positions)
7197 register struct save_window_data *d1, *d2;
7198 struct Lisp_Vector *sws1, *sws2;
7199 ptrdiff_t i;
7201 CHECK_WINDOW_CONFIGURATION (configuration1);
7202 CHECK_WINDOW_CONFIGURATION (configuration2);
7204 d1 = (struct save_window_data *) XVECTOR (configuration1);
7205 d2 = (struct save_window_data *) XVECTOR (configuration2);
7206 sws1 = XVECTOR (d1->saved_windows);
7207 sws2 = XVECTOR (d2->saved_windows);
7209 /* Frame settings must match. */
7210 if (d1->frame_cols != d2->frame_cols
7211 || d1->frame_lines != d2->frame_lines
7212 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
7213 || !EQ (d1->selected_frame, d2->selected_frame)
7214 || !EQ (d1->current_buffer, d2->current_buffer)
7215 || (!ignore_positions
7216 && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
7217 || !EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)))
7218 || !EQ (d1->focus_frame, d2->focus_frame)
7219 /* Verify that the two configurations have the same number of windows. */
7220 || sws1->header.size != sws2->header.size)
7221 return false;
7223 for (i = 0; i < sws1->header.size; i++)
7225 struct saved_window *sw1, *sw2;
7227 sw1 = SAVED_WINDOW_N (sws1, i);
7228 sw2 = SAVED_WINDOW_N (sws2, i);
7230 if (
7231 /* The "current" windows in the two configurations must
7232 correspond to each other. */
7233 EQ (d1->current_window, sw1->window)
7234 != EQ (d2->current_window, sw2->window)
7235 /* Windows' buffers must match. */
7236 || !EQ (sw1->buffer, sw2->buffer)
7237 || !EQ (sw1->pixel_left, sw2->pixel_left)
7238 || !EQ (sw1->pixel_top, sw2->pixel_top)
7239 || !EQ (sw1->pixel_height, sw2->pixel_height)
7240 || !EQ (sw1->pixel_width, sw2->pixel_width)
7241 || !EQ (sw1->left_col, sw2->left_col)
7242 || !EQ (sw1->top_line, sw2->top_line)
7243 || !EQ (sw1->total_cols, sw2->total_cols)
7244 || !EQ (sw1->total_lines, sw2->total_lines)
7245 || !EQ (sw1->display_table, sw2->display_table)
7246 /* The next two disjuncts check the window structure for
7247 equality. */
7248 || !EQ (sw1->parent, sw2->parent)
7249 || !EQ (sw1->prev, sw2->prev)
7250 || (!ignore_positions
7251 && (!EQ (sw1->hscroll, sw2->hscroll)
7252 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
7253 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
7254 || NILP (Fequal (sw1->start, sw2->start))
7255 || NILP (Fequal (sw1->pointm, sw2->pointm))))
7256 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
7257 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
7258 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
7259 || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
7260 || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
7261 || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
7262 || !EQ (sw1->scroll_bar_height, sw2->scroll_bar_height)
7263 || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type)
7264 || !EQ (sw1->horizontal_scroll_bar_type, sw2->horizontal_scroll_bar_type))
7265 return false;
7268 return true;
7271 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7272 Scompare_window_configurations, 2, 2, 0,
7273 doc: /* Compare two window configurations as regards the structure of windows.
7274 This function ignores details such as the values of point
7275 and scrolling positions. */)
7276 (Lisp_Object x, Lisp_Object y)
7278 if (compare_window_configurations (x, y, true))
7279 return Qt;
7280 return Qnil;
7283 void
7284 init_window_once (void)
7286 struct frame *f = make_initial_frame ();
7287 XSETFRAME (selected_frame, f);
7288 Vterminal_frame = selected_frame;
7289 minibuf_window = f->minibuffer_window;
7290 selected_window = f->selected_window;
7293 void
7294 init_window (void)
7296 Vwindow_list = Qnil;
7299 void
7300 syms_of_window (void)
7302 DEFSYM (Qscroll_up, "scroll-up");
7303 DEFSYM (Qscroll_down, "scroll-down");
7304 DEFSYM (Qscroll_command, "scroll-command");
7306 Fput (Qscroll_up, Qscroll_command, Qt);
7307 Fput (Qscroll_down, Qscroll_command, Qt);
7309 DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
7310 DEFSYM (Qwindowp, "windowp");
7311 DEFSYM (Qwindow_configuration_p, "window-configuration-p");
7312 DEFSYM (Qwindow_live_p, "window-live-p");
7313 DEFSYM (Qwindow_valid_p, "window-valid-p");
7314 DEFSYM (Qwindow_deletable_p, "window-deletable-p");
7315 DEFSYM (Qdelete_window, "delete-window");
7316 DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
7317 DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
7318 DEFSYM (Qwindow_sanitize_window_sizes, "window--sanitize-window-sizes");
7319 DEFSYM (Qwindow_pixel_to_total, "window--pixel-to-total");
7320 DEFSYM (Qsafe, "safe");
7321 DEFSYM (Qdisplay_buffer, "display-buffer");
7322 DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
7323 DEFSYM (Qrecord_window_buffer, "record-window-buffer");
7324 DEFSYM (Qget_mru_window, "get-mru-window");
7325 DEFSYM (Qwindow_size, "window-size");
7326 DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
7327 DEFSYM (Qabove, "above");
7328 DEFSYM (Qbelow, "below");
7329 DEFSYM (Qclone_of, "clone-of");
7330 DEFSYM (Qfloor, "floor");
7331 DEFSYM (Qceiling, "ceiling");
7333 staticpro (&Vwindow_list);
7335 minibuf_selected_window = Qnil;
7336 staticpro (&minibuf_selected_window);
7338 window_scroll_pixel_based_preserve_x = -1;
7339 window_scroll_pixel_based_preserve_y = -1;
7340 window_scroll_preserve_hpos = -1;
7341 window_scroll_preserve_vpos = -1;
7343 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
7344 doc: /* Non-nil means call as function to display a help buffer.
7345 The function is called with one argument, the buffer to be displayed.
7346 Used by `with-output-to-temp-buffer'.
7347 If this function is used, then it must do the entire job of showing
7348 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7349 Vtemp_buffer_show_function = Qnil;
7351 DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
7352 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7353 Vminibuf_scroll_window = Qnil;
7355 DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
7356 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7357 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7358 is displayed in the `mode-line' face. */);
7359 mode_line_in_non_selected_windows = true;
7361 DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
7362 doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window. */);
7363 Vother_window_scroll_buffer = Qnil;
7365 DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
7366 doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7367 auto_window_vscroll_p = true;
7369 DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
7370 doc: /* Number of lines of continuity when scrolling by screenfuls. */);
7371 next_screen_context_lines = 2;
7373 DEFVAR_LISP ("scroll-preserve-screen-position",
7374 Vscroll_preserve_screen_position,
7375 doc: /* Controls if scroll commands move point to keep its screen position unchanged.
7376 A value of nil means point does not keep its screen position except
7377 at the scroll margin or window boundary respectively.
7378 A value of t means point keeps its screen position if the scroll
7379 command moved it vertically out of the window, e.g. when scrolling
7380 by full screens.
7381 Any other value means point always keeps its screen position.
7382 Scroll commands should have the `scroll-command' property
7383 on their symbols to be controlled by this variable. */);
7384 Vscroll_preserve_screen_position = Qnil;
7386 DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
7387 doc: /* Type of marker to use for `window-point'. */);
7388 Vwindow_point_insertion_type = Qnil;
7389 DEFSYM (Qwindow_point_insertion_type, "window_point_insertion_type");
7391 DEFVAR_LISP ("window-configuration-change-hook",
7392 Vwindow_configuration_change_hook,
7393 doc: /* Functions to call when window configuration changes.
7394 The buffer-local part is run once per window, with the relevant window
7395 selected; while the global part is run only once for the modified frame,
7396 with the relevant frame selected. */);
7397 Vwindow_configuration_change_hook = Qnil;
7399 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
7400 doc: /* Non-nil means `recenter' redraws entire frame.
7401 If this option is non-nil, then the `recenter' command with a nil
7402 argument will redraw the entire frame; the special value `tty' causes
7403 the frame to be redrawn only if it is a tty frame. */);
7404 Vrecenter_redisplay = Qtty;
7406 DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
7407 doc: /* If t, resize window combinations proportionally.
7408 If this variable is nil, splitting a window gets the entire screen space
7409 for displaying the new window from the window to split. Deleting and
7410 resizing a window preferably resizes one adjacent window only.
7412 If this variable is t, splitting a window tries to get the space
7413 proportionally from all windows in the same combination. This also
7414 allows to split a window that is otherwise too small or of fixed size.
7415 Resizing and deleting a window proportionally resize all windows in the
7416 same combination.
7418 Other values are reserved for future use.
7420 This variable takes no effect if the variable `window-combination-limit' is
7421 non-nil. */);
7422 Vwindow_combination_resize = Qnil;
7424 DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
7425 doc: /* If non-nil, splitting a window makes a new parent window.
7426 The following values are recognized:
7428 nil means splitting a window will create a new parent window only if the
7429 window has no parent window or the window shall become part of a
7430 combination orthogonal to the one it is part of.
7432 `window-size' means that splitting a window for displaying a buffer
7433 makes a new parent window provided `display-buffer' is supposed to
7434 explicitly set the window's size due to the presence of a
7435 `window-height' or `window-width' entry in the alist used by
7436 `display-buffer'. Otherwise, this value is handled like nil.
7438 `temp-buffer' means that splitting a window for displaying a temporary
7439 buffer always makes a new parent window. Otherwise, this value is
7440 handled like nil.
7442 `display-buffer' means that splitting a window for displaying a buffer
7443 always makes a new parent window. Since temporary buffers are
7444 displayed by the function `display-buffer', this value is stronger
7445 than `temp-buffer'. Splitting a window for other purpose makes a
7446 new parent window only if needed.
7448 t means that splitting a window always creates a new parent window. If
7449 all splits behave this way, each frame's window tree is a binary
7450 tree and every window but the frame's root window has exactly one
7451 sibling.
7453 Other values are reserved for future use. */);
7454 Vwindow_combination_limit = Qwindow_size;
7456 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
7457 doc: /* Alist of persistent window parameters.
7458 This alist specifies which window parameters shall get saved by
7459 `current-window-configuration' and `window-state-get' and subsequently
7460 restored to their previous values by `set-window-configuration' and
7461 `window-state-put'.
7463 The car of each entry of this alist is the symbol specifying the
7464 parameter. The cdr is one of the following:
7466 nil means the parameter is neither saved by `window-state-get' nor by
7467 `current-window-configuration'.
7469 t means the parameter is saved by `current-window-configuration' and,
7470 provided its WRITABLE argument is nil, by `window-state-get'.
7472 The symbol `writable' means the parameter is saved unconditionally by
7473 both `current-window-configuration' and `window-state-get'. Do not use
7474 this value for parameters without read syntax (like windows or frames).
7476 Parameters not saved by `current-window-configuration' or
7477 `window-state-get' are left alone by `set-window-configuration'
7478 respectively are not installed by `window-state-put'. */);
7479 Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
7481 DEFVAR_BOOL ("window-resize-pixelwise", window_resize_pixelwise,
7482 doc: /* Non-nil means resize windows pixelwise.
7483 This currently affects the functions: `split-window', `maximize-window',
7484 `minimize-window', `fit-window-to-buffer' and `fit-frame-to-buffer', and
7485 all functions that symmetrically resize a parent window.
7487 Note that when a frame's pixel size is not a multiple of the
7488 frame's character size, at least one window may get resized
7489 pixelwise even if this option is nil. */);
7490 window_resize_pixelwise = false;
7492 DEFVAR_BOOL ("fast-but-imprecise-scrolling",
7493 Vfast_but_imprecise_scrolling,
7494 doc: /* When non-nil, accelerate scrolling operations.
7495 This comes into play when scrolling rapidly over previously
7496 unfontified buffer regions. Only those portions of the buffer which
7497 are actually going to be displayed get fontified.
7499 Note that this optimization can cause the portion of the buffer
7500 displayed after a scrolling operation to be somewhat inaccurate. */);
7501 Vfast_but_imprecise_scrolling = false;
7503 defsubr (&Sselected_window);
7504 defsubr (&Sminibuffer_window);
7505 defsubr (&Swindow_minibuffer_p);
7506 defsubr (&Swindowp);
7507 defsubr (&Swindow_valid_p);
7508 defsubr (&Swindow_live_p);
7509 defsubr (&Swindow_frame);
7510 defsubr (&Sframe_root_window);
7511 defsubr (&Sframe_first_window);
7512 defsubr (&Sframe_selected_window);
7513 defsubr (&Sset_frame_selected_window);
7514 defsubr (&Spos_visible_in_window_p);
7515 defsubr (&Swindow_line_height);
7516 defsubr (&Swindow_buffer);
7517 defsubr (&Swindow_parent);
7518 defsubr (&Swindow_top_child);
7519 defsubr (&Swindow_left_child);
7520 defsubr (&Swindow_next_sibling);
7521 defsubr (&Swindow_prev_sibling);
7522 defsubr (&Swindow_combination_limit);
7523 defsubr (&Sset_window_combination_limit);
7524 defsubr (&Swindow_use_time);
7525 defsubr (&Swindow_pixel_width);
7526 defsubr (&Swindow_pixel_height);
7527 defsubr (&Swindow_total_width);
7528 defsubr (&Swindow_total_height);
7529 defsubr (&Swindow_normal_size);
7530 defsubr (&Swindow_new_pixel);
7531 defsubr (&Swindow_new_total);
7532 defsubr (&Swindow_new_normal);
7533 defsubr (&Swindow_pixel_left);
7534 defsubr (&Swindow_pixel_top);
7535 defsubr (&Swindow_left_column);
7536 defsubr (&Swindow_top_line);
7537 defsubr (&Sset_window_new_pixel);
7538 defsubr (&Sset_window_new_total);
7539 defsubr (&Sset_window_new_normal);
7540 defsubr (&Swindow_resize_apply);
7541 defsubr (&Swindow_resize_apply_total);
7542 defsubr (&Swindow_body_height);
7543 defsubr (&Swindow_body_width);
7544 defsubr (&Swindow_hscroll);
7545 defsubr (&Sset_window_hscroll);
7546 defsubr (&Swindow_redisplay_end_trigger);
7547 defsubr (&Sset_window_redisplay_end_trigger);
7548 defsubr (&Swindow_edges);
7549 defsubr (&Swindow_pixel_edges);
7550 defsubr (&Swindow_absolute_pixel_edges);
7551 defsubr (&Swindow_mode_line_height);
7552 defsubr (&Swindow_header_line_height);
7553 defsubr (&Swindow_right_divider_width);
7554 defsubr (&Swindow_bottom_divider_width);
7555 defsubr (&Swindow_scroll_bar_width);
7556 defsubr (&Swindow_scroll_bar_height);
7557 defsubr (&Swindow_inside_edges);
7558 defsubr (&Swindow_inside_pixel_edges);
7559 defsubr (&Swindow_inside_absolute_pixel_edges);
7560 defsubr (&Scoordinates_in_window_p);
7561 defsubr (&Swindow_at);
7562 defsubr (&Swindow_point);
7563 defsubr (&Swindow_old_point);
7564 defsubr (&Swindow_start);
7565 defsubr (&Swindow_end);
7566 defsubr (&Sset_window_point);
7567 defsubr (&Sset_window_start);
7568 defsubr (&Swindow_dedicated_p);
7569 defsubr (&Sset_window_dedicated_p);
7570 defsubr (&Swindow_display_table);
7571 defsubr (&Sset_window_display_table);
7572 defsubr (&Snext_window);
7573 defsubr (&Sprevious_window);
7574 defsubr (&Swindow__sanitize_window_sizes);
7575 defsubr (&Sget_buffer_window);
7576 defsubr (&Sdelete_other_windows_internal);
7577 defsubr (&Sdelete_window_internal);
7578 defsubr (&Sresize_mini_window_internal);
7579 defsubr (&Sset_window_buffer);
7580 defsubr (&Srun_window_configuration_change_hook);
7581 defsubr (&Srun_window_scroll_functions);
7582 defsubr (&Sselect_window);
7583 defsubr (&Sforce_window_update);
7584 defsubr (&Ssplit_window_internal);
7585 defsubr (&Sscroll_up);
7586 defsubr (&Sscroll_down);
7587 defsubr (&Sscroll_left);
7588 defsubr (&Sscroll_right);
7589 defsubr (&Sother_window_for_scrolling);
7590 defsubr (&Sscroll_other_window);
7591 defsubr (&Sminibuffer_selected_window);
7592 defsubr (&Srecenter);
7593 defsubr (&Swindow_text_width);
7594 defsubr (&Swindow_text_height);
7595 defsubr (&Smove_to_window_line);
7596 defsubr (&Swindow_configuration_p);
7597 defsubr (&Swindow_configuration_frame);
7598 defsubr (&Sset_window_configuration);
7599 defsubr (&Scurrent_window_configuration);
7600 defsubr (&Sset_window_margins);
7601 defsubr (&Swindow_margins);
7602 defsubr (&Sset_window_fringes);
7603 defsubr (&Swindow_fringes);
7604 defsubr (&Sset_window_scroll_bars);
7605 defsubr (&Swindow_scroll_bars);
7606 defsubr (&Swindow_vscroll);
7607 defsubr (&Sset_window_vscroll);
7608 defsubr (&Scompare_window_configurations);
7609 defsubr (&Swindow_list);
7610 defsubr (&Swindow_list_1);
7611 defsubr (&Swindow_prev_buffers);
7612 defsubr (&Sset_window_prev_buffers);
7613 defsubr (&Swindow_next_buffers);
7614 defsubr (&Sset_window_next_buffers);
7615 defsubr (&Swindow_parameters);
7616 defsubr (&Swindow_parameter);
7617 defsubr (&Sset_window_parameter);
7620 void
7621 keys_of_window (void)
7623 initial_define_key (control_x_map, '<', "scroll-left");
7624 initial_define_key (control_x_map, '>', "scroll-right");
7626 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
7627 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7628 initial_define_key (meta_map, 'v', "scroll-down-command");