* doc/lispref/frames.texi (Display Feature Testing): Add indexes.
[emacs.git] / src / window.c
blob47a7b58ba9b4caa08452a527c5c7e6a8d7c67102
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_left_fringe_width (struct window *w, Lisp_Object val)
156 w->left_fringe_width = val;
158 static void
159 wset_left_margin_cols (struct window *w, Lisp_Object val)
161 w->left_margin_cols = val;
163 static void
164 wset_new_normal (struct window *w, Lisp_Object val)
166 w->new_normal = val;
168 static void
169 wset_new_total (struct window *w, Lisp_Object val)
171 w->new_total = val;
173 static void
174 wset_normal_cols (struct window *w, Lisp_Object val)
176 w->normal_cols = val;
178 static void
179 wset_normal_lines (struct window *w, Lisp_Object val)
181 w->normal_lines = val;
183 static void
184 wset_parent (struct window *w, Lisp_Object val)
186 w->parent = val;
188 static void
189 wset_pointm (struct window *w, Lisp_Object val)
191 w->pointm = val;
193 static void
194 wset_right_fringe_width (struct window *w, Lisp_Object val)
196 w->right_fringe_width = val;
198 static void
199 wset_right_margin_cols (struct window *w, Lisp_Object val)
201 w->right_margin_cols = val;
203 static void
204 wset_scroll_bar_width (struct window *w, Lisp_Object val)
206 w->scroll_bar_width = val;
208 static void
209 wset_start (struct window *w, Lisp_Object val)
211 w->start = val;
213 static void
214 wset_temslot (struct window *w, Lisp_Object val)
216 w->temslot = val;
218 static void
219 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
221 w->vertical_scroll_bar_type = val;
223 static void
224 wset_window_parameters (struct window *w, Lisp_Object val)
226 w->window_parameters = val;
228 static void
229 wset_combination (struct window *w, bool horflag, Lisp_Object val)
231 /* Since leaf windows never becomes non-leaf, there should
232 be no buffer and markers in start and pointm fields of W. */
233 eassert (!BUFFERP (w->contents) && NILP (w->start) && NILP (w->pointm));
234 w->contents = val;
235 /* When an internal window is deleted and VAL is nil, HORFLAG
236 is meaningless. */
237 if (!NILP (val))
238 w->horizontal = horflag;
241 /* Nonzero if leaf window W doesn't reflect the actual state
242 of displayed buffer due to its text or overlays change. */
244 bool
245 window_outdated (struct window *w)
247 struct buffer *b = XBUFFER (w->contents);
248 return (w->last_modified < BUF_MODIFF (b)
249 || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b));
252 struct window *
253 decode_live_window (register Lisp_Object window)
255 if (NILP (window))
256 return XWINDOW (selected_window);
258 CHECK_LIVE_WINDOW (window);
259 return XWINDOW (window);
262 struct window *
263 decode_any_window (register Lisp_Object window)
265 struct window *w;
267 if (NILP (window))
268 return XWINDOW (selected_window);
270 CHECK_WINDOW (window);
271 w = XWINDOW (window);
272 return w;
275 static struct window *
276 decode_valid_window (register Lisp_Object window)
278 struct window *w;
280 if (NILP (window))
281 return XWINDOW (selected_window);
283 CHECK_VALID_WINDOW (window);
284 w = XWINDOW (window);
285 return w;
288 /* Called when W's buffer slot is changed. ARG -1 means that W is about to
289 cease its buffer, and 1 means that W is about to set up the new one. */
291 static void
292 adjust_window_count (struct window *w, int arg)
294 eassert (eabs (arg) == 1);
295 if (BUFFERP (w->contents))
297 struct buffer *b = XBUFFER (w->contents);
299 if (b->base_buffer)
300 b = b->base_buffer;
301 b->window_count += arg;
302 eassert (b->window_count >= 0);
303 /* These should be recalculated by redisplay code. */
304 w->window_end_valid = 0;
305 w->base_line_pos = 0;
309 /* Set W's buffer slot to VAL and recompute number
310 of windows showing VAL if it is a buffer. */
312 void
313 wset_buffer (struct window *w, Lisp_Object val)
315 adjust_window_count (w, -1);
316 if (BUFFERP (val))
317 /* Make sure that we do not assign the buffer
318 to an internal window. */
319 eassert (MARKERP (w->start) && MARKERP (w->pointm));
320 w->contents = val;
321 adjust_window_count (w, 1);
324 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
325 doc: /* Return t if OBJECT is a window and nil otherwise. */)
326 (Lisp_Object object)
328 return WINDOWP (object) ? Qt : Qnil;
331 DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
332 doc: /* Return t if OBJECT is a valid window and nil otherwise.
333 A valid window is either a window that displays a buffer or an internal
334 window. Deleted windows are not live. */)
335 (Lisp_Object object)
337 return WINDOW_VALID_P (object) ? Qt : Qnil;
340 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
341 doc: /* Return t if OBJECT is a live window and nil otherwise.
342 A live window is a window that displays a buffer.
343 Internal windows and deleted windows are not live. */)
344 (Lisp_Object object)
346 return WINDOW_LIVE_P (object) ? Qt : Qnil;
349 /* Frames and windows. */
350 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 0, 1, 0,
351 doc: /* Return the frame that window WINDOW is on.
352 WINDOW must be a valid window and defaults to the selected one. */)
353 (Lisp_Object window)
355 return decode_valid_window (window)->frame;
358 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
359 doc: /* Return the root window of FRAME-OR-WINDOW.
360 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
361 With a frame argument, return that frame's root window.
362 With a window argument, return the root window of that window's frame. */)
363 (Lisp_Object frame_or_window)
365 Lisp_Object window;
367 if (NILP (frame_or_window))
368 window = SELECTED_FRAME ()->root_window;
369 else if (WINDOW_VALID_P (frame_or_window))
370 window = XFRAME (XWINDOW (frame_or_window)->frame)->root_window;
371 else
373 CHECK_LIVE_FRAME (frame_or_window);
374 window = XFRAME (frame_or_window)->root_window;
377 return window;
380 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
381 doc: /* Return the minibuffer window for frame FRAME.
382 If FRAME is omitted or nil, it defaults to the selected frame. */)
383 (Lisp_Object frame)
385 return FRAME_MINIBUF_WINDOW (decode_live_frame (frame));
388 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
389 Swindow_minibuffer_p, 0, 1, 0,
390 doc: /* Return non-nil if WINDOW is a minibuffer window.
391 WINDOW must be a valid window and defaults to the selected one. */)
392 (Lisp_Object window)
394 return MINI_WINDOW_P (decode_valid_window (window)) ? Qt : Qnil;
397 /* Don't move this to window.el - this must be a safe routine. */
398 DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
399 doc: /* Return the topmost, leftmost live window on FRAME-OR-WINDOW.
400 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
401 Else if FRAME-OR-WINDOW denotes a valid window, return the first window
402 of that window's frame. If FRAME-OR-WINDOW denotes a live frame, return
403 the first window of that frame. */)
404 (Lisp_Object frame_or_window)
406 Lisp_Object window;
408 if (NILP (frame_or_window))
409 window = SELECTED_FRAME ()->root_window;
410 else if (WINDOW_VALID_P (frame_or_window))
411 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
412 else
414 CHECK_LIVE_FRAME (frame_or_window);
415 window = XFRAME (frame_or_window)->root_window;
418 while (WINDOWP (XWINDOW (window)->contents))
419 window = XWINDOW (window)->contents;
421 return window;
424 DEFUN ("frame-selected-window", Fframe_selected_window,
425 Sframe_selected_window, 0, 1, 0,
426 doc: /* Return the selected window of FRAME-OR-WINDOW.
427 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
428 Else if FRAME-OR-WINDOW denotes a valid window, return the selected
429 window of that window's frame. If FRAME-OR-WINDOW denotes a live frame,
430 return the selected window of that frame. */)
431 (Lisp_Object frame_or_window)
433 Lisp_Object window;
435 if (NILP (frame_or_window))
436 window = SELECTED_FRAME ()->selected_window;
437 else if (WINDOW_VALID_P (frame_or_window))
438 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
439 else
441 CHECK_LIVE_FRAME (frame_or_window);
442 window = XFRAME (frame_or_window)->selected_window;
445 return window;
448 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
449 Sset_frame_selected_window, 2, 3, 0,
450 doc: /* Set selected window of FRAME to WINDOW.
451 FRAME must be a live frame and defaults to the selected one. If FRAME
452 is the selected frame, this makes WINDOW the selected window. Optional
453 argument NORECORD non-nil means to neither change the order of recently
454 selected windows nor the buffer list. WINDOW must denote a live window.
455 Return WINDOW. */)
456 (Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
458 if (NILP (frame))
459 frame = selected_frame;
461 CHECK_LIVE_FRAME (frame);
462 CHECK_LIVE_WINDOW (window);
464 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
465 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
467 if (EQ (frame, selected_frame))
468 return Fselect_window (window, norecord);
469 else
471 fset_selected_window (XFRAME (frame), window);
472 return window;
476 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
477 doc: /* Return the selected window.
478 The selected window is the window in which the standard cursor for
479 selected windows appears and to which many commands apply. */)
480 (void)
482 return selected_window;
485 int window_select_count;
487 /* If select_window is called with inhibit_point_swap non-zero it will
488 not store point of the old selected window's buffer back into that
489 window's pointm slot. This is needed by Fset_window_configuration to
490 avoid that the display routine is called with selected_window set to
491 Qnil causing a subsequent crash. */
492 static Lisp_Object
493 select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
495 register struct window *w;
496 struct frame *sf;
498 CHECK_LIVE_WINDOW (window);
500 w = XWINDOW (window);
502 /* Make the selected window's buffer current. */
503 Fset_buffer (w->contents);
505 if (EQ (window, selected_window) && !inhibit_point_swap)
506 /* `switch-to-buffer' uses (select-window (selected-window)) as a "clever"
507 way to call record_buffer from Elisp, so it's important that we call
508 record_buffer before returning here. */
509 goto record_and_return;
511 sf = SELECTED_FRAME ();
512 if (XFRAME (WINDOW_FRAME (w)) != sf)
514 fset_selected_window (XFRAME (WINDOW_FRAME (w)), window);
515 /* Use this rather than Fhandle_switch_frame
516 so that FRAME_FOCUS_FRAME is moved appropriately as we
517 move around in the state where a minibuffer in a separate
518 frame is active. */
519 Fselect_frame (WINDOW_FRAME (w), norecord);
520 /* Fselect_frame called us back so we've done all the work already. */
521 eassert (EQ (window, selected_window));
522 return window;
524 else
525 fset_selected_window (sf, window);
527 select_window_1 (window, inhibit_point_swap);
528 bset_last_selected_window (XBUFFER (w->contents), window);
529 windows_or_buffers_changed++;
531 record_and_return:
532 /* record_buffer can run QUIT, so make sure it is run only after we have
533 re-established the invariant between selected_window and selected_frame,
534 otherwise the temporary broken invariant might "escape" (bug#14161). */
535 if (NILP (norecord))
537 w->use_time = ++window_select_count;
538 record_buffer (w->contents);
541 return window;
544 /* Select window with a minimum of fuss, i.e. don't record the change anywhere
545 (not even for redisplay's benefit), and assume that the window's frame is
546 already selected. */
547 static void
548 select_window_1 (Lisp_Object window, bool inhibit_point_swap)
550 /* Store the old selected window's buffer's point in pointm of the old
551 selected window. It belongs to that window, and when the window is
552 not selected, must be in the window. */
553 if (!inhibit_point_swap)
555 struct window *ow = XWINDOW (selected_window);
556 if (BUFFERP (ow->contents))
557 set_marker_both (ow->pointm, ow->contents,
558 BUF_PT (XBUFFER (ow->contents)),
559 BUF_PT_BYTE (XBUFFER (ow->contents)));
562 selected_window = window;
564 /* Go to the point recorded in the window.
565 This is important when the buffer is in more
566 than one window. It also matters when
567 redisplay_window has altered point after scrolling,
568 because it makes the change only in the window. */
570 register ptrdiff_t new_point = marker_position (XWINDOW (window)->pointm);
571 if (new_point < BEGV)
572 SET_PT (BEGV);
573 else if (new_point > ZV)
574 SET_PT (ZV);
575 else
576 SET_PT (new_point);
580 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
581 doc: /* Select WINDOW which must be a live window.
582 Also make WINDOW's frame the selected frame and WINDOW that frame's
583 selected window. In addition, make WINDOW's buffer current and set that
584 buffer's value of `point' to the value of WINDOW's `window-point'.
585 Return WINDOW.
587 Optional second arg NORECORD non-nil means do not put this buffer at the
588 front of the buffer list and do not make this window the most recently
589 selected one.
591 Note that the main editor command loop sets the current buffer to the
592 buffer of the selected window before each command. */)
593 (register Lisp_Object window, Lisp_Object norecord)
595 return select_window (window, norecord, 0);
598 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
599 doc: /* Return the buffer displayed in window WINDOW.
600 If WINDOW is omitted or nil, it defaults to the selected window.
601 Return nil for an internal window or a deleted window. */)
602 (Lisp_Object window)
604 struct window *w = decode_any_window (window);
605 return WINDOW_LEAF_P (w) ? w->contents : Qnil;
608 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
609 doc: /* Return the parent window of window WINDOW.
610 WINDOW must be a valid window and defaults to the selected one.
611 Return nil for a window with no parent (e.g. a root window). */)
612 (Lisp_Object window)
614 return decode_valid_window (window)->parent;
617 DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 0, 1, 0,
618 doc: /* Return the topmost child window of window WINDOW.
619 WINDOW must be a valid window and defaults to the selected one.
620 Return nil if WINDOW is a live window (live windows have no children).
621 Return nil if WINDOW is an internal window whose children form a
622 horizontal combination. */)
623 (Lisp_Object window)
625 struct window *w = decode_valid_window (window);
626 return WINDOW_VERTICAL_COMBINATION_P (w) ? w->contents : Qnil;
629 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
630 doc: /* Return the leftmost child window of window WINDOW.
631 WINDOW must be a valid window and defaults to the selected one.
632 Return nil if WINDOW is a live window (live windows have no children).
633 Return nil if WINDOW is an internal window whose children form a
634 vertical combination. */)
635 (Lisp_Object window)
637 struct window *w = decode_valid_window (window);
638 return WINDOW_HORIZONTAL_COMBINATION_P (w) ? w->contents : Qnil;
641 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
642 doc: /* Return the next sibling window of window WINDOW.
643 WINDOW must be a valid window and defaults to the selected one.
644 Return nil if WINDOW has no next sibling. */)
645 (Lisp_Object window)
647 return decode_valid_window (window)->next;
650 DEFUN ("window-prev-sibling", Fwindow_prev_sibling, Swindow_prev_sibling, 0, 1, 0,
651 doc: /* Return the previous sibling window of window WINDOW.
652 WINDOW must be a valid window and defaults to the selected one.
653 Return nil if WINDOW has no previous sibling. */)
654 (Lisp_Object window)
656 return decode_valid_window (window)->prev;
659 DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
660 doc: /* Return combination limit of window WINDOW.
661 WINDOW must be a valid window used in horizontal or vertical combination.
662 If the return value is nil, child windows of WINDOW can be recombined with
663 WINDOW's siblings. A return value of t means that child windows of
664 WINDOW are never \(re-)combined with WINDOW's siblings. */)
665 (Lisp_Object window)
667 struct window *w;
669 CHECK_VALID_WINDOW (window);
670 w = XWINDOW (window);
671 if (WINDOW_LEAF_P (w))
672 error ("Combination limit is meaningful for internal windows only");
673 return w->combination_limit;
676 DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
677 doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
678 WINDOW must be a valid window used in horizontal or vertical combination.
679 If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
680 siblings. LIMIT t means that child windows of WINDOW are never
681 \(re-)combined with WINDOW's siblings. Other values are reserved for
682 future use. */)
683 (Lisp_Object window, Lisp_Object limit)
685 struct window *w;
687 CHECK_VALID_WINDOW (window);
688 w = XWINDOW (window);
689 if (WINDOW_LEAF_P (w))
690 error ("Combination limit is meaningful for internal windows only");
691 wset_combination_limit (w, limit);
692 return limit;
695 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
696 doc: /* Return the use time of window WINDOW.
697 WINDOW must be a live window and defaults to the selected one.
698 The window with the highest use time is the most recently selected
699 one. The window with the lowest use time is the least recently
700 selected one. */)
701 (Lisp_Object window)
703 return make_number (decode_live_window (window)->use_time);
706 DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 1, 0,
707 doc: /* Return the total height, in lines, of window WINDOW.
708 WINDOW must be a valid window and defaults to the selected one.
710 The return value includes the mode line and header line, if any.
711 If WINDOW is an internal window, the total height is the height
712 of the screen areas spanned by its children.
714 On a graphical display, this total height is reported as an
715 integer multiple of the default character height. */)
716 (Lisp_Object window)
718 return make_number (decode_valid_window (window)->total_lines);
721 DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 1, 0,
722 doc: /* Return the total width, in columns, of window WINDOW.
723 WINDOW must be a valid window and defaults to the selected one.
725 The return value includes any vertical dividers or scroll bars
726 belonging to WINDOW. If WINDOW is an internal window, the total width
727 is the width of the screen areas spanned by its children.
729 On a graphical display, this total width is reported as an
730 integer multiple of the default character width. */)
731 (Lisp_Object window)
733 return make_number (decode_valid_window (window)->total_cols);
736 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
737 doc: /* Return the new total size of window WINDOW.
738 WINDOW must be a valid window and defaults to the selected one. */)
739 (Lisp_Object window)
741 return decode_valid_window (window)->new_total;
744 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
745 doc: /* Return the normal height of window WINDOW.
746 WINDOW must be a valid window and defaults to the selected one.
747 If HORIZONTAL is non-nil, return the normal width of WINDOW. */)
748 (Lisp_Object window, Lisp_Object horizontal)
750 struct window *w = decode_valid_window (window);
752 return NILP (horizontal) ? w->normal_lines : w->normal_cols;
755 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
756 doc: /* Return new normal size of window WINDOW.
757 WINDOW must be a valid window and defaults to the selected one. */)
758 (Lisp_Object window)
760 return decode_valid_window (window)->new_normal;
763 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
764 doc: /* Return left column of window WINDOW.
765 This is the distance, in columns, between the left edge of WINDOW and
766 the left edge of the frame's window area. For instance, the return
767 value is 0 if there is no window to the left of WINDOW.
769 WINDOW must be a valid window and defaults to the selected one. */)
770 (Lisp_Object window)
772 return make_number (decode_valid_window (window)->left_col);
775 DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
776 doc: /* Return top line of window WINDOW.
777 This is the distance, in lines, between the top of WINDOW and the top
778 of the frame's window area. For instance, the return value is 0 if
779 there is no window above WINDOW.
781 WINDOW must be a valid window and defaults to the selected one. */)
782 (Lisp_Object window)
784 return make_number (decode_valid_window (window)->top_line);
787 /* Return the number of lines of W's body. Don't count any mode or
788 header line of W. */
790 static int
791 window_body_lines (struct window *w)
793 int height = w->total_lines;
795 if (!MINI_WINDOW_P (w))
797 if (WINDOW_WANTS_MODELINE_P (w))
798 --height;
799 if (WINDOW_WANTS_HEADER_LINE_P (w))
800 --height;
803 return height;
806 /* Return the number of columns of W's body. Don't count columns
807 occupied by the scroll bar or the vertical bar separating W from its
808 right sibling. On window-systems don't count fringes or display
809 margins either. */
812 window_body_cols (struct window *w)
814 struct frame *f = XFRAME (WINDOW_FRAME (w));
815 int width = w->total_cols;
817 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
818 /* Scroll bars occupy a few columns. */
819 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
820 else if (!FRAME_WINDOW_P (f)
821 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
822 /* The column of `|' characters separating side-by-side windows
823 occupies one column only. */
824 width -= 1;
826 /* Display margins cannot be used for normal text. */
827 width -= WINDOW_LEFT_MARGIN_COLS (w) + WINDOW_RIGHT_MARGIN_COLS (w);
829 if (FRAME_WINDOW_P (f))
830 /* On window-systems, fringes cannot be used for normal text. */
831 width -= WINDOW_FRINGE_COLS (w);
833 return width;
836 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 1, 0,
837 doc: /* Return the height, in lines, of WINDOW's text area.
838 WINDOW must be a live window and defaults to the selected one.
840 The returned height does not include the mode line or header line.
841 On a graphical display, the height is expressed as an integer multiple
842 of the default character height. If a line at the bottom of the text
843 area is only partially visible, that counts as a whole line; to
844 exclude partially-visible lines, use `window-text-height'. */)
845 (Lisp_Object window)
847 return make_number (window_body_lines (decode_live_window (window)));
850 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 1, 0,
851 doc: /* Return the width, in columns, of WINDOW's text area.
852 WINDOW must be a live window and defaults to the selected one.
854 The return value does not include any vertical dividers, fringe or
855 marginal areas, or scroll bars. On a graphical display, the width is
856 expressed as an integer multiple of the default character width. */)
857 (Lisp_Object window)
859 return make_number (window_body_cols (decode_live_window (window)));
862 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
863 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
864 WINDOW must be a live window and defaults to the selected one. */)
865 (Lisp_Object window)
867 return make_number (decode_live_window (window)->hscroll);
870 /* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
871 range, returning the new amount as a fixnum. */
872 static Lisp_Object
873 set_window_hscroll (struct window *w, EMACS_INT hscroll)
875 /* Horizontal scrolling has problems with large scroll amounts.
876 It's too slow with long lines, and even with small lines the
877 display can be messed up. For now, though, impose only the limits
878 required by the internal representation: horizontal scrolling must
879 fit in fixnum (since it's visible to Elisp) and into ptrdiff_t
880 (since it's stored in a ptrdiff_t). */
881 ptrdiff_t hscroll_max = min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX);
882 ptrdiff_t new_hscroll = clip_to_bounds (0, hscroll, hscroll_max);
884 /* Prevent redisplay shortcuts when changing the hscroll. */
885 if (w->hscroll != new_hscroll)
886 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
888 w->hscroll = new_hscroll;
889 return make_number (new_hscroll);
892 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
893 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
894 WINDOW must be a live window and defaults to the selected one.
895 Clip the number to a reasonable value if out of range.
896 Return the new number. NCOL should be zero or positive.
898 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
899 window so that the location of point moves off-window. */)
900 (Lisp_Object window, Lisp_Object ncol)
902 CHECK_NUMBER (ncol);
903 return set_window_hscroll (decode_live_window (window), XINT (ncol));
906 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
907 Swindow_redisplay_end_trigger, 0, 1, 0,
908 doc: /* Return WINDOW's redisplay end trigger value.
909 WINDOW must be a live window and defaults to the selected one.
910 See `set-window-redisplay-end-trigger' for more information. */)
911 (Lisp_Object window)
913 return decode_live_window (window)->redisplay_end_trigger;
916 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
917 Sset_window_redisplay_end_trigger, 2, 2, 0,
918 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
919 WINDOW must be a live window and defaults to the selected one. VALUE
920 should be a buffer position (typically a marker) or nil. If it is a
921 buffer position, then if redisplay in WINDOW reaches a position beyond
922 VALUE, the functions in `redisplay-end-trigger-functions' are called
923 with two arguments: WINDOW, and the end trigger value. Afterwards the
924 end-trigger value is reset to nil. */)
925 (register Lisp_Object window, Lisp_Object value)
927 wset_redisplay_end_trigger (decode_live_window (window), value);
928 return value;
931 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
932 doc: /* Return a list of the edge coordinates of WINDOW.
933 WINDOW must be a valid window and defaults to the selected one.
935 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
936 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
937 0 at top left corner of frame.
939 RIGHT is one more than the rightmost column occupied by WINDOW. BOTTOM
940 is one more than the bottommost row occupied by WINDOW. The edges
941 include the space used by WINDOW's scroll bar, display margins, fringes,
942 header line, and/or mode line. For the edges of just the text area, use
943 `window-inside-edges'. */)
944 (Lisp_Object window)
946 register struct window *w = decode_valid_window (window);
948 return list4i (WINDOW_LEFT_EDGE_COL (w), WINDOW_TOP_EDGE_LINE (w),
949 WINDOW_RIGHT_EDGE_COL (w), WINDOW_BOTTOM_EDGE_LINE (w));
952 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
953 doc: /* Return a list of the edge pixel coordinates of WINDOW.
954 WINDOW must be a valid window and defaults to the selected one.
956 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
957 0, 0 at the top left corner of the frame.
959 RIGHT is one more than the rightmost x position occupied by WINDOW.
960 BOTTOM is one more than the bottommost y position occupied by WINDOW.
961 The pixel edges include the space used by WINDOW's scroll bar, display
962 margins, fringes, header line, and/or mode line. For the pixel edges
963 of just the text area, use `window-inside-pixel-edges'. */)
964 (Lisp_Object window)
966 register struct window *w = decode_valid_window (window);
968 return list4i (WINDOW_LEFT_EDGE_X (w), WINDOW_TOP_EDGE_Y (w),
969 WINDOW_RIGHT_EDGE_X (w), WINDOW_BOTTOM_EDGE_Y (w));
972 static void
973 calc_absolute_offset (struct window *w, int *add_x, int *add_y)
975 struct frame *f = XFRAME (w->frame);
976 *add_y = f->top_pos;
977 #ifdef FRAME_MENUBAR_HEIGHT
978 *add_y += FRAME_MENUBAR_HEIGHT (f);
979 #endif
980 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
981 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
982 #elif FRAME_TOOLBAR_HEIGHT
983 *add_y += FRAME_TOOLBAR_HEIGHT (f);
984 #endif
985 #ifdef FRAME_NS_TITLEBAR_HEIGHT
986 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
987 #endif
988 *add_x = f->left_pos;
989 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
990 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
991 #endif
994 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
995 Swindow_absolute_pixel_edges, 0, 1, 0,
996 doc: /* Return a list of the edge pixel coordinates of WINDOW.
997 WINDOW must be a valid window and defaults to the selected one.
999 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1000 0, 0 at the top left corner of the display.
1002 RIGHT is one more than the rightmost x position occupied by WINDOW.
1003 BOTTOM is one more than the bottommost y position occupied by WINDOW.
1004 The pixel edges include the space used by WINDOW's scroll bar, display
1005 margins, fringes, header line, and/or mode line. For the pixel edges
1006 of just the text area, use `window-inside-absolute-pixel-edges'. */)
1007 (Lisp_Object window)
1009 register struct window *w = decode_valid_window (window);
1010 int add_x, add_y;
1012 calc_absolute_offset (w, &add_x, &add_y);
1014 return list4i (WINDOW_LEFT_EDGE_X (w) + add_x,
1015 WINDOW_TOP_EDGE_Y (w) + add_y,
1016 WINDOW_RIGHT_EDGE_X (w) + add_x,
1017 WINDOW_BOTTOM_EDGE_Y (w) + add_y);
1020 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
1021 doc: /* Return a list of the edge coordinates of WINDOW.
1022 WINDOW must be a live window and defaults to the selected one.
1024 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
1025 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
1026 0 at top left corner of frame.
1028 RIGHT is one more than the rightmost column of WINDOW's text area.
1029 BOTTOM is one more than the bottommost row of WINDOW's text area. The
1030 inside edges do not include the space used by the WINDOW's scroll bar,
1031 display margins, fringes, header line, and/or mode line. */)
1032 (Lisp_Object window)
1034 register struct window *w = decode_live_window (window);
1036 return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w)
1037 + WINDOW_LEFT_MARGIN_COLS (w)
1038 + WINDOW_LEFT_FRINGE_COLS (w)),
1039 (WINDOW_TOP_EDGE_LINE (w)
1040 + WINDOW_HEADER_LINE_LINES (w)),
1041 (WINDOW_BOX_RIGHT_EDGE_COL (w)
1042 - WINDOW_RIGHT_MARGIN_COLS (w)
1043 - WINDOW_RIGHT_FRINGE_COLS (w)),
1044 (WINDOW_BOTTOM_EDGE_LINE (w)
1045 - WINDOW_MODE_LINE_LINES (w)));
1048 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
1049 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1050 WINDOW must be a live window and defaults to the selected one.
1052 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1053 (0,0) at the top left corner of the frame's window area.
1055 RIGHT is one more than the rightmost x position of WINDOW's text area.
1056 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1057 The inside edges do not include the space used by WINDOW's scroll bar,
1058 display margins, fringes, header line, and/or mode line. */)
1059 (Lisp_Object window)
1061 register struct window *w = decode_live_window (window);
1063 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1064 + WINDOW_LEFT_MARGIN_WIDTH (w)
1065 + WINDOW_LEFT_FRINGE_WIDTH (w)),
1066 (WINDOW_TOP_EDGE_Y (w)
1067 + WINDOW_HEADER_LINE_HEIGHT (w)),
1068 (WINDOW_BOX_RIGHT_EDGE_X (w)
1069 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1070 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
1071 (WINDOW_BOTTOM_EDGE_Y (w)
1072 - WINDOW_MODE_LINE_HEIGHT (w)));
1075 DEFUN ("window-inside-absolute-pixel-edges",
1076 Fwindow_inside_absolute_pixel_edges,
1077 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
1078 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1079 WINDOW must be a live window and defaults to the selected one.
1081 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1082 (0,0) at the top left corner of the frame's window area.
1084 RIGHT is one more than the rightmost x position of WINDOW's text area.
1085 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1086 The inside edges do not include the space used by WINDOW's scroll bar,
1087 display margins, fringes, header line, and/or mode line. */)
1088 (Lisp_Object window)
1090 register struct window *w = decode_live_window (window);
1091 int add_x, add_y;
1093 calc_absolute_offset (w, &add_x, &add_y);
1095 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1096 + WINDOW_LEFT_MARGIN_WIDTH (w)
1097 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
1098 (WINDOW_TOP_EDGE_Y (w)
1099 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
1100 (WINDOW_BOX_RIGHT_EDGE_X (w)
1101 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1102 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
1103 (WINDOW_BOTTOM_EDGE_Y (w)
1104 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
1107 /* Test if the character at column X, row Y is within window W.
1108 If it is not, return ON_NOTHING;
1109 if it is in the window's text area, return ON_TEXT;
1110 if it is on the window's modeline, return ON_MODE_LINE;
1111 if it is on the border between the window and its right sibling,
1112 return ON_VERTICAL_BORDER.
1113 if it is on a scroll bar, return ON_SCROLL_BAR.
1114 if it is on the window's top line, return ON_HEADER_LINE;
1115 if it is in left or right fringe of the window,
1116 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
1117 if it is in the marginal area to the left/right of the window,
1118 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
1120 X and Y are frame relative pixel coordinates. */
1122 static enum window_part
1123 coordinates_in_window (register struct window *w, int x, int y)
1125 struct frame *f = XFRAME (WINDOW_FRAME (w));
1126 enum window_part part;
1127 int ux = FRAME_COLUMN_WIDTH (f);
1128 int left_x = WINDOW_LEFT_EDGE_X (w);
1129 int right_x = WINDOW_RIGHT_EDGE_X (w);
1130 int top_y = WINDOW_TOP_EDGE_Y (w);
1131 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
1132 /* The width of the area where the vertical line can be dragged.
1133 (Between mode lines for instance. */
1134 int grabbable_width = ux;
1135 int lmargin_width, rmargin_width, text_left, text_right;
1137 /* Outside any interesting row or column? */
1138 if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
1139 return ON_NOTHING;
1141 /* On the mode line or header line? */
1142 if ((WINDOW_WANTS_MODELINE_P (w)
1143 && y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
1144 && (part = ON_MODE_LINE))
1145 || (WINDOW_WANTS_HEADER_LINE_P (w)
1146 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
1147 && (part = ON_HEADER_LINE)))
1149 /* If it's under/over the scroll bar portion of the mode/header
1150 line, say it's on the vertical line. That's to be able to
1151 resize windows horizontally in case we're using toolkit scroll
1152 bars. Note: If scrollbars are on the left, the window that
1153 must be eventually resized is that on the left of WINDOW. */
1154 if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1155 && !WINDOW_LEFTMOST_P (w)
1156 && eabs (x - left_x) < grabbable_width)
1157 || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1158 && !WINDOW_RIGHTMOST_P (w)
1159 && eabs (x - right_x) < grabbable_width))
1160 return ON_VERTICAL_BORDER;
1161 else
1162 return part;
1165 /* In what's below, we subtract 1 when computing right_x because we
1166 want the rightmost pixel, which is given by left_pixel+width-1. */
1167 if (w->pseudo_window_p)
1169 left_x = 0;
1170 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
1172 else
1174 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
1175 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
1178 /* Outside any interesting column? */
1179 if (x < left_x || x > right_x)
1180 return ON_SCROLL_BAR;
1182 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
1183 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
1185 text_left = window_box_left (w, TEXT_AREA);
1186 text_right = text_left + window_box_width (w, TEXT_AREA);
1188 if (FRAME_WINDOW_P (f))
1190 if (!w->pseudo_window_p
1191 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
1192 && !WINDOW_RIGHTMOST_P (w)
1193 && (eabs (x - right_x) < grabbable_width))
1194 return ON_VERTICAL_BORDER;
1196 /* Need to say "x > right_x" rather than >=, since on character
1197 terminals, the vertical line's x coordinate is right_x. */
1198 else if (!w->pseudo_window_p
1199 && !WINDOW_RIGHTMOST_P (w)
1200 && x > right_x - ux)
1201 return ON_VERTICAL_BORDER;
1203 if (x < text_left)
1205 if (lmargin_width > 0
1206 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1207 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
1208 : (x < left_x + lmargin_width)))
1209 return ON_LEFT_MARGIN;
1211 return ON_LEFT_FRINGE;
1214 if (x >= text_right)
1216 if (rmargin_width > 0
1217 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1218 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
1219 : (x >= right_x - rmargin_width)))
1220 return ON_RIGHT_MARGIN;
1222 return ON_RIGHT_FRINGE;
1225 /* Everything special ruled out - must be on text area */
1226 return ON_TEXT;
1229 /* Take X is the frame-relative pixel x-coordinate, and return the
1230 x-coordinate relative to part PART of window W. */
1232 window_relative_x_coord (struct window *w, enum window_part part, int x)
1234 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
1236 switch (part)
1238 case ON_TEXT:
1239 return x - window_box_left (w, TEXT_AREA);
1241 case ON_LEFT_FRINGE:
1242 return x - left_x;
1244 case ON_RIGHT_FRINGE:
1245 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
1247 case ON_LEFT_MARGIN:
1248 return (x - left_x
1249 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1250 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
1252 case ON_RIGHT_MARGIN:
1253 return (x + 1
1254 - ((w->pseudo_window_p)
1255 ? WINDOW_TOTAL_WIDTH (w)
1256 : WINDOW_BOX_RIGHT_EDGE_X (w))
1257 + window_box_width (w, RIGHT_MARGIN_AREA)
1258 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1259 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
1262 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
1263 return 0;
1267 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
1268 Scoordinates_in_window_p, 2, 2, 0,
1269 doc: /* Return non-nil if COORDINATES are in WINDOW.
1270 WINDOW must be a live window and defaults to the selected one.
1271 COORDINATES is a cons of the form (X . Y), X and Y being distances
1272 measured in characters from the upper-left corner of the frame.
1273 \(0 . 0) denotes the character in the upper left corner of the
1274 frame.
1275 If COORDINATES are in the text portion of WINDOW,
1276 the coordinates relative to the window are returned.
1277 If they are in the mode line of WINDOW, `mode-line' is returned.
1278 If they are in the top mode line of WINDOW, `header-line' is returned.
1279 If they are in the left fringe of WINDOW, `left-fringe' is returned.
1280 If they are in the right fringe of WINDOW, `right-fringe' is returned.
1281 If they are on the border between WINDOW and its right sibling,
1282 `vertical-line' is returned.
1283 If they are in the windows's left or right marginal areas, `left-margin'\n\
1284 or `right-margin' is returned. */)
1285 (register Lisp_Object coordinates, Lisp_Object window)
1287 struct window *w;
1288 struct frame *f;
1289 int x, y;
1290 Lisp_Object lx, ly;
1292 w = decode_live_window (window);
1293 f = XFRAME (w->frame);
1294 CHECK_CONS (coordinates);
1295 lx = Fcar (coordinates);
1296 ly = Fcdr (coordinates);
1297 CHECK_NUMBER_OR_FLOAT (lx);
1298 CHECK_NUMBER_OR_FLOAT (ly);
1299 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1300 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
1302 switch (coordinates_in_window (w, x, y))
1304 case ON_NOTHING:
1305 return Qnil;
1307 case ON_TEXT:
1308 /* Convert X and Y to window relative pixel coordinates, and
1309 return the canonical char units. */
1310 x -= window_box_left (w, TEXT_AREA);
1311 y -= WINDOW_TOP_EDGE_Y (w);
1312 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1313 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
1315 case ON_MODE_LINE:
1316 return Qmode_line;
1318 case ON_VERTICAL_BORDER:
1319 return Qvertical_line;
1321 case ON_HEADER_LINE:
1322 return Qheader_line;
1324 case ON_LEFT_FRINGE:
1325 return Qleft_fringe;
1327 case ON_RIGHT_FRINGE:
1328 return Qright_fringe;
1330 case ON_LEFT_MARGIN:
1331 return Qleft_margin;
1333 case ON_RIGHT_MARGIN:
1334 return Qright_margin;
1336 case ON_SCROLL_BAR:
1337 /* Historically we are supposed to return nil in this case. */
1338 return Qnil;
1340 default:
1341 emacs_abort ();
1346 /* Callback for foreach_window, used in window_from_coordinates.
1347 Check if window W contains coordinates specified by USER_DATA which
1348 is actually a pointer to a struct check_window_data CW.
1350 Check if window W contains coordinates *CW->x and *CW->y. If it
1351 does, return W in *CW->window, as Lisp_Object, and return in
1352 *CW->part the part of the window under coordinates *X,*Y. Return
1353 zero from this function to stop iterating over windows. */
1355 struct check_window_data
1357 Lisp_Object *window;
1358 int x, y;
1359 enum window_part *part;
1362 static int
1363 check_window_containing (struct window *w, void *user_data)
1365 struct check_window_data *cw = user_data;
1366 enum window_part found;
1367 int continue_p = 1;
1369 found = coordinates_in_window (w, cw->x, cw->y);
1370 if (found != ON_NOTHING)
1372 *cw->part = found;
1373 XSETWINDOW (*cw->window, w);
1374 continue_p = 0;
1377 return continue_p;
1381 /* Find the window containing frame-relative pixel position X/Y and
1382 return it as a Lisp_Object.
1384 If X, Y is on one of the window's special `window_part' elements,
1385 set *PART to the id of that element.
1387 If there is no window under X, Y return nil and leave *PART
1388 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1390 This function was previously implemented with a loop cycling over
1391 windows with Fnext_window, and starting with the frame's selected
1392 window. It turned out that this doesn't work with an
1393 implementation of next_window using Vwindow_list, because
1394 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1395 tree of F when this function is called asynchronously from
1396 note_mouse_highlight. The original loop didn't terminate in this
1397 case. */
1399 Lisp_Object
1400 window_from_coordinates (struct frame *f, int x, int y,
1401 enum window_part *part, bool tool_bar_p)
1403 Lisp_Object window;
1404 struct check_window_data cw;
1405 enum window_part dummy;
1407 if (part == 0)
1408 part = &dummy;
1410 window = Qnil;
1411 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
1412 foreach_window (f, check_window_containing, &cw);
1414 /* If not found above, see if it's in the tool bar window, if a tool
1415 bar exists. */
1416 if (NILP (window)
1417 && tool_bar_p
1418 && WINDOWP (f->tool_bar_window)
1419 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1420 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
1421 != ON_NOTHING))
1423 *part = ON_TEXT;
1424 window = f->tool_bar_window;
1427 return window;
1430 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1431 doc: /* Return window containing coordinates X and Y on FRAME.
1432 FRAME must be a live frame and defaults to the selected one.
1433 The top left corner of the frame is considered to be row 0,
1434 column 0. */)
1435 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1437 struct frame *f = decode_live_frame (frame);
1439 /* Check that arguments are integers or floats. */
1440 CHECK_NUMBER_OR_FLOAT (x);
1441 CHECK_NUMBER_OR_FLOAT (y);
1443 return window_from_coordinates (f,
1444 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1445 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1446 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1447 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1448 0, 0);
1451 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1452 doc: /* Return current value of point in WINDOW.
1453 WINDOW must be a live window and defaults to the selected one.
1455 For a nonselected window, this is the value point would have if that
1456 window were selected.
1458 Note that, when WINDOW is selected, the value returned is the same as
1459 that returned by `point' for WINDOW's buffer. It would be more strictly
1460 correct to return the top-level value of `point', outside of any
1461 `save-excursion' forms. But that is hard to define. */)
1462 (Lisp_Object window)
1464 register struct window *w = decode_live_window (window);
1466 if (w == XWINDOW (selected_window))
1467 return make_number (BUF_PT (XBUFFER (w->contents)));
1468 else
1469 return Fmarker_position (w->pointm);
1472 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1473 doc: /* Return position at which display currently starts in WINDOW.
1474 WINDOW must be a live window and defaults to the selected one.
1475 This is updated by redisplay or by calling `set-window-start'. */)
1476 (Lisp_Object window)
1478 return Fmarker_position (decode_live_window (window)->start);
1481 /* This is text temporarily removed from the doc string below.
1483 This function returns nil if the position is not currently known.
1484 That happens when redisplay is preempted and doesn't finish.
1485 If in that case you want to compute where the end of the window would
1486 have been if redisplay had finished, do this:
1487 (save-excursion
1488 (goto-char (window-start window))
1489 (vertical-motion (1- (window-height window)) window)
1490 (point))") */
1492 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1493 doc: /* Return position at which display currently ends in WINDOW.
1494 WINDOW must be a live window and defaults to the selected one.
1495 This is updated by redisplay, when it runs to completion.
1496 Simply changing the buffer text or setting `window-start'
1497 does not update this value.
1498 Return nil if there is no recorded value. (This can happen if the
1499 last redisplay of WINDOW was preempted, and did not finish.)
1500 If UPDATE is non-nil, compute the up-to-date position
1501 if it isn't already recorded. */)
1502 (Lisp_Object window, Lisp_Object update)
1504 Lisp_Object value;
1505 struct window *w = decode_live_window (window);
1506 Lisp_Object buf;
1507 struct buffer *b;
1509 buf = w->contents;
1510 CHECK_BUFFER (buf);
1511 b = XBUFFER (buf);
1513 if (! NILP (update)
1514 && (windows_or_buffers_changed
1515 || !w->window_end_valid
1516 || b->clip_changed
1517 || b->prevent_redisplay_optimizations_p
1518 || window_outdated (w))
1519 && !noninteractive)
1521 struct text_pos startp;
1522 ptrdiff_t charpos = marker_position (w->start);
1523 struct it it;
1524 struct buffer *old_buffer = NULL;
1525 void *itdata = NULL;
1527 /* Cannot use Fvertical_motion because that function doesn't
1528 cope with variable-height lines. */
1529 if (b != current_buffer)
1531 old_buffer = current_buffer;
1532 set_buffer_internal (b);
1535 /* In case W->start is out of the range, use something
1536 reasonable. This situation occurred when loading a file with
1537 `-l' containing a call to `rmail' with subsequent other
1538 commands. At the end, W->start happened to be BEG, while
1539 rmail had already narrowed the buffer. */
1540 if (charpos < BEGV)
1541 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1542 else if (charpos > ZV)
1543 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1544 else
1545 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1547 itdata = bidi_shelve_cache ();
1548 start_display (&it, w, startp);
1549 move_it_vertically (&it, window_box_height (w));
1550 if (it.current_y < it.last_visible_y)
1551 move_it_past_eol (&it);
1552 value = make_number (IT_CHARPOS (it));
1553 bidi_unshelve_cache (itdata, 0);
1555 if (old_buffer)
1556 set_buffer_internal (old_buffer);
1558 else
1559 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1561 return value;
1564 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1565 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1566 WINDOW must be a live window and defaults to the selected one.
1567 Return POS. */)
1568 (Lisp_Object window, Lisp_Object pos)
1570 register struct window *w = decode_live_window (window);
1572 /* Type of POS is checked by Fgoto_char or set_marker_restricted ... */
1574 if (w == XWINDOW (selected_window))
1576 if (XBUFFER (w->contents) == current_buffer)
1577 Fgoto_char (pos);
1578 else
1580 struct buffer *old_buffer = current_buffer;
1582 /* ... but here we want to catch type error before buffer change. */
1583 CHECK_NUMBER_COERCE_MARKER (pos);
1584 set_buffer_internal (XBUFFER (w->contents));
1585 Fgoto_char (pos);
1586 set_buffer_internal (old_buffer);
1589 else
1591 set_marker_restricted (w->pointm, pos, w->contents);
1592 /* We have to make sure that redisplay updates the window to show
1593 the new value of point. */
1594 ++windows_or_buffers_changed;
1597 return pos;
1600 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1601 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1602 WINDOW must be a live window and defaults to the selected one. Return
1603 POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
1604 overriding motion of point in order to display at this exact start. */)
1605 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1607 register struct window *w = decode_live_window (window);
1609 set_marker_restricted (w->start, pos, w->contents);
1610 /* This is not right, but much easier than doing what is right. */
1611 w->start_at_line_beg = 0;
1612 if (NILP (noforce))
1613 w->force_start = 1;
1614 w->update_mode_line = 1;
1615 if (!EQ (window, selected_window))
1616 /* Enforce full redisplay. FIXME: make it more selective. */
1617 windows_or_buffers_changed++;
1619 return pos;
1622 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1623 Spos_visible_in_window_p, 0, 3, 0,
1624 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1625 WINDOW must be a live window and defaults to the selected one.
1627 Return nil if that position is scrolled vertically out of view. If a
1628 character is only partially visible, nil is returned, unless the
1629 optional argument PARTIALLY is non-nil. If POS is only out of view
1630 because of horizontal scrolling, return non-nil. If POS is t, it
1631 specifies the position of the last visible glyph in WINDOW. POS
1632 defaults to point in WINDOW; WINDOW defaults to the selected window.
1634 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
1635 the return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
1636 where X and Y are the pixel coordinates relative to the top left corner
1637 of the window. The remaining elements are omitted if the character after
1638 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1639 off-window at the top and bottom of the screen line ("row") containing
1640 POS, ROWH is the visible height of that row, and VPOS is the row number
1641 \(zero-based). */)
1642 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1644 register struct window *w;
1645 register EMACS_INT posint;
1646 register struct buffer *buf;
1647 struct text_pos top;
1648 Lisp_Object in_window = Qnil;
1649 int rtop, rbot, rowh, vpos, fully_p = 1;
1650 int x, y;
1652 w = decode_live_window (window);
1653 buf = XBUFFER (w->contents);
1654 SET_TEXT_POS_FROM_MARKER (top, w->start);
1656 if (EQ (pos, Qt))
1657 posint = -1;
1658 else if (!NILP (pos))
1660 CHECK_NUMBER_COERCE_MARKER (pos);
1661 posint = XINT (pos);
1663 else if (w == XWINDOW (selected_window))
1664 posint = PT;
1665 else
1666 posint = marker_position (w->pointm);
1668 /* If position is above window start or outside buffer boundaries,
1669 or if window start is out of range, position is not visible. */
1670 if ((EQ (pos, Qt)
1671 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
1672 && CHARPOS (top) >= BUF_BEGV (buf)
1673 && CHARPOS (top) <= BUF_ZV (buf)
1674 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
1675 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
1676 in_window = Qt;
1678 if (!NILP (in_window) && !NILP (partially))
1680 Lisp_Object part = Qnil;
1681 if (!fully_p)
1682 part = list4i (rtop, rbot, rowh, vpos);
1683 in_window = Fcons (make_number (x),
1684 Fcons (make_number (y), part));
1687 return in_window;
1690 DEFUN ("window-line-height", Fwindow_line_height,
1691 Swindow_line_height, 0, 2, 0,
1692 doc: /* Return height in pixels of text line LINE in window WINDOW.
1693 WINDOW must be a live window and defaults to the selected one.
1695 Return height of current line if LINE is omitted or nil. Return height of
1696 header or mode line if LINE is `header-line' or `mode-line'.
1697 Otherwise, LINE is a text line number starting from 0. A negative number
1698 counts from the end of the window.
1700 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
1701 in pixels of the visible part of the line, VPOS and YPOS are the
1702 vertical position in lines and pixels of the line, relative to the top
1703 of the first text line, and OFFBOT is the number of off-window pixels at
1704 the bottom of the text line. If there are off-window pixels at the top
1705 of the (first) text line, YPOS is negative.
1707 Return nil if window display is not up-to-date. In that case, use
1708 `pos-visible-in-window-p' to obtain the information. */)
1709 (Lisp_Object line, Lisp_Object window)
1711 register struct window *w;
1712 register struct buffer *b;
1713 struct glyph_row *row, *end_row;
1714 int max_y, crop, i;
1715 EMACS_INT n;
1717 w = decode_live_window (window);
1719 if (noninteractive || w->pseudo_window_p)
1720 return Qnil;
1722 CHECK_BUFFER (w->contents);
1723 b = XBUFFER (w->contents);
1725 /* Fail if current matrix is not up-to-date. */
1726 if (!w->window_end_valid
1727 || windows_or_buffers_changed
1728 || b->clip_changed
1729 || b->prevent_redisplay_optimizations_p
1730 || window_outdated (w))
1731 return Qnil;
1733 if (NILP (line))
1735 i = w->cursor.vpos;
1736 if (i < 0 || i >= w->current_matrix->nrows
1737 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
1738 return Qnil;
1739 max_y = window_text_bottom_y (w);
1740 goto found_row;
1743 if (EQ (line, Qheader_line))
1745 if (!WINDOW_WANTS_HEADER_LINE_P (w))
1746 return Qnil;
1747 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1748 return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
1751 if (EQ (line, Qmode_line))
1753 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1754 return (row->enabled_p ?
1755 list4i (row->height,
1756 0, /* not accurate */
1757 (WINDOW_HEADER_LINE_HEIGHT (w)
1758 + window_text_bottom_y (w)),
1760 : Qnil);
1763 CHECK_NUMBER (line);
1764 n = XINT (line);
1766 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1767 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
1768 max_y = window_text_bottom_y (w);
1769 i = 0;
1771 while ((n < 0 || i < n)
1772 && row <= end_row && row->enabled_p
1773 && row->y + row->height < max_y)
1774 row++, i++;
1776 if (row > end_row || !row->enabled_p)
1777 return Qnil;
1779 if (++n < 0)
1781 if (-n > i)
1782 return Qnil;
1783 row += n;
1784 i += n;
1787 found_row:
1788 crop = max (0, (row->y + row->height) - max_y);
1789 return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
1792 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1793 0, 1, 0,
1794 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1795 More precisely, return the value assigned by the last call of
1796 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1797 never called with WINDOW as its argument, or the value set by that
1798 function was internally reset since its last call. WINDOW must be a
1799 live window and defaults to the selected one.
1801 When a window is dedicated to its buffer, `display-buffer' will refrain
1802 from displaying another buffer in it. `get-lru-window' and
1803 `get-largest-window' treat dedicated windows specially.
1804 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1805 `kill-buffer' can delete a dedicated window and the containing frame.
1807 Functions like `set-window-buffer' may change the buffer displayed by a
1808 window, unless that window is "strongly" dedicated to its buffer, that
1809 is the value returned by `window-dedicated-p' is t. */)
1810 (Lisp_Object window)
1812 return decode_live_window (window)->dedicated;
1815 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1816 Sset_window_dedicated_p, 2, 2, 0,
1817 doc: /* Mark WINDOW as dedicated according to FLAG.
1818 WINDOW must be a live window and defaults to the selected one. FLAG
1819 non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
1820 mark WINDOW as non-dedicated. Return FLAG.
1822 When a window is dedicated to its buffer, `display-buffer' will refrain
1823 from displaying another buffer in it. `get-lru-window' and
1824 `get-largest-window' treat dedicated windows specially.
1825 `delete-windows-on', `replace-buffer-in-windows', `quit-window',
1826 `quit-restore-window' and `kill-buffer' can delete a dedicated window
1827 and the containing frame.
1829 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1830 its buffer. Functions like `set-window-buffer' may change the buffer
1831 displayed by a window, unless that window is strongly dedicated to its
1832 buffer. If and when `set-window-buffer' displays another buffer in a
1833 window, it also makes sure that the window is no more dedicated. */)
1834 (Lisp_Object window, Lisp_Object flag)
1836 wset_dedicated (decode_live_window (window), flag);
1837 return flag;
1840 DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
1841 0, 1, 0,
1842 doc: /* Return buffers previously shown in WINDOW.
1843 WINDOW must be a live window and defaults to the selected one.
1845 The return value is a list of elements (BUFFER WINDOW-START POS),
1846 where BUFFER is a buffer, WINDOW-START is the start position of the
1847 window for that buffer, and POS is a window-specific point value. */)
1848 (Lisp_Object window)
1850 return decode_live_window (window)->prev_buffers;
1853 DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
1854 Sset_window_prev_buffers, 2, 2, 0,
1855 doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
1856 WINDOW must be a live window and defaults to the selected one.
1858 PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS),
1859 where BUFFER is a buffer, WINDOW-START is the start position of the
1860 window for that buffer, and POS is a window-specific point value. */)
1861 (Lisp_Object window, Lisp_Object prev_buffers)
1863 wset_prev_buffers (decode_live_window (window), prev_buffers);
1864 return prev_buffers;
1867 DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
1868 0, 1, 0,
1869 doc: /* Return list of buffers recently re-shown in WINDOW.
1870 WINDOW must be a live window and defaults to the selected one. */)
1871 (Lisp_Object window)
1873 return decode_live_window (window)->next_buffers;
1876 DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
1877 Sset_window_next_buffers, 2, 2, 0,
1878 doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
1879 WINDOW must be a live window and defaults to the selected one.
1880 NEXT-BUFFERS should be a list of buffers. */)
1881 (Lisp_Object window, Lisp_Object next_buffers)
1883 wset_next_buffers (decode_live_window (window), next_buffers);
1884 return next_buffers;
1887 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1888 0, 1, 0,
1889 doc: /* Return the parameters of WINDOW and their values.
1890 WINDOW must be a valid window and defaults to the selected one. The
1891 return value is a list of elements of the form (PARAMETER . VALUE). */)
1892 (Lisp_Object window)
1894 return Fcopy_alist (decode_valid_window (window)->window_parameters);
1897 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1898 2, 2, 0,
1899 doc: /* Return WINDOW's value for PARAMETER.
1900 WINDOW can be any window and defaults to the selected one. */)
1901 (Lisp_Object window, Lisp_Object parameter)
1903 Lisp_Object result;
1905 result = Fassq (parameter, decode_any_window (window)->window_parameters);
1906 return CDR_SAFE (result);
1909 DEFUN ("set-window-parameter", Fset_window_parameter,
1910 Sset_window_parameter, 3, 3, 0,
1911 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1912 WINDOW can be any window and defaults to the selected one.
1913 Return VALUE. */)
1914 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
1916 register struct window *w = decode_any_window (window);
1917 Lisp_Object old_alist_elt;
1919 old_alist_elt = Fassq (parameter, w->window_parameters);
1920 if (NILP (old_alist_elt))
1921 wset_window_parameters
1922 (w, Fcons (Fcons (parameter, value), w->window_parameters));
1923 else
1924 Fsetcdr (old_alist_elt, value);
1925 return value;
1928 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1929 0, 1, 0,
1930 doc: /* Return the display-table that WINDOW is using.
1931 WINDOW must be a live window and defaults to the selected one. */)
1932 (Lisp_Object window)
1934 return decode_live_window (window)->display_table;
1937 /* Get the display table for use on window W. This is either W's
1938 display table or W's buffer's display table. Ignore the specified
1939 tables if they are not valid; if no valid table is specified,
1940 return 0. */
1942 struct Lisp_Char_Table *
1943 window_display_table (struct window *w)
1945 struct Lisp_Char_Table *dp = NULL;
1947 if (DISP_TABLE_P (w->display_table))
1948 dp = XCHAR_TABLE (w->display_table);
1949 else if (BUFFERP (w->contents))
1951 struct buffer *b = XBUFFER (w->contents);
1953 if (DISP_TABLE_P (BVAR (b, display_table)))
1954 dp = XCHAR_TABLE (BVAR (b, display_table));
1955 else if (DISP_TABLE_P (Vstandard_display_table))
1956 dp = XCHAR_TABLE (Vstandard_display_table);
1959 return dp;
1962 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1963 doc: /* Set WINDOW's display-table to TABLE.
1964 WINDOW must be a live window and defaults to the selected one. */)
1965 (register Lisp_Object window, Lisp_Object table)
1967 wset_display_table (decode_live_window (window), table);
1968 return table;
1971 /* Record info on buffer window W is displaying
1972 when it is about to cease to display that buffer. */
1973 static void
1974 unshow_buffer (register struct window *w)
1976 Lisp_Object buf = w->contents;
1977 struct buffer *b = XBUFFER (buf);
1979 eassert (b == XMARKER (w->pointm)->buffer);
1981 #if 0
1982 if (w == XWINDOW (selected_window)
1983 || ! EQ (buf, XWINDOW (selected_window)->contents))
1984 /* Do this except when the selected window's buffer
1985 is being removed from some other window. */
1986 #endif
1987 /* last_window_start records the start position that this buffer
1988 had in the last window to be disconnected from it.
1989 Now that this statement is unconditional,
1990 it is possible for the buffer to be displayed in the
1991 selected window, while last_window_start reflects another
1992 window which was recently showing the same buffer.
1993 Some people might say that might be a good thing. Let's see. */
1994 b->last_window_start = marker_position (w->start);
1996 /* Point in the selected window's buffer
1997 is actually stored in that buffer, and the window's pointm isn't used.
1998 So don't clobber point in that buffer. */
1999 if (! EQ (buf, XWINDOW (selected_window)->contents)
2000 /* Don't clobber point in current buffer either (this could be
2001 useful in connection with bug#12208).
2002 && XBUFFER (buf) != current_buffer */
2003 /* This line helps to fix Horsley's testbug.el bug. */
2004 && !(WINDOWP (BVAR (b, last_selected_window))
2005 && w != XWINDOW (BVAR (b, last_selected_window))
2006 && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->contents)))
2007 temp_set_point_both (b,
2008 clip_to_bounds (BUF_BEGV (b),
2009 marker_position (w->pointm),
2010 BUF_ZV (b)),
2011 clip_to_bounds (BUF_BEGV_BYTE (b),
2012 marker_byte_position (w->pointm),
2013 BUF_ZV_BYTE (b)));
2015 if (WINDOWP (BVAR (b, last_selected_window))
2016 && w == XWINDOW (BVAR (b, last_selected_window)))
2017 bset_last_selected_window (b, Qnil);
2020 /* Put NEW into the window structure in place of OLD. SETFLAG zero
2021 means change window structure only. Otherwise store geometry and
2022 other settings as well. */
2023 static void
2024 replace_window (Lisp_Object old, Lisp_Object new, int setflag)
2026 register Lisp_Object tem;
2027 register struct window *o = XWINDOW (old), *n = XWINDOW (new);
2029 /* If OLD is its frame's root window, then NEW is the new
2030 root window for that frame. */
2031 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
2032 fset_root_window (XFRAME (o->frame), new);
2034 if (setflag)
2036 n->left_col = o->left_col;
2037 n->top_line = o->top_line;
2038 n->total_cols = o->total_cols;
2039 n->total_lines = o->total_lines;
2040 wset_normal_cols (n, o->normal_cols);
2041 wset_normal_cols (o, make_float (1.0));
2042 wset_normal_lines (n, o->normal_lines);
2043 wset_normal_lines (o, make_float (1.0));
2044 n->desired_matrix = n->current_matrix = 0;
2045 n->vscroll = 0;
2046 memset (&n->cursor, 0, sizeof (n->cursor));
2047 memset (&n->last_cursor, 0, sizeof (n->last_cursor));
2048 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
2049 n->phys_cursor_type = -1;
2050 n->phys_cursor_width = -1;
2051 n->must_be_updated_p = 0;
2052 n->pseudo_window_p = 0;
2053 wset_window_end_vpos (n, make_number (0));
2054 wset_window_end_pos (n, make_number (0));
2055 n->window_end_valid = 0;
2058 tem = o->next;
2059 wset_next (n, tem);
2060 if (!NILP (tem))
2061 wset_prev (XWINDOW (tem), new);
2063 tem = o->prev;
2064 wset_prev (n, tem);
2065 if (!NILP (tem))
2066 wset_next (XWINDOW (tem), new);
2068 tem = o->parent;
2069 wset_parent (n, tem);
2070 if (!NILP (tem) && EQ (XWINDOW (tem)->contents, old))
2071 wset_combination (XWINDOW (tem), XWINDOW (tem)->horizontal, new);
2074 /* If window WINDOW and its parent window are iso-combined, merge
2075 WINDOW's children into those of its parent window and mark WINDOW as
2076 deleted. */
2078 static void
2079 recombine_windows (Lisp_Object window)
2081 struct window *w, *p, *c;
2082 Lisp_Object parent, child;
2083 bool horflag;
2085 w = XWINDOW (window);
2086 parent = w->parent;
2087 if (!NILP (parent) && NILP (w->combination_limit))
2089 p = XWINDOW (parent);
2090 if (WINDOWP (p->contents) && WINDOWP (w->contents)
2091 && p->horizontal == w->horizontal)
2092 /* WINDOW and PARENT are both either a vertical or a horizontal
2093 combination. */
2095 horflag = WINDOW_HORIZONTAL_COMBINATION_P (w);
2096 child = w->contents;
2097 c = XWINDOW (child);
2099 /* Splice WINDOW's children into its parent's children and
2100 assign new normal sizes. */
2101 if (NILP (w->prev))
2102 wset_combination (p, horflag, child);
2103 else
2105 wset_prev (c, w->prev);
2106 wset_next (XWINDOW (w->prev), child);
2109 while (c)
2111 wset_parent (c, parent);
2113 if (horflag)
2114 wset_normal_cols (c,
2115 make_float ((double) c->total_cols
2116 / (double) p->total_cols));
2117 else
2118 wset_normal_lines (c,
2119 make_float ((double) c->total_lines
2120 / (double) p->total_lines));
2122 if (NILP (c->next))
2124 if (!NILP (w->next))
2126 wset_next (c, w->next);
2127 wset_prev (XWINDOW (c->next), child);
2130 c = 0;
2132 else
2134 child = c->next;
2135 c = XWINDOW (child);
2139 /* WINDOW can be deleted now. */
2140 wset_combination (w, 0, Qnil);
2145 /* If WINDOW can be deleted, delete it. */
2146 static void
2147 delete_deletable_window (Lisp_Object window)
2149 if (!NILP (call1 (Qwindow_deletable_p, window)))
2150 call1 (Qdelete_window, window);
2153 /***********************************************************************
2154 Window List
2155 ***********************************************************************/
2157 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
2158 pointer. This is a callback function for foreach_window, used in
2159 the window_list function. */
2161 static int
2162 add_window_to_list (struct window *w, void *user_data)
2164 Lisp_Object *list = user_data;
2165 Lisp_Object window;
2166 XSETWINDOW (window, w);
2167 *list = Fcons (window, *list);
2168 return 1;
2172 /* Return a list of all windows, for use by next_window. If
2173 Vwindow_list is a list, return that list. Otherwise, build a new
2174 list, cache it in Vwindow_list, and return that. */
2176 static Lisp_Object
2177 window_list (void)
2179 if (!CONSP (Vwindow_list))
2181 Lisp_Object tail, frame;
2183 Vwindow_list = Qnil;
2184 FOR_EACH_FRAME (tail, frame)
2186 Lisp_Object args[2];
2188 /* We are visiting windows in canonical order, and add
2189 new windows at the front of args[1], which means we
2190 have to reverse this list at the end. */
2191 args[1] = Qnil;
2192 foreach_window (XFRAME (frame), add_window_to_list, &args[1]);
2193 args[0] = Vwindow_list;
2194 args[1] = Fnreverse (args[1]);
2195 Vwindow_list = Fnconc (2, args);
2199 return Vwindow_list;
2203 /* Value is non-zero if WINDOW satisfies the constraints given by
2204 OWINDOW, MINIBUF and ALL_FRAMES.
2206 MINIBUF t means WINDOW may be minibuffer windows.
2207 `lambda' means WINDOW may not be a minibuffer window.
2208 a window means a specific minibuffer window
2210 ALL_FRAMES t means search all frames,
2211 nil means search just current frame,
2212 `visible' means search just visible frames on the
2213 current terminal,
2214 0 means search visible and iconified frames on the
2215 current terminal,
2216 a window means search the frame that window belongs to,
2217 a frame means consider windows on that frame, only. */
2219 static bool
2220 candidate_window_p (Lisp_Object window, Lisp_Object owindow,
2221 Lisp_Object minibuf, Lisp_Object all_frames)
2223 struct window *w = XWINDOW (window);
2224 struct frame *f = XFRAME (w->frame);
2225 bool candidate_p = 1;
2227 if (!BUFFERP (w->contents))
2228 candidate_p = 0;
2229 else if (MINI_WINDOW_P (w)
2230 && (EQ (minibuf, Qlambda)
2231 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
2233 /* If MINIBUF is `lambda' don't consider any mini-windows.
2234 If it is a window, consider only that one. */
2235 candidate_p = 0;
2237 else if (EQ (all_frames, Qt))
2238 candidate_p = 1;
2239 else if (NILP (all_frames))
2241 eassert (WINDOWP (owindow));
2242 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
2244 else if (EQ (all_frames, Qvisible))
2246 candidate_p = FRAME_VISIBLE_P (f)
2247 && (FRAME_TERMINAL (XFRAME (w->frame))
2248 == FRAME_TERMINAL (XFRAME (selected_frame)));
2251 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2253 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2254 #ifdef HAVE_X_WINDOWS
2255 /* Yuck!! If we've just created the frame and the
2256 window-manager requested the user to place it
2257 manually, the window may still not be considered
2258 `visible'. I'd argue it should be at least
2259 something like `iconified', but don't know how to do
2260 that yet. --Stef */
2261 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
2262 && !f->output_data.x->has_been_visible)
2263 #endif
2265 && (FRAME_TERMINAL (XFRAME (w->frame))
2266 == FRAME_TERMINAL (XFRAME (selected_frame)));
2268 else if (WINDOWP (all_frames))
2269 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
2270 || EQ (XWINDOW (all_frames)->frame, w->frame)
2271 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
2272 else if (FRAMEP (all_frames))
2273 candidate_p = EQ (all_frames, w->frame);
2275 return candidate_p;
2279 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
2280 Fwindow_list. See candidate_window_p for the meaning of WINDOW,
2281 MINIBUF, and ALL_FRAMES. */
2283 static void
2284 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
2286 struct window *w = decode_live_window (*window);
2288 XSETWINDOW (*window, w);
2289 /* MINIBUF nil may or may not include minibuffers. Decide if it
2290 does. */
2291 if (NILP (*minibuf))
2292 *minibuf = minibuf_level ? minibuf_window : Qlambda;
2293 else if (!EQ (*minibuf, Qt))
2294 *minibuf = Qlambda;
2296 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
2297 => count none of them, or a specific minibuffer window (the
2298 active one) to count. */
2300 /* ALL_FRAMES nil doesn't specify which frames to include. */
2301 if (NILP (*all_frames))
2302 *all_frames
2303 = (!EQ (*minibuf, Qlambda)
2304 ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame))
2305 : Qnil);
2306 else if (EQ (*all_frames, Qvisible))
2308 else if (EQ (*all_frames, make_number (0)))
2310 else if (FRAMEP (*all_frames))
2312 else if (!EQ (*all_frames, Qt))
2313 *all_frames = Qnil;
2317 /* Return the next or previous window of WINDOW in cyclic ordering
2318 of windows. NEXT_P non-zero means return the next window. See the
2319 documentation string of next-window for the meaning of MINIBUF and
2320 ALL_FRAMES. */
2322 static Lisp_Object
2323 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
2325 decode_next_window_args (&window, &minibuf, &all_frames);
2327 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
2328 return the first window on the frame. */
2329 if (FRAMEP (all_frames)
2330 && !EQ (all_frames, XWINDOW (window)->frame))
2331 return Fframe_first_window (all_frames);
2333 if (next_p)
2335 Lisp_Object list;
2337 /* Find WINDOW in the list of all windows. */
2338 list = Fmemq (window, window_list ());
2340 /* Scan forward from WINDOW to the end of the window list. */
2341 if (CONSP (list))
2342 for (list = XCDR (list); CONSP (list); list = XCDR (list))
2343 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2344 break;
2346 /* Scan from the start of the window list up to WINDOW. */
2347 if (!CONSP (list))
2348 for (list = Vwindow_list;
2349 CONSP (list) && !EQ (XCAR (list), window);
2350 list = XCDR (list))
2351 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2352 break;
2354 if (CONSP (list))
2355 window = XCAR (list);
2357 else
2359 Lisp_Object candidate, list;
2361 /* Scan through the list of windows for candidates. If there are
2362 candidate windows in front of WINDOW, the last one of these
2363 is the one we want. If there are candidates following WINDOW
2364 in the list, again the last one of these is the one we want. */
2365 candidate = Qnil;
2366 for (list = window_list (); CONSP (list); list = XCDR (list))
2368 if (EQ (XCAR (list), window))
2370 if (WINDOWP (candidate))
2371 break;
2373 else if (candidate_window_p (XCAR (list), window, minibuf,
2374 all_frames))
2375 candidate = XCAR (list);
2378 if (WINDOWP (candidate))
2379 window = candidate;
2382 return window;
2386 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2387 doc: /* Return live window after WINDOW in the cyclic ordering of windows.
2388 WINDOW must be a live window and defaults to the selected one. The
2389 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2390 consider.
2392 MINIBUF nil or omitted means consider the minibuffer window only if the
2393 minibuffer is active. MINIBUF t means consider the minibuffer window
2394 even if the minibuffer is not active. Any other value means do not
2395 consider the minibuffer window even if the minibuffer is active.
2397 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2398 plus the minibuffer window if specified by the MINIBUF argument. If the
2399 minibuffer counts, consider all windows on all frames that share that
2400 minibuffer too. The following non-nil values of ALL-FRAMES have special
2401 meanings:
2403 - t means consider all windows on all existing frames.
2405 - `visible' means consider all windows on all visible frames.
2407 - 0 (the number zero) means consider all windows on all visible and
2408 iconified frames.
2410 - A frame means consider all windows on that frame only.
2412 Anything else means consider all windows on WINDOW's frame and no
2413 others.
2415 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2416 `next-window' to iterate through the entire cycle of acceptable
2417 windows, eventually ending up back at the window you started with.
2418 `previous-window' traverses the same cycle, in the reverse order. */)
2419 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2421 return next_window (window, minibuf, all_frames, 1);
2425 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2426 doc: /* Return live window before WINDOW in the cyclic ordering of windows.
2427 WINDOW must be a live window and defaults to the selected one. The
2428 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2429 consider.
2431 MINIBUF nil or omitted means consider the minibuffer window only if the
2432 minibuffer is active. MINIBUF t means consider the minibuffer window
2433 even if the minibuffer is not active. Any other value means do not
2434 consider the minibuffer window even if the minibuffer is active.
2436 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2437 plus the minibuffer window if specified by the MINIBUF argument. If the
2438 minibuffer counts, consider all windows on all frames that share that
2439 minibuffer too. The following non-nil values of ALL-FRAMES have special
2440 meanings:
2442 - t means consider all windows on all existing frames.
2444 - `visible' means consider all windows on all visible frames.
2446 - 0 (the number zero) means consider all windows on all visible and
2447 iconified frames.
2449 - A frame means consider all windows on that frame only.
2451 Anything else means consider all windows on WINDOW's frame and no
2452 others.
2454 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2455 use `previous-window' to iterate through the entire cycle of
2456 acceptable windows, eventually ending up back at the window you
2457 started with. `next-window' traverses the same cycle, in the
2458 reverse order. */)
2459 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2461 return next_window (window, minibuf, all_frames, 0);
2465 /* Return a list of windows in cyclic ordering. Arguments are like
2466 for `next-window'. */
2468 static Lisp_Object
2469 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2471 Lisp_Object tail, list, rest;
2473 decode_next_window_args (&window, &minibuf, &all_frames);
2474 list = Qnil;
2476 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2477 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2478 list = Fcons (XCAR (tail), list);
2480 /* Rotate the list to start with WINDOW. */
2481 list = Fnreverse (list);
2482 rest = Fmemq (window, list);
2483 if (!NILP (rest) && !EQ (rest, list))
2485 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2487 XSETCDR (tail, Qnil);
2488 list = nconc2 (rest, list);
2490 return list;
2494 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2495 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2496 FRAME nil or omitted means use the selected frame.
2497 WINDOW nil or omitted means use the window selected within FRAME.
2498 MINIBUF t means include the minibuffer window, even if it isn't active.
2499 MINIBUF nil or omitted means include the minibuffer window only
2500 if it's active.
2501 MINIBUF neither nil nor t means never include the minibuffer window. */)
2502 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2504 if (NILP (window))
2505 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2506 CHECK_WINDOW (window);
2507 if (NILP (frame))
2508 frame = selected_frame;
2510 if (!EQ (frame, XWINDOW (window)->frame))
2511 error ("Window is on a different frame");
2513 return window_list_1 (window, minibuf, frame);
2517 DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2518 doc: /* Return a list of all live windows.
2519 WINDOW specifies the first window to list and defaults to the selected
2520 window.
2522 Optional argument MINIBUF nil or omitted means consider the minibuffer
2523 window only if the minibuffer is active. MINIBUF t means consider the
2524 minibuffer window even if the minibuffer is not active. Any other value
2525 means do not consider the minibuffer window even if the minibuffer is
2526 active.
2528 Optional argument ALL-FRAMES nil or omitted means consider all windows
2529 on WINDOW's frame, plus the minibuffer window if specified by the
2530 MINIBUF argument. If the minibuffer counts, consider all windows on all
2531 frames that share that minibuffer too. The following non-nil values of
2532 ALL-FRAMES have special meanings:
2534 - t means consider all windows on all existing frames.
2536 - `visible' means consider all windows on all visible frames.
2538 - 0 (the number zero) means consider all windows on all visible and
2539 iconified frames.
2541 - A frame means consider all windows on that frame only.
2543 Anything else means consider all windows on WINDOW's frame and no
2544 others.
2546 If WINDOW is not on the list of windows returned, some other window will
2547 be listed first but no error is signaled. */)
2548 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2550 return window_list_1 (window, minibuf, all_frames);
2553 /* Look at all windows, performing an operation specified by TYPE
2554 with argument OBJ.
2555 If FRAMES is Qt, look at all frames;
2556 Qnil, look at just the selected frame;
2557 Qvisible, look at visible frames;
2558 a frame, just look at windows on that frame.
2559 If MINI is non-zero, perform the operation on minibuffer windows too. */
2561 enum window_loop
2563 WINDOW_LOOP_UNUSED,
2564 GET_BUFFER_WINDOW, /* Arg is buffer */
2565 REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
2566 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2567 CHECK_ALL_WINDOWS /* Arg is ignored */
2570 static Lisp_Object
2571 window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
2573 Lisp_Object window, windows, best_window, frame_arg;
2574 int frame_best_window_flag = 0;
2575 struct frame *f;
2576 struct gcpro gcpro1;
2578 /* If we're only looping through windows on a particular frame,
2579 frame points to that frame. If we're looping through windows
2580 on all frames, frame is 0. */
2581 if (FRAMEP (frames))
2582 f = XFRAME (frames);
2583 else if (NILP (frames))
2584 f = SELECTED_FRAME ();
2585 else
2586 f = NULL;
2588 if (f)
2589 frame_arg = Qlambda;
2590 else if (EQ (frames, make_number (0)))
2591 frame_arg = frames;
2592 else if (EQ (frames, Qvisible))
2593 frame_arg = frames;
2594 else
2595 frame_arg = Qt;
2597 /* frame_arg is Qlambda to stick to one frame,
2598 Qvisible to consider all visible frames,
2599 or Qt otherwise. */
2601 /* Pick a window to start with. */
2602 if (WINDOWP (obj))
2603 window = obj;
2604 else if (f)
2605 window = FRAME_SELECTED_WINDOW (f);
2606 else
2607 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2609 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2610 GCPRO1 (windows);
2611 best_window = Qnil;
2613 for (; CONSP (windows); windows = XCDR (windows))
2615 struct window *w;
2617 window = XCAR (windows);
2618 w = XWINDOW (window);
2620 /* Note that we do not pay attention here to whether the frame
2621 is visible, since Fwindow_list skips non-visible frames if
2622 that is desired, under the control of frame_arg. */
2623 if (!MINI_WINDOW_P (w)
2624 /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
2625 consider all windows. */
2626 || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
2627 || (mini && minibuf_level > 0))
2628 switch (type)
2630 case GET_BUFFER_WINDOW:
2631 if (EQ (w->contents, obj)
2632 /* Don't find any minibuffer window except the one that
2633 is currently in use. */
2634 && (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
2636 if (EQ (window, selected_window))
2637 /* Preferably return the selected window. */
2638 RETURN_UNGCPRO (window);
2639 else if (EQ (XWINDOW (window)->frame, selected_frame)
2640 && !frame_best_window_flag)
2641 /* Prefer windows on the current frame (but don't
2642 choose another one if we have one already). */
2644 best_window = window;
2645 frame_best_window_flag = 1;
2647 else if (NILP (best_window))
2648 best_window = window;
2650 break;
2652 case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
2653 /* We could simply check whether the buffer shown by window
2654 is live, and show another buffer in case it isn't. */
2655 if (EQ (w->contents, obj))
2657 /* Undedicate WINDOW. */
2658 wset_dedicated (w, Qnil);
2659 /* Make WINDOW show the buffer returned by
2660 other_buffer_safely, don't run any hooks. */
2661 set_window_buffer
2662 (window, other_buffer_safely (w->contents), 0, 0);
2663 /* If WINDOW is the selected window, make its buffer
2664 current. But do so only if the window shows the
2665 current buffer (Bug#6454). */
2666 if (EQ (window, selected_window)
2667 && XBUFFER (w->contents) == current_buffer)
2668 Fset_buffer (w->contents);
2670 break;
2672 case REDISPLAY_BUFFER_WINDOWS:
2673 if (EQ (w->contents, obj))
2675 mark_window_display_accurate (window, 0);
2676 w->update_mode_line = 1;
2677 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2678 ++update_mode_lines;
2679 best_window = window;
2681 break;
2683 /* Check for a leaf window that has a killed buffer
2684 or broken markers. */
2685 case CHECK_ALL_WINDOWS:
2686 if (BUFFERP (w->contents))
2688 struct buffer *b = XBUFFER (w->contents);
2690 if (!BUFFER_LIVE_P (b))
2691 emacs_abort ();
2692 if (!MARKERP (w->start) || XMARKER (w->start)->buffer != b)
2693 emacs_abort ();
2694 if (!MARKERP (w->pointm) || XMARKER (w->pointm)->buffer != b)
2695 emacs_abort ();
2697 break;
2699 case WINDOW_LOOP_UNUSED:
2700 break;
2704 UNGCPRO;
2705 return best_window;
2708 /* Used for debugging. Abort if any window has a dead buffer. */
2710 extern void check_all_windows (void) EXTERNALLY_VISIBLE;
2711 void
2712 check_all_windows (void)
2714 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2717 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2718 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2719 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
2720 the current buffer.
2722 The optional argument ALL-FRAMES specifies the frames to consider:
2724 - t means consider all windows on all existing frames.
2726 - `visible' means consider all windows on all visible frames.
2728 - 0 (the number zero) means consider all windows on all visible
2729 and iconified frames.
2731 - A frame means consider all windows on that frame only.
2733 Any other value of ALL-FRAMES means consider all windows on the
2734 selected frame and no others. */)
2735 (Lisp_Object buffer_or_name, Lisp_Object all_frames)
2737 Lisp_Object buffer;
2739 if (NILP (buffer_or_name))
2740 buffer = Fcurrent_buffer ();
2741 else
2742 buffer = Fget_buffer (buffer_or_name);
2744 if (BUFFERP (buffer))
2745 return window_loop (GET_BUFFER_WINDOW, buffer, 1, all_frames);
2746 else
2747 return Qnil;
2750 static Lisp_Object
2751 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore)
2753 return call4 (Qwindow_resize_root_window, window, delta, horizontal, ignore);
2757 DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
2758 Sdelete_other_windows_internal, 0, 2, "",
2759 doc: /* Make WINDOW fill its frame.
2760 Only the frame WINDOW is on is affected. WINDOW must be a valid window
2761 and defaults to the selected one.
2763 Optional argument ROOT, if non-nil, must specify an internal window such
2764 that WINDOW is in its window subtree. If this is the case, replace ROOT
2765 by WINDOW and leave alone any windows not part of ROOT's subtree.
2767 When WINDOW is live try to reduce display jumps by keeping the text
2768 previously visible in WINDOW in the same place on the frame. Doing this
2769 depends on the value of (window-start WINDOW), so if calling this
2770 function in a program gives strange scrolling, make sure the
2771 window-start value is reasonable when this function is called. */)
2772 (Lisp_Object window, Lisp_Object root)
2774 struct window *w, *r, *s;
2775 struct frame *f;
2776 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
2777 ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0);
2778 int top IF_LINT (= 0), new_top, resize_failed;
2780 w = decode_valid_window (window);
2781 XSETWINDOW (window, w);
2782 f = XFRAME (w->frame);
2784 if (NILP (root))
2785 /* ROOT is the frame's root window. */
2787 root = FRAME_ROOT_WINDOW (f);
2788 r = XWINDOW (root);
2790 else
2791 /* ROOT must be an ancestor of WINDOW. */
2793 r = decode_valid_window (root);
2794 pwindow = XWINDOW (window)->parent;
2795 while (!NILP (pwindow))
2796 if (EQ (pwindow, root))
2797 break;
2798 else
2799 pwindow = XWINDOW (pwindow)->parent;
2800 if (!EQ (pwindow, root))
2801 error ("Specified root is not an ancestor of specified window");
2804 if (EQ (window, root))
2805 /* A noop. */
2806 return Qnil;
2807 /* I don't understand the "top > 0" part below. If we deal with a
2808 standalone minibuffer it would have been caught by the preceding
2809 test. */
2810 else if (MINI_WINDOW_P (w)) /* && top > 0) */
2811 error ("Can't expand minibuffer to full frame");
2813 if (BUFFERP (w->contents))
2815 startpos = marker_position (w->start);
2816 startbyte = marker_byte_position (w->start);
2817 top = WINDOW_TOP_EDGE_LINE (w)
2818 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2819 /* Make sure WINDOW is the frame's selected window. */
2820 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
2822 if (EQ (selected_frame, w->frame))
2823 Fselect_window (window, Qnil);
2824 else
2825 fset_selected_window (f, window);
2828 else
2830 /* See if the frame's selected window is a part of the window
2831 subtree rooted at WINDOW, by finding all the selected window's
2832 parents and comparing each one with WINDOW. If it isn't we
2833 need a new selected window for this frame. */
2834 swindow = FRAME_SELECTED_WINDOW (f);
2835 while (1)
2837 pwindow = swindow;
2838 while (!NILP (pwindow) && !EQ (window, pwindow))
2839 pwindow = XWINDOW (pwindow)->parent;
2841 if (EQ (window, pwindow))
2842 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
2843 as the new selected window. */
2844 break;
2845 else
2846 /* Else try the previous window of SWINDOW. */
2847 swindow = Fprevious_window (swindow, Qlambda, Qnil);
2850 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
2852 if (EQ (selected_frame, w->frame))
2853 Fselect_window (swindow, Qnil);
2854 else
2855 fset_selected_window (f, swindow);
2859 block_input ();
2860 if (!FRAME_INITIAL_P (f))
2862 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
2864 /* We are going to free the glyph matrices of WINDOW, and with
2865 that we might lose any information about glyph rows that have
2866 some of their glyphs highlighted in mouse face. (These rows
2867 are marked with a non-zero mouse_face_p flag.) If WINDOW
2868 indeed has some glyphs highlighted in mouse face, signal to
2869 frame's up-to-date hook that mouse highlight was overwritten,
2870 so that it will arrange for redisplaying the highlight. */
2871 if (EQ (hlinfo->mouse_face_window, window))
2873 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
2874 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
2875 hlinfo->mouse_face_window = Qnil;
2878 free_window_matrices (r);
2880 windows_or_buffers_changed++;
2881 Vwindow_list = Qnil;
2882 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
2883 resize_failed = 0;
2885 if (!WINDOW_LEAF_P (w))
2887 /* Resize child windows vertically. */
2888 XSETINT (delta, r->total_lines - w->total_lines);
2889 w->top_line = r->top_line;
2890 resize_root_window (window, delta, Qnil, Qnil);
2891 if (window_resize_check (w, 0))
2892 window_resize_apply (w, 0);
2893 else
2895 resize_root_window (window, delta, Qnil, Qt);
2896 if (window_resize_check (w, 0))
2897 window_resize_apply (w, 0);
2898 else
2899 resize_failed = 1;
2902 /* Resize child windows horizontally. */
2903 if (!resize_failed)
2905 w->left_col = r->left_col;
2906 XSETINT (delta, r->total_cols - w->total_cols);
2907 resize_root_window (window, delta, Qt, Qnil);
2908 if (window_resize_check (w, 1))
2909 window_resize_apply (w, 1);
2910 else
2912 resize_root_window (window, delta, Qt, Qt);
2913 if (window_resize_check (w, 1))
2914 window_resize_apply (w, 1);
2915 else
2916 resize_failed = 1;
2920 if (resize_failed)
2921 /* Play safe, if we still can ... */
2923 window = swindow;
2924 w = XWINDOW (window);
2928 /* Cleanly unlink WINDOW from window-tree. */
2929 if (!NILP (w->prev))
2930 /* Get SIBLING above (on the left of) WINDOW. */
2932 sibling = w->prev;
2933 s = XWINDOW (sibling);
2934 wset_next (s, w->next);
2935 if (!NILP (s->next))
2936 wset_prev (XWINDOW (s->next), sibling);
2938 else
2939 /* Get SIBLING below (on the right of) WINDOW. */
2941 sibling = w->next;
2942 s = XWINDOW (sibling);
2943 wset_prev (s, Qnil);
2944 wset_combination (XWINDOW (w->parent),
2945 XWINDOW (w->parent)->horizontal, sibling);
2948 /* Delete ROOT and all child windows of ROOT. */
2949 if (WINDOWP (r->contents))
2951 delete_all_child_windows (r->contents);
2952 wset_combination (r, 0, Qnil);
2955 replace_window (root, window, 1);
2957 /* This must become SWINDOW anyway ....... */
2958 if (BUFFERP (w->contents) && !resize_failed)
2960 /* Try to minimize scrolling, by setting the window start to the
2961 point will cause the text at the old window start to be at the
2962 same place on the frame. But don't try to do this if the
2963 window start is outside the visible portion (as might happen
2964 when the display is not current, due to typeahead). */
2965 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2966 if (new_top != top
2967 && startpos >= BUF_BEGV (XBUFFER (w->contents))
2968 && startpos <= BUF_ZV (XBUFFER (w->contents)))
2970 struct position pos;
2971 struct buffer *obuf = current_buffer;
2973 Fset_buffer (w->contents);
2974 /* This computation used to temporarily move point, but that
2975 can have unwanted side effects due to text properties. */
2976 pos = *vmotion (startpos, startbyte, -top, w);
2978 set_marker_both (w->start, w->contents, pos.bufpos, pos.bytepos);
2979 w->window_end_valid = 0;
2980 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
2981 || FETCH_BYTE (pos.bytepos - 1) == '\n');
2982 /* We need to do this, so that the window-scroll-functions
2983 get called. */
2984 w->optional_new_start = 1;
2986 set_buffer_internal (obuf);
2990 adjust_glyphs (f);
2991 unblock_input ();
2993 run_window_configuration_change_hook (f);
2995 return Qnil;
2999 void
3000 replace_buffer_in_windows (Lisp_Object buffer)
3002 call1 (Qreplace_buffer_in_windows, buffer);
3005 /* If BUFFER is shown in a window, safely replace it with some other
3006 buffer in all windows of all frames, even those on other keyboards. */
3008 void
3009 replace_buffer_in_windows_safely (Lisp_Object buffer)
3011 if (buffer_window_count (XBUFFER (buffer)))
3013 Lisp_Object tail, frame;
3015 /* A single call to window_loop won't do the job because it only
3016 considers frames on the current keyboard. So loop manually over
3017 frames, and handle each one. */
3018 FOR_EACH_FRAME (tail, frame)
3019 window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
3023 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3024 minimum allowable size. */
3026 void
3027 check_frame_size (struct frame *frame, int *rows, int *cols)
3029 /* For height, we have to see:
3030 how many windows the frame has at minimum (one or two),
3031 and whether it has a menu bar or other special stuff at the top. */
3032 int min_height
3033 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
3034 ? MIN_SAFE_WINDOW_HEIGHT
3035 : 2 * MIN_SAFE_WINDOW_HEIGHT);
3037 if (FRAME_TOP_MARGIN (frame) > 0)
3038 min_height += FRAME_TOP_MARGIN (frame);
3040 if (*rows < min_height)
3041 *rows = min_height;
3042 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3043 *cols = MIN_SAFE_WINDOW_WIDTH;
3046 /* Adjust the margins of window W if text area is too small.
3047 Return 1 if window width is ok after adjustment; 0 if window
3048 is still too narrow. */
3050 static int
3051 adjust_window_margins (struct window *w)
3053 int box_cols = (WINDOW_TOTAL_COLS (w)
3054 - WINDOW_FRINGE_COLS (w)
3055 - WINDOW_SCROLL_BAR_COLS (w));
3056 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
3057 + WINDOW_RIGHT_MARGIN_COLS (w));
3059 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
3060 return 1;
3062 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
3063 return 0;
3065 /* Window's text area is too narrow, but reducing the window
3066 margins will fix that. */
3067 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
3068 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
3070 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
3072 wset_left_margin_cols (w, make_number (margin_cols / 2));
3073 wset_right_margin_cols (w, make_number (margin_cols / 2));
3075 else
3076 wset_right_margin_cols (w, make_number (margin_cols));
3078 else
3079 wset_left_margin_cols (w, make_number (margin_cols));
3080 return 1;
3083 /* The following three routines are needed for running a window's
3084 configuration change hook. */
3085 static void
3086 run_funs (Lisp_Object funs)
3088 for (; CONSP (funs); funs = XCDR (funs))
3089 if (!EQ (XCAR (funs), Qt))
3090 call0 (XCAR (funs));
3093 static void
3094 select_window_norecord (Lisp_Object window)
3096 if (WINDOW_LIVE_P (window))
3097 Fselect_window (window, Qt);
3100 static void
3101 select_frame_norecord (Lisp_Object frame)
3103 if (FRAME_LIVE_P (XFRAME (frame)))
3104 Fselect_frame (frame, Qt);
3107 void
3108 run_window_configuration_change_hook (struct frame *f)
3110 ptrdiff_t count = SPECPDL_INDEX ();
3111 Lisp_Object frame, global_wcch
3112 = Fdefault_value (Qwindow_configuration_change_hook);
3113 XSETFRAME (frame, f);
3115 if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code))
3116 return;
3118 /* Use the right buffer. Matters when running the local hooks. */
3119 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3121 record_unwind_current_buffer ();
3122 Fset_buffer (Fwindow_buffer (Qnil));
3125 if (SELECTED_FRAME () != f)
3127 record_unwind_protect (select_frame_norecord, selected_frame);
3128 select_frame_norecord (frame);
3131 /* Look for buffer-local values. */
3133 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3134 for (; CONSP (windows); windows = XCDR (windows))
3136 Lisp_Object window = XCAR (windows);
3137 Lisp_Object buffer = Fwindow_buffer (window);
3138 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3139 buffer)))
3141 ptrdiff_t inner_count = SPECPDL_INDEX ();
3142 record_unwind_protect (select_window_norecord, selected_window);
3143 select_window_norecord (window);
3144 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3145 buffer));
3146 unbind_to (inner_count, Qnil);
3151 run_funs (global_wcch);
3152 unbind_to (count, Qnil);
3155 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
3156 Srun_window_configuration_change_hook, 0, 1, 0,
3157 doc: /* Run `window-configuration-change-hook' for FRAME.
3158 If FRAME is omitted or nil, it defaults to the selected frame. */)
3159 (Lisp_Object frame)
3161 run_window_configuration_change_hook (decode_live_frame (frame));
3162 return Qnil;
3165 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3166 means it's allowed to run hooks. See make_frame for a case where
3167 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3168 margins, fringes, and scroll-bar settings of the window are not
3169 reset from the buffer's local settings. */
3171 void
3172 set_window_buffer (Lisp_Object window, Lisp_Object buffer,
3173 bool run_hooks_p, bool keep_margins_p)
3175 struct window *w = XWINDOW (window);
3176 struct buffer *b = XBUFFER (buffer);
3177 ptrdiff_t count = SPECPDL_INDEX ();
3178 int samebuf = EQ (buffer, w->contents);
3180 wset_buffer (w, buffer);
3182 if (EQ (window, selected_window))
3183 bset_last_selected_window (b, window);
3185 /* Let redisplay errors through. */
3186 b->display_error_modiff = 0;
3188 /* Update time stamps of buffer display. */
3189 if (INTEGERP (BVAR (b, display_count)))
3190 bset_display_count (b, make_number (XINT (BVAR (b, display_count)) + 1));
3191 bset_display_time (b, Fcurrent_time ());
3193 wset_window_end_pos (w, make_number (0));
3194 wset_window_end_vpos (w, make_number (0));
3195 memset (&w->last_cursor, 0, sizeof w->last_cursor);
3197 if (!(keep_margins_p && samebuf))
3198 { /* If we're not actually changing the buffer, don't reset hscroll and
3199 vscroll. This case happens for example when called from
3200 change_frame_size_1, where we use a dummy call to
3201 Fset_window_buffer on the frame's selected window (and no other)
3202 just in order to run window-configuration-change-hook.
3203 Resetting hscroll and vscroll here is problematic for things like
3204 image-mode and doc-view-mode since it resets the image's position
3205 whenever we resize the frame. */
3206 w->hscroll = w->min_hscroll = 0;
3207 w->vscroll = 0;
3208 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3209 set_marker_restricted (w->start,
3210 make_number (b->last_window_start),
3211 buffer);
3212 w->start_at_line_beg = 0;
3213 w->force_start = 0;
3215 /* Maybe we could move this into the `if' but it's not obviously safe and
3216 I doubt it's worth the trouble. */
3217 windows_or_buffers_changed++;
3219 /* We must select BUFFER for running the window-scroll-functions. */
3220 /* We can't check ! NILP (Vwindow_scroll_functions) here
3221 because that might itself be a local variable. */
3222 if (window_initialized)
3224 record_unwind_current_buffer ();
3225 Fset_buffer (buffer);
3228 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3230 if (!keep_margins_p)
3232 /* Set left and right marginal area width etc. from buffer. */
3234 /* This may call adjust_window_margins three times, so
3235 temporarily disable window margins. */
3236 Lisp_Object save_left = w->left_margin_cols;
3237 Lisp_Object save_right = w->right_margin_cols;
3239 wset_left_margin_cols (w, Qnil);
3240 wset_right_margin_cols (w, Qnil);
3242 Fset_window_fringes (window,
3243 BVAR (b, left_fringe_width), BVAR (b, right_fringe_width),
3244 BVAR (b, fringes_outside_margins));
3246 Fset_window_scroll_bars (window,
3247 BVAR (b, scroll_bar_width),
3248 BVAR (b, vertical_scroll_bar_type), Qnil);
3250 wset_left_margin_cols (w, save_left);
3251 wset_right_margin_cols (w, save_right);
3253 Fset_window_margins (window,
3254 BVAR (b, left_margin_cols), BVAR (b, right_margin_cols));
3257 if (run_hooks_p)
3259 if (! NILP (Vwindow_scroll_functions))
3260 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3261 Fmarker_position (w->start));
3262 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3265 unbind_to (count, Qnil);
3268 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3269 doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3270 WINDOW must be a live window and defaults to the selected one.
3271 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
3273 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
3274 display margins, fringe widths, and scroll bar settings are preserved;
3275 the default is to reset these from the local settings for BUFFER-OR-NAME
3276 or the frame defaults. Return nil.
3278 This function throws an error when WINDOW is strongly dedicated to its
3279 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3280 already display BUFFER-OR-NAME.
3282 This function runs `window-scroll-functions' before running
3283 `window-configuration-change-hook'. */)
3284 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3286 register Lisp_Object tem, buffer;
3287 register struct window *w = decode_live_window (window);
3289 XSETWINDOW (window, w);
3290 buffer = Fget_buffer (buffer_or_name);
3291 CHECK_BUFFER (buffer);
3292 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3293 error ("Attempt to display deleted buffer");
3295 tem = w->contents;
3296 if (NILP (tem))
3297 error ("Window is deleted");
3298 else
3300 if (!EQ (tem, buffer))
3302 if (EQ (w->dedicated, Qt))
3303 /* WINDOW is strongly dedicated to its buffer, signal an
3304 error. */
3305 error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
3306 else
3307 /* WINDOW is weakly dedicated to its buffer, reset
3308 dedication. */
3309 wset_dedicated (w, Qnil);
3311 call1 (Qrecord_window_buffer, window);
3314 unshow_buffer (w);
3317 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3319 return Qnil;
3322 static Lisp_Object
3323 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3325 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3328 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3329 0, 1, 0,
3330 doc: /* Force all windows to be updated on next redisplay.
3331 If optional arg OBJECT is a window, force redisplay of that window only.
3332 If OBJECT is a buffer or buffer name, force redisplay of all windows
3333 displaying that buffer. */)
3334 (Lisp_Object object)
3336 if (NILP (object))
3338 windows_or_buffers_changed++;
3339 update_mode_lines++;
3340 return Qt;
3343 if (WINDOWP (object))
3345 struct window *w = XWINDOW (object);
3346 mark_window_display_accurate (object, 0);
3347 w->update_mode_line = 1;
3348 if (BUFFERP (w->contents))
3349 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
3350 ++update_mode_lines;
3351 return Qt;
3354 if (STRINGP (object))
3355 object = Fget_buffer (object);
3356 if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))
3357 && buffer_window_count (XBUFFER (object)))
3359 /* If buffer is live and shown in at least one window, find
3360 all windows showing this buffer and force update of them. */
3361 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3362 return NILP (object) ? Qnil : Qt;
3365 /* If nothing suitable was found, just return.
3366 We could signal an error, but this feature will typically be used
3367 asynchronously in timers or process sentinels, so we don't. */
3368 return Qnil;
3371 /* Obsolete since 24.3. */
3372 void
3373 temp_output_buffer_show (register Lisp_Object buf)
3375 register struct buffer *old = current_buffer;
3376 register Lisp_Object window;
3377 register struct window *w;
3379 bset_directory (XBUFFER (buf), BVAR (current_buffer, directory));
3381 Fset_buffer (buf);
3382 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3383 BEGV = BEG;
3384 ZV = Z;
3385 SET_PT (BEG);
3386 set_buffer_internal (old);
3388 if (!NILP (Vtemp_buffer_show_function))
3389 call1 (Vtemp_buffer_show_function, buf);
3390 else
3392 window = display_buffer (buf, Qnil, Qnil);
3394 if (!EQ (XWINDOW (window)->frame, selected_frame))
3395 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3396 Vminibuf_scroll_window = window;
3397 w = XWINDOW (window);
3398 w->hscroll = 0;
3399 w->min_hscroll = 0;
3400 set_marker_restricted_both (w->start, buf, BEG, BEG);
3401 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3403 /* Run temp-buffer-show-hook, with the chosen window selected
3404 and its buffer current. */
3406 ptrdiff_t count = SPECPDL_INDEX ();
3407 Lisp_Object prev_window, prev_buffer;
3408 prev_window = selected_window;
3409 XSETBUFFER (prev_buffer, old);
3411 /* Select the window that was chosen, for running the hook.
3412 Note: Both Fselect_window and select_window_norecord may
3413 set-buffer to the buffer displayed in the window,
3414 so we need to save the current buffer. --stef */
3415 record_unwind_protect (restore_buffer, prev_buffer);
3416 record_unwind_protect (select_window_norecord, prev_window);
3417 Fselect_window (window, Qt);
3418 Fset_buffer (w->contents);
3419 Frun_hooks (1, &Qtemp_buffer_show_hook);
3420 unbind_to (count, Qnil);
3425 /* Make new window, have it replace WINDOW in window-tree, and make
3426 WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
3427 horizontal child). */
3428 static void
3429 make_parent_window (Lisp_Object window, bool horflag)
3431 Lisp_Object parent;
3432 register struct window *o, *p;
3434 o = XWINDOW (window);
3435 p = allocate_window ();
3436 memcpy ((char *) p + sizeof (struct vectorlike_header),
3437 (char *) o + sizeof (struct vectorlike_header),
3438 word_size * VECSIZE (struct window));
3439 /* P's buffer slot may change from nil to a buffer... */
3440 adjust_window_count (p, 1);
3441 XSETWINDOW (parent, p);
3443 replace_window (window, parent, 1);
3445 wset_next (o, Qnil);
3446 wset_prev (o, Qnil);
3447 wset_parent (o, parent);
3448 /* ...but now P becomes an internal window. */
3449 wset_start (p, Qnil);
3450 wset_pointm (p, Qnil);
3451 wset_buffer (p, Qnil);
3452 wset_combination (p, horflag, window);
3453 wset_combination_limit (p, Qnil);
3454 wset_window_parameters (p, Qnil);
3457 /* Make new window from scratch. */
3458 Lisp_Object
3459 make_window (void)
3461 Lisp_Object window;
3462 register struct window *w;
3464 w = allocate_window ();
3465 /* Initialize Lisp data. Note that allocate_window initializes all
3466 Lisp data to nil, so do it only for slots which should not be nil. */
3467 wset_normal_lines (w, make_float (1.0));
3468 wset_normal_cols (w, make_float (1.0));
3469 wset_new_total (w, make_number (0));
3470 wset_new_normal (w, make_number (0));
3471 wset_start (w, Fmake_marker ());
3472 wset_pointm (w, Fmake_marker ());
3473 wset_vertical_scroll_bar_type (w, Qt);
3474 wset_window_end_pos (w, make_number (0));
3475 wset_window_end_vpos (w, make_number (0));
3476 /* These Lisp fields are marked specially so they're not set to nil by
3477 allocate_window. */
3478 wset_prev_buffers (w, Qnil);
3479 wset_next_buffers (w, Qnil);
3481 /* Initialize non-Lisp data. Note that allocate_window zeroes out all
3482 non-Lisp data, so do it only for slots which should not be zero. */
3483 w->nrows_scale_factor = w->ncols_scale_factor = 1;
3484 w->phys_cursor_type = -1;
3485 w->phys_cursor_width = -1;
3486 w->column_number_displayed = -1;
3488 /* Reset window_list. */
3489 Vwindow_list = Qnil;
3490 /* Return window. */
3491 XSETWINDOW (window, w);
3492 return window;
3495 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
3496 doc: /* Set new total size of WINDOW to SIZE.
3497 WINDOW must be a valid window and defaults to the selected one.
3498 Return SIZE.
3500 Optional argument ADD non-nil means add SIZE to the new total size of
3501 WINDOW and return the sum.
3503 Note: This function does not operate on any child windows of WINDOW. */)
3504 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3506 struct window *w = decode_valid_window (window);
3508 CHECK_NUMBER (size);
3509 if (NILP (add))
3510 wset_new_total (w, size);
3511 else
3512 wset_new_total (w, make_number (XINT (w->new_total) + XINT (size)));
3514 return w->new_total;
3517 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
3518 doc: /* Set new normal size of WINDOW to SIZE.
3519 WINDOW must be a valid window and defaults to the selected one.
3520 Return SIZE.
3522 Note: This function does not operate on any child windows of WINDOW. */)
3523 (Lisp_Object window, Lisp_Object size)
3525 wset_new_normal (decode_valid_window (window), size);
3526 return size;
3529 /* Return 1 if setting w->total_lines (w->total_cols if HORFLAG is
3530 non-zero) to w->new_total would result in correct heights (widths)
3531 for window W and recursively all child windows of W.
3533 Note: This function does not check any of `window-fixed-size-p',
3534 `window-min-height' or `window-min-width'. It does check that window
3535 sizes do not drop below one line (two columns). */
3536 static int
3537 window_resize_check (struct window *w, bool horflag)
3539 struct window *c;
3541 if (WINDOW_VERTICAL_COMBINATION_P (w))
3542 /* W is a vertical combination. */
3544 c = XWINDOW (w->contents);
3545 if (horflag)
3546 /* All child windows of W must have the same width as W. */
3548 while (c)
3550 if ((XINT (c->new_total) != XINT (w->new_total))
3551 || !window_resize_check (c, horflag))
3552 return 0;
3553 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3555 return 1;
3557 else
3558 /* The sum of the heights of the child windows of W must equal
3559 W's height. */
3561 int sum_of_sizes = 0;
3562 while (c)
3564 if (!window_resize_check (c, horflag))
3565 return 0;
3566 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3567 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3569 return (sum_of_sizes == XINT (w->new_total));
3572 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3573 /* W is a horizontal combination. */
3575 c = XWINDOW (w->contents);
3576 if (horflag)
3577 /* The sum of the widths of the child windows of W must equal W's
3578 width. */
3580 int sum_of_sizes = 0;
3581 while (c)
3583 if (!window_resize_check (c, horflag))
3584 return 0;
3585 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3586 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3588 return (sum_of_sizes == XINT (w->new_total));
3590 else
3591 /* All child windows of W must have the same height as W. */
3593 while (c)
3595 if ((XINT (c->new_total) != XINT (w->new_total))
3596 || !window_resize_check (c, horflag))
3597 return 0;
3598 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3600 return 1;
3603 else
3604 /* A leaf window. Make sure it's not too small. The following
3605 hardcodes the values of `window-safe-min-width' (2) and
3606 `window-safe-min-height' (1) which are defined in window.el. */
3607 return XINT (w->new_total) >= (horflag ? 2 : 1);
3610 /* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
3611 w->new_total for window W and recursively all child windows of W.
3612 Also calculate and assign the new vertical (horizontal) start
3613 positions of each of these windows.
3615 This function does not perform any error checks. Make sure you have
3616 run window_resize_check on W before applying this function. */
3617 static void
3618 window_resize_apply (struct window *w, bool horflag)
3620 struct window *c;
3621 int pos;
3623 /* Note: Assigning new_normal requires that the new total size of the
3624 parent window has been set *before*. */
3625 if (horflag)
3627 w->total_cols = XFASTINT (w->new_total);
3628 if (NUMBERP (w->new_normal))
3629 wset_normal_cols (w, w->new_normal);
3631 pos = w->left_col;
3633 else
3635 w->total_lines = XFASTINT (w->new_total);
3636 if (NUMBERP (w->new_normal))
3637 wset_normal_lines (w, w->new_normal);
3639 pos = w->top_line;
3642 if (WINDOW_VERTICAL_COMBINATION_P (w))
3643 /* W is a vertical combination. */
3645 c = XWINDOW (w->contents);
3646 while (c)
3648 if (horflag)
3649 c->left_col = pos;
3650 else
3651 c->top_line = pos;
3652 window_resize_apply (c, horflag);
3653 if (!horflag)
3654 pos = pos + c->total_lines;
3655 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3658 else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
3659 /* W is a horizontal combination. */
3661 c = XWINDOW (w->contents);
3662 while (c)
3664 if (horflag)
3665 c->left_col = pos;
3666 else
3667 c->top_line = pos;
3668 window_resize_apply (c, horflag);
3669 if (horflag)
3670 pos = pos + c->total_cols;
3671 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3677 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 0, 2, 0,
3678 doc: /* Apply requested size values for window-tree of FRAME.
3679 If FRAME is omitted or nil, it defaults to the selected frame.
3681 Optional argument HORIZONTAL omitted or nil means apply requested
3682 height values. HORIZONTAL non-nil means apply requested width values.
3684 This function checks whether the requested values sum up to a valid
3685 window layout, recursively assigns the new sizes of all child windows
3686 and calculates and assigns the new start positions of these windows.
3688 Note: This function does not check any of `window-fixed-size-p',
3689 `window-min-height' or `window-min-width'. All these checks have to
3690 be applied on the Elisp level. */)
3691 (Lisp_Object frame, Lisp_Object horizontal)
3693 struct frame *f = decode_live_frame (frame);
3694 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
3695 bool horflag = !NILP (horizontal);
3697 if (!window_resize_check (r, horflag)
3698 || (XINT (r->new_total)
3699 != (horflag ? r->total_cols : r->total_lines)))
3700 return Qnil;
3702 block_input ();
3703 window_resize_apply (r, horflag);
3705 windows_or_buffers_changed++;
3706 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3708 adjust_glyphs (f);
3709 unblock_input ();
3711 run_window_configuration_change_hook (f);
3713 return Qt;
3717 /* Resize frame F's windows when number of lines of F is set to SIZE.
3718 HORFLAG 1 means resize windows when number of columns of F is set to
3719 SIZE.
3721 This function can delete all windows but the selected one in order to
3722 satisfy the request. The result will be meaningful if and only if
3723 F's windows have meaningful sizes when you call this. */
3724 void
3725 resize_frame_windows (struct frame *f, int size, bool horflag)
3727 Lisp_Object root = f->root_window;
3728 struct window *r = XWINDOW (root);
3729 Lisp_Object mini = f->minibuffer_window;
3730 struct window *m;
3731 /* new_size is the new size of the frame's root window. */
3732 int new_size = (horflag
3733 ? size
3734 : (size
3735 - FRAME_TOP_MARGIN (f)
3736 - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3737 ? 1 : 0)));
3739 r->top_line = FRAME_TOP_MARGIN (f);
3740 if (WINDOW_LEAF_P (r))
3741 /* For a leaf root window just set the size. */
3742 if (horflag)
3743 r->total_cols = new_size;
3744 else
3745 r->total_lines = new_size;
3746 else
3748 /* old_size is the old size of the frame's root window. */
3749 int old_size = horflag ? r->total_cols : r->total_lines;
3750 Lisp_Object delta;
3752 XSETINT (delta, new_size - old_size);
3753 /* Try a "normal" resize first. */
3754 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil);
3755 if (window_resize_check (r, horflag)
3756 && new_size == XINT (r->new_total))
3757 window_resize_apply (r, horflag);
3758 else
3760 /* Try with "reasonable" minimum sizes next. */
3761 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt);
3762 if (window_resize_check (r, horflag)
3763 && new_size == XINT (r->new_total))
3764 window_resize_apply (r, horflag);
3765 else
3767 /* Finally, try with "safe" minimum sizes. */
3768 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe);
3769 if (window_resize_check (r, horflag)
3770 && new_size == XINT (r->new_total))
3771 window_resize_apply (r, horflag);
3772 else
3774 /* We lost. Delete all windows but the frame's
3775 selected one. */
3776 root = f->selected_window;
3777 Fdelete_other_windows_internal (root, Qnil);
3778 if (horflag)
3779 XWINDOW (root)->total_cols = new_size;
3780 else
3781 XWINDOW (root)->total_lines = new_size;
3787 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3789 m = XWINDOW (mini);
3790 if (horflag)
3791 m->total_cols = size;
3792 else
3794 /* Are we sure we always want 1 line here? */
3795 m->total_lines = 1;
3796 m->top_line = r->top_line + r->total_lines;
3800 windows_or_buffers_changed++;
3804 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
3805 doc: /* Split window OLD.
3806 Second argument TOTAL-SIZE specifies the number of lines or columns of the
3807 new window. In any case TOTAL-SIZE must be a positive integer.
3809 Third argument SIDE nil (or `below') specifies that the new window shall
3810 be located below WINDOW. SIDE `above' means the new window shall be
3811 located above WINDOW. In both cases TOTAL-SIZE specifies the number of
3812 lines of the new window including space reserved for the mode and/or
3813 header line.
3815 SIDE t (or `right') specifies that the new window shall be located on
3816 the right side of WINDOW. SIDE `left' means the new window shall be
3817 located on the left of WINDOW. In both cases TOTAL-SIZE specifies the
3818 number of columns of the new window including space reserved for fringes
3819 and the scrollbar or a divider column.
3821 Fourth argument NORMAL-SIZE specifies the normal size of the new window
3822 according to the SIDE argument.
3824 The new total and normal sizes of all involved windows must have been
3825 set correctly. See the code of `split-window' for how this is done. */)
3826 (Lisp_Object old, Lisp_Object total_size, Lisp_Object side, Lisp_Object normal_size)
3828 /* OLD (*o) is the window we have to split. (*p) is either OLD's
3829 parent window or an internal window we have to install as OLD's new
3830 parent. REFERENCE (*r) must denote a live window, or is set to OLD
3831 provided OLD is a leaf window, or to the frame's selected window.
3832 NEW (*n) is the new window created with some parameters taken from
3833 REFERENCE (*r). */
3834 register Lisp_Object new, frame, reference;
3835 register struct window *o, *p, *n, *r;
3836 struct frame *f;
3837 bool horflag
3838 /* HORFLAG is 1 when we split side-by-side, 0 otherwise. */
3839 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
3840 int combination_limit = 0;
3842 CHECK_WINDOW (old);
3843 o = XWINDOW (old);
3844 frame = WINDOW_FRAME (o);
3845 f = XFRAME (frame);
3847 CHECK_NUMBER (total_size);
3849 /* Set combination_limit to 1 if we have to make a new parent window.
3850 We do that if either `window-combination-limit' is t, or OLD has no
3851 parent, or OLD is ortho-combined. */
3852 combination_limit =
3853 EQ (Vwindow_combination_limit, Qt)
3854 || NILP (o->parent)
3855 || (horflag
3856 ? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
3857 : WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent)));
3859 /* We need a live reference window to initialize some parameters. */
3860 if (WINDOW_LIVE_P (old))
3861 /* OLD is live, use it as reference window. */
3862 reference = old;
3863 else
3864 /* Use the frame's selected window as reference window. */
3865 reference = FRAME_SELECTED_WINDOW (f);
3866 r = XWINDOW (reference);
3868 /* The following bugs are caught by `split-window'. */
3869 if (MINI_WINDOW_P (o))
3870 error ("Attempt to split minibuffer window");
3871 else if (XINT (total_size) < (horflag ? 2 : 1))
3872 error ("Size of new window too small (after split)");
3873 else if (!combination_limit && !NILP (Vwindow_combination_resize))
3874 /* `window-combination-resize' non-nil means try to resize OLD's siblings
3875 proportionally. */
3877 p = XWINDOW (o->parent);
3878 /* Temporarily pretend we split the parent window. */
3879 wset_new_total
3880 (p, make_number ((horflag ? p->total_cols : p->total_lines)
3881 - XINT (total_size)));
3882 if (!window_resize_check (p, horflag))
3883 error ("Window sizes don't fit");
3884 else
3885 /* Undo the temporary pretension. */
3886 wset_new_total (p, make_number
3887 (horflag ? p->total_cols : p->total_lines));
3889 else
3891 if (!window_resize_check (o, horflag))
3892 error ("Resizing old window failed");
3893 else if (XINT (total_size) + XINT (o->new_total)
3894 != (horflag ? o->total_cols : o->total_lines))
3895 error ("Sum of sizes of old and new window don't fit");
3898 /* This is our point of no return. */
3899 if (combination_limit)
3901 /* Save the old value of o->normal_cols/lines. It gets corrupted
3902 by make_parent_window and we need it below for assigning it to
3903 p->new_normal. */
3904 Lisp_Object new_normal
3905 = horflag ? o->normal_cols : o->normal_lines;
3907 make_parent_window (old, horflag);
3908 p = XWINDOW (o->parent);
3909 if (EQ (Vwindow_combination_limit, Qt))
3910 /* Store t in the new parent's combination_limit slot to avoid
3911 that its children get merged into another window. */
3912 wset_combination_limit (p, Qt);
3913 /* These get applied below. */
3914 wset_new_total (p, make_number
3915 (horflag ? o->total_cols : o->total_lines));
3916 wset_new_normal (p, new_normal);
3918 else
3919 p = XWINDOW (o->parent);
3921 windows_or_buffers_changed++;
3922 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3923 new = make_window ();
3924 n = XWINDOW (new);
3925 wset_frame (n, frame);
3926 wset_parent (n, o->parent);
3928 if (EQ (side, Qabove) || EQ (side, Qleft))
3930 wset_prev (n, o->prev);
3931 if (NILP (n->prev))
3932 wset_combination (p, horflag, new);
3933 else
3934 wset_next (XWINDOW (n->prev), new);
3935 wset_next (n, old);
3936 wset_prev (o, new);
3938 else
3940 wset_next (n, o->next);
3941 if (!NILP (n->next))
3942 wset_prev (XWINDOW (n->next), new);
3943 wset_prev (n, old);
3944 wset_next (o, new);
3947 n->window_end_valid = 0;
3948 memset (&n->last_cursor, 0, sizeof n->last_cursor);
3950 /* Get special geometry settings from reference window. */
3951 wset_left_margin_cols (n, r->left_margin_cols);
3952 wset_right_margin_cols (n, r->right_margin_cols);
3953 wset_left_fringe_width (n, r->left_fringe_width);
3954 wset_right_fringe_width (n, r->right_fringe_width);
3955 n->fringes_outside_margins = r->fringes_outside_margins;
3956 wset_scroll_bar_width (n, r->scroll_bar_width);
3957 wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
3959 /* Directly assign orthogonal coordinates and sizes. */
3960 if (horflag)
3962 n->top_line = o->top_line;
3963 n->total_lines = o->total_lines;
3965 else
3967 n->left_col = o->left_col;
3968 n->total_cols = o->total_cols;
3971 /* Iso-coordinates and sizes are assigned by window_resize_apply,
3972 get them ready here. */
3973 wset_new_total (n, total_size);
3974 wset_new_normal (n, normal_size);
3976 block_input ();
3977 window_resize_apply (p, horflag);
3978 adjust_glyphs (f);
3979 /* Set buffer of NEW to buffer of reference window. Don't run
3980 any hooks. */
3981 set_window_buffer (new, r->contents, 0, 1);
3982 unblock_input ();
3984 /* Maybe we should run the scroll functions in Elisp (which already
3985 runs the configuration change hook). */
3986 if (! NILP (Vwindow_scroll_functions))
3987 run_hook_with_args_2 (Qwindow_scroll_functions, new,
3988 Fmarker_position (n->start));
3989 /* Return NEW. */
3990 return new;
3994 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
3995 doc: /* Remove WINDOW from its frame.
3996 WINDOW defaults to the selected window. Return nil.
3997 Signal an error when WINDOW is the only window on its frame. */)
3998 (register Lisp_Object window)
4000 register Lisp_Object parent, sibling, frame, root;
4001 struct window *w, *p, *s, *r;
4002 struct frame *f;
4003 bool horflag, before_sibling = 0;
4005 w = decode_any_window (window);
4006 XSETWINDOW (window, w);
4007 if (NILP (w->contents))
4008 /* It's a no-op to delete an already deleted window. */
4009 return Qnil;
4011 parent = w->parent;
4012 if (NILP (parent))
4013 /* Never delete a minibuffer or frame root window. */
4014 error ("Attempt to delete minibuffer or sole ordinary window");
4015 else if (NILP (w->prev) && NILP (w->next))
4016 /* Rather bow out here, this case should be handled on the Elisp
4017 level. */
4018 error ("Attempt to delete sole window of parent");
4020 p = XWINDOW (parent);
4021 horflag = WINDOW_HORIZONTAL_COMBINATION_P (p);
4023 frame = WINDOW_FRAME (w);
4024 f = XFRAME (frame);
4026 root = FRAME_ROOT_WINDOW (f);
4027 r = XWINDOW (root);
4029 /* Unlink WINDOW from window tree. */
4030 if (NILP (w->prev))
4031 /* Get SIBLING below (on the right of) WINDOW. */
4033 /* before_sibling 1 means WINDOW is the first child of its
4034 parent and thus before the sibling. */
4035 before_sibling = 1;
4036 sibling = w->next;
4037 s = XWINDOW (sibling);
4038 wset_prev (s, Qnil);
4039 wset_combination (p, horflag, sibling);
4041 else
4042 /* Get SIBLING above (on the left of) WINDOW. */
4044 sibling = w->prev;
4045 s = XWINDOW (sibling);
4046 wset_next (s, w->next);
4047 if (!NILP (s->next))
4048 wset_prev (XWINDOW (s->next), sibling);
4051 if (window_resize_check (r, horflag)
4052 && (XINT (r->new_total)
4053 == (horflag ? r->total_cols : r->total_lines)))
4054 /* We can delete WINDOW now. */
4057 /* Block input. */
4058 block_input ();
4059 window_resize_apply (p, horflag);
4061 /* If this window is referred to by the dpyinfo's mouse
4062 highlight, invalidate that slot to be safe (Bug#9904). */
4063 if (!FRAME_INITIAL_P (f))
4065 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
4067 if (EQ (hlinfo->mouse_face_window, window))
4068 hlinfo->mouse_face_window = Qnil;
4071 windows_or_buffers_changed++;
4072 Vwindow_list = Qnil;
4073 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4075 wset_next (w, Qnil); /* Don't delete w->next too. */
4076 free_window_matrices (w);
4078 if (WINDOWP (w->contents))
4080 delete_all_child_windows (w->contents);
4081 wset_combination (w, 0, Qnil);
4083 else
4085 unshow_buffer (w);
4086 unchain_marker (XMARKER (w->pointm));
4087 unchain_marker (XMARKER (w->start));
4088 wset_buffer (w, Qnil);
4091 if (NILP (s->prev) && NILP (s->next))
4092 /* A matrjoshka where SIBLING has become the only child of
4093 PARENT. */
4095 /* Put SIBLING into PARENT's place. */
4096 replace_window (parent, sibling, 0);
4097 /* Have SIBLING inherit the following three slot values from
4098 PARENT (the combination_limit slot is not inherited). */
4099 wset_normal_cols (s, p->normal_cols);
4100 wset_normal_lines (s, p->normal_lines);
4101 /* Mark PARENT as deleted. */
4102 wset_combination (p, 0, Qnil);
4103 /* Try to merge SIBLING into its new parent. */
4104 recombine_windows (sibling);
4107 adjust_glyphs (f);
4109 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
4110 /* We deleted the frame's selected window. */
4112 /* Use the frame's first window as fallback ... */
4113 Lisp_Object new_selected_window = Fframe_first_window (frame);
4114 /* ... but preferably use its most recently used window. */
4115 Lisp_Object mru_window;
4117 /* `get-mru-window' might fail for some reason so play it safe
4118 - promote the first window _without recording it_ first. */
4119 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4120 Fselect_window (new_selected_window, Qt);
4121 else
4122 fset_selected_window (f, new_selected_window);
4124 unblock_input ();
4126 /* Now look whether `get-mru-window' gets us something. */
4127 mru_window = call1 (Qget_mru_window, frame);
4128 if (WINDOW_LIVE_P (mru_window)
4129 && EQ (XWINDOW (mru_window)->frame, frame))
4130 new_selected_window = mru_window;
4132 /* If all ended up well, we now promote the mru window. */
4133 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4134 Fselect_window (new_selected_window, Qnil);
4135 else
4136 fset_selected_window (f, new_selected_window);
4138 else
4139 unblock_input ();
4141 /* Must be run by the caller:
4142 run_window_configuration_change_hook (f); */
4144 else
4145 /* We failed: Relink WINDOW into window tree. */
4147 if (before_sibling)
4149 wset_prev (s, window);
4150 wset_combination (p, horflag, window);
4152 else
4154 wset_next (s, window);
4155 if (!NILP (w->next))
4156 wset_prev (XWINDOW (w->next), window);
4158 error ("Deletion failed");
4161 return Qnil;
4164 /***********************************************************************
4165 Resizing Mini-Windows
4166 ***********************************************************************/
4168 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
4169 can. */
4170 void
4171 grow_mini_window (struct window *w, int delta)
4173 struct frame *f = XFRAME (w->frame);
4174 struct window *r;
4175 Lisp_Object root, value;
4177 eassert (MINI_WINDOW_P (w));
4178 eassert (delta >= 0);
4180 root = FRAME_ROOT_WINDOW (f);
4181 r = XWINDOW (root);
4182 value = call2 (Qwindow_resize_root_window_vertically,
4183 root, make_number (- delta));
4184 if (INTEGERP (value) && window_resize_check (r, 0))
4186 block_input ();
4187 window_resize_apply (r, 0);
4189 /* Grow the mini-window. */
4190 w->top_line = r->top_line + r->total_lines;
4191 w->total_lines -= XINT (value);
4192 /* Enforce full redisplay. FIXME: make it more selective. */
4193 windows_or_buffers_changed++;
4194 adjust_glyphs (f);
4195 unblock_input ();
4200 /* Shrink mini-window W. */
4201 void
4202 shrink_mini_window (struct window *w)
4204 struct frame *f = XFRAME (w->frame);
4205 struct window *r;
4206 Lisp_Object root, value;
4207 EMACS_INT size;
4209 eassert (MINI_WINDOW_P (w));
4211 size = w->total_lines;
4212 if (size > 1)
4214 root = FRAME_ROOT_WINDOW (f);
4215 r = XWINDOW (root);
4216 value = call2 (Qwindow_resize_root_window_vertically,
4217 root, make_number (size - 1));
4218 if (INTEGERP (value) && window_resize_check (r, 0))
4220 block_input ();
4221 window_resize_apply (r, 0);
4223 /* Shrink the mini-window. */
4224 w->top_line = r->top_line + r->total_lines;
4225 w->total_lines = 1;
4226 /* Enforce full redisplay. FIXME: make it more selective. */
4227 windows_or_buffers_changed++;
4228 adjust_glyphs (f);
4229 unblock_input ();
4231 /* If the above failed for whatever strange reason we must make a
4232 one window frame here. The same routine will be needed when
4233 shrinking the frame (and probably when making the initial
4234 *scratch* window). For the moment leave things as they are. */
4238 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
4239 doc: /* Resize minibuffer window WINDOW. */)
4240 (Lisp_Object window)
4242 struct window *w = XWINDOW (window);
4243 struct window *r;
4244 struct frame *f;
4245 int height;
4247 CHECK_WINDOW (window);
4248 f = XFRAME (w->frame);
4250 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
4251 error ("Not a valid minibuffer window");
4252 else if (FRAME_MINIBUF_ONLY_P (f))
4253 error ("Cannot resize a minibuffer-only frame");
4255 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4256 height = r->total_lines + w->total_lines;
4257 if (window_resize_check (r, 0)
4258 && XINT (w->new_total) > 0
4259 && height == XINT (r->new_total) + XINT (w->new_total))
4261 block_input ();
4262 window_resize_apply (r, 0);
4264 w->total_lines = XFASTINT (w->new_total);
4265 w->top_line = r->top_line + r->total_lines;
4267 windows_or_buffers_changed++;
4268 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4269 adjust_glyphs (f);
4270 unblock_input ();
4272 run_window_configuration_change_hook (f);
4273 return Qt;
4275 else error ("Failed to resize minibuffer window");
4278 /* Mark window cursors off for all windows in the window tree rooted
4279 at W by setting their phys_cursor_on_p flag to zero. Called from
4280 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4281 the frame are cleared. */
4283 void
4284 mark_window_cursors_off (struct window *w)
4286 while (w)
4288 if (WINDOWP (w->contents))
4289 mark_window_cursors_off (XWINDOW (w->contents));
4290 else
4291 w->phys_cursor_on_p = 0;
4293 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4298 /* Return number of lines of text (not counting mode lines) in W. */
4301 window_internal_height (struct window *w)
4303 int ht = w->total_lines;
4305 if (!MINI_WINDOW_P (w))
4307 if (!NILP (w->parent)
4308 || WINDOWP (w->contents)
4309 || !NILP (w->next)
4310 || !NILP (w->prev)
4311 || WINDOW_WANTS_MODELINE_P (w))
4312 --ht;
4314 if (WINDOW_WANTS_HEADER_LINE_P (w))
4315 --ht;
4318 return ht;
4321 /************************************************************************
4322 Window Scrolling
4323 ***********************************************************************/
4325 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4326 N screen-fulls, which is defined as the height of the window minus
4327 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4328 instead. Negative values of N mean scroll down. NOERROR non-zero
4329 means don't signal an error if we try to move over BEGV or ZV,
4330 respectively. */
4332 static void
4333 window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
4335 immediate_quit = 1;
4336 n = clip_to_bounds (INT_MIN, n, INT_MAX);
4338 /* If we must, use the pixel-based version which is much slower than
4339 the line-based one but can handle varying line heights. */
4340 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4341 window_scroll_pixel_based (window, n, whole, noerror);
4342 else
4343 window_scroll_line_based (window, n, whole, noerror);
4345 immediate_quit = 0;
4349 /* Implementation of window_scroll that works based on pixel line
4350 heights. See the comment of window_scroll for parameter
4351 descriptions. */
4353 static void
4354 window_scroll_pixel_based (Lisp_Object window, int n, bool whole, int noerror)
4356 struct it it;
4357 struct window *w = XWINDOW (window);
4358 struct text_pos start;
4359 int this_scroll_margin;
4360 /* True if we fiddled the window vscroll field without really scrolling. */
4361 int vscrolled = 0;
4362 int x, y, rtop, rbot, rowh, vpos;
4363 void *itdata = NULL;
4364 int window_total_lines;
4365 int frame_line_height = default_line_pixel_height (w);
4367 SET_TEXT_POS_FROM_MARKER (start, w->start);
4368 /* Scrolling a minibuffer window via scroll bar when the echo area
4369 shows long text sometimes resets the minibuffer contents behind
4370 our backs. */
4371 if (CHARPOS (start) > ZV)
4372 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4374 /* If PT is not visible in WINDOW, move back one half of
4375 the screen. Allow PT to be partially visible, otherwise
4376 something like (scroll-down 1) with PT in the line before
4377 the partially visible one would recenter. */
4379 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4381 itdata = bidi_shelve_cache ();
4382 /* Move backward half the height of the window. Performance note:
4383 vmotion used here is about 10% faster, but would give wrong
4384 results for variable height lines. */
4385 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4386 it.current_y = it.last_visible_y;
4387 move_it_vertically_backward (&it, window_box_height (w) / 2);
4389 /* The function move_iterator_vertically may move over more than
4390 the specified y-distance. If it->w is small, e.g. a
4391 mini-buffer window, we may end up in front of the window's
4392 display area. This is the case when Start displaying at the
4393 start of the line containing PT in this case. */
4394 if (it.current_y <= 0)
4396 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4397 move_it_vertically_backward (&it, 0);
4398 it.current_y = 0;
4401 start = it.current.pos;
4402 bidi_unshelve_cache (itdata, 0);
4404 else if (auto_window_vscroll_p)
4406 if (rtop || rbot) /* partially visible */
4408 int px;
4409 int dy = frame_line_height;
4410 if (whole)
4411 dy = max ((window_box_height (w)
4412 - next_screen_context_lines * dy),
4413 dy);
4414 dy *= n;
4416 if (n < 0)
4418 /* Only vscroll backwards if already vscrolled forwards. */
4419 if (w->vscroll < 0 && rtop > 0)
4421 px = max (0, -w->vscroll - min (rtop, -dy));
4422 Fset_window_vscroll (window, make_number (px), Qt);
4423 return;
4426 if (n > 0)
4428 /* Do vscroll if already vscrolled or only display line. */
4429 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4431 px = max (0, -w->vscroll + min (rbot, dy));
4432 Fset_window_vscroll (window, make_number (px), Qt);
4433 return;
4436 /* Maybe modify window start instead of scrolling. */
4437 if (rbot > 0 || w->vscroll < 0)
4439 ptrdiff_t spos;
4441 Fset_window_vscroll (window, make_number (0), Qt);
4442 /* If there are other text lines above the current row,
4443 move window start to current row. Else to next row. */
4444 if (rbot > 0)
4445 spos = XINT (Fline_beginning_position (Qnil));
4446 else
4447 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4448 set_marker_restricted (w->start, make_number (spos),
4449 w->contents);
4450 w->start_at_line_beg = 1;
4451 w->update_mode_line = 1;
4452 /* Set force_start so that redisplay_window will run the
4453 window-scroll-functions. */
4454 w->force_start = 1;
4455 return;
4459 /* Cancel previous vscroll. */
4460 Fset_window_vscroll (window, make_number (0), Qt);
4463 itdata = bidi_shelve_cache ();
4464 /* If scroll_preserve_screen_position is non-nil, we try to set
4465 point in the same window line as it is now, so get that line. */
4466 if (!NILP (Vscroll_preserve_screen_position))
4468 /* We preserve the goal pixel coordinate across consecutive
4469 calls to scroll-up, scroll-down and other commands that
4470 have the `scroll-command' property. This avoids the
4471 possibility of point becoming "stuck" on a tall line when
4472 scrolling by one line. */
4473 if (window_scroll_pixel_based_preserve_y < 0
4474 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4475 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4477 start_display (&it, w, start);
4478 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4479 window_scroll_pixel_based_preserve_y = it.current_y;
4480 window_scroll_pixel_based_preserve_x = it.current_x;
4483 else
4484 window_scroll_pixel_based_preserve_y
4485 = window_scroll_pixel_based_preserve_x = -1;
4487 /* Move iterator it from start the specified distance forward or
4488 backward. The result is the new window start. */
4489 start_display (&it, w, start);
4490 if (whole)
4492 ptrdiff_t start_pos = IT_CHARPOS (it);
4493 int dy = frame_line_height;
4494 dy = max ((window_box_height (w)
4495 - next_screen_context_lines * dy),
4496 dy) * n;
4498 /* Note that move_it_vertically always moves the iterator to the
4499 start of a line. So, if the last line doesn't have a newline,
4500 we would end up at the start of the line ending at ZV. */
4501 if (dy <= 0)
4503 move_it_vertically_backward (&it, -dy);
4504 /* Ensure we actually do move, e.g. in case we are currently
4505 looking at an image that is taller that the window height. */
4506 while (start_pos == IT_CHARPOS (it)
4507 && start_pos > BEGV)
4508 move_it_by_lines (&it, -1);
4510 else if (dy > 0)
4512 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4513 MOVE_TO_POS | MOVE_TO_Y);
4514 /* Ensure we actually do move, e.g. in case we are currently
4515 looking at an image that is taller that the window height. */
4516 while (start_pos == IT_CHARPOS (it)
4517 && start_pos < ZV)
4518 move_it_by_lines (&it, 1);
4521 else
4522 move_it_by_lines (&it, n);
4524 /* We failed if we find ZV is already on the screen (scrolling up,
4525 means there's nothing past the end), or if we can't start any
4526 earlier (scrolling down, means there's nothing past the top). */
4527 if ((n > 0 && IT_CHARPOS (it) == ZV)
4528 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4530 if (IT_CHARPOS (it) == ZV)
4532 if (it.current_y < it.last_visible_y
4533 && (it.current_y + it.max_ascent + it.max_descent
4534 > it.last_visible_y))
4536 /* The last line was only partially visible, make it fully
4537 visible. */
4538 w->vscroll = (it.last_visible_y
4539 - it.current_y + it.max_ascent + it.max_descent);
4540 adjust_glyphs (it.f);
4542 else
4544 bidi_unshelve_cache (itdata, 0);
4545 if (noerror)
4546 return;
4547 else if (n < 0) /* could happen with empty buffers */
4548 xsignal0 (Qbeginning_of_buffer);
4549 else
4550 xsignal0 (Qend_of_buffer);
4553 else
4555 if (w->vscroll != 0)
4556 /* The first line was only partially visible, make it fully
4557 visible. */
4558 w->vscroll = 0;
4559 else
4561 bidi_unshelve_cache (itdata, 0);
4562 if (noerror)
4563 return;
4564 else
4565 xsignal0 (Qbeginning_of_buffer);
4569 /* If control gets here, then we vscrolled. */
4571 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
4573 /* Don't try to change the window start below. */
4574 vscrolled = 1;
4577 if (! vscrolled)
4579 ptrdiff_t pos = IT_CHARPOS (it);
4580 ptrdiff_t bytepos;
4582 /* If in the middle of a multi-glyph character move forward to
4583 the next character. */
4584 if (in_display_vector_p (&it))
4586 ++pos;
4587 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4590 /* Set the window start, and set up the window for redisplay. */
4591 set_marker_restricted_both (w->start, w->contents, IT_CHARPOS (it),
4592 IT_BYTEPOS (it));
4593 bytepos = marker_byte_position (w->start);
4594 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
4595 w->update_mode_line = 1;
4596 /* Set force_start so that redisplay_window will run the
4597 window-scroll-functions. */
4598 w->force_start = 1;
4601 /* The rest of this function uses current_y in a nonstandard way,
4602 not including the height of the header line if any. */
4603 it.current_y = it.vpos = 0;
4605 /* Move PT out of scroll margins.
4606 This code wants current_y to be zero at the window start position
4607 even if there is a header line. */
4608 window_total_lines
4609 = w->total_lines * WINDOW_FRAME_LINE_HEIGHT (w) / frame_line_height;
4610 this_scroll_margin = max (0, scroll_margin);
4611 this_scroll_margin
4612 = min (this_scroll_margin, window_total_lines / 4);
4613 this_scroll_margin *= frame_line_height;
4615 if (n > 0)
4617 /* We moved the window start towards ZV, so PT may be now
4618 in the scroll margin at the top. */
4619 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4620 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
4621 && (NILP (Vscroll_preserve_screen_position)
4622 || EQ (Vscroll_preserve_screen_position, Qt)))
4623 /* We found PT at a legitimate height. Leave it alone. */
4625 else if (window_scroll_pixel_based_preserve_y >= 0)
4627 /* If we have a header line, take account of it.
4628 This is necessary because we set it.current_y to 0, above. */
4629 move_it_to (&it, -1,
4630 window_scroll_pixel_based_preserve_x,
4631 window_scroll_pixel_based_preserve_y
4632 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
4633 -1, MOVE_TO_Y | MOVE_TO_X);
4634 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4636 else
4638 while (it.current_y < this_scroll_margin)
4640 int prev = it.current_y;
4641 move_it_by_lines (&it, 1);
4642 if (prev == it.current_y)
4643 break;
4645 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4648 else if (n < 0)
4650 ptrdiff_t charpos, bytepos;
4651 int partial_p;
4653 /* Save our position, for the
4654 window_scroll_pixel_based_preserve_y case. */
4655 charpos = IT_CHARPOS (it);
4656 bytepos = IT_BYTEPOS (it);
4658 /* We moved the window start towards BEGV, so PT may be now
4659 in the scroll margin at the bottom. */
4660 move_it_to (&it, PT, -1,
4661 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
4662 - this_scroll_margin - 1),
4664 MOVE_TO_POS | MOVE_TO_Y);
4666 /* Save our position, in case it's correct. */
4667 charpos = IT_CHARPOS (it);
4668 bytepos = IT_BYTEPOS (it);
4670 /* See if point is on a partially visible line at the end. */
4671 if (it.what == IT_EOB)
4672 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
4673 else
4675 move_it_by_lines (&it, 1);
4676 partial_p = it.current_y > it.last_visible_y;
4679 if (charpos == PT && !partial_p
4680 && (NILP (Vscroll_preserve_screen_position)
4681 || EQ (Vscroll_preserve_screen_position, Qt)))
4682 /* We found PT before we found the display margin, so PT is ok. */
4684 else if (window_scroll_pixel_based_preserve_y >= 0)
4686 SET_TEXT_POS_FROM_MARKER (start, w->start);
4687 start_display (&it, w, start);
4688 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
4689 here because we called start_display again and did not
4690 alter it.current_y this time. */
4691 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
4692 window_scroll_pixel_based_preserve_y, -1,
4693 MOVE_TO_Y | MOVE_TO_X);
4694 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4696 else
4698 if (partial_p)
4699 /* The last line was only partially visible, so back up two
4700 lines to make sure we're on a fully visible line. */
4702 move_it_by_lines (&it, -2);
4703 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4705 else
4706 /* No, the position we saved is OK, so use it. */
4707 SET_PT_BOTH (charpos, bytepos);
4710 bidi_unshelve_cache (itdata, 0);
4714 /* Implementation of window_scroll that works based on screen lines.
4715 See the comment of window_scroll for parameter descriptions. */
4717 static void
4718 window_scroll_line_based (Lisp_Object window, int n, bool whole, int noerror)
4720 register struct window *w = XWINDOW (window);
4721 /* Fvertical_motion enters redisplay, which can trigger
4722 fontification, which in turn can modify buffer text (e.g., if the
4723 fontification functions replace escape sequences with faces, as
4724 in `grep-mode-font-lock-keywords'). So we use a marker to record
4725 the old point position, to prevent crashes in SET_PT_BOTH. */
4726 Lisp_Object opoint_marker = Fpoint_marker ();
4727 register ptrdiff_t pos, pos_byte;
4728 register int ht = window_internal_height (w);
4729 register Lisp_Object tem;
4730 bool lose;
4731 Lisp_Object bolp;
4732 ptrdiff_t startpos = marker_position (w->start);
4733 ptrdiff_t startbyte = marker_byte_position (w->start);
4734 Lisp_Object original_pos = Qnil;
4736 /* If scrolling screen-fulls, compute the number of lines to
4737 scroll from the window's height. */
4738 if (whole)
4739 n *= max (1, ht - next_screen_context_lines);
4741 if (!NILP (Vscroll_preserve_screen_position))
4743 if (window_scroll_preserve_vpos <= 0
4744 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4745 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4747 struct position posit
4748 = *compute_motion (startpos, startbyte, 0, 0, 0,
4749 PT, ht, 0, -1, w->hscroll, 0, w);
4750 window_scroll_preserve_vpos = posit.vpos;
4751 window_scroll_preserve_hpos = posit.hpos + w->hscroll;
4754 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
4755 make_number (window_scroll_preserve_vpos));
4758 XSETFASTINT (tem, PT);
4759 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4761 if (NILP (tem))
4763 Fvertical_motion (make_number (- (ht / 2)), window);
4764 startpos = PT;
4765 startbyte = PT_BYTE;
4768 SET_PT_BOTH (startpos, startbyte);
4769 lose = n < 0 && PT == BEGV;
4770 Fvertical_motion (make_number (n), window);
4771 pos = PT;
4772 pos_byte = PT_BYTE;
4773 bolp = Fbolp ();
4774 SET_PT_BOTH (marker_position (opoint_marker),
4775 marker_byte_position (opoint_marker));
4777 if (lose)
4779 if (noerror)
4780 return;
4781 else
4782 xsignal0 (Qbeginning_of_buffer);
4785 if (pos < ZV)
4787 /* Don't use a scroll margin that is negative or too large. */
4788 int this_scroll_margin =
4789 max (0, min (scroll_margin, w->total_lines / 4));
4791 set_marker_restricted_both (w->start, w->contents, pos, pos_byte);
4792 w->start_at_line_beg = !NILP (bolp);
4793 w->update_mode_line = 1;
4794 /* Set force_start so that redisplay_window will run
4795 the window-scroll-functions. */
4796 w->force_start = 1;
4798 if (!NILP (Vscroll_preserve_screen_position)
4799 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
4801 SET_PT_BOTH (pos, pos_byte);
4802 Fvertical_motion (original_pos, window);
4804 /* If we scrolled forward, put point enough lines down
4805 that it is outside the scroll margin. */
4806 else if (n > 0)
4808 int top_margin;
4810 if (this_scroll_margin > 0)
4812 SET_PT_BOTH (pos, pos_byte);
4813 Fvertical_motion (make_number (this_scroll_margin), window);
4814 top_margin = PT;
4816 else
4817 top_margin = pos;
4819 if (top_margin <= marker_position (opoint_marker))
4820 SET_PT_BOTH (marker_position (opoint_marker),
4821 marker_byte_position (opoint_marker));
4822 else if (!NILP (Vscroll_preserve_screen_position))
4824 SET_PT_BOTH (pos, pos_byte);
4825 Fvertical_motion (original_pos, window);
4827 else
4828 SET_PT (top_margin);
4830 else if (n < 0)
4832 int bottom_margin;
4834 /* If we scrolled backward, put point near the end of the window
4835 but not within the scroll margin. */
4836 SET_PT_BOTH (pos, pos_byte);
4837 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4838 if (XFASTINT (tem) == ht - this_scroll_margin)
4839 bottom_margin = PT;
4840 else
4841 bottom_margin = PT + 1;
4843 if (bottom_margin > marker_position (opoint_marker))
4844 SET_PT_BOTH (marker_position (opoint_marker),
4845 marker_byte_position (opoint_marker));
4846 else
4848 if (!NILP (Vscroll_preserve_screen_position))
4850 SET_PT_BOTH (pos, pos_byte);
4851 Fvertical_motion (original_pos, window);
4853 else
4854 Fvertical_motion (make_number (-1), window);
4858 else
4860 if (noerror)
4861 return;
4862 else
4863 xsignal0 (Qend_of_buffer);
4868 /* Scroll selected_window up or down. If N is nil, scroll a
4869 screen-full which is defined as the height of the window minus
4870 next_screen_context_lines. If N is the symbol `-', scroll.
4871 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4872 up. This is the guts of Fscroll_up and Fscroll_down. */
4874 static void
4875 scroll_command (Lisp_Object n, int direction)
4877 ptrdiff_t count = SPECPDL_INDEX ();
4879 eassert (eabs (direction) == 1);
4881 /* If selected window's buffer isn't current, make it current for
4882 the moment. But don't screw up if window_scroll gets an error. */
4883 if (XBUFFER (XWINDOW (selected_window)->contents) != current_buffer)
4885 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4886 Fset_buffer (XWINDOW (selected_window)->contents);
4888 /* Make redisplay consider other windows than just selected_window. */
4889 ++windows_or_buffers_changed;
4892 if (NILP (n))
4893 window_scroll (selected_window, direction, 1, 0);
4894 else if (EQ (n, Qminus))
4895 window_scroll (selected_window, -direction, 1, 0);
4896 else
4898 n = Fprefix_numeric_value (n);
4899 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4902 unbind_to (count, Qnil);
4905 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
4906 doc: /* Scroll text of selected window upward ARG lines.
4907 If ARG is omitted or nil, scroll upward by a near full screen.
4908 A near full screen is `next-screen-context-lines' less than a full screen.
4909 Negative ARG means scroll downward.
4910 If ARG is the atom `-', scroll downward by nearly full screen.
4911 When calling from a program, supply as argument a number, nil, or `-'. */)
4912 (Lisp_Object arg)
4914 scroll_command (arg, 1);
4915 return Qnil;
4918 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
4919 doc: /* Scroll text of selected window down ARG lines.
4920 If ARG is omitted or nil, scroll down by a near full screen.
4921 A near full screen is `next-screen-context-lines' less than a full screen.
4922 Negative ARG means scroll upward.
4923 If ARG is the atom `-', scroll upward by nearly full screen.
4924 When calling from a program, supply as argument a number, nil, or `-'. */)
4925 (Lisp_Object arg)
4927 scroll_command (arg, -1);
4928 return Qnil;
4931 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4932 doc: /* Return the other window for \"other window scroll\" commands.
4933 If `other-window-scroll-buffer' is non-nil, a window
4934 showing that buffer is used.
4935 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4936 specifies the window. This takes precedence over
4937 `other-window-scroll-buffer'. */)
4938 (void)
4940 Lisp_Object window;
4942 if (MINI_WINDOW_P (XWINDOW (selected_window))
4943 && !NILP (Vminibuf_scroll_window))
4944 window = Vminibuf_scroll_window;
4945 /* If buffer is specified, scroll that buffer. */
4946 else if (!NILP (Vother_window_scroll_buffer))
4948 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4949 if (NILP (window))
4950 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4952 else
4954 /* Nothing specified; look for a neighboring window on the same
4955 frame. */
4956 window = Fnext_window (selected_window, Qnil, Qnil);
4958 if (EQ (window, selected_window))
4959 /* That didn't get us anywhere; look for a window on another
4960 visible frame. */
4962 window = Fnext_window (window, Qnil, Qt);
4963 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4964 && ! EQ (window, selected_window));
4967 CHECK_LIVE_WINDOW (window);
4969 if (EQ (window, selected_window))
4970 error ("There is no other window");
4972 return window;
4975 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4976 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4977 A near full screen is `next-screen-context-lines' less than a full screen.
4978 The next window is the one below the current one; or the one at the top
4979 if the current one is at the bottom. Negative ARG means scroll downward.
4980 If ARG is the atom `-', scroll downward by nearly full screen.
4981 When calling from a program, supply as argument a number, nil, or `-'.
4983 If `other-window-scroll-buffer' is non-nil, scroll the window
4984 showing that buffer, popping the buffer up if necessary.
4985 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4986 specifies the window to scroll. This takes precedence over
4987 `other-window-scroll-buffer'. */)
4988 (Lisp_Object arg)
4990 Lisp_Object window;
4991 struct window *w;
4992 ptrdiff_t count = SPECPDL_INDEX ();
4994 window = Fother_window_for_scrolling ();
4995 w = XWINDOW (window);
4997 /* Don't screw up if window_scroll gets an error. */
4998 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4999 ++windows_or_buffers_changed;
5001 Fset_buffer (w->contents);
5002 SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
5004 if (NILP (arg))
5005 window_scroll (window, 1, 1, 1);
5006 else if (EQ (arg, Qminus))
5007 window_scroll (window, -1, 1, 1);
5008 else
5010 if (CONSP (arg))
5011 arg = XCAR (arg);
5012 CHECK_NUMBER (arg);
5013 window_scroll (window, XINT (arg), 0, 1);
5016 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5017 unbind_to (count, Qnil);
5019 return Qnil;
5022 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5023 doc: /* Scroll selected window display ARG columns left.
5024 Default for ARG is window width minus 2.
5025 Value is the total amount of leftward horizontal scrolling in
5026 effect after the change.
5027 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5028 lower bound for automatic scrolling, i.e. automatic scrolling
5029 will not scroll a window to a column less than the value returned
5030 by this function. This happens in an interactive call. */)
5031 (register Lisp_Object arg, Lisp_Object set_minimum)
5033 struct window *w = XWINDOW (selected_window);
5034 EMACS_INT requested_arg = (NILP (arg)
5035 ? window_body_cols (w) - 2
5036 : XINT (Fprefix_numeric_value (arg)));
5037 Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
5039 if (!NILP (set_minimum))
5040 w->min_hscroll = w->hscroll;
5042 return result;
5045 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5046 doc: /* Scroll selected window display ARG columns right.
5047 Default for ARG is window width minus 2.
5048 Value is the total amount of leftward horizontal scrolling in
5049 effect after the change.
5050 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5051 lower bound for automatic scrolling, i.e. automatic scrolling
5052 will not scroll a window to a column less than the value returned
5053 by this function. This happens in an interactive call. */)
5054 (register Lisp_Object arg, Lisp_Object set_minimum)
5056 struct window *w = XWINDOW (selected_window);
5057 EMACS_INT requested_arg = (NILP (arg)
5058 ? window_body_cols (w) - 2
5059 : XINT (Fprefix_numeric_value (arg)));
5060 Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
5062 if (!NILP (set_minimum))
5063 w->min_hscroll = w->hscroll;
5065 return result;
5068 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5069 doc: /* Return the window which was selected when entering the minibuffer.
5070 Returns nil, if selected window is not a minibuffer window. */)
5071 (void)
5073 if (minibuf_level > 0
5074 && MINI_WINDOW_P (XWINDOW (selected_window))
5075 && WINDOW_LIVE_P (minibuf_selected_window))
5076 return minibuf_selected_window;
5078 return Qnil;
5081 /* Value is the number of lines actually displayed in window W,
5082 as opposed to its height. */
5084 static int
5085 displayed_window_lines (struct window *w)
5087 struct it it;
5088 struct text_pos start;
5089 ptrdiff_t charpos = marker_position (w->start);
5090 int height = window_box_height (w);
5091 struct buffer *old_buffer;
5092 int bottom_y;
5093 void *itdata = NULL;
5095 if (XBUFFER (w->contents) != current_buffer)
5097 old_buffer = current_buffer;
5098 set_buffer_internal (XBUFFER (w->contents));
5100 else
5101 old_buffer = NULL;
5103 /* In case W->start is out of the accessible range, do something
5104 reasonable. This happens in Info mode when Info-scroll-down
5105 calls (recenter -1) while W->start is 1. */
5106 if (charpos < BEGV)
5107 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5108 else if (charpos > ZV)
5109 SET_TEXT_POS (start, ZV, ZV_BYTE);
5110 else
5111 SET_TEXT_POS_FROM_MARKER (start, w->start);
5113 itdata = bidi_shelve_cache ();
5114 start_display (&it, w, start);
5115 move_it_vertically (&it, height);
5116 bottom_y = line_bottom_y (&it);
5117 bidi_unshelve_cache (itdata, 0);
5119 /* rms: On a non-window display,
5120 the value of it.vpos at the bottom of the screen
5121 seems to be 1 larger than window_box_height (w).
5122 This kludge fixes a bug whereby (move-to-window-line -1)
5123 when ZV is on the last screen line
5124 moves to the previous screen line instead of the last one. */
5125 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5126 height++;
5128 /* Add in empty lines at the bottom of the window. */
5129 if (bottom_y < height)
5131 int uy = FRAME_LINE_HEIGHT (it.f);
5132 it.vpos += (height - bottom_y + uy - 1) / uy;
5135 if (old_buffer)
5136 set_buffer_internal (old_buffer);
5138 return it.vpos;
5142 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5143 doc: /* Center point in selected window and maybe redisplay frame.
5144 With a numeric prefix argument ARG, recenter putting point on screen line ARG
5145 relative to the selected window. If ARG is negative, it counts up from the
5146 bottom of the window. (ARG should be less than the height of the window.)
5148 If ARG is omitted or nil, then recenter with point on the middle line of
5149 the selected window; if the variable `recenter-redisplay' is non-nil,
5150 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5151 is set to `grow-only', this resets the tool-bar's height to the minimum
5152 height needed); if `recenter-redisplay' has the special value `tty',
5153 then only tty frames are redrawn.
5155 Just C-u as prefix means put point in the center of the window
5156 and redisplay normally--don't erase and redraw the frame. */)
5157 (register Lisp_Object arg)
5159 struct window *w = XWINDOW (selected_window);
5160 struct buffer *buf = XBUFFER (w->contents);
5161 struct buffer *obuf = current_buffer;
5162 bool center_p = 0;
5163 ptrdiff_t charpos, bytepos;
5164 EMACS_INT iarg IF_LINT (= 0);
5165 int this_scroll_margin;
5167 /* If redisplay is suppressed due to an error, try again. */
5168 obuf->display_error_modiff = 0;
5170 if (NILP (arg))
5172 if (!NILP (Vrecenter_redisplay)
5173 && (!EQ (Vrecenter_redisplay, Qtty)
5174 || !NILP (Ftty_type (selected_frame))))
5176 ptrdiff_t i;
5178 /* Invalidate pixel data calculated for all compositions. */
5179 for (i = 0; i < n_compositions; i++)
5180 composition_table[i]->font = NULL;
5182 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5184 Fredraw_frame (WINDOW_FRAME (w));
5185 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5188 center_p = 1;
5190 else if (CONSP (arg)) /* Just C-u. */
5191 center_p = 1;
5192 else
5194 arg = Fprefix_numeric_value (arg);
5195 CHECK_NUMBER (arg);
5196 iarg = XINT (arg);
5199 set_buffer_internal (buf);
5201 /* Do this after making BUF current
5202 in case scroll_margin is buffer-local. */
5203 this_scroll_margin =
5204 max (0, min (scroll_margin, w->total_lines / 4));
5206 /* Handle centering on a graphical frame specially. Such frames can
5207 have variable-height lines and centering point on the basis of
5208 line counts would lead to strange effects. */
5209 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5211 if (center_p)
5213 struct it it;
5214 struct text_pos pt;
5215 void *itdata = bidi_shelve_cache ();
5217 SET_TEXT_POS (pt, PT, PT_BYTE);
5218 start_display (&it, w, pt);
5219 move_it_vertically_backward (&it, window_box_height (w) / 2);
5220 charpos = IT_CHARPOS (it);
5221 bytepos = IT_BYTEPOS (it);
5222 bidi_unshelve_cache (itdata, 0);
5224 else if (iarg < 0)
5226 struct it it;
5227 struct text_pos pt;
5228 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
5229 int extra_line_spacing;
5230 int h = window_box_height (w);
5231 void *itdata = bidi_shelve_cache ();
5233 iarg = - max (-iarg, this_scroll_margin);
5235 SET_TEXT_POS (pt, PT, PT_BYTE);
5236 start_display (&it, w, pt);
5238 /* Be sure we have the exact height of the full line containing PT. */
5239 move_it_by_lines (&it, 0);
5241 /* The amount of pixels we have to move back is the window
5242 height minus what's displayed in the line containing PT,
5243 and the lines below. */
5244 it.current_y = 0;
5245 it.vpos = 0;
5246 move_it_by_lines (&it, nlines);
5248 if (it.vpos == nlines)
5249 h -= it.current_y;
5250 else
5252 /* Last line has no newline */
5253 h -= line_bottom_y (&it);
5254 it.vpos++;
5257 /* Don't reserve space for extra line spacing of last line. */
5258 extra_line_spacing = it.max_extra_line_spacing;
5260 /* If we can't move down NLINES lines because we hit
5261 the end of the buffer, count in some empty lines. */
5262 if (it.vpos < nlines)
5264 nlines -= it.vpos;
5265 extra_line_spacing = it.extra_line_spacing;
5266 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5268 if (h <= 0)
5270 bidi_unshelve_cache (itdata, 0);
5271 return Qnil;
5274 /* Now find the new top line (starting position) of the window. */
5275 start_display (&it, w, pt);
5276 it.current_y = 0;
5277 move_it_vertically_backward (&it, h);
5279 /* If extra line spacing is present, we may move too far
5280 back. This causes the last line to be only partially
5281 visible (which triggers redisplay to recenter that line
5282 in the middle), so move forward.
5283 But ignore extra line spacing on last line, as it is not
5284 considered to be part of the visible height of the line.
5286 h += extra_line_spacing;
5287 while (-it.current_y > h)
5288 move_it_by_lines (&it, 1);
5290 charpos = IT_CHARPOS (it);
5291 bytepos = IT_BYTEPOS (it);
5293 bidi_unshelve_cache (itdata, 0);
5295 else
5297 struct position pos;
5299 iarg = max (iarg, this_scroll_margin);
5301 pos = *vmotion (PT, PT_BYTE, -iarg, w);
5302 charpos = pos.bufpos;
5303 bytepos = pos.bytepos;
5306 else
5308 struct position pos;
5309 int ht = window_internal_height (w);
5311 if (center_p)
5312 iarg = ht / 2;
5313 else if (iarg < 0)
5314 iarg += ht;
5316 /* Don't let it get into the margin at either top or bottom. */
5317 iarg = clip_to_bounds (this_scroll_margin, iarg,
5318 ht - this_scroll_margin - 1);
5320 pos = *vmotion (PT, PT_BYTE, - iarg, w);
5321 charpos = pos.bufpos;
5322 bytepos = pos.bytepos;
5325 /* Set the new window start. */
5326 set_marker_both (w->start, w->contents, charpos, bytepos);
5327 w->window_end_valid = 0;
5329 w->optional_new_start = 1;
5331 w->start_at_line_beg = (bytepos == BEGV_BYTE ||
5332 FETCH_BYTE (bytepos - 1) == '\n');
5334 set_buffer_internal (obuf);
5335 return Qnil;
5338 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5339 0, 1, 0,
5340 doc: /* Return the height in lines of the text display area of WINDOW.
5341 WINDOW must be a live window and defaults to the selected one.
5343 The returned height does not include the mode line, any header line,
5344 nor any partial-height lines at the bottom of the text area. */)
5345 (Lisp_Object window)
5347 struct window *w = decode_live_window (window);
5348 int pixel_height = window_box_height (w);
5349 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5350 return make_number (line_height);
5355 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5356 1, 1, "P",
5357 doc: /* Position point relative to window.
5358 ARG nil means position point at center of window.
5359 Else, ARG specifies vertical position within the window;
5360 zero means top of window, negative means relative to bottom of window. */)
5361 (Lisp_Object arg)
5363 struct window *w = XWINDOW (selected_window);
5364 int lines, start;
5365 Lisp_Object window;
5366 #if 0
5367 int this_scroll_margin;
5368 #endif
5370 if (!(BUFFERP (w->contents) && XBUFFER (w->contents) == current_buffer))
5371 /* This test is needed to make sure PT/PT_BYTE make sense in w->contents
5372 when passed below to set_marker_both. */
5373 error ("move-to-window-line called from unrelated buffer");
5375 window = selected_window;
5376 start = marker_position (w->start);
5377 if (start < BEGV || start > ZV)
5379 int height = window_internal_height (w);
5380 Fvertical_motion (make_number (- (height / 2)), window);
5381 set_marker_both (w->start, w->contents, PT, PT_BYTE);
5382 w->start_at_line_beg = !NILP (Fbolp ());
5383 w->force_start = 1;
5385 else
5386 Fgoto_char (w->start);
5388 lines = displayed_window_lines (w);
5390 #if 0
5391 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
5392 #endif
5394 if (NILP (arg))
5395 XSETFASTINT (arg, lines / 2);
5396 else
5398 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
5400 if (iarg < 0)
5401 iarg = iarg + lines;
5403 #if 0 /* This code would prevent move-to-window-line from moving point
5404 to a place inside the scroll margins (which would cause the
5405 next redisplay to scroll). I wrote this code, but then concluded
5406 it is probably better not to install it. However, it is here
5407 inside #if 0 so as not to lose it. -- rms. */
5409 /* Don't let it get into the margin at either top or bottom. */
5410 iarg = max (iarg, this_scroll_margin);
5411 iarg = min (iarg, lines - this_scroll_margin - 1);
5412 #endif
5414 arg = make_number (iarg);
5417 /* Skip past a partially visible first line. */
5418 if (w->vscroll)
5419 XSETINT (arg, XINT (arg) + 1);
5421 return Fvertical_motion (arg, window);
5426 /***********************************************************************
5427 Window Configuration
5428 ***********************************************************************/
5430 struct save_window_data
5432 struct vectorlike_header header;
5433 Lisp_Object selected_frame;
5434 Lisp_Object current_window;
5435 Lisp_Object current_buffer;
5436 Lisp_Object minibuf_scroll_window;
5437 Lisp_Object minibuf_selected_window;
5438 Lisp_Object root_window;
5439 Lisp_Object focus_frame;
5440 /* A vector, each of whose elements is a struct saved_window
5441 for one window. */
5442 Lisp_Object saved_windows;
5444 /* All fields above are traced by the GC.
5445 From `fame-cols' down, the fields are ignored by the GC. */
5447 int frame_cols, frame_lines, frame_menu_bar_lines;
5448 int frame_tool_bar_lines;
5451 /* This is saved as a Lisp_Vector */
5452 struct saved_window
5454 struct vectorlike_header header;
5456 Lisp_Object window, buffer, start, pointm, mark;
5457 Lisp_Object left_col, top_line, total_cols, total_lines;
5458 Lisp_Object normal_cols, normal_lines;
5459 Lisp_Object hscroll, min_hscroll;
5460 Lisp_Object parent, prev;
5461 Lisp_Object start_at_line_beg;
5462 Lisp_Object display_table;
5463 Lisp_Object left_margin_cols, right_margin_cols;
5464 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5465 Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
5466 Lisp_Object combination_limit, window_parameters;
5469 #define SAVED_WINDOW_N(swv,n) \
5470 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5472 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5473 doc: /* Return t if OBJECT is a window-configuration object. */)
5474 (Lisp_Object object)
5476 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5479 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5480 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5481 (Lisp_Object config)
5483 register struct save_window_data *data;
5484 struct Lisp_Vector *saved_windows;
5486 CHECK_WINDOW_CONFIGURATION (config);
5488 data = (struct save_window_data *) XVECTOR (config);
5489 saved_windows = XVECTOR (data->saved_windows);
5490 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5493 DEFUN ("set-window-configuration", Fset_window_configuration,
5494 Sset_window_configuration, 1, 1, 0,
5495 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5496 CONFIGURATION must be a value previously returned
5497 by `current-window-configuration' (which see).
5498 If CONFIGURATION was made from a frame that is now deleted,
5499 only frame-independent values can be restored. In this case,
5500 the return value is nil. Otherwise the value is t. */)
5501 (Lisp_Object configuration)
5503 register struct save_window_data *data;
5504 struct Lisp_Vector *saved_windows;
5505 Lisp_Object new_current_buffer;
5506 Lisp_Object frame;
5507 struct frame *f;
5508 ptrdiff_t old_point = -1;
5510 CHECK_WINDOW_CONFIGURATION (configuration);
5512 data = (struct save_window_data *) XVECTOR (configuration);
5513 saved_windows = XVECTOR (data->saved_windows);
5515 new_current_buffer = data->current_buffer;
5516 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5517 new_current_buffer = Qnil;
5518 else
5520 if (XBUFFER (new_current_buffer) == current_buffer)
5521 /* The code further down "preserves point" by saving here PT in
5522 old_point and then setting it later back into PT. When the
5523 current-selected-window and the final-selected-window both show
5524 the current buffer, this suffers from the problem that the
5525 current PT is the window-point of the current-selected-window,
5526 while the final PT is the point of the final-selected-window, so
5527 this copy from one PT to the other would end up moving the
5528 window-point of the final-selected-window to the window-point of
5529 the current-selected-window. So we have to be careful which
5530 point of the current-buffer we copy into old_point. */
5531 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
5532 && WINDOWP (selected_window)
5533 && EQ (XWINDOW (selected_window)->contents, new_current_buffer)
5534 && !EQ (selected_window, data->current_window))
5535 old_point = marker_position (XWINDOW (data->current_window)->pointm);
5536 else
5537 old_point = PT;
5538 else
5539 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5540 point in new_current_buffer as of the last time this buffer was
5541 used. This can be non-deterministic since it can be changed by
5542 things like jit-lock by mere temporary selection of some random
5543 window that happens to show this buffer.
5544 So if possible we want this arbitrary choice of "which point" to
5545 be the one from the to-be-selected-window so as to prevent this
5546 window's cursor from being copied from another window. */
5547 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer)
5548 /* If current_window = selected_window, its point is in BUF_PT. */
5549 && !EQ (selected_window, data->current_window))
5550 old_point = marker_position (XWINDOW (data->current_window)->pointm);
5551 else
5552 old_point = BUF_PT (XBUFFER (new_current_buffer));
5555 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5556 f = XFRAME (frame);
5558 /* If f is a dead frame, don't bother rebuilding its window tree.
5559 However, there is other stuff we should still try to do below. */
5560 if (FRAME_LIVE_P (f))
5562 Lisp_Object window;
5563 Lisp_Object dead_windows = Qnil;
5564 register Lisp_Object tem, par, pers;
5565 register struct window *w;
5566 register struct saved_window *p;
5567 struct window *root_window;
5568 struct window **leaf_windows;
5569 int n_leaf_windows;
5570 ptrdiff_t k;
5571 int i, n;
5573 /* If the frame has been resized since this window configuration was
5574 made, we change the frame to the size specified in the
5575 configuration, restore the configuration, and then resize it
5576 back. We keep track of the prevailing height in these variables. */
5577 int previous_frame_lines = FRAME_LINES (f);
5578 int previous_frame_cols = FRAME_COLS (f);
5579 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5580 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5582 /* Don't do this within the main loop below: This may call Lisp
5583 code and is thus potentially unsafe while input is blocked. */
5584 for (k = 0; k < saved_windows->header.size; k++)
5586 p = SAVED_WINDOW_N (saved_windows, k);
5587 window = p->window;
5588 w = XWINDOW (window);
5589 if (BUFFERP (w->contents)
5590 && !EQ (w->contents, p->buffer)
5591 && BUFFER_LIVE_P (XBUFFER (p->buffer)))
5592 /* If a window we restore gets another buffer, record the
5593 window's old buffer. */
5594 call1 (Qrecord_window_buffer, window);
5597 /* The mouse highlighting code could get screwed up
5598 if it runs during this. */
5599 block_input ();
5601 if (data->frame_lines != previous_frame_lines
5602 || data->frame_cols != previous_frame_cols)
5603 change_frame_size (f, data->frame_lines,
5604 data->frame_cols, 0, 0, 0);
5605 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5606 if (data->frame_menu_bar_lines
5607 != previous_frame_menu_bar_lines)
5608 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
5609 make_number (0));
5610 #ifdef HAVE_WINDOW_SYSTEM
5611 if (data->frame_tool_bar_lines
5612 != previous_frame_tool_bar_lines)
5613 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
5614 make_number (0));
5615 #endif
5616 #endif
5618 /* "Swap out" point from the selected window's buffer
5619 into the window itself. (Normally the pointm of the selected
5620 window holds garbage.) We do this now, before
5621 restoring the window contents, and prevent it from
5622 being done later on when we select a new window. */
5623 if (! NILP (XWINDOW (selected_window)->contents))
5625 w = XWINDOW (selected_window);
5626 set_marker_both (w->pointm,
5627 w->contents,
5628 BUF_PT (XBUFFER (w->contents)),
5629 BUF_PT_BYTE (XBUFFER (w->contents)));
5632 windows_or_buffers_changed++;
5633 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5635 /* Problem: Freeing all matrices and later allocating them again
5636 is a serious redisplay flickering problem. What we would
5637 really like to do is to free only those matrices not reused
5638 below. */
5639 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5640 leaf_windows = alloca (count_windows (root_window)
5641 * sizeof *leaf_windows);
5642 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5644 /* Kludge Alert!
5645 Mark all windows now on frame as "deleted".
5646 Restoring the new configuration "undeletes" any that are in it.
5648 Save their current buffers in their height fields, since we may
5649 need it later, if a buffer saved in the configuration is now
5650 dead. */
5651 delete_all_child_windows (FRAME_ROOT_WINDOW (f));
5653 for (k = 0; k < saved_windows->header.size; k++)
5655 p = SAVED_WINDOW_N (saved_windows, k);
5656 window = p->window;
5657 w = XWINDOW (window);
5658 wset_next (w, Qnil);
5660 if (!NILP (p->parent))
5661 wset_parent
5662 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window);
5663 else
5664 wset_parent (w, Qnil);
5666 if (!NILP (p->prev))
5668 wset_prev
5669 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window);
5670 wset_next (XWINDOW (w->prev), p->window);
5672 else
5674 wset_prev (w, Qnil);
5675 if (!NILP (w->parent))
5676 wset_combination (XWINDOW (w->parent),
5677 (XINT (p->total_cols)
5678 != XWINDOW (w->parent)->total_cols),
5679 p->window);
5682 /* If we squirreled away the buffer, restore it now. */
5683 if (BUFFERP (w->combination_limit))
5684 wset_buffer (w, w->combination_limit);
5685 w->left_col = XFASTINT (p->left_col);
5686 w->top_line = XFASTINT (p->top_line);
5687 w->total_cols = XFASTINT (p->total_cols);
5688 w->total_lines = XFASTINT (p->total_lines);
5689 wset_normal_cols (w, p->normal_cols);
5690 wset_normal_lines (w, p->normal_lines);
5691 w->hscroll = XFASTINT (p->hscroll);
5692 w->min_hscroll = XFASTINT (p->min_hscroll);
5693 wset_display_table (w, p->display_table);
5694 wset_left_margin_cols (w, p->left_margin_cols);
5695 wset_right_margin_cols (w, p->right_margin_cols);
5696 wset_left_fringe_width (w, p->left_fringe_width);
5697 wset_right_fringe_width (w, p->right_fringe_width);
5698 w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
5699 wset_scroll_bar_width (w, p->scroll_bar_width);
5700 wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
5701 wset_dedicated (w, p->dedicated);
5702 wset_combination_limit (w, p->combination_limit);
5703 /* Restore any window parameters that have been saved.
5704 Parameters that have not been saved are left alone. */
5705 for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
5707 pers = XCAR (tem);
5708 if (CONSP (pers))
5710 if (NILP (XCDR (pers)))
5712 par = Fassq (XCAR (pers), w->window_parameters);
5713 if (CONSP (par) && !NILP (XCDR (par)))
5714 /* Reset a parameter to nil if and only if it
5715 has a non-nil association. Don't make new
5716 associations. */
5717 Fsetcdr (par, Qnil);
5719 else
5720 /* Always restore a non-nil value. */
5721 Fset_window_parameter (window, XCAR (pers), XCDR (pers));
5725 if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
5726 /* If saved buffer is alive, install it. */
5728 wset_buffer (w, p->buffer);
5729 w->start_at_line_beg = !NILP (p->start_at_line_beg);
5730 set_marker_restricted (w->start, p->start, w->contents);
5731 set_marker_restricted (w->pointm, p->pointm,
5732 w->contents);
5733 Fset_marker (BVAR (XBUFFER (w->contents), mark),
5734 p->mark, w->contents);
5736 /* As documented in Fcurrent_window_configuration, don't
5737 restore the location of point in the buffer which was
5738 current when the window configuration was recorded. */
5739 if (!EQ (p->buffer, new_current_buffer)
5740 && XBUFFER (p->buffer) == current_buffer)
5741 Fgoto_char (w->pointm);
5743 else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
5744 /* Keep window's old buffer; make sure the markers are real. */
5746 /* Set window markers at start of visible range. */
5747 if (XMARKER (w->start)->buffer == 0)
5748 set_marker_restricted_both (w->start, w->contents, 0, 0);
5749 if (XMARKER (w->pointm)->buffer == 0)
5750 set_marker_restricted_both
5751 (w->pointm, w->contents,
5752 BUF_PT (XBUFFER (w->contents)),
5753 BUF_PT_BYTE (XBUFFER (w->contents)));
5754 w->start_at_line_beg = 1;
5756 else if (!NILP (w->start))
5757 /* Leaf window has no live buffer, get one. */
5759 /* Get the buffer via other_buffer_safely in order to
5760 avoid showing an unimportant buffer and, if necessary, to
5761 recreate *scratch* in the course (part of Juanma's bs-show
5762 scenario from March 2011). */
5763 wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
5764 /* This will set the markers to beginning of visible
5765 range. */
5766 set_marker_restricted_both (w->start, w->contents, 0, 0);
5767 set_marker_restricted_both (w->pointm, w->contents, 0, 0);
5768 w->start_at_line_beg = 1;
5769 if (!NILP (w->dedicated))
5770 /* Record this window as dead. */
5771 dead_windows = Fcons (window, dead_windows);
5772 /* Make sure window is no more dedicated. */
5773 wset_dedicated (w, Qnil);
5777 fset_root_window (f, data->root_window);
5778 /* Arrange *not* to restore point in the buffer that was
5779 current when the window configuration was saved. */
5780 if (EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
5781 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5782 make_number (old_point),
5783 XWINDOW (data->current_window)->contents);
5785 /* In the following call to `select-window', prevent "swapping out
5786 point" in the old selected window using the buffer that has
5787 been restored into it. We already swapped out that point from
5788 that window's old buffer. */
5789 select_window (data->current_window, Qnil, 1);
5790 BVAR (XBUFFER (XWINDOW (selected_window)->contents), last_selected_window)
5791 = selected_window;
5793 if (NILP (data->focus_frame)
5794 || (FRAMEP (data->focus_frame)
5795 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5796 Fredirect_frame_focus (frame, data->focus_frame);
5798 /* Set the screen height to the value it had before this function. */
5799 if (previous_frame_lines != FRAME_LINES (f)
5800 || previous_frame_cols != FRAME_COLS (f))
5801 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5802 0, 0, 0);
5803 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5804 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5805 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5806 make_number (0));
5807 #ifdef HAVE_WINDOW_SYSTEM
5808 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5809 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5810 make_number (0));
5811 #endif
5812 #endif
5814 /* Now, free glyph matrices in windows that were not reused. */
5815 for (i = n = 0; i < n_leaf_windows; ++i)
5817 if (NILP (leaf_windows[i]->contents))
5818 free_window_matrices (leaf_windows[i]);
5819 else if (EQ (leaf_windows[i]->contents, new_current_buffer))
5820 ++n;
5823 adjust_glyphs (f);
5824 unblock_input ();
5826 /* Scan dead buffer windows. */
5827 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
5829 window = XCAR (dead_windows);
5830 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
5831 delete_deletable_window (window);
5834 /* Fselect_window will have made f the selected frame, so we
5835 reselect the proper frame here. Fhandle_switch_frame will change the
5836 selected window too, but that doesn't make the call to
5837 Fselect_window above totally superfluous; it still sets f's
5838 selected window. */
5839 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5840 do_switch_frame (data->selected_frame, 0, 0, Qnil);
5842 run_window_configuration_change_hook (f);
5845 if (!NILP (new_current_buffer))
5847 Fset_buffer (new_current_buffer);
5848 /* If the new current buffer doesn't appear in the selected
5849 window, go to its old point (see bug#12208). */
5850 if (!EQ (XWINDOW (data->current_window)->contents, new_current_buffer))
5851 Fgoto_char (make_number (old_point));
5854 Vminibuf_scroll_window = data->minibuf_scroll_window;
5855 minibuf_selected_window = data->minibuf_selected_window;
5857 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5860 void
5861 restore_window_configuration (Lisp_Object configuration)
5863 Fset_window_configuration (configuration);
5867 /* If WINDOW is an internal window, recursively delete all child windows
5868 reachable via the next and contents slots of WINDOW. Otherwise setup
5869 WINDOW to not show any buffer. */
5871 void
5872 delete_all_child_windows (Lisp_Object window)
5874 register struct window *w;
5876 w = XWINDOW (window);
5878 if (!NILP (w->next))
5879 /* Delete WINDOW's siblings (we traverse postorderly). */
5880 delete_all_child_windows (w->next);
5882 if (WINDOWP (w->contents))
5884 delete_all_child_windows (w->contents);
5885 wset_combination (w, 0, Qnil);
5887 else if (BUFFERP (w->contents))
5889 unshow_buffer (w);
5890 unchain_marker (XMARKER (w->pointm));
5891 unchain_marker (XMARKER (w->start));
5892 /* Since combination limit makes sense for an internal windows
5893 only, we use this slot to save the buffer for the sake of
5894 possible resurrection in Fset_window_configuration. */
5895 wset_combination_limit (w, w->contents);
5896 wset_buffer (w, Qnil);
5899 Vwindow_list = Qnil;
5902 static int
5903 count_windows (register struct window *window)
5905 register int count = 1;
5906 if (!NILP (window->next))
5907 count += count_windows (XWINDOW (window->next));
5908 if (WINDOWP (window->contents))
5909 count += count_windows (XWINDOW (window->contents));
5910 return count;
5914 /* Fill vector FLAT with leaf windows under W, starting at index I.
5915 Value is last index + 1. */
5916 static int
5917 get_leaf_windows (struct window *w, struct window **flat, int i)
5919 while (w)
5921 if (WINDOWP (w->contents))
5922 i = get_leaf_windows (XWINDOW (w->contents), flat, i);
5923 else
5924 flat[i++] = w;
5926 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5929 return i;
5933 /* Return a pointer to the glyph W's physical cursor is on. Value is
5934 null if W's current matrix is invalid, so that no meaningful glyph
5935 can be returned. */
5936 struct glyph *
5937 get_phys_cursor_glyph (struct window *w)
5939 struct glyph_row *row;
5940 struct glyph *glyph;
5941 int hpos = w->phys_cursor.hpos;
5943 if (!(w->phys_cursor.vpos >= 0
5944 && w->phys_cursor.vpos < w->current_matrix->nrows))
5945 return NULL;
5947 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5948 if (!row->enabled_p)
5949 return NULL;
5951 if (w->hscroll)
5953 /* When the window is hscrolled, cursor hpos can legitimately be
5954 out of bounds, but we draw the cursor at the corresponding
5955 window margin in that case. */
5956 if (!row->reversed_p && hpos < 0)
5957 hpos = 0;
5958 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
5959 hpos = row->used[TEXT_AREA] - 1;
5962 if (0 <= hpos && hpos < row->used[TEXT_AREA])
5963 glyph = row->glyphs[TEXT_AREA] + hpos;
5964 else
5965 glyph = NULL;
5967 return glyph;
5971 static int
5972 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
5974 register struct saved_window *p;
5975 register struct window *w;
5976 register Lisp_Object tem, pers, par;
5978 for (; !NILP (window); window = w->next)
5980 p = SAVED_WINDOW_N (vector, i);
5981 w = XWINDOW (window);
5983 wset_temslot (w, make_number (i)); i++;
5984 p->window = window;
5985 p->buffer = (WINDOW_LEAF_P (w) ? w->contents : Qnil);
5986 p->left_col = make_number (w->left_col);
5987 p->top_line = make_number (w->top_line);
5988 p->total_cols = make_number (w->total_cols);
5989 p->total_lines = make_number (w->total_lines);
5990 p->normal_cols = w->normal_cols;
5991 p->normal_lines = w->normal_lines;
5992 XSETFASTINT (p->hscroll, w->hscroll);
5993 XSETFASTINT (p->min_hscroll, w->min_hscroll);
5994 p->display_table = w->display_table;
5995 p->left_margin_cols = w->left_margin_cols;
5996 p->right_margin_cols = w->right_margin_cols;
5997 p->left_fringe_width = w->left_fringe_width;
5998 p->right_fringe_width = w->right_fringe_width;
5999 p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
6000 p->scroll_bar_width = w->scroll_bar_width;
6001 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6002 p->dedicated = w->dedicated;
6003 p->combination_limit = w->combination_limit;
6004 p->window_parameters = Qnil;
6006 if (!NILP (Vwindow_persistent_parameters))
6008 /* Run cycle detection on Vwindow_persistent_parameters. */
6009 Lisp_Object tortoise, hare;
6011 hare = tortoise = Vwindow_persistent_parameters;
6012 while (CONSP (hare))
6014 hare = XCDR (hare);
6015 if (!CONSP (hare))
6016 break;
6018 hare = XCDR (hare);
6019 tortoise = XCDR (tortoise);
6021 if (EQ (hare, tortoise))
6022 /* Reset Vwindow_persistent_parameters to Qnil. */
6024 Vwindow_persistent_parameters = Qnil;
6025 break;
6029 for (tem = Vwindow_persistent_parameters; CONSP (tem);
6030 tem = XCDR (tem))
6032 pers = XCAR (tem);
6033 /* Save values for persistent window parameters. */
6034 if (CONSP (pers) && !NILP (XCDR (pers)))
6036 par = Fassq (XCAR (pers), w->window_parameters);
6037 if (NILP (par))
6038 /* If the window has no value for the parameter,
6039 make one. */
6040 p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
6041 p->window_parameters);
6042 else
6043 /* If the window has a value for the parameter,
6044 save it. */
6045 p->window_parameters = Fcons (Fcons (XCAR (par),
6046 XCDR (par)),
6047 p->window_parameters);
6052 if (BUFFERP (w->contents))
6054 /* Save w's value of point in the window configuration. If w
6055 is the selected window, then get the value of point from
6056 the buffer; pointm is garbage in the selected window. */
6057 if (EQ (window, selected_window))
6058 p->pointm = build_marker (XBUFFER (w->contents),
6059 BUF_PT (XBUFFER (w->contents)),
6060 BUF_PT_BYTE (XBUFFER (w->contents)));
6061 else
6062 p->pointm = Fcopy_marker (w->pointm, Qnil);
6063 XMARKER (p->pointm)->insertion_type
6064 = !NILP (Vwindow_point_insertion_type);
6066 p->start = Fcopy_marker (w->start, Qnil);
6067 p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
6069 tem = BVAR (XBUFFER (w->contents), mark);
6070 p->mark = Fcopy_marker (tem, Qnil);
6072 else
6074 p->pointm = Qnil;
6075 p->start = Qnil;
6076 p->mark = Qnil;
6077 p->start_at_line_beg = Qnil;
6080 if (NILP (w->parent))
6081 p->parent = Qnil;
6082 else
6083 p->parent = XWINDOW (w->parent)->temslot;
6085 if (NILP (w->prev))
6086 p->prev = Qnil;
6087 else
6088 p->prev = XWINDOW (w->prev)->temslot;
6090 if (WINDOWP (w->contents))
6091 i = save_window_save (w->contents, vector, i);
6094 return i;
6097 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6098 Scurrent_window_configuration, 0, 1, 0,
6099 doc: /* Return an object representing the current window configuration of FRAME.
6100 If FRAME is nil or omitted, use the selected frame.
6101 This describes the number of windows, their sizes and current buffers,
6102 and for each displayed buffer, where display starts, and the positions of
6103 point and mark. An exception is made for point in the current buffer:
6104 its value is -not- saved.
6105 This also records the currently selected frame, and FRAME's focus
6106 redirection (see `redirect-frame-focus'). The variable
6107 `window-persistent-parameters' specifies which window parameters are
6108 saved by this function. */)
6109 (Lisp_Object frame)
6111 register Lisp_Object tem;
6112 register int n_windows;
6113 register struct save_window_data *data;
6114 register int i;
6115 struct frame *f = decode_live_frame (frame);
6117 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6118 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6119 PVEC_WINDOW_CONFIGURATION);
6121 data->frame_cols = FRAME_COLS (f);
6122 data->frame_lines = FRAME_LINES (f);
6123 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6124 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6125 data->selected_frame = selected_frame;
6126 data->current_window = FRAME_SELECTED_WINDOW (f);
6127 XSETBUFFER (data->current_buffer, current_buffer);
6128 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6129 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6130 data->root_window = FRAME_ROOT_WINDOW (f);
6131 data->focus_frame = FRAME_FOCUS_FRAME (f);
6132 tem = make_uninit_vector (n_windows);
6133 data->saved_windows = tem;
6134 for (i = 0; i < n_windows; i++)
6135 ASET (tem, i,
6136 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil));
6137 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6138 XSETWINDOW_CONFIGURATION (tem, data);
6139 return (tem);
6142 /***********************************************************************
6143 Marginal Areas
6144 ***********************************************************************/
6146 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6147 2, 3, 0,
6148 doc: /* Set width of marginal areas of window WINDOW.
6149 WINDOW must be a live window and defaults to the selected one.
6151 Second arg LEFT-WIDTH specifies the number of character cells to
6152 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6153 does the same for the right marginal area. A nil width parameter
6154 means no margin. */)
6155 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6157 struct window *w = decode_live_window (window);
6159 /* Translate negative or zero widths to nil.
6160 Margins that are too wide have to be checked elsewhere. */
6162 if (!NILP (left_width))
6164 CHECK_NUMBER (left_width);
6165 if (XINT (left_width) <= 0)
6166 left_width = Qnil;
6169 if (!NILP (right_width))
6171 CHECK_NUMBER (right_width);
6172 if (XINT (right_width) <= 0)
6173 right_width = Qnil;
6176 if (!EQ (w->left_margin_cols, left_width)
6177 || !EQ (w->right_margin_cols, right_width))
6179 wset_left_margin_cols (w, left_width);
6180 wset_right_margin_cols (w, right_width);
6182 adjust_window_margins (w);
6184 ++windows_or_buffers_changed;
6185 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6188 return Qnil;
6192 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6193 0, 1, 0,
6194 doc: /* Get width of marginal areas of window WINDOW.
6195 WINDOW must be a live window and defaults to the selected one.
6197 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6198 If a marginal area does not exist, its width will be returned
6199 as nil. */)
6200 (Lisp_Object window)
6202 struct window *w = decode_live_window (window);
6203 return Fcons (w->left_margin_cols, w->right_margin_cols);
6208 /***********************************************************************
6209 Fringes
6210 ***********************************************************************/
6212 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6213 2, 4, 0,
6214 doc: /* Set the fringe widths of window WINDOW.
6215 WINDOW must be a live window and defaults to the selected one.
6217 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6218 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6219 fringe width. If a fringe width arg is nil, that means to use the
6220 frame's default fringe width. Default fringe widths can be set with
6221 the command `set-fringe-style'.
6222 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6223 outside of the display margins. By default, fringes are drawn between
6224 display marginal areas and the text area. */)
6225 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width, Lisp_Object outside_margins)
6227 struct window *w = decode_live_window (window);
6228 int outside = !NILP (outside_margins);
6230 if (!NILP (left_width))
6231 CHECK_NATNUM (left_width);
6232 if (!NILP (right_width))
6233 CHECK_NATNUM (right_width);
6235 /* Do nothing on a tty. */
6236 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6237 && (!EQ (w->left_fringe_width, left_width)
6238 || !EQ (w->right_fringe_width, right_width)
6239 || w->fringes_outside_margins != outside))
6241 wset_left_fringe_width (w, left_width);
6242 wset_right_fringe_width (w, right_width);
6243 w->fringes_outside_margins = outside;
6245 adjust_window_margins (w);
6247 clear_glyph_matrix (w->current_matrix);
6248 w->window_end_valid = 0;
6250 ++windows_or_buffers_changed;
6251 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6254 return Qnil;
6258 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6259 0, 1, 0,
6260 doc: /* Get width of fringes of window WINDOW.
6261 WINDOW must be a live window and defaults to the selected one.
6263 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6264 (Lisp_Object window)
6266 struct window *w = decode_live_window (window);
6268 return list3 (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6269 make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6270 WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil);
6275 /***********************************************************************
6276 Scroll bars
6277 ***********************************************************************/
6279 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
6280 Sset_window_scroll_bars, 2, 4, 0,
6281 doc: /* Set width and type of scroll bars of window WINDOW.
6282 WINDOW must be a live window and defaults to the selected one.
6284 Second parameter WIDTH specifies the pixel width for the scroll bar;
6285 this is automatically adjusted to a multiple of the frame column width.
6286 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6287 bar: left, right, or nil.
6288 If WIDTH is nil, use the frame's scroll-bar width.
6289 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6290 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6291 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, Lisp_Object horizontal_type)
6293 struct window *w = decode_live_window (window);
6295 if (!NILP (width))
6297 CHECK_RANGED_INTEGER (width, 0, INT_MAX);
6299 if (XINT (width) == 0)
6300 vertical_type = Qnil;
6303 if (!(NILP (vertical_type)
6304 || EQ (vertical_type, Qleft)
6305 || EQ (vertical_type, Qright)
6306 || EQ (vertical_type, Qt)))
6307 error ("Invalid type of vertical scroll bar");
6309 if (!EQ (w->scroll_bar_width, width)
6310 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6312 wset_scroll_bar_width (w, width);
6313 wset_vertical_scroll_bar_type (w, vertical_type);
6315 adjust_window_margins (w);
6317 clear_glyph_matrix (w->current_matrix);
6318 w->window_end_valid = 0;
6320 ++windows_or_buffers_changed;
6321 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6324 return Qnil;
6328 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6329 0, 1, 0,
6330 doc: /* Get width and type of scroll bars of window WINDOW.
6331 WINDOW must be a live window and defaults to the selected one.
6333 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6334 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6335 value. */)
6336 (Lisp_Object window)
6338 struct window *w = decode_live_window (window);
6340 return list4 (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6341 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6342 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6343 make_number (WINDOW_SCROLL_BAR_COLS (w)),
6344 w->vertical_scroll_bar_type, Qnil);
6349 /***********************************************************************
6350 Smooth scrolling
6351 ***********************************************************************/
6353 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6354 doc: /* Return the amount by which WINDOW is scrolled vertically.
6355 If WINDOW is omitted or nil, it defaults to the selected window.
6356 Normally, value is a multiple of the canonical character height of WINDOW;
6357 optional second arg PIXELS-P means value is measured in pixels. */)
6358 (Lisp_Object window, Lisp_Object pixels_p)
6360 Lisp_Object result;
6361 struct window *w = decode_live_window (window);
6362 struct frame *f = XFRAME (w->frame);
6364 if (FRAME_WINDOW_P (f))
6365 result = (NILP (pixels_p)
6366 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6367 : make_number (-w->vscroll));
6368 else
6369 result = make_number (0);
6370 return result;
6374 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6375 2, 3, 0,
6376 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6377 WINDOW nil means use the selected window. Normally, VSCROLL is a
6378 non-negative multiple of the canonical character height of WINDOW;
6379 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6380 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6381 corresponds to an integral number of pixels. The return value is the
6382 result of this rounding.
6383 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6384 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
6386 struct window *w = decode_live_window (window);
6387 struct frame *f = XFRAME (w->frame);
6389 CHECK_NUMBER_OR_FLOAT (vscroll);
6391 if (FRAME_WINDOW_P (f))
6393 int old_dy = w->vscroll;
6395 w->vscroll = - (NILP (pixels_p)
6396 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6397 : XFLOATINT (vscroll));
6398 w->vscroll = min (w->vscroll, 0);
6400 if (w->vscroll != old_dy)
6402 /* Adjust glyph matrix of the frame if the virtual display
6403 area becomes larger than before. */
6404 if (w->vscroll < 0 && w->vscroll < old_dy)
6405 adjust_glyphs (f);
6407 /* Prevent redisplay shortcuts. */
6408 XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
6412 return Fwindow_vscroll (window, pixels_p);
6416 /* Call FN for all leaf windows on frame F. FN is called with the
6417 first argument being a pointer to the leaf window, and with
6418 additional argument USER_DATA. Stops when FN returns 0. */
6420 static void
6421 foreach_window (struct frame *f, int (*fn) (struct window *, void *),
6422 void *user_data)
6424 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6425 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6426 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6430 /* Helper function for foreach_window. Call FN for all leaf windows
6431 reachable from W. FN is called with the first argument being a
6432 pointer to the leaf window, and with additional argument USER_DATA.
6433 Stop when FN returns 0. Value is 0 if stopped by FN. */
6435 static int
6436 foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
6438 int cont;
6440 for (cont = 1; w && cont;)
6442 if (WINDOWP (w->contents))
6443 cont = foreach_window_1 (XWINDOW (w->contents), fn, user_data);
6444 else
6445 cont = fn (w, user_data);
6447 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6450 return cont;
6453 /***********************************************************************
6454 Initialization
6455 ***********************************************************************/
6457 /* Return 1 if window configurations CONFIGURATION1 and CONFIGURATION2
6458 describe the same state of affairs. This is used by Fequal.
6460 IGNORE_POSITIONS means ignore non-matching scroll positions
6461 and the like.
6463 This ignores a couple of things like the dedication status of
6464 window, combination_limit and the like. This might have to be
6465 fixed. */
6467 bool
6468 compare_window_configurations (Lisp_Object configuration1,
6469 Lisp_Object configuration2,
6470 bool ignore_positions)
6472 register struct save_window_data *d1, *d2;
6473 struct Lisp_Vector *sws1, *sws2;
6474 ptrdiff_t i;
6476 CHECK_WINDOW_CONFIGURATION (configuration1);
6477 CHECK_WINDOW_CONFIGURATION (configuration2);
6479 d1 = (struct save_window_data *) XVECTOR (configuration1);
6480 d2 = (struct save_window_data *) XVECTOR (configuration2);
6481 sws1 = XVECTOR (d1->saved_windows);
6482 sws2 = XVECTOR (d2->saved_windows);
6484 /* Frame settings must match. */
6485 if (d1->frame_cols != d2->frame_cols
6486 || d1->frame_lines != d2->frame_lines
6487 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
6488 || !EQ (d1->selected_frame, d2->selected_frame)
6489 || !EQ (d1->current_buffer, d2->current_buffer)
6490 || (!ignore_positions
6491 && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
6492 || !EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)))
6493 || !EQ (d1->focus_frame, d2->focus_frame)
6494 /* Verify that the two configurations have the same number of windows. */
6495 || sws1->header.size != sws2->header.size)
6496 return 0;
6498 for (i = 0; i < sws1->header.size; i++)
6500 struct saved_window *sw1, *sw2;
6502 sw1 = SAVED_WINDOW_N (sws1, i);
6503 sw2 = SAVED_WINDOW_N (sws2, i);
6505 if (
6506 /* The "current" windows in the two configurations must
6507 correspond to each other. */
6508 EQ (d1->current_window, sw1->window)
6509 != EQ (d2->current_window, sw2->window)
6510 /* Windows' buffers must match. */
6511 || !EQ (sw1->buffer, sw2->buffer)
6512 || !EQ (sw1->left_col, sw2->left_col)
6513 || !EQ (sw1->top_line, sw2->top_line)
6514 || !EQ (sw1->total_cols, sw2->total_cols)
6515 || !EQ (sw1->total_lines, sw2->total_lines)
6516 || !EQ (sw1->display_table, sw2->display_table)
6517 /* The next two disjuncts check the window structure for
6518 equality. */
6519 || !EQ (sw1->parent, sw2->parent)
6520 || !EQ (sw1->prev, sw2->prev)
6521 || (!ignore_positions
6522 && (!EQ (sw1->hscroll, sw2->hscroll)
6523 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
6524 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
6525 || NILP (Fequal (sw1->start, sw2->start))
6526 || NILP (Fequal (sw1->pointm, sw2->pointm))
6527 || NILP (Fequal (sw1->mark, sw2->mark))))
6528 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
6529 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
6530 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
6531 || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
6532 || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
6533 || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
6534 || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type))
6535 return 0;
6538 return 1;
6541 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6542 Scompare_window_configurations, 2, 2, 0,
6543 doc: /* Compare two window configurations as regards the structure of windows.
6544 This function ignores details such as the values of point and mark
6545 and scrolling positions. */)
6546 (Lisp_Object x, Lisp_Object y)
6548 if (compare_window_configurations (x, y, 1))
6549 return Qt;
6550 return Qnil;
6553 void
6554 init_window_once (void)
6556 struct frame *f = make_initial_frame ();
6557 XSETFRAME (selected_frame, f);
6558 Vterminal_frame = selected_frame;
6559 minibuf_window = f->minibuffer_window;
6560 selected_window = f->selected_window;
6561 last_nonminibuf_frame = f;
6563 window_initialized = 1;
6566 void
6567 init_window (void)
6569 Vwindow_list = Qnil;
6572 void
6573 syms_of_window (void)
6575 DEFSYM (Qscroll_up, "scroll-up");
6576 DEFSYM (Qscroll_down, "scroll-down");
6577 DEFSYM (Qscroll_command, "scroll-command");
6579 Fput (Qscroll_up, Qscroll_command, Qt);
6580 Fput (Qscroll_down, Qscroll_command, Qt);
6582 DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
6583 DEFSYM (Qwindowp, "windowp");
6584 DEFSYM (Qwindow_configuration_p, "window-configuration-p");
6585 DEFSYM (Qwindow_live_p, "window-live-p");
6586 DEFSYM (Qwindow_valid_p, "window-valid-p");
6587 DEFSYM (Qwindow_deletable_p, "window-deletable-p");
6588 DEFSYM (Qdelete_window, "delete-window");
6589 DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
6590 DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
6591 DEFSYM (Qsafe, "safe");
6592 DEFSYM (Qdisplay_buffer, "display-buffer");
6593 DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
6594 DEFSYM (Qrecord_window_buffer, "record-window-buffer");
6595 DEFSYM (Qget_mru_window, "get-mru-window");
6596 DEFSYM (Qwindow_size, "window-size");
6597 DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6598 DEFSYM (Qabove, "above");
6599 DEFSYM (Qbelow, "below");
6600 DEFSYM (Qclone_of, "clone-of");
6602 staticpro (&Vwindow_list);
6604 minibuf_selected_window = Qnil;
6605 staticpro (&minibuf_selected_window);
6607 window_scroll_pixel_based_preserve_x = -1;
6608 window_scroll_pixel_based_preserve_y = -1;
6609 window_scroll_preserve_hpos = -1;
6610 window_scroll_preserve_vpos = -1;
6612 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
6613 doc: /* Non-nil means call as function to display a help buffer.
6614 The function is called with one argument, the buffer to be displayed.
6615 Used by `with-output-to-temp-buffer'.
6616 If this function is used, then it must do the entire job of showing
6617 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6618 Vtemp_buffer_show_function = Qnil;
6620 DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
6621 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6622 Vminibuf_scroll_window = Qnil;
6624 DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
6625 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6626 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6627 is displayed in the `mode-line' face. */);
6628 mode_line_in_non_selected_windows = 1;
6630 DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
6631 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6632 Vother_window_scroll_buffer = Qnil;
6634 DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
6635 doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
6636 auto_window_vscroll_p = 1;
6638 DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
6639 doc: /* Number of lines of continuity when scrolling by screenfuls. */);
6640 next_screen_context_lines = 2;
6642 DEFVAR_LISP ("scroll-preserve-screen-position",
6643 Vscroll_preserve_screen_position,
6644 doc: /* Controls if scroll commands move point to keep its screen position unchanged.
6645 A value of nil means point does not keep its screen position except
6646 at the scroll margin or window boundary respectively.
6647 A value of t means point keeps its screen position if the scroll
6648 command moved it vertically out of the window, e.g. when scrolling
6649 by full screens.
6650 Any other value means point always keeps its screen position.
6651 Scroll commands should have the `scroll-command' property
6652 on their symbols to be controlled by this variable. */);
6653 Vscroll_preserve_screen_position = Qnil;
6655 DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
6656 doc: /* Type of marker to use for `window-point'. */);
6657 Vwindow_point_insertion_type = Qnil;
6659 DEFVAR_LISP ("window-configuration-change-hook",
6660 Vwindow_configuration_change_hook,
6661 doc: /* Functions to call when window configuration changes.
6662 The buffer-local part is run once per window, with the relevant window
6663 selected; while the global part is run only once for the modified frame,
6664 with the relevant frame selected. */);
6665 Vwindow_configuration_change_hook = Qnil;
6667 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
6668 doc: /* Non-nil means `recenter' redraws entire frame.
6669 If this option is non-nil, then the `recenter' command with a nil
6670 argument will redraw the entire frame; the special value `tty' causes
6671 the frame to be redrawn only if it is a tty frame. */);
6672 Vrecenter_redisplay = Qtty;
6674 DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
6675 doc: /* If t, resize window combinations proportionally.
6676 If this variable is nil, splitting a window gets the entire screen space
6677 for displaying the new window from the window to split. Deleting and
6678 resizing a window preferably resizes one adjacent window only.
6680 If this variable is t, splitting a window tries to get the space
6681 proportionally from all windows in the same combination. This also
6682 allows to split a window that is otherwise too small or of fixed size.
6683 Resizing and deleting a window proportionally resize all windows in the
6684 same combination.
6686 Other values are reserved for future use.
6688 This variable takes no effect if the variable `window-combination-limit' is
6689 non-nil. */);
6690 Vwindow_combination_resize = Qnil;
6692 DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
6693 doc: /* If non-nil, splitting a window makes a new parent window.
6694 The following values are recognized:
6696 nil means splitting a window will create a new parent window only if the
6697 window has no parent window or the window shall become part of a
6698 combination orthogonal to the one it is part of.
6700 `window-size' means that splitting a window for displaying a buffer
6701 makes a new parent window provided `display-buffer' is supposed to
6702 explicitly set the window's size due to the presence of a
6703 `window-height' or `window-width' entry in the alist used by
6704 `display-buffer'. Otherwise, this value is handled like nil.
6706 `temp-buffer' means that splitting a window for displaying a temporary
6707 buffer always makes a new parent window. Otherwise, this value is
6708 handled like nil.
6710 `display-buffer' means that splitting a window for displaying a buffer
6711 always makes a new parent window. Since temporary buffers are
6712 displayed by the function `display-buffer', this value is stronger
6713 than `temp-buffer'. Splitting a window for other purpose makes a
6714 new parent window only if needed.
6716 t means that splitting a window always creates a new parent window. If
6717 all splits behave this way, each frame's window tree is a binary
6718 tree and every window but the frame's root window has exactly one
6719 sibling.
6721 Other values are reserved for future use. */);
6722 Vwindow_combination_limit = Qwindow_size;
6724 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
6725 doc: /* Alist of persistent window parameters.
6726 This alist specifies which window parameters shall get saved by
6727 `current-window-configuration' and `window-state-get' and subsequently
6728 restored to their previous values by `set-window-configuration' and
6729 `window-state-put'.
6731 The car of each entry of this alist is the symbol specifying the
6732 parameter. The cdr is one of the following:
6734 nil means the parameter is neither saved by `window-state-get' nor by
6735 `current-window-configuration'.
6737 t means the parameter is saved by `current-window-configuration' and,
6738 provided its WRITABLE argument is nil, by `window-state-get'.
6740 The symbol `writable' means the parameter is saved unconditionally by
6741 both `current-window-configuration' and `window-state-get'. Do not use
6742 this value for parameters without read syntax (like windows or frames).
6744 Parameters not saved by `current-window-configuration' or
6745 `window-state-get' are left alone by `set-window-configuration'
6746 respectively are not installed by `window-state-put'. */);
6747 Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
6749 defsubr (&Sselected_window);
6750 defsubr (&Sminibuffer_window);
6751 defsubr (&Swindow_minibuffer_p);
6752 defsubr (&Swindowp);
6753 defsubr (&Swindow_valid_p);
6754 defsubr (&Swindow_live_p);
6755 defsubr (&Swindow_frame);
6756 defsubr (&Sframe_root_window);
6757 defsubr (&Sframe_first_window);
6758 defsubr (&Sframe_selected_window);
6759 defsubr (&Sset_frame_selected_window);
6760 defsubr (&Spos_visible_in_window_p);
6761 defsubr (&Swindow_line_height);
6762 defsubr (&Swindow_buffer);
6763 defsubr (&Swindow_parent);
6764 defsubr (&Swindow_top_child);
6765 defsubr (&Swindow_left_child);
6766 defsubr (&Swindow_next_sibling);
6767 defsubr (&Swindow_prev_sibling);
6768 defsubr (&Swindow_combination_limit);
6769 defsubr (&Sset_window_combination_limit);
6770 defsubr (&Swindow_use_time);
6771 defsubr (&Swindow_top_line);
6772 defsubr (&Swindow_left_column);
6773 defsubr (&Swindow_total_height);
6774 defsubr (&Swindow_total_width);
6775 defsubr (&Swindow_normal_size);
6776 defsubr (&Swindow_new_total);
6777 defsubr (&Swindow_new_normal);
6778 defsubr (&Sset_window_new_total);
6779 defsubr (&Sset_window_new_normal);
6780 defsubr (&Swindow_resize_apply);
6781 defsubr (&Swindow_body_height);
6782 defsubr (&Swindow_body_width);
6783 defsubr (&Swindow_hscroll);
6784 defsubr (&Sset_window_hscroll);
6785 defsubr (&Swindow_redisplay_end_trigger);
6786 defsubr (&Sset_window_redisplay_end_trigger);
6787 defsubr (&Swindow_edges);
6788 defsubr (&Swindow_pixel_edges);
6789 defsubr (&Swindow_absolute_pixel_edges);
6790 defsubr (&Swindow_inside_edges);
6791 defsubr (&Swindow_inside_pixel_edges);
6792 defsubr (&Swindow_inside_absolute_pixel_edges);
6793 defsubr (&Scoordinates_in_window_p);
6794 defsubr (&Swindow_at);
6795 defsubr (&Swindow_point);
6796 defsubr (&Swindow_start);
6797 defsubr (&Swindow_end);
6798 defsubr (&Sset_window_point);
6799 defsubr (&Sset_window_start);
6800 defsubr (&Swindow_dedicated_p);
6801 defsubr (&Sset_window_dedicated_p);
6802 defsubr (&Swindow_display_table);
6803 defsubr (&Sset_window_display_table);
6804 defsubr (&Snext_window);
6805 defsubr (&Sprevious_window);
6806 defsubr (&Sget_buffer_window);
6807 defsubr (&Sdelete_other_windows_internal);
6808 defsubr (&Sdelete_window_internal);
6809 defsubr (&Sresize_mini_window_internal);
6810 defsubr (&Sset_window_buffer);
6811 defsubr (&Srun_window_configuration_change_hook);
6812 defsubr (&Sselect_window);
6813 defsubr (&Sforce_window_update);
6814 defsubr (&Ssplit_window_internal);
6815 defsubr (&Sscroll_up);
6816 defsubr (&Sscroll_down);
6817 defsubr (&Sscroll_left);
6818 defsubr (&Sscroll_right);
6819 defsubr (&Sother_window_for_scrolling);
6820 defsubr (&Sscroll_other_window);
6821 defsubr (&Sminibuffer_selected_window);
6822 defsubr (&Srecenter);
6823 defsubr (&Swindow_text_height);
6824 defsubr (&Smove_to_window_line);
6825 defsubr (&Swindow_configuration_p);
6826 defsubr (&Swindow_configuration_frame);
6827 defsubr (&Sset_window_configuration);
6828 defsubr (&Scurrent_window_configuration);
6829 defsubr (&Sset_window_margins);
6830 defsubr (&Swindow_margins);
6831 defsubr (&Sset_window_fringes);
6832 defsubr (&Swindow_fringes);
6833 defsubr (&Sset_window_scroll_bars);
6834 defsubr (&Swindow_scroll_bars);
6835 defsubr (&Swindow_vscroll);
6836 defsubr (&Sset_window_vscroll);
6837 defsubr (&Scompare_window_configurations);
6838 defsubr (&Swindow_list);
6839 defsubr (&Swindow_list_1);
6840 defsubr (&Swindow_prev_buffers);
6841 defsubr (&Sset_window_prev_buffers);
6842 defsubr (&Swindow_next_buffers);
6843 defsubr (&Sset_window_next_buffers);
6844 defsubr (&Swindow_parameters);
6845 defsubr (&Swindow_parameter);
6846 defsubr (&Sset_window_parameter);
6849 void
6850 keys_of_window (void)
6852 initial_define_key (control_x_map, '<', "scroll-left");
6853 initial_define_key (control_x_map, '>', "scroll-right");
6855 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
6856 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6857 initial_define_key (meta_map, 'v', "scroll-down-command");