Fix the Windows build broken by 2013-08-13T15:29:25Z!dmantipov@yandex.ru.
[emacs.git] / src / window.c
blobf9084e6c05fa33f2a30cf94a9472f80a90f7e911
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985-1987, 1993-1998, 2000-2013 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 #define WINDOW_INLINE EXTERN_INLINE
25 #include <stdio.h>
27 #include "lisp.h"
28 #include "character.h"
29 #include "buffer.h"
30 #include "keyboard.h"
31 #include "keymap.h"
32 #include "frame.h"
33 #include "window.h"
34 #include "commands.h"
35 #include "indent.h"
36 #include "termchar.h"
37 #include "disptab.h"
38 #include "dispextern.h"
39 #include "blockinput.h"
40 #include "intervals.h"
41 #include "termhooks.h" /* For FRAME_TERMINAL. */
43 #ifdef HAVE_X_WINDOWS
44 #include "xterm.h"
45 #endif /* HAVE_X_WINDOWS */
46 #ifdef HAVE_NTGUI
47 #include "w32term.h"
48 #endif
49 #ifdef MSDOS
50 #include "msdos.h"
51 #endif
52 #ifdef HAVE_NS
53 #include "nsterm.h"
54 #endif
56 Lisp_Object Qwindowp, Qwindow_live_p;
57 static Lisp_Object Qwindow_valid_p;
58 static Lisp_Object Qwindow_configuration_p;
59 static Lisp_Object Qrecord_window_buffer;
60 static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
61 static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
62 static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
63 static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
64 static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
66 static int displayed_window_lines (struct window *);
67 static int count_windows (struct window *);
68 static int get_leaf_windows (struct window *, struct window **, int);
69 static void window_scroll (Lisp_Object, EMACS_INT, bool, int);
70 static void window_scroll_pixel_based (Lisp_Object, int, bool, int);
71 static void window_scroll_line_based (Lisp_Object, int, bool, int);
72 static Lisp_Object window_list (void);
73 static int add_window_to_list (struct window *, void *);
74 static Lisp_Object next_window (Lisp_Object, Lisp_Object,
75 Lisp_Object, int);
76 static void decode_next_window_args (Lisp_Object *, Lisp_Object *,
77 Lisp_Object *);
78 static void foreach_window (struct frame *,
79 int (* fn) (struct window *, void *),
80 void *);
81 static int foreach_window_1 (struct window *,
82 int (* fn) (struct window *, void *),
83 void *);
84 static Lisp_Object window_list_1 (Lisp_Object, Lisp_Object, Lisp_Object);
85 static int window_resize_check (struct window *, bool);
86 static void window_resize_apply (struct window *, bool);
87 static Lisp_Object select_window (Lisp_Object, Lisp_Object, int);
88 static void select_window_1 (Lisp_Object, bool);
90 /* This is the window in which the terminal's cursor should
91 be left when nothing is being done with it. This must
92 always be a leaf window, and its buffer is selected by
93 the top level editing loop at the end of each command.
95 This value is always the same as
96 FRAME_SELECTED_WINDOW (selected_frame). */
97 Lisp_Object selected_window;
99 /* A list of all windows for use by next_window and Fwindow_list.
100 Functions creating or deleting windows should invalidate this cache
101 by setting it to nil. */
102 Lisp_Object Vwindow_list;
104 /* The mini-buffer window of the selected frame.
105 Note that you cannot test for mini-bufferness of an arbitrary window
106 by comparing against this; but you can test for mini-bufferness of
107 the selected window. */
108 Lisp_Object minibuf_window;
110 /* Non-nil means it is the window whose mode line should be
111 shown as the selected window when the minibuffer is selected. */
112 Lisp_Object minibuf_selected_window;
114 /* Hook run at end of temp_output_buffer_show. */
115 static Lisp_Object Qtemp_buffer_show_hook;
117 /* Nonzero after init_window_once has finished. */
118 static int window_initialized;
120 /* Hook to run when window config changes. */
121 static Lisp_Object Qwindow_configuration_change_hook;
123 /* Used by the function window_scroll_pixel_based */
124 static int window_scroll_pixel_based_preserve_x;
125 static int window_scroll_pixel_based_preserve_y;
127 /* Same for window_scroll_line_based. */
128 static EMACS_INT window_scroll_preserve_hpos;
129 static EMACS_INT window_scroll_preserve_vpos;
131 static void
132 CHECK_WINDOW_CONFIGURATION (Lisp_Object x)
134 CHECK_TYPE (WINDOW_CONFIGURATIONP (x), Qwindow_configuration_p, x);
137 /* These setters are used only in this file, so they can be private. */
138 static void
139 wset_combination_limit (struct window *w, Lisp_Object val)
141 w->combination_limit = val;
143 static void
144 wset_dedicated (struct window *w, Lisp_Object val)
146 w->dedicated = val;
148 static void
149 wset_display_table (struct window *w, Lisp_Object val)
151 w->display_table = val;
153 static void
154 wset_new_normal (struct window *w, Lisp_Object val)
156 w->new_normal = val;
158 static void
159 wset_new_total (struct window *w, Lisp_Object val)
161 w->new_total = val;
163 static void
164 wset_normal_cols (struct window *w, Lisp_Object val)
166 w->normal_cols = val;
168 static void
169 wset_normal_lines (struct window *w, Lisp_Object val)
171 w->normal_lines = val;
173 static void
174 wset_parent (struct window *w, Lisp_Object val)
176 w->parent = val;
178 static void
179 wset_pointm (struct window *w, Lisp_Object val)
181 w->pointm = val;
183 static void
184 wset_scroll_bar_width (struct window *w, Lisp_Object val)
186 w->scroll_bar_width = val;
188 static void
189 wset_start (struct window *w, Lisp_Object val)
191 w->start = val;
193 static void
194 wset_temslot (struct window *w, Lisp_Object val)
196 w->temslot = val;
198 static void
199 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
201 w->vertical_scroll_bar_type = val;
203 static void
204 wset_window_parameters (struct window *w, Lisp_Object val)
206 w->window_parameters = val;
208 static void
209 wset_combination (struct window *w, bool horflag, Lisp_Object val)
211 /* Since leaf windows never becomes non-leaf, there should
212 be no buffer and markers in start and pointm fields of W. */
213 eassert (!BUFFERP (w->contents) && NILP (w->start) && NILP (w->pointm));
214 w->contents = val;
215 /* When an internal window is deleted and VAL is nil, HORFLAG
216 is meaningless. */
217 if (!NILP (val))
218 w->horizontal = horflag;
221 /* Nonzero if leaf window W doesn't reflect the actual state
222 of displayed buffer due to its text or overlays change. */
224 bool
225 window_outdated (struct window *w)
227 struct buffer *b = XBUFFER (w->contents);
228 return (w->last_modified < BUF_MODIFF (b)
229 || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b));
232 struct window *
233 decode_live_window (register Lisp_Object window)
235 if (NILP (window))
236 return XWINDOW (selected_window);
238 CHECK_LIVE_WINDOW (window);
239 return XWINDOW (window);
242 struct window *
243 decode_any_window (register Lisp_Object window)
245 struct window *w;
247 if (NILP (window))
248 return XWINDOW (selected_window);
250 CHECK_WINDOW (window);
251 w = XWINDOW (window);
252 return w;
255 static struct window *
256 decode_valid_window (register Lisp_Object window)
258 struct window *w;
260 if (NILP (window))
261 return XWINDOW (selected_window);
263 CHECK_VALID_WINDOW (window);
264 w = XWINDOW (window);
265 return w;
268 /* Called when W's buffer slot is changed. ARG -1 means that W is about to
269 cease its buffer, and 1 means that W is about to set up the new one. */
271 static void
272 adjust_window_count (struct window *w, int arg)
274 eassert (eabs (arg) == 1);
275 if (BUFFERP (w->contents))
277 struct buffer *b = XBUFFER (w->contents);
279 if (b->base_buffer)
280 b = b->base_buffer;
281 b->window_count += arg;
282 eassert (b->window_count >= 0);
283 /* These should be recalculated by redisplay code. */
284 w->window_end_valid = 0;
285 w->base_line_pos = 0;
289 /* Set W's buffer slot to VAL and recompute number
290 of windows showing VAL if it is a buffer. */
292 void
293 wset_buffer (struct window *w, Lisp_Object val)
295 adjust_window_count (w, -1);
296 if (BUFFERP (val))
297 /* Make sure that we do not assign the buffer
298 to an internal window. */
299 eassert (MARKERP (w->start) && MARKERP (w->pointm));
300 w->contents = val;
301 adjust_window_count (w, 1);
304 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
305 doc: /* Return t if OBJECT is a window and nil otherwise. */)
306 (Lisp_Object object)
308 return WINDOWP (object) ? Qt : Qnil;
311 DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
312 doc: /* Return t if OBJECT is a valid window and nil otherwise.
313 A valid window is either a window that displays a buffer or an internal
314 window. Deleted windows are not live. */)
315 (Lisp_Object object)
317 return WINDOW_VALID_P (object) ? Qt : Qnil;
320 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
321 doc: /* Return t if OBJECT is a live window and nil otherwise.
322 A live window is a window that displays a buffer.
323 Internal windows and deleted windows are not live. */)
324 (Lisp_Object object)
326 return WINDOW_LIVE_P (object) ? Qt : Qnil;
329 /* Frames and windows. */
330 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 0, 1, 0,
331 doc: /* Return the frame that window WINDOW is on.
332 WINDOW must be a valid window and defaults to the selected one. */)
333 (Lisp_Object window)
335 return decode_valid_window (window)->frame;
338 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
339 doc: /* Return the root window of FRAME-OR-WINDOW.
340 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
341 With a frame argument, return that frame's root window.
342 With a window argument, return the root window of that window's frame. */)
343 (Lisp_Object frame_or_window)
345 Lisp_Object window;
347 if (NILP (frame_or_window))
348 window = SELECTED_FRAME ()->root_window;
349 else if (WINDOW_VALID_P (frame_or_window))
350 window = XFRAME (XWINDOW (frame_or_window)->frame)->root_window;
351 else
353 CHECK_LIVE_FRAME (frame_or_window);
354 window = XFRAME (frame_or_window)->root_window;
357 return window;
360 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
361 doc: /* Return the minibuffer window for frame FRAME.
362 If FRAME is omitted or nil, it defaults to the selected frame. */)
363 (Lisp_Object frame)
365 return FRAME_MINIBUF_WINDOW (decode_live_frame (frame));
368 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
369 Swindow_minibuffer_p, 0, 1, 0,
370 doc: /* Return non-nil if WINDOW is a minibuffer window.
371 WINDOW must be a valid window and defaults to the selected one. */)
372 (Lisp_Object window)
374 return MINI_WINDOW_P (decode_valid_window (window)) ? Qt : Qnil;
377 /* Don't move this to window.el - this must be a safe routine. */
378 DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
379 doc: /* Return the topmost, leftmost live window on FRAME-OR-WINDOW.
380 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
381 Else if FRAME-OR-WINDOW denotes a valid window, return the first window
382 of that window's frame. If FRAME-OR-WINDOW denotes a live frame, return
383 the first window of that frame. */)
384 (Lisp_Object frame_or_window)
386 Lisp_Object window;
388 if (NILP (frame_or_window))
389 window = SELECTED_FRAME ()->root_window;
390 else if (WINDOW_VALID_P (frame_or_window))
391 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
392 else
394 CHECK_LIVE_FRAME (frame_or_window);
395 window = XFRAME (frame_or_window)->root_window;
398 while (WINDOWP (XWINDOW (window)->contents))
399 window = XWINDOW (window)->contents;
401 return window;
404 DEFUN ("frame-selected-window", Fframe_selected_window,
405 Sframe_selected_window, 0, 1, 0,
406 doc: /* Return the selected window of FRAME-OR-WINDOW.
407 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
408 Else if FRAME-OR-WINDOW denotes a valid window, return the selected
409 window of that window's frame. If FRAME-OR-WINDOW denotes a live frame,
410 return the selected window of that frame. */)
411 (Lisp_Object frame_or_window)
413 Lisp_Object window;
415 if (NILP (frame_or_window))
416 window = SELECTED_FRAME ()->selected_window;
417 else if (WINDOW_VALID_P (frame_or_window))
418 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
419 else
421 CHECK_LIVE_FRAME (frame_or_window);
422 window = XFRAME (frame_or_window)->selected_window;
425 return window;
428 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
429 Sset_frame_selected_window, 2, 3, 0,
430 doc: /* Set selected window of FRAME to WINDOW.
431 FRAME must be a live frame and defaults to the selected one. If FRAME
432 is the selected frame, this makes WINDOW the selected window. Optional
433 argument NORECORD non-nil means to neither change the order of recently
434 selected windows nor the buffer list. WINDOW must denote a live window.
435 Return WINDOW. */)
436 (Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
438 if (NILP (frame))
439 frame = selected_frame;
441 CHECK_LIVE_FRAME (frame);
442 CHECK_LIVE_WINDOW (window);
444 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
445 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
447 if (EQ (frame, selected_frame))
448 return Fselect_window (window, norecord);
449 else
451 fset_selected_window (XFRAME (frame), window);
452 return window;
456 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
457 doc: /* Return the selected window.
458 The selected window is the window in which the standard cursor for
459 selected windows appears and to which many commands apply. */)
460 (void)
462 return selected_window;
465 int window_select_count;
467 /* If select_window is called with inhibit_point_swap non-zero it will
468 not store point of the old selected window's buffer back into that
469 window's pointm slot. This is needed by Fset_window_configuration to
470 avoid that the display routine is called with selected_window set to
471 Qnil causing a subsequent crash. */
472 static Lisp_Object
473 select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
475 register struct window *w;
476 struct frame *sf;
478 CHECK_LIVE_WINDOW (window);
480 w = XWINDOW (window);
482 /* Make the selected window's buffer current. */
483 Fset_buffer (w->contents);
485 if (EQ (window, selected_window) && !inhibit_point_swap)
486 /* `switch-to-buffer' uses (select-window (selected-window)) as a "clever"
487 way to call record_buffer from Elisp, so it's important that we call
488 record_buffer before returning here. */
489 goto record_and_return;
491 sf = SELECTED_FRAME ();
492 if (XFRAME (WINDOW_FRAME (w)) != sf)
494 fset_selected_window (XFRAME (WINDOW_FRAME (w)), window);
495 /* Use this rather than Fhandle_switch_frame
496 so that FRAME_FOCUS_FRAME is moved appropriately as we
497 move around in the state where a minibuffer in a separate
498 frame is active. */
499 Fselect_frame (WINDOW_FRAME (w), norecord);
500 /* Fselect_frame called us back so we've done all the work already. */
501 eassert (EQ (window, selected_window));
502 return window;
504 else
505 fset_selected_window (sf, window);
507 select_window_1 (window, inhibit_point_swap);
508 bset_last_selected_window (XBUFFER (w->contents), window);
509 windows_or_buffers_changed++;
511 record_and_return:
512 /* record_buffer can run QUIT, so make sure it is run only after we have
513 re-established the invariant between selected_window and selected_frame,
514 otherwise the temporary broken invariant might "escape" (bug#14161). */
515 if (NILP (norecord))
517 w->use_time = ++window_select_count;
518 record_buffer (w->contents);
521 return window;
524 /* Select window with a minimum of fuss, i.e. don't record the change anywhere
525 (not even for redisplay's benefit), and assume that the window's frame is
526 already selected. */
527 static void
528 select_window_1 (Lisp_Object window, bool inhibit_point_swap)
530 /* Store the old selected window's buffer's point in pointm of the old
531 selected window. It belongs to that window, and when the window is
532 not selected, must be in the window. */
533 if (!inhibit_point_swap)
535 struct window *ow = XWINDOW (selected_window);
536 if (BUFFERP (ow->contents))
537 set_marker_both (ow->pointm, ow->contents,
538 BUF_PT (XBUFFER (ow->contents)),
539 BUF_PT_BYTE (XBUFFER (ow->contents)));
542 selected_window = window;
544 /* Go to the point recorded in the window.
545 This is important when the buffer is in more
546 than one window. It also matters when
547 redisplay_window has altered point after scrolling,
548 because it makes the change only in the window. */
550 register ptrdiff_t new_point = marker_position (XWINDOW (window)->pointm);
551 if (new_point < BEGV)
552 SET_PT (BEGV);
553 else if (new_point > ZV)
554 SET_PT (ZV);
555 else
556 SET_PT (new_point);
560 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
561 doc: /* Select WINDOW which must be a live window.
562 Also make WINDOW's frame the selected frame and WINDOW that frame's
563 selected window. In addition, make WINDOW's buffer current and set that
564 buffer's value of `point' to the value of WINDOW's `window-point'.
565 Return WINDOW.
567 Optional second arg NORECORD non-nil means do not put this buffer at the
568 front of the buffer list and do not make this window the most recently
569 selected one.
571 Note that the main editor command loop sets the current buffer to the
572 buffer of the selected window before each command. */)
573 (register Lisp_Object window, Lisp_Object norecord)
575 return select_window (window, norecord, 0);
578 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
579 doc: /* Return the buffer displayed in window WINDOW.
580 If WINDOW is omitted or nil, it defaults to the selected window.
581 Return nil for an internal window or a deleted window. */)
582 (Lisp_Object window)
584 struct window *w = decode_any_window (window);
585 return WINDOW_LEAF_P (w) ? w->contents : Qnil;
588 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
589 doc: /* Return the parent window of window WINDOW.
590 WINDOW must be a valid window and defaults to the selected one.
591 Return nil for a window with no parent (e.g. a root window). */)
592 (Lisp_Object window)
594 return decode_valid_window (window)->parent;
597 DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 0, 1, 0,
598 doc: /* Return the topmost child window of window WINDOW.
599 WINDOW must be a valid window and defaults to the selected one.
600 Return nil if WINDOW is a live window (live windows have no children).
601 Return nil if WINDOW is an internal window whose children form a
602 horizontal combination. */)
603 (Lisp_Object window)
605 struct window *w = decode_valid_window (window);
606 return WINDOW_VERTICAL_COMBINATION_P (w) ? w->contents : Qnil;
609 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
610 doc: /* Return the leftmost child window of window WINDOW.
611 WINDOW must be a valid window and defaults to the selected one.
612 Return nil if WINDOW is a live window (live windows have no children).
613 Return nil if WINDOW is an internal window whose children form a
614 vertical combination. */)
615 (Lisp_Object window)
617 struct window *w = decode_valid_window (window);
618 return WINDOW_HORIZONTAL_COMBINATION_P (w) ? w->contents : Qnil;
621 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
622 doc: /* Return the next sibling window of window WINDOW.
623 WINDOW must be a valid window and defaults to the selected one.
624 Return nil if WINDOW has no next sibling. */)
625 (Lisp_Object window)
627 return decode_valid_window (window)->next;
630 DEFUN ("window-prev-sibling", Fwindow_prev_sibling, Swindow_prev_sibling, 0, 1, 0,
631 doc: /* Return the previous sibling window of window WINDOW.
632 WINDOW must be a valid window and defaults to the selected one.
633 Return nil if WINDOW has no previous sibling. */)
634 (Lisp_Object window)
636 return decode_valid_window (window)->prev;
639 DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
640 doc: /* Return combination limit of window WINDOW.
641 WINDOW must be a valid window used in horizontal or vertical combination.
642 If the return value is nil, child windows of WINDOW can be recombined with
643 WINDOW's siblings. A return value of t means that child windows of
644 WINDOW are never \(re-)combined with WINDOW's siblings. */)
645 (Lisp_Object window)
647 struct window *w;
649 CHECK_VALID_WINDOW (window);
650 w = XWINDOW (window);
651 if (WINDOW_LEAF_P (w))
652 error ("Combination limit is meaningful for internal windows only");
653 return w->combination_limit;
656 DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
657 doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
658 WINDOW must be a valid window used in horizontal or vertical combination.
659 If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
660 siblings. LIMIT t means that child windows of WINDOW are never
661 \(re-)combined with WINDOW's siblings. Other values are reserved for
662 future use. */)
663 (Lisp_Object window, Lisp_Object limit)
665 struct window *w;
667 CHECK_VALID_WINDOW (window);
668 w = XWINDOW (window);
669 if (WINDOW_LEAF_P (w))
670 error ("Combination limit is meaningful for internal windows only");
671 wset_combination_limit (w, limit);
672 return limit;
675 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
676 doc: /* Return the use time of window WINDOW.
677 WINDOW must be a live window and defaults to the selected one.
678 The window with the highest use time is the most recently selected
679 one. The window with the lowest use time is the least recently
680 selected one. */)
681 (Lisp_Object window)
683 return make_number (decode_live_window (window)->use_time);
686 DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 1, 0,
687 doc: /* Return the total height, in lines, of window WINDOW.
688 WINDOW must be a valid window and defaults to the selected one.
690 The return value includes the mode line and header line, if any.
691 If WINDOW is an internal window, the total height is the height
692 of the screen areas spanned by its children.
694 On a graphical display, this total height is reported as an
695 integer multiple of the default character height. */)
696 (Lisp_Object window)
698 return make_number (decode_valid_window (window)->total_lines);
701 DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 1, 0,
702 doc: /* Return the total width, in columns, of window WINDOW.
703 WINDOW must be a valid window and defaults to the selected one.
705 The return value includes any vertical dividers or scroll bars
706 belonging to WINDOW. If WINDOW is an internal window, the total width
707 is the width of the screen areas spanned by its children.
709 On a graphical display, this total width is reported as an
710 integer multiple of the default character width. */)
711 (Lisp_Object window)
713 return make_number (decode_valid_window (window)->total_cols);
716 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
717 doc: /* Return the new total size of window WINDOW.
718 WINDOW must be a valid window and defaults to the selected one. */)
719 (Lisp_Object window)
721 return decode_valid_window (window)->new_total;
724 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
725 doc: /* Return the normal height of window WINDOW.
726 WINDOW must be a valid window and defaults to the selected one.
727 If HORIZONTAL is non-nil, return the normal width of WINDOW. */)
728 (Lisp_Object window, Lisp_Object horizontal)
730 struct window *w = decode_valid_window (window);
732 return NILP (horizontal) ? w->normal_lines : w->normal_cols;
735 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
736 doc: /* Return new normal size of window WINDOW.
737 WINDOW must be a valid window and defaults to the selected one. */)
738 (Lisp_Object window)
740 return decode_valid_window (window)->new_normal;
743 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
744 doc: /* Return left column of window WINDOW.
745 This is the distance, in columns, between the left edge of WINDOW and
746 the left edge of the frame's window area. For instance, the return
747 value is 0 if there is no window to the left of WINDOW.
749 WINDOW must be a valid window and defaults to the selected one. */)
750 (Lisp_Object window)
752 return make_number (decode_valid_window (window)->left_col);
755 DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
756 doc: /* Return top line of window WINDOW.
757 This is the distance, in lines, between the top of WINDOW and the top
758 of the frame's window area. For instance, the return value is 0 if
759 there is no window above WINDOW.
761 WINDOW must be a valid window and defaults to the selected one. */)
762 (Lisp_Object window)
764 return make_number (decode_valid_window (window)->top_line);
767 /* Return the number of lines of W's body. Don't count any mode or
768 header line of W. */
770 static int
771 window_body_lines (struct window *w)
773 int height = w->total_lines;
775 if (!MINI_WINDOW_P (w))
777 if (WINDOW_WANTS_MODELINE_P (w))
778 --height;
779 if (WINDOW_WANTS_HEADER_LINE_P (w))
780 --height;
783 return height;
786 /* Return the number of columns of W's body. Don't count columns
787 occupied by the scroll bar or the vertical bar separating W from its
788 right sibling. On window-systems don't count fringes or display
789 margins either. */
792 window_body_cols (struct window *w)
794 struct frame *f = XFRAME (WINDOW_FRAME (w));
795 int width = w->total_cols;
797 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
798 /* Scroll bars occupy a few columns. */
799 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
800 else if (!FRAME_WINDOW_P (f)
801 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
802 /* The column of `|' characters separating side-by-side windows
803 occupies one column only. */
804 width -= 1;
806 /* Display margins cannot be used for normal text. */
807 width -= WINDOW_LEFT_MARGIN_COLS (w) + WINDOW_RIGHT_MARGIN_COLS (w);
809 if (FRAME_WINDOW_P (f))
810 /* On window-systems, fringes cannot be used for normal text. */
811 width -= WINDOW_FRINGE_COLS (w);
813 return width;
816 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 1, 0,
817 doc: /* Return the height, in lines, of WINDOW's text area.
818 WINDOW must be a live window and defaults to the selected one.
820 The returned height does not include the mode line or header line.
821 On a graphical display, the height is expressed as an integer multiple
822 of the default character height. If a line at the bottom of the text
823 area is only partially visible, that counts as a whole line; to
824 exclude partially-visible lines, use `window-text-height'. */)
825 (Lisp_Object window)
827 return make_number (window_body_lines (decode_live_window (window)));
830 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 1, 0,
831 doc: /* Return the width, in columns, of WINDOW's text area.
832 WINDOW must be a live window and defaults to the selected one.
834 The return value does not include any vertical dividers, fringe or
835 marginal areas, or scroll bars. On a graphical display, the width is
836 expressed as an integer multiple of the default character width. */)
837 (Lisp_Object window)
839 return make_number (window_body_cols (decode_live_window (window)));
842 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
843 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
844 WINDOW must be a live window and defaults to the selected one. */)
845 (Lisp_Object window)
847 return make_number (decode_live_window (window)->hscroll);
850 /* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
851 range, returning the new amount as a fixnum. */
852 static Lisp_Object
853 set_window_hscroll (struct window *w, EMACS_INT hscroll)
855 /* Horizontal scrolling has problems with large scroll amounts.
856 It's too slow with long lines, and even with small lines the
857 display can be messed up. For now, though, impose only the limits
858 required by the internal representation: horizontal scrolling must
859 fit in fixnum (since it's visible to Elisp) and into ptrdiff_t
860 (since it's stored in a ptrdiff_t). */
861 ptrdiff_t hscroll_max = min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX);
862 ptrdiff_t new_hscroll = clip_to_bounds (0, hscroll, hscroll_max);
864 /* Prevent redisplay shortcuts when changing the hscroll. */
865 if (w->hscroll != new_hscroll)
866 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
868 w->hscroll = new_hscroll;
869 return make_number (new_hscroll);
872 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
873 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
874 WINDOW must be a live window and defaults to the selected one.
875 Clip the number to a reasonable value if out of range.
876 Return the new number. NCOL should be zero or positive.
878 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
879 window so that the location of point moves off-window. */)
880 (Lisp_Object window, Lisp_Object ncol)
882 CHECK_NUMBER (ncol);
883 return set_window_hscroll (decode_live_window (window), XINT (ncol));
886 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
887 Swindow_redisplay_end_trigger, 0, 1, 0,
888 doc: /* Return WINDOW's redisplay end trigger value.
889 WINDOW must be a live window and defaults to the selected one.
890 See `set-window-redisplay-end-trigger' for more information. */)
891 (Lisp_Object window)
893 return decode_live_window (window)->redisplay_end_trigger;
896 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
897 Sset_window_redisplay_end_trigger, 2, 2, 0,
898 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
899 WINDOW must be a live window and defaults to the selected one. VALUE
900 should be a buffer position (typically a marker) or nil. If it is a
901 buffer position, then if redisplay in WINDOW reaches a position beyond
902 VALUE, the functions in `redisplay-end-trigger-functions' are called
903 with two arguments: WINDOW, and the end trigger value. Afterwards the
904 end-trigger value is reset to nil. */)
905 (register Lisp_Object window, Lisp_Object value)
907 wset_redisplay_end_trigger (decode_live_window (window), value);
908 return value;
911 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
912 doc: /* Return a list of the edge coordinates of WINDOW.
913 WINDOW must be a valid window and defaults to the selected one.
915 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
916 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
917 0 at top left corner of frame.
919 RIGHT is one more than the rightmost column occupied by WINDOW. BOTTOM
920 is one more than the bottommost row occupied by WINDOW. The edges
921 include the space used by WINDOW's scroll bar, display margins, fringes,
922 header line, and/or mode line. For the edges of just the text area, use
923 `window-inside-edges'. */)
924 (Lisp_Object window)
926 register struct window *w = decode_valid_window (window);
928 return list4i (WINDOW_LEFT_EDGE_COL (w), WINDOW_TOP_EDGE_LINE (w),
929 WINDOW_RIGHT_EDGE_COL (w), WINDOW_BOTTOM_EDGE_LINE (w));
932 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
933 doc: /* Return a list of the edge pixel coordinates of WINDOW.
934 WINDOW must be a valid window and defaults to the selected one.
936 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
937 0, 0 at the top left corner of the frame.
939 RIGHT is one more than the rightmost x position occupied by WINDOW.
940 BOTTOM is one more than the bottommost y position occupied by WINDOW.
941 The pixel edges include the space used by WINDOW's scroll bar, display
942 margins, fringes, header line, and/or mode line. For the pixel edges
943 of just the text area, use `window-inside-pixel-edges'. */)
944 (Lisp_Object window)
946 register struct window *w = decode_valid_window (window);
948 return list4i (WINDOW_LEFT_EDGE_X (w), WINDOW_TOP_EDGE_Y (w),
949 WINDOW_RIGHT_EDGE_X (w), WINDOW_BOTTOM_EDGE_Y (w));
952 static void
953 calc_absolute_offset (struct window *w, int *add_x, int *add_y)
955 struct frame *f = XFRAME (w->frame);
956 *add_y = f->top_pos;
957 #ifdef FRAME_MENUBAR_HEIGHT
958 *add_y += FRAME_MENUBAR_HEIGHT (f);
959 #endif
960 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
961 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
962 #elif FRAME_TOOLBAR_HEIGHT
963 *add_y += FRAME_TOOLBAR_HEIGHT (f);
964 #endif
965 #ifdef FRAME_NS_TITLEBAR_HEIGHT
966 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
967 #endif
968 *add_x = f->left_pos;
969 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
970 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
971 #endif
974 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
975 Swindow_absolute_pixel_edges, 0, 1, 0,
976 doc: /* Return a list of the edge pixel coordinates of WINDOW.
977 WINDOW must be a valid window and defaults to the selected one.
979 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
980 0, 0 at the top left corner of the display.
982 RIGHT is one more than the rightmost x position occupied by WINDOW.
983 BOTTOM is one more than the bottommost y position occupied by WINDOW.
984 The pixel edges include the space used by WINDOW's scroll bar, display
985 margins, fringes, header line, and/or mode line. For the pixel edges
986 of just the text area, use `window-inside-absolute-pixel-edges'. */)
987 (Lisp_Object window)
989 register struct window *w = decode_valid_window (window);
990 int add_x, add_y;
992 calc_absolute_offset (w, &add_x, &add_y);
994 return list4i (WINDOW_LEFT_EDGE_X (w) + add_x,
995 WINDOW_TOP_EDGE_Y (w) + add_y,
996 WINDOW_RIGHT_EDGE_X (w) + add_x,
997 WINDOW_BOTTOM_EDGE_Y (w) + add_y);
1000 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
1001 doc: /* Return a list of the edge coordinates of WINDOW.
1002 WINDOW must be a live window and defaults to the selected one.
1004 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
1005 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
1006 0 at top left corner of frame.
1008 RIGHT is one more than the rightmost column of WINDOW's text area.
1009 BOTTOM is one more than the bottommost row of WINDOW's text area. The
1010 inside edges do not include the space used by the WINDOW's scroll bar,
1011 display margins, fringes, header line, and/or mode line. */)
1012 (Lisp_Object window)
1014 register struct window *w = decode_live_window (window);
1016 return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w)
1017 + WINDOW_LEFT_MARGIN_COLS (w)
1018 + WINDOW_LEFT_FRINGE_COLS (w)),
1019 (WINDOW_TOP_EDGE_LINE (w)
1020 + WINDOW_HEADER_LINE_LINES (w)),
1021 (WINDOW_BOX_RIGHT_EDGE_COL (w)
1022 - WINDOW_RIGHT_MARGIN_COLS (w)
1023 - WINDOW_RIGHT_FRINGE_COLS (w)),
1024 (WINDOW_BOTTOM_EDGE_LINE (w)
1025 - WINDOW_MODE_LINE_LINES (w)));
1028 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
1029 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1030 WINDOW must be a live window and defaults to the selected one.
1032 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1033 (0,0) at the top left corner of the frame's window area.
1035 RIGHT is one more than the rightmost x position of WINDOW's text area.
1036 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1037 The inside edges do not include the space used by WINDOW's scroll bar,
1038 display margins, fringes, header line, and/or mode line. */)
1039 (Lisp_Object window)
1041 register struct window *w = decode_live_window (window);
1043 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1044 + WINDOW_LEFT_MARGIN_WIDTH (w)
1045 + WINDOW_LEFT_FRINGE_WIDTH (w)),
1046 (WINDOW_TOP_EDGE_Y (w)
1047 + WINDOW_HEADER_LINE_HEIGHT (w)),
1048 (WINDOW_BOX_RIGHT_EDGE_X (w)
1049 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1050 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
1051 (WINDOW_BOTTOM_EDGE_Y (w)
1052 - WINDOW_MODE_LINE_HEIGHT (w)));
1055 DEFUN ("window-inside-absolute-pixel-edges",
1056 Fwindow_inside_absolute_pixel_edges,
1057 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
1058 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1059 WINDOW must be a live window and defaults to the selected one.
1061 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1062 (0,0) at the top left corner of the frame's window area.
1064 RIGHT is one more than the rightmost x position of WINDOW's text area.
1065 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1066 The inside edges do not include the space used by WINDOW's scroll bar,
1067 display margins, fringes, header line, and/or mode line. */)
1068 (Lisp_Object window)
1070 register struct window *w = decode_live_window (window);
1071 int add_x, add_y;
1073 calc_absolute_offset (w, &add_x, &add_y);
1075 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1076 + WINDOW_LEFT_MARGIN_WIDTH (w)
1077 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
1078 (WINDOW_TOP_EDGE_Y (w)
1079 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
1080 (WINDOW_BOX_RIGHT_EDGE_X (w)
1081 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1082 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
1083 (WINDOW_BOTTOM_EDGE_Y (w)
1084 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
1087 /* Test if the character at column X, row Y is within window W.
1088 If it is not, return ON_NOTHING;
1089 if it is in the window's text area, return ON_TEXT;
1090 if it is on the window's modeline, return ON_MODE_LINE;
1091 if it is on the border between the window and its right sibling,
1092 return ON_VERTICAL_BORDER.
1093 if it is on a scroll bar, return ON_SCROLL_BAR.
1094 if it is on the window's top line, return ON_HEADER_LINE;
1095 if it is in left or right fringe of the window,
1096 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
1097 if it is in the marginal area to the left/right of the window,
1098 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
1100 X and Y are frame relative pixel coordinates. */
1102 static enum window_part
1103 coordinates_in_window (register struct window *w, int x, int y)
1105 struct frame *f = XFRAME (WINDOW_FRAME (w));
1106 enum window_part part;
1107 int ux = FRAME_COLUMN_WIDTH (f);
1108 int left_x = WINDOW_LEFT_EDGE_X (w);
1109 int right_x = WINDOW_RIGHT_EDGE_X (w);
1110 int top_y = WINDOW_TOP_EDGE_Y (w);
1111 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
1112 /* The width of the area where the vertical line can be dragged.
1113 (Between mode lines for instance. */
1114 int grabbable_width = ux;
1115 int lmargin_width, rmargin_width, text_left, text_right;
1117 /* Outside any interesting row or column? */
1118 if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
1119 return ON_NOTHING;
1121 /* On the mode line or header line? */
1122 if ((WINDOW_WANTS_MODELINE_P (w)
1123 && y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
1124 && (part = ON_MODE_LINE))
1125 || (WINDOW_WANTS_HEADER_LINE_P (w)
1126 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
1127 && (part = ON_HEADER_LINE)))
1129 /* If it's under/over the scroll bar portion of the mode/header
1130 line, say it's on the vertical line. That's to be able to
1131 resize windows horizontally in case we're using toolkit scroll
1132 bars. Note: If scrollbars are on the left, the window that
1133 must be eventually resized is that on the left of WINDOW. */
1134 if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1135 && !WINDOW_LEFTMOST_P (w)
1136 && eabs (x - left_x) < grabbable_width)
1137 || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1138 && !WINDOW_RIGHTMOST_P (w)
1139 && eabs (x - right_x) < grabbable_width))
1140 return ON_VERTICAL_BORDER;
1141 else
1142 return part;
1145 /* In what's below, we subtract 1 when computing right_x because we
1146 want the rightmost pixel, which is given by left_pixel+width-1. */
1147 if (w->pseudo_window_p)
1149 left_x = 0;
1150 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
1152 else
1154 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
1155 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
1158 /* Outside any interesting column? */
1159 if (x < left_x || x > right_x)
1160 return ON_SCROLL_BAR;
1162 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
1163 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
1165 text_left = window_box_left (w, TEXT_AREA);
1166 text_right = text_left + window_box_width (w, TEXT_AREA);
1168 if (FRAME_WINDOW_P (f))
1170 if (!w->pseudo_window_p
1171 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
1172 && !WINDOW_RIGHTMOST_P (w)
1173 && (eabs (x - right_x) < grabbable_width))
1174 return ON_VERTICAL_BORDER;
1176 /* Need to say "x > right_x" rather than >=, since on character
1177 terminals, the vertical line's x coordinate is right_x. */
1178 else if (!w->pseudo_window_p
1179 && !WINDOW_RIGHTMOST_P (w)
1180 && x > right_x - ux)
1181 return ON_VERTICAL_BORDER;
1183 if (x < text_left)
1185 if (lmargin_width > 0
1186 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1187 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
1188 : (x < left_x + lmargin_width)))
1189 return ON_LEFT_MARGIN;
1191 return ON_LEFT_FRINGE;
1194 if (x >= text_right)
1196 if (rmargin_width > 0
1197 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1198 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
1199 : (x >= right_x - rmargin_width)))
1200 return ON_RIGHT_MARGIN;
1202 return ON_RIGHT_FRINGE;
1205 /* Everything special ruled out - must be on text area */
1206 return ON_TEXT;
1209 /* Take X is the frame-relative pixel x-coordinate, and return the
1210 x-coordinate relative to part PART of window W. */
1212 window_relative_x_coord (struct window *w, enum window_part part, int x)
1214 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
1216 switch (part)
1218 case ON_TEXT:
1219 return x - window_box_left (w, TEXT_AREA);
1221 case ON_LEFT_FRINGE:
1222 return x - left_x;
1224 case ON_RIGHT_FRINGE:
1225 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
1227 case ON_LEFT_MARGIN:
1228 return (x - left_x
1229 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1230 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
1232 case ON_RIGHT_MARGIN:
1233 return (x + 1
1234 - ((w->pseudo_window_p)
1235 ? WINDOW_TOTAL_WIDTH (w)
1236 : WINDOW_BOX_RIGHT_EDGE_X (w))
1237 + window_box_width (w, RIGHT_MARGIN_AREA)
1238 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1239 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
1242 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
1243 return 0;
1247 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
1248 Scoordinates_in_window_p, 2, 2, 0,
1249 doc: /* Return non-nil if COORDINATES are in WINDOW.
1250 WINDOW must be a live window and defaults to the selected one.
1251 COORDINATES is a cons of the form (X . Y), X and Y being distances
1252 measured in characters from the upper-left corner of the frame.
1253 \(0 . 0) denotes the character in the upper left corner of the
1254 frame.
1255 If COORDINATES are in the text portion of WINDOW,
1256 the coordinates relative to the window are returned.
1257 If they are in the mode line of WINDOW, `mode-line' is returned.
1258 If they are in the top mode line of WINDOW, `header-line' is returned.
1259 If they are in the left fringe of WINDOW, `left-fringe' is returned.
1260 If they are in the right fringe of WINDOW, `right-fringe' is returned.
1261 If they are on the border between WINDOW and its right sibling,
1262 `vertical-line' is returned.
1263 If they are in the windows's left or right marginal areas, `left-margin'\n\
1264 or `right-margin' is returned. */)
1265 (register Lisp_Object coordinates, Lisp_Object window)
1267 struct window *w;
1268 struct frame *f;
1269 int x, y;
1270 Lisp_Object lx, ly;
1272 w = decode_live_window (window);
1273 f = XFRAME (w->frame);
1274 CHECK_CONS (coordinates);
1275 lx = Fcar (coordinates);
1276 ly = Fcdr (coordinates);
1277 CHECK_NUMBER_OR_FLOAT (lx);
1278 CHECK_NUMBER_OR_FLOAT (ly);
1279 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1280 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
1282 switch (coordinates_in_window (w, x, y))
1284 case ON_NOTHING:
1285 return Qnil;
1287 case ON_TEXT:
1288 /* Convert X and Y to window relative pixel coordinates, and
1289 return the canonical char units. */
1290 x -= window_box_left (w, TEXT_AREA);
1291 y -= WINDOW_TOP_EDGE_Y (w);
1292 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1293 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
1295 case ON_MODE_LINE:
1296 return Qmode_line;
1298 case ON_VERTICAL_BORDER:
1299 return Qvertical_line;
1301 case ON_HEADER_LINE:
1302 return Qheader_line;
1304 case ON_LEFT_FRINGE:
1305 return Qleft_fringe;
1307 case ON_RIGHT_FRINGE:
1308 return Qright_fringe;
1310 case ON_LEFT_MARGIN:
1311 return Qleft_margin;
1313 case ON_RIGHT_MARGIN:
1314 return Qright_margin;
1316 case ON_SCROLL_BAR:
1317 /* Historically we are supposed to return nil in this case. */
1318 return Qnil;
1320 default:
1321 emacs_abort ();
1326 /* Callback for foreach_window, used in window_from_coordinates.
1327 Check if window W contains coordinates specified by USER_DATA which
1328 is actually a pointer to a struct check_window_data CW.
1330 Check if window W contains coordinates *CW->x and *CW->y. If it
1331 does, return W in *CW->window, as Lisp_Object, and return in
1332 *CW->part the part of the window under coordinates *X,*Y. Return
1333 zero from this function to stop iterating over windows. */
1335 struct check_window_data
1337 Lisp_Object *window;
1338 int x, y;
1339 enum window_part *part;
1342 static int
1343 check_window_containing (struct window *w, void *user_data)
1345 struct check_window_data *cw = user_data;
1346 enum window_part found;
1347 int continue_p = 1;
1349 found = coordinates_in_window (w, cw->x, cw->y);
1350 if (found != ON_NOTHING)
1352 *cw->part = found;
1353 XSETWINDOW (*cw->window, w);
1354 continue_p = 0;
1357 return continue_p;
1361 /* Find the window containing frame-relative pixel position X/Y and
1362 return it as a Lisp_Object.
1364 If X, Y is on one of the window's special `window_part' elements,
1365 set *PART to the id of that element.
1367 If there is no window under X, Y return nil and leave *PART
1368 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1370 This function was previously implemented with a loop cycling over
1371 windows with Fnext_window, and starting with the frame's selected
1372 window. It turned out that this doesn't work with an
1373 implementation of next_window using Vwindow_list, because
1374 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1375 tree of F when this function is called asynchronously from
1376 note_mouse_highlight. The original loop didn't terminate in this
1377 case. */
1379 Lisp_Object
1380 window_from_coordinates (struct frame *f, int x, int y,
1381 enum window_part *part, bool tool_bar_p)
1383 Lisp_Object window;
1384 struct check_window_data cw;
1385 enum window_part dummy;
1387 if (part == 0)
1388 part = &dummy;
1390 window = Qnil;
1391 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
1392 foreach_window (f, check_window_containing, &cw);
1394 /* If not found above, see if it's in the tool bar window, if a tool
1395 bar exists. */
1396 if (NILP (window)
1397 && tool_bar_p
1398 && WINDOWP (f->tool_bar_window)
1399 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1400 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
1401 != ON_NOTHING))
1403 *part = ON_TEXT;
1404 window = f->tool_bar_window;
1407 return window;
1410 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1411 doc: /* Return window containing coordinates X and Y on FRAME.
1412 FRAME must be a live frame and defaults to the selected one.
1413 The top left corner of the frame is considered to be row 0,
1414 column 0. */)
1415 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1417 struct frame *f = decode_live_frame (frame);
1419 /* Check that arguments are integers or floats. */
1420 CHECK_NUMBER_OR_FLOAT (x);
1421 CHECK_NUMBER_OR_FLOAT (y);
1423 return window_from_coordinates (f,
1424 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1425 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1426 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1427 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1428 0, 0);
1431 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1432 doc: /* Return current value of point in WINDOW.
1433 WINDOW must be a live window and defaults to the selected one.
1435 For a nonselected window, this is the value point would have if that
1436 window were selected.
1438 Note that, when WINDOW is selected, the value returned is the same as
1439 that returned by `point' for WINDOW's buffer. It would be more strictly
1440 correct to return the top-level value of `point', outside of any
1441 `save-excursion' forms. But that is hard to define. */)
1442 (Lisp_Object window)
1444 register struct window *w = decode_live_window (window);
1446 if (w == XWINDOW (selected_window))
1447 return make_number (BUF_PT (XBUFFER (w->contents)));
1448 else
1449 return Fmarker_position (w->pointm);
1452 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1453 doc: /* Return position at which display currently starts in WINDOW.
1454 WINDOW must be a live window and defaults to the selected one.
1455 This is updated by redisplay or by calling `set-window-start'. */)
1456 (Lisp_Object window)
1458 return Fmarker_position (decode_live_window (window)->start);
1461 /* This is text temporarily removed from the doc string below.
1463 This function returns nil if the position is not currently known.
1464 That happens when redisplay is preempted and doesn't finish.
1465 If in that case you want to compute where the end of the window would
1466 have been if redisplay had finished, do this:
1467 (save-excursion
1468 (goto-char (window-start window))
1469 (vertical-motion (1- (window-height window)) window)
1470 (point))") */
1472 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1473 doc: /* Return position at which display currently ends in WINDOW.
1474 WINDOW must be a live window and defaults to the selected one.
1475 This is updated by redisplay, when it runs to completion.
1476 Simply changing the buffer text or setting `window-start'
1477 does not update this value.
1478 Return nil if there is no recorded value. (This can happen if the
1479 last redisplay of WINDOW was preempted, and did not finish.)
1480 If UPDATE is non-nil, compute the up-to-date position
1481 if it isn't already recorded. */)
1482 (Lisp_Object window, Lisp_Object update)
1484 Lisp_Object value;
1485 struct window *w = decode_live_window (window);
1486 Lisp_Object buf;
1487 struct buffer *b;
1489 buf = w->contents;
1490 CHECK_BUFFER (buf);
1491 b = XBUFFER (buf);
1493 if (! NILP (update)
1494 && (windows_or_buffers_changed
1495 || !w->window_end_valid
1496 || b->clip_changed
1497 || b->prevent_redisplay_optimizations_p
1498 || window_outdated (w))
1499 && !noninteractive)
1501 struct text_pos startp;
1502 ptrdiff_t charpos = marker_position (w->start);
1503 struct it it;
1504 struct buffer *old_buffer = NULL;
1505 void *itdata = NULL;
1507 /* Cannot use Fvertical_motion because that function doesn't
1508 cope with variable-height lines. */
1509 if (b != current_buffer)
1511 old_buffer = current_buffer;
1512 set_buffer_internal (b);
1515 /* In case W->start is out of the range, use something
1516 reasonable. This situation occurred when loading a file with
1517 `-l' containing a call to `rmail' with subsequent other
1518 commands. At the end, W->start happened to be BEG, while
1519 rmail had already narrowed the buffer. */
1520 if (charpos < BEGV)
1521 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1522 else if (charpos > ZV)
1523 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1524 else
1525 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1527 itdata = bidi_shelve_cache ();
1528 start_display (&it, w, startp);
1529 move_it_vertically (&it, window_box_height (w));
1530 if (it.current_y < it.last_visible_y)
1531 move_it_past_eol (&it);
1532 value = make_number (IT_CHARPOS (it));
1533 bidi_unshelve_cache (itdata, 0);
1535 if (old_buffer)
1536 set_buffer_internal (old_buffer);
1538 else
1539 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1541 return value;
1544 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1545 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1546 WINDOW must be a live window and defaults to the selected one.
1547 Return POS. */)
1548 (Lisp_Object window, Lisp_Object pos)
1550 register struct window *w = decode_live_window (window);
1552 /* Type of POS is checked by Fgoto_char or set_marker_restricted ... */
1554 if (w == XWINDOW (selected_window))
1556 if (XBUFFER (w->contents) == current_buffer)
1557 Fgoto_char (pos);
1558 else
1560 struct buffer *old_buffer = current_buffer;
1562 /* ... but here we want to catch type error before buffer change. */
1563 CHECK_NUMBER_COERCE_MARKER (pos);
1564 set_buffer_internal (XBUFFER (w->contents));
1565 Fgoto_char (pos);
1566 set_buffer_internal (old_buffer);
1569 else
1571 set_marker_restricted (w->pointm, pos, w->contents);
1572 /* We have to make sure that redisplay updates the window to show
1573 the new value of point. */
1574 ++windows_or_buffers_changed;
1577 return pos;
1580 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1581 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1582 WINDOW must be a live window and defaults to the selected one. Return
1583 POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
1584 overriding motion of point in order to display at this exact start. */)
1585 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1587 register struct window *w = decode_live_window (window);
1589 set_marker_restricted (w->start, pos, w->contents);
1590 /* This is not right, but much easier than doing what is right. */
1591 w->start_at_line_beg = 0;
1592 if (NILP (noforce))
1593 w->force_start = 1;
1594 w->update_mode_line = 1;
1595 if (w != XWINDOW (selected_window))
1596 /* Enforce full redisplay. FIXME: make it more selective. */
1597 windows_or_buffers_changed++;
1599 return pos;
1602 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1603 Spos_visible_in_window_p, 0, 3, 0,
1604 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1605 WINDOW must be a live window and defaults to the selected one.
1607 Return nil if that position is scrolled vertically out of view. If a
1608 character is only partially visible, nil is returned, unless the
1609 optional argument PARTIALLY is non-nil. If POS is only out of view
1610 because of horizontal scrolling, return non-nil. If POS is t, it
1611 specifies the position of the last visible glyph in WINDOW. POS
1612 defaults to point in WINDOW; WINDOW defaults to the selected window.
1614 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
1615 the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
1616 where X and Y are the pixel coordinates relative to the top left corner
1617 of the window. The remaining elements are omitted if the character after
1618 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1619 off-window at the top and bottom of the screen line ("row") containing
1620 POS, ROWH is the visible height of that row, and VPOS is the row number
1621 \(zero-based). */)
1622 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1624 register struct window *w;
1625 register EMACS_INT posint;
1626 register struct buffer *buf;
1627 struct text_pos top;
1628 Lisp_Object in_window = Qnil;
1629 int rtop, rbot, rowh, vpos, fully_p = 1;
1630 int x, y;
1632 w = decode_live_window (window);
1633 buf = XBUFFER (w->contents);
1634 SET_TEXT_POS_FROM_MARKER (top, w->start);
1636 if (EQ (pos, Qt))
1637 posint = -1;
1638 else if (!NILP (pos))
1640 CHECK_NUMBER_COERCE_MARKER (pos);
1641 posint = XINT (pos);
1643 else if (w == XWINDOW (selected_window))
1644 posint = PT;
1645 else
1646 posint = marker_position (w->pointm);
1648 /* If position is above window start or outside buffer boundaries,
1649 or if window start is out of range, position is not visible. */
1650 if ((EQ (pos, Qt)
1651 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
1652 && CHARPOS (top) >= BUF_BEGV (buf)
1653 && CHARPOS (top) <= BUF_ZV (buf)
1654 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
1655 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
1656 in_window = Qt;
1658 if (!NILP (in_window) && !NILP (partially))
1660 Lisp_Object part = Qnil;
1661 if (!fully_p)
1662 part = list4i (rtop, rbot, rowh, vpos);
1663 in_window = Fcons (make_number (x),
1664 Fcons (make_number (y), part));
1667 return in_window;
1670 DEFUN ("window-line-height", Fwindow_line_height,
1671 Swindow_line_height, 0, 2, 0,
1672 doc: /* Return height in pixels of text line LINE in window WINDOW.
1673 WINDOW must be a live window and defaults to the selected one.
1675 Return height of current line if LINE is omitted or nil. Return height of
1676 header or mode line if LINE is `header-line' or `mode-line'.
1677 Otherwise, LINE is a text line number starting from 0. A negative number
1678 counts from the end of the window.
1680 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
1681 in pixels of the visible part of the line, VPOS and YPOS are the
1682 vertical position in lines and pixels of the line, relative to the top
1683 of the first text line, and OFFBOT is the number of off-window pixels at
1684 the bottom of the text line. If there are off-window pixels at the top
1685 of the (first) text line, YPOS is negative.
1687 Return nil if window display is not up-to-date. In that case, use
1688 `pos-visible-in-window-p' to obtain the information. */)
1689 (Lisp_Object line, Lisp_Object window)
1691 register struct window *w;
1692 register struct buffer *b;
1693 struct glyph_row *row, *end_row;
1694 int max_y, crop, i;
1695 EMACS_INT n;
1697 w = decode_live_window (window);
1699 if (noninteractive || w->pseudo_window_p)
1700 return Qnil;
1702 CHECK_BUFFER (w->contents);
1703 b = XBUFFER (w->contents);
1705 /* Fail if current matrix is not up-to-date. */
1706 if (!w->window_end_valid
1707 || windows_or_buffers_changed
1708 || b->clip_changed
1709 || b->prevent_redisplay_optimizations_p
1710 || window_outdated (w))
1711 return Qnil;
1713 if (NILP (line))
1715 i = w->cursor.vpos;
1716 if (i < 0 || i >= w->current_matrix->nrows
1717 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
1718 return Qnil;
1719 max_y = window_text_bottom_y (w);
1720 goto found_row;
1723 if (EQ (line, Qheader_line))
1725 if (!WINDOW_WANTS_HEADER_LINE_P (w))
1726 return Qnil;
1727 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1728 return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
1731 if (EQ (line, Qmode_line))
1733 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1734 return (row->enabled_p ?
1735 list4i (row->height,
1736 0, /* not accurate */
1737 (WINDOW_HEADER_LINE_HEIGHT (w)
1738 + window_text_bottom_y (w)),
1740 : Qnil);
1743 CHECK_NUMBER (line);
1744 n = XINT (line);
1746 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1747 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
1748 max_y = window_text_bottom_y (w);
1749 i = 0;
1751 while ((n < 0 || i < n)
1752 && row <= end_row && row->enabled_p
1753 && row->y + row->height < max_y)
1754 row++, i++;
1756 if (row > end_row || !row->enabled_p)
1757 return Qnil;
1759 if (++n < 0)
1761 if (-n > i)
1762 return Qnil;
1763 row += n;
1764 i += n;
1767 found_row:
1768 crop = max (0, (row->y + row->height) - max_y);
1769 return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
1772 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1773 0, 1, 0,
1774 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1775 More precisely, return the value assigned by the last call of
1776 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1777 never called with WINDOW as its argument, or the value set by that
1778 function was internally reset since its last call. WINDOW must be a
1779 live window and defaults to the selected one.
1781 When a window is dedicated to its buffer, `display-buffer' will refrain
1782 from displaying another buffer in it. `get-lru-window' and
1783 `get-largest-window' treat dedicated windows specially.
1784 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1785 `kill-buffer' can delete a dedicated window and the containing frame.
1787 Functions like `set-window-buffer' may change the buffer displayed by a
1788 window, unless that window is "strongly" dedicated to its buffer, that
1789 is the value returned by `window-dedicated-p' is t. */)
1790 (Lisp_Object window)
1792 return decode_live_window (window)->dedicated;
1795 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1796 Sset_window_dedicated_p, 2, 2, 0,
1797 doc: /* Mark WINDOW as dedicated according to FLAG.
1798 WINDOW must be a live window and defaults to the selected one. FLAG
1799 non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
1800 mark WINDOW as non-dedicated. Return FLAG.
1802 When a window is dedicated to its buffer, `display-buffer' will refrain
1803 from displaying another buffer in it. `get-lru-window' and
1804 `get-largest-window' treat dedicated windows specially.
1805 `delete-windows-on', `replace-buffer-in-windows', `quit-window',
1806 `quit-restore-window' and `kill-buffer' can delete a dedicated window
1807 and the containing frame.
1809 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1810 its buffer. Functions like `set-window-buffer' may change the buffer
1811 displayed by a window, unless that window is strongly dedicated to its
1812 buffer. If and when `set-window-buffer' displays another buffer in a
1813 window, it also makes sure that the window is no more dedicated. */)
1814 (Lisp_Object window, Lisp_Object flag)
1816 wset_dedicated (decode_live_window (window), flag);
1817 return flag;
1820 DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
1821 0, 1, 0,
1822 doc: /* Return buffers previously shown in WINDOW.
1823 WINDOW must be a live window and defaults to the selected one.
1825 The return value is a list of elements (BUFFER WINDOW-START POS),
1826 where BUFFER is a buffer, WINDOW-START is the start position of the
1827 window for that buffer, and POS is a window-specific point value. */)
1828 (Lisp_Object window)
1830 return decode_live_window (window)->prev_buffers;
1833 DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
1834 Sset_window_prev_buffers, 2, 2, 0,
1835 doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
1836 WINDOW must be a live window and defaults to the selected one.
1838 PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS),
1839 where BUFFER is a buffer, WINDOW-START is the start position of the
1840 window for that buffer, and POS is a window-specific point value. */)
1841 (Lisp_Object window, Lisp_Object prev_buffers)
1843 wset_prev_buffers (decode_live_window (window), prev_buffers);
1844 return prev_buffers;
1847 DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
1848 0, 1, 0,
1849 doc: /* Return list of buffers recently re-shown in WINDOW.
1850 WINDOW must be a live window and defaults to the selected one. */)
1851 (Lisp_Object window)
1853 return decode_live_window (window)->next_buffers;
1856 DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
1857 Sset_window_next_buffers, 2, 2, 0,
1858 doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
1859 WINDOW must be a live window and defaults to the selected one.
1860 NEXT-BUFFERS should be a list of buffers. */)
1861 (Lisp_Object window, Lisp_Object next_buffers)
1863 wset_next_buffers (decode_live_window (window), next_buffers);
1864 return next_buffers;
1867 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1868 0, 1, 0,
1869 doc: /* Return the parameters of WINDOW and their values.
1870 WINDOW must be a valid window and defaults to the selected one. The
1871 return value is a list of elements of the form (PARAMETER . VALUE). */)
1872 (Lisp_Object window)
1874 return Fcopy_alist (decode_valid_window (window)->window_parameters);
1877 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1878 2, 2, 0,
1879 doc: /* Return WINDOW's value for PARAMETER.
1880 WINDOW can be any window and defaults to the selected one. */)
1881 (Lisp_Object window, Lisp_Object parameter)
1883 Lisp_Object result;
1885 result = Fassq (parameter, decode_any_window (window)->window_parameters);
1886 return CDR_SAFE (result);
1889 DEFUN ("set-window-parameter", Fset_window_parameter,
1890 Sset_window_parameter, 3, 3, 0,
1891 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1892 WINDOW can be any window and defaults to the selected one.
1893 Return VALUE. */)
1894 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
1896 register struct window *w = decode_any_window (window);
1897 Lisp_Object old_alist_elt;
1899 old_alist_elt = Fassq (parameter, w->window_parameters);
1900 if (NILP (old_alist_elt))
1901 wset_window_parameters
1902 (w, Fcons (Fcons (parameter, value), w->window_parameters));
1903 else
1904 Fsetcdr (old_alist_elt, value);
1905 return value;
1908 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1909 0, 1, 0,
1910 doc: /* Return the display-table that WINDOW is using.
1911 WINDOW must be a live window and defaults to the selected one. */)
1912 (Lisp_Object window)
1914 return decode_live_window (window)->display_table;
1917 /* Get the display table for use on window W. This is either W's
1918 display table or W's buffer's display table. Ignore the specified
1919 tables if they are not valid; if no valid table is specified,
1920 return 0. */
1922 struct Lisp_Char_Table *
1923 window_display_table (struct window *w)
1925 struct Lisp_Char_Table *dp = NULL;
1927 if (DISP_TABLE_P (w->display_table))
1928 dp = XCHAR_TABLE (w->display_table);
1929 else if (BUFFERP (w->contents))
1931 struct buffer *b = XBUFFER (w->contents);
1933 if (DISP_TABLE_P (BVAR (b, display_table)))
1934 dp = XCHAR_TABLE (BVAR (b, display_table));
1935 else if (DISP_TABLE_P (Vstandard_display_table))
1936 dp = XCHAR_TABLE (Vstandard_display_table);
1939 return dp;
1942 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1943 doc: /* Set WINDOW's display-table to TABLE.
1944 WINDOW must be a live window and defaults to the selected one. */)
1945 (register Lisp_Object window, Lisp_Object table)
1947 wset_display_table (decode_live_window (window), table);
1948 return table;
1951 /* Record info on buffer window W is displaying
1952 when it is about to cease to display that buffer. */
1953 static void
1954 unshow_buffer (register struct window *w)
1956 Lisp_Object buf = w->contents;
1957 struct buffer *b = XBUFFER (buf);
1959 eassert (b == XMARKER (w->pointm)->buffer);
1961 #if 0
1962 if (w == XWINDOW (selected_window)
1963 || ! EQ (buf, XWINDOW (selected_window)->contents))
1964 /* Do this except when the selected window's buffer
1965 is being removed from some other window. */
1966 #endif
1967 /* last_window_start records the start position that this buffer
1968 had in the last window to be disconnected from it.
1969 Now that this statement is unconditional,
1970 it is possible for the buffer to be displayed in the
1971 selected window, while last_window_start reflects another
1972 window which was recently showing the same buffer.
1973 Some people might say that might be a good thing. Let's see. */
1974 b->last_window_start = marker_position (w->start);
1976 /* Point in the selected window's buffer
1977 is actually stored in that buffer, and the window's pointm isn't used.
1978 So don't clobber point in that buffer. */
1979 if (! EQ (buf, XWINDOW (selected_window)->contents)
1980 /* Don't clobber point in current buffer either (this could be
1981 useful in connection with bug#12208).
1982 && XBUFFER (buf) != current_buffer */
1983 /* This line helps to fix Horsley's testbug.el bug. */
1984 && !(WINDOWP (BVAR (b, last_selected_window))
1985 && w != XWINDOW (BVAR (b, last_selected_window))
1986 && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->contents)))
1987 temp_set_point_both (b,
1988 clip_to_bounds (BUF_BEGV (b),
1989 marker_position (w->pointm),
1990 BUF_ZV (b)),
1991 clip_to_bounds (BUF_BEGV_BYTE (b),
1992 marker_byte_position (w->pointm),
1993 BUF_ZV_BYTE (b)));
1995 if (WINDOWP (BVAR (b, last_selected_window))
1996 && w == XWINDOW (BVAR (b, last_selected_window)))
1997 bset_last_selected_window (b, Qnil);
2000 /* Put NEW into the window structure in place of OLD. SETFLAG zero
2001 means change window structure only. Otherwise store geometry and
2002 other settings as well. */
2003 static void
2004 replace_window (Lisp_Object old, Lisp_Object new, int setflag)
2006 register Lisp_Object tem;
2007 register struct window *o = XWINDOW (old), *n = XWINDOW (new);
2009 /* If OLD is its frame's root window, then NEW is the new
2010 root window for that frame. */
2011 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
2012 fset_root_window (XFRAME (o->frame), new);
2014 if (setflag)
2016 n->left_col = o->left_col;
2017 n->top_line = o->top_line;
2018 n->total_cols = o->total_cols;
2019 n->total_lines = o->total_lines;
2020 wset_normal_cols (n, o->normal_cols);
2021 wset_normal_cols (o, make_float (1.0));
2022 wset_normal_lines (n, o->normal_lines);
2023 wset_normal_lines (o, make_float (1.0));
2024 n->desired_matrix = n->current_matrix = 0;
2025 n->vscroll = 0;
2026 memset (&n->cursor, 0, sizeof (n->cursor));
2027 memset (&n->last_cursor, 0, sizeof (n->last_cursor));
2028 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
2029 n->phys_cursor_type = -1;
2030 n->phys_cursor_width = -1;
2031 n->must_be_updated_p = 0;
2032 n->pseudo_window_p = 0;
2033 wset_window_end_vpos (n, make_number (0));
2034 wset_window_end_pos (n, make_number (0));
2035 n->window_end_valid = 0;
2038 tem = o->next;
2039 wset_next (n, tem);
2040 if (!NILP (tem))
2041 wset_prev (XWINDOW (tem), new);
2043 tem = o->prev;
2044 wset_prev (n, tem);
2045 if (!NILP (tem))
2046 wset_next (XWINDOW (tem), new);
2048 tem = o->parent;
2049 wset_parent (n, tem);
2050 if (!NILP (tem) && EQ (XWINDOW (tem)->contents, old))
2051 wset_combination (XWINDOW (tem), XWINDOW (tem)->horizontal, new);
2054 /* If window WINDOW and its parent window are iso-combined, merge
2055 WINDOW's children into those of its parent window and mark WINDOW as
2056 deleted. */
2058 static void
2059 recombine_windows (Lisp_Object window)
2061 struct window *w, *p, *c;
2062 Lisp_Object parent, child;
2063 bool horflag;
2065 w = XWINDOW (window);
2066 parent = w->parent;
2067 if (!NILP (parent) && NILP (w->combination_limit))
2069 p = XWINDOW (parent);
2070 if (WINDOWP (p->contents) && WINDOWP (w->contents)
2071 && p->horizontal == w->horizontal)
2072 /* WINDOW and PARENT are both either a vertical or a horizontal
2073 combination. */
2075 horflag = WINDOW_HORIZONTAL_COMBINATION_P (w);
2076 child = w->contents;
2077 c = XWINDOW (child);
2079 /* Splice WINDOW's children into its parent's children and
2080 assign new normal sizes. */
2081 if (NILP (w->prev))
2082 wset_combination (p, horflag, child);
2083 else
2085 wset_prev (c, w->prev);
2086 wset_next (XWINDOW (w->prev), child);
2089 while (c)
2091 wset_parent (c, parent);
2093 if (horflag)
2094 wset_normal_cols (c,
2095 make_float ((double) c->total_cols
2096 / (double) p->total_cols));
2097 else
2098 wset_normal_lines (c,
2099 make_float ((double) c->total_lines
2100 / (double) p->total_lines));
2102 if (NILP (c->next))
2104 if (!NILP (w->next))
2106 wset_next (c, w->next);
2107 wset_prev (XWINDOW (c->next), child);
2110 c = 0;
2112 else
2114 child = c->next;
2115 c = XWINDOW (child);
2119 /* WINDOW can be deleted now. */
2120 wset_combination (w, 0, Qnil);
2125 /* If WINDOW can be deleted, delete it. */
2126 static void
2127 delete_deletable_window (Lisp_Object window)
2129 if (!NILP (call1 (Qwindow_deletable_p, window)))
2130 call1 (Qdelete_window, window);
2133 /***********************************************************************
2134 Window List
2135 ***********************************************************************/
2137 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
2138 pointer. This is a callback function for foreach_window, used in
2139 the window_list function. */
2141 static int
2142 add_window_to_list (struct window *w, void *user_data)
2144 Lisp_Object *list = user_data;
2145 Lisp_Object window;
2146 XSETWINDOW (window, w);
2147 *list = Fcons (window, *list);
2148 return 1;
2152 /* Return a list of all windows, for use by next_window. If
2153 Vwindow_list is a list, return that list. Otherwise, build a new
2154 list, cache it in Vwindow_list, and return that. */
2156 static Lisp_Object
2157 window_list (void)
2159 if (!CONSP (Vwindow_list))
2161 Lisp_Object tail, frame;
2163 Vwindow_list = Qnil;
2164 FOR_EACH_FRAME (tail, frame)
2166 Lisp_Object args[2];
2168 /* We are visiting windows in canonical order, and add
2169 new windows at the front of args[1], which means we
2170 have to reverse this list at the end. */
2171 args[1] = Qnil;
2172 foreach_window (XFRAME (frame), add_window_to_list, &args[1]);
2173 args[0] = Vwindow_list;
2174 args[1] = Fnreverse (args[1]);
2175 Vwindow_list = Fnconc (2, args);
2179 return Vwindow_list;
2183 /* Value is non-zero if WINDOW satisfies the constraints given by
2184 OWINDOW, MINIBUF and ALL_FRAMES.
2186 MINIBUF t means WINDOW may be minibuffer windows.
2187 `lambda' means WINDOW may not be a minibuffer window.
2188 a window means a specific minibuffer window
2190 ALL_FRAMES t means search all frames,
2191 nil means search just current frame,
2192 `visible' means search just visible frames on the
2193 current terminal,
2194 0 means search visible and iconified frames on the
2195 current terminal,
2196 a window means search the frame that window belongs to,
2197 a frame means consider windows on that frame, only. */
2199 static bool
2200 candidate_window_p (Lisp_Object window, Lisp_Object owindow,
2201 Lisp_Object minibuf, Lisp_Object all_frames)
2203 struct window *w = XWINDOW (window);
2204 struct frame *f = XFRAME (w->frame);
2205 bool candidate_p = 1;
2207 if (!BUFFERP (w->contents))
2208 candidate_p = 0;
2209 else if (MINI_WINDOW_P (w)
2210 && (EQ (minibuf, Qlambda)
2211 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
2213 /* If MINIBUF is `lambda' don't consider any mini-windows.
2214 If it is a window, consider only that one. */
2215 candidate_p = 0;
2217 else if (EQ (all_frames, Qt))
2218 candidate_p = 1;
2219 else if (NILP (all_frames))
2221 eassert (WINDOWP (owindow));
2222 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
2224 else if (EQ (all_frames, Qvisible))
2226 candidate_p = FRAME_VISIBLE_P (f)
2227 && (FRAME_TERMINAL (XFRAME (w->frame))
2228 == FRAME_TERMINAL (XFRAME (selected_frame)));
2231 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2233 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2234 #ifdef HAVE_X_WINDOWS
2235 /* Yuck!! If we've just created the frame and the
2236 window-manager requested the user to place it
2237 manually, the window may still not be considered
2238 `visible'. I'd argue it should be at least
2239 something like `iconified', but don't know how to do
2240 that yet. --Stef */
2241 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
2242 && !f->output_data.x->has_been_visible)
2243 #endif
2245 && (FRAME_TERMINAL (XFRAME (w->frame))
2246 == FRAME_TERMINAL (XFRAME (selected_frame)));
2248 else if (WINDOWP (all_frames))
2249 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
2250 || EQ (XWINDOW (all_frames)->frame, w->frame)
2251 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
2252 else if (FRAMEP (all_frames))
2253 candidate_p = EQ (all_frames, w->frame);
2255 return candidate_p;
2259 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
2260 Fwindow_list. See candidate_window_p for the meaning of WINDOW,
2261 MINIBUF, and ALL_FRAMES. */
2263 static void
2264 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
2266 struct window *w = decode_live_window (*window);
2268 XSETWINDOW (*window, w);
2269 /* MINIBUF nil may or may not include minibuffers. Decide if it
2270 does. */
2271 if (NILP (*minibuf))
2272 *minibuf = minibuf_level ? minibuf_window : Qlambda;
2273 else if (!EQ (*minibuf, Qt))
2274 *minibuf = Qlambda;
2276 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
2277 => count none of them, or a specific minibuffer window (the
2278 active one) to count. */
2280 /* ALL_FRAMES nil doesn't specify which frames to include. */
2281 if (NILP (*all_frames))
2282 *all_frames
2283 = (!EQ (*minibuf, Qlambda)
2284 ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame))
2285 : Qnil);
2286 else if (EQ (*all_frames, Qvisible))
2288 else if (EQ (*all_frames, make_number (0)))
2290 else if (FRAMEP (*all_frames))
2292 else if (!EQ (*all_frames, Qt))
2293 *all_frames = Qnil;
2297 /* Return the next or previous window of WINDOW in cyclic ordering
2298 of windows. NEXT_P non-zero means return the next window. See the
2299 documentation string of next-window for the meaning of MINIBUF and
2300 ALL_FRAMES. */
2302 static Lisp_Object
2303 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
2305 decode_next_window_args (&window, &minibuf, &all_frames);
2307 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
2308 return the first window on the frame. */
2309 if (FRAMEP (all_frames)
2310 && !EQ (all_frames, XWINDOW (window)->frame))
2311 return Fframe_first_window (all_frames);
2313 if (next_p)
2315 Lisp_Object list;
2317 /* Find WINDOW in the list of all windows. */
2318 list = Fmemq (window, window_list ());
2320 /* Scan forward from WINDOW to the end of the window list. */
2321 if (CONSP (list))
2322 for (list = XCDR (list); CONSP (list); list = XCDR (list))
2323 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2324 break;
2326 /* Scan from the start of the window list up to WINDOW. */
2327 if (!CONSP (list))
2328 for (list = Vwindow_list;
2329 CONSP (list) && !EQ (XCAR (list), window);
2330 list = XCDR (list))
2331 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2332 break;
2334 if (CONSP (list))
2335 window = XCAR (list);
2337 else
2339 Lisp_Object candidate, list;
2341 /* Scan through the list of windows for candidates. If there are
2342 candidate windows in front of WINDOW, the last one of these
2343 is the one we want. If there are candidates following WINDOW
2344 in the list, again the last one of these is the one we want. */
2345 candidate = Qnil;
2346 for (list = window_list (); CONSP (list); list = XCDR (list))
2348 if (EQ (XCAR (list), window))
2350 if (WINDOWP (candidate))
2351 break;
2353 else if (candidate_window_p (XCAR (list), window, minibuf,
2354 all_frames))
2355 candidate = XCAR (list);
2358 if (WINDOWP (candidate))
2359 window = candidate;
2362 return window;
2366 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2367 doc: /* Return live window after WINDOW in the cyclic ordering of windows.
2368 WINDOW must be a live window and defaults to the selected one. The
2369 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2370 consider.
2372 MINIBUF nil or omitted means consider the minibuffer window only if the
2373 minibuffer is active. MINIBUF t means consider the minibuffer window
2374 even if the minibuffer is not active. Any other value means do not
2375 consider the minibuffer window even if the minibuffer is active.
2377 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2378 plus the minibuffer window if specified by the MINIBUF argument. If the
2379 minibuffer counts, consider all windows on all frames that share that
2380 minibuffer too. The following non-nil values of ALL-FRAMES have special
2381 meanings:
2383 - t means consider all windows on all existing frames.
2385 - `visible' means consider all windows on all visible frames.
2387 - 0 (the number zero) means consider all windows on all visible and
2388 iconified frames.
2390 - A frame means consider all windows on that frame only.
2392 Anything else means consider all windows on WINDOW's frame and no
2393 others.
2395 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2396 `next-window' to iterate through the entire cycle of acceptable
2397 windows, eventually ending up back at the window you started with.
2398 `previous-window' traverses the same cycle, in the reverse order. */)
2399 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2401 return next_window (window, minibuf, all_frames, 1);
2405 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2406 doc: /* Return live window before WINDOW in the cyclic ordering of windows.
2407 WINDOW must be a live window and defaults to the selected one. The
2408 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2409 consider.
2411 MINIBUF nil or omitted means consider the minibuffer window only if the
2412 minibuffer is active. MINIBUF t means consider the minibuffer window
2413 even if the minibuffer is not active. Any other value means do not
2414 consider the minibuffer window even if the minibuffer is active.
2416 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2417 plus the minibuffer window if specified by the MINIBUF argument. If the
2418 minibuffer counts, consider all windows on all frames that share that
2419 minibuffer too. The following non-nil values of ALL-FRAMES have special
2420 meanings:
2422 - t means consider all windows on all existing frames.
2424 - `visible' means consider all windows on all visible frames.
2426 - 0 (the number zero) means consider all windows on all visible and
2427 iconified frames.
2429 - A frame means consider all windows on that frame only.
2431 Anything else means consider all windows on WINDOW's frame and no
2432 others.
2434 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2435 use `previous-window' to iterate through the entire cycle of
2436 acceptable windows, eventually ending up back at the window you
2437 started with. `next-window' traverses the same cycle, in the
2438 reverse order. */)
2439 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2441 return next_window (window, minibuf, all_frames, 0);
2445 /* Return a list of windows in cyclic ordering. Arguments are like
2446 for `next-window'. */
2448 static Lisp_Object
2449 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2451 Lisp_Object tail, list, rest;
2453 decode_next_window_args (&window, &minibuf, &all_frames);
2454 list = Qnil;
2456 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2457 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2458 list = Fcons (XCAR (tail), list);
2460 /* Rotate the list to start with WINDOW. */
2461 list = Fnreverse (list);
2462 rest = Fmemq (window, list);
2463 if (!NILP (rest) && !EQ (rest, list))
2465 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2467 XSETCDR (tail, Qnil);
2468 list = nconc2 (rest, list);
2470 return list;
2474 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2475 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2476 FRAME nil or omitted means use the selected frame.
2477 WINDOW nil or omitted means use the window selected within FRAME.
2478 MINIBUF t means include the minibuffer window, even if it isn't active.
2479 MINIBUF nil or omitted means include the minibuffer window only
2480 if it's active.
2481 MINIBUF neither nil nor t means never include the minibuffer window. */)
2482 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2484 if (NILP (window))
2485 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2486 CHECK_WINDOW (window);
2487 if (NILP (frame))
2488 frame = selected_frame;
2490 if (!EQ (frame, XWINDOW (window)->frame))
2491 error ("Window is on a different frame");
2493 return window_list_1 (window, minibuf, frame);
2497 DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2498 doc: /* Return a list of all live windows.
2499 WINDOW specifies the first window to list and defaults to the selected
2500 window.
2502 Optional argument MINIBUF nil or omitted means consider the minibuffer
2503 window only if the minibuffer is active. MINIBUF t means consider the
2504 minibuffer window even if the minibuffer is not active. Any other value
2505 means do not consider the minibuffer window even if the minibuffer is
2506 active.
2508 Optional argument ALL-FRAMES nil or omitted means consider all windows
2509 on WINDOW's frame, plus the minibuffer window if specified by the
2510 MINIBUF argument. If the minibuffer counts, consider all windows on all
2511 frames that share that minibuffer too. The following non-nil values of
2512 ALL-FRAMES have special meanings:
2514 - t means consider all windows on all existing frames.
2516 - `visible' means consider all windows on all visible frames.
2518 - 0 (the number zero) means consider all windows on all visible and
2519 iconified frames.
2521 - A frame means consider all windows on that frame only.
2523 Anything else means consider all windows on WINDOW's frame and no
2524 others.
2526 If WINDOW is not on the list of windows returned, some other window will
2527 be listed first but no error is signaled. */)
2528 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2530 return window_list_1 (window, minibuf, all_frames);
2533 /* Look at all windows, performing an operation specified by TYPE
2534 with argument OBJ.
2535 If FRAMES is Qt, look at all frames;
2536 Qnil, look at just the selected frame;
2537 Qvisible, look at visible frames;
2538 a frame, just look at windows on that frame.
2539 If MINI is non-zero, perform the operation on minibuffer windows too. */
2541 enum window_loop
2543 WINDOW_LOOP_UNUSED,
2544 GET_BUFFER_WINDOW, /* Arg is buffer */
2545 REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
2546 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2547 CHECK_ALL_WINDOWS /* Arg is ignored */
2550 static Lisp_Object
2551 window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
2553 Lisp_Object window, windows, best_window, frame_arg;
2554 int frame_best_window_flag = 0;
2555 struct frame *f;
2556 struct gcpro gcpro1;
2558 /* If we're only looping through windows on a particular frame,
2559 frame points to that frame. If we're looping through windows
2560 on all frames, frame is 0. */
2561 if (FRAMEP (frames))
2562 f = XFRAME (frames);
2563 else if (NILP (frames))
2564 f = SELECTED_FRAME ();
2565 else
2566 f = NULL;
2568 if (f)
2569 frame_arg = Qlambda;
2570 else if (EQ (frames, make_number (0)))
2571 frame_arg = frames;
2572 else if (EQ (frames, Qvisible))
2573 frame_arg = frames;
2574 else
2575 frame_arg = Qt;
2577 /* frame_arg is Qlambda to stick to one frame,
2578 Qvisible to consider all visible frames,
2579 or Qt otherwise. */
2581 /* Pick a window to start with. */
2582 if (WINDOWP (obj))
2583 window = obj;
2584 else if (f)
2585 window = FRAME_SELECTED_WINDOW (f);
2586 else
2587 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2589 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2590 GCPRO1 (windows);
2591 best_window = Qnil;
2593 for (; CONSP (windows); windows = XCDR (windows))
2595 struct window *w;
2597 window = XCAR (windows);
2598 w = XWINDOW (window);
2600 /* Note that we do not pay attention here to whether the frame
2601 is visible, since Fwindow_list skips non-visible frames if
2602 that is desired, under the control of frame_arg. */
2603 if (!MINI_WINDOW_P (w)
2604 /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
2605 consider all windows. */
2606 || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
2607 || (mini && minibuf_level > 0))
2608 switch (type)
2610 case GET_BUFFER_WINDOW:
2611 if (EQ (w->contents, obj)
2612 /* Don't find any minibuffer window except the one that
2613 is currently in use. */
2614 && (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
2616 if (EQ (window, selected_window))
2617 /* Preferably return the selected window. */
2618 RETURN_UNGCPRO (window);
2619 else if (EQ (XWINDOW (window)->frame, selected_frame)
2620 && !frame_best_window_flag)
2621 /* Prefer windows on the current frame (but don't
2622 choose another one if we have one already). */
2624 best_window = window;
2625 frame_best_window_flag = 1;
2627 else if (NILP (best_window))
2628 best_window = window;
2630 break;
2632 case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
2633 /* We could simply check whether the buffer shown by window
2634 is live, and show another buffer in case it isn't. */
2635 if (EQ (w->contents, obj))
2637 /* Undedicate WINDOW. */
2638 wset_dedicated (w, Qnil);
2639 /* Make WINDOW show the buffer returned by
2640 other_buffer_safely, don't run any hooks. */
2641 set_window_buffer
2642 (window, other_buffer_safely (w->contents), 0, 0);
2643 /* If WINDOW is the selected window, make its buffer
2644 current. But do so only if the window shows the
2645 current buffer (Bug#6454). */
2646 if (EQ (window, selected_window)
2647 && XBUFFER (w->contents) == current_buffer)
2648 Fset_buffer (w->contents);
2650 break;
2652 case REDISPLAY_BUFFER_WINDOWS:
2653 if (EQ (w->contents, obj))
2655 mark_window_display_accurate (window, 0);
2656 w->update_mode_line = 1;
2657 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2658 ++update_mode_lines;
2659 best_window = window;
2661 break;
2663 /* Check for a leaf window that has a killed buffer
2664 or broken markers. */
2665 case CHECK_ALL_WINDOWS:
2666 if (BUFFERP (w->contents))
2668 struct buffer *b = XBUFFER (w->contents);
2670 if (!BUFFER_LIVE_P (b))
2671 emacs_abort ();
2672 if (!MARKERP (w->start) || XMARKER (w->start)->buffer != b)
2673 emacs_abort ();
2674 if (!MARKERP (w->pointm) || XMARKER (w->pointm)->buffer != b)
2675 emacs_abort ();
2677 break;
2679 case WINDOW_LOOP_UNUSED:
2680 break;
2684 UNGCPRO;
2685 return best_window;
2688 /* Used for debugging. Abort if any window has a dead buffer. */
2690 extern void check_all_windows (void) EXTERNALLY_VISIBLE;
2691 void
2692 check_all_windows (void)
2694 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2697 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2698 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2699 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
2700 the current buffer.
2702 The optional argument ALL-FRAMES specifies the frames to consider:
2704 - t means consider all windows on all existing frames.
2706 - `visible' means consider all windows on all visible frames.
2708 - 0 (the number zero) means consider all windows on all visible
2709 and iconified frames.
2711 - A frame means consider all windows on that frame only.
2713 Any other value of ALL-FRAMES means consider all windows on the
2714 selected frame and no others. */)
2715 (Lisp_Object buffer_or_name, Lisp_Object all_frames)
2717 Lisp_Object buffer;
2719 if (NILP (buffer_or_name))
2720 buffer = Fcurrent_buffer ();
2721 else
2722 buffer = Fget_buffer (buffer_or_name);
2724 if (BUFFERP (buffer))
2725 return window_loop (GET_BUFFER_WINDOW, buffer, 1, all_frames);
2726 else
2727 return Qnil;
2730 static Lisp_Object
2731 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore)
2733 return call4 (Qwindow_resize_root_window, window, delta, horizontal, ignore);
2737 DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
2738 Sdelete_other_windows_internal, 0, 2, "",
2739 doc: /* Make WINDOW fill its frame.
2740 Only the frame WINDOW is on is affected. WINDOW must be a valid window
2741 and defaults to the selected one.
2743 Optional argument ROOT, if non-nil, must specify an internal window such
2744 that WINDOW is in its window subtree. If this is the case, replace ROOT
2745 by WINDOW and leave alone any windows not part of ROOT's subtree.
2747 When WINDOW is live try to reduce display jumps by keeping the text
2748 previously visible in WINDOW in the same place on the frame. Doing this
2749 depends on the value of (window-start WINDOW), so if calling this
2750 function in a program gives strange scrolling, make sure the
2751 window-start value is reasonable when this function is called. */)
2752 (Lisp_Object window, Lisp_Object root)
2754 struct window *w, *r, *s;
2755 struct frame *f;
2756 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
2757 ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0);
2758 int top IF_LINT (= 0), new_top, resize_failed;
2760 w = decode_valid_window (window);
2761 XSETWINDOW (window, w);
2762 f = XFRAME (w->frame);
2764 if (NILP (root))
2765 /* ROOT is the frame's root window. */
2767 root = FRAME_ROOT_WINDOW (f);
2768 r = XWINDOW (root);
2770 else
2771 /* ROOT must be an ancestor of WINDOW. */
2773 r = decode_valid_window (root);
2774 pwindow = XWINDOW (window)->parent;
2775 while (!NILP (pwindow))
2776 if (EQ (pwindow, root))
2777 break;
2778 else
2779 pwindow = XWINDOW (pwindow)->parent;
2780 if (!EQ (pwindow, root))
2781 error ("Specified root is not an ancestor of specified window");
2784 if (EQ (window, root))
2785 /* A noop. */
2786 return Qnil;
2787 /* I don't understand the "top > 0" part below. If we deal with a
2788 standalone minibuffer it would have been caught by the preceding
2789 test. */
2790 else if (MINI_WINDOW_P (w)) /* && top > 0) */
2791 error ("Can't expand minibuffer to full frame");
2793 if (BUFFERP (w->contents))
2795 startpos = marker_position (w->start);
2796 startbyte = marker_byte_position (w->start);
2797 top = WINDOW_TOP_EDGE_LINE (w)
2798 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2799 /* Make sure WINDOW is the frame's selected window. */
2800 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
2802 if (EQ (selected_frame, w->frame))
2803 Fselect_window (window, Qnil);
2804 else
2805 fset_selected_window (f, window);
2808 else
2810 /* See if the frame's selected window is a part of the window
2811 subtree rooted at WINDOW, by finding all the selected window's
2812 parents and comparing each one with WINDOW. If it isn't we
2813 need a new selected window for this frame. */
2814 swindow = FRAME_SELECTED_WINDOW (f);
2815 while (1)
2817 pwindow = swindow;
2818 while (!NILP (pwindow) && !EQ (window, pwindow))
2819 pwindow = XWINDOW (pwindow)->parent;
2821 if (EQ (window, pwindow))
2822 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
2823 as the new selected window. */
2824 break;
2825 else
2826 /* Else try the previous window of SWINDOW. */
2827 swindow = Fprevious_window (swindow, Qlambda, Qnil);
2830 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
2832 if (EQ (selected_frame, w->frame))
2833 Fselect_window (swindow, Qnil);
2834 else
2835 fset_selected_window (f, swindow);
2839 block_input ();
2840 if (!FRAME_INITIAL_P (f))
2842 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
2844 /* We are going to free the glyph matrices of WINDOW, and with
2845 that we might lose any information about glyph rows that have
2846 some of their glyphs highlighted in mouse face. (These rows
2847 are marked with a non-zero mouse_face_p flag.) If WINDOW
2848 indeed has some glyphs highlighted in mouse face, signal to
2849 frame's up-to-date hook that mouse highlight was overwritten,
2850 so that it will arrange for redisplaying the highlight. */
2851 if (EQ (hlinfo->mouse_face_window, window))
2853 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
2854 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
2855 hlinfo->mouse_face_window = Qnil;
2858 free_window_matrices (r);
2860 windows_or_buffers_changed++;
2861 Vwindow_list = Qnil;
2862 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
2863 resize_failed = 0;
2865 if (!WINDOW_LEAF_P (w))
2867 /* Resize child windows vertically. */
2868 XSETINT (delta, r->total_lines - w->total_lines);
2869 w->top_line = r->top_line;
2870 resize_root_window (window, delta, Qnil, Qnil);
2871 if (window_resize_check (w, 0))
2872 window_resize_apply (w, 0);
2873 else
2875 resize_root_window (window, delta, Qnil, Qt);
2876 if (window_resize_check (w, 0))
2877 window_resize_apply (w, 0);
2878 else
2879 resize_failed = 1;
2882 /* Resize child windows horizontally. */
2883 if (!resize_failed)
2885 w->left_col = r->left_col;
2886 XSETINT (delta, r->total_cols - w->total_cols);
2887 resize_root_window (window, delta, Qt, Qnil);
2888 if (window_resize_check (w, 1))
2889 window_resize_apply (w, 1);
2890 else
2892 resize_root_window (window, delta, Qt, Qt);
2893 if (window_resize_check (w, 1))
2894 window_resize_apply (w, 1);
2895 else
2896 resize_failed = 1;
2900 if (resize_failed)
2901 /* Play safe, if we still can ... */
2903 window = swindow;
2904 w = XWINDOW (window);
2908 /* Cleanly unlink WINDOW from window-tree. */
2909 if (!NILP (w->prev))
2910 /* Get SIBLING above (on the left of) WINDOW. */
2912 sibling = w->prev;
2913 s = XWINDOW (sibling);
2914 wset_next (s, w->next);
2915 if (!NILP (s->next))
2916 wset_prev (XWINDOW (s->next), sibling);
2918 else
2919 /* Get SIBLING below (on the right of) WINDOW. */
2921 sibling = w->next;
2922 s = XWINDOW (sibling);
2923 wset_prev (s, Qnil);
2924 wset_combination (XWINDOW (w->parent),
2925 XWINDOW (w->parent)->horizontal, sibling);
2928 /* Delete ROOT and all child windows of ROOT. */
2929 if (WINDOWP (r->contents))
2931 delete_all_child_windows (r->contents);
2932 wset_combination (r, 0, Qnil);
2935 replace_window (root, window, 1);
2937 /* This must become SWINDOW anyway ....... */
2938 if (BUFFERP (w->contents) && !resize_failed)
2940 /* Try to minimize scrolling, by setting the window start to the
2941 point will cause the text at the old window start to be at the
2942 same place on the frame. But don't try to do this if the
2943 window start is outside the visible portion (as might happen
2944 when the display is not current, due to typeahead). */
2945 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2946 if (new_top != top
2947 && startpos >= BUF_BEGV (XBUFFER (w->contents))
2948 && startpos <= BUF_ZV (XBUFFER (w->contents)))
2950 struct position pos;
2951 struct buffer *obuf = current_buffer;
2953 Fset_buffer (w->contents);
2954 /* This computation used to temporarily move point, but that
2955 can have unwanted side effects due to text properties. */
2956 pos = *vmotion (startpos, startbyte, -top, w);
2958 set_marker_both (w->start, w->contents, pos.bufpos, pos.bytepos);
2959 w->window_end_valid = 0;
2960 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
2961 || FETCH_BYTE (pos.bytepos - 1) == '\n');
2962 /* We need to do this, so that the window-scroll-functions
2963 get called. */
2964 w->optional_new_start = 1;
2966 set_buffer_internal (obuf);
2970 adjust_glyphs (f);
2971 unblock_input ();
2973 run_window_configuration_change_hook (f);
2975 return Qnil;
2979 void
2980 replace_buffer_in_windows (Lisp_Object buffer)
2982 call1 (Qreplace_buffer_in_windows, buffer);
2985 /* If BUFFER is shown in a window, safely replace it with some other
2986 buffer in all windows of all frames, even those on other keyboards. */
2988 void
2989 replace_buffer_in_windows_safely (Lisp_Object buffer)
2991 if (buffer_window_count (XBUFFER (buffer)))
2993 Lisp_Object tail, frame;
2995 /* A single call to window_loop won't do the job because it only
2996 considers frames on the current keyboard. So loop manually over
2997 frames, and handle each one. */
2998 FOR_EACH_FRAME (tail, frame)
2999 window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
3003 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3004 minimum allowable size. */
3006 void
3007 check_frame_size (struct frame *frame, int *rows, int *cols)
3009 /* For height, we have to see:
3010 how many windows the frame has at minimum (one or two),
3011 and whether it has a menu bar or other special stuff at the top. */
3012 int min_height
3013 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
3014 ? MIN_SAFE_WINDOW_HEIGHT
3015 : 2 * MIN_SAFE_WINDOW_HEIGHT);
3017 if (FRAME_TOP_MARGIN (frame) > 0)
3018 min_height += FRAME_TOP_MARGIN (frame);
3020 if (*rows < min_height)
3021 *rows = min_height;
3022 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3023 *cols = MIN_SAFE_WINDOW_WIDTH;
3026 /* Adjust the margins of window W if text area is too small.
3027 Return 1 if window width is ok after adjustment; 0 if window
3028 is still too narrow. */
3030 static int
3031 adjust_window_margins (struct window *w)
3033 int box_cols = (WINDOW_TOTAL_COLS (w)
3034 - WINDOW_FRINGE_COLS (w)
3035 - WINDOW_SCROLL_BAR_COLS (w));
3036 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
3037 + WINDOW_RIGHT_MARGIN_COLS (w));
3039 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
3040 return 1;
3042 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
3043 return 0;
3045 /* Window's text area is too narrow, but reducing the window
3046 margins will fix that. */
3047 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
3048 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
3050 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
3051 w->left_margin_cols = w->right_margin_cols = margin_cols / 2;
3052 else
3053 w->right_margin_cols = margin_cols;
3055 else
3056 w->left_margin_cols = margin_cols;
3057 return 1;
3060 /* The following three routines are needed for running a window's
3061 configuration change hook. */
3062 static void
3063 run_funs (Lisp_Object funs)
3065 for (; CONSP (funs); funs = XCDR (funs))
3066 if (!EQ (XCAR (funs), Qt))
3067 call0 (XCAR (funs));
3070 static void
3071 select_window_norecord (Lisp_Object window)
3073 if (WINDOW_LIVE_P (window))
3074 Fselect_window (window, Qt);
3077 static void
3078 select_frame_norecord (Lisp_Object frame)
3080 if (FRAME_LIVE_P (XFRAME (frame)))
3081 Fselect_frame (frame, Qt);
3084 void
3085 run_window_configuration_change_hook (struct frame *f)
3087 ptrdiff_t count = SPECPDL_INDEX ();
3088 Lisp_Object frame, global_wcch
3089 = Fdefault_value (Qwindow_configuration_change_hook);
3090 XSETFRAME (frame, f);
3092 if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code))
3093 return;
3095 /* Use the right buffer. Matters when running the local hooks. */
3096 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3098 record_unwind_current_buffer ();
3099 Fset_buffer (Fwindow_buffer (Qnil));
3102 if (SELECTED_FRAME () != f)
3104 record_unwind_protect (select_frame_norecord, selected_frame);
3105 select_frame_norecord (frame);
3108 /* Look for buffer-local values. */
3110 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3111 for (; CONSP (windows); windows = XCDR (windows))
3113 Lisp_Object window = XCAR (windows);
3114 Lisp_Object buffer = Fwindow_buffer (window);
3115 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3116 buffer)))
3118 ptrdiff_t inner_count = SPECPDL_INDEX ();
3119 record_unwind_protect (select_window_norecord, selected_window);
3120 select_window_norecord (window);
3121 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3122 buffer));
3123 unbind_to (inner_count, Qnil);
3128 run_funs (global_wcch);
3129 unbind_to (count, Qnil);
3132 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
3133 Srun_window_configuration_change_hook, 0, 1, 0,
3134 doc: /* Run `window-configuration-change-hook' for FRAME.
3135 If FRAME is omitted or nil, it defaults to the selected frame. */)
3136 (Lisp_Object frame)
3138 run_window_configuration_change_hook (decode_live_frame (frame));
3139 return Qnil;
3142 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3143 means it's allowed to run hooks. See make_frame for a case where
3144 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3145 margins, fringes, and scroll-bar settings of the window are not
3146 reset from the buffer's local settings. */
3148 void
3149 set_window_buffer (Lisp_Object window, Lisp_Object buffer,
3150 bool run_hooks_p, bool keep_margins_p)
3152 struct window *w = XWINDOW (window);
3153 struct buffer *b = XBUFFER (buffer);
3154 ptrdiff_t count = SPECPDL_INDEX ();
3155 int samebuf = EQ (buffer, w->contents);
3157 wset_buffer (w, buffer);
3159 if (EQ (window, selected_window))
3160 bset_last_selected_window (b, window);
3162 /* Let redisplay errors through. */
3163 b->display_error_modiff = 0;
3165 /* Update time stamps of buffer display. */
3166 if (INTEGERP (BVAR (b, display_count)))
3167 bset_display_count (b, make_number (XINT (BVAR (b, display_count)) + 1));
3168 bset_display_time (b, Fcurrent_time ());
3170 wset_window_end_pos (w, make_number (0));
3171 wset_window_end_vpos (w, make_number (0));
3172 memset (&w->last_cursor, 0, sizeof w->last_cursor);
3174 if (!(keep_margins_p && samebuf))
3175 { /* If we're not actually changing the buffer, don't reset hscroll and
3176 vscroll. This case happens for example when called from
3177 change_frame_size_1, where we use a dummy call to
3178 Fset_window_buffer on the frame's selected window (and no other)
3179 just in order to run window-configuration-change-hook.
3180 Resetting hscroll and vscroll here is problematic for things like
3181 image-mode and doc-view-mode since it resets the image's position
3182 whenever we resize the frame. */
3183 w->hscroll = w->min_hscroll = 0;
3184 w->vscroll = 0;
3185 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3186 set_marker_restricted (w->start,
3187 make_number (b->last_window_start),
3188 buffer);
3189 w->start_at_line_beg = 0;
3190 w->force_start = 0;
3192 /* Maybe we could move this into the `if' but it's not obviously safe and
3193 I doubt it's worth the trouble. */
3194 windows_or_buffers_changed++;
3196 /* We must select BUFFER for running the window-scroll-functions. */
3197 /* We can't check ! NILP (Vwindow_scroll_functions) here
3198 because that might itself be a local variable. */
3199 if (window_initialized)
3201 record_unwind_current_buffer ();
3202 Fset_buffer (buffer);
3205 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3207 if (!keep_margins_p)
3209 /* Set left and right marginal area width etc. from buffer. */
3211 /* This may call adjust_window_margins three times, so
3212 temporarily disable window margins. */
3213 int save_left = w->left_margin_cols;
3214 int save_right = w->right_margin_cols;
3216 w->left_margin_cols = 0;
3217 w->right_margin_cols = 0;
3219 Fset_window_fringes (window,
3220 BVAR (b, left_fringe_width), BVAR (b, right_fringe_width),
3221 BVAR (b, fringes_outside_margins));
3223 Fset_window_scroll_bars (window,
3224 BVAR (b, scroll_bar_width),
3225 BVAR (b, vertical_scroll_bar_type), Qnil);
3227 w->left_margin_cols = save_left;
3228 w->right_margin_cols = save_right;
3230 Fset_window_margins (window,
3231 BVAR (b, left_margin_cols), BVAR (b, right_margin_cols));
3234 if (run_hooks_p)
3236 if (! NILP (Vwindow_scroll_functions))
3237 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3238 Fmarker_position (w->start));
3239 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3242 unbind_to (count, Qnil);
3245 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3246 doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3247 WINDOW must be a live window and defaults to the selected one.
3248 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
3250 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
3251 display margins, fringe widths, and scroll bar settings are preserved;
3252 the default is to reset these from the local settings for BUFFER-OR-NAME
3253 or the frame defaults. Return nil.
3255 This function throws an error when WINDOW is strongly dedicated to its
3256 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3257 already display BUFFER-OR-NAME.
3259 This function runs `window-scroll-functions' before running
3260 `window-configuration-change-hook'. */)
3261 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3263 register Lisp_Object tem, buffer;
3264 register struct window *w = decode_live_window (window);
3266 XSETWINDOW (window, w);
3267 buffer = Fget_buffer (buffer_or_name);
3268 CHECK_BUFFER (buffer);
3269 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3270 error ("Attempt to display deleted buffer");
3272 tem = w->contents;
3273 if (NILP (tem))
3274 error ("Window is deleted");
3275 else
3277 if (!EQ (tem, buffer))
3279 if (EQ (w->dedicated, Qt))
3280 /* WINDOW is strongly dedicated to its buffer, signal an
3281 error. */
3282 error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
3283 else
3284 /* WINDOW is weakly dedicated to its buffer, reset
3285 dedication. */
3286 wset_dedicated (w, Qnil);
3288 call1 (Qrecord_window_buffer, window);
3291 unshow_buffer (w);
3294 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3296 return Qnil;
3299 static Lisp_Object
3300 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3302 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3305 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3306 0, 1, 0,
3307 doc: /* Force all windows to be updated on next redisplay.
3308 If optional arg OBJECT is a window, force redisplay of that window only.
3309 If OBJECT is a buffer or buffer name, force redisplay of all windows
3310 displaying that buffer. */)
3311 (Lisp_Object object)
3313 if (NILP (object))
3315 windows_or_buffers_changed++;
3316 update_mode_lines++;
3317 return Qt;
3320 if (WINDOWP (object))
3322 struct window *w = XWINDOW (object);
3323 mark_window_display_accurate (object, 0);
3324 w->update_mode_line = 1;
3325 if (BUFFERP (w->contents))
3326 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
3327 ++update_mode_lines;
3328 return Qt;
3331 if (STRINGP (object))
3332 object = Fget_buffer (object);
3333 if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))
3334 && buffer_window_count (XBUFFER (object)))
3336 /* If buffer is live and shown in at least one window, find
3337 all windows showing this buffer and force update of them. */
3338 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3339 return NILP (object) ? Qnil : Qt;
3342 /* If nothing suitable was found, just return.
3343 We could signal an error, but this feature will typically be used
3344 asynchronously in timers or process sentinels, so we don't. */
3345 return Qnil;
3348 /* Obsolete since 24.3. */
3349 void
3350 temp_output_buffer_show (register Lisp_Object buf)
3352 register struct buffer *old = current_buffer;
3353 register Lisp_Object window;
3354 register struct window *w;
3356 bset_directory (XBUFFER (buf), BVAR (current_buffer, directory));
3358 Fset_buffer (buf);
3359 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3360 BEGV = BEG;
3361 ZV = Z;
3362 SET_PT (BEG);
3363 set_buffer_internal (old);
3365 if (!NILP (Vtemp_buffer_show_function))
3366 call1 (Vtemp_buffer_show_function, buf);
3367 else
3369 window = display_buffer (buf, Qnil, Qnil);
3371 if (!EQ (XWINDOW (window)->frame, selected_frame))
3372 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3373 Vminibuf_scroll_window = window;
3374 w = XWINDOW (window);
3375 w->hscroll = 0;
3376 w->min_hscroll = 0;
3377 set_marker_restricted_both (w->start, buf, BEG, BEG);
3378 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3380 /* Run temp-buffer-show-hook, with the chosen window selected
3381 and its buffer current. */
3383 ptrdiff_t count = SPECPDL_INDEX ();
3384 Lisp_Object prev_window, prev_buffer;
3385 prev_window = selected_window;
3386 XSETBUFFER (prev_buffer, old);
3388 /* Select the window that was chosen, for running the hook.
3389 Note: Both Fselect_window and select_window_norecord may
3390 set-buffer to the buffer displayed in the window,
3391 so we need to save the current buffer. --stef */
3392 record_unwind_protect (restore_buffer, prev_buffer);
3393 record_unwind_protect (select_window_norecord, prev_window);
3394 Fselect_window (window, Qt);
3395 Fset_buffer (w->contents);
3396 Frun_hooks (1, &Qtemp_buffer_show_hook);
3397 unbind_to (count, Qnil);
3402 /* Make new window, have it replace WINDOW in window-tree, and make
3403 WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
3404 horizontal child). */
3405 static void
3406 make_parent_window (Lisp_Object window, bool horflag)
3408 Lisp_Object parent;
3409 register struct window *o, *p;
3411 o = XWINDOW (window);
3412 p = allocate_window ();
3413 memcpy ((char *) p + sizeof (struct vectorlike_header),
3414 (char *) o + sizeof (struct vectorlike_header),
3415 word_size * VECSIZE (struct window));
3416 /* P's buffer slot may change from nil to a buffer... */
3417 adjust_window_count (p, 1);
3418 XSETWINDOW (parent, p);
3420 replace_window (window, parent, 1);
3422 wset_next (o, Qnil);
3423 wset_prev (o, Qnil);
3424 wset_parent (o, parent);
3425 /* ...but now P becomes an internal window. */
3426 wset_start (p, Qnil);
3427 wset_pointm (p, Qnil);
3428 wset_buffer (p, Qnil);
3429 wset_combination (p, horflag, window);
3430 wset_combination_limit (p, Qnil);
3431 wset_window_parameters (p, Qnil);
3434 /* Make new window from scratch. */
3435 Lisp_Object
3436 make_window (void)
3438 Lisp_Object window;
3439 register struct window *w;
3441 w = allocate_window ();
3442 /* Initialize Lisp data. Note that allocate_window initializes all
3443 Lisp data to nil, so do it only for slots which should not be nil. */
3444 wset_normal_lines (w, make_float (1.0));
3445 wset_normal_cols (w, make_float (1.0));
3446 wset_new_total (w, make_number (0));
3447 wset_new_normal (w, make_number (0));
3448 wset_start (w, Fmake_marker ());
3449 wset_pointm (w, Fmake_marker ());
3450 wset_vertical_scroll_bar_type (w, Qt);
3451 wset_window_end_pos (w, make_number (0));
3452 wset_window_end_vpos (w, make_number (0));
3453 /* These Lisp fields are marked specially so they're not set to nil by
3454 allocate_window. */
3455 wset_prev_buffers (w, Qnil);
3456 wset_next_buffers (w, Qnil);
3458 /* Initialize non-Lisp data. Note that allocate_window zeroes out all
3459 non-Lisp data, so do it only for slots which should not be zero. */
3460 w->nrows_scale_factor = w->ncols_scale_factor = 1;
3461 w->left_fringe_width = w->right_fringe_width = -1;
3462 w->phys_cursor_type = -1;
3463 w->phys_cursor_width = -1;
3464 w->column_number_displayed = -1;
3466 /* Reset window_list. */
3467 Vwindow_list = Qnil;
3468 /* Return window. */
3469 XSETWINDOW (window, w);
3470 return window;
3473 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
3474 doc: /* Set new total size of WINDOW to SIZE.
3475 WINDOW must be a valid window and defaults to the selected one.
3476 Return SIZE.
3478 Optional argument ADD non-nil means add SIZE to the new total size of
3479 WINDOW and return the sum.
3481 Note: This function does not operate on any child windows of WINDOW. */)
3482 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3484 struct window *w = decode_valid_window (window);
3486 CHECK_NUMBER (size);
3487 if (NILP (add))
3488 wset_new_total (w, size);
3489 else
3490 wset_new_total (w, make_number (XINT (w->new_total) + XINT (size)));
3492 return w->new_total;
3495 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
3496 doc: /* Set new normal size of WINDOW to SIZE.
3497 WINDOW must be a valid window and defaults to the selected one.
3498 Return SIZE.
3500 Note: This function does not operate on any child windows of WINDOW. */)
3501 (Lisp_Object window, Lisp_Object size)
3503 wset_new_normal (decode_valid_window (window), size);
3504 return size;
3507 /* Return 1 if setting w->total_lines (w->total_cols if HORFLAG is
3508 non-zero) to w->new_total would result in correct heights (widths)
3509 for window W and recursively all child windows of W.
3511 Note: This function does not check any of `window-fixed-size-p',
3512 `window-min-height' or `window-min-width'. It does check that window
3513 sizes do not drop below one line (two columns). */
3514 static int
3515 window_resize_check (struct window *w, bool horflag)
3517 struct window *c;
3519 if (WINDOW_VERTICAL_COMBINATION_P (w))
3520 /* W is a vertical combination. */
3522 c = XWINDOW (w->contents);
3523 if (horflag)
3524 /* All child windows of W must have the same width as W. */
3526 while (c)
3528 if ((XINT (c->new_total) != XINT (w->new_total))
3529 || !window_resize_check (c, horflag))
3530 return 0;
3531 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3533 return 1;
3535 else
3536 /* The sum of the heights of the child windows of W must equal
3537 W's height. */
3539 int sum_of_sizes = 0;
3540 while (c)
3542 if (!window_resize_check (c, horflag))
3543 return 0;
3544 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3545 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3547 return (sum_of_sizes == XINT (w->new_total));
3550 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3551 /* W is a horizontal combination. */
3553 c = XWINDOW (w->contents);
3554 if (horflag)
3555 /* The sum of the widths of the child windows of W must equal W's
3556 width. */
3558 int sum_of_sizes = 0;
3559 while (c)
3561 if (!window_resize_check (c, horflag))
3562 return 0;
3563 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3564 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3566 return (sum_of_sizes == XINT (w->new_total));
3568 else
3569 /* All child windows of W must have the same height as W. */
3571 while (c)
3573 if ((XINT (c->new_total) != XINT (w->new_total))
3574 || !window_resize_check (c, horflag))
3575 return 0;
3576 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3578 return 1;
3581 else
3582 /* A leaf window. Make sure it's not too small. The following
3583 hardcodes the values of `window-safe-min-width' (2) and
3584 `window-safe-min-height' (1) which are defined in window.el. */
3585 return XINT (w->new_total) >= (horflag ? 2 : 1);
3588 /* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
3589 w->new_total for window W and recursively all child windows of W.
3590 Also calculate and assign the new vertical (horizontal) start
3591 positions of each of these windows.
3593 This function does not perform any error checks. Make sure you have
3594 run window_resize_check on W before applying this function. */
3595 static void
3596 window_resize_apply (struct window *w, bool horflag)
3598 struct window *c;
3599 int pos;
3601 /* Note: Assigning new_normal requires that the new total size of the
3602 parent window has been set *before*. */
3603 if (horflag)
3605 w->total_cols = XFASTINT (w->new_total);
3606 if (NUMBERP (w->new_normal))
3607 wset_normal_cols (w, w->new_normal);
3609 pos = w->left_col;
3611 else
3613 w->total_lines = XFASTINT (w->new_total);
3614 if (NUMBERP (w->new_normal))
3615 wset_normal_lines (w, w->new_normal);
3617 pos = w->top_line;
3620 if (WINDOW_VERTICAL_COMBINATION_P (w))
3621 /* W is a vertical combination. */
3623 c = XWINDOW (w->contents);
3624 while (c)
3626 if (horflag)
3627 c->left_col = pos;
3628 else
3629 c->top_line = pos;
3630 window_resize_apply (c, horflag);
3631 if (!horflag)
3632 pos = pos + c->total_lines;
3633 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3636 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3637 /* W is a horizontal combination. */
3639 c = XWINDOW (w->contents);
3640 while (c)
3642 if (horflag)
3643 c->left_col = pos;
3644 else
3645 c->top_line = pos;
3646 window_resize_apply (c, horflag);
3647 if (horflag)
3648 pos = pos + c->total_cols;
3649 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3655 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 0, 2, 0,
3656 doc: /* Apply requested size values for window-tree of FRAME.
3657 If FRAME is omitted or nil, it defaults to the selected frame.
3659 Optional argument HORIZONTAL omitted or nil means apply requested
3660 height values. HORIZONTAL non-nil means apply requested width values.
3662 This function checks whether the requested values sum up to a valid
3663 window layout, recursively assigns the new sizes of all child windows
3664 and calculates and assigns the new start positions of these windows.
3666 Note: This function does not check any of `window-fixed-size-p',
3667 `window-min-height' or `window-min-width'. All these checks have to
3668 be applied on the Elisp level. */)
3669 (Lisp_Object frame, Lisp_Object horizontal)
3671 struct frame *f = decode_live_frame (frame);
3672 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
3673 bool horflag = !NILP (horizontal);
3675 if (!window_resize_check (r, horflag)
3676 || (XINT (r->new_total)
3677 != (horflag ? r->total_cols : r->total_lines)))
3678 return Qnil;
3680 block_input ();
3681 window_resize_apply (r, horflag);
3683 windows_or_buffers_changed++;
3684 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3686 adjust_glyphs (f);
3687 unblock_input ();
3689 run_window_configuration_change_hook (f);
3691 return Qt;
3695 /* Resize frame F's windows when number of lines of F is set to SIZE.
3696 HORFLAG 1 means resize windows when number of columns of F is set to
3697 SIZE.
3699 This function can delete all windows but the selected one in order to
3700 satisfy the request. The result will be meaningful if and only if
3701 F's windows have meaningful sizes when you call this. */
3702 void
3703 resize_frame_windows (struct frame *f, int size, bool horflag)
3705 Lisp_Object root = f->root_window;
3706 struct window *r = XWINDOW (root);
3707 Lisp_Object mini = f->minibuffer_window;
3708 struct window *m;
3709 /* new_size is the new size of the frame's root window. */
3710 int new_size = (horflag
3711 ? size
3712 : (size
3713 - FRAME_TOP_MARGIN (f)
3714 - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3715 ? 1 : 0)));
3717 r->top_line = FRAME_TOP_MARGIN (f);
3718 if (WINDOW_LEAF_P (r))
3719 /* For a leaf root window just set the size. */
3720 if (horflag)
3721 r->total_cols = new_size;
3722 else
3723 r->total_lines = new_size;
3724 else
3726 /* old_size is the old size of the frame's root window. */
3727 int old_size = horflag ? r->total_cols : r->total_lines;
3728 Lisp_Object delta;
3730 XSETINT (delta, new_size - old_size);
3731 /* Try a "normal" resize first. */
3732 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil);
3733 if (window_resize_check (r, horflag)
3734 && new_size == XINT (r->new_total))
3735 window_resize_apply (r, horflag);
3736 else
3738 /* Try with "reasonable" minimum sizes next. */
3739 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt);
3740 if (window_resize_check (r, horflag)
3741 && new_size == XINT (r->new_total))
3742 window_resize_apply (r, horflag);
3743 else
3745 /* Finally, try with "safe" minimum sizes. */
3746 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe);
3747 if (window_resize_check (r, horflag)
3748 && new_size == XINT (r->new_total))
3749 window_resize_apply (r, horflag);
3750 else
3752 /* We lost. Delete all windows but the frame's
3753 selected one. */
3754 root = f->selected_window;
3755 Fdelete_other_windows_internal (root, Qnil);
3756 if (horflag)
3757 XWINDOW (root)->total_cols = new_size;
3758 else
3759 XWINDOW (root)->total_lines = new_size;
3765 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3767 m = XWINDOW (mini);
3768 if (horflag)
3769 m->total_cols = size;
3770 else
3772 /* Are we sure we always want 1 line here? */
3773 m->total_lines = 1;
3774 m->top_line = r->top_line + r->total_lines;
3778 windows_or_buffers_changed++;
3782 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
3783 doc: /* Split window OLD.
3784 Second argument TOTAL-SIZE specifies the number of lines or columns of the
3785 new window. In any case TOTAL-SIZE must be a positive integer.
3787 Third argument SIDE nil (or `below') specifies that the new window shall
3788 be located below WINDOW. SIDE `above' means the new window shall be
3789 located above WINDOW. In both cases TOTAL-SIZE specifies the number of
3790 lines of the new window including space reserved for the mode and/or
3791 header line.
3793 SIDE t (or `right') specifies that the new window shall be located on
3794 the right side of WINDOW. SIDE `left' means the new window shall be
3795 located on the left of WINDOW. In both cases TOTAL-SIZE specifies the
3796 number of columns of the new window including space reserved for fringes
3797 and the scrollbar or a divider column.
3799 Fourth argument NORMAL-SIZE specifies the normal size of the new window
3800 according to the SIDE argument.
3802 The new total and normal sizes of all involved windows must have been
3803 set correctly. See the code of `split-window' for how this is done. */)
3804 (Lisp_Object old, Lisp_Object total_size, Lisp_Object side, Lisp_Object normal_size)
3806 /* OLD (*o) is the window we have to split. (*p) is either OLD's
3807 parent window or an internal window we have to install as OLD's new
3808 parent. REFERENCE (*r) must denote a live window, or is set to OLD
3809 provided OLD is a leaf window, or to the frame's selected window.
3810 NEW (*n) is the new window created with some parameters taken from
3811 REFERENCE (*r). */
3812 register Lisp_Object new, frame, reference;
3813 register struct window *o, *p, *n, *r;
3814 struct frame *f;
3815 bool horflag
3816 /* HORFLAG is 1 when we split side-by-side, 0 otherwise. */
3817 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
3818 int combination_limit = 0;
3820 CHECK_WINDOW (old);
3821 o = XWINDOW (old);
3822 frame = WINDOW_FRAME (o);
3823 f = XFRAME (frame);
3825 CHECK_NUMBER (total_size);
3827 /* Set combination_limit to 1 if we have to make a new parent window.
3828 We do that if either `window-combination-limit' is t, or OLD has no
3829 parent, or OLD is ortho-combined. */
3830 combination_limit =
3831 EQ (Vwindow_combination_limit, Qt)
3832 || NILP (o->parent)
3833 || (horflag
3834 ? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
3835 : WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent)));
3837 /* We need a live reference window to initialize some parameters. */
3838 if (WINDOW_LIVE_P (old))
3839 /* OLD is live, use it as reference window. */
3840 reference = old;
3841 else
3842 /* Use the frame's selected window as reference window. */
3843 reference = FRAME_SELECTED_WINDOW (f);
3844 r = XWINDOW (reference);
3846 /* The following bugs are caught by `split-window'. */
3847 if (MINI_WINDOW_P (o))
3848 error ("Attempt to split minibuffer window");
3849 else if (XINT (total_size) < (horflag ? 2 : 1))
3850 error ("Size of new window too small (after split)");
3851 else if (!combination_limit && !NILP (Vwindow_combination_resize))
3852 /* `window-combination-resize' non-nil means try to resize OLD's siblings
3853 proportionally. */
3855 p = XWINDOW (o->parent);
3856 /* Temporarily pretend we split the parent window. */
3857 wset_new_total
3858 (p, make_number ((horflag ? p->total_cols : p->total_lines)
3859 - XINT (total_size)));
3860 if (!window_resize_check (p, horflag))
3861 error ("Window sizes don't fit");
3862 else
3863 /* Undo the temporary pretension. */
3864 wset_new_total (p, make_number
3865 (horflag ? p->total_cols : p->total_lines));
3867 else
3869 if (!window_resize_check (o, horflag))
3870 error ("Resizing old window failed");
3871 else if (XINT (total_size) + XINT (o->new_total)
3872 != (horflag ? o->total_cols : o->total_lines))
3873 error ("Sum of sizes of old and new window don't fit");
3876 /* This is our point of no return. */
3877 if (combination_limit)
3879 /* Save the old value of o->normal_cols/lines. It gets corrupted
3880 by make_parent_window and we need it below for assigning it to
3881 p->new_normal. */
3882 Lisp_Object new_normal
3883 = horflag ? o->normal_cols : o->normal_lines;
3885 make_parent_window (old, horflag);
3886 p = XWINDOW (o->parent);
3887 if (EQ (Vwindow_combination_limit, Qt))
3888 /* Store t in the new parent's combination_limit slot to avoid
3889 that its children get merged into another window. */
3890 wset_combination_limit (p, Qt);
3891 /* These get applied below. */
3892 wset_new_total (p, make_number
3893 (horflag ? o->total_cols : o->total_lines));
3894 wset_new_normal (p, new_normal);
3896 else
3897 p = XWINDOW (o->parent);
3899 windows_or_buffers_changed++;
3900 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3901 new = make_window ();
3902 n = XWINDOW (new);
3903 wset_frame (n, frame);
3904 wset_parent (n, o->parent);
3906 if (EQ (side, Qabove) || EQ (side, Qleft))
3908 wset_prev (n, o->prev);
3909 if (NILP (n->prev))
3910 wset_combination (p, horflag, new);
3911 else
3912 wset_next (XWINDOW (n->prev), new);
3913 wset_next (n, old);
3914 wset_prev (o, new);
3916 else
3918 wset_next (n, o->next);
3919 if (!NILP (n->next))
3920 wset_prev (XWINDOW (n->next), new);
3921 wset_prev (n, old);
3922 wset_next (o, new);
3925 n->window_end_valid = 0;
3926 memset (&n->last_cursor, 0, sizeof n->last_cursor);
3928 /* Get special geometry settings from reference window. */
3929 n->left_margin_cols = r->left_margin_cols;
3930 n->right_margin_cols = r->right_margin_cols;
3931 n->left_fringe_width = r->left_fringe_width;
3932 n->right_fringe_width = r->right_fringe_width;
3933 n->fringes_outside_margins = r->fringes_outside_margins;
3934 wset_scroll_bar_width (n, r->scroll_bar_width);
3935 wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
3937 /* Directly assign orthogonal coordinates and sizes. */
3938 if (horflag)
3940 n->top_line = o->top_line;
3941 n->total_lines = o->total_lines;
3943 else
3945 n->left_col = o->left_col;
3946 n->total_cols = o->total_cols;
3949 /* Iso-coordinates and sizes are assigned by window_resize_apply,
3950 get them ready here. */
3951 wset_new_total (n, total_size);
3952 wset_new_normal (n, normal_size);
3954 block_input ();
3955 window_resize_apply (p, horflag);
3956 adjust_glyphs (f);
3957 /* Set buffer of NEW to buffer of reference window. Don't run
3958 any hooks. */
3959 set_window_buffer (new, r->contents, 0, 1);
3960 unblock_input ();
3962 /* Maybe we should run the scroll functions in Elisp (which already
3963 runs the configuration change hook). */
3964 if (! NILP (Vwindow_scroll_functions))
3965 run_hook_with_args_2 (Qwindow_scroll_functions, new,
3966 Fmarker_position (n->start));
3967 /* Return NEW. */
3968 return new;
3972 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
3973 doc: /* Remove WINDOW from its frame.
3974 WINDOW defaults to the selected window. Return nil.
3975 Signal an error when WINDOW is the only window on its frame. */)
3976 (register Lisp_Object window)
3978 register Lisp_Object parent, sibling, frame, root;
3979 struct window *w, *p, *s, *r;
3980 struct frame *f;
3981 bool horflag, before_sibling = 0;
3983 w = decode_any_window (window);
3984 XSETWINDOW (window, w);
3985 if (NILP (w->contents))
3986 /* It's a no-op to delete an already deleted window. */
3987 return Qnil;
3989 parent = w->parent;
3990 if (NILP (parent))
3991 /* Never delete a minibuffer or frame root window. */
3992 error ("Attempt to delete minibuffer or sole ordinary window");
3993 else if (NILP (w->prev) && NILP (w->next))
3994 /* Rather bow out here, this case should be handled on the Elisp
3995 level. */
3996 error ("Attempt to delete sole window of parent");
3998 p = XWINDOW (parent);
3999 horflag = WINDOW_HORIZONTAL_COMBINATION_P (p);
4001 frame = WINDOW_FRAME (w);
4002 f = XFRAME (frame);
4004 root = FRAME_ROOT_WINDOW (f);
4005 r = XWINDOW (root);
4007 /* Unlink WINDOW from window tree. */
4008 if (NILP (w->prev))
4009 /* Get SIBLING below (on the right of) WINDOW. */
4011 /* before_sibling 1 means WINDOW is the first child of its
4012 parent and thus before the sibling. */
4013 before_sibling = 1;
4014 sibling = w->next;
4015 s = XWINDOW (sibling);
4016 wset_prev (s, Qnil);
4017 wset_combination (p, horflag, sibling);
4019 else
4020 /* Get SIBLING above (on the left of) WINDOW. */
4022 sibling = w->prev;
4023 s = XWINDOW (sibling);
4024 wset_next (s, w->next);
4025 if (!NILP (s->next))
4026 wset_prev (XWINDOW (s->next), sibling);
4029 if (window_resize_check (r, horflag)
4030 && (XINT (r->new_total)
4031 == (horflag ? r->total_cols : r->total_lines)))
4032 /* We can delete WINDOW now. */
4035 /* Block input. */
4036 block_input ();
4037 window_resize_apply (p, horflag);
4039 /* If this window is referred to by the dpyinfo's mouse
4040 highlight, invalidate that slot to be safe (Bug#9904). */
4041 if (!FRAME_INITIAL_P (f))
4043 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
4045 if (EQ (hlinfo->mouse_face_window, window))
4046 hlinfo->mouse_face_window = Qnil;
4049 windows_or_buffers_changed++;
4050 Vwindow_list = Qnil;
4051 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4053 wset_next (w, Qnil); /* Don't delete w->next too. */
4054 free_window_matrices (w);
4056 if (WINDOWP (w->contents))
4058 delete_all_child_windows (w->contents);
4059 wset_combination (w, 0, Qnil);
4061 else
4063 unshow_buffer (w);
4064 unchain_marker (XMARKER (w->pointm));
4065 unchain_marker (XMARKER (w->start));
4066 wset_buffer (w, Qnil);
4069 if (NILP (s->prev) && NILP (s->next))
4070 /* A matrjoshka where SIBLING has become the only child of
4071 PARENT. */
4073 /* Put SIBLING into PARENT's place. */
4074 replace_window (parent, sibling, 0);
4075 /* Have SIBLING inherit the following three slot values from
4076 PARENT (the combination_limit slot is not inherited). */
4077 wset_normal_cols (s, p->normal_cols);
4078 wset_normal_lines (s, p->normal_lines);
4079 /* Mark PARENT as deleted. */
4080 wset_combination (p, 0, Qnil);
4081 /* Try to merge SIBLING into its new parent. */
4082 recombine_windows (sibling);
4085 adjust_glyphs (f);
4087 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
4088 /* We deleted the frame's selected window. */
4090 /* Use the frame's first window as fallback ... */
4091 Lisp_Object new_selected_window = Fframe_first_window (frame);
4092 /* ... but preferably use its most recently used window. */
4093 Lisp_Object mru_window;
4095 /* `get-mru-window' might fail for some reason so play it safe
4096 - promote the first window _without recording it_ first. */
4097 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4098 Fselect_window (new_selected_window, Qt);
4099 else
4100 fset_selected_window (f, new_selected_window);
4102 unblock_input ();
4104 /* Now look whether `get-mru-window' gets us something. */
4105 mru_window = call1 (Qget_mru_window, frame);
4106 if (WINDOW_LIVE_P (mru_window)
4107 && EQ (XWINDOW (mru_window)->frame, frame))
4108 new_selected_window = mru_window;
4110 /* If all ended up well, we now promote the mru window. */
4111 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4112 Fselect_window (new_selected_window, Qnil);
4113 else
4114 fset_selected_window (f, new_selected_window);
4116 else
4117 unblock_input ();
4119 /* Must be run by the caller:
4120 run_window_configuration_change_hook (f); */
4122 else
4123 /* We failed: Relink WINDOW into window tree. */
4125 if (before_sibling)
4127 wset_prev (s, window);
4128 wset_combination (p, horflag, window);
4130 else
4132 wset_next (s, window);
4133 if (!NILP (w->next))
4134 wset_prev (XWINDOW (w->next), window);
4136 error ("Deletion failed");
4139 return Qnil;
4142 /***********************************************************************
4143 Resizing Mini-Windows
4144 ***********************************************************************/
4146 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
4147 can. */
4148 void
4149 grow_mini_window (struct window *w, int delta)
4151 struct frame *f = XFRAME (w->frame);
4152 struct window *r;
4153 Lisp_Object root, value;
4155 eassert (MINI_WINDOW_P (w));
4156 eassert (delta >= 0);
4158 root = FRAME_ROOT_WINDOW (f);
4159 r = XWINDOW (root);
4160 value = call2 (Qwindow_resize_root_window_vertically,
4161 root, make_number (- delta));
4162 if (INTEGERP (value) && window_resize_check (r, 0))
4164 block_input ();
4165 window_resize_apply (r, 0);
4167 /* Grow the mini-window. */
4168 w->top_line = r->top_line + r->total_lines;
4169 w->total_lines -= XINT (value);
4170 /* Enforce full redisplay. FIXME: make it more selective. */
4171 windows_or_buffers_changed++;
4172 adjust_glyphs (f);
4173 unblock_input ();
4178 /* Shrink mini-window W. */
4179 void
4180 shrink_mini_window (struct window *w)
4182 struct frame *f = XFRAME (w->frame);
4183 struct window *r;
4184 Lisp_Object root, value;
4185 EMACS_INT size;
4187 eassert (MINI_WINDOW_P (w));
4189 size = w->total_lines;
4190 if (size > 1)
4192 root = FRAME_ROOT_WINDOW (f);
4193 r = XWINDOW (root);
4194 value = call2 (Qwindow_resize_root_window_vertically,
4195 root, make_number (size - 1));
4196 if (INTEGERP (value) && window_resize_check (r, 0))
4198 block_input ();
4199 window_resize_apply (r, 0);
4201 /* Shrink the mini-window. */
4202 w->top_line = r->top_line + r->total_lines;
4203 w->total_lines = 1;
4204 /* Enforce full redisplay. FIXME: make it more selective. */
4205 windows_or_buffers_changed++;
4206 adjust_glyphs (f);
4207 unblock_input ();
4209 /* If the above failed for whatever strange reason we must make a
4210 one window frame here. The same routine will be needed when
4211 shrinking the frame (and probably when making the initial
4212 *scratch* window). For the moment leave things as they are. */
4216 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
4217 doc: /* Resize minibuffer window WINDOW. */)
4218 (Lisp_Object window)
4220 struct window *w = XWINDOW (window);
4221 struct window *r;
4222 struct frame *f;
4223 int height;
4225 CHECK_WINDOW (window);
4226 f = XFRAME (w->frame);
4228 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
4229 error ("Not a valid minibuffer window");
4230 else if (FRAME_MINIBUF_ONLY_P (f))
4231 error ("Cannot resize a minibuffer-only frame");
4233 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4234 height = r->total_lines + w->total_lines;
4235 if (window_resize_check (r, 0)
4236 && XINT (w->new_total) > 0
4237 && height == XINT (r->new_total) + XINT (w->new_total))
4239 block_input ();
4240 window_resize_apply (r, 0);
4242 w->total_lines = XFASTINT (w->new_total);
4243 w->top_line = r->top_line + r->total_lines;
4245 windows_or_buffers_changed++;
4246 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4247 adjust_glyphs (f);
4248 unblock_input ();
4250 run_window_configuration_change_hook (f);
4251 return Qt;
4253 else error ("Failed to resize minibuffer window");
4256 /* Mark window cursors off for all windows in the window tree rooted
4257 at W by setting their phys_cursor_on_p flag to zero. Called from
4258 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4259 the frame are cleared. */
4261 void
4262 mark_window_cursors_off (struct window *w)
4264 while (w)
4266 if (WINDOWP (w->contents))
4267 mark_window_cursors_off (XWINDOW (w->contents));
4268 else
4269 w->phys_cursor_on_p = 0;
4271 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4276 /* Return number of lines of text (not counting mode lines) in W. */
4279 window_internal_height (struct window *w)
4281 int ht = w->total_lines;
4283 if (!MINI_WINDOW_P (w))
4285 if (!NILP (w->parent)
4286 || WINDOWP (w->contents)
4287 || !NILP (w->next)
4288 || !NILP (w->prev)
4289 || WINDOW_WANTS_MODELINE_P (w))
4290 --ht;
4292 if (WINDOW_WANTS_HEADER_LINE_P (w))
4293 --ht;
4296 return ht;
4299 /************************************************************************
4300 Window Scrolling
4301 ***********************************************************************/
4303 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4304 N screen-fulls, which is defined as the height of the window minus
4305 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4306 instead. Negative values of N mean scroll down. NOERROR non-zero
4307 means don't signal an error if we try to move over BEGV or ZV,
4308 respectively. */
4310 static void
4311 window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
4313 immediate_quit = 1;
4314 n = clip_to_bounds (INT_MIN, n, INT_MAX);
4316 /* If we must, use the pixel-based version which is much slower than
4317 the line-based one but can handle varying line heights. */
4318 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4319 window_scroll_pixel_based (window, n, whole, noerror);
4320 else
4321 window_scroll_line_based (window, n, whole, noerror);
4323 immediate_quit = 0;
4327 /* Implementation of window_scroll that works based on pixel line
4328 heights. See the comment of window_scroll for parameter
4329 descriptions. */
4331 static void
4332 window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
4334 struct it it;
4335 struct window *w = XWINDOW (window);
4336 struct text_pos start;
4337 int this_scroll_margin;
4338 /* True if we fiddled the window vscroll field without really scrolling. */
4339 int vscrolled = 0;
4340 int x, y, rtop, rbot, rowh, vpos;
4341 void *itdata = NULL;
4342 int window_total_lines;
4343 int frame_line_height = default_line_pixel_height (w);
4345 SET_TEXT_POS_FROM_MARKER (start, w->start);
4346 /* Scrolling a minibuffer window via scroll bar when the echo area
4347 shows long text sometimes resets the minibuffer contents behind
4348 our backs. */
4349 if (CHARPOS (start) > ZV)
4350 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4352 /* If PT is not visible in WINDOW, move back one half of
4353 the screen. Allow PT to be partially visible, otherwise
4354 something like (scroll-down 1) with PT in the line before
4355 the partially visible one would recenter. */
4357 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4359 itdata = bidi_shelve_cache ();
4360 /* Move backward half the height of the window. Performance note:
4361 vmotion used here is about 10% faster, but would give wrong
4362 results for variable height lines. */
4363 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4364 it.current_y = it.last_visible_y;
4365 move_it_vertically_backward (&it, window_box_height (w) / 2);
4367 /* The function move_iterator_vertically may move over more than
4368 the specified y-distance. If it->w is small, e.g. a
4369 mini-buffer window, we may end up in front of the window's
4370 display area. This is the case when Start displaying at the
4371 start of the line containing PT in this case. */
4372 if (it.current_y <= 0)
4374 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4375 move_it_vertically_backward (&it, 0);
4376 it.current_y = 0;
4379 start = it.current.pos;
4380 bidi_unshelve_cache (itdata, 0);
4382 else if (auto_window_vscroll_p)
4384 if (rtop || rbot) /* partially visible */
4386 int px;
4387 int dy = frame_line_height;
4388 if (whole)
4389 dy = max ((window_box_height (w)
4390 - next_screen_context_lines * dy),
4391 dy);
4392 dy *= n;
4394 if (n < 0)
4396 /* Only vscroll backwards if already vscrolled forwards. */
4397 if (w->vscroll < 0 && rtop > 0)
4399 px = max (0, -w->vscroll - min (rtop, -dy));
4400 Fset_window_vscroll (window, make_number (px), Qt);
4401 return;
4404 if (n > 0)
4406 /* Do vscroll if already vscrolled or only display line. */
4407 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4409 px = max (0, -w->vscroll + min (rbot, dy));
4410 Fset_window_vscroll (window, make_number (px), Qt);
4411 return;
4414 /* Maybe modify window start instead of scrolling. */
4415 if (rbot > 0 || w->vscroll < 0)
4417 ptrdiff_t spos;
4419 Fset_window_vscroll (window, make_number (0), Qt);
4420 /* If there are other text lines above the current row,
4421 move window start to current row. Else to next row. */
4422 if (rbot > 0)
4423 spos = XINT (Fline_beginning_position (Qnil));
4424 else
4425 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4426 set_marker_restricted (w->start, make_number (spos),
4427 w->contents);
4428 w->start_at_line_beg = 1;
4429 w->update_mode_line = 1;
4430 /* Set force_start so that redisplay_window will run the
4431 window-scroll-functions. */
4432 w->force_start = 1;
4433 return;
4437 /* Cancel previous vscroll. */
4438 Fset_window_vscroll (window, make_number (0), Qt);
4441 itdata = bidi_shelve_cache ();
4442 /* If scroll_preserve_screen_position is non-nil, we try to set
4443 point in the same window line as it is now, so get that line. */
4444 if (!NILP (Vscroll_preserve_screen_position))
4446 /* We preserve the goal pixel coordinate across consecutive
4447 calls to scroll-up, scroll-down and other commands that
4448 have the `scroll-command' property. This avoids the
4449 possibility of point becoming "stuck" on a tall line when
4450 scrolling by one line. */
4451 if (window_scroll_pixel_based_preserve_y < 0
4452 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4453 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4455 start_display (&it, w, start);
4456 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4457 window_scroll_pixel_based_preserve_y = it.current_y;
4458 window_scroll_pixel_based_preserve_x = it.current_x;
4461 else
4462 window_scroll_pixel_based_preserve_y
4463 = window_scroll_pixel_based_preserve_x = -1;
4465 /* Move iterator it from start the specified distance forward or
4466 backward. The result is the new window start. */
4467 start_display (&it, w, start);
4468 if (whole)
4470 ptrdiff_t start_pos = IT_CHARPOS (it);
4471 int dy = frame_line_height;
4472 dy = max ((window_box_height (w)
4473 - next_screen_context_lines * dy),
4474 dy) * n;
4476 /* Note that move_it_vertically always moves the iterator to the
4477 start of a line. So, if the last line doesn't have a newline,
4478 we would end up at the start of the line ending at ZV. */
4479 if (dy <= 0)
4481 move_it_vertically_backward (&it, -dy);
4482 /* Ensure we actually do move, e.g. in case we are currently
4483 looking at an image that is taller that the window height. */
4484 while (start_pos == IT_CHARPOS (it)
4485 && start_pos > BEGV)
4486 move_it_by_lines (&it, -1);
4488 else if (dy > 0)
4490 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4491 MOVE_TO_POS | MOVE_TO_Y);
4492 /* Ensure we actually do move, e.g. in case we are currently
4493 looking at an image that is taller that the window height. */
4494 while (start_pos == IT_CHARPOS (it)
4495 && start_pos < ZV)
4496 move_it_by_lines (&it, 1);
4499 else
4500 move_it_by_lines (&it, n);
4502 /* We failed if we find ZV is already on the screen (scrolling up,
4503 means there's nothing past the end), or if we can't start any
4504 earlier (scrolling down, means there's nothing past the top). */
4505 if ((n > 0 && IT_CHARPOS (it) == ZV)
4506 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4508 if (IT_CHARPOS (it) == ZV)
4510 if (it.current_y < it.last_visible_y
4511 && (it.current_y + it.max_ascent + it.max_descent
4512 > it.last_visible_y))
4514 /* The last line was only partially visible, make it fully
4515 visible. */
4516 w->vscroll = (it.last_visible_y
4517 - it.current_y + it.max_ascent + it.max_descent);
4518 adjust_glyphs (it.f);
4520 else
4522 bidi_unshelve_cache (itdata, 0);
4523 if (noerror)
4524 return;
4525 else if (n < 0) /* could happen with empty buffers */
4526 xsignal0 (Qbeginning_of_buffer);
4527 else
4528 xsignal0 (Qend_of_buffer);
4531 else
4533 if (w->vscroll != 0)
4534 /* The first line was only partially visible, make it fully
4535 visible. */
4536 w->vscroll = 0;
4537 else
4539 bidi_unshelve_cache (itdata, 0);
4540 if (noerror)
4541 return;
4542 else
4543 xsignal0 (Qbeginning_of_buffer);
4547 /* If control gets here, then we vscrolled. */
4549 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
4551 /* Don't try to change the window start below. */
4552 vscrolled = 1;
4555 if (! vscrolled)
4557 ptrdiff_t pos = IT_CHARPOS (it);
4558 ptrdiff_t bytepos;
4560 /* If in the middle of a multi-glyph character move forward to
4561 the next character. */
4562 if (in_display_vector_p (&it))
4564 ++pos;
4565 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4568 /* Set the window start, and set up the window for redisplay. */
4569 set_marker_restricted_both (w->start, w->contents, IT_CHARPOS (it),
4570 IT_BYTEPOS (it));
4571 bytepos = marker_byte_position (w->start);
4572 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
4573 w->update_mode_line = 1;
4574 /* Set force_start so that redisplay_window will run the
4575 window-scroll-functions. */
4576 w->force_start = 1;
4579 /* The rest of this function uses current_y in a nonstandard way,
4580 not including the height of the header line if any. */
4581 it.current_y = it.vpos = 0;
4583 /* Move PT out of scroll margins.
4584 This code wants current_y to be zero at the window start position
4585 even if there is a header line. */
4586 window_total_lines
4587 = w->total_lines * WINDOW_FRAME_LINE_HEIGHT (w) / frame_line_height;
4588 this_scroll_margin = max (0, scroll_margin);
4589 this_scroll_margin
4590 = min (this_scroll_margin, window_total_lines / 4);
4591 this_scroll_margin *= frame_line_height;
4593 if (n > 0)
4595 /* We moved the window start towards ZV, so PT may be now
4596 in the scroll margin at the top. */
4597 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4598 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
4599 && (NILP (Vscroll_preserve_screen_position)
4600 || EQ (Vscroll_preserve_screen_position, Qt)))
4601 /* We found PT at a legitimate height. Leave it alone. */
4603 else if (window_scroll_pixel_based_preserve_y >= 0)
4605 /* If we have a header line, take account of it.
4606 This is necessary because we set it.current_y to 0, above. */
4607 move_it_to (&it, -1,
4608 window_scroll_pixel_based_preserve_x,
4609 window_scroll_pixel_based_preserve_y
4610 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
4611 -1, MOVE_TO_Y | MOVE_TO_X);
4612 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4614 else
4616 while (it.current_y < this_scroll_margin)
4618 int prev = it.current_y;
4619 move_it_by_lines (&it, 1);
4620 if (prev == it.current_y)
4621 break;
4623 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4626 else if (n < 0)
4628 ptrdiff_t charpos, bytepos;
4629 int partial_p;
4631 /* Save our position, for the
4632 window_scroll_pixel_based_preserve_y case. */
4633 charpos = IT_CHARPOS (it);
4634 bytepos = IT_BYTEPOS (it);
4636 /* We moved the window start towards BEGV, so PT may be now
4637 in the scroll margin at the bottom. */
4638 move_it_to (&it, PT, -1,
4639 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
4640 - this_scroll_margin - 1),
4642 MOVE_TO_POS | MOVE_TO_Y);
4644 /* Save our position, in case it's correct. */
4645 charpos = IT_CHARPOS (it);
4646 bytepos = IT_BYTEPOS (it);
4648 /* See if point is on a partially visible line at the end. */
4649 if (it.what == IT_EOB)
4650 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
4651 else
4653 move_it_by_lines (&it, 1);
4654 partial_p = it.current_y > it.last_visible_y;
4657 if (charpos == PT && !partial_p
4658 && (NILP (Vscroll_preserve_screen_position)
4659 || EQ (Vscroll_preserve_screen_position, Qt)))
4660 /* We found PT before we found the display margin, so PT is ok. */
4662 else if (window_scroll_pixel_based_preserve_y >= 0)
4664 SET_TEXT_POS_FROM_MARKER (start, w->start);
4665 start_display (&it, w, start);
4666 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
4667 here because we called start_display again and did not
4668 alter it.current_y this time. */
4669 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
4670 window_scroll_pixel_based_preserve_y, -1,
4671 MOVE_TO_Y | MOVE_TO_X);
4672 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4674 else
4676 if (partial_p)
4677 /* The last line was only partially visible, so back up two
4678 lines to make sure we're on a fully visible line. */
4680 move_it_by_lines (&it, -2);
4681 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4683 else
4684 /* No, the position we saved is OK, so use it. */
4685 SET_PT_BOTH (charpos, bytepos);
4688 bidi_unshelve_cache (itdata, 0);
4692 /* Implementation of window_scroll that works based on screen lines.
4693 See the comment of window_scroll for parameter descriptions. */
4695 static void
4696 window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
4698 register struct window *w = XWINDOW (window);
4699 /* Fvertical_motion enters redisplay, which can trigger
4700 fontification, which in turn can modify buffer text (e.g., if the
4701 fontification functions replace escape sequences with faces, as
4702 in `grep-mode-font-lock-keywords'). So we use a marker to record
4703 the old point position, to prevent crashes in SET_PT_BOTH. */
4704 Lisp_Object opoint_marker = Fpoint_marker ();
4705 register ptrdiff_t pos, pos_byte;
4706 register int ht = window_internal_height (w);
4707 register Lisp_Object tem;
4708 bool lose;
4709 Lisp_Object bolp;
4710 ptrdiff_t startpos = marker_position (w->start);
4711 ptrdiff_t startbyte = marker_byte_position (w->start);
4712 Lisp_Object original_pos = Qnil;
4714 /* If scrolling screen-fulls, compute the number of lines to
4715 scroll from the window's height. */
4716 if (whole)
4717 n *= max (1, ht - next_screen_context_lines);
4719 if (!NILP (Vscroll_preserve_screen_position))
4721 if (window_scroll_preserve_vpos <= 0
4722 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4723 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4725 struct position posit
4726 = *compute_motion (startpos, startbyte, 0, 0, 0,
4727 PT, ht, 0, -1, w->hscroll, 0, w);
4728 window_scroll_preserve_vpos = posit.vpos;
4729 window_scroll_preserve_hpos = posit.hpos + w->hscroll;
4732 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
4733 make_number (window_scroll_preserve_vpos));
4736 XSETFASTINT (tem, PT);
4737 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4739 if (NILP (tem))
4741 Fvertical_motion (make_number (- (ht / 2)), window);
4742 startpos = PT;
4743 startbyte = PT_BYTE;
4746 SET_PT_BOTH (startpos, startbyte);
4747 lose = n < 0 && PT == BEGV;
4748 Fvertical_motion (make_number (n), window);
4749 pos = PT;
4750 pos_byte = PT_BYTE;
4751 bolp = Fbolp ();
4752 SET_PT_BOTH (marker_position (opoint_marker),
4753 marker_byte_position (opoint_marker));
4755 if (lose)
4757 if (noerror)
4758 return;
4759 else
4760 xsignal0 (Qbeginning_of_buffer);
4763 if (pos < ZV)
4765 /* Don't use a scroll margin that is negative or too large. */
4766 int this_scroll_margin =
4767 max (0, min (scroll_margin, w->total_lines / 4));
4769 set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
4770 w->start_at_line_beg = !NILP (bolp);
4771 w->update_mode_line = 1;
4772 /* Set force_start so that redisplay_window will run
4773 the window-scroll-functions. */
4774 w->force_start = 1;
4776 if (!NILP (Vscroll_preserve_screen_position)
4777 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
4779 SET_PT_BOTH (pos, pos_byte);
4780 Fvertical_motion (original_pos, window);
4782 /* If we scrolled forward, put point enough lines down
4783 that it is outside the scroll margin. */
4784 else if (n > 0)
4786 int top_margin;
4788 if (this_scroll_margin > 0)
4790 SET_PT_BOTH (pos, pos_byte);
4791 Fvertical_motion (make_number (this_scroll_margin), window);
4792 top_margin = PT;
4794 else
4795 top_margin = pos;
4797 if (top_margin <= marker_position (opoint_marker))
4798 SET_PT_BOTH (marker_position (opoint_marker),
4799 marker_byte_position (opoint_marker));
4800 else if (!NILP (Vscroll_preserve_screen_position))
4802 SET_PT_BOTH (pos, pos_byte);
4803 Fvertical_motion (original_pos, window);
4805 else
4806 SET_PT (top_margin);
4808 else if (n < 0)
4810 int bottom_margin;
4812 /* If we scrolled backward, put point near the end of the window
4813 but not within the scroll margin. */
4814 SET_PT_BOTH (pos, pos_byte);
4815 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4816 if (XFASTINT (tem) == ht - this_scroll_margin)
4817 bottom_margin = PT;
4818 else
4819 bottom_margin = PT + 1;
4821 if (bottom_margin > marker_position (opoint_marker))
4822 SET_PT_BOTH (marker_position (opoint_marker),
4823 marker_byte_position (opoint_marker));
4824 else
4826 if (!NILP (Vscroll_preserve_screen_position))
4828 SET_PT_BOTH (pos, pos_byte);
4829 Fvertical_motion (original_pos, window);
4831 else
4832 Fvertical_motion (make_number (-1), window);
4836 else
4838 if (noerror)
4839 return;
4840 else
4841 xsignal0 (Qend_of_buffer);
4846 /* Scroll selected_window up or down. If N is nil, scroll a
4847 screen-full which is defined as the height of the window minus
4848 next_screen_context_lines. If N is the symbol `-', scroll.
4849 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4850 up. This is the guts of Fscroll_up and Fscroll_down. */
4852 static void
4853 scroll_command (Lisp_Object n, int direction)
4855 ptrdiff_t count = SPECPDL_INDEX ();
4857 eassert (eabs (direction) == 1);
4859 /* If selected window's buffer isn't current, make it current for
4860 the moment. But don't screw up if window_scroll gets an error. */
4861 if (XBUFFER (XWINDOW (selected_window)->contents) != current_buffer)
4863 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4864 Fset_buffer (XWINDOW (selected_window)->contents);
4866 /* Make redisplay consider other windows than just selected_window. */
4867 ++windows_or_buffers_changed;
4870 if (NILP (n))
4871 window_scroll (selected_window, direction, 1, 0);
4872 else if (EQ (n, Qminus))
4873 window_scroll (selected_window, -direction, 1, 0);
4874 else
4876 n = Fprefix_numeric_value (n);
4877 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4880 unbind_to (count, Qnil);
4883 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
4884 doc: /* Scroll text of selected window upward ARG lines.
4885 If ARG is omitted or nil, scroll upward by a near full screen.
4886 A near full screen is `next-screen-context-lines' less than a full screen.
4887 Negative ARG means scroll downward.
4888 If ARG is the atom `-', scroll downward by nearly full screen.
4889 When calling from a program, supply as argument a number, nil, or `-'. */)
4890 (Lisp_Object arg)
4892 scroll_command (arg, 1);
4893 return Qnil;
4896 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
4897 doc: /* Scroll text of selected window down ARG lines.
4898 If ARG is omitted or nil, scroll down by a near full screen.
4899 A near full screen is `next-screen-context-lines' less than a full screen.
4900 Negative ARG means scroll upward.
4901 If ARG is the atom `-', scroll upward by nearly full screen.
4902 When calling from a program, supply as argument a number, nil, or `-'. */)
4903 (Lisp_Object arg)
4905 scroll_command (arg, -1);
4906 return Qnil;
4909 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4910 doc: /* Return the other window for \"other window scroll\" commands.
4911 If `other-window-scroll-buffer' is non-nil, a window
4912 showing that buffer is used.
4913 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4914 specifies the window. This takes precedence over
4915 `other-window-scroll-buffer'. */)
4916 (void)
4918 Lisp_Object window;
4920 if (MINI_WINDOW_P (XWINDOW (selected_window))
4921 && !NILP (Vminibuf_scroll_window))
4922 window = Vminibuf_scroll_window;
4923 /* If buffer is specified, scroll that buffer. */
4924 else if (!NILP (Vother_window_scroll_buffer))
4926 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4927 if (NILP (window))
4928 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4930 else
4932 /* Nothing specified; look for a neighboring window on the same
4933 frame. */
4934 window = Fnext_window (selected_window, Qnil, Qnil);
4936 if (EQ (window, selected_window))
4937 /* That didn't get us anywhere; look for a window on another
4938 visible frame. */
4940 window = Fnext_window (window, Qnil, Qt);
4941 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4942 && ! EQ (window, selected_window));
4945 CHECK_LIVE_WINDOW (window);
4947 if (EQ (window, selected_window))
4948 error ("There is no other window");
4950 return window;
4953 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4954 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4955 A near full screen is `next-screen-context-lines' less than a full screen.
4956 The next window is the one below the current one; or the one at the top
4957 if the current one is at the bottom. Negative ARG means scroll downward.
4958 If ARG is the atom `-', scroll downward by nearly full screen.
4959 When calling from a program, supply as argument a number, nil, or `-'.
4961 If `other-window-scroll-buffer' is non-nil, scroll the window
4962 showing that buffer, popping the buffer up if necessary.
4963 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4964 specifies the window to scroll. This takes precedence over
4965 `other-window-scroll-buffer'. */)
4966 (Lisp_Object arg)
4968 Lisp_Object window;
4969 struct window *w;
4970 ptrdiff_t count = SPECPDL_INDEX ();
4972 window = Fother_window_for_scrolling ();
4973 w = XWINDOW (window);
4975 /* Don't screw up if window_scroll gets an error. */
4976 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4977 ++windows_or_buffers_changed;
4979 Fset_buffer (w->contents);
4980 SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
4982 if (NILP (arg))
4983 window_scroll (window, 1, 1, 1);
4984 else if (EQ (arg, Qminus))
4985 window_scroll (window, -1, 1, 1);
4986 else
4988 if (CONSP (arg))
4989 arg = XCAR (arg);
4990 CHECK_NUMBER (arg);
4991 window_scroll (window, XINT (arg), 0, 1);
4994 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4995 unbind_to (count, Qnil);
4997 return Qnil;
5000 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5001 doc: /* Scroll selected window display ARG columns left.
5002 Default for ARG is window width minus 2.
5003 Value is the total amount of leftward horizontal scrolling in
5004 effect after the change.
5005 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5006 lower bound for automatic scrolling, i.e. automatic scrolling
5007 will not scroll a window to a column less than the value returned
5008 by this function. This happens in an interactive call. */)
5009 (register Lisp_Object arg, Lisp_Object set_minimum)
5011 struct window *w = XWINDOW (selected_window);
5012 EMACS_INT requested_arg = (NILP (arg)
5013 ? window_body_cols (w) - 2
5014 : XINT (Fprefix_numeric_value (arg)));
5015 Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
5017 if (!NILP (set_minimum))
5018 w->min_hscroll = w->hscroll;
5020 return result;
5023 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5024 doc: /* Scroll selected window display ARG columns right.
5025 Default for ARG is window width minus 2.
5026 Value is the total amount of leftward horizontal scrolling in
5027 effect after the change.
5028 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5029 lower bound for automatic scrolling, i.e. automatic scrolling
5030 will not scroll a window to a column less than the value returned
5031 by this function. This happens in an interactive call. */)
5032 (register Lisp_Object arg, Lisp_Object set_minimum)
5034 struct window *w = XWINDOW (selected_window);
5035 EMACS_INT requested_arg = (NILP (arg)
5036 ? window_body_cols (w) - 2
5037 : XINT (Fprefix_numeric_value (arg)));
5038 Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
5040 if (!NILP (set_minimum))
5041 w->min_hscroll = w->hscroll;
5043 return result;
5046 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5047 doc: /* Return the window which was selected when entering the minibuffer.
5048 Returns nil, if selected window is not a minibuffer window. */)
5049 (void)
5051 if (minibuf_level > 0
5052 && MINI_WINDOW_P (XWINDOW (selected_window))
5053 && WINDOW_LIVE_P (minibuf_selected_window))
5054 return minibuf_selected_window;
5056 return Qnil;
5059 /* Value is the number of lines actually displayed in window W,
5060 as opposed to its height. */
5062 static int
5063 displayed_window_lines (struct window *w)
5065 struct it it;
5066 struct text_pos start;
5067 ptrdiff_t charpos = marker_position (w->start);
5068 int height = window_box_height (w);
5069 struct buffer *old_buffer;
5070 int bottom_y;
5071 void *itdata = NULL;
5073 if (XBUFFER (w->contents) != current_buffer)
5075 old_buffer = current_buffer;
5076 set_buffer_internal (XBUFFER (w->contents));
5078 else
5079 old_buffer = NULL;
5081 /* In case W->start is out of the accessible range, do something
5082 reasonable. This happens in Info mode when Info-scroll-down
5083 calls (recenter -1) while W->start is 1. */
5084 if (charpos < BEGV)
5085 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5086 else if (charpos > ZV)
5087 SET_TEXT_POS (start, ZV, ZV_BYTE);
5088 else
5089 SET_TEXT_POS_FROM_MARKER (start, w->start);
5091 itdata = bidi_shelve_cache ();
5092 start_display (&it, w, start);
5093 move_it_vertically (&it, height);
5094 bottom_y = line_bottom_y (&it);
5095 bidi_unshelve_cache (itdata, 0);
5097 /* rms: On a non-window display,
5098 the value of it.vpos at the bottom of the screen
5099 seems to be 1 larger than window_box_height (w).
5100 This kludge fixes a bug whereby (move-to-window-line -1)
5101 when ZV is on the last screen line
5102 moves to the previous screen line instead of the last one. */
5103 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5104 height++;
5106 /* Add in empty lines at the bottom of the window. */
5107 if (bottom_y < height)
5109 int uy = FRAME_LINE_HEIGHT (it.f);
5110 it.vpos += (height - bottom_y + uy - 1) / uy;
5113 if (old_buffer)
5114 set_buffer_internal (old_buffer);
5116 return it.vpos;
5120 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5121 doc: /* Center point in selected window and maybe redisplay frame.
5122 With a numeric prefix argument ARG, recenter putting point on screen line ARG
5123 relative to the selected window. If ARG is negative, it counts up from the
5124 bottom of the window. (ARG should be less than the height of the window.)
5126 If ARG is omitted or nil, then recenter with point on the middle line of
5127 the selected window; if the variable `recenter-redisplay' is non-nil,
5128 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5129 is set to `grow-only', this resets the tool-bar's height to the minimum
5130 height needed); if `recenter-redisplay' has the special value `tty',
5131 then only tty frames are redrawn.
5133 Just C-u as prefix means put point in the center of the window
5134 and redisplay normally--don't erase and redraw the frame. */)
5135 (register Lisp_Object arg)
5137 struct window *w = XWINDOW (selected_window);
5138 struct buffer *buf = XBUFFER (w->contents);
5139 struct buffer *obuf = current_buffer;
5140 bool center_p = 0;
5141 ptrdiff_t charpos, bytepos;
5142 EMACS_INT iarg IF_LINT (= 0);
5143 int this_scroll_margin;
5145 /* If redisplay is suppressed due to an error, try again. */
5146 obuf->display_error_modiff = 0;
5148 if (NILP (arg))
5150 if (!NILP (Vrecenter_redisplay)
5151 && (!EQ (Vrecenter_redisplay, Qtty)
5152 || !NILP (Ftty_type (selected_frame))))
5154 ptrdiff_t i;
5156 /* Invalidate pixel data calculated for all compositions. */
5157 for (i = 0; i < n_compositions; i++)
5158 composition_table[i]->font = NULL;
5160 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5162 Fredraw_frame (WINDOW_FRAME (w));
5163 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5166 center_p = 1;
5168 else if (CONSP (arg)) /* Just C-u. */
5169 center_p = 1;
5170 else
5172 arg = Fprefix_numeric_value (arg);
5173 CHECK_NUMBER (arg);
5174 iarg = XINT (arg);
5177 set_buffer_internal (buf);
5179 /* Do this after making BUF current
5180 in case scroll_margin is buffer-local. */
5181 this_scroll_margin =
5182 max (0, min (scroll_margin, w->total_lines / 4));
5184 /* Handle centering on a graphical frame specially. Such frames can
5185 have variable-height lines and centering point on the basis of
5186 line counts would lead to strange effects. */
5187 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5189 if (center_p)
5191 struct it it;
5192 struct text_pos pt;
5193 void *itdata = bidi_shelve_cache ();
5195 SET_TEXT_POS (pt, PT, PT_BYTE);
5196 start_display (&it, w, pt);
5197 move_it_vertically_backward (&it, window_box_height (w) / 2);
5198 charpos = IT_CHARPOS (it);
5199 bytepos = IT_BYTEPOS (it);
5200 bidi_unshelve_cache (itdata, 0);
5202 else if (iarg < 0)
5204 struct it it;
5205 struct text_pos pt;
5206 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
5207 int extra_line_spacing;
5208 int h = window_box_height (w);
5209 void *itdata = bidi_shelve_cache ();
5211 iarg = - max (-iarg, this_scroll_margin);
5213 SET_TEXT_POS (pt, PT, PT_BYTE);
5214 start_display (&it, w, pt);
5216 /* Be sure we have the exact height of the full line containing PT. */
5217 move_it_by_lines (&it, 0);
5219 /* The amount of pixels we have to move back is the window
5220 height minus what's displayed in the line containing PT,
5221 and the lines below. */
5222 it.current_y = 0;
5223 it.vpos = 0;
5224 move_it_by_lines (&it, nlines);
5226 if (it.vpos == nlines)
5227 h -= it.current_y;
5228 else
5230 /* Last line has no newline */
5231 h -= line_bottom_y (&it);
5232 it.vpos++;
5235 /* Don't reserve space for extra line spacing of last line. */
5236 extra_line_spacing = it.max_extra_line_spacing;
5238 /* If we can't move down NLINES lines because we hit
5239 the end of the buffer, count in some empty lines. */
5240 if (it.vpos < nlines)
5242 nlines -= it.vpos;
5243 extra_line_spacing = it.extra_line_spacing;
5244 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5246 if (h <= 0)
5248 bidi_unshelve_cache (itdata, 0);
5249 return Qnil;
5252 /* Now find the new top line (starting position) of the window. */
5253 start_display (&it, w, pt);
5254 it.current_y = 0;
5255 move_it_vertically_backward (&it, h);
5257 /* If extra line spacing is present, we may move too far
5258 back. This causes the last line to be only partially
5259 visible (which triggers redisplay to recenter that line
5260 in the middle), so move forward.
5261 But ignore extra line spacing on last line, as it is not
5262 considered to be part of the visible height of the line.
5264 h += extra_line_spacing;
5265 while (-it.current_y > h)
5266 move_it_by_lines (&it, 1);
5268 charpos = IT_CHARPOS (it);
5269 bytepos = IT_BYTEPOS (it);
5271 bidi_unshelve_cache (itdata, 0);
5273 else
5275 struct position pos;
5277 iarg = max (iarg, this_scroll_margin);
5279 pos = *vmotion (PT, PT_BYTE, -iarg, w);
5280 charpos = pos.bufpos;
5281 bytepos = pos.bytepos;
5284 else
5286 struct position pos;
5287 int ht = window_internal_height (w);
5289 if (center_p)
5290 iarg = ht / 2;
5291 else if (iarg < 0)
5292 iarg += ht;
5294 /* Don't let it get into the margin at either top or bottom. */
5295 iarg = clip_to_bounds (this_scroll_margin, iarg,
5296 ht - this_scroll_margin - 1);
5298 pos = *vmotion (PT, PT_BYTE, - iarg, w);
5299 charpos = pos.bufpos;
5300 bytepos = pos.bytepos;
5303 /* Set the new window start. */
5304 set_marker_both (w->start, w->contents, charpos, bytepos);
5305 w->window_end_valid = 0;
5307 w->optional_new_start = 1;
5309 w->start_at_line_beg = (bytepos == BEGV_BYTE ||
5310 FETCH_BYTE (bytepos - 1) == '\n');
5312 set_buffer_internal (obuf);
5313 return Qnil;
5316 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5317 0, 1, 0,
5318 doc: /* Return the height in lines of the text display area of WINDOW.
5319 WINDOW must be a live window and defaults to the selected one.
5321 The returned height does not include the mode line, any header line,
5322 nor any partial-height lines at the bottom of the text area. */)
5323 (Lisp_Object window)
5325 struct window *w = decode_live_window (window);
5326 int pixel_height = window_box_height (w);
5327 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5328 return make_number (line_height);
5333 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5334 1, 1, "P",
5335 doc: /* Position point relative to window.
5336 ARG nil means position point at center of window.
5337 Else, ARG specifies vertical position within the window;
5338 zero means top of window, negative means relative to bottom of window. */)
5339 (Lisp_Object arg)
5341 struct window *w = XWINDOW (selected_window);
5342 int lines, start;
5343 Lisp_Object window;
5344 #if 0
5345 int this_scroll_margin;
5346 #endif
5348 if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer))
5349 /* This test is needed to make sure PT/PT_BYTE make sense in w->contents
5350 when passed below to set_marker_both. */
5351 error ("move-to-window-line called from unrelated buffer");
5353 window = selected_window;
5354 start = marker_position (w->start);
5355 if (start < BEGV || start > ZV)
5357 int height = window_internal_height (w);
5358 Fvertical_motion (make_number (- (height / 2)), window);
5359 set_marker_both (w->start, w->contents, PT, PT_BYTE);
5360 w->start_at_line_beg = !NILP (Fbolp ());
5361 w->force_start = 1;
5363 else
5364 Fgoto_char (w->start);
5366 lines = displayed_window_lines (w);
5368 #if 0
5369 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
5370 #endif
5372 if (NILP (arg))
5373 XSETFASTINT (arg, lines / 2);
5374 else
5376 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
5378 if (iarg < 0)
5379 iarg = iarg + lines;
5381 #if 0 /* This code would prevent move-to-window-line from moving point
5382 to a place inside the scroll margins (which would cause the
5383 next redisplay to scroll). I wrote this code, but then concluded
5384 it is probably better not to install it. However, it is here
5385 inside #if 0 so as not to lose it. -- rms. */
5387 /* Don't let it get into the margin at either top or bottom. */
5388 iarg = max (iarg, this_scroll_margin);
5389 iarg = min (iarg, lines - this_scroll_margin - 1);
5390 #endif
5392 arg = make_number (iarg);
5395 /* Skip past a partially visible first line. */
5396 if (w->vscroll)
5397 XSETINT (arg, XINT (arg) + 1);
5399 return Fvertical_motion (arg, window);
5404 /***********************************************************************
5405 Window Configuration
5406 ***********************************************************************/
5408 struct save_window_data
5410 struct vectorlike_header header;
5411 Lisp_Object selected_frame;
5412 Lisp_Object current_window;
5413 Lisp_Object current_buffer;
5414 Lisp_Object minibuf_scroll_window;
5415 Lisp_Object minibuf_selected_window;
5416 Lisp_Object root_window;
5417 Lisp_Object focus_frame;
5418 /* A vector, each of whose elements is a struct saved_window
5419 for one window. */
5420 Lisp_Object saved_windows;
5422 /* All fields above are traced by the GC.
5423 From `fame-cols' down, the fields are ignored by the GC. */
5425 int frame_cols, frame_lines, frame_menu_bar_lines;
5426 int frame_tool_bar_lines;
5429 /* This is saved as a Lisp_Vector */
5430 struct saved_window
5432 struct vectorlike_header header;
5434 Lisp_Object window, buffer, start, pointm, mark;
5435 Lisp_Object left_col, top_line, total_cols, total_lines;
5436 Lisp_Object normal_cols, normal_lines;
5437 Lisp_Object hscroll, min_hscroll;
5438 Lisp_Object parent, prev;
5439 Lisp_Object start_at_line_beg;
5440 Lisp_Object display_table;
5441 Lisp_Object left_margin_cols, right_margin_cols;
5442 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5443 Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
5444 Lisp_Object combination_limit, window_parameters;
5447 #define SAVED_WINDOW_N(swv,n) \
5448 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5450 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5451 doc: /* Return t if OBJECT is a window-configuration object. */)
5452 (Lisp_Object object)
5454 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5457 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5458 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5459 (Lisp_Object config)
5461 register struct save_window_data *data;
5462 struct Lisp_Vector *saved_windows;
5464 CHECK_WINDOW_CONFIGURATION (config);
5466 data = (struct save_window_data *) XVECTOR (config);
5467 saved_windows = XVECTOR (data->saved_windows);
5468 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5471 DEFUN ("set-window-configuration", Fset_window_configuration,
5472 Sset_window_configuration, 1, 1, 0,
5473 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5474 CONFIGURATION must be a value previously returned
5475 by `current-window-configuration' (which see).
5476 If CONFIGURATION was made from a frame that is now deleted,
5477 only frame-independent values can be restored. In this case,
5478 the return value is nil. Otherwise the value is t. */)
5479 (Lisp_Object configuration)
5481 register struct save_window_data *data;
5482 struct Lisp_Vector *saved_windows;
5483 Lisp_Object new_current_buffer;
5484 Lisp_Object frame;
5485 struct frame *f;
5486 ptrdiff_t old_point = -1;
5488 CHECK_WINDOW_CONFIGURATION (configuration);
5490 data = (struct save_window_data *) XVECTOR (configuration);
5491 saved_windows = XVECTOR (data->saved_windows);
5493 new_current_buffer = data->current_buffer;
5494 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5495 new_current_buffer = Qnil;
5496 else
5498 if (XBUFFER (new_current_buffer) == current_buffer)
5499 /* The code further down "preserves point" by saving here PT in
5500 old_point and then setting it later back into PT. When the
5501 current-selected-window and the final-selected-window both show
5502 the current buffer, this suffers from the problem that the
5503 current PT is the window-point of the current-selected-window,
5504 while the final PT is the point of the final-selected-window, so
5505 this copy from one PT to the other would end up moving the
5506 window-point of the final-selected-window to the window-point of
5507 the current-selected-window. So we have to be careful which
5508 point of the current-buffer we copy into old_point. */
5509 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
5510 && WINDOWP (selected_window)
5511 && EQ (XWINDOW (selected_window)->contents, new_current_buffer)
5512 && !EQ (selected_window, data->current_window))
5513 old_point = marker_position (XWINDOW (data->current_window)->pointm);
5514 else
5515 old_point = PT;
5516 else
5517 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5518 point in new_current_buffer as of the last time this buffer was
5519 used. This can be non-deterministic since it can be changed by
5520 things like jit-lock by mere temporary selection of some random
5521 window that happens to show this buffer.
5522 So if possible we want this arbitrary choice of "which point" to
5523 be the one from the to-be-selected-window so as to prevent this
5524 window's cursor from being copied from another window. */
5525 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
5526 /* If current_window = selected_window, its point is in BUF_PT. */
5527 && !EQ (selected_window, data->current_window))
5528 old_point = marker_position (XWINDOW (data->current_window)->pointm);
5529 else
5530 old_point = BUF_PT (XBUFFER (new_current_buffer));
5533 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5534 f = XFRAME (frame);
5536 /* If f is a dead frame, don't bother rebuilding its window tree.
5537 However, there is other stuff we should still try to do below. */
5538 if (FRAME_LIVE_P (f))
5540 Lisp_Object window;
5541 Lisp_Object dead_windows = Qnil;
5542 register Lisp_Object tem, par, pers;
5543 register struct window *w;
5544 register struct saved_window *p;
5545 struct window *root_window;
5546 struct window **leaf_windows;
5547 int n_leaf_windows;
5548 ptrdiff_t k;
5549 int i, n;
5551 /* If the frame has been resized since this window configuration was
5552 made, we change the frame to the size specified in the
5553 configuration, restore the configuration, and then resize it
5554 back. We keep track of the prevailing height in these variables. */
5555 int previous_frame_lines = FRAME_LINES (f);
5556 int previous_frame_cols = FRAME_COLS (f);
5557 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5558 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5560 /* Don't do this within the main loop below: This may call Lisp
5561 code and is thus potentially unsafe while input is blocked. */
5562 for (k = 0; k < saved_windows->header.size; k++)
5564 p = SAVED_WINDOW_N (saved_windows, k);
5565 window = p->window;
5566 w = XWINDOW (window);
5567 if (BUFFERP (w->contents)
5568 && !EQ (w->contents, p->buffer)
5569 && BUFFER_LIVE_P (XBUFFER (p->buffer)))
5570 /* If a window we restore gets another buffer, record the
5571 window's old buffer. */
5572 call1 (Qrecord_window_buffer, window);
5575 /* The mouse highlighting code could get screwed up
5576 if it runs during this. */
5577 block_input ();
5579 if (data->frame_lines != previous_frame_lines
5580 || data->frame_cols != previous_frame_cols)
5581 change_frame_size (f, data->frame_lines,
5582 data->frame_cols, 0, 0, 0);
5583 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5584 if (data->frame_menu_bar_lines
5585 != previous_frame_menu_bar_lines)
5586 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
5587 make_number (0));
5588 #ifdef HAVE_WINDOW_SYSTEM
5589 if (data->frame_tool_bar_lines
5590 != previous_frame_tool_bar_lines)
5591 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
5592 make_number (0));
5593 #endif
5594 #endif
5596 /* "Swap out" point from the selected window's buffer
5597 into the window itself. (Normally the pointm of the selected
5598 window holds garbage.) We do this now, before
5599 restoring the window contents, and prevent it from
5600 being done later on when we select a new window. */
5601 if (! NILP (XWINDOW (selected_window)->contents))
5603 w = XWINDOW (selected_window);
5604 set_marker_both (w->pointm,
5605 w->contents,
5606 BUF_PT (XBUFFER (w->contents)),
5607 BUF_PT_BYTE (XBUFFER (w->contents)));
5610 windows_or_buffers_changed++;
5611 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5613 /* Problem: Freeing all matrices and later allocating them again
5614 is a serious redisplay flickering problem. What we would
5615 really like to do is to free only those matrices not reused
5616 below. */
5617 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5618 leaf_windows = alloca (count_windows (root_window)
5619 * sizeof *leaf_windows);
5620 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5622 /* Kludge Alert!
5623 Mark all windows now on frame as "deleted".
5624 Restoring the new configuration "undeletes" any that are in it.
5626 Save their current buffers in their height fields, since we may
5627 need it later, if a buffer saved in the configuration is now
5628 dead. */
5629 delete_all_child_windows (FRAME_ROOT_WINDOW (f));
5631 for (k = 0; k < saved_windows->header.size; k++)
5633 p = SAVED_WINDOW_N (saved_windows, k);
5634 window = p->window;
5635 w = XWINDOW (window);
5636 wset_next (w, Qnil);
5638 if (!NILP (p->parent))
5639 wset_parent
5640 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window);
5641 else
5642 wset_parent (w, Qnil);
5644 if (!NILP (p->prev))
5646 wset_prev
5647 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window);
5648 wset_next (XWINDOW (w->prev), p->window);
5650 else
5652 wset_prev (w, Qnil);
5653 if (!NILP (w->parent))
5654 wset_combination (XWINDOW (w->parent),
5655 (XINT (p->total_cols)
5656 != XWINDOW (w->parent)->total_cols),
5657 p->window);
5660 /* If we squirreled away the buffer, restore it now. */
5661 if (BUFFERP (w->combination_limit))
5662 wset_buffer (w, w->combination_limit);
5663 w->left_col = XFASTINT (p->left_col);
5664 w->top_line = XFASTINT (p->top_line);
5665 w->total_cols = XFASTINT (p->total_cols);
5666 w->total_lines = XFASTINT (p->total_lines);
5667 wset_normal_cols (w, p->normal_cols);
5668 wset_normal_lines (w, p->normal_lines);
5669 w->hscroll = XFASTINT (p->hscroll);
5670 w->min_hscroll = XFASTINT (p->min_hscroll);
5671 wset_display_table (w, p->display_table);
5672 w->left_margin_cols = XINT (p->left_margin_cols);
5673 w->right_margin_cols = XINT (p->right_margin_cols);
5674 w->left_fringe_width = XINT (p->left_fringe_width);
5675 w->right_fringe_width = XINT (p->right_fringe_width);
5676 w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
5677 wset_scroll_bar_width (w, p->scroll_bar_width);
5678 wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
5679 wset_dedicated (w, p->dedicated);
5680 wset_combination_limit (w, p->combination_limit);
5681 /* Restore any window parameters that have been saved.
5682 Parameters that have not been saved are left alone. */
5683 for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
5685 pers = XCAR (tem);
5686 if (CONSP (pers))
5688 if (NILP (XCDR (pers)))
5690 par = Fassq (XCAR (pers), w->window_parameters);
5691 if (CONSP (par) && !NILP (XCDR (par)))
5692 /* Reset a parameter to nil if and only if it
5693 has a non-nil association. Don't make new
5694 associations. */
5695 Fsetcdr (par, Qnil);
5697 else
5698 /* Always restore a non-nil value. */
5699 Fset_window_parameter (window, XCAR (pers), XCDR (pers));
5703 if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
5704 /* If saved buffer is alive, install it. */
5706 wset_buffer (w, p->buffer);
5707 w->start_at_line_beg = !NILP (p->start_at_line_beg);
5708 set_marker_restricted (w->start, p->start, w->contents);
5709 set_marker_restricted (w->pointm, p->pointm,
5710 w->contents);
5711 Fset_marker (BVAR (XBUFFER (w->contents), mark),
5712 p->mark, w->contents);
5714 /* As documented in Fcurrent_window_configuration, don't
5715 restore the location of point in the buffer which was
5716 current when the window configuration was recorded. */
5717 if (!EQ (p->buffer, new_current_buffer)
5718 && XBUFFER (p->buffer) == current_buffer)
5719 Fgoto_char (w->pointm);
5721 else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
5722 /* Keep window's old buffer; make sure the markers are real. */
5724 /* Set window markers at start of visible range. */
5725 if (XMARKER (w->start)->buffer == 0)
5726 set_marker_restricted_both (w->start, w->contents, 0, 0);
5727 if (XMARKER (w->pointm)->buffer == 0)
5728 set_marker_restricted_both
5729 (w->pointm, w->contents,
5730 BUF_PT (XBUFFER (w->contents)),
5731 BUF_PT_BYTE (XBUFFER (w->contents)));
5732 w->start_at_line_beg = 1;
5734 else if (!NILP (w->start))
5735 /* Leaf window has no live buffer, get one. */
5737 /* Get the buffer via other_buffer_safely in order to
5738 avoid showing an unimportant buffer and, if necessary, to
5739 recreate *scratch* in the course (part of Juanma's bs-show
5740 scenario from March 2011). */
5741 wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
5742 /* This will set the markers to beginning of visible
5743 range. */
5744 set_marker_restricted_both (w->start, w->contents, 0, 0);
5745 set_marker_restricted_both (w->pointm, w->contents, 0, 0);
5746 w->start_at_line_beg = 1;
5747 if (!NILP (w->dedicated))
5748 /* Record this window as dead. */
5749 dead_windows = Fcons (window, dead_windows);
5750 /* Make sure window is no more dedicated. */
5751 wset_dedicated (w, Qnil);
5755 fset_root_window (f, data->root_window);
5756 /* Arrange *not* to restore point in the buffer that was
5757 current when the window configuration was saved. */
5758 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
5759 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5760 make_number (old_point),
5761 XWINDOW (data->current_window)->contents);
5763 /* In the following call to `select-window', prevent "swapping out
5764 point" in the old selected window using the buffer that has
5765 been restored into it. We already swapped out that point from
5766 that window's old buffer. */
5767 select_window (data->current_window, Qnil, 1);
5768 BVAR (XBUFFER (XWINDOW (selected_window)->contents), last_selected_window)
5769 = selected_window;
5771 if (NILP (data->focus_frame)
5772 || (FRAMEP (data->focus_frame)
5773 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5774 Fredirect_frame_focus (frame, data->focus_frame);
5776 /* Set the screen height to the value it had before this function. */
5777 if (previous_frame_lines != FRAME_LINES (f)
5778 || previous_frame_cols != FRAME_COLS (f))
5779 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5780 0, 0, 0);
5781 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5782 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5783 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5784 make_number (0));
5785 #ifdef HAVE_WINDOW_SYSTEM
5786 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5787 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5788 make_number (0));
5789 #endif
5790 #endif
5792 /* Now, free glyph matrices in windows that were not reused. */
5793 for (i = n = 0; i < n_leaf_windows; ++i)
5795 if (NILP (leaf_windows[i]->contents))
5796 free_window_matrices (leaf_windows[i]);
5797 else if (EQ (leaf_windows[i]->contents, new_current_buffer))
5798 ++n;
5801 adjust_glyphs (f);
5802 unblock_input ();
5804 /* Scan dead buffer windows. */
5805 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
5807 window = XCAR (dead_windows);
5808 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
5809 delete_deletable_window (window);
5812 /* Fselect_window will have made f the selected frame, so we
5813 reselect the proper frame here. Fhandle_switch_frame will change the
5814 selected window too, but that doesn't make the call to
5815 Fselect_window above totally superfluous; it still sets f's
5816 selected window. */
5817 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5818 do_switch_frame (data->selected_frame, 0, 0, Qnil);
5820 run_window_configuration_change_hook (f);
5823 if (!NILP (new_current_buffer))
5825 Fset_buffer (new_current_buffer);
5826 /* If the new current buffer doesn't appear in the selected
5827 window, go to its old point (see bug#12208). */
5828 if (!EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
5829 Fgoto_char (make_number (old_point));
5832 Vminibuf_scroll_window = data->minibuf_scroll_window;
5833 minibuf_selected_window = data->minibuf_selected_window;
5835 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5838 void
5839 restore_window_configuration (Lisp_Object configuration)
5841 Fset_window_configuration (configuration);
5845 /* If WINDOW is an internal window, recursively delete all child windows
5846 reachable via the next and contents slots of WINDOW. Otherwise setup
5847 WINDOW to not show any buffer. */
5849 void
5850 delete_all_child_windows (Lisp_Object window)
5852 register struct window *w;
5854 w = XWINDOW (window);
5856 if (!NILP (w->next))
5857 /* Delete WINDOW's siblings (we traverse postorderly). */
5858 delete_all_child_windows (w->next);
5860 if (WINDOWP (w->contents))
5862 delete_all_child_windows (w->contents);
5863 wset_combination (w, 0, Qnil);
5865 else if (BUFFERP (w->contents))
5867 unshow_buffer (w);
5868 unchain_marker (XMARKER (w->pointm));
5869 unchain_marker (XMARKER (w->start));
5870 /* Since combination limit makes sense for an internal windows
5871 only, we use this slot to save the buffer for the sake of
5872 possible resurrection in Fset_window_configuration. */
5873 wset_combination_limit (w, w->contents);
5874 wset_buffer (w, Qnil);
5877 Vwindow_list = Qnil;
5880 static int
5881 count_windows (register struct window *window)
5883 register int count = 1;
5884 if (!NILP (window->next))
5885 count += count_windows (XWINDOW (window->next));
5886 if (WINDOWP (window->contents))
5887 count += count_windows (XWINDOW (window->contents));
5888 return count;
5892 /* Fill vector FLAT with leaf windows under W, starting at index I.
5893 Value is last index + 1. */
5894 static int
5895 get_leaf_windows (struct window *w, struct window **flat, int i)
5897 while (w)
5899 if (WINDOWP (w->contents))
5900 i = get_leaf_windows (XWINDOW (w->contents), flat, i);
5901 else
5902 flat[i++] = w;
5904 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5907 return i;
5911 /* Return a pointer to the glyph W's physical cursor is on. Value is
5912 null if W's current matrix is invalid, so that no meaningful glyph
5913 can be returned. */
5914 struct glyph *
5915 get_phys_cursor_glyph (struct window *w)
5917 struct glyph_row *row;
5918 struct glyph *glyph;
5919 int hpos = w->phys_cursor.hpos;
5921 if (!(w->phys_cursor.vpos >= 0
5922 && w->phys_cursor.vpos < w->current_matrix->nrows))
5923 return NULL;
5925 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5926 if (!row->enabled_p)
5927 return NULL;
5929 if (w->hscroll)
5931 /* When the window is hscrolled, cursor hpos can legitimately be
5932 out of bounds, but we draw the cursor at the corresponding
5933 window margin in that case. */
5934 if (!row->reversed_p && hpos < 0)
5935 hpos = 0;
5936 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
5937 hpos = row->used[TEXT_AREA] - 1;
5940 if (0 <= hpos && hpos < row->used[TEXT_AREA])
5941 glyph = row->glyphs[TEXT_AREA] + hpos;
5942 else
5943 glyph = NULL;
5945 return glyph;
5949 static int
5950 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
5952 register struct saved_window *p;
5953 register struct window *w;
5954 register Lisp_Object tem, pers, par;
5956 for (; !NILP (window); window = w->next)
5958 p = SAVED_WINDOW_N (vector, i);
5959 w = XWINDOW (window);
5961 wset_temslot (w, make_number (i)); i++;
5962 p->window = window;
5963 p->buffer = (WINDOW_LEAF_P (w) ? w->contents : Qnil);
5964 p->left_col = make_number (w->left_col);
5965 p->top_line = make_number (w->top_line);
5966 p->total_cols = make_number (w->total_cols);
5967 p->total_lines = make_number (w->total_lines);
5968 p->normal_cols = w->normal_cols;
5969 p->normal_lines = w->normal_lines;
5970 XSETFASTINT (p->hscroll, w->hscroll);
5971 XSETFASTINT (p->min_hscroll, w->min_hscroll);
5972 p->display_table = w->display_table;
5973 p->left_margin_cols = make_number (w->left_margin_cols);
5974 p->right_margin_cols = make_number (w->right_margin_cols);
5975 p->left_fringe_width = make_number (w->left_fringe_width);
5976 p->right_fringe_width = make_number (w->right_fringe_width);
5977 p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
5978 p->scroll_bar_width = w->scroll_bar_width;
5979 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
5980 p->dedicated = w->dedicated;
5981 p->combination_limit = w->combination_limit;
5982 p->window_parameters = Qnil;
5984 if (!NILP (Vwindow_persistent_parameters))
5986 /* Run cycle detection on Vwindow_persistent_parameters. */
5987 Lisp_Object tortoise, hare;
5989 hare = tortoise = Vwindow_persistent_parameters;
5990 while (CONSP (hare))
5992 hare = XCDR (hare);
5993 if (!CONSP (hare))
5994 break;
5996 hare = XCDR (hare);
5997 tortoise = XCDR (tortoise);
5999 if (EQ (hare, tortoise))
6000 /* Reset Vwindow_persistent_parameters to Qnil. */
6002 Vwindow_persistent_parameters = Qnil;
6003 break;
6007 for (tem = Vwindow_persistent_parameters; CONSP (tem);
6008 tem = XCDR (tem))
6010 pers = XCAR (tem);
6011 /* Save values for persistent window parameters. */
6012 if (CONSP (pers) && !NILP (XCDR (pers)))
6014 par = Fassq (XCAR (pers), w->window_parameters);
6015 if (NILP (par))
6016 /* If the window has no value for the parameter,
6017 make one. */
6018 p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
6019 p->window_parameters);
6020 else
6021 /* If the window has a value for the parameter,
6022 save it. */
6023 p->window_parameters = Fcons (Fcons (XCAR (par),
6024 XCDR (par)),
6025 p->window_parameters);
6030 if (BUFFERP (w->contents))
6032 /* Save w's value of point in the window configuration. If w
6033 is the selected window, then get the value of point from
6034 the buffer; pointm is garbage in the selected window. */
6035 if (EQ (window, selected_window))
6036 p->pointm = build_marker (XBUFFER (w->contents),
6037 BUF_PT (XBUFFER (w->contents)),
6038 BUF_PT_BYTE (XBUFFER (w->contents)));
6039 else
6040 p->pointm = Fcopy_marker (w->pointm, Qnil);
6041 XMARKER (p->pointm)->insertion_type
6042 = !NILP (Vwindow_point_insertion_type);
6044 p->start = Fcopy_marker (w->start, Qnil);
6045 p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
6047 tem = BVAR (XBUFFER (w->contents), mark);
6048 p->mark = Fcopy_marker (tem, Qnil);
6050 else
6052 p->pointm = Qnil;
6053 p->start = Qnil;
6054 p->mark = Qnil;
6055 p->start_at_line_beg = Qnil;
6058 if (NILP (w->parent))
6059 p->parent = Qnil;
6060 else
6061 p->parent = XWINDOW (w->parent)->temslot;
6063 if (NILP (w->prev))
6064 p->prev = Qnil;
6065 else
6066 p->prev = XWINDOW (w->prev)->temslot;
6068 if (WINDOWP (w->contents))
6069 i = save_window_save (w->contents, vector, i);
6072 return i;
6075 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6076 Scurrent_window_configuration, 0, 1, 0,
6077 doc: /* Return an object representing the current window configuration of FRAME.
6078 If FRAME is nil or omitted, use the selected frame.
6079 This describes the number of windows, their sizes and current buffers,
6080 and for each displayed buffer, where display starts, and the positions of
6081 point and mark. An exception is made for point in the current buffer:
6082 its value is -not- saved.
6083 This also records the currently selected frame, and FRAME's focus
6084 redirection (see `redirect-frame-focus'). The variable
6085 `window-persistent-parameters' specifies which window parameters are
6086 saved by this function. */)
6087 (Lisp_Object frame)
6089 register Lisp_Object tem;
6090 register int n_windows;
6091 register struct save_window_data *data;
6092 register int i;
6093 struct frame *f = decode_live_frame (frame);
6095 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6096 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6097 PVEC_WINDOW_CONFIGURATION);
6099 data->frame_cols = FRAME_COLS (f);
6100 data->frame_lines = FRAME_LINES (f);
6101 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6102 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6103 data->selected_frame = selected_frame;
6104 data->current_window = FRAME_SELECTED_WINDOW (f);
6105 XSETBUFFER (data->current_buffer, current_buffer);
6106 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6107 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6108 data->root_window = FRAME_ROOT_WINDOW (f);
6109 data->focus_frame = FRAME_FOCUS_FRAME (f);
6110 tem = make_uninit_vector (n_windows);
6111 data->saved_windows = tem;
6112 for (i = 0; i < n_windows; i++)
6113 ASET (tem, i,
6114 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil));
6115 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6116 XSETWINDOW_CONFIGURATION (tem, data);
6117 return (tem);
6120 /***********************************************************************
6121 Marginal Areas
6122 ***********************************************************************/
6124 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6125 2, 3, 0,
6126 doc: /* Set width of marginal areas of window WINDOW.
6127 WINDOW must be a live window and defaults to the selected one.
6129 Second arg LEFT-WIDTH specifies the number of character cells to
6130 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6131 does the same for the right marginal area. A nil width parameter
6132 means no margin.
6134 Return t if any margin was actually changed and nil otherwise. */)
6135 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6137 struct window *w = decode_live_window (window);
6138 int left, right;
6140 /* FIXME: what about margins that are too wide? */
6142 left = (NILP (left_width) ? 0
6143 : (CHECK_NATNUM (left_width), XINT (left_width)));
6144 right = (NILP (right_width) ? 0
6145 : (CHECK_NATNUM (right_width), XINT (right_width)));
6147 if (w->left_margin_cols != left || w->right_margin_cols != right)
6149 w->left_margin_cols = left;
6150 w->right_margin_cols = right;
6152 adjust_window_margins (w);
6154 ++windows_or_buffers_changed;
6155 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6156 return Qt;
6159 return Qnil;
6163 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6164 0, 1, 0,
6165 doc: /* Get width of marginal areas of window WINDOW.
6166 WINDOW must be a live window and defaults to the selected one.
6168 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6169 If a marginal area does not exist, its width will be returned
6170 as nil. */)
6171 (Lisp_Object window)
6173 struct window *w = decode_live_window (window);
6174 return Fcons (w->left_margin_cols ? make_number (w->left_margin_cols) : Qnil,
6175 w->right_margin_cols ? make_number (w->right_margin_cols) : Qnil);
6180 /***********************************************************************
6181 Fringes
6182 ***********************************************************************/
6184 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6185 2, 4, 0,
6186 doc: /* Set the fringe widths of window WINDOW.
6187 WINDOW must be a live window and defaults to the selected one.
6189 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6190 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6191 fringe width. If a fringe width arg is nil, that means to use the
6192 frame's default fringe width. Default fringe widths can be set with
6193 the command `set-fringe-style'.
6194 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6195 outside of the display margins. By default, fringes are drawn between
6196 display marginal areas and the text area.
6198 Return t if any fringe was actually changed and nil otherwise. */)
6199 (Lisp_Object window, Lisp_Object left_width,
6200 Lisp_Object right_width, Lisp_Object outside_margins)
6202 struct window *w = decode_live_window (window);
6203 int left, right, outside = !NILP (outside_margins);
6205 left = (NILP (left_width) ? -1
6206 : (CHECK_NATNUM (left_width), XINT (left_width)));
6207 right = (NILP (right_width) ? -1
6208 : (CHECK_NATNUM (right_width), XINT (right_width)));
6210 /* Do nothing on a tty or if nothing to actually change. */
6211 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6212 && (w->left_fringe_width != left
6213 || w->right_fringe_width != right
6214 || w->fringes_outside_margins != outside))
6216 w->left_fringe_width = left;
6217 w->right_fringe_width = right;
6218 w->fringes_outside_margins = outside;
6220 adjust_window_margins (w);
6222 clear_glyph_matrix (w->current_matrix);
6223 w->window_end_valid = 0;
6225 ++windows_or_buffers_changed;
6226 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6227 return Qt;
6230 return Qnil;
6234 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6235 0, 1, 0,
6236 doc: /* Get width of fringes of window WINDOW.
6237 WINDOW must be a live window and defaults to the selected one.
6239 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6240 (Lisp_Object window)
6242 struct window *w = decode_live_window (window);
6244 return list3 (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6245 make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6246 WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil);
6251 /***********************************************************************
6252 Scroll bars
6253 ***********************************************************************/
6255 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
6256 Sset_window_scroll_bars, 2, 4, 0,
6257 doc: /* Set width and type of scroll bars of window WINDOW.
6258 WINDOW must be a live window and defaults to the selected one.
6260 Second parameter WIDTH specifies the pixel width for the scroll bar;
6261 this is automatically adjusted to a multiple of the frame column width.
6262 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6263 bar: left, right, or nil.
6264 If WIDTH is nil, use the frame's scroll-bar width.
6265 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6266 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6267 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, Lisp_Object horizontal_type)
6269 struct window *w = decode_live_window (window);
6271 if (!NILP (width))
6273 CHECK_RANGED_INTEGER (width, 0, INT_MAX);
6275 if (XINT (width) == 0)
6276 vertical_type = Qnil;
6279 if (!(NILP (vertical_type)
6280 || EQ (vertical_type, Qleft)
6281 || EQ (vertical_type, Qright)
6282 || EQ (vertical_type, Qt)))
6283 error ("Invalid type of vertical scroll bar");
6285 if (!EQ (w->scroll_bar_width, width)
6286 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6288 wset_scroll_bar_width (w, width);
6289 wset_vertical_scroll_bar_type (w, vertical_type);
6291 adjust_window_margins (w);
6293 clear_glyph_matrix (w->current_matrix);
6294 w->window_end_valid = 0;
6296 ++windows_or_buffers_changed;
6297 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6300 return Qnil;
6304 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6305 0, 1, 0,
6306 doc: /* Get width and type of scroll bars of window WINDOW.
6307 WINDOW must be a live window and defaults to the selected one.
6309 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6310 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6311 value. */)
6312 (Lisp_Object window)
6314 struct window *w = decode_live_window (window);
6316 return list4 (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6317 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6318 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6319 make_number (WINDOW_SCROLL_BAR_COLS (w)),
6320 w->vertical_scroll_bar_type, Qnil);
6325 /***********************************************************************
6326 Smooth scrolling
6327 ***********************************************************************/
6329 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6330 doc: /* Return the amount by which WINDOW is scrolled vertically.
6331 If WINDOW is omitted or nil, it defaults to the selected window.
6332 Normally, value is a multiple of the canonical character height of WINDOW;
6333 optional second arg PIXELS-P means value is measured in pixels. */)
6334 (Lisp_Object window, Lisp_Object pixels_p)
6336 Lisp_Object result;
6337 struct window *w = decode_live_window (window);
6338 struct frame *f = XFRAME (w->frame);
6340 if (FRAME_WINDOW_P (f))
6341 result = (NILP (pixels_p)
6342 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6343 : make_number (-w->vscroll));
6344 else
6345 result = make_number (0);
6346 return result;
6350 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6351 2, 3, 0,
6352 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6353 WINDOW nil means use the selected window. Normally, VSCROLL is a
6354 non-negative multiple of the canonical character height of WINDOW;
6355 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6356 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6357 corresponds to an integral number of pixels. The return value is the
6358 result of this rounding.
6359 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6360 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
6362 struct window *w = decode_live_window (window);
6363 struct frame *f = XFRAME (w->frame);
6365 CHECK_NUMBER_OR_FLOAT (vscroll);
6367 if (FRAME_WINDOW_P (f))
6369 int old_dy = w->vscroll;
6371 w->vscroll = - (NILP (pixels_p)
6372 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6373 : XFLOATINT (vscroll));
6374 w->vscroll = min (w->vscroll, 0);
6376 if (w->vscroll != old_dy)
6378 /* Adjust glyph matrix of the frame if the virtual display
6379 area becomes larger than before. */
6380 if (w->vscroll < 0 && w->vscroll < old_dy)
6381 adjust_glyphs (f);
6383 /* Prevent redisplay shortcuts. */
6384 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
6388 return Fwindow_vscroll (window, pixels_p);
6392 /* Call FN for all leaf windows on frame F. FN is called with the
6393 first argument being a pointer to the leaf window, and with
6394 additional argument USER_DATA. Stops when FN returns 0. */
6396 static void
6397 foreach_window (struct frame *f, int (*fn) (struct window *, void *),
6398 void *user_data)
6400 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6401 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6402 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6406 /* Helper function for foreach_window. Call FN for all leaf windows
6407 reachable from W. FN is called with the first argument being a
6408 pointer to the leaf window, and with additional argument USER_DATA.
6409 Stop when FN returns 0. Value is 0 if stopped by FN. */
6411 static int
6412 foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
6414 int cont;
6416 for (cont = 1; w && cont;)
6418 if (WINDOWP (w->contents))
6419 cont = foreach_window_1 (XWINDOW (w->contents), fn, user_data);
6420 else
6421 cont = fn (w, user_data);
6423 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6426 return cont;
6429 /***********************************************************************
6430 Initialization
6431 ***********************************************************************/
6433 /* Return 1 if window configurations CONFIGURATION1 and CONFIGURATION2
6434 describe the same state of affairs. This is used by Fequal.
6436 IGNORE_POSITIONS means ignore non-matching scroll positions
6437 and the like.
6439 This ignores a couple of things like the dedication status of
6440 window, combination_limit and the like. This might have to be
6441 fixed. */
6443 bool
6444 compare_window_configurations (Lisp_Object configuration1,
6445 Lisp_Object configuration2,
6446 bool ignore_positions)
6448 register struct save_window_data *d1, *d2;
6449 struct Lisp_Vector *sws1, *sws2;
6450 ptrdiff_t i;
6452 CHECK_WINDOW_CONFIGURATION (configuration1);
6453 CHECK_WINDOW_CONFIGURATION (configuration2);
6455 d1 = (struct save_window_data *) XVECTOR (configuration1);
6456 d2 = (struct save_window_data *) XVECTOR (configuration2);
6457 sws1 = XVECTOR (d1->saved_windows);
6458 sws2 = XVECTOR (d2->saved_windows);
6460 /* Frame settings must match. */
6461 if (d1->frame_cols != d2->frame_cols
6462 || d1->frame_lines != d2->frame_lines
6463 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
6464 || !EQ (d1->selected_frame, d2->selected_frame)
6465 || !EQ (d1->current_buffer, d2->current_buffer)
6466 || (!ignore_positions
6467 && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
6468 || !EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)))
6469 || !EQ (d1->focus_frame, d2->focus_frame)
6470 /* Verify that the two configurations have the same number of windows. */
6471 || sws1->header.size != sws2->header.size)
6472 return 0;
6474 for (i = 0; i < sws1->header.size; i++)
6476 struct saved_window *sw1, *sw2;
6478 sw1 = SAVED_WINDOW_N (sws1, i);
6479 sw2 = SAVED_WINDOW_N (sws2, i);
6481 if (
6482 /* The "current" windows in the two configurations must
6483 correspond to each other. */
6484 EQ (d1->current_window, sw1->window)
6485 != EQ (d2->current_window, sw2->window)
6486 /* Windows' buffers must match. */
6487 || !EQ (sw1->buffer, sw2->buffer)
6488 || !EQ (sw1->left_col, sw2->left_col)
6489 || !EQ (sw1->top_line, sw2->top_line)
6490 || !EQ (sw1->total_cols, sw2->total_cols)
6491 || !EQ (sw1->total_lines, sw2->total_lines)
6492 || !EQ (sw1->display_table, sw2->display_table)
6493 /* The next two disjuncts check the window structure for
6494 equality. */
6495 || !EQ (sw1->parent, sw2->parent)
6496 || !EQ (sw1->prev, sw2->prev)
6497 || (!ignore_positions
6498 && (!EQ (sw1->hscroll, sw2->hscroll)
6499 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
6500 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
6501 || NILP (Fequal (sw1->start, sw2->start))
6502 || NILP (Fequal (sw1->pointm, sw2->pointm))
6503 || NILP (Fequal (sw1->mark, sw2->mark))))
6504 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
6505 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
6506 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
6507 || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
6508 || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
6509 || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
6510 || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type))
6511 return 0;
6514 return 1;
6517 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6518 Scompare_window_configurations, 2, 2, 0,
6519 doc: /* Compare two window configurations as regards the structure of windows.
6520 This function ignores details such as the values of point and mark
6521 and scrolling positions. */)
6522 (Lisp_Object x, Lisp_Object y)
6524 if (compare_window_configurations (x, y, 1))
6525 return Qt;
6526 return Qnil;
6529 void
6530 init_window_once (void)
6532 struct frame *f = make_initial_frame ();
6533 XSETFRAME (selected_frame, f);
6534 Vterminal_frame = selected_frame;
6535 minibuf_window = f->minibuffer_window;
6536 selected_window = f->selected_window;
6537 last_nonminibuf_frame = f;
6539 window_initialized = 1;
6542 void
6543 init_window (void)
6545 Vwindow_list = Qnil;
6548 void
6549 syms_of_window (void)
6551 DEFSYM (Qscroll_up, "scroll-up");
6552 DEFSYM (Qscroll_down, "scroll-down");
6553 DEFSYM (Qscroll_command, "scroll-command");
6555 Fput (Qscroll_up, Qscroll_command, Qt);
6556 Fput (Qscroll_down, Qscroll_command, Qt);
6558 DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
6559 DEFSYM (Qwindowp, "windowp");
6560 DEFSYM (Qwindow_configuration_p, "window-configuration-p");
6561 DEFSYM (Qwindow_live_p, "window-live-p");
6562 DEFSYM (Qwindow_valid_p, "window-valid-p");
6563 DEFSYM (Qwindow_deletable_p, "window-deletable-p");
6564 DEFSYM (Qdelete_window, "delete-window");
6565 DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
6566 DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
6567 DEFSYM (Qsafe, "safe");
6568 DEFSYM (Qdisplay_buffer, "display-buffer");
6569 DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
6570 DEFSYM (Qrecord_window_buffer, "record-window-buffer");
6571 DEFSYM (Qget_mru_window, "get-mru-window");
6572 DEFSYM (Qwindow_size, "window-size");
6573 DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6574 DEFSYM (Qabove, "above");
6575 DEFSYM (Qbelow, "below");
6576 DEFSYM (Qclone_of, "clone-of");
6578 staticpro (&Vwindow_list);
6580 minibuf_selected_window = Qnil;
6581 staticpro (&minibuf_selected_window);
6583 window_scroll_pixel_based_preserve_x = -1;
6584 window_scroll_pixel_based_preserve_y = -1;
6585 window_scroll_preserve_hpos = -1;
6586 window_scroll_preserve_vpos = -1;
6588 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
6589 doc: /* Non-nil means call as function to display a help buffer.
6590 The function is called with one argument, the buffer to be displayed.
6591 Used by `with-output-to-temp-buffer'.
6592 If this function is used, then it must do the entire job of showing
6593 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6594 Vtemp_buffer_show_function = Qnil;
6596 DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
6597 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6598 Vminibuf_scroll_window = Qnil;
6600 DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
6601 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6602 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6603 is displayed in the `mode-line' face. */);
6604 mode_line_in_non_selected_windows = 1;
6606 DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
6607 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6608 Vother_window_scroll_buffer = Qnil;
6610 DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
6611 doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
6612 auto_window_vscroll_p = 1;
6614 DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
6615 doc: /* Number of lines of continuity when scrolling by screenfuls. */);
6616 next_screen_context_lines = 2;
6618 DEFVAR_LISP ("scroll-preserve-screen-position",
6619 Vscroll_preserve_screen_position,
6620 doc: /* Controls if scroll commands move point to keep its screen position unchanged.
6621 A value of nil means point does not keep its screen position except
6622 at the scroll margin or window boundary respectively.
6623 A value of t means point keeps its screen position if the scroll
6624 command moved it vertically out of the window, e.g. when scrolling
6625 by full screens.
6626 Any other value means point always keeps its screen position.
6627 Scroll commands should have the `scroll-command' property
6628 on their symbols to be controlled by this variable. */);
6629 Vscroll_preserve_screen_position = Qnil;
6631 DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
6632 doc: /* Type of marker to use for `window-point'. */);
6633 Vwindow_point_insertion_type = Qnil;
6635 DEFVAR_LISP ("window-configuration-change-hook",
6636 Vwindow_configuration_change_hook,
6637 doc: /* Functions to call when window configuration changes.
6638 The buffer-local part is run once per window, with the relevant window
6639 selected; while the global part is run only once for the modified frame,
6640 with the relevant frame selected. */);
6641 Vwindow_configuration_change_hook = Qnil;
6643 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
6644 doc: /* Non-nil means `recenter' redraws entire frame.
6645 If this option is non-nil, then the `recenter' command with a nil
6646 argument will redraw the entire frame; the special value `tty' causes
6647 the frame to be redrawn only if it is a tty frame. */);
6648 Vrecenter_redisplay = Qtty;
6650 DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
6651 doc: /* If t, resize window combinations proportionally.
6652 If this variable is nil, splitting a window gets the entire screen space
6653 for displaying the new window from the window to split. Deleting and
6654 resizing a window preferably resizes one adjacent window only.
6656 If this variable is t, splitting a window tries to get the space
6657 proportionally from all windows in the same combination. This also
6658 allows to split a window that is otherwise too small or of fixed size.
6659 Resizing and deleting a window proportionally resize all windows in the
6660 same combination.
6662 Other values are reserved for future use.
6664 This variable takes no effect if the variable `window-combination-limit' is
6665 non-nil. */);
6666 Vwindow_combination_resize = Qnil;
6668 DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
6669 doc: /* If non-nil, splitting a window makes a new parent window.
6670 The following values are recognized:
6672 nil means splitting a window will create a new parent window only if the
6673 window has no parent window or the window shall become part of a
6674 combination orthogonal to the one it is part of.
6676 `window-size' means that splitting a window for displaying a buffer
6677 makes a new parent window provided `display-buffer' is supposed to
6678 explicitly set the window's size due to the presence of a
6679 `window-height' or `window-width' entry in the alist used by
6680 `display-buffer'. Otherwise, this value is handled like nil.
6682 `temp-buffer' means that splitting a window for displaying a temporary
6683 buffer always makes a new parent window. Otherwise, this value is
6684 handled like nil.
6686 `display-buffer' means that splitting a window for displaying a buffer
6687 always makes a new parent window. Since temporary buffers are
6688 displayed by the function `display-buffer', this value is stronger
6689 than `temp-buffer'. Splitting a window for other purpose makes a
6690 new parent window only if needed.
6692 t means that splitting a window always creates a new parent window. If
6693 all splits behave this way, each frame's window tree is a binary
6694 tree and every window but the frame's root window has exactly one
6695 sibling.
6697 Other values are reserved for future use. */);
6698 Vwindow_combination_limit = Qwindow_size;
6700 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
6701 doc: /* Alist of persistent window parameters.
6702 This alist specifies which window parameters shall get saved by
6703 `current-window-configuration' and `window-state-get' and subsequently
6704 restored to their previous values by `set-window-configuration' and
6705 `window-state-put'.
6707 The car of each entry of this alist is the symbol specifying the
6708 parameter. The cdr is one of the following:
6710 nil means the parameter is neither saved by `window-state-get' nor by
6711 `current-window-configuration'.
6713 t means the parameter is saved by `current-window-configuration' and,
6714 provided its WRITABLE argument is nil, by `window-state-get'.
6716 The symbol `writable' means the parameter is saved unconditionally by
6717 both `current-window-configuration' and `window-state-get'. Do not use
6718 this value for parameters without read syntax (like windows or frames).
6720 Parameters not saved by `current-window-configuration' or
6721 `window-state-get' are left alone by `set-window-configuration'
6722 respectively are not installed by `window-state-put'. */);
6723 Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
6725 defsubr (&Sselected_window);
6726 defsubr (&Sminibuffer_window);
6727 defsubr (&Swindow_minibuffer_p);
6728 defsubr (&Swindowp);
6729 defsubr (&Swindow_valid_p);
6730 defsubr (&Swindow_live_p);
6731 defsubr (&Swindow_frame);
6732 defsubr (&Sframe_root_window);
6733 defsubr (&Sframe_first_window);
6734 defsubr (&Sframe_selected_window);
6735 defsubr (&Sset_frame_selected_window);
6736 defsubr (&Spos_visible_in_window_p);
6737 defsubr (&Swindow_line_height);
6738 defsubr (&Swindow_buffer);
6739 defsubr (&Swindow_parent);
6740 defsubr (&Swindow_top_child);
6741 defsubr (&Swindow_left_child);
6742 defsubr (&Swindow_next_sibling);
6743 defsubr (&Swindow_prev_sibling);
6744 defsubr (&Swindow_combination_limit);
6745 defsubr (&Sset_window_combination_limit);
6746 defsubr (&Swindow_use_time);
6747 defsubr (&Swindow_top_line);
6748 defsubr (&Swindow_left_column);
6749 defsubr (&Swindow_total_height);
6750 defsubr (&Swindow_total_width);
6751 defsubr (&Swindow_normal_size);
6752 defsubr (&Swindow_new_total);
6753 defsubr (&Swindow_new_normal);
6754 defsubr (&Sset_window_new_total);
6755 defsubr (&Sset_window_new_normal);
6756 defsubr (&Swindow_resize_apply);
6757 defsubr (&Swindow_body_height);
6758 defsubr (&Swindow_body_width);
6759 defsubr (&Swindow_hscroll);
6760 defsubr (&Sset_window_hscroll);
6761 defsubr (&Swindow_redisplay_end_trigger);
6762 defsubr (&Sset_window_redisplay_end_trigger);
6763 defsubr (&Swindow_edges);
6764 defsubr (&Swindow_pixel_edges);
6765 defsubr (&Swindow_absolute_pixel_edges);
6766 defsubr (&Swindow_inside_edges);
6767 defsubr (&Swindow_inside_pixel_edges);
6768 defsubr (&Swindow_inside_absolute_pixel_edges);
6769 defsubr (&Scoordinates_in_window_p);
6770 defsubr (&Swindow_at);
6771 defsubr (&Swindow_point);
6772 defsubr (&Swindow_start);
6773 defsubr (&Swindow_end);
6774 defsubr (&Sset_window_point);
6775 defsubr (&Sset_window_start);
6776 defsubr (&Swindow_dedicated_p);
6777 defsubr (&Sset_window_dedicated_p);
6778 defsubr (&Swindow_display_table);
6779 defsubr (&Sset_window_display_table);
6780 defsubr (&Snext_window);
6781 defsubr (&Sprevious_window);
6782 defsubr (&Sget_buffer_window);
6783 defsubr (&Sdelete_other_windows_internal);
6784 defsubr (&Sdelete_window_internal);
6785 defsubr (&Sresize_mini_window_internal);
6786 defsubr (&Sset_window_buffer);
6787 defsubr (&Srun_window_configuration_change_hook);
6788 defsubr (&Sselect_window);
6789 defsubr (&Sforce_window_update);
6790 defsubr (&Ssplit_window_internal);
6791 defsubr (&Sscroll_up);
6792 defsubr (&Sscroll_down);
6793 defsubr (&Sscroll_left);
6794 defsubr (&Sscroll_right);
6795 defsubr (&Sother_window_for_scrolling);
6796 defsubr (&Sscroll_other_window);
6797 defsubr (&Sminibuffer_selected_window);
6798 defsubr (&Srecenter);
6799 defsubr (&Swindow_text_height);
6800 defsubr (&Smove_to_window_line);
6801 defsubr (&Swindow_configuration_p);
6802 defsubr (&Swindow_configuration_frame);
6803 defsubr (&Sset_window_configuration);
6804 defsubr (&Scurrent_window_configuration);
6805 defsubr (&Sset_window_margins);
6806 defsubr (&Swindow_margins);
6807 defsubr (&Sset_window_fringes);
6808 defsubr (&Swindow_fringes);
6809 defsubr (&Sset_window_scroll_bars);
6810 defsubr (&Swindow_scroll_bars);
6811 defsubr (&Swindow_vscroll);
6812 defsubr (&Sset_window_vscroll);
6813 defsubr (&Scompare_window_configurations);
6814 defsubr (&Swindow_list);
6815 defsubr (&Swindow_list_1);
6816 defsubr (&Swindow_prev_buffers);
6817 defsubr (&Sset_window_prev_buffers);
6818 defsubr (&Swindow_next_buffers);
6819 defsubr (&Sset_window_next_buffers);
6820 defsubr (&Swindow_parameters);
6821 defsubr (&Swindow_parameter);
6822 defsubr (&Sset_window_parameter);
6825 void
6826 keys_of_window (void)
6828 initial_define_key (control_x_map, '<', "scroll-left");
6829 initial_define_key (control_x_map, '>', "scroll-right");
6831 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
6832 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6833 initial_define_key (meta_map, 'v', "scroll-down-command");