Minor fixes in window resizing routines and documentation update.
[emacs.git] / src / window.c
blob7565e271859c7bc2f01e85562dcd9c8824c87ef4
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985-1987, 1993-1998, 2000-2011
4 Free Software 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>
22 #include <stdio.h>
23 #include <setjmp.h>
25 #include "lisp.h"
26 #include "buffer.h"
27 #include "keyboard.h"
28 #include "keymap.h"
29 #include "frame.h"
30 #include "window.h"
31 #include "commands.h"
32 #include "indent.h"
33 #include "termchar.h"
34 #include "disptab.h"
35 #include "dispextern.h"
36 #include "blockinput.h"
37 #include "intervals.h"
38 #include "termhooks.h" /* For FRAME_TERMINAL. */
40 #ifdef HAVE_X_WINDOWS
41 #include "xterm.h"
42 #endif /* HAVE_X_WINDOWS */
43 #ifdef WINDOWSNT
44 #include "w32term.h"
45 #endif
46 #ifdef MSDOS
47 #include "msdos.h"
48 #endif
49 #ifdef HAVE_NS
50 #include "nsterm.h"
51 #endif
53 Lisp_Object Qwindowp, Qwindow_live_p;
54 static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer;
55 static Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
56 static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
57 static Lisp_Object Qresize_root_window, Qresize_root_window_vertically;
58 static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
59 static Lisp_Object Qsafe, Qabove, Qbelow;
60 static Lisp_Object Qauto_buffer_name;
62 static int displayed_window_lines (struct window *);
63 static struct window *decode_window (Lisp_Object);
64 static int count_windows (struct window *);
65 static int get_leaf_windows (struct window *, struct window **, int);
66 static void window_scroll (Lisp_Object, int, int, int);
67 static void window_scroll_pixel_based (Lisp_Object, int, int, int);
68 static void window_scroll_line_based (Lisp_Object, int, int, int);
69 static int freeze_window_start (struct window *, void *);
70 static Lisp_Object window_list (void);
71 static int add_window_to_list (struct window *, void *);
72 static int candidate_window_p (Lisp_Object, Lisp_Object, Lisp_Object,
73 Lisp_Object);
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 void resize_window_apply (struct window *, int);
86 static Lisp_Object select_window (Lisp_Object, Lisp_Object, int);
88 /* This is the window in which the terminal's cursor should
89 be left when nothing is being done with it. This must
90 always be a leaf window, and its buffer is selected by
91 the top level editing loop at the end of each command.
93 This value is always the same as
94 FRAME_SELECTED_WINDOW (selected_frame). */
95 Lisp_Object selected_window;
97 /* A list of all windows for use by next_window and Fwindow_list.
98 Functions creating or deleting windows should invalidate this cache
99 by setting it to nil. */
100 Lisp_Object Vwindow_list;
102 /* The mini-buffer window of the selected frame.
103 Note that you cannot test for mini-bufferness of an arbitrary window
104 by comparing against this; but you can test for mini-bufferness of
105 the selected window. */
106 Lisp_Object minibuf_window;
108 /* Non-nil means it is the window whose mode line should be
109 shown as the selected window when the minibuffer is selected. */
110 Lisp_Object minibuf_selected_window;
112 /* Hook run at end of temp_output_buffer_show. */
113 static Lisp_Object Qtemp_buffer_show_hook;
115 /* Incremented for each window created. */
116 static int sequence_number;
118 /* Nonzero after init_window_once has finished. */
119 static int window_initialized;
121 /* Hook to run when window config changes. */
122 static Lisp_Object Qwindow_configuration_change_hook;
123 /* Incremented by 1 whenever a window is deleted. */
125 static int window_deletion_count;
127 /* Used by the function window_scroll_pixel_based */
128 static int window_scroll_pixel_based_preserve_x;
129 static int window_scroll_pixel_based_preserve_y;
131 /* Same for window_scroll_line_based. */
132 static int window_scroll_preserve_hpos;
133 static int window_scroll_preserve_vpos;
135 static struct window *
136 decode_window (register Lisp_Object window)
138 if (NILP (window))
139 return XWINDOW (selected_window);
141 CHECK_LIVE_WINDOW (window);
142 return XWINDOW (window);
145 static struct window *
146 decode_any_window (register Lisp_Object window)
148 if (NILP (window))
149 return XWINDOW (selected_window);
151 CHECK_WINDOW (window);
152 return XWINDOW (window);
155 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
156 doc: /* Return t if OBJECT is a window. */)
157 (Lisp_Object object)
159 return WINDOWP (object) ? Qt : Qnil;
162 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
163 doc: /* Return t if OBJECT is a live window and nil otherwise.
164 A live window is a window that is currently used to display a
165 buffer. */)
166 (Lisp_Object object)
168 return WINDOW_LIVE_P (object) ? Qt : Qnil;
171 /* Frames and windows. */
172 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
173 doc: /* Return the frame that window WINDOW is on.
174 WINDOW can be any window and defaults to the selected one. */)
175 (Lisp_Object window)
177 return decode_any_window (window)->frame;
180 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
181 doc: /* Return the root window of FRAME_OR_WINDOW.
182 If omitted, FRAME_OR_WINDOW defaults to the currently selected frame.
183 Else if FRAME_OR_WINDOW denotes any window, return the root window of
184 that window's frame. If FRAME_OR_WINDOW denotes a live frame, return
185 the root window of that frame. */)
186 (Lisp_Object frame_or_window)
188 Lisp_Object window;
190 if (NILP (frame_or_window))
191 window = SELECTED_FRAME ()->root_window;
192 else if (WINDOWP (frame_or_window))
193 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
194 else
196 CHECK_LIVE_FRAME (frame_or_window);
197 window = XFRAME (frame_or_window)->root_window;
200 return window;
203 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
204 doc: /* Return the window used now for minibuffers.
205 If the optional argument FRAME is specified, return the minibuffer window
206 used by that frame. */)
207 (Lisp_Object frame)
209 if (NILP (frame))
210 frame = selected_frame;
211 CHECK_LIVE_FRAME (frame);
212 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
215 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
216 Swindow_minibuffer_p, 0, 1, 0,
217 doc: /* Return non-nil if WINDOW is a minibuffer window.
218 WINDOW can be any window and defaults to the selected one. */)
219 (Lisp_Object window)
221 return MINI_WINDOW_P (decode_any_window (window)) ? Qt : Qnil;
224 /* Don't move this to window.el - this must be a safe routine. */
225 DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
226 doc: /* Return the topmost, leftmost live window on FRAME_OR_WINDOW.
227 If omitted, FRAME_OR_WINDOW defaults to the currently selected frame.
228 Else if FRAME_OR_WINDOW denotes any window, return the first window of
229 that window's frame. If FRAME_OR_WINDOW denotes a live frame, return
230 the first window of that frame. */)
231 (Lisp_Object frame_or_window)
233 Lisp_Object window;
235 if (NILP (frame_or_window))
236 window = SELECTED_FRAME ()->root_window;
237 else if (WINDOWP (frame_or_window))
238 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
239 else
241 CHECK_LIVE_FRAME (frame_or_window);
242 window = XFRAME (frame_or_window)->root_window;
245 while (NILP (XWINDOW (window)->buffer))
247 if (! NILP (XWINDOW (window)->hchild))
248 window = XWINDOW (window)->hchild;
249 else if (! NILP (XWINDOW (window)->vchild))
250 window = XWINDOW (window)->vchild;
251 else
252 abort ();
255 return window;
258 DEFUN ("frame-selected-window", Fframe_selected_window,
259 Sframe_selected_window, 0, 1, 0,
260 doc: /* Return the selected window of FRAME_OR_WINDOW.
261 If omitted, FRAME_OR_WINDOW defaults to the currently selected frame.
262 Else if FRAME_OR_WINDOW denotes any window, return the selected window
263 of that window's frame. If FRAME_OR_WINDOW denotes a live frame, return
264 the selected window of that frame. */)
265 (Lisp_Object frame_or_window)
267 Lisp_Object window;
269 if (NILP (frame_or_window))
270 window = SELECTED_FRAME ()->selected_window;
271 else if (WINDOWP (frame_or_window))
272 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
273 else
275 CHECK_LIVE_FRAME (frame_or_window);
276 window = XFRAME (frame_or_window)->selected_window;
279 return window;
282 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
283 Sset_frame_selected_window, 2, 3, 0,
284 doc: /* Set selected window of FRAME to WINDOW.
285 FRAME must be a live frame and defaults to the selected one. If FRAME
286 is the selected frame, this makes WINDOW the selected window. Optional
287 argument NORECORD non-nil means to neither change the order of recently
288 selected windows nor the buffer list. WINDOW must denote a live window.
289 Return WINDOW. */)
290 (Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
292 if (NILP (frame))
293 frame = selected_frame;
295 CHECK_LIVE_FRAME (frame);
296 CHECK_LIVE_WINDOW (window);
298 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
299 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
301 if (EQ (frame, selected_frame))
302 return Fselect_window (window, norecord);
303 else
304 return XFRAME (frame)->selected_window = window;
307 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
308 doc: /* Return the selected window.
309 The selected window is the window in which the standard cursor for
310 selected windows appears and to which many commands apply. */)
311 (void)
313 return selected_window;
316 int window_select_count;
318 /* If select_window is called with inhibit_point_swap non-zero it will
319 not store point of the old selected window's buffer back into that
320 window's pointm slot. This is needed by Fset_window_configuration to
321 avoid that the display routine is called with selected_window set to
322 Qnil causing a subsequent crash. */
323 static Lisp_Object
324 select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
326 register struct window *w;
327 register struct window *ow;
328 struct frame *sf;
330 CHECK_LIVE_WINDOW (window);
332 w = XWINDOW (window);
333 w->frozen_window_start_p = 0;
335 if (NILP (norecord))
337 ++window_select_count;
338 XSETFASTINT (w->use_time, window_select_count);
339 record_buffer (w->buffer);
342 if (EQ (window, selected_window) && !inhibit_point_swap)
343 return window;
345 sf = SELECTED_FRAME ();
346 if (XFRAME (WINDOW_FRAME (w)) != sf)
348 XFRAME (WINDOW_FRAME (w))->selected_window = window;
349 /* Use this rather than Fhandle_switch_frame
350 so that FRAME_FOCUS_FRAME is moved appropriately as we
351 move around in the state where a minibuffer in a separate
352 frame is active. */
353 Fselect_frame (WINDOW_FRAME (w), norecord);
354 /* Fselect_frame called us back so we've done all the work already. */
355 eassert (EQ (window, selected_window));
356 return window;
358 else
359 sf->selected_window = window;
361 /* Store the current buffer's actual point into the
362 old selected window. It belongs to that window,
363 and when the window is not selected, must be in the window. */
364 if (!inhibit_point_swap)
366 ow = XWINDOW (selected_window);
367 if (! NILP (ow->buffer))
368 set_marker_both (ow->pointm, ow->buffer,
369 BUF_PT (XBUFFER (ow->buffer)),
370 BUF_PT_BYTE (XBUFFER (ow->buffer)));
373 selected_window = window;
375 Fset_buffer (w->buffer);
377 BVAR (XBUFFER (w->buffer), last_selected_window) = window;
379 /* Go to the point recorded in the window.
380 This is important when the buffer is in more
381 than one window. It also matters when
382 redisplay_window has altered point after scrolling,
383 because it makes the change only in the window. */
385 register EMACS_INT new_point = marker_position (w->pointm);
386 if (new_point < BEGV)
387 SET_PT (BEGV);
388 else if (new_point > ZV)
389 SET_PT (ZV);
390 else
391 SET_PT (new_point);
394 windows_or_buffers_changed++;
395 return window;
398 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
399 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
400 Also make WINDOW's buffer current and make WINDOW the frame's selected
401 window. Return WINDOW.
403 Optional second arg NORECORD non-nil means do not put this buffer at the
404 front of the buffer list and do not make this window the most recently
405 selected one.
407 Note that the main editor command loop sets the current buffer to the
408 buffer of the selected window before each command. */)
409 (register Lisp_Object window, Lisp_Object norecord)
411 return select_window (window, norecord, 0);
414 DEFUN ("window-clone-number", Fwindow_clone_number, Swindow_clone_number, 0, 1, 0,
415 doc: /* Return WINDOW's clone number.
416 WINDOW can be any window and defaults to the selected one. */)
417 (Lisp_Object window)
419 return decode_any_window (window)->clone_number;
422 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
423 doc: /* Return the buffer that WINDOW is displaying.
424 WINDOW can be any window and defaults to the selected one.
425 If WINDOW is an internal window return nil. */)
426 (Lisp_Object window)
428 return decode_any_window (window)->buffer;
431 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
432 doc: /* Return WINDOW's parent window.
433 WINDOW can be any window and defaults to the selected one.
434 Return nil if WINDOW has no parent. */)
435 (Lisp_Object window)
437 return decode_any_window (window)->parent;
440 DEFUN ("window-vchild", Fwindow_vchild, Swindow_vchild, 0, 1, 0,
441 doc: /* Return WINDOW's first vertical child window.
442 WINDOW can be any window and defaults to the selected one.
443 Return nil if WINDOW has no vertical child. */)
444 (Lisp_Object window)
446 return decode_any_window (window)->vchild;
449 DEFUN ("window-hchild", Fwindow_hchild, Swindow_hchild, 0, 1, 0,
450 doc: /* Return WINDOW's first horizontal child window.
451 WINDOW can be any window and defaults to the selected one.
452 Return nil if WINDOW has no horizontal child. */)
453 (Lisp_Object window)
455 return decode_any_window (window)->hchild;
458 DEFUN ("window-next", Fwindow_next, Swindow_next, 0, 1, 0,
459 doc: /* Return WINDOW's right sibling window.
460 WINDOW can be any window and defaults to the selected one.
461 Return nil if WINDOW has no right sibling. */)
462 (Lisp_Object window)
464 return decode_any_window (window)->next;
467 DEFUN ("window-prev", Fwindow_prev, Swindow_prev, 0, 1, 0,
468 doc: /* Return WINDOW's left sibling window.
469 WINDOW can be any window and defaults to the selected one.
470 Return nil if WINDOW has no left sibling. */)
471 (Lisp_Object window)
473 return decode_any_window (window)->prev;
476 DEFUN ("window-splits", Fwindow_splits, Swindow_splits, 0, 1, 0,
477 doc: /* Return splits status for WINDOW.
478 WINDOW can be any window and defaults to the selected one.
480 If the value returned by this function is nil and WINDOW is resized, the
481 corresponding space is preferably taken from (or given to) WINDOW's
482 right sibling. When WINDOW is deleted, its space is given to its left
483 sibling.
485 If the value returned by this function is non-nil, resizing and deleting
486 WINDOW may resize all windows in the same combination. */)
487 (Lisp_Object window)
489 return decode_any_window (window)->splits;
492 DEFUN ("set-window-splits", Fset_window_splits, Sset_window_splits, 2, 2, 0,
493 doc: /* Set splits status of WINDOW to STATUS.
494 WINDOW can be any window and defaults to the selected one. Return
495 STATUS.
497 If STATUS is nil and WINDOW is later resized, the corresponding space is
498 preferably taken from (or given to) WINDOW's right sibling. When WINDOW
499 is deleted, its space is given to its left sibling.
501 If STATUS is non-nil, resizing and deleting WINDOW may resize all
502 windows in the same combination. */)
503 (Lisp_Object window, Lisp_Object status)
505 register struct window *w = decode_any_window (window);
507 w->splits = status;
509 return w->splits;
512 DEFUN ("window-nest", Fwindow_nest, Swindow_nest, 0, 1, 0,
513 doc: /* Return nest status of WINDOW.
514 WINDOW can be any window and defaults to the selected one.
516 If the return value is nil, subwindows of WINDOW can be recombined with
517 WINDOW's siblings. A return value of nil means that subwindows of
518 WINDOW are never \(re-)combined with WINDOW's siblings. */)
519 (Lisp_Object window)
521 return decode_any_window (window)->nest;
524 DEFUN ("set-window-nest", Fset_window_nest, Sset_window_nest, 2, 2, 0,
525 doc: /* Set nest status of WINDOW to STATUS.
526 WINDOW can be any window and defaults to the selected one. Return
527 STATUS.
529 If the return value is nil, subwindows of WINDOW can be recombined with
530 WINDOW's siblings. A return value of nil means that subwindows of
531 WINDOW are never \(re-)combined with WINDOW's siblings. */)
532 (Lisp_Object window, Lisp_Object status)
534 register struct window *w = decode_any_window (window);
536 w->nest = status;
538 return w->nest;
541 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
542 doc: /* Return WINDOW's use time.
543 WINDOW defaults to the selected window. The window with the highest use
544 time is the most recently selected one. The window with the lowest use
545 time is the least recently selected one. */)
546 (Lisp_Object window)
548 return decode_window (window)->use_time;
551 DEFUN ("window-total-size", Fwindow_total_size, Swindow_total_size, 0, 2, 0,
552 doc: /* Return the total number of lines of WINDOW.
553 WINDOW can be any window and defaults to the selected one. The return
554 value includes WINDOW's mode line and header line, if any. If WINDOW
555 is internal, the return value is the sum of the total number of lines
556 of WINDOW's child windows if these are vertically combined and the
557 height of WINDOW's first child otherwise.
559 Optional argument HORIZONTAL non-nil means return the total number of
560 columns of WINDOW. In this case the return value includes any vertical
561 dividers or scrollbars of WINDOW. If WINDOW is internal, the return
562 value is the sum of the total number of columns of WINDOW's child
563 windows if they are horizontally combined and the width of WINDOW's
564 first child otherwise. */)
565 (Lisp_Object window, Lisp_Object horizontal)
567 if (NILP (horizontal))
568 return decode_any_window (window)->total_lines;
569 else
570 return decode_any_window (window)->total_cols;
573 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
574 doc: /* Return new total size of WINDOW.
575 WINDOW defaults to the selected window. */)
576 (Lisp_Object window)
578 return decode_any_window (window)->new_total;
581 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
582 doc: /* Return normal height of WINDOW.
583 WINDOW can be any window and defaults to the selected one. Optional
584 argument HORIZONTAL non-nil means return normal width of WINDOW. */)
585 (Lisp_Object window, Lisp_Object horizontal)
587 if (NILP (horizontal))
588 return decode_any_window (window)->normal_lines;
589 else
590 return decode_any_window (window)->normal_cols;
593 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
594 doc: /* Return new normal size of WINDOW.
595 WINDOW can be any window and defaults to the selected one. */)
596 (Lisp_Object window)
598 return decode_any_window (window)->new_normal;
601 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
602 doc: /* Return left column of WINDOW.
603 WINDOW can be any window and defaults to the selected one. */)
604 (Lisp_Object window)
606 return decode_any_window (window)->left_col;
609 DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
610 doc: /* Return top line of WINDOW.
611 WINDOW can be any window and defaults to the selected one. */)
612 (Lisp_Object window)
614 return decode_any_window (window)->top_line;
617 /* Return the number of lines of W's body. Don't count any mode or
618 header line of W. */
621 window_body_lines (struct window *w)
623 int height = XFASTINT (w->total_lines);
625 if (!MINI_WINDOW_P (w))
627 if (WINDOW_WANTS_MODELINE_P (w))
628 --height;
629 if (WINDOW_WANTS_HEADER_LINE_P (w))
630 --height;
633 return height;
636 /* Return the number of columns of W's body. Don't count columns
637 occupied by the scroll bar or the vertical bar separating W from its
638 right sibling. On window-systems don't count fringes or display
639 margins either. */
642 window_body_cols (struct window *w)
644 struct frame *f = XFRAME (WINDOW_FRAME (w));
645 int width = XINT (w->total_cols);
647 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
648 /* Scroll bars occupy a few columns. */
649 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
650 else if (!FRAME_WINDOW_P (f)
651 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
652 /* The column of `|' characters separating side-by-side windows
653 occupies one column only. */
654 width -= 1;
656 if (FRAME_WINDOW_P (f))
657 /* On window-systems, fringes and display margins cannot be
658 used for normal text. */
659 width -= (WINDOW_FRINGE_COLS (w)
660 + WINDOW_LEFT_MARGIN_COLS (w)
661 + WINDOW_RIGHT_MARGIN_COLS (w));
663 return width;
666 DEFUN ("window-body-size", Fwindow_body_size, Swindow_body_size, 0, 2, 0,
667 doc: /* Return the number of lines of WINDOW's body.
668 WINDOW must be a live window and defaults to the selected one. The
669 return value does not include WINDOW's mode line and header line, if
670 any.
672 Optional argument HORIZONTAL non-nil means return the number of columns
673 of WINDOW's body. In this case, the return value does not include any
674 vertical dividers or scroll bars owned by WINDOW. On a window-system
675 the return value does not include the number of columns used for
676 WINDOW's fringes or display margins either. */)
677 (Lisp_Object window, Lisp_Object horizontal)
679 struct window *w = decode_any_window (window);
681 if (NILP (horizontal))
682 return make_number (window_body_lines (w));
683 else
684 return make_number (window_body_cols (w));
687 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
688 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
689 WINDOW must be a live window and defaults to the selected one. */)
690 (Lisp_Object window)
692 return decode_window (window)->hscroll;
695 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
696 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
697 Return NCOL. NCOL should be zero or positive.
699 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
700 window so that the location of point moves off-window. */)
701 (Lisp_Object window, Lisp_Object ncol)
703 struct window *w = decode_window (window);
704 int hscroll;
706 CHECK_NUMBER (ncol);
707 hscroll = max (0, XINT (ncol));
709 /* Prevent redisplay shortcuts when changing the hscroll. */
710 if (XINT (w->hscroll) != hscroll)
711 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
713 w->hscroll = make_number (hscroll);
714 return ncol;
717 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
718 Swindow_redisplay_end_trigger, 0, 1, 0,
719 doc: /* Return WINDOW's redisplay end trigger value.
720 WINDOW defaults to the selected window.
721 See `set-window-redisplay-end-trigger' for more information. */)
722 (Lisp_Object window)
724 return decode_window (window)->redisplay_end_trigger;
727 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
728 Sset_window_redisplay_end_trigger, 2, 2, 0,
729 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
730 VALUE should be a buffer position (typically a marker) or nil.
731 If it is a buffer position, then if redisplay in WINDOW reaches a position
732 beyond VALUE, the functions in `redisplay-end-trigger-functions' are called
733 with two arguments: WINDOW, and the end trigger value.
734 Afterwards the end-trigger value is reset to nil. */)
735 (register Lisp_Object window, Lisp_Object value)
737 register struct window *w;
739 w = decode_window (window);
740 w->redisplay_end_trigger = value;
741 return value;
744 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
745 doc: /* Return a list of the edge coordinates of WINDOW.
746 The list has the form (LEFT TOP RIGHT BOTTOM).
747 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
748 all relative to 0, 0 at top left corner of frame.
750 RIGHT is one more than the rightmost column occupied by WINDOW.
751 BOTTOM is one more than the bottommost row occupied by WINDOW.
752 The edges include the space used by WINDOW's scroll bar, display
753 margins, fringes, header line, and/or mode line. For the edges of
754 just the text area, use `window-inside-edges'. */)
755 (Lisp_Object window)
757 register struct window *w = decode_any_window (window);
759 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
760 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
761 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
762 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
763 Qnil))));
766 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
767 doc: /* Return a list of the edge pixel coordinates of WINDOW.
768 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
769 the top left corner of the frame.
771 RIGHT is one more than the rightmost x position occupied by WINDOW.
772 BOTTOM is one more than the bottommost y position occupied by WINDOW.
773 The pixel edges include the space used by WINDOW's scroll bar, display
774 margins, fringes, header line, and/or mode line. For the pixel edges
775 of just the text area, use `window-inside-pixel-edges'. */)
776 (Lisp_Object window)
778 register struct window *w = decode_any_window (window);
780 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
781 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
782 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
783 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
784 Qnil))));
787 static void
788 calc_absolute_offset(struct window *w, int *add_x, int *add_y)
790 struct frame *f = XFRAME (w->frame);
791 *add_y = f->top_pos;
792 #ifdef FRAME_MENUBAR_HEIGHT
793 *add_y += FRAME_MENUBAR_HEIGHT (f);
794 #endif
795 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
796 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
797 #elif FRAME_TOOLBAR_HEIGHT
798 *add_y += FRAME_TOOLBAR_HEIGHT (f);
799 #endif
800 #ifdef FRAME_NS_TITLEBAR_HEIGHT
801 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
802 #endif
803 *add_x = f->left_pos;
804 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
805 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
806 #endif
809 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
810 Swindow_absolute_pixel_edges, 0, 1, 0,
811 doc: /* Return a list of the edge pixel coordinates of WINDOW.
812 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
813 the top left corner of the display.
815 RIGHT is one more than the rightmost x position occupied by WINDOW.
816 BOTTOM is one more than the bottommost y position occupied by WINDOW.
817 The pixel edges include the space used by WINDOW's scroll bar, display
818 margins, fringes, header line, and/or mode line. For the pixel edges
819 of just the text area, use `window-inside-absolute-pixel-edges'. */)
820 (Lisp_Object window)
822 register struct window *w = decode_any_window (window);
823 int add_x, add_y;
824 calc_absolute_offset (w, &add_x, &add_y);
826 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w) + add_x),
827 Fcons (make_number (WINDOW_TOP_EDGE_Y (w) + add_y),
828 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w) + add_x),
829 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w) + add_y),
830 Qnil))));
833 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
834 doc: /* Return a list of the edge coordinates of WINDOW.
835 The list has the form (LEFT TOP RIGHT BOTTOM).
836 TOP and BOTTOM count by lines, and LEFT and RIGHT count by columns,
837 all relative to 0, 0 at top left corner of frame.
839 RIGHT is one more than the rightmost column of WINDOW's text area.
840 BOTTOM is one more than the bottommost row of WINDOW's text area.
841 The inside edges do not include the space used by the WINDOW's scroll
842 bar, display margins, fringes, header line, and/or mode line. */)
843 (Lisp_Object window)
845 register struct window *w = decode_any_window (window);
847 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
848 + WINDOW_LEFT_MARGIN_COLS (w)
849 + WINDOW_LEFT_FRINGE_COLS (w)),
850 make_number (WINDOW_TOP_EDGE_LINE (w)
851 + WINDOW_HEADER_LINE_LINES (w)),
852 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
853 - WINDOW_RIGHT_MARGIN_COLS (w)
854 - WINDOW_RIGHT_FRINGE_COLS (w)),
855 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
856 - WINDOW_MODE_LINE_LINES (w)));
859 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
860 doc: /* Return a list of the edge pixel coordinates of WINDOW.
861 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
862 the top left corner of the frame.
864 RIGHT is one more than the rightmost x position of WINDOW's text area.
865 BOTTOM is one more than the bottommost y position of WINDOW's text area.
866 The inside edges do not include the space used by WINDOW's scroll bar,
867 display margins, fringes, header line, and/or mode line. */)
868 (Lisp_Object window)
870 register struct window *w = decode_any_window (window);
872 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
873 + WINDOW_LEFT_MARGIN_WIDTH (w)
874 + WINDOW_LEFT_FRINGE_WIDTH (w)),
875 make_number (WINDOW_TOP_EDGE_Y (w)
876 + WINDOW_HEADER_LINE_HEIGHT (w)),
877 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
878 - WINDOW_RIGHT_MARGIN_WIDTH (w)
879 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
880 make_number (WINDOW_BOTTOM_EDGE_Y (w)
881 - WINDOW_MODE_LINE_HEIGHT (w)));
884 DEFUN ("window-inside-absolute-pixel-edges",
885 Fwindow_inside_absolute_pixel_edges,
886 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
887 doc: /* Return a list of the edge pixel coordinates of WINDOW.
888 The list has the form (LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at
889 the top left corner of the display.
891 RIGHT is one more than the rightmost x position of WINDOW's text area.
892 BOTTOM is one more than the bottommost y position of WINDOW's text area.
893 The inside edges do not include the space used by WINDOW's scroll bar,
894 display margins, fringes, header line, and/or mode line. */)
895 (Lisp_Object window)
897 register struct window *w = decode_any_window (window);
898 int add_x, add_y;
899 calc_absolute_offset (w, &add_x, &add_y);
901 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
902 + WINDOW_LEFT_MARGIN_WIDTH (w)
903 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
904 make_number (WINDOW_TOP_EDGE_Y (w)
905 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
906 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
907 - WINDOW_RIGHT_MARGIN_WIDTH (w)
908 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
909 make_number (WINDOW_BOTTOM_EDGE_Y (w)
910 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
913 /* Test if the character at column X, row Y is within window W.
914 If it is not, return ON_NOTHING;
915 if it is in the window's text area, return ON_TEXT;
916 if it is on the window's modeline, return ON_MODE_LINE;
917 if it is on the border between the window and its right sibling,
918 return ON_VERTICAL_BORDER.
919 if it is on a scroll bar, return ON_SCROLL_BAR.
920 if it is on the window's top line, return ON_HEADER_LINE;
921 if it is in left or right fringe of the window,
922 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
923 if it is in the marginal area to the left/right of the window,
924 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
926 X and Y are frame relative pixel coordinates. */
928 static enum window_part
929 coordinates_in_window (register struct window *w, int x, int y)
931 struct frame *f = XFRAME (WINDOW_FRAME (w));
932 int left_x, right_x;
933 enum window_part part;
934 int ux = FRAME_COLUMN_WIDTH (f);
935 int x0 = WINDOW_LEFT_EDGE_X (w);
936 int x1 = WINDOW_RIGHT_EDGE_X (w);
937 /* The width of the area where the vertical line can be dragged.
938 (Between mode lines for instance. */
939 int grabbable_width = ux;
940 int lmargin_width, rmargin_width, text_left, text_right;
941 int top_y = WINDOW_TOP_EDGE_Y (w);
942 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
944 /* Outside any interesting row? */
945 if (y < top_y || y >= bottom_y)
946 return ON_NOTHING;
948 /* In what's below, we subtract 1 when computing right_x because we
949 want the rightmost pixel, which is given by left_pixel+width-1. */
950 if (w->pseudo_window_p)
952 left_x = 0;
953 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
955 else
957 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
958 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
961 /* On the mode line or header line? If it's near the start of
962 the mode or header line of window that's has a horizontal
963 sibling, say it's on the vertical line. That's to be able
964 to resize windows horizontally in case we're using toolkit
965 scroll bars. */
967 if (WINDOW_WANTS_MODELINE_P (w)
968 && y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
970 part = ON_MODE_LINE;
972 header_vertical_border_check:
973 /* We're somewhere on the mode line. We consider the place
974 between mode lines of horizontally adjacent mode lines
975 as the vertical border. If scroll bars on the left,
976 return the right window. */
977 if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
978 || WINDOW_RIGHTMOST_P (w))
979 && !WINDOW_LEFTMOST_P (w)
980 && eabs (x - x0) < grabbable_width)
981 return ON_VERTICAL_BORDER;
983 /* Make sure we're not at the rightmost position of a
984 mode-/header-line and there's yet another window on the
985 right. (Bug#1372) */
986 else if ((WINDOW_RIGHTMOST_P (w) || x < x1)
987 && eabs (x - x1) < grabbable_width)
988 return ON_VERTICAL_BORDER;
990 if (x < x0 || x >= x1)
991 return ON_NOTHING;
993 return part;
996 if (WINDOW_WANTS_HEADER_LINE_P (w)
997 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
999 part = ON_HEADER_LINE;
1000 goto header_vertical_border_check;
1003 if (x < x0 || x >= x1) return ON_NOTHING;
1005 /* Outside any interesting column? */
1006 if (x < left_x || x > right_x)
1007 return ON_SCROLL_BAR;
1009 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
1010 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
1012 text_left = window_box_left (w, TEXT_AREA);
1013 text_right = text_left + window_box_width (w, TEXT_AREA);
1015 if (FRAME_WINDOW_P (f))
1017 if (!w->pseudo_window_p
1018 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
1019 && !WINDOW_RIGHTMOST_P (w)
1020 && (eabs (x - right_x) < grabbable_width))
1021 return ON_VERTICAL_BORDER;
1023 /* Need to say "x > right_x" rather than >=, since on character
1024 terminals, the vertical line's x coordinate is right_x. */
1025 else if (!w->pseudo_window_p
1026 && !WINDOW_RIGHTMOST_P (w)
1027 && x > right_x - ux)
1028 return ON_VERTICAL_BORDER;
1030 if (x < text_left)
1032 if (lmargin_width > 0
1033 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1034 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
1035 : (x < left_x + lmargin_width)))
1036 return ON_LEFT_MARGIN;
1038 return ON_LEFT_FRINGE;
1041 if (x >= text_right)
1043 if (rmargin_width > 0
1044 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1045 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
1046 : (x >= right_x - rmargin_width)))
1047 return ON_RIGHT_MARGIN;
1049 return ON_RIGHT_FRINGE;
1052 /* Everything special ruled out - must be on text area */
1053 return ON_TEXT;
1056 /* Take X is the frame-relative pixel x-coordinate, and return the
1057 x-coordinate relative to part PART of window W. */
1059 window_relative_x_coord (struct window *w, enum window_part part, int x)
1061 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
1063 switch (part)
1065 case ON_TEXT:
1066 return x - window_box_left (w, TEXT_AREA);
1068 case ON_LEFT_FRINGE:
1069 return x - left_x;
1071 case ON_RIGHT_FRINGE:
1072 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
1074 case ON_LEFT_MARGIN:
1075 return (x - left_x
1076 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1077 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
1079 case ON_RIGHT_MARGIN:
1080 return (x + 1
1081 - ((w->pseudo_window_p)
1082 ? WINDOW_TOTAL_WIDTH (w)
1083 : WINDOW_BOX_RIGHT_EDGE_X (w))
1084 + window_box_width (w, RIGHT_MARGIN_AREA)
1085 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1086 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
1089 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
1090 return 0;
1094 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
1095 Scoordinates_in_window_p, 2, 2, 0,
1096 doc: /* Return non-nil if COORDINATES are in WINDOW.
1097 COORDINATES is a cons of the form (X . Y), X and Y being distances
1098 measured in characters from the upper-left corner of the frame.
1099 \(0 . 0) denotes the character in the upper left corner of the
1100 frame.
1101 If COORDINATES are in the text portion of WINDOW,
1102 the coordinates relative to the window are returned.
1103 If they are in the mode line of WINDOW, `mode-line' is returned.
1104 If they are in the top mode line of WINDOW, `header-line' is returned.
1105 If they are in the left fringe of WINDOW, `left-fringe' is returned.
1106 If they are in the right fringe of WINDOW, `right-fringe' is returned.
1107 If they are on the border between WINDOW and its right sibling,
1108 `vertical-line' is returned.
1109 If they are in the windows's left or right marginal areas, `left-margin'\n\
1110 or `right-margin' is returned. */)
1111 (register Lisp_Object coordinates, Lisp_Object window)
1113 struct window *w;
1114 struct frame *f;
1115 int x, y;
1116 Lisp_Object lx, ly;
1118 CHECK_WINDOW (window);
1119 w = XWINDOW (window);
1120 f = XFRAME (w->frame);
1121 CHECK_CONS (coordinates);
1122 lx = Fcar (coordinates);
1123 ly = Fcdr (coordinates);
1124 CHECK_NUMBER_OR_FLOAT (lx);
1125 CHECK_NUMBER_OR_FLOAT (ly);
1126 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1127 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
1129 switch (coordinates_in_window (w, x, y))
1131 case ON_NOTHING:
1132 return Qnil;
1134 case ON_TEXT:
1135 /* Convert X and Y to window relative pixel coordinates, and
1136 return the canonical char units. */
1137 x -= window_box_left (w, TEXT_AREA);
1138 y -= WINDOW_TOP_EDGE_Y (w);
1139 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1140 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
1142 case ON_MODE_LINE:
1143 return Qmode_line;
1145 case ON_VERTICAL_BORDER:
1146 return Qvertical_line;
1148 case ON_HEADER_LINE:
1149 return Qheader_line;
1151 case ON_LEFT_FRINGE:
1152 return Qleft_fringe;
1154 case ON_RIGHT_FRINGE:
1155 return Qright_fringe;
1157 case ON_LEFT_MARGIN:
1158 return Qleft_margin;
1160 case ON_RIGHT_MARGIN:
1161 return Qright_margin;
1163 case ON_SCROLL_BAR:
1164 /* Historically we are supposed to return nil in this case. */
1165 return Qnil;
1167 default:
1168 abort ();
1173 /* Callback for foreach_window, used in window_from_coordinates.
1174 Check if window W contains coordinates specified by USER_DATA which
1175 is actually a pointer to a struct check_window_data CW.
1177 Check if window W contains coordinates *CW->x and *CW->y. If it
1178 does, return W in *CW->window, as Lisp_Object, and return in
1179 *CW->part the part of the window under coordinates *X,*Y. Return
1180 zero from this function to stop iterating over windows. */
1182 struct check_window_data
1184 Lisp_Object *window;
1185 int x, y;
1186 enum window_part *part;
1189 static int
1190 check_window_containing (struct window *w, void *user_data)
1192 struct check_window_data *cw = (struct check_window_data *) user_data;
1193 enum window_part found;
1194 int continue_p = 1;
1196 found = coordinates_in_window (w, cw->x, cw->y);
1197 if (found != ON_NOTHING)
1199 *cw->part = found;
1200 XSETWINDOW (*cw->window, w);
1201 continue_p = 0;
1204 return continue_p;
1208 /* Find the window containing frame-relative pixel position X/Y and
1209 return it as a Lisp_Object.
1211 If X, Y is on one of the window's special `window_part' elements,
1212 set *PART to the id of that element.
1214 If there is no window under X, Y return nil and leave *PART
1215 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1217 This function was previously implemented with a loop cycling over
1218 windows with Fnext_window, and starting with the frame's selected
1219 window. It turned out that this doesn't work with an
1220 implementation of next_window using Vwindow_list, because
1221 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1222 tree of F when this function is called asynchronously from
1223 note_mouse_highlight. The original loop didn't terminate in this
1224 case. */
1226 Lisp_Object
1227 window_from_coordinates (struct frame *f, int x, int y,
1228 enum window_part *part, int tool_bar_p)
1230 Lisp_Object window;
1231 struct check_window_data cw;
1232 enum window_part dummy;
1234 if (part == 0)
1235 part = &dummy;
1237 window = Qnil;
1238 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
1239 foreach_window (f, check_window_containing, &cw);
1241 /* If not found above, see if it's in the tool bar window, if a tool
1242 bar exists. */
1243 if (NILP (window)
1244 && tool_bar_p
1245 && WINDOWP (f->tool_bar_window)
1246 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1247 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
1248 != ON_NOTHING))
1250 *part = ON_TEXT;
1251 window = f->tool_bar_window;
1254 return window;
1257 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1258 doc: /* Return window containing coordinates X and Y on FRAME.
1259 FRAME must be a live frame and defaults to the selected one.
1260 The top left corner of the frame is considered to be row 0,
1261 column 0. */)
1262 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1264 struct frame *f;
1266 if (NILP (frame))
1267 frame = selected_frame;
1268 CHECK_LIVE_FRAME (frame);
1269 f = XFRAME (frame);
1271 /* Check that arguments are integers or floats. */
1272 CHECK_NUMBER_OR_FLOAT (x);
1273 CHECK_NUMBER_OR_FLOAT (y);
1275 return window_from_coordinates (f,
1276 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1277 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1278 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1279 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1280 0, 0);
1283 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1284 doc: /* Return current value of point in WINDOW.
1285 WINDOW must be a live window and defaults to the selected one.
1287 For a nonselected window, this is the value point would have
1288 if that window were selected.
1290 Note that, when WINDOW is the selected window and its buffer
1291 is also currently selected, the value returned is the same as (point).
1292 It would be more strictly correct to return the `top-level' value
1293 of point, outside of any save-excursion forms.
1294 But that is hard to define. */)
1295 (Lisp_Object window)
1297 register struct window *w = decode_window (window);
1299 if (w == XWINDOW (selected_window)
1300 && current_buffer == XBUFFER (w->buffer))
1301 return Fpoint ();
1302 return Fmarker_position (w->pointm);
1305 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1306 doc: /* Return position at which display currently starts in WINDOW.
1307 WINDOW must be a live window and defaults to the selected one.
1308 This is updated by redisplay or by calling `set-window-start'. */)
1309 (Lisp_Object window)
1311 return Fmarker_position (decode_window (window)->start);
1314 /* This is text temporarily removed from the doc string below.
1316 This function returns nil if the position is not currently known.
1317 That happens when redisplay is preempted and doesn't finish.
1318 If in that case you want to compute where the end of the window would
1319 have been if redisplay had finished, do this:
1320 (save-excursion
1321 (goto-char (window-start window))
1322 (vertical-motion (1- (window-height window)) window)
1323 (point))") */
1325 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1326 doc: /* Return position at which display currently ends in WINDOW.
1327 WINDOW must be a live window and defaults to the selected one.
1328 This is updated by redisplay, when it runs to completion.
1329 Simply changing the buffer text or setting `window-start'
1330 does not update this value.
1331 Return nil if there is no recorded value. \(This can happen if the
1332 last redisplay of WINDOW was preempted, and did not finish.)
1333 If UPDATE is non-nil, compute the up-to-date position
1334 if it isn't already recorded. */)
1335 (Lisp_Object window, Lisp_Object update)
1337 Lisp_Object value;
1338 struct window *w = decode_window (window);
1339 Lisp_Object buf;
1340 struct buffer *b;
1342 buf = w->buffer;
1343 CHECK_BUFFER (buf);
1344 b = XBUFFER (buf);
1346 #if 0 /* This change broke some things. We should make it later. */
1347 /* If we don't know the end position, return nil.
1348 The user can compute it with vertical-motion if he wants to.
1349 It would be nicer to do it automatically,
1350 but that's so slow that it would probably bother people. */
1351 if (NILP (w->window_end_valid))
1352 return Qnil;
1353 #endif
1355 if (! NILP (update)
1356 && ! (! NILP (w->window_end_valid)
1357 && XFASTINT (w->last_modified) >= BUF_MODIFF (b)
1358 && XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
1359 && !noninteractive)
1361 struct text_pos startp;
1362 struct it it;
1363 struct buffer *old_buffer = NULL;
1365 /* Cannot use Fvertical_motion because that function doesn't
1366 cope with variable-height lines. */
1367 if (b != current_buffer)
1369 old_buffer = current_buffer;
1370 set_buffer_internal (b);
1373 /* In case W->start is out of the range, use something
1374 reasonable. This situation occurred when loading a file with
1375 `-l' containing a call to `rmail' with subsequent other
1376 commands. At the end, W->start happened to be BEG, while
1377 rmail had already narrowed the buffer. */
1378 if (XMARKER (w->start)->charpos < BEGV)
1379 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1380 else if (XMARKER (w->start)->charpos > ZV)
1381 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1382 else
1383 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1385 start_display (&it, w, startp);
1386 move_it_vertically (&it, window_box_height (w));
1387 if (it.current_y < it.last_visible_y)
1388 move_it_past_eol (&it);
1389 value = make_number (IT_CHARPOS (it));
1391 if (old_buffer)
1392 set_buffer_internal (old_buffer);
1394 else
1395 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1397 return value;
1400 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1401 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1402 Return POS. */)
1403 (Lisp_Object window, Lisp_Object pos)
1405 register struct window *w = decode_window (window);
1407 CHECK_NUMBER_COERCE_MARKER (pos);
1408 if (w == XWINDOW (selected_window)
1409 && XBUFFER (w->buffer) == current_buffer)
1410 Fgoto_char (pos);
1411 else
1412 set_marker_restricted (w->pointm, pos, w->buffer);
1414 /* We have to make sure that redisplay updates the window to show
1415 the new value of point. */
1416 if (!EQ (window, selected_window))
1417 ++windows_or_buffers_changed;
1419 return pos;
1422 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1423 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1424 WINDOW defaults to the selected window. Return POS.
1425 Optional third arg NOFORCE non-nil inhibits next redisplay from
1426 overriding motion of point in order to display at this exact start. */)
1427 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1429 register struct window *w = decode_window (window);
1431 CHECK_NUMBER_COERCE_MARKER (pos);
1432 set_marker_restricted (w->start, pos, w->buffer);
1433 /* this is not right, but much easier than doing what is right. */
1434 w->start_at_line_beg = Qnil;
1435 if (NILP (noforce))
1436 w->force_start = Qt;
1437 w->update_mode_line = Qt;
1438 XSETFASTINT (w->last_modified, 0);
1439 XSETFASTINT (w->last_overlay_modified, 0);
1440 if (!EQ (window, selected_window))
1441 windows_or_buffers_changed++;
1443 return pos;
1446 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1447 Spos_visible_in_window_p, 0, 3, 0,
1448 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1449 Return nil if that position is scrolled vertically out of view.
1450 If a character is only partially visible, nil is returned, unless the
1451 optional argument PARTIALLY is non-nil.
1452 If POS is only out of view because of horizontal scrolling, return non-nil.
1453 If POS is t, it specifies the position of the last visible glyph in WINDOW.
1454 POS defaults to point in WINDOW; WINDOW defaults to the selected window.
1456 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
1457 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
1458 where X and Y are the pixel coordinates relative to the top left corner
1459 of the window. The remaining elements are omitted if the character after
1460 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1461 off-window at the top and bottom of the row, ROWH is the height of the
1462 display row, and VPOS is the row number (0-based) containing POS. */)
1463 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1465 register struct window *w;
1466 register EMACS_INT posint;
1467 register struct buffer *buf;
1468 struct text_pos top;
1469 Lisp_Object in_window = Qnil;
1470 int rtop, rbot, rowh, vpos, fully_p = 1;
1471 int x, y;
1473 w = decode_window (window);
1474 buf = XBUFFER (w->buffer);
1475 SET_TEXT_POS_FROM_MARKER (top, w->start);
1477 if (EQ (pos, Qt))
1478 posint = -1;
1479 else if (!NILP (pos))
1481 CHECK_NUMBER_COERCE_MARKER (pos);
1482 posint = XINT (pos);
1484 else if (w == XWINDOW (selected_window))
1485 posint = PT;
1486 else
1487 posint = XMARKER (w->pointm)->charpos;
1489 /* If position is above window start or outside buffer boundaries,
1490 or if window start is out of range, position is not visible. */
1491 if ((EQ (pos, Qt)
1492 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
1493 && CHARPOS (top) >= BUF_BEGV (buf)
1494 && CHARPOS (top) <= BUF_ZV (buf)
1495 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
1496 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
1497 in_window = Qt;
1499 if (!NILP (in_window) && !NILP (partially))
1501 Lisp_Object part = Qnil;
1502 if (!fully_p)
1503 part = list4 (make_number (rtop), make_number (rbot),
1504 make_number (rowh), make_number (vpos));
1505 in_window = Fcons (make_number (x),
1506 Fcons (make_number (y), part));
1509 return in_window;
1512 DEFUN ("window-line-height", Fwindow_line_height,
1513 Swindow_line_height, 0, 2, 0,
1514 doc: /* Return height in pixels of text line LINE in window WINDOW.
1515 WINDOW defaults to the selected window.
1517 Return height of current line if LINE is omitted or nil. Return height of
1518 header or mode line if LINE is `header-line' or `mode-line'.
1519 Otherwise, LINE is a text line number starting from 0. A negative number
1520 counts from the end of the window.
1522 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
1523 in pixels of the visible part of the line, VPOS and YPOS are the
1524 vertical position in lines and pixels of the line, relative to the top
1525 of the first text line, and OFFBOT is the number of off-window pixels at
1526 the bottom of the text line. If there are off-window pixels at the top
1527 of the (first) text line, YPOS is negative.
1529 Return nil if window display is not up-to-date. In that case, use
1530 `pos-visible-in-window-p' to obtain the information. */)
1531 (Lisp_Object line, Lisp_Object window)
1533 register struct window *w;
1534 register struct buffer *b;
1535 struct glyph_row *row, *end_row;
1536 int max_y, crop, i, n;
1538 w = decode_window (window);
1540 if (noninteractive || w->pseudo_window_p)
1541 return Qnil;
1543 CHECK_BUFFER (w->buffer);
1544 b = XBUFFER (w->buffer);
1546 /* Fail if current matrix is not up-to-date. */
1547 if (NILP (w->window_end_valid)
1548 || current_buffer->clip_changed
1549 || current_buffer->prevent_redisplay_optimizations_p
1550 || XFASTINT (w->last_modified) < BUF_MODIFF (b)
1551 || XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
1552 return Qnil;
1554 if (NILP (line))
1556 i = w->cursor.vpos;
1557 if (i < 0 || i >= w->current_matrix->nrows
1558 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
1559 return Qnil;
1560 max_y = window_text_bottom_y (w);
1561 goto found_row;
1564 if (EQ (line, Qheader_line))
1566 if (!WINDOW_WANTS_HEADER_LINE_P (w))
1567 return Qnil;
1568 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1569 if (!row->enabled_p)
1570 return Qnil;
1571 return list4 (make_number (row->height),
1572 make_number (0), make_number (0),
1573 make_number (0));
1576 if (EQ (line, Qmode_line))
1578 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1579 if (!row->enabled_p)
1580 return Qnil;
1581 return list4 (make_number (row->height),
1582 make_number (0), /* not accurate */
1583 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
1584 + window_text_bottom_y (w)),
1585 make_number (0));
1588 CHECK_NUMBER (line);
1589 n = XINT (line);
1591 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1592 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
1593 max_y = window_text_bottom_y (w);
1594 i = 0;
1596 while ((n < 0 || i < n)
1597 && row <= end_row && row->enabled_p
1598 && row->y + row->height < max_y)
1599 row++, i++;
1601 if (row > end_row || !row->enabled_p)
1602 return Qnil;
1604 if (++n < 0)
1606 if (-n > i)
1607 return Qnil;
1608 row += n;
1609 i += n;
1612 found_row:
1613 crop = max (0, (row->y + row->height) - max_y);
1614 return list4 (make_number (row->height + min (0, row->y) - crop),
1615 make_number (i),
1616 make_number (row->y),
1617 make_number (crop));
1620 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1621 0, 1, 0,
1622 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1623 More precisely, return the value assigned by the last call of
1624 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1625 never called with WINDOW as its argument, or the value set by that
1626 function was internally reset since its last call. WINDOW defaults to
1627 the selected window.
1629 When a window is dedicated to its buffer, `display-buffer' will refrain
1630 from displaying another buffer in it. `get-lru-window' and
1631 `get-largest-window' treat dedicated windows specially.
1632 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1633 `kill-buffer' can delete a dedicated window and the containing frame.
1635 Functions like `set-window-buffer' may change the buffer displayed by a
1636 window, unless that window is "strongly" dedicated to its buffer, that
1637 is the value returned by `window-dedicated-p' is t. */)
1638 (Lisp_Object window)
1640 return decode_window (window)->dedicated;
1643 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1644 Sset_window_dedicated_p, 2, 2, 0,
1645 doc: /* Mark WINDOW as dedicated according to FLAG.
1646 WINDOW must be a live window and defaults to the selected one. FLAG
1647 non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
1648 mark WINDOW as non-dedicated. Return FLAG.
1650 When a window is dedicated to its buffer, `display-buffer' will refrain
1651 from displaying another buffer in it. `get-lru-window' and
1652 `get-largest-window' treat dedicated windows specially.
1653 `delete-windows-on', `replace-buffer-in-windows', `quit-window',
1654 `quit-restore-window' and `kill-buffer' can delete a dedicated window
1655 and the containing frame.
1657 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1658 its buffer. Functions like `set-window-buffer' may change the buffer
1659 displayed by a window, unless that window is strongly dedicated to its
1660 buffer. If and when `set-window-buffer' displays another buffer in a
1661 window, it also makes sure that the window is no more dedicated. */)
1662 (Lisp_Object window, Lisp_Object flag)
1664 register struct window *w = decode_window (window);
1666 w->dedicated = flag;
1667 return w->dedicated;
1670 DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
1671 0, 1, 0,
1672 doc: /* Return buffers previously shown in WINDOW.
1673 WINDOW must be a live window and defaults to the selected one.
1675 The return value is either nil or a list of <buffer, window-start,
1676 window-point> triples where buffer was previously shown in WINDOW. */)
1677 (Lisp_Object window)
1679 return decode_window (window)->prev_buffers;
1682 DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
1683 Sset_window_prev_buffers, 2, 2, 0,
1684 doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
1685 WINDOW must be a live window and defaults to the selected one. Return
1686 PREV-BUFFERS.
1688 PREV-BUFFERS should be either nil or a list of <buffer, window-start,
1689 window-point> triples where buffer was previously shown in WINDOW. */)
1690 (Lisp_Object window, Lisp_Object prev_buffers)
1692 return decode_any_window (window)->prev_buffers = prev_buffers;
1695 DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
1696 0, 1, 0,
1697 doc: /* Return list of buffers recently re-shown in WINDOW.
1698 WINDOW must be a live window and defaults to the selected one. */)
1699 (Lisp_Object window)
1701 return decode_window (window)->next_buffers;
1704 DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
1705 Sset_window_next_buffers, 2, 2, 0,
1706 doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
1707 WINDOW must be a live window and defaults to the selected one. Return
1708 NEXT-BUFFERS.
1710 NEXT-BUFFERS should be either nil or a list of buffers that have been
1711 recently re-shown in WINDOW. */)
1712 (Lisp_Object window, Lisp_Object next_buffers)
1714 return decode_any_window (window)->next_buffers = next_buffers;
1717 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1718 0, 1, 0,
1719 doc: /* Return the parameters of WINDOW and their values.
1720 WINDOW defaults to the selected window. The return value is a list of
1721 elements of the form (PARAMETER . VALUE). */)
1722 (Lisp_Object window)
1724 return Fcopy_alist (decode_any_window (window)->window_parameters);
1727 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1728 2, 2, 0,
1729 doc: /* Return WINDOW's value for PARAMETER.
1730 WINDOW defaults to the selected window. */)
1731 (Lisp_Object window, Lisp_Object parameter)
1733 Lisp_Object result;
1735 result = Fassq (parameter, decode_any_window (window)->window_parameters);
1736 return CDR_SAFE (result);
1739 DEFUN ("set-window-parameter", Fset_window_parameter,
1740 Sset_window_parameter, 3, 3, 0,
1741 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1742 WINDOW defaults to the selected window. Return VALUE. */)
1743 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
1745 register struct window *w = decode_any_window (window);
1746 Lisp_Object old_alist_elt;
1748 old_alist_elt = Fassq (parameter, w->window_parameters);
1749 if (NILP (old_alist_elt))
1750 w->window_parameters = Fcons (Fcons (parameter, value), w->window_parameters);
1751 else
1752 Fsetcdr (old_alist_elt, value);
1753 return value;
1756 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1757 0, 1, 0,
1758 doc: /* Return the display-table that WINDOW is using.
1759 WINDOW defaults to the selected window. */)
1760 (Lisp_Object window)
1762 return decode_window (window)->display_table;
1765 /* Get the display table for use on window W. This is either W's
1766 display table or W's buffer's display table. Ignore the specified
1767 tables if they are not valid; if no valid table is specified,
1768 return 0. */
1770 struct Lisp_Char_Table *
1771 window_display_table (struct window *w)
1773 struct Lisp_Char_Table *dp = NULL;
1775 if (DISP_TABLE_P (w->display_table))
1776 dp = XCHAR_TABLE (w->display_table);
1777 else if (BUFFERP (w->buffer))
1779 struct buffer *b = XBUFFER (w->buffer);
1781 if (DISP_TABLE_P (BVAR (b, display_table)))
1782 dp = XCHAR_TABLE (BVAR (b, display_table));
1783 else if (DISP_TABLE_P (Vstandard_display_table))
1784 dp = XCHAR_TABLE (Vstandard_display_table);
1787 return dp;
1790 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1791 doc: /* Set WINDOW's display-table to TABLE. */)
1792 (register Lisp_Object window, Lisp_Object table)
1794 register struct window *w;
1796 w = decode_window (window);
1797 w->display_table = table;
1798 return table;
1801 /* Record info on buffer window W is displaying
1802 when it is about to cease to display that buffer. */
1803 static void
1804 unshow_buffer (register struct window *w)
1806 Lisp_Object buf;
1807 struct buffer *b;
1809 buf = w->buffer;
1810 b = XBUFFER (buf);
1811 if (b != XMARKER (w->pointm)->buffer)
1812 abort ();
1814 #if 0
1815 if (w == XWINDOW (selected_window)
1816 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1817 /* Do this except when the selected window's buffer
1818 is being removed from some other window. */
1819 #endif
1820 /* last_window_start records the start position that this buffer
1821 had in the last window to be disconnected from it.
1822 Now that this statement is unconditional,
1823 it is possible for the buffer to be displayed in the
1824 selected window, while last_window_start reflects another
1825 window which was recently showing the same buffer.
1826 Some people might say that might be a good thing. Let's see. */
1827 b->last_window_start = marker_position (w->start);
1829 /* Point in the selected window's buffer
1830 is actually stored in that buffer, and the window's pointm isn't used.
1831 So don't clobber point in that buffer. */
1832 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1833 /* This line helps to fix Horsley's testbug.el bug. */
1834 && !(WINDOWP (BVAR (b, last_selected_window))
1835 && w != XWINDOW (BVAR (b, last_selected_window))
1836 && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->buffer)))
1837 temp_set_point_both (b,
1838 clip_to_bounds (BUF_BEGV (b),
1839 XMARKER (w->pointm)->charpos,
1840 BUF_ZV (b)),
1841 clip_to_bounds (BUF_BEGV_BYTE (b),
1842 marker_byte_position (w->pointm),
1843 BUF_ZV_BYTE (b)));
1845 if (WINDOWP (BVAR (b, last_selected_window))
1846 && w == XWINDOW (BVAR (b, last_selected_window)))
1847 BVAR (b, last_selected_window) = Qnil;
1850 /* Put NEW into the window structure in place of OLD. SETFLAG zero
1851 means change window structure only. Otherwise store geometry and
1852 other settings as well. */
1853 static void
1854 replace_window (Lisp_Object old, Lisp_Object new, int setflag)
1856 register Lisp_Object tem;
1857 register struct window *o = XWINDOW (old), *n = XWINDOW (new);
1859 /* If OLD is its frame's root window, then NEW is the new
1860 root window for that frame. */
1861 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1862 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = new;
1864 if (setflag)
1866 n->left_col = o->left_col;
1867 n->top_line = o->top_line;
1868 n->total_cols = o->total_cols;
1869 n->total_lines = o->total_lines;
1870 n->normal_cols = o->normal_cols;
1871 o->normal_cols = make_float (1.0);
1872 n->normal_lines = o->normal_lines;
1873 o->normal_lines = make_float (1.0);
1874 n->desired_matrix = n->current_matrix = 0;
1875 n->vscroll = 0;
1876 memset (&n->cursor, 0, sizeof (n->cursor));
1877 memset (&n->last_cursor, 0, sizeof (n->last_cursor));
1878 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
1879 n->phys_cursor_type = -1;
1880 n->phys_cursor_width = -1;
1881 n->must_be_updated_p = 0;
1882 n->pseudo_window_p = 0;
1883 XSETFASTINT (n->window_end_vpos, 0);
1884 XSETFASTINT (n->window_end_pos, 0);
1885 n->window_end_valid = Qnil;
1886 n->frozen_window_start_p = 0;
1889 n->next = tem = o->next;
1890 if (!NILP (tem))
1891 XWINDOW (tem)->prev = new;
1893 n->prev = tem = o->prev;
1894 if (!NILP (tem))
1895 XWINDOW (tem)->next = new;
1897 n->parent = tem = o->parent;
1898 if (!NILP (tem))
1900 if (EQ (XWINDOW (tem)->vchild, old))
1901 XWINDOW (tem)->vchild = new;
1902 if (EQ (XWINDOW (tem)->hchild, old))
1903 XWINDOW (tem)->hchild = new;
1907 /* If window WINDOW and its parent window are iso-combined, merge
1908 WINDOW's children into those of its parent window and mark WINDOW as
1909 deleted. */
1911 static void
1912 recombine_windows (Lisp_Object window)
1914 struct window *w, *p, *c;
1915 Lisp_Object parent, child;
1916 int horflag;
1918 w = XWINDOW (window);
1919 parent = w->parent;
1920 if (!NILP (parent) && NILP (w->nest))
1922 p = XWINDOW (parent);
1923 if (((!NILP (p->vchild) && !NILP (w->vchild))
1924 || (!NILP (p->hchild) && !NILP (w->hchild))))
1925 /* WINDOW and PARENT are both either a vertical or a horizontal
1926 combination. */
1928 horflag = NILP (w->vchild);
1929 child = horflag ? w->hchild : w->vchild;
1930 c = XWINDOW (child);
1932 /* Splice WINDOW's children into its parent's children and
1933 assign new normal sizes. */
1934 if (NILP (w->prev))
1935 if (horflag)
1936 p->hchild = child;
1937 else
1938 p->vchild = child;
1939 else
1941 c->prev = w->prev;
1942 XWINDOW (w->prev)->next = child;
1945 while (c)
1947 c->parent = parent;
1949 if (horflag)
1950 c->normal_cols
1951 = make_float (XFLOATINT (c->total_cols)
1952 / XFLOATINT (p->total_cols));
1953 else
1954 c->normal_lines
1955 = make_float (XFLOATINT (c->total_lines)
1956 / XFLOATINT (p->total_lines));
1958 if (NILP (c->next))
1960 if (!NILP (w->next))
1962 c->next = w->next;
1963 XWINDOW (c->next)->prev = child;
1966 c = 0;
1968 else
1970 child = c->next;
1971 c = XWINDOW (child);
1975 /* WINDOW can be deleted now. */
1976 w->vchild = w->hchild = Qnil;
1981 /* If WINDOW can be deleted, delete it. */
1982 Lisp_Object
1983 delete_deletable_window (Lisp_Object window)
1985 if (!NILP (call1 (Qwindow_deletable_p, window)))
1986 call1 (Qdelete_window, window);
1989 /***********************************************************************
1990 Window List
1991 ***********************************************************************/
1993 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
1994 pointer. This is a callback function for foreach_window, used in
1995 the window_list function. */
1997 static int
1998 add_window_to_list (struct window *w, void *user_data)
2000 Lisp_Object *list = (Lisp_Object *) user_data;
2001 Lisp_Object window;
2002 XSETWINDOW (window, w);
2003 *list = Fcons (window, *list);
2004 return 1;
2008 /* Return a list of all windows, for use by next_window. If
2009 Vwindow_list is a list, return that list. Otherwise, build a new
2010 list, cache it in Vwindow_list, and return that. */
2012 static Lisp_Object
2013 window_list (void)
2015 if (!CONSP (Vwindow_list))
2017 Lisp_Object tail;
2019 Vwindow_list = Qnil;
2020 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
2022 Lisp_Object args[2];
2024 /* We are visiting windows in canonical order, and add
2025 new windows at the front of args[1], which means we
2026 have to reverse this list at the end. */
2027 args[1] = Qnil;
2028 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
2029 args[0] = Vwindow_list;
2030 args[1] = Fnreverse (args[1]);
2031 Vwindow_list = Fnconc (2, args);
2035 return Vwindow_list;
2039 /* Value is non-zero if WINDOW satisfies the constraints given by
2040 OWINDOW, MINIBUF and ALL_FRAMES.
2042 MINIBUF t means WINDOW may be minibuffer windows.
2043 `lambda' means WINDOW may not be a minibuffer window.
2044 a window means a specific minibuffer window
2046 ALL_FRAMES t means search all frames,
2047 nil means search just current frame,
2048 `visible' means search just visible frames on the
2049 current terminal,
2050 0 means search visible and iconified frames on the
2051 current terminal,
2052 a window means search the frame that window belongs to,
2053 a frame means consider windows on that frame, only. */
2055 static int
2056 candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf, Lisp_Object all_frames)
2058 struct window *w = XWINDOW (window);
2059 struct frame *f = XFRAME (w->frame);
2060 int candidate_p = 1;
2062 if (!BUFFERP (w->buffer))
2063 candidate_p = 0;
2064 else if (MINI_WINDOW_P (w)
2065 && (EQ (minibuf, Qlambda)
2066 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
2068 /* If MINIBUF is `lambda' don't consider any mini-windows.
2069 If it is a window, consider only that one. */
2070 candidate_p = 0;
2072 else if (EQ (all_frames, Qt))
2073 candidate_p = 1;
2074 else if (NILP (all_frames))
2076 xassert (WINDOWP (owindow));
2077 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
2079 else if (EQ (all_frames, Qvisible))
2081 FRAME_SAMPLE_VISIBILITY (f);
2082 candidate_p = FRAME_VISIBLE_P (f)
2083 && (FRAME_TERMINAL (XFRAME (w->frame))
2084 == FRAME_TERMINAL (XFRAME (selected_frame)));
2087 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2089 FRAME_SAMPLE_VISIBILITY (f);
2090 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2091 #ifdef HAVE_X_WINDOWS
2092 /* Yuck!! If we've just created the frame and the
2093 window-manager requested the user to place it
2094 manually, the window may still not be considered
2095 `visible'. I'd argue it should be at least
2096 something like `iconified', but don't know how to do
2097 that yet. --Stef */
2098 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
2099 && !f->output_data.x->has_been_visible)
2100 #endif
2102 && (FRAME_TERMINAL (XFRAME (w->frame))
2103 == FRAME_TERMINAL (XFRAME (selected_frame)));
2105 else if (WINDOWP (all_frames))
2106 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
2107 || EQ (XWINDOW (all_frames)->frame, w->frame)
2108 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
2109 else if (FRAMEP (all_frames))
2110 candidate_p = EQ (all_frames, w->frame);
2112 return candidate_p;
2116 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
2117 Fwindow_list. See candidate_window_p for the meaning of WINDOW,
2118 MINIBUF, and ALL_FRAMES. */
2120 static void
2121 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
2123 if (NILP (*window))
2124 *window = selected_window;
2125 else
2126 CHECK_LIVE_WINDOW (*window);
2128 /* MINIBUF nil may or may not include minibuffers. Decide if it
2129 does. */
2130 if (NILP (*minibuf))
2131 *minibuf = minibuf_level ? minibuf_window : Qlambda;
2132 else if (!EQ (*minibuf, Qt))
2133 *minibuf = Qlambda;
2135 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
2136 => count none of them, or a specific minibuffer window (the
2137 active one) to count. */
2139 /* ALL_FRAMES nil doesn't specify which frames to include. */
2140 if (NILP (*all_frames))
2141 *all_frames = (!EQ (*minibuf, Qlambda)
2142 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
2143 : Qnil);
2144 else if (EQ (*all_frames, Qvisible))
2146 else if (EQ (*all_frames, make_number (0)))
2148 else if (FRAMEP (*all_frames))
2150 else if (!EQ (*all_frames, Qt))
2151 *all_frames = Qnil;
2155 /* Return the next or previous window of WINDOW in cyclic ordering
2156 of windows. NEXT_P non-zero means return the next window. See the
2157 documentation string of next-window for the meaning of MINIBUF and
2158 ALL_FRAMES. */
2160 static Lisp_Object
2161 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
2163 decode_next_window_args (&window, &minibuf, &all_frames);
2165 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
2166 return the first window on the frame. */
2167 if (FRAMEP (all_frames)
2168 && !EQ (all_frames, XWINDOW (window)->frame))
2169 return Fframe_first_window (all_frames);
2171 if (next_p)
2173 Lisp_Object list;
2175 /* Find WINDOW in the list of all windows. */
2176 list = Fmemq (window, window_list ());
2178 /* Scan forward from WINDOW to the end of the window list. */
2179 if (CONSP (list))
2180 for (list = XCDR (list); CONSP (list); list = XCDR (list))
2181 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2182 break;
2184 /* Scan from the start of the window list up to WINDOW. */
2185 if (!CONSP (list))
2186 for (list = Vwindow_list;
2187 CONSP (list) && !EQ (XCAR (list), window);
2188 list = XCDR (list))
2189 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2190 break;
2192 if (CONSP (list))
2193 window = XCAR (list);
2195 else
2197 Lisp_Object candidate, list;
2199 /* Scan through the list of windows for candidates. If there are
2200 candidate windows in front of WINDOW, the last one of these
2201 is the one we want. If there are candidates following WINDOW
2202 in the list, again the last one of these is the one we want. */
2203 candidate = Qnil;
2204 for (list = window_list (); CONSP (list); list = XCDR (list))
2206 if (EQ (XCAR (list), window))
2208 if (WINDOWP (candidate))
2209 break;
2211 else if (candidate_window_p (XCAR (list), window, minibuf,
2212 all_frames))
2213 candidate = XCAR (list);
2216 if (WINDOWP (candidate))
2217 window = candidate;
2220 return window;
2224 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2225 doc: /* Return window following WINDOW in cyclic ordering of windows.
2226 WINDOW must be a live window and defaults to the selected one. The
2227 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2228 consider.
2230 MINIBUF nil or omitted means consider the minibuffer window only if the
2231 minibuffer is active. MINIBUF t means consider the minibuffer window
2232 even if the minibuffer is not active. Any other value means do not
2233 consider the minibuffer window even if the minibuffer is active.
2235 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2236 plus the minibuffer window if specified by the MINIBUF argument. If the
2237 minibuffer counts, consider all windows on all frames that share that
2238 minibuffer too. The following non-nil values of ALL-FRAMES have special
2239 meanings:
2241 - t means consider all windows on all existing frames.
2243 - `visible' means consider all windows on all visible frames.
2245 - 0 (the number zero) means consider all windows on all visible and
2246 iconified frames.
2248 - A frame means consider all windows on that frame only.
2250 Anything else means consider all windows on WINDOW's frame and no
2251 others.
2253 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2254 `next-window' to iterate through the entire cycle of acceptable
2255 windows, eventually ending up back at the window you started with.
2256 `previous-window' traverses the same cycle, in the reverse order. */)
2257 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2259 return next_window (window, minibuf, all_frames, 1);
2263 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2264 doc: /* Return window preceding WINDOW in cyclic ordering of windows.
2265 WINDOW must be a live window and defaults to the selected one. The
2266 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2267 consider.
2269 MINIBUF nil or omitted means consider the minibuffer window only if the
2270 minibuffer is active. MINIBUF t means consider the minibuffer window
2271 even if the minibuffer is not active. Any other value means do not
2272 consider the minibuffer window even if the minibuffer is active.
2274 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2275 plus the minibuffer window if specified by the MINIBUF argument. If the
2276 minibuffer counts, consider all windows on all frames that share that
2277 minibuffer too. The following non-nil values of ALL-FRAMES have special
2278 meanings:
2280 - t means consider all windows on all existing frames.
2282 - `visible' means consider all windows on all visible frames.
2284 - 0 (the number zero) means consider all windows on all visible and
2285 iconified frames.
2287 - A frame means consider all windows on that frame only.
2289 Anything else means consider all windows on WINDOW's frame and no
2290 others.
2292 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2293 use `previous-window' to iterate through the entire cycle of
2294 acceptable windows, eventually ending up back at the window you
2295 started with. `next-window' traverses the same cycle, in the
2296 reverse order. */)
2297 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2299 return next_window (window, minibuf, all_frames, 0);
2303 /* Return a list of windows in cyclic ordering. Arguments are like
2304 for `next-window'. */
2306 static Lisp_Object
2307 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2309 Lisp_Object tail, list, rest;
2311 decode_next_window_args (&window, &minibuf, &all_frames);
2312 list = Qnil;
2314 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2315 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2316 list = Fcons (XCAR (tail), list);
2318 /* Rotate the list to start with WINDOW. */
2319 list = Fnreverse (list);
2320 rest = Fmemq (window, list);
2321 if (!NILP (rest) && !EQ (rest, list))
2323 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2325 XSETCDR (tail, Qnil);
2326 list = nconc2 (rest, list);
2328 return list;
2332 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2333 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2334 FRAME nil or omitted means use the selected frame.
2335 WINDOW nil or omitted means use the selected window.
2336 MINIBUF t means include the minibuffer window, even if it isn't active.
2337 MINIBUF nil or omitted means include the minibuffer window only
2338 if it's active.
2339 MINIBUF neither nil nor t means never include the minibuffer window. */)
2340 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2342 if (NILP (window))
2343 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2344 CHECK_WINDOW (window);
2345 if (NILP (frame))
2346 frame = selected_frame;
2348 if (!EQ (frame, XWINDOW (window)->frame))
2349 error ("Window is on a different frame");
2351 return window_list_1 (window, minibuf, frame);
2355 DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2356 doc: /* Return a list of all live windows.
2357 WINDOW specifies the first window to list and defaults to the selected
2358 window.
2360 Optional argument MINIBUF nil or omitted means consider the minibuffer
2361 window only if the minibuffer is active. MINIBUF t means consider the
2362 minibuffer window even if the minibuffer is not active. Any other value
2363 means do not consider the minibuffer window even if the minibuffer is
2364 active.
2366 Optional argument ALL-FRAMES nil or omitted means consider all windows
2367 on WINDOW's frame, plus the minibuffer window if specified by the
2368 MINIBUF argument. If the minibuffer counts, consider all windows on all
2369 frames that share that minibuffer too. The following non-nil values of
2370 ALL-FRAMES have special meanings:
2372 - t means consider all windows on all existing frames.
2374 - `visible' means consider all windows on all visible frames.
2376 - 0 (the number zero) means consider all windows on all visible and
2377 iconified frames.
2379 - A frame means consider all windows on that frame only.
2381 Anything else means consider all windows on WINDOW's frame and no
2382 others.
2384 If WINDOW is not on the list of windows returned, some other window will
2385 be listed first but no error is signalled. */)
2386 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2388 return window_list_1 (window, minibuf, all_frames);
2391 /* Look at all windows, performing an operation specified by TYPE
2392 with argument OBJ.
2393 If FRAMES is Qt, look at all frames;
2394 Qnil, look at just the selected frame;
2395 Qvisible, look at visible frames;
2396 a frame, just look at windows on that frame.
2397 If MINI is non-zero, perform the operation on minibuffer windows too. */
2399 enum window_loop
2401 WINDOW_LOOP_UNUSED,
2402 GET_BUFFER_WINDOW, /* Arg is buffer */
2403 REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
2404 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2405 CHECK_ALL_WINDOWS
2408 static Lisp_Object
2409 window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
2411 Lisp_Object window, windows, best_window, frame_arg;
2412 int frame_best_window_flag = 0;
2413 struct frame *f;
2414 struct gcpro gcpro1;
2416 /* If we're only looping through windows on a particular frame,
2417 frame points to that frame. If we're looping through windows
2418 on all frames, frame is 0. */
2419 if (FRAMEP (frames))
2420 f = XFRAME (frames);
2421 else if (NILP (frames))
2422 f = SELECTED_FRAME ();
2423 else
2424 f = NULL;
2426 if (f)
2427 frame_arg = Qlambda;
2428 else if (EQ (frames, make_number (0)))
2429 frame_arg = frames;
2430 else if (EQ (frames, Qvisible))
2431 frame_arg = frames;
2432 else
2433 frame_arg = Qt;
2435 /* frame_arg is Qlambda to stick to one frame,
2436 Qvisible to consider all visible frames,
2437 or Qt otherwise. */
2439 /* Pick a window to start with. */
2440 if (WINDOWP (obj))
2441 window = obj;
2442 else if (f)
2443 window = FRAME_SELECTED_WINDOW (f);
2444 else
2445 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2447 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2448 GCPRO1 (windows);
2449 best_window = Qnil;
2451 for (; CONSP (windows); windows = XCDR (windows))
2453 struct window *w;
2455 window = XCAR (windows);
2456 w = XWINDOW (window);
2458 /* Note that we do not pay attention here to whether the frame
2459 is visible, since Fwindow_list skips non-visible frames if
2460 that is desired, under the control of frame_arg. */
2461 if (!MINI_WINDOW_P (w)
2462 /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
2463 consider all windows. */
2464 || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
2465 || (mini && minibuf_level > 0))
2466 switch (type)
2468 case GET_BUFFER_WINDOW:
2469 if (EQ (w->buffer, obj)
2470 /* Don't find any minibuffer window except the one that
2471 is currently in use. */
2472 && (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
2474 if (EQ (window, selected_window))
2475 /* Preferably return the selected window. */
2476 RETURN_UNGCPRO (window);
2477 else if (EQ (XWINDOW (window)->frame, selected_frame)
2478 && !frame_best_window_flag)
2479 /* Prefer windows on the current frame (but don't
2480 choose another one if we have one already). */
2482 best_window = window;
2483 frame_best_window_flag = 1;
2485 else if (NILP (best_window))
2486 best_window = window;
2488 break;
2490 case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
2491 /* We could simply check whether the buffer shown by window
2492 is live, and show another buffer in case it isn't. */
2493 if (EQ (w->buffer, obj))
2495 /* Undedicate WINDOW. */
2496 w->dedicated = Qnil;
2497 /* Make WINDOW show the buffer returned by
2498 other_buffer_safely, don't run any hooks. */
2499 set_window_buffer
2500 (window, other_buffer_safely (w->buffer), 0, 0);
2501 /* If WINDOW is the selected window, make its buffer
2502 current. But do so only if the window shows the
2503 current buffer (Bug#6454). */
2504 if (EQ (window, selected_window)
2505 && XBUFFER (w->buffer) == current_buffer)
2506 Fset_buffer (w->buffer);
2508 break;
2510 case REDISPLAY_BUFFER_WINDOWS:
2511 if (EQ (w->buffer, obj))
2513 mark_window_display_accurate (window, 0);
2514 w->update_mode_line = Qt;
2515 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2516 ++update_mode_lines;
2517 best_window = window;
2519 break;
2521 /* Check for a window that has a killed buffer. */
2522 case CHECK_ALL_WINDOWS:
2523 if (! NILP (w->buffer)
2524 && NILP (BVAR (XBUFFER (w->buffer), name)))
2525 abort ();
2526 break;
2528 case WINDOW_LOOP_UNUSED:
2529 break;
2533 UNGCPRO;
2534 return best_window;
2537 /* Used for debugging. Abort if any window has a dead buffer. */
2539 extern void check_all_windows (void) EXTERNALLY_VISIBLE;
2540 void
2541 check_all_windows (void)
2543 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2546 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2547 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2548 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
2549 the current buffer.
2551 The optional argument ALL-FRAMES specifies the frames to consider:
2553 - t means consider all windows on all existing frames.
2555 - `visible' means consider all windows on all visible frames.
2557 - 0 (the number zero) means consider all windows on all visible
2558 and iconified frames.
2560 - A frame means consider all windows on that frame only.
2562 Any other value of ALL-FRAMES means consider all windows on the
2563 selected frame and no others. */)
2564 (Lisp_Object buffer_or_name, Lisp_Object all_frames)
2566 Lisp_Object buffer;
2568 if (NILP (buffer_or_name))
2569 buffer = Fcurrent_buffer ();
2570 else
2571 buffer = Fget_buffer (buffer_or_name);
2573 if (BUFFERP (buffer))
2574 return window_loop (GET_BUFFER_WINDOW, buffer, 1, all_frames);
2575 else
2576 return Qnil;
2579 Lisp_Object
2580 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore)
2582 return call4 (Qresize_root_window, window, delta, horizontal, ignore);
2586 DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
2587 Sdelete_other_windows_internal, 0, 2, "",
2588 doc: /* Make WINDOW fill its frame.
2589 Only the frame WINDOW is on is affected. WINDOW may be any window and
2590 defaults to the selected one.
2592 Optional argument ROOT, if non-nil, must specify an internal window
2593 containing WINDOW as a subwindow. If this is the case, replace ROOT by
2594 WINDOW and leave alone any windows not contained in ROOT.
2596 When WINDOW is live try to reduce display jumps by keeping the text
2597 previously visible in WINDOW in the same place on the frame. Doing this
2598 depends on the value of (window-start WINDOW), so if calling this
2599 function in a program gives strange scrolling, make sure the
2600 window-start value is reasonable when this function is called. */)
2601 (Lisp_Object window, Lisp_Object root)
2603 struct window *w, *r, *s;
2604 struct frame *f;
2605 Lisp_Object sibling, pwindow, swindow, delta;
2606 EMACS_INT startpos;
2607 int top, new_top, resize_failed;
2609 w = decode_any_window (window);
2610 XSETWINDOW (window, w);
2611 f = XFRAME (w->frame);
2613 if (NILP (root))
2614 /* ROOT is the frame's root window. */
2616 root = FRAME_ROOT_WINDOW (f);
2617 r = XWINDOW (root);
2619 else
2620 /* ROOT must be an ancestor of WINDOW. */
2622 r = decode_any_window (root);
2623 pwindow = XWINDOW (window)->parent;
2624 while (!NILP (pwindow))
2625 if (EQ (pwindow, root))
2626 break;
2627 else
2628 pwindow = XWINDOW (pwindow)->parent;
2629 if (!EQ (pwindow, root))
2630 error ("Specified root is not an ancestor of specified window");
2633 if (EQ (window, root))
2634 /* A noop. */
2635 return Qnil;
2636 /* I don't understand the "top > 0" part below. If we deal with a
2637 standalone minibuffer it would have been caught by the preceding
2638 test. */
2639 else if (MINI_WINDOW_P (w)) /* && top > 0) */
2640 error ("Can't expand minibuffer to full frame");
2642 if (!NILP (w->buffer))
2644 startpos = marker_position (w->start);
2645 top = WINDOW_TOP_EDGE_LINE (w)
2646 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2647 /* Make sure WINDOW is the frame's selected window. */
2648 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
2650 if (EQ (selected_frame, w->frame))
2651 Fselect_window (window, Qnil);
2652 else
2653 FRAME_SELECTED_WINDOW (f) = window;
2656 else
2658 /* See if the frame's selected window is a subwindow of WINDOW, by
2659 finding all the selected window's parents and comparing each
2660 one with WINDOW. If it isn't we need a new selected window for
2661 this frame. */
2662 swindow = FRAME_SELECTED_WINDOW (f);
2663 while (1)
2665 pwindow = swindow;
2666 while (!NILP (pwindow) && !EQ (window, pwindow))
2667 pwindow = XWINDOW (pwindow)->parent;
2669 if (EQ (window, pwindow))
2670 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
2671 as the new selected window. */
2672 break;
2673 else
2674 /* Else try the previous window of SWINDOW. */
2675 swindow = Fprevious_window (swindow, Qlambda, Qnil);
2678 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
2680 if (EQ (selected_frame, w->frame))
2681 Fselect_window (swindow, Qnil);
2682 else
2683 FRAME_SELECTED_WINDOW (f) = swindow;
2687 BLOCK_INPUT;
2688 free_window_matrices (r);
2690 windows_or_buffers_changed++;
2691 Vwindow_list = Qnil;
2692 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
2694 if (NILP (w->buffer))
2696 resize_failed = 0;
2697 /* Resize subwindows vertically. */
2698 XSETINT (delta, XINT (r->total_lines) - XINT (w->total_lines));
2699 w->top_line = r->top_line;
2700 resize_root_window (window, delta, Qnil, Qnil);
2701 if (resize_window_check (w, 0))
2702 resize_window_apply (w, 0);
2703 else
2705 resize_root_window (window, delta, Qnil, Qt);
2706 if (resize_window_check (w, 0))
2707 resize_window_apply (w, 0);
2708 else
2709 resize_failed = 1;
2712 /* Resize subwindows horizontally. */
2713 if (!resize_failed)
2715 w->left_col = r->left_col;
2716 XSETINT (delta, XINT (r->total_cols) - XINT (w->total_cols));
2717 w->left_col = r->left_col;
2718 resize_root_window (window, delta, Qt, Qnil);
2719 if (resize_window_check (w, 1))
2720 resize_window_apply (w, 1);
2721 else
2723 resize_root_window (window, delta, Qt, Qt);
2724 if (resize_window_check (w, 1))
2725 resize_window_apply (w, 1);
2726 else
2727 resize_failed = 1;
2731 if (resize_failed)
2732 /* Play safe, if we still can ... */
2734 window = swindow;
2735 w = XWINDOW (window);
2739 /* Cleanly unlink WINDOW from window-tree. */
2740 if (!NILP (w->prev))
2741 /* Get SIBLING above (on the left of) WINDOW. */
2743 sibling = w->prev;
2744 s = XWINDOW (sibling);
2745 s->next = w->next;
2746 if (!NILP (s->next))
2747 XWINDOW (s->next)->prev = sibling;
2749 else
2750 /* Get SIBLING below (on the right of) WINDOW. */
2752 sibling = w->next;
2753 s = XWINDOW (sibling);
2754 s->prev = Qnil;
2755 if (!NILP (XWINDOW (w->parent)->vchild))
2756 XWINDOW (w->parent)->vchild = sibling;
2757 else
2758 XWINDOW (w->parent)->hchild = sibling;
2761 /* Delete ROOT and all subwindows of ROOT. */
2762 if (!NILP (r->vchild))
2764 delete_all_subwindows (r->vchild);
2765 r->vchild = Qnil;
2767 else if (!NILP (r->hchild))
2769 delete_all_subwindows (r->hchild);
2770 r->hchild = Qnil;
2773 replace_window (root, window, 1);
2775 /* Reset WINDOW's splits status. */
2776 w->splits = Qnil;
2778 /* This must become SWINDOW anyway ....... */
2779 if (!NILP (w->buffer) && !resize_failed)
2781 /* Try to minimize scrolling, by setting the window start to the
2782 point will cause the text at the old window start to be at the
2783 same place on the frame. But don't try to do this if the
2784 window start is outside the visible portion (as might happen
2785 when the display is not current, due to typeahead). */
2786 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2787 if (new_top != top
2788 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2789 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2791 struct position pos;
2792 struct buffer *obuf = current_buffer;
2794 Fset_buffer (w->buffer);
2795 /* This computation used to temporarily move point, but that
2796 can have unwanted side effects due to text properties. */
2797 pos = *vmotion (startpos, -top, w);
2799 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2800 w->window_end_valid = Qnil;
2801 w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
2802 || FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
2803 : Qnil);
2804 /* We need to do this, so that the window-scroll-functions
2805 get called. */
2806 w->optional_new_start = Qt;
2808 set_buffer_internal (obuf);
2812 adjust_glyphs (f);
2813 UNBLOCK_INPUT;
2815 run_window_configuration_change_hook (f);
2817 return Qnil;
2821 void
2822 replace_buffer_in_windows (Lisp_Object buffer)
2824 call1 (Qreplace_buffer_in_windows, buffer);
2828 /* Safely replace BUFFER with some other buffer in all windows of all
2829 frames, even those on other keyboards. */
2831 void
2832 replace_buffer_in_windows_safely (Lisp_Object buffer)
2834 Lisp_Object tail, frame;
2836 /* A single call to window_loop won't do the job because it only
2837 considers frames on the current keyboard. So loop manually over
2838 frames, and handle each one. */
2839 FOR_EACH_FRAME (tail, frame)
2840 window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
2843 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2844 minimum allowable size. */
2846 void
2847 check_frame_size (FRAME_PTR frame, int *rows, int *cols)
2849 /* For height, we have to see:
2850 how many windows the frame has at minimum (one or two),
2851 and whether it has a menu bar or other special stuff at the top. */
2852 int min_height
2853 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
2854 ? MIN_SAFE_WINDOW_HEIGHT
2855 : 2 * MIN_SAFE_WINDOW_HEIGHT);
2857 if (FRAME_TOP_MARGIN (frame) > 0)
2858 min_height += FRAME_TOP_MARGIN (frame);
2860 if (*rows < min_height)
2861 *rows = min_height;
2862 if (*cols < MIN_SAFE_WINDOW_WIDTH)
2863 *cols = MIN_SAFE_WINDOW_WIDTH;
2866 /* Adjust the margins of window W if text area is too small.
2867 Return 1 if window width is ok after adjustment; 0 if window
2868 is still too narrow. */
2870 static int
2871 adjust_window_margins (struct window *w)
2873 int box_cols = (WINDOW_TOTAL_COLS (w)
2874 - WINDOW_FRINGE_COLS (w)
2875 - WINDOW_SCROLL_BAR_COLS (w));
2876 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
2877 + WINDOW_RIGHT_MARGIN_COLS (w));
2879 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
2880 return 1;
2882 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
2883 return 0;
2885 /* Window's text area is too narrow, but reducing the window
2886 margins will fix that. */
2887 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
2888 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
2890 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
2891 w->left_margin_cols = w->right_margin_cols
2892 = make_number (margin_cols/2);
2893 else
2894 w->right_margin_cols = make_number (margin_cols);
2896 else
2897 w->left_margin_cols = make_number (margin_cols);
2898 return 1;
2901 static Lisp_Object Fset_window_margins (Lisp_Object, Lisp_Object, Lisp_Object);
2902 static Lisp_Object Fset_window_fringes (Lisp_Object, Lisp_Object, Lisp_Object,
2903 Lisp_Object);
2904 static Lisp_Object Fset_window_scroll_bars (Lisp_Object, Lisp_Object,
2905 Lisp_Object, Lisp_Object);
2906 static Lisp_Object Fset_window_vscroll (Lisp_Object, Lisp_Object, Lisp_Object);
2908 /* The following three routines are needed for running a window's
2909 configuration change hook. */
2910 static void
2911 run_funs (Lisp_Object funs)
2913 for (; CONSP (funs); funs = XCDR (funs))
2914 if (!EQ (XCAR (funs), Qt))
2915 call0 (XCAR (funs));
2918 static Lisp_Object
2919 select_window_norecord (Lisp_Object window)
2921 return WINDOW_LIVE_P (window)
2922 ? Fselect_window (window, Qt) : selected_window;
2925 static Lisp_Object
2926 select_frame_norecord (Lisp_Object frame)
2928 return FRAME_LIVE_P (XFRAME (frame))
2929 ? Fselect_frame (frame, Qt) : selected_frame;
2932 void
2933 run_window_configuration_change_hook (struct frame *f)
2935 int count = SPECPDL_INDEX ();
2936 Lisp_Object frame, global_wcch
2937 = Fdefault_value (Qwindow_configuration_change_hook);
2938 XSETFRAME (frame, f);
2940 if (NILP (Vrun_hooks))
2941 return;
2943 /* Use the right buffer. Matters when running the local hooks. */
2944 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
2946 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
2947 Fset_buffer (Fwindow_buffer (Qnil));
2950 if (SELECTED_FRAME () != f)
2952 record_unwind_protect (select_frame_norecord, Fselected_frame ());
2953 select_frame_norecord (frame);
2956 /* Look for buffer-local values. */
2958 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
2959 for (; CONSP (windows); windows = XCDR (windows))
2961 Lisp_Object window = XCAR (windows);
2962 Lisp_Object buffer = Fwindow_buffer (window);
2963 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
2964 buffer)))
2966 int count = SPECPDL_INDEX ();
2967 record_unwind_protect (select_window_norecord, Fselected_window ());
2968 select_window_norecord (window);
2969 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
2970 buffer));
2971 unbind_to (count, Qnil);
2976 run_funs (global_wcch);
2977 unbind_to (count, Qnil);
2980 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
2981 Srun_window_configuration_change_hook, 1, 1, 0,
2982 doc: /* Run `window-configuration-change-hook' for FRAME. */)
2983 (Lisp_Object frame)
2985 CHECK_LIVE_FRAME (frame);
2986 run_window_configuration_change_hook (XFRAME (frame));
2987 return Qnil;
2990 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
2991 means it's allowed to run hooks. See make_frame for a case where
2992 it's not allowed. KEEP_MARGINS_P non-zero means that the current
2993 margins, fringes, and scroll-bar settings of the window are not
2994 reset from the buffer's local settings. */
2996 void
2997 set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int keep_margins_p)
2999 struct window *w = XWINDOW (window);
3000 struct buffer *b = XBUFFER (buffer);
3001 int count = SPECPDL_INDEX ();
3002 int samebuf = EQ (buffer, w->buffer);
3004 w->buffer = buffer;
3006 if (EQ (window, selected_window))
3007 BVAR (b, last_selected_window) = window;
3009 /* Let redisplay errors through. */
3010 b->display_error_modiff = 0;
3012 /* Update time stamps of buffer display. */
3013 if (INTEGERP (BVAR (b, display_count)))
3014 XSETINT (BVAR (b, display_count), XINT (BVAR (b, display_count)) + 1);
3015 BVAR (b, display_time) = Fcurrent_time ();
3017 XSETFASTINT (w->window_end_pos, 0);
3018 XSETFASTINT (w->window_end_vpos, 0);
3019 memset (&w->last_cursor, 0, sizeof w->last_cursor);
3020 w->window_end_valid = Qnil;
3021 if (!(keep_margins_p && samebuf))
3022 { /* If we're not actually changing the buffer, don't reset hscroll and
3023 vscroll. This case happens for example when called from
3024 change_frame_size_1, where we use a dummy call to
3025 Fset_window_buffer on the frame's selected window (and no other)
3026 just in order to run window-configuration-change-hook.
3027 Resetting hscroll and vscroll here is problematic for things like
3028 image-mode and doc-view-mode since it resets the image's position
3029 whenever we resize the frame. */
3030 w->hscroll = w->min_hscroll = make_number (0);
3031 w->vscroll = 0;
3032 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3033 set_marker_restricted (w->start,
3034 make_number (b->last_window_start),
3035 buffer);
3036 w->start_at_line_beg = Qnil;
3037 w->force_start = Qnil;
3038 XSETFASTINT (w->last_modified, 0);
3039 XSETFASTINT (w->last_overlay_modified, 0);
3041 /* Maybe we could move this into the `if' but it's not obviously safe and
3042 I doubt it's worth the trouble. */
3043 windows_or_buffers_changed++;
3045 /* We must select BUFFER for running the window-scroll-functions. */
3046 /* We can't check ! NILP (Vwindow_scroll_functions) here
3047 because that might itself be a local variable. */
3048 if (window_initialized)
3050 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
3051 Fset_buffer (buffer);
3054 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3056 if (!keep_margins_p)
3058 /* Set left and right marginal area width etc. from buffer. */
3060 /* This may call adjust_window_margins three times, so
3061 temporarily disable window margins. */
3062 Lisp_Object save_left = w->left_margin_cols;
3063 Lisp_Object save_right = w->right_margin_cols;
3065 w->left_margin_cols = w->right_margin_cols = Qnil;
3067 Fset_window_fringes (window,
3068 BVAR (b, left_fringe_width), BVAR (b, right_fringe_width),
3069 BVAR (b, fringes_outside_margins));
3071 Fset_window_scroll_bars (window,
3072 BVAR (b, scroll_bar_width),
3073 BVAR (b, vertical_scroll_bar_type), Qnil);
3075 w->left_margin_cols = save_left;
3076 w->right_margin_cols = save_right;
3078 Fset_window_margins (window,
3079 BVAR (b, left_margin_cols), BVAR (b, right_margin_cols));
3082 if (run_hooks_p)
3084 if (! NILP (Vwindow_scroll_functions))
3085 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3086 Fmarker_position (w->start));
3087 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3090 unbind_to (count, Qnil);
3093 DEFUN ("set-window-clone-number", Fset_window_clone_number, Sset_window_clone_number, 2, 2, 0,
3094 doc: /* Set WINDOW's clone number to CLONE-NUMBER.
3095 WINDOW can be any window and defaults to the selected one. */)
3096 (Lisp_Object window, Lisp_Object clone_number)
3098 register struct window *w = decode_any_window (window);
3100 CHECK_NUMBER (clone_number);
3101 w->clone_number = clone_number;
3102 return w->clone_number;
3105 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3106 doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3107 WINDOW has to be a live window and defaults to the selected one.
3108 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
3110 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
3111 display margins, fringe widths, and scroll bar settings are preserved;
3112 the default is to reset these from the local settings for BUFFER-OR-NAME
3113 or the frame defaults. Return nil.
3115 This function throws an error when WINDOW is strongly dedicated to its
3116 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3117 already display BUFFER-OR-NAME.
3119 This function runs `window-scroll-functions' before running
3120 `window-configuration-change-hook'. */)
3121 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3123 register Lisp_Object tem, buffer;
3124 register struct window *w = decode_window (window);
3126 XSETWINDOW (window, w);
3127 buffer = Fget_buffer (buffer_or_name);
3128 CHECK_BUFFER (buffer);
3129 if (NILP (BVAR (XBUFFER (buffer), name)))
3130 error ("Attempt to display deleted buffer");
3132 tem = w->buffer;
3133 if (NILP (tem))
3134 error ("Window is deleted");
3135 else if (!EQ (tem, Qt))
3136 /* w->buffer is t when the window is first being set up. */
3138 if (!EQ (tem, buffer))
3140 if (EQ (w->dedicated, Qt))
3141 /* WINDOW is strongly dedicated to its buffer, signal an
3142 error. */
3143 error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
3144 else
3145 /* WINDOW is weakly dedicated to its buffer, reset
3146 dedicatedness. */
3147 w->dedicated = Qnil;
3149 call1 (Qrecord_window_buffer, window);
3152 unshow_buffer (w);
3155 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3157 return Qnil;
3160 static Lisp_Object
3161 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3163 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3166 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3167 0, 1, 0,
3168 doc: /* Force all windows to be updated on next redisplay.
3169 If optional arg OBJECT is a window, force redisplay of that window only.
3170 If OBJECT is a buffer or buffer name, force redisplay of all windows
3171 displaying that buffer. */)
3172 (Lisp_Object object)
3174 if (NILP (object))
3176 windows_or_buffers_changed++;
3177 update_mode_lines++;
3178 return Qt;
3181 if (WINDOWP (object))
3183 struct window *w = XWINDOW (object);
3184 mark_window_display_accurate (object, 0);
3185 w->update_mode_line = Qt;
3186 if (BUFFERP (w->buffer))
3187 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3188 ++update_mode_lines;
3189 return Qt;
3192 if (STRINGP (object))
3193 object = Fget_buffer (object);
3194 if (BUFFERP (object) && !NILP (BVAR (XBUFFER (object), name)))
3196 /* Walk all windows looking for buffer, and force update
3197 of each of those windows. */
3199 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3200 return NILP (object) ? Qnil : Qt;
3203 /* If nothing suitable was found, just return.
3204 We could signal an error, but this feature will typically be used
3205 asynchronously in timers or process sentinels, so we don't. */
3206 return Qnil;
3210 void
3211 temp_output_buffer_show (register Lisp_Object buf)
3213 register struct buffer *old = current_buffer;
3214 register Lisp_Object window;
3215 register struct window *w;
3217 BVAR (XBUFFER (buf), directory) = BVAR (current_buffer, directory);
3219 Fset_buffer (buf);
3220 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3221 BEGV = BEG;
3222 ZV = Z;
3223 SET_PT (BEG);
3224 set_buffer_internal (old);
3226 if (!NILP (Vtemp_buffer_show_function))
3227 call1 (Vtemp_buffer_show_function, buf);
3228 else
3230 window = display_buffer (buf, Vtemp_buffer_show_specifiers, Qnil);
3231 /* Reset Vtemp_buffer_show_specifiers immediately so it won't
3232 affect subsequent calls. */
3233 Vtemp_buffer_show_specifiers = Qnil;
3235 if (!EQ (XWINDOW (window)->frame, selected_frame))
3236 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3237 Vminibuf_scroll_window = window;
3238 w = XWINDOW (window);
3239 XSETFASTINT (w->hscroll, 0);
3240 XSETFASTINT (w->min_hscroll, 0);
3241 set_marker_restricted_both (w->start, buf, BEG, BEG);
3242 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3244 /* Run temp-buffer-show-hook, with the chosen window selected
3245 and its buffer current. */
3247 int count = SPECPDL_INDEX ();
3248 Lisp_Object prev_window, prev_buffer;
3249 prev_window = selected_window;
3250 XSETBUFFER (prev_buffer, old);
3252 /* Select the window that was chosen, for running the hook.
3253 Note: Both Fselect_window and select_window_norecord may
3254 set-buffer to the buffer displayed in the window,
3255 so we need to save the current buffer. --stef */
3256 record_unwind_protect (Fset_buffer, prev_buffer);
3257 record_unwind_protect (select_window_norecord, prev_window);
3258 Fselect_window (window, Qt);
3259 Fset_buffer (w->buffer);
3260 Frun_hooks (1, &Qtemp_buffer_show_hook);
3261 unbind_to (count, Qnil);
3266 DEFUN ("internal-temp-output-buffer-show",
3267 Ftemp_output_buffer_show, Stemp_output_buffer_show,
3268 1, 1, 0,
3269 doc: /* Internal function for `with-output-to-temp-buffer''. */)
3270 (Lisp_Object buf)
3272 temp_output_buffer_show (buf);
3273 return Qnil;
3276 /* Make new window, have it replace WINDOW in window-tree, and make
3277 WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
3278 horizontal child). */
3279 static void
3280 make_parent_window (Lisp_Object window, int horflag)
3282 Lisp_Object parent;
3283 register struct window *o, *p;
3284 int i;
3286 o = XWINDOW (window);
3287 p = allocate_window ();
3288 for (i = 0; i < VECSIZE (struct window); ++i)
3289 ((struct Lisp_Vector *) p)->contents[i]
3290 = ((struct Lisp_Vector *) o)->contents[i];
3291 XSETWINDOW (parent, p);
3293 ++sequence_number;
3294 XSETFASTINT (p->sequence_number, sequence_number);
3295 XSETFASTINT (p->clone_number, sequence_number);
3297 replace_window (window, parent, 1);
3299 o->next = Qnil;
3300 o->prev = Qnil;
3301 o->parent = parent;
3303 p->hchild = horflag ? window : Qnil;
3304 p->vchild = horflag ? Qnil : window;
3305 p->start = Qnil;
3306 p->pointm = Qnil;
3307 p->buffer = Qnil;
3308 p->splits = Qnil;
3309 p->nest = Qnil;
3310 p->window_parameters = Qnil;
3313 /* Make new window from scratch. */
3314 Lisp_Object
3315 make_window (void)
3317 Lisp_Object window;
3318 register struct window *w;
3320 w = allocate_window ();
3321 /* Initialize all Lisp data. */
3322 w->frame = w->mini_p = Qnil;
3323 w->next = w->prev = w->hchild = w->vchild = w->parent = Qnil;
3324 XSETFASTINT (w->left_col, 0);
3325 XSETFASTINT (w->top_line, 0);
3326 XSETFASTINT (w->total_lines, 0);
3327 XSETFASTINT (w->total_cols, 0);
3328 w->normal_lines = make_float (1.0);
3329 w->normal_cols = make_float (1.0);
3330 XSETFASTINT (w->new_total, 0);
3331 XSETFASTINT (w->new_normal, 0);
3332 w->buffer = Qnil;
3333 w->start = Fmake_marker ();
3334 w->pointm = Fmake_marker ();
3335 w->force_start = w->optional_new_start = Qnil;
3336 XSETFASTINT (w->hscroll, 0);
3337 XSETFASTINT (w->min_hscroll, 0);
3338 XSETFASTINT (w->use_time, 0);
3339 ++sequence_number;
3340 XSETFASTINT (w->sequence_number, sequence_number);
3341 XSETFASTINT (w->clone_number, sequence_number);
3342 w->temslot = w->last_modified = w->last_overlay_modified = Qnil;
3343 XSETFASTINT (w->last_point, 0);
3344 w->last_had_star = w->vertical_scroll_bar = Qnil;
3345 w->left_margin_cols = w->right_margin_cols = Qnil;
3346 w->left_fringe_width = w->right_fringe_width = Qnil;
3347 w->fringes_outside_margins = Qnil;
3348 w->scroll_bar_width = Qnil;
3349 w->vertical_scroll_bar_type = Qt;
3350 w->last_mark_x = w->last_mark_y = Qnil;
3351 XSETFASTINT (w->window_end_pos, 0);
3352 XSETFASTINT (w->window_end_vpos, 0);
3353 w->window_end_valid = w->update_mode_line = Qnil;
3354 w->start_at_line_beg = w->display_table = w->dedicated = Qnil;
3355 w->base_line_number = w->base_line_pos = w->region_showing = Qnil;
3356 w->column_number_displayed = w->redisplay_end_trigger = Qnil;
3357 w->splits = w->nest = w->window_parameters = Qnil;
3358 w->prev_buffers = w->next_buffers = Qnil;
3359 /* Initialize non-Lisp data. */
3360 w->desired_matrix = w->current_matrix = 0;
3361 w->nrows_scale_factor = w->ncols_scale_factor = 1;
3362 memset (&w->cursor, 0, sizeof (w->cursor));
3363 memset (&w->last_cursor, 0, sizeof (w->last_cursor));
3364 memset (&w->phys_cursor, 0, sizeof (w->phys_cursor));
3365 w->phys_cursor_type = -1;
3366 w->phys_cursor_width = -1;
3367 w->last_cursor_off_p = w->cursor_off_p = 0;
3368 w->must_be_updated_p = 0;
3369 w->pseudo_window_p = 0;
3370 w->frozen_window_start_p = 0;
3371 w->vscroll = 0;
3372 /* Reset window_list. */
3373 Vwindow_list = Qnil;
3374 /* Return window. */
3375 XSETWINDOW (window, w);
3376 return window;
3379 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
3380 doc: /* Set new total size of WINDOW to SIZE.
3381 Return SIZE.
3383 Optional argument ADD non-nil means add SIZE to the new total size of
3384 WINDOW and return the sum.
3386 Note: This function does not operate on any subwindows of WINDOW. */)
3387 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3389 struct window *w = decode_any_window (window);
3391 CHECK_NUMBER (size);
3392 if (NILP (add))
3393 XSETINT (w->new_total, XINT (size));
3394 else
3395 XSETINT (w->new_total, XINT (w->new_total) + XINT (size));
3397 return w->new_total;
3400 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
3401 doc: /* Set new normal size of WINDOW to SIZE.
3402 Return SIZE.
3404 Note: This function does not operate on any subwindows of WINDOW. */)
3405 (Lisp_Object window, Lisp_Object size)
3407 struct window *w = decode_any_window (window);
3409 w->new_normal = size;
3410 return w->new_normal;
3413 /* Return 1 if setting w->total_lines (w->total_cols if HORFLAG is
3414 non-zero) to w->new_total would result in correct heights (widths)
3415 for window W and recursively all subwindows of W.
3417 Note: This function does not check any of `window-fixed-size-p',
3418 `window-min-height' or `window-min-width'. It does check that window
3419 sizes do not drop below one line (two columns). */
3421 resize_window_check (struct window *w, int horflag)
3423 struct window *c;
3425 if (!NILP (w->vchild))
3426 /* W is a vertical combination. */
3428 c = XWINDOW (w->vchild);
3429 if (horflag)
3430 /* All subwindows of W must have the same width as W. */
3432 while (c)
3434 if ((XINT (c->new_total) != XINT (w->new_total))
3435 || !resize_window_check (c, horflag))
3436 return 0;
3437 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3439 return 1;
3441 else
3442 /* The sum of the heights of the subwindows of W must equal W's
3443 height. */
3445 int sum_of_sizes = 0;
3446 while (c)
3448 if (!resize_window_check (c, horflag))
3449 return 0;
3450 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3451 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3453 return (sum_of_sizes == XINT (w->new_total));
3456 else if (!NILP (w->hchild))
3457 /* W is a horizontal combination. */
3459 c = XWINDOW (w->hchild);
3460 if (horflag)
3461 /* The sum of the widths of the subwindows of W must equal W's
3462 width. */
3464 int sum_of_sizes = 0;
3465 while (c)
3467 if (!resize_window_check (c, horflag))
3468 return 0;
3469 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3470 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3472 return (sum_of_sizes == XINT (w->new_total));
3474 else
3475 /* All subwindows of W must have the same height as W. */
3477 while (c)
3479 if ((XINT (c->new_total) != XINT (w->new_total))
3480 || !resize_window_check (c, horflag))
3481 return 0;
3482 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3484 return 1;
3487 else
3488 /* A leaf window. Make sure it's not too small. The following
3489 hardcodes the values of `window-safe-min-width' (2) and
3490 `window-safe-min-height' (1) which are defined in window.el. */
3491 return XINT (w->new_total) >= (horflag ? 2 : 1);
3494 /* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
3495 w->new_total for window W and recursively all subwindows of W. Also
3496 calculate and assign the new vertical (horizontal) start positions of
3497 each of these windows.
3499 This function does not perform any error checks. Make sure you have
3500 run resize_window_check on W before applying this function. */
3501 void
3502 resize_window_apply (struct window *w, int horflag)
3504 struct window *c, *p;
3505 int pos;
3507 /* Note: Assigning new_normal requires that the new total size of the
3508 parent window has been set *before*. */
3509 if (horflag)
3511 w->total_cols = w->new_total;
3512 if (NUMBERP (w->new_normal))
3513 w->normal_cols = w->new_normal;
3515 pos = XINT (w->left_col);
3517 else
3519 w->total_lines = w->new_total;
3520 if (NUMBERP (w->new_normal))
3521 w->normal_lines = w->new_normal;
3523 pos = XINT (w->top_line);
3526 if (!NILP (w->vchild))
3527 /* W is a vertical combination. */
3529 c = XWINDOW (w->vchild);
3530 while (c)
3532 if (horflag)
3533 XSETFASTINT (c->left_col, pos);
3534 else
3535 XSETFASTINT (c->top_line, pos);
3536 resize_window_apply (c, horflag);
3537 if (!horflag)
3538 pos = pos + XINT (c->total_lines);
3539 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3542 else if (!NILP (w->hchild))
3543 /* W is a horizontal combination. */
3545 c = XWINDOW (w->hchild);
3546 while (c)
3548 if (horflag)
3549 XSETFASTINT (c->left_col, pos);
3550 else
3551 XSETFASTINT (c->top_line, pos);
3552 resize_window_apply (c, horflag);
3553 if (horflag)
3554 pos = pos + XINT (c->total_cols);
3555 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3559 /* Clear out some redisplay caches. */
3560 XSETFASTINT (w->last_modified, 0);
3561 XSETFASTINT (w->last_overlay_modified, 0);
3565 DEFUN ("resize-window-apply", Fresize_window_apply, Sresize_window_apply, 1, 2, 0,
3566 doc: /* Apply requested size values for window-tree of FRAME.
3567 Optional argument HORIZONTAL omitted or nil means apply requested height
3568 values. HORIZONTAL non-nil means apply requested width values.
3570 This function checks whether the requested values sum up to a valid
3571 window layout, recursively assigns the new sizes of all subwindows and
3572 calculates and assigns the new start positions of these windows.
3574 Note: This function does not check any of `window-fixed-size-p',
3575 `window-min-height' or `window-min-width'. All these checks have to
3576 be applied on the Elisp level. */)
3577 (Lisp_Object frame, Lisp_Object horizontal)
3579 struct frame *f;
3580 struct window *r;
3581 int horflag = !NILP (horizontal);
3583 if (NILP (frame))
3584 frame = selected_frame;
3585 CHECK_LIVE_FRAME (frame);
3587 f = XFRAME (frame);
3588 r = XWINDOW (FRAME_ROOT_WINDOW (f));
3590 if (!resize_window_check (r, horflag)
3591 || ! EQ (r->new_total, (horflag ? r->total_cols : r->total_lines)))
3592 return Qnil;
3594 BLOCK_INPUT;
3595 resize_window_apply (r, horflag);
3597 windows_or_buffers_changed++;
3598 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3600 adjust_glyphs (f);
3601 UNBLOCK_INPUT;
3603 run_window_configuration_change_hook (f);
3605 return Qt;
3609 /* Resize frame F's windows when number of lines of F is set to SIZE.
3610 HORFLAG 1 means resize windows when number of columns of F is set to
3611 SIZE.
3613 This function can delete all windows but the selected one in order to
3614 satisfy the request. The result will be meaningful if and only if
3615 F's windows have meaningful sizes when you call this. */
3616 void
3617 resize_frame_windows (struct frame *f, int size, int horflag)
3619 Lisp_Object root = f->root_window;
3620 struct window *r = XWINDOW (root);
3621 Lisp_Object mini = f->minibuffer_window;
3622 struct window *m;
3623 /* new_size is the new size of the frame's root window. */
3624 int new_size = (horflag
3625 ? size
3626 : (size
3627 - FRAME_TOP_MARGIN (f)
3628 - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3629 ? 1 : 0)));
3631 XSETFASTINT (r->top_line, FRAME_TOP_MARGIN (f));
3632 if (NILP (r->vchild) && NILP (r->hchild))
3633 /* For a leaf root window just set the size. */
3634 if (horflag)
3635 XSETFASTINT (r->total_cols, new_size);
3636 else
3637 XSETFASTINT (r->total_lines, new_size);
3638 else
3640 /* old_size is the old size of the frame's root window. */
3641 int old_size = XFASTINT (horflag ? r->total_cols : r->total_lines);
3642 Lisp_Object delta;
3644 XSETINT (delta, new_size - old_size);
3645 /* Try a "normal" resize first. */
3646 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil);
3647 if (resize_window_check (r, horflag) && new_size == XINT (r->new_total))
3648 resize_window_apply (r, horflag);
3649 else
3651 /* Try with "reasonable" minimum sizes next. */
3652 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt);
3653 if (resize_window_check (r, horflag)
3654 && new_size == XINT (r->new_total))
3655 resize_window_apply (r, horflag);
3656 else
3658 /* Finally, try with "safe" minimum sizes. */
3659 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe);
3660 if (resize_window_check (r, horflag)
3661 && new_size == XINT (r->new_total))
3662 resize_window_apply (r, horflag);
3663 else
3665 /* We lost. Delete all windows but the frame's
3666 selected one. */
3667 root = f->selected_window;
3668 Fdelete_other_windows_internal (root, Qnil);
3669 if (horflag)
3670 XSETFASTINT (XWINDOW (root)->total_cols, new_size);
3671 else
3672 XSETFASTINT (XWINDOW (root)->total_lines, new_size);
3678 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3680 m = XWINDOW (mini);
3681 if (horflag)
3682 XSETFASTINT (m->total_cols, size);
3683 else
3685 /* Are we sure we always want 1 line here? */
3686 XSETFASTINT (m->total_lines, 1);
3687 XSETFASTINT (m->top_line, XINT (r->top_line) + XINT (r->total_lines));
3693 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
3694 doc: /* Split window OLD.
3695 Second argument TOTAL-SIZE specifies the number of lines or columns of the
3696 new window. In any case TOTAL-SIZE must be a positive integer
3698 Third argument SIDE nil (or `below') specifies that the new window shall
3699 be located below WINDOW. SIDE `above' means the new window shall be
3700 located above WINDOW. In both cases TOTAL-SIZE specifies the number of
3701 lines of the new window including space reserved for the mode and/or
3702 header line.
3704 SIDE t (or `right') specifies that the new window shall be located on
3705 the right side of WINDOW. SIDE `left' means the new window shall be
3706 located on the left of WINDOW. In both cases TOTAL-SIZE specifies the
3707 number of columns of the new window including space reserved for fringes
3708 and the scrollbar or a divider column.
3710 Fourth argument NORMAL-SIZE specifies the normal size of the new window
3711 according to the SIDE argument.
3713 The new total and normal sizes of all involved windows must have been
3714 set correctly. See the code of `split-window' for how this is done. */)
3715 (Lisp_Object old, Lisp_Object total_size, Lisp_Object side, Lisp_Object normal_size)
3717 /* OLD (*o) is the window we have to split. (*p) is either OLD's
3718 parent window or an internal window we have to install as OLD's new
3719 parent. REFERENCE (*r) must denote a live window, or is set to OLD
3720 provided OLD is a leaf window, or to the frame's selected window.
3721 NEW (*n) is the new window created with some parameters taken from
3722 REFERENCE (*r). */
3723 register Lisp_Object new, frame, reference;
3724 register struct window *o, *p, *n, *r;
3725 struct frame *f;
3726 int horflag
3727 /* HORFLAG is 1 when we split side-by-side, 0 otherwise. */
3728 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
3729 int do_nest = 0;
3731 CHECK_WINDOW (old);
3732 o = XWINDOW (old);
3733 frame = WINDOW_FRAME (o);
3734 f = XFRAME (frame);
3736 CHECK_NUMBER (total_size);
3738 /* Set do_nest to 1 if we have to make a new parent window. We do
3739 that if either `window-nest' is non-nil, or OLD has no parent, or
3740 OLD is ortho-combined. */
3741 do_nest =
3742 !NILP (Vwindow_nest)
3743 || NILP (o->parent)
3744 || NILP (horflag
3745 ? (XWINDOW (o->parent)->hchild)
3746 : (XWINDOW (o->parent)->vchild));
3748 /* We need a live reference window to initialize some parameters. */
3749 if (WINDOW_LIVE_P (old))
3750 /* OLD is live, use it as reference window. */
3751 reference = old;
3752 else
3753 /* Use the frame's selected window as reference window. */
3754 reference = FRAME_SELECTED_WINDOW (f);
3755 r = XWINDOW (reference);
3757 /* The following bugs are caught by `split-window'. */
3758 if (MINI_WINDOW_P (o))
3759 error ("Attempt to split minibuffer window");
3760 else if (XINT (total_size) < (horflag ? 2 : 1))
3761 error ("Size of new window too small (after split)");
3762 else if (!do_nest && !NILP (Vwindow_splits))
3763 /* `window-splits' non-nil means try to resize OLD's siblings
3764 proportionally. */
3766 p = XWINDOW (o->parent);
3767 /* Temporarily pretend we split the parent window. */
3768 XSETINT (p->new_total,
3769 XINT (horflag ? p->total_cols : p->total_lines)
3770 - XINT (total_size));
3771 if (!resize_window_check (p, horflag))
3772 error ("Window sizes don't fit");
3773 else
3774 /* Undo the temporary pretension. */
3775 p->new_total = horflag ? p->total_cols : p->total_lines;
3777 else
3779 if (!resize_window_check (o, horflag))
3780 error ("Resizing old window failed");
3781 else if (XINT (total_size) + XINT (o->new_total)
3782 != XINT (horflag ? o->total_cols : o->total_lines))
3783 error ("Sum of sizes of old and new window don't fit");
3786 /* This is our point of no return. */
3787 if (do_nest)
3789 /* Save the old value of o->normal_cols/lines. It gets corrupted
3790 by make_parent_window and we need it below for assigning it to
3791 p->new_normal. */
3792 Lisp_Object new_normal = horflag ? o->normal_cols : o->normal_lines;
3794 make_parent_window (old, horflag);
3795 p = XWINDOW (o->parent);
3796 /* Store value of `window-nest' in new parent's nest slot. */
3797 p->nest = Vwindow_nest;
3798 /* Have PARENT inherit splits slot value from OLD. */
3799 p->splits = o->splits;
3800 /* Store value of `window-splits' in OLD's splits slot. */
3801 o->splits = Vwindow_splits;
3802 /* These get applied below. */
3803 p->new_total = horflag ? o->total_cols : o->total_lines;
3804 p->new_normal = new_normal;
3806 else
3807 p = XWINDOW (o->parent);
3809 windows_or_buffers_changed++;
3810 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3811 new = make_window ();
3812 n = XWINDOW (new);
3813 n->frame = frame;
3814 n->parent = o->parent;
3815 n->vchild = n->hchild = Qnil;
3817 if (EQ (side, Qabove) || EQ (side, Qleft))
3819 n->prev = o->prev;
3820 if (NILP (n->prev))
3821 if (horflag)
3822 p->hchild = new;
3823 else
3824 p->vchild = new;
3825 else
3826 XWINDOW (n->prev)->next = new;
3827 n->next = old;
3828 o->prev = new;
3830 else
3832 n->next = o->next;
3833 if (!NILP (n->next))
3834 XWINDOW (n->next)->prev = new;
3835 n->prev = old;
3836 o->next = new;
3839 n->buffer = Qt;
3840 n->window_end_valid = Qnil;
3841 memset (&n->last_cursor, 0, sizeof n->last_cursor);
3843 /* Get special geometry settings from reference window. */
3844 n->left_margin_cols = r->left_margin_cols;
3845 n->right_margin_cols = r->right_margin_cols;
3846 n->left_fringe_width = r->left_fringe_width;
3847 n->right_fringe_width = r->right_fringe_width;
3848 n->fringes_outside_margins = r->fringes_outside_margins;
3849 n->scroll_bar_width = r->scroll_bar_width;
3850 n->vertical_scroll_bar_type = r->vertical_scroll_bar_type;
3852 /* Store `window-splits' in NEW's splits slot. */
3853 n->splits = Vwindow_splits;
3855 /* Directly assign orthogonal coordinates and sizes. */
3856 if (horflag)
3858 n->top_line = o->top_line;
3859 n->total_lines = o->total_lines;
3861 else
3863 n->left_col = o->left_col;
3864 n->total_cols = o->total_cols;
3867 /* Iso-coordinates and sizes are assigned by resize_window_apply,
3868 get them ready here. */
3869 n->new_total = total_size;
3870 n->new_normal = normal_size;
3872 BLOCK_INPUT;
3873 resize_window_apply (p, horflag);
3874 adjust_glyphs (f);
3875 /* Set buffer of NEW to buffer of reference window. Don't run
3876 any hooks. */
3877 set_window_buffer (new, r->buffer, 0, 1);
3878 UNBLOCK_INPUT;
3880 /* Maybe we should run the scroll functions in Elisp (which already
3881 runs the configuration change hook). */
3882 if (! NILP (Vwindow_scroll_functions))
3883 run_hook_with_args_2 (Qwindow_scroll_functions, new,
3884 Fmarker_position (n->start));
3885 /* Return NEW. */
3886 return new;
3890 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
3891 doc: /* Remove WINDOW from its frame.
3892 WINDOW defaults to the selected window. Return nil. Signal an error
3893 when WINDOW is the only window on its frame. */)
3894 (register Lisp_Object window)
3896 register Lisp_Object parent, sibling, frame, root;
3897 struct window *w, *p, *s, *r;
3898 struct frame *f;
3899 int horflag;
3900 int before_sibling = 0;
3902 w = decode_any_window (window);
3903 XSETWINDOW (window, w);
3904 if (NILP (w->buffer) && NILP (w->hchild) && NILP (w->vchild))
3905 /* It's a no-op to delete an already deleted window. */
3906 return Qnil;
3908 parent = w->parent;
3909 if (NILP (parent))
3910 /* Never delete a minibuffer or frame root window. */
3911 error ("Attempt to delete minibuffer or sole ordinary window");
3912 else if (NILP (w->prev) && NILP (w->next))
3913 /* Rather bow out here, this case should be handled on the Elisp
3914 level. */
3915 error ("Attempt to delete sole window of parent");
3917 p = XWINDOW (parent);
3918 horflag = NILP (p->vchild);
3920 frame = WINDOW_FRAME (w);
3921 f = XFRAME (frame);
3923 root = FRAME_ROOT_WINDOW (f);
3924 r = XWINDOW (root);
3926 /* Unlink WINDOW from window tree. */
3927 if (NILP (w->prev))
3928 /* Get SIBLING below (on the right of) WINDOW. */
3930 /* before_sibling 1 means WINDOW is the first child of its
3931 parent and thus before the sibling. */
3932 before_sibling = 1;
3933 sibling = w->next;
3934 s = XWINDOW (sibling);
3935 s->prev = Qnil;
3936 if (horflag)
3937 p->hchild = sibling;
3938 else
3939 p->vchild = sibling;
3941 else
3942 /* Get SIBLING above (on the left of) WINDOW. */
3944 sibling = w->prev;
3945 s = XWINDOW (sibling);
3946 s->next = w->next;
3947 if (!NILP (s->next))
3948 XWINDOW (s->next)->prev = sibling;
3951 if (resize_window_check (r, horflag)
3952 && EQ (r->new_total, (horflag ? r->total_cols : r->total_lines)))
3953 /* We can delete WINDOW now. */
3955 /* Block input. */
3956 BLOCK_INPUT;
3957 resize_window_apply (p, horflag);
3959 windows_or_buffers_changed++;
3960 Vwindow_list = Qnil;
3961 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3963 w->next = Qnil; /* Don't delete w->next too. */
3964 free_window_matrices (w);
3966 if (!NILP (w->vchild))
3968 delete_all_subwindows (w->vchild);
3969 w->vchild = Qnil;
3971 else if (!NILP (w->hchild))
3973 delete_all_subwindows (w->hchild);
3974 w->hchild = Qnil;
3976 else if (!NILP (w->buffer))
3978 unshow_buffer (w);
3979 unchain_marker (XMARKER (w->pointm));
3980 unchain_marker (XMARKER (w->start));
3981 w->buffer = Qnil;
3984 if (NILP (s->prev) && NILP (s->next))
3985 /* A matrjoshka where SIBLING has become the only child of
3986 PARENT. */
3988 /* Put SIBLING into PARENT's place. */
3989 replace_window (parent, sibling, 0);
3990 /* Have SIBLING inherit the following three slot values from
3991 PARENT (the nest slot is not inherited). */
3992 s->normal_cols = p->normal_cols;
3993 s->normal_lines = p->normal_lines;
3994 s->splits = p->splits;
3995 /* Mark PARENT as deleted. */
3996 p->vchild = p->hchild = Qnil;
3997 /* Try to merge SIBLING into its new parent. */
3998 recombine_windows (sibling);
4001 adjust_glyphs (f);
4003 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
4004 /* We deleted the frame's selected window. */
4006 /* Use the frame's first window as fallback ... */
4007 Lisp_Object new_selected_window = Fframe_first_window (frame);
4008 /* ... but preferably use its most recently used window. */
4009 Lisp_Object mru_window;
4011 /* `get-mru-window' might fail for some reason so play it safe
4012 - promote the first window _without recording it_ first. */
4013 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4014 Fselect_window (new_selected_window, Qt);
4015 else
4016 FRAME_SELECTED_WINDOW (f) = new_selected_window;
4018 UNBLOCK_INPUT;
4020 /* Now look whether `get-mru-window' gets us something. */
4021 mru_window = call1 (Qget_mru_window, frame);
4022 if (WINDOW_LIVE_P (mru_window)
4023 && EQ (XWINDOW (mru_window)->frame, frame))
4024 new_selected_window = mru_window;
4026 /* If all ended up well, we now promote the mru window. */
4027 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4028 Fselect_window (new_selected_window, Qnil);
4029 else
4030 FRAME_SELECTED_WINDOW (f) = new_selected_window;
4032 else
4033 UNBLOCK_INPUT;
4035 /* Must be run by the caller:
4036 run_window_configuration_change_hook (f); */
4038 else
4039 /* We failed: Relink WINDOW into window tree. */
4041 if (before_sibling)
4043 s->prev = window;
4044 if (horflag)
4045 p->hchild = window;
4046 else
4047 p->vchild = window;
4049 else
4051 s->next = window;
4052 if (!NILP (w->next))
4053 XWINDOW (w->next)->prev = window;
4055 error ("Deletion failed");
4058 return Qnil;
4061 /***********************************************************************
4062 Resizing Mini-Windows
4063 ***********************************************************************/
4065 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
4066 can. */
4067 void
4068 grow_mini_window (struct window *w, int delta)
4070 struct frame *f = XFRAME (w->frame);
4071 struct window *r;
4072 Lisp_Object root, value;
4074 xassert (MINI_WINDOW_P (w));
4075 xassert (delta >= 0);
4077 root = FRAME_ROOT_WINDOW (f);
4078 r = XWINDOW (root);
4079 value = call2 (Qresize_root_window_vertically, root, make_number (- delta));
4080 if (INTEGERP (value) && resize_window_check (r, 0))
4082 BLOCK_INPUT;
4083 resize_window_apply (r, 0);
4085 /* Grow the mini-window. */
4086 XSETFASTINT (w->top_line, XFASTINT (r->top_line) + XFASTINT (r->total_lines));
4087 XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - XINT (value));
4088 XSETFASTINT (w->last_modified, 0);
4089 XSETFASTINT (w->last_overlay_modified, 0);
4091 adjust_glyphs (f);
4092 UNBLOCK_INPUT;
4097 /* Shrink mini-window W. */
4098 void
4099 shrink_mini_window (struct window *w)
4101 struct frame *f = XFRAME (w->frame);
4102 struct window *r;
4103 Lisp_Object root, value;
4104 EMACS_INT size;
4106 xassert (MINI_WINDOW_P (w));
4108 size = XINT (w->total_lines);
4109 if (size > 1)
4111 root = FRAME_ROOT_WINDOW (f);
4112 r = XWINDOW (root);
4113 value = call2 (Qresize_root_window_vertically,
4114 root, make_number (size - 1));
4115 if (INTEGERP (value) && resize_window_check (r, 0))
4117 BLOCK_INPUT;
4118 resize_window_apply (r, 0);
4120 /* Shrink the mini-window. */
4121 XSETFASTINT (w->top_line, XFASTINT (r->top_line) + XFASTINT (r->total_lines));
4122 XSETFASTINT (w->total_lines, 1);
4124 XSETFASTINT (w->last_modified, 0);
4125 XSETFASTINT (w->last_overlay_modified, 0);
4127 adjust_glyphs (f);
4128 UNBLOCK_INPUT;
4130 /* If the above failed for whatever strange reason we must make a
4131 one window frame here. The same routine will be needed when
4132 shrinking the frame (and probably when making the initial
4133 *scratch* window). For the moment leave things as they are. */
4137 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
4138 doc: /* Resize minibuffer window WINDOW. */)
4139 (Lisp_Object window)
4141 struct window *w = XWINDOW (window);
4142 struct window *r;
4143 struct frame *f;
4144 int height;
4146 CHECK_WINDOW (window);
4147 f = XFRAME (w->frame);
4149 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
4150 error ("Not a valid minibuffer window");
4151 else if (FRAME_MINIBUF_ONLY_P (f))
4152 error ("Cannot resize a minibuffer-only frame");
4154 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4155 height = XINT (r->total_lines) + XINT (w->total_lines);
4156 if (resize_window_check (r, 0)
4157 && XINT (w->new_total) > 0
4158 && height == XINT (r->new_total) + XINT (w->new_total))
4160 BLOCK_INPUT;
4161 resize_window_apply (r, 0);
4163 w->total_lines = w->new_total;
4164 XSETFASTINT (w->top_line, XINT (r->top_line) + XINT (r->total_lines));
4166 windows_or_buffers_changed++;
4167 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4168 adjust_glyphs (f);
4169 UNBLOCK_INPUT;
4171 run_window_configuration_change_hook (f);
4172 return Qt;
4174 else error ("Failed to resize minibuffer window");
4177 /* Mark window cursors off for all windows in the window tree rooted
4178 at W by setting their phys_cursor_on_p flag to zero. Called from
4179 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4180 the frame are cleared. */
4182 void
4183 mark_window_cursors_off (struct window *w)
4185 while (w)
4187 if (!NILP (w->hchild))
4188 mark_window_cursors_off (XWINDOW (w->hchild));
4189 else if (!NILP (w->vchild))
4190 mark_window_cursors_off (XWINDOW (w->vchild));
4191 else
4192 w->phys_cursor_on_p = 0;
4194 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4199 /* Return number of lines of text (not counting mode lines) in W. */
4202 window_internal_height (struct window *w)
4204 int ht = XFASTINT (w->total_lines);
4206 if (!MINI_WINDOW_P (w))
4208 if (!NILP (w->parent)
4209 || !NILP (w->vchild)
4210 || !NILP (w->hchild)
4211 || !NILP (w->next)
4212 || !NILP (w->prev)
4213 || WINDOW_WANTS_MODELINE_P (w))
4214 --ht;
4216 if (WINDOW_WANTS_HEADER_LINE_P (w))
4217 --ht;
4220 return ht;
4223 /************************************************************************
4224 Window Scrolling
4225 ***********************************************************************/
4227 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4228 N screen-fulls, which is defined as the height of the window minus
4229 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4230 instead. Negative values of N mean scroll down. NOERROR non-zero
4231 means don't signal an error if we try to move over BEGV or ZV,
4232 respectively. */
4234 static void
4235 window_scroll (Lisp_Object window, int n, int whole, int noerror)
4237 immediate_quit = 1;
4239 /* If we must, use the pixel-based version which is much slower than
4240 the line-based one but can handle varying line heights. */
4241 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4242 window_scroll_pixel_based (window, n, whole, noerror);
4243 else
4244 window_scroll_line_based (window, n, whole, noerror);
4246 immediate_quit = 0;
4250 /* Implementation of window_scroll that works based on pixel line
4251 heights. See the comment of window_scroll for parameter
4252 descriptions. */
4254 static void
4255 window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4257 struct it it;
4258 struct window *w = XWINDOW (window);
4259 struct text_pos start;
4260 int this_scroll_margin;
4261 /* True if we fiddled the window vscroll field without really scrolling. */
4262 int vscrolled = 0;
4263 int x, y, rtop, rbot, rowh, vpos;
4265 SET_TEXT_POS_FROM_MARKER (start, w->start);
4267 /* If PT is not visible in WINDOW, move back one half of
4268 the screen. Allow PT to be partially visible, otherwise
4269 something like (scroll-down 1) with PT in the line before
4270 the partially visible one would recenter. */
4272 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4274 /* Move backward half the height of the window. Performance note:
4275 vmotion used here is about 10% faster, but would give wrong
4276 results for variable height lines. */
4277 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4278 it.current_y = it.last_visible_y;
4279 move_it_vertically_backward (&it, window_box_height (w) / 2);
4281 /* The function move_iterator_vertically may move over more than
4282 the specified y-distance. If it->w is small, e.g. a
4283 mini-buffer window, we may end up in front of the window's
4284 display area. This is the case when Start displaying at the
4285 start of the line containing PT in this case. */
4286 if (it.current_y <= 0)
4288 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4289 move_it_vertically_backward (&it, 0);
4290 it.current_y = 0;
4293 start = it.current.pos;
4295 else if (auto_window_vscroll_p)
4297 if (rtop || rbot) /* partially visible */
4299 int px;
4300 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4301 if (whole)
4302 dy = max ((window_box_height (w)
4303 - next_screen_context_lines * dy),
4304 dy);
4305 dy *= n;
4307 if (n < 0)
4309 /* Only vscroll backwards if already vscrolled forwards. */
4310 if (w->vscroll < 0 && rtop > 0)
4312 px = max (0, -w->vscroll - min (rtop, -dy));
4313 Fset_window_vscroll (window, make_number (px), Qt);
4314 return;
4317 if (n > 0)
4319 /* Do vscroll if already vscrolled or only display line. */
4320 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4322 px = max (0, -w->vscroll + min (rbot, dy));
4323 Fset_window_vscroll (window, make_number (px), Qt);
4324 return;
4327 /* Maybe modify window start instead of scrolling. */
4328 if (rbot > 0 || w->vscroll < 0)
4330 EMACS_INT spos;
4332 Fset_window_vscroll (window, make_number (0), Qt);
4333 /* If there are other text lines above the current row,
4334 move window start to current row. Else to next row. */
4335 if (rbot > 0)
4336 spos = XINT (Fline_beginning_position (Qnil));
4337 else
4338 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4339 set_marker_restricted (w->start, make_number (spos),
4340 w->buffer);
4341 w->start_at_line_beg = Qt;
4342 w->update_mode_line = Qt;
4343 XSETFASTINT (w->last_modified, 0);
4344 XSETFASTINT (w->last_overlay_modified, 0);
4345 /* Set force_start so that redisplay_window will run the
4346 window-scroll-functions. */
4347 w->force_start = Qt;
4348 return;
4352 /* Cancel previous vscroll. */
4353 Fset_window_vscroll (window, make_number (0), Qt);
4356 /* If scroll_preserve_screen_position is non-nil, we try to set
4357 point in the same window line as it is now, so get that line. */
4358 if (!NILP (Vscroll_preserve_screen_position))
4360 /* We preserve the goal pixel coordinate across consecutive
4361 calls to scroll-up, scroll-down and other commands that
4362 have the `scroll-command' property. This avoids the
4363 possibility of point becoming "stuck" on a tall line when
4364 scrolling by one line. */
4365 if (window_scroll_pixel_based_preserve_y < 0
4366 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4367 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4369 start_display (&it, w, start);
4370 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4371 window_scroll_pixel_based_preserve_y = it.current_y;
4372 window_scroll_pixel_based_preserve_x = it.current_x;
4375 else
4376 window_scroll_pixel_based_preserve_y
4377 = window_scroll_pixel_based_preserve_x = -1;
4379 /* Move iterator it from start the specified distance forward or
4380 backward. The result is the new window start. */
4381 start_display (&it, w, start);
4382 if (whole)
4384 EMACS_INT start_pos = IT_CHARPOS (it);
4385 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4386 dy = max ((window_box_height (w)
4387 - next_screen_context_lines * dy),
4388 dy) * n;
4390 /* Note that move_it_vertically always moves the iterator to the
4391 start of a line. So, if the last line doesn't have a newline,
4392 we would end up at the start of the line ending at ZV. */
4393 if (dy <= 0)
4395 move_it_vertically_backward (&it, -dy);
4396 /* Ensure we actually do move, e.g. in case we are currently
4397 looking at an image that is taller that the window height. */
4398 while (start_pos == IT_CHARPOS (it)
4399 && start_pos > BEGV)
4400 move_it_by_lines (&it, -1);
4402 else if (dy > 0)
4404 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4405 MOVE_TO_POS | MOVE_TO_Y);
4406 /* Ensure we actually do move, e.g. in case we are currently
4407 looking at an image that is taller that the window height. */
4408 while (start_pos == IT_CHARPOS (it)
4409 && start_pos < ZV)
4410 move_it_by_lines (&it, 1);
4413 else
4414 move_it_by_lines (&it, n);
4416 /* We failed if we find ZV is already on the screen (scrolling up,
4417 means there's nothing past the end), or if we can't start any
4418 earlier (scrolling down, means there's nothing past the top). */
4419 if ((n > 0 && IT_CHARPOS (it) == ZV)
4420 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4422 if (IT_CHARPOS (it) == ZV)
4424 if (it.current_y < it.last_visible_y
4425 && (it.current_y + it.max_ascent + it.max_descent
4426 > it.last_visible_y))
4428 /* The last line was only partially visible, make it fully
4429 visible. */
4430 w->vscroll = (it.last_visible_y
4431 - it.current_y + it.max_ascent + it.max_descent);
4432 adjust_glyphs (it.f);
4434 else if (noerror)
4435 return;
4436 else if (n < 0) /* could happen with empty buffers */
4437 xsignal0 (Qbeginning_of_buffer);
4438 else
4439 xsignal0 (Qend_of_buffer);
4441 else
4443 if (w->vscroll != 0)
4444 /* The first line was only partially visible, make it fully
4445 visible. */
4446 w->vscroll = 0;
4447 else if (noerror)
4448 return;
4449 else
4450 xsignal0 (Qbeginning_of_buffer);
4453 /* If control gets here, then we vscrolled. */
4455 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4457 /* Don't try to change the window start below. */
4458 vscrolled = 1;
4461 if (! vscrolled)
4463 EMACS_INT pos = IT_CHARPOS (it);
4464 EMACS_INT bytepos;
4466 /* If in the middle of a multi-glyph character move forward to
4467 the next character. */
4468 if (in_display_vector_p (&it))
4470 ++pos;
4471 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4474 /* Set the window start, and set up the window for redisplay. */
4475 set_marker_restricted (w->start, make_number (pos),
4476 w->buffer);
4477 bytepos = XMARKER (w->start)->bytepos;
4478 w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
4479 ? Qt : Qnil);
4480 w->update_mode_line = Qt;
4481 XSETFASTINT (w->last_modified, 0);
4482 XSETFASTINT (w->last_overlay_modified, 0);
4483 /* Set force_start so that redisplay_window will run the
4484 window-scroll-functions. */
4485 w->force_start = Qt;
4488 /* The rest of this function uses current_y in a nonstandard way,
4489 not including the height of the header line if any. */
4490 it.current_y = it.vpos = 0;
4492 /* Move PT out of scroll margins.
4493 This code wants current_y to be zero at the window start position
4494 even if there is a header line. */
4495 this_scroll_margin = max (0, scroll_margin);
4496 this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4497 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4499 if (n > 0)
4501 /* We moved the window start towards ZV, so PT may be now
4502 in the scroll margin at the top. */
4503 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4504 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
4505 && (NILP (Vscroll_preserve_screen_position)
4506 || EQ (Vscroll_preserve_screen_position, Qt)))
4507 /* We found PT at a legitimate height. Leave it alone. */
4509 else if (window_scroll_pixel_based_preserve_y >= 0)
4511 /* If we have a header line, take account of it.
4512 This is necessary because we set it.current_y to 0, above. */
4513 move_it_to (&it, -1,
4514 window_scroll_pixel_based_preserve_x,
4515 window_scroll_pixel_based_preserve_y
4516 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
4517 -1, MOVE_TO_Y | MOVE_TO_X);
4518 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4520 else
4522 while (it.current_y < this_scroll_margin)
4524 int prev = it.current_y;
4525 move_it_by_lines (&it, 1);
4526 if (prev == it.current_y)
4527 break;
4529 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4532 else if (n < 0)
4534 EMACS_INT charpos, bytepos;
4535 int partial_p;
4537 /* Save our position, for the
4538 window_scroll_pixel_based_preserve_y case. */
4539 charpos = IT_CHARPOS (it);
4540 bytepos = IT_BYTEPOS (it);
4542 /* We moved the window start towards BEGV, so PT may be now
4543 in the scroll margin at the bottom. */
4544 move_it_to (&it, PT, -1,
4545 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
4546 - this_scroll_margin - 1),
4548 MOVE_TO_POS | MOVE_TO_Y);
4550 /* Save our position, in case it's correct. */
4551 charpos = IT_CHARPOS (it);
4552 bytepos = IT_BYTEPOS (it);
4554 /* See if point is on a partially visible line at the end. */
4555 if (it.what == IT_EOB)
4556 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
4557 else
4559 move_it_by_lines (&it, 1);
4560 partial_p = it.current_y > it.last_visible_y;
4563 if (charpos == PT && !partial_p
4564 && (NILP (Vscroll_preserve_screen_position)
4565 || EQ (Vscroll_preserve_screen_position, Qt)))
4566 /* We found PT before we found the display margin, so PT is ok. */
4568 else if (window_scroll_pixel_based_preserve_y >= 0)
4570 SET_TEXT_POS_FROM_MARKER (start, w->start);
4571 start_display (&it, w, start);
4572 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
4573 here because we called start_display again and did not
4574 alter it.current_y this time. */
4575 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
4576 window_scroll_pixel_based_preserve_y, -1,
4577 MOVE_TO_Y | MOVE_TO_X);
4578 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4580 else
4582 if (partial_p)
4583 /* The last line was only partially visible, so back up two
4584 lines to make sure we're on a fully visible line. */
4586 move_it_by_lines (&it, -2);
4587 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4589 else
4590 /* No, the position we saved is OK, so use it. */
4591 SET_PT_BOTH (charpos, bytepos);
4597 /* Implementation of window_scroll that works based on screen lines.
4598 See the comment of window_scroll for parameter descriptions. */
4600 static void
4601 window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
4603 register struct window *w = XWINDOW (window);
4604 /* Fvertical_motion enters redisplay, which can trigger
4605 fontification, which in turn can modify buffer text (e.g., if the
4606 fontification functions replace escape sequences with faces, as
4607 in `grep-mode-font-lock-keywords'). So we use a marker to record
4608 the old point position, to prevent crashes in SET_PT_BOTH. */
4609 Lisp_Object opoint_marker = Fpoint_marker ();
4610 register EMACS_INT pos, pos_byte;
4611 register int ht = window_internal_height (w);
4612 register Lisp_Object tem;
4613 int lose;
4614 Lisp_Object bolp;
4615 EMACS_INT startpos;
4616 Lisp_Object original_pos = Qnil;
4618 /* If scrolling screen-fulls, compute the number of lines to
4619 scroll from the window's height. */
4620 if (whole)
4621 n *= max (1, ht - next_screen_context_lines);
4623 startpos = marker_position (w->start);
4625 if (!NILP (Vscroll_preserve_screen_position))
4627 if (window_scroll_preserve_vpos <= 0
4628 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4629 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4631 struct position posit
4632 = *compute_motion (startpos, 0, 0, 0,
4633 PT, ht, 0,
4634 -1, XINT (w->hscroll),
4635 0, w);
4636 window_scroll_preserve_vpos = posit.vpos;
4637 window_scroll_preserve_hpos = posit.hpos + XINT (w->hscroll);
4640 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
4641 make_number (window_scroll_preserve_vpos));
4644 XSETFASTINT (tem, PT);
4645 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4647 if (NILP (tem))
4649 Fvertical_motion (make_number (- (ht / 2)), window);
4650 startpos = PT;
4653 SET_PT (startpos);
4654 lose = n < 0 && PT == BEGV;
4655 Fvertical_motion (make_number (n), window);
4656 pos = PT;
4657 pos_byte = PT_BYTE;
4658 bolp = Fbolp ();
4659 SET_PT_BOTH (marker_position (opoint_marker),
4660 marker_byte_position (opoint_marker));
4662 if (lose)
4664 if (noerror)
4665 return;
4666 else
4667 xsignal0 (Qbeginning_of_buffer);
4670 if (pos < ZV)
4672 int this_scroll_margin = scroll_margin;
4674 /* Don't use a scroll margin that is negative or too large. */
4675 if (this_scroll_margin < 0)
4676 this_scroll_margin = 0;
4678 if (XINT (w->total_lines) < 4 * scroll_margin)
4679 this_scroll_margin = XINT (w->total_lines) / 4;
4681 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4682 w->start_at_line_beg = bolp;
4683 w->update_mode_line = Qt;
4684 XSETFASTINT (w->last_modified, 0);
4685 XSETFASTINT (w->last_overlay_modified, 0);
4686 /* Set force_start so that redisplay_window will run
4687 the window-scroll-functions. */
4688 w->force_start = Qt;
4690 if (!NILP (Vscroll_preserve_screen_position)
4691 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
4693 SET_PT_BOTH (pos, pos_byte);
4694 Fvertical_motion (original_pos, window);
4696 /* If we scrolled forward, put point enough lines down
4697 that it is outside the scroll margin. */
4698 else if (n > 0)
4700 int top_margin;
4702 if (this_scroll_margin > 0)
4704 SET_PT_BOTH (pos, pos_byte);
4705 Fvertical_motion (make_number (this_scroll_margin), window);
4706 top_margin = PT;
4708 else
4709 top_margin = pos;
4711 if (top_margin <= marker_position (opoint_marker))
4712 SET_PT_BOTH (marker_position (opoint_marker),
4713 marker_byte_position (opoint_marker));
4714 else if (!NILP (Vscroll_preserve_screen_position))
4716 SET_PT_BOTH (pos, pos_byte);
4717 Fvertical_motion (original_pos, window);
4719 else
4720 SET_PT (top_margin);
4722 else if (n < 0)
4724 int bottom_margin;
4726 /* If we scrolled backward, put point near the end of the window
4727 but not within the scroll margin. */
4728 SET_PT_BOTH (pos, pos_byte);
4729 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4730 if (XFASTINT (tem) == ht - this_scroll_margin)
4731 bottom_margin = PT;
4732 else
4733 bottom_margin = PT + 1;
4735 if (bottom_margin > marker_position (opoint_marker))
4736 SET_PT_BOTH (marker_position (opoint_marker),
4737 marker_byte_position (opoint_marker));
4738 else
4740 if (!NILP (Vscroll_preserve_screen_position))
4742 SET_PT_BOTH (pos, pos_byte);
4743 Fvertical_motion (original_pos, window);
4745 else
4746 Fvertical_motion (make_number (-1), window);
4750 else
4752 if (noerror)
4753 return;
4754 else
4755 xsignal0 (Qend_of_buffer);
4760 /* Scroll selected_window up or down. If N is nil, scroll a
4761 screen-full which is defined as the height of the window minus
4762 next_screen_context_lines. If N is the symbol `-', scroll.
4763 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4764 up. This is the guts of Fscroll_up and Fscroll_down. */
4766 static void
4767 scroll_command (Lisp_Object n, int direction)
4769 int count = SPECPDL_INDEX ();
4771 xassert (eabs (direction) == 1);
4773 /* If selected window's buffer isn't current, make it current for
4774 the moment. But don't screw up if window_scroll gets an error. */
4775 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4777 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4778 Fset_buffer (XWINDOW (selected_window)->buffer);
4780 /* Make redisplay consider other windows than just selected_window. */
4781 ++windows_or_buffers_changed;
4784 if (NILP (n))
4785 window_scroll (selected_window, direction, 1, 0);
4786 else if (EQ (n, Qminus))
4787 window_scroll (selected_window, -direction, 1, 0);
4788 else
4790 n = Fprefix_numeric_value (n);
4791 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4794 unbind_to (count, Qnil);
4797 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
4798 doc: /* Scroll text of selected window upward ARG lines.
4799 If ARG is omitted or nil, scroll upward by a near full screen.
4800 A near full screen is `next-screen-context-lines' less than a full screen.
4801 Negative ARG means scroll downward.
4802 If ARG is the atom `-', scroll downward by nearly full screen.
4803 When calling from a program, supply as argument a number, nil, or `-'. */)
4804 (Lisp_Object arg)
4806 scroll_command (arg, 1);
4807 return Qnil;
4810 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
4811 doc: /* Scroll text of selected window down ARG lines.
4812 If ARG is omitted or nil, scroll down by a near full screen.
4813 A near full screen is `next-screen-context-lines' less than a full screen.
4814 Negative ARG means scroll upward.
4815 If ARG is the atom `-', scroll upward by nearly full screen.
4816 When calling from a program, supply as argument a number, nil, or `-'. */)
4817 (Lisp_Object arg)
4819 scroll_command (arg, -1);
4820 return Qnil;
4823 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4824 doc: /* Return the other window for \"other window scroll\" commands.
4825 If `other-window-scroll-buffer' is non-nil, a window
4826 showing that buffer is used.
4827 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4828 specifies the window. This takes precedence over
4829 `other-window-scroll-buffer'. */)
4830 (void)
4832 Lisp_Object window;
4834 if (MINI_WINDOW_P (XWINDOW (selected_window))
4835 && !NILP (Vminibuf_scroll_window))
4836 window = Vminibuf_scroll_window;
4837 /* If buffer is specified, scroll that buffer. */
4838 else if (!NILP (Vother_window_scroll_buffer))
4840 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4841 if (NILP (window))
4842 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4844 else
4846 /* Nothing specified; look for a neighboring window on the same
4847 frame. */
4848 window = Fnext_window (selected_window, Qnil, Qnil);
4850 if (EQ (window, selected_window))
4851 /* That didn't get us anywhere; look for a window on another
4852 visible frame. */
4854 window = Fnext_window (window, Qnil, Qt);
4855 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4856 && ! EQ (window, selected_window));
4859 CHECK_LIVE_WINDOW (window);
4861 if (EQ (window, selected_window))
4862 error ("There is no other window");
4864 return window;
4867 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
4868 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
4869 A near full screen is `next-screen-context-lines' less than a full screen.
4870 The next window is the one below the current one; or the one at the top
4871 if the current one is at the bottom. Negative ARG means scroll downward.
4872 If ARG is the atom `-', scroll downward by nearly full screen.
4873 When calling from a program, supply as argument a number, nil, or `-'.
4875 If `other-window-scroll-buffer' is non-nil, scroll the window
4876 showing that buffer, popping the buffer up if necessary.
4877 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4878 specifies the window to scroll. This takes precedence over
4879 `other-window-scroll-buffer'. */)
4880 (Lisp_Object arg)
4882 Lisp_Object window;
4883 struct window *w;
4884 int count = SPECPDL_INDEX ();
4886 window = Fother_window_for_scrolling ();
4887 w = XWINDOW (window);
4889 /* Don't screw up if window_scroll gets an error. */
4890 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4891 ++windows_or_buffers_changed;
4893 Fset_buffer (w->buffer);
4894 SET_PT (marker_position (w->pointm));
4896 if (NILP (arg))
4897 window_scroll (window, 1, 1, 1);
4898 else if (EQ (arg, Qminus))
4899 window_scroll (window, -1, 1, 1);
4900 else
4902 if (CONSP (arg))
4903 arg = Fcar (arg);
4904 CHECK_NUMBER (arg);
4905 window_scroll (window, XINT (arg), 0, 1);
4908 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
4909 unbind_to (count, Qnil);
4911 return Qnil;
4914 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
4915 doc: /* Scroll selected window display ARG columns left.
4916 Default for ARG is window width minus 2.
4917 Value is the total amount of leftward horizontal scrolling in
4918 effect after the change.
4919 If SET-MINIMUM is non-nil, the new scroll amount becomes the
4920 lower bound for automatic scrolling, i.e. automatic scrolling
4921 will not scroll a window to a column less than the value returned
4922 by this function. This happens in an interactive call. */)
4923 (register Lisp_Object arg, Lisp_Object set_minimum)
4925 Lisp_Object result;
4926 int hscroll;
4927 struct window *w = XWINDOW (selected_window);
4929 if (NILP (arg))
4930 XSETFASTINT (arg, window_body_cols (w) - 2);
4931 else
4932 arg = Fprefix_numeric_value (arg);
4934 hscroll = XINT (w->hscroll) + XINT (arg);
4935 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4937 if (!NILP (set_minimum))
4938 w->min_hscroll = w->hscroll;
4940 return result;
4943 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
4944 doc: /* Scroll selected window display ARG columns right.
4945 Default for ARG is window width minus 2.
4946 Value is the total amount of leftward horizontal scrolling in
4947 effect after the change.
4948 If SET-MINIMUM is non-nil, the new scroll amount becomes the
4949 lower bound for automatic scrolling, i.e. automatic scrolling
4950 will not scroll a window to a column less than the value returned
4951 by this function. This happens in an interactive call. */)
4952 (register Lisp_Object arg, Lisp_Object set_minimum)
4954 Lisp_Object result;
4955 int hscroll;
4956 struct window *w = XWINDOW (selected_window);
4958 if (NILP (arg))
4959 XSETFASTINT (arg, window_body_cols (w) - 2);
4960 else
4961 arg = Fprefix_numeric_value (arg);
4963 hscroll = XINT (w->hscroll) - XINT (arg);
4964 result = Fset_window_hscroll (selected_window, make_number (hscroll));
4966 if (!NILP (set_minimum))
4967 w->min_hscroll = w->hscroll;
4969 return result;
4972 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
4973 doc: /* Return the window which was selected when entering the minibuffer.
4974 Returns nil, if selected window is not a minibuffer window. */)
4975 (void)
4977 if (minibuf_level > 0
4978 && MINI_WINDOW_P (XWINDOW (selected_window))
4979 && WINDOW_LIVE_P (minibuf_selected_window))
4980 return minibuf_selected_window;
4982 return Qnil;
4985 /* Value is the number of lines actually displayed in window W,
4986 as opposed to its height. */
4988 static int
4989 displayed_window_lines (struct window *w)
4991 struct it it;
4992 struct text_pos start;
4993 int height = window_box_height (w);
4994 struct buffer *old_buffer;
4995 int bottom_y;
4997 if (XBUFFER (w->buffer) != current_buffer)
4999 old_buffer = current_buffer;
5000 set_buffer_internal (XBUFFER (w->buffer));
5002 else
5003 old_buffer = NULL;
5005 /* In case W->start is out of the accessible range, do something
5006 reasonable. This happens in Info mode when Info-scroll-down
5007 calls (recenter -1) while W->start is 1. */
5008 if (XMARKER (w->start)->charpos < BEGV)
5009 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5010 else if (XMARKER (w->start)->charpos > ZV)
5011 SET_TEXT_POS (start, ZV, ZV_BYTE);
5012 else
5013 SET_TEXT_POS_FROM_MARKER (start, w->start);
5015 start_display (&it, w, start);
5016 move_it_vertically (&it, height);
5017 bottom_y = line_bottom_y (&it);
5019 /* rms: On a non-window display,
5020 the value of it.vpos at the bottom of the screen
5021 seems to be 1 larger than window_box_height (w).
5022 This kludge fixes a bug whereby (move-to-window-line -1)
5023 when ZV is on the last screen line
5024 moves to the previous screen line instead of the last one. */
5025 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5026 height++;
5028 /* Add in empty lines at the bottom of the window. */
5029 if (bottom_y < height)
5031 int uy = FRAME_LINE_HEIGHT (it.f);
5032 it.vpos += (height - bottom_y + uy - 1) / uy;
5035 if (old_buffer)
5036 set_buffer_internal (old_buffer);
5038 return it.vpos;
5042 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5043 doc: /* Center point in selected window and maybe redisplay frame.
5044 With prefix argument ARG, recenter putting point on screen line ARG
5045 relative to the selected window. If ARG is negative, it counts up from the
5046 bottom of the window. (ARG should be less than the height of the window.)
5048 If ARG is omitted or nil, then recenter with point on the middle line of
5049 the selected window; if the variable `recenter-redisplay' is non-nil,
5050 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5051 is set to `grow-only', this resets the tool-bar's height to the minimum
5052 height needed); if `recenter-redisplay' has the special value `tty',
5053 then only tty frame are redrawn.
5055 Just C-u as prefix means put point in the center of the window
5056 and redisplay normally--don't erase and redraw the frame. */)
5057 (register Lisp_Object arg)
5059 struct window *w = XWINDOW (selected_window);
5060 struct buffer *buf = XBUFFER (w->buffer);
5061 struct buffer *obuf = current_buffer;
5062 int center_p = 0;
5063 EMACS_INT charpos, bytepos;
5064 int iarg IF_LINT (= 0);
5065 int this_scroll_margin;
5067 /* If redisplay is suppressed due to an error, try again. */
5068 obuf->display_error_modiff = 0;
5070 if (NILP (arg))
5072 if (!NILP (Vrecenter_redisplay)
5073 && (!EQ (Vrecenter_redisplay, Qtty)
5074 || !NILP (Ftty_type (selected_frame))))
5076 int i;
5078 /* Invalidate pixel data calculated for all compositions. */
5079 for (i = 0; i < n_compositions; i++)
5080 composition_table[i]->font = NULL;
5082 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5084 Fredraw_frame (WINDOW_FRAME (w));
5085 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5088 center_p = 1;
5090 else if (CONSP (arg)) /* Just C-u. */
5091 center_p = 1;
5092 else
5094 arg = Fprefix_numeric_value (arg);
5095 CHECK_NUMBER (arg);
5096 iarg = XINT (arg);
5099 set_buffer_internal (buf);
5101 /* Do this after making BUF current
5102 in case scroll_margin is buffer-local. */
5103 this_scroll_margin = max (0, scroll_margin);
5104 this_scroll_margin = min (this_scroll_margin,
5105 XFASTINT (w->total_lines) / 4);
5107 /* Handle centering on a graphical frame specially. Such frames can
5108 have variable-height lines and centering point on the basis of
5109 line counts would lead to strange effects. */
5110 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5112 if (center_p)
5114 struct it it;
5115 struct text_pos pt;
5117 SET_TEXT_POS (pt, PT, PT_BYTE);
5118 start_display (&it, w, pt);
5119 move_it_vertically_backward (&it, window_box_height (w) / 2);
5120 charpos = IT_CHARPOS (it);
5121 bytepos = IT_BYTEPOS (it);
5123 else if (iarg < 0)
5125 struct it it;
5126 struct text_pos pt;
5127 int nlines = -iarg;
5128 int extra_line_spacing;
5129 int h = window_box_height (w);
5131 iarg = - max (-iarg, this_scroll_margin);
5133 SET_TEXT_POS (pt, PT, PT_BYTE);
5134 start_display (&it, w, pt);
5136 /* Be sure we have the exact height of the full line containing PT. */
5137 move_it_by_lines (&it, 0);
5139 /* The amount of pixels we have to move back is the window
5140 height minus what's displayed in the line containing PT,
5141 and the lines below. */
5142 it.current_y = 0;
5143 it.vpos = 0;
5144 move_it_by_lines (&it, nlines);
5146 if (it.vpos == nlines)
5147 h -= it.current_y;
5148 else
5150 /* Last line has no newline */
5151 h -= line_bottom_y (&it);
5152 it.vpos++;
5155 /* Don't reserve space for extra line spacing of last line. */
5156 extra_line_spacing = it.max_extra_line_spacing;
5158 /* If we can't move down NLINES lines because we hit
5159 the end of the buffer, count in some empty lines. */
5160 if (it.vpos < nlines)
5162 nlines -= it.vpos;
5163 extra_line_spacing = it.extra_line_spacing;
5164 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5166 if (h <= 0)
5167 return Qnil;
5169 /* Now find the new top line (starting position) of the window. */
5170 start_display (&it, w, pt);
5171 it.current_y = 0;
5172 move_it_vertically_backward (&it, h);
5174 /* If extra line spacing is present, we may move too far
5175 back. This causes the last line to be only partially
5176 visible (which triggers redisplay to recenter that line
5177 in the middle), so move forward.
5178 But ignore extra line spacing on last line, as it is not
5179 considered to be part of the visible height of the line.
5181 h += extra_line_spacing;
5182 while (-it.current_y > h)
5183 move_it_by_lines (&it, 1);
5185 charpos = IT_CHARPOS (it);
5186 bytepos = IT_BYTEPOS (it);
5188 else
5190 struct position pos;
5192 iarg = max (iarg, this_scroll_margin);
5194 pos = *vmotion (PT, -iarg, w);
5195 charpos = pos.bufpos;
5196 bytepos = pos.bytepos;
5199 else
5201 struct position pos;
5202 int ht = window_internal_height (w);
5204 if (center_p)
5205 iarg = ht / 2;
5206 else if (iarg < 0)
5207 iarg += ht;
5209 /* Don't let it get into the margin at either top or bottom. */
5210 iarg = max (iarg, this_scroll_margin);
5211 iarg = min (iarg, ht - this_scroll_margin - 1);
5213 pos = *vmotion (PT, - iarg, w);
5214 charpos = pos.bufpos;
5215 bytepos = pos.bytepos;
5218 /* Set the new window start. */
5219 set_marker_both (w->start, w->buffer, charpos, bytepos);
5220 w->window_end_valid = Qnil;
5222 w->optional_new_start = Qt;
5224 if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
5225 w->start_at_line_beg = Qt;
5226 else
5227 w->start_at_line_beg = Qnil;
5229 set_buffer_internal (obuf);
5230 return Qnil;
5233 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5234 0, 1, 0,
5235 doc: /* Return the height in lines of the text display area of WINDOW.
5236 WINDOW defaults to the selected window.
5238 The return value does not include the mode line, any header line, nor
5239 any partial-height lines in the text display area. */)
5240 (Lisp_Object window)
5242 struct window *w = decode_window (window);
5243 int pixel_height = window_box_height (w);
5244 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5245 return make_number (line_height);
5250 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5251 1, 1, "P",
5252 doc: /* Position point relative to window.
5253 With no argument, position point at center of window.
5254 An argument specifies vertical position within the window;
5255 zero means top of window, negative means relative to bottom of window. */)
5256 (Lisp_Object arg)
5258 struct window *w = XWINDOW (selected_window);
5259 int lines, start;
5260 Lisp_Object window;
5261 #if 0
5262 int this_scroll_margin;
5263 #endif
5265 if (!(BUFFERP (w->buffer)
5266 && XBUFFER (w->buffer) == current_buffer))
5267 /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
5268 when passed below to set_marker_both. */
5269 error ("move-to-window-line called from unrelated buffer");
5271 window = selected_window;
5272 start = marker_position (w->start);
5273 if (start < BEGV || start > ZV)
5275 int height = window_internal_height (w);
5276 Fvertical_motion (make_number (- (height / 2)), window);
5277 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5278 w->start_at_line_beg = Fbolp ();
5279 w->force_start = Qt;
5281 else
5282 Fgoto_char (w->start);
5284 lines = displayed_window_lines (w);
5286 #if 0
5287 this_scroll_margin = max (0, scroll_margin);
5288 this_scroll_margin = min (this_scroll_margin, lines / 4);
5289 #endif
5291 if (NILP (arg))
5292 XSETFASTINT (arg, lines / 2);
5293 else
5295 int iarg = XINT (Fprefix_numeric_value (arg));
5297 if (iarg < 0)
5298 iarg = iarg + lines;
5300 #if 0 /* This code would prevent move-to-window-line from moving point
5301 to a place inside the scroll margins (which would cause the
5302 next redisplay to scroll). I wrote this code, but then concluded
5303 it is probably better not to install it. However, it is here
5304 inside #if 0 so as not to lose it. -- rms. */
5306 /* Don't let it get into the margin at either top or bottom. */
5307 iarg = max (iarg, this_scroll_margin);
5308 iarg = min (iarg, lines - this_scroll_margin - 1);
5309 #endif
5311 arg = make_number (iarg);
5314 /* Skip past a partially visible first line. */
5315 if (w->vscroll)
5316 XSETINT (arg, XINT (arg) + 1);
5318 return Fvertical_motion (arg, window);
5323 /***********************************************************************
5324 Window Configuration
5325 ***********************************************************************/
5327 struct save_window_data
5329 struct vectorlike_header header;
5330 Lisp_Object selected_frame;
5331 Lisp_Object current_window;
5332 Lisp_Object current_buffer;
5333 Lisp_Object minibuf_scroll_window;
5334 Lisp_Object minibuf_selected_window;
5335 Lisp_Object root_window;
5336 Lisp_Object focus_frame;
5337 /* A vector, each of whose elements is a struct saved_window
5338 for one window. */
5339 Lisp_Object saved_windows;
5341 /* All fields above are traced by the GC.
5342 From `fame-cols' down, the fields are ignored by the GC. */
5344 int frame_cols, frame_lines, frame_menu_bar_lines;
5345 int frame_tool_bar_lines;
5348 /* This is saved as a Lisp_Vector */
5349 struct saved_window
5351 struct vectorlike_header header;
5353 Lisp_Object window, clone_number;
5354 Lisp_Object buffer, start, pointm, mark;
5355 Lisp_Object left_col, top_line, total_cols, total_lines;
5356 Lisp_Object normal_cols, normal_lines;
5357 Lisp_Object hscroll, min_hscroll;
5358 Lisp_Object parent, prev;
5359 Lisp_Object start_at_line_beg;
5360 Lisp_Object display_table;
5361 Lisp_Object left_margin_cols, right_margin_cols;
5362 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5363 Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
5364 Lisp_Object splits, nest, window_parameters;
5367 #define SAVED_WINDOW_N(swv,n) \
5368 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5370 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5371 doc: /* Return t if OBJECT is a window-configuration object. */)
5372 (Lisp_Object object)
5374 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5377 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5378 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5379 (Lisp_Object config)
5381 register struct save_window_data *data;
5382 struct Lisp_Vector *saved_windows;
5384 CHECK_WINDOW_CONFIGURATION (config);
5386 data = (struct save_window_data *) XVECTOR (config);
5387 saved_windows = XVECTOR (data->saved_windows);
5388 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5391 DEFUN ("set-window-configuration", Fset_window_configuration,
5392 Sset_window_configuration, 1, 1, 0,
5393 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5394 CONFIGURATION must be a value previously returned
5395 by `current-window-configuration' (which see).
5396 If CONFIGURATION was made from a frame that is now deleted,
5397 only frame-independent values can be restored. In this case,
5398 the return value is nil. Otherwise the value is t. */)
5399 (Lisp_Object configuration)
5401 register struct save_window_data *data;
5402 struct Lisp_Vector *saved_windows;
5403 Lisp_Object new_current_buffer;
5404 Lisp_Object frame;
5405 Lisp_Object auto_buffer_name;
5406 FRAME_PTR f;
5407 EMACS_INT old_point = -1;
5409 CHECK_WINDOW_CONFIGURATION (configuration);
5411 data = (struct save_window_data *) XVECTOR (configuration);
5412 saved_windows = XVECTOR (data->saved_windows);
5414 new_current_buffer = data->current_buffer;
5415 if (NILP (BVAR (XBUFFER (new_current_buffer), name)))
5416 new_current_buffer = Qnil;
5417 else
5419 if (XBUFFER (new_current_buffer) == current_buffer)
5420 /* The code further down "preserves point" by saving here PT in
5421 old_point and then setting it later back into PT. When the
5422 current-selected-window and the final-selected-window both show
5423 the current buffer, this suffers from the problem that the
5424 current PT is the window-point of the current-selected-window,
5425 while the final PT is the point of the final-selected-window, so
5426 this copy from one PT to the other would end up moving the
5427 window-point of the final-selected-window to the window-point of
5428 the current-selected-window. So we have to be careful which
5429 point of the current-buffer we copy into old_point. */
5430 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5431 && WINDOWP (selected_window)
5432 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
5433 && !EQ (selected_window, data->current_window))
5434 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5435 else
5436 old_point = PT;
5437 else
5438 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5439 point in new_current_buffer as of the last time this buffer was
5440 used. This can be non-deterministic since it can be changed by
5441 things like jit-lock by mere temporary selection of some random
5442 window that happens to show this buffer.
5443 So if possible we want this arbitrary choice of "which point" to
5444 be the one from the to-be-selected-window so as to prevent this
5445 window's cursor from being copied from another window. */
5446 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5447 /* If current_window = selected_window, its point is in BUF_PT. */
5448 && !EQ (selected_window, data->current_window))
5449 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5450 else
5451 old_point = BUF_PT (XBUFFER (new_current_buffer));
5454 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5455 f = XFRAME (frame);
5457 /* If f is a dead frame, don't bother rebuilding its window tree.
5458 However, there is other stuff we should still try to do below. */
5459 if (FRAME_LIVE_P (f))
5461 Lisp_Object window;
5462 Lisp_Object dead_windows = Qnil;
5463 register struct window *w;
5464 register struct saved_window *p;
5465 struct window *root_window;
5466 struct window **leaf_windows;
5467 int n_leaf_windows;
5468 int k, i, n;
5470 /* If the frame has been resized since this window configuration was
5471 made, we change the frame to the size specified in the
5472 configuration, restore the configuration, and then resize it
5473 back. We keep track of the prevailing height in these variables. */
5474 int previous_frame_lines = FRAME_LINES (f);
5475 int previous_frame_cols = FRAME_COLS (f);
5476 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5477 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5479 /* The mouse highlighting code could get screwed up
5480 if it runs during this. */
5481 BLOCK_INPUT;
5483 if (data->frame_lines != previous_frame_lines
5484 || data->frame_cols != previous_frame_cols)
5485 change_frame_size (f, data->frame_lines,
5486 data->frame_cols, 0, 0, 0);
5487 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5488 if (data->frame_menu_bar_lines
5489 != previous_frame_menu_bar_lines)
5490 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
5491 make_number (0));
5492 #ifdef HAVE_WINDOW_SYSTEM
5493 if (data->frame_tool_bar_lines
5494 != previous_frame_tool_bar_lines)
5495 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
5496 make_number (0));
5497 #endif
5498 #endif
5500 /* "Swap out" point from the selected window's buffer
5501 into the window itself. (Normally the pointm of the selected
5502 window holds garbage.) We do this now, before
5503 restoring the window contents, and prevent it from
5504 being done later on when we select a new window. */
5505 if (! NILP (XWINDOW (selected_window)->buffer))
5507 w = XWINDOW (selected_window);
5508 set_marker_both (w->pointm,
5509 w->buffer,
5510 BUF_PT (XBUFFER (w->buffer)),
5511 BUF_PT_BYTE (XBUFFER (w->buffer)));
5514 windows_or_buffers_changed++;
5515 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5517 /* Problem: Freeing all matrices and later allocating them again
5518 is a serious redisplay flickering problem. What we would
5519 really like to do is to free only those matrices not reused
5520 below. */
5521 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5522 leaf_windows
5523 = (struct window **) alloca (count_windows (root_window)
5524 * sizeof (struct window *));
5525 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5527 /* Kludge Alert!
5528 Mark all windows now on frame as "deleted".
5529 Restoring the new configuration "undeletes" any that are in it.
5531 Save their current buffers in their height fields, since we may
5532 need it later, if a buffer saved in the configuration is now
5533 dead. */
5534 delete_all_subwindows (FRAME_ROOT_WINDOW (f));
5536 for (k = 0; k < saved_windows->header.size; k++)
5538 p = SAVED_WINDOW_N (saved_windows, k);
5539 window = p->window;
5540 w = XWINDOW (window);
5541 w->next = Qnil;
5543 if (!NILP (p->parent))
5544 w->parent = SAVED_WINDOW_N (saved_windows,
5545 XFASTINT (p->parent))->window;
5546 else
5547 w->parent = Qnil;
5549 if (!NILP (p->prev))
5551 w->prev = SAVED_WINDOW_N (saved_windows,
5552 XFASTINT (p->prev))->window;
5553 XWINDOW (w->prev)->next = p->window;
5555 else
5557 w->prev = Qnil;
5558 if (!NILP (w->parent))
5560 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
5562 XWINDOW (w->parent)->vchild = p->window;
5563 XWINDOW (w->parent)->hchild = Qnil;
5565 else
5567 XWINDOW (w->parent)->hchild = p->window;
5568 XWINDOW (w->parent)->vchild = Qnil;
5573 w->clone_number = p->clone_number;
5574 /* If we squirreled away the buffer in the window's height,
5575 restore it now. */
5576 if (BUFFERP (w->total_lines))
5577 w->buffer = w->total_lines;
5578 w->left_col = p->left_col;
5579 w->top_line = p->top_line;
5580 w->total_cols = p->total_cols;
5581 w->total_lines = p->total_lines;
5582 w->normal_cols = p->normal_cols;
5583 w->normal_lines = p->normal_lines;
5584 w->hscroll = p->hscroll;
5585 w->min_hscroll = p->min_hscroll;
5586 w->display_table = p->display_table;
5587 w->left_margin_cols = p->left_margin_cols;
5588 w->right_margin_cols = p->right_margin_cols;
5589 w->left_fringe_width = p->left_fringe_width;
5590 w->right_fringe_width = p->right_fringe_width;
5591 w->fringes_outside_margins = p->fringes_outside_margins;
5592 w->scroll_bar_width = p->scroll_bar_width;
5593 w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
5594 w->dedicated = p->dedicated;
5595 w->splits = p->splits;
5596 w->nest = p->nest;
5597 w->window_parameters = p->window_parameters;
5598 XSETFASTINT (w->last_modified, 0);
5599 XSETFASTINT (w->last_overlay_modified, 0);
5601 /* Reinstall the saved buffer and pointers into it. */
5602 if (NILP (p->buffer))
5603 /* An internal window. */
5604 w->buffer = p->buffer;
5605 else if (!NILP (BVAR (XBUFFER (p->buffer), name)))
5606 /* If saved buffer is alive, install it. */
5608 w->buffer = p->buffer;
5609 w->start_at_line_beg = p->start_at_line_beg;
5610 set_marker_restricted (w->start, p->start, w->buffer);
5611 set_marker_restricted (w->pointm, p->pointm, w->buffer);
5612 Fset_marker (BVAR (XBUFFER (w->buffer), mark),
5613 p->mark, w->buffer);
5615 /* As documented in Fcurrent_window_configuration, don't
5616 restore the location of point in the buffer which was
5617 current when the window configuration was recorded. */
5618 if (!EQ (p->buffer, new_current_buffer)
5619 && XBUFFER (p->buffer) == current_buffer)
5620 Fgoto_char (w->pointm);
5622 else if (!NILP (w->buffer) && !NILP (BVAR (XBUFFER (w->buffer), name)))
5623 /* Keep window's old buffer; make sure the markers are
5624 real. */
5626 /* Set window markers at start of visible range. */
5627 if (XMARKER (w->start)->buffer == 0)
5628 set_marker_restricted (w->start, make_number (0),
5629 w->buffer);
5630 if (XMARKER (w->pointm)->buffer == 0)
5631 set_marker_restricted_both (w->pointm, w->buffer,
5632 BUF_PT (XBUFFER (w->buffer)),
5633 BUF_PT_BYTE (XBUFFER (w->buffer)));
5634 w->start_at_line_beg = Qt;
5636 else if (STRINGP (auto_buffer_name =
5637 Fwindow_parameter (window, Qauto_buffer_name))
5638 && SCHARS (auto_buffer_name) != 0
5639 && !NILP (w->buffer = Fget_buffer_create (auto_buffer_name)))
5641 set_marker_restricted (w->start, make_number (0), w->buffer);
5642 set_marker_restricted (w->pointm, make_number (0), w->buffer);
5643 w->start_at_line_beg = Qt;
5645 else
5646 /* Window has no live buffer, get one. */
5648 /* Get the buffer via other_buffer_safely in order to
5649 avoid showing an unimportant buffer and, if necessary, to
5650 recreate *scratch* in the course (part of Juanma's bs-show
5651 scenario from March 2011). */
5652 w->buffer = other_buffer_safely (Fcurrent_buffer ());
5653 /* This will set the markers to beginning of visible
5654 range. */
5655 set_marker_restricted (w->start, make_number (0), w->buffer);
5656 set_marker_restricted (w->pointm, make_number (0), w->buffer);
5657 w->start_at_line_beg = Qt;
5658 if (!NILP (w->dedicated))
5659 /* Record this window as dead. */
5660 dead_windows = Fcons (window, dead_windows);
5661 /* Make sure window is no more dedicated. */
5662 w->dedicated = Qnil;
5666 FRAME_ROOT_WINDOW (f) = data->root_window;
5667 /* Arrange *not* to restore point in the buffer that was
5668 current when the window configuration was saved. */
5669 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5670 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5671 make_number (old_point),
5672 XWINDOW (data->current_window)->buffer);
5674 /* In the following call to `select-window', prevent "swapping out
5675 point" in the old selected window using the buffer that has
5676 been restored into it. We already swapped out that point from
5677 that window's old buffer. */
5678 select_window (data->current_window, Qnil, 1);
5679 BVAR (XBUFFER (XWINDOW (selected_window)->buffer), last_selected_window)
5680 = selected_window;
5682 if (NILP (data->focus_frame)
5683 || (FRAMEP (data->focus_frame)
5684 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5685 Fredirect_frame_focus (frame, data->focus_frame);
5687 /* Set the screen height to the value it had before this function. */
5688 if (previous_frame_lines != FRAME_LINES (f)
5689 || previous_frame_cols != FRAME_COLS (f))
5690 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5691 0, 0, 0);
5692 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5693 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5694 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5695 make_number (0));
5696 #ifdef HAVE_WINDOW_SYSTEM
5697 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5698 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5699 make_number (0));
5700 #endif
5701 #endif
5703 /* Now, free glyph matrices in windows that were not reused. */
5704 for (i = n = 0; i < n_leaf_windows; ++i)
5706 if (NILP (leaf_windows[i]->buffer))
5708 /* Assert it's not reused as a combination. */
5709 xassert (NILP (leaf_windows[i]->hchild)
5710 && NILP (leaf_windows[i]->vchild));
5711 free_window_matrices (leaf_windows[i]);
5713 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5714 ++n;
5717 adjust_glyphs (f);
5718 UNBLOCK_INPUT;
5720 /* Scan dead buffer windows. */
5721 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
5723 window = XCAR (dead_windows);
5724 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
5725 delete_deletable_window (window);
5728 /* Fselect_window will have made f the selected frame, so we
5729 reselect the proper frame here. Fhandle_switch_frame will change the
5730 selected window too, but that doesn't make the call to
5731 Fselect_window above totally superfluous; it still sets f's
5732 selected window. */
5733 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5734 do_switch_frame (data->selected_frame, 0, 0, Qnil);
5736 run_window_configuration_change_hook (f);
5739 if (!NILP (new_current_buffer))
5740 Fset_buffer (new_current_buffer);
5742 Vminibuf_scroll_window = data->minibuf_scroll_window;
5743 minibuf_selected_window = data->minibuf_selected_window;
5745 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5749 /* Delete all subwindows of the parent window of WINDOW. */
5750 void
5751 delete_all_subwindows (Lisp_Object window)
5753 register struct window *w;
5755 w = XWINDOW (window);
5757 if (!NILP (w->next))
5758 /* Delete WINDOW's siblings (we traverse postorderly). */
5759 delete_all_subwindows (w->next);
5761 w->total_lines = w->buffer; /* See Fset_window_configuration for excuse. */
5763 if (!NILP (w->vchild))
5765 delete_all_subwindows (w->vchild);
5766 w->vchild = Qnil;
5768 else if (!NILP (w->hchild))
5770 delete_all_subwindows (w->hchild);
5771 w->hchild = Qnil;
5773 else if (!NILP (w->buffer))
5775 unshow_buffer (w);
5776 unchain_marker (XMARKER (w->pointm));
5777 unchain_marker (XMARKER (w->start));
5778 w->buffer = Qnil;
5781 Vwindow_list = Qnil;
5784 static int
5785 count_windows (register struct window *window)
5787 register int count = 1;
5788 if (!NILP (window->next))
5789 count += count_windows (XWINDOW (window->next));
5790 if (!NILP (window->vchild))
5791 count += count_windows (XWINDOW (window->vchild));
5792 if (!NILP (window->hchild))
5793 count += count_windows (XWINDOW (window->hchild));
5794 return count;
5798 /* Fill vector FLAT with leaf windows under W, starting at index I.
5799 Value is last index + 1. */
5800 static int
5801 get_leaf_windows (struct window *w, struct window **flat, int i)
5803 while (w)
5805 if (!NILP (w->hchild))
5806 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5807 else if (!NILP (w->vchild))
5808 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5809 else
5810 flat[i++] = w;
5812 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5815 return i;
5819 /* Return a pointer to the glyph W's physical cursor is on. Value is
5820 null if W's current matrix is invalid, so that no meaningfull glyph
5821 can be returned. */
5822 struct glyph *
5823 get_phys_cursor_glyph (struct window *w)
5825 struct glyph_row *row;
5826 struct glyph *glyph;
5828 if (w->phys_cursor.vpos >= 0
5829 && w->phys_cursor.vpos < w->current_matrix->nrows
5830 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
5831 row->enabled_p)
5832 && row->used[TEXT_AREA] > w->phys_cursor.hpos)
5833 glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
5834 else
5835 glyph = NULL;
5837 return glyph;
5841 static int
5842 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
5844 register struct saved_window *p;
5845 register struct window *w;
5846 register Lisp_Object tem;
5848 for (;!NILP (window); window = w->next)
5850 p = SAVED_WINDOW_N (vector, i);
5851 w = XWINDOW (window);
5853 XSETFASTINT (w->temslot, i); i++;
5854 p->window = window;
5855 p->clone_number = w->clone_number;
5856 p->buffer = w->buffer;
5857 p->left_col = w->left_col;
5858 p->top_line = w->top_line;
5859 p->total_cols = w->total_cols;
5860 p->total_lines = w->total_lines;
5861 p->normal_cols = w->normal_cols;
5862 p->normal_lines = w->normal_lines;
5863 p->hscroll = w->hscroll;
5864 p->min_hscroll = w->min_hscroll;
5865 p->display_table = w->display_table;
5866 p->left_margin_cols = w->left_margin_cols;
5867 p->right_margin_cols = w->right_margin_cols;
5868 p->left_fringe_width = w->left_fringe_width;
5869 p->right_fringe_width = w->right_fringe_width;
5870 p->fringes_outside_margins = w->fringes_outside_margins;
5871 p->scroll_bar_width = w->scroll_bar_width;
5872 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
5873 p->dedicated = w->dedicated;
5874 p->splits = w->splits;
5875 p->nest = w->nest;
5876 p->window_parameters = w->window_parameters;
5877 if (!NILP (w->buffer))
5879 /* Save w's value of point in the window configuration.
5880 If w is the selected window, then get the value of point
5881 from the buffer; pointm is garbage in the selected window. */
5882 if (EQ (window, selected_window))
5884 p->pointm = Fmake_marker ();
5885 set_marker_both (p->pointm, w->buffer,
5886 BUF_PT (XBUFFER (w->buffer)),
5887 BUF_PT_BYTE (XBUFFER (w->buffer)));
5889 else
5890 p->pointm = Fcopy_marker (w->pointm, Qnil);
5892 p->start = Fcopy_marker (w->start, Qnil);
5893 p->start_at_line_beg = w->start_at_line_beg;
5895 tem = BVAR (XBUFFER (w->buffer), mark);
5896 p->mark = Fcopy_marker (tem, Qnil);
5898 else
5900 p->pointm = Qnil;
5901 p->start = Qnil;
5902 p->mark = Qnil;
5903 p->start_at_line_beg = Qnil;
5906 if (NILP (w->parent))
5907 p->parent = Qnil;
5908 else
5909 p->parent = XWINDOW (w->parent)->temslot;
5911 if (NILP (w->prev))
5912 p->prev = Qnil;
5913 else
5914 p->prev = XWINDOW (w->prev)->temslot;
5916 if (!NILP (w->vchild))
5917 i = save_window_save (w->vchild, vector, i);
5918 if (!NILP (w->hchild))
5919 i = save_window_save (w->hchild, vector, i);
5922 return i;
5925 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
5926 Scurrent_window_configuration, 0, 1, 0,
5927 doc: /* Return an object representing the current window configuration of FRAME.
5928 If FRAME is nil or omitted, use the selected frame.
5929 This describes the number of windows, their sizes and current buffers,
5930 and for each displayed buffer, where display starts, and the positions of
5931 point and mark. An exception is made for point in the current buffer:
5932 its value is -not- saved.
5933 This also records the currently selected frame, and FRAME's focus
5934 redirection (see `redirect-frame-focus'). */)
5935 (Lisp_Object frame)
5937 register Lisp_Object tem;
5938 register int n_windows;
5939 register struct save_window_data *data;
5940 register int i;
5941 FRAME_PTR f;
5943 if (NILP (frame))
5944 frame = selected_frame;
5945 CHECK_LIVE_FRAME (frame);
5946 f = XFRAME (frame);
5948 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
5949 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
5950 PVEC_WINDOW_CONFIGURATION);
5952 data->frame_cols = FRAME_COLS (f);
5953 data->frame_lines = FRAME_LINES (f);
5954 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5955 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5956 data->selected_frame = selected_frame;
5957 data->current_window = FRAME_SELECTED_WINDOW (f);
5958 XSETBUFFER (data->current_buffer, current_buffer);
5959 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
5960 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
5961 data->root_window = FRAME_ROOT_WINDOW (f);
5962 data->focus_frame = FRAME_FOCUS_FRAME (f);
5963 tem = Fmake_vector (make_number (n_windows), Qnil);
5964 data->saved_windows = tem;
5965 for (i = 0; i < n_windows; i++)
5966 XVECTOR (tem)->contents[i]
5967 = Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
5968 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
5969 XSETWINDOW_CONFIGURATION (tem, data);
5970 return (tem);
5973 DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
5974 0, UNEVALLED, 0,
5975 doc: /* Execute BODY, preserving window sizes and contents.
5976 Return the value of the last form in BODY.
5977 Restore which buffer appears in which window, where display starts,
5978 and the value of point and mark for each window.
5979 Also restore the choice of selected window.
5980 Also restore which buffer is current.
5981 Does not restore the value of point in current buffer.
5982 usage: (save-window-excursion BODY...) */)
5983 (Lisp_Object args)
5985 register Lisp_Object val;
5986 register int count = SPECPDL_INDEX ();
5988 record_unwind_protect (Fset_window_configuration,
5989 Fcurrent_window_configuration (Qnil));
5990 val = Fprogn (args);
5991 return unbind_to (count, val);
5994 /***********************************************************************
5995 Marginal Areas
5996 ***********************************************************************/
5998 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
5999 2, 3, 0,
6000 doc: /* Set width of marginal areas of window WINDOW.
6001 If WINDOW is nil, set margins of the currently selected window.
6002 Second arg LEFT-WIDTH specifies the number of character cells to
6003 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6004 does the same for the right marginal area. A nil width parameter
6005 means no margin. */)
6006 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6008 struct window *w = decode_window (window);
6010 /* Translate negative or zero widths to nil.
6011 Margins that are too wide have to be checked elsewhere. */
6013 if (!NILP (left_width))
6015 CHECK_NUMBER (left_width);
6016 if (XINT (left_width) <= 0)
6017 left_width = Qnil;
6020 if (!NILP (right_width))
6022 CHECK_NUMBER (right_width);
6023 if (XINT (right_width) <= 0)
6024 right_width = Qnil;
6027 if (!EQ (w->left_margin_cols, left_width)
6028 || !EQ (w->right_margin_cols, right_width))
6030 w->left_margin_cols = left_width;
6031 w->right_margin_cols = right_width;
6033 adjust_window_margins (w);
6035 ++windows_or_buffers_changed;
6036 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6039 return Qnil;
6043 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6044 0, 1, 0,
6045 doc: /* Get width of marginal areas of window WINDOW.
6046 If WINDOW is omitted or nil, use the currently selected window.
6047 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6048 If a marginal area does not exist, its width will be returned
6049 as nil. */)
6050 (Lisp_Object window)
6052 struct window *w = decode_window (window);
6053 return Fcons (w->left_margin_cols, w->right_margin_cols);
6058 /***********************************************************************
6059 Fringes
6060 ***********************************************************************/
6062 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6063 2, 4, 0,
6064 doc: /* Set the fringe widths of window WINDOW.
6065 If WINDOW is nil, set the fringe widths of the currently selected
6066 window.
6067 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6068 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6069 fringe width. If a fringe width arg is nil, that means to use the
6070 frame's default fringe width. Default fringe widths can be set with
6071 the command `set-fringe-style'.
6072 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6073 outside of the display margins. By default, fringes are drawn between
6074 display marginal areas and the text area. */)
6075 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width, Lisp_Object outside_margins)
6077 struct window *w = decode_window (window);
6079 if (!NILP (left_width))
6080 CHECK_NATNUM (left_width);
6081 if (!NILP (right_width))
6082 CHECK_NATNUM (right_width);
6084 /* Do nothing on a tty. */
6085 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6086 && (!EQ (w->left_fringe_width, left_width)
6087 || !EQ (w->right_fringe_width, right_width)
6088 || !EQ (w->fringes_outside_margins, outside_margins)))
6090 w->left_fringe_width = left_width;
6091 w->right_fringe_width = right_width;
6092 w->fringes_outside_margins = outside_margins;
6094 adjust_window_margins (w);
6096 clear_glyph_matrix (w->current_matrix);
6097 w->window_end_valid = Qnil;
6099 ++windows_or_buffers_changed;
6100 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6103 return Qnil;
6107 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6108 0, 1, 0,
6109 doc: /* Get width of fringes of window WINDOW.
6110 If WINDOW is omitted or nil, use the currently selected window.
6111 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6112 (Lisp_Object window)
6114 struct window *w = decode_window (window);
6116 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6117 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6118 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6119 ? Qt : Qnil), Qnil)));
6124 /***********************************************************************
6125 Scroll bars
6126 ***********************************************************************/
6128 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
6129 Sset_window_scroll_bars, 2, 4, 0,
6130 doc: /* Set width and type of scroll bars of window WINDOW.
6131 If window is nil, set scroll bars of the currently selected window.
6132 Second parameter WIDTH specifies the pixel width for the scroll bar;
6133 this is automatically adjusted to a multiple of the frame column width.
6134 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6135 bar: left, right, or nil.
6136 If WIDTH is nil, use the frame's scroll-bar width.
6137 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6138 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6139 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, Lisp_Object horizontal_type)
6141 struct window *w = decode_window (window);
6143 if (!NILP (width))
6145 CHECK_NATNUM (width);
6147 if (XINT (width) == 0)
6148 vertical_type = Qnil;
6151 if (!(NILP (vertical_type)
6152 || EQ (vertical_type, Qleft)
6153 || EQ (vertical_type, Qright)
6154 || EQ (vertical_type, Qt)))
6155 error ("Invalid type of vertical scroll bar");
6157 if (!EQ (w->scroll_bar_width, width)
6158 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6160 w->scroll_bar_width = width;
6161 w->vertical_scroll_bar_type = vertical_type;
6163 adjust_window_margins (w);
6165 clear_glyph_matrix (w->current_matrix);
6166 w->window_end_valid = Qnil;
6168 ++windows_or_buffers_changed;
6169 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6172 return Qnil;
6176 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6177 0, 1, 0,
6178 doc: /* Get width and type of scroll bars of window WINDOW.
6179 If WINDOW is omitted or nil, use the currently selected window.
6180 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6181 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6182 value. */)
6183 (Lisp_Object window)
6185 struct window *w = decode_window (window);
6186 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6187 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6188 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6189 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6190 Fcons (w->vertical_scroll_bar_type,
6191 Fcons (Qnil, Qnil))));
6196 /***********************************************************************
6197 Smooth scrolling
6198 ***********************************************************************/
6200 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6201 doc: /* Return the amount by which WINDOW is scrolled vertically.
6202 Use the selected window if WINDOW is nil or omitted.
6203 Normally, value is a multiple of the canonical character height of WINDOW;
6204 optional second arg PIXELS-P means value is measured in pixels. */)
6205 (Lisp_Object window, Lisp_Object pixels_p)
6207 Lisp_Object result;
6208 struct frame *f;
6209 struct window *w;
6211 if (NILP (window))
6212 window = selected_window;
6213 else
6214 CHECK_WINDOW (window);
6215 w = XWINDOW (window);
6216 f = XFRAME (w->frame);
6218 if (FRAME_WINDOW_P (f))
6219 result = (NILP (pixels_p)
6220 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6221 : make_number (-w->vscroll));
6222 else
6223 result = make_number (0);
6224 return result;
6228 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6229 2, 3, 0,
6230 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6231 WINDOW nil means use the selected window. Normally, VSCROLL is a
6232 non-negative multiple of the canonical character height of WINDOW;
6233 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6234 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6235 corresponds to an integral number of pixels. The return value is the
6236 result of this rounding.
6237 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6238 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
6240 struct window *w;
6241 struct frame *f;
6243 if (NILP (window))
6244 window = selected_window;
6245 else
6246 CHECK_WINDOW (window);
6247 CHECK_NUMBER_OR_FLOAT (vscroll);
6249 w = XWINDOW (window);
6250 f = XFRAME (w->frame);
6252 if (FRAME_WINDOW_P (f))
6254 int old_dy = w->vscroll;
6256 w->vscroll = - (NILP (pixels_p)
6257 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6258 : XFLOATINT (vscroll));
6259 w->vscroll = min (w->vscroll, 0);
6261 if (w->vscroll != old_dy)
6263 /* Adjust glyph matrix of the frame if the virtual display
6264 area becomes larger than before. */
6265 if (w->vscroll < 0 && w->vscroll < old_dy)
6266 adjust_glyphs (f);
6268 /* Prevent redisplay shortcuts. */
6269 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6273 return Fwindow_vscroll (window, pixels_p);
6277 /* Call FN for all leaf windows on frame F. FN is called with the
6278 first argument being a pointer to the leaf window, and with
6279 additional argument USER_DATA. Stops when FN returns 0. */
6281 static void
6282 foreach_window (struct frame *f, int (*fn) (struct window *, void *),
6283 void *user_data)
6285 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6286 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6287 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6291 /* Helper function for foreach_window. Call FN for all leaf windows
6292 reachable from W. FN is called with the first argument being a
6293 pointer to the leaf window, and with additional argument USER_DATA.
6294 Stop when FN returns 0. Value is 0 if stopped by FN. */
6296 static int
6297 foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
6299 int cont;
6301 for (cont = 1; w && cont;)
6303 if (!NILP (w->hchild))
6304 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6305 else if (!NILP (w->vchild))
6306 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6307 else
6308 cont = fn (w, user_data);
6310 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6313 return cont;
6317 /* Freeze or unfreeze the window start of W unless it is a
6318 mini-window or the selected window. FREEZE_P non-null means freeze
6319 the window start. */
6321 static int
6322 freeze_window_start (struct window *w, void *freeze_p)
6324 if (MINI_WINDOW_P (w)
6325 || (WINDOWP (selected_window) /* Can be nil in corner cases. */
6326 && (w == XWINDOW (selected_window)
6327 || (MINI_WINDOW_P (XWINDOW (selected_window))
6328 && ! NILP (Vminibuf_scroll_window)
6329 && w == XWINDOW (Vminibuf_scroll_window)))))
6330 freeze_p = NULL;
6332 w->frozen_window_start_p = freeze_p != NULL;
6333 return 1;
6337 /* Freeze or unfreeze the window starts of all leaf windows on frame
6338 F, except the selected window and a mini-window. FREEZE_P non-zero
6339 means freeze the window start. */
6341 void
6342 freeze_window_starts (struct frame *f, int freeze_p)
6344 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6348 /***********************************************************************
6349 Initialization
6350 ***********************************************************************/
6352 /* Return 1 if window configurations CONFIGURATION1 and CONFIGURATION2
6353 describe the same state of affairs. This is used by Fequal.
6355 ignore_positions non-zero means ignore non-matching scroll positions
6356 and the like.
6358 This ignores a couple of things like the dedicatedness status of
6359 window, splits, nest and the like. This might have to be fixed. */
6362 compare_window_configurations (Lisp_Object configuration1, Lisp_Object configuration2, int ignore_positions)
6364 register struct save_window_data *d1, *d2;
6365 struct Lisp_Vector *sws1, *sws2;
6366 int i;
6368 CHECK_WINDOW_CONFIGURATION (configuration1);
6369 CHECK_WINDOW_CONFIGURATION (configuration2);
6371 d1 = (struct save_window_data *) XVECTOR (configuration1);
6372 d2 = (struct save_window_data *) XVECTOR (configuration2);
6373 sws1 = XVECTOR (d1->saved_windows);
6374 sws2 = XVECTOR (d2->saved_windows);
6376 /* Frame settings must match. */
6377 if (d1->frame_cols != d2->frame_cols
6378 || d1->frame_lines != d2->frame_lines
6379 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
6380 || !EQ (d1->selected_frame, d2->selected_frame)
6381 || !EQ (d1->current_buffer, d2->current_buffer)
6382 || (!ignore_positions
6383 && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
6384 || !EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)))
6385 || !EQ (d1->focus_frame, d2->focus_frame)
6386 /* Verify that the two configurations have the same number of windows. */
6387 || sws1->header.size != sws2->header.size)
6388 return 0;
6390 for (i = 0; i < sws1->header.size; i++)
6392 struct saved_window *sw1, *sw2;
6393 int w1_is_current, w2_is_current;
6395 sw1 = SAVED_WINDOW_N (sws1, i);
6396 sw2 = SAVED_WINDOW_N (sws2, i);
6398 if (
6399 /* The "current" windows in the two configurations must
6400 correspond to each other. */
6401 EQ (d1->current_window, sw1->window)
6402 != EQ (d2->current_window, sw2->window)
6403 /* Windows' buffers must match. */
6404 || !EQ (sw1->buffer, sw2->buffer)
6405 || !EQ (sw1->left_col, sw2->left_col)
6406 || !EQ (sw1->top_line, sw2->top_line)
6407 || !EQ (sw1->total_cols, sw2->total_cols)
6408 || !EQ (sw1->total_lines, sw2->total_lines)
6409 || !EQ (sw1->display_table, sw2->display_table)
6410 /* The next two disjuncts check the window structure for
6411 equality. */
6412 || !EQ (sw1->parent, sw2->parent)
6413 || !EQ (sw1->prev, sw2->prev)
6414 || (!ignore_positions
6415 && (!EQ (sw1->hscroll, sw2->hscroll)
6416 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
6417 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
6418 || NILP (Fequal (sw1->start, sw2->start))
6419 || NILP (Fequal (sw1->pointm, sw2->pointm))
6420 || NILP (Fequal (sw1->mark, sw2->mark))))
6421 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
6422 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
6423 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
6424 || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
6425 || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
6426 || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
6427 || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type))
6428 return 0;
6431 return 1;
6434 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6435 Scompare_window_configurations, 2, 2, 0,
6436 doc: /* Compare two window configurations as regards the structure of windows.
6437 This function ignores details such as the values of point and mark
6438 and scrolling positions. */)
6439 (Lisp_Object x, Lisp_Object y)
6441 if (compare_window_configurations (x, y, 1))
6442 return Qt;
6443 return Qnil;
6446 void
6447 init_window_once (void)
6449 struct frame *f = make_initial_frame ();
6450 XSETFRAME (selected_frame, f);
6451 Vterminal_frame = selected_frame;
6452 minibuf_window = f->minibuffer_window;
6453 selected_window = f->selected_window;
6454 last_nonminibuf_frame = f;
6456 window_initialized = 1;
6459 void
6460 init_window (void)
6462 Vwindow_list = Qnil;
6465 void
6466 syms_of_window (void)
6468 Qscroll_up = intern_c_string ("scroll-up");
6469 staticpro (&Qscroll_up);
6471 Qscroll_down = intern_c_string ("scroll-down");
6472 staticpro (&Qscroll_down);
6474 Qscroll_command = intern_c_string ("scroll-command");
6475 staticpro (&Qscroll_command);
6477 Fput (Qscroll_up, Qscroll_command, Qt);
6478 Fput (Qscroll_down, Qscroll_command, Qt);
6480 staticpro (&Qwindow_configuration_change_hook);
6481 Qwindow_configuration_change_hook
6482 = intern_c_string ("window-configuration-change-hook");
6484 Qwindowp = intern_c_string ("windowp");
6485 staticpro (&Qwindowp);
6487 Qwindow_configuration_p = intern_c_string ("window-configuration-p");
6488 staticpro (&Qwindow_configuration_p);
6490 Qwindow_live_p = intern_c_string ("window-live-p");
6491 staticpro (&Qwindow_live_p);
6493 Qwindow_deletable_p = intern_c_string ("window-deletable-p");
6494 staticpro (&Qwindow_deletable_p);
6496 Qdelete_window = intern_c_string ("delete-window");
6497 staticpro (&Qdelete_window);
6499 Qresize_root_window = intern_c_string ("resize-root-window");
6500 staticpro (&Qresize_root_window);
6502 Qresize_root_window_vertically = intern_c_string ("resize-root-window-vertically");
6503 staticpro (&Qresize_root_window_vertically);
6505 Qsafe = intern_c_string ("safe");
6506 staticpro (&Qsafe);
6508 Qdisplay_buffer = intern_c_string ("display-buffer");
6509 staticpro (&Qdisplay_buffer);
6511 Qreplace_buffer_in_windows = intern_c_string ("replace-buffer-in-windows");
6512 staticpro (&Qreplace_buffer_in_windows);
6514 Qrecord_window_buffer = intern_c_string ("record-window-buffer");
6515 staticpro (&Qrecord_window_buffer);
6517 Qget_mru_window = intern_c_string ("get-mru-window");
6518 staticpro (&Qget_mru_window);
6520 Qtemp_buffer_show_hook = intern_c_string ("temp-buffer-show-hook");
6521 staticpro (&Qtemp_buffer_show_hook);
6523 Qabove = intern_c_string ("above");
6524 staticpro (&Qabove);
6526 Qbelow = intern_c_string ("below");
6527 staticpro (&Qbelow);
6529 Qauto_buffer_name = intern_c_string ("auto-buffer-name");
6530 staticpro (&Qauto_buffer_name);
6532 staticpro (&Vwindow_list);
6534 minibuf_selected_window = Qnil;
6535 staticpro (&minibuf_selected_window);
6537 window_scroll_pixel_based_preserve_x = -1;
6538 window_scroll_pixel_based_preserve_y = -1;
6539 window_scroll_preserve_hpos = -1;
6540 window_scroll_preserve_vpos = -1;
6542 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
6543 doc: /* Non-nil means call as function to display a help buffer.
6544 The function is called with one argument, the buffer to be displayed.
6545 Used by `with-output-to-temp-buffer'.
6546 If this function is used, then it must do the entire job of showing
6547 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6548 Vtemp_buffer_show_function = Qnil;
6550 DEFVAR_LISP ("temp-buffer-show-specifiers", Vtemp_buffer_show_specifiers,
6551 doc: /* Buffer display specifiers used by `with-output-to-temp-buffer'.
6552 These specifiers are passed by `with-output-to-temp-buffer' as second
6553 argument to `display-buffer'. Applications should only let-bind this
6554 around a call to `with-output-to-temp-buffer'.
6556 For a description of buffer display specifiers see the variable
6557 `display-buffer-names'. */);
6558 Vtemp_buffer_show_specifiers = Qnil;
6560 DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
6561 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6562 Vminibuf_scroll_window = Qnil;
6564 DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
6565 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6566 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6567 is displayed in the `mode-line' face. */);
6568 mode_line_in_non_selected_windows = 1;
6570 DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
6571 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6572 Vother_window_scroll_buffer = Qnil;
6574 DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
6575 doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
6576 auto_window_vscroll_p = 1;
6578 DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
6579 doc: /* Number of lines of continuity when scrolling by screenfuls. */);
6580 next_screen_context_lines = 2;
6582 DEFVAR_LISP ("scroll-preserve-screen-position",
6583 Vscroll_preserve_screen_position,
6584 doc: /* Controls if scroll commands move point to keep its screen position unchanged.
6585 A value of nil means point does not keep its screen position except
6586 at the scroll margin or window boundary respectively.
6587 A value of t means point keeps its screen position if the scroll
6588 command moved it vertically out of the window, e.g. when scrolling
6589 by full screens.
6590 Any other value means point always keeps its screen position.
6591 Scroll commands should have the `scroll-command' property
6592 on their symbols to be controlled by this variable. */);
6593 Vscroll_preserve_screen_position = Qnil;
6595 DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
6596 doc: /* Type of marker to use for `window-point'. */);
6597 Vwindow_point_insertion_type = Qnil;
6599 DEFVAR_LISP ("window-configuration-change-hook",
6600 Vwindow_configuration_change_hook,
6601 doc: /* Functions to call when window configuration changes.
6602 The buffer-local part is run once per window, with the relevant window
6603 selected; while the global part is run only once for the modified frame,
6604 with the relevant frame selected. */);
6605 Vwindow_configuration_change_hook = Qnil;
6607 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
6608 doc: /* If non-nil, then the `recenter' command with a nil argument
6609 will redraw the entire frame; the special value `tty' causes the
6610 frame to be redrawn only if it is a tty frame. */);
6611 Vrecenter_redisplay = Qtty;
6613 DEFVAR_LISP ("window-splits", Vwindow_splits,
6614 doc: /* Non-nil means splitting windows is handled specially.
6615 If this variable is nil, splitting a window gets the entire screen space
6616 for displaying the new window from the window to split. If this
6617 variable is non-nil, splitting a window may resize all windows in the
6618 same combination. This also allows to split a window that is otherwise
6619 too small or of fixed size.
6621 The value of this variable is also assigned to the split status of the
6622 new window and, provided the old and new window form a new combination,
6623 to the window that was split as well. The split status of a window can
6624 be retrieved with the function `window-splits' and altered by the
6625 function `set-window-splits'.
6627 If the value of the variable `window-nest' is non-nil, the space for the
6628 new window is exclusively taken from the window that shall be split, but
6629 the split status of the window that is split as well as that of the new
6630 window are still set to the value of this variable. */);
6631 Vwindow_splits = Qnil;
6633 DEFVAR_LISP ("window-nest", Vwindow_nest,
6634 doc: /* Non-nil means splitting a window makes a new parent window.
6635 If this variable is nil, splitting a window will create a new parent
6636 window only if the window has no parent window or the window shall
6637 become a combination orthogonal to the one it it is part of.
6639 If this variable is non-nil, splitting a window always creates a new
6640 parent window. If all splits behave this way, each frame's window tree
6641 is a binary tree and every window but the frame's root window has
6642 exactly one sibling.
6644 The value of this variable is also assigned to the nest status of the
6645 new parent window. The nest status of a window can be retrieved via the
6646 function `window-nest' and altered by the function `set-window-nest'. */);
6647 Vwindow_nest = Qnil;
6649 defsubr (&Sselected_window);
6650 defsubr (&Sminibuffer_window);
6651 defsubr (&Swindow_minibuffer_p);
6652 defsubr (&Swindowp);
6653 defsubr (&Swindow_live_p);
6654 defsubr (&Swindow_frame);
6655 defsubr (&Sframe_root_window);
6656 defsubr (&Sframe_first_window);
6657 defsubr (&Sframe_selected_window);
6658 defsubr (&Sset_frame_selected_window);
6659 defsubr (&Spos_visible_in_window_p);
6660 defsubr (&Swindow_line_height);
6661 defsubr (&Swindow_clone_number);
6662 defsubr (&Swindow_buffer);
6663 defsubr (&Swindow_parent);
6664 defsubr (&Swindow_vchild);
6665 defsubr (&Swindow_hchild);
6666 defsubr (&Swindow_next);
6667 defsubr (&Swindow_prev);
6668 defsubr (&Swindow_splits);
6669 defsubr (&Sset_window_splits);
6670 defsubr (&Swindow_nest);
6671 defsubr (&Sset_window_nest);
6672 defsubr (&Swindow_use_time);
6673 defsubr (&Swindow_top_line);
6674 defsubr (&Swindow_left_column);
6675 defsubr (&Swindow_total_size);
6676 defsubr (&Swindow_normal_size);
6677 defsubr (&Swindow_new_total);
6678 defsubr (&Swindow_new_normal);
6679 defsubr (&Sset_window_new_total);
6680 defsubr (&Sset_window_new_normal);
6681 defsubr (&Sresize_window_apply);
6682 defsubr (&Swindow_body_size);
6683 defsubr (&Swindow_hscroll);
6684 defsubr (&Sset_window_hscroll);
6685 defsubr (&Swindow_redisplay_end_trigger);
6686 defsubr (&Sset_window_redisplay_end_trigger);
6687 defsubr (&Swindow_edges);
6688 defsubr (&Swindow_pixel_edges);
6689 defsubr (&Swindow_absolute_pixel_edges);
6690 defsubr (&Swindow_inside_edges);
6691 defsubr (&Swindow_inside_pixel_edges);
6692 defsubr (&Swindow_inside_absolute_pixel_edges);
6693 defsubr (&Scoordinates_in_window_p);
6694 defsubr (&Swindow_at);
6695 defsubr (&Swindow_point);
6696 defsubr (&Swindow_start);
6697 defsubr (&Swindow_end);
6698 defsubr (&Sset_window_point);
6699 defsubr (&Sset_window_start);
6700 defsubr (&Swindow_dedicated_p);
6701 defsubr (&Sset_window_dedicated_p);
6702 defsubr (&Swindow_display_table);
6703 defsubr (&Sset_window_display_table);
6704 defsubr (&Snext_window);
6705 defsubr (&Sprevious_window);
6706 defsubr (&Sget_buffer_window);
6707 defsubr (&Sdelete_other_windows_internal);
6708 defsubr (&Sdelete_window_internal);
6709 defsubr (&Sresize_mini_window_internal);
6710 defsubr (&Sset_window_buffer);
6711 defsubr (&Sset_window_clone_number);
6712 defsubr (&Srun_window_configuration_change_hook);
6713 defsubr (&Sselect_window);
6714 defsubr (&Sforce_window_update);
6715 defsubr (&Stemp_output_buffer_show);
6716 defsubr (&Ssplit_window_internal);
6717 defsubr (&Sscroll_up);
6718 defsubr (&Sscroll_down);
6719 defsubr (&Sscroll_left);
6720 defsubr (&Sscroll_right);
6721 defsubr (&Sother_window_for_scrolling);
6722 defsubr (&Sscroll_other_window);
6723 defsubr (&Sminibuffer_selected_window);
6724 defsubr (&Srecenter);
6725 defsubr (&Swindow_text_height);
6726 defsubr (&Smove_to_window_line);
6727 defsubr (&Swindow_configuration_p);
6728 defsubr (&Swindow_configuration_frame);
6729 defsubr (&Sset_window_configuration);
6730 defsubr (&Scurrent_window_configuration);
6731 defsubr (&Ssave_window_excursion);
6732 defsubr (&Sset_window_margins);
6733 defsubr (&Swindow_margins);
6734 defsubr (&Sset_window_fringes);
6735 defsubr (&Swindow_fringes);
6736 defsubr (&Sset_window_scroll_bars);
6737 defsubr (&Swindow_scroll_bars);
6738 defsubr (&Swindow_vscroll);
6739 defsubr (&Sset_window_vscroll);
6740 defsubr (&Scompare_window_configurations);
6741 defsubr (&Swindow_list);
6742 defsubr (&Swindow_list_1);
6743 defsubr (&Swindow_prev_buffers);
6744 defsubr (&Sset_window_prev_buffers);
6745 defsubr (&Swindow_next_buffers);
6746 defsubr (&Sset_window_next_buffers);
6747 defsubr (&Swindow_parameters);
6748 defsubr (&Swindow_parameter);
6749 defsubr (&Sset_window_parameter);
6752 void
6753 keys_of_window (void)
6755 initial_define_key (control_x_map, '<', "scroll-left");
6756 initial_define_key (control_x_map, '>', "scroll-right");
6758 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
6759 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6760 initial_define_key (meta_map, 'v', "scroll-down-command");