Typo fix.
[emacs.git] / src / window.c
blob60ec913ebbfa2bc7159fb46e0971baa92c5754c8
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985-1987, 1993-1998, 2000-2014 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 "frame.h"
31 #include "window.h"
32 #include "commands.h"
33 #include "indent.h"
34 #include "termchar.h"
35 #include "disptab.h"
36 #include "dispextern.h"
37 #include "blockinput.h"
38 #include "intervals.h"
39 #include "termhooks.h" /* For FRAME_TERMINAL. */
40 #ifdef HAVE_WINDOW_SYSTEM
41 #include TERM_HEADER
42 #endif /* HAVE_WINDOW_SYSTEM */
43 #ifdef MSDOS
44 #include "msdos.h"
45 #endif
47 Lisp_Object Qwindowp, Qwindow_live_p;
48 static Lisp_Object Qwindow_valid_p;
49 static Lisp_Object Qwindow_configuration_p;
50 static Lisp_Object Qrecord_window_buffer;
51 static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
52 static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
53 static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
54 static Lisp_Object Qwindow_pixel_to_total;
55 static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
56 static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
57 static Lisp_Object Qfloor, Qceiling;
59 static int displayed_window_lines (struct window *);
60 static int count_windows (struct window *);
61 static int get_leaf_windows (struct window *, struct window **, int);
62 static void window_scroll (Lisp_Object, EMACS_INT, bool, int);
63 static void window_scroll_pixel_based (Lisp_Object, int, bool, int);
64 static void window_scroll_line_based (Lisp_Object, int, bool, int);
65 static int add_window_to_list (struct window *, void *);
66 static Lisp_Object next_window (Lisp_Object, Lisp_Object,
67 Lisp_Object, int);
68 static void decode_next_window_args (Lisp_Object *, Lisp_Object *,
69 Lisp_Object *);
70 static void foreach_window (struct frame *,
71 int (* fn) (struct window *, void *),
72 void *);
73 static int foreach_window_1 (struct window *,
74 int (* fn) (struct window *, void *),
75 void *);
76 static Lisp_Object window_list_1 (Lisp_Object, Lisp_Object, Lisp_Object);
77 static int window_resize_check (struct window *, bool);
78 static void window_resize_apply (struct window *, bool);
79 static void window_resize_apply_total (struct window *, bool);
80 static Lisp_Object select_window (Lisp_Object, Lisp_Object, int);
81 static void select_window_1 (Lisp_Object, bool);
83 static struct window *set_window_fringes (struct window *, Lisp_Object,
84 Lisp_Object, Lisp_Object);
85 static struct window *set_window_margins (struct window *, Lisp_Object,
86 Lisp_Object);
87 static struct window *set_window_scroll_bars (struct window *, Lisp_Object,
88 Lisp_Object, Lisp_Object);
89 static void apply_window_adjustment (struct window *);
91 /* This is the window in which the terminal's cursor should
92 be left when nothing is being done with it. This must
93 always be a leaf window, and its buffer is selected by
94 the top level editing loop at the end of each command.
96 This value is always the same as
97 FRAME_SELECTED_WINDOW (selected_frame). */
98 Lisp_Object selected_window;
100 /* A list of all windows for use by next_window and Fwindow_list.
101 Functions creating or deleting windows should invalidate this cache
102 by setting it to nil. */
103 Lisp_Object Vwindow_list;
105 /* The mini-buffer window of the selected frame.
106 Note that you cannot test for mini-bufferness of an arbitrary window
107 by comparing against this; but you can test for mini-bufferness of
108 the selected window. */
109 Lisp_Object minibuf_window;
111 /* Non-nil means it is the window whose mode line should be
112 shown as the selected window when the minibuffer is selected. */
113 Lisp_Object minibuf_selected_window;
115 /* Hook run at end of temp_output_buffer_show. */
116 static Lisp_Object Qtemp_buffer_show_hook;
118 /* Incremented for each window created. */
119 static int sequence_number;
121 /* Nonzero after init_window_once has finished. */
122 static int window_initialized;
124 /* Hook to run when window config changes. */
125 static Lisp_Object Qwindow_configuration_change_hook;
127 /* Used by the function window_scroll_pixel_based */
128 static int window_scroll_pixel_based_preserve_x;
129 static int window_scroll_pixel_based_preserve_y;
131 /* Same for window_scroll_line_based. */
132 static EMACS_INT window_scroll_preserve_hpos;
133 static EMACS_INT window_scroll_preserve_vpos;
135 static void
136 CHECK_WINDOW_CONFIGURATION (Lisp_Object x)
138 CHECK_TYPE (WINDOW_CONFIGURATIONP (x), Qwindow_configuration_p, x);
141 /* These setters are used only in this file, so they can be private. */
142 static void
143 wset_combination_limit (struct window *w, Lisp_Object val)
145 w->combination_limit = val;
147 static void
148 wset_dedicated (struct window *w, Lisp_Object val)
150 w->dedicated = val;
152 static void
153 wset_display_table (struct window *w, Lisp_Object val)
155 w->display_table = val;
157 static void
158 wset_new_normal (struct window *w, Lisp_Object val)
160 w->new_normal = val;
162 static void
163 wset_new_total (struct window *w, Lisp_Object val)
165 w->new_total = val;
167 static void
168 wset_normal_cols (struct window *w, Lisp_Object val)
170 w->normal_cols = val;
172 static void
173 wset_normal_lines (struct window *w, Lisp_Object val)
175 w->normal_lines = val;
177 static void
178 wset_parent (struct window *w, Lisp_Object val)
180 w->parent = val;
182 static void
183 wset_pointm (struct window *w, Lisp_Object val)
185 w->pointm = val;
187 static void
188 wset_start (struct window *w, Lisp_Object val)
190 w->start = val;
192 static void
193 wset_temslot (struct window *w, Lisp_Object val)
195 w->temslot = val;
197 static void
198 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
200 w->vertical_scroll_bar_type = val;
202 static void
203 wset_window_parameters (struct window *w, Lisp_Object val)
205 w->window_parameters = val;
207 static void
208 wset_combination (struct window *w, bool horflag, Lisp_Object val)
210 /* Since leaf windows never becomes non-leaf, there should
211 be no buffer and markers in start and pointm fields of W. */
212 eassert (!BUFFERP (w->contents) && NILP (w->start) && NILP (w->pointm));
213 w->contents = val;
214 /* When an internal window is deleted and VAL is nil, HORFLAG
215 is meaningless. */
216 if (!NILP (val))
217 w->horizontal = horflag;
220 /* Nonzero if leaf window W doesn't reflect the actual state
221 of displayed buffer due to its text or overlays change. */
223 bool
224 window_outdated (struct window *w)
226 struct buffer *b = XBUFFER (w->contents);
227 return (w->last_modified < BUF_MODIFF (b)
228 || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b));
231 struct window *
232 decode_live_window (register Lisp_Object window)
234 if (NILP (window))
235 return XWINDOW (selected_window);
237 CHECK_LIVE_WINDOW (window);
238 return XWINDOW (window);
241 struct window *
242 decode_any_window (register Lisp_Object window)
244 struct window *w;
246 if (NILP (window))
247 return XWINDOW (selected_window);
249 CHECK_WINDOW (window);
250 w = XWINDOW (window);
251 return w;
254 static struct window *
255 decode_valid_window (register Lisp_Object window)
257 struct window *w;
259 if (NILP (window))
260 return XWINDOW (selected_window);
262 CHECK_VALID_WINDOW (window);
263 w = XWINDOW (window);
264 return w;
267 /* Called when W's buffer slot is changed. ARG -1 means that W is about to
268 cease its buffer, and 1 means that W is about to set up the new one. */
270 static void
271 adjust_window_count (struct window *w, int arg)
273 eassert (eabs (arg) == 1);
274 if (BUFFERP (w->contents))
276 struct buffer *b = XBUFFER (w->contents);
278 if (b->base_buffer)
279 b = b->base_buffer;
280 b->window_count += arg;
281 eassert (b->window_count >= 0);
282 /* These should be recalculated by redisplay code. */
283 w->window_end_valid = 0;
284 w->base_line_pos = 0;
288 /* Set W's buffer slot to VAL and recompute number
289 of windows showing VAL if it is a buffer. */
291 void
292 wset_buffer (struct window *w, Lisp_Object val)
294 adjust_window_count (w, -1);
295 if (BUFFERP (val))
296 /* Make sure that we do not assign the buffer
297 to an internal window. */
298 eassert (MARKERP (w->start) && MARKERP (w->pointm));
299 w->contents = val;
300 adjust_window_count (w, 1);
303 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
304 doc: /* Return t if OBJECT is a window and nil otherwise. */)
305 (Lisp_Object object)
307 return WINDOWP (object) ? Qt : Qnil;
310 DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
311 doc: /* Return t if OBJECT is a valid window and nil otherwise.
312 A valid window is either a window that displays a buffer or an internal
313 window. Deleted windows are not live. */)
314 (Lisp_Object object)
316 return WINDOW_VALID_P (object) ? Qt : Qnil;
319 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
320 doc: /* Return t if OBJECT is a live window and nil otherwise.
321 A live window is a window that displays a buffer.
322 Internal windows and deleted windows are not live. */)
323 (Lisp_Object object)
325 return WINDOW_LIVE_P (object) ? Qt : Qnil;
328 /* Frames and windows. */
329 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 0, 1, 0,
330 doc: /* Return the frame that window WINDOW is on.
331 WINDOW must be a valid window and defaults to the selected one. */)
332 (Lisp_Object window)
334 return decode_valid_window (window)->frame;
337 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
338 doc: /* Return the root window of FRAME-OR-WINDOW.
339 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
340 With a frame argument, return that frame's root window.
341 With a window argument, return the root window of that window's frame. */)
342 (Lisp_Object frame_or_window)
344 Lisp_Object window;
346 if (NILP (frame_or_window))
347 window = SELECTED_FRAME ()->root_window;
348 else if (WINDOW_VALID_P (frame_or_window))
349 window = XFRAME (XWINDOW (frame_or_window)->frame)->root_window;
350 else
352 CHECK_LIVE_FRAME (frame_or_window);
353 window = XFRAME (frame_or_window)->root_window;
356 return window;
359 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
360 doc: /* Return the minibuffer window for frame FRAME.
361 If FRAME is omitted or nil, it defaults to the selected frame. */)
362 (Lisp_Object frame)
364 return FRAME_MINIBUF_WINDOW (decode_live_frame (frame));
367 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
368 Swindow_minibuffer_p, 0, 1, 0,
369 doc: /* Return non-nil if WINDOW is a minibuffer window.
370 WINDOW must be a valid window and defaults to the selected one. */)
371 (Lisp_Object window)
373 return MINI_WINDOW_P (decode_valid_window (window)) ? Qt : Qnil;
376 /* Don't move this to window.el - this must be a safe routine. */
377 DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
378 doc: /* Return the topmost, leftmost live window on FRAME-OR-WINDOW.
379 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
380 Else if FRAME-OR-WINDOW denotes a valid window, return the first window
381 of that window's frame. If FRAME-OR-WINDOW denotes a live frame, return
382 the first window of that frame. */)
383 (Lisp_Object frame_or_window)
385 Lisp_Object window;
387 if (NILP (frame_or_window))
388 window = SELECTED_FRAME ()->root_window;
389 else if (WINDOW_VALID_P (frame_or_window))
390 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
391 else
393 CHECK_LIVE_FRAME (frame_or_window);
394 window = XFRAME (frame_or_window)->root_window;
397 while (WINDOWP (XWINDOW (window)->contents))
398 window = XWINDOW (window)->contents;
400 return window;
403 DEFUN ("frame-selected-window", Fframe_selected_window,
404 Sframe_selected_window, 0, 1, 0,
405 doc: /* Return the selected window of FRAME-OR-WINDOW.
406 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
407 Else if FRAME-OR-WINDOW denotes a valid window, return the selected
408 window of that window's frame. If FRAME-OR-WINDOW denotes a live frame,
409 return the selected window of that frame. */)
410 (Lisp_Object frame_or_window)
412 Lisp_Object window;
414 if (NILP (frame_or_window))
415 window = SELECTED_FRAME ()->selected_window;
416 else if (WINDOW_VALID_P (frame_or_window))
417 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
418 else
420 CHECK_LIVE_FRAME (frame_or_window);
421 window = XFRAME (frame_or_window)->selected_window;
424 return window;
427 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
428 Sset_frame_selected_window, 2, 3, 0,
429 doc: /* Set selected window of FRAME to WINDOW.
430 FRAME must be a live frame and defaults to the selected one. If FRAME
431 is the selected frame, this makes WINDOW the selected window. Optional
432 argument NORECORD non-nil means to neither change the order of recently
433 selected windows nor the buffer list. WINDOW must denote a live window.
434 Return WINDOW. */)
435 (Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
437 if (NILP (frame))
438 frame = selected_frame;
440 CHECK_LIVE_FRAME (frame);
441 CHECK_LIVE_WINDOW (window);
443 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
444 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
446 if (EQ (frame, selected_frame))
447 return Fselect_window (window, norecord);
448 else
450 fset_selected_window (XFRAME (frame), window);
451 return window;
455 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
456 doc: /* Return the selected window.
457 The selected window is the window in which the standard cursor for
458 selected windows appears and to which many commands apply. */)
459 (void)
461 return selected_window;
464 int window_select_count;
466 /* If select_window is called with inhibit_point_swap non-zero it will
467 not store point of the old selected window's buffer back into that
468 window's pointm slot. This is needed by Fset_window_configuration to
469 avoid that the display routine is called with selected_window set to
470 Qnil causing a subsequent crash. */
471 static Lisp_Object
472 select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
474 register struct window *w;
475 struct frame *sf;
477 CHECK_LIVE_WINDOW (window);
479 w = XWINDOW (window);
481 /* Make the selected window's buffer current. */
482 Fset_buffer (w->contents);
484 if (EQ (window, selected_window) && !inhibit_point_swap)
485 /* `switch-to-buffer' uses (select-window (selected-window)) as a "clever"
486 way to call record_buffer from Elisp, so it's important that we call
487 record_buffer before returning here. */
488 goto record_and_return;
490 if (NILP (norecord))
491 { /* Mark the window for redisplay since the selected-window has
492 a different mode-line. */
493 wset_redisplay (XWINDOW (selected_window));
494 wset_redisplay (w);
496 else
497 redisplay_other_windows ();
499 sf = SELECTED_FRAME ();
500 if (XFRAME (WINDOW_FRAME (w)) != sf)
502 fset_selected_window (XFRAME (WINDOW_FRAME (w)), window);
503 /* Use this rather than Fhandle_switch_frame
504 so that FRAME_FOCUS_FRAME is moved appropriately as we
505 move around in the state where a minibuffer in a separate
506 frame is active. */
507 Fselect_frame (WINDOW_FRAME (w), norecord);
508 /* Fselect_frame called us back so we've done all the work already. */
509 eassert (EQ (window, selected_window));
510 return window;
512 else
513 fset_selected_window (sf, window);
515 select_window_1 (window, inhibit_point_swap);
516 bset_last_selected_window (XBUFFER (w->contents), window);
518 record_and_return:
519 /* record_buffer can run QUIT, so make sure it is run only after we have
520 re-established the invariant between selected_window and selected_frame,
521 otherwise the temporary broken invariant might "escape" (bug#14161). */
522 if (NILP (norecord))
524 w->use_time = ++window_select_count;
525 record_buffer (w->contents);
528 return window;
531 /* Select window with a minimum of fuss, i.e. don't record the change anywhere
532 (not even for redisplay's benefit), and assume that the window's frame is
533 already selected. */
534 static void
535 select_window_1 (Lisp_Object window, bool inhibit_point_swap)
537 /* Store the old selected window's buffer's point in pointm of the old
538 selected window. It belongs to that window, and when the window is
539 not selected, must be in the window. */
540 if (!inhibit_point_swap)
542 struct window *ow = XWINDOW (selected_window);
543 if (BUFFERP (ow->contents))
544 set_marker_both (ow->pointm, ow->contents,
545 BUF_PT (XBUFFER (ow->contents)),
546 BUF_PT_BYTE (XBUFFER (ow->contents)));
549 selected_window = window;
551 /* Go to the point recorded in the window.
552 This is important when the buffer is in more
553 than one window. It also matters when
554 redisplay_window has altered point after scrolling,
555 because it makes the change only in the window. */
556 set_point_from_marker (XWINDOW (window)->pointm);
559 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
560 doc: /* Select WINDOW which must be a live window.
561 Also make WINDOW's frame the selected frame and WINDOW that frame's
562 selected window. In addition, make WINDOW's buffer current and set that
563 buffer's value of `point' to the value of WINDOW's `window-point'.
564 Return WINDOW.
566 Optional second arg NORECORD non-nil means do not put this buffer at the
567 front of the buffer list and do not make this window the most recently
568 selected one.
570 Note that the main editor command loop sets the current buffer to the
571 buffer of the selected window before each command. */)
572 (register Lisp_Object window, Lisp_Object norecord)
574 return select_window (window, norecord, 0);
577 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
578 doc: /* Return the buffer displayed in window WINDOW.
579 If WINDOW is omitted or nil, it defaults to the selected window.
580 Return nil for an internal window or a deleted window. */)
581 (Lisp_Object window)
583 struct window *w = decode_any_window (window);
584 return WINDOW_LEAF_P (w) ? w->contents : Qnil;
587 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
588 doc: /* Return the parent window of window WINDOW.
589 WINDOW must be a valid window and defaults to the selected one.
590 Return nil for a window with no parent (e.g. a root window). */)
591 (Lisp_Object window)
593 return decode_valid_window (window)->parent;
596 DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 0, 1, 0,
597 doc: /* Return the topmost child window of window WINDOW.
598 WINDOW must be a valid window and defaults to the selected one.
599 Return nil if WINDOW is a live window (live windows have no children).
600 Return nil if WINDOW is an internal window whose children form a
601 horizontal combination. */)
602 (Lisp_Object window)
604 struct window *w = decode_valid_window (window);
605 return WINDOW_VERTICAL_COMBINATION_P (w) ? w->contents : Qnil;
608 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
609 doc: /* Return the leftmost child window of window WINDOW.
610 WINDOW must be a valid window and defaults to the selected one.
611 Return nil if WINDOW is a live window (live windows have no children).
612 Return nil if WINDOW is an internal window whose children form a
613 vertical combination. */)
614 (Lisp_Object window)
616 struct window *w = decode_valid_window (window);
617 return WINDOW_HORIZONTAL_COMBINATION_P (w) ? w->contents : Qnil;
620 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
621 doc: /* Return the next sibling window of window WINDOW.
622 WINDOW must be a valid window and defaults to the selected one.
623 Return nil if WINDOW has no next sibling. */)
624 (Lisp_Object window)
626 return decode_valid_window (window)->next;
629 DEFUN ("window-prev-sibling", Fwindow_prev_sibling, Swindow_prev_sibling, 0, 1, 0,
630 doc: /* Return the previous sibling window of window WINDOW.
631 WINDOW must be a valid window and defaults to the selected one.
632 Return nil if WINDOW has no previous sibling. */)
633 (Lisp_Object window)
635 return decode_valid_window (window)->prev;
638 DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
639 doc: /* Return combination limit of window WINDOW.
640 WINDOW must be a valid window used in horizontal or vertical combination.
641 If the return value is nil, child windows of WINDOW can be recombined with
642 WINDOW's siblings. A return value of t means that child windows of
643 WINDOW are never \(re-)combined with WINDOW's siblings. */)
644 (Lisp_Object window)
646 struct window *w;
648 CHECK_VALID_WINDOW (window);
649 w = XWINDOW (window);
650 if (WINDOW_LEAF_P (w))
651 error ("Combination limit is meaningful for internal windows only");
652 return w->combination_limit;
655 DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
656 doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
657 WINDOW must be a valid window used in horizontal or vertical combination.
658 If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
659 siblings. LIMIT t means that child windows of WINDOW are never
660 \(re-)combined with WINDOW's siblings. Other values are reserved for
661 future use. */)
662 (Lisp_Object window, Lisp_Object limit)
664 struct window *w;
666 CHECK_VALID_WINDOW (window);
667 w = XWINDOW (window);
668 if (WINDOW_LEAF_P (w))
669 error ("Combination limit is meaningful for internal windows only");
670 wset_combination_limit (w, limit);
671 return limit;
674 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
675 doc: /* Return the use time of window WINDOW.
676 WINDOW must be a live window and defaults to the selected one.
677 The window with the highest use time is the most recently selected
678 one. The window with the lowest use time is the least recently
679 selected one. */)
680 (Lisp_Object window)
682 return make_number (decode_live_window (window)->use_time);
685 DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0,
686 doc: /* Return the width of window WINDOW in pixels.
687 WINDOW must be a valid window and defaults to the selected one.
689 The return value includes the fringes and margins of WINDOW as well as
690 any vertical dividers or scroll bars belonging to WINDOW. If WINDOW is
691 an internal window, its pixel width is the width of the screen areas
692 spanned by its children. */)
693 (Lisp_Object window)
695 return make_number (decode_valid_window (window)->pixel_width);
698 DEFUN ("window-pixel-height", Fwindow_pixel_height, Swindow_pixel_height, 0, 1, 0,
699 doc: /* Return the height of window WINDOW in pixels.
700 WINDOW must be a valid window and defaults to the selected one.
702 The return value includes the mode line and header line, if any. If
703 WINDOW is an internal window, its pixel height is the height of the
704 screen areas spanned by its children. */)
705 (Lisp_Object window)
707 return make_number (decode_valid_window (window)->pixel_height);
710 DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0,
711 doc: /* Return the height of window WINDOW in lines.
712 WINDOW must be a valid window and defaults to the selected one.
714 The return value includes the heights of WINDOW's mode and header line
715 and its bottom divider, if any. If WINDOW is an internal window, the
716 total height is the height of the screen areas spanned by its children.
718 If WINDOW's pixel height is not an integral multiple of its frame's
719 character height, the number of lines occupied by WINDOW is rounded
720 internally. This is done in a way such that, if WINDOW is a parent
721 window, the sum of the total heights of all its children internally
722 equals the total height of WINDOW.
724 If the optional argument ROUND is `ceiling', return the smallest integer
725 larger than WINDOW's pixel height divided by the character height of
726 WINDOW's frame. ROUND `floor' means to return the largest integer
727 smaller than WINDOW's pixel height divided by the character height of
728 WINDOW's frame. Any other value of ROUND means to return the internal
729 total height of WINDOW. */)
730 (Lisp_Object window, Lisp_Object round)
732 struct window *w = decode_valid_window (window);
734 if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
735 return make_number (w->total_lines);
736 else
738 int unit = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
740 return make_number (EQ (round, Qceiling)
741 ? ((w->pixel_height + unit - 1) /unit)
742 : (w->pixel_height / unit));
746 DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 2, 0,
747 doc: /* Return the total width of window WINDOW in columns.
748 WINDOW must be a valid window and defaults to the selected one.
750 The return value includes the widths of WINDOW's fringes, margins,
751 scroll bars and its right divider, if any. If WINDOW is an internal
752 window, the total width is the width of the screen areas spanned by its
753 children.
755 If WINDOW's pixel width is not an integral multiple of its frame's
756 character width, the number of lines occupied by WINDOW is rounded
757 internally. This is done in a way such that, if WINDOW is a parent
758 window, the sum of the total widths of all its children internally
759 equals the total width of WINDOW.
761 If the optional argument ROUND is `ceiling', return the smallest integer
762 larger than WINDOW's pixel width divided by the character width of
763 WINDOW's frame. ROUND `floor' means to return the largest integer
764 smaller than WINDOW's pixel width divided by the character width of
765 WINDOW's frame. Any other value of ROUND means to return the internal
766 total width of WINDOW. */)
767 (Lisp_Object window, Lisp_Object round)
769 struct window *w = decode_valid_window (window);
771 if (! EQ (round, Qfloor) && ! EQ (round, Qceiling))
772 return make_number (w->total_cols);
773 else
775 int unit = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
777 return make_number (EQ (round, Qceiling)
778 ? ((w->pixel_width + unit - 1) /unit)
779 : (w->pixel_width / unit));
783 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
784 doc: /* Return the new total size of window WINDOW.
785 WINDOW must be a valid window and defaults to the selected one. */)
786 (Lisp_Object window)
788 return decode_valid_window (window)->new_total;
791 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
792 doc: /* Return the normal height of window WINDOW.
793 WINDOW must be a valid window and defaults to the selected one.
794 If HORIZONTAL is non-nil, return the normal width of WINDOW. */)
795 (Lisp_Object window, Lisp_Object horizontal)
797 struct window *w = decode_valid_window (window);
799 return NILP (horizontal) ? w->normal_lines : w->normal_cols;
802 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
803 doc: /* Return new normal size of window WINDOW.
804 WINDOW must be a valid window and defaults to the selected one. */)
805 (Lisp_Object window)
807 return decode_valid_window (window)->new_normal;
810 DEFUN ("window-new-pixel", Fwindow_new_pixel, Swindow_new_pixel, 0, 1, 0,
811 doc: /* Return new pixel size of window WINDOW.
812 WINDOW must be a valid window and defaults to the selected one. */)
813 (Lisp_Object window)
815 return decode_valid_window (window)->new_pixel;
818 DEFUN ("window-pixel-left", Fwindow_pixel_left, Swindow_pixel_left, 0, 1, 0,
819 doc: /* Return left pixel edge of window WINDOW.
820 WINDOW must be a valid window and defaults to the selected one. */)
821 (Lisp_Object window)
823 return make_number (decode_valid_window (window)->pixel_left);
826 DEFUN ("window-pixel-top", Fwindow_pixel_top, Swindow_pixel_top, 0, 1, 0,
827 doc: /* Return top pixel edge of window WINDOW.
828 WINDOW must be a valid window and defaults to the selected one. */)
829 (Lisp_Object window)
831 return make_number (decode_valid_window (window)->pixel_top);
834 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
835 doc: /* Return left column of window WINDOW.
836 This is the distance, in columns, between the left edge of WINDOW and
837 the left edge of the frame's window area. For instance, the return
838 value is 0 if there is no window to the left of WINDOW.
840 WINDOW must be a valid window and defaults to the selected one. */)
841 (Lisp_Object window)
843 return make_number (decode_valid_window (window)->left_col);
846 DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
847 doc: /* Return top line of window WINDOW.
848 This is the distance, in lines, between the top of WINDOW and the top
849 of the frame's window area. For instance, the return value is 0 if
850 there is no window above WINDOW.
852 WINDOW must be a valid window and defaults to the selected one. */)
853 (Lisp_Object window)
855 return make_number (decode_valid_window (window)->top_line);
858 /* Return the number of lines/pixels of W's body. Don't count any mode
859 or header line or horizontal divider of W. Rounds down to nearest
860 integer when not working pixelwise. */
861 static int
862 window_body_height (struct window *w, bool pixelwise)
864 int height = (w->pixel_height
865 - WINDOW_HEADER_LINE_HEIGHT (w)
866 - WINDOW_MODE_LINE_HEIGHT (w)
867 - WINDOW_BOTTOM_DIVIDER_WIDTH (w));
869 return pixelwise ? height : height / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
872 /* Return the number of columns/pixels of W's body. Don't count columns
873 occupied by the scroll bar or the divider/vertical bar separating W
874 from its right sibling or margins. On window-systems don't count
875 fringes either. Round down to nearest integer when not working
876 pixelwise. */
878 window_body_width (struct window *w, bool pixelwise)
880 struct frame *f = XFRAME (WINDOW_FRAME (w));
882 int width = (w->pixel_width
883 - WINDOW_RIGHT_DIVIDER_WIDTH (w)
884 - (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
885 ? WINDOW_SCROLL_BAR_AREA_WIDTH (w)
886 : ((!FRAME_WINDOW_P (f)
887 && !WINDOW_RIGHTMOST_P (w)
888 && !WINDOW_RIGHT_DIVIDER_WIDTH (w))
889 /* A vertical bar is either 1 or 0. */
890 ? 1 : 0))
891 - WINDOW_MARGINS_WIDTH (w)
892 - (FRAME_WINDOW_P (f)
893 ? WINDOW_FRINGES_WIDTH (w)
894 : 0));
896 return pixelwise ? width : width / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
899 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
900 doc: /* Return the height of WINDOW's text area.
901 WINDOW must be a live window and defaults to the selected one. Optional
902 argument PIXELWISE non-nil means return the height of WINDOW's text area
903 in pixels. The return value does not include the mode line or header
904 line or any horizontal divider.
906 If PIXELWISE is nil, return the largest integer smaller than WINDOW's
907 pixel height divided by the character height of WINDOW's frame. This
908 means that if a line at the bottom of the text area is only partially
909 visible, that line is not counted. */)
910 (Lisp_Object window, Lisp_Object pixelwise)
912 return make_number (window_body_height (decode_live_window (window),
913 NILP (pixelwise) ? 0 : 1));
916 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
917 doc: /* Return the width of WINDOW's text area.
918 WINDOW must be a live window and defaults to the selected one. Optional
919 argument PIXELWISE non-nil means return the width in pixels. The return
920 value does not include any vertical dividers, fringes or marginal areas,
921 or scroll bars.
923 If PIXELWISE is nil, return the largest integer smaller than WINDOW's
924 pixel width divided by the character width of WINDOW's frame. This
925 means that if a column at the right of the text area is only partially
926 visible, that column is not counted. */)
927 (Lisp_Object window, Lisp_Object pixelwise)
929 return make_number (window_body_width (decode_live_window (window),
930 NILP (pixelwise) ? 0 : 1));
933 DEFUN ("window-mode-line-height", Fwindow_mode_line_height,
934 Swindow_mode_line_height, 0, 1, 0,
935 doc: /* Return the height in pixels of WINDOW's mode-line.
936 WINDOW must be a live window and defaults to the selected one. */)
937 (Lisp_Object window)
939 return (make_number (WINDOW_MODE_LINE_HEIGHT (decode_live_window (window))));
942 DEFUN ("window-header-line-height", Fwindow_header_line_height,
943 Swindow_header_line_height, 0, 1, 0,
944 doc: /* Return the height in pixels of WINDOW's header-line.
945 WINDOW must be a live window and defaults to the selected one. */)
946 (Lisp_Object window)
948 return (make_number (WINDOW_HEADER_LINE_HEIGHT (decode_live_window (window))));
951 DEFUN ("window-right-divider-width", Fwindow_right_divider_width,
952 Swindow_right_divider_width, 0, 1, 0,
953 doc: /* Return the width in pixels of WINDOW's right divider.
954 WINDOW must be a live window and defaults to the selected one. */)
955 (Lisp_Object window)
957 return (make_number (WINDOW_RIGHT_DIVIDER_WIDTH (decode_live_window (window))));
960 DEFUN ("window-bottom-divider-width", Fwindow_bottom_divider_width,
961 Swindow_bottom_divider_width, 0, 1, 0,
962 doc: /* Return the width in pixels of WINDOW's bottom divider.
963 WINDOW must be a live window and defaults to the selected one. */)
964 (Lisp_Object window)
966 return (make_number (WINDOW_BOTTOM_DIVIDER_WIDTH (decode_live_window (window))));
969 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
970 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
971 WINDOW must be a live window and defaults to the selected one. */)
972 (Lisp_Object window)
974 return make_number (decode_live_window (window)->hscroll);
977 /* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
978 range, returning the new amount as a fixnum. */
979 static Lisp_Object
980 set_window_hscroll (struct window *w, EMACS_INT hscroll)
982 /* Horizontal scrolling has problems with large scroll amounts.
983 It's too slow with long lines, and even with small lines the
984 display can be messed up. For now, though, impose only the limits
985 required by the internal representation: horizontal scrolling must
986 fit in fixnum (since it's visible to Elisp) and into ptrdiff_t
987 (since it's stored in a ptrdiff_t). */
988 ptrdiff_t hscroll_max = min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX);
989 ptrdiff_t new_hscroll = clip_to_bounds (0, hscroll, hscroll_max);
991 /* Prevent redisplay shortcuts when changing the hscroll. */
992 if (w->hscroll != new_hscroll)
993 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
995 w->hscroll = new_hscroll;
996 return make_number (new_hscroll);
999 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
1000 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
1001 WINDOW must be a live window and defaults to the selected one.
1002 Clip the number to a reasonable value if out of range.
1003 Return the new number. NCOL should be zero or positive.
1005 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
1006 window so that the location of point moves off-window. */)
1007 (Lisp_Object window, Lisp_Object ncol)
1009 CHECK_NUMBER (ncol);
1010 return set_window_hscroll (decode_live_window (window), XINT (ncol));
1013 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
1014 Swindow_redisplay_end_trigger, 0, 1, 0,
1015 doc: /* Return WINDOW's redisplay end trigger value.
1016 WINDOW must be a live window and defaults to the selected one.
1017 See `set-window-redisplay-end-trigger' for more information. */)
1018 (Lisp_Object window)
1020 return decode_live_window (window)->redisplay_end_trigger;
1023 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
1024 Sset_window_redisplay_end_trigger, 2, 2, 0,
1025 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
1026 WINDOW must be a live window and defaults to the selected one. VALUE
1027 should be a buffer position (typically a marker) or nil. If it is a
1028 buffer position, then if redisplay in WINDOW reaches a position beyond
1029 VALUE, the functions in `redisplay-end-trigger-functions' are called
1030 with two arguments: WINDOW, and the end trigger value. Afterwards the
1031 end-trigger value is reset to nil. */)
1032 (register Lisp_Object window, Lisp_Object value)
1034 wset_redisplay_end_trigger (decode_live_window (window), value);
1035 return value;
1038 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
1039 doc: /* Return a list of the edge coordinates of WINDOW.
1040 WINDOW must be a valid window and defaults to the selected one.
1042 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
1043 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
1044 0 at top left corner of frame.
1046 RIGHT is one more than the rightmost column occupied by WINDOW. BOTTOM
1047 is one more than the bottommost row occupied by WINDOW. The edges
1048 include the space used by WINDOW's scroll bar, display margins, fringes,
1049 header line, and/or mode line. For the edges of just the text area, use
1050 `window-inside-edges'. */)
1051 (Lisp_Object window)
1053 register struct window *w = decode_valid_window (window);
1055 return list4i (WINDOW_LEFT_EDGE_COL (w), WINDOW_TOP_EDGE_LINE (w),
1056 WINDOW_RIGHT_EDGE_COL (w), WINDOW_BOTTOM_EDGE_LINE (w));
1059 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
1060 doc: /* Return a list of the edge pixel coordinates of WINDOW.
1061 WINDOW must be a valid window and defaults to the selected one.
1063 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1064 0, 0 at the top left corner of the frame.
1066 RIGHT is one more than the rightmost x position occupied by WINDOW.
1067 BOTTOM is one more than the bottommost y position occupied by WINDOW.
1068 The pixel edges include the space used by WINDOW's scroll bar, display
1069 margins, fringes, header line, and/or mode line. For the pixel edges
1070 of just the text area, use `window-inside-pixel-edges'. */)
1071 (Lisp_Object window)
1073 register struct window *w = decode_valid_window (window);
1075 return list4i (WINDOW_LEFT_EDGE_X (w), WINDOW_TOP_EDGE_Y (w),
1076 WINDOW_RIGHT_EDGE_X (w), WINDOW_BOTTOM_EDGE_Y (w));
1079 static void
1080 calc_absolute_offset (struct window *w, int *add_x, int *add_y)
1082 struct frame *f = XFRAME (w->frame);
1083 *add_y = f->top_pos;
1084 #ifdef FRAME_MENUBAR_HEIGHT
1085 *add_y += FRAME_MENUBAR_HEIGHT (f);
1086 #endif
1087 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
1088 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
1089 #elif defined (FRAME_TOOLBAR_HEIGHT)
1090 *add_y += FRAME_TOOLBAR_HEIGHT (f);
1091 #endif
1092 #ifdef FRAME_NS_TITLEBAR_HEIGHT
1093 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
1094 #endif
1095 *add_x = f->left_pos;
1096 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
1097 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
1098 #endif
1101 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
1102 Swindow_absolute_pixel_edges, 0, 1, 0,
1103 doc: /* Return a list of the edge pixel coordinates of WINDOW.
1104 WINDOW must be a valid window and defaults to the selected one.
1106 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1107 0, 0 at the top left corner of the display.
1109 RIGHT is one more than the rightmost x position occupied by WINDOW.
1110 BOTTOM is one more than the bottommost y position occupied by WINDOW.
1111 The pixel edges include the space used by WINDOW's scroll bar, display
1112 margins, fringes, header line, and/or mode line. For the pixel edges
1113 of just the text area, use `window-inside-absolute-pixel-edges'. */)
1114 (Lisp_Object window)
1116 register struct window *w = decode_valid_window (window);
1117 int add_x, add_y;
1119 calc_absolute_offset (w, &add_x, &add_y);
1121 return list4i (WINDOW_LEFT_EDGE_X (w) + add_x,
1122 WINDOW_TOP_EDGE_Y (w) + add_y,
1123 WINDOW_RIGHT_EDGE_X (w) + add_x,
1124 WINDOW_BOTTOM_EDGE_Y (w) + add_y);
1127 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
1128 doc: /* Return a list of the edge coordinates of WINDOW.
1129 WINDOW must be a live window and defaults to the selected one.
1131 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
1132 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
1133 0 at top left corner of frame.
1135 RIGHT is one more than the rightmost column of WINDOW's text area.
1136 BOTTOM is one more than the bottommost row of WINDOW's text area. The
1137 inside edges do not include the space used by the WINDOW's scroll bar,
1138 display margins, fringes, header line, and/or mode line. */)
1139 (Lisp_Object window)
1141 register struct window *w = decode_live_window (window);
1143 return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w)
1144 + WINDOW_LEFT_MARGIN_COLS (w)
1145 + WINDOW_LEFT_FRINGE_COLS (w)),
1146 (WINDOW_TOP_EDGE_LINE (w)
1147 + WINDOW_HEADER_LINE_LINES (w)),
1148 (WINDOW_BOX_RIGHT_EDGE_COL (w)
1149 - WINDOW_RIGHT_MARGIN_COLS (w)
1150 - WINDOW_RIGHT_FRINGE_COLS (w)),
1151 (WINDOW_BOTTOM_EDGE_LINE (w)
1152 - WINDOW_MODE_LINE_LINES (w)));
1155 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
1156 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1157 WINDOW must be a live window and defaults to the selected one.
1159 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1160 (0,0) at the top left corner of the frame's window area.
1162 RIGHT is one more than the rightmost x position of WINDOW's text area.
1163 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1164 The inside edges do not include the space used by WINDOW's scroll bar,
1165 display margins, fringes, header line, and/or mode line. */)
1166 (Lisp_Object window)
1168 register struct window *w = decode_live_window (window);
1170 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1171 + WINDOW_LEFT_MARGIN_WIDTH (w)
1172 + WINDOW_LEFT_FRINGE_WIDTH (w)),
1173 (WINDOW_TOP_EDGE_Y (w)
1174 + WINDOW_HEADER_LINE_HEIGHT (w)),
1175 (WINDOW_BOX_RIGHT_EDGE_X (w)
1176 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1177 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
1178 (WINDOW_BOTTOM_EDGE_Y (w)
1179 - WINDOW_MODE_LINE_HEIGHT (w)));
1182 DEFUN ("window-inside-absolute-pixel-edges",
1183 Fwindow_inside_absolute_pixel_edges,
1184 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
1185 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1186 WINDOW must be a live window and defaults to the selected one.
1188 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1189 (0,0) at the top left corner of the frame's window area.
1191 RIGHT is one more than the rightmost x position of WINDOW's text area.
1192 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1193 The inside edges do not include the space used by WINDOW's scroll bar,
1194 display margins, fringes, header line, and/or mode line. */)
1195 (Lisp_Object window)
1197 register struct window *w = decode_live_window (window);
1198 int add_x, add_y;
1200 calc_absolute_offset (w, &add_x, &add_y);
1202 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1203 + WINDOW_LEFT_MARGIN_WIDTH (w)
1204 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
1205 (WINDOW_TOP_EDGE_Y (w)
1206 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
1207 (WINDOW_BOX_RIGHT_EDGE_X (w)
1208 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1209 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
1210 (WINDOW_BOTTOM_EDGE_Y (w)
1211 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
1214 /* Test if the character at column X, row Y is within window W.
1215 If it is not, return ON_NOTHING;
1216 if it is on the window's vertical divider, return
1217 ON_RIGHT_DIVIDER;
1218 if it is on the window's horizontal divider, return
1219 ON_BOTTOM_DIVIDER;
1220 if it is in the window's text area, return ON_TEXT;
1221 if it is on the window's modeline, return ON_MODE_LINE;
1222 if it is on the border between the window and its right sibling,
1223 return ON_VERTICAL_BORDER;
1224 if it is on a scroll bar, return ON_SCROLL_BAR;
1225 if it is on the window's top line, return ON_HEADER_LINE;
1226 if it is in left or right fringe of the window,
1227 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
1228 if it is in the marginal area to the left/right of the window,
1229 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
1231 X and Y are frame relative pixel coordinates. */
1233 static enum window_part
1234 coordinates_in_window (register struct window *w, int x, int y)
1236 struct frame *f = XFRAME (WINDOW_FRAME (w));
1237 enum window_part part;
1238 int ux = FRAME_COLUMN_WIDTH (f);
1239 int left_x = WINDOW_LEFT_EDGE_X (w);
1240 int right_x = WINDOW_RIGHT_EDGE_X (w);
1241 int top_y = WINDOW_TOP_EDGE_Y (w);
1242 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
1243 /* The width of the area where the vertical line can be dragged.
1244 (Between mode lines for instance. */
1245 int grabbable_width = ux;
1246 int lmargin_width, rmargin_width, text_left, text_right;
1248 /* Outside any interesting row or column? */
1249 if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
1250 return ON_NOTHING;
1252 /* On vertical window divider (which prevails horizontal
1253 dividers)? */
1254 if (!WINDOW_RIGHTMOST_P (w)
1255 && WINDOW_RIGHT_DIVIDER_WIDTH (w)
1256 && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
1257 && x <= right_x)
1258 return ON_RIGHT_DIVIDER;
1259 /* On the horizontal window divider? */
1260 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
1261 && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1262 && y <= bottom_y)
1263 return ON_BOTTOM_DIVIDER;
1264 /* On the mode or header line? */
1265 else if ((WINDOW_WANTS_MODELINE_P (w)
1266 && y >= (bottom_y
1267 - CURRENT_MODE_LINE_HEIGHT (w)
1268 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1269 && y <= bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
1270 && (part = ON_MODE_LINE))
1271 || (WINDOW_WANTS_HEADER_LINE_P (w)
1272 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
1273 && (part = ON_HEADER_LINE)))
1275 /* If it's under/over the scroll bar portion of the mode/header
1276 line, say it's on the vertical line. That's to be able to
1277 resize windows horizontally in case we're using toolkit scroll
1278 bars. Note: If scrollbars are on the left, the window that
1279 must be eventually resized is that on the left of WINDOW. */
1280 if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1281 && !WINDOW_LEFTMOST_P (w)
1282 && eabs (x - left_x) < grabbable_width)
1283 || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1284 && !WINDOW_RIGHTMOST_P (w)
1285 && eabs (x - right_x) < grabbable_width))
1286 return ON_VERTICAL_BORDER;
1287 else
1288 return part;
1291 /* In what's below, we subtract 1 when computing right_x because we
1292 want the rightmost pixel, which is given by left_pixel+width-1. */
1293 if (w->pseudo_window_p)
1295 left_x = 0;
1296 right_x = WINDOW_PIXEL_WIDTH (w) - 1;
1298 else
1300 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
1301 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
1304 /* Outside any interesting column? */
1305 if (x < left_x || x > right_x)
1306 return ON_SCROLL_BAR;
1308 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
1309 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
1311 text_left = window_box_left (w, TEXT_AREA);
1312 text_right = text_left + window_box_width (w, TEXT_AREA);
1314 if (FRAME_WINDOW_P (f))
1316 if (!w->pseudo_window_p
1317 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
1318 && !WINDOW_RIGHTMOST_P (w)
1319 && (eabs (x - right_x) < grabbable_width))
1320 return ON_VERTICAL_BORDER;
1322 /* Need to say "x > right_x" rather than >=, since on character
1323 terminals, the vertical line's x coordinate is right_x. */
1324 else if (!w->pseudo_window_p
1325 && !WINDOW_RIGHTMOST_P (w)
1326 /* Why check ux if we are not the rightmost window? Also
1327 shouldn't a pseudo window always be rightmost? */
1328 && x > right_x - ux)
1329 return ON_VERTICAL_BORDER;
1331 if (x < text_left)
1333 if (lmargin_width > 0
1334 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1335 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
1336 : (x < left_x + lmargin_width)))
1337 return ON_LEFT_MARGIN;
1339 return ON_LEFT_FRINGE;
1342 if (x >= text_right)
1344 if (rmargin_width > 0
1345 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1346 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
1347 : (x >= right_x - rmargin_width)))
1348 return ON_RIGHT_MARGIN;
1350 return ON_RIGHT_FRINGE;
1353 /* Everything special ruled out - must be on text area */
1354 return ON_TEXT;
1357 /* Take X is the frame-relative pixel x-coordinate, and return the
1358 x-coordinate relative to part PART of window W. */
1360 window_relative_x_coord (struct window *w, enum window_part part, int x)
1362 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
1364 switch (part)
1366 case ON_TEXT:
1367 return x - window_box_left (w, TEXT_AREA);
1369 case ON_LEFT_FRINGE:
1370 return x - left_x;
1372 case ON_RIGHT_FRINGE:
1373 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
1375 case ON_LEFT_MARGIN:
1376 return (x - left_x
1377 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1378 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
1380 case ON_RIGHT_MARGIN:
1381 return (x + 1
1382 - ((w->pseudo_window_p)
1383 ? WINDOW_PIXEL_WIDTH (w)
1384 : WINDOW_BOX_RIGHT_EDGE_X (w))
1385 + window_box_width (w, RIGHT_MARGIN_AREA)
1386 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1387 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
1390 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
1391 return 0;
1395 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
1396 Scoordinates_in_window_p, 2, 2, 0,
1397 doc: /* Return non-nil if COORDINATES are in WINDOW.
1398 WINDOW must be a live window and defaults to the selected one.
1399 COORDINATES is a cons of the form (X . Y), X and Y being distances
1400 measured in characters from the upper-left corner of the frame.
1401 \(0 . 0) denotes the character in the upper left corner of the
1402 frame.
1403 If COORDINATES are in the text portion of WINDOW,
1404 the coordinates relative to the window are returned.
1405 If they are in the mode line of WINDOW, `mode-line' is returned.
1406 If they are in the top mode line of WINDOW, `header-line' is returned.
1407 If they are in the left fringe of WINDOW, `left-fringe' is returned.
1408 If they are in the right fringe of WINDOW, `right-fringe' is returned.
1409 If they are on the border between WINDOW and its right sibling,
1410 `vertical-line' is returned.
1411 If they are in the windows's left or right marginal areas, `left-margin'\n\
1412 or `right-margin' is returned. */)
1413 (register Lisp_Object coordinates, Lisp_Object window)
1415 struct window *w;
1416 struct frame *f;
1417 int x, y;
1418 Lisp_Object lx, ly;
1420 w = decode_live_window (window);
1421 f = XFRAME (w->frame);
1422 CHECK_CONS (coordinates);
1423 lx = Fcar (coordinates);
1424 ly = Fcdr (coordinates);
1425 CHECK_NUMBER_OR_FLOAT (lx);
1426 CHECK_NUMBER_OR_FLOAT (ly);
1427 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1428 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
1430 switch (coordinates_in_window (w, x, y))
1432 case ON_NOTHING:
1433 return Qnil;
1435 case ON_TEXT:
1436 /* Convert X and Y to window relative pixel coordinates, and
1437 return the canonical char units. */
1438 x -= window_box_left (w, TEXT_AREA);
1439 y -= WINDOW_TOP_EDGE_Y (w);
1440 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1441 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
1443 case ON_MODE_LINE:
1444 return Qmode_line;
1446 case ON_VERTICAL_BORDER:
1447 return Qvertical_line;
1449 case ON_HEADER_LINE:
1450 return Qheader_line;
1452 case ON_LEFT_FRINGE:
1453 return Qleft_fringe;
1455 case ON_RIGHT_FRINGE:
1456 return Qright_fringe;
1458 case ON_LEFT_MARGIN:
1459 return Qleft_margin;
1461 case ON_RIGHT_MARGIN:
1462 return Qright_margin;
1464 case ON_SCROLL_BAR:
1465 /* Historically we are supposed to return nil in this case. */
1466 return Qnil;
1468 case ON_RIGHT_DIVIDER:
1469 return Qright_divider;
1471 case ON_BOTTOM_DIVIDER:
1472 return Qbottom_divider;
1474 default:
1475 emacs_abort ();
1480 /* Callback for foreach_window, used in window_from_coordinates.
1481 Check if window W contains coordinates specified by USER_DATA which
1482 is actually a pointer to a struct check_window_data CW.
1484 Check if window W contains coordinates *CW->x and *CW->y. If it
1485 does, return W in *CW->window, as Lisp_Object, and return in
1486 *CW->part the part of the window under coordinates *X,*Y. Return
1487 zero from this function to stop iterating over windows. */
1489 struct check_window_data
1491 Lisp_Object *window;
1492 int x, y;
1493 enum window_part *part;
1496 static int
1497 check_window_containing (struct window *w, void *user_data)
1499 struct check_window_data *cw = user_data;
1500 enum window_part found;
1501 int continue_p = 1;
1503 found = coordinates_in_window (w, cw->x, cw->y);
1504 if (found != ON_NOTHING)
1506 *cw->part = found;
1507 XSETWINDOW (*cw->window, w);
1508 continue_p = 0;
1511 return continue_p;
1515 /* Find the window containing frame-relative pixel position X/Y and
1516 return it as a Lisp_Object.
1518 If X, Y is on one of the window's special `window_part' elements,
1519 set *PART to the id of that element.
1521 If there is no window under X, Y return nil and leave *PART
1522 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1524 This function was previously implemented with a loop cycling over
1525 windows with Fnext_window, and starting with the frame's selected
1526 window. It turned out that this doesn't work with an
1527 implementation of next_window using Vwindow_list, because
1528 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1529 tree of F when this function is called asynchronously from
1530 note_mouse_highlight. The original loop didn't terminate in this
1531 case. */
1533 Lisp_Object
1534 window_from_coordinates (struct frame *f, int x, int y,
1535 enum window_part *part, bool tool_bar_p)
1537 Lisp_Object window;
1538 struct check_window_data cw;
1539 enum window_part dummy;
1541 if (part == 0)
1542 part = &dummy;
1544 window = Qnil;
1545 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
1546 foreach_window (f, check_window_containing, &cw);
1548 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
1549 /* If not found above, see if it's in the tool bar window, if a tool
1550 bar exists. */
1551 if (NILP (window)
1552 && tool_bar_p
1553 && WINDOWP (f->tool_bar_window)
1554 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1555 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
1556 != ON_NOTHING))
1558 *part = ON_TEXT;
1559 window = f->tool_bar_window;
1561 #endif
1563 return window;
1566 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1567 doc: /* Return window containing coordinates X and Y on FRAME.
1568 FRAME must be a live frame and defaults to the selected one.
1569 The top left corner of the frame is considered to be row 0,
1570 column 0. */)
1571 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1573 struct frame *f = decode_live_frame (frame);
1575 /* Check that arguments are integers or floats. */
1576 CHECK_NUMBER_OR_FLOAT (x);
1577 CHECK_NUMBER_OR_FLOAT (y);
1579 return window_from_coordinates (f,
1580 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1581 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1582 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1583 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1584 0, 0);
1587 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1588 doc: /* Return current value of point in WINDOW.
1589 WINDOW must be a live window and defaults to the selected one.
1591 For a nonselected window, this is the value point would have if that
1592 window were selected.
1594 Note that, when WINDOW is selected, the value returned is the same as
1595 that returned by `point' for WINDOW's buffer. It would be more strictly
1596 correct to return the top-level value of `point', outside of any
1597 `save-excursion' forms. But that is hard to define. */)
1598 (Lisp_Object window)
1600 register struct window *w = decode_live_window (window);
1602 if (w == XWINDOW (selected_window))
1603 return make_number (BUF_PT (XBUFFER (w->contents)));
1604 else
1605 return Fmarker_position (w->pointm);
1608 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1609 doc: /* Return position at which display currently starts in WINDOW.
1610 WINDOW must be a live window and defaults to the selected one.
1611 This is updated by redisplay or by calling `set-window-start'. */)
1612 (Lisp_Object window)
1614 return Fmarker_position (decode_live_window (window)->start);
1617 /* This is text temporarily removed from the doc string below.
1619 This function returns nil if the position is not currently known.
1620 That happens when redisplay is preempted and doesn't finish.
1621 If in that case you want to compute where the end of the window would
1622 have been if redisplay had finished, do this:
1623 (save-excursion
1624 (goto-char (window-start window))
1625 (vertical-motion (1- (window-height window)) window)
1626 (point))") */
1628 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1629 doc: /* Return position at which display currently ends in WINDOW.
1630 WINDOW must be a live window and defaults to the selected one.
1631 This is updated by redisplay, when it runs to completion.
1632 Simply changing the buffer text or setting `window-start'
1633 does not update this value.
1634 Return nil if there is no recorded value. (This can happen if the
1635 last redisplay of WINDOW was preempted, and did not finish.)
1636 If UPDATE is non-nil, compute the up-to-date position
1637 if it isn't already recorded. */)
1638 (Lisp_Object window, Lisp_Object update)
1640 Lisp_Object value;
1641 struct window *w = decode_live_window (window);
1642 Lisp_Object buf;
1643 struct buffer *b;
1645 buf = w->contents;
1646 CHECK_BUFFER (buf);
1647 b = XBUFFER (buf);
1649 if (! NILP (update)
1650 && (windows_or_buffers_changed
1651 || !w->window_end_valid
1652 || b->clip_changed
1653 || b->prevent_redisplay_optimizations_p
1654 || window_outdated (w))
1655 && !noninteractive)
1657 struct text_pos startp;
1658 struct it it;
1659 struct buffer *old_buffer = NULL;
1660 void *itdata = NULL;
1662 /* Cannot use Fvertical_motion because that function doesn't
1663 cope with variable-height lines. */
1664 if (b != current_buffer)
1666 old_buffer = current_buffer;
1667 set_buffer_internal (b);
1670 /* In case W->start is out of the range, use something
1671 reasonable. This situation occurred when loading a file with
1672 `-l' containing a call to `rmail' with subsequent other
1673 commands. At the end, W->start happened to be BEG, while
1674 rmail had already narrowed the buffer. */
1675 CLIP_TEXT_POS_FROM_MARKER (startp, w->start);
1677 itdata = bidi_shelve_cache ();
1678 start_display (&it, w, startp);
1679 move_it_vertically (&it, window_box_height (w));
1680 if (it.current_y < it.last_visible_y)
1681 move_it_past_eol (&it);
1682 value = make_number (IT_CHARPOS (it));
1683 bidi_unshelve_cache (itdata, 0);
1685 if (old_buffer)
1686 set_buffer_internal (old_buffer);
1688 else
1689 XSETINT (value, BUF_Z (b) - w->window_end_pos);
1691 return value;
1694 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1695 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1696 WINDOW must be a live window and defaults to the selected one.
1697 Return POS. */)
1698 (Lisp_Object window, Lisp_Object pos)
1700 register struct window *w = decode_live_window (window);
1702 /* Type of POS is checked by Fgoto_char or set_marker_restricted ... */
1704 if (w == XWINDOW (selected_window))
1706 if (XBUFFER (w->contents) == current_buffer)
1707 Fgoto_char (pos);
1708 else
1710 struct buffer *old_buffer = current_buffer;
1712 /* ... but here we want to catch type error before buffer change. */
1713 CHECK_NUMBER_COERCE_MARKER (pos);
1714 set_buffer_internal (XBUFFER (w->contents));
1715 Fgoto_char (pos);
1716 set_buffer_internal (old_buffer);
1719 else
1721 set_marker_restricted (w->pointm, pos, w->contents);
1722 /* We have to make sure that redisplay updates the window to show
1723 the new value of point. */
1724 wset_redisplay (w);
1727 return pos;
1730 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1731 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1732 WINDOW must be a live window and defaults to the selected one. Return
1733 POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
1734 overriding motion of point in order to display at this exact start. */)
1735 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1737 register struct window *w = decode_live_window (window);
1739 set_marker_restricted (w->start, pos, w->contents);
1740 /* This is not right, but much easier than doing what is right. */
1741 w->start_at_line_beg = 0;
1742 if (NILP (noforce))
1743 w->force_start = 1;
1744 w->update_mode_line = 1;
1745 /* Bug#15957. */
1746 w->window_end_valid = 0;
1747 wset_redisplay (w);
1749 return pos;
1752 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1753 Spos_visible_in_window_p, 0, 3, 0,
1754 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1755 WINDOW must be a live window and defaults to the selected one.
1757 Return nil if that position is scrolled vertically out of view. If a
1758 character is only partially visible, nil is returned, unless the
1759 optional argument PARTIALLY is non-nil. If POS is only out of view
1760 because of horizontal scrolling, return non-nil. If POS is t, it
1761 specifies the position of the last visible glyph in WINDOW. POS
1762 defaults to point in WINDOW; WINDOW defaults to the selected window.
1764 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
1765 the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
1766 where X and Y are the pixel coordinates relative to the top left corner
1767 of the window. The remaining elements are omitted if the character after
1768 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1769 off-window at the top and bottom of the screen line ("row") containing
1770 POS, ROWH is the visible height of that row, and VPOS is the row number
1771 \(zero-based). */)
1772 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1774 register struct window *w;
1775 register EMACS_INT posint;
1776 register struct buffer *buf;
1777 struct text_pos top;
1778 Lisp_Object in_window = Qnil;
1779 int rtop, rbot, rowh, vpos, fully_p = 1;
1780 int x, y;
1782 w = decode_live_window (window);
1783 buf = XBUFFER (w->contents);
1784 SET_TEXT_POS_FROM_MARKER (top, w->start);
1786 if (EQ (pos, Qt))
1787 posint = -1;
1788 else if (!NILP (pos))
1790 CHECK_NUMBER_COERCE_MARKER (pos);
1791 posint = XINT (pos);
1793 else if (w == XWINDOW (selected_window))
1794 posint = PT;
1795 else
1796 posint = marker_position (w->pointm);
1798 /* If position is above window start or outside buffer boundaries,
1799 or if window start is out of range, position is not visible. */
1800 if ((EQ (pos, Qt)
1801 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
1802 && CHARPOS (top) >= BUF_BEGV (buf)
1803 && CHARPOS (top) <= BUF_ZV (buf)
1804 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
1805 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
1806 in_window = Qt;
1808 if (!NILP (in_window) && !NILP (partially))
1810 Lisp_Object part = Qnil;
1811 if (!fully_p)
1812 part = list4i (rtop, rbot, rowh, vpos);
1813 in_window = Fcons (make_number (x),
1814 Fcons (make_number (y), part));
1817 return in_window;
1820 DEFUN ("window-line-height", Fwindow_line_height,
1821 Swindow_line_height, 0, 2, 0,
1822 doc: /* Return height in pixels of text line LINE in window WINDOW.
1823 WINDOW must be a live window and defaults to the selected one.
1825 Return height of current line if LINE is omitted or nil. Return height of
1826 header or mode line if LINE is `header-line' or `mode-line'.
1827 Otherwise, LINE is a text line number starting from 0. A negative number
1828 counts from the end of the window.
1830 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
1831 in pixels of the visible part of the line, VPOS and YPOS are the
1832 vertical position in lines and pixels of the line, relative to the top
1833 of the first text line, and OFFBOT is the number of off-window pixels at
1834 the bottom of the text line. If there are off-window pixels at the top
1835 of the (first) text line, YPOS is negative.
1837 Return nil if window display is not up-to-date. In that case, use
1838 `pos-visible-in-window-p' to obtain the information. */)
1839 (Lisp_Object line, Lisp_Object window)
1841 register struct window *w;
1842 register struct buffer *b;
1843 struct glyph_row *row, *end_row;
1844 int max_y, crop, i;
1845 EMACS_INT n;
1847 w = decode_live_window (window);
1849 if (noninteractive || w->pseudo_window_p)
1850 return Qnil;
1852 CHECK_BUFFER (w->contents);
1853 b = XBUFFER (w->contents);
1855 /* Fail if current matrix is not up-to-date. */
1856 if (!w->window_end_valid
1857 || windows_or_buffers_changed
1858 || b->clip_changed
1859 || b->prevent_redisplay_optimizations_p
1860 || window_outdated (w))
1861 return Qnil;
1863 if (NILP (line))
1865 i = w->cursor.vpos;
1866 if (i < 0 || i >= w->current_matrix->nrows
1867 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
1868 return Qnil;
1869 max_y = window_text_bottom_y (w);
1870 goto found_row;
1873 if (EQ (line, Qheader_line))
1875 if (!WINDOW_WANTS_HEADER_LINE_P (w))
1876 return Qnil;
1877 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1878 return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
1881 if (EQ (line, Qmode_line))
1883 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1884 return (row->enabled_p ?
1885 list4i (row->height,
1886 0, /* not accurate */
1887 (WINDOW_HEADER_LINE_HEIGHT (w)
1888 + window_text_bottom_y (w)),
1890 : Qnil);
1893 CHECK_NUMBER (line);
1894 n = XINT (line);
1896 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1897 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
1898 max_y = window_text_bottom_y (w);
1899 i = 0;
1901 while ((n < 0 || i < n)
1902 && row <= end_row && row->enabled_p
1903 && row->y + row->height < max_y)
1904 row++, i++;
1906 if (row > end_row || !row->enabled_p)
1907 return Qnil;
1909 if (++n < 0)
1911 if (-n > i)
1912 return Qnil;
1913 row += n;
1914 i += n;
1917 found_row:
1918 crop = max (0, (row->y + row->height) - max_y);
1919 return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
1922 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1923 0, 1, 0,
1924 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1925 More precisely, return the value assigned by the last call of
1926 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1927 never called with WINDOW as its argument, or the value set by that
1928 function was internally reset since its last call. WINDOW must be a
1929 live window and defaults to the selected one.
1931 When a window is dedicated to its buffer, `display-buffer' will refrain
1932 from displaying another buffer in it. `get-lru-window' and
1933 `get-largest-window' treat dedicated windows specially.
1934 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1935 `kill-buffer' can delete a dedicated window and the containing frame.
1937 Functions like `set-window-buffer' may change the buffer displayed by a
1938 window, unless that window is "strongly" dedicated to its buffer, that
1939 is the value returned by `window-dedicated-p' is t. */)
1940 (Lisp_Object window)
1942 return decode_live_window (window)->dedicated;
1945 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1946 Sset_window_dedicated_p, 2, 2, 0,
1947 doc: /* Mark WINDOW as dedicated according to FLAG.
1948 WINDOW must be a live window and defaults to the selected one. FLAG
1949 non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
1950 mark WINDOW as non-dedicated. Return FLAG.
1952 When a window is dedicated to its buffer, `display-buffer' will refrain
1953 from displaying another buffer in it. `get-lru-window' and
1954 `get-largest-window' treat dedicated windows specially.
1955 `delete-windows-on', `replace-buffer-in-windows', `quit-window',
1956 `quit-restore-window' and `kill-buffer' can delete a dedicated window
1957 and the containing frame.
1959 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1960 its buffer. Functions like `set-window-buffer' may change the buffer
1961 displayed by a window, unless that window is strongly dedicated to its
1962 buffer. If and when `set-window-buffer' displays another buffer in a
1963 window, it also makes sure that the window is no more dedicated. */)
1964 (Lisp_Object window, Lisp_Object flag)
1966 wset_dedicated (decode_live_window (window), flag);
1967 return flag;
1970 DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
1971 0, 1, 0,
1972 doc: /* Return buffers previously shown in WINDOW.
1973 WINDOW must be a live window and defaults to the selected one.
1975 The return value is a list of elements (BUFFER WINDOW-START POS),
1976 where BUFFER is a buffer, WINDOW-START is the start position of the
1977 window for that buffer, and POS is a window-specific point value. */)
1978 (Lisp_Object window)
1980 return decode_live_window (window)->prev_buffers;
1983 DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
1984 Sset_window_prev_buffers, 2, 2, 0,
1985 doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
1986 WINDOW must be a live window and defaults to the selected one.
1988 PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS),
1989 where BUFFER is a buffer, WINDOW-START is the start position of the
1990 window for that buffer, and POS is a window-specific point value. */)
1991 (Lisp_Object window, Lisp_Object prev_buffers)
1993 wset_prev_buffers (decode_live_window (window), prev_buffers);
1994 return prev_buffers;
1997 DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
1998 0, 1, 0,
1999 doc: /* Return list of buffers recently re-shown in WINDOW.
2000 WINDOW must be a live window and defaults to the selected one. */)
2001 (Lisp_Object window)
2003 return decode_live_window (window)->next_buffers;
2006 DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
2007 Sset_window_next_buffers, 2, 2, 0,
2008 doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
2009 WINDOW must be a live window and defaults to the selected one.
2010 NEXT-BUFFERS should be a list of buffers. */)
2011 (Lisp_Object window, Lisp_Object next_buffers)
2013 wset_next_buffers (decode_live_window (window), next_buffers);
2014 return next_buffers;
2017 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
2018 0, 1, 0,
2019 doc: /* Return the parameters of WINDOW and their values.
2020 WINDOW must be a valid window and defaults to the selected one. The
2021 return value is a list of elements of the form (PARAMETER . VALUE). */)
2022 (Lisp_Object window)
2024 return Fcopy_alist (decode_valid_window (window)->window_parameters);
2027 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
2028 2, 2, 0,
2029 doc: /* Return WINDOW's value for PARAMETER.
2030 WINDOW can be any window and defaults to the selected one. */)
2031 (Lisp_Object window, Lisp_Object parameter)
2033 Lisp_Object result;
2035 result = Fassq (parameter, decode_any_window (window)->window_parameters);
2036 return CDR_SAFE (result);
2039 DEFUN ("set-window-parameter", Fset_window_parameter,
2040 Sset_window_parameter, 3, 3, 0,
2041 doc: /* Set WINDOW's value of PARAMETER to VALUE.
2042 WINDOW can be any window and defaults to the selected one.
2043 Return VALUE. */)
2044 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
2046 register struct window *w = decode_any_window (window);
2047 Lisp_Object old_alist_elt;
2049 old_alist_elt = Fassq (parameter, w->window_parameters);
2050 if (NILP (old_alist_elt))
2051 wset_window_parameters
2052 (w, Fcons (Fcons (parameter, value), w->window_parameters));
2053 else
2054 Fsetcdr (old_alist_elt, value);
2055 return value;
2058 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
2059 0, 1, 0,
2060 doc: /* Return the display-table that WINDOW is using.
2061 WINDOW must be a live window and defaults to the selected one. */)
2062 (Lisp_Object window)
2064 return decode_live_window (window)->display_table;
2067 /* Get the display table for use on window W. This is either W's
2068 display table or W's buffer's display table. Ignore the specified
2069 tables if they are not valid; if no valid table is specified,
2070 return 0. */
2072 struct Lisp_Char_Table *
2073 window_display_table (struct window *w)
2075 struct Lisp_Char_Table *dp = NULL;
2077 if (DISP_TABLE_P (w->display_table))
2078 dp = XCHAR_TABLE (w->display_table);
2079 else if (BUFFERP (w->contents))
2081 struct buffer *b = XBUFFER (w->contents);
2083 if (DISP_TABLE_P (BVAR (b, display_table)))
2084 dp = XCHAR_TABLE (BVAR (b, display_table));
2085 else if (DISP_TABLE_P (Vstandard_display_table))
2086 dp = XCHAR_TABLE (Vstandard_display_table);
2089 return dp;
2092 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
2093 doc: /* Set WINDOW's display-table to TABLE.
2094 WINDOW must be a live window and defaults to the selected one. */)
2095 (register Lisp_Object window, Lisp_Object table)
2097 wset_display_table (decode_live_window (window), table);
2098 return table;
2101 /* Record info on buffer window W is displaying
2102 when it is about to cease to display that buffer. */
2103 static void
2104 unshow_buffer (register struct window *w)
2106 Lisp_Object buf = w->contents;
2107 struct buffer *b = XBUFFER (buf);
2109 eassert (b == XMARKER (w->pointm)->buffer);
2111 #if 0
2112 if (w == XWINDOW (selected_window)
2113 || ! EQ (buf, XWINDOW (selected_window)->contents))
2114 /* Do this except when the selected window's buffer
2115 is being removed from some other window. */
2116 #endif
2117 /* last_window_start records the start position that this buffer
2118 had in the last window to be disconnected from it.
2119 Now that this statement is unconditional,
2120 it is possible for the buffer to be displayed in the
2121 selected window, while last_window_start reflects another
2122 window which was recently showing the same buffer.
2123 Some people might say that might be a good thing. Let's see. */
2124 b->last_window_start = marker_position (w->start);
2126 /* Point in the selected window's buffer
2127 is actually stored in that buffer, and the window's pointm isn't used.
2128 So don't clobber point in that buffer. */
2129 if (! EQ (buf, XWINDOW (selected_window)->contents)
2130 /* Don't clobber point in current buffer either (this could be
2131 useful in connection with bug#12208).
2132 && XBUFFER (buf) != current_buffer */
2133 /* This line helps to fix Horsley's testbug.el bug. */
2134 && !(WINDOWP (BVAR (b, last_selected_window))
2135 && w != XWINDOW (BVAR (b, last_selected_window))
2136 && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->contents)))
2137 temp_set_point_both (b,
2138 clip_to_bounds (BUF_BEGV (b),
2139 marker_position (w->pointm),
2140 BUF_ZV (b)),
2141 clip_to_bounds (BUF_BEGV_BYTE (b),
2142 marker_byte_position (w->pointm),
2143 BUF_ZV_BYTE (b)));
2145 if (WINDOWP (BVAR (b, last_selected_window))
2146 && w == XWINDOW (BVAR (b, last_selected_window)))
2147 bset_last_selected_window (b, Qnil);
2150 /* Put NEW into the window structure in place of OLD. SETFLAG zero
2151 means change window structure only. Otherwise store geometry and
2152 other settings as well. */
2153 static void
2154 replace_window (Lisp_Object old, Lisp_Object new, int setflag)
2156 register Lisp_Object tem;
2157 register struct window *o = XWINDOW (old), *n = XWINDOW (new);
2159 /* If OLD is its frame's root window, then NEW is the new
2160 root window for that frame. */
2161 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
2162 fset_root_window (XFRAME (o->frame), new);
2164 if (setflag)
2166 n->pixel_left = o->pixel_left;
2167 n->pixel_top = o->pixel_top;
2168 n->pixel_width = o->pixel_width;
2169 n->pixel_height = o->pixel_height;
2170 n->left_col = o->left_col;
2171 n->top_line = o->top_line;
2172 n->total_cols = o->total_cols;
2173 n->total_lines = o->total_lines;
2174 wset_normal_cols (n, o->normal_cols);
2175 wset_normal_cols (o, make_float (1.0));
2176 wset_normal_lines (n, o->normal_lines);
2177 wset_normal_lines (o, make_float (1.0));
2178 n->desired_matrix = n->current_matrix = 0;
2179 n->vscroll = 0;
2180 memset (&n->cursor, 0, sizeof (n->cursor));
2181 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
2182 n->last_cursor_vpos = 0;
2183 #ifdef HAVE_WINDOW_SYSTEM
2184 n->phys_cursor_type = NO_CURSOR;
2185 n->phys_cursor_width = -1;
2186 #endif
2187 n->must_be_updated_p = 0;
2188 n->pseudo_window_p = 0;
2189 n->window_end_vpos = 0;
2190 n->window_end_pos = 0;
2191 n->window_end_valid = 0;
2194 tem = o->next;
2195 wset_next (n, tem);
2196 if (!NILP (tem))
2197 wset_prev (XWINDOW (tem), new);
2199 tem = o->prev;
2200 wset_prev (n, tem);
2201 if (!NILP (tem))
2202 wset_next (XWINDOW (tem), new);
2204 tem = o->parent;
2205 wset_parent (n, tem);
2206 if (!NILP (tem) && EQ (XWINDOW (tem)->contents, old))
2207 wset_combination (XWINDOW (tem), XWINDOW (tem)->horizontal, new);
2210 /* If window WINDOW and its parent window are iso-combined, merge
2211 WINDOW's children into those of its parent window and mark WINDOW as
2212 deleted. */
2214 static void
2215 recombine_windows (Lisp_Object window)
2217 struct window *w, *p, *c;
2218 Lisp_Object parent, child;
2219 bool horflag;
2221 w = XWINDOW (window);
2222 parent = w->parent;
2223 if (!NILP (parent) && NILP (w->combination_limit))
2225 p = XWINDOW (parent);
2226 if (WINDOWP (p->contents) && WINDOWP (w->contents)
2227 && p->horizontal == w->horizontal)
2228 /* WINDOW and PARENT are both either a vertical or a horizontal
2229 combination. */
2231 horflag = WINDOW_HORIZONTAL_COMBINATION_P (w);
2232 child = w->contents;
2233 c = XWINDOW (child);
2235 /* Splice WINDOW's children into its parent's children and
2236 assign new normal sizes. */
2237 if (NILP (w->prev))
2238 wset_combination (p, horflag, child);
2239 else
2241 wset_prev (c, w->prev);
2242 wset_next (XWINDOW (w->prev), child);
2245 while (c)
2247 wset_parent (c, parent);
2249 if (horflag)
2250 wset_normal_cols
2251 (c, make_float ((double) c->pixel_width
2252 / (double) p->pixel_width));
2253 else
2254 wset_normal_lines
2255 (c, make_float ((double) c->pixel_height
2256 / (double) p->pixel_height));
2258 if (NILP (c->next))
2260 if (!NILP (w->next))
2262 wset_next (c, w->next);
2263 wset_prev (XWINDOW (c->next), child);
2266 c = 0;
2268 else
2270 child = c->next;
2271 c = XWINDOW (child);
2275 /* WINDOW can be deleted now. */
2276 wset_combination (w, 0, Qnil);
2281 /* If WINDOW can be deleted, delete it. */
2282 static void
2283 delete_deletable_window (Lisp_Object window)
2285 if (!NILP (call1 (Qwindow_deletable_p, window)))
2286 call1 (Qdelete_window, window);
2289 /***********************************************************************
2290 Window List
2291 ***********************************************************************/
2293 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
2294 pointer. This is a callback function for foreach_window, used in
2295 the window_list function. */
2297 static int
2298 add_window_to_list (struct window *w, void *user_data)
2300 Lisp_Object *list = user_data;
2301 Lisp_Object window;
2302 XSETWINDOW (window, w);
2303 *list = Fcons (window, *list);
2304 return 1;
2308 /* Return a list of all windows, for use by next_window. If
2309 Vwindow_list is a list, return that list. Otherwise, build a new
2310 list, cache it in Vwindow_list, and return that. */
2312 Lisp_Object
2313 window_list (void)
2315 if (!CONSP (Vwindow_list))
2317 Lisp_Object tail, frame;
2319 Vwindow_list = Qnil;
2320 FOR_EACH_FRAME (tail, frame)
2322 Lisp_Object args[2];
2324 /* We are visiting windows in canonical order, and add
2325 new windows at the front of args[1], which means we
2326 have to reverse this list at the end. */
2327 args[1] = Qnil;
2328 foreach_window (XFRAME (frame), add_window_to_list, &args[1]);
2329 args[0] = Vwindow_list;
2330 args[1] = Fnreverse (args[1]);
2331 Vwindow_list = Fnconc (2, args);
2335 return Vwindow_list;
2339 /* Value is non-zero if WINDOW satisfies the constraints given by
2340 OWINDOW, MINIBUF and ALL_FRAMES.
2342 MINIBUF t means WINDOW may be minibuffer windows.
2343 `lambda' means WINDOW may not be a minibuffer window.
2344 a window means a specific minibuffer window
2346 ALL_FRAMES t means search all frames,
2347 nil means search just current frame,
2348 `visible' means search just visible frames on the
2349 current terminal,
2350 0 means search visible and iconified frames on the
2351 current terminal,
2352 a window means search the frame that window belongs to,
2353 a frame means consider windows on that frame, only. */
2355 static bool
2356 candidate_window_p (Lisp_Object window, Lisp_Object owindow,
2357 Lisp_Object minibuf, Lisp_Object all_frames)
2359 struct window *w = XWINDOW (window);
2360 struct frame *f = XFRAME (w->frame);
2361 bool candidate_p = 1;
2363 if (!BUFFERP (w->contents))
2364 candidate_p = 0;
2365 else if (MINI_WINDOW_P (w)
2366 && (EQ (minibuf, Qlambda)
2367 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
2369 /* If MINIBUF is `lambda' don't consider any mini-windows.
2370 If it is a window, consider only that one. */
2371 candidate_p = 0;
2373 else if (EQ (all_frames, Qt))
2374 candidate_p = 1;
2375 else if (NILP (all_frames))
2377 eassert (WINDOWP (owindow));
2378 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
2380 else if (EQ (all_frames, Qvisible))
2382 candidate_p = FRAME_VISIBLE_P (f)
2383 && (FRAME_TERMINAL (XFRAME (w->frame))
2384 == FRAME_TERMINAL (XFRAME (selected_frame)));
2387 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2389 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2390 #ifdef HAVE_X_WINDOWS
2391 /* Yuck!! If we've just created the frame and the
2392 window-manager requested the user to place it
2393 manually, the window may still not be considered
2394 `visible'. I'd argue it should be at least
2395 something like `iconified', but don't know how to do
2396 that yet. --Stef */
2397 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
2398 && !f->output_data.x->has_been_visible)
2399 #endif
2401 && (FRAME_TERMINAL (XFRAME (w->frame))
2402 == FRAME_TERMINAL (XFRAME (selected_frame)));
2404 else if (WINDOWP (all_frames))
2405 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
2406 || EQ (XWINDOW (all_frames)->frame, w->frame)
2407 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
2408 else if (FRAMEP (all_frames))
2409 candidate_p = EQ (all_frames, w->frame);
2411 return candidate_p;
2415 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
2416 Fwindow_list. See candidate_window_p for the meaning of WINDOW,
2417 MINIBUF, and ALL_FRAMES. */
2419 static void
2420 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
2422 struct window *w = decode_live_window (*window);
2424 XSETWINDOW (*window, w);
2425 /* MINIBUF nil may or may not include minibuffers. Decide if it
2426 does. */
2427 if (NILP (*minibuf))
2428 *minibuf = minibuf_level ? minibuf_window : Qlambda;
2429 else if (!EQ (*minibuf, Qt))
2430 *minibuf = Qlambda;
2432 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
2433 => count none of them, or a specific minibuffer window (the
2434 active one) to count. */
2436 /* ALL_FRAMES nil doesn't specify which frames to include. */
2437 if (NILP (*all_frames))
2438 *all_frames
2439 = (!EQ (*minibuf, Qlambda)
2440 ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame))
2441 : Qnil);
2442 else if (EQ (*all_frames, Qvisible))
2444 else if (EQ (*all_frames, make_number (0)))
2446 else if (FRAMEP (*all_frames))
2448 else if (!EQ (*all_frames, Qt))
2449 *all_frames = Qnil;
2453 /* Return the next or previous window of WINDOW in cyclic ordering
2454 of windows. NEXT_P non-zero means return the next window. See the
2455 documentation string of next-window for the meaning of MINIBUF and
2456 ALL_FRAMES. */
2458 static Lisp_Object
2459 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
2461 decode_next_window_args (&window, &minibuf, &all_frames);
2463 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
2464 return the first window on the frame. */
2465 if (FRAMEP (all_frames)
2466 && !EQ (all_frames, XWINDOW (window)->frame))
2467 return Fframe_first_window (all_frames);
2469 if (next_p)
2471 Lisp_Object list;
2473 /* Find WINDOW in the list of all windows. */
2474 list = Fmemq (window, window_list ());
2476 /* Scan forward from WINDOW to the end of the window list. */
2477 if (CONSP (list))
2478 for (list = XCDR (list); CONSP (list); list = XCDR (list))
2479 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2480 break;
2482 /* Scan from the start of the window list up to WINDOW. */
2483 if (!CONSP (list))
2484 for (list = Vwindow_list;
2485 CONSP (list) && !EQ (XCAR (list), window);
2486 list = XCDR (list))
2487 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2488 break;
2490 if (CONSP (list))
2491 window = XCAR (list);
2493 else
2495 Lisp_Object candidate, list;
2497 /* Scan through the list of windows for candidates. If there are
2498 candidate windows in front of WINDOW, the last one of these
2499 is the one we want. If there are candidates following WINDOW
2500 in the list, again the last one of these is the one we want. */
2501 candidate = Qnil;
2502 for (list = window_list (); CONSP (list); list = XCDR (list))
2504 if (EQ (XCAR (list), window))
2506 if (WINDOWP (candidate))
2507 break;
2509 else if (candidate_window_p (XCAR (list), window, minibuf,
2510 all_frames))
2511 candidate = XCAR (list);
2514 if (WINDOWP (candidate))
2515 window = candidate;
2518 return window;
2522 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2523 doc: /* Return live window after WINDOW in the cyclic ordering of windows.
2524 WINDOW must be a live window and defaults to the selected one. The
2525 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2526 consider.
2528 MINIBUF nil or omitted means consider the minibuffer window only if the
2529 minibuffer is active. MINIBUF t means consider the minibuffer window
2530 even if the minibuffer is not active. Any other value means do not
2531 consider the minibuffer window even if the minibuffer is active.
2533 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2534 plus the minibuffer window if specified by the MINIBUF argument. If the
2535 minibuffer counts, consider all windows on all frames that share that
2536 minibuffer too. The following non-nil values of ALL-FRAMES have special
2537 meanings:
2539 - t means consider all windows on all existing frames.
2541 - `visible' means consider all windows on all visible frames.
2543 - 0 (the number zero) means consider all windows on all visible and
2544 iconified frames.
2546 - A frame means consider all windows on that frame only.
2548 Anything else means consider all windows on WINDOW's frame and no
2549 others.
2551 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2552 `next-window' to iterate through the entire cycle of acceptable
2553 windows, eventually ending up back at the window you started with.
2554 `previous-window' traverses the same cycle, in the reverse order. */)
2555 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2557 return next_window (window, minibuf, all_frames, 1);
2561 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2562 doc: /* Return live window before WINDOW in the cyclic ordering of windows.
2563 WINDOW must be a live window and defaults to the selected one. The
2564 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2565 consider.
2567 MINIBUF nil or omitted means consider the minibuffer window only if the
2568 minibuffer is active. MINIBUF t means consider the minibuffer window
2569 even if the minibuffer is not active. Any other value means do not
2570 consider the minibuffer window even if the minibuffer is active.
2572 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2573 plus the minibuffer window if specified by the MINIBUF argument. If the
2574 minibuffer counts, consider all windows on all frames that share that
2575 minibuffer too. The following non-nil values of ALL-FRAMES have special
2576 meanings:
2578 - t means consider all windows on all existing frames.
2580 - `visible' means consider all windows on all visible frames.
2582 - 0 (the number zero) means consider all windows on all visible and
2583 iconified frames.
2585 - A frame means consider all windows on that frame only.
2587 Anything else means consider all windows on WINDOW's frame and no
2588 others.
2590 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2591 use `previous-window' to iterate through the entire cycle of
2592 acceptable windows, eventually ending up back at the window you
2593 started with. `next-window' traverses the same cycle, in the
2594 reverse order. */)
2595 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2597 return next_window (window, minibuf, all_frames, 0);
2601 /* Return a list of windows in cyclic ordering. Arguments are like
2602 for `next-window'. */
2604 static Lisp_Object
2605 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2607 Lisp_Object tail, list, rest;
2609 decode_next_window_args (&window, &minibuf, &all_frames);
2610 list = Qnil;
2612 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2613 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2614 list = Fcons (XCAR (tail), list);
2616 /* Rotate the list to start with WINDOW. */
2617 list = Fnreverse (list);
2618 rest = Fmemq (window, list);
2619 if (!NILP (rest) && !EQ (rest, list))
2621 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2623 XSETCDR (tail, Qnil);
2624 list = nconc2 (rest, list);
2626 return list;
2630 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2631 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2632 FRAME nil or omitted means use the selected frame.
2633 WINDOW nil or omitted means use the window selected within FRAME.
2634 MINIBUF t means include the minibuffer window, even if it isn't active.
2635 MINIBUF nil or omitted means include the minibuffer window only
2636 if it's active.
2637 MINIBUF neither nil nor t means never include the minibuffer window. */)
2638 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2640 if (NILP (window))
2641 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2642 CHECK_WINDOW (window);
2643 if (NILP (frame))
2644 frame = selected_frame;
2646 if (!EQ (frame, XWINDOW (window)->frame))
2647 error ("Window is on a different frame");
2649 return window_list_1 (window, minibuf, frame);
2653 DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2654 doc: /* Return a list of all live windows.
2655 WINDOW specifies the first window to list and defaults to the selected
2656 window.
2658 Optional argument MINIBUF nil or omitted means consider the minibuffer
2659 window only if the minibuffer is active. MINIBUF t means consider the
2660 minibuffer window even if the minibuffer is not active. Any other value
2661 means do not consider the minibuffer window even if the minibuffer is
2662 active.
2664 Optional argument ALL-FRAMES nil or omitted means consider all windows
2665 on WINDOW's frame, plus the minibuffer window if specified by the
2666 MINIBUF argument. If the minibuffer counts, consider all windows on all
2667 frames that share that minibuffer too. The following non-nil values of
2668 ALL-FRAMES have special meanings:
2670 - t means consider all windows on all existing frames.
2672 - `visible' means consider all windows on all visible frames.
2674 - 0 (the number zero) means consider all windows on all visible and
2675 iconified frames.
2677 - A frame means consider all windows on that frame only.
2679 Anything else means consider all windows on WINDOW's frame and no
2680 others.
2682 If WINDOW is not on the list of windows returned, some other window will
2683 be listed first but no error is signaled. */)
2684 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2686 return window_list_1 (window, minibuf, all_frames);
2689 /* Look at all windows, performing an operation specified by TYPE
2690 with argument OBJ.
2691 If FRAMES is Qt, look at all frames;
2692 Qnil, look at just the selected frame;
2693 Qvisible, look at visible frames;
2694 a frame, just look at windows on that frame.
2695 If MINI is non-zero, perform the operation on minibuffer windows too. */
2697 enum window_loop
2699 WINDOW_LOOP_UNUSED,
2700 GET_BUFFER_WINDOW, /* Arg is buffer */
2701 REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
2702 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2703 CHECK_ALL_WINDOWS /* Arg is ignored */
2706 static Lisp_Object
2707 window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
2709 Lisp_Object window, windows, best_window, frame_arg;
2710 int frame_best_window_flag = 0;
2711 struct frame *f;
2712 struct gcpro gcpro1;
2714 /* If we're only looping through windows on a particular frame,
2715 frame points to that frame. If we're looping through windows
2716 on all frames, frame is 0. */
2717 if (FRAMEP (frames))
2718 f = XFRAME (frames);
2719 else if (NILP (frames))
2720 f = SELECTED_FRAME ();
2721 else
2722 f = NULL;
2724 if (f)
2725 frame_arg = Qlambda;
2726 else if (EQ (frames, make_number (0)))
2727 frame_arg = frames;
2728 else if (EQ (frames, Qvisible))
2729 frame_arg = frames;
2730 else
2731 frame_arg = Qt;
2733 /* frame_arg is Qlambda to stick to one frame,
2734 Qvisible to consider all visible frames,
2735 or Qt otherwise. */
2737 /* Pick a window to start with. */
2738 if (WINDOWP (obj))
2739 window = obj;
2740 else if (f)
2741 window = FRAME_SELECTED_WINDOW (f);
2742 else
2743 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2745 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2746 GCPRO1 (windows);
2747 best_window = Qnil;
2749 for (; CONSP (windows); windows = XCDR (windows))
2751 struct window *w;
2753 window = XCAR (windows);
2754 w = XWINDOW (window);
2756 /* Note that we do not pay attention here to whether the frame
2757 is visible, since Fwindow_list skips non-visible frames if
2758 that is desired, under the control of frame_arg. */
2759 if (!MINI_WINDOW_P (w)
2760 /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
2761 consider all windows. */
2762 || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
2763 || (mini && minibuf_level > 0))
2764 switch (type)
2766 case GET_BUFFER_WINDOW:
2767 if (EQ (w->contents, obj)
2768 /* Don't find any minibuffer window except the one that
2769 is currently in use. */
2770 && (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
2772 if (EQ (window, selected_window))
2773 /* Preferably return the selected window. */
2774 RETURN_UNGCPRO (window);
2775 else if (EQ (XWINDOW (window)->frame, selected_frame)
2776 && !frame_best_window_flag)
2777 /* Prefer windows on the current frame (but don't
2778 choose another one if we have one already). */
2780 best_window = window;
2781 frame_best_window_flag = 1;
2783 else if (NILP (best_window))
2784 best_window = window;
2786 break;
2788 case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
2789 /* We could simply check whether the buffer shown by window
2790 is live, and show another buffer in case it isn't. */
2791 if (EQ (w->contents, obj))
2793 /* Undedicate WINDOW. */
2794 wset_dedicated (w, Qnil);
2795 /* Make WINDOW show the buffer returned by
2796 other_buffer_safely, don't run any hooks. */
2797 set_window_buffer
2798 (window, other_buffer_safely (w->contents), 0, 0);
2799 /* If WINDOW is the selected window, make its buffer
2800 current. But do so only if the window shows the
2801 current buffer (Bug#6454). */
2802 if (EQ (window, selected_window)
2803 && XBUFFER (w->contents) == current_buffer)
2804 Fset_buffer (w->contents);
2806 break;
2808 case REDISPLAY_BUFFER_WINDOWS:
2809 if (EQ (w->contents, obj))
2811 mark_window_display_accurate (window, 0);
2812 w->update_mode_line = 1;
2813 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2814 update_mode_lines = 27;
2815 best_window = window;
2817 break;
2819 /* Check for a leaf window that has a killed buffer
2820 or broken markers. */
2821 case CHECK_ALL_WINDOWS:
2822 if (BUFFERP (w->contents))
2824 struct buffer *b = XBUFFER (w->contents);
2826 if (!BUFFER_LIVE_P (b))
2827 emacs_abort ();
2828 if (!MARKERP (w->start) || XMARKER (w->start)->buffer != b)
2829 emacs_abort ();
2830 if (!MARKERP (w->pointm) || XMARKER (w->pointm)->buffer != b)
2831 emacs_abort ();
2833 break;
2835 case WINDOW_LOOP_UNUSED:
2836 break;
2840 UNGCPRO;
2841 return best_window;
2844 /* Used for debugging. Abort if any window has a dead buffer. */
2846 extern void check_all_windows (void) EXTERNALLY_VISIBLE;
2847 void
2848 check_all_windows (void)
2850 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2853 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2854 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2855 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
2856 the current buffer.
2858 The optional argument ALL-FRAMES specifies the frames to consider:
2860 - t means consider all windows on all existing frames.
2862 - `visible' means consider all windows on all visible frames.
2864 - 0 (the number zero) means consider all windows on all visible
2865 and iconified frames.
2867 - A frame means consider all windows on that frame only.
2869 Any other value of ALL-FRAMES means consider all windows on the
2870 selected frame and no others. */)
2871 (Lisp_Object buffer_or_name, Lisp_Object all_frames)
2873 Lisp_Object buffer;
2875 if (NILP (buffer_or_name))
2876 buffer = Fcurrent_buffer ();
2877 else
2878 buffer = Fget_buffer (buffer_or_name);
2880 if (BUFFERP (buffer))
2881 return window_loop (GET_BUFFER_WINDOW, buffer, 1, all_frames);
2882 else
2883 return Qnil;
2886 static Lisp_Object
2887 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore, Lisp_Object pixelwise)
2889 return call5 (Qwindow_resize_root_window, window, delta, horizontal, ignore, pixelwise);
2893 static Lisp_Object
2894 window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal)
2896 return call2(Qwindow_pixel_to_total, frame, horizontal);
2900 DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
2901 Sdelete_other_windows_internal, 0, 2, "",
2902 doc: /* Make WINDOW fill its frame.
2903 Only the frame WINDOW is on is affected. WINDOW must be a valid window
2904 and defaults to the selected one.
2906 Optional argument ROOT, if non-nil, must specify an internal window such
2907 that WINDOW is in its window subtree. If this is the case, replace ROOT
2908 by WINDOW and leave alone any windows not part of ROOT's subtree.
2910 When WINDOW is live try to reduce display jumps by keeping the text
2911 previously visible in WINDOW in the same place on the frame. Doing this
2912 depends on the value of (window-start WINDOW), so if calling this
2913 function in a program gives strange scrolling, make sure the
2914 window-start value is reasonable when this function is called. */)
2915 (Lisp_Object window, Lisp_Object root)
2917 struct window *w, *r, *s;
2918 struct frame *f;
2919 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
2920 ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0);
2921 int top IF_LINT (= 0), new_top, resize_failed;
2923 w = decode_valid_window (window);
2924 XSETWINDOW (window, w);
2925 f = XFRAME (w->frame);
2927 if (NILP (root))
2928 /* ROOT is the frame's root window. */
2930 root = FRAME_ROOT_WINDOW (f);
2931 r = XWINDOW (root);
2933 else
2934 /* ROOT must be an ancestor of WINDOW. */
2936 r = decode_valid_window (root);
2937 pwindow = XWINDOW (window)->parent;
2938 while (!NILP (pwindow))
2939 if (EQ (pwindow, root))
2940 break;
2941 else
2942 pwindow = XWINDOW (pwindow)->parent;
2943 if (!EQ (pwindow, root))
2944 error ("Specified root is not an ancestor of specified window");
2947 if (EQ (window, root))
2948 /* A noop. */
2949 return Qnil;
2950 /* I don't understand the "top > 0" part below. If we deal with a
2951 standalone minibuffer it would have been caught by the preceding
2952 test. */
2953 else if (MINI_WINDOW_P (w)) /* && top > 0) */
2954 error ("Can't expand minibuffer to full frame");
2956 if (BUFFERP (w->contents))
2958 startpos = marker_position (w->start);
2959 startbyte = marker_byte_position (w->start);
2960 top = (WINDOW_TOP_EDGE_LINE (w)
2961 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))));
2962 /* Make sure WINDOW is the frame's selected window. */
2963 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
2965 if (EQ (selected_frame, w->frame))
2966 Fselect_window (window, Qnil);
2967 else
2968 fset_selected_window (f, window);
2971 else
2973 /* See if the frame's selected window is a part of the window
2974 subtree rooted at WINDOW, by finding all the selected window's
2975 parents and comparing each one with WINDOW. If it isn't we
2976 need a new selected window for this frame. */
2977 swindow = FRAME_SELECTED_WINDOW (f);
2978 while (1)
2980 pwindow = swindow;
2981 while (!NILP (pwindow) && !EQ (window, pwindow))
2982 pwindow = XWINDOW (pwindow)->parent;
2984 if (EQ (window, pwindow))
2985 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
2986 as the new selected window. */
2987 break;
2988 else
2989 /* Else try the previous window of SWINDOW. */
2990 swindow = Fprevious_window (swindow, Qlambda, Qnil);
2993 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
2995 if (EQ (selected_frame, w->frame))
2996 Fselect_window (swindow, Qnil);
2997 else
2998 fset_selected_window (f, swindow);
3002 block_input ();
3003 if (!FRAME_INITIAL_P (f))
3005 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
3007 /* We are going to free the glyph matrices of WINDOW, and with
3008 that we might lose any information about glyph rows that have
3009 some of their glyphs highlighted in mouse face. (These rows
3010 are marked with a non-zero mouse_face_p flag.) If WINDOW
3011 indeed has some glyphs highlighted in mouse face, signal to
3012 frame's up-to-date hook that mouse highlight was overwritten,
3013 so that it will arrange for redisplaying the highlight. */
3014 if (EQ (hlinfo->mouse_face_window, window))
3015 reset_mouse_highlight (hlinfo);
3017 free_window_matrices (r);
3019 fset_redisplay (f);
3020 Vwindow_list = Qnil;
3021 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3022 resize_failed = 0;
3024 if (!WINDOW_LEAF_P (w))
3026 /* Resize child windows vertically. */
3027 XSETINT (delta, r->pixel_height - w->pixel_height);
3028 w->pixel_top = r->pixel_top;
3029 w->top_line = r->top_line;
3030 resize_root_window (window, delta, Qnil, Qnil, Qt);
3031 if (window_resize_check (w, 0))
3033 window_resize_apply (w, 0);
3034 window_pixel_to_total (w->frame, Qnil);
3036 else
3038 resize_root_window (window, delta, Qnil, Qt, Qt);
3039 if (window_resize_check (w, 0))
3041 window_resize_apply (w, 0);
3042 window_pixel_to_total (w->frame, Qnil);
3044 else
3045 resize_failed = 1;
3048 /* Resize child windows horizontally. */
3049 if (!resize_failed)
3051 w->left_col = r->left_col;
3052 w->pixel_left = r->pixel_left;
3053 XSETINT (delta, r->pixel_width - w->pixel_width);
3054 resize_root_window (window, delta, Qt, Qnil, Qt);
3055 if (window_resize_check (w, 1))
3057 window_resize_apply (w, 1);
3058 window_pixel_to_total (w->frame, Qt);
3060 else
3062 resize_root_window (window, delta, Qt, Qt, Qt);
3063 if (window_resize_check (w, 1))
3065 window_resize_apply (w, 1);
3066 window_pixel_to_total (w->frame, Qt);
3068 else
3069 resize_failed = 1;
3073 if (resize_failed)
3074 /* Play safe, if we still can ... */
3076 window = swindow;
3077 w = XWINDOW (window);
3081 /* Cleanly unlink WINDOW from window-tree. */
3082 if (!NILP (w->prev))
3083 /* Get SIBLING above (on the left of) WINDOW. */
3085 sibling = w->prev;
3086 s = XWINDOW (sibling);
3087 wset_next (s, w->next);
3088 if (!NILP (s->next))
3089 wset_prev (XWINDOW (s->next), sibling);
3091 else
3092 /* Get SIBLING below (on the right of) WINDOW. */
3094 sibling = w->next;
3095 s = XWINDOW (sibling);
3096 wset_prev (s, Qnil);
3097 wset_combination (XWINDOW (w->parent),
3098 XWINDOW (w->parent)->horizontal, sibling);
3101 /* Delete ROOT and all child windows of ROOT. */
3102 if (WINDOWP (r->contents))
3104 delete_all_child_windows (r->contents);
3105 wset_combination (r, 0, Qnil);
3108 replace_window (root, window, 1);
3110 /* This must become SWINDOW anyway ....... */
3111 if (BUFFERP (w->contents) && !resize_failed)
3113 /* Try to minimize scrolling, by setting the window start to the
3114 point will cause the text at the old window start to be at the
3115 same place on the frame. But don't try to do this if the
3116 window start is outside the visible portion (as might happen
3117 when the display is not current, due to typeahead). */
3118 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
3119 if (new_top != top
3120 && startpos >= BUF_BEGV (XBUFFER (w->contents))
3121 && startpos <= BUF_ZV (XBUFFER (w->contents)))
3123 struct position pos;
3124 struct buffer *obuf = current_buffer;
3126 Fset_buffer (w->contents);
3127 /* This computation used to temporarily move point, but that
3128 can have unwanted side effects due to text properties. */
3129 pos = *vmotion (startpos, startbyte, -top, w);
3131 set_marker_both (w->start, w->contents, pos.bufpos, pos.bytepos);
3132 w->window_end_valid = 0;
3133 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
3134 || FETCH_BYTE (pos.bytepos - 1) == '\n');
3135 /* We need to do this, so that the window-scroll-functions
3136 get called. */
3137 w->optional_new_start = 1;
3139 set_buffer_internal (obuf);
3143 adjust_frame_glyphs (f);
3144 unblock_input ();
3146 run_window_configuration_change_hook (f);
3148 return Qnil;
3152 void
3153 replace_buffer_in_windows (Lisp_Object buffer)
3155 call1 (Qreplace_buffer_in_windows, buffer);
3158 /* If BUFFER is shown in a window, safely replace it with some other
3159 buffer in all windows of all frames, even those on other keyboards. */
3161 void
3162 replace_buffer_in_windows_safely (Lisp_Object buffer)
3164 if (buffer_window_count (XBUFFER (buffer)))
3166 Lisp_Object tail, frame;
3168 /* A single call to window_loop won't do the job because it only
3169 considers frames on the current keyboard. So loop manually over
3170 frames, and handle each one. */
3171 FOR_EACH_FRAME (tail, frame)
3172 window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
3176 /* If *HEIGHT or *WIDTH are too small a size for FRAME, set them to the
3177 minimum allowable size. PIXELWISE means interpret these as pixel
3178 sizes. */
3180 void
3181 check_frame_size (struct frame *frame, int *width, int *height, bool pixelwise)
3183 /* For height, we have to see:
3184 how many windows the frame has at minimum (one or two),
3185 and whether it has a menu bar or other special stuff at the top. */
3186 if (pixelwise)
3188 int min_height = MIN_SAFE_WINDOW_HEIGHT * FRAME_LINE_HEIGHT (frame);
3189 int min_width = MIN_SAFE_WINDOW_WIDTH * FRAME_COLUMN_WIDTH (frame);
3191 if (!FRAME_MINIBUF_ONLY_P (frame) && FRAME_HAS_MINIBUF_P (frame))
3192 min_height = 2 * min_height;
3194 min_height += FRAME_TOP_MARGIN_HEIGHT (frame);
3195 min_height += FRAME_INTERNAL_BORDER_WIDTH (frame);
3197 if (*height < min_height)
3198 *height = min_height;
3199 if (*width < min_width)
3200 *width = min_width;
3202 else
3204 int min_height
3205 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
3206 ? MIN_SAFE_WINDOW_HEIGHT
3207 : 2 * MIN_SAFE_WINDOW_HEIGHT);
3209 if (FRAME_TOP_MARGIN (frame) > 0)
3210 min_height += FRAME_TOP_MARGIN (frame);
3212 if (*height < min_height)
3213 *height = min_height;
3214 if (*width < MIN_SAFE_WINDOW_WIDTH)
3215 *width = MIN_SAFE_WINDOW_WIDTH;
3219 /* Adjust the margins of window W if text area is too small.
3220 Return 1 if window width is ok after adjustment; 0 if window
3221 is still too narrow. */
3223 static int
3224 adjust_window_margins (struct window *w)
3226 int box_width = (WINDOW_PIXEL_WIDTH (w)
3227 - WINDOW_FRINGES_WIDTH (w)
3228 - WINDOW_SCROLL_BAR_AREA_WIDTH (w));
3229 int margin_width = WINDOW_MARGINS_WIDTH (w);
3231 if (box_width - margin_width >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
3232 return 1;
3234 if (margin_width < 0 || box_width < MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
3235 return 0;
3236 else
3237 /* Window's text area is too narrow, but reducing the window
3238 margins will fix that. */
3240 int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
3242 margin_width = box_width - MIN_SAFE_WINDOW_PIXEL_WIDTH (w);
3244 if (WINDOW_RIGHT_MARGIN_WIDTH (w) > 0)
3246 if (WINDOW_LEFT_MARGIN_WIDTH (w) > 0)
3247 w->left_margin_cols = w->right_margin_cols =
3248 margin_width / (2 * unit);
3249 else
3250 w->right_margin_cols = margin_width / unit;
3252 else
3253 w->left_margin_cols = margin_width / unit;
3255 return 1;
3259 /* The following three routines are needed for running a window's
3260 configuration change hook. */
3261 static void
3262 run_funs (Lisp_Object funs)
3264 for (; CONSP (funs); funs = XCDR (funs))
3265 if (!EQ (XCAR (funs), Qt))
3266 call0 (XCAR (funs));
3269 static void
3270 select_window_norecord (Lisp_Object window)
3272 if (WINDOW_LIVE_P (window))
3273 Fselect_window (window, Qt);
3276 static void
3277 select_frame_norecord (Lisp_Object frame)
3279 if (FRAME_LIVE_P (XFRAME (frame)))
3280 Fselect_frame (frame, Qt);
3283 void
3284 run_window_configuration_change_hook (struct frame *f)
3286 ptrdiff_t count = SPECPDL_INDEX ();
3287 Lisp_Object frame, global_wcch
3288 = Fdefault_value (Qwindow_configuration_change_hook);
3289 XSETFRAME (frame, f);
3291 if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code))
3292 return;
3294 /* Use the right buffer. Matters when running the local hooks. */
3295 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3297 record_unwind_current_buffer ();
3298 Fset_buffer (Fwindow_buffer (Qnil));
3301 if (SELECTED_FRAME () != f)
3303 record_unwind_protect (select_frame_norecord, selected_frame);
3304 select_frame_norecord (frame);
3307 /* Look for buffer-local values. */
3309 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3310 for (; CONSP (windows); windows = XCDR (windows))
3312 Lisp_Object window = XCAR (windows);
3313 Lisp_Object buffer = Fwindow_buffer (window);
3314 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3315 buffer)))
3317 ptrdiff_t inner_count = SPECPDL_INDEX ();
3318 record_unwind_protect (select_window_norecord, selected_window);
3319 select_window_norecord (window);
3320 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3321 buffer));
3322 unbind_to (inner_count, Qnil);
3327 run_funs (global_wcch);
3328 unbind_to (count, Qnil);
3331 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
3332 Srun_window_configuration_change_hook, 0, 1, 0,
3333 doc: /* Run `window-configuration-change-hook' for FRAME.
3334 If FRAME is omitted or nil, it defaults to the selected frame. */)
3335 (Lisp_Object frame)
3337 run_window_configuration_change_hook (decode_live_frame (frame));
3338 return Qnil;
3341 DEFUN ("run-window-scroll-functions", Frun_window_scroll_functions,
3342 Srun_window_scroll_functions, 0, 1, 0,
3343 doc: /* Run `window-scroll-functions' for WINDOW.
3344 If WINDOW is omitted or nil, it defaults to the selected window. */)
3345 (Lisp_Object window)
3347 if (! NILP (Vwindow_scroll_functions))
3348 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3349 Fmarker_position (decode_live_window (window)->start));
3350 return Qnil;
3353 /* Make WINDOW display BUFFER. RUN_HOOKS_P non-zero means it's allowed
3354 to run hooks. See make_frame for a case where it's not allowed.
3355 KEEP_MARGINS_P non-zero means that the current margins, fringes, and
3356 scroll-bar settings of the window are not reset from the buffer's
3357 local settings. */
3359 void
3360 set_window_buffer (Lisp_Object window, Lisp_Object buffer,
3361 bool run_hooks_p, bool keep_margins_p)
3363 struct window *w = XWINDOW (window);
3364 struct buffer *b = XBUFFER (buffer);
3365 ptrdiff_t count = SPECPDL_INDEX ();
3366 bool samebuf = EQ (buffer, w->contents);
3368 wset_buffer (w, buffer);
3370 if (EQ (window, selected_window))
3371 bset_last_selected_window (b, window);
3373 /* Let redisplay errors through. */
3374 b->display_error_modiff = 0;
3376 /* Update time stamps of buffer display. */
3377 if (INTEGERP (BVAR (b, display_count)))
3378 bset_display_count (b, make_number (XINT (BVAR (b, display_count)) + 1));
3379 bset_display_time (b, Fcurrent_time ());
3381 w->window_end_pos = 0;
3382 w->window_end_vpos = 0;
3383 w->last_cursor_vpos = 0;
3385 if (!(keep_margins_p && samebuf))
3386 { /* If we're not actually changing the buffer, don't reset hscroll and
3387 vscroll. This case happens for example when called from
3388 change_frame_size_1, where we use a dummy call to
3389 Fset_window_buffer on the frame's selected window (and no other)
3390 just in order to run window-configuration-change-hook.
3391 Resetting hscroll and vscroll here is problematic for things like
3392 image-mode and doc-view-mode since it resets the image's position
3393 whenever we resize the frame. */
3394 w->hscroll = w->min_hscroll = 0;
3395 w->vscroll = 0;
3396 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3397 set_marker_restricted (w->start,
3398 make_number (b->last_window_start),
3399 buffer);
3400 w->start_at_line_beg = 0;
3401 w->force_start = 0;
3403 /* Maybe we could move this into the `if' but it's not obviously safe and
3404 I doubt it's worth the trouble. */
3405 wset_redisplay (w);
3406 w->update_mode_line = true;
3408 /* We must select BUFFER for running the window-scroll-functions. */
3409 /* We can't check ! NILP (Vwindow_scroll_functions) here
3410 because that might itself be a local variable. */
3411 if (window_initialized)
3413 record_unwind_current_buffer ();
3414 Fset_buffer (buffer);
3417 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3419 if (!keep_margins_p)
3421 /* Set left and right marginal area width etc. from buffer. */
3422 set_window_fringes (w, BVAR (b, left_fringe_width),
3423 BVAR (b, right_fringe_width),
3424 BVAR (b, fringes_outside_margins));
3425 set_window_scroll_bars (w, BVAR (b, scroll_bar_width),
3426 BVAR (b, vertical_scroll_bar_type), Qnil);
3427 set_window_margins (w, BVAR (b, left_margin_cols),
3428 BVAR (b, right_margin_cols));
3429 apply_window_adjustment (w);
3432 if (run_hooks_p)
3434 if (! NILP (Vwindow_scroll_functions))
3435 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3436 Fmarker_position (w->start));
3437 if (!samebuf)
3438 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3441 unbind_to (count, Qnil);
3444 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3445 doc: /* Make WINDOW display BUFFER-OR-NAME.
3446 WINDOW must be a live window and defaults to the selected one.
3447 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
3449 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
3450 display margins, fringe widths, and scroll bar settings are preserved;
3451 the default is to reset these from the local settings for BUFFER-OR-NAME
3452 or the frame defaults. Return nil.
3454 This function throws an error when WINDOW is strongly dedicated to its
3455 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3456 already display BUFFER-OR-NAME.
3458 This function runs `window-scroll-functions' before running
3459 `window-configuration-change-hook'. */)
3460 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3462 register Lisp_Object tem, buffer;
3463 register struct window *w = decode_live_window (window);
3465 XSETWINDOW (window, w);
3466 buffer = Fget_buffer (buffer_or_name);
3467 CHECK_BUFFER (buffer);
3468 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3469 error ("Attempt to display deleted buffer");
3471 tem = w->contents;
3472 if (NILP (tem))
3473 error ("Window is deleted");
3474 else
3476 if (!EQ (tem, buffer))
3478 if (EQ (w->dedicated, Qt))
3479 /* WINDOW is strongly dedicated to its buffer, signal an
3480 error. */
3481 error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
3482 else
3483 /* WINDOW is weakly dedicated to its buffer, reset
3484 dedication. */
3485 wset_dedicated (w, Qnil);
3487 call1 (Qrecord_window_buffer, window);
3490 unshow_buffer (w);
3493 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3495 return Qnil;
3498 static Lisp_Object
3499 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3501 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3504 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3505 0, 1, 0,
3506 doc: /* Force all windows to be updated on next redisplay.
3507 If optional arg OBJECT is a window, force redisplay of that window only.
3508 If OBJECT is a buffer or buffer name, force redisplay of all windows
3509 displaying that buffer. */)
3510 (Lisp_Object object)
3512 if (NILP (object))
3514 windows_or_buffers_changed = 29;
3515 update_mode_lines = 28;
3516 return Qt;
3519 if (WINDOWP (object))
3521 struct window *w = XWINDOW (object);
3522 mark_window_display_accurate (object, 0);
3523 w->update_mode_line = 1;
3524 if (BUFFERP (w->contents))
3525 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
3526 update_mode_lines = 29;
3527 return Qt;
3530 if (STRINGP (object))
3531 object = Fget_buffer (object);
3532 if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))
3533 && buffer_window_count (XBUFFER (object)))
3535 /* If buffer is live and shown in at least one window, find
3536 all windows showing this buffer and force update of them. */
3537 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3538 return NILP (object) ? Qnil : Qt;
3541 /* If nothing suitable was found, just return.
3542 We could signal an error, but this feature will typically be used
3543 asynchronously in timers or process sentinels, so we don't. */
3544 return Qnil;
3547 /* Obsolete since 24.3. */
3548 void
3549 temp_output_buffer_show (register Lisp_Object buf)
3551 register struct buffer *old = current_buffer;
3552 register Lisp_Object window;
3553 register struct window *w;
3555 bset_directory (XBUFFER (buf), BVAR (current_buffer, directory));
3557 Fset_buffer (buf);
3558 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3559 BEGV = BEG;
3560 ZV = Z;
3561 SET_PT (BEG);
3562 set_buffer_internal (old);
3564 if (!NILP (Vtemp_buffer_show_function))
3565 call1 (Vtemp_buffer_show_function, buf);
3566 else if (WINDOW_LIVE_P (window = display_buffer (buf, Qnil, Qnil)))
3568 if (!EQ (XWINDOW (window)->frame, selected_frame))
3569 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3570 Vminibuf_scroll_window = window;
3571 w = XWINDOW (window);
3572 w->hscroll = 0;
3573 w->min_hscroll = 0;
3574 set_marker_restricted_both (w->start, buf, BEG, BEG);
3575 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3577 /* Run temp-buffer-show-hook, with the chosen window selected
3578 and its buffer current. */
3580 ptrdiff_t count = SPECPDL_INDEX ();
3581 Lisp_Object prev_window, prev_buffer;
3582 prev_window = selected_window;
3583 XSETBUFFER (prev_buffer, old);
3585 /* Select the window that was chosen, for running the hook.
3586 Note: Both Fselect_window and select_window_norecord may
3587 set-buffer to the buffer displayed in the window,
3588 so we need to save the current buffer. --stef */
3589 record_unwind_protect (restore_buffer, prev_buffer);
3590 record_unwind_protect (select_window_norecord, prev_window);
3591 Fselect_window (window, Qt);
3592 Fset_buffer (w->contents);
3593 Frun_hooks (1, &Qtemp_buffer_show_hook);
3594 unbind_to (count, Qnil);
3599 /* Make new window, have it replace WINDOW in window-tree, and make
3600 WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
3601 horizontal child). */
3602 static void
3603 make_parent_window (Lisp_Object window, bool horflag)
3605 Lisp_Object parent;
3606 register struct window *o, *p;
3608 o = XWINDOW (window);
3609 p = allocate_window ();
3610 memcpy ((char *) p + sizeof (struct vectorlike_header),
3611 (char *) o + sizeof (struct vectorlike_header),
3612 word_size * VECSIZE (struct window));
3613 /* P's buffer slot may change from nil to a buffer... */
3614 adjust_window_count (p, 1);
3615 XSETWINDOW (parent, p);
3617 p->sequence_number = ++sequence_number;
3619 replace_window (window, parent, 1);
3621 wset_next (o, Qnil);
3622 wset_prev (o, Qnil);
3623 wset_parent (o, parent);
3624 /* ...but now P becomes an internal window. */
3625 wset_start (p, Qnil);
3626 wset_pointm (p, Qnil);
3627 wset_buffer (p, Qnil);
3628 wset_combination (p, horflag, window);
3629 wset_combination_limit (p, Qnil);
3630 wset_window_parameters (p, Qnil);
3633 /* Make new window from scratch. */
3634 Lisp_Object
3635 make_window (void)
3637 Lisp_Object window;
3638 register struct window *w;
3640 w = allocate_window ();
3641 /* Initialize Lisp data. Note that allocate_window initializes all
3642 Lisp data to nil, so do it only for slots which should not be nil. */
3643 wset_normal_lines (w, make_float (1.0));
3644 wset_normal_cols (w, make_float (1.0));
3645 wset_new_total (w, make_number (0));
3646 wset_new_normal (w, make_number (0));
3647 wset_new_pixel (w, make_number (0));
3648 wset_start (w, Fmake_marker ());
3649 wset_pointm (w, Fmake_marker ());
3650 wset_vertical_scroll_bar_type (w, Qt);
3651 /* These Lisp fields are marked specially so they're not set to nil by
3652 allocate_window. */
3653 wset_prev_buffers (w, Qnil);
3654 wset_next_buffers (w, Qnil);
3656 /* Initialize non-Lisp data. Note that allocate_window zeroes out all
3657 non-Lisp data, so do it only for slots which should not be zero. */
3658 w->nrows_scale_factor = w->ncols_scale_factor = 1;
3659 w->left_fringe_width = w->right_fringe_width = -1;
3660 w->mode_line_height = w->header_line_height = -1;
3661 #ifdef HAVE_WINDOW_SYSTEM
3662 w->phys_cursor_type = NO_CURSOR;
3663 w->phys_cursor_width = -1;
3664 #endif
3665 w->sequence_number = ++sequence_number;
3666 w->scroll_bar_width = -1;
3667 w->column_number_displayed = -1;
3669 /* Reset window_list. */
3670 Vwindow_list = Qnil;
3671 /* Return window. */
3672 XSETWINDOW (window, w);
3673 return window;
3676 DEFUN ("set-window-new-pixel", Fset_window_new_pixel, Sset_window_new_pixel, 2, 3, 0,
3677 doc: /* Set new pixel size of WINDOW to SIZE.
3678 WINDOW must be a valid window and defaults to the selected one.
3679 Return SIZE.
3681 Optional argument ADD non-nil means add SIZE to the new pixel size of
3682 WINDOW and return the sum.
3684 Note: This function does not operate on any child windows of WINDOW. */)
3685 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3687 struct window *w = decode_valid_window (window);
3688 EMACS_INT size_min = NILP (add) ? 0 : - XINT (w->new_pixel);
3689 EMACS_INT size_max = size_min + min (INT_MAX, MOST_POSITIVE_FIXNUM);
3691 CHECK_RANGED_INTEGER (size, size_min, size_max);
3692 if (NILP (add))
3693 wset_new_pixel (w, size);
3694 else
3695 wset_new_pixel (w, make_number (XINT (w->new_pixel) + XINT (size)));
3697 return w->new_pixel;
3700 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
3701 doc: /* Set new total size of WINDOW to SIZE.
3702 WINDOW must be a valid window and defaults to the selected one.
3703 Return SIZE.
3705 Optional argument ADD non-nil means add SIZE to the new total size of
3706 WINDOW and return the sum.
3708 Note: This function does not operate on any child windows of WINDOW. */)
3709 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3711 struct window *w = decode_valid_window (window);
3713 CHECK_NUMBER (size);
3714 if (NILP (add))
3715 wset_new_total (w, size);
3716 else
3717 wset_new_total (w, make_number (XINT (w->new_total) + XINT (size)));
3719 return w->new_total;
3722 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
3723 doc: /* Set new normal size of WINDOW to SIZE.
3724 WINDOW must be a valid window and defaults to the selected one.
3725 Return SIZE.
3727 Note: This function does not operate on any child windows of WINDOW. */)
3728 (Lisp_Object window, Lisp_Object size)
3730 wset_new_normal (decode_valid_window (window), size);
3731 return size;
3734 /* Return 1 if setting w->pixel_height (w->pixel_width if HORFLAG is
3735 non-zero) to w->new_pixel would result in correct heights (widths)
3736 for window W and recursively all child windows of W.
3738 Note: This function does not check any of `window-fixed-size-p',
3739 `window-min-height' or `window-min-width'. It does check that window
3740 sizes do not drop below one line (two columns). */
3741 static int
3742 window_resize_check (struct window *w, bool horflag)
3744 struct frame *f = XFRAME (w->frame);
3745 struct window *c;
3747 if (WINDOW_VERTICAL_COMBINATION_P (w))
3748 /* W is a vertical combination. */
3750 c = XWINDOW (w->contents);
3751 if (horflag)
3752 /* All child windows of W must have the same width as W. */
3754 while (c)
3756 if (XINT (c->new_pixel) != XINT (w->new_pixel)
3757 || !window_resize_check (c, horflag))
3758 return 0;
3760 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3763 return 1;
3765 else
3766 /* The sum of the heights of the child windows of W must equal
3767 W's height. */
3769 int remaining_pixels = XINT (w->new_pixel);
3771 while (c)
3773 if (!window_resize_check (c, horflag))
3774 return 0;
3776 remaining_pixels -= XINT (c->new_pixel);
3777 if (remaining_pixels < 0)
3778 return 0;
3779 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3782 return remaining_pixels == 0;
3785 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3786 /* W is a horizontal combination. */
3788 c = XWINDOW (w->contents);
3789 if (horflag)
3790 /* The sum of the widths of the child windows of W must equal W's
3791 width. */
3793 int remaining_pixels = XINT (w->new_pixel);
3795 while (c)
3797 if (!window_resize_check (c, horflag))
3798 return 0;
3800 remaining_pixels -= XINT (c->new_pixel);
3801 if (remaining_pixels < 0)
3802 return 0;
3803 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3806 return remaining_pixels == 0;
3808 else
3809 /* All child windows of W must have the same height as W. */
3811 while (c)
3813 if (XINT (c->new_pixel) != XINT (w->new_pixel)
3814 || !window_resize_check (c, horflag))
3815 return 0;
3817 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3820 return 1;
3823 else
3824 /* A leaf window. Make sure it's not too small. The following
3825 hardcodes the values of `window-safe-min-width' (2) and
3826 `window-safe-min-height' (1) which are defined in window.el. */
3827 return (XINT (w->new_pixel) >= (horflag
3828 ? (2 * FRAME_COLUMN_WIDTH (f))
3829 : FRAME_LINE_HEIGHT (f)));
3833 /* Set w->pixel_height (w->pixel_height if HORIZONTAL is non-zero) to
3834 w->new_pixel for window W and recursively all child windows of W.
3835 Also calculate and assign the new vertical (horizontal) pixel start
3836 positions of each of these windows.
3838 This function does not perform any error checks. Make sure you have
3839 run window_resize_check on W before applying this function. */
3840 static void
3841 window_resize_apply (struct window *w, bool horflag)
3843 struct window *c;
3844 int edge;
3845 int unit = (horflag
3846 ? FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w))
3847 : FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
3849 /* Note: Assigning new_normal requires that the new total size of the
3850 parent window has been set *before*. */
3851 if (horflag)
3853 w->pixel_width = XFASTINT (w->new_pixel);
3854 w->total_cols = w->pixel_width / unit;
3855 if (NUMBERP (w->new_normal))
3856 wset_normal_cols (w, w->new_normal);
3858 edge = w->pixel_left;
3860 else
3862 w->pixel_height = XFASTINT (w->new_pixel);
3863 w->total_lines = w->pixel_height / unit;
3864 if (NUMBERP (w->new_normal))
3865 wset_normal_lines (w, w->new_normal);
3867 edge = w->pixel_top;
3870 if (WINDOW_VERTICAL_COMBINATION_P (w))
3871 /* W is a vertical combination. */
3873 c = XWINDOW (w->contents);
3874 while (c)
3876 if (horflag)
3878 c->pixel_left = edge;
3879 c->left_col = edge / unit;
3881 else
3883 c->pixel_top = edge;
3884 c->top_line = edge / unit;
3886 window_resize_apply (c, horflag);
3887 if (!horflag)
3888 edge = edge + c->pixel_height;
3890 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3893 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3894 /* W is a horizontal combination. */
3896 c = XWINDOW (w->contents);
3897 while (c)
3899 if (horflag)
3901 c->pixel_left = edge;
3902 c->left_col = edge / unit;
3904 else
3906 c->pixel_top = edge;
3907 c->top_line = edge / unit;
3910 window_resize_apply (c, horflag);
3911 if (horflag)
3912 edge = edge + c->pixel_width;
3914 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3917 else
3918 /* Bug#15957. */
3919 w->window_end_valid = 0;
3923 /* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
3924 w->new_total for window W and recursively all child windows of W.
3925 Also calculate and assign the new vertical (horizontal) start
3926 positions of each of these windows. */
3927 static void
3928 window_resize_apply_total (struct window *w, bool horflag)
3930 struct window *c;
3931 int edge;
3933 /* Note: Assigning new_normal requires that the new total size of the
3934 parent window has been set *before*. */
3935 if (horflag)
3937 w->total_cols = XFASTINT (w->new_total);
3938 edge = w->left_col;
3940 else
3942 w->total_lines = XFASTINT (w->new_total);
3943 edge = w->top_line;
3946 if (WINDOW_VERTICAL_COMBINATION_P (w))
3947 /* W is a vertical combination. */
3949 c = XWINDOW (w->contents);
3950 while (c)
3952 if (horflag)
3953 c->left_col = edge;
3954 else
3955 c->top_line = edge;
3957 window_resize_apply_total (c, horflag);
3958 if (!horflag)
3959 edge = edge + c->total_lines;
3961 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3964 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3965 /* W is a horizontal combination. */
3967 c = XWINDOW (w->contents);
3968 while (c)
3970 if (horflag)
3971 c->left_col = edge;
3972 else
3973 c->top_line = edge;
3975 window_resize_apply_total (c, horflag);
3976 if (horflag)
3977 edge = edge + c->total_cols;
3979 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3984 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 0, 2, 0,
3985 doc: /* Apply requested size values for window-tree of FRAME.
3986 If FRAME is omitted or nil, it defaults to the selected frame.
3988 Optional argument HORIZONTAL omitted or nil means apply requested
3989 height values. HORIZONTAL non-nil means apply requested width values.
3991 This function checks whether the requested values sum up to a valid
3992 window layout, recursively assigns the new sizes of all child windows
3993 and calculates and assigns the new start positions of these windows.
3995 Note: This function does not check any of `window-fixed-size-p',
3996 `window-min-height' or `window-min-width'. All these checks have to
3997 be applied on the Elisp level. */)
3998 (Lisp_Object frame, Lisp_Object horizontal)
4000 struct frame *f = decode_live_frame (frame);
4001 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
4002 bool horflag = !NILP (horizontal);
4004 if (!window_resize_check (r, horflag)
4005 || (XINT (r->new_pixel)
4006 != (horflag ? r->pixel_width : r->pixel_height)))
4007 return Qnil;
4009 block_input ();
4010 window_resize_apply (r, horflag);
4012 fset_redisplay (f);
4013 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4015 adjust_frame_glyphs (f);
4016 unblock_input ();
4018 return Qt;
4022 DEFUN ("window-resize-apply-total", Fwindow_resize_apply_total, Swindow_resize_apply_total, 0, 2, 0,
4023 doc: /* Apply requested total size values for window-tree of FRAME.
4024 If FRAME is omitted or nil, it defaults to the selected frame.
4026 This function does not assign pixel or normal size values. You should
4027 have run `window-resize-apply' before running this.
4029 Optional argument HORIZONTAL omitted or nil means apply requested
4030 height values. HORIZONTAL non-nil means apply requested width
4031 values. */)
4032 (Lisp_Object frame, Lisp_Object horizontal)
4034 struct frame *f = decode_live_frame (frame);
4035 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
4037 block_input ();
4038 /* Necessary when deleting the top-/or leftmost window. */
4039 r->left_col = 0;
4040 r->top_line = FRAME_TOP_MARGIN (f);
4041 window_resize_apply_total (r, !NILP (horizontal));
4042 /* Handle the mini window. */
4043 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
4045 struct window *m = XWINDOW (f->minibuffer_window);
4047 if (NILP (horizontal))
4049 m->top_line = r->top_line + r->total_lines;
4050 m->total_lines = XFASTINT (m->new_total);
4052 else
4053 m->total_cols = XFASTINT (m->new_total);
4056 unblock_input ();
4058 return Qt;
4062 /* Resize frame F's windows when number of lines of F is set to SIZE.
4063 HORFLAG 1 means resize windows when number of columns of F is set to
4064 SIZE. PIXELWISE 1 means to interpret SIZE as pixels.
4066 This function can delete all windows but the selected one in order to
4067 satisfy the request. The result will be meaningful if and only if
4068 F's windows have meaningful sizes when you call this. */
4069 void
4070 resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
4072 Lisp_Object root = f->root_window;
4073 struct window *r = XWINDOW (root);
4074 Lisp_Object mini = f->minibuffer_window;
4075 struct window *m;
4076 /* old_size is the old size of the frame's root window. */
4077 int old_size = horflag ? r->total_cols : r->total_lines;
4078 int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
4079 /* new_size is the new size of the frame's root window. */
4080 int new_size, new_pixel_size;
4081 int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
4083 /* Don't let the size drop below one unit. This is more comforting
4084 when we are called from x_set_tool_bar_lines since the latter may
4085 have implicitly given us a zero or negative height. */
4086 if (pixelwise)
4088 /* Note: This does not include the size for internal borders
4089 since these are not part of the frame's text area. */
4090 new_pixel_size = max (horflag
4091 ? size
4092 : (size
4093 - FRAME_TOP_MARGIN_HEIGHT (f)
4094 - ((FRAME_HAS_MINIBUF_P (f)
4095 && !FRAME_MINIBUF_ONLY_P (f))
4096 ? FRAME_LINE_HEIGHT (f) : 0)),
4097 unit);
4098 new_size = new_pixel_size / unit;
4100 else
4102 new_size = max (horflag
4103 ? size
4104 : (size
4105 - FRAME_TOP_MARGIN (f)
4106 - ((FRAME_HAS_MINIBUF_P (f)
4107 && !FRAME_MINIBUF_ONLY_P (f))
4108 ? 1 : 0)),
4110 new_pixel_size = new_size * unit;
4113 r->top_line = FRAME_TOP_MARGIN (f);
4114 r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
4116 if (new_pixel_size == old_pixel_size)
4118 else if (WINDOW_LEAF_P (r))
4119 /* For a leaf root window just set the size. */
4120 if (horflag)
4122 r->total_cols = new_size;
4123 r->pixel_width = new_pixel_size;
4125 else
4127 r->total_lines = new_size;
4128 r->pixel_height = new_pixel_size;
4130 else
4132 Lisp_Object delta;
4134 if (pixelwise)
4135 XSETINT (delta, new_pixel_size - old_pixel_size);
4136 else
4137 XSETINT (delta, new_size - old_size);
4139 /* Try a "normal" resize first. */
4140 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil,
4141 pixelwise ? Qt : Qnil);
4142 if (window_resize_check (r, horflag)
4143 && new_pixel_size == XINT (r->new_pixel))
4145 window_resize_apply (r, horflag);
4146 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4148 else
4150 /* Try with "reasonable" minimum sizes next. */
4151 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt,
4152 pixelwise ? Qt : Qnil);
4153 if (window_resize_check (r, horflag)
4154 && new_pixel_size == XINT (r->new_pixel))
4156 window_resize_apply (r, horflag);
4157 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4159 else
4161 /* Finally, try with "safe" minimum sizes. */
4162 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe,
4163 pixelwise ? Qt : Qnil);
4164 if (window_resize_check (r, horflag)
4165 && new_pixel_size == XINT (r->new_pixel))
4167 window_resize_apply (r, horflag);
4168 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
4170 #if 0 /* Let's try without killing other windows. */
4171 else
4173 /* We lost. Delete all windows but the frame's
4174 selected one. */
4175 root = f->selected_window;
4176 Fdelete_other_windows_internal (root, Qnil);
4177 if (horflag)
4179 XWINDOW (root)->total_cols = new_size;
4180 XWINDOW (root)->pixel_width = new_pixel_size;
4182 else
4184 XWINDOW (root)->total_lines = new_size;
4185 XWINDOW (root)->pixel_height = new_pixel_size;
4188 #endif /* 0 */
4193 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
4195 m = XWINDOW (mini);
4196 if (horflag)
4198 m->total_cols = size;
4199 m->pixel_width = new_pixel_size;
4201 else
4203 /* Are we sure we always want 1 line here? */
4204 m->total_lines = 1;
4205 m->pixel_height = FRAME_LINE_HEIGHT (f);
4206 m->top_line = r->top_line + r->total_lines;
4207 m->pixel_top = r->pixel_top + r->pixel_height;
4211 fset_redisplay (f);
4215 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
4216 doc: /* Split window OLD.
4217 Second argument PIXEL-SIZE specifies the number of pixels of the
4218 new window. In any case TOTAL-SIZE must be a positive integer.
4220 Third argument SIDE nil (or `below') specifies that the new window shall
4221 be located below WINDOW. SIDE `above' means the new window shall be
4222 located above WINDOW. In both cases PIXEL-SIZE specifies the pixel
4223 height of the new window including space reserved for the mode and/or
4224 header line.
4226 SIDE t (or `right') specifies that the new window shall be located on
4227 the right side of WINDOW. SIDE `left' means the new window shall be
4228 located on the left of WINDOW. In both cases PIXEL-SIZE specifies the
4229 width of the new window including space reserved for fringes and the
4230 scrollbar or a divider column.
4232 Fourth argument NORMAL-SIZE specifies the normal size of the new window
4233 according to the SIDE argument.
4235 The new pixel and normal sizes of all involved windows must have been
4236 set correctly. See the code of `split-window' for how this is done. */)
4237 (Lisp_Object old, Lisp_Object pixel_size, Lisp_Object side, Lisp_Object normal_size)
4239 /* OLD (*o) is the window we have to split. (*p) is either OLD's
4240 parent window or an internal window we have to install as OLD's new
4241 parent. REFERENCE (*r) must denote a live window, or is set to OLD
4242 provided OLD is a leaf window, or to the frame's selected window.
4243 NEW (*n) is the new window created with some parameters taken from
4244 REFERENCE (*r). */
4245 register Lisp_Object new, frame, reference;
4246 register struct window *o, *p, *n, *r, *c;
4247 struct frame *f;
4248 bool horflag
4249 /* HORFLAG is 1 when we split side-by-side, 0 otherwise. */
4250 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
4251 int combination_limit = 0, sum = 0;
4252 int total_size;
4254 CHECK_WINDOW (old);
4255 o = XWINDOW (old);
4256 frame = WINDOW_FRAME (o);
4257 f = XFRAME (frame);
4259 CHECK_NUMBER (pixel_size);
4260 total_size
4261 = XINT (pixel_size) / (horflag
4262 ? FRAME_COLUMN_WIDTH (f)
4263 : FRAME_LINE_HEIGHT (f));
4265 /* Set combination_limit to 1 if we have to make a new parent window.
4266 We do that if either `window-combination-limit' is t, or OLD has no
4267 parent, or OLD is ortho-combined. */
4268 combination_limit =
4269 EQ (Vwindow_combination_limit, Qt)
4270 || NILP (o->parent)
4271 || (horflag
4272 ? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
4273 : WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent)));
4275 /* We need a live reference window to initialize some parameters. */
4276 if (WINDOW_LIVE_P (old))
4277 /* OLD is live, use it as reference window. */
4278 reference = old;
4279 else
4280 /* Use the frame's selected window as reference window. */
4281 reference = FRAME_SELECTED_WINDOW (f);
4282 r = XWINDOW (reference);
4284 /* The following bugs are caught by `split-window'. */
4285 if (MINI_WINDOW_P (o))
4286 error ("Attempt to split minibuffer window");
4287 else if (total_size < (horflag ? 2 : 1))
4288 error ("Size of new window too small (after split)");
4289 else if (!combination_limit && !NILP (Vwindow_combination_resize))
4290 /* `window-combination-resize' non-nil means try to resize OLD's siblings
4291 proportionally. */
4293 p = XWINDOW (o->parent);
4294 /* Temporarily pretend we split the parent window. */
4295 wset_new_pixel
4296 (p, make_number ((horflag ? p->pixel_width : p->pixel_height)
4297 - XINT (pixel_size)));
4298 if (!window_resize_check (p, horflag))
4299 error ("Window sizes don't fit");
4300 else
4301 /* Undo the temporary pretension. */
4302 wset_new_pixel (p, make_number (horflag ? p->pixel_width : p->pixel_height));
4304 else
4306 if (!window_resize_check (o, horflag))
4307 error ("Resizing old window failed");
4308 else if (XINT (pixel_size) + XINT (o->new_pixel)
4309 != (horflag ? o->pixel_width : o->pixel_height))
4310 error ("Sum of sizes of old and new window don't fit");
4313 /* This is our point of no return. */
4314 if (combination_limit)
4316 /* Save the old value of o->normal_cols/lines. It gets corrupted
4317 by make_parent_window and we need it below for assigning it to
4318 p->new_normal. */
4319 Lisp_Object new_normal
4320 = horflag ? o->normal_cols : o->normal_lines;
4322 make_parent_window (old, horflag);
4323 p = XWINDOW (o->parent);
4324 if (EQ (Vwindow_combination_limit, Qt))
4325 /* Store t in the new parent's combination_limit slot to avoid
4326 that its children get merged into another window. */
4327 wset_combination_limit (p, Qt);
4328 /* These get applied below. */
4329 wset_new_pixel
4330 (p, make_number (horflag ? o->pixel_width : o->pixel_height));
4331 wset_new_total
4332 (p, make_number (horflag ? o->total_cols : o->total_lines));
4333 wset_new_normal (p, new_normal);
4335 else
4336 p = XWINDOW (o->parent);
4338 fset_redisplay (f);
4339 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4340 new = make_window ();
4341 n = XWINDOW (new);
4342 wset_frame (n, frame);
4343 wset_parent (n, o->parent);
4345 if (EQ (side, Qabove) || EQ (side, Qleft))
4347 wset_prev (n, o->prev);
4348 if (NILP (n->prev))
4349 wset_combination (p, horflag, new);
4350 else
4351 wset_next (XWINDOW (n->prev), new);
4352 wset_next (n, old);
4353 wset_prev (o, new);
4355 else
4357 wset_next (n, o->next);
4358 if (!NILP (n->next))
4359 wset_prev (XWINDOW (n->next), new);
4360 wset_prev (n, old);
4361 wset_next (o, new);
4364 n->window_end_valid = 0;
4365 n->last_cursor_vpos = 0;
4367 /* Get special geometry settings from reference window. */
4368 n->left_margin_cols = r->left_margin_cols;
4369 n->right_margin_cols = r->right_margin_cols;
4370 n->left_fringe_width = r->left_fringe_width;
4371 n->right_fringe_width = r->right_fringe_width;
4372 n->fringes_outside_margins = r->fringes_outside_margins;
4373 n->scroll_bar_width = r->scroll_bar_width;
4374 wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
4376 /* Directly assign orthogonal coordinates and sizes. */
4377 if (horflag)
4379 n->pixel_top = o->pixel_top;
4380 n->top_line = o->top_line;
4381 n->pixel_height = o->pixel_height;
4382 n->total_lines = o->total_lines;
4384 else
4386 n->pixel_left = o->pixel_left;
4387 n->left_col = o->left_col;
4388 n->pixel_width = o->pixel_width;
4389 n->total_cols = o->total_cols;
4392 /* Iso-coordinates and sizes are assigned by window_resize_apply,
4393 get them ready here. */
4394 wset_new_pixel (n, pixel_size);
4395 c = XWINDOW (p->contents);
4396 while (c)
4398 if (c != n)
4399 sum = sum + XINT (c->new_total);
4400 c = NILP (c->next) ? 0 : XWINDOW (c->next);
4402 wset_new_total (n, make_number ((horflag
4403 ? p->total_cols
4404 : p->total_lines)
4405 - sum));
4406 wset_new_normal (n, normal_size);
4408 block_input ();
4409 window_resize_apply (p, horflag);
4410 adjust_frame_glyphs (f);
4411 /* Set buffer of NEW to buffer of reference window. Don't run
4412 any hooks. */
4413 set_window_buffer (new, r->contents, 0, 1);
4414 unblock_input ();
4416 /* Maybe we should run the scroll functions in Elisp (which already
4417 runs the configuration change hook). */
4418 if (! NILP (Vwindow_scroll_functions))
4419 run_hook_with_args_2 (Qwindow_scroll_functions, new,
4420 Fmarker_position (n->start));
4421 /* Return NEW. */
4422 return new;
4426 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
4427 doc: /* Remove WINDOW from its frame.
4428 WINDOW defaults to the selected window. Return nil.
4429 Signal an error when WINDOW is the only window on its frame. */)
4430 (register Lisp_Object window)
4432 register Lisp_Object parent, sibling, frame, root;
4433 struct window *w, *p, *s, *r;
4434 struct frame *f;
4435 bool horflag, before_sibling = 0;
4437 w = decode_any_window (window);
4438 XSETWINDOW (window, w);
4439 if (NILP (w->contents))
4440 /* It's a no-op to delete an already deleted window. */
4441 return Qnil;
4443 parent = w->parent;
4444 if (NILP (parent))
4445 /* Never delete a minibuffer or frame root window. */
4446 error ("Attempt to delete minibuffer or sole ordinary window");
4447 else if (NILP (w->prev) && NILP (w->next))
4448 /* Rather bow out here, this case should be handled on the Elisp
4449 level. */
4450 error ("Attempt to delete sole window of parent");
4452 p = XWINDOW (parent);
4453 horflag = WINDOW_HORIZONTAL_COMBINATION_P (p);
4455 frame = WINDOW_FRAME (w);
4456 f = XFRAME (frame);
4458 root = FRAME_ROOT_WINDOW (f);
4459 r = XWINDOW (root);
4461 /* Unlink WINDOW from window tree. */
4462 if (NILP (w->prev))
4463 /* Get SIBLING below (on the right of) WINDOW. */
4465 /* before_sibling 1 means WINDOW is the first child of its
4466 parent and thus before the sibling. */
4467 before_sibling = 1;
4468 sibling = w->next;
4469 s = XWINDOW (sibling);
4470 wset_prev (s, Qnil);
4471 wset_combination (p, horflag, sibling);
4473 else
4474 /* Get SIBLING above (on the left of) WINDOW. */
4476 sibling = w->prev;
4477 s = XWINDOW (sibling);
4478 wset_next (s, w->next);
4479 if (!NILP (s->next))
4480 wset_prev (XWINDOW (s->next), sibling);
4483 if (window_resize_check (r, horflag)
4484 && (XINT (r->new_pixel)
4485 == (horflag ? r->pixel_width : r->pixel_height)))
4486 /* We can delete WINDOW now. */
4489 /* Block input. */
4490 block_input ();
4491 window_resize_apply (p, horflag);
4492 /* If this window is referred to by the dpyinfo's mouse
4493 highlight, invalidate that slot to be safe (Bug#9904). */
4494 if (!FRAME_INITIAL_P (f))
4496 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
4498 if (EQ (hlinfo->mouse_face_window, window))
4499 hlinfo->mouse_face_window = Qnil;
4502 fset_redisplay (f);
4503 Vwindow_list = Qnil;
4504 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4506 wset_next (w, Qnil); /* Don't delete w->next too. */
4507 free_window_matrices (w);
4509 if (WINDOWP (w->contents))
4511 delete_all_child_windows (w->contents);
4512 wset_combination (w, 0, Qnil);
4514 else
4516 unshow_buffer (w);
4517 unchain_marker (XMARKER (w->pointm));
4518 unchain_marker (XMARKER (w->start));
4519 wset_buffer (w, Qnil);
4522 if (NILP (s->prev) && NILP (s->next))
4523 /* A matrjoshka where SIBLING has become the only child of
4524 PARENT. */
4526 /* Put SIBLING into PARENT's place. */
4527 replace_window (parent, sibling, 0);
4528 /* Have SIBLING inherit the following three slot values from
4529 PARENT (the combination_limit slot is not inherited). */
4530 wset_normal_cols (s, p->normal_cols);
4531 wset_normal_lines (s, p->normal_lines);
4532 /* Mark PARENT as deleted. */
4533 wset_combination (p, 0, Qnil);
4534 /* Try to merge SIBLING into its new parent. */
4535 recombine_windows (sibling);
4538 adjust_frame_glyphs (f);
4540 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
4541 /* We deleted the frame's selected window. */
4543 /* Use the frame's first window as fallback ... */
4544 Lisp_Object new_selected_window = Fframe_first_window (frame);
4545 /* ... but preferably use its most recently used window. */
4546 Lisp_Object mru_window;
4548 /* `get-mru-window' might fail for some reason so play it safe
4549 - promote the first window _without recording it_ first. */
4550 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4551 Fselect_window (new_selected_window, Qt);
4552 else
4553 fset_selected_window (f, new_selected_window);
4555 unblock_input ();
4557 /* Now look whether `get-mru-window' gets us something. */
4558 mru_window = call1 (Qget_mru_window, frame);
4559 if (WINDOW_LIVE_P (mru_window)
4560 && EQ (XWINDOW (mru_window)->frame, frame))
4561 new_selected_window = mru_window;
4563 /* If all ended up well, we now promote the mru window. */
4564 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4565 Fselect_window (new_selected_window, Qnil);
4566 else
4567 fset_selected_window (f, new_selected_window);
4569 else
4570 unblock_input ();
4572 /* Must be run by the caller:
4573 run_window_configuration_change_hook (f); */
4575 else
4576 /* We failed: Relink WINDOW into window tree. */
4578 if (before_sibling)
4580 wset_prev (s, window);
4581 wset_combination (p, horflag, window);
4583 else
4585 wset_next (s, window);
4586 if (!NILP (w->next))
4587 wset_prev (XWINDOW (w->next), window);
4589 error ("Deletion failed");
4592 return Qnil;
4595 /***********************************************************************
4596 Resizing Mini-Windows
4597 ***********************************************************************/
4599 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
4600 can. */
4601 void
4602 grow_mini_window (struct window *w, int delta, bool pixelwise)
4604 struct frame *f = XFRAME (w->frame);
4605 struct window *r;
4606 Lisp_Object root, height;
4607 int line_height, pixel_height;
4609 eassert (MINI_WINDOW_P (w));
4610 eassert (delta >= 0);
4612 if (delta > 0)
4614 root = FRAME_ROOT_WINDOW (f);
4615 r = XWINDOW (root);
4616 height = call3 (Qwindow_resize_root_window_vertically,
4617 root, make_number (- delta), pixelwise ? Qt : Qnil);
4618 if (INTEGERP (height) && window_resize_check (r, 0))
4620 block_input ();
4621 window_resize_apply (r, 0);
4623 if (pixelwise)
4625 pixel_height = min (-XINT (height), INT_MAX - w->pixel_height);
4626 line_height = pixel_height / FRAME_LINE_HEIGHT (f);
4628 else
4630 line_height = min (-XINT (height),
4631 ((INT_MAX - w->pixel_height)
4632 / FRAME_LINE_HEIGHT (f)));
4633 pixel_height = line_height * FRAME_LINE_HEIGHT (f);
4636 /* Grow the mini-window. */
4637 w->pixel_top = r->pixel_top + r->pixel_height;
4638 w->top_line = r->top_line + r->total_lines;
4639 /* Make sure the mini-window has always at least one line. */
4640 w->pixel_height = max (w->pixel_height + pixel_height,
4641 FRAME_LINE_HEIGHT (f));
4642 w->total_lines = max (w->total_lines + line_height, 1);
4644 /* Enforce full redisplay of the frame. */
4645 /* FIXME: Shouldn't window--resize-root-window-vertically do it? */
4646 fset_redisplay (f);
4647 adjust_frame_glyphs (f);
4648 unblock_input ();
4653 /* Shrink mini-window W to one line. */
4654 void
4655 shrink_mini_window (struct window *w, bool pixelwise)
4657 struct frame *f = XFRAME (w->frame);
4658 struct window *r;
4659 Lisp_Object root, delta;
4660 EMACS_INT height, unit;
4662 eassert (MINI_WINDOW_P (w));
4664 height = pixelwise ? w->pixel_height : w->total_lines;
4665 unit = pixelwise ? FRAME_LINE_HEIGHT (f) : 1;
4666 if (height > unit)
4668 root = FRAME_ROOT_WINDOW (f);
4669 r = XWINDOW (root);
4670 delta = call3 (Qwindow_resize_root_window_vertically,
4671 root, make_number (height - unit),
4672 pixelwise ? Qt : Qnil);
4673 if (INTEGERP (delta) && window_resize_check (r, 0))
4675 block_input ();
4676 window_resize_apply (r, 0);
4678 /* Shrink the mini-window. */
4679 w->top_line = r->top_line + r->total_lines;
4680 w->total_lines = 1;
4681 w->pixel_top = r->pixel_top + r->pixel_height;
4682 w->pixel_height = FRAME_LINE_HEIGHT (f);
4683 /* Enforce full redisplay of the frame. */
4684 /* FIXME: Shouldn't window--resize-root-window-vertically do it? */
4685 fset_redisplay (f);
4686 adjust_frame_glyphs (f);
4687 unblock_input ();
4689 /* If the above failed for whatever strange reason we must make a
4690 one window frame here. The same routine will be needed when
4691 shrinking the frame (and probably when making the initial
4692 *scratch* window). For the moment leave things as they are. */
4696 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
4697 doc: /* Resize minibuffer window WINDOW. */)
4698 (Lisp_Object window)
4700 struct window *w = XWINDOW (window);
4701 struct window *r;
4702 struct frame *f;
4703 int height;
4705 CHECK_WINDOW (window);
4706 f = XFRAME (w->frame);
4708 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
4709 error ("Not a valid minibuffer window");
4710 else if (FRAME_MINIBUF_ONLY_P (f))
4711 error ("Cannot resize a minibuffer-only frame");
4713 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4714 height = r->pixel_height + w->pixel_height;
4715 if (window_resize_check (r, 0)
4716 && XINT (w->new_pixel) > 0
4717 && height == XINT (r->new_pixel) + XINT (w->new_pixel))
4719 block_input ();
4720 window_resize_apply (r, 0);
4722 w->total_lines = XFASTINT (w->new_total);
4723 w->top_line = r->top_line + r->total_lines;
4724 w->pixel_height = XFASTINT (w->new_pixel);
4725 w->pixel_top = r->pixel_top + r->pixel_height;
4727 fset_redisplay (f);
4728 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4729 adjust_frame_glyphs (f);
4730 unblock_input ();
4731 return Qt;
4733 else
4734 error ("Failed to resize minibuffer window");
4737 /* Mark window cursors off for all windows in the window tree rooted
4738 at W by setting their phys_cursor_on_p flag to zero. Called from
4739 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4740 the frame are cleared. */
4742 void
4743 mark_window_cursors_off (struct window *w)
4745 while (w)
4747 if (WINDOWP (w->contents))
4748 mark_window_cursors_off (XWINDOW (w->contents));
4749 else
4750 w->phys_cursor_on_p = 0;
4752 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4757 /* Return number of lines of text (not counting mode lines) in W. */
4760 window_internal_height (struct window *w)
4762 int ht = w->total_lines;
4764 if (!MINI_WINDOW_P (w))
4766 if (!NILP (w->parent)
4767 || WINDOWP (w->contents)
4768 || !NILP (w->next)
4769 || !NILP (w->prev)
4770 || WINDOW_WANTS_MODELINE_P (w))
4771 --ht;
4773 if (WINDOW_WANTS_HEADER_LINE_P (w))
4774 --ht;
4777 return ht;
4780 /************************************************************************
4781 Window Scrolling
4782 ***********************************************************************/
4784 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4785 N screen-fulls, which is defined as the height of the window minus
4786 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4787 instead. Negative values of N mean scroll down. NOERROR non-zero
4788 means don't signal an error if we try to move over BEGV or ZV,
4789 respectively. */
4791 static void
4792 window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
4794 immediate_quit = 1;
4795 n = clip_to_bounds (INT_MIN, n, INT_MAX);
4797 wset_redisplay (XWINDOW (window));
4799 /* If we must, use the pixel-based version which is much slower than
4800 the line-based one but can handle varying line heights. */
4801 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4802 window_scroll_pixel_based (window, n, whole, noerror);
4803 else
4804 window_scroll_line_based (window, n, whole, noerror);
4806 /* Bug#15957. */
4807 XWINDOW (window)->window_end_valid = 0;
4808 immediate_quit = 0;
4812 /* Implementation of window_scroll that works based on pixel line
4813 heights. See the comment of window_scroll for parameter
4814 descriptions. */
4816 static void
4817 window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
4819 struct it it;
4820 struct window *w = XWINDOW (window);
4821 struct text_pos start;
4822 int this_scroll_margin;
4823 /* True if we fiddled the window vscroll field without really scrolling. */
4824 int vscrolled = 0;
4825 int x, y, rtop, rbot, rowh, vpos;
4826 void *itdata = NULL;
4827 int window_total_lines;
4828 int frame_line_height = default_line_pixel_height (w);
4830 SET_TEXT_POS_FROM_MARKER (start, w->start);
4831 /* Scrolling a minibuffer window via scroll bar when the echo area
4832 shows long text sometimes resets the minibuffer contents behind
4833 our backs. */
4834 if (CHARPOS (start) > ZV)
4835 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4837 /* If PT is not visible in WINDOW, move back one half of
4838 the screen. Allow PT to be partially visible, otherwise
4839 something like (scroll-down 1) with PT in the line before
4840 the partially visible one would recenter. */
4842 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4844 itdata = bidi_shelve_cache ();
4845 /* Move backward half the height of the window. Performance note:
4846 vmotion used here is about 10% faster, but would give wrong
4847 results for variable height lines. */
4848 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4849 it.current_y = it.last_visible_y;
4850 move_it_vertically_backward (&it, window_box_height (w) / 2);
4852 /* The function move_iterator_vertically may move over more than
4853 the specified y-distance. If it->w is small, e.g. a
4854 mini-buffer window, we may end up in front of the window's
4855 display area. This is the case when Start displaying at the
4856 start of the line containing PT in this case. */
4857 if (it.current_y <= 0)
4859 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4860 move_it_vertically_backward (&it, 0);
4861 it.current_y = 0;
4864 start = it.current.pos;
4865 bidi_unshelve_cache (itdata, 0);
4867 else if (auto_window_vscroll_p)
4869 if (rtop || rbot) /* partially visible */
4871 int px;
4872 int dy = frame_line_height;
4873 if (whole)
4874 dy = max ((window_box_height (w)
4875 - next_screen_context_lines * dy),
4876 dy);
4877 dy *= n;
4879 if (n < 0)
4881 /* Only vscroll backwards if already vscrolled forwards. */
4882 if (w->vscroll < 0 && rtop > 0)
4884 px = max (0, -w->vscroll - min (rtop, -dy));
4885 Fset_window_vscroll (window, make_number (px), Qt);
4886 return;
4889 if (n > 0)
4891 /* Do vscroll if already vscrolled or only display line. */
4892 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4894 px = max (0, -w->vscroll + min (rbot, dy));
4895 Fset_window_vscroll (window, make_number (px), Qt);
4896 return;
4899 /* Maybe modify window start instead of scrolling. */
4900 if (rbot > 0 || w->vscroll < 0)
4902 ptrdiff_t spos;
4904 Fset_window_vscroll (window, make_number (0), Qt);
4905 /* If there are other text lines above the current row,
4906 move window start to current row. Else to next row. */
4907 if (rbot > 0)
4908 spos = XINT (Fline_beginning_position (Qnil));
4909 else
4910 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4911 set_marker_restricted (w->start, make_number (spos),
4912 w->contents);
4913 w->start_at_line_beg = 1;
4914 w->update_mode_line = 1;
4915 /* Set force_start so that redisplay_window will run the
4916 window-scroll-functions. */
4917 w->force_start = 1;
4918 return;
4922 /* Cancel previous vscroll. */
4923 Fset_window_vscroll (window, make_number (0), Qt);
4926 itdata = bidi_shelve_cache ();
4927 /* If scroll_preserve_screen_position is non-nil, we try to set
4928 point in the same window line as it is now, so get that line. */
4929 if (!NILP (Vscroll_preserve_screen_position))
4931 /* We preserve the goal pixel coordinate across consecutive
4932 calls to scroll-up, scroll-down and other commands that
4933 have the `scroll-command' property. This avoids the
4934 possibility of point becoming "stuck" on a tall line when
4935 scrolling by one line. */
4936 if (window_scroll_pixel_based_preserve_y < 0
4937 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4938 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4940 start_display (&it, w, start);
4941 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4942 window_scroll_pixel_based_preserve_y = it.current_y;
4943 window_scroll_pixel_based_preserve_x = it.current_x;
4946 else
4947 window_scroll_pixel_based_preserve_y
4948 = window_scroll_pixel_based_preserve_x = -1;
4950 /* Move iterator it from start the specified distance forward or
4951 backward. The result is the new window start. */
4952 start_display (&it, w, start);
4953 if (whole)
4955 ptrdiff_t start_pos = IT_CHARPOS (it);
4956 int dy = frame_line_height;
4957 dy = max ((window_box_height (w)
4958 - next_screen_context_lines * dy),
4959 dy) * n;
4961 /* Note that move_it_vertically always moves the iterator to the
4962 start of a line. So, if the last line doesn't have a newline,
4963 we would end up at the start of the line ending at ZV. */
4964 if (dy <= 0)
4966 move_it_vertically_backward (&it, -dy);
4967 /* Ensure we actually do move, e.g. in case we are currently
4968 looking at an image that is taller that the window height. */
4969 while (start_pos == IT_CHARPOS (it)
4970 && start_pos > BEGV)
4971 move_it_by_lines (&it, -1);
4973 else if (dy > 0)
4975 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4976 MOVE_TO_POS | MOVE_TO_Y);
4977 /* Ensure we actually do move, e.g. in case we are currently
4978 looking at an image that is taller that the window height. */
4979 while (start_pos == IT_CHARPOS (it)
4980 && start_pos < ZV)
4981 move_it_by_lines (&it, 1);
4984 else
4985 move_it_by_lines (&it, n);
4987 /* We failed if we find ZV is already on the screen (scrolling up,
4988 means there's nothing past the end), or if we can't start any
4989 earlier (scrolling down, means there's nothing past the top). */
4990 if ((n > 0 && IT_CHARPOS (it) == ZV)
4991 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4993 if (IT_CHARPOS (it) == ZV)
4995 if (it.current_y < it.last_visible_y
4996 && (it.current_y + it.max_ascent + it.max_descent
4997 > it.last_visible_y))
4999 /* The last line was only partially visible, make it fully
5000 visible. */
5001 w->vscroll = (it.last_visible_y
5002 - it.current_y + it.max_ascent + it.max_descent);
5003 adjust_frame_glyphs (it.f);
5005 else
5007 bidi_unshelve_cache (itdata, 0);
5008 if (noerror)
5009 return;
5010 else if (n < 0) /* could happen with empty buffers */
5011 xsignal0 (Qbeginning_of_buffer);
5012 else
5013 xsignal0 (Qend_of_buffer);
5016 else
5018 if (w->vscroll != 0)
5019 /* The first line was only partially visible, make it fully
5020 visible. */
5021 w->vscroll = 0;
5022 else
5024 bidi_unshelve_cache (itdata, 0);
5025 if (noerror)
5026 return;
5027 else
5028 xsignal0 (Qbeginning_of_buffer);
5032 /* If control gets here, then we vscrolled. */
5034 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
5036 /* Don't try to change the window start below. */
5037 vscrolled = 1;
5040 if (! vscrolled)
5042 ptrdiff_t pos = IT_CHARPOS (it);
5043 ptrdiff_t bytepos;
5045 /* If in the middle of a multi-glyph character move forward to
5046 the next character. */
5047 if (in_display_vector_p (&it))
5049 ++pos;
5050 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
5053 /* Set the window start, and set up the window for redisplay. */
5054 set_marker_restricted_both (w->start, w->contents, IT_CHARPOS (it),
5055 IT_BYTEPOS (it));
5056 bytepos = marker_byte_position (w->start);
5057 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
5058 w->update_mode_line = 1;
5059 /* Set force_start so that redisplay_window will run the
5060 window-scroll-functions. */
5061 w->force_start = 1;
5064 /* The rest of this function uses current_y in a nonstandard way,
5065 not including the height of the header line if any. */
5066 it.current_y = it.vpos = 0;
5068 /* Move PT out of scroll margins.
5069 This code wants current_y to be zero at the window start position
5070 even if there is a header line. */
5071 window_total_lines
5072 = w->total_lines * WINDOW_FRAME_LINE_HEIGHT (w) / frame_line_height;
5073 this_scroll_margin = max (0, scroll_margin);
5074 this_scroll_margin
5075 = min (this_scroll_margin, window_total_lines / 4);
5076 this_scroll_margin *= frame_line_height;
5078 if (n > 0)
5080 /* We moved the window start towards ZV, so PT may be now
5081 in the scroll margin at the top. */
5082 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
5083 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
5084 && (NILP (Vscroll_preserve_screen_position)
5085 || EQ (Vscroll_preserve_screen_position, Qt)))
5086 /* We found PT at a legitimate height. Leave it alone. */
5088 else if (window_scroll_pixel_based_preserve_y >= 0)
5090 /* If we have a header line, take account of it.
5091 This is necessary because we set it.current_y to 0, above. */
5092 move_it_to (&it, -1,
5093 window_scroll_pixel_based_preserve_x,
5094 window_scroll_pixel_based_preserve_y
5095 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
5096 -1, MOVE_TO_Y | MOVE_TO_X);
5097 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5099 else
5101 while (it.current_y < this_scroll_margin)
5103 int prev = it.current_y;
5104 move_it_by_lines (&it, 1);
5105 if (prev == it.current_y)
5106 break;
5108 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5111 else if (n < 0)
5113 ptrdiff_t charpos, bytepos;
5114 int partial_p;
5116 /* Save our position, for the
5117 window_scroll_pixel_based_preserve_y case. */
5118 charpos = IT_CHARPOS (it);
5119 bytepos = IT_BYTEPOS (it);
5121 /* We moved the window start towards BEGV, so PT may be now
5122 in the scroll margin at the bottom. */
5123 move_it_to (&it, PT, -1,
5124 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
5125 - this_scroll_margin - 1),
5127 MOVE_TO_POS | MOVE_TO_Y);
5129 /* Save our position, in case it's correct. */
5130 charpos = IT_CHARPOS (it);
5131 bytepos = IT_BYTEPOS (it);
5133 /* See if point is on a partially visible line at the end. */
5134 if (it.what == IT_EOB)
5135 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
5136 else
5138 move_it_by_lines (&it, 1);
5139 partial_p = it.current_y > it.last_visible_y;
5142 if (charpos == PT && !partial_p
5143 && (NILP (Vscroll_preserve_screen_position)
5144 || EQ (Vscroll_preserve_screen_position, Qt)))
5145 /* We found PT before we found the display margin, so PT is ok. */
5147 else if (window_scroll_pixel_based_preserve_y >= 0)
5149 SET_TEXT_POS_FROM_MARKER (start, w->start);
5150 start_display (&it, w, start);
5151 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
5152 here because we called start_display again and did not
5153 alter it.current_y this time. */
5154 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
5155 window_scroll_pixel_based_preserve_y, -1,
5156 MOVE_TO_Y | MOVE_TO_X);
5157 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5159 else
5161 if (partial_p)
5162 /* The last line was only partially visible, so back up two
5163 lines to make sure we're on a fully visible line. */
5165 move_it_by_lines (&it, -2);
5166 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
5168 else
5169 /* No, the position we saved is OK, so use it. */
5170 SET_PT_BOTH (charpos, bytepos);
5173 bidi_unshelve_cache (itdata, 0);
5177 /* Implementation of window_scroll that works based on screen lines.
5178 See the comment of window_scroll for parameter descriptions. */
5180 static void
5181 window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
5183 register struct window *w = XWINDOW (window);
5184 /* Fvertical_motion enters redisplay, which can trigger
5185 fontification, which in turn can modify buffer text (e.g., if the
5186 fontification functions replace escape sequences with faces, as
5187 in `grep-mode-font-lock-keywords'). So we use a marker to record
5188 the old point position, to prevent crashes in SET_PT_BOTH. */
5189 Lisp_Object opoint_marker = Fpoint_marker ();
5190 register ptrdiff_t pos, pos_byte;
5191 register int ht = window_internal_height (w);
5192 register Lisp_Object tem;
5193 bool lose;
5194 Lisp_Object bolp;
5195 ptrdiff_t startpos = marker_position (w->start);
5196 ptrdiff_t startbyte = marker_byte_position (w->start);
5197 Lisp_Object original_pos = Qnil;
5199 /* If scrolling screen-fulls, compute the number of lines to
5200 scroll from the window's height. */
5201 if (whole)
5202 n *= max (1, ht - next_screen_context_lines);
5204 if (!NILP (Vscroll_preserve_screen_position))
5206 if (window_scroll_preserve_vpos <= 0
5207 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
5208 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
5210 struct position posit
5211 = *compute_motion (startpos, startbyte, 0, 0, 0,
5212 PT, ht, 0, -1, w->hscroll, 0, w);
5213 window_scroll_preserve_vpos = posit.vpos;
5214 window_scroll_preserve_hpos = posit.hpos + w->hscroll;
5217 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
5218 make_number (window_scroll_preserve_vpos));
5221 XSETFASTINT (tem, PT);
5222 tem = Fpos_visible_in_window_p (tem, window, Qnil);
5224 if (NILP (tem))
5226 Fvertical_motion (make_number (- (ht / 2)), window);
5227 startpos = PT;
5228 startbyte = PT_BYTE;
5231 SET_PT_BOTH (startpos, startbyte);
5232 lose = n < 0 && PT == BEGV;
5233 Fvertical_motion (make_number (n), window);
5234 pos = PT;
5235 pos_byte = PT_BYTE;
5236 bolp = Fbolp ();
5237 SET_PT_BOTH (marker_position (opoint_marker),
5238 marker_byte_position (opoint_marker));
5240 if (lose)
5242 if (noerror)
5243 return;
5244 else
5245 xsignal0 (Qbeginning_of_buffer);
5248 if (pos < ZV)
5250 /* Don't use a scroll margin that is negative or too large. */
5251 int this_scroll_margin =
5252 max (0, min (scroll_margin, w->total_lines / 4));
5254 set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
5255 w->start_at_line_beg = !NILP (bolp);
5256 w->update_mode_line = 1;
5257 /* Set force_start so that redisplay_window will run
5258 the window-scroll-functions. */
5259 w->force_start = 1;
5261 if (!NILP (Vscroll_preserve_screen_position)
5262 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
5264 SET_PT_BOTH (pos, pos_byte);
5265 Fvertical_motion (original_pos, window);
5267 /* If we scrolled forward, put point enough lines down
5268 that it is outside the scroll margin. */
5269 else if (n > 0)
5271 int top_margin;
5273 if (this_scroll_margin > 0)
5275 SET_PT_BOTH (pos, pos_byte);
5276 Fvertical_motion (make_number (this_scroll_margin), window);
5277 top_margin = PT;
5279 else
5280 top_margin = pos;
5282 if (top_margin <= marker_position (opoint_marker))
5283 SET_PT_BOTH (marker_position (opoint_marker),
5284 marker_byte_position (opoint_marker));
5285 else if (!NILP (Vscroll_preserve_screen_position))
5287 SET_PT_BOTH (pos, pos_byte);
5288 Fvertical_motion (original_pos, window);
5290 else
5291 SET_PT (top_margin);
5293 else if (n < 0)
5295 int bottom_margin;
5297 /* If we scrolled backward, put point near the end of the window
5298 but not within the scroll margin. */
5299 SET_PT_BOTH (pos, pos_byte);
5300 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
5301 if (XFASTINT (tem) == ht - this_scroll_margin)
5302 bottom_margin = PT;
5303 else
5304 bottom_margin = PT + 1;
5306 if (bottom_margin > marker_position (opoint_marker))
5307 SET_PT_BOTH (marker_position (opoint_marker),
5308 marker_byte_position (opoint_marker));
5309 else
5311 if (!NILP (Vscroll_preserve_screen_position))
5313 SET_PT_BOTH (pos, pos_byte);
5314 Fvertical_motion (original_pos, window);
5316 else
5317 Fvertical_motion (make_number (-1), window);
5321 else
5323 if (noerror)
5324 return;
5325 else
5326 xsignal0 (Qend_of_buffer);
5331 /* Scroll selected_window up or down. If N is nil, scroll a
5332 screen-full which is defined as the height of the window minus
5333 next_screen_context_lines. If N is the symbol `-', scroll.
5334 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
5335 up. This is the guts of Fscroll_up and Fscroll_down. */
5337 static void
5338 scroll_command (Lisp_Object n, int direction)
5340 ptrdiff_t count = SPECPDL_INDEX ();
5342 eassert (eabs (direction) == 1);
5344 /* If selected window's buffer isn't current, make it current for
5345 the moment. But don't screw up if window_scroll gets an error. */
5346 if (XBUFFER (XWINDOW (selected_window)->contents) != current_buffer)
5348 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5349 Fset_buffer (XWINDOW (selected_window)->contents);
5352 if (NILP (n))
5353 window_scroll (selected_window, direction, 1, 0);
5354 else if (EQ (n, Qminus))
5355 window_scroll (selected_window, -direction, 1, 0);
5356 else
5358 n = Fprefix_numeric_value (n);
5359 window_scroll (selected_window, XINT (n) * direction, 0, 0);
5362 unbind_to (count, Qnil);
5365 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
5366 doc: /* Scroll text of selected window upward ARG lines.
5367 If ARG is omitted or nil, scroll upward by a near full screen.
5368 A near full screen is `next-screen-context-lines' less than a full screen.
5369 Negative ARG means scroll downward.
5370 If ARG is the atom `-', scroll downward by nearly full screen.
5371 When calling from a program, supply as argument a number, nil, or `-'. */)
5372 (Lisp_Object arg)
5374 scroll_command (arg, 1);
5375 return Qnil;
5378 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
5379 doc: /* Scroll text of selected window down ARG lines.
5380 If ARG is omitted or nil, scroll down by a near full screen.
5381 A near full screen is `next-screen-context-lines' less than a full screen.
5382 Negative ARG means scroll upward.
5383 If ARG is the atom `-', scroll upward by nearly full screen.
5384 When calling from a program, supply as argument a number, nil, or `-'. */)
5385 (Lisp_Object arg)
5387 scroll_command (arg, -1);
5388 return Qnil;
5391 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
5392 doc: /* Return the other window for \"other window scroll\" commands.
5393 If `other-window-scroll-buffer' is non-nil, a window
5394 showing that buffer is used.
5395 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5396 specifies the window. This takes precedence over
5397 `other-window-scroll-buffer'. */)
5398 (void)
5400 Lisp_Object window;
5402 if (MINI_WINDOW_P (XWINDOW (selected_window))
5403 && !NILP (Vminibuf_scroll_window))
5404 window = Vminibuf_scroll_window;
5405 /* If buffer is specified, scroll that buffer. */
5406 else if (!NILP (Vother_window_scroll_buffer))
5408 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
5409 if (NILP (window))
5410 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5412 else
5414 /* Nothing specified; look for a neighboring window on the same
5415 frame. */
5416 window = Fnext_window (selected_window, Qnil, Qnil);
5418 if (EQ (window, selected_window))
5419 /* That didn't get us anywhere; look for a window on another
5420 visible frame. */
5422 window = Fnext_window (window, Qnil, Qt);
5423 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5424 && ! EQ (window, selected_window));
5427 CHECK_LIVE_WINDOW (window);
5429 if (EQ (window, selected_window))
5430 error ("There is no other window");
5432 return window;
5435 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5436 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5437 A near full screen is `next-screen-context-lines' less than a full screen.
5438 The next window is the one below the current one; or the one at the top
5439 if the current one is at the bottom. Negative ARG means scroll downward.
5440 If ARG is the atom `-', scroll downward by nearly full screen.
5441 When calling from a program, supply as argument a number, nil, or `-'.
5443 If `other-window-scroll-buffer' is non-nil, scroll the window
5444 showing that buffer, popping the buffer up if necessary.
5445 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5446 specifies the window to scroll. This takes precedence over
5447 `other-window-scroll-buffer'. */)
5448 (Lisp_Object arg)
5450 Lisp_Object window;
5451 struct window *w;
5452 ptrdiff_t count = SPECPDL_INDEX ();
5454 window = Fother_window_for_scrolling ();
5455 w = XWINDOW (window);
5457 /* Don't screw up if window_scroll gets an error. */
5458 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5460 Fset_buffer (w->contents);
5461 SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
5463 if (NILP (arg))
5464 window_scroll (window, 1, 1, 1);
5465 else if (EQ (arg, Qminus))
5466 window_scroll (window, -1, 1, 1);
5467 else
5469 if (CONSP (arg))
5470 arg = XCAR (arg);
5471 CHECK_NUMBER (arg);
5472 window_scroll (window, XINT (arg), 0, 1);
5475 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5476 unbind_to (count, Qnil);
5478 return Qnil;
5481 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5482 doc: /* Scroll selected window display ARG columns left.
5483 Default for ARG is window width minus 2.
5484 Value is the total amount of leftward horizontal scrolling in
5485 effect after the change.
5486 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5487 lower bound for automatic scrolling, i.e. automatic scrolling
5488 will not scroll a window to a column less than the value returned
5489 by this function. This happens in an interactive call. */)
5490 (register Lisp_Object arg, Lisp_Object set_minimum)
5492 struct window *w = XWINDOW (selected_window);
5493 EMACS_INT requested_arg = (NILP (arg)
5494 ? window_body_width (w, 0) - 2
5495 : XINT (Fprefix_numeric_value (arg)));
5496 Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
5498 if (!NILP (set_minimum))
5499 w->min_hscroll = w->hscroll;
5501 return result;
5504 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5505 doc: /* Scroll selected window display ARG columns right.
5506 Default for ARG is window width minus 2.
5507 Value is the total amount of leftward horizontal scrolling in
5508 effect after the change.
5509 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5510 lower bound for automatic scrolling, i.e. automatic scrolling
5511 will not scroll a window to a column less than the value returned
5512 by this function. This happens in an interactive call. */)
5513 (register Lisp_Object arg, Lisp_Object set_minimum)
5515 struct window *w = XWINDOW (selected_window);
5516 EMACS_INT requested_arg = (NILP (arg)
5517 ? window_body_width (w, 0) - 2
5518 : XINT (Fprefix_numeric_value (arg)));
5519 Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
5521 if (!NILP (set_minimum))
5522 w->min_hscroll = w->hscroll;
5524 return result;
5527 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5528 doc: /* Return the window which was selected when entering the minibuffer.
5529 Returns nil, if selected window is not a minibuffer window. */)
5530 (void)
5532 if (minibuf_level > 0
5533 && MINI_WINDOW_P (XWINDOW (selected_window))
5534 && WINDOW_LIVE_P (minibuf_selected_window))
5535 return minibuf_selected_window;
5537 return Qnil;
5540 /* Value is the number of lines actually displayed in window W,
5541 as opposed to its height. */
5543 static int
5544 displayed_window_lines (struct window *w)
5546 struct it it;
5547 struct text_pos start;
5548 int height = window_box_height (w);
5549 struct buffer *old_buffer;
5550 int bottom_y;
5551 void *itdata = NULL;
5553 if (XBUFFER (w->contents) != current_buffer)
5555 old_buffer = current_buffer;
5556 set_buffer_internal (XBUFFER (w->contents));
5558 else
5559 old_buffer = NULL;
5561 /* In case W->start is out of the accessible range, do something
5562 reasonable. This happens in Info mode when Info-scroll-down
5563 calls (recenter -1) while W->start is 1. */
5564 CLIP_TEXT_POS_FROM_MARKER (start, w->start);
5566 itdata = bidi_shelve_cache ();
5567 start_display (&it, w, start);
5568 move_it_vertically (&it, height);
5569 bottom_y = line_bottom_y (&it);
5570 bidi_unshelve_cache (itdata, 0);
5572 /* rms: On a non-window display,
5573 the value of it.vpos at the bottom of the screen
5574 seems to be 1 larger than window_box_height (w).
5575 This kludge fixes a bug whereby (move-to-window-line -1)
5576 when ZV is on the last screen line
5577 moves to the previous screen line instead of the last one. */
5578 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5579 height++;
5581 /* Add in empty lines at the bottom of the window. */
5582 if (bottom_y < height)
5584 int uy = FRAME_LINE_HEIGHT (it.f);
5585 it.vpos += (height - bottom_y + uy - 1) / uy;
5588 if (old_buffer)
5589 set_buffer_internal (old_buffer);
5591 return it.vpos;
5595 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5596 doc: /* Center point in selected window and maybe redisplay frame.
5597 With a numeric prefix argument ARG, recenter putting point on screen line ARG
5598 relative to the selected window. If ARG is negative, it counts up from the
5599 bottom of the window. (ARG should be less than the height of the window.)
5601 If ARG is omitted or nil, then recenter with point on the middle line of
5602 the selected window; if the variable `recenter-redisplay' is non-nil,
5603 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5604 is set to `grow-only', this resets the tool-bar's height to the minimum
5605 height needed); if `recenter-redisplay' has the special value `tty',
5606 then only tty frames are redrawn.
5608 Just C-u as prefix means put point in the center of the window
5609 and redisplay normally--don't erase and redraw the frame. */)
5610 (register Lisp_Object arg)
5612 struct window *w = XWINDOW (selected_window);
5613 struct buffer *buf = XBUFFER (w->contents);
5614 struct buffer *obuf = current_buffer;
5615 bool center_p = 0;
5616 ptrdiff_t charpos, bytepos;
5617 EMACS_INT iarg IF_LINT (= 0);
5618 int this_scroll_margin;
5620 /* If redisplay is suppressed due to an error, try again. */
5621 obuf->display_error_modiff = 0;
5623 if (NILP (arg))
5625 if (!NILP (Vrecenter_redisplay)
5626 && (!EQ (Vrecenter_redisplay, Qtty)
5627 || !NILP (Ftty_type (selected_frame))))
5629 ptrdiff_t i;
5631 /* Invalidate pixel data calculated for all compositions. */
5632 for (i = 0; i < n_compositions; i++)
5633 composition_table[i]->font = NULL;
5634 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
5635 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5636 #endif
5637 Fredraw_frame (WINDOW_FRAME (w));
5638 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5641 center_p = 1;
5643 else if (CONSP (arg)) /* Just C-u. */
5644 center_p = 1;
5645 else
5647 arg = Fprefix_numeric_value (arg);
5648 CHECK_NUMBER (arg);
5649 iarg = XINT (arg);
5652 set_buffer_internal (buf);
5654 /* Do this after making BUF current
5655 in case scroll_margin is buffer-local. */
5656 this_scroll_margin =
5657 max (0, min (scroll_margin, w->total_lines / 4));
5659 /* Handle centering on a graphical frame specially. Such frames can
5660 have variable-height lines and centering point on the basis of
5661 line counts would lead to strange effects. */
5662 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5664 if (center_p)
5666 struct it it;
5667 struct text_pos pt;
5668 void *itdata = bidi_shelve_cache ();
5670 SET_TEXT_POS (pt, PT, PT_BYTE);
5671 start_display (&it, w, pt);
5672 move_it_vertically_backward (&it, window_box_height (w) / 2);
5673 charpos = IT_CHARPOS (it);
5674 bytepos = IT_BYTEPOS (it);
5675 bidi_unshelve_cache (itdata, 0);
5677 else if (iarg < 0)
5679 struct it it;
5680 struct text_pos pt;
5681 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
5682 int extra_line_spacing;
5683 int h = window_box_height (w);
5684 void *itdata = bidi_shelve_cache ();
5686 iarg = - max (-iarg, this_scroll_margin);
5688 SET_TEXT_POS (pt, PT, PT_BYTE);
5689 start_display (&it, w, pt);
5691 /* Be sure we have the exact height of the full line containing PT. */
5692 move_it_by_lines (&it, 0);
5694 /* The amount of pixels we have to move back is the window
5695 height minus what's displayed in the line containing PT,
5696 and the lines below. */
5697 it.current_y = 0;
5698 it.vpos = 0;
5699 move_it_by_lines (&it, nlines);
5701 if (it.vpos == nlines)
5702 h -= it.current_y;
5703 else
5705 /* Last line has no newline */
5706 h -= line_bottom_y (&it);
5707 it.vpos++;
5710 /* Don't reserve space for extra line spacing of last line. */
5711 extra_line_spacing = it.max_extra_line_spacing;
5713 /* If we can't move down NLINES lines because we hit
5714 the end of the buffer, count in some empty lines. */
5715 if (it.vpos < nlines)
5717 nlines -= it.vpos;
5718 extra_line_spacing = it.extra_line_spacing;
5719 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5721 if (h <= 0)
5723 bidi_unshelve_cache (itdata, 0);
5724 return Qnil;
5727 /* Now find the new top line (starting position) of the window. */
5728 start_display (&it, w, pt);
5729 it.current_y = 0;
5730 move_it_vertically_backward (&it, h);
5732 /* If extra line spacing is present, we may move too far
5733 back. This causes the last line to be only partially
5734 visible (which triggers redisplay to recenter that line
5735 in the middle), so move forward.
5736 But ignore extra line spacing on last line, as it is not
5737 considered to be part of the visible height of the line.
5739 h += extra_line_spacing;
5740 while (-it.current_y > h)
5741 move_it_by_lines (&it, 1);
5743 charpos = IT_CHARPOS (it);
5744 bytepos = IT_BYTEPOS (it);
5746 bidi_unshelve_cache (itdata, 0);
5748 else
5750 struct position pos;
5752 iarg = max (iarg, this_scroll_margin);
5754 pos = *vmotion (PT, PT_BYTE, -iarg, w);
5755 charpos = pos.bufpos;
5756 bytepos = pos.bytepos;
5759 else
5761 struct position pos;
5762 int ht = window_internal_height (w);
5764 if (center_p)
5765 iarg = ht / 2;
5766 else if (iarg < 0)
5767 iarg += ht;
5769 /* Don't let it get into the margin at either top or bottom. */
5770 iarg = clip_to_bounds (this_scroll_margin, iarg,
5771 ht - this_scroll_margin - 1);
5773 pos = *vmotion (PT, PT_BYTE, - iarg, w);
5774 charpos = pos.bufpos;
5775 bytepos = pos.bytepos;
5778 /* Set the new window start. */
5779 set_marker_both (w->start, w->contents, charpos, bytepos);
5780 w->window_end_valid = 0;
5782 w->optional_new_start = 1;
5784 w->start_at_line_beg = (bytepos == BEGV_BYTE ||
5785 FETCH_BYTE (bytepos - 1) == '\n');
5787 set_buffer_internal (obuf);
5788 return Qnil;
5791 DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
5792 0, 1, 0,
5793 doc: /* Return the width in columns of the text display area of WINDOW.
5794 WINDOW must be a live window and defaults to the selected one.
5796 The returned width does not include dividers, scrollbars, margins,
5797 fringes, nor any partial-width columns at the right of the text
5798 area. */)
5799 (Lisp_Object window)
5801 struct window *w = decode_live_window (window);
5803 return make_number (window_box_width (w, TEXT_AREA)
5804 / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
5807 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5808 0, 1, 0,
5809 doc: /* Return the height in lines of the text display area of WINDOW.
5810 WINDOW must be a live window and defaults to the selected one.
5812 The returned height does not include dividers, the mode line, any header
5813 line, nor any partial-height lines at the bottom of the text area. */)
5814 (Lisp_Object window)
5816 struct window *w = decode_live_window (window);
5818 return make_number (window_box_height (w)
5819 / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
5822 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5823 1, 1, "P",
5824 doc: /* Position point relative to window.
5825 ARG nil means position point at center of window.
5826 Else, ARG specifies vertical position within the window;
5827 zero means top of window, negative means relative to bottom of window. */)
5828 (Lisp_Object arg)
5830 struct window *w = XWINDOW (selected_window);
5831 int lines, start;
5832 Lisp_Object window;
5833 #if 0
5834 int this_scroll_margin;
5835 #endif
5837 if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer))
5838 /* This test is needed to make sure PT/PT_BYTE make sense in w->contents
5839 when passed below to set_marker_both. */
5840 error ("move-to-window-line called from unrelated buffer");
5842 window = selected_window;
5843 start = marker_position (w->start);
5844 if (start < BEGV || start > ZV)
5846 int height = window_internal_height (w);
5847 Fvertical_motion (make_number (- (height / 2)), window);
5848 set_marker_both (w->start, w->contents, PT, PT_BYTE);
5849 w->start_at_line_beg = !NILP (Fbolp ());
5850 w->force_start = 1;
5852 else
5853 Fgoto_char (w->start);
5855 lines = displayed_window_lines (w);
5857 #if 0
5858 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
5859 #endif
5861 if (NILP (arg))
5862 XSETFASTINT (arg, lines / 2);
5863 else
5865 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
5867 if (iarg < 0)
5868 iarg = iarg + lines;
5870 #if 0 /* This code would prevent move-to-window-line from moving point
5871 to a place inside the scroll margins (which would cause the
5872 next redisplay to scroll). I wrote this code, but then concluded
5873 it is probably better not to install it. However, it is here
5874 inside #if 0 so as not to lose it. -- rms. */
5876 /* Don't let it get into the margin at either top or bottom. */
5877 iarg = max (iarg, this_scroll_margin);
5878 iarg = min (iarg, lines - this_scroll_margin - 1);
5879 #endif
5881 arg = make_number (iarg);
5884 /* Skip past a partially visible first line. */
5885 if (w->vscroll)
5886 XSETINT (arg, XINT (arg) + 1);
5888 return Fvertical_motion (arg, window);
5893 /***********************************************************************
5894 Window Configuration
5895 ***********************************************************************/
5897 struct save_window_data
5899 struct vectorlike_header header;
5900 Lisp_Object selected_frame;
5901 Lisp_Object current_window;
5902 Lisp_Object current_buffer;
5903 Lisp_Object minibuf_scroll_window;
5904 Lisp_Object minibuf_selected_window;
5905 Lisp_Object root_window;
5906 Lisp_Object focus_frame;
5907 /* A vector, each of whose elements is a struct saved_window
5908 for one window. */
5909 Lisp_Object saved_windows;
5911 /* All fields above are traced by the GC.
5912 From `frame-cols' down, the fields are ignored by the GC. */
5913 /* We should be able to do without the following two. */
5914 int frame_cols, frame_lines;
5915 /* These two should get eventually replaced by their pixel
5916 counterparts. */
5917 int frame_menu_bar_lines, frame_tool_bar_lines;
5918 int frame_text_width, frame_text_height;
5919 /* These are currently unused. We need them as soon as we convert
5920 to pixels. */
5921 int frame_menu_bar_height, frame_tool_bar_height;
5924 /* This is saved as a Lisp_Vector */
5925 struct saved_window
5927 struct vectorlike_header header;
5929 Lisp_Object window, buffer, start, pointm, mark;
5930 Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
5931 Lisp_Object left_col, top_line, total_cols, total_lines;
5932 Lisp_Object normal_cols, normal_lines;
5933 Lisp_Object hscroll, min_hscroll;
5934 Lisp_Object parent, prev;
5935 Lisp_Object start_at_line_beg;
5936 Lisp_Object display_table;
5937 Lisp_Object left_margin_cols, right_margin_cols;
5938 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5939 Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
5940 Lisp_Object combination_limit, window_parameters;
5943 #define SAVED_WINDOW_N(swv,n) \
5944 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5946 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5947 doc: /* Return t if OBJECT is a window-configuration object. */)
5948 (Lisp_Object object)
5950 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5953 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5954 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5955 (Lisp_Object config)
5957 register struct save_window_data *data;
5958 struct Lisp_Vector *saved_windows;
5960 CHECK_WINDOW_CONFIGURATION (config);
5962 data = (struct save_window_data *) XVECTOR (config);
5963 saved_windows = XVECTOR (data->saved_windows);
5964 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5967 /* From Chong's unwind_create_frame_1. */
5968 static void
5969 unwind_change_frame (Lisp_Object val)
5971 inhibit_lisp_code = val;
5974 DEFUN ("set-window-configuration", Fset_window_configuration,
5975 Sset_window_configuration, 1, 1, 0,
5976 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5977 CONFIGURATION must be a value previously returned
5978 by `current-window-configuration' (which see).
5979 If CONFIGURATION was made from a frame that is now deleted,
5980 only frame-independent values can be restored. In this case,
5981 the return value is nil. Otherwise the value is t. */)
5982 (Lisp_Object configuration)
5984 register struct save_window_data *data;
5985 struct Lisp_Vector *saved_windows;
5986 Lisp_Object new_current_buffer;
5987 Lisp_Object frame;
5988 struct frame *f;
5989 ptrdiff_t old_point = -1;
5991 CHECK_WINDOW_CONFIGURATION (configuration);
5993 data = (struct save_window_data *) XVECTOR (configuration);
5994 saved_windows = XVECTOR (data->saved_windows);
5996 new_current_buffer = data->current_buffer;
5997 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5998 new_current_buffer = Qnil;
5999 else
6001 if (XBUFFER (new_current_buffer) == current_buffer)
6002 /* The code further down "preserves point" by saving here PT in
6003 old_point and then setting it later back into PT. When the
6004 current-selected-window and the final-selected-window both show
6005 the current buffer, this suffers from the problem that the
6006 current PT is the window-point of the current-selected-window,
6007 while the final PT is the point of the final-selected-window, so
6008 this copy from one PT to the other would end up moving the
6009 window-point of the final-selected-window to the window-point of
6010 the current-selected-window. So we have to be careful which
6011 point of the current-buffer we copy into old_point. */
6012 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
6013 && WINDOWP (selected_window)
6014 && EQ (XWINDOW (selected_window)->contents, new_current_buffer)
6015 && !EQ (selected_window, data->current_window))
6016 old_point = marker_position (XWINDOW (data->current_window)->pointm);
6017 else
6018 old_point = PT;
6019 else
6020 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
6021 point in new_current_buffer as of the last time this buffer was
6022 used. This can be non-deterministic since it can be changed by
6023 things like jit-lock by mere temporary selection of some random
6024 window that happens to show this buffer.
6025 So if possible we want this arbitrary choice of "which point" to
6026 be the one from the to-be-selected-window so as to prevent this
6027 window's cursor from being copied from another window. */
6028 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
6029 /* If current_window = selected_window, its point is in BUF_PT. */
6030 && !EQ (selected_window, data->current_window))
6031 old_point = marker_position (XWINDOW (data->current_window)->pointm);
6032 else
6033 old_point = BUF_PT (XBUFFER (new_current_buffer));
6036 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
6037 f = XFRAME (frame);
6039 /* If f is a dead frame, don't bother rebuilding its window tree.
6040 However, there is other stuff we should still try to do below. */
6041 if (FRAME_LIVE_P (f))
6043 Lisp_Object window;
6044 Lisp_Object dead_windows = Qnil;
6045 register Lisp_Object tem, par, pers;
6046 register struct window *w;
6047 register struct saved_window *p;
6048 struct window *root_window;
6049 struct window **leaf_windows;
6050 int n_leaf_windows;
6051 ptrdiff_t k;
6052 int i, n;
6053 ptrdiff_t count = SPECPDL_INDEX ();
6054 /* If the frame has been resized since this window configuration was
6055 made, we change the frame to the size specified in the
6056 configuration, restore the configuration, and then resize it
6057 back. We keep track of the prevailing height in these variables. */
6058 int previous_frame_text_height = FRAME_TEXT_HEIGHT (f);
6059 int previous_frame_text_width = FRAME_TEXT_WIDTH (f);
6060 /* int previous_frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f); */
6061 /* int previous_frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f); */
6062 /* int previous_frame_lines = FRAME_LINES (f); */
6063 /* int previous_frame_cols = FRAME_COLS (f); */
6064 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6065 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6067 /* Don't do this within the main loop below: This may call Lisp
6068 code and is thus potentially unsafe while input is blocked. */
6069 for (k = 0; k < saved_windows->header.size; k++)
6071 p = SAVED_WINDOW_N (saved_windows, k);
6072 window = p->window;
6073 w = XWINDOW (window);
6074 if (BUFFERP (w->contents)
6075 && !EQ (w->contents, p->buffer)
6076 && BUFFER_LIVE_P (XBUFFER (p->buffer)))
6077 /* If a window we restore gets another buffer, record the
6078 window's old buffer. */
6079 call1 (Qrecord_window_buffer, window);
6082 /* Don't run lisp in the following segment since the frame is in a
6083 completely inconsistent state. See Bug#16207. */
6084 record_unwind_protect (unwind_change_frame, inhibit_lisp_code);
6085 inhibit_lisp_code = Qt;
6086 /* The mouse highlighting code could get screwed up
6087 if it runs during this. */
6088 block_input ();
6090 if (data->frame_text_width != previous_frame_text_width
6091 || data->frame_text_height != previous_frame_text_height)
6092 change_frame_size (f, data->frame_text_width,
6093 data->frame_text_height, 0, 0, 0, 1);
6095 if (data->frame_menu_bar_lines != previous_frame_menu_bar_lines)
6097 #ifdef HAVE_WINDOW_SYSTEM
6098 if (FRAME_WINDOW_P (f))
6099 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
6100 make_number (0));
6101 else /* TTY or MSDOS */
6102 #endif
6103 set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
6104 make_number (0));
6106 #ifdef HAVE_WINDOW_SYSTEM
6107 if (data->frame_tool_bar_lines != previous_frame_tool_bar_lines)
6108 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
6109 make_number (0));
6110 #endif
6112 /* "Swap out" point from the selected window's buffer
6113 into the window itself. (Normally the pointm of the selected
6114 window holds garbage.) We do this now, before
6115 restoring the window contents, and prevent it from
6116 being done later on when we select a new window. */
6117 if (! NILP (XWINDOW (selected_window)->contents))
6119 w = XWINDOW (selected_window);
6120 set_marker_both (w->pointm,
6121 w->contents,
6122 BUF_PT (XBUFFER (w->contents)),
6123 BUF_PT_BYTE (XBUFFER (w->contents)));
6126 fset_redisplay (f);
6127 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
6129 /* Problem: Freeing all matrices and later allocating them again
6130 is a serious redisplay flickering problem. What we would
6131 really like to do is to free only those matrices not reused
6132 below. */
6133 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
6134 leaf_windows = alloca (count_windows (root_window)
6135 * sizeof *leaf_windows);
6136 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
6138 /* Kludge Alert!
6139 Mark all windows now on frame as "deleted".
6140 Restoring the new configuration "undeletes" any that are in it.
6142 Save their current buffers in their height fields, since we may
6143 need it later, if a buffer saved in the configuration is now
6144 dead. */
6145 delete_all_child_windows (FRAME_ROOT_WINDOW (f));
6147 for (k = 0; k < saved_windows->header.size; k++)
6149 p = SAVED_WINDOW_N (saved_windows, k);
6150 window = p->window;
6151 w = XWINDOW (window);
6152 wset_next (w, Qnil);
6154 if (!NILP (p->parent))
6155 wset_parent
6156 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window);
6157 else
6158 wset_parent (w, Qnil);
6160 if (!NILP (p->prev))
6162 wset_prev
6163 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window);
6164 wset_next (XWINDOW (w->prev), p->window);
6166 else
6168 wset_prev (w, Qnil);
6169 if (!NILP (w->parent))
6170 wset_combination (XWINDOW (w->parent),
6171 (XINT (p->total_cols)
6172 != XWINDOW (w->parent)->total_cols),
6173 p->window);
6176 /* If we squirreled away the buffer, restore it now. */
6177 if (BUFFERP (w->combination_limit))
6178 wset_buffer (w, w->combination_limit);
6179 w->pixel_left = XFASTINT (p->pixel_left);
6180 w->pixel_top = XFASTINT (p->pixel_top);
6181 w->pixel_width = XFASTINT (p->pixel_width);
6182 w->pixel_height = XFASTINT (p->pixel_height);
6183 w->left_col = XFASTINT (p->left_col);
6184 w->top_line = XFASTINT (p->top_line);
6185 w->total_cols = XFASTINT (p->total_cols);
6186 w->total_lines = XFASTINT (p->total_lines);
6187 wset_normal_cols (w, p->normal_cols);
6188 wset_normal_lines (w, p->normal_lines);
6189 w->hscroll = XFASTINT (p->hscroll);
6190 w->min_hscroll = XFASTINT (p->min_hscroll);
6191 wset_display_table (w, p->display_table);
6192 w->left_margin_cols = XINT (p->left_margin_cols);
6193 w->right_margin_cols = XINT (p->right_margin_cols);
6194 w->left_fringe_width = XINT (p->left_fringe_width);
6195 w->right_fringe_width = XINT (p->right_fringe_width);
6196 w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
6197 w->scroll_bar_width = XINT (p->scroll_bar_width);
6198 wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
6199 wset_dedicated (w, p->dedicated);
6200 wset_combination_limit (w, p->combination_limit);
6201 /* Restore any window parameters that have been saved.
6202 Parameters that have not been saved are left alone. */
6203 for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
6205 pers = XCAR (tem);
6206 if (CONSP (pers))
6208 if (NILP (XCDR (pers)))
6210 par = Fassq (XCAR (pers), w->window_parameters);
6211 if (CONSP (par) && !NILP (XCDR (par)))
6212 /* Reset a parameter to nil if and only if it
6213 has a non-nil association. Don't make new
6214 associations. */
6215 Fsetcdr (par, Qnil);
6217 else
6218 /* Always restore a non-nil value. */
6219 Fset_window_parameter (window, XCAR (pers), XCDR (pers));
6223 if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
6224 /* If saved buffer is alive, install it. */
6226 wset_buffer (w, p->buffer);
6227 w->start_at_line_beg = !NILP (p->start_at_line_beg);
6228 set_marker_restricted (w->start, p->start, w->contents);
6229 set_marker_restricted (w->pointm, p->pointm,
6230 w->contents);
6231 Fset_marker (BVAR (XBUFFER (w->contents), mark),
6232 p->mark, w->contents);
6234 /* As documented in Fcurrent_window_configuration, don't
6235 restore the location of point in the buffer which was
6236 current when the window configuration was recorded. */
6237 if (!EQ (p->buffer, new_current_buffer)
6238 && XBUFFER (p->buffer) == current_buffer)
6239 Fgoto_char (w->pointm);
6241 else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
6242 /* Keep window's old buffer; make sure the markers are real. */
6244 /* Set window markers at start of visible range. */
6245 if (XMARKER (w->start)->buffer == 0)
6246 set_marker_restricted_both (w->start, w->contents, 0, 0);
6247 if (XMARKER (w->pointm)->buffer == 0)
6248 set_marker_restricted_both
6249 (w->pointm, w->contents,
6250 BUF_PT (XBUFFER (w->contents)),
6251 BUF_PT_BYTE (XBUFFER (w->contents)));
6252 w->start_at_line_beg = 1;
6254 else if (!NILP (w->start))
6255 /* Leaf window has no live buffer, get one. */
6257 /* Get the buffer via other_buffer_safely in order to
6258 avoid showing an unimportant buffer and, if necessary, to
6259 recreate *scratch* in the course (part of Juanma's bs-show
6260 scenario from March 2011). */
6261 wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
6262 /* This will set the markers to beginning of visible
6263 range. */
6264 set_marker_restricted_both (w->start, w->contents, 0, 0);
6265 set_marker_restricted_both (w->pointm, w->contents, 0, 0);
6266 w->start_at_line_beg = 1;
6267 if (!NILP (w->dedicated))
6268 /* Record this window as dead. */
6269 dead_windows = Fcons (window, dead_windows);
6270 /* Make sure window is no more dedicated. */
6271 wset_dedicated (w, Qnil);
6275 fset_root_window (f, data->root_window);
6276 /* Arrange *not* to restore point in the buffer that was
6277 current when the window configuration was saved. */
6278 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
6279 set_marker_restricted (XWINDOW (data->current_window)->pointm,
6280 make_number (old_point),
6281 XWINDOW (data->current_window)->contents);
6283 /* In the following call to `select-window', prevent "swapping out
6284 point" in the old selected window using the buffer that has
6285 been restored into it. We already swapped out that point from
6286 that window's old buffer.
6288 Do not record the buffer here. We do that in a separate call
6289 to select_window below. See also Bug#16207. */
6290 select_window (data->current_window, Qt, 1);
6291 BVAR (XBUFFER (XWINDOW (selected_window)->contents),
6292 last_selected_window)
6293 = selected_window;
6295 if (NILP (data->focus_frame)
6296 || (FRAMEP (data->focus_frame)
6297 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
6298 Fredirect_frame_focus (frame, data->focus_frame);
6300 /* Set the frame size to the value it had before this function. */
6301 if (previous_frame_text_width != FRAME_TEXT_WIDTH (f)
6302 || previous_frame_text_height != FRAME_TEXT_HEIGHT (f))
6303 change_frame_size (f, previous_frame_text_width,
6304 previous_frame_text_height, 0, 0, 0, 1);
6306 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
6308 #ifdef HAVE_WINDOW_SYSTEM
6309 if (FRAME_WINDOW_P (f))
6310 x_set_menu_bar_lines (f,
6311 make_number (previous_frame_menu_bar_lines),
6312 make_number (0));
6313 else /* TTY or MSDOS */
6314 #endif
6315 set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
6316 make_number (0));
6318 #ifdef HAVE_WINDOW_SYSTEM
6319 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
6320 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
6321 make_number (0));
6322 #endif
6324 /* Now, free glyph matrices in windows that were not reused. */
6325 for (i = n = 0; i < n_leaf_windows; ++i)
6327 if (NILP (leaf_windows[i]->contents))
6328 free_window_matrices (leaf_windows[i]);
6329 else if (EQ (leaf_windows[i]->contents, new_current_buffer))
6330 ++n;
6333 adjust_frame_glyphs (f);
6334 unblock_input ();
6335 unbind_to (count, Qnil);
6337 /* Scan dead buffer windows. */
6338 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
6340 window = XCAR (dead_windows);
6341 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
6342 delete_deletable_window (window);
6345 /* Record the selected window's buffer here. The window should
6346 already be the selected one from the call above. */
6347 select_window (data->current_window, Qnil, 0);
6349 /* Fselect_window will have made f the selected frame, so we
6350 reselect the proper frame here. Fhandle_switch_frame will change the
6351 selected window too, but that doesn't make the call to
6352 Fselect_window above totally superfluous; it still sets f's
6353 selected window. */
6354 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6355 do_switch_frame (data->selected_frame, 0, 0, Qnil);
6357 run_window_configuration_change_hook (f);
6360 if (!NILP (new_current_buffer))
6362 Fset_buffer (new_current_buffer);
6363 /* If the new current buffer doesn't appear in the selected
6364 window, go to its old point (see bug#12208). */
6365 if (!EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
6366 Fgoto_char (make_number (old_point));
6369 Vminibuf_scroll_window = data->minibuf_scroll_window;
6370 minibuf_selected_window = data->minibuf_selected_window;
6372 return (FRAME_LIVE_P (f) ? Qt : Qnil);
6375 void
6376 restore_window_configuration (Lisp_Object configuration)
6378 Fset_window_configuration (configuration);
6382 /* If WINDOW is an internal window, recursively delete all child windows
6383 reachable via the next and contents slots of WINDOW. Otherwise setup
6384 WINDOW to not show any buffer. */
6386 void
6387 delete_all_child_windows (Lisp_Object window)
6389 register struct window *w;
6391 w = XWINDOW (window);
6393 if (!NILP (w->next))
6394 /* Delete WINDOW's siblings (we traverse postorderly). */
6395 delete_all_child_windows (w->next);
6397 if (WINDOWP (w->contents))
6399 delete_all_child_windows (w->contents);
6400 wset_combination (w, 0, Qnil);
6402 else if (BUFFERP (w->contents))
6404 unshow_buffer (w);
6405 unchain_marker (XMARKER (w->pointm));
6406 unchain_marker (XMARKER (w->start));
6407 /* Since combination limit makes sense for an internal windows
6408 only, we use this slot to save the buffer for the sake of
6409 possible resurrection in Fset_window_configuration. */
6410 wset_combination_limit (w, w->contents);
6411 wset_buffer (w, Qnil);
6414 Vwindow_list = Qnil;
6417 static int
6418 count_windows (register struct window *window)
6420 register int count = 1;
6421 if (!NILP (window->next))
6422 count += count_windows (XWINDOW (window->next));
6423 if (WINDOWP (window->contents))
6424 count += count_windows (XWINDOW (window->contents));
6425 return count;
6429 /* Fill vector FLAT with leaf windows under W, starting at index I.
6430 Value is last index + 1. */
6431 static int
6432 get_leaf_windows (struct window *w, struct window **flat, int i)
6434 while (w)
6436 if (WINDOWP (w->contents))
6437 i = get_leaf_windows (XWINDOW (w->contents), flat, i);
6438 else
6439 flat[i++] = w;
6441 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6444 return i;
6448 /* Return a pointer to the glyph W's physical cursor is on. Value is
6449 null if W's current matrix is invalid, so that no meaningful glyph
6450 can be returned. */
6451 struct glyph *
6452 get_phys_cursor_glyph (struct window *w)
6454 struct glyph_row *row;
6455 struct glyph *glyph;
6456 int hpos = w->phys_cursor.hpos;
6458 if (!(w->phys_cursor.vpos >= 0
6459 && w->phys_cursor.vpos < w->current_matrix->nrows))
6460 return NULL;
6462 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
6463 if (!row->enabled_p)
6464 return NULL;
6466 if (w->hscroll)
6468 /* When the window is hscrolled, cursor hpos can legitimately be
6469 out of bounds, but we draw the cursor at the corresponding
6470 window margin in that case. */
6471 if (!row->reversed_p && hpos < 0)
6472 hpos = 0;
6473 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
6474 hpos = row->used[TEXT_AREA] - 1;
6477 if (0 <= hpos && hpos < row->used[TEXT_AREA])
6478 glyph = row->glyphs[TEXT_AREA] + hpos;
6479 else
6480 glyph = NULL;
6482 return glyph;
6486 static int
6487 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
6489 register struct saved_window *p;
6490 register struct window *w;
6491 register Lisp_Object tem, pers, par;
6493 for (; !NILP (window); window = w->next)
6495 p = SAVED_WINDOW_N (vector, i);
6496 w = XWINDOW (window);
6498 wset_temslot (w, make_number (i)); i++;
6499 p->window = window;
6500 p->buffer = (WINDOW_LEAF_P (w) ? w->contents : Qnil);
6501 p->pixel_left = make_number (w->pixel_left);
6502 p->pixel_top = make_number (w->pixel_top);
6503 p->pixel_width = make_number (w->pixel_width);
6504 p->pixel_height = make_number (w->pixel_height);
6505 p->left_col = make_number (w->left_col);
6506 p->top_line = make_number (w->top_line);
6507 p->total_cols = make_number (w->total_cols);
6508 p->total_lines = make_number (w->total_lines);
6509 p->normal_cols = w->normal_cols;
6510 p->normal_lines = w->normal_lines;
6511 XSETFASTINT (p->hscroll, w->hscroll);
6512 XSETFASTINT (p->min_hscroll, w->min_hscroll);
6513 p->display_table = w->display_table;
6514 p->left_margin_cols = make_number (w->left_margin_cols);
6515 p->right_margin_cols = make_number (w->right_margin_cols);
6516 p->left_fringe_width = make_number (w->left_fringe_width);
6517 p->right_fringe_width = make_number (w->right_fringe_width);
6518 p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
6519 p->scroll_bar_width = make_number (w->scroll_bar_width);
6520 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6521 p->dedicated = w->dedicated;
6522 p->combination_limit = w->combination_limit;
6523 p->window_parameters = Qnil;
6525 if (!NILP (Vwindow_persistent_parameters))
6527 /* Run cycle detection on Vwindow_persistent_parameters. */
6528 Lisp_Object tortoise, hare;
6530 hare = tortoise = Vwindow_persistent_parameters;
6531 while (CONSP (hare))
6533 hare = XCDR (hare);
6534 if (!CONSP (hare))
6535 break;
6537 hare = XCDR (hare);
6538 tortoise = XCDR (tortoise);
6540 if (EQ (hare, tortoise))
6541 /* Reset Vwindow_persistent_parameters to Qnil. */
6543 Vwindow_persistent_parameters = Qnil;
6544 break;
6548 for (tem = Vwindow_persistent_parameters; CONSP (tem);
6549 tem = XCDR (tem))
6551 pers = XCAR (tem);
6552 /* Save values for persistent window parameters. */
6553 if (CONSP (pers) && !NILP (XCDR (pers)))
6555 par = Fassq (XCAR (pers), w->window_parameters);
6556 if (NILP (par))
6557 /* If the window has no value for the parameter,
6558 make one. */
6559 p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
6560 p->window_parameters);
6561 else
6562 /* If the window has a value for the parameter,
6563 save it. */
6564 p->window_parameters = Fcons (Fcons (XCAR (par),
6565 XCDR (par)),
6566 p->window_parameters);
6571 if (BUFFERP (w->contents))
6573 /* Save w's value of point in the window configuration. If w
6574 is the selected window, then get the value of point from
6575 the buffer; pointm is garbage in the selected window. */
6576 if (EQ (window, selected_window))
6577 p->pointm = build_marker (XBUFFER (w->contents),
6578 BUF_PT (XBUFFER (w->contents)),
6579 BUF_PT_BYTE (XBUFFER (w->contents)));
6580 else
6581 p->pointm = Fcopy_marker (w->pointm, Qnil);
6582 XMARKER (p->pointm)->insertion_type
6583 = !NILP (Vwindow_point_insertion_type);
6585 p->start = Fcopy_marker (w->start, Qnil);
6586 p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
6588 tem = BVAR (XBUFFER (w->contents), mark);
6589 p->mark = Fcopy_marker (tem, Qnil);
6591 else
6593 p->pointm = Qnil;
6594 p->start = Qnil;
6595 p->mark = Qnil;
6596 p->start_at_line_beg = Qnil;
6599 if (NILP (w->parent))
6600 p->parent = Qnil;
6601 else
6602 p->parent = XWINDOW (w->parent)->temslot;
6604 if (NILP (w->prev))
6605 p->prev = Qnil;
6606 else
6607 p->prev = XWINDOW (w->prev)->temslot;
6609 if (WINDOWP (w->contents))
6610 i = save_window_save (w->contents, vector, i);
6613 return i;
6616 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6617 Scurrent_window_configuration, 0, 1, 0,
6618 doc: /* Return an object representing the current window configuration of FRAME.
6619 If FRAME is nil or omitted, use the selected frame.
6620 This describes the number of windows, their sizes and current buffers,
6621 and for each displayed buffer, where display starts, and the positions of
6622 point and mark. An exception is made for point in the current buffer:
6623 its value is -not- saved.
6624 This also records the currently selected frame, and FRAME's focus
6625 redirection (see `redirect-frame-focus'). The variable
6626 `window-persistent-parameters' specifies which window parameters are
6627 saved by this function. */)
6628 (Lisp_Object frame)
6630 register Lisp_Object tem;
6631 register int n_windows;
6632 register struct save_window_data *data;
6633 register int i;
6634 struct frame *f = decode_live_frame (frame);
6636 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6637 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6638 PVEC_WINDOW_CONFIGURATION);
6640 data->frame_cols = FRAME_COLS (f);
6641 data->frame_lines = FRAME_LINES (f);
6642 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6643 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6644 data->frame_text_width = FRAME_TEXT_WIDTH (f);
6645 data->frame_text_height = FRAME_TEXT_HEIGHT (f);
6646 data->frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
6647 data->frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
6648 data->selected_frame = selected_frame;
6649 data->current_window = FRAME_SELECTED_WINDOW (f);
6650 XSETBUFFER (data->current_buffer, current_buffer);
6651 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6652 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6653 data->root_window = FRAME_ROOT_WINDOW (f);
6654 data->focus_frame = FRAME_FOCUS_FRAME (f);
6655 tem = make_uninit_vector (n_windows);
6656 data->saved_windows = tem;
6657 for (i = 0; i < n_windows; i++)
6658 ASET (tem, i,
6659 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil));
6660 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6661 XSETWINDOW_CONFIGURATION (tem, data);
6662 return (tem);
6665 /* Called after W's margins, fringes or scroll bars was adjusted. */
6667 static void
6668 apply_window_adjustment (struct window *w)
6670 eassert (w);
6671 adjust_window_margins (w);
6672 clear_glyph_matrix (w->current_matrix);
6673 w->window_end_valid = 0;
6674 windows_or_buffers_changed = 30;
6675 wset_redisplay (w);
6676 adjust_frame_glyphs (XFRAME (WINDOW_FRAME (w)));
6680 /***********************************************************************
6681 Marginal Areas
6682 ***********************************************************************/
6684 static struct window *
6685 set_window_margins (struct window *w, Lisp_Object left_width,
6686 Lisp_Object right_width)
6688 int left, right;
6690 /* FIXME: what about margins that are too wide? */
6691 left = (NILP (left_width) ? 0
6692 : (CHECK_NATNUM (left_width), XINT (left_width)));
6693 right = (NILP (right_width) ? 0
6694 : (CHECK_NATNUM (right_width), XINT (right_width)));
6696 if (w->left_margin_cols != left || w->right_margin_cols != right)
6698 w->left_margin_cols = left;
6699 w->right_margin_cols = right;
6700 return w;
6702 return NULL;
6705 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6706 2, 3, 0,
6707 doc: /* Set width of marginal areas of window WINDOW.
6708 WINDOW must be a live window and defaults to the selected one.
6710 Second arg LEFT-WIDTH specifies the number of character cells to
6711 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6712 does the same for the right marginal area. A nil width parameter
6713 means no margin.
6715 Return t if any margin was actually changed and nil otherwise. */)
6716 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6718 struct window *w = set_window_margins (decode_live_window (window),
6719 left_width, right_width);
6720 return w ? (apply_window_adjustment (w), Qt) : Qnil;
6724 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6725 0, 1, 0,
6726 doc: /* Get width of marginal areas of window WINDOW.
6727 WINDOW must be a live window and defaults to the selected one.
6729 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6730 If a marginal area does not exist, its width will be returned
6731 as nil. */)
6732 (Lisp_Object window)
6734 struct window *w = decode_live_window (window);
6735 return Fcons (w->left_margin_cols
6736 ? make_number (w->left_margin_cols) : Qnil,
6737 w->right_margin_cols
6738 ? make_number (w->right_margin_cols) : Qnil);
6743 /***********************************************************************
6744 Fringes
6745 ***********************************************************************/
6747 static struct window *
6748 set_window_fringes (struct window *w, Lisp_Object left_width,
6749 Lisp_Object right_width, Lisp_Object outside_margins)
6751 int left, right, outside = !NILP (outside_margins);
6753 left = (NILP (left_width) ? -1
6754 : (CHECK_NATNUM (left_width), XINT (left_width)));
6755 right = (NILP (right_width) ? -1
6756 : (CHECK_NATNUM (right_width), XINT (right_width)));
6758 /* Do nothing on a tty or if nothing to actually change. */
6759 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6760 && (w->left_fringe_width != left
6761 || w->right_fringe_width != right
6762 || w->fringes_outside_margins != outside))
6764 w->left_fringe_width = left;
6765 w->right_fringe_width = right;
6766 w->fringes_outside_margins = outside;
6767 return w;
6769 return NULL;
6772 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6773 2, 4, 0,
6774 doc: /* Set the fringe widths of window WINDOW.
6775 WINDOW must be a live window and defaults to the selected one.
6777 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6778 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6779 fringe width. If a fringe width arg is nil, that means to use the
6780 frame's default fringe width. Default fringe widths can be set with
6781 the command `set-fringe-style'.
6782 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6783 outside of the display margins. By default, fringes are drawn between
6784 display marginal areas and the text area.
6786 Return t if any fringe was actually changed and nil otherwise. */)
6787 (Lisp_Object window, Lisp_Object left_width,
6788 Lisp_Object right_width, Lisp_Object outside_margins)
6790 struct window *w
6791 = set_window_fringes (decode_live_window (window),
6792 left_width, right_width, outside_margins);
6793 return w ? (apply_window_adjustment (w), Qt) : Qnil;
6797 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6798 0, 1, 0,
6799 doc: /* Get width of fringes of window WINDOW.
6800 WINDOW must be a live window and defaults to the selected one.
6802 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6803 (Lisp_Object window)
6805 struct window *w = decode_live_window (window);
6807 return list3 (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6808 make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6809 WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil);
6814 /***********************************************************************
6815 Scroll bars
6816 ***********************************************************************/
6818 static struct window *
6819 set_window_scroll_bars (struct window *w, Lisp_Object width,
6820 Lisp_Object vertical_type, Lisp_Object horizontal_type)
6822 int iwidth = (NILP (width) ? -1 : (CHECK_NATNUM (width), XINT (width)));
6824 if (iwidth == 0)
6825 vertical_type = Qnil;
6827 if (!(NILP (vertical_type)
6828 || EQ (vertical_type, Qleft)
6829 || EQ (vertical_type, Qright)
6830 || EQ (vertical_type, Qt)))
6831 error ("Invalid type of vertical scroll bar");
6833 if (w->scroll_bar_width != iwidth
6834 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6836 w->scroll_bar_width = iwidth;
6837 wset_vertical_scroll_bar_type (w, vertical_type);
6838 return w;
6840 return NULL;
6843 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
6844 Sset_window_scroll_bars, 2, 4, 0,
6845 doc: /* Set width and type of scroll bars of window WINDOW.
6846 WINDOW must be a live window and defaults to the selected one.
6848 Second parameter WIDTH specifies the pixel width for the scroll bar.
6849 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6850 bar: left, right, or nil.
6851 If WIDTH is nil, use the frame's scroll-bar width.
6852 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6853 Fourth parameter HORIZONTAL-TYPE is currently unused.
6855 Return t if scroll bars were actually changed and nil otherwise. */)
6856 (Lisp_Object window, Lisp_Object width,
6857 Lisp_Object vertical_type, Lisp_Object horizontal_type)
6859 struct window *w
6860 = set_window_scroll_bars (decode_live_window (window),
6861 width, vertical_type, horizontal_type);
6862 return w ? (apply_window_adjustment (w), Qt) : Qnil;
6866 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6867 0, 1, 0,
6868 doc: /* Get width and type of scroll bars of window WINDOW.
6869 WINDOW must be a live window and defaults to the selected one.
6871 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6872 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6873 value. */)
6874 (Lisp_Object window)
6876 struct window *w = decode_live_window (window);
6878 return list4 (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (w)),
6879 make_number (WINDOW_SCROLL_BAR_COLS (w)),
6880 w->vertical_scroll_bar_type, Qnil);
6885 /***********************************************************************
6886 Smooth scrolling
6887 ***********************************************************************/
6889 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6890 doc: /* Return the amount by which WINDOW is scrolled vertically.
6891 If WINDOW is omitted or nil, it defaults to the selected window.
6892 Normally, value is a multiple of the canonical character height of WINDOW;
6893 optional second arg PIXELS-P means value is measured in pixels. */)
6894 (Lisp_Object window, Lisp_Object pixels_p)
6896 Lisp_Object result;
6897 struct window *w = decode_live_window (window);
6898 struct frame *f = XFRAME (w->frame);
6900 if (FRAME_WINDOW_P (f))
6901 result = (NILP (pixels_p)
6902 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6903 : make_number (-w->vscroll));
6904 else
6905 result = make_number (0);
6906 return result;
6910 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6911 2, 3, 0,
6912 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6913 WINDOW nil means use the selected window. Normally, VSCROLL is a
6914 non-negative multiple of the canonical character height of WINDOW;
6915 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6916 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6917 corresponds to an integral number of pixels. The return value is the
6918 result of this rounding.
6919 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6920 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
6922 struct window *w = decode_live_window (window);
6923 struct frame *f = XFRAME (w->frame);
6925 CHECK_NUMBER_OR_FLOAT (vscroll);
6927 if (FRAME_WINDOW_P (f))
6929 int old_dy = w->vscroll;
6931 w->vscroll = - (NILP (pixels_p)
6932 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6933 : XFLOATINT (vscroll));
6934 w->vscroll = min (w->vscroll, 0);
6936 if (w->vscroll != old_dy)
6938 /* Adjust glyph matrix of the frame if the virtual display
6939 area becomes larger than before. */
6940 if (w->vscroll < 0 && w->vscroll < old_dy)
6941 adjust_frame_glyphs (f);
6943 /* Prevent redisplay shortcuts. */
6944 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
6948 return Fwindow_vscroll (window, pixels_p);
6952 /* Call FN for all leaf windows on frame F. FN is called with the
6953 first argument being a pointer to the leaf window, and with
6954 additional argument USER_DATA. Stops when FN returns 0. */
6956 static void
6957 foreach_window (struct frame *f, int (*fn) (struct window *, void *),
6958 void *user_data)
6960 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6961 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6962 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6966 /* Helper function for foreach_window. Call FN for all leaf windows
6967 reachable from W. FN is called with the first argument being a
6968 pointer to the leaf window, and with additional argument USER_DATA.
6969 Stop when FN returns 0. Value is 0 if stopped by FN. */
6971 static int
6972 foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
6974 int cont;
6976 for (cont = 1; w && cont;)
6978 if (WINDOWP (w->contents))
6979 cont = foreach_window_1 (XWINDOW (w->contents), fn, user_data);
6980 else
6981 cont = fn (w, user_data);
6983 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6986 return cont;
6989 /***********************************************************************
6990 Initialization
6991 ***********************************************************************/
6993 /* Return 1 if window configurations CONFIGURATION1 and CONFIGURATION2
6994 describe the same state of affairs. This is used by Fequal.
6996 IGNORE_POSITIONS means ignore non-matching scroll positions
6997 and the like.
6999 This ignores a couple of things like the dedication status of
7000 window, combination_limit and the like. This might have to be
7001 fixed. */
7003 bool
7004 compare_window_configurations (Lisp_Object configuration1,
7005 Lisp_Object configuration2,
7006 bool ignore_positions)
7008 register struct save_window_data *d1, *d2;
7009 struct Lisp_Vector *sws1, *sws2;
7010 ptrdiff_t i;
7012 CHECK_WINDOW_CONFIGURATION (configuration1);
7013 CHECK_WINDOW_CONFIGURATION (configuration2);
7015 d1 = (struct save_window_data *) XVECTOR (configuration1);
7016 d2 = (struct save_window_data *) XVECTOR (configuration2);
7017 sws1 = XVECTOR (d1->saved_windows);
7018 sws2 = XVECTOR (d2->saved_windows);
7020 /* Frame settings must match. */
7021 if (d1->frame_cols != d2->frame_cols
7022 || d1->frame_lines != d2->frame_lines
7023 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
7024 || !EQ (d1->selected_frame, d2->selected_frame)
7025 || !EQ (d1->current_buffer, d2->current_buffer)
7026 || (!ignore_positions
7027 && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
7028 || !EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)))
7029 || !EQ (d1->focus_frame, d2->focus_frame)
7030 /* Verify that the two configurations have the same number of windows. */
7031 || sws1->header.size != sws2->header.size)
7032 return 0;
7034 for (i = 0; i < sws1->header.size; i++)
7036 struct saved_window *sw1, *sw2;
7038 sw1 = SAVED_WINDOW_N (sws1, i);
7039 sw2 = SAVED_WINDOW_N (sws2, i);
7041 if (
7042 /* The "current" windows in the two configurations must
7043 correspond to each other. */
7044 EQ (d1->current_window, sw1->window)
7045 != EQ (d2->current_window, sw2->window)
7046 /* Windows' buffers must match. */
7047 || !EQ (sw1->buffer, sw2->buffer)
7048 || !EQ (sw1->pixel_left, sw2->pixel_left)
7049 || !EQ (sw1->pixel_top, sw2->pixel_top)
7050 || !EQ (sw1->pixel_height, sw2->pixel_height)
7051 || !EQ (sw1->pixel_width, sw2->pixel_width)
7052 || !EQ (sw1->left_col, sw2->left_col)
7053 || !EQ (sw1->top_line, sw2->top_line)
7054 || !EQ (sw1->total_cols, sw2->total_cols)
7055 || !EQ (sw1->total_lines, sw2->total_lines)
7056 || !EQ (sw1->display_table, sw2->display_table)
7057 /* The next two disjuncts check the window structure for
7058 equality. */
7059 || !EQ (sw1->parent, sw2->parent)
7060 || !EQ (sw1->prev, sw2->prev)
7061 || (!ignore_positions
7062 && (!EQ (sw1->hscroll, sw2->hscroll)
7063 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
7064 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
7065 || NILP (Fequal (sw1->start, sw2->start))
7066 || NILP (Fequal (sw1->pointm, sw2->pointm))
7067 || NILP (Fequal (sw1->mark, sw2->mark))))
7068 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
7069 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
7070 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
7071 || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
7072 || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
7073 || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
7074 || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type))
7075 return 0;
7078 return 1;
7081 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
7082 Scompare_window_configurations, 2, 2, 0,
7083 doc: /* Compare two window configurations as regards the structure of windows.
7084 This function ignores details such as the values of point and mark
7085 and scrolling positions. */)
7086 (Lisp_Object x, Lisp_Object y)
7088 if (compare_window_configurations (x, y, 1))
7089 return Qt;
7090 return Qnil;
7093 void
7094 init_window_once (void)
7096 struct frame *f = make_initial_frame ();
7097 XSETFRAME (selected_frame, f);
7098 Vterminal_frame = selected_frame;
7099 minibuf_window = f->minibuffer_window;
7100 selected_window = f->selected_window;
7102 window_initialized = 1;
7105 void
7106 init_window (void)
7108 Vwindow_list = Qnil;
7111 void
7112 syms_of_window (void)
7114 DEFSYM (Qscroll_up, "scroll-up");
7115 DEFSYM (Qscroll_down, "scroll-down");
7116 DEFSYM (Qscroll_command, "scroll-command");
7118 Fput (Qscroll_up, Qscroll_command, Qt);
7119 Fput (Qscroll_down, Qscroll_command, Qt);
7121 DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
7122 DEFSYM (Qwindowp, "windowp");
7123 DEFSYM (Qwindow_configuration_p, "window-configuration-p");
7124 DEFSYM (Qwindow_live_p, "window-live-p");
7125 DEFSYM (Qwindow_valid_p, "window-valid-p");
7126 DEFSYM (Qwindow_deletable_p, "window-deletable-p");
7127 DEFSYM (Qdelete_window, "delete-window");
7128 DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
7129 DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
7130 DEFSYM (Qwindow_pixel_to_total, "window--pixel-to-total");
7131 DEFSYM (Qsafe, "safe");
7132 DEFSYM (Qdisplay_buffer, "display-buffer");
7133 DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
7134 DEFSYM (Qrecord_window_buffer, "record-window-buffer");
7135 DEFSYM (Qget_mru_window, "get-mru-window");
7136 DEFSYM (Qwindow_size, "window-size");
7137 DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
7138 DEFSYM (Qabove, "above");
7139 DEFSYM (Qbelow, "below");
7140 DEFSYM (Qclone_of, "clone-of");
7141 DEFSYM (Qfloor, "floor");
7142 DEFSYM (Qceiling, "ceiling");
7144 staticpro (&Vwindow_list);
7146 minibuf_selected_window = Qnil;
7147 staticpro (&minibuf_selected_window);
7149 window_scroll_pixel_based_preserve_x = -1;
7150 window_scroll_pixel_based_preserve_y = -1;
7151 window_scroll_preserve_hpos = -1;
7152 window_scroll_preserve_vpos = -1;
7154 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
7155 doc: /* Non-nil means call as function to display a help buffer.
7156 The function is called with one argument, the buffer to be displayed.
7157 Used by `with-output-to-temp-buffer'.
7158 If this function is used, then it must do the entire job of showing
7159 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
7160 Vtemp_buffer_show_function = Qnil;
7162 DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
7163 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
7164 Vminibuf_scroll_window = Qnil;
7166 DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
7167 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
7168 If the minibuffer is active, the `minibuffer-scroll-window' mode line
7169 is displayed in the `mode-line' face. */);
7170 mode_line_in_non_selected_windows = 1;
7172 DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
7173 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
7174 Vother_window_scroll_buffer = Qnil;
7176 DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
7177 doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
7178 auto_window_vscroll_p = 1;
7180 DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
7181 doc: /* Number of lines of continuity when scrolling by screenfuls. */);
7182 next_screen_context_lines = 2;
7184 DEFVAR_LISP ("scroll-preserve-screen-position",
7185 Vscroll_preserve_screen_position,
7186 doc: /* Controls if scroll commands move point to keep its screen position unchanged.
7187 A value of nil means point does not keep its screen position except
7188 at the scroll margin or window boundary respectively.
7189 A value of t means point keeps its screen position if the scroll
7190 command moved it vertically out of the window, e.g. when scrolling
7191 by full screens.
7192 Any other value means point always keeps its screen position.
7193 Scroll commands should have the `scroll-command' property
7194 on their symbols to be controlled by this variable. */);
7195 Vscroll_preserve_screen_position = Qnil;
7197 DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
7198 doc: /* Type of marker to use for `window-point'. */);
7199 Vwindow_point_insertion_type = Qnil;
7201 DEFVAR_LISP ("window-configuration-change-hook",
7202 Vwindow_configuration_change_hook,
7203 doc: /* Functions to call when window configuration changes.
7204 The buffer-local part is run once per window, with the relevant window
7205 selected; while the global part is run only once for the modified frame,
7206 with the relevant frame selected. */);
7207 Vwindow_configuration_change_hook = Qnil;
7209 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
7210 doc: /* Non-nil means `recenter' redraws entire frame.
7211 If this option is non-nil, then the `recenter' command with a nil
7212 argument will redraw the entire frame; the special value `tty' causes
7213 the frame to be redrawn only if it is a tty frame. */);
7214 Vrecenter_redisplay = Qtty;
7216 DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
7217 doc: /* If t, resize window combinations proportionally.
7218 If this variable is nil, splitting a window gets the entire screen space
7219 for displaying the new window from the window to split. Deleting and
7220 resizing a window preferably resizes one adjacent window only.
7222 If this variable is t, splitting a window tries to get the space
7223 proportionally from all windows in the same combination. This also
7224 allows to split a window that is otherwise too small or of fixed size.
7225 Resizing and deleting a window proportionally resize all windows in the
7226 same combination.
7228 Other values are reserved for future use.
7230 This variable takes no effect if the variable `window-combination-limit' is
7231 non-nil. */);
7232 Vwindow_combination_resize = Qnil;
7234 DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
7235 doc: /* If non-nil, splitting a window makes a new parent window.
7236 The following values are recognized:
7238 nil means splitting a window will create a new parent window only if the
7239 window has no parent window or the window shall become part of a
7240 combination orthogonal to the one it is part of.
7242 `window-size' means that splitting a window for displaying a buffer
7243 makes a new parent window provided `display-buffer' is supposed to
7244 explicitly set the window's size due to the presence of a
7245 `window-height' or `window-width' entry in the alist used by
7246 `display-buffer'. Otherwise, this value is handled like nil.
7248 `temp-buffer' means that splitting a window for displaying a temporary
7249 buffer always makes a new parent window. Otherwise, this value is
7250 handled like nil.
7252 `display-buffer' means that splitting a window for displaying a buffer
7253 always makes a new parent window. Since temporary buffers are
7254 displayed by the function `display-buffer', this value is stronger
7255 than `temp-buffer'. Splitting a window for other purpose makes a
7256 new parent window only if needed.
7258 t means that splitting a window always creates a new parent window. If
7259 all splits behave this way, each frame's window tree is a binary
7260 tree and every window but the frame's root window has exactly one
7261 sibling.
7263 Other values are reserved for future use. */);
7264 Vwindow_combination_limit = Qwindow_size;
7266 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
7267 doc: /* Alist of persistent window parameters.
7268 This alist specifies which window parameters shall get saved by
7269 `current-window-configuration' and `window-state-get' and subsequently
7270 restored to their previous values by `set-window-configuration' and
7271 `window-state-put'.
7273 The car of each entry of this alist is the symbol specifying the
7274 parameter. The cdr is one of the following:
7276 nil means the parameter is neither saved by `window-state-get' nor by
7277 `current-window-configuration'.
7279 t means the parameter is saved by `current-window-configuration' and,
7280 provided its WRITABLE argument is nil, by `window-state-get'.
7282 The symbol `writable' means the parameter is saved unconditionally by
7283 both `current-window-configuration' and `window-state-get'. Do not use
7284 this value for parameters without read syntax (like windows or frames).
7286 Parameters not saved by `current-window-configuration' or
7287 `window-state-get' are left alone by `set-window-configuration'
7288 respectively are not installed by `window-state-put'. */);
7289 Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
7291 DEFVAR_BOOL ("window-resize-pixelwise", window_resize_pixelwise,
7292 doc: /* Non-nil means resizing windows works pixelwise.
7293 Functions currently affected by this option are `split-window',
7294 `maximize-window', `minimize-window', `fit-window-to-buffer' and
7295 `fit-frame-to-buffer' and all functions symmetrically resizing a
7296 parent window.
7298 Note that when a frame's pixel size is not a multiple of the
7299 frame's character size, at least one window may get resized
7300 pixelwise even if this option is nil. */);
7301 window_resize_pixelwise = 0;
7303 defsubr (&Sselected_window);
7304 defsubr (&Sminibuffer_window);
7305 defsubr (&Swindow_minibuffer_p);
7306 defsubr (&Swindowp);
7307 defsubr (&Swindow_valid_p);
7308 defsubr (&Swindow_live_p);
7309 defsubr (&Swindow_frame);
7310 defsubr (&Sframe_root_window);
7311 defsubr (&Sframe_first_window);
7312 defsubr (&Sframe_selected_window);
7313 defsubr (&Sset_frame_selected_window);
7314 defsubr (&Spos_visible_in_window_p);
7315 defsubr (&Swindow_line_height);
7316 defsubr (&Swindow_buffer);
7317 defsubr (&Swindow_parent);
7318 defsubr (&Swindow_top_child);
7319 defsubr (&Swindow_left_child);
7320 defsubr (&Swindow_next_sibling);
7321 defsubr (&Swindow_prev_sibling);
7322 defsubr (&Swindow_combination_limit);
7323 defsubr (&Sset_window_combination_limit);
7324 defsubr (&Swindow_use_time);
7325 defsubr (&Swindow_pixel_width);
7326 defsubr (&Swindow_pixel_height);
7327 defsubr (&Swindow_total_width);
7328 defsubr (&Swindow_total_height);
7329 defsubr (&Swindow_normal_size);
7330 defsubr (&Swindow_new_pixel);
7331 defsubr (&Swindow_new_total);
7332 defsubr (&Swindow_new_normal);
7333 defsubr (&Swindow_pixel_left);
7334 defsubr (&Swindow_pixel_top);
7335 defsubr (&Swindow_left_column);
7336 defsubr (&Swindow_top_line);
7337 defsubr (&Sset_window_new_pixel);
7338 defsubr (&Sset_window_new_total);
7339 defsubr (&Sset_window_new_normal);
7340 defsubr (&Swindow_resize_apply);
7341 defsubr (&Swindow_resize_apply_total);
7342 defsubr (&Swindow_body_height);
7343 defsubr (&Swindow_body_width);
7344 defsubr (&Swindow_hscroll);
7345 defsubr (&Sset_window_hscroll);
7346 defsubr (&Swindow_redisplay_end_trigger);
7347 defsubr (&Sset_window_redisplay_end_trigger);
7348 defsubr (&Swindow_edges);
7349 defsubr (&Swindow_pixel_edges);
7350 defsubr (&Swindow_absolute_pixel_edges);
7351 defsubr (&Swindow_mode_line_height);
7352 defsubr (&Swindow_header_line_height);
7353 defsubr (&Swindow_right_divider_width);
7354 defsubr (&Swindow_bottom_divider_width);
7355 defsubr (&Swindow_inside_edges);
7356 defsubr (&Swindow_inside_pixel_edges);
7357 defsubr (&Swindow_inside_absolute_pixel_edges);
7358 defsubr (&Scoordinates_in_window_p);
7359 defsubr (&Swindow_at);
7360 defsubr (&Swindow_point);
7361 defsubr (&Swindow_start);
7362 defsubr (&Swindow_end);
7363 defsubr (&Sset_window_point);
7364 defsubr (&Sset_window_start);
7365 defsubr (&Swindow_dedicated_p);
7366 defsubr (&Sset_window_dedicated_p);
7367 defsubr (&Swindow_display_table);
7368 defsubr (&Sset_window_display_table);
7369 defsubr (&Snext_window);
7370 defsubr (&Sprevious_window);
7371 defsubr (&Sget_buffer_window);
7372 defsubr (&Sdelete_other_windows_internal);
7373 defsubr (&Sdelete_window_internal);
7374 defsubr (&Sresize_mini_window_internal);
7375 defsubr (&Sset_window_buffer);
7376 defsubr (&Srun_window_configuration_change_hook);
7377 defsubr (&Srun_window_scroll_functions);
7378 defsubr (&Sselect_window);
7379 defsubr (&Sforce_window_update);
7380 defsubr (&Ssplit_window_internal);
7381 defsubr (&Sscroll_up);
7382 defsubr (&Sscroll_down);
7383 defsubr (&Sscroll_left);
7384 defsubr (&Sscroll_right);
7385 defsubr (&Sother_window_for_scrolling);
7386 defsubr (&Sscroll_other_window);
7387 defsubr (&Sminibuffer_selected_window);
7388 defsubr (&Srecenter);
7389 defsubr (&Swindow_text_width);
7390 defsubr (&Swindow_text_height);
7391 defsubr (&Smove_to_window_line);
7392 defsubr (&Swindow_configuration_p);
7393 defsubr (&Swindow_configuration_frame);
7394 defsubr (&Sset_window_configuration);
7395 defsubr (&Scurrent_window_configuration);
7396 defsubr (&Sset_window_margins);
7397 defsubr (&Swindow_margins);
7398 defsubr (&Sset_window_fringes);
7399 defsubr (&Swindow_fringes);
7400 defsubr (&Sset_window_scroll_bars);
7401 defsubr (&Swindow_scroll_bars);
7402 defsubr (&Swindow_vscroll);
7403 defsubr (&Sset_window_vscroll);
7404 defsubr (&Scompare_window_configurations);
7405 defsubr (&Swindow_list);
7406 defsubr (&Swindow_list_1);
7407 defsubr (&Swindow_prev_buffers);
7408 defsubr (&Sset_window_prev_buffers);
7409 defsubr (&Swindow_next_buffers);
7410 defsubr (&Sset_window_next_buffers);
7411 defsubr (&Swindow_parameters);
7412 defsubr (&Swindow_parameter);
7413 defsubr (&Sset_window_parameter);
7416 void
7417 keys_of_window (void)
7419 initial_define_key (control_x_map, '<', "scroll-left");
7420 initial_define_key (control_x_map, '>', "scroll-right");
7422 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
7423 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
7424 initial_define_key (meta_map, 'v', "scroll-down-command");