Remove no-longer-needed Solaris 2.4 vfork bug workaround.
[emacs.git] / src / window.c
blobfbccab8b358e1e0a17d8501b51947debc7674e6b
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985-1987, 1993-1998, 2000-2012
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>
23 #define WINDOW_INLINE EXTERN_INLINE
25 #include <stdio.h>
27 #include "lisp.h"
28 #include "character.h"
29 #include "buffer.h"
30 #include "keyboard.h"
31 #include "keymap.h"
32 #include "frame.h"
33 #include "window.h"
34 #include "commands.h"
35 #include "indent.h"
36 #include "termchar.h"
37 #include "disptab.h"
38 #include "dispextern.h"
39 #include "blockinput.h"
40 #include "intervals.h"
41 #include "termhooks.h" /* For FRAME_TERMINAL. */
43 #ifdef HAVE_X_WINDOWS
44 #include "xterm.h"
45 #endif /* HAVE_X_WINDOWS */
46 #ifdef WINDOWSNT
47 #include "w32term.h"
48 #endif
49 #ifdef MSDOS
50 #include "msdos.h"
51 #endif
52 #ifdef HAVE_NS
53 #include "nsterm.h"
54 #endif
56 Lisp_Object Qwindowp, Qwindow_live_p;
57 static Lisp_Object Qwindow_valid_p;
58 static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer;
59 static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
60 static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
61 static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
62 static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
63 static Lisp_Object Qsafe, Qabove, Qbelow;
64 static Lisp_Object Qclone_of;
66 static int displayed_window_lines (struct window *);
67 static int count_windows (struct window *);
68 static int get_leaf_windows (struct window *, struct window **, int);
69 static void window_scroll (Lisp_Object, EMACS_INT, int, int);
70 static void window_scroll_pixel_based (Lisp_Object, int, int, int);
71 static void window_scroll_line_based (Lisp_Object, int, int, int);
72 static int freeze_window_start (struct window *, void *);
73 static Lisp_Object window_list (void);
74 static int add_window_to_list (struct window *, void *);
75 static int candidate_window_p (Lisp_Object, Lisp_Object, Lisp_Object,
76 Lisp_Object);
77 static Lisp_Object next_window (Lisp_Object, Lisp_Object,
78 Lisp_Object, int);
79 static void decode_next_window_args (Lisp_Object *, Lisp_Object *,
80 Lisp_Object *);
81 static void foreach_window (struct frame *,
82 int (* fn) (struct window *, void *),
83 void *);
84 static int foreach_window_1 (struct window *,
85 int (* fn) (struct window *, void *),
86 void *);
87 static Lisp_Object window_list_1 (Lisp_Object, Lisp_Object, Lisp_Object);
88 static int window_resize_check (struct window *, int);
89 static void window_resize_apply (struct window *, int);
90 static Lisp_Object select_window (Lisp_Object, Lisp_Object, int);
92 /* This is the window in which the terminal's cursor should
93 be left when nothing is being done with it. This must
94 always be a leaf window, and its buffer is selected by
95 the top level editing loop at the end of each command.
97 This value is always the same as
98 FRAME_SELECTED_WINDOW (selected_frame). */
99 Lisp_Object selected_window;
101 /* A list of all windows for use by next_window and Fwindow_list.
102 Functions creating or deleting windows should invalidate this cache
103 by setting it to nil. */
104 Lisp_Object Vwindow_list;
106 /* The mini-buffer window of the selected frame.
107 Note that you cannot test for mini-bufferness of an arbitrary window
108 by comparing against this; but you can test for mini-bufferness of
109 the selected window. */
110 Lisp_Object minibuf_window;
112 /* Non-nil means it is the window whose mode line should be
113 shown as the selected window when the minibuffer is selected. */
114 Lisp_Object minibuf_selected_window;
116 /* Hook run at end of temp_output_buffer_show. */
117 static Lisp_Object Qtemp_buffer_show_hook;
119 /* Incremented for each window created. */
120 static int sequence_number;
122 /* Nonzero after init_window_once has finished. */
123 static int window_initialized;
125 /* Hook to run when window config changes. */
126 static Lisp_Object Qwindow_configuration_change_hook;
128 /* Used by the function window_scroll_pixel_based */
129 static int window_scroll_pixel_based_preserve_x;
130 static int window_scroll_pixel_based_preserve_y;
132 /* Same for window_scroll_line_based. */
133 static EMACS_INT window_scroll_preserve_hpos;
134 static EMACS_INT window_scroll_preserve_vpos;
136 /* These setters are used only in this file, so they can be private. */
137 static inline void
138 wset_combination_limit (struct window *w, Lisp_Object val)
140 w->combination_limit = val;
142 static inline void
143 wset_dedicated (struct window *w, Lisp_Object val)
145 w->dedicated = val;
147 static inline void
148 wset_display_table (struct window *w, Lisp_Object val)
150 w->display_table = val;
152 static inline void
153 wset_hchild (struct window *w, Lisp_Object val)
155 w->hchild = val;
157 static inline void
158 wset_left_fringe_width (struct window *w, Lisp_Object val)
160 w->left_fringe_width = val;
162 static inline void
163 wset_left_margin_cols (struct window *w, Lisp_Object val)
165 w->left_margin_cols = val;
167 static inline void
168 wset_new_normal (struct window *w, Lisp_Object val)
170 w->new_normal = val;
172 static inline void
173 wset_new_total (struct window *w, Lisp_Object val)
175 w->new_total = val;
177 static inline void
178 wset_normal_cols (struct window *w, Lisp_Object val)
180 w->normal_cols = val;
182 static inline void
183 wset_normal_lines (struct window *w, Lisp_Object val)
185 w->normal_lines = val;
187 static inline void
188 wset_parent (struct window *w, Lisp_Object val)
190 w->parent = val;
192 static inline void
193 wset_pointm (struct window *w, Lisp_Object val)
195 w->pointm = val;
197 static inline void
198 wset_right_fringe_width (struct window *w, Lisp_Object val)
200 w->right_fringe_width = val;
202 static inline void
203 wset_right_margin_cols (struct window *w, Lisp_Object val)
205 w->right_margin_cols = val;
207 static inline void
208 wset_scroll_bar_width (struct window *w, Lisp_Object val)
210 w->scroll_bar_width = val;
212 static inline void
213 wset_start (struct window *w, Lisp_Object val)
215 w->start = val;
217 static inline void
218 wset_temslot (struct window *w, Lisp_Object val)
220 w->temslot = val;
222 static inline void
223 wset_vchild (struct window *w, Lisp_Object val)
225 w->vchild = val;
227 static inline void
228 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
230 w->vertical_scroll_bar_type = val;
232 static inline void
233 wset_window_parameters (struct window *w, Lisp_Object val)
235 w->window_parameters = val;
238 struct window *
239 decode_live_window (register Lisp_Object window)
241 if (NILP (window))
242 return XWINDOW (selected_window);
244 CHECK_LIVE_WINDOW (window);
245 return XWINDOW (window);
248 static struct window *
249 decode_any_window (register Lisp_Object window)
251 struct window *w;
253 if (NILP (window))
254 return XWINDOW (selected_window);
256 CHECK_WINDOW (window);
257 w = XWINDOW (window);
258 return w;
261 static struct window *
262 decode_valid_window (register Lisp_Object window)
264 struct window *w;
266 if (NILP (window))
267 return XWINDOW (selected_window);
269 CHECK_VALID_WINDOW (window);
270 w = XWINDOW (window);
271 return w;
274 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
275 doc: /* Return t if OBJECT is a window and nil otherwise. */)
276 (Lisp_Object object)
278 return WINDOWP (object) ? Qt : Qnil;
281 DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
282 doc: /* Return t if OBJECT is a valid window and nil otherwise.
283 A valid window is either a window that displays a buffer or an internal
284 window. Deleted windows are not live. */)
285 (Lisp_Object object)
287 return WINDOW_VALID_P (object) ? Qt : Qnil;
290 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
291 doc: /* Return t if OBJECT is a live window and nil otherwise.
292 A live window is a window that displays a buffer.
293 Internal windows and deleted windows are not live. */)
294 (Lisp_Object object)
296 return WINDOW_LIVE_P (object) ? Qt : Qnil;
299 /* Frames and windows. */
300 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
301 doc: /* Return the frame that window WINDOW is on.
302 WINDOW must be a valid window and defaults to the selected one. */)
303 (Lisp_Object window)
305 return decode_valid_window (window)->frame;
308 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
309 doc: /* Return the root window of FRAME-OR-WINDOW.
310 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
311 With a frame argument, return that frame's root window.
312 With a window argument, return the root window of that window's frame. */)
313 (Lisp_Object frame_or_window)
315 Lisp_Object window;
317 if (NILP (frame_or_window))
318 window = SELECTED_FRAME ()->root_window;
319 else if (WINDOW_VALID_P (frame_or_window))
320 window = XFRAME (XWINDOW (frame_or_window)->frame)->root_window;
321 else
323 CHECK_LIVE_FRAME (frame_or_window);
324 window = XFRAME (frame_or_window)->root_window;
327 return window;
330 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
331 doc: /* Return the minibuffer window for frame FRAME.
332 If FRAME is omitted or nil, it defaults to the selected frame. */)
333 (Lisp_Object frame)
335 if (NILP (frame))
336 frame = selected_frame;
337 CHECK_LIVE_FRAME (frame);
338 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
341 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
342 Swindow_minibuffer_p, 0, 1, 0,
343 doc: /* Return non-nil if WINDOW is a minibuffer window.
344 WINDOW must be a valid window and defaults to the selected one. */)
345 (Lisp_Object window)
347 return MINI_WINDOW_P (decode_valid_window (window)) ? Qt : Qnil;
350 /* Don't move this to window.el - this must be a safe routine. */
351 DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
352 doc: /* Return the topmost, leftmost live window on FRAME-OR-WINDOW.
353 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
354 Else if FRAME-OR-WINDOW denotes a valid window, return the first window
355 of that window's frame. If FRAME-OR-WINDOW denotes a live frame, return
356 the first window of that frame. */)
357 (Lisp_Object frame_or_window)
359 Lisp_Object window;
361 if (NILP (frame_or_window))
362 window = SELECTED_FRAME ()->root_window;
363 else if (WINDOW_VALID_P (frame_or_window))
364 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
365 else
367 CHECK_LIVE_FRAME (frame_or_window);
368 window = XFRAME (frame_or_window)->root_window;
371 while (NILP (XWINDOW (window)->buffer))
373 if (! NILP (XWINDOW (window)->hchild))
374 window = XWINDOW (window)->hchild;
375 else if (! NILP (XWINDOW (window)->vchild))
376 window = XWINDOW (window)->vchild;
377 else
378 emacs_abort ();
381 return window;
384 DEFUN ("frame-selected-window", Fframe_selected_window,
385 Sframe_selected_window, 0, 1, 0,
386 doc: /* Return the selected window of FRAME-OR-WINDOW.
387 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
388 Else if FRAME-OR-WINDOW denotes a valid window, return the selected
389 window of that window's frame. If FRAME-OR-WINDOW denotes a live frame,
390 return the selected window of that frame. */)
391 (Lisp_Object frame_or_window)
393 Lisp_Object window;
395 if (NILP (frame_or_window))
396 window = SELECTED_FRAME ()->selected_window;
397 else if (WINDOW_VALID_P (frame_or_window))
398 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
399 else
401 CHECK_LIVE_FRAME (frame_or_window);
402 window = XFRAME (frame_or_window)->selected_window;
405 return window;
408 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
409 Sset_frame_selected_window, 2, 3, 0,
410 doc: /* Set selected window of FRAME to WINDOW.
411 FRAME must be a live frame and defaults to the selected one. If FRAME
412 is the selected frame, this makes WINDOW the selected window. Optional
413 argument NORECORD non-nil means to neither change the order of recently
414 selected windows nor the buffer list. WINDOW must denote a live window.
415 Return WINDOW. */)
416 (Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
418 if (NILP (frame))
419 frame = selected_frame;
421 CHECK_LIVE_FRAME (frame);
422 CHECK_LIVE_WINDOW (window);
424 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
425 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
427 if (EQ (frame, selected_frame))
428 return Fselect_window (window, norecord);
429 else
431 fset_selected_window (XFRAME (frame), window);
432 return window;
436 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
437 doc: /* Return the selected window.
438 The selected window is the window in which the standard cursor for
439 selected windows appears and to which many commands apply. */)
440 (void)
442 return selected_window;
445 int window_select_count;
447 /* If select_window is called with inhibit_point_swap non-zero it will
448 not store point of the old selected window's buffer back into that
449 window's pointm slot. This is needed by Fset_window_configuration to
450 avoid that the display routine is called with selected_window set to
451 Qnil causing a subsequent crash. */
452 static Lisp_Object
453 select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
455 register struct window *w;
456 register struct window *ow;
457 struct frame *sf;
459 CHECK_LIVE_WINDOW (window);
461 w = XWINDOW (window);
462 w->frozen_window_start_p = 0;
464 if (NILP (norecord))
466 w->use_time = ++window_select_count;
467 record_buffer (w->buffer);
470 /* Make the selected window's buffer current. */
471 Fset_buffer (w->buffer);
473 if (EQ (window, selected_window) && !inhibit_point_swap)
474 return window;
476 sf = SELECTED_FRAME ();
477 if (XFRAME (WINDOW_FRAME (w)) != sf)
479 fset_selected_window (XFRAME (WINDOW_FRAME (w)), window);
480 /* Use this rather than Fhandle_switch_frame
481 so that FRAME_FOCUS_FRAME is moved appropriately as we
482 move around in the state where a minibuffer in a separate
483 frame is active. */
484 Fselect_frame (WINDOW_FRAME (w), norecord);
485 /* Fselect_frame called us back so we've done all the work already. */
486 eassert (EQ (window, selected_window));
487 return window;
489 else
490 fset_selected_window (sf, window);
492 /* Store the old selected window's buffer's point in pointm of the old
493 selected window. It belongs to that window, and when the window is
494 not selected, must be in the window. */
495 if (!inhibit_point_swap)
497 ow = XWINDOW (selected_window);
498 if (! NILP (ow->buffer))
499 set_marker_both (ow->pointm, ow->buffer,
500 BUF_PT (XBUFFER (ow->buffer)),
501 BUF_PT_BYTE (XBUFFER (ow->buffer)));
504 selected_window = window;
505 bset_last_selected_window (XBUFFER (w->buffer), window);
507 /* Go to the point recorded in the window.
508 This is important when the buffer is in more
509 than one window. It also matters when
510 redisplay_window has altered point after scrolling,
511 because it makes the change only in the window. */
513 register ptrdiff_t new_point = marker_position (w->pointm);
514 if (new_point < BEGV)
515 SET_PT (BEGV);
516 else if (new_point > ZV)
517 SET_PT (ZV);
518 else
519 SET_PT (new_point);
522 windows_or_buffers_changed++;
523 return window;
526 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
527 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
528 Also make WINDOW's buffer current and make WINDOW the frame's selected
529 window. Return WINDOW.
531 Optional second arg NORECORD non-nil means do not put this buffer at the
532 front of the buffer list and do not make this window the most recently
533 selected one.
535 Note that the main editor command loop sets the current buffer to the
536 buffer of the selected window before each command. */)
537 (register Lisp_Object window, Lisp_Object norecord)
539 return select_window (window, norecord, 0);
542 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
543 doc: /* Return the buffer displayed in window WINDOW.
544 If WINDOW is omitted or nil, it defaults to the selected window.
545 Return nil for an internal window or a deleted window. */)
546 (Lisp_Object window)
548 return decode_any_window (window)->buffer;
551 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
552 doc: /* Return the parent window of window WINDOW.
553 WINDOW must be a valid window and defaults to the selected one.
554 Return nil for a window with no parent (e.g. a root window). */)
555 (Lisp_Object window)
557 return decode_valid_window (window)->parent;
560 DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 1, 1, 0,
561 doc: /* Return the topmost child window of window WINDOW.
562 WINDOW must be a valid window and defaults to the selected one.
563 Return nil if WINDOW is a live window (live windows have no children).
564 Return nil if WINDOW is an internal window whose children form a
565 horizontal combination. */)
566 (Lisp_Object window)
568 CHECK_WINDOW (window);
569 return decode_valid_window (window)->vchild;
572 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 1, 1, 0,
573 doc: /* Return the leftmost child window of window WINDOW.
574 WINDOW must be a valid window and defaults to the selected one.
575 Return nil if WINDOW is a live window (live windows have no children).
576 Return nil if WINDOW is an internal window whose children form a
577 vertical combination. */)
578 (Lisp_Object window)
580 CHECK_WINDOW (window);
581 return decode_valid_window (window)->hchild;
584 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
585 doc: /* Return the next sibling window of window WINDOW.
586 WINDOW must be a valid window and defaults to the selected one.
587 Return nil if WINDOW has no next sibling. */)
588 (Lisp_Object window)
590 return decode_valid_window (window)->next;
593 DEFUN ("window-prev-sibling", Fwindow_prev_sibling, Swindow_prev_sibling, 0, 1, 0,
594 doc: /* Return the previous sibling window of window WINDOW.
595 WINDOW must be a valid window and defaults to the selected one.
596 Return nil if WINDOW has no previous sibling. */)
597 (Lisp_Object window)
599 return decode_valid_window (window)->prev;
602 DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
603 doc: /* Return combination limit of window WINDOW.
604 WINDOW must be a valid window and defaults to the selected one.
605 If the return value is nil, child windows of WINDOW can be recombined with
606 WINDOW's siblings. A return value of t means that child windows of
607 WINDOW are never \(re-)combined with WINDOW's siblings. */)
608 (Lisp_Object window)
610 return decode_valid_window (window)->combination_limit;
613 DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
614 doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
615 WINDOW must be a valid window and defaults to the selected one.
616 If LIMIT is nil, child windows of WINDOW can be recombined with
617 WINDOW's siblings. LIMIT t means that child windows of WINDOW are
618 never \(re-)combined with WINDOW's siblings. Other values are reserved
619 for future use. */)
620 (Lisp_Object window, Lisp_Object limit)
622 wset_combination_limit (decode_valid_window (window), limit);
623 return limit;
626 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
627 doc: /* Return the use time of window WINDOW.
628 WINDOW must be a live window and defaults to the selected one.
629 The window with the highest use time is the most recently selected
630 one. The window with the lowest use time is the least recently
631 selected one. */)
632 (Lisp_Object window)
634 return make_number (decode_live_window (window)->use_time);
637 DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 1, 0,
638 doc: /* Return the total height, in lines, of window WINDOW.
639 WINDOW must be a valid window and defaults to the selected one.
641 The return value includes the mode line and header line, if any.
642 If WINDOW is an internal window, the total height is the height
643 of the screen areas spanned by its children.
645 On a graphical display, this total height is reported as an
646 integer multiple of the default character height. */)
647 (Lisp_Object window)
649 return decode_valid_window (window)->total_lines;
652 DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 1, 0,
653 doc: /* Return the total width, in columns, of window WINDOW.
654 WINDOW must be a valid window and defaults to the selected one.
656 The return value includes any vertical dividers or scroll bars
657 belonging to WINDOW. If WINDOW is an internal window, the total width
658 is the width of the screen areas spanned by its children.
660 On a graphical display, this total width is reported as an
661 integer multiple of the default character width. */)
662 (Lisp_Object window)
664 return decode_valid_window (window)->total_cols;
667 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
668 doc: /* Return the new total size of window WINDOW.
669 WINDOW must be a valid window and defaults to the selected one. */)
670 (Lisp_Object window)
672 return decode_valid_window (window)->new_total;
675 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
676 doc: /* Return the normal height of window WINDOW.
677 WINDOW must be a valid window and defaults to the selected one.
678 If HORIZONTAL is non-nil, return the normal width of WINDOW. */)
679 (Lisp_Object window, Lisp_Object horizontal)
681 struct window *w = decode_valid_window (window);
683 return NILP (horizontal) ? w->normal_lines : w->normal_cols;
686 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
687 doc: /* Return new normal size of window WINDOW.
688 WINDOW must be a valid window and defaults to the selected one. */)
689 (Lisp_Object window)
691 return decode_valid_window (window)->new_normal;
694 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
695 doc: /* Return left column of window WINDOW.
696 This is the distance, in columns, between the left edge of WINDOW and
697 the left edge of the frame's window area. For instance, the return
698 value is 0 if there is no window to the left of WINDOW.
700 WINDOW must be a valid window and defaults to the selected one. */)
701 (Lisp_Object window)
703 return decode_valid_window (window)->left_col;
706 DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
707 doc: /* Return top line of window WINDOW.
708 This is the distance, in lines, between the top of WINDOW and the top
709 of the frame's window area. For instance, the return value is 0 if
710 there is no window above WINDOW.
712 WINDOW must be a valid window and defaults to the selected one. */)
713 (Lisp_Object window)
715 return decode_valid_window (window)->top_line;
718 /* Return the number of lines of W's body. Don't count any mode or
719 header line of W. */
721 static int
722 window_body_lines (struct window *w)
724 int height = XFASTINT (w->total_lines);
726 if (!MINI_WINDOW_P (w))
728 if (WINDOW_WANTS_MODELINE_P (w))
729 --height;
730 if (WINDOW_WANTS_HEADER_LINE_P (w))
731 --height;
734 return height;
737 /* Return the number of columns of W's body. Don't count columns
738 occupied by the scroll bar or the vertical bar separating W from its
739 right sibling. On window-systems don't count fringes or display
740 margins either. */
743 window_body_cols (struct window *w)
745 struct frame *f = XFRAME (WINDOW_FRAME (w));
746 int width = XINT (w->total_cols);
748 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
749 /* Scroll bars occupy a few columns. */
750 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
751 else if (!FRAME_WINDOW_P (f)
752 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
753 /* The column of `|' characters separating side-by-side windows
754 occupies one column only. */
755 width -= 1;
757 if (FRAME_WINDOW_P (f))
758 /* On window-systems, fringes and display margins cannot be
759 used for normal text. */
760 width -= (WINDOW_FRINGE_COLS (w)
761 + WINDOW_LEFT_MARGIN_COLS (w)
762 + WINDOW_RIGHT_MARGIN_COLS (w));
764 return width;
767 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 1, 0,
768 doc: /* Return the height, in lines, of WINDOW's text area.
769 WINDOW must be a live window and defaults to the selected one.
771 The returned height does not include the mode line or header line.
772 On a graphical display, the height is expressed as an integer multiple
773 of the default character height. If a line at the bottom of the text
774 area is only partially visible, that counts as a whole line; to
775 exclude partially-visible lines, use `window-text-height'. */)
776 (Lisp_Object window)
778 struct window *w = decode_live_window (window);
779 return make_number (window_body_lines (w));
782 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 1, 0,
783 doc: /* Return the width, in columns, of WINDOW's text area.
784 WINDOW must be a live window and defaults to the selected one.
786 The return value does not include any vertical dividers, fringe or
787 marginal areas, or scroll bars. On a graphical display, the width is
788 expressed as an integer multiple of the default character width. */)
789 (Lisp_Object window)
791 struct window *w = decode_live_window (window);
792 return make_number (window_body_cols (w));
795 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
796 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
797 WINDOW must be a live window and defaults to the selected one. */)
798 (Lisp_Object window)
800 return make_number (decode_live_window (window)->hscroll);
803 /* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
804 range, returning the new amount as a fixnum. */
805 static Lisp_Object
806 set_window_hscroll (struct window *w, EMACS_INT hscroll)
808 /* Horizontal scrolling has problems with large scroll amounts.
809 It's too slow with long lines, and even with small lines the
810 display can be messed up. For now, though, impose only the limits
811 required by the internal representation: horizontal scrolling must
812 fit in fixnum (since it's visible to Elisp) and into ptrdiff_t
813 (since it's stored in a ptrdiff_t). */
814 ptrdiff_t hscroll_max = min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX);
815 ptrdiff_t new_hscroll = clip_to_bounds (0, hscroll, hscroll_max);
817 /* Prevent redisplay shortcuts when changing the hscroll. */
818 if (w->hscroll != new_hscroll)
819 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
821 w->hscroll = new_hscroll;
822 return make_number (new_hscroll);
825 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
826 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
827 WINDOW must be a live window and defaults to the selected one.
828 Clip the number to a reasonable value if out of range.
829 Return the new number. NCOL should be zero or positive.
831 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
832 window so that the location of point moves off-window. */)
833 (Lisp_Object window, Lisp_Object ncol)
835 struct window *w = decode_live_window (window);
837 CHECK_NUMBER (ncol);
838 return set_window_hscroll (w, XINT (ncol));
841 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
842 Swindow_redisplay_end_trigger, 0, 1, 0,
843 doc: /* Return WINDOW's redisplay end trigger value.
844 WINDOW must be a live window and defaults to the selected one.
845 See `set-window-redisplay-end-trigger' for more information. */)
846 (Lisp_Object window)
848 return decode_live_window (window)->redisplay_end_trigger;
851 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
852 Sset_window_redisplay_end_trigger, 2, 2, 0,
853 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
854 WINDOW must be a live window and defaults to the selected one. VALUE
855 should be a buffer position (typically a marker) or nil. If it is a
856 buffer position, then if redisplay in WINDOW reaches a position beyond
857 VALUE, the functions in `redisplay-end-trigger-functions' are called
858 with two arguments: WINDOW, and the end trigger value. Afterwards the
859 end-trigger value is reset to nil. */)
860 (register Lisp_Object window, Lisp_Object value)
862 wset_redisplay_end_trigger (decode_live_window (window), value);
863 return value;
866 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
867 doc: /* Return a list of the edge coordinates of WINDOW.
868 WINDOW must be a valid window and defaults to the selected one.
870 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
871 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
872 0 at top left corner of frame.
874 RIGHT is one more than the rightmost column occupied by WINDOW. BOTTOM
875 is one more than the bottommost row occupied by WINDOW. The edges
876 include the space used by WINDOW's scroll bar, display margins, fringes,
877 header line, and/or mode line. For the edges of just the text area, use
878 `window-inside-edges'. */)
879 (Lisp_Object window)
881 register struct window *w = decode_valid_window (window);
883 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
884 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
885 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
886 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
887 Qnil))));
890 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
891 doc: /* Return a list of the edge pixel coordinates of WINDOW.
892 WINDOW must be a valid window and defaults to the selected one.
894 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
895 0, 0 at the top left corner of the frame.
897 RIGHT is one more than the rightmost x position occupied by WINDOW.
898 BOTTOM is one more than the bottommost y position occupied by WINDOW.
899 The pixel edges include the space used by WINDOW's scroll bar, display
900 margins, fringes, header line, and/or mode line. For the pixel edges
901 of just the text area, use `window-inside-pixel-edges'. */)
902 (Lisp_Object window)
904 register struct window *w = decode_valid_window (window);
906 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
907 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
908 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
909 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
910 Qnil))));
913 static void
914 calc_absolute_offset (struct window *w, int *add_x, int *add_y)
916 struct frame *f = XFRAME (w->frame);
917 *add_y = f->top_pos;
918 #ifdef FRAME_MENUBAR_HEIGHT
919 *add_y += FRAME_MENUBAR_HEIGHT (f);
920 #endif
921 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
922 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
923 #elif FRAME_TOOLBAR_HEIGHT
924 *add_y += FRAME_TOOLBAR_HEIGHT (f);
925 #endif
926 #ifdef FRAME_NS_TITLEBAR_HEIGHT
927 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
928 #endif
929 *add_x = f->left_pos;
930 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
931 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
932 #endif
935 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
936 Swindow_absolute_pixel_edges, 0, 1, 0,
937 doc: /* Return a list of the edge pixel coordinates of WINDOW.
938 WINDOW must be a valid window and defaults to the selected one.
940 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
941 0, 0 at the top left corner of the display.
943 RIGHT is one more than the rightmost x position occupied by WINDOW.
944 BOTTOM is one more than the bottommost y position occupied by WINDOW.
945 The pixel edges include the space used by WINDOW's scroll bar, display
946 margins, fringes, header line, and/or mode line. For the pixel edges
947 of just the text area, use `window-inside-absolute-pixel-edges'. */)
948 (Lisp_Object window)
950 register struct window *w = decode_valid_window (window);
951 int add_x, add_y;
952 calc_absolute_offset (w, &add_x, &add_y);
954 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w) + add_x),
955 Fcons (make_number (WINDOW_TOP_EDGE_Y (w) + add_y),
956 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w) + add_x),
957 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w) + add_y),
958 Qnil))));
961 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
962 doc: /* Return a list of the edge coordinates of WINDOW.
963 WINDOW must be a live window and defaults to the selected one.
965 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
966 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
967 0 at top left corner of frame.
969 RIGHT is one more than the rightmost column of WINDOW's text area.
970 BOTTOM is one more than the bottommost row of WINDOW's text area. The
971 inside edges do not include the space used by the WINDOW's scroll bar,
972 display margins, fringes, header line, and/or mode line. */)
973 (Lisp_Object window)
975 register struct window *w = decode_live_window (window);
977 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
978 + WINDOW_LEFT_MARGIN_COLS (w)
979 + WINDOW_LEFT_FRINGE_COLS (w)),
980 make_number (WINDOW_TOP_EDGE_LINE (w)
981 + WINDOW_HEADER_LINE_LINES (w)),
982 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
983 - WINDOW_RIGHT_MARGIN_COLS (w)
984 - WINDOW_RIGHT_FRINGE_COLS (w)),
985 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
986 - WINDOW_MODE_LINE_LINES (w)));
989 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
990 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
991 WINDOW must be a live window and defaults to the selected one.
993 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
994 (0,0) at the top left corner of the frame's window area.
996 RIGHT is one more than the rightmost x position of WINDOW's text area.
997 BOTTOM is one more than the bottommost y position of WINDOW's text area.
998 The inside edges do not include the space used by WINDOW's scroll bar,
999 display margins, fringes, header line, and/or mode line. */)
1000 (Lisp_Object window)
1002 register struct window *w = decode_live_window (window);
1004 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
1005 + WINDOW_LEFT_MARGIN_WIDTH (w)
1006 + WINDOW_LEFT_FRINGE_WIDTH (w)),
1007 make_number (WINDOW_TOP_EDGE_Y (w)
1008 + WINDOW_HEADER_LINE_HEIGHT (w)),
1009 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
1010 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1011 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
1012 make_number (WINDOW_BOTTOM_EDGE_Y (w)
1013 - WINDOW_MODE_LINE_HEIGHT (w)));
1016 DEFUN ("window-inside-absolute-pixel-edges",
1017 Fwindow_inside_absolute_pixel_edges,
1018 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
1019 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1020 WINDOW must be a live window and defaults to the selected one.
1022 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1023 (0,0) at the top left corner of the frame's window area.
1025 RIGHT is one more than the rightmost x position of WINDOW's text area.
1026 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1027 The inside edges do not include the space used by WINDOW's scroll bar,
1028 display margins, fringes, header line, and/or mode line. */)
1029 (Lisp_Object window)
1031 register struct window *w = decode_live_window (window);
1032 int add_x, add_y;
1033 calc_absolute_offset (w, &add_x, &add_y);
1035 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
1036 + WINDOW_LEFT_MARGIN_WIDTH (w)
1037 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
1038 make_number (WINDOW_TOP_EDGE_Y (w)
1039 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
1040 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
1041 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1042 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
1043 make_number (WINDOW_BOTTOM_EDGE_Y (w)
1044 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
1047 /* Test if the character at column X, row Y is within window W.
1048 If it is not, return ON_NOTHING;
1049 if it is in the window's text area, return ON_TEXT;
1050 if it is on the window's modeline, return ON_MODE_LINE;
1051 if it is on the border between the window and its right sibling,
1052 return ON_VERTICAL_BORDER.
1053 if it is on a scroll bar, return ON_SCROLL_BAR.
1054 if it is on the window's top line, return ON_HEADER_LINE;
1055 if it is in left or right fringe of the window,
1056 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
1057 if it is in the marginal area to the left/right of the window,
1058 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
1060 X and Y are frame relative pixel coordinates. */
1062 static enum window_part
1063 coordinates_in_window (register struct window *w, int x, int y)
1065 struct frame *f = XFRAME (WINDOW_FRAME (w));
1066 enum window_part part;
1067 int ux = FRAME_COLUMN_WIDTH (f);
1068 int left_x = WINDOW_LEFT_EDGE_X (w);
1069 int right_x = WINDOW_RIGHT_EDGE_X (w);
1070 int top_y = WINDOW_TOP_EDGE_Y (w);
1071 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
1072 /* The width of the area where the vertical line can be dragged.
1073 (Between mode lines for instance. */
1074 int grabbable_width = ux;
1075 int lmargin_width, rmargin_width, text_left, text_right;
1077 /* Outside any interesting row or column? */
1078 if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
1079 return ON_NOTHING;
1081 /* On the mode line or header line? */
1082 if ((WINDOW_WANTS_MODELINE_P (w)
1083 && y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
1084 && (part = ON_MODE_LINE))
1085 || (WINDOW_WANTS_HEADER_LINE_P (w)
1086 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
1087 && (part = ON_HEADER_LINE)))
1089 /* If it's under/over the scroll bar portion of the mode/header
1090 line, say it's on the vertical line. That's to be able to
1091 resize windows horizontally in case we're using toolkit scroll
1092 bars. Note: If scrollbars are on the left, the window that
1093 must be eventually resized is that on the left of WINDOW. */
1094 if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1095 && !WINDOW_LEFTMOST_P (w)
1096 && eabs (x - left_x) < grabbable_width)
1097 || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1098 && !WINDOW_RIGHTMOST_P (w)
1099 && eabs (x - right_x) < grabbable_width))
1100 return ON_VERTICAL_BORDER;
1101 else
1102 return part;
1105 /* In what's below, we subtract 1 when computing right_x because we
1106 want the rightmost pixel, which is given by left_pixel+width-1. */
1107 if (w->pseudo_window_p)
1109 left_x = 0;
1110 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
1112 else
1114 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
1115 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
1118 /* Outside any interesting column? */
1119 if (x < left_x || x > right_x)
1120 return ON_SCROLL_BAR;
1122 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
1123 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
1125 text_left = window_box_left (w, TEXT_AREA);
1126 text_right = text_left + window_box_width (w, TEXT_AREA);
1128 if (FRAME_WINDOW_P (f))
1130 if (!w->pseudo_window_p
1131 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
1132 && !WINDOW_RIGHTMOST_P (w)
1133 && (eabs (x - right_x) < grabbable_width))
1134 return ON_VERTICAL_BORDER;
1136 /* Need to say "x > right_x" rather than >=, since on character
1137 terminals, the vertical line's x coordinate is right_x. */
1138 else if (!w->pseudo_window_p
1139 && !WINDOW_RIGHTMOST_P (w)
1140 && x > right_x - ux)
1141 return ON_VERTICAL_BORDER;
1143 if (x < text_left)
1145 if (lmargin_width > 0
1146 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1147 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
1148 : (x < left_x + lmargin_width)))
1149 return ON_LEFT_MARGIN;
1151 return ON_LEFT_FRINGE;
1154 if (x >= text_right)
1156 if (rmargin_width > 0
1157 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1158 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
1159 : (x >= right_x - rmargin_width)))
1160 return ON_RIGHT_MARGIN;
1162 return ON_RIGHT_FRINGE;
1165 /* Everything special ruled out - must be on text area */
1166 return ON_TEXT;
1169 /* Take X is the frame-relative pixel x-coordinate, and return the
1170 x-coordinate relative to part PART of window W. */
1172 window_relative_x_coord (struct window *w, enum window_part part, int x)
1174 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
1176 switch (part)
1178 case ON_TEXT:
1179 return x - window_box_left (w, TEXT_AREA);
1181 case ON_LEFT_FRINGE:
1182 return x - left_x;
1184 case ON_RIGHT_FRINGE:
1185 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
1187 case ON_LEFT_MARGIN:
1188 return (x - left_x
1189 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1190 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
1192 case ON_RIGHT_MARGIN:
1193 return (x + 1
1194 - ((w->pseudo_window_p)
1195 ? WINDOW_TOTAL_WIDTH (w)
1196 : WINDOW_BOX_RIGHT_EDGE_X (w))
1197 + window_box_width (w, RIGHT_MARGIN_AREA)
1198 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1199 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
1202 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
1203 return 0;
1207 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
1208 Scoordinates_in_window_p, 2, 2, 0,
1209 doc: /* Return non-nil if COORDINATES are in WINDOW.
1210 WINDOW must be a live window and defaults to the selected one.
1211 COORDINATES is a cons of the form (X . Y), X and Y being distances
1212 measured in characters from the upper-left corner of the frame.
1213 \(0 . 0) denotes the character in the upper left corner of the
1214 frame.
1215 If COORDINATES are in the text portion of WINDOW,
1216 the coordinates relative to the window are returned.
1217 If they are in the mode line of WINDOW, `mode-line' is returned.
1218 If they are in the top mode line of WINDOW, `header-line' is returned.
1219 If they are in the left fringe of WINDOW, `left-fringe' is returned.
1220 If they are in the right fringe of WINDOW, `right-fringe' is returned.
1221 If they are on the border between WINDOW and its right sibling,
1222 `vertical-line' is returned.
1223 If they are in the windows's left or right marginal areas, `left-margin'\n\
1224 or `right-margin' is returned. */)
1225 (register Lisp_Object coordinates, Lisp_Object window)
1227 struct window *w;
1228 struct frame *f;
1229 int x, y;
1230 Lisp_Object lx, ly;
1232 w = decode_live_window (window);
1233 f = XFRAME (w->frame);
1234 CHECK_CONS (coordinates);
1235 lx = Fcar (coordinates);
1236 ly = Fcdr (coordinates);
1237 CHECK_NUMBER_OR_FLOAT (lx);
1238 CHECK_NUMBER_OR_FLOAT (ly);
1239 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1240 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
1242 switch (coordinates_in_window (w, x, y))
1244 case ON_NOTHING:
1245 return Qnil;
1247 case ON_TEXT:
1248 /* Convert X and Y to window relative pixel coordinates, and
1249 return the canonical char units. */
1250 x -= window_box_left (w, TEXT_AREA);
1251 y -= WINDOW_TOP_EDGE_Y (w);
1252 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1253 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
1255 case ON_MODE_LINE:
1256 return Qmode_line;
1258 case ON_VERTICAL_BORDER:
1259 return Qvertical_line;
1261 case ON_HEADER_LINE:
1262 return Qheader_line;
1264 case ON_LEFT_FRINGE:
1265 return Qleft_fringe;
1267 case ON_RIGHT_FRINGE:
1268 return Qright_fringe;
1270 case ON_LEFT_MARGIN:
1271 return Qleft_margin;
1273 case ON_RIGHT_MARGIN:
1274 return Qright_margin;
1276 case ON_SCROLL_BAR:
1277 /* Historically we are supposed to return nil in this case. */
1278 return Qnil;
1280 default:
1281 emacs_abort ();
1286 /* Callback for foreach_window, used in window_from_coordinates.
1287 Check if window W contains coordinates specified by USER_DATA which
1288 is actually a pointer to a struct check_window_data CW.
1290 Check if window W contains coordinates *CW->x and *CW->y. If it
1291 does, return W in *CW->window, as Lisp_Object, and return in
1292 *CW->part the part of the window under coordinates *X,*Y. Return
1293 zero from this function to stop iterating over windows. */
1295 struct check_window_data
1297 Lisp_Object *window;
1298 int x, y;
1299 enum window_part *part;
1302 static int
1303 check_window_containing (struct window *w, void *user_data)
1305 struct check_window_data *cw = (struct check_window_data *) user_data;
1306 enum window_part found;
1307 int continue_p = 1;
1309 found = coordinates_in_window (w, cw->x, cw->y);
1310 if (found != ON_NOTHING)
1312 *cw->part = found;
1313 XSETWINDOW (*cw->window, w);
1314 continue_p = 0;
1317 return continue_p;
1321 /* Find the window containing frame-relative pixel position X/Y and
1322 return it as a Lisp_Object.
1324 If X, Y is on one of the window's special `window_part' elements,
1325 set *PART to the id of that element.
1327 If there is no window under X, Y return nil and leave *PART
1328 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1330 This function was previously implemented with a loop cycling over
1331 windows with Fnext_window, and starting with the frame's selected
1332 window. It turned out that this doesn't work with an
1333 implementation of next_window using Vwindow_list, because
1334 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1335 tree of F when this function is called asynchronously from
1336 note_mouse_highlight. The original loop didn't terminate in this
1337 case. */
1339 Lisp_Object
1340 window_from_coordinates (struct frame *f, int x, int y,
1341 enum window_part *part, int tool_bar_p)
1343 Lisp_Object window;
1344 struct check_window_data cw;
1345 enum window_part dummy;
1347 if (part == 0)
1348 part = &dummy;
1350 window = Qnil;
1351 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
1352 foreach_window (f, check_window_containing, &cw);
1354 /* If not found above, see if it's in the tool bar window, if a tool
1355 bar exists. */
1356 if (NILP (window)
1357 && tool_bar_p
1358 && WINDOWP (f->tool_bar_window)
1359 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1360 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
1361 != ON_NOTHING))
1363 *part = ON_TEXT;
1364 window = f->tool_bar_window;
1367 return window;
1370 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1371 doc: /* Return window containing coordinates X and Y on FRAME.
1372 FRAME must be a live frame and defaults to the selected one.
1373 The top left corner of the frame is considered to be row 0,
1374 column 0. */)
1375 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1377 struct frame *f;
1379 if (NILP (frame))
1380 frame = selected_frame;
1381 CHECK_LIVE_FRAME (frame);
1382 f = XFRAME (frame);
1384 /* Check that arguments are integers or floats. */
1385 CHECK_NUMBER_OR_FLOAT (x);
1386 CHECK_NUMBER_OR_FLOAT (y);
1388 return window_from_coordinates (f,
1389 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1390 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1391 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1392 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1393 0, 0);
1396 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1397 doc: /* Return current value of point in WINDOW.
1398 WINDOW must be a live window and defaults to the selected one.
1400 For a nonselected window, this is the value point would have if that
1401 window were selected.
1403 Note that, when WINDOW is selected, the value returned is the same as
1404 that returned by `point' for WINDOW's buffer. It would be more strictly
1405 correct to return the `top-level' value of `point', outside of any
1406 `save-excursion' forms. But that is hard to define. */)
1407 (Lisp_Object window)
1409 register struct window *w = decode_live_window (window);
1411 if (w == XWINDOW (selected_window))
1412 return make_number (BUF_PT (XBUFFER (w->buffer)));
1413 else
1414 return Fmarker_position (w->pointm);
1417 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1418 doc: /* Return position at which display currently starts in WINDOW.
1419 WINDOW must be a live window and defaults to the selected one.
1420 This is updated by redisplay or by calling `set-window-start'. */)
1421 (Lisp_Object window)
1423 return Fmarker_position (decode_live_window (window)->start);
1426 /* This is text temporarily removed from the doc string below.
1428 This function returns nil if the position is not currently known.
1429 That happens when redisplay is preempted and doesn't finish.
1430 If in that case you want to compute where the end of the window would
1431 have been if redisplay had finished, do this:
1432 (save-excursion
1433 (goto-char (window-start window))
1434 (vertical-motion (1- (window-height window)) window)
1435 (point))") */
1437 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1438 doc: /* Return position at which display currently ends in WINDOW.
1439 WINDOW must be a live window and defaults to the selected one.
1440 This is updated by redisplay, when it runs to completion.
1441 Simply changing the buffer text or setting `window-start'
1442 does not update this value.
1443 Return nil if there is no recorded value. (This can happen if the
1444 last redisplay of WINDOW was preempted, and did not finish.)
1445 If UPDATE is non-nil, compute the up-to-date position
1446 if it isn't already recorded. */)
1447 (Lisp_Object window, Lisp_Object update)
1449 Lisp_Object value;
1450 struct window *w = decode_live_window (window);
1451 Lisp_Object buf;
1452 struct buffer *b;
1454 buf = w->buffer;
1455 CHECK_BUFFER (buf);
1456 b = XBUFFER (buf);
1458 #if 0 /* This change broke some things. We should make it later. */
1459 /* If we don't know the end position, return nil.
1460 The user can compute it with vertical-motion if he wants to.
1461 It would be nicer to do it automatically,
1462 but that's so slow that it would probably bother people. */
1463 if (NILP (w->window_end_valid))
1464 return Qnil;
1465 #endif
1467 if (! NILP (update)
1468 && ! (! NILP (w->window_end_valid)
1469 && w->last_modified >= BUF_MODIFF (b)
1470 && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b))
1471 && !noninteractive)
1473 struct text_pos startp;
1474 struct it it;
1475 struct buffer *old_buffer = NULL;
1476 void *itdata = NULL;
1478 /* Cannot use Fvertical_motion because that function doesn't
1479 cope with variable-height lines. */
1480 if (b != current_buffer)
1482 old_buffer = current_buffer;
1483 set_buffer_internal (b);
1486 /* In case W->start is out of the range, use something
1487 reasonable. This situation occurred when loading a file with
1488 `-l' containing a call to `rmail' with subsequent other
1489 commands. At the end, W->start happened to be BEG, while
1490 rmail had already narrowed the buffer. */
1491 if (XMARKER (w->start)->charpos < BEGV)
1492 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1493 else if (XMARKER (w->start)->charpos > ZV)
1494 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1495 else
1496 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1498 itdata = bidi_shelve_cache ();
1499 start_display (&it, w, startp);
1500 move_it_vertically (&it, window_box_height (w));
1501 if (it.current_y < it.last_visible_y)
1502 move_it_past_eol (&it);
1503 value = make_number (IT_CHARPOS (it));
1504 bidi_unshelve_cache (itdata, 0);
1506 if (old_buffer)
1507 set_buffer_internal (old_buffer);
1509 else
1510 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1512 return value;
1515 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1516 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1517 WINDOW must be a live window and defaults to the selected one.
1518 Return POS. */)
1519 (Lisp_Object window, Lisp_Object pos)
1521 register struct window *w = decode_live_window (window);
1523 CHECK_NUMBER_COERCE_MARKER (pos);
1525 if (w == XWINDOW (selected_window))
1527 if (XBUFFER (w->buffer) == current_buffer)
1528 Fgoto_char (pos);
1529 else
1531 struct buffer *old_buffer = current_buffer;
1533 set_buffer_internal (XBUFFER (w->buffer));
1534 Fgoto_char (pos);
1535 set_buffer_internal (old_buffer);
1538 else
1540 set_marker_restricted (w->pointm, pos, w->buffer);
1541 /* We have to make sure that redisplay updates the window to show
1542 the new value of point. */
1543 ++windows_or_buffers_changed;
1546 return pos;
1549 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1550 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1551 WINDOW must be a live window and defaults to the selected one. Return
1552 POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
1553 overriding motion of point in order to display at this exact start. */)
1554 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1556 register struct window *w = decode_live_window (window);
1558 CHECK_NUMBER_COERCE_MARKER (pos);
1559 set_marker_restricted (w->start, pos, w->buffer);
1560 /* this is not right, but much easier than doing what is right. */
1561 w->start_at_line_beg = 0;
1562 if (NILP (noforce))
1563 w->force_start = 1;
1564 w->update_mode_line = 1;
1565 w->last_modified = 0;
1566 w->last_overlay_modified = 0;
1567 if (!EQ (window, selected_window))
1568 windows_or_buffers_changed++;
1570 return pos;
1573 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1574 Spos_visible_in_window_p, 0, 3, 0,
1575 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1576 WINDOW must be a live window and defaults to the selected one.
1578 Return nil if that position is scrolled vertically out of view. If a
1579 character is only partially visible, nil is returned, unless the
1580 optional argument PARTIALLY is non-nil. If POS is only out of view
1581 because of horizontal scrolling, return non-nil. If POS is t, it
1582 specifies the position of the last visible glyph in WINDOW. POS
1583 defaults to point in WINDOW; WINDOW defaults to the selected window.
1585 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
1586 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
1587 where X and Y are the pixel coordinates relative to the top left corner
1588 of the window. The remaining elements are omitted if the character after
1589 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1590 off-window at the top and bottom of the row, ROWH is the height of the
1591 display row, and VPOS is the row number (0-based) containing POS. */)
1592 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1594 register struct window *w;
1595 register EMACS_INT posint;
1596 register struct buffer *buf;
1597 struct text_pos top;
1598 Lisp_Object in_window = Qnil;
1599 int rtop, rbot, rowh, vpos, fully_p = 1;
1600 int x, y;
1602 w = decode_live_window (window);
1603 buf = XBUFFER (w->buffer);
1604 SET_TEXT_POS_FROM_MARKER (top, w->start);
1606 if (EQ (pos, Qt))
1607 posint = -1;
1608 else if (!NILP (pos))
1610 CHECK_NUMBER_COERCE_MARKER (pos);
1611 posint = XINT (pos);
1613 else if (w == XWINDOW (selected_window))
1614 posint = PT;
1615 else
1616 posint = XMARKER (w->pointm)->charpos;
1618 /* If position is above window start or outside buffer boundaries,
1619 or if window start is out of range, position is not visible. */
1620 if ((EQ (pos, Qt)
1621 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
1622 && CHARPOS (top) >= BUF_BEGV (buf)
1623 && CHARPOS (top) <= BUF_ZV (buf)
1624 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
1625 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
1626 in_window = Qt;
1628 if (!NILP (in_window) && !NILP (partially))
1630 Lisp_Object part = Qnil;
1631 if (!fully_p)
1632 part = list4 (make_number (rtop), make_number (rbot),
1633 make_number (rowh), make_number (vpos));
1634 in_window = Fcons (make_number (x),
1635 Fcons (make_number (y), part));
1638 return in_window;
1641 DEFUN ("window-line-height", Fwindow_line_height,
1642 Swindow_line_height, 0, 2, 0,
1643 doc: /* Return height in pixels of text line LINE in window WINDOW.
1644 WINDOW must be a live window and defaults to the selected one.
1646 Return height of current line if LINE is omitted or nil. Return height of
1647 header or mode line if LINE is `header-line' or `mode-line'.
1648 Otherwise, LINE is a text line number starting from 0. A negative number
1649 counts from the end of the window.
1651 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
1652 in pixels of the visible part of the line, VPOS and YPOS are the
1653 vertical position in lines and pixels of the line, relative to the top
1654 of the first text line, and OFFBOT is the number of off-window pixels at
1655 the bottom of the text line. If there are off-window pixels at the top
1656 of the (first) text line, YPOS is negative.
1658 Return nil if window display is not up-to-date. In that case, use
1659 `pos-visible-in-window-p' to obtain the information. */)
1660 (Lisp_Object line, Lisp_Object window)
1662 register struct window *w;
1663 register struct buffer *b;
1664 struct glyph_row *row, *end_row;
1665 int max_y, crop, i;
1666 EMACS_INT n;
1668 w = decode_live_window (window);
1670 if (noninteractive || w->pseudo_window_p)
1671 return Qnil;
1673 CHECK_BUFFER (w->buffer);
1674 b = XBUFFER (w->buffer);
1676 /* Fail if current matrix is not up-to-date. */
1677 if (NILP (w->window_end_valid)
1678 || current_buffer->clip_changed
1679 || current_buffer->prevent_redisplay_optimizations_p
1680 || w->last_modified < BUF_MODIFF (b)
1681 || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b))
1682 return Qnil;
1684 if (NILP (line))
1686 i = w->cursor.vpos;
1687 if (i < 0 || i >= w->current_matrix->nrows
1688 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
1689 return Qnil;
1690 max_y = window_text_bottom_y (w);
1691 goto found_row;
1694 if (EQ (line, Qheader_line))
1696 if (!WINDOW_WANTS_HEADER_LINE_P (w))
1697 return Qnil;
1698 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1699 if (!row->enabled_p)
1700 return Qnil;
1701 return list4 (make_number (row->height),
1702 make_number (0), make_number (0),
1703 make_number (0));
1706 if (EQ (line, Qmode_line))
1708 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1709 if (!row->enabled_p)
1710 return Qnil;
1711 return list4 (make_number (row->height),
1712 make_number (0), /* not accurate */
1713 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
1714 + window_text_bottom_y (w)),
1715 make_number (0));
1718 CHECK_NUMBER (line);
1719 n = XINT (line);
1721 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1722 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
1723 max_y = window_text_bottom_y (w);
1724 i = 0;
1726 while ((n < 0 || i < n)
1727 && row <= end_row && row->enabled_p
1728 && row->y + row->height < max_y)
1729 row++, i++;
1731 if (row > end_row || !row->enabled_p)
1732 return Qnil;
1734 if (++n < 0)
1736 if (-n > i)
1737 return Qnil;
1738 row += n;
1739 i += n;
1742 found_row:
1743 crop = max (0, (row->y + row->height) - max_y);
1744 return list4 (make_number (row->height + min (0, row->y) - crop),
1745 make_number (i),
1746 make_number (row->y),
1747 make_number (crop));
1750 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1751 0, 1, 0,
1752 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1753 More precisely, return the value assigned by the last call of
1754 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1755 never called with WINDOW as its argument, or the value set by that
1756 function was internally reset since its last call. WINDOW must be a
1757 live window and defaults to the selected one.
1759 When a window is dedicated to its buffer, `display-buffer' will refrain
1760 from displaying another buffer in it. `get-lru-window' and
1761 `get-largest-window' treat dedicated windows specially.
1762 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1763 `kill-buffer' can delete a dedicated window and the containing frame.
1765 Functions like `set-window-buffer' may change the buffer displayed by a
1766 window, unless that window is "strongly" dedicated to its buffer, that
1767 is the value returned by `window-dedicated-p' is t. */)
1768 (Lisp_Object window)
1770 return decode_live_window (window)->dedicated;
1773 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1774 Sset_window_dedicated_p, 2, 2, 0,
1775 doc: /* Mark WINDOW as dedicated according to FLAG.
1776 WINDOW must be a live window and defaults to the selected one. FLAG
1777 non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
1778 mark WINDOW as non-dedicated. Return FLAG.
1780 When a window is dedicated to its buffer, `display-buffer' will refrain
1781 from displaying another buffer in it. `get-lru-window' and
1782 `get-largest-window' treat dedicated windows specially.
1783 `delete-windows-on', `replace-buffer-in-windows', `quit-window',
1784 `quit-restore-window' and `kill-buffer' can delete a dedicated window
1785 and the containing frame.
1787 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1788 its buffer. Functions like `set-window-buffer' may change the buffer
1789 displayed by a window, unless that window is strongly dedicated to its
1790 buffer. If and when `set-window-buffer' displays another buffer in a
1791 window, it also makes sure that the window is no more dedicated. */)
1792 (Lisp_Object window, Lisp_Object flag)
1794 wset_dedicated (decode_live_window (window), flag);
1795 return flag;
1798 DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
1799 0, 1, 0,
1800 doc: /* Return buffers previously shown in WINDOW.
1801 WINDOW must be a live window and defaults to the selected one.
1803 The return value is a list of elements (BUFFER WINDOW-START POS),
1804 where BUFFER is a buffer, WINDOW-START is the start position of the
1805 window for that buffer, and POS is a window-specific point value. */)
1806 (Lisp_Object window)
1808 return decode_live_window (window)->prev_buffers;
1811 DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
1812 Sset_window_prev_buffers, 2, 2, 0,
1813 doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
1814 WINDOW must be a live window and defaults to the selected one.
1816 PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS),
1817 where BUFFER is a buffer, WINDOW-START is the start position of the
1818 window for that buffer, and POS is a window-specific point value. */)
1819 (Lisp_Object window, Lisp_Object prev_buffers)
1821 wset_prev_buffers (decode_live_window (window), prev_buffers);
1822 return prev_buffers;
1825 DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
1826 0, 1, 0,
1827 doc: /* Return list of buffers recently re-shown in WINDOW.
1828 WINDOW must be a live window and defaults to the selected one. */)
1829 (Lisp_Object window)
1831 return decode_live_window (window)->next_buffers;
1834 DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
1835 Sset_window_next_buffers, 2, 2, 0,
1836 doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
1837 WINDOW must be a live window and defaults to the selected one.
1838 NEXT-BUFFERS should be a list of buffers. */)
1839 (Lisp_Object window, Lisp_Object next_buffers)
1841 wset_next_buffers (decode_live_window (window), next_buffers);
1842 return next_buffers;
1845 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1846 0, 1, 0,
1847 doc: /* Return the parameters of WINDOW and their values.
1848 WINDOW must be a valid window and defaults to the selected one. The
1849 return value is a list of elements of the form (PARAMETER . VALUE). */)
1850 (Lisp_Object window)
1852 return Fcopy_alist (decode_valid_window (window)->window_parameters);
1855 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1856 2, 2, 0,
1857 doc: /* Return WINDOW's value for PARAMETER.
1858 WINDOW can be any window and defaults to the selected one. */)
1859 (Lisp_Object window, Lisp_Object parameter)
1861 Lisp_Object result;
1863 result = Fassq (parameter, decode_any_window (window)->window_parameters);
1864 return CDR_SAFE (result);
1867 DEFUN ("set-window-parameter", Fset_window_parameter,
1868 Sset_window_parameter, 3, 3, 0,
1869 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1870 WINDOW can be any window and defaults to the selected one.
1871 Return VALUE. */)
1872 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
1874 register struct window *w = decode_any_window (window);
1875 Lisp_Object old_alist_elt;
1877 old_alist_elt = Fassq (parameter, w->window_parameters);
1878 if (NILP (old_alist_elt))
1879 wset_window_parameters
1880 (w, Fcons (Fcons (parameter, value), w->window_parameters));
1881 else
1882 Fsetcdr (old_alist_elt, value);
1883 return value;
1886 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1887 0, 1, 0,
1888 doc: /* Return the display-table that WINDOW is using.
1889 WINDOW must be a live window and defaults to the selected one. */)
1890 (Lisp_Object window)
1892 return decode_live_window (window)->display_table;
1895 /* Get the display table for use on window W. This is either W's
1896 display table or W's buffer's display table. Ignore the specified
1897 tables if they are not valid; if no valid table is specified,
1898 return 0. */
1900 struct Lisp_Char_Table *
1901 window_display_table (struct window *w)
1903 struct Lisp_Char_Table *dp = NULL;
1905 if (DISP_TABLE_P (w->display_table))
1906 dp = XCHAR_TABLE (w->display_table);
1907 else if (BUFFERP (w->buffer))
1909 struct buffer *b = XBUFFER (w->buffer);
1911 if (DISP_TABLE_P (BVAR (b, display_table)))
1912 dp = XCHAR_TABLE (BVAR (b, display_table));
1913 else if (DISP_TABLE_P (Vstandard_display_table))
1914 dp = XCHAR_TABLE (Vstandard_display_table);
1917 return dp;
1920 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1921 doc: /* Set WINDOW's display-table to TABLE.
1922 WINDOW must be a live window and defaults to the selected one. */)
1923 (register Lisp_Object window, Lisp_Object table)
1925 wset_display_table (decode_live_window (window), table);
1926 return table;
1929 /* Record info on buffer window W is displaying
1930 when it is about to cease to display that buffer. */
1931 static void
1932 unshow_buffer (register struct window *w)
1934 Lisp_Object buf;
1935 struct buffer *b;
1937 buf = w->buffer;
1938 b = XBUFFER (buf);
1939 if (b != XMARKER (w->pointm)->buffer)
1940 emacs_abort ();
1942 #if 0
1943 if (w == XWINDOW (selected_window)
1944 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1945 /* Do this except when the selected window's buffer
1946 is being removed from some other window. */
1947 #endif
1948 /* last_window_start records the start position that this buffer
1949 had in the last window to be disconnected from it.
1950 Now that this statement is unconditional,
1951 it is possible for the buffer to be displayed in the
1952 selected window, while last_window_start reflects another
1953 window which was recently showing the same buffer.
1954 Some people might say that might be a good thing. Let's see. */
1955 b->last_window_start = marker_position (w->start);
1957 /* Point in the selected window's buffer
1958 is actually stored in that buffer, and the window's pointm isn't used.
1959 So don't clobber point in that buffer. */
1960 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1961 /* Don't clobber point in current buffer either (this could be
1962 useful in connection with bug#12208).
1963 && XBUFFER (buf) != current_buffer */
1964 /* This line helps to fix Horsley's testbug.el bug. */
1965 && !(WINDOWP (BVAR (b, last_selected_window))
1966 && w != XWINDOW (BVAR (b, last_selected_window))
1967 && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->buffer)))
1968 temp_set_point_both (b,
1969 clip_to_bounds (BUF_BEGV (b),
1970 XMARKER (w->pointm)->charpos,
1971 BUF_ZV (b)),
1972 clip_to_bounds (BUF_BEGV_BYTE (b),
1973 marker_byte_position (w->pointm),
1974 BUF_ZV_BYTE (b)));
1976 if (WINDOWP (BVAR (b, last_selected_window))
1977 && w == XWINDOW (BVAR (b, last_selected_window)))
1978 bset_last_selected_window (b, Qnil);
1981 /* Put NEW into the window structure in place of OLD. SETFLAG zero
1982 means change window structure only. Otherwise store geometry and
1983 other settings as well. */
1984 static void
1985 replace_window (Lisp_Object old, Lisp_Object new, int setflag)
1987 register Lisp_Object tem;
1988 register struct window *o = XWINDOW (old), *n = XWINDOW (new);
1990 /* If OLD is its frame's root window, then NEW is the new
1991 root window for that frame. */
1992 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1993 fset_root_window (XFRAME (o->frame), new);
1995 if (setflag)
1997 wset_left_col (n, o->left_col);
1998 wset_top_line (n, o->top_line);
1999 wset_total_cols (n, o->total_cols);
2000 wset_total_lines (n, o->total_lines);
2001 wset_normal_cols (n, o->normal_cols);
2002 wset_normal_cols (o, make_float (1.0));
2003 wset_normal_lines (n, o->normal_lines);
2004 wset_normal_lines (o, make_float (1.0));
2005 n->desired_matrix = n->current_matrix = 0;
2006 n->vscroll = 0;
2007 memset (&n->cursor, 0, sizeof (n->cursor));
2008 memset (&n->last_cursor, 0, sizeof (n->last_cursor));
2009 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
2010 n->phys_cursor_type = -1;
2011 n->phys_cursor_width = -1;
2012 n->must_be_updated_p = 0;
2013 n->pseudo_window_p = 0;
2014 wset_window_end_vpos (n, make_number (0));
2015 wset_window_end_pos (n, make_number (0));
2016 wset_window_end_valid (n, Qnil);
2017 n->frozen_window_start_p = 0;
2020 tem = o->next;
2021 wset_next (n, tem);
2022 if (!NILP (tem))
2023 wset_prev (XWINDOW (tem), new);
2025 tem = o->prev;
2026 wset_prev (n, tem);
2027 if (!NILP (tem))
2028 wset_next (XWINDOW (tem), new);
2030 tem = o->parent;
2031 wset_parent (n, tem);
2032 if (!NILP (tem))
2034 if (EQ (XWINDOW (tem)->vchild, old))
2035 wset_vchild (XWINDOW (tem), new);
2036 if (EQ (XWINDOW (tem)->hchild, old))
2037 wset_hchild (XWINDOW (tem), new);
2041 /* If window WINDOW and its parent window are iso-combined, merge
2042 WINDOW's children into those of its parent window and mark WINDOW as
2043 deleted. */
2045 static void
2046 recombine_windows (Lisp_Object window)
2048 struct window *w, *p, *c;
2049 Lisp_Object parent, child;
2050 int horflag;
2052 w = XWINDOW (window);
2053 parent = w->parent;
2054 if (!NILP (parent) && NILP (w->combination_limit))
2056 p = XWINDOW (parent);
2057 if (((!NILP (p->vchild) && !NILP (w->vchild))
2058 || (!NILP (p->hchild) && !NILP (w->hchild))))
2059 /* WINDOW and PARENT are both either a vertical or a horizontal
2060 combination. */
2062 horflag = NILP (w->vchild);
2063 child = horflag ? w->hchild : w->vchild;
2064 c = XWINDOW (child);
2066 /* Splice WINDOW's children into its parent's children and
2067 assign new normal sizes. */
2068 if (NILP (w->prev))
2069 if (horflag)
2070 wset_hchild (p, child);
2071 else
2072 wset_vchild (p, child);
2073 else
2075 wset_prev (c, w->prev);
2076 wset_next (XWINDOW (w->prev), child);
2079 while (c)
2081 wset_parent (c, parent);
2083 if (horflag)
2084 wset_normal_cols (c,
2085 make_float (XFLOATINT (c->total_cols)
2086 / XFLOATINT (p->total_cols)));
2087 else
2088 wset_normal_lines (c,
2089 make_float (XFLOATINT (c->total_lines)
2090 / XFLOATINT (p->total_lines)));
2092 if (NILP (c->next))
2094 if (!NILP (w->next))
2096 wset_next (c, w->next);
2097 wset_prev (XWINDOW (c->next), child);
2100 c = 0;
2102 else
2104 child = c->next;
2105 c = XWINDOW (child);
2109 /* WINDOW can be deleted now. */
2110 wset_vchild (w, Qnil);
2111 wset_hchild (w, Qnil);
2116 /* If WINDOW can be deleted, delete it. */
2117 static void
2118 delete_deletable_window (Lisp_Object window)
2120 if (!NILP (call1 (Qwindow_deletable_p, window)))
2121 call1 (Qdelete_window, window);
2124 /***********************************************************************
2125 Window List
2126 ***********************************************************************/
2128 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
2129 pointer. This is a callback function for foreach_window, used in
2130 the window_list function. */
2132 static int
2133 add_window_to_list (struct window *w, void *user_data)
2135 Lisp_Object *list = (Lisp_Object *) user_data;
2136 Lisp_Object window;
2137 XSETWINDOW (window, w);
2138 *list = Fcons (window, *list);
2139 return 1;
2143 /* Return a list of all windows, for use by next_window. If
2144 Vwindow_list is a list, return that list. Otherwise, build a new
2145 list, cache it in Vwindow_list, and return that. */
2147 static Lisp_Object
2148 window_list (void)
2150 if (!CONSP (Vwindow_list))
2152 Lisp_Object tail;
2154 Vwindow_list = Qnil;
2155 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
2157 Lisp_Object args[2];
2159 /* We are visiting windows in canonical order, and add
2160 new windows at the front of args[1], which means we
2161 have to reverse this list at the end. */
2162 args[1] = Qnil;
2163 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
2164 args[0] = Vwindow_list;
2165 args[1] = Fnreverse (args[1]);
2166 Vwindow_list = Fnconc (2, args);
2170 return Vwindow_list;
2174 /* Value is non-zero if WINDOW satisfies the constraints given by
2175 OWINDOW, MINIBUF and ALL_FRAMES.
2177 MINIBUF t means WINDOW may be minibuffer windows.
2178 `lambda' means WINDOW may not be a minibuffer window.
2179 a window means a specific minibuffer window
2181 ALL_FRAMES t means search all frames,
2182 nil means search just current frame,
2183 `visible' means search just visible frames on the
2184 current terminal,
2185 0 means search visible and iconified frames on the
2186 current terminal,
2187 a window means search the frame that window belongs to,
2188 a frame means consider windows on that frame, only. */
2190 static int
2191 candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf, Lisp_Object all_frames)
2193 struct window *w = XWINDOW (window);
2194 struct frame *f = XFRAME (w->frame);
2195 int candidate_p = 1;
2197 if (!BUFFERP (w->buffer))
2198 candidate_p = 0;
2199 else if (MINI_WINDOW_P (w)
2200 && (EQ (minibuf, Qlambda)
2201 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
2203 /* If MINIBUF is `lambda' don't consider any mini-windows.
2204 If it is a window, consider only that one. */
2205 candidate_p = 0;
2207 else if (EQ (all_frames, Qt))
2208 candidate_p = 1;
2209 else if (NILP (all_frames))
2211 eassert (WINDOWP (owindow));
2212 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
2214 else if (EQ (all_frames, Qvisible))
2216 FRAME_SAMPLE_VISIBILITY (f);
2217 candidate_p = FRAME_VISIBLE_P (f)
2218 && (FRAME_TERMINAL (XFRAME (w->frame))
2219 == FRAME_TERMINAL (XFRAME (selected_frame)));
2222 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2224 FRAME_SAMPLE_VISIBILITY (f);
2225 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2226 #ifdef HAVE_X_WINDOWS
2227 /* Yuck!! If we've just created the frame and the
2228 window-manager requested the user to place it
2229 manually, the window may still not be considered
2230 `visible'. I'd argue it should be at least
2231 something like `iconified', but don't know how to do
2232 that yet. --Stef */
2233 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
2234 && !f->output_data.x->has_been_visible)
2235 #endif
2237 && (FRAME_TERMINAL (XFRAME (w->frame))
2238 == FRAME_TERMINAL (XFRAME (selected_frame)));
2240 else if (WINDOWP (all_frames))
2241 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
2242 || EQ (XWINDOW (all_frames)->frame, w->frame)
2243 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
2244 else if (FRAMEP (all_frames))
2245 candidate_p = EQ (all_frames, w->frame);
2247 return candidate_p;
2251 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
2252 Fwindow_list. See candidate_window_p for the meaning of WINDOW,
2253 MINIBUF, and ALL_FRAMES. */
2255 static void
2256 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
2258 if (NILP (*window))
2259 *window = selected_window;
2260 else
2261 CHECK_LIVE_WINDOW (*window);
2263 /* MINIBUF nil may or may not include minibuffers. Decide if it
2264 does. */
2265 if (NILP (*minibuf))
2266 *minibuf = minibuf_level ? minibuf_window : Qlambda;
2267 else if (!EQ (*minibuf, Qt))
2268 *minibuf = Qlambda;
2270 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
2271 => count none of them, or a specific minibuffer window (the
2272 active one) to count. */
2274 /* ALL_FRAMES nil doesn't specify which frames to include. */
2275 if (NILP (*all_frames))
2276 *all_frames
2277 = (!EQ (*minibuf, Qlambda)
2278 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
2279 : Qnil);
2280 else if (EQ (*all_frames, Qvisible))
2282 else if (EQ (*all_frames, make_number (0)))
2284 else if (FRAMEP (*all_frames))
2286 else if (!EQ (*all_frames, Qt))
2287 *all_frames = Qnil;
2291 /* Return the next or previous window of WINDOW in cyclic ordering
2292 of windows. NEXT_P non-zero means return the next window. See the
2293 documentation string of next-window for the meaning of MINIBUF and
2294 ALL_FRAMES. */
2296 static Lisp_Object
2297 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
2299 decode_next_window_args (&window, &minibuf, &all_frames);
2301 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
2302 return the first window on the frame. */
2303 if (FRAMEP (all_frames)
2304 && !EQ (all_frames, XWINDOW (window)->frame))
2305 return Fframe_first_window (all_frames);
2307 if (next_p)
2309 Lisp_Object list;
2311 /* Find WINDOW in the list of all windows. */
2312 list = Fmemq (window, window_list ());
2314 /* Scan forward from WINDOW to the end of the window list. */
2315 if (CONSP (list))
2316 for (list = XCDR (list); CONSP (list); list = XCDR (list))
2317 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2318 break;
2320 /* Scan from the start of the window list up to WINDOW. */
2321 if (!CONSP (list))
2322 for (list = Vwindow_list;
2323 CONSP (list) && !EQ (XCAR (list), window);
2324 list = XCDR (list))
2325 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2326 break;
2328 if (CONSP (list))
2329 window = XCAR (list);
2331 else
2333 Lisp_Object candidate, list;
2335 /* Scan through the list of windows for candidates. If there are
2336 candidate windows in front of WINDOW, the last one of these
2337 is the one we want. If there are candidates following WINDOW
2338 in the list, again the last one of these is the one we want. */
2339 candidate = Qnil;
2340 for (list = window_list (); CONSP (list); list = XCDR (list))
2342 if (EQ (XCAR (list), window))
2344 if (WINDOWP (candidate))
2345 break;
2347 else if (candidate_window_p (XCAR (list), window, minibuf,
2348 all_frames))
2349 candidate = XCAR (list);
2352 if (WINDOWP (candidate))
2353 window = candidate;
2356 return window;
2360 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2361 doc: /* Return live window after WINDOW in the cyclic ordering of windows.
2362 WINDOW must be a live window and defaults to the selected one. The
2363 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2364 consider.
2366 MINIBUF nil or omitted means consider the minibuffer window only if the
2367 minibuffer is active. MINIBUF t means consider the minibuffer window
2368 even if the minibuffer is not active. Any other value means do not
2369 consider the minibuffer window even if the minibuffer is active.
2371 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2372 plus the minibuffer window if specified by the MINIBUF argument. If the
2373 minibuffer counts, consider all windows on all frames that share that
2374 minibuffer too. The following non-nil values of ALL-FRAMES have special
2375 meanings:
2377 - t means consider all windows on all existing frames.
2379 - `visible' means consider all windows on all visible frames.
2381 - 0 (the number zero) means consider all windows on all visible and
2382 iconified frames.
2384 - A frame means consider all windows on that frame only.
2386 Anything else means consider all windows on WINDOW's frame and no
2387 others.
2389 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2390 `next-window' to iterate through the entire cycle of acceptable
2391 windows, eventually ending up back at the window you started with.
2392 `previous-window' traverses the same cycle, in the reverse order. */)
2393 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2395 return next_window (window, minibuf, all_frames, 1);
2399 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2400 doc: /* Return live window before WINDOW in the cyclic ordering of windows.
2401 WINDOW must be a live window and defaults to the selected one. The
2402 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2403 consider.
2405 MINIBUF nil or omitted means consider the minibuffer window only if the
2406 minibuffer is active. MINIBUF t means consider the minibuffer window
2407 even if the minibuffer is not active. Any other value means do not
2408 consider the minibuffer window even if the minibuffer is active.
2410 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2411 plus the minibuffer window if specified by the MINIBUF argument. If the
2412 minibuffer counts, consider all windows on all frames that share that
2413 minibuffer too. The following non-nil values of ALL-FRAMES have special
2414 meanings:
2416 - t means consider all windows on all existing frames.
2418 - `visible' means consider all windows on all visible frames.
2420 - 0 (the number zero) means consider all windows on all visible and
2421 iconified frames.
2423 - A frame means consider all windows on that frame only.
2425 Anything else means consider all windows on WINDOW's frame and no
2426 others.
2428 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2429 use `previous-window' to iterate through the entire cycle of
2430 acceptable windows, eventually ending up back at the window you
2431 started with. `next-window' traverses the same cycle, in the
2432 reverse order. */)
2433 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2435 return next_window (window, minibuf, all_frames, 0);
2439 /* Return a list of windows in cyclic ordering. Arguments are like
2440 for `next-window'. */
2442 static Lisp_Object
2443 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2445 Lisp_Object tail, list, rest;
2447 decode_next_window_args (&window, &minibuf, &all_frames);
2448 list = Qnil;
2450 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2451 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2452 list = Fcons (XCAR (tail), list);
2454 /* Rotate the list to start with WINDOW. */
2455 list = Fnreverse (list);
2456 rest = Fmemq (window, list);
2457 if (!NILP (rest) && !EQ (rest, list))
2459 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2461 XSETCDR (tail, Qnil);
2462 list = nconc2 (rest, list);
2464 return list;
2468 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2469 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2470 FRAME nil or omitted means use the selected frame.
2471 WINDOW nil or omitted means use the window selected within FRAME.
2472 MINIBUF t means include the minibuffer window, even if it isn't active.
2473 MINIBUF nil or omitted means include the minibuffer window only
2474 if it's active.
2475 MINIBUF neither nil nor t means never include the minibuffer window. */)
2476 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2478 if (NILP (window))
2479 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2480 CHECK_WINDOW (window);
2481 if (NILP (frame))
2482 frame = selected_frame;
2484 if (!EQ (frame, XWINDOW (window)->frame))
2485 error ("Window is on a different frame");
2487 return window_list_1 (window, minibuf, frame);
2491 DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2492 doc: /* Return a list of all live windows.
2493 WINDOW specifies the first window to list and defaults to the selected
2494 window.
2496 Optional argument MINIBUF nil or omitted means consider the minibuffer
2497 window only if the minibuffer is active. MINIBUF t means consider the
2498 minibuffer window even if the minibuffer is not active. Any other value
2499 means do not consider the minibuffer window even if the minibuffer is
2500 active.
2502 Optional argument ALL-FRAMES nil or omitted means consider all windows
2503 on WINDOW's frame, plus the minibuffer window if specified by the
2504 MINIBUF argument. If the minibuffer counts, consider all windows on all
2505 frames that share that minibuffer too. The following non-nil values of
2506 ALL-FRAMES have special meanings:
2508 - t means consider all windows on all existing frames.
2510 - `visible' means consider all windows on all visible frames.
2512 - 0 (the number zero) means consider all windows on all visible and
2513 iconified frames.
2515 - A frame means consider all windows on that frame only.
2517 Anything else means consider all windows on WINDOW's frame and no
2518 others.
2520 If WINDOW is not on the list of windows returned, some other window will
2521 be listed first but no error is signaled. */)
2522 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2524 return window_list_1 (window, minibuf, all_frames);
2527 /* Look at all windows, performing an operation specified by TYPE
2528 with argument OBJ.
2529 If FRAMES is Qt, look at all frames;
2530 Qnil, look at just the selected frame;
2531 Qvisible, look at visible frames;
2532 a frame, just look at windows on that frame.
2533 If MINI is non-zero, perform the operation on minibuffer windows too. */
2535 enum window_loop
2537 WINDOW_LOOP_UNUSED,
2538 GET_BUFFER_WINDOW, /* Arg is buffer */
2539 REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
2540 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2541 CHECK_ALL_WINDOWS
2544 static Lisp_Object
2545 window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
2547 Lisp_Object window, windows, best_window, frame_arg;
2548 int frame_best_window_flag = 0;
2549 struct frame *f;
2550 struct gcpro gcpro1;
2552 /* If we're only looping through windows on a particular frame,
2553 frame points to that frame. If we're looping through windows
2554 on all frames, frame is 0. */
2555 if (FRAMEP (frames))
2556 f = XFRAME (frames);
2557 else if (NILP (frames))
2558 f = SELECTED_FRAME ();
2559 else
2560 f = NULL;
2562 if (f)
2563 frame_arg = Qlambda;
2564 else if (EQ (frames, make_number (0)))
2565 frame_arg = frames;
2566 else if (EQ (frames, Qvisible))
2567 frame_arg = frames;
2568 else
2569 frame_arg = Qt;
2571 /* frame_arg is Qlambda to stick to one frame,
2572 Qvisible to consider all visible frames,
2573 or Qt otherwise. */
2575 /* Pick a window to start with. */
2576 if (WINDOWP (obj))
2577 window = obj;
2578 else if (f)
2579 window = FRAME_SELECTED_WINDOW (f);
2580 else
2581 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2583 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2584 GCPRO1 (windows);
2585 best_window = Qnil;
2587 for (; CONSP (windows); windows = XCDR (windows))
2589 struct window *w;
2591 window = XCAR (windows);
2592 w = XWINDOW (window);
2594 /* Note that we do not pay attention here to whether the frame
2595 is visible, since Fwindow_list skips non-visible frames if
2596 that is desired, under the control of frame_arg. */
2597 if (!MINI_WINDOW_P (w)
2598 /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
2599 consider all windows. */
2600 || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
2601 || (mini && minibuf_level > 0))
2602 switch (type)
2604 case GET_BUFFER_WINDOW:
2605 if (EQ (w->buffer, obj)
2606 /* Don't find any minibuffer window except the one that
2607 is currently in use. */
2608 && (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
2610 if (EQ (window, selected_window))
2611 /* Preferably return the selected window. */
2612 RETURN_UNGCPRO (window);
2613 else if (EQ (XWINDOW (window)->frame, selected_frame)
2614 && !frame_best_window_flag)
2615 /* Prefer windows on the current frame (but don't
2616 choose another one if we have one already). */
2618 best_window = window;
2619 frame_best_window_flag = 1;
2621 else if (NILP (best_window))
2622 best_window = window;
2624 break;
2626 case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
2627 /* We could simply check whether the buffer shown by window
2628 is live, and show another buffer in case it isn't. */
2629 if (EQ (w->buffer, obj))
2631 /* Undedicate WINDOW. */
2632 wset_dedicated (w, Qnil);
2633 /* Make WINDOW show the buffer returned by
2634 other_buffer_safely, don't run any hooks. */
2635 set_window_buffer
2636 (window, other_buffer_safely (w->buffer), 0, 0);
2637 /* If WINDOW is the selected window, make its buffer
2638 current. But do so only if the window shows the
2639 current buffer (Bug#6454). */
2640 if (EQ (window, selected_window)
2641 && XBUFFER (w->buffer) == current_buffer)
2642 Fset_buffer (w->buffer);
2644 break;
2646 case REDISPLAY_BUFFER_WINDOWS:
2647 if (EQ (w->buffer, obj))
2649 mark_window_display_accurate (window, 0);
2650 w->update_mode_line = 1;
2651 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2652 ++update_mode_lines;
2653 best_window = window;
2655 break;
2657 /* Check for a window that has a killed buffer. */
2658 case CHECK_ALL_WINDOWS:
2659 if (! NILP (w->buffer)
2660 && !BUFFER_LIVE_P (XBUFFER (w->buffer)))
2661 emacs_abort ();
2662 break;
2664 case WINDOW_LOOP_UNUSED:
2665 break;
2669 UNGCPRO;
2670 return best_window;
2673 /* Used for debugging. Abort if any window has a dead buffer. */
2675 extern void check_all_windows (void) EXTERNALLY_VISIBLE;
2676 void
2677 check_all_windows (void)
2679 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2682 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2683 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2684 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
2685 the current buffer.
2687 The optional argument ALL-FRAMES specifies the frames to consider:
2689 - t means consider all windows on all existing frames.
2691 - `visible' means consider all windows on all visible frames.
2693 - 0 (the number zero) means consider all windows on all visible
2694 and iconified frames.
2696 - A frame means consider all windows on that frame only.
2698 Any other value of ALL-FRAMES means consider all windows on the
2699 selected frame and no others. */)
2700 (Lisp_Object buffer_or_name, Lisp_Object all_frames)
2702 Lisp_Object buffer;
2704 if (NILP (buffer_or_name))
2705 buffer = Fcurrent_buffer ();
2706 else
2707 buffer = Fget_buffer (buffer_or_name);
2709 if (BUFFERP (buffer))
2710 return window_loop (GET_BUFFER_WINDOW, buffer, 1, all_frames);
2711 else
2712 return Qnil;
2715 static Lisp_Object
2716 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore)
2718 return call4 (Qwindow_resize_root_window, window, delta, horizontal, ignore);
2722 DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
2723 Sdelete_other_windows_internal, 0, 2, "",
2724 doc: /* Make WINDOW fill its frame.
2725 Only the frame WINDOW is on is affected. WINDOW must be a valid window
2726 and defaults to the selected one.
2728 Optional argument ROOT, if non-nil, must specify an internal window such
2729 that WINDOW is in its window subtree. If this is the case, replace ROOT
2730 by WINDOW and leave alone any windows not part of ROOT's subtree.
2732 When WINDOW is live try to reduce display jumps by keeping the text
2733 previously visible in WINDOW in the same place on the frame. Doing this
2734 depends on the value of (window-start WINDOW), so if calling this
2735 function in a program gives strange scrolling, make sure the
2736 window-start value is reasonable when this function is called. */)
2737 (Lisp_Object window, Lisp_Object root)
2739 struct window *w, *r, *s;
2740 struct frame *f;
2741 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
2742 ptrdiff_t startpos IF_LINT (= 0);
2743 int top IF_LINT (= 0), new_top, resize_failed;
2745 w = decode_valid_window (window);
2746 XSETWINDOW (window, w);
2747 f = XFRAME (w->frame);
2749 if (NILP (root))
2750 /* ROOT is the frame's root window. */
2752 root = FRAME_ROOT_WINDOW (f);
2753 r = XWINDOW (root);
2755 else
2756 /* ROOT must be an ancestor of WINDOW. */
2758 r = decode_valid_window (root);
2759 pwindow = XWINDOW (window)->parent;
2760 while (!NILP (pwindow))
2761 if (EQ (pwindow, root))
2762 break;
2763 else
2764 pwindow = XWINDOW (pwindow)->parent;
2765 if (!EQ (pwindow, root))
2766 error ("Specified root is not an ancestor of specified window");
2769 if (EQ (window, root))
2770 /* A noop. */
2771 return Qnil;
2772 /* I don't understand the "top > 0" part below. If we deal with a
2773 standalone minibuffer it would have been caught by the preceding
2774 test. */
2775 else if (MINI_WINDOW_P (w)) /* && top > 0) */
2776 error ("Can't expand minibuffer to full frame");
2778 if (!NILP (w->buffer))
2780 startpos = marker_position (w->start);
2781 top = WINDOW_TOP_EDGE_LINE (w)
2782 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2783 /* Make sure WINDOW is the frame's selected window. */
2784 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
2786 if (EQ (selected_frame, w->frame))
2787 Fselect_window (window, Qnil);
2788 else
2789 fset_selected_window (f, window);
2792 else
2794 /* See if the frame's selected window is a part of the window
2795 subtree rooted at WINDOW, by finding all the selected window's
2796 parents and comparing each one with WINDOW. If it isn't we
2797 need a new selected window for this frame. */
2798 swindow = FRAME_SELECTED_WINDOW (f);
2799 while (1)
2801 pwindow = swindow;
2802 while (!NILP (pwindow) && !EQ (window, pwindow))
2803 pwindow = XWINDOW (pwindow)->parent;
2805 if (EQ (window, pwindow))
2806 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
2807 as the new selected window. */
2808 break;
2809 else
2810 /* Else try the previous window of SWINDOW. */
2811 swindow = Fprevious_window (swindow, Qlambda, Qnil);
2814 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
2816 if (EQ (selected_frame, w->frame))
2817 Fselect_window (swindow, Qnil);
2818 else
2819 fset_selected_window (f, swindow);
2823 BLOCK_INPUT;
2824 if (!FRAME_INITIAL_P (f))
2826 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
2828 /* We are going to free the glyph matrices of WINDOW, and with
2829 that we might lose any information about glyph rows that have
2830 some of their glyphs highlighted in mouse face. (These rows
2831 are marked with a non-zero mouse_face_p flag.) If WINDOW
2832 indeed has some glyphs highlighted in mouse face, signal to
2833 frame's up-to-date hook that mouse highlight was overwritten,
2834 so that it will arrange for redisplaying the highlight. */
2835 if (EQ (hlinfo->mouse_face_window, window))
2837 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
2838 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
2839 hlinfo->mouse_face_window = Qnil;
2842 free_window_matrices (r);
2844 windows_or_buffers_changed++;
2845 Vwindow_list = Qnil;
2846 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
2847 resize_failed = 0;
2849 if (NILP (w->buffer))
2851 /* Resize child windows vertically. */
2852 XSETINT (delta, XINT (r->total_lines)
2853 - XINT (w->total_lines));
2854 wset_top_line (w, r->top_line);
2855 resize_root_window (window, delta, Qnil, Qnil);
2856 if (window_resize_check (w, 0))
2857 window_resize_apply (w, 0);
2858 else
2860 resize_root_window (window, delta, Qnil, Qt);
2861 if (window_resize_check (w, 0))
2862 window_resize_apply (w, 0);
2863 else
2864 resize_failed = 1;
2867 /* Resize child windows horizontally. */
2868 if (!resize_failed)
2870 wset_left_col (w, r->left_col);
2871 XSETINT (delta,
2872 XINT (r->total_cols) - XINT (w->total_cols));
2873 wset_left_col (w, r->left_col);
2874 resize_root_window (window, delta, Qt, Qnil);
2875 if (window_resize_check (w, 1))
2876 window_resize_apply (w, 1);
2877 else
2879 resize_root_window (window, delta, Qt, Qt);
2880 if (window_resize_check (w, 1))
2881 window_resize_apply (w, 1);
2882 else
2883 resize_failed = 1;
2887 if (resize_failed)
2888 /* Play safe, if we still can ... */
2890 window = swindow;
2891 w = XWINDOW (window);
2895 /* Cleanly unlink WINDOW from window-tree. */
2896 if (!NILP (w->prev))
2897 /* Get SIBLING above (on the left of) WINDOW. */
2899 sibling = w->prev;
2900 s = XWINDOW (sibling);
2901 wset_next (s, w->next);
2902 if (!NILP (s->next))
2903 wset_prev (XWINDOW (s->next), sibling);
2905 else
2906 /* Get SIBLING below (on the right of) WINDOW. */
2908 sibling = w->next;
2909 s = XWINDOW (sibling);
2910 wset_prev (s, Qnil);
2911 if (!NILP (XWINDOW (w->parent)->vchild))
2912 wset_vchild (XWINDOW (w->parent), sibling);
2913 else
2914 wset_hchild (XWINDOW (w->parent), sibling);
2917 /* Delete ROOT and all child windows of ROOT. */
2918 if (!NILP (r->vchild))
2920 delete_all_child_windows (r->vchild);
2921 wset_vchild (r, Qnil);
2923 else if (!NILP (r->hchild))
2925 delete_all_child_windows (r->hchild);
2926 wset_hchild (r, Qnil);
2929 replace_window (root, window, 1);
2931 /* This must become SWINDOW anyway ....... */
2932 if (!NILP (w->buffer) && !resize_failed)
2934 /* Try to minimize scrolling, by setting the window start to the
2935 point will cause the text at the old window start to be at the
2936 same place on the frame. But don't try to do this if the
2937 window start is outside the visible portion (as might happen
2938 when the display is not current, due to typeahead). */
2939 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2940 if (new_top != top
2941 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2942 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2944 struct position pos;
2945 struct buffer *obuf = current_buffer;
2947 Fset_buffer (w->buffer);
2948 /* This computation used to temporarily move point, but that
2949 can have unwanted side effects due to text properties. */
2950 pos = *vmotion (startpos, -top, w);
2952 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2953 wset_window_end_valid (w, Qnil);
2954 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
2955 || FETCH_BYTE (pos.bytepos - 1) == '\n');
2956 /* We need to do this, so that the window-scroll-functions
2957 get called. */
2958 w->optional_new_start = 1;
2960 set_buffer_internal (obuf);
2964 adjust_glyphs (f);
2965 UNBLOCK_INPUT;
2967 run_window_configuration_change_hook (f);
2969 return Qnil;
2973 void
2974 replace_buffer_in_windows (Lisp_Object buffer)
2976 call1 (Qreplace_buffer_in_windows, buffer);
2980 /* Safely replace BUFFER with some other buffer in all windows of all
2981 frames, even those on other keyboards. */
2983 void
2984 replace_buffer_in_windows_safely (Lisp_Object buffer)
2986 Lisp_Object tail, frame;
2988 /* A single call to window_loop won't do the job because it only
2989 considers frames on the current keyboard. So loop manually over
2990 frames, and handle each one. */
2991 FOR_EACH_FRAME (tail, frame)
2992 window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
2995 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2996 minimum allowable size. */
2998 void
2999 check_frame_size (FRAME_PTR frame, int *rows, int *cols)
3001 /* For height, we have to see:
3002 how many windows the frame has at minimum (one or two),
3003 and whether it has a menu bar or other special stuff at the top. */
3004 int min_height
3005 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
3006 ? MIN_SAFE_WINDOW_HEIGHT
3007 : 2 * MIN_SAFE_WINDOW_HEIGHT);
3009 if (FRAME_TOP_MARGIN (frame) > 0)
3010 min_height += FRAME_TOP_MARGIN (frame);
3012 if (*rows < min_height)
3013 *rows = min_height;
3014 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3015 *cols = MIN_SAFE_WINDOW_WIDTH;
3018 /* Adjust the margins of window W if text area is too small.
3019 Return 1 if window width is ok after adjustment; 0 if window
3020 is still too narrow. */
3022 static int
3023 adjust_window_margins (struct window *w)
3025 int box_cols = (WINDOW_TOTAL_COLS (w)
3026 - WINDOW_FRINGE_COLS (w)
3027 - WINDOW_SCROLL_BAR_COLS (w));
3028 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
3029 + WINDOW_RIGHT_MARGIN_COLS (w));
3031 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
3032 return 1;
3034 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
3035 return 0;
3037 /* Window's text area is too narrow, but reducing the window
3038 margins will fix that. */
3039 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
3040 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
3042 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
3044 wset_left_margin_cols (w, make_number (margin_cols / 2));
3045 wset_right_margin_cols (w, make_number (margin_cols / 2));
3047 else
3048 wset_right_margin_cols (w, make_number (margin_cols));
3050 else
3051 wset_left_margin_cols (w, make_number (margin_cols));
3052 return 1;
3055 /* The following three routines are needed for running a window's
3056 configuration change hook. */
3057 static void
3058 run_funs (Lisp_Object funs)
3060 for (; CONSP (funs); funs = XCDR (funs))
3061 if (!EQ (XCAR (funs), Qt))
3062 call0 (XCAR (funs));
3065 static Lisp_Object
3066 select_window_norecord (Lisp_Object window)
3068 return WINDOW_LIVE_P (window)
3069 ? Fselect_window (window, Qt) : selected_window;
3072 static Lisp_Object
3073 select_frame_norecord (Lisp_Object frame)
3075 return FRAME_LIVE_P (XFRAME (frame))
3076 ? Fselect_frame (frame, Qt) : selected_frame;
3079 void
3080 run_window_configuration_change_hook (struct frame *f)
3082 ptrdiff_t count = SPECPDL_INDEX ();
3083 Lisp_Object frame, global_wcch
3084 = Fdefault_value (Qwindow_configuration_change_hook);
3085 XSETFRAME (frame, f);
3087 if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code))
3088 return;
3090 /* Use the right buffer. Matters when running the local hooks. */
3091 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3093 record_unwind_current_buffer ();
3094 Fset_buffer (Fwindow_buffer (Qnil));
3097 if (SELECTED_FRAME () != f)
3099 record_unwind_protect (select_frame_norecord, Fselected_frame ());
3100 select_frame_norecord (frame);
3103 /* Look for buffer-local values. */
3105 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3106 for (; CONSP (windows); windows = XCDR (windows))
3108 Lisp_Object window = XCAR (windows);
3109 Lisp_Object buffer = Fwindow_buffer (window);
3110 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3111 buffer)))
3113 ptrdiff_t inner_count = SPECPDL_INDEX ();
3114 record_unwind_protect (select_window_norecord, Fselected_window ());
3115 select_window_norecord (window);
3116 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3117 buffer));
3118 unbind_to (inner_count, Qnil);
3123 run_funs (global_wcch);
3124 unbind_to (count, Qnil);
3127 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
3128 Srun_window_configuration_change_hook, 1, 1, 0,
3129 doc: /* Run `window-configuration-change-hook' for FRAME. */)
3130 (Lisp_Object frame)
3132 CHECK_LIVE_FRAME (frame);
3133 run_window_configuration_change_hook (XFRAME (frame));
3134 return Qnil;
3137 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3138 means it's allowed to run hooks. See make_frame for a case where
3139 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3140 margins, fringes, and scroll-bar settings of the window are not
3141 reset from the buffer's local settings. */
3143 void
3144 set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int keep_margins_p)
3146 struct window *w = XWINDOW (window);
3147 struct buffer *b = XBUFFER (buffer);
3148 ptrdiff_t count = SPECPDL_INDEX ();
3149 int samebuf = EQ (buffer, w->buffer);
3151 wset_buffer (w, buffer);
3153 if (EQ (window, selected_window))
3154 bset_last_selected_window (b, window);
3156 /* Let redisplay errors through. */
3157 b->display_error_modiff = 0;
3159 /* Update time stamps of buffer display. */
3160 if (INTEGERP (BVAR (b, display_count)))
3161 bset_display_count (b, make_number (XINT (BVAR (b, display_count)) + 1));
3162 bset_display_time (b, Fcurrent_time ());
3164 wset_window_end_pos (w, make_number (0));
3165 wset_window_end_vpos (w, make_number (0));
3166 memset (&w->last_cursor, 0, sizeof w->last_cursor);
3167 wset_window_end_valid (w, Qnil);
3168 if (!(keep_margins_p && samebuf))
3169 { /* If we're not actually changing the buffer, don't reset hscroll and
3170 vscroll. This case happens for example when called from
3171 change_frame_size_1, where we use a dummy call to
3172 Fset_window_buffer on the frame's selected window (and no other)
3173 just in order to run window-configuration-change-hook.
3174 Resetting hscroll and vscroll here is problematic for things like
3175 image-mode and doc-view-mode since it resets the image's position
3176 whenever we resize the frame. */
3177 w->hscroll = w->min_hscroll = 0;
3178 w->vscroll = 0;
3179 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3180 set_marker_restricted (w->start,
3181 make_number (b->last_window_start),
3182 buffer);
3183 w->start_at_line_beg = 0;
3184 w->force_start = 0;
3185 w->last_modified = 0;
3186 w->last_overlay_modified = 0;
3188 /* Maybe we could move this into the `if' but it's not obviously safe and
3189 I doubt it's worth the trouble. */
3190 windows_or_buffers_changed++;
3192 /* We must select BUFFER for running the window-scroll-functions. */
3193 /* We can't check ! NILP (Vwindow_scroll_functions) here
3194 because that might itself be a local variable. */
3195 if (window_initialized)
3197 record_unwind_current_buffer ();
3198 Fset_buffer (buffer);
3201 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3203 if (!keep_margins_p)
3205 /* Set left and right marginal area width etc. from buffer. */
3207 /* This may call adjust_window_margins three times, so
3208 temporarily disable window margins. */
3209 Lisp_Object save_left = w->left_margin_cols;
3210 Lisp_Object save_right = w->right_margin_cols;
3212 wset_left_margin_cols (w, Qnil);
3213 wset_right_margin_cols (w, Qnil);
3215 Fset_window_fringes (window,
3216 BVAR (b, left_fringe_width), BVAR (b, right_fringe_width),
3217 BVAR (b, fringes_outside_margins));
3219 Fset_window_scroll_bars (window,
3220 BVAR (b, scroll_bar_width),
3221 BVAR (b, vertical_scroll_bar_type), Qnil);
3223 wset_left_margin_cols (w, save_left);
3224 wset_right_margin_cols (w, save_right);
3226 Fset_window_margins (window,
3227 BVAR (b, left_margin_cols), BVAR (b, right_margin_cols));
3230 if (run_hooks_p)
3232 if (! NILP (Vwindow_scroll_functions))
3233 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3234 Fmarker_position (w->start));
3235 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3238 unbind_to (count, Qnil);
3241 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3242 doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3243 WINDOW must be a live window and defaults to the selected one.
3244 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
3246 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
3247 display margins, fringe widths, and scroll bar settings are preserved;
3248 the default is to reset these from the local settings for BUFFER-OR-NAME
3249 or the frame defaults. Return nil.
3251 This function throws an error when WINDOW is strongly dedicated to its
3252 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3253 already display BUFFER-OR-NAME.
3255 This function runs `window-scroll-functions' before running
3256 `window-configuration-change-hook'. */)
3257 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3259 register Lisp_Object tem, buffer;
3260 register struct window *w = decode_live_window (window);
3262 XSETWINDOW (window, w);
3263 buffer = Fget_buffer (buffer_or_name);
3264 CHECK_BUFFER (buffer);
3265 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3266 error ("Attempt to display deleted buffer");
3268 tem = w->buffer;
3269 if (NILP (tem))
3270 error ("Window is deleted");
3271 else if (!EQ (tem, Qt))
3272 /* w->buffer is t when the window is first being set up. */
3274 if (!EQ (tem, buffer))
3276 if (EQ (w->dedicated, Qt))
3277 /* WINDOW is strongly dedicated to its buffer, signal an
3278 error. */
3279 error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
3280 else
3281 /* WINDOW is weakly dedicated to its buffer, reset
3282 dedication. */
3283 wset_dedicated (w, Qnil);
3285 call1 (Qrecord_window_buffer, window);
3288 unshow_buffer (w);
3291 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3293 return Qnil;
3296 static Lisp_Object
3297 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3299 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3302 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3303 0, 1, 0,
3304 doc: /* Force all windows to be updated on next redisplay.
3305 If optional arg OBJECT is a window, force redisplay of that window only.
3306 If OBJECT is a buffer or buffer name, force redisplay of all windows
3307 displaying that buffer. */)
3308 (Lisp_Object object)
3310 if (NILP (object))
3312 windows_or_buffers_changed++;
3313 update_mode_lines++;
3314 return Qt;
3317 if (WINDOWP (object))
3319 struct window *w = XWINDOW (object);
3320 mark_window_display_accurate (object, 0);
3321 w->update_mode_line = 1;
3322 if (BUFFERP (w->buffer))
3323 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3324 ++update_mode_lines;
3325 return Qt;
3328 if (STRINGP (object))
3329 object = Fget_buffer (object);
3330 if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object)))
3332 /* Walk all windows looking for buffer, and force update
3333 of each of those windows. */
3335 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3336 return NILP (object) ? Qnil : Qt;
3339 /* If nothing suitable was found, just return.
3340 We could signal an error, but this feature will typically be used
3341 asynchronously in timers or process sentinels, so we don't. */
3342 return Qnil;
3346 void
3347 temp_output_buffer_show (register Lisp_Object buf)
3349 register struct buffer *old = current_buffer;
3350 register Lisp_Object window;
3351 register struct window *w;
3353 bset_directory (XBUFFER (buf), BVAR (current_buffer, directory));
3355 Fset_buffer (buf);
3356 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3357 BEGV = BEG;
3358 ZV = Z;
3359 SET_PT (BEG);
3360 set_buffer_internal (old);
3362 if (!NILP (Vtemp_buffer_show_function))
3363 call1 (Vtemp_buffer_show_function, buf);
3364 else
3366 window = display_buffer (buf, Qnil, Qnil);
3368 if (!EQ (XWINDOW (window)->frame, selected_frame))
3369 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3370 Vminibuf_scroll_window = window;
3371 w = XWINDOW (window);
3372 w->hscroll = 0;
3373 w->min_hscroll = 0;
3374 set_marker_restricted_both (w->start, buf, BEG, BEG);
3375 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3377 /* Run temp-buffer-show-hook, with the chosen window selected
3378 and its buffer current. */
3380 ptrdiff_t count = SPECPDL_INDEX ();
3381 Lisp_Object prev_window, prev_buffer;
3382 prev_window = selected_window;
3383 XSETBUFFER (prev_buffer, old);
3385 /* Select the window that was chosen, for running the hook.
3386 Note: Both Fselect_window and select_window_norecord may
3387 set-buffer to the buffer displayed in the window,
3388 so we need to save the current buffer. --stef */
3389 record_unwind_protect (Fset_buffer, prev_buffer);
3390 record_unwind_protect (select_window_norecord, prev_window);
3391 Fselect_window (window, Qt);
3392 Fset_buffer (w->buffer);
3393 Frun_hooks (1, &Qtemp_buffer_show_hook);
3394 unbind_to (count, Qnil);
3399 DEFUN ("internal-temp-output-buffer-show",
3400 Ftemp_output_buffer_show, Stemp_output_buffer_show,
3401 1, 1, 0,
3402 doc: /* Internal function for `with-output-to-temp-buffer'. */)
3403 (Lisp_Object buf)
3405 temp_output_buffer_show (buf);
3406 return Qnil;
3409 /* Make new window, have it replace WINDOW in window-tree, and make
3410 WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
3411 horizontal child). */
3412 static void
3413 make_parent_window (Lisp_Object window, int horflag)
3415 Lisp_Object parent;
3416 register struct window *o, *p;
3418 o = XWINDOW (window);
3419 p = allocate_window ();
3420 memcpy ((char *) p + sizeof (struct vectorlike_header),
3421 (char *) o + sizeof (struct vectorlike_header),
3422 word_size * VECSIZE (struct window));
3423 XSETWINDOW (parent, p);
3425 p->sequence_number = ++sequence_number;
3427 replace_window (window, parent, 1);
3429 wset_next (o, Qnil);
3430 wset_prev (o, Qnil);
3431 wset_parent (o, parent);
3433 wset_hchild (p, horflag ? window : Qnil);
3434 wset_vchild (p, horflag ? Qnil : window);
3435 wset_start (p, Qnil);
3436 wset_pointm (p, Qnil);
3437 wset_buffer (p, Qnil);
3438 wset_combination_limit (p, Qnil);
3439 wset_window_parameters (p, Qnil);
3442 /* Make new window from scratch. */
3443 Lisp_Object
3444 make_window (void)
3446 Lisp_Object window;
3447 register struct window *w;
3449 w = allocate_window ();
3450 /* Initialize Lisp data. Note that allocate_window initializes all
3451 Lisp data to nil, so do it only for slots which should not be nil. */
3452 wset_left_col (w, make_number (0));
3453 wset_top_line (w, make_number (0));
3454 wset_total_lines (w, make_number (0));
3455 wset_total_cols (w, make_number (0));
3456 wset_normal_lines (w, make_float (1.0));
3457 wset_normal_cols (w, make_float (1.0));
3458 wset_new_total (w, make_number (0));
3459 wset_new_normal (w, make_number (0));
3460 wset_start (w, Fmake_marker ());
3461 wset_pointm (w, Fmake_marker ());
3462 wset_vertical_scroll_bar_type (w, Qt);
3463 wset_window_end_pos (w, make_number (0));
3464 wset_window_end_vpos (w, make_number (0));
3466 /* Initialize non-Lisp data. Note that allocate_window zeroes out all
3467 non-Lisp data, so do it only for slots which should not be zero. */
3468 w->nrows_scale_factor = w->ncols_scale_factor = 1;
3469 w->phys_cursor_type = -1;
3470 w->phys_cursor_width = -1;
3471 w->sequence_number = ++sequence_number;
3473 /* Reset window_list. */
3474 Vwindow_list = Qnil;
3475 /* Return window. */
3476 XSETWINDOW (window, w);
3477 return window;
3480 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
3481 doc: /* Set new total size of WINDOW to SIZE.
3482 WINDOW must be a valid window and defaults to the selected one.
3483 Return SIZE.
3485 Optional argument ADD non-nil means add SIZE to the new total size of
3486 WINDOW and return the sum.
3488 Note: This function does not operate on any child windows of WINDOW. */)
3489 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3491 struct window *w = decode_valid_window (window);
3493 CHECK_NUMBER (size);
3494 if (NILP (add))
3495 wset_new_total (w, size);
3496 else
3497 wset_new_total (w, make_number (XINT (w->new_total) + XINT (size)));
3499 return w->new_total;
3502 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
3503 doc: /* Set new normal size of WINDOW to SIZE.
3504 WINDOW must be a valid window and defaults to the selected one.
3505 Return SIZE.
3507 Note: This function does not operate on any child windows of WINDOW. */)
3508 (Lisp_Object window, Lisp_Object size)
3510 wset_new_normal (decode_valid_window (window), size);
3511 return size;
3514 /* Return 1 if setting w->total_lines (w->total_cols if HORFLAG is
3515 non-zero) to w->new_total would result in correct heights (widths)
3516 for window W and recursively all child windows of W.
3518 Note: This function does not check any of `window-fixed-size-p',
3519 `window-min-height' or `window-min-width'. It does check that window
3520 sizes do not drop below one line (two columns). */
3521 static int
3522 window_resize_check (struct window *w, int horflag)
3524 struct window *c;
3526 if (!NILP (w->vchild))
3527 /* W is a vertical combination. */
3529 c = XWINDOW (w->vchild);
3530 if (horflag)
3531 /* All child windows of W must have the same width as W. */
3533 while (c)
3535 if ((XINT (c->new_total) != XINT (w->new_total))
3536 || !window_resize_check (c, horflag))
3537 return 0;
3538 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3540 return 1;
3542 else
3543 /* The sum of the heights of the child windows of W must equal
3544 W's height. */
3546 int sum_of_sizes = 0;
3547 while (c)
3549 if (!window_resize_check (c, horflag))
3550 return 0;
3551 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3552 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3554 return (sum_of_sizes == XINT (w->new_total));
3557 else if (!NILP (w->hchild))
3558 /* W is a horizontal combination. */
3560 c = XWINDOW (w->hchild);
3561 if (horflag)
3562 /* The sum of the widths of the child windows of W must equal W's
3563 width. */
3565 int sum_of_sizes = 0;
3566 while (c)
3568 if (!window_resize_check (c, horflag))
3569 return 0;
3570 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3571 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3573 return (sum_of_sizes == XINT (w->new_total));
3575 else
3576 /* All child windows of W must have the same height as W. */
3578 while (c)
3580 if ((XINT (c->new_total) != XINT (w->new_total))
3581 || !window_resize_check (c, horflag))
3582 return 0;
3583 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3585 return 1;
3588 else
3589 /* A leaf window. Make sure it's not too small. The following
3590 hardcodes the values of `window-safe-min-width' (2) and
3591 `window-safe-min-height' (1) which are defined in window.el. */
3592 return XINT (w->new_total) >= (horflag ? 2 : 1);
3595 /* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
3596 w->new_total for window W and recursively all child windows of W.
3597 Also calculate and assign the new vertical (horizontal) start
3598 positions of each of these windows.
3600 This function does not perform any error checks. Make sure you have
3601 run window_resize_check on W before applying this function. */
3602 static void
3603 window_resize_apply (struct window *w, int horflag)
3605 struct window *c;
3606 int pos;
3608 /* Note: Assigning new_normal requires that the new total size of the
3609 parent window has been set *before*. */
3610 if (horflag)
3612 wset_total_cols (w, w->new_total);
3613 if (NUMBERP (w->new_normal))
3614 wset_normal_cols (w, w->new_normal);
3616 pos = XINT (w->left_col);
3618 else
3620 wset_total_lines (w, w->new_total);
3621 if (NUMBERP (w->new_normal))
3622 wset_normal_lines (w, w->new_normal);
3624 pos = XINT (w->top_line);
3627 if (!NILP (w->vchild))
3628 /* W is a vertical combination. */
3630 c = XWINDOW (w->vchild);
3631 while (c)
3633 if (horflag)
3634 wset_left_col (c, make_number (pos));
3635 else
3636 wset_top_line (c, make_number (pos));
3637 window_resize_apply (c, horflag);
3638 if (!horflag)
3639 pos = pos + XINT (c->total_lines);
3640 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3643 else if (!NILP (w->hchild))
3644 /* W is a horizontal combination. */
3646 c = XWINDOW (w->hchild);
3647 while (c)
3649 if (horflag)
3650 wset_left_col (c, make_number (pos));
3651 else
3652 wset_top_line (c, make_number (pos));
3653 window_resize_apply (c, horflag);
3654 if (horflag)
3655 pos = pos + XINT (c->total_cols);
3656 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3660 /* Clear out some redisplay caches. */
3661 w->last_modified = 0;
3662 w->last_overlay_modified = 0;
3666 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 1, 2, 0,
3667 doc: /* Apply requested size values for window-tree of FRAME.
3668 Optional argument HORIZONTAL omitted or nil means apply requested height
3669 values. HORIZONTAL non-nil means apply requested width values.
3671 This function checks whether the requested values sum up to a valid
3672 window layout, recursively assigns the new sizes of all child windows
3673 and calculates and assigns the new start positions of these windows.
3675 Note: This function does not check any of `window-fixed-size-p',
3676 `window-min-height' or `window-min-width'. All these checks have to
3677 be applied on the Elisp level. */)
3678 (Lisp_Object frame, Lisp_Object horizontal)
3680 struct frame *f;
3681 struct window *r;
3682 int horflag = !NILP (horizontal);
3684 if (NILP (frame))
3685 frame = selected_frame;
3686 CHECK_LIVE_FRAME (frame);
3688 f = XFRAME (frame);
3689 r = XWINDOW (FRAME_ROOT_WINDOW (f));
3691 if (!window_resize_check (r, horflag)
3692 || ! EQ (r->new_total,
3693 (horflag ? r->total_cols : r->total_lines)))
3694 return Qnil;
3696 BLOCK_INPUT;
3697 window_resize_apply (r, horflag);
3699 windows_or_buffers_changed++;
3700 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3702 adjust_glyphs (f);
3703 UNBLOCK_INPUT;
3705 run_window_configuration_change_hook (f);
3707 return Qt;
3711 /* Resize frame F's windows when number of lines of F is set to SIZE.
3712 HORFLAG 1 means resize windows when number of columns of F is set to
3713 SIZE.
3715 This function can delete all windows but the selected one in order to
3716 satisfy the request. The result will be meaningful if and only if
3717 F's windows have meaningful sizes when you call this. */
3718 void
3719 resize_frame_windows (struct frame *f, int size, int horflag)
3721 Lisp_Object root = f->root_window;
3722 struct window *r = XWINDOW (root);
3723 Lisp_Object mini = f->minibuffer_window;
3724 struct window *m;
3725 /* new_size is the new size of the frame's root window. */
3726 int new_size = (horflag
3727 ? size
3728 : (size
3729 - FRAME_TOP_MARGIN (f)
3730 - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3731 ? 1 : 0)));
3733 wset_top_line (r, make_number (FRAME_TOP_MARGIN (f)));
3734 if (NILP (r->vchild) && NILP (r->hchild))
3735 /* For a leaf root window just set the size. */
3736 if (horflag)
3737 wset_total_cols (r, make_number (new_size));
3738 else
3739 wset_total_lines (r, make_number (new_size));
3740 else
3742 /* old_size is the old size of the frame's root window. */
3743 int old_size = XFASTINT (horflag ? r->total_cols
3744 : r->total_lines);
3745 Lisp_Object delta;
3747 XSETINT (delta, new_size - old_size);
3748 /* Try a "normal" resize first. */
3749 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil);
3750 if (window_resize_check (r, horflag)
3751 && new_size == XINT (r->new_total))
3752 window_resize_apply (r, horflag);
3753 else
3755 /* Try with "reasonable" minimum sizes next. */
3756 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt);
3757 if (window_resize_check (r, horflag)
3758 && new_size == XINT (r->new_total))
3759 window_resize_apply (r, horflag);
3760 else
3762 /* Finally, try with "safe" minimum sizes. */
3763 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe);
3764 if (window_resize_check (r, horflag)
3765 && new_size == XINT (r->new_total))
3766 window_resize_apply (r, horflag);
3767 else
3769 /* We lost. Delete all windows but the frame's
3770 selected one. */
3771 root = f->selected_window;
3772 Fdelete_other_windows_internal (root, Qnil);
3773 if (horflag)
3774 wset_total_cols (XWINDOW (root), make_number (new_size));
3775 else
3776 wset_total_lines (XWINDOW (root), make_number (new_size));
3782 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3784 m = XWINDOW (mini);
3785 if (horflag)
3786 wset_total_cols (m, make_number (size));
3787 else
3789 /* Are we sure we always want 1 line here? */
3790 wset_total_lines (m, make_number (1));
3791 wset_top_line
3792 (m, make_number (XINT (r->top_line) + XINT (r->total_lines)));
3798 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
3799 doc: /* Split window OLD.
3800 Second argument TOTAL-SIZE specifies the number of lines or columns of the
3801 new window. In any case TOTAL-SIZE must be a positive integer.
3803 Third argument SIDE nil (or `below') specifies that the new window shall
3804 be located below WINDOW. SIDE `above' means the new window shall be
3805 located above WINDOW. In both cases TOTAL-SIZE specifies the number of
3806 lines of the new window including space reserved for the mode and/or
3807 header line.
3809 SIDE t (or `right') specifies that the new window shall be located on
3810 the right side of WINDOW. SIDE `left' means the new window shall be
3811 located on the left of WINDOW. In both cases TOTAL-SIZE specifies the
3812 number of columns of the new window including space reserved for fringes
3813 and the scrollbar or a divider column.
3815 Fourth argument NORMAL-SIZE specifies the normal size of the new window
3816 according to the SIDE argument.
3818 The new total and normal sizes of all involved windows must have been
3819 set correctly. See the code of `split-window' for how this is done. */)
3820 (Lisp_Object old, Lisp_Object total_size, Lisp_Object side, Lisp_Object normal_size)
3822 /* OLD (*o) is the window we have to split. (*p) is either OLD's
3823 parent window or an internal window we have to install as OLD's new
3824 parent. REFERENCE (*r) must denote a live window, or is set to OLD
3825 provided OLD is a leaf window, or to the frame's selected window.
3826 NEW (*n) is the new window created with some parameters taken from
3827 REFERENCE (*r). */
3828 register Lisp_Object new, frame, reference;
3829 register struct window *o, *p, *n, *r;
3830 struct frame *f;
3831 int horflag
3832 /* HORFLAG is 1 when we split side-by-side, 0 otherwise. */
3833 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
3834 int combination_limit = 0;
3836 CHECK_WINDOW (old);
3837 o = XWINDOW (old);
3838 frame = WINDOW_FRAME (o);
3839 f = XFRAME (frame);
3841 CHECK_NUMBER (total_size);
3843 /* Set combination_limit to 1 if we have to make a new parent window.
3844 We do that if either `window-combination-limit' is t, or OLD has no
3845 parent, or OLD is ortho-combined. */
3846 combination_limit =
3847 !NILP (Vwindow_combination_limit)
3848 || NILP (o->parent)
3849 || NILP (horflag
3850 ? (XWINDOW (o->parent)->hchild)
3851 : (XWINDOW (o->parent)->vchild));
3853 /* We need a live reference window to initialize some parameters. */
3854 if (WINDOW_LIVE_P (old))
3855 /* OLD is live, use it as reference window. */
3856 reference = old;
3857 else
3858 /* Use the frame's selected window as reference window. */
3859 reference = FRAME_SELECTED_WINDOW (f);
3860 r = XWINDOW (reference);
3862 /* The following bugs are caught by `split-window'. */
3863 if (MINI_WINDOW_P (o))
3864 error ("Attempt to split minibuffer window");
3865 else if (XINT (total_size) < (horflag ? 2 : 1))
3866 error ("Size of new window too small (after split)");
3867 else if (!combination_limit && !NILP (Vwindow_combination_resize))
3868 /* `window-combination-resize' non-nil means try to resize OLD's siblings
3869 proportionally. */
3871 p = XWINDOW (o->parent);
3872 /* Temporarily pretend we split the parent window. */
3873 wset_new_total
3874 (p, make_number (XINT (horflag ? p->total_cols : p->total_lines)
3875 - XINT (total_size)));
3876 if (!window_resize_check (p, horflag))
3877 error ("Window sizes don't fit");
3878 else
3879 /* Undo the temporary pretension. */
3880 wset_new_total (p, horflag ? p->total_cols : p->total_lines);
3882 else
3884 if (!window_resize_check (o, horflag))
3885 error ("Resizing old window failed");
3886 else if (XINT (total_size) + XINT (o->new_total)
3887 != XINT (horflag ? o->total_cols : o->total_lines))
3888 error ("Sum of sizes of old and new window don't fit");
3891 /* This is our point of no return. */
3892 if (combination_limit)
3894 /* Save the old value of o->normal_cols/lines. It gets corrupted
3895 by make_parent_window and we need it below for assigning it to
3896 p->new_normal. */
3897 Lisp_Object new_normal
3898 = horflag ? o->normal_cols : o->normal_lines;
3900 make_parent_window (old, horflag);
3901 p = XWINDOW (o->parent);
3902 /* Store value of `window-combination-limit' in new parent's
3903 combination_limit slot. */
3904 wset_combination_limit (p, Vwindow_combination_limit);
3905 /* These get applied below. */
3906 wset_new_total (p, horflag ? o->total_cols : o->total_lines);
3907 wset_new_normal (p, new_normal);
3909 else
3910 p = XWINDOW (o->parent);
3912 windows_or_buffers_changed++;
3913 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3914 new = make_window ();
3915 n = XWINDOW (new);
3916 wset_frame (n, frame);
3917 wset_parent (n, o->parent);
3918 wset_vchild (n, Qnil);
3919 wset_hchild (n, Qnil);
3921 if (EQ (side, Qabove) || EQ (side, Qleft))
3923 wset_prev (n, o->prev);
3924 if (NILP (n->prev))
3925 if (horflag)
3926 wset_hchild (p, new);
3927 else
3928 wset_vchild (p, new);
3929 else
3930 wset_next (XWINDOW (n->prev), new);
3931 wset_next (n, old);
3932 wset_prev (o, new);
3934 else
3936 wset_next (n, o->next);
3937 if (!NILP (n->next))
3938 wset_prev (XWINDOW (n->next), new);
3939 wset_prev (n, old);
3940 wset_next (o, new);
3943 wset_buffer (n, Qt);
3944 wset_window_end_valid (n, Qnil);
3945 memset (&n->last_cursor, 0, sizeof n->last_cursor);
3947 /* Get special geometry settings from reference window. */
3948 wset_left_margin_cols (n, r->left_margin_cols);
3949 wset_right_margin_cols (n, r->right_margin_cols);
3950 wset_left_fringe_width (n, r->left_fringe_width);
3951 wset_right_fringe_width (n, r->right_fringe_width);
3952 n->fringes_outside_margins = r->fringes_outside_margins;
3953 wset_scroll_bar_width (n, r->scroll_bar_width);
3954 wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
3956 /* Directly assign orthogonal coordinates and sizes. */
3957 if (horflag)
3959 wset_top_line (n, o->top_line);
3960 wset_total_lines (n, o->total_lines);
3962 else
3964 wset_left_col (n, o->left_col);
3965 wset_total_cols (n, o->total_cols);
3968 /* Iso-coordinates and sizes are assigned by window_resize_apply,
3969 get them ready here. */
3970 wset_new_total (n, total_size);
3971 wset_new_normal (n, normal_size);
3973 BLOCK_INPUT;
3974 window_resize_apply (p, horflag);
3975 adjust_glyphs (f);
3976 /* Set buffer of NEW to buffer of reference window. Don't run
3977 any hooks. */
3978 set_window_buffer (new, r->buffer, 0, 1);
3979 UNBLOCK_INPUT;
3981 /* Maybe we should run the scroll functions in Elisp (which already
3982 runs the configuration change hook). */
3983 if (! NILP (Vwindow_scroll_functions))
3984 run_hook_with_args_2 (Qwindow_scroll_functions, new,
3985 Fmarker_position (n->start));
3986 /* Return NEW. */
3987 return new;
3991 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
3992 doc: /* Remove WINDOW from its frame.
3993 WINDOW defaults to the selected window. Return nil.
3994 Signal an error when WINDOW is the only window on its frame. */)
3995 (register Lisp_Object window)
3997 register Lisp_Object parent, sibling, frame, root;
3998 struct window *w, *p, *s, *r;
3999 struct frame *f;
4000 int horflag;
4001 int before_sibling = 0;
4003 w = decode_any_window (window);
4004 XSETWINDOW (window, w);
4005 if (NILP (w->buffer)
4006 && NILP (w->hchild) && NILP (w->vchild))
4007 /* It's a no-op to delete an already deleted window. */
4008 return Qnil;
4010 parent = w->parent;
4011 if (NILP (parent))
4012 /* Never delete a minibuffer or frame root window. */
4013 error ("Attempt to delete minibuffer or sole ordinary window");
4014 else if (NILP (w->prev) && NILP (w->next))
4015 /* Rather bow out here, this case should be handled on the Elisp
4016 level. */
4017 error ("Attempt to delete sole window of parent");
4019 p = XWINDOW (parent);
4020 horflag = NILP (p->vchild);
4022 frame = WINDOW_FRAME (w);
4023 f = XFRAME (frame);
4025 root = FRAME_ROOT_WINDOW (f);
4026 r = XWINDOW (root);
4028 /* Unlink WINDOW from window tree. */
4029 if (NILP (w->prev))
4030 /* Get SIBLING below (on the right of) WINDOW. */
4032 /* before_sibling 1 means WINDOW is the first child of its
4033 parent and thus before the sibling. */
4034 before_sibling = 1;
4035 sibling = w->next;
4036 s = XWINDOW (sibling);
4037 wset_prev (s, Qnil);
4038 if (horflag)
4039 wset_hchild (p, sibling);
4040 else
4041 wset_vchild (p, sibling);
4043 else
4044 /* Get SIBLING above (on the left of) WINDOW. */
4046 sibling = w->prev;
4047 s = XWINDOW (sibling);
4048 wset_next (s, w->next);
4049 if (!NILP (s->next))
4050 wset_prev (XWINDOW (s->next), sibling);
4053 if (window_resize_check (r, horflag)
4054 && EQ (r->new_total,
4055 (horflag ? r->total_cols : r->total_lines)))
4056 /* We can delete WINDOW now. */
4059 /* Block input. */
4060 BLOCK_INPUT;
4061 window_resize_apply (p, horflag);
4063 /* If this window is referred to by the dpyinfo's mouse
4064 highlight, invalidate that slot to be safe (Bug#9904). */
4065 if (!FRAME_INITIAL_P (f))
4067 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
4069 if (EQ (hlinfo->mouse_face_window, window))
4070 hlinfo->mouse_face_window = Qnil;
4073 windows_or_buffers_changed++;
4074 Vwindow_list = Qnil;
4075 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4077 wset_next (w, Qnil); /* Don't delete w->next too. */
4078 free_window_matrices (w);
4080 if (!NILP (w->vchild))
4082 delete_all_child_windows (w->vchild);
4083 wset_vchild (w, Qnil);
4085 else if (!NILP (w->hchild))
4087 delete_all_child_windows (w->hchild);
4088 wset_hchild (w, Qnil);
4090 else if (!NILP (w->buffer))
4092 unshow_buffer (w);
4093 unchain_marker (XMARKER (w->pointm));
4094 unchain_marker (XMARKER (w->start));
4095 wset_buffer (w, Qnil);
4098 if (NILP (s->prev) && NILP (s->next))
4099 /* A matrjoshka where SIBLING has become the only child of
4100 PARENT. */
4102 /* Put SIBLING into PARENT's place. */
4103 replace_window (parent, sibling, 0);
4104 /* Have SIBLING inherit the following three slot values from
4105 PARENT (the combination_limit slot is not inherited). */
4106 wset_normal_cols (s, p->normal_cols);
4107 wset_normal_lines (s, p->normal_lines);
4108 /* Mark PARENT as deleted. */
4109 wset_vchild (p, Qnil);
4110 wset_hchild (p, Qnil);
4111 /* Try to merge SIBLING into its new parent. */
4112 recombine_windows (sibling);
4115 adjust_glyphs (f);
4117 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
4118 /* We deleted the frame's selected window. */
4120 /* Use the frame's first window as fallback ... */
4121 Lisp_Object new_selected_window = Fframe_first_window (frame);
4122 /* ... but preferably use its most recently used window. */
4123 Lisp_Object mru_window;
4125 /* `get-mru-window' might fail for some reason so play it safe
4126 - promote the first window _without recording it_ first. */
4127 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4128 Fselect_window (new_selected_window, Qt);
4129 else
4130 fset_selected_window (f, new_selected_window);
4132 UNBLOCK_INPUT;
4134 /* Now look whether `get-mru-window' gets us something. */
4135 mru_window = call1 (Qget_mru_window, frame);
4136 if (WINDOW_LIVE_P (mru_window)
4137 && EQ (XWINDOW (mru_window)->frame, frame))
4138 new_selected_window = mru_window;
4140 /* If all ended up well, we now promote the mru window. */
4141 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4142 Fselect_window (new_selected_window, Qnil);
4143 else
4144 fset_selected_window (f, new_selected_window);
4146 else
4147 UNBLOCK_INPUT;
4149 /* Must be run by the caller:
4150 run_window_configuration_change_hook (f); */
4152 else
4153 /* We failed: Relink WINDOW into window tree. */
4155 if (before_sibling)
4157 wset_prev (s, window);
4158 if (horflag)
4159 wset_hchild (p, window);
4160 else
4161 wset_vchild (p, window);
4163 else
4165 wset_next (s, window);
4166 if (!NILP (w->next))
4167 wset_prev (XWINDOW (w->next), window);
4169 error ("Deletion failed");
4172 return Qnil;
4175 /***********************************************************************
4176 Resizing Mini-Windows
4177 ***********************************************************************/
4179 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
4180 can. */
4181 void
4182 grow_mini_window (struct window *w, int delta)
4184 struct frame *f = XFRAME (w->frame);
4185 struct window *r;
4186 Lisp_Object root, value;
4188 eassert (MINI_WINDOW_P (w));
4189 eassert (delta >= 0);
4191 root = FRAME_ROOT_WINDOW (f);
4192 r = XWINDOW (root);
4193 value = call2 (Qwindow_resize_root_window_vertically,
4194 root, make_number (- delta));
4195 if (INTEGERP (value) && window_resize_check (r, 0))
4197 BLOCK_INPUT;
4198 window_resize_apply (r, 0);
4200 /* Grow the mini-window. */
4201 wset_top_line
4202 (w, make_number (XFASTINT (r->top_line) + XFASTINT (r->total_lines)));
4203 wset_total_lines
4204 (w, make_number (XFASTINT (w->total_lines) - XINT (value)));
4205 w->last_modified = 0;
4206 w->last_overlay_modified = 0;
4208 adjust_glyphs (f);
4209 UNBLOCK_INPUT;
4214 /* Shrink mini-window W. */
4215 void
4216 shrink_mini_window (struct window *w)
4218 struct frame *f = XFRAME (w->frame);
4219 struct window *r;
4220 Lisp_Object root, value;
4221 EMACS_INT size;
4223 eassert (MINI_WINDOW_P (w));
4225 size = XINT (w->total_lines);
4226 if (size > 1)
4228 root = FRAME_ROOT_WINDOW (f);
4229 r = XWINDOW (root);
4230 value = call2 (Qwindow_resize_root_window_vertically,
4231 root, make_number (size - 1));
4232 if (INTEGERP (value) && window_resize_check (r, 0))
4234 BLOCK_INPUT;
4235 window_resize_apply (r, 0);
4237 /* Shrink the mini-window. */
4238 wset_top_line (w, make_number (XFASTINT (r->top_line)
4239 + XFASTINT (r->total_lines)));
4240 wset_total_lines (w, make_number (1));
4242 w->last_modified = 0;
4243 w->last_overlay_modified = 0;
4245 adjust_glyphs (f);
4246 UNBLOCK_INPUT;
4248 /* If the above failed for whatever strange reason we must make a
4249 one window frame here. The same routine will be needed when
4250 shrinking the frame (and probably when making the initial
4251 *scratch* window). For the moment leave things as they are. */
4255 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
4256 doc: /* Resize minibuffer window WINDOW. */)
4257 (Lisp_Object window)
4259 struct window *w = XWINDOW (window);
4260 struct window *r;
4261 struct frame *f;
4262 int height;
4264 CHECK_WINDOW (window);
4265 f = XFRAME (w->frame);
4267 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
4268 error ("Not a valid minibuffer window");
4269 else if (FRAME_MINIBUF_ONLY_P (f))
4270 error ("Cannot resize a minibuffer-only frame");
4272 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4273 height = XINT (r->total_lines) + XINT (w->total_lines);
4274 if (window_resize_check (r, 0)
4275 && XINT (w->new_total) > 0
4276 && height == XINT (r->new_total) + XINT (w->new_total))
4278 BLOCK_INPUT;
4279 window_resize_apply (r, 0);
4281 wset_total_lines (w, w->new_total);
4282 wset_top_line (w, make_number (XINT (r->top_line)
4283 + XINT (r->total_lines)));
4285 windows_or_buffers_changed++;
4286 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4287 adjust_glyphs (f);
4288 UNBLOCK_INPUT;
4290 run_window_configuration_change_hook (f);
4291 return Qt;
4293 else error ("Failed to resize minibuffer window");
4296 /* Mark window cursors off for all windows in the window tree rooted
4297 at W by setting their phys_cursor_on_p flag to zero. Called from
4298 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4299 the frame are cleared. */
4301 void
4302 mark_window_cursors_off (struct window *w)
4304 while (w)
4306 if (!NILP (w->hchild))
4307 mark_window_cursors_off (XWINDOW (w->hchild));
4308 else if (!NILP (w->vchild))
4309 mark_window_cursors_off (XWINDOW (w->vchild));
4310 else
4311 w->phys_cursor_on_p = 0;
4313 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4318 /* Return number of lines of text (not counting mode lines) in W. */
4321 window_internal_height (struct window *w)
4323 int ht = XFASTINT (w->total_lines);
4325 if (!MINI_WINDOW_P (w))
4327 if (!NILP (w->parent)
4328 || !NILP (w->vchild)
4329 || !NILP (w->hchild)
4330 || !NILP (w->next)
4331 || !NILP (w->prev)
4332 || WINDOW_WANTS_MODELINE_P (w))
4333 --ht;
4335 if (WINDOW_WANTS_HEADER_LINE_P (w))
4336 --ht;
4339 return ht;
4342 /************************************************************************
4343 Window Scrolling
4344 ***********************************************************************/
4346 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4347 N screen-fulls, which is defined as the height of the window minus
4348 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4349 instead. Negative values of N mean scroll down. NOERROR non-zero
4350 means don't signal an error if we try to move over BEGV or ZV,
4351 respectively. */
4353 static void
4354 window_scroll (Lisp_Object window, EMACS_INT n, int whole, int noerror)
4356 immediate_quit = 1;
4357 n = clip_to_bounds (INT_MIN, n, INT_MAX);
4359 /* If we must, use the pixel-based version which is much slower than
4360 the line-based one but can handle varying line heights. */
4361 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4362 window_scroll_pixel_based (window, n, whole, noerror);
4363 else
4364 window_scroll_line_based (window, n, whole, noerror);
4366 immediate_quit = 0;
4370 /* Implementation of window_scroll that works based on pixel line
4371 heights. See the comment of window_scroll for parameter
4372 descriptions. */
4374 static void
4375 window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4377 struct it it;
4378 struct window *w = XWINDOW (window);
4379 struct text_pos start;
4380 int this_scroll_margin;
4381 /* True if we fiddled the window vscroll field without really scrolling. */
4382 int vscrolled = 0;
4383 int x, y, rtop, rbot, rowh, vpos;
4384 void *itdata = NULL;
4386 SET_TEXT_POS_FROM_MARKER (start, w->start);
4387 /* Scrolling a minibuffer window via scroll bar when the echo area
4388 shows long text sometimes resets the minibuffer contents behind
4389 our backs. */
4390 if (CHARPOS (start) > ZV)
4391 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4393 /* If PT is not visible in WINDOW, move back one half of
4394 the screen. Allow PT to be partially visible, otherwise
4395 something like (scroll-down 1) with PT in the line before
4396 the partially visible one would recenter. */
4398 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4400 itdata = bidi_shelve_cache ();
4401 /* Move backward half the height of the window. Performance note:
4402 vmotion used here is about 10% faster, but would give wrong
4403 results for variable height lines. */
4404 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4405 it.current_y = it.last_visible_y;
4406 move_it_vertically_backward (&it, window_box_height (w) / 2);
4408 /* The function move_iterator_vertically may move over more than
4409 the specified y-distance. If it->w is small, e.g. a
4410 mini-buffer window, we may end up in front of the window's
4411 display area. This is the case when Start displaying at the
4412 start of the line containing PT in this case. */
4413 if (it.current_y <= 0)
4415 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4416 move_it_vertically_backward (&it, 0);
4417 it.current_y = 0;
4420 start = it.current.pos;
4421 bidi_unshelve_cache (itdata, 0);
4423 else if (auto_window_vscroll_p)
4425 if (rtop || rbot) /* partially visible */
4427 int px;
4428 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4429 if (whole)
4430 dy = max ((window_box_height (w)
4431 - next_screen_context_lines * dy),
4432 dy);
4433 dy *= n;
4435 if (n < 0)
4437 /* Only vscroll backwards if already vscrolled forwards. */
4438 if (w->vscroll < 0 && rtop > 0)
4440 px = max (0, -w->vscroll - min (rtop, -dy));
4441 Fset_window_vscroll (window, make_number (px), Qt);
4442 return;
4445 if (n > 0)
4447 /* Do vscroll if already vscrolled or only display line. */
4448 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4450 px = max (0, -w->vscroll + min (rbot, dy));
4451 Fset_window_vscroll (window, make_number (px), Qt);
4452 return;
4455 /* Maybe modify window start instead of scrolling. */
4456 if (rbot > 0 || w->vscroll < 0)
4458 ptrdiff_t spos;
4460 Fset_window_vscroll (window, make_number (0), Qt);
4461 /* If there are other text lines above the current row,
4462 move window start to current row. Else to next row. */
4463 if (rbot > 0)
4464 spos = XINT (Fline_beginning_position (Qnil));
4465 else
4466 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4467 set_marker_restricted (w->start, make_number (spos),
4468 w->buffer);
4469 w->start_at_line_beg = 1;
4470 w->update_mode_line = 1;
4471 w->last_modified = 0;
4472 w->last_overlay_modified = 0;
4473 /* Set force_start so that redisplay_window will run the
4474 window-scroll-functions. */
4475 w->force_start = 1;
4476 return;
4480 /* Cancel previous vscroll. */
4481 Fset_window_vscroll (window, make_number (0), Qt);
4484 itdata = bidi_shelve_cache ();
4485 /* If scroll_preserve_screen_position is non-nil, we try to set
4486 point in the same window line as it is now, so get that line. */
4487 if (!NILP (Vscroll_preserve_screen_position))
4489 /* We preserve the goal pixel coordinate across consecutive
4490 calls to scroll-up, scroll-down and other commands that
4491 have the `scroll-command' property. This avoids the
4492 possibility of point becoming "stuck" on a tall line when
4493 scrolling by one line. */
4494 if (window_scroll_pixel_based_preserve_y < 0
4495 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4496 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4498 start_display (&it, w, start);
4499 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4500 window_scroll_pixel_based_preserve_y = it.current_y;
4501 window_scroll_pixel_based_preserve_x = it.current_x;
4504 else
4505 window_scroll_pixel_based_preserve_y
4506 = window_scroll_pixel_based_preserve_x = -1;
4508 /* Move iterator it from start the specified distance forward or
4509 backward. The result is the new window start. */
4510 start_display (&it, w, start);
4511 if (whole)
4513 ptrdiff_t start_pos = IT_CHARPOS (it);
4514 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4515 dy = max ((window_box_height (w)
4516 - next_screen_context_lines * dy),
4517 dy) * n;
4519 /* Note that move_it_vertically always moves the iterator to the
4520 start of a line. So, if the last line doesn't have a newline,
4521 we would end up at the start of the line ending at ZV. */
4522 if (dy <= 0)
4524 move_it_vertically_backward (&it, -dy);
4525 /* Ensure we actually do move, e.g. in case we are currently
4526 looking at an image that is taller that the window height. */
4527 while (start_pos == IT_CHARPOS (it)
4528 && start_pos > BEGV)
4529 move_it_by_lines (&it, -1);
4531 else if (dy > 0)
4533 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4534 MOVE_TO_POS | MOVE_TO_Y);
4535 /* Ensure we actually do move, e.g. in case we are currently
4536 looking at an image that is taller that the window height. */
4537 while (start_pos == IT_CHARPOS (it)
4538 && start_pos < ZV)
4539 move_it_by_lines (&it, 1);
4542 else
4543 move_it_by_lines (&it, n);
4545 /* We failed if we find ZV is already on the screen (scrolling up,
4546 means there's nothing past the end), or if we can't start any
4547 earlier (scrolling down, means there's nothing past the top). */
4548 if ((n > 0 && IT_CHARPOS (it) == ZV)
4549 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4551 if (IT_CHARPOS (it) == ZV)
4553 if (it.current_y < it.last_visible_y
4554 && (it.current_y + it.max_ascent + it.max_descent
4555 > it.last_visible_y))
4557 /* The last line was only partially visible, make it fully
4558 visible. */
4559 w->vscroll = (it.last_visible_y
4560 - it.current_y + it.max_ascent + it.max_descent);
4561 adjust_glyphs (it.f);
4563 else
4565 bidi_unshelve_cache (itdata, 0);
4566 if (noerror)
4567 return;
4568 else if (n < 0) /* could happen with empty buffers */
4569 xsignal0 (Qbeginning_of_buffer);
4570 else
4571 xsignal0 (Qend_of_buffer);
4574 else
4576 if (w->vscroll != 0)
4577 /* The first line was only partially visible, make it fully
4578 visible. */
4579 w->vscroll = 0;
4580 else
4582 bidi_unshelve_cache (itdata, 0);
4583 if (noerror)
4584 return;
4585 else
4586 xsignal0 (Qbeginning_of_buffer);
4590 /* If control gets here, then we vscrolled. */
4592 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4594 /* Don't try to change the window start below. */
4595 vscrolled = 1;
4598 if (! vscrolled)
4600 ptrdiff_t pos = IT_CHARPOS (it);
4601 ptrdiff_t bytepos;
4603 /* If in the middle of a multi-glyph character move forward to
4604 the next character. */
4605 if (in_display_vector_p (&it))
4607 ++pos;
4608 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4611 /* Set the window start, and set up the window for redisplay. */
4612 set_marker_restricted (w->start, make_number (pos),
4613 w->buffer);
4614 bytepos = XMARKER (w->start)->bytepos;
4615 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
4616 w->update_mode_line = 1;
4617 w->last_modified = 0;
4618 w->last_overlay_modified = 0;
4619 /* Set force_start so that redisplay_window will run the
4620 window-scroll-functions. */
4621 w->force_start = 1;
4624 /* The rest of this function uses current_y in a nonstandard way,
4625 not including the height of the header line if any. */
4626 it.current_y = it.vpos = 0;
4628 /* Move PT out of scroll margins.
4629 This code wants current_y to be zero at the window start position
4630 even if there is a header line. */
4631 this_scroll_margin = max (0, scroll_margin);
4632 this_scroll_margin
4633 = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4634 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4636 if (n > 0)
4638 /* We moved the window start towards ZV, so PT may be now
4639 in the scroll margin at the top. */
4640 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4641 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
4642 && (NILP (Vscroll_preserve_screen_position)
4643 || EQ (Vscroll_preserve_screen_position, Qt)))
4644 /* We found PT at a legitimate height. Leave it alone. */
4646 else if (window_scroll_pixel_based_preserve_y >= 0)
4648 /* If we have a header line, take account of it.
4649 This is necessary because we set it.current_y to 0, above. */
4650 move_it_to (&it, -1,
4651 window_scroll_pixel_based_preserve_x,
4652 window_scroll_pixel_based_preserve_y
4653 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
4654 -1, MOVE_TO_Y | MOVE_TO_X);
4655 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4657 else
4659 while (it.current_y < this_scroll_margin)
4661 int prev = it.current_y;
4662 move_it_by_lines (&it, 1);
4663 if (prev == it.current_y)
4664 break;
4666 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4669 else if (n < 0)
4671 ptrdiff_t charpos, bytepos;
4672 int partial_p;
4674 /* Save our position, for the
4675 window_scroll_pixel_based_preserve_y case. */
4676 charpos = IT_CHARPOS (it);
4677 bytepos = IT_BYTEPOS (it);
4679 /* We moved the window start towards BEGV, so PT may be now
4680 in the scroll margin at the bottom. */
4681 move_it_to (&it, PT, -1,
4682 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
4683 - this_scroll_margin - 1),
4685 MOVE_TO_POS | MOVE_TO_Y);
4687 /* Save our position, in case it's correct. */
4688 charpos = IT_CHARPOS (it);
4689 bytepos = IT_BYTEPOS (it);
4691 /* See if point is on a partially visible line at the end. */
4692 if (it.what == IT_EOB)
4693 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
4694 else
4696 move_it_by_lines (&it, 1);
4697 partial_p = it.current_y > it.last_visible_y;
4700 if (charpos == PT && !partial_p
4701 && (NILP (Vscroll_preserve_screen_position)
4702 || EQ (Vscroll_preserve_screen_position, Qt)))
4703 /* We found PT before we found the display margin, so PT is ok. */
4705 else if (window_scroll_pixel_based_preserve_y >= 0)
4707 SET_TEXT_POS_FROM_MARKER (start, w->start);
4708 start_display (&it, w, start);
4709 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
4710 here because we called start_display again and did not
4711 alter it.current_y this time. */
4712 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
4713 window_scroll_pixel_based_preserve_y, -1,
4714 MOVE_TO_Y | MOVE_TO_X);
4715 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4717 else
4719 if (partial_p)
4720 /* The last line was only partially visible, so back up two
4721 lines to make sure we're on a fully visible line. */
4723 move_it_by_lines (&it, -2);
4724 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4726 else
4727 /* No, the position we saved is OK, so use it. */
4728 SET_PT_BOTH (charpos, bytepos);
4731 bidi_unshelve_cache (itdata, 0);
4735 /* Implementation of window_scroll that works based on screen lines.
4736 See the comment of window_scroll for parameter descriptions. */
4738 static void
4739 window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
4741 register struct window *w = XWINDOW (window);
4742 /* Fvertical_motion enters redisplay, which can trigger
4743 fontification, which in turn can modify buffer text (e.g., if the
4744 fontification functions replace escape sequences with faces, as
4745 in `grep-mode-font-lock-keywords'). So we use a marker to record
4746 the old point position, to prevent crashes in SET_PT_BOTH. */
4747 Lisp_Object opoint_marker = Fpoint_marker ();
4748 register ptrdiff_t pos, pos_byte;
4749 register int ht = window_internal_height (w);
4750 register Lisp_Object tem;
4751 int lose;
4752 Lisp_Object bolp;
4753 ptrdiff_t startpos;
4754 Lisp_Object original_pos = Qnil;
4756 /* If scrolling screen-fulls, compute the number of lines to
4757 scroll from the window's height. */
4758 if (whole)
4759 n *= max (1, ht - next_screen_context_lines);
4761 startpos = marker_position (w->start);
4763 if (!NILP (Vscroll_preserve_screen_position))
4765 if (window_scroll_preserve_vpos <= 0
4766 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4767 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4769 struct position posit
4770 = *compute_motion (startpos, 0, 0, 0,
4771 PT, ht, 0,
4772 -1, w->hscroll,
4773 0, w);
4774 window_scroll_preserve_vpos = posit.vpos;
4775 window_scroll_preserve_hpos = posit.hpos + w->hscroll;
4778 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
4779 make_number (window_scroll_preserve_vpos));
4782 XSETFASTINT (tem, PT);
4783 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4785 if (NILP (tem))
4787 Fvertical_motion (make_number (- (ht / 2)), window);
4788 startpos = PT;
4791 SET_PT (startpos);
4792 lose = n < 0 && PT == BEGV;
4793 Fvertical_motion (make_number (n), window);
4794 pos = PT;
4795 pos_byte = PT_BYTE;
4796 bolp = Fbolp ();
4797 SET_PT_BOTH (marker_position (opoint_marker),
4798 marker_byte_position (opoint_marker));
4800 if (lose)
4802 if (noerror)
4803 return;
4804 else
4805 xsignal0 (Qbeginning_of_buffer);
4808 if (pos < ZV)
4810 /* Don't use a scroll margin that is negative or too large. */
4811 int this_scroll_margin =
4812 max (0, min (scroll_margin, XINT (w->total_lines) / 4));
4814 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4815 w->start_at_line_beg = !NILP (bolp);
4816 w->update_mode_line = 1;
4817 w->last_modified = 0;
4818 w->last_overlay_modified = 0;
4819 /* Set force_start so that redisplay_window will run
4820 the window-scroll-functions. */
4821 w->force_start = 1;
4823 if (!NILP (Vscroll_preserve_screen_position)
4824 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
4826 SET_PT_BOTH (pos, pos_byte);
4827 Fvertical_motion (original_pos, window);
4829 /* If we scrolled forward, put point enough lines down
4830 that it is outside the scroll margin. */
4831 else if (n > 0)
4833 int top_margin;
4835 if (this_scroll_margin > 0)
4837 SET_PT_BOTH (pos, pos_byte);
4838 Fvertical_motion (make_number (this_scroll_margin), window);
4839 top_margin = PT;
4841 else
4842 top_margin = pos;
4844 if (top_margin <= marker_position (opoint_marker))
4845 SET_PT_BOTH (marker_position (opoint_marker),
4846 marker_byte_position (opoint_marker));
4847 else if (!NILP (Vscroll_preserve_screen_position))
4849 SET_PT_BOTH (pos, pos_byte);
4850 Fvertical_motion (original_pos, window);
4852 else
4853 SET_PT (top_margin);
4855 else if (n < 0)
4857 int bottom_margin;
4859 /* If we scrolled backward, put point near the end of the window
4860 but not within the scroll margin. */
4861 SET_PT_BOTH (pos, pos_byte);
4862 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4863 if (XFASTINT (tem) == ht - this_scroll_margin)
4864 bottom_margin = PT;
4865 else
4866 bottom_margin = PT + 1;
4868 if (bottom_margin > marker_position (opoint_marker))
4869 SET_PT_BOTH (marker_position (opoint_marker),
4870 marker_byte_position (opoint_marker));
4871 else
4873 if (!NILP (Vscroll_preserve_screen_position))
4875 SET_PT_BOTH (pos, pos_byte);
4876 Fvertical_motion (original_pos, window);
4878 else
4879 Fvertical_motion (make_number (-1), window);
4883 else
4885 if (noerror)
4886 return;
4887 else
4888 xsignal0 (Qend_of_buffer);
4893 /* Scroll selected_window up or down. If N is nil, scroll a
4894 screen-full which is defined as the height of the window minus
4895 next_screen_context_lines. If N is the symbol `-', scroll.
4896 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4897 up. This is the guts of Fscroll_up and Fscroll_down. */
4899 static void
4900 scroll_command (Lisp_Object n, int direction)
4902 ptrdiff_t count = SPECPDL_INDEX ();
4904 eassert (eabs (direction) == 1);
4906 /* If selected window's buffer isn't current, make it current for
4907 the moment. But don't screw up if window_scroll gets an error. */
4908 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4910 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4911 Fset_buffer (XWINDOW (selected_window)->buffer);
4913 /* Make redisplay consider other windows than just selected_window. */
4914 ++windows_or_buffers_changed;
4917 if (NILP (n))
4918 window_scroll (selected_window, direction, 1, 0);
4919 else if (EQ (n, Qminus))
4920 window_scroll (selected_window, -direction, 1, 0);
4921 else
4923 n = Fprefix_numeric_value (n);
4924 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4927 unbind_to (count, Qnil);
4930 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
4931 doc: /* Scroll text of selected window upward ARG lines.
4932 If ARG is omitted or nil, scroll upward by a near full screen.
4933 A near full screen is `next-screen-context-lines' less than a full screen.
4934 Negative ARG means scroll downward.
4935 If ARG is the atom `-', scroll downward by nearly full screen.
4936 When calling from a program, supply as argument a number, nil, or `-'. */)
4937 (Lisp_Object arg)
4939 scroll_command (arg, 1);
4940 return Qnil;
4943 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
4944 doc: /* Scroll text of selected window down ARG lines.
4945 If ARG is omitted or nil, scroll down by a near full screen.
4946 A near full screen is `next-screen-context-lines' less than a full screen.
4947 Negative ARG means scroll upward.
4948 If ARG is the atom `-', scroll upward by nearly full screen.
4949 When calling from a program, supply as argument a number, nil, or `-'. */)
4950 (Lisp_Object arg)
4952 scroll_command (arg, -1);
4953 return Qnil;
4956 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4957 doc: /* Return the other window for \"other window scroll\" commands.
4958 If `other-window-scroll-buffer' is non-nil, a window
4959 showing that buffer is used.
4960 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4961 specifies the window. This takes precedence over
4962 `other-window-scroll-buffer'. */)
4963 (void)
4965 Lisp_Object window;
4967 if (MINI_WINDOW_P (XWINDOW (selected_window))
4968 && !NILP (Vminibuf_scroll_window))
4969 window = Vminibuf_scroll_window;
4970 /* If buffer is specified, scroll that buffer. */
4971 else if (!NILP (Vother_window_scroll_buffer))
4973 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4974 if (NILP (window))
4975 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4977 else
4979 /* Nothing specified; look for a neighboring window on the same
4980 frame. */
4981 window = Fnext_window (selected_window, Qnil, Qnil);
4983 if (EQ (window, selected_window))
4984 /* That didn't get us anywhere; look for a window on another
4985 visible frame. */
4987 window = Fnext_window (window, Qnil, Qt);
4988 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4989 && ! EQ (window, selected_window));
4992 CHECK_LIVE_WINDOW (window);
4994 if (EQ (window, selected_window))
4995 error ("There is no other window");
4997 return window;
5000 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5001 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5002 A near full screen is `next-screen-context-lines' less than a full screen.
5003 The next window is the one below the current one; or the one at the top
5004 if the current one is at the bottom. Negative ARG means scroll downward.
5005 If ARG is the atom `-', scroll downward by nearly full screen.
5006 When calling from a program, supply as argument a number, nil, or `-'.
5008 If `other-window-scroll-buffer' is non-nil, scroll the window
5009 showing that buffer, popping the buffer up if necessary.
5010 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5011 specifies the window to scroll. This takes precedence over
5012 `other-window-scroll-buffer'. */)
5013 (Lisp_Object arg)
5015 Lisp_Object window;
5016 struct window *w;
5017 ptrdiff_t count = SPECPDL_INDEX ();
5019 window = Fother_window_for_scrolling ();
5020 w = XWINDOW (window);
5022 /* Don't screw up if window_scroll gets an error. */
5023 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5024 ++windows_or_buffers_changed;
5026 Fset_buffer (w->buffer);
5027 SET_PT (marker_position (w->pointm));
5029 if (NILP (arg))
5030 window_scroll (window, 1, 1, 1);
5031 else if (EQ (arg, Qminus))
5032 window_scroll (window, -1, 1, 1);
5033 else
5035 if (CONSP (arg))
5036 arg = XCAR (arg);
5037 CHECK_NUMBER (arg);
5038 window_scroll (window, XINT (arg), 0, 1);
5041 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5042 unbind_to (count, Qnil);
5044 return Qnil;
5047 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5048 doc: /* Scroll selected window display ARG columns left.
5049 Default for ARG is window width minus 2.
5050 Value is the total amount of leftward horizontal scrolling in
5051 effect after the change.
5052 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5053 lower bound for automatic scrolling, i.e. automatic scrolling
5054 will not scroll a window to a column less than the value returned
5055 by this function. This happens in an interactive call. */)
5056 (register Lisp_Object arg, Lisp_Object set_minimum)
5058 struct window *w = XWINDOW (selected_window);
5059 EMACS_INT requested_arg = (NILP (arg)
5060 ? window_body_cols (w) - 2
5061 : XINT (Fprefix_numeric_value (arg)));
5062 Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
5064 if (!NILP (set_minimum))
5065 w->min_hscroll = w->hscroll;
5067 return result;
5070 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5071 doc: /* Scroll selected window display ARG columns right.
5072 Default for ARG is window width minus 2.
5073 Value is the total amount of leftward horizontal scrolling in
5074 effect after the change.
5075 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5076 lower bound for automatic scrolling, i.e. automatic scrolling
5077 will not scroll a window to a column less than the value returned
5078 by this function. This happens in an interactive call. */)
5079 (register Lisp_Object arg, Lisp_Object set_minimum)
5081 struct window *w = XWINDOW (selected_window);
5082 EMACS_INT requested_arg = (NILP (arg)
5083 ? window_body_cols (w) - 2
5084 : XINT (Fprefix_numeric_value (arg)));
5085 Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
5087 if (!NILP (set_minimum))
5088 w->min_hscroll = w->hscroll;
5090 return result;
5093 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5094 doc: /* Return the window which was selected when entering the minibuffer.
5095 Returns nil, if selected window is not a minibuffer window. */)
5096 (void)
5098 if (minibuf_level > 0
5099 && MINI_WINDOW_P (XWINDOW (selected_window))
5100 && WINDOW_LIVE_P (minibuf_selected_window))
5101 return minibuf_selected_window;
5103 return Qnil;
5106 /* Value is the number of lines actually displayed in window W,
5107 as opposed to its height. */
5109 static int
5110 displayed_window_lines (struct window *w)
5112 struct it it;
5113 struct text_pos start;
5114 int height = window_box_height (w);
5115 struct buffer *old_buffer;
5116 int bottom_y;
5117 void *itdata = NULL;
5119 if (XBUFFER (w->buffer) != current_buffer)
5121 old_buffer = current_buffer;
5122 set_buffer_internal (XBUFFER (w->buffer));
5124 else
5125 old_buffer = NULL;
5127 /* In case W->start is out of the accessible range, do something
5128 reasonable. This happens in Info mode when Info-scroll-down
5129 calls (recenter -1) while W->start is 1. */
5130 if (XMARKER (w->start)->charpos < BEGV)
5131 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5132 else if (XMARKER (w->start)->charpos > ZV)
5133 SET_TEXT_POS (start, ZV, ZV_BYTE);
5134 else
5135 SET_TEXT_POS_FROM_MARKER (start, w->start);
5137 itdata = bidi_shelve_cache ();
5138 start_display (&it, w, start);
5139 move_it_vertically (&it, height);
5140 bottom_y = line_bottom_y (&it);
5141 bidi_unshelve_cache (itdata, 0);
5143 /* rms: On a non-window display,
5144 the value of it.vpos at the bottom of the screen
5145 seems to be 1 larger than window_box_height (w).
5146 This kludge fixes a bug whereby (move-to-window-line -1)
5147 when ZV is on the last screen line
5148 moves to the previous screen line instead of the last one. */
5149 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5150 height++;
5152 /* Add in empty lines at the bottom of the window. */
5153 if (bottom_y < height)
5155 int uy = FRAME_LINE_HEIGHT (it.f);
5156 it.vpos += (height - bottom_y + uy - 1) / uy;
5159 if (old_buffer)
5160 set_buffer_internal (old_buffer);
5162 return it.vpos;
5166 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5167 doc: /* Center point in selected window and maybe redisplay frame.
5168 With prefix argument ARG, recenter putting point on screen line ARG
5169 relative to the selected window. If ARG is negative, it counts up from the
5170 bottom of the window. (ARG should be less than the height of the window.)
5172 If ARG is omitted or nil, then recenter with point on the middle line of
5173 the selected window; if the variable `recenter-redisplay' is non-nil,
5174 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5175 is set to `grow-only', this resets the tool-bar's height to the minimum
5176 height needed); if `recenter-redisplay' has the special value `tty',
5177 then only tty frames are redrawn.
5179 Just C-u as prefix means put point in the center of the window
5180 and redisplay normally--don't erase and redraw the frame. */)
5181 (register Lisp_Object arg)
5183 struct window *w = XWINDOW (selected_window);
5184 struct buffer *buf = XBUFFER (w->buffer);
5185 struct buffer *obuf = current_buffer;
5186 int center_p = 0;
5187 ptrdiff_t charpos, bytepos;
5188 EMACS_INT iarg IF_LINT (= 0);
5189 int this_scroll_margin;
5191 /* If redisplay is suppressed due to an error, try again. */
5192 obuf->display_error_modiff = 0;
5194 if (NILP (arg))
5196 if (!NILP (Vrecenter_redisplay)
5197 && (!EQ (Vrecenter_redisplay, Qtty)
5198 || !NILP (Ftty_type (selected_frame))))
5200 ptrdiff_t i;
5202 /* Invalidate pixel data calculated for all compositions. */
5203 for (i = 0; i < n_compositions; i++)
5204 composition_table[i]->font = NULL;
5206 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5208 Fredraw_frame (WINDOW_FRAME (w));
5209 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5212 center_p = 1;
5214 else if (CONSP (arg)) /* Just C-u. */
5215 center_p = 1;
5216 else
5218 arg = Fprefix_numeric_value (arg);
5219 CHECK_NUMBER (arg);
5220 iarg = XINT (arg);
5223 set_buffer_internal (buf);
5225 /* Do this after making BUF current
5226 in case scroll_margin is buffer-local. */
5227 this_scroll_margin =
5228 max (0, min (scroll_margin, XFASTINT (w->total_lines) / 4));
5230 /* Handle centering on a graphical frame specially. Such frames can
5231 have variable-height lines and centering point on the basis of
5232 line counts would lead to strange effects. */
5233 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5235 if (center_p)
5237 struct it it;
5238 struct text_pos pt;
5239 void *itdata = bidi_shelve_cache ();
5241 SET_TEXT_POS (pt, PT, PT_BYTE);
5242 start_display (&it, w, pt);
5243 move_it_vertically_backward (&it, window_box_height (w) / 2);
5244 charpos = IT_CHARPOS (it);
5245 bytepos = IT_BYTEPOS (it);
5246 bidi_unshelve_cache (itdata, 0);
5248 else if (iarg < 0)
5250 struct it it;
5251 struct text_pos pt;
5252 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
5253 int extra_line_spacing;
5254 int h = window_box_height (w);
5255 void *itdata = bidi_shelve_cache ();
5257 iarg = - max (-iarg, this_scroll_margin);
5259 SET_TEXT_POS (pt, PT, PT_BYTE);
5260 start_display (&it, w, pt);
5262 /* Be sure we have the exact height of the full line containing PT. */
5263 move_it_by_lines (&it, 0);
5265 /* The amount of pixels we have to move back is the window
5266 height minus what's displayed in the line containing PT,
5267 and the lines below. */
5268 it.current_y = 0;
5269 it.vpos = 0;
5270 move_it_by_lines (&it, nlines);
5272 if (it.vpos == nlines)
5273 h -= it.current_y;
5274 else
5276 /* Last line has no newline */
5277 h -= line_bottom_y (&it);
5278 it.vpos++;
5281 /* Don't reserve space for extra line spacing of last line. */
5282 extra_line_spacing = it.max_extra_line_spacing;
5284 /* If we can't move down NLINES lines because we hit
5285 the end of the buffer, count in some empty lines. */
5286 if (it.vpos < nlines)
5288 nlines -= it.vpos;
5289 extra_line_spacing = it.extra_line_spacing;
5290 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5292 if (h <= 0)
5294 bidi_unshelve_cache (itdata, 0);
5295 return Qnil;
5298 /* Now find the new top line (starting position) of the window. */
5299 start_display (&it, w, pt);
5300 it.current_y = 0;
5301 move_it_vertically_backward (&it, h);
5303 /* If extra line spacing is present, we may move too far
5304 back. This causes the last line to be only partially
5305 visible (which triggers redisplay to recenter that line
5306 in the middle), so move forward.
5307 But ignore extra line spacing on last line, as it is not
5308 considered to be part of the visible height of the line.
5310 h += extra_line_spacing;
5311 while (-it.current_y > h)
5312 move_it_by_lines (&it, 1);
5314 charpos = IT_CHARPOS (it);
5315 bytepos = IT_BYTEPOS (it);
5317 bidi_unshelve_cache (itdata, 0);
5319 else
5321 struct position pos;
5323 iarg = max (iarg, this_scroll_margin);
5325 pos = *vmotion (PT, -iarg, w);
5326 charpos = pos.bufpos;
5327 bytepos = pos.bytepos;
5330 else
5332 struct position pos;
5333 int ht = window_internal_height (w);
5335 if (center_p)
5336 iarg = ht / 2;
5337 else if (iarg < 0)
5338 iarg += ht;
5340 /* Don't let it get into the margin at either top or bottom. */
5341 iarg = max (iarg, this_scroll_margin);
5342 iarg = min (iarg, ht - this_scroll_margin - 1);
5344 pos = *vmotion (PT, - iarg, w);
5345 charpos = pos.bufpos;
5346 bytepos = pos.bytepos;
5349 /* Set the new window start. */
5350 set_marker_both (w->start, w->buffer, charpos, bytepos);
5351 wset_window_end_valid (w, Qnil);
5353 w->optional_new_start = 1;
5355 w->start_at_line_beg = (bytepos == BEGV_BYTE ||
5356 FETCH_BYTE (bytepos - 1) == '\n');
5358 set_buffer_internal (obuf);
5359 return Qnil;
5362 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5363 0, 1, 0,
5364 doc: /* Return the height in lines of the text display area of WINDOW.
5365 WINDOW must be a live window and defaults to the selected one.
5367 The returned height does not include the mode line, any header line,
5368 nor any partial-height lines at the bottom of the text area. */)
5369 (Lisp_Object window)
5371 struct window *w = decode_live_window (window);
5372 int pixel_height = window_box_height (w);
5373 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5374 return make_number (line_height);
5379 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5380 1, 1, "P",
5381 doc: /* Position point relative to window.
5382 ARG nil means position point at center of window.
5383 Else, ARG specifies vertical position within the window;
5384 zero means top of window, negative means relative to bottom of window. */)
5385 (Lisp_Object arg)
5387 struct window *w = XWINDOW (selected_window);
5388 int lines, start;
5389 Lisp_Object window;
5390 #if 0
5391 int this_scroll_margin;
5392 #endif
5394 if (!(BUFFERP (w->buffer)
5395 && XBUFFER (w->buffer) == current_buffer))
5396 /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
5397 when passed below to set_marker_both. */
5398 error ("move-to-window-line called from unrelated buffer");
5400 window = selected_window;
5401 start = marker_position (w->start);
5402 if (start < BEGV || start > ZV)
5404 int height = window_internal_height (w);
5405 Fvertical_motion (make_number (- (height / 2)), window);
5406 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5407 w->start_at_line_beg = !NILP (Fbolp ());
5408 w->force_start = 1;
5410 else
5411 Fgoto_char (w->start);
5413 lines = displayed_window_lines (w);
5415 #if 0
5416 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
5417 #endif
5419 if (NILP (arg))
5420 XSETFASTINT (arg, lines / 2);
5421 else
5423 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
5425 if (iarg < 0)
5426 iarg = iarg + lines;
5428 #if 0 /* This code would prevent move-to-window-line from moving point
5429 to a place inside the scroll margins (which would cause the
5430 next redisplay to scroll). I wrote this code, but then concluded
5431 it is probably better not to install it. However, it is here
5432 inside #if 0 so as not to lose it. -- rms. */
5434 /* Don't let it get into the margin at either top or bottom. */
5435 iarg = max (iarg, this_scroll_margin);
5436 iarg = min (iarg, lines - this_scroll_margin - 1);
5437 #endif
5439 arg = make_number (iarg);
5442 /* Skip past a partially visible first line. */
5443 if (w->vscroll)
5444 XSETINT (arg, XINT (arg) + 1);
5446 return Fvertical_motion (arg, window);
5451 /***********************************************************************
5452 Window Configuration
5453 ***********************************************************************/
5455 struct save_window_data
5457 struct vectorlike_header header;
5458 Lisp_Object selected_frame;
5459 Lisp_Object current_window;
5460 Lisp_Object current_buffer;
5461 Lisp_Object minibuf_scroll_window;
5462 Lisp_Object minibuf_selected_window;
5463 Lisp_Object root_window;
5464 Lisp_Object focus_frame;
5465 /* A vector, each of whose elements is a struct saved_window
5466 for one window. */
5467 Lisp_Object saved_windows;
5469 /* All fields above are traced by the GC.
5470 From `fame-cols' down, the fields are ignored by the GC. */
5472 int frame_cols, frame_lines, frame_menu_bar_lines;
5473 int frame_tool_bar_lines;
5476 /* This is saved as a Lisp_Vector */
5477 struct saved_window
5479 struct vectorlike_header header;
5481 Lisp_Object window, buffer, start, pointm, mark;
5482 Lisp_Object left_col, top_line, total_cols, total_lines;
5483 Lisp_Object normal_cols, normal_lines;
5484 Lisp_Object hscroll, min_hscroll;
5485 Lisp_Object parent, prev;
5486 Lisp_Object start_at_line_beg;
5487 Lisp_Object display_table;
5488 Lisp_Object left_margin_cols, right_margin_cols;
5489 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5490 Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
5491 Lisp_Object combination_limit, window_parameters;
5494 #define SAVED_WINDOW_N(swv,n) \
5495 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5497 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5498 doc: /* Return t if OBJECT is a window-configuration object. */)
5499 (Lisp_Object object)
5501 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5504 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5505 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5506 (Lisp_Object config)
5508 register struct save_window_data *data;
5509 struct Lisp_Vector *saved_windows;
5511 CHECK_WINDOW_CONFIGURATION (config);
5513 data = (struct save_window_data *) XVECTOR (config);
5514 saved_windows = XVECTOR (data->saved_windows);
5515 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5518 DEFUN ("set-window-configuration", Fset_window_configuration,
5519 Sset_window_configuration, 1, 1, 0,
5520 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5521 CONFIGURATION must be a value previously returned
5522 by `current-window-configuration' (which see).
5523 If CONFIGURATION was made from a frame that is now deleted,
5524 only frame-independent values can be restored. In this case,
5525 the return value is nil. Otherwise the value is t. */)
5526 (Lisp_Object configuration)
5528 register struct save_window_data *data;
5529 struct Lisp_Vector *saved_windows;
5530 Lisp_Object new_current_buffer;
5531 Lisp_Object frame;
5532 FRAME_PTR f;
5533 ptrdiff_t old_point = -1;
5535 CHECK_WINDOW_CONFIGURATION (configuration);
5537 data = (struct save_window_data *) XVECTOR (configuration);
5538 saved_windows = XVECTOR (data->saved_windows);
5540 new_current_buffer = data->current_buffer;
5541 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5542 new_current_buffer = Qnil;
5543 else
5545 if (XBUFFER (new_current_buffer) == current_buffer)
5546 /* The code further down "preserves point" by saving here PT in
5547 old_point and then setting it later back into PT. When the
5548 current-selected-window and the final-selected-window both show
5549 the current buffer, this suffers from the problem that the
5550 current PT is the window-point of the current-selected-window,
5551 while the final PT is the point of the final-selected-window, so
5552 this copy from one PT to the other would end up moving the
5553 window-point of the final-selected-window to the window-point of
5554 the current-selected-window. So we have to be careful which
5555 point of the current-buffer we copy into old_point. */
5556 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5557 && WINDOWP (selected_window)
5558 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
5559 && !EQ (selected_window, data->current_window))
5560 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5561 else
5562 old_point = PT;
5563 else
5564 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5565 point in new_current_buffer as of the last time this buffer was
5566 used. This can be non-deterministic since it can be changed by
5567 things like jit-lock by mere temporary selection of some random
5568 window that happens to show this buffer.
5569 So if possible we want this arbitrary choice of "which point" to
5570 be the one from the to-be-selected-window so as to prevent this
5571 window's cursor from being copied from another window. */
5572 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5573 /* If current_window = selected_window, its point is in BUF_PT. */
5574 && !EQ (selected_window, data->current_window))
5575 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5576 else
5577 old_point = BUF_PT (XBUFFER (new_current_buffer));
5580 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5581 f = XFRAME (frame);
5583 /* If f is a dead frame, don't bother rebuilding its window tree.
5584 However, there is other stuff we should still try to do below. */
5585 if (FRAME_LIVE_P (f))
5587 Lisp_Object window;
5588 Lisp_Object dead_windows = Qnil;
5589 register Lisp_Object tem, par, pers;
5590 register struct window *w;
5591 register struct saved_window *p;
5592 struct window *root_window;
5593 struct window **leaf_windows;
5594 int n_leaf_windows;
5595 ptrdiff_t k;
5596 int i, n;
5598 /* If the frame has been resized since this window configuration was
5599 made, we change the frame to the size specified in the
5600 configuration, restore the configuration, and then resize it
5601 back. We keep track of the prevailing height in these variables. */
5602 int previous_frame_lines = FRAME_LINES (f);
5603 int previous_frame_cols = FRAME_COLS (f);
5604 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5605 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5607 /* Don't do this within the main loop below: This may call Lisp
5608 code and is thus potentially unsafe while input is blocked. */
5609 for (k = 0; k < saved_windows->header.size; k++)
5611 p = SAVED_WINDOW_N (saved_windows, k);
5612 window = p->window;
5613 w = XWINDOW (window);
5614 if (!NILP (w->buffer)
5615 && !EQ (w->buffer, p->buffer)
5616 && BUFFER_LIVE_P (XBUFFER (p->buffer)))
5617 /* If a window we restore gets another buffer, record the
5618 window's old buffer. */
5619 call1 (Qrecord_window_buffer, window);
5622 /* The mouse highlighting code could get screwed up
5623 if it runs during this. */
5624 BLOCK_INPUT;
5626 if (data->frame_lines != previous_frame_lines
5627 || data->frame_cols != previous_frame_cols)
5628 change_frame_size (f, data->frame_lines,
5629 data->frame_cols, 0, 0, 0);
5630 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5631 if (data->frame_menu_bar_lines
5632 != previous_frame_menu_bar_lines)
5633 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
5634 make_number (0));
5635 #ifdef HAVE_WINDOW_SYSTEM
5636 if (data->frame_tool_bar_lines
5637 != previous_frame_tool_bar_lines)
5638 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
5639 make_number (0));
5640 #endif
5641 #endif
5643 /* "Swap out" point from the selected window's buffer
5644 into the window itself. (Normally the pointm of the selected
5645 window holds garbage.) We do this now, before
5646 restoring the window contents, and prevent it from
5647 being done later on when we select a new window. */
5648 if (! NILP (XWINDOW (selected_window)->buffer))
5650 w = XWINDOW (selected_window);
5651 set_marker_both (w->pointm,
5652 w->buffer,
5653 BUF_PT (XBUFFER (w->buffer)),
5654 BUF_PT_BYTE (XBUFFER (w->buffer)));
5657 windows_or_buffers_changed++;
5658 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5660 /* Problem: Freeing all matrices and later allocating them again
5661 is a serious redisplay flickering problem. What we would
5662 really like to do is to free only those matrices not reused
5663 below. */
5664 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5665 leaf_windows = alloca (count_windows (root_window)
5666 * sizeof *leaf_windows);
5667 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5669 /* Kludge Alert!
5670 Mark all windows now on frame as "deleted".
5671 Restoring the new configuration "undeletes" any that are in it.
5673 Save their current buffers in their height fields, since we may
5674 need it later, if a buffer saved in the configuration is now
5675 dead. */
5676 delete_all_child_windows (FRAME_ROOT_WINDOW (f));
5678 for (k = 0; k < saved_windows->header.size; k++)
5680 p = SAVED_WINDOW_N (saved_windows, k);
5681 window = p->window;
5682 w = XWINDOW (window);
5683 wset_next (w, Qnil);
5685 if (!NILP (p->parent))
5686 wset_parent
5687 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window);
5688 else
5689 wset_parent (w, Qnil);
5691 if (!NILP (p->prev))
5693 wset_prev
5694 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window);
5695 wset_next (XWINDOW (w->prev), p->window);
5697 else
5699 wset_prev (w, Qnil);
5700 if (!NILP (w->parent))
5702 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
5704 wset_vchild (XWINDOW (w->parent), p->window);
5705 wset_hchild (XWINDOW (w->parent), Qnil);
5707 else
5709 wset_hchild (XWINDOW (w->parent), p->window);
5710 wset_vchild (XWINDOW (w->parent), Qnil);
5715 /* If we squirreled away the buffer in the window's height,
5716 restore it now. */
5717 if (BUFFERP (w->total_lines))
5718 wset_buffer (w, w->total_lines);
5719 wset_left_col (w, p->left_col);
5720 wset_top_line (w, p->top_line);
5721 wset_total_cols (w, p->total_cols);
5722 wset_total_lines (w, p->total_lines);
5723 wset_normal_cols (w, p->normal_cols);
5724 wset_normal_lines (w, p->normal_lines);
5725 w->hscroll = XFASTINT (p->hscroll);
5726 w->min_hscroll = XFASTINT (p->min_hscroll);
5727 wset_display_table (w, p->display_table);
5728 wset_left_margin_cols (w, p->left_margin_cols);
5729 wset_right_margin_cols (w, p->right_margin_cols);
5730 wset_left_fringe_width (w, p->left_fringe_width);
5731 wset_right_fringe_width (w, p->right_fringe_width);
5732 w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
5733 wset_scroll_bar_width (w, p->scroll_bar_width);
5734 wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
5735 wset_dedicated (w, p->dedicated);
5736 wset_combination_limit (w, p->combination_limit);
5737 /* Restore any window parameters that have been saved.
5738 Parameters that have not been saved are left alone. */
5739 for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
5741 pers = XCAR (tem);
5742 if (CONSP (pers))
5744 if (NILP (XCDR (pers)))
5746 par = Fassq (XCAR (pers), w->window_parameters);
5747 if (CONSP (par) && !NILP (XCDR (par)))
5748 /* Reset a parameter to nil if and only if it
5749 has a non-nil association. Don't make new
5750 associations. */
5751 Fsetcdr (par, Qnil);
5753 else
5754 /* Always restore a non-nil value. */
5755 Fset_window_parameter (window, XCAR (pers), XCDR (pers));
5759 w->last_modified = 0;
5760 w->last_overlay_modified = 0;
5762 /* Reinstall the saved buffer and pointers into it. */
5763 if (NILP (p->buffer))
5764 /* An internal window. */
5765 wset_buffer (w, p->buffer);
5766 else if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5767 /* If saved buffer is alive, install it. */
5769 wset_buffer (w, p->buffer);
5770 w->start_at_line_beg = !NILP (p->start_at_line_beg);
5771 set_marker_restricted (w->start, p->start, w->buffer);
5772 set_marker_restricted (w->pointm, p->pointm,
5773 w->buffer);
5774 Fset_marker (BVAR (XBUFFER (w->buffer), mark),
5775 p->mark, w->buffer);
5777 /* As documented in Fcurrent_window_configuration, don't
5778 restore the location of point in the buffer which was
5779 current when the window configuration was recorded. */
5780 if (!EQ (p->buffer, new_current_buffer)
5781 && XBUFFER (p->buffer) == current_buffer)
5782 Fgoto_char (w->pointm);
5784 else if (!NILP (w->buffer)
5785 && BUFFER_LIVE_P (XBUFFER (w->buffer)))
5786 /* Keep window's old buffer; make sure the markers are
5787 real. */
5789 /* Set window markers at start of visible range. */
5790 if (XMARKER (w->start)->buffer == 0)
5791 set_marker_restricted (w->start, make_number (0),
5792 w->buffer);
5793 if (XMARKER (w->pointm)->buffer == 0)
5794 set_marker_restricted_both
5795 (w->pointm, w->buffer,
5796 BUF_PT (XBUFFER (w->buffer)),
5797 BUF_PT_BYTE (XBUFFER (w->buffer)));
5798 w->start_at_line_beg = 1;
5800 else
5801 /* Window has no live buffer, get one. */
5803 /* Get the buffer via other_buffer_safely in order to
5804 avoid showing an unimportant buffer and, if necessary, to
5805 recreate *scratch* in the course (part of Juanma's bs-show
5806 scenario from March 2011). */
5807 wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
5808 /* This will set the markers to beginning of visible
5809 range. */
5810 set_marker_restricted (w->start,
5811 make_number (0), w->buffer);
5812 set_marker_restricted (w->pointm,
5813 make_number (0), w->buffer);
5814 w->start_at_line_beg = 1;
5815 if (!NILP (w->dedicated))
5816 /* Record this window as dead. */
5817 dead_windows = Fcons (window, dead_windows);
5818 /* Make sure window is no more dedicated. */
5819 wset_dedicated (w, Qnil);
5823 fset_root_window (f, data->root_window);
5824 /* Arrange *not* to restore point in the buffer that was
5825 current when the window configuration was saved. */
5826 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5827 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5828 make_number (old_point),
5829 XWINDOW (data->current_window)->buffer);
5831 /* In the following call to `select-window', prevent "swapping out
5832 point" in the old selected window using the buffer that has
5833 been restored into it. We already swapped out that point from
5834 that window's old buffer. */
5835 select_window (data->current_window, Qnil, 1);
5836 BVAR (XBUFFER (XWINDOW (selected_window)->buffer), last_selected_window)
5837 = selected_window;
5839 if (NILP (data->focus_frame)
5840 || (FRAMEP (data->focus_frame)
5841 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5842 Fredirect_frame_focus (frame, data->focus_frame);
5844 /* Set the screen height to the value it had before this function. */
5845 if (previous_frame_lines != FRAME_LINES (f)
5846 || previous_frame_cols != FRAME_COLS (f))
5847 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5848 0, 0, 0);
5849 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5850 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5851 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5852 make_number (0));
5853 #ifdef HAVE_WINDOW_SYSTEM
5854 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5855 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5856 make_number (0));
5857 #endif
5858 #endif
5860 /* Now, free glyph matrices in windows that were not reused. */
5861 for (i = n = 0; i < n_leaf_windows; ++i)
5863 if (NILP (leaf_windows[i]->buffer))
5865 /* Assert it's not reused as a combination. */
5866 eassert (NILP (leaf_windows[i]->hchild)
5867 && NILP (leaf_windows[i]->vchild));
5868 free_window_matrices (leaf_windows[i]);
5870 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5871 ++n;
5874 adjust_glyphs (f);
5875 UNBLOCK_INPUT;
5877 /* Scan dead buffer windows. */
5878 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
5880 window = XCAR (dead_windows);
5881 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
5882 delete_deletable_window (window);
5885 /* Fselect_window will have made f the selected frame, so we
5886 reselect the proper frame here. Fhandle_switch_frame will change the
5887 selected window too, but that doesn't make the call to
5888 Fselect_window above totally superfluous; it still sets f's
5889 selected window. */
5890 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5891 do_switch_frame (data->selected_frame, 0, 0, Qnil);
5893 run_window_configuration_change_hook (f);
5896 if (!NILP (new_current_buffer))
5898 Fset_buffer (new_current_buffer);
5899 /* If the new current buffer doesn't appear in the selected
5900 window, go to its old point (see bug#12208). */
5901 if (!EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5902 Fgoto_char (make_number (old_point));
5905 Vminibuf_scroll_window = data->minibuf_scroll_window;
5906 minibuf_selected_window = data->minibuf_selected_window;
5908 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5912 /* Recursively delete all child windows reachable via the next, vchild,
5913 and hchild slots of WINDOW. */
5914 void
5915 delete_all_child_windows (Lisp_Object window)
5917 register struct window *w;
5919 w = XWINDOW (window);
5921 if (!NILP (w->next))
5922 /* Delete WINDOW's siblings (we traverse postorderly). */
5923 delete_all_child_windows (w->next);
5925 /* See Fset_window_configuration for excuse. */
5926 wset_total_lines (w, w->buffer);
5928 if (!NILP (w->vchild))
5930 delete_all_child_windows (w->vchild);
5931 wset_vchild (w, Qnil);
5933 else if (!NILP (w->hchild))
5935 delete_all_child_windows (w->hchild);
5936 wset_hchild (w, Qnil);
5938 else if (!NILP (w->buffer))
5940 unshow_buffer (w);
5941 unchain_marker (XMARKER (w->pointm));
5942 unchain_marker (XMARKER (w->start));
5943 wset_buffer (w, Qnil);
5946 Vwindow_list = Qnil;
5949 static int
5950 count_windows (register struct window *window)
5952 register int count = 1;
5953 if (!NILP (window->next))
5954 count += count_windows (XWINDOW (window->next));
5955 if (!NILP (window->vchild))
5956 count += count_windows (XWINDOW (window->vchild));
5957 if (!NILP (window->hchild))
5958 count += count_windows (XWINDOW (window->hchild));
5959 return count;
5963 /* Fill vector FLAT with leaf windows under W, starting at index I.
5964 Value is last index + 1. */
5965 static int
5966 get_leaf_windows (struct window *w, struct window **flat, int i)
5968 while (w)
5970 if (!NILP (w->hchild))
5971 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5972 else if (!NILP (w->vchild))
5973 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5974 else
5975 flat[i++] = w;
5977 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5980 return i;
5984 /* Return a pointer to the glyph W's physical cursor is on. Value is
5985 null if W's current matrix is invalid, so that no meaningful glyph
5986 can be returned. */
5987 struct glyph *
5988 get_phys_cursor_glyph (struct window *w)
5990 struct glyph_row *row;
5991 struct glyph *glyph;
5992 int hpos = w->phys_cursor.hpos;
5994 if (!(w->phys_cursor.vpos >= 0
5995 && w->phys_cursor.vpos < w->current_matrix->nrows))
5996 return NULL;
5998 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5999 if (!row->enabled_p)
6000 return NULL;
6002 if (w->hscroll)
6004 /* When the window is hscrolled, cursor hpos can legitimately be
6005 out of bounds, but we draw the cursor at the corresponding
6006 window margin in that case. */
6007 if (!row->reversed_p && hpos < 0)
6008 hpos = 0;
6009 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
6010 hpos = row->used[TEXT_AREA] - 1;
6013 if (row->used[TEXT_AREA] > hpos
6014 && 0 <= hpos)
6015 glyph = row->glyphs[TEXT_AREA] + hpos;
6016 else
6017 glyph = NULL;
6019 return glyph;
6023 static int
6024 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
6026 register struct saved_window *p;
6027 register struct window *w;
6028 register Lisp_Object tem, pers, par;
6030 for (;!NILP (window); window = w->next)
6032 p = SAVED_WINDOW_N (vector, i);
6033 w = XWINDOW (window);
6035 wset_temslot (w, make_number (i)); i++;
6036 p->window = window;
6037 p->buffer = w->buffer;
6038 p->left_col = w->left_col;
6039 p->top_line = w->top_line;
6040 p->total_cols = w->total_cols;
6041 p->total_lines = w->total_lines;
6042 p->normal_cols = w->normal_cols;
6043 p->normal_lines = w->normal_lines;
6044 XSETFASTINT (p->hscroll, w->hscroll);
6045 XSETFASTINT (p->min_hscroll, w->min_hscroll);
6046 p->display_table = w->display_table;
6047 p->left_margin_cols = w->left_margin_cols;
6048 p->right_margin_cols = w->right_margin_cols;
6049 p->left_fringe_width = w->left_fringe_width;
6050 p->right_fringe_width = w->right_fringe_width;
6051 p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
6052 p->scroll_bar_width = w->scroll_bar_width;
6053 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6054 p->dedicated = w->dedicated;
6055 p->combination_limit = w->combination_limit;
6056 p->window_parameters = Qnil;
6058 if (!NILP (Vwindow_persistent_parameters))
6060 /* Run cycle detection on Vwindow_persistent_parameters. */
6061 Lisp_Object tortoise, hare;
6063 hare = tortoise = Vwindow_persistent_parameters;
6064 while (CONSP (hare))
6066 hare = XCDR (hare);
6067 if (!CONSP (hare))
6068 break;
6070 hare = XCDR (hare);
6071 tortoise = XCDR (tortoise);
6073 if (EQ (hare, tortoise))
6074 /* Reset Vwindow_persistent_parameters to Qnil. */
6076 Vwindow_persistent_parameters = Qnil;
6077 break;
6081 for (tem = Vwindow_persistent_parameters; CONSP (tem);
6082 tem = XCDR (tem))
6084 pers = XCAR (tem);
6085 /* Save values for persistent window parameters. */
6086 if (CONSP (pers) && !NILP (XCDR (pers)))
6088 par = Fassq (XCAR (pers), w->window_parameters);
6089 if (NILP (par))
6090 /* If the window has no value for the parameter,
6091 make one. */
6092 p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
6093 p->window_parameters);
6094 else
6095 /* If the window has a value for the parameter,
6096 save it. */
6097 p->window_parameters = Fcons (Fcons (XCAR (par),
6098 XCDR (par)),
6099 p->window_parameters);
6104 if (!NILP (w->buffer))
6106 /* Save w's value of point in the window configuration. If w
6107 is the selected window, then get the value of point from
6108 the buffer; pointm is garbage in the selected window. */
6109 if (EQ (window, selected_window))
6110 p->pointm = build_marker (XBUFFER (w->buffer),
6111 BUF_PT (XBUFFER (w->buffer)),
6112 BUF_PT_BYTE (XBUFFER (w->buffer)));
6113 else
6114 p->pointm = Fcopy_marker (w->pointm, Qnil);
6115 XMARKER (p->pointm)->insertion_type
6116 = !NILP (Vwindow_point_insertion_type);
6118 p->start = Fcopy_marker (w->start, Qnil);
6119 p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
6121 tem = BVAR (XBUFFER (w->buffer), mark);
6122 p->mark = Fcopy_marker (tem, Qnil);
6124 else
6126 p->pointm = Qnil;
6127 p->start = Qnil;
6128 p->mark = Qnil;
6129 p->start_at_line_beg = Qnil;
6132 if (NILP (w->parent))
6133 p->parent = Qnil;
6134 else
6135 p->parent = XWINDOW (w->parent)->temslot;
6137 if (NILP (w->prev))
6138 p->prev = Qnil;
6139 else
6140 p->prev = XWINDOW (w->prev)->temslot;
6142 if (!NILP (w->vchild))
6143 i = save_window_save (w->vchild, vector, i);
6144 if (!NILP (w->hchild))
6145 i = save_window_save (w->hchild, vector, i);
6148 return i;
6151 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6152 Scurrent_window_configuration, 0, 1, 0,
6153 doc: /* Return an object representing the current window configuration of FRAME.
6154 If FRAME is nil or omitted, use the selected frame.
6155 This describes the number of windows, their sizes and current buffers,
6156 and for each displayed buffer, where display starts, and the positions of
6157 point and mark. An exception is made for point in the current buffer:
6158 its value is -not- saved.
6159 This also records the currently selected frame, and FRAME's focus
6160 redirection (see `redirect-frame-focus'). The variable
6161 `window-persistent-parameters' specifies which window parameters are
6162 saved by this function. */)
6163 (Lisp_Object frame)
6165 register Lisp_Object tem;
6166 register int n_windows;
6167 register struct save_window_data *data;
6168 register int i;
6169 FRAME_PTR f;
6171 if (NILP (frame))
6172 frame = selected_frame;
6173 CHECK_LIVE_FRAME (frame);
6174 f = XFRAME (frame);
6176 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6177 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6178 PVEC_WINDOW_CONFIGURATION);
6180 data->frame_cols = FRAME_COLS (f);
6181 data->frame_lines = FRAME_LINES (f);
6182 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6183 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6184 data->selected_frame = selected_frame;
6185 data->current_window = FRAME_SELECTED_WINDOW (f);
6186 XSETBUFFER (data->current_buffer, current_buffer);
6187 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6188 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6189 data->root_window = FRAME_ROOT_WINDOW (f);
6190 data->focus_frame = FRAME_FOCUS_FRAME (f);
6191 tem = Fmake_vector (make_number (n_windows), Qnil);
6192 data->saved_windows = tem;
6193 for (i = 0; i < n_windows; i++)
6194 ASET (tem, i,
6195 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil));
6196 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6197 XSETWINDOW_CONFIGURATION (tem, data);
6198 return (tem);
6201 /***********************************************************************
6202 Marginal Areas
6203 ***********************************************************************/
6205 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6206 2, 3, 0,
6207 doc: /* Set width of marginal areas of window WINDOW.
6208 WINDOW must be a live window and defaults to the selected one.
6210 Second arg LEFT-WIDTH specifies the number of character cells to
6211 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6212 does the same for the right marginal area. A nil width parameter
6213 means no margin. */)
6214 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6216 struct window *w = decode_live_window (window);
6218 /* Translate negative or zero widths to nil.
6219 Margins that are too wide have to be checked elsewhere. */
6221 if (!NILP (left_width))
6223 CHECK_NUMBER (left_width);
6224 if (XINT (left_width) <= 0)
6225 left_width = Qnil;
6228 if (!NILP (right_width))
6230 CHECK_NUMBER (right_width);
6231 if (XINT (right_width) <= 0)
6232 right_width = Qnil;
6235 if (!EQ (w->left_margin_cols, left_width)
6236 || !EQ (w->right_margin_cols, right_width))
6238 wset_left_margin_cols (w, left_width);
6239 wset_right_margin_cols (w, right_width);
6241 adjust_window_margins (w);
6243 ++windows_or_buffers_changed;
6244 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6247 return Qnil;
6251 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6252 0, 1, 0,
6253 doc: /* Get width of marginal areas of window WINDOW.
6254 WINDOW must be a live window and defaults to the selected one.
6256 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6257 If a marginal area does not exist, its width will be returned
6258 as nil. */)
6259 (Lisp_Object window)
6261 struct window *w = decode_live_window (window);
6262 return Fcons (w->left_margin_cols, w->right_margin_cols);
6267 /***********************************************************************
6268 Fringes
6269 ***********************************************************************/
6271 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6272 2, 4, 0,
6273 doc: /* Set the fringe widths of window WINDOW.
6274 WINDOW must be a live window and defaults to the selected one.
6276 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6277 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6278 fringe width. If a fringe width arg is nil, that means to use the
6279 frame's default fringe width. Default fringe widths can be set with
6280 the command `set-fringe-style'.
6281 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6282 outside of the display margins. By default, fringes are drawn between
6283 display marginal areas and the text area. */)
6284 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width, Lisp_Object outside_margins)
6286 struct window *w = decode_live_window (window);
6287 int outside = !NILP (outside_margins);
6289 if (!NILP (left_width))
6290 CHECK_NATNUM (left_width);
6291 if (!NILP (right_width))
6292 CHECK_NATNUM (right_width);
6294 /* Do nothing on a tty. */
6295 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6296 && (!EQ (w->left_fringe_width, left_width)
6297 || !EQ (w->right_fringe_width, right_width)
6298 || w->fringes_outside_margins != outside))
6300 wset_left_fringe_width (w, left_width);
6301 wset_right_fringe_width (w, right_width);
6302 w->fringes_outside_margins = outside;
6304 adjust_window_margins (w);
6306 clear_glyph_matrix (w->current_matrix);
6307 wset_window_end_valid (w, Qnil);
6309 ++windows_or_buffers_changed;
6310 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6313 return Qnil;
6317 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6318 0, 1, 0,
6319 doc: /* Get width of fringes of window WINDOW.
6320 WINDOW must be a live window and defaults to the selected one.
6322 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6323 (Lisp_Object window)
6325 struct window *w = decode_live_window (window);
6327 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6328 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6329 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6330 ? Qt : Qnil), Qnil)));
6335 /***********************************************************************
6336 Scroll bars
6337 ***********************************************************************/
6339 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
6340 Sset_window_scroll_bars, 2, 4, 0,
6341 doc: /* Set width and type of scroll bars of window WINDOW.
6342 WINDOW must be a live window and defaults to the selected one.
6344 Second parameter WIDTH specifies the pixel width for the scroll bar;
6345 this is automatically adjusted to a multiple of the frame column width.
6346 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6347 bar: left, right, or nil.
6348 If WIDTH is nil, use the frame's scroll-bar width.
6349 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6350 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6351 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, Lisp_Object horizontal_type)
6353 struct window *w = decode_live_window (window);
6355 if (!NILP (width))
6357 CHECK_RANGED_INTEGER (width, 0, INT_MAX);
6359 if (XINT (width) == 0)
6360 vertical_type = Qnil;
6363 if (!(NILP (vertical_type)
6364 || EQ (vertical_type, Qleft)
6365 || EQ (vertical_type, Qright)
6366 || EQ (vertical_type, Qt)))
6367 error ("Invalid type of vertical scroll bar");
6369 if (!EQ (w->scroll_bar_width, width)
6370 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6372 wset_scroll_bar_width (w, width);
6373 wset_vertical_scroll_bar_type (w, vertical_type);
6375 adjust_window_margins (w);
6377 clear_glyph_matrix (w->current_matrix);
6378 wset_window_end_valid (w, Qnil);
6380 ++windows_or_buffers_changed;
6381 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6384 return Qnil;
6388 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6389 0, 1, 0,
6390 doc: /* Get width and type of scroll bars of window WINDOW.
6391 WINDOW must be a live window and defaults to the selected one.
6393 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6394 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6395 value. */)
6396 (Lisp_Object window)
6398 struct window *w = decode_live_window (window);
6399 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6400 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6401 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6402 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6403 Fcons (w->vertical_scroll_bar_type,
6404 Fcons (Qnil, Qnil))));
6409 /***********************************************************************
6410 Smooth scrolling
6411 ***********************************************************************/
6413 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6414 doc: /* Return the amount by which WINDOW is scrolled vertically.
6415 If WINDOW is omitted or nil, it defaults to the selected window.
6416 Normally, value is a multiple of the canonical character height of WINDOW;
6417 optional second arg PIXELS-P means value is measured in pixels. */)
6418 (Lisp_Object window, Lisp_Object pixels_p)
6420 Lisp_Object result;
6421 struct frame *f;
6422 struct window *w;
6424 if (NILP (window))
6425 window = selected_window;
6426 else
6427 CHECK_WINDOW (window);
6428 w = XWINDOW (window);
6429 f = XFRAME (w->frame);
6431 if (FRAME_WINDOW_P (f))
6432 result = (NILP (pixels_p)
6433 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6434 : make_number (-w->vscroll));
6435 else
6436 result = make_number (0);
6437 return result;
6441 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6442 2, 3, 0,
6443 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6444 WINDOW nil means use the selected window. Normally, VSCROLL is a
6445 non-negative multiple of the canonical character height of WINDOW;
6446 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6447 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6448 corresponds to an integral number of pixels. The return value is the
6449 result of this rounding.
6450 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6451 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
6453 struct window *w;
6454 struct frame *f;
6456 if (NILP (window))
6457 window = selected_window;
6458 else
6459 CHECK_WINDOW (window);
6460 CHECK_NUMBER_OR_FLOAT (vscroll);
6462 w = XWINDOW (window);
6463 f = XFRAME (w->frame);
6465 if (FRAME_WINDOW_P (f))
6467 int old_dy = w->vscroll;
6469 w->vscroll = - (NILP (pixels_p)
6470 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6471 : XFLOATINT (vscroll));
6472 w->vscroll = min (w->vscroll, 0);
6474 if (w->vscroll != old_dy)
6476 /* Adjust glyph matrix of the frame if the virtual display
6477 area becomes larger than before. */
6478 if (w->vscroll < 0 && w->vscroll < old_dy)
6479 adjust_glyphs (f);
6481 /* Prevent redisplay shortcuts. */
6482 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6486 return Fwindow_vscroll (window, pixels_p);
6490 /* Call FN for all leaf windows on frame F. FN is called with the
6491 first argument being a pointer to the leaf window, and with
6492 additional argument USER_DATA. Stops when FN returns 0. */
6494 static void
6495 foreach_window (struct frame *f, int (*fn) (struct window *, void *),
6496 void *user_data)
6498 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6499 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6500 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6504 /* Helper function for foreach_window. Call FN for all leaf windows
6505 reachable from W. FN is called with the first argument being a
6506 pointer to the leaf window, and with additional argument USER_DATA.
6507 Stop when FN returns 0. Value is 0 if stopped by FN. */
6509 static int
6510 foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
6512 int cont;
6514 for (cont = 1; w && cont;)
6516 if (!NILP (w->hchild))
6517 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6518 else if (!NILP (w->vchild))
6519 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6520 else
6521 cont = fn (w, user_data);
6523 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6526 return cont;
6530 /* Freeze or unfreeze the window start of W unless it is a
6531 mini-window or the selected window. FREEZE_P non-null means freeze
6532 the window start. */
6534 static int
6535 freeze_window_start (struct window *w, void *freeze_p)
6537 if (MINI_WINDOW_P (w)
6538 || (WINDOWP (selected_window) /* Can be nil in corner cases. */
6539 && (w == XWINDOW (selected_window)
6540 || (MINI_WINDOW_P (XWINDOW (selected_window))
6541 && ! NILP (Vminibuf_scroll_window)
6542 && w == XWINDOW (Vminibuf_scroll_window)))))
6543 freeze_p = NULL;
6545 w->frozen_window_start_p = freeze_p != NULL;
6546 return 1;
6550 /* Freeze or unfreeze the window starts of all leaf windows on frame
6551 F, except the selected window and a mini-window. FREEZE_P non-zero
6552 means freeze the window start. */
6554 void
6555 freeze_window_starts (struct frame *f, int freeze_p)
6557 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6561 /***********************************************************************
6562 Initialization
6563 ***********************************************************************/
6565 /* Return 1 if window configurations CONFIGURATION1 and CONFIGURATION2
6566 describe the same state of affairs. This is used by Fequal.
6568 IGNORE_POSITIONS means ignore non-matching scroll positions
6569 and the like.
6571 This ignores a couple of things like the dedication status of
6572 window, combination_limit and the like. This might have to be
6573 fixed. */
6575 bool
6576 compare_window_configurations (Lisp_Object configuration1,
6577 Lisp_Object configuration2,
6578 bool ignore_positions)
6580 register struct save_window_data *d1, *d2;
6581 struct Lisp_Vector *sws1, *sws2;
6582 ptrdiff_t i;
6584 CHECK_WINDOW_CONFIGURATION (configuration1);
6585 CHECK_WINDOW_CONFIGURATION (configuration2);
6587 d1 = (struct save_window_data *) XVECTOR (configuration1);
6588 d2 = (struct save_window_data *) XVECTOR (configuration2);
6589 sws1 = XVECTOR (d1->saved_windows);
6590 sws2 = XVECTOR (d2->saved_windows);
6592 /* Frame settings must match. */
6593 if (d1->frame_cols != d2->frame_cols
6594 || d1->frame_lines != d2->frame_lines
6595 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
6596 || !EQ (d1->selected_frame, d2->selected_frame)
6597 || !EQ (d1->current_buffer, d2->current_buffer)
6598 || (!ignore_positions
6599 && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
6600 || !EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)))
6601 || !EQ (d1->focus_frame, d2->focus_frame)
6602 /* Verify that the two configurations have the same number of windows. */
6603 || sws1->header.size != sws2->header.size)
6604 return 0;
6606 for (i = 0; i < sws1->header.size; i++)
6608 struct saved_window *sw1, *sw2;
6610 sw1 = SAVED_WINDOW_N (sws1, i);
6611 sw2 = SAVED_WINDOW_N (sws2, i);
6613 if (
6614 /* The "current" windows in the two configurations must
6615 correspond to each other. */
6616 EQ (d1->current_window, sw1->window)
6617 != EQ (d2->current_window, sw2->window)
6618 /* Windows' buffers must match. */
6619 || !EQ (sw1->buffer, sw2->buffer)
6620 || !EQ (sw1->left_col, sw2->left_col)
6621 || !EQ (sw1->top_line, sw2->top_line)
6622 || !EQ (sw1->total_cols, sw2->total_cols)
6623 || !EQ (sw1->total_lines, sw2->total_lines)
6624 || !EQ (sw1->display_table, sw2->display_table)
6625 /* The next two disjuncts check the window structure for
6626 equality. */
6627 || !EQ (sw1->parent, sw2->parent)
6628 || !EQ (sw1->prev, sw2->prev)
6629 || (!ignore_positions
6630 && (!EQ (sw1->hscroll, sw2->hscroll)
6631 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
6632 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
6633 || NILP (Fequal (sw1->start, sw2->start))
6634 || NILP (Fequal (sw1->pointm, sw2->pointm))
6635 || NILP (Fequal (sw1->mark, sw2->mark))))
6636 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
6637 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
6638 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
6639 || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
6640 || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
6641 || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
6642 || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type))
6643 return 0;
6646 return 1;
6649 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6650 Scompare_window_configurations, 2, 2, 0,
6651 doc: /* Compare two window configurations as regards the structure of windows.
6652 This function ignores details such as the values of point and mark
6653 and scrolling positions. */)
6654 (Lisp_Object x, Lisp_Object y)
6656 if (compare_window_configurations (x, y, 1))
6657 return Qt;
6658 return Qnil;
6661 void
6662 init_window_once (void)
6664 struct frame *f = make_initial_frame ();
6665 XSETFRAME (selected_frame, f);
6666 Vterminal_frame = selected_frame;
6667 minibuf_window = f->minibuffer_window;
6668 selected_window = f->selected_window;
6669 last_nonminibuf_frame = f;
6671 window_initialized = 1;
6674 void
6675 init_window (void)
6677 Vwindow_list = Qnil;
6680 void
6681 syms_of_window (void)
6683 DEFSYM (Qscroll_up, "scroll-up");
6684 DEFSYM (Qscroll_down, "scroll-down");
6685 DEFSYM (Qscroll_command, "scroll-command");
6687 Fput (Qscroll_up, Qscroll_command, Qt);
6688 Fput (Qscroll_down, Qscroll_command, Qt);
6690 DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
6691 DEFSYM (Qwindowp, "windowp");
6692 DEFSYM (Qwindow_configuration_p, "window-configuration-p");
6693 DEFSYM (Qwindow_live_p, "window-live-p");
6694 DEFSYM (Qwindow_valid_p, "window-valid-p");
6695 DEFSYM (Qwindow_deletable_p, "window-deletable-p");
6696 DEFSYM (Qdelete_window, "delete-window");
6697 DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
6698 DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
6699 DEFSYM (Qsafe, "safe");
6700 DEFSYM (Qdisplay_buffer, "display-buffer");
6701 DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
6702 DEFSYM (Qrecord_window_buffer, "record-window-buffer");
6703 DEFSYM (Qget_mru_window, "get-mru-window");
6704 DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6705 DEFSYM (Qabove, "above");
6706 DEFSYM (Qbelow, "below");
6707 DEFSYM (Qclone_of, "clone-of");
6709 staticpro (&Vwindow_list);
6711 minibuf_selected_window = Qnil;
6712 staticpro (&minibuf_selected_window);
6714 window_scroll_pixel_based_preserve_x = -1;
6715 window_scroll_pixel_based_preserve_y = -1;
6716 window_scroll_preserve_hpos = -1;
6717 window_scroll_preserve_vpos = -1;
6719 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
6720 doc: /* Non-nil means call as function to display a help buffer.
6721 The function is called with one argument, the buffer to be displayed.
6722 Used by `with-output-to-temp-buffer'.
6723 If this function is used, then it must do the entire job of showing
6724 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6725 Vtemp_buffer_show_function = Qnil;
6727 DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
6728 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6729 Vminibuf_scroll_window = Qnil;
6731 DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
6732 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6733 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6734 is displayed in the `mode-line' face. */);
6735 mode_line_in_non_selected_windows = 1;
6737 DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
6738 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6739 Vother_window_scroll_buffer = Qnil;
6741 DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
6742 doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
6743 auto_window_vscroll_p = 1;
6745 DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
6746 doc: /* Number of lines of continuity when scrolling by screenfuls. */);
6747 next_screen_context_lines = 2;
6749 DEFVAR_LISP ("scroll-preserve-screen-position",
6750 Vscroll_preserve_screen_position,
6751 doc: /* Controls if scroll commands move point to keep its screen position unchanged.
6752 A value of nil means point does not keep its screen position except
6753 at the scroll margin or window boundary respectively.
6754 A value of t means point keeps its screen position if the scroll
6755 command moved it vertically out of the window, e.g. when scrolling
6756 by full screens.
6757 Any other value means point always keeps its screen position.
6758 Scroll commands should have the `scroll-command' property
6759 on their symbols to be controlled by this variable. */);
6760 Vscroll_preserve_screen_position = Qnil;
6762 DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
6763 doc: /* Type of marker to use for `window-point'. */);
6764 Vwindow_point_insertion_type = Qnil;
6766 DEFVAR_LISP ("window-configuration-change-hook",
6767 Vwindow_configuration_change_hook,
6768 doc: /* Functions to call when window configuration changes.
6769 The buffer-local part is run once per window, with the relevant window
6770 selected; while the global part is run only once for the modified frame,
6771 with the relevant frame selected. */);
6772 Vwindow_configuration_change_hook = Qnil;
6774 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
6775 doc: /* Non-nil means `recenter' redraws entire frame.
6776 If this option is non-nil, then the `recenter' command with a nil
6777 argument will redraw the entire frame; the special value `tty' causes
6778 the frame to be redrawn only if it is a tty frame. */);
6779 Vrecenter_redisplay = Qtty;
6781 DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
6782 doc: /* If t, resize window combinations proportionally.
6783 If this variable is nil, splitting a window gets the entire screen space
6784 for displaying the new window from the window to split. Deleting and
6785 resizing a window preferably resizes one adjacent window only.
6787 If this variable is t, splitting a window tries to get the space
6788 proportionally from all windows in the same combination. This also
6789 allows to split a window that is otherwise too small or of fixed size.
6790 Resizing and deleting a window proportionally resize all windows in the
6791 same combination.
6793 Other values are reserved for future use.
6795 This variable takes no effect if `window-combination-limit' is non-nil. */);
6796 Vwindow_combination_resize = Qnil;
6798 DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
6799 doc: /* If t, splitting a window makes a new parent window.
6800 If this variable is nil, splitting a window will create a new parent
6801 window only if the window has no parent window or the window shall
6802 become a combination orthogonal to the one it is part of.
6804 If this variable is t, splitting a window always creates a new parent
6805 window. If all splits behave this way, each frame's window tree is a
6806 binary tree and every window but the frame's root window has exactly one
6807 sibling.
6809 Other values are reserved for future use.
6811 The value of this variable is also assigned to the combination limit of
6812 the new parent window. The combination limit of a window can be
6813 retrieved via the function `window-combination-limit' and altered by the
6814 function `set-window-combination-limit'. */);
6815 Vwindow_combination_limit = Qnil;
6817 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
6818 doc: /* Alist of persistent window parameters.
6819 This alist specifies which window parameters shall get saved by
6820 `current-window-configuration' and `window-state-get' and subsequently
6821 restored to their previous values by `set-window-configuration' and
6822 `window-state-put'.
6824 The car of each entry of this alist is the symbol specifying the
6825 parameter. The cdr is one of the following:
6827 nil means the parameter is neither saved by `window-state-get' nor by
6828 `current-window-configuration'.
6830 t means the parameter is saved by `current-window-configuration' and,
6831 provided its WRITABLE argument is nil, by `window-state-get'.
6833 The symbol `writable' means the parameter is saved unconditionally by
6834 both `current-window-configuration' and `window-state-get'. Do not use
6835 this value for parameters without read syntax (like windows or frames).
6837 Parameters not saved by `current-window-configuration' or
6838 `window-state-get' are left alone by `set-window-configuration'
6839 respectively are not installed by `window-state-put'. */);
6840 Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
6842 defsubr (&Sselected_window);
6843 defsubr (&Sminibuffer_window);
6844 defsubr (&Swindow_minibuffer_p);
6845 defsubr (&Swindowp);
6846 defsubr (&Swindow_valid_p);
6847 defsubr (&Swindow_live_p);
6848 defsubr (&Swindow_frame);
6849 defsubr (&Sframe_root_window);
6850 defsubr (&Sframe_first_window);
6851 defsubr (&Sframe_selected_window);
6852 defsubr (&Sset_frame_selected_window);
6853 defsubr (&Spos_visible_in_window_p);
6854 defsubr (&Swindow_line_height);
6855 defsubr (&Swindow_buffer);
6856 defsubr (&Swindow_parent);
6857 defsubr (&Swindow_top_child);
6858 defsubr (&Swindow_left_child);
6859 defsubr (&Swindow_next_sibling);
6860 defsubr (&Swindow_prev_sibling);
6861 defsubr (&Swindow_combination_limit);
6862 defsubr (&Sset_window_combination_limit);
6863 defsubr (&Swindow_use_time);
6864 defsubr (&Swindow_top_line);
6865 defsubr (&Swindow_left_column);
6866 defsubr (&Swindow_total_height);
6867 defsubr (&Swindow_total_width);
6868 defsubr (&Swindow_normal_size);
6869 defsubr (&Swindow_new_total);
6870 defsubr (&Swindow_new_normal);
6871 defsubr (&Sset_window_new_total);
6872 defsubr (&Sset_window_new_normal);
6873 defsubr (&Swindow_resize_apply);
6874 defsubr (&Swindow_body_height);
6875 defsubr (&Swindow_body_width);
6876 defsubr (&Swindow_hscroll);
6877 defsubr (&Sset_window_hscroll);
6878 defsubr (&Swindow_redisplay_end_trigger);
6879 defsubr (&Sset_window_redisplay_end_trigger);
6880 defsubr (&Swindow_edges);
6881 defsubr (&Swindow_pixel_edges);
6882 defsubr (&Swindow_absolute_pixel_edges);
6883 defsubr (&Swindow_inside_edges);
6884 defsubr (&Swindow_inside_pixel_edges);
6885 defsubr (&Swindow_inside_absolute_pixel_edges);
6886 defsubr (&Scoordinates_in_window_p);
6887 defsubr (&Swindow_at);
6888 defsubr (&Swindow_point);
6889 defsubr (&Swindow_start);
6890 defsubr (&Swindow_end);
6891 defsubr (&Sset_window_point);
6892 defsubr (&Sset_window_start);
6893 defsubr (&Swindow_dedicated_p);
6894 defsubr (&Sset_window_dedicated_p);
6895 defsubr (&Swindow_display_table);
6896 defsubr (&Sset_window_display_table);
6897 defsubr (&Snext_window);
6898 defsubr (&Sprevious_window);
6899 defsubr (&Sget_buffer_window);
6900 defsubr (&Sdelete_other_windows_internal);
6901 defsubr (&Sdelete_window_internal);
6902 defsubr (&Sresize_mini_window_internal);
6903 defsubr (&Sset_window_buffer);
6904 defsubr (&Srun_window_configuration_change_hook);
6905 defsubr (&Sselect_window);
6906 defsubr (&Sforce_window_update);
6907 defsubr (&Stemp_output_buffer_show);
6908 defsubr (&Ssplit_window_internal);
6909 defsubr (&Sscroll_up);
6910 defsubr (&Sscroll_down);
6911 defsubr (&Sscroll_left);
6912 defsubr (&Sscroll_right);
6913 defsubr (&Sother_window_for_scrolling);
6914 defsubr (&Sscroll_other_window);
6915 defsubr (&Sminibuffer_selected_window);
6916 defsubr (&Srecenter);
6917 defsubr (&Swindow_text_height);
6918 defsubr (&Smove_to_window_line);
6919 defsubr (&Swindow_configuration_p);
6920 defsubr (&Swindow_configuration_frame);
6921 defsubr (&Sset_window_configuration);
6922 defsubr (&Scurrent_window_configuration);
6923 defsubr (&Sset_window_margins);
6924 defsubr (&Swindow_margins);
6925 defsubr (&Sset_window_fringes);
6926 defsubr (&Swindow_fringes);
6927 defsubr (&Sset_window_scroll_bars);
6928 defsubr (&Swindow_scroll_bars);
6929 defsubr (&Swindow_vscroll);
6930 defsubr (&Sset_window_vscroll);
6931 defsubr (&Scompare_window_configurations);
6932 defsubr (&Swindow_list);
6933 defsubr (&Swindow_list_1);
6934 defsubr (&Swindow_prev_buffers);
6935 defsubr (&Sset_window_prev_buffers);
6936 defsubr (&Swindow_next_buffers);
6937 defsubr (&Sset_window_next_buffers);
6938 defsubr (&Swindow_parameters);
6939 defsubr (&Swindow_parameter);
6940 defsubr (&Sset_window_parameter);
6943 void
6944 keys_of_window (void)
6946 initial_define_key (control_x_map, '<', "scroll-left");
6947 initial_define_key (control_x_map, '>', "scroll-right");
6949 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
6950 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6951 initial_define_key (meta_map, 'v', "scroll-down-command");