auto upstream
[emacs.git] / src / window.c
blobeafd6ef9e40d582ff42cfb5f629588a11d1acb7d
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985-1987, 1993-1998, 2000-2013 Free Software
4 Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 #include <config.h>
23 #define WINDOW_INLINE EXTERN_INLINE
25 #include <stdio.h>
27 #include "lisp.h"
28 #include "character.h"
29 #include "buffer.h"
30 #include "keyboard.h"
31 #include "keymap.h"
32 #include "frame.h"
33 #include "window.h"
34 #include "commands.h"
35 #include "indent.h"
36 #include "termchar.h"
37 #include "disptab.h"
38 #include "dispextern.h"
39 #include "blockinput.h"
40 #include "intervals.h"
41 #include "termhooks.h" /* For FRAME_TERMINAL. */
43 #ifdef HAVE_X_WINDOWS
44 #include "xterm.h"
45 #endif /* HAVE_X_WINDOWS */
46 #ifdef HAVE_NTGUI
47 #include "w32term.h"
48 #endif
49 #ifdef MSDOS
50 #include "msdos.h"
51 #endif
52 #ifdef HAVE_NS
53 #include "nsterm.h"
54 #endif
55 #ifdef HAVE_XWIDGETS
56 #include "xwidget.h"
57 #endif
58 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_valid_p;
59 static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer;
60 static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
61 static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
62 static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
63 static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
64 static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
66 static int displayed_window_lines (struct window *);
67 static int count_windows (struct window *);
68 static int get_leaf_windows (struct window *, struct window **, int);
69 static void window_scroll (Lisp_Object, EMACS_INT, 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);
91 static void select_window_1 (Lisp_Object, bool);
93 /* This is the window in which the terminal's cursor should
94 be left when nothing is being done with it. This must
95 always be a leaf window, and its buffer is selected by
96 the top level editing loop at the end of each command.
98 This value is always the same as
99 FRAME_SELECTED_WINDOW (selected_frame). */
100 Lisp_Object selected_window;
102 /* A list of all windows for use by next_window and Fwindow_list.
103 Functions creating or deleting windows should invalidate this cache
104 by setting it to nil. */
105 Lisp_Object Vwindow_list;
107 /* The mini-buffer window of the selected frame.
108 Note that you cannot test for mini-bufferness of an arbitrary window
109 by comparing against this; but you can test for mini-bufferness of
110 the selected window. */
111 Lisp_Object minibuf_window;
113 /* Non-nil means it is the window whose mode line should be
114 shown as the selected window when the minibuffer is selected. */
115 Lisp_Object minibuf_selected_window;
117 /* Hook run at end of temp_output_buffer_show. */
118 static Lisp_Object Qtemp_buffer_show_hook;
120 /* Incremented for each window created. */
121 static int sequence_number;
123 /* Nonzero after init_window_once has finished. */
124 static int window_initialized;
126 /* Hook to run when window config changes. */
127 static Lisp_Object Qwindow_configuration_change_hook;
129 /* Used by the function window_scroll_pixel_based */
130 static int window_scroll_pixel_based_preserve_x;
131 static int window_scroll_pixel_based_preserve_y;
133 /* Same for window_scroll_line_based. */
134 static EMACS_INT window_scroll_preserve_hpos;
135 static EMACS_INT window_scroll_preserve_vpos;
137 /* These setters are used only in this file, so they can be private. */
138 static void
139 wset_combination_limit (struct window *w, Lisp_Object val)
141 w->combination_limit = val;
143 static void
144 wset_dedicated (struct window *w, Lisp_Object val)
146 w->dedicated = val;
148 static void
149 wset_display_table (struct window *w, Lisp_Object val)
151 w->display_table = val;
153 static void
154 wset_hchild (struct window *w, Lisp_Object val)
156 w->hchild = val;
158 static void
159 wset_left_fringe_width (struct window *w, Lisp_Object val)
161 w->left_fringe_width = val;
163 static void
164 wset_left_margin_cols (struct window *w, Lisp_Object val)
166 w->left_margin_cols = val;
168 static void
169 wset_new_normal (struct window *w, Lisp_Object val)
171 w->new_normal = val;
173 static void
174 wset_new_total (struct window *w, Lisp_Object val)
176 w->new_total = val;
178 static void
179 wset_normal_cols (struct window *w, Lisp_Object val)
181 w->normal_cols = val;
183 static void
184 wset_normal_lines (struct window *w, Lisp_Object val)
186 w->normal_lines = val;
188 static void
189 wset_parent (struct window *w, Lisp_Object val)
191 w->parent = val;
193 static void
194 wset_pointm (struct window *w, Lisp_Object val)
196 w->pointm = val;
198 static void
199 wset_right_fringe_width (struct window *w, Lisp_Object val)
201 w->right_fringe_width = val;
203 static void
204 wset_right_margin_cols (struct window *w, Lisp_Object val)
206 w->right_margin_cols = val;
208 static void
209 wset_scroll_bar_width (struct window *w, Lisp_Object val)
211 w->scroll_bar_width = val;
213 static void
214 wset_start (struct window *w, Lisp_Object val)
216 w->start = val;
218 static void
219 wset_temslot (struct window *w, Lisp_Object val)
221 w->temslot = val;
223 static void
224 wset_vchild (struct window *w, Lisp_Object val)
226 w->vchild = val;
228 static void
229 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
231 w->vertical_scroll_bar_type = val;
233 static void
234 wset_window_parameters (struct window *w, Lisp_Object val)
236 w->window_parameters = val;
239 struct window *
240 decode_live_window (register Lisp_Object window)
242 if (NILP (window))
243 return XWINDOW (selected_window);
245 CHECK_LIVE_WINDOW (window);
246 return XWINDOW (window);
249 struct window *
250 decode_any_window (register Lisp_Object window)
252 struct window *w;
254 if (NILP (window))
255 return XWINDOW (selected_window);
257 CHECK_WINDOW (window);
258 w = XWINDOW (window);
259 return w;
262 static struct window *
263 decode_valid_window (register Lisp_Object window)
265 struct window *w;
267 if (NILP (window))
268 return XWINDOW (selected_window);
270 CHECK_VALID_WINDOW (window);
271 w = XWINDOW (window);
272 return w;
275 /* Called when W's buffer slot is changed. ARG -1 means that W is about to
276 cease its buffer, and 1 means that W is about to set up the new one. */
278 static void
279 adjust_window_count (struct window *w, int arg)
281 eassert (eabs (arg) == 1);
282 if (BUFFERP (w->buffer))
284 struct buffer *b = XBUFFER (w->buffer);
286 if (b->base_buffer)
287 b = b->base_buffer;
288 b->window_count += arg;
289 eassert (b->window_count >= 0);
293 /* Set W's buffer slot to VAL and recompute number
294 of windows showing VAL if it is a buffer. */
296 void
297 wset_buffer (struct window *w, Lisp_Object val)
299 adjust_window_count (w, -1);
300 w->buffer = val;
301 adjust_window_count (w, 1);
304 /* Build a frequently used 4-integer (X Y W H) list. */
306 static Lisp_Object
307 list4i (EMACS_INT x, EMACS_INT y, EMACS_INT w, EMACS_INT h)
309 return list4 (make_number (x), make_number (y),
310 make_number (w), make_number (h));
313 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
314 doc: /* Return t if OBJECT is a window and nil otherwise. */)
315 (Lisp_Object object)
317 return WINDOWP (object) ? Qt : Qnil;
320 DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
321 doc: /* Return t if OBJECT is a valid window and nil otherwise.
322 A valid window is either a window that displays a buffer or an internal
323 window. Deleted windows are not live. */)
324 (Lisp_Object object)
326 return WINDOW_VALID_P (object) ? Qt : Qnil;
329 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
330 doc: /* Return t if OBJECT is a live window and nil otherwise.
331 A live window is a window that displays a buffer.
332 Internal windows and deleted windows are not live. */)
333 (Lisp_Object object)
335 return WINDOW_LIVE_P (object) ? Qt : Qnil;
338 /* Frames and windows. */
339 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 0, 1, 0,
340 doc: /* Return the frame that window WINDOW is on.
341 WINDOW must be a valid window and defaults to the selected one. */)
342 (Lisp_Object window)
344 return decode_valid_window (window)->frame;
347 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
348 doc: /* Return the root window of FRAME-OR-WINDOW.
349 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
350 With a frame argument, return that frame's root window.
351 With a window argument, return the root window of that window's frame. */)
352 (Lisp_Object frame_or_window)
354 Lisp_Object window;
356 if (NILP (frame_or_window))
357 window = SELECTED_FRAME ()->root_window;
358 else if (WINDOW_VALID_P (frame_or_window))
359 window = XFRAME (XWINDOW (frame_or_window)->frame)->root_window;
360 else
362 CHECK_LIVE_FRAME (frame_or_window);
363 window = XFRAME (frame_or_window)->root_window;
366 return window;
369 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
370 doc: /* Return the minibuffer window for frame FRAME.
371 If FRAME is omitted or nil, it defaults to the selected frame. */)
372 (Lisp_Object frame)
374 return FRAME_MINIBUF_WINDOW (decode_live_frame (frame));
377 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
378 Swindow_minibuffer_p, 0, 1, 0,
379 doc: /* Return non-nil if WINDOW is a minibuffer window.
380 WINDOW must be a valid window and defaults to the selected one. */)
381 (Lisp_Object window)
383 return MINI_WINDOW_P (decode_valid_window (window)) ? Qt : Qnil;
386 /* Don't move this to window.el - this must be a safe routine. */
387 DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
388 doc: /* Return the topmost, leftmost live window on FRAME-OR-WINDOW.
389 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
390 Else if FRAME-OR-WINDOW denotes a valid window, return the first window
391 of that window's frame. If FRAME-OR-WINDOW denotes a live frame, return
392 the first window of that frame. */)
393 (Lisp_Object frame_or_window)
395 Lisp_Object window;
397 if (NILP (frame_or_window))
398 window = SELECTED_FRAME ()->root_window;
399 else if (WINDOW_VALID_P (frame_or_window))
400 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
401 else
403 CHECK_LIVE_FRAME (frame_or_window);
404 window = XFRAME (frame_or_window)->root_window;
407 while (NILP (XWINDOW (window)->buffer))
409 if (! NILP (XWINDOW (window)->hchild))
410 window = XWINDOW (window)->hchild;
411 else if (! NILP (XWINDOW (window)->vchild))
412 window = XWINDOW (window)->vchild;
413 else
414 emacs_abort ();
417 return window;
420 DEFUN ("frame-selected-window", Fframe_selected_window,
421 Sframe_selected_window, 0, 1, 0,
422 doc: /* Return the selected window of FRAME-OR-WINDOW.
423 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
424 Else if FRAME-OR-WINDOW denotes a valid window, return the selected
425 window of that window's frame. If FRAME-OR-WINDOW denotes a live frame,
426 return the selected window of that frame. */)
427 (Lisp_Object frame_or_window)
429 Lisp_Object window;
431 if (NILP (frame_or_window))
432 window = SELECTED_FRAME ()->selected_window;
433 else if (WINDOW_VALID_P (frame_or_window))
434 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
435 else
437 CHECK_LIVE_FRAME (frame_or_window);
438 window = XFRAME (frame_or_window)->selected_window;
441 return window;
444 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
445 Sset_frame_selected_window, 2, 3, 0,
446 doc: /* Set selected window of FRAME to WINDOW.
447 FRAME must be a live frame and defaults to the selected one. If FRAME
448 is the selected frame, this makes WINDOW the selected window. Optional
449 argument NORECORD non-nil means to neither change the order of recently
450 selected windows nor the buffer list. WINDOW must denote a live window.
451 Return WINDOW. */)
452 (Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
454 if (NILP (frame))
455 frame = selected_frame;
457 CHECK_LIVE_FRAME (frame);
458 CHECK_LIVE_WINDOW (window);
460 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
461 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
463 if (EQ (frame, selected_frame))
464 return Fselect_window (window, norecord);
465 else
467 fset_selected_window (XFRAME (frame), window);
468 return window;
472 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
473 doc: /* Return the selected window.
474 The selected window is the window in which the standard cursor for
475 selected windows appears and to which many commands apply. */)
476 (void)
478 return selected_window;
481 int window_select_count;
483 /* If select_window is called with inhibit_point_swap non-zero it will
484 not store point of the old selected window's buffer back into that
485 window's pointm slot. This is needed by Fset_window_configuration to
486 avoid that the display routine is called with selected_window set to
487 Qnil causing a subsequent crash. */
488 static Lisp_Object
489 select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
491 register struct window *w;
492 struct frame *sf;
494 CHECK_LIVE_WINDOW (window);
496 w = XWINDOW (window);
497 w->frozen_window_start_p = 0;
499 if (NILP (norecord))
501 w->use_time = ++window_select_count;
502 record_buffer (w->buffer);
505 /* Make the selected window's buffer current. */
506 Fset_buffer (w->buffer);
508 if (EQ (window, selected_window) && !inhibit_point_swap)
509 return window;
511 sf = SELECTED_FRAME ();
512 if (XFRAME (WINDOW_FRAME (w)) != sf)
514 fset_selected_window (XFRAME (WINDOW_FRAME (w)), window);
515 /* Use this rather than Fhandle_switch_frame
516 so that FRAME_FOCUS_FRAME is moved appropriately as we
517 move around in the state where a minibuffer in a separate
518 frame is active. */
519 Fselect_frame (WINDOW_FRAME (w), norecord);
520 /* Fselect_frame called us back so we've done all the work already. */
521 eassert (EQ (window, selected_window));
522 return window;
524 else
525 fset_selected_window (sf, window);
527 select_window_1 (window, inhibit_point_swap);
529 bset_last_selected_window (XBUFFER (w->buffer), window);
530 windows_or_buffers_changed++;
531 return window;
534 /* Select window with a minimum of fuss, i.e. don't record the change anywhere
535 (not even for redisplay's benefit), and assume that the window's frame is
536 already selected. */
537 static void
538 select_window_1 (Lisp_Object window, bool inhibit_point_swap)
540 /* Store the old selected window's buffer's point in pointm of the old
541 selected window. It belongs to that window, and when the window is
542 not selected, must be in the window. */
543 if (!inhibit_point_swap)
545 struct window *ow = XWINDOW (selected_window);
546 if (! NILP (ow->buffer))
547 set_marker_both (ow->pointm, ow->buffer,
548 BUF_PT (XBUFFER (ow->buffer)),
549 BUF_PT_BYTE (XBUFFER (ow->buffer)));
552 selected_window = window;
554 /* Go to the point recorded in the window.
555 This is important when the buffer is in more
556 than one window. It also matters when
557 redisplay_window has altered point after scrolling,
558 because it makes the change only in the window. */
560 register ptrdiff_t new_point = marker_position (XWINDOW (window)->pointm);
561 if (new_point < BEGV)
562 SET_PT (BEGV);
563 else if (new_point > ZV)
564 SET_PT (ZV);
565 else
566 SET_PT (new_point);
570 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
571 doc: /* Select WINDOW which must be a live window.
572 Also make WINDOW's frame the selected frame and WINDOW that frame's
573 selected window. In addition, make WINDOW's buffer current and set that
574 buffer's value of `point' to the value of WINDOW's `window-point'.
575 Return WINDOW.
577 Optional second arg NORECORD non-nil means do not put this buffer at the
578 front of the buffer list and do not make this window the most recently
579 selected one.
581 Note that the main editor command loop sets the current buffer to the
582 buffer of the selected window before each command. */)
583 (register Lisp_Object window, Lisp_Object norecord)
585 return select_window (window, norecord, 0);
588 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
589 doc: /* Return the buffer displayed in window WINDOW.
590 If WINDOW is omitted or nil, it defaults to the selected window.
591 Return nil for an internal window or a deleted window. */)
592 (Lisp_Object window)
594 return decode_any_window (window)->buffer;
597 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
598 doc: /* Return the parent window of window WINDOW.
599 WINDOW must be a valid window and defaults to the selected one.
600 Return nil for a window with no parent (e.g. a root window). */)
601 (Lisp_Object window)
603 return decode_valid_window (window)->parent;
606 DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 0, 1, 0,
607 doc: /* Return the topmost child window of window WINDOW.
608 WINDOW must be a valid window and defaults to the selected one.
609 Return nil if WINDOW is a live window (live windows have no children).
610 Return nil if WINDOW is an internal window whose children form a
611 horizontal combination. */)
612 (Lisp_Object window)
614 return decode_valid_window (window)->vchild;
617 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 0, 1, 0,
618 doc: /* Return the leftmost child window of window WINDOW.
619 WINDOW must be a valid window and defaults to the selected one.
620 Return nil if WINDOW is a live window (live windows have no children).
621 Return nil if WINDOW is an internal window whose children form a
622 vertical combination. */)
623 (Lisp_Object window)
625 return decode_valid_window (window)->hchild;
628 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
629 doc: /* Return the next sibling window of window WINDOW.
630 WINDOW must be a valid window and defaults to the selected one.
631 Return nil if WINDOW has no next sibling. */)
632 (Lisp_Object window)
634 return decode_valid_window (window)->next;
637 DEFUN ("window-prev-sibling", Fwindow_prev_sibling, Swindow_prev_sibling, 0, 1, 0,
638 doc: /* Return the previous sibling window of window WINDOW.
639 WINDOW must be a valid window and defaults to the selected one.
640 Return nil if WINDOW has no previous sibling. */)
641 (Lisp_Object window)
643 return decode_valid_window (window)->prev;
646 DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
647 doc: /* Return combination limit of window WINDOW.
648 If the return value is nil, child windows of WINDOW can be recombined with
649 WINDOW's siblings. A return value of t means that child windows of
650 WINDOW are never \(re-)combined with WINDOW's siblings.
652 WINDOW must be a valid window. The return value is meaningful for
653 internal windows only. */)
654 (Lisp_Object window)
656 CHECK_VALID_WINDOW (window);
657 return XWINDOW (window)->combination_limit;
660 DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
661 doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
662 If LIMIT is nil, child windows of WINDOW can be recombined with WINDOW's
663 siblings. LIMIT t means that child windows of WINDOW are never
664 \(re-)combined with WINDOW's siblings. Other values are reserved for
665 future use.
667 WINDOW must be a valid window. Setting the combination limit is
668 meaningful for internal windows only. */)
669 (Lisp_Object window, Lisp_Object limit)
671 wset_combination_limit (decode_valid_window (window), limit);
672 return limit;
675 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
676 doc: /* Return the use time of window WINDOW.
677 WINDOW must be a live window and defaults to the selected one.
678 The window with the highest use time is the most recently selected
679 one. The window with the lowest use time is the least recently
680 selected one. */)
681 (Lisp_Object window)
683 return make_number (decode_live_window (window)->use_time);
686 DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 1, 0,
687 doc: /* Return the total height, in lines, of window WINDOW.
688 WINDOW must be a valid window and defaults to the selected one.
690 The return value includes the mode line and header line, if any.
691 If WINDOW is an internal window, the total height is the height
692 of the screen areas spanned by its children.
694 On a graphical display, this total height is reported as an
695 integer multiple of the default character height. */)
696 (Lisp_Object window)
698 return decode_valid_window (window)->total_lines;
701 DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 1, 0,
702 doc: /* Return the total width, in columns, of window WINDOW.
703 WINDOW must be a valid window and defaults to the selected one.
705 The return value includes any vertical dividers or scroll bars
706 belonging to WINDOW. If WINDOW is an internal window, the total width
707 is the width of the screen areas spanned by its children.
709 On a graphical display, this total width is reported as an
710 integer multiple of the default character width. */)
711 (Lisp_Object window)
713 return decode_valid_window (window)->total_cols;
716 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
717 doc: /* Return the new total size of window WINDOW.
718 WINDOW must be a valid window and defaults to the selected one. */)
719 (Lisp_Object window)
721 return decode_valid_window (window)->new_total;
724 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
725 doc: /* Return the normal height of window WINDOW.
726 WINDOW must be a valid window and defaults to the selected one.
727 If HORIZONTAL is non-nil, return the normal width of WINDOW. */)
728 (Lisp_Object window, Lisp_Object horizontal)
730 struct window *w = decode_valid_window (window);
732 return NILP (horizontal) ? w->normal_lines : w->normal_cols;
735 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
736 doc: /* Return new normal size of window WINDOW.
737 WINDOW must be a valid window and defaults to the selected one. */)
738 (Lisp_Object window)
740 return decode_valid_window (window)->new_normal;
743 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
744 doc: /* Return left column of window WINDOW.
745 This is the distance, in columns, between the left edge of WINDOW and
746 the left edge of the frame's window area. For instance, the return
747 value is 0 if there is no window to the left of WINDOW.
749 WINDOW must be a valid window and defaults to the selected one. */)
750 (Lisp_Object window)
752 return decode_valid_window (window)->left_col;
755 DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
756 doc: /* Return top line of window WINDOW.
757 This is the distance, in lines, between the top of WINDOW and the top
758 of the frame's window area. For instance, the return value is 0 if
759 there is no window above WINDOW.
761 WINDOW must be a valid window and defaults to the selected one. */)
762 (Lisp_Object window)
764 return decode_valid_window (window)->top_line;
767 /* Return the number of lines of W's body. Don't count any mode or
768 header line of W. */
770 static int
771 window_body_lines (struct window *w)
773 int height = XFASTINT (w->total_lines);
775 if (!MINI_WINDOW_P (w))
777 if (WINDOW_WANTS_MODELINE_P (w))
778 --height;
779 if (WINDOW_WANTS_HEADER_LINE_P (w))
780 --height;
783 return height;
786 /* Return the number of columns of W's body. Don't count columns
787 occupied by the scroll bar or the vertical bar separating W from its
788 right sibling. On window-systems don't count fringes or display
789 margins either. */
792 window_body_cols (struct window *w)
794 struct frame *f = XFRAME (WINDOW_FRAME (w));
795 int width = XINT (w->total_cols);
797 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
798 /* Scroll bars occupy a few columns. */
799 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
800 else if (!FRAME_WINDOW_P (f)
801 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
802 /* The column of `|' characters separating side-by-side windows
803 occupies one column only. */
804 width -= 1;
806 /* Display margins cannot be used for normal text. */
807 width -= WINDOW_LEFT_MARGIN_COLS (w) + WINDOW_RIGHT_MARGIN_COLS (w);
809 if (FRAME_WINDOW_P (f))
810 /* On window-systems, fringes cannot be used for normal text. */
811 width -= WINDOW_FRINGE_COLS (w);
813 return width;
816 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 1, 0,
817 doc: /* Return the height, in lines, of WINDOW's text area.
818 WINDOW must be a live window and defaults to the selected one.
820 The returned height does not include the mode line or header line.
821 On a graphical display, the height is expressed as an integer multiple
822 of the default character height. If a line at the bottom of the text
823 area is only partially visible, that counts as a whole line; to
824 exclude partially-visible lines, use `window-text-height'. */)
825 (Lisp_Object window)
827 return make_number (window_body_lines (decode_live_window (window)));
830 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 1, 0,
831 doc: /* Return the width, in columns, of WINDOW's text area.
832 WINDOW must be a live window and defaults to the selected one.
834 The return value does not include any vertical dividers, fringe or
835 marginal areas, or scroll bars. On a graphical display, the width is
836 expressed as an integer multiple of the default character width. */)
837 (Lisp_Object window)
839 return make_number (window_body_cols (decode_live_window (window)));
842 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
843 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
844 WINDOW must be a live window and defaults to the selected one. */)
845 (Lisp_Object window)
847 return make_number (decode_live_window (window)->hscroll);
850 /* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
851 range, returning the new amount as a fixnum. */
852 static Lisp_Object
853 set_window_hscroll (struct window *w, EMACS_INT hscroll)
855 /* Horizontal scrolling has problems with large scroll amounts.
856 It's too slow with long lines, and even with small lines the
857 display can be messed up. For now, though, impose only the limits
858 required by the internal representation: horizontal scrolling must
859 fit in fixnum (since it's visible to Elisp) and into ptrdiff_t
860 (since it's stored in a ptrdiff_t). */
861 ptrdiff_t hscroll_max = min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX);
862 ptrdiff_t new_hscroll = clip_to_bounds (0, hscroll, hscroll_max);
864 /* Prevent redisplay shortcuts when changing the hscroll. */
865 if (w->hscroll != new_hscroll)
866 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
868 w->hscroll = new_hscroll;
869 return make_number (new_hscroll);
872 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
873 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
874 WINDOW must be a live window and defaults to the selected one.
875 Clip the number to a reasonable value if out of range.
876 Return the new number. NCOL should be zero or positive.
878 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
879 window so that the location of point moves off-window. */)
880 (Lisp_Object window, Lisp_Object ncol)
882 CHECK_NUMBER (ncol);
883 return set_window_hscroll (decode_live_window (window), XINT (ncol));
886 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
887 Swindow_redisplay_end_trigger, 0, 1, 0,
888 doc: /* Return WINDOW's redisplay end trigger value.
889 WINDOW must be a live window and defaults to the selected one.
890 See `set-window-redisplay-end-trigger' for more information. */)
891 (Lisp_Object window)
893 return decode_live_window (window)->redisplay_end_trigger;
896 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
897 Sset_window_redisplay_end_trigger, 2, 2, 0,
898 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
899 WINDOW must be a live window and defaults to the selected one. VALUE
900 should be a buffer position (typically a marker) or nil. If it is a
901 buffer position, then if redisplay in WINDOW reaches a position beyond
902 VALUE, the functions in `redisplay-end-trigger-functions' are called
903 with two arguments: WINDOW, and the end trigger value. Afterwards the
904 end-trigger value is reset to nil. */)
905 (register Lisp_Object window, Lisp_Object value)
907 wset_redisplay_end_trigger (decode_live_window (window), value);
908 return value;
911 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
912 doc: /* Return a list of the edge coordinates of WINDOW.
913 WINDOW must be a valid window and defaults to the selected one.
915 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
916 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
917 0 at top left corner of frame.
919 RIGHT is one more than the rightmost column occupied by WINDOW. BOTTOM
920 is one more than the bottommost row occupied by WINDOW. The edges
921 include the space used by WINDOW's scroll bar, display margins, fringes,
922 header line, and/or mode line. For the edges of just the text area, use
923 `window-inside-edges'. */)
924 (Lisp_Object window)
926 register struct window *w = decode_valid_window (window);
928 return list4i (WINDOW_LEFT_EDGE_COL (w), WINDOW_TOP_EDGE_LINE (w),
929 WINDOW_RIGHT_EDGE_COL (w), WINDOW_BOTTOM_EDGE_LINE (w));
932 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
933 doc: /* Return a list of the edge pixel coordinates of WINDOW.
934 WINDOW must be a valid window and defaults to the selected one.
936 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
937 0, 0 at the top left corner of the frame.
939 RIGHT is one more than the rightmost x position occupied by WINDOW.
940 BOTTOM is one more than the bottommost y position occupied by WINDOW.
941 The pixel edges include the space used by WINDOW's scroll bar, display
942 margins, fringes, header line, and/or mode line. For the pixel edges
943 of just the text area, use `window-inside-pixel-edges'. */)
944 (Lisp_Object window)
946 register struct window *w = decode_valid_window (window);
948 return list4i (WINDOW_LEFT_EDGE_X (w), WINDOW_TOP_EDGE_Y (w),
949 WINDOW_RIGHT_EDGE_X (w), WINDOW_BOTTOM_EDGE_Y (w));
952 static void
953 calc_absolute_offset (struct window *w, int *add_x, int *add_y)
955 struct frame *f = XFRAME (w->frame);
956 *add_y = f->top_pos;
957 #ifdef FRAME_MENUBAR_HEIGHT
958 *add_y += FRAME_MENUBAR_HEIGHT (f);
959 #endif
960 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
961 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
962 #elif FRAME_TOOLBAR_HEIGHT
963 *add_y += FRAME_TOOLBAR_HEIGHT (f);
964 #endif
965 #ifdef FRAME_NS_TITLEBAR_HEIGHT
966 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
967 #endif
968 *add_x = f->left_pos;
969 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
970 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
971 #endif
974 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
975 Swindow_absolute_pixel_edges, 0, 1, 0,
976 doc: /* Return a list of the edge pixel coordinates of WINDOW.
977 WINDOW must be a valid window and defaults to the selected one.
979 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
980 0, 0 at the top left corner of the display.
982 RIGHT is one more than the rightmost x position occupied by WINDOW.
983 BOTTOM is one more than the bottommost y position occupied by WINDOW.
984 The pixel edges include the space used by WINDOW's scroll bar, display
985 margins, fringes, header line, and/or mode line. For the pixel edges
986 of just the text area, use `window-inside-absolute-pixel-edges'. */)
987 (Lisp_Object window)
989 register struct window *w = decode_valid_window (window);
990 int add_x, add_y;
992 calc_absolute_offset (w, &add_x, &add_y);
994 return list4i (WINDOW_LEFT_EDGE_X (w) + add_x,
995 WINDOW_TOP_EDGE_Y (w) + add_y,
996 WINDOW_RIGHT_EDGE_X (w) + add_x,
997 WINDOW_BOTTOM_EDGE_Y (w) + add_y);
1000 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
1001 doc: /* Return a list of the edge coordinates of WINDOW.
1002 WINDOW must be a live window and defaults to the selected one.
1004 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
1005 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
1006 0 at top left corner of frame.
1008 RIGHT is one more than the rightmost column of WINDOW's text area.
1009 BOTTOM is one more than the bottommost row of WINDOW's text area. The
1010 inside edges do not include the space used by the WINDOW's scroll bar,
1011 display margins, fringes, header line, and/or mode line. */)
1012 (Lisp_Object window)
1014 register struct window *w = decode_live_window (window);
1016 return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w)
1017 + WINDOW_LEFT_MARGIN_COLS (w)
1018 + WINDOW_LEFT_FRINGE_COLS (w)),
1019 (WINDOW_TOP_EDGE_LINE (w)
1020 + WINDOW_HEADER_LINE_LINES (w)),
1021 (WINDOW_BOX_RIGHT_EDGE_COL (w)
1022 - WINDOW_RIGHT_MARGIN_COLS (w)
1023 - WINDOW_RIGHT_FRINGE_COLS (w)),
1024 (WINDOW_BOTTOM_EDGE_LINE (w)
1025 - WINDOW_MODE_LINE_LINES (w)));
1028 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
1029 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1030 WINDOW must be a live window and defaults to the selected one.
1032 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1033 (0,0) at the top left corner of the frame's window area.
1035 RIGHT is one more than the rightmost x position of WINDOW's text area.
1036 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1037 The inside edges do not include the space used by WINDOW's scroll bar,
1038 display margins, fringes, header line, and/or mode line. */)
1039 (Lisp_Object window)
1041 register struct window *w = decode_live_window (window);
1043 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1044 + WINDOW_LEFT_MARGIN_WIDTH (w)
1045 + WINDOW_LEFT_FRINGE_WIDTH (w)),
1046 (WINDOW_TOP_EDGE_Y (w)
1047 + WINDOW_HEADER_LINE_HEIGHT (w)),
1048 (WINDOW_BOX_RIGHT_EDGE_X (w)
1049 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1050 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
1051 (WINDOW_BOTTOM_EDGE_Y (w)
1052 - WINDOW_MODE_LINE_HEIGHT (w)));
1055 DEFUN ("window-inside-absolute-pixel-edges",
1056 Fwindow_inside_absolute_pixel_edges,
1057 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
1058 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1059 WINDOW must be a live window and defaults to the selected one.
1061 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1062 (0,0) at the top left corner of the frame's window area.
1064 RIGHT is one more than the rightmost x position of WINDOW's text area.
1065 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1066 The inside edges do not include the space used by WINDOW's scroll bar,
1067 display margins, fringes, header line, and/or mode line. */)
1068 (Lisp_Object window)
1070 register struct window *w = decode_live_window (window);
1071 int add_x, add_y;
1073 calc_absolute_offset (w, &add_x, &add_y);
1075 return list4i ((WINDOW_BOX_LEFT_EDGE_X (w)
1076 + WINDOW_LEFT_MARGIN_WIDTH (w)
1077 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
1078 (WINDOW_TOP_EDGE_Y (w)
1079 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
1080 (WINDOW_BOX_RIGHT_EDGE_X (w)
1081 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1082 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
1083 (WINDOW_BOTTOM_EDGE_Y (w)
1084 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
1087 /* Test if the character at column X, row Y is within window W.
1088 If it is not, return ON_NOTHING;
1089 if it is in the window's text area, return ON_TEXT;
1090 if it is on the window's modeline, return ON_MODE_LINE;
1091 if it is on the border between the window and its right sibling,
1092 return ON_VERTICAL_BORDER.
1093 if it is on a scroll bar, return ON_SCROLL_BAR.
1094 if it is on the window's top line, return ON_HEADER_LINE;
1095 if it is in left or right fringe of the window,
1096 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
1097 if it is in the marginal area to the left/right of the window,
1098 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
1100 X and Y are frame relative pixel coordinates. */
1102 static enum window_part
1103 coordinates_in_window (register struct window *w, int x, int y)
1105 struct frame *f = XFRAME (WINDOW_FRAME (w));
1106 enum window_part part;
1107 int ux = FRAME_COLUMN_WIDTH (f);
1108 int left_x = WINDOW_LEFT_EDGE_X (w);
1109 int right_x = WINDOW_RIGHT_EDGE_X (w);
1110 int top_y = WINDOW_TOP_EDGE_Y (w);
1111 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
1112 /* The width of the area where the vertical line can be dragged.
1113 (Between mode lines for instance. */
1114 int grabbable_width = ux;
1115 int lmargin_width, rmargin_width, text_left, text_right;
1117 /* Outside any interesting row or column? */
1118 if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
1119 return ON_NOTHING;
1121 /* On the mode line or header line? */
1122 if ((WINDOW_WANTS_MODELINE_P (w)
1123 && y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
1124 && (part = ON_MODE_LINE))
1125 || (WINDOW_WANTS_HEADER_LINE_P (w)
1126 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
1127 && (part = ON_HEADER_LINE)))
1129 /* If it's under/over the scroll bar portion of the mode/header
1130 line, say it's on the vertical line. That's to be able to
1131 resize windows horizontally in case we're using toolkit scroll
1132 bars. Note: If scrollbars are on the left, the window that
1133 must be eventually resized is that on the left of WINDOW. */
1134 if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1135 && !WINDOW_LEFTMOST_P (w)
1136 && eabs (x - left_x) < grabbable_width)
1137 || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1138 && !WINDOW_RIGHTMOST_P (w)
1139 && eabs (x - right_x) < grabbable_width))
1140 return ON_VERTICAL_BORDER;
1141 else
1142 return part;
1145 /* In what's below, we subtract 1 when computing right_x because we
1146 want the rightmost pixel, which is given by left_pixel+width-1. */
1147 if (w->pseudo_window_p)
1149 left_x = 0;
1150 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
1152 else
1154 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
1155 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
1158 /* Outside any interesting column? */
1159 if (x < left_x || x > right_x)
1160 return ON_SCROLL_BAR;
1162 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
1163 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
1165 text_left = window_box_left (w, TEXT_AREA);
1166 text_right = text_left + window_box_width (w, TEXT_AREA);
1168 if (FRAME_WINDOW_P (f))
1170 if (!w->pseudo_window_p
1171 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
1172 && !WINDOW_RIGHTMOST_P (w)
1173 && (eabs (x - right_x) < grabbable_width))
1174 return ON_VERTICAL_BORDER;
1176 /* Need to say "x > right_x" rather than >=, since on character
1177 terminals, the vertical line's x coordinate is right_x. */
1178 else if (!w->pseudo_window_p
1179 && !WINDOW_RIGHTMOST_P (w)
1180 && x > right_x - ux)
1181 return ON_VERTICAL_BORDER;
1183 if (x < text_left)
1185 if (lmargin_width > 0
1186 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1187 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
1188 : (x < left_x + lmargin_width)))
1189 return ON_LEFT_MARGIN;
1191 return ON_LEFT_FRINGE;
1194 if (x >= text_right)
1196 if (rmargin_width > 0
1197 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1198 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
1199 : (x >= right_x - rmargin_width)))
1200 return ON_RIGHT_MARGIN;
1202 return ON_RIGHT_FRINGE;
1205 /* Everything special ruled out - must be on text area */
1206 return ON_TEXT;
1209 /* Take X is the frame-relative pixel x-coordinate, and return the
1210 x-coordinate relative to part PART of window W. */
1212 window_relative_x_coord (struct window *w, enum window_part part, int x)
1214 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
1216 switch (part)
1218 case ON_TEXT:
1219 return x - window_box_left (w, TEXT_AREA);
1221 case ON_LEFT_FRINGE:
1222 return x - left_x;
1224 case ON_RIGHT_FRINGE:
1225 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
1227 case ON_LEFT_MARGIN:
1228 return (x - left_x
1229 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1230 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
1232 case ON_RIGHT_MARGIN:
1233 return (x + 1
1234 - ((w->pseudo_window_p)
1235 ? WINDOW_TOTAL_WIDTH (w)
1236 : WINDOW_BOX_RIGHT_EDGE_X (w))
1237 + window_box_width (w, RIGHT_MARGIN_AREA)
1238 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1239 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
1242 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
1243 return 0;
1247 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
1248 Scoordinates_in_window_p, 2, 2, 0,
1249 doc: /* Return non-nil if COORDINATES are in WINDOW.
1250 WINDOW must be a live window and defaults to the selected one.
1251 COORDINATES is a cons of the form (X . Y), X and Y being distances
1252 measured in characters from the upper-left corner of the frame.
1253 \(0 . 0) denotes the character in the upper left corner of the
1254 frame.
1255 If COORDINATES are in the text portion of WINDOW,
1256 the coordinates relative to the window are returned.
1257 If they are in the mode line of WINDOW, `mode-line' is returned.
1258 If they are in the top mode line of WINDOW, `header-line' is returned.
1259 If they are in the left fringe of WINDOW, `left-fringe' is returned.
1260 If they are in the right fringe of WINDOW, `right-fringe' is returned.
1261 If they are on the border between WINDOW and its right sibling,
1262 `vertical-line' is returned.
1263 If they are in the windows's left or right marginal areas, `left-margin'\n\
1264 or `right-margin' is returned. */)
1265 (register Lisp_Object coordinates, Lisp_Object window)
1267 struct window *w;
1268 struct frame *f;
1269 int x, y;
1270 Lisp_Object lx, ly;
1272 w = decode_live_window (window);
1273 f = XFRAME (w->frame);
1274 CHECK_CONS (coordinates);
1275 lx = Fcar (coordinates);
1276 ly = Fcdr (coordinates);
1277 CHECK_NUMBER_OR_FLOAT (lx);
1278 CHECK_NUMBER_OR_FLOAT (ly);
1279 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1280 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
1282 switch (coordinates_in_window (w, x, y))
1284 case ON_NOTHING:
1285 return Qnil;
1287 case ON_TEXT:
1288 /* Convert X and Y to window relative pixel coordinates, and
1289 return the canonical char units. */
1290 x -= window_box_left (w, TEXT_AREA);
1291 y -= WINDOW_TOP_EDGE_Y (w);
1292 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1293 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
1295 case ON_MODE_LINE:
1296 return Qmode_line;
1298 case ON_VERTICAL_BORDER:
1299 return Qvertical_line;
1301 case ON_HEADER_LINE:
1302 return Qheader_line;
1304 case ON_LEFT_FRINGE:
1305 return Qleft_fringe;
1307 case ON_RIGHT_FRINGE:
1308 return Qright_fringe;
1310 case ON_LEFT_MARGIN:
1311 return Qleft_margin;
1313 case ON_RIGHT_MARGIN:
1314 return Qright_margin;
1316 case ON_SCROLL_BAR:
1317 /* Historically we are supposed to return nil in this case. */
1318 return Qnil;
1320 default:
1321 emacs_abort ();
1326 /* Callback for foreach_window, used in window_from_coordinates.
1327 Check if window W contains coordinates specified by USER_DATA which
1328 is actually a pointer to a struct check_window_data CW.
1330 Check if window W contains coordinates *CW->x and *CW->y. If it
1331 does, return W in *CW->window, as Lisp_Object, and return in
1332 *CW->part the part of the window under coordinates *X,*Y. Return
1333 zero from this function to stop iterating over windows. */
1335 struct check_window_data
1337 Lisp_Object *window;
1338 int x, y;
1339 enum window_part *part;
1342 static int
1343 check_window_containing (struct window *w, void *user_data)
1345 struct check_window_data *cw = (struct check_window_data *) user_data;
1346 enum window_part found;
1347 int continue_p = 1;
1349 found = coordinates_in_window (w, cw->x, cw->y);
1350 if (found != ON_NOTHING)
1352 *cw->part = found;
1353 XSETWINDOW (*cw->window, w);
1354 continue_p = 0;
1357 return continue_p;
1361 /* Find the window containing frame-relative pixel position X/Y and
1362 return it as a Lisp_Object.
1364 If X, Y is on one of the window's special `window_part' elements,
1365 set *PART to the id of that element.
1367 If there is no window under X, Y return nil and leave *PART
1368 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1370 This function was previously implemented with a loop cycling over
1371 windows with Fnext_window, and starting with the frame's selected
1372 window. It turned out that this doesn't work with an
1373 implementation of next_window using Vwindow_list, because
1374 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1375 tree of F when this function is called asynchronously from
1376 note_mouse_highlight. The original loop didn't terminate in this
1377 case. */
1379 Lisp_Object
1380 window_from_coordinates (struct frame *f, int x, int y,
1381 enum window_part *part, int tool_bar_p)
1383 Lisp_Object window;
1384 struct check_window_data cw;
1385 enum window_part dummy;
1387 if (part == 0)
1388 part = &dummy;
1390 window = Qnil;
1391 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
1392 foreach_window (f, check_window_containing, &cw);
1394 /* If not found above, see if it's in the tool bar window, if a tool
1395 bar exists. */
1396 if (NILP (window)
1397 && tool_bar_p
1398 && WINDOWP (f->tool_bar_window)
1399 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1400 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
1401 != ON_NOTHING))
1403 *part = ON_TEXT;
1404 window = f->tool_bar_window;
1407 return window;
1410 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1411 doc: /* Return window containing coordinates X and Y on FRAME.
1412 FRAME must be a live frame and defaults to the selected one.
1413 The top left corner of the frame is considered to be row 0,
1414 column 0. */)
1415 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1417 struct frame *f = decode_live_frame (frame);
1419 /* Check that arguments are integers or floats. */
1420 CHECK_NUMBER_OR_FLOAT (x);
1421 CHECK_NUMBER_OR_FLOAT (y);
1423 return window_from_coordinates (f,
1424 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1425 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1426 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1427 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1428 0, 0);
1431 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1432 doc: /* Return current value of point in WINDOW.
1433 WINDOW must be a live window and defaults to the selected one.
1435 For a nonselected window, this is the value point would have if that
1436 window were selected.
1438 Note that, when WINDOW is selected, the value returned is the same as
1439 that returned by `point' for WINDOW's buffer. It would be more strictly
1440 correct to return the `top-level' value of `point', outside of any
1441 `save-excursion' forms. But that is hard to define. */)
1442 (Lisp_Object window)
1444 register struct window *w = decode_live_window (window);
1446 if (w == XWINDOW (selected_window))
1447 return make_number (BUF_PT (XBUFFER (w->buffer)));
1448 else
1449 return Fmarker_position (w->pointm);
1452 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1453 doc: /* Return position at which display currently starts in WINDOW.
1454 WINDOW must be a live window and defaults to the selected one.
1455 This is updated by redisplay or by calling `set-window-start'. */)
1456 (Lisp_Object window)
1458 return Fmarker_position (decode_live_window (window)->start);
1461 /* This is text temporarily removed from the doc string below.
1463 This function returns nil if the position is not currently known.
1464 That happens when redisplay is preempted and doesn't finish.
1465 If in that case you want to compute where the end of the window would
1466 have been if redisplay had finished, do this:
1467 (save-excursion
1468 (goto-char (window-start window))
1469 (vertical-motion (1- (window-height window)) window)
1470 (point))") */
1472 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1473 doc: /* Return position at which display currently ends in WINDOW.
1474 WINDOW must be a live window and defaults to the selected one.
1475 This is updated by redisplay, when it runs to completion.
1476 Simply changing the buffer text or setting `window-start'
1477 does not update this value.
1478 Return nil if there is no recorded value. (This can happen if the
1479 last redisplay of WINDOW was preempted, and did not finish.)
1480 If UPDATE is non-nil, compute the up-to-date position
1481 if it isn't already recorded. */)
1482 (Lisp_Object window, Lisp_Object update)
1484 Lisp_Object value;
1485 struct window *w = decode_live_window (window);
1486 Lisp_Object buf;
1487 struct buffer *b;
1489 buf = w->buffer;
1490 CHECK_BUFFER (buf);
1491 b = XBUFFER (buf);
1493 #if 0 /* This change broke some things. We should make it later. */
1494 /* If we don't know the end position, return nil.
1495 The user can compute it with vertical-motion if he wants to.
1496 It would be nicer to do it automatically,
1497 but that's so slow that it would probably bother people. */
1498 if (NILP (w->window_end_valid))
1499 return Qnil;
1500 #endif
1502 if (! NILP (update)
1503 && (windows_or_buffers_changed || NILP (w->window_end_valid))
1504 && !noninteractive)
1506 struct text_pos startp;
1507 ptrdiff_t charpos = marker_position (w->start);
1508 struct it it;
1509 struct buffer *old_buffer = NULL;
1510 void *itdata = NULL;
1512 /* Cannot use Fvertical_motion because that function doesn't
1513 cope with variable-height lines. */
1514 if (b != current_buffer)
1516 old_buffer = current_buffer;
1517 set_buffer_internal (b);
1520 /* In case W->start is out of the range, use something
1521 reasonable. This situation occurred when loading a file with
1522 `-l' containing a call to `rmail' with subsequent other
1523 commands. At the end, W->start happened to be BEG, while
1524 rmail had already narrowed the buffer. */
1525 if (charpos < BEGV)
1526 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1527 else if (charpos > ZV)
1528 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1529 else
1530 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1532 itdata = bidi_shelve_cache ();
1533 start_display (&it, w, startp);
1534 move_it_vertically (&it, window_box_height (w));
1535 if (it.current_y < it.last_visible_y)
1536 move_it_past_eol (&it);
1537 value = make_number (IT_CHARPOS (it));
1538 bidi_unshelve_cache (itdata, 0);
1540 if (old_buffer)
1541 set_buffer_internal (old_buffer);
1543 else
1544 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1546 return value;
1549 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1550 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1551 WINDOW must be a live window and defaults to the selected one.
1552 Return POS. */)
1553 (Lisp_Object window, Lisp_Object pos)
1555 register struct window *w = decode_live_window (window);
1557 CHECK_NUMBER_COERCE_MARKER (pos);
1559 if (w == XWINDOW (selected_window))
1561 if (XBUFFER (w->buffer) == current_buffer)
1562 Fgoto_char (pos);
1563 else
1565 struct buffer *old_buffer = current_buffer;
1567 set_buffer_internal (XBUFFER (w->buffer));
1568 Fgoto_char (pos);
1569 set_buffer_internal (old_buffer);
1572 else
1574 set_marker_restricted (w->pointm, pos, w->buffer);
1575 /* We have to make sure that redisplay updates the window to show
1576 the new value of point. */
1577 ++windows_or_buffers_changed;
1580 return pos;
1583 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1584 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1585 WINDOW must be a live window and defaults to the selected one. Return
1586 POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
1587 overriding motion of point in order to display at this exact start. */)
1588 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1590 register struct window *w = decode_live_window (window);
1592 CHECK_NUMBER_COERCE_MARKER (pos);
1593 set_marker_restricted (w->start, pos, w->buffer);
1594 /* this is not right, but much easier than doing what is right. */
1595 w->start_at_line_beg = 0;
1596 if (NILP (noforce))
1597 w->force_start = 1;
1598 w->update_mode_line = 1;
1599 w->last_modified = 0;
1600 w->last_overlay_modified = 0;
1601 if (!EQ (window, selected_window))
1602 windows_or_buffers_changed++;
1604 return pos;
1607 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1608 Spos_visible_in_window_p, 0, 3, 0,
1609 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1610 WINDOW must be a live window and defaults to the selected one.
1612 Return nil if that position is scrolled vertically out of view. If a
1613 character is only partially visible, nil is returned, unless the
1614 optional argument PARTIALLY is non-nil. If POS is only out of view
1615 because of horizontal scrolling, return non-nil. If POS is t, it
1616 specifies the position of the last visible glyph in WINDOW. POS
1617 defaults to point in WINDOW; WINDOW defaults to the selected window.
1619 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
1620 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
1621 where X and Y are the pixel coordinates relative to the top left corner
1622 of the window. The remaining elements are omitted if the character after
1623 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1624 off-window at the top and bottom of the row, ROWH is the height of the
1625 display row, and VPOS is the row number (0-based) containing POS. */)
1626 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1628 register struct window *w;
1629 register EMACS_INT posint;
1630 register struct buffer *buf;
1631 struct text_pos top;
1632 Lisp_Object in_window = Qnil;
1633 int rtop, rbot, rowh, vpos, fully_p = 1;
1634 int x, y;
1636 w = decode_live_window (window);
1637 buf = XBUFFER (w->buffer);
1638 SET_TEXT_POS_FROM_MARKER (top, w->start);
1640 if (EQ (pos, Qt))
1641 posint = -1;
1642 else if (!NILP (pos))
1644 CHECK_NUMBER_COERCE_MARKER (pos);
1645 posint = XINT (pos);
1647 else if (w == XWINDOW (selected_window))
1648 posint = PT;
1649 else
1650 posint = marker_position (w->pointm);
1652 /* If position is above window start or outside buffer boundaries,
1653 or if window start is out of range, position is not visible. */
1654 if ((EQ (pos, Qt)
1655 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
1656 && CHARPOS (top) >= BUF_BEGV (buf)
1657 && CHARPOS (top) <= BUF_ZV (buf)
1658 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
1659 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
1660 in_window = Qt;
1662 if (!NILP (in_window) && !NILP (partially))
1664 Lisp_Object part = Qnil;
1665 if (!fully_p)
1666 part = list4i (rtop, rbot, rowh, vpos);
1667 in_window = Fcons (make_number (x),
1668 Fcons (make_number (y), part));
1671 return in_window;
1674 DEFUN ("window-line-height", Fwindow_line_height,
1675 Swindow_line_height, 0, 2, 0,
1676 doc: /* Return height in pixels of text line LINE in window WINDOW.
1677 WINDOW must be a live window and defaults to the selected one.
1679 Return height of current line if LINE is omitted or nil. Return height of
1680 header or mode line if LINE is `header-line' or `mode-line'.
1681 Otherwise, LINE is a text line number starting from 0. A negative number
1682 counts from the end of the window.
1684 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
1685 in pixels of the visible part of the line, VPOS and YPOS are the
1686 vertical position in lines and pixels of the line, relative to the top
1687 of the first text line, and OFFBOT is the number of off-window pixels at
1688 the bottom of the text line. If there are off-window pixels at the top
1689 of the (first) text line, YPOS is negative.
1691 Return nil if window display is not up-to-date. In that case, use
1692 `pos-visible-in-window-p' to obtain the information. */)
1693 (Lisp_Object line, Lisp_Object window)
1695 register struct window *w;
1696 register struct buffer *b;
1697 struct glyph_row *row, *end_row;
1698 int max_y, crop, i;
1699 EMACS_INT n;
1701 w = decode_live_window (window);
1703 if (noninteractive || w->pseudo_window_p)
1704 return Qnil;
1706 CHECK_BUFFER (w->buffer);
1707 b = XBUFFER (w->buffer);
1709 /* Fail if current matrix is not up-to-date. */
1710 if (NILP (w->window_end_valid)
1711 || current_buffer->clip_changed
1712 || current_buffer->prevent_redisplay_optimizations_p
1713 || w->last_modified < BUF_MODIFF (b)
1714 || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b))
1715 return Qnil;
1717 if (NILP (line))
1719 i = w->cursor.vpos;
1720 if (i < 0 || i >= w->current_matrix->nrows
1721 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
1722 return Qnil;
1723 max_y = window_text_bottom_y (w);
1724 goto found_row;
1727 if (EQ (line, Qheader_line))
1729 if (!WINDOW_WANTS_HEADER_LINE_P (w))
1730 return Qnil;
1731 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1732 return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
1735 if (EQ (line, Qmode_line))
1737 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1738 return (row->enabled_p ?
1739 list4i (row->height,
1740 0, /* not accurate */
1741 (WINDOW_HEADER_LINE_HEIGHT (w)
1742 + window_text_bottom_y (w)),
1744 : Qnil);
1747 CHECK_NUMBER (line);
1748 n = XINT (line);
1750 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1751 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
1752 max_y = window_text_bottom_y (w);
1753 i = 0;
1755 while ((n < 0 || i < n)
1756 && row <= end_row && row->enabled_p
1757 && row->y + row->height < max_y)
1758 row++, i++;
1760 if (row > end_row || !row->enabled_p)
1761 return Qnil;
1763 if (++n < 0)
1765 if (-n > i)
1766 return Qnil;
1767 row += n;
1768 i += n;
1771 found_row:
1772 crop = max (0, (row->y + row->height) - max_y);
1773 return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
1776 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1777 0, 1, 0,
1778 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1779 More precisely, return the value assigned by the last call of
1780 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1781 never called with WINDOW as its argument, or the value set by that
1782 function was internally reset since its last call. WINDOW must be a
1783 live window and defaults to the selected one.
1785 When a window is dedicated to its buffer, `display-buffer' will refrain
1786 from displaying another buffer in it. `get-lru-window' and
1787 `get-largest-window' treat dedicated windows specially.
1788 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1789 `kill-buffer' can delete a dedicated window and the containing frame.
1791 Functions like `set-window-buffer' may change the buffer displayed by a
1792 window, unless that window is "strongly" dedicated to its buffer, that
1793 is the value returned by `window-dedicated-p' is t. */)
1794 (Lisp_Object window)
1796 return decode_live_window (window)->dedicated;
1799 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1800 Sset_window_dedicated_p, 2, 2, 0,
1801 doc: /* Mark WINDOW as dedicated according to FLAG.
1802 WINDOW must be a live window and defaults to the selected one. FLAG
1803 non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
1804 mark WINDOW as non-dedicated. Return FLAG.
1806 When a window is dedicated to its buffer, `display-buffer' will refrain
1807 from displaying another buffer in it. `get-lru-window' and
1808 `get-largest-window' treat dedicated windows specially.
1809 `delete-windows-on', `replace-buffer-in-windows', `quit-window',
1810 `quit-restore-window' and `kill-buffer' can delete a dedicated window
1811 and the containing frame.
1813 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1814 its buffer. Functions like `set-window-buffer' may change the buffer
1815 displayed by a window, unless that window is strongly dedicated to its
1816 buffer. If and when `set-window-buffer' displays another buffer in a
1817 window, it also makes sure that the window is no more dedicated. */)
1818 (Lisp_Object window, Lisp_Object flag)
1820 wset_dedicated (decode_live_window (window), flag);
1821 return flag;
1824 DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
1825 0, 1, 0,
1826 doc: /* Return buffers previously shown in WINDOW.
1827 WINDOW must be a live window and defaults to the selected one.
1829 The return value is a list of elements (BUFFER WINDOW-START POS),
1830 where BUFFER is a buffer, WINDOW-START is the start position of the
1831 window for that buffer, and POS is a window-specific point value. */)
1832 (Lisp_Object window)
1834 return decode_live_window (window)->prev_buffers;
1837 DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
1838 Sset_window_prev_buffers, 2, 2, 0,
1839 doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
1840 WINDOW must be a live window and defaults to the selected one.
1842 PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS),
1843 where BUFFER is a buffer, WINDOW-START is the start position of the
1844 window for that buffer, and POS is a window-specific point value. */)
1845 (Lisp_Object window, Lisp_Object prev_buffers)
1847 wset_prev_buffers (decode_live_window (window), prev_buffers);
1848 return prev_buffers;
1851 DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
1852 0, 1, 0,
1853 doc: /* Return list of buffers recently re-shown in WINDOW.
1854 WINDOW must be a live window and defaults to the selected one. */)
1855 (Lisp_Object window)
1857 return decode_live_window (window)->next_buffers;
1860 DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
1861 Sset_window_next_buffers, 2, 2, 0,
1862 doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
1863 WINDOW must be a live window and defaults to the selected one.
1864 NEXT-BUFFERS should be a list of buffers. */)
1865 (Lisp_Object window, Lisp_Object next_buffers)
1867 wset_next_buffers (decode_live_window (window), next_buffers);
1868 return next_buffers;
1871 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1872 0, 1, 0,
1873 doc: /* Return the parameters of WINDOW and their values.
1874 WINDOW must be a valid window and defaults to the selected one. The
1875 return value is a list of elements of the form (PARAMETER . VALUE). */)
1876 (Lisp_Object window)
1878 return Fcopy_alist (decode_valid_window (window)->window_parameters);
1881 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1882 2, 2, 0,
1883 doc: /* Return WINDOW's value for PARAMETER.
1884 WINDOW can be any window and defaults to the selected one. */)
1885 (Lisp_Object window, Lisp_Object parameter)
1887 Lisp_Object result;
1889 result = Fassq (parameter, decode_any_window (window)->window_parameters);
1890 return CDR_SAFE (result);
1893 DEFUN ("set-window-parameter", Fset_window_parameter,
1894 Sset_window_parameter, 3, 3, 0,
1895 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1896 WINDOW can be any window and defaults to the selected one.
1897 Return VALUE. */)
1898 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
1900 register struct window *w = decode_any_window (window);
1901 Lisp_Object old_alist_elt;
1903 old_alist_elt = Fassq (parameter, w->window_parameters);
1904 if (NILP (old_alist_elt))
1905 wset_window_parameters
1906 (w, Fcons (Fcons (parameter, value), w->window_parameters));
1907 else
1908 Fsetcdr (old_alist_elt, value);
1909 return value;
1912 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1913 0, 1, 0,
1914 doc: /* Return the display-table that WINDOW is using.
1915 WINDOW must be a live window and defaults to the selected one. */)
1916 (Lisp_Object window)
1918 return decode_live_window (window)->display_table;
1921 /* Get the display table for use on window W. This is either W's
1922 display table or W's buffer's display table. Ignore the specified
1923 tables if they are not valid; if no valid table is specified,
1924 return 0. */
1926 struct Lisp_Char_Table *
1927 window_display_table (struct window *w)
1929 struct Lisp_Char_Table *dp = NULL;
1931 if (DISP_TABLE_P (w->display_table))
1932 dp = XCHAR_TABLE (w->display_table);
1933 else if (BUFFERP (w->buffer))
1935 struct buffer *b = XBUFFER (w->buffer);
1937 if (DISP_TABLE_P (BVAR (b, display_table)))
1938 dp = XCHAR_TABLE (BVAR (b, display_table));
1939 else if (DISP_TABLE_P (Vstandard_display_table))
1940 dp = XCHAR_TABLE (Vstandard_display_table);
1943 return dp;
1946 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1947 doc: /* Set WINDOW's display-table to TABLE.
1948 WINDOW must be a live window and defaults to the selected one. */)
1949 (register Lisp_Object window, Lisp_Object table)
1951 wset_display_table (decode_live_window (window), table);
1952 return table;
1955 /* Record info on buffer window W is displaying
1956 when it is about to cease to display that buffer. */
1957 static void
1958 unshow_buffer (register struct window *w)
1960 Lisp_Object buf;
1961 struct buffer *b;
1963 buf = w->buffer;
1964 b = XBUFFER (buf);
1965 if (b != XMARKER (w->pointm)->buffer)
1966 emacs_abort ();
1968 #if 0
1969 if (w == XWINDOW (selected_window)
1970 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1971 /* Do this except when the selected window's buffer
1972 is being removed from some other window. */
1973 #endif
1974 /* last_window_start records the start position that this buffer
1975 had in the last window to be disconnected from it.
1976 Now that this statement is unconditional,
1977 it is possible for the buffer to be displayed in the
1978 selected window, while last_window_start reflects another
1979 window which was recently showing the same buffer.
1980 Some people might say that might be a good thing. Let's see. */
1981 b->last_window_start = marker_position (w->start);
1983 /* Point in the selected window's buffer
1984 is actually stored in that buffer, and the window's pointm isn't used.
1985 So don't clobber point in that buffer. */
1986 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1987 /* Don't clobber point in current buffer either (this could be
1988 useful in connection with bug#12208).
1989 && XBUFFER (buf) != current_buffer */
1990 /* This line helps to fix Horsley's testbug.el bug. */
1991 && !(WINDOWP (BVAR (b, last_selected_window))
1992 && w != XWINDOW (BVAR (b, last_selected_window))
1993 && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->buffer)))
1994 temp_set_point_both (b,
1995 clip_to_bounds (BUF_BEGV (b),
1996 marker_position (w->pointm),
1997 BUF_ZV (b)),
1998 clip_to_bounds (BUF_BEGV_BYTE (b),
1999 marker_byte_position (w->pointm),
2000 BUF_ZV_BYTE (b)));
2002 if (WINDOWP (BVAR (b, last_selected_window))
2003 && w == XWINDOW (BVAR (b, last_selected_window)))
2004 bset_last_selected_window (b, Qnil);
2007 /* Put NEW into the window structure in place of OLD. SETFLAG zero
2008 means change window structure only. Otherwise store geometry and
2009 other settings as well. */
2010 static void
2011 replace_window (Lisp_Object old, Lisp_Object new, int setflag)
2013 register Lisp_Object tem;
2014 register struct window *o = XWINDOW (old), *n = XWINDOW (new);
2016 /* If OLD is its frame's root window, then NEW is the new
2017 root window for that frame. */
2018 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
2019 fset_root_window (XFRAME (o->frame), new);
2021 if (setflag)
2023 wset_left_col (n, o->left_col);
2024 wset_top_line (n, o->top_line);
2025 wset_total_cols (n, o->total_cols);
2026 wset_total_lines (n, o->total_lines);
2027 wset_normal_cols (n, o->normal_cols);
2028 wset_normal_cols (o, make_float (1.0));
2029 wset_normal_lines (n, o->normal_lines);
2030 wset_normal_lines (o, make_float (1.0));
2031 n->desired_matrix = n->current_matrix = 0;
2032 n->vscroll = 0;
2033 memset (&n->cursor, 0, sizeof (n->cursor));
2034 memset (&n->last_cursor, 0, sizeof (n->last_cursor));
2035 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
2036 n->phys_cursor_type = -1;
2037 n->phys_cursor_width = -1;
2038 n->must_be_updated_p = 0;
2039 n->pseudo_window_p = 0;
2040 wset_window_end_vpos (n, make_number (0));
2041 wset_window_end_pos (n, make_number (0));
2042 wset_window_end_valid (n, Qnil);
2043 n->frozen_window_start_p = 0;
2046 tem = o->next;
2047 wset_next (n, tem);
2048 if (!NILP (tem))
2049 wset_prev (XWINDOW (tem), new);
2051 tem = o->prev;
2052 wset_prev (n, tem);
2053 if (!NILP (tem))
2054 wset_next (XWINDOW (tem), new);
2056 tem = o->parent;
2057 wset_parent (n, tem);
2058 if (!NILP (tem))
2060 if (EQ (XWINDOW (tem)->vchild, old))
2061 wset_vchild (XWINDOW (tem), new);
2062 if (EQ (XWINDOW (tem)->hchild, old))
2063 wset_hchild (XWINDOW (tem), new);
2067 /* If window WINDOW and its parent window are iso-combined, merge
2068 WINDOW's children into those of its parent window and mark WINDOW as
2069 deleted. */
2071 static void
2072 recombine_windows (Lisp_Object window)
2074 struct window *w, *p, *c;
2075 Lisp_Object parent, child;
2076 int horflag;
2078 w = XWINDOW (window);
2079 parent = w->parent;
2080 if (!NILP (parent) && NILP (w->combination_limit))
2082 p = XWINDOW (parent);
2083 if (((!NILP (p->vchild) && !NILP (w->vchild))
2084 || (!NILP (p->hchild) && !NILP (w->hchild))))
2085 /* WINDOW and PARENT are both either a vertical or a horizontal
2086 combination. */
2088 horflag = NILP (w->vchild);
2089 child = horflag ? w->hchild : w->vchild;
2090 c = XWINDOW (child);
2092 /* Splice WINDOW's children into its parent's children and
2093 assign new normal sizes. */
2094 if (NILP (w->prev))
2095 if (horflag)
2096 wset_hchild (p, child);
2097 else
2098 wset_vchild (p, child);
2099 else
2101 wset_prev (c, w->prev);
2102 wset_next (XWINDOW (w->prev), child);
2105 while (c)
2107 wset_parent (c, parent);
2109 if (horflag)
2110 wset_normal_cols (c,
2111 make_float (XFLOATINT (c->total_cols)
2112 / XFLOATINT (p->total_cols)));
2113 else
2114 wset_normal_lines (c,
2115 make_float (XFLOATINT (c->total_lines)
2116 / XFLOATINT (p->total_lines)));
2118 if (NILP (c->next))
2120 if (!NILP (w->next))
2122 wset_next (c, w->next);
2123 wset_prev (XWINDOW (c->next), child);
2126 c = 0;
2128 else
2130 child = c->next;
2131 c = XWINDOW (child);
2135 /* WINDOW can be deleted now. */
2136 wset_vchild (w, Qnil);
2137 wset_hchild (w, Qnil);
2142 /* If WINDOW can be deleted, delete it. */
2143 static void
2144 delete_deletable_window (Lisp_Object window)
2146 if (!NILP (call1 (Qwindow_deletable_p, window)))
2147 call1 (Qdelete_window, window);
2150 /***********************************************************************
2151 Window List
2152 ***********************************************************************/
2154 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
2155 pointer. This is a callback function for foreach_window, used in
2156 the window_list function. */
2158 static int
2159 add_window_to_list (struct window *w, void *user_data)
2161 Lisp_Object *list = (Lisp_Object *) user_data;
2162 Lisp_Object window;
2163 XSETWINDOW (window, w);
2164 *list = Fcons (window, *list);
2165 return 1;
2169 /* Return a list of all windows, for use by next_window. If
2170 Vwindow_list is a list, return that list. Otherwise, build a new
2171 list, cache it in Vwindow_list, and return that. */
2173 static Lisp_Object
2174 window_list (void)
2176 if (!CONSP (Vwindow_list))
2178 Lisp_Object tail, frame;
2180 Vwindow_list = Qnil;
2181 FOR_EACH_FRAME (tail, frame)
2183 Lisp_Object args[2];
2185 /* We are visiting windows in canonical order, and add
2186 new windows at the front of args[1], which means we
2187 have to reverse this list at the end. */
2188 args[1] = Qnil;
2189 foreach_window (XFRAME (frame), add_window_to_list, &args[1]);
2190 args[0] = Vwindow_list;
2191 args[1] = Fnreverse (args[1]);
2192 Vwindow_list = Fnconc (2, args);
2196 return Vwindow_list;
2200 /* Value is non-zero if WINDOW satisfies the constraints given by
2201 OWINDOW, MINIBUF and ALL_FRAMES.
2203 MINIBUF t means WINDOW may be minibuffer windows.
2204 `lambda' means WINDOW may not be a minibuffer window.
2205 a window means a specific minibuffer window
2207 ALL_FRAMES t means search all frames,
2208 nil means search just current frame,
2209 `visible' means search just visible frames on the
2210 current terminal,
2211 0 means search visible and iconified frames on the
2212 current terminal,
2213 a window means search the frame that window belongs to,
2214 a frame means consider windows on that frame, only. */
2216 static int
2217 candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf, Lisp_Object all_frames)
2219 struct window *w = XWINDOW (window);
2220 struct frame *f = XFRAME (w->frame);
2221 int candidate_p = 1;
2223 if (!BUFFERP (w->buffer))
2224 candidate_p = 0;
2225 else if (MINI_WINDOW_P (w)
2226 && (EQ (minibuf, Qlambda)
2227 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
2229 /* If MINIBUF is `lambda' don't consider any mini-windows.
2230 If it is a window, consider only that one. */
2231 candidate_p = 0;
2233 else if (EQ (all_frames, Qt))
2234 candidate_p = 1;
2235 else if (NILP (all_frames))
2237 eassert (WINDOWP (owindow));
2238 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
2240 else if (EQ (all_frames, Qvisible))
2242 FRAME_SAMPLE_VISIBILITY (f);
2243 candidate_p = FRAME_VISIBLE_P (f)
2244 && (FRAME_TERMINAL (XFRAME (w->frame))
2245 == FRAME_TERMINAL (XFRAME (selected_frame)));
2248 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2250 FRAME_SAMPLE_VISIBILITY (f);
2251 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2252 #ifdef HAVE_X_WINDOWS
2253 /* Yuck!! If we've just created the frame and the
2254 window-manager requested the user to place it
2255 manually, the window may still not be considered
2256 `visible'. I'd argue it should be at least
2257 something like `iconified', but don't know how to do
2258 that yet. --Stef */
2259 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
2260 && !f->output_data.x->has_been_visible)
2261 #endif
2263 && (FRAME_TERMINAL (XFRAME (w->frame))
2264 == FRAME_TERMINAL (XFRAME (selected_frame)));
2266 else if (WINDOWP (all_frames))
2267 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
2268 || EQ (XWINDOW (all_frames)->frame, w->frame)
2269 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
2270 else if (FRAMEP (all_frames))
2271 candidate_p = EQ (all_frames, w->frame);
2273 return candidate_p;
2277 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
2278 Fwindow_list. See candidate_window_p for the meaning of WINDOW,
2279 MINIBUF, and ALL_FRAMES. */
2281 static void
2282 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
2284 struct window *w = decode_live_window (*window);
2286 XSETWINDOW (*window, w);
2287 /* MINIBUF nil may or may not include minibuffers. Decide if it
2288 does. */
2289 if (NILP (*minibuf))
2290 *minibuf = minibuf_level ? minibuf_window : Qlambda;
2291 else if (!EQ (*minibuf, Qt))
2292 *minibuf = Qlambda;
2294 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
2295 => count none of them, or a specific minibuffer window (the
2296 active one) to count. */
2298 /* ALL_FRAMES nil doesn't specify which frames to include. */
2299 if (NILP (*all_frames))
2300 *all_frames
2301 = (!EQ (*minibuf, Qlambda)
2302 ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame))
2303 : Qnil);
2304 else if (EQ (*all_frames, Qvisible))
2306 else if (EQ (*all_frames, make_number (0)))
2308 else if (FRAMEP (*all_frames))
2310 else if (!EQ (*all_frames, Qt))
2311 *all_frames = Qnil;
2315 /* Return the next or previous window of WINDOW in cyclic ordering
2316 of windows. NEXT_P non-zero means return the next window. See the
2317 documentation string of next-window for the meaning of MINIBUF and
2318 ALL_FRAMES. */
2320 static Lisp_Object
2321 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
2323 decode_next_window_args (&window, &minibuf, &all_frames);
2325 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
2326 return the first window on the frame. */
2327 if (FRAMEP (all_frames)
2328 && !EQ (all_frames, XWINDOW (window)->frame))
2329 return Fframe_first_window (all_frames);
2331 if (next_p)
2333 Lisp_Object list;
2335 /* Find WINDOW in the list of all windows. */
2336 list = Fmemq (window, window_list ());
2338 /* Scan forward from WINDOW to the end of the window list. */
2339 if (CONSP (list))
2340 for (list = XCDR (list); CONSP (list); list = XCDR (list))
2341 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2342 break;
2344 /* Scan from the start of the window list up to WINDOW. */
2345 if (!CONSP (list))
2346 for (list = Vwindow_list;
2347 CONSP (list) && !EQ (XCAR (list), window);
2348 list = XCDR (list))
2349 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2350 break;
2352 if (CONSP (list))
2353 window = XCAR (list);
2355 else
2357 Lisp_Object candidate, list;
2359 /* Scan through the list of windows for candidates. If there are
2360 candidate windows in front of WINDOW, the last one of these
2361 is the one we want. If there are candidates following WINDOW
2362 in the list, again the last one of these is the one we want. */
2363 candidate = Qnil;
2364 for (list = window_list (); CONSP (list); list = XCDR (list))
2366 if (EQ (XCAR (list), window))
2368 if (WINDOWP (candidate))
2369 break;
2371 else if (candidate_window_p (XCAR (list), window, minibuf,
2372 all_frames))
2373 candidate = XCAR (list);
2376 if (WINDOWP (candidate))
2377 window = candidate;
2380 return window;
2384 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2385 doc: /* Return live window after WINDOW in the cyclic ordering of windows.
2386 WINDOW must be a live window and defaults to the selected one. The
2387 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2388 consider.
2390 MINIBUF nil or omitted means consider the minibuffer window only if the
2391 minibuffer is active. MINIBUF t means consider the minibuffer window
2392 even if the minibuffer is not active. Any other value means do not
2393 consider the minibuffer window even if the minibuffer is active.
2395 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2396 plus the minibuffer window if specified by the MINIBUF argument. If the
2397 minibuffer counts, consider all windows on all frames that share that
2398 minibuffer too. The following non-nil values of ALL-FRAMES have special
2399 meanings:
2401 - t means consider all windows on all existing frames.
2403 - `visible' means consider all windows on all visible frames.
2405 - 0 (the number zero) means consider all windows on all visible and
2406 iconified frames.
2408 - A frame means consider all windows on that frame only.
2410 Anything else means consider all windows on WINDOW's frame and no
2411 others.
2413 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2414 `next-window' to iterate through the entire cycle of acceptable
2415 windows, eventually ending up back at the window you started with.
2416 `previous-window' traverses the same cycle, in the reverse order. */)
2417 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2419 return next_window (window, minibuf, all_frames, 1);
2423 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2424 doc: /* Return live window before WINDOW in the cyclic ordering of windows.
2425 WINDOW must be a live window and defaults to the selected one. The
2426 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2427 consider.
2429 MINIBUF nil or omitted means consider the minibuffer window only if the
2430 minibuffer is active. MINIBUF t means consider the minibuffer window
2431 even if the minibuffer is not active. Any other value means do not
2432 consider the minibuffer window even if the minibuffer is active.
2434 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2435 plus the minibuffer window if specified by the MINIBUF argument. If the
2436 minibuffer counts, consider all windows on all frames that share that
2437 minibuffer too. The following non-nil values of ALL-FRAMES have special
2438 meanings:
2440 - t means consider all windows on all existing frames.
2442 - `visible' means consider all windows on all visible frames.
2444 - 0 (the number zero) means consider all windows on all visible and
2445 iconified frames.
2447 - A frame means consider all windows on that frame only.
2449 Anything else means consider all windows on WINDOW's frame and no
2450 others.
2452 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2453 use `previous-window' to iterate through the entire cycle of
2454 acceptable windows, eventually ending up back at the window you
2455 started with. `next-window' traverses the same cycle, in the
2456 reverse order. */)
2457 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2459 return next_window (window, minibuf, all_frames, 0);
2463 /* Return a list of windows in cyclic ordering. Arguments are like
2464 for `next-window'. */
2466 static Lisp_Object
2467 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2469 Lisp_Object tail, list, rest;
2471 decode_next_window_args (&window, &minibuf, &all_frames);
2472 list = Qnil;
2474 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2475 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2476 list = Fcons (XCAR (tail), list);
2478 /* Rotate the list to start with WINDOW. */
2479 list = Fnreverse (list);
2480 rest = Fmemq (window, list);
2481 if (!NILP (rest) && !EQ (rest, list))
2483 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2485 XSETCDR (tail, Qnil);
2486 list = nconc2 (rest, list);
2488 return list;
2492 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2493 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2494 FRAME nil or omitted means use the selected frame.
2495 WINDOW nil or omitted means use the window selected within FRAME.
2496 MINIBUF t means include the minibuffer window, even if it isn't active.
2497 MINIBUF nil or omitted means include the minibuffer window only
2498 if it's active.
2499 MINIBUF neither nil nor t means never include the minibuffer window. */)
2500 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2502 if (NILP (window))
2503 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2504 CHECK_WINDOW (window);
2505 if (NILP (frame))
2506 frame = selected_frame;
2508 if (!EQ (frame, XWINDOW (window)->frame))
2509 error ("Window is on a different frame");
2511 return window_list_1 (window, minibuf, frame);
2515 DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2516 doc: /* Return a list of all live windows.
2517 WINDOW specifies the first window to list and defaults to the selected
2518 window.
2520 Optional argument MINIBUF nil or omitted means consider the minibuffer
2521 window only if the minibuffer is active. MINIBUF t means consider the
2522 minibuffer window even if the minibuffer is not active. Any other value
2523 means do not consider the minibuffer window even if the minibuffer is
2524 active.
2526 Optional argument ALL-FRAMES nil or omitted means consider all windows
2527 on WINDOW's frame, plus the minibuffer window if specified by the
2528 MINIBUF argument. If the minibuffer counts, consider all windows on all
2529 frames that share that minibuffer too. The following non-nil values of
2530 ALL-FRAMES have special meanings:
2532 - t means consider all windows on all existing frames.
2534 - `visible' means consider all windows on all visible frames.
2536 - 0 (the number zero) means consider all windows on all visible and
2537 iconified frames.
2539 - A frame means consider all windows on that frame only.
2541 Anything else means consider all windows on WINDOW's frame and no
2542 others.
2544 If WINDOW is not on the list of windows returned, some other window will
2545 be listed first but no error is signaled. */)
2546 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2548 return window_list_1 (window, minibuf, all_frames);
2551 /* Look at all windows, performing an operation specified by TYPE
2552 with argument OBJ.
2553 If FRAMES is Qt, look at all frames;
2554 Qnil, look at just the selected frame;
2555 Qvisible, look at visible frames;
2556 a frame, just look at windows on that frame.
2557 If MINI is non-zero, perform the operation on minibuffer windows too. */
2559 enum window_loop
2561 WINDOW_LOOP_UNUSED,
2562 GET_BUFFER_WINDOW, /* Arg is buffer */
2563 REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
2564 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2565 CHECK_ALL_WINDOWS
2568 static Lisp_Object
2569 window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
2571 Lisp_Object window, windows, best_window, frame_arg;
2572 int frame_best_window_flag = 0;
2573 struct frame *f;
2574 struct gcpro gcpro1;
2576 /* If we're only looping through windows on a particular frame,
2577 frame points to that frame. If we're looping through windows
2578 on all frames, frame is 0. */
2579 if (FRAMEP (frames))
2580 f = XFRAME (frames);
2581 else if (NILP (frames))
2582 f = SELECTED_FRAME ();
2583 else
2584 f = NULL;
2586 if (f)
2587 frame_arg = Qlambda;
2588 else if (EQ (frames, make_number (0)))
2589 frame_arg = frames;
2590 else if (EQ (frames, Qvisible))
2591 frame_arg = frames;
2592 else
2593 frame_arg = Qt;
2595 /* frame_arg is Qlambda to stick to one frame,
2596 Qvisible to consider all visible frames,
2597 or Qt otherwise. */
2599 /* Pick a window to start with. */
2600 if (WINDOWP (obj))
2601 window = obj;
2602 else if (f)
2603 window = FRAME_SELECTED_WINDOW (f);
2604 else
2605 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2607 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2608 GCPRO1 (windows);
2609 best_window = Qnil;
2611 for (; CONSP (windows); windows = XCDR (windows))
2613 struct window *w;
2615 window = XCAR (windows);
2616 w = XWINDOW (window);
2618 /* Note that we do not pay attention here to whether the frame
2619 is visible, since Fwindow_list skips non-visible frames if
2620 that is desired, under the control of frame_arg. */
2621 if (!MINI_WINDOW_P (w)
2622 /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
2623 consider all windows. */
2624 || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
2625 || (mini && minibuf_level > 0))
2626 switch (type)
2628 case GET_BUFFER_WINDOW:
2629 if (EQ (w->buffer, obj)
2630 /* Don't find any minibuffer window except the one that
2631 is currently in use. */
2632 && (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
2634 if (EQ (window, selected_window))
2635 /* Preferably return the selected window. */
2636 RETURN_UNGCPRO (window);
2637 else if (EQ (XWINDOW (window)->frame, selected_frame)
2638 && !frame_best_window_flag)
2639 /* Prefer windows on the current frame (but don't
2640 choose another one if we have one already). */
2642 best_window = window;
2643 frame_best_window_flag = 1;
2645 else if (NILP (best_window))
2646 best_window = window;
2648 break;
2650 case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
2651 /* We could simply check whether the buffer shown by window
2652 is live, and show another buffer in case it isn't. */
2653 if (EQ (w->buffer, obj))
2655 /* Undedicate WINDOW. */
2656 wset_dedicated (w, Qnil);
2657 /* Make WINDOW show the buffer returned by
2658 other_buffer_safely, don't run any hooks. */
2659 set_window_buffer
2660 (window, other_buffer_safely (w->buffer), 0, 0);
2661 /* If WINDOW is the selected window, make its buffer
2662 current. But do so only if the window shows the
2663 current buffer (Bug#6454). */
2664 if (EQ (window, selected_window)
2665 && XBUFFER (w->buffer) == current_buffer)
2666 Fset_buffer (w->buffer);
2668 break;
2670 case REDISPLAY_BUFFER_WINDOWS:
2671 if (EQ (w->buffer, obj))
2673 mark_window_display_accurate (window, 0);
2674 w->update_mode_line = 1;
2675 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2676 ++update_mode_lines;
2677 best_window = window;
2679 break;
2681 /* Check for a window that has a killed buffer. */
2682 case CHECK_ALL_WINDOWS:
2683 if (! NILP (w->buffer)
2684 && !BUFFER_LIVE_P (XBUFFER (w->buffer)))
2685 emacs_abort ();
2686 break;
2688 case WINDOW_LOOP_UNUSED:
2689 break;
2693 UNGCPRO;
2694 return best_window;
2697 /* Used for debugging. Abort if any window has a dead buffer. */
2699 extern void check_all_windows (void) EXTERNALLY_VISIBLE;
2700 void
2701 check_all_windows (void)
2703 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2706 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2707 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2708 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
2709 the current buffer.
2711 The optional argument ALL-FRAMES specifies the frames to consider:
2713 - t means consider all windows on all existing frames.
2715 - `visible' means consider all windows on all visible frames.
2717 - 0 (the number zero) means consider all windows on all visible
2718 and iconified frames.
2720 - A frame means consider all windows on that frame only.
2722 Any other value of ALL-FRAMES means consider all windows on the
2723 selected frame and no others. */)
2724 (Lisp_Object buffer_or_name, Lisp_Object all_frames)
2726 Lisp_Object buffer;
2728 if (NILP (buffer_or_name))
2729 buffer = Fcurrent_buffer ();
2730 else
2731 buffer = Fget_buffer (buffer_or_name);
2733 if (BUFFERP (buffer))
2734 return window_loop (GET_BUFFER_WINDOW, buffer, 1, all_frames);
2735 else
2736 return Qnil;
2739 static Lisp_Object
2740 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore)
2742 return call4 (Qwindow_resize_root_window, window, delta, horizontal, ignore);
2746 DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
2747 Sdelete_other_windows_internal, 0, 2, "",
2748 doc: /* Make WINDOW fill its frame.
2749 Only the frame WINDOW is on is affected. WINDOW must be a valid window
2750 and defaults to the selected one.
2752 Optional argument ROOT, if non-nil, must specify an internal window such
2753 that WINDOW is in its window subtree. If this is the case, replace ROOT
2754 by WINDOW and leave alone any windows not part of ROOT's subtree.
2756 When WINDOW is live try to reduce display jumps by keeping the text
2757 previously visible in WINDOW in the same place on the frame. Doing this
2758 depends on the value of (window-start WINDOW), so if calling this
2759 function in a program gives strange scrolling, make sure the
2760 window-start value is reasonable when this function is called. */)
2761 (Lisp_Object window, Lisp_Object root)
2763 struct window *w, *r, *s;
2764 struct frame *f;
2765 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
2766 ptrdiff_t startpos IF_LINT (= 0);
2767 int top IF_LINT (= 0), new_top, resize_failed;
2769 w = decode_valid_window (window);
2770 XSETWINDOW (window, w);
2771 f = XFRAME (w->frame);
2773 if (NILP (root))
2774 /* ROOT is the frame's root window. */
2776 root = FRAME_ROOT_WINDOW (f);
2777 r = XWINDOW (root);
2779 else
2780 /* ROOT must be an ancestor of WINDOW. */
2782 r = decode_valid_window (root);
2783 pwindow = XWINDOW (window)->parent;
2784 while (!NILP (pwindow))
2785 if (EQ (pwindow, root))
2786 break;
2787 else
2788 pwindow = XWINDOW (pwindow)->parent;
2789 if (!EQ (pwindow, root))
2790 error ("Specified root is not an ancestor of specified window");
2793 if (EQ (window, root))
2794 /* A noop. */
2795 return Qnil;
2796 /* I don't understand the "top > 0" part below. If we deal with a
2797 standalone minibuffer it would have been caught by the preceding
2798 test. */
2799 else if (MINI_WINDOW_P (w)) /* && top > 0) */
2800 error ("Can't expand minibuffer to full frame");
2802 if (!NILP (w->buffer))
2804 startpos = marker_position (w->start);
2805 top = WINDOW_TOP_EDGE_LINE (w)
2806 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2807 /* Make sure WINDOW is the frame's selected window. */
2808 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
2810 if (EQ (selected_frame, w->frame))
2811 Fselect_window (window, Qnil);
2812 else
2813 fset_selected_window (f, window);
2816 else
2818 /* See if the frame's selected window is a part of the window
2819 subtree rooted at WINDOW, by finding all the selected window's
2820 parents and comparing each one with WINDOW. If it isn't we
2821 need a new selected window for this frame. */
2822 swindow = FRAME_SELECTED_WINDOW (f);
2823 while (1)
2825 pwindow = swindow;
2826 while (!NILP (pwindow) && !EQ (window, pwindow))
2827 pwindow = XWINDOW (pwindow)->parent;
2829 if (EQ (window, pwindow))
2830 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
2831 as the new selected window. */
2832 break;
2833 else
2834 /* Else try the previous window of SWINDOW. */
2835 swindow = Fprevious_window (swindow, Qlambda, Qnil);
2838 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
2840 if (EQ (selected_frame, w->frame))
2841 Fselect_window (swindow, Qnil);
2842 else
2843 fset_selected_window (f, swindow);
2847 block_input ();
2848 if (!FRAME_INITIAL_P (f))
2850 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
2852 /* We are going to free the glyph matrices of WINDOW, and with
2853 that we might lose any information about glyph rows that have
2854 some of their glyphs highlighted in mouse face. (These rows
2855 are marked with a non-zero mouse_face_p flag.) If WINDOW
2856 indeed has some glyphs highlighted in mouse face, signal to
2857 frame's up-to-date hook that mouse highlight was overwritten,
2858 so that it will arrange for redisplaying the highlight. */
2859 if (EQ (hlinfo->mouse_face_window, window))
2861 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
2862 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
2863 hlinfo->mouse_face_window = Qnil;
2866 free_window_matrices (r);
2868 windows_or_buffers_changed++;
2869 Vwindow_list = Qnil;
2870 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
2871 resize_failed = 0;
2873 if (NILP (w->buffer))
2875 /* Resize child windows vertically. */
2876 XSETINT (delta, XINT (r->total_lines)
2877 - XINT (w->total_lines));
2878 wset_top_line (w, r->top_line);
2879 resize_root_window (window, delta, Qnil, Qnil);
2880 if (window_resize_check (w, 0))
2881 window_resize_apply (w, 0);
2882 else
2884 resize_root_window (window, delta, Qnil, Qt);
2885 if (window_resize_check (w, 0))
2886 window_resize_apply (w, 0);
2887 else
2888 resize_failed = 1;
2891 /* Resize child windows horizontally. */
2892 if (!resize_failed)
2894 wset_left_col (w, r->left_col);
2895 XSETINT (delta,
2896 XINT (r->total_cols) - XINT (w->total_cols));
2897 wset_left_col (w, r->left_col);
2898 resize_root_window (window, delta, Qt, Qnil);
2899 if (window_resize_check (w, 1))
2900 window_resize_apply (w, 1);
2901 else
2903 resize_root_window (window, delta, Qt, Qt);
2904 if (window_resize_check (w, 1))
2905 window_resize_apply (w, 1);
2906 else
2907 resize_failed = 1;
2911 if (resize_failed)
2912 /* Play safe, if we still can ... */
2914 window = swindow;
2915 w = XWINDOW (window);
2919 /* Cleanly unlink WINDOW from window-tree. */
2920 if (!NILP (w->prev))
2921 /* Get SIBLING above (on the left of) WINDOW. */
2923 sibling = w->prev;
2924 s = XWINDOW (sibling);
2925 wset_next (s, w->next);
2926 if (!NILP (s->next))
2927 wset_prev (XWINDOW (s->next), sibling);
2929 else
2930 /* Get SIBLING below (on the right of) WINDOW. */
2932 sibling = w->next;
2933 s = XWINDOW (sibling);
2934 wset_prev (s, Qnil);
2935 if (!NILP (XWINDOW (w->parent)->vchild))
2936 wset_vchild (XWINDOW (w->parent), sibling);
2937 else
2938 wset_hchild (XWINDOW (w->parent), sibling);
2941 /* Delete ROOT and all child windows of ROOT. */
2942 if (!NILP (r->vchild))
2944 delete_all_child_windows (r->vchild);
2945 wset_vchild (r, Qnil);
2947 else if (!NILP (r->hchild))
2949 delete_all_child_windows (r->hchild);
2950 wset_hchild (r, Qnil);
2953 replace_window (root, window, 1);
2955 /* This must become SWINDOW anyway ....... */
2956 if (!NILP (w->buffer) && !resize_failed)
2958 /* Try to minimize scrolling, by setting the window start to the
2959 point will cause the text at the old window start to be at the
2960 same place on the frame. But don't try to do this if the
2961 window start is outside the visible portion (as might happen
2962 when the display is not current, due to typeahead). */
2963 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2964 if (new_top != top
2965 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2966 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2968 struct position pos;
2969 struct buffer *obuf = current_buffer;
2971 Fset_buffer (w->buffer);
2972 /* This computation used to temporarily move point, but that
2973 can have unwanted side effects due to text properties. */
2974 pos = *vmotion (startpos, -top, w);
2976 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2977 wset_window_end_valid (w, Qnil);
2978 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
2979 || FETCH_BYTE (pos.bytepos - 1) == '\n');
2980 /* We need to do this, so that the window-scroll-functions
2981 get called. */
2982 w->optional_new_start = 1;
2984 set_buffer_internal (obuf);
2988 adjust_glyphs (f);
2989 unblock_input ();
2991 run_window_configuration_change_hook (f);
2993 return Qnil;
2997 void
2998 replace_buffer_in_windows (Lisp_Object buffer)
3000 call1 (Qreplace_buffer_in_windows, buffer);
3003 /* If BUFFER is shown in a window, safely replace it with some other
3004 buffer in all windows of all frames, even those on other keyboards. */
3006 void
3007 replace_buffer_in_windows_safely (Lisp_Object buffer)
3009 if (buffer_window_count (XBUFFER (buffer)))
3011 Lisp_Object tail, frame;
3013 /* A single call to window_loop won't do the job because it only
3014 considers frames on the current keyboard. So loop manually over
3015 frames, and handle each one. */
3016 FOR_EACH_FRAME (tail, frame)
3017 window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
3021 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
3022 minimum allowable size. */
3024 void
3025 check_frame_size (FRAME_PTR frame, int *rows, int *cols)
3027 /* For height, we have to see:
3028 how many windows the frame has at minimum (one or two),
3029 and whether it has a menu bar or other special stuff at the top. */
3030 int min_height
3031 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
3032 ? MIN_SAFE_WINDOW_HEIGHT
3033 : 2 * MIN_SAFE_WINDOW_HEIGHT);
3035 if (FRAME_TOP_MARGIN (frame) > 0)
3036 min_height += FRAME_TOP_MARGIN (frame);
3038 if (*rows < min_height)
3039 *rows = min_height;
3040 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3041 *cols = MIN_SAFE_WINDOW_WIDTH;
3044 /* Adjust the margins of window W if text area is too small.
3045 Return 1 if window width is ok after adjustment; 0 if window
3046 is still too narrow. */
3048 static int
3049 adjust_window_margins (struct window *w)
3051 int box_cols = (WINDOW_TOTAL_COLS (w)
3052 - WINDOW_FRINGE_COLS (w)
3053 - WINDOW_SCROLL_BAR_COLS (w));
3054 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
3055 + WINDOW_RIGHT_MARGIN_COLS (w));
3057 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
3058 return 1;
3060 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
3061 return 0;
3063 /* Window's text area is too narrow, but reducing the window
3064 margins will fix that. */
3065 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
3066 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
3068 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
3070 wset_left_margin_cols (w, make_number (margin_cols / 2));
3071 wset_right_margin_cols (w, make_number (margin_cols / 2));
3073 else
3074 wset_right_margin_cols (w, make_number (margin_cols));
3076 else
3077 wset_left_margin_cols (w, make_number (margin_cols));
3078 return 1;
3081 /* The following three routines are needed for running a window's
3082 configuration change hook. */
3083 static void
3084 run_funs (Lisp_Object funs)
3086 for (; CONSP (funs); funs = XCDR (funs))
3087 if (!EQ (XCAR (funs), Qt))
3088 call0 (XCAR (funs));
3091 static Lisp_Object
3092 select_window_norecord (Lisp_Object window)
3094 return WINDOW_LIVE_P (window)
3095 ? Fselect_window (window, Qt) : selected_window;
3098 static Lisp_Object
3099 select_frame_norecord (Lisp_Object frame)
3101 return FRAME_LIVE_P (XFRAME (frame))
3102 ? Fselect_frame (frame, Qt) : selected_frame;
3105 void
3106 run_window_configuration_change_hook (struct frame *f)
3108 ptrdiff_t count = SPECPDL_INDEX ();
3109 Lisp_Object frame, global_wcch
3110 = Fdefault_value (Qwindow_configuration_change_hook);
3111 XSETFRAME (frame, f);
3113 if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code))
3114 return;
3116 /* Use the right buffer. Matters when running the local hooks. */
3117 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3119 record_unwind_current_buffer ();
3120 Fset_buffer (Fwindow_buffer (Qnil));
3123 if (SELECTED_FRAME () != f)
3125 record_unwind_protect (select_frame_norecord, Fselected_frame ());
3126 select_frame_norecord (frame);
3129 /* Look for buffer-local values. */
3131 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3132 for (; CONSP (windows); windows = XCDR (windows))
3134 Lisp_Object window = XCAR (windows);
3135 Lisp_Object buffer = Fwindow_buffer (window);
3136 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3137 buffer)))
3139 ptrdiff_t inner_count = SPECPDL_INDEX ();
3140 record_unwind_protect (select_window_norecord, Fselected_window ());
3141 select_window_norecord (window);
3142 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3143 buffer));
3144 unbind_to (inner_count, Qnil);
3149 run_funs (global_wcch);
3150 unbind_to (count, Qnil);
3153 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
3154 Srun_window_configuration_change_hook, 0, 1, 0,
3155 doc: /* Run `window-configuration-change-hook' for FRAME.
3156 If FRAME is omitted or nil, it defaults to the selected frame. */)
3157 (Lisp_Object frame)
3159 run_window_configuration_change_hook (decode_live_frame (frame));
3160 return Qnil;
3163 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3164 means it's allowed to run hooks. See make_frame for a case where
3165 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3166 margins, fringes, and scroll-bar settings of the window are not
3167 reset from the buffer's local settings. */
3169 void
3170 set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int keep_margins_p)
3172 struct window *w = XWINDOW (window);
3173 struct buffer *b = XBUFFER (buffer);
3174 ptrdiff_t count = SPECPDL_INDEX ();
3175 int samebuf = EQ (buffer, w->buffer);
3177 wset_buffer (w, buffer);
3179 if (EQ (window, selected_window))
3180 bset_last_selected_window (b, window);
3182 /* Let redisplay errors through. */
3183 b->display_error_modiff = 0;
3185 /* Update time stamps of buffer display. */
3186 if (INTEGERP (BVAR (b, display_count)))
3187 bset_display_count (b, make_number (XINT (BVAR (b, display_count)) + 1));
3188 bset_display_time (b, Fcurrent_time ());
3190 wset_window_end_pos (w, make_number (0));
3191 wset_window_end_vpos (w, make_number (0));
3192 memset (&w->last_cursor, 0, sizeof w->last_cursor);
3193 wset_window_end_valid (w, Qnil);
3194 if (!(keep_margins_p && samebuf))
3195 { /* If we're not actually changing the buffer, don't reset hscroll and
3196 vscroll. This case happens for example when called from
3197 change_frame_size_1, where we use a dummy call to
3198 Fset_window_buffer on the frame's selected window (and no other)
3199 just in order to run window-configuration-change-hook.
3200 Resetting hscroll and vscroll here is problematic for things like
3201 image-mode and doc-view-mode since it resets the image's position
3202 whenever we resize the frame. */
3203 w->hscroll = w->min_hscroll = 0;
3204 w->vscroll = 0;
3205 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3206 set_marker_restricted (w->start,
3207 make_number (b->last_window_start),
3208 buffer);
3209 w->start_at_line_beg = 0;
3210 w->force_start = 0;
3211 w->last_modified = 0;
3212 w->last_overlay_modified = 0;
3214 /* Maybe we could move this into the `if' but it's not obviously safe and
3215 I doubt it's worth the trouble. */
3216 windows_or_buffers_changed++;
3218 /* We must select BUFFER for running the window-scroll-functions. */
3219 /* We can't check ! NILP (Vwindow_scroll_functions) here
3220 because that might itself be a local variable. */
3221 if (window_initialized)
3223 record_unwind_current_buffer ();
3224 Fset_buffer (buffer);
3227 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3229 if (!keep_margins_p)
3231 /* Set left and right marginal area width etc. from buffer. */
3233 /* This may call adjust_window_margins three times, so
3234 temporarily disable window margins. */
3235 Lisp_Object save_left = w->left_margin_cols;
3236 Lisp_Object save_right = w->right_margin_cols;
3238 wset_left_margin_cols (w, Qnil);
3239 wset_right_margin_cols (w, Qnil);
3241 Fset_window_fringes (window,
3242 BVAR (b, left_fringe_width), BVAR (b, right_fringe_width),
3243 BVAR (b, fringes_outside_margins));
3245 Fset_window_scroll_bars (window,
3246 BVAR (b, scroll_bar_width),
3247 BVAR (b, vertical_scroll_bar_type), Qnil);
3249 wset_left_margin_cols (w, save_left);
3250 wset_right_margin_cols (w, save_right);
3252 Fset_window_margins (window,
3253 BVAR (b, left_margin_cols), BVAR (b, right_margin_cols));
3256 if (run_hooks_p)
3258 if (! NILP (Vwindow_scroll_functions))
3259 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3260 Fmarker_position (w->start));
3261 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3264 unbind_to (count, Qnil);
3267 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3268 doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3269 WINDOW must be a live window and defaults to the selected one.
3270 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
3272 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
3273 display margins, fringe widths, and scroll bar settings are preserved;
3274 the default is to reset these from the local settings for BUFFER-OR-NAME
3275 or the frame defaults. Return nil.
3277 This function throws an error when WINDOW is strongly dedicated to its
3278 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3279 already display BUFFER-OR-NAME.
3281 This function runs `window-scroll-functions' before running
3282 `window-configuration-change-hook'. */)
3283 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3285 register Lisp_Object tem, buffer;
3286 register struct window *w = decode_live_window (window);
3288 XSETWINDOW (window, w);
3289 buffer = Fget_buffer (buffer_or_name);
3290 CHECK_BUFFER (buffer);
3291 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3292 error ("Attempt to display deleted buffer");
3294 tem = w->buffer;
3295 if (NILP (tem))
3296 error ("Window is deleted");
3297 else
3299 if (!EQ (tem, buffer))
3301 if (EQ (w->dedicated, Qt))
3302 /* WINDOW is strongly dedicated to its buffer, signal an
3303 error. */
3304 error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
3305 else
3306 /* WINDOW is weakly dedicated to its buffer, reset
3307 dedication. */
3308 wset_dedicated (w, Qnil);
3310 call1 (Qrecord_window_buffer, window);
3313 unshow_buffer (w);
3316 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3318 return Qnil;
3321 static Lisp_Object
3322 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3324 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3327 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3328 0, 1, 0,
3329 doc: /* Force all windows to be updated on next redisplay.
3330 If optional arg OBJECT is a window, force redisplay of that window only.
3331 If OBJECT is a buffer or buffer name, force redisplay of all windows
3332 displaying that buffer. */)
3333 (Lisp_Object object)
3335 if (NILP (object))
3337 windows_or_buffers_changed++;
3338 update_mode_lines++;
3339 return Qt;
3342 if (WINDOWP (object))
3344 struct window *w = XWINDOW (object);
3345 mark_window_display_accurate (object, 0);
3346 w->update_mode_line = 1;
3347 if (BUFFERP (w->buffer))
3348 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3349 ++update_mode_lines;
3350 return Qt;
3353 if (STRINGP (object))
3354 object = Fget_buffer (object);
3355 if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object))
3356 && buffer_window_count (XBUFFER (object)))
3358 /* If buffer is live and shown in at least one window, find
3359 all windows showing this buffer and force update of them. */
3360 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3361 return NILP (object) ? Qnil : Qt;
3364 /* If nothing suitable was found, just return.
3365 We could signal an error, but this feature will typically be used
3366 asynchronously in timers or process sentinels, so we don't. */
3367 return Qnil;
3370 /* Obsolete since 24.3. */
3371 void
3372 temp_output_buffer_show (register Lisp_Object buf)
3374 register struct buffer *old = current_buffer;
3375 register Lisp_Object window;
3376 register struct window *w;
3378 bset_directory (XBUFFER (buf), BVAR (current_buffer, directory));
3380 Fset_buffer (buf);
3381 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3382 BEGV = BEG;
3383 ZV = Z;
3384 SET_PT (BEG);
3385 set_buffer_internal (old);
3387 if (!NILP (Vtemp_buffer_show_function))
3388 call1 (Vtemp_buffer_show_function, buf);
3389 else
3391 window = display_buffer (buf, Qnil, Qnil);
3393 if (!EQ (XWINDOW (window)->frame, selected_frame))
3394 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3395 Vminibuf_scroll_window = window;
3396 w = XWINDOW (window);
3397 w->hscroll = 0;
3398 w->min_hscroll = 0;
3399 set_marker_restricted_both (w->start, buf, BEG, BEG);
3400 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3402 /* Run temp-buffer-show-hook, with the chosen window selected
3403 and its buffer current. */
3405 ptrdiff_t count = SPECPDL_INDEX ();
3406 Lisp_Object prev_window, prev_buffer;
3407 prev_window = selected_window;
3408 XSETBUFFER (prev_buffer, old);
3410 /* Select the window that was chosen, for running the hook.
3411 Note: Both Fselect_window and select_window_norecord may
3412 set-buffer to the buffer displayed in the window,
3413 so we need to save the current buffer. --stef */
3414 record_unwind_protect (Fset_buffer, prev_buffer);
3415 record_unwind_protect (select_window_norecord, prev_window);
3416 Fselect_window (window, Qt);
3417 Fset_buffer (w->buffer);
3418 Frun_hooks (1, &Qtemp_buffer_show_hook);
3419 unbind_to (count, Qnil);
3424 /* Make new window, have it replace WINDOW in window-tree, and make
3425 WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
3426 horizontal child). */
3427 static void
3428 make_parent_window (Lisp_Object window, int horflag)
3430 Lisp_Object parent;
3431 register struct window *o, *p;
3433 o = XWINDOW (window);
3434 p = allocate_window ();
3435 memcpy ((char *) p + sizeof (struct vectorlike_header),
3436 (char *) o + sizeof (struct vectorlike_header),
3437 word_size * VECSIZE (struct window));
3438 /* P's buffer slot may change from nil to a buffer. */
3439 adjust_window_count (p, 1);
3440 XSETWINDOW (parent, p);
3442 p->sequence_number = ++sequence_number;
3444 replace_window (window, parent, 1);
3446 wset_next (o, Qnil);
3447 wset_prev (o, Qnil);
3448 wset_parent (o, parent);
3450 wset_hchild (p, horflag ? window : Qnil);
3451 wset_vchild (p, horflag ? Qnil : window);
3452 wset_start (p, Qnil);
3453 wset_pointm (p, Qnil);
3454 wset_buffer (p, Qnil);
3455 wset_combination_limit (p, Qnil);
3456 wset_window_parameters (p, Qnil);
3459 /* Make new window from scratch. */
3460 Lisp_Object
3461 make_window (void)
3463 Lisp_Object window;
3464 register struct window *w;
3466 w = allocate_window ();
3467 /* Initialize Lisp data. Note that allocate_window initializes all
3468 Lisp data to nil, so do it only for slots which should not be nil. */
3469 wset_left_col (w, make_number (0));
3470 wset_top_line (w, make_number (0));
3471 wset_total_lines (w, make_number (0));
3472 wset_total_cols (w, make_number (0));
3473 wset_normal_lines (w, make_float (1.0));
3474 wset_normal_cols (w, make_float (1.0));
3475 wset_new_total (w, make_number (0));
3476 wset_new_normal (w, make_number (0));
3477 wset_start (w, Fmake_marker ());
3478 wset_pointm (w, Fmake_marker ());
3479 wset_vertical_scroll_bar_type (w, Qt);
3480 wset_window_end_pos (w, make_number (0));
3481 wset_window_end_vpos (w, make_number (0));
3482 /* These Lisp fields are marked specially so they're not set to nil by
3483 allocate_window. */
3484 wset_prev_buffers (w, Qnil);
3485 wset_next_buffers (w, Qnil);
3487 /* Initialize non-Lisp data. Note that allocate_window zeroes out all
3488 non-Lisp data, so do it only for slots which should not be zero. */
3489 w->nrows_scale_factor = w->ncols_scale_factor = 1;
3490 w->phys_cursor_type = -1;
3491 w->phys_cursor_width = -1;
3492 w->sequence_number = ++sequence_number;
3494 /* Reset window_list. */
3495 Vwindow_list = Qnil;
3496 /* Return window. */
3497 XSETWINDOW (window, w);
3498 return window;
3501 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
3502 doc: /* Set new total size of WINDOW to SIZE.
3503 WINDOW must be a valid window and defaults to the selected one.
3504 Return SIZE.
3506 Optional argument ADD non-nil means add SIZE to the new total size of
3507 WINDOW and return the sum.
3509 Note: This function does not operate on any child windows of WINDOW. */)
3510 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3512 struct window *w = decode_valid_window (window);
3514 CHECK_NUMBER (size);
3515 if (NILP (add))
3516 wset_new_total (w, size);
3517 else
3518 wset_new_total (w, make_number (XINT (w->new_total) + XINT (size)));
3520 return w->new_total;
3523 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
3524 doc: /* Set new normal size of WINDOW to SIZE.
3525 WINDOW must be a valid window and defaults to the selected one.
3526 Return SIZE.
3528 Note: This function does not operate on any child windows of WINDOW. */)
3529 (Lisp_Object window, Lisp_Object size)
3531 wset_new_normal (decode_valid_window (window), size);
3532 return size;
3535 /* Return 1 if setting w->total_lines (w->total_cols if HORFLAG is
3536 non-zero) to w->new_total would result in correct heights (widths)
3537 for window W and recursively all child windows of W.
3539 Note: This function does not check any of `window-fixed-size-p',
3540 `window-min-height' or `window-min-width'. It does check that window
3541 sizes do not drop below one line (two columns). */
3542 static int
3543 window_resize_check (struct window *w, int horflag)
3545 struct window *c;
3547 if (!NILP (w->vchild))
3548 /* W is a vertical combination. */
3550 c = XWINDOW (w->vchild);
3551 if (horflag)
3552 /* All child windows of W must have the same width as W. */
3554 while (c)
3556 if ((XINT (c->new_total) != XINT (w->new_total))
3557 || !window_resize_check (c, horflag))
3558 return 0;
3559 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3561 return 1;
3563 else
3564 /* The sum of the heights of the child windows of W must equal
3565 W's height. */
3567 int sum_of_sizes = 0;
3568 while (c)
3570 if (!window_resize_check (c, horflag))
3571 return 0;
3572 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3573 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3575 return (sum_of_sizes == XINT (w->new_total));
3578 else if (!NILP (w->hchild))
3579 /* W is a horizontal combination. */
3581 c = XWINDOW (w->hchild);
3582 if (horflag)
3583 /* The sum of the widths of the child windows of W must equal W's
3584 width. */
3586 int sum_of_sizes = 0;
3587 while (c)
3589 if (!window_resize_check (c, horflag))
3590 return 0;
3591 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3592 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3594 return (sum_of_sizes == XINT (w->new_total));
3596 else
3597 /* All child windows of W must have the same height as W. */
3599 while (c)
3601 if ((XINT (c->new_total) != XINT (w->new_total))
3602 || !window_resize_check (c, horflag))
3603 return 0;
3604 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3606 return 1;
3609 else
3610 /* A leaf window. Make sure it's not too small. The following
3611 hardcodes the values of `window-safe-min-width' (2) and
3612 `window-safe-min-height' (1) which are defined in window.el. */
3613 return XINT (w->new_total) >= (horflag ? 2 : 1);
3616 /* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
3617 w->new_total for window W and recursively all child windows of W.
3618 Also calculate and assign the new vertical (horizontal) start
3619 positions of each of these windows.
3621 This function does not perform any error checks. Make sure you have
3622 run window_resize_check on W before applying this function. */
3623 static void
3624 window_resize_apply (struct window *w, int horflag)
3626 struct window *c;
3627 int pos;
3629 /* Note: Assigning new_normal requires that the new total size of the
3630 parent window has been set *before*. */
3631 if (horflag)
3633 wset_total_cols (w, w->new_total);
3634 if (NUMBERP (w->new_normal))
3635 wset_normal_cols (w, w->new_normal);
3637 pos = XINT (w->left_col);
3639 else
3641 wset_total_lines (w, w->new_total);
3642 if (NUMBERP (w->new_normal))
3643 wset_normal_lines (w, w->new_normal);
3645 pos = XINT (w->top_line);
3648 if (!NILP (w->vchild))
3649 /* W is a vertical combination. */
3651 c = XWINDOW (w->vchild);
3652 while (c)
3654 if (horflag)
3655 wset_left_col (c, make_number (pos));
3656 else
3657 wset_top_line (c, make_number (pos));
3658 window_resize_apply (c, horflag);
3659 if (!horflag)
3660 pos = pos + XINT (c->total_lines);
3661 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3664 else if (!NILP (w->hchild))
3665 /* W is a horizontal combination. */
3667 c = XWINDOW (w->hchild);
3668 while (c)
3670 if (horflag)
3671 wset_left_col (c, make_number (pos));
3672 else
3673 wset_top_line (c, make_number (pos));
3674 window_resize_apply (c, horflag);
3675 if (horflag)
3676 pos = pos + XINT (c->total_cols);
3677 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3681 /* Clear out some redisplay caches. */
3682 w->last_modified = 0;
3683 w->last_overlay_modified = 0;
3687 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 0, 2, 0,
3688 doc: /* Apply requested size values for window-tree of FRAME.
3689 If FRAME is omitted or nil, it defaults to the selected frame.
3691 Optional argument HORIZONTAL omitted or nil means apply requested
3692 height values. HORIZONTAL non-nil means apply requested width values.
3694 This function checks whether the requested values sum up to a valid
3695 window layout, recursively assigns the new sizes of all child windows
3696 and calculates and assigns the new start positions of these windows.
3698 Note: This function does not check any of `window-fixed-size-p',
3699 `window-min-height' or `window-min-width'. All these checks have to
3700 be applied on the Elisp level. */)
3701 (Lisp_Object frame, Lisp_Object horizontal)
3703 struct frame *f = decode_live_frame (frame);
3704 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
3705 int horflag = !NILP (horizontal);
3707 if (!window_resize_check (r, horflag)
3708 || ! EQ (r->new_total,
3709 (horflag ? r->total_cols : r->total_lines)))
3710 return Qnil;
3712 block_input ();
3713 window_resize_apply (r, horflag);
3715 windows_or_buffers_changed++;
3716 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3718 adjust_glyphs (f);
3719 unblock_input ();
3721 run_window_configuration_change_hook (f);
3723 return Qt;
3727 /* Resize frame F's windows when number of lines of F is set to SIZE.
3728 HORFLAG 1 means resize windows when number of columns of F is set to
3729 SIZE.
3731 This function can delete all windows but the selected one in order to
3732 satisfy the request. The result will be meaningful if and only if
3733 F's windows have meaningful sizes when you call this. */
3734 void
3735 resize_frame_windows (struct frame *f, int size, int horflag)
3737 Lisp_Object root = f->root_window;
3738 struct window *r = XWINDOW (root);
3739 Lisp_Object mini = f->minibuffer_window;
3740 struct window *m;
3741 /* new_size is the new size of the frame's root window. */
3742 int new_size = (horflag
3743 ? size
3744 : (size
3745 - FRAME_TOP_MARGIN (f)
3746 - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3747 ? 1 : 0)));
3749 wset_top_line (r, make_number (FRAME_TOP_MARGIN (f)));
3750 if (NILP (r->vchild) && NILP (r->hchild))
3751 /* For a leaf root window just set the size. */
3752 if (horflag)
3753 wset_total_cols (r, make_number (new_size));
3754 else
3755 wset_total_lines (r, make_number (new_size));
3756 else
3758 /* old_size is the old size of the frame's root window. */
3759 int old_size = XFASTINT (horflag ? r->total_cols
3760 : r->total_lines);
3761 Lisp_Object delta;
3763 XSETINT (delta, new_size - old_size);
3764 /* Try a "normal" resize first. */
3765 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil);
3766 if (window_resize_check (r, horflag)
3767 && new_size == XINT (r->new_total))
3768 window_resize_apply (r, horflag);
3769 else
3771 /* Try with "reasonable" minimum sizes next. */
3772 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt);
3773 if (window_resize_check (r, horflag)
3774 && new_size == XINT (r->new_total))
3775 window_resize_apply (r, horflag);
3776 else
3778 /* Finally, try with "safe" minimum sizes. */
3779 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe);
3780 if (window_resize_check (r, horflag)
3781 && new_size == XINT (r->new_total))
3782 window_resize_apply (r, horflag);
3783 else
3785 /* We lost. Delete all windows but the frame's
3786 selected one. */
3787 root = f->selected_window;
3788 Fdelete_other_windows_internal (root, Qnil);
3789 if (horflag)
3790 wset_total_cols (XWINDOW (root), make_number (new_size));
3791 else
3792 wset_total_lines (XWINDOW (root), make_number (new_size));
3798 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3800 m = XWINDOW (mini);
3801 if (horflag)
3802 wset_total_cols (m, make_number (size));
3803 else
3805 /* Are we sure we always want 1 line here? */
3806 wset_total_lines (m, make_number (1));
3807 wset_top_line
3808 (m, make_number (XINT (r->top_line) + XINT (r->total_lines)));
3812 windows_or_buffers_changed++;
3816 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
3817 doc: /* Split window OLD.
3818 Second argument TOTAL-SIZE specifies the number of lines or columns of the
3819 new window. In any case TOTAL-SIZE must be a positive integer.
3821 Third argument SIDE nil (or `below') specifies that the new window shall
3822 be located below WINDOW. SIDE `above' means the new window shall be
3823 located above WINDOW. In both cases TOTAL-SIZE specifies the number of
3824 lines of the new window including space reserved for the mode and/or
3825 header line.
3827 SIDE t (or `right') specifies that the new window shall be located on
3828 the right side of WINDOW. SIDE `left' means the new window shall be
3829 located on the left of WINDOW. In both cases TOTAL-SIZE specifies the
3830 number of columns of the new window including space reserved for fringes
3831 and the scrollbar or a divider column.
3833 Fourth argument NORMAL-SIZE specifies the normal size of the new window
3834 according to the SIDE argument.
3836 The new total and normal sizes of all involved windows must have been
3837 set correctly. See the code of `split-window' for how this is done. */)
3838 (Lisp_Object old, Lisp_Object total_size, Lisp_Object side, Lisp_Object normal_size)
3840 /* OLD (*o) is the window we have to split. (*p) is either OLD's
3841 parent window or an internal window we have to install as OLD's new
3842 parent. REFERENCE (*r) must denote a live window, or is set to OLD
3843 provided OLD is a leaf window, or to the frame's selected window.
3844 NEW (*n) is the new window created with some parameters taken from
3845 REFERENCE (*r). */
3846 register Lisp_Object new, frame, reference;
3847 register struct window *o, *p, *n, *r;
3848 struct frame *f;
3849 int horflag
3850 /* HORFLAG is 1 when we split side-by-side, 0 otherwise. */
3851 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
3852 int combination_limit = 0;
3854 CHECK_WINDOW (old);
3855 o = XWINDOW (old);
3856 frame = WINDOW_FRAME (o);
3857 f = XFRAME (frame);
3859 CHECK_NUMBER (total_size);
3861 /* Set combination_limit to 1 if we have to make a new parent window.
3862 We do that if either `window-combination-limit' is t, or OLD has no
3863 parent, or OLD is ortho-combined. */
3864 combination_limit =
3865 EQ (Vwindow_combination_limit, Qt)
3866 || NILP (o->parent)
3867 || NILP (horflag
3868 ? (XWINDOW (o->parent)->hchild)
3869 : (XWINDOW (o->parent)->vchild));
3871 /* We need a live reference window to initialize some parameters. */
3872 if (WINDOW_LIVE_P (old))
3873 /* OLD is live, use it as reference window. */
3874 reference = old;
3875 else
3876 /* Use the frame's selected window as reference window. */
3877 reference = FRAME_SELECTED_WINDOW (f);
3878 r = XWINDOW (reference);
3880 /* The following bugs are caught by `split-window'. */
3881 if (MINI_WINDOW_P (o))
3882 error ("Attempt to split minibuffer window");
3883 else if (XINT (total_size) < (horflag ? 2 : 1))
3884 error ("Size of new window too small (after split)");
3885 else if (!combination_limit && !NILP (Vwindow_combination_resize))
3886 /* `window-combination-resize' non-nil means try to resize OLD's siblings
3887 proportionally. */
3889 p = XWINDOW (o->parent);
3890 /* Temporarily pretend we split the parent window. */
3891 wset_new_total
3892 (p, make_number (XINT (horflag ? p->total_cols : p->total_lines)
3893 - XINT (total_size)));
3894 if (!window_resize_check (p, horflag))
3895 error ("Window sizes don't fit");
3896 else
3897 /* Undo the temporary pretension. */
3898 wset_new_total (p, horflag ? p->total_cols : p->total_lines);
3900 else
3902 if (!window_resize_check (o, horflag))
3903 error ("Resizing old window failed");
3904 else if (XINT (total_size) + XINT (o->new_total)
3905 != XINT (horflag ? o->total_cols : o->total_lines))
3906 error ("Sum of sizes of old and new window don't fit");
3909 /* This is our point of no return. */
3910 if (combination_limit)
3912 /* Save the old value of o->normal_cols/lines. It gets corrupted
3913 by make_parent_window and we need it below for assigning it to
3914 p->new_normal. */
3915 Lisp_Object new_normal
3916 = horflag ? o->normal_cols : o->normal_lines;
3918 make_parent_window (old, horflag);
3919 p = XWINDOW (o->parent);
3920 if (EQ (Vwindow_combination_limit, Qt))
3921 /* Store t in the new parent's combination_limit slot to avoid
3922 that its children get merged into another window. */
3923 wset_combination_limit (p, Qt);
3924 /* These get applied below. */
3925 wset_new_total (p, horflag ? o->total_cols : o->total_lines);
3926 wset_new_normal (p, new_normal);
3928 else
3929 p = XWINDOW (o->parent);
3931 windows_or_buffers_changed++;
3932 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3933 new = make_window ();
3934 n = XWINDOW (new);
3935 wset_frame (n, frame);
3936 wset_parent (n, o->parent);
3937 wset_vchild (n, Qnil);
3938 wset_hchild (n, Qnil);
3940 if (EQ (side, Qabove) || EQ (side, Qleft))
3942 wset_prev (n, o->prev);
3943 if (NILP (n->prev))
3944 if (horflag)
3945 wset_hchild (p, new);
3946 else
3947 wset_vchild (p, new);
3948 else
3949 wset_next (XWINDOW (n->prev), new);
3950 wset_next (n, old);
3951 wset_prev (o, new);
3953 else
3955 wset_next (n, o->next);
3956 if (!NILP (n->next))
3957 wset_prev (XWINDOW (n->next), new);
3958 wset_prev (n, old);
3959 wset_next (o, new);
3962 wset_window_end_valid (n, Qnil);
3963 memset (&n->last_cursor, 0, sizeof n->last_cursor);
3965 /* Get special geometry settings from reference window. */
3966 wset_left_margin_cols (n, r->left_margin_cols);
3967 wset_right_margin_cols (n, r->right_margin_cols);
3968 wset_left_fringe_width (n, r->left_fringe_width);
3969 wset_right_fringe_width (n, r->right_fringe_width);
3970 n->fringes_outside_margins = r->fringes_outside_margins;
3971 wset_scroll_bar_width (n, r->scroll_bar_width);
3972 wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
3974 /* Directly assign orthogonal coordinates and sizes. */
3975 if (horflag)
3977 wset_top_line (n, o->top_line);
3978 wset_total_lines (n, o->total_lines);
3980 else
3982 wset_left_col (n, o->left_col);
3983 wset_total_cols (n, o->total_cols);
3986 /* Iso-coordinates and sizes are assigned by window_resize_apply,
3987 get them ready here. */
3988 wset_new_total (n, total_size);
3989 wset_new_normal (n, normal_size);
3991 block_input ();
3992 window_resize_apply (p, horflag);
3993 adjust_glyphs (f);
3994 /* Set buffer of NEW to buffer of reference window. Don't run
3995 any hooks. */
3996 set_window_buffer (new, r->buffer, 0, 1);
3997 unblock_input ();
3999 /* Maybe we should run the scroll functions in Elisp (which already
4000 runs the configuration change hook). */
4001 if (! NILP (Vwindow_scroll_functions))
4002 run_hook_with_args_2 (Qwindow_scroll_functions, new,
4003 Fmarker_position (n->start));
4004 /* Return NEW. */
4005 return new;
4009 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
4010 doc: /* Remove WINDOW from its frame.
4011 WINDOW defaults to the selected window. Return nil.
4012 Signal an error when WINDOW is the only window on its frame. */)
4013 (register Lisp_Object window)
4015 register Lisp_Object parent, sibling, frame, root;
4016 struct window *w, *p, *s, *r;
4017 struct frame *f;
4018 int horflag;
4019 int before_sibling = 0;
4021 w = decode_any_window (window);
4022 XSETWINDOW (window, w);
4023 if (NILP (w->buffer)
4024 && NILP (w->hchild) && NILP (w->vchild))
4025 /* It's a no-op to delete an already deleted window. */
4026 return Qnil;
4028 parent = w->parent;
4029 if (NILP (parent))
4030 /* Never delete a minibuffer or frame root window. */
4031 error ("Attempt to delete minibuffer or sole ordinary window");
4032 else if (NILP (w->prev) && NILP (w->next))
4033 /* Rather bow out here, this case should be handled on the Elisp
4034 level. */
4035 error ("Attempt to delete sole window of parent");
4037 p = XWINDOW (parent);
4038 horflag = NILP (p->vchild);
4040 frame = WINDOW_FRAME (w);
4041 f = XFRAME (frame);
4043 root = FRAME_ROOT_WINDOW (f);
4044 r = XWINDOW (root);
4046 /* Unlink WINDOW from window tree. */
4047 if (NILP (w->prev))
4048 /* Get SIBLING below (on the right of) WINDOW. */
4050 /* before_sibling 1 means WINDOW is the first child of its
4051 parent and thus before the sibling. */
4052 before_sibling = 1;
4053 sibling = w->next;
4054 s = XWINDOW (sibling);
4055 wset_prev (s, Qnil);
4056 if (horflag)
4057 wset_hchild (p, sibling);
4058 else
4059 wset_vchild (p, sibling);
4061 else
4062 /* Get SIBLING above (on the left of) WINDOW. */
4064 sibling = w->prev;
4065 s = XWINDOW (sibling);
4066 wset_next (s, w->next);
4067 if (!NILP (s->next))
4068 wset_prev (XWINDOW (s->next), sibling);
4071 if (window_resize_check (r, horflag)
4072 && EQ (r->new_total,
4073 (horflag ? r->total_cols : r->total_lines)))
4074 /* We can delete WINDOW now. */
4077 /* Block input. */
4078 block_input ();
4079 #ifdef HAVE_XWIDGETS
4080 xwidget_view_delete_all_in_window(w);
4081 #endif
4082 window_resize_apply (p, horflag);
4084 /* If this window is referred to by the dpyinfo's mouse
4085 highlight, invalidate that slot to be safe (Bug#9904). */
4086 if (!FRAME_INITIAL_P (f))
4088 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
4090 if (EQ (hlinfo->mouse_face_window, window))
4091 hlinfo->mouse_face_window = Qnil;
4094 windows_or_buffers_changed++;
4095 Vwindow_list = Qnil;
4096 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4098 wset_next (w, Qnil); /* Don't delete w->next too. */
4099 free_window_matrices (w);
4101 if (!NILP (w->vchild))
4103 delete_all_child_windows (w->vchild);
4104 wset_vchild (w, Qnil);
4106 else if (!NILP (w->hchild))
4108 delete_all_child_windows (w->hchild);
4109 wset_hchild (w, Qnil);
4111 else if (!NILP (w->buffer))
4113 unshow_buffer (w);
4114 unchain_marker (XMARKER (w->pointm));
4115 unchain_marker (XMARKER (w->start));
4116 wset_buffer (w, Qnil);
4119 if (NILP (s->prev) && NILP (s->next))
4120 /* A matrjoshka where SIBLING has become the only child of
4121 PARENT. */
4123 /* Put SIBLING into PARENT's place. */
4124 replace_window (parent, sibling, 0);
4125 /* Have SIBLING inherit the following three slot values from
4126 PARENT (the combination_limit slot is not inherited). */
4127 wset_normal_cols (s, p->normal_cols);
4128 wset_normal_lines (s, p->normal_lines);
4129 /* Mark PARENT as deleted. */
4130 wset_vchild (p, Qnil);
4131 wset_hchild (p, Qnil);
4132 /* Try to merge SIBLING into its new parent. */
4133 recombine_windows (sibling);
4136 adjust_glyphs (f);
4138 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
4139 /* We deleted the frame's selected window. */
4141 /* Use the frame's first window as fallback ... */
4142 Lisp_Object new_selected_window = Fframe_first_window (frame);
4143 /* ... but preferably use its most recently used window. */
4144 Lisp_Object mru_window;
4146 /* `get-mru-window' might fail for some reason so play it safe
4147 - promote the first window _without recording it_ first. */
4148 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4149 Fselect_window (new_selected_window, Qt);
4150 else
4151 fset_selected_window (f, new_selected_window);
4153 unblock_input ();
4155 /* Now look whether `get-mru-window' gets us something. */
4156 mru_window = call1 (Qget_mru_window, frame);
4157 if (WINDOW_LIVE_P (mru_window)
4158 && EQ (XWINDOW (mru_window)->frame, frame))
4159 new_selected_window = mru_window;
4161 /* If all ended up well, we now promote the mru window. */
4162 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4163 Fselect_window (new_selected_window, Qnil);
4164 else
4165 fset_selected_window (f, new_selected_window);
4167 else
4168 unblock_input ();
4170 /* Must be run by the caller:
4171 run_window_configuration_change_hook (f); */
4173 else
4174 /* We failed: Relink WINDOW into window tree. */
4176 if (before_sibling)
4178 wset_prev (s, window);
4179 if (horflag)
4180 wset_hchild (p, window);
4181 else
4182 wset_vchild (p, window);
4184 else
4186 wset_next (s, window);
4187 if (!NILP (w->next))
4188 wset_prev (XWINDOW (w->next), window);
4190 error ("Deletion failed");
4193 return Qnil;
4196 /***********************************************************************
4197 Resizing Mini-Windows
4198 ***********************************************************************/
4200 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
4201 can. */
4202 void
4203 grow_mini_window (struct window *w, int delta)
4205 struct frame *f = XFRAME (w->frame);
4206 struct window *r;
4207 Lisp_Object root, value;
4209 eassert (MINI_WINDOW_P (w));
4210 eassert (delta >= 0);
4212 root = FRAME_ROOT_WINDOW (f);
4213 r = XWINDOW (root);
4214 value = call2 (Qwindow_resize_root_window_vertically,
4215 root, make_number (- delta));
4216 if (INTEGERP (value) && window_resize_check (r, 0))
4218 block_input ();
4219 window_resize_apply (r, 0);
4221 /* Grow the mini-window. */
4222 wset_top_line
4223 (w, make_number (XFASTINT (r->top_line) + XFASTINT (r->total_lines)));
4224 wset_total_lines
4225 (w, make_number (XFASTINT (w->total_lines) - XINT (value)));
4226 w->last_modified = 0;
4227 w->last_overlay_modified = 0;
4229 windows_or_buffers_changed++;
4230 adjust_glyphs (f);
4231 unblock_input ();
4236 /* Shrink mini-window W. */
4237 void
4238 shrink_mini_window (struct window *w)
4240 struct frame *f = XFRAME (w->frame);
4241 struct window *r;
4242 Lisp_Object root, value;
4243 EMACS_INT size;
4245 eassert (MINI_WINDOW_P (w));
4247 size = XINT (w->total_lines);
4248 if (size > 1)
4250 root = FRAME_ROOT_WINDOW (f);
4251 r = XWINDOW (root);
4252 value = call2 (Qwindow_resize_root_window_vertically,
4253 root, make_number (size - 1));
4254 if (INTEGERP (value) && window_resize_check (r, 0))
4256 block_input ();
4257 window_resize_apply (r, 0);
4259 /* Shrink the mini-window. */
4260 wset_top_line (w, make_number (XFASTINT (r->top_line)
4261 + XFASTINT (r->total_lines)));
4262 wset_total_lines (w, make_number (1));
4264 w->last_modified = 0;
4265 w->last_overlay_modified = 0;
4267 windows_or_buffers_changed++;
4268 adjust_glyphs (f);
4269 unblock_input ();
4271 /* If the above failed for whatever strange reason we must make a
4272 one window frame here. The same routine will be needed when
4273 shrinking the frame (and probably when making the initial
4274 *scratch* window). For the moment leave things as they are. */
4278 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
4279 doc: /* Resize minibuffer window WINDOW. */)
4280 (Lisp_Object window)
4282 struct window *w = XWINDOW (window);
4283 struct window *r;
4284 struct frame *f;
4285 int height;
4287 CHECK_WINDOW (window);
4288 f = XFRAME (w->frame);
4290 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
4291 error ("Not a valid minibuffer window");
4292 else if (FRAME_MINIBUF_ONLY_P (f))
4293 error ("Cannot resize a minibuffer-only frame");
4295 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4296 height = XINT (r->total_lines) + XINT (w->total_lines);
4297 if (window_resize_check (r, 0)
4298 && XINT (w->new_total) > 0
4299 && height == XINT (r->new_total) + XINT (w->new_total))
4301 block_input ();
4302 window_resize_apply (r, 0);
4304 wset_total_lines (w, w->new_total);
4305 wset_top_line (w, make_number (XINT (r->top_line)
4306 + XINT (r->total_lines)));
4308 windows_or_buffers_changed++;
4309 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4310 adjust_glyphs (f);
4311 unblock_input ();
4313 run_window_configuration_change_hook (f);
4314 return Qt;
4316 else error ("Failed to resize minibuffer window");
4319 /* Mark window cursors off for all windows in the window tree rooted
4320 at W by setting their phys_cursor_on_p flag to zero. Called from
4321 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4322 the frame are cleared. */
4324 void
4325 mark_window_cursors_off (struct window *w)
4327 while (w)
4329 if (!NILP (w->hchild))
4330 mark_window_cursors_off (XWINDOW (w->hchild));
4331 else if (!NILP (w->vchild))
4332 mark_window_cursors_off (XWINDOW (w->vchild));
4333 else
4334 w->phys_cursor_on_p = 0;
4336 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4341 /* Return number of lines of text (not counting mode lines) in W. */
4344 window_internal_height (struct window *w)
4346 int ht = XFASTINT (w->total_lines);
4348 if (!MINI_WINDOW_P (w))
4350 if (!NILP (w->parent)
4351 || !NILP (w->vchild)
4352 || !NILP (w->hchild)
4353 || !NILP (w->next)
4354 || !NILP (w->prev)
4355 || WINDOW_WANTS_MODELINE_P (w))
4356 --ht;
4358 if (WINDOW_WANTS_HEADER_LINE_P (w))
4359 --ht;
4362 return ht;
4365 /************************************************************************
4366 Window Scrolling
4367 ***********************************************************************/
4369 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4370 N screen-fulls, which is defined as the height of the window minus
4371 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4372 instead. Negative values of N mean scroll down. NOERROR non-zero
4373 means don't signal an error if we try to move over BEGV or ZV,
4374 respectively. */
4376 static void
4377 window_scroll (Lisp_Object window, EMACS_INT n, int whole, int noerror)
4379 immediate_quit = 1;
4380 n = clip_to_bounds (INT_MIN, n, INT_MAX);
4382 /* If we must, use the pixel-based version which is much slower than
4383 the line-based one but can handle varying line heights. */
4384 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4385 window_scroll_pixel_based (window, n, whole, noerror);
4386 else
4387 window_scroll_line_based (window, n, whole, noerror);
4389 immediate_quit = 0;
4393 /* Implementation of window_scroll that works based on pixel line
4394 heights. See the comment of window_scroll for parameter
4395 descriptions. */
4397 static void
4398 window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4400 struct it it;
4401 struct window *w = XWINDOW (window);
4402 struct text_pos start;
4403 int this_scroll_margin;
4404 /* True if we fiddled the window vscroll field without really scrolling. */
4405 int vscrolled = 0;
4406 int x, y, rtop, rbot, rowh, vpos;
4407 void *itdata = NULL;
4409 SET_TEXT_POS_FROM_MARKER (start, w->start);
4410 /* Scrolling a minibuffer window via scroll bar when the echo area
4411 shows long text sometimes resets the minibuffer contents behind
4412 our backs. */
4413 if (CHARPOS (start) > ZV)
4414 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4416 /* If PT is not visible in WINDOW, move back one half of
4417 the screen. Allow PT to be partially visible, otherwise
4418 something like (scroll-down 1) with PT in the line before
4419 the partially visible one would recenter. */
4421 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4423 itdata = bidi_shelve_cache ();
4424 /* Move backward half the height of the window. Performance note:
4425 vmotion used here is about 10% faster, but would give wrong
4426 results for variable height lines. */
4427 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4428 it.current_y = it.last_visible_y;
4429 move_it_vertically_backward (&it, window_box_height (w) / 2);
4431 /* The function move_iterator_vertically may move over more than
4432 the specified y-distance. If it->w is small, e.g. a
4433 mini-buffer window, we may end up in front of the window's
4434 display area. This is the case when Start displaying at the
4435 start of the line containing PT in this case. */
4436 if (it.current_y <= 0)
4438 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4439 move_it_vertically_backward (&it, 0);
4440 it.current_y = 0;
4443 start = it.current.pos;
4444 bidi_unshelve_cache (itdata, 0);
4446 else if (auto_window_vscroll_p)
4448 if (rtop || rbot) /* partially visible */
4450 int px;
4451 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4452 if (whole)
4453 dy = max ((window_box_height (w)
4454 - next_screen_context_lines * dy),
4455 dy);
4456 dy *= n;
4458 if (n < 0)
4460 /* Only vscroll backwards if already vscrolled forwards. */
4461 if (w->vscroll < 0 && rtop > 0)
4463 px = max (0, -w->vscroll - min (rtop, -dy));
4464 Fset_window_vscroll (window, make_number (px), Qt);
4465 return;
4468 if (n > 0)
4470 /* Do vscroll if already vscrolled or only display line. */
4471 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4473 px = max (0, -w->vscroll + min (rbot, dy));
4474 Fset_window_vscroll (window, make_number (px), Qt);
4475 return;
4478 /* Maybe modify window start instead of scrolling. */
4479 if (rbot > 0 || w->vscroll < 0)
4481 ptrdiff_t spos;
4483 Fset_window_vscroll (window, make_number (0), Qt);
4484 /* If there are other text lines above the current row,
4485 move window start to current row. Else to next row. */
4486 if (rbot > 0)
4487 spos = XINT (Fline_beginning_position (Qnil));
4488 else
4489 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4490 set_marker_restricted (w->start, make_number (spos),
4491 w->buffer);
4492 w->start_at_line_beg = 1;
4493 w->update_mode_line = 1;
4494 w->last_modified = 0;
4495 w->last_overlay_modified = 0;
4496 /* Set force_start so that redisplay_window will run the
4497 window-scroll-functions. */
4498 w->force_start = 1;
4499 return;
4503 /* Cancel previous vscroll. */
4504 Fset_window_vscroll (window, make_number (0), Qt);
4507 itdata = bidi_shelve_cache ();
4508 /* If scroll_preserve_screen_position is non-nil, we try to set
4509 point in the same window line as it is now, so get that line. */
4510 if (!NILP (Vscroll_preserve_screen_position))
4512 /* We preserve the goal pixel coordinate across consecutive
4513 calls to scroll-up, scroll-down and other commands that
4514 have the `scroll-command' property. This avoids the
4515 possibility of point becoming "stuck" on a tall line when
4516 scrolling by one line. */
4517 if (window_scroll_pixel_based_preserve_y < 0
4518 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4519 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4521 start_display (&it, w, start);
4522 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4523 window_scroll_pixel_based_preserve_y = it.current_y;
4524 window_scroll_pixel_based_preserve_x = it.current_x;
4527 else
4528 window_scroll_pixel_based_preserve_y
4529 = window_scroll_pixel_based_preserve_x = -1;
4531 /* Move iterator it from start the specified distance forward or
4532 backward. The result is the new window start. */
4533 start_display (&it, w, start);
4534 if (whole)
4536 ptrdiff_t start_pos = IT_CHARPOS (it);
4537 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4538 dy = max ((window_box_height (w)
4539 - next_screen_context_lines * dy),
4540 dy) * n;
4542 /* Note that move_it_vertically always moves the iterator to the
4543 start of a line. So, if the last line doesn't have a newline,
4544 we would end up at the start of the line ending at ZV. */
4545 if (dy <= 0)
4547 move_it_vertically_backward (&it, -dy);
4548 /* Ensure we actually do move, e.g. in case we are currently
4549 looking at an image that is taller that the window height. */
4550 while (start_pos == IT_CHARPOS (it)
4551 && start_pos > BEGV)
4552 move_it_by_lines (&it, -1);
4554 else if (dy > 0)
4556 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4557 MOVE_TO_POS | MOVE_TO_Y);
4558 /* Ensure we actually do move, e.g. in case we are currently
4559 looking at an image that is taller that the window height. */
4560 while (start_pos == IT_CHARPOS (it)
4561 && start_pos < ZV)
4562 move_it_by_lines (&it, 1);
4565 else
4566 move_it_by_lines (&it, n);
4568 /* We failed if we find ZV is already on the screen (scrolling up,
4569 means there's nothing past the end), or if we can't start any
4570 earlier (scrolling down, means there's nothing past the top). */
4571 if ((n > 0 && IT_CHARPOS (it) == ZV)
4572 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4574 if (IT_CHARPOS (it) == ZV)
4576 if (it.current_y < it.last_visible_y
4577 && (it.current_y + it.max_ascent + it.max_descent
4578 > it.last_visible_y))
4580 /* The last line was only partially visible, make it fully
4581 visible. */
4582 w->vscroll = (it.last_visible_y
4583 - it.current_y + it.max_ascent + it.max_descent);
4584 adjust_glyphs (it.f);
4586 else
4588 bidi_unshelve_cache (itdata, 0);
4589 if (noerror)
4590 return;
4591 else if (n < 0) /* could happen with empty buffers */
4592 xsignal0 (Qbeginning_of_buffer);
4593 else
4594 xsignal0 (Qend_of_buffer);
4597 else
4599 if (w->vscroll != 0)
4600 /* The first line was only partially visible, make it fully
4601 visible. */
4602 w->vscroll = 0;
4603 else
4605 bidi_unshelve_cache (itdata, 0);
4606 if (noerror)
4607 return;
4608 else
4609 xsignal0 (Qbeginning_of_buffer);
4613 /* If control gets here, then we vscrolled. */
4615 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4617 /* Don't try to change the window start below. */
4618 vscrolled = 1;
4621 if (! vscrolled)
4623 ptrdiff_t pos = IT_CHARPOS (it);
4624 ptrdiff_t bytepos;
4626 /* If in the middle of a multi-glyph character move forward to
4627 the next character. */
4628 if (in_display_vector_p (&it))
4630 ++pos;
4631 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4634 /* Set the window start, and set up the window for redisplay. */
4635 set_marker_restricted (w->start, make_number (pos),
4636 w->buffer);
4637 bytepos = marker_byte_position (w->start);
4638 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
4639 w->update_mode_line = 1;
4640 w->last_modified = 0;
4641 w->last_overlay_modified = 0;
4642 /* Set force_start so that redisplay_window will run the
4643 window-scroll-functions. */
4644 w->force_start = 1;
4647 /* The rest of this function uses current_y in a nonstandard way,
4648 not including the height of the header line if any. */
4649 it.current_y = it.vpos = 0;
4651 /* Move PT out of scroll margins.
4652 This code wants current_y to be zero at the window start position
4653 even if there is a header line. */
4654 this_scroll_margin = max (0, scroll_margin);
4655 this_scroll_margin
4656 = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4657 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4659 if (n > 0)
4661 /* We moved the window start towards ZV, so PT may be now
4662 in the scroll margin at the top. */
4663 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4664 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
4665 && (NILP (Vscroll_preserve_screen_position)
4666 || EQ (Vscroll_preserve_screen_position, Qt)))
4667 /* We found PT at a legitimate height. Leave it alone. */
4669 else if (window_scroll_pixel_based_preserve_y >= 0)
4671 /* If we have a header line, take account of it.
4672 This is necessary because we set it.current_y to 0, above. */
4673 move_it_to (&it, -1,
4674 window_scroll_pixel_based_preserve_x,
4675 window_scroll_pixel_based_preserve_y
4676 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
4677 -1, MOVE_TO_Y | MOVE_TO_X);
4678 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4680 else
4682 while (it.current_y < this_scroll_margin)
4684 int prev = it.current_y;
4685 move_it_by_lines (&it, 1);
4686 if (prev == it.current_y)
4687 break;
4689 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4692 else if (n < 0)
4694 ptrdiff_t charpos, bytepos;
4695 int partial_p;
4697 /* Save our position, for the
4698 window_scroll_pixel_based_preserve_y case. */
4699 charpos = IT_CHARPOS (it);
4700 bytepos = IT_BYTEPOS (it);
4702 /* We moved the window start towards BEGV, so PT may be now
4703 in the scroll margin at the bottom. */
4704 move_it_to (&it, PT, -1,
4705 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
4706 - this_scroll_margin - 1),
4708 MOVE_TO_POS | MOVE_TO_Y);
4710 /* Save our position, in case it's correct. */
4711 charpos = IT_CHARPOS (it);
4712 bytepos = IT_BYTEPOS (it);
4714 /* See if point is on a partially visible line at the end. */
4715 if (it.what == IT_EOB)
4716 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
4717 else
4719 move_it_by_lines (&it, 1);
4720 partial_p = it.current_y > it.last_visible_y;
4723 if (charpos == PT && !partial_p
4724 && (NILP (Vscroll_preserve_screen_position)
4725 || EQ (Vscroll_preserve_screen_position, Qt)))
4726 /* We found PT before we found the display margin, so PT is ok. */
4728 else if (window_scroll_pixel_based_preserve_y >= 0)
4730 SET_TEXT_POS_FROM_MARKER (start, w->start);
4731 start_display (&it, w, start);
4732 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
4733 here because we called start_display again and did not
4734 alter it.current_y this time. */
4735 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
4736 window_scroll_pixel_based_preserve_y, -1,
4737 MOVE_TO_Y | MOVE_TO_X);
4738 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4740 else
4742 if (partial_p)
4743 /* The last line was only partially visible, so back up two
4744 lines to make sure we're on a fully visible line. */
4746 move_it_by_lines (&it, -2);
4747 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4749 else
4750 /* No, the position we saved is OK, so use it. */
4751 SET_PT_BOTH (charpos, bytepos);
4754 bidi_unshelve_cache (itdata, 0);
4758 /* Implementation of window_scroll that works based on screen lines.
4759 See the comment of window_scroll for parameter descriptions. */
4761 static void
4762 window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
4764 register struct window *w = XWINDOW (window);
4765 /* Fvertical_motion enters redisplay, which can trigger
4766 fontification, which in turn can modify buffer text (e.g., if the
4767 fontification functions replace escape sequences with faces, as
4768 in `grep-mode-font-lock-keywords'). So we use a marker to record
4769 the old point position, to prevent crashes in SET_PT_BOTH. */
4770 Lisp_Object opoint_marker = Fpoint_marker ();
4771 register ptrdiff_t pos, pos_byte;
4772 register int ht = window_internal_height (w);
4773 register Lisp_Object tem;
4774 int lose;
4775 Lisp_Object bolp;
4776 ptrdiff_t startpos;
4777 Lisp_Object original_pos = Qnil;
4779 /* If scrolling screen-fulls, compute the number of lines to
4780 scroll from the window's height. */
4781 if (whole)
4782 n *= max (1, ht - next_screen_context_lines);
4784 startpos = marker_position (w->start);
4786 if (!NILP (Vscroll_preserve_screen_position))
4788 if (window_scroll_preserve_vpos <= 0
4789 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4790 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4792 struct position posit
4793 = *compute_motion (startpos, 0, 0, 0,
4794 PT, ht, 0,
4795 -1, w->hscroll,
4796 0, w);
4797 window_scroll_preserve_vpos = posit.vpos;
4798 window_scroll_preserve_hpos = posit.hpos + w->hscroll;
4801 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
4802 make_number (window_scroll_preserve_vpos));
4805 XSETFASTINT (tem, PT);
4806 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4808 if (NILP (tem))
4810 Fvertical_motion (make_number (- (ht / 2)), window);
4811 startpos = PT;
4814 SET_PT (startpos);
4815 lose = n < 0 && PT == BEGV;
4816 Fvertical_motion (make_number (n), window);
4817 pos = PT;
4818 pos_byte = PT_BYTE;
4819 bolp = Fbolp ();
4820 SET_PT_BOTH (marker_position (opoint_marker),
4821 marker_byte_position (opoint_marker));
4823 if (lose)
4825 if (noerror)
4826 return;
4827 else
4828 xsignal0 (Qbeginning_of_buffer);
4831 if (pos < ZV)
4833 /* Don't use a scroll margin that is negative or too large. */
4834 int this_scroll_margin =
4835 max (0, min (scroll_margin, XINT (w->total_lines) / 4));
4837 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4838 w->start_at_line_beg = !NILP (bolp);
4839 w->update_mode_line = 1;
4840 w->last_modified = 0;
4841 w->last_overlay_modified = 0;
4842 /* Set force_start so that redisplay_window will run
4843 the window-scroll-functions. */
4844 w->force_start = 1;
4846 if (!NILP (Vscroll_preserve_screen_position)
4847 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
4849 SET_PT_BOTH (pos, pos_byte);
4850 Fvertical_motion (original_pos, window);
4852 /* If we scrolled forward, put point enough lines down
4853 that it is outside the scroll margin. */
4854 else if (n > 0)
4856 int top_margin;
4858 if (this_scroll_margin > 0)
4860 SET_PT_BOTH (pos, pos_byte);
4861 Fvertical_motion (make_number (this_scroll_margin), window);
4862 top_margin = PT;
4864 else
4865 top_margin = pos;
4867 if (top_margin <= marker_position (opoint_marker))
4868 SET_PT_BOTH (marker_position (opoint_marker),
4869 marker_byte_position (opoint_marker));
4870 else if (!NILP (Vscroll_preserve_screen_position))
4872 SET_PT_BOTH (pos, pos_byte);
4873 Fvertical_motion (original_pos, window);
4875 else
4876 SET_PT (top_margin);
4878 else if (n < 0)
4880 int bottom_margin;
4882 /* If we scrolled backward, put point near the end of the window
4883 but not within the scroll margin. */
4884 SET_PT_BOTH (pos, pos_byte);
4885 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4886 if (XFASTINT (tem) == ht - this_scroll_margin)
4887 bottom_margin = PT;
4888 else
4889 bottom_margin = PT + 1;
4891 if (bottom_margin > marker_position (opoint_marker))
4892 SET_PT_BOTH (marker_position (opoint_marker),
4893 marker_byte_position (opoint_marker));
4894 else
4896 if (!NILP (Vscroll_preserve_screen_position))
4898 SET_PT_BOTH (pos, pos_byte);
4899 Fvertical_motion (original_pos, window);
4901 else
4902 Fvertical_motion (make_number (-1), window);
4906 else
4908 if (noerror)
4909 return;
4910 else
4911 xsignal0 (Qend_of_buffer);
4916 /* Scroll selected_window up or down. If N is nil, scroll a
4917 screen-full which is defined as the height of the window minus
4918 next_screen_context_lines. If N is the symbol `-', scroll.
4919 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4920 up. This is the guts of Fscroll_up and Fscroll_down. */
4922 static void
4923 scroll_command (Lisp_Object n, int direction)
4925 ptrdiff_t count = SPECPDL_INDEX ();
4927 eassert (eabs (direction) == 1);
4929 /* If selected window's buffer isn't current, make it current for
4930 the moment. But don't screw up if window_scroll gets an error. */
4931 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4933 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4934 Fset_buffer (XWINDOW (selected_window)->buffer);
4936 /* Make redisplay consider other windows than just selected_window. */
4937 ++windows_or_buffers_changed;
4940 if (NILP (n))
4941 window_scroll (selected_window, direction, 1, 0);
4942 else if (EQ (n, Qminus))
4943 window_scroll (selected_window, -direction, 1, 0);
4944 else
4946 n = Fprefix_numeric_value (n);
4947 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4950 unbind_to (count, Qnil);
4953 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
4954 doc: /* Scroll text of selected window upward ARG lines.
4955 If ARG is omitted or nil, scroll upward by a near full screen.
4956 A near full screen is `next-screen-context-lines' less than a full screen.
4957 Negative ARG means scroll downward.
4958 If ARG is the atom `-', scroll downward by nearly full screen.
4959 When calling from a program, supply as argument a number, nil, or `-'. */)
4960 (Lisp_Object arg)
4962 scroll_command (arg, 1);
4963 return Qnil;
4966 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
4967 doc: /* Scroll text of selected window down ARG lines.
4968 If ARG is omitted or nil, scroll down by a near full screen.
4969 A near full screen is `next-screen-context-lines' less than a full screen.
4970 Negative ARG means scroll upward.
4971 If ARG is the atom `-', scroll upward by nearly full screen.
4972 When calling from a program, supply as argument a number, nil, or `-'. */)
4973 (Lisp_Object arg)
4975 scroll_command (arg, -1);
4976 return Qnil;
4979 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4980 doc: /* Return the other window for \"other window scroll\" commands.
4981 If `other-window-scroll-buffer' is non-nil, a window
4982 showing that buffer is used.
4983 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4984 specifies the window. This takes precedence over
4985 `other-window-scroll-buffer'. */)
4986 (void)
4988 Lisp_Object window;
4990 if (MINI_WINDOW_P (XWINDOW (selected_window))
4991 && !NILP (Vminibuf_scroll_window))
4992 window = Vminibuf_scroll_window;
4993 /* If buffer is specified, scroll that buffer. */
4994 else if (!NILP (Vother_window_scroll_buffer))
4996 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4997 if (NILP (window))
4998 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
5000 else
5002 /* Nothing specified; look for a neighboring window on the same
5003 frame. */
5004 window = Fnext_window (selected_window, Qnil, Qnil);
5006 if (EQ (window, selected_window))
5007 /* That didn't get us anywhere; look for a window on another
5008 visible frame. */
5010 window = Fnext_window (window, Qnil, Qt);
5011 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
5012 && ! EQ (window, selected_window));
5015 CHECK_LIVE_WINDOW (window);
5017 if (EQ (window, selected_window))
5018 error ("There is no other window");
5020 return window;
5023 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5024 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5025 A near full screen is `next-screen-context-lines' less than a full screen.
5026 The next window is the one below the current one; or the one at the top
5027 if the current one is at the bottom. Negative ARG means scroll downward.
5028 If ARG is the atom `-', scroll downward by nearly full screen.
5029 When calling from a program, supply as argument a number, nil, or `-'.
5031 If `other-window-scroll-buffer' is non-nil, scroll the window
5032 showing that buffer, popping the buffer up if necessary.
5033 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5034 specifies the window to scroll. This takes precedence over
5035 `other-window-scroll-buffer'. */)
5036 (Lisp_Object arg)
5038 Lisp_Object window;
5039 struct window *w;
5040 ptrdiff_t count = SPECPDL_INDEX ();
5042 window = Fother_window_for_scrolling ();
5043 w = XWINDOW (window);
5045 /* Don't screw up if window_scroll gets an error. */
5046 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5047 ++windows_or_buffers_changed;
5049 Fset_buffer (w->buffer);
5050 SET_PT (marker_position (w->pointm));
5052 if (NILP (arg))
5053 window_scroll (window, 1, 1, 1);
5054 else if (EQ (arg, Qminus))
5055 window_scroll (window, -1, 1, 1);
5056 else
5058 if (CONSP (arg))
5059 arg = XCAR (arg);
5060 CHECK_NUMBER (arg);
5061 window_scroll (window, XINT (arg), 0, 1);
5064 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5065 unbind_to (count, Qnil);
5067 return Qnil;
5070 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5071 doc: /* Scroll selected window display ARG columns left.
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 ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5094 doc: /* Scroll selected window display ARG columns right.
5095 Default for ARG is window width minus 2.
5096 Value is the total amount of leftward horizontal scrolling in
5097 effect after the change.
5098 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5099 lower bound for automatic scrolling, i.e. automatic scrolling
5100 will not scroll a window to a column less than the value returned
5101 by this function. This happens in an interactive call. */)
5102 (register Lisp_Object arg, Lisp_Object set_minimum)
5104 struct window *w = XWINDOW (selected_window);
5105 EMACS_INT requested_arg = (NILP (arg)
5106 ? window_body_cols (w) - 2
5107 : XINT (Fprefix_numeric_value (arg)));
5108 Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
5110 if (!NILP (set_minimum))
5111 w->min_hscroll = w->hscroll;
5113 return result;
5116 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5117 doc: /* Return the window which was selected when entering the minibuffer.
5118 Returns nil, if selected window is not a minibuffer window. */)
5119 (void)
5121 if (minibuf_level > 0
5122 && MINI_WINDOW_P (XWINDOW (selected_window))
5123 && WINDOW_LIVE_P (minibuf_selected_window))
5124 return minibuf_selected_window;
5126 return Qnil;
5129 /* Value is the number of lines actually displayed in window W,
5130 as opposed to its height. */
5132 static int
5133 displayed_window_lines (struct window *w)
5135 struct it it;
5136 struct text_pos start;
5137 ptrdiff_t charpos = marker_position (w->start);
5138 int height = window_box_height (w);
5139 struct buffer *old_buffer;
5140 int bottom_y;
5141 void *itdata = NULL;
5143 if (XBUFFER (w->buffer) != current_buffer)
5145 old_buffer = current_buffer;
5146 set_buffer_internal (XBUFFER (w->buffer));
5148 else
5149 old_buffer = NULL;
5151 /* In case W->start is out of the accessible range, do something
5152 reasonable. This happens in Info mode when Info-scroll-down
5153 calls (recenter -1) while W->start is 1. */
5154 if (charpos < BEGV)
5155 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5156 else if (charpos > ZV)
5157 SET_TEXT_POS (start, ZV, ZV_BYTE);
5158 else
5159 SET_TEXT_POS_FROM_MARKER (start, w->start);
5161 itdata = bidi_shelve_cache ();
5162 start_display (&it, w, start);
5163 move_it_vertically (&it, height);
5164 bottom_y = line_bottom_y (&it);
5165 bidi_unshelve_cache (itdata, 0);
5167 /* rms: On a non-window display,
5168 the value of it.vpos at the bottom of the screen
5169 seems to be 1 larger than window_box_height (w).
5170 This kludge fixes a bug whereby (move-to-window-line -1)
5171 when ZV is on the last screen line
5172 moves to the previous screen line instead of the last one. */
5173 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5174 height++;
5176 /* Add in empty lines at the bottom of the window. */
5177 if (bottom_y < height)
5179 int uy = FRAME_LINE_HEIGHT (it.f);
5180 it.vpos += (height - bottom_y + uy - 1) / uy;
5183 if (old_buffer)
5184 set_buffer_internal (old_buffer);
5186 return it.vpos;
5190 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5191 doc: /* Center point in selected window and maybe redisplay frame.
5192 With prefix argument ARG, recenter putting point on screen line ARG
5193 relative to the selected window. If ARG is negative, it counts up from the
5194 bottom of the window. (ARG should be less than the height of the window.)
5196 If ARG is omitted or nil, then recenter with point on the middle line of
5197 the selected window; if the variable `recenter-redisplay' is non-nil,
5198 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5199 is set to `grow-only', this resets the tool-bar's height to the minimum
5200 height needed); if `recenter-redisplay' has the special value `tty',
5201 then only tty frames are redrawn.
5203 Just C-u as prefix means put point in the center of the window
5204 and redisplay normally--don't erase and redraw the frame. */)
5205 (register Lisp_Object arg)
5207 struct window *w = XWINDOW (selected_window);
5208 struct buffer *buf = XBUFFER (w->buffer);
5209 struct buffer *obuf = current_buffer;
5210 int center_p = 0;
5211 ptrdiff_t charpos, bytepos;
5212 EMACS_INT iarg IF_LINT (= 0);
5213 int this_scroll_margin;
5215 /* If redisplay is suppressed due to an error, try again. */
5216 obuf->display_error_modiff = 0;
5218 if (NILP (arg))
5220 if (!NILP (Vrecenter_redisplay)
5221 && (!EQ (Vrecenter_redisplay, Qtty)
5222 || !NILP (Ftty_type (selected_frame))))
5224 ptrdiff_t i;
5226 /* Invalidate pixel data calculated for all compositions. */
5227 for (i = 0; i < n_compositions; i++)
5228 composition_table[i]->font = NULL;
5230 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5232 Fredraw_frame (WINDOW_FRAME (w));
5233 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5236 center_p = 1;
5238 else if (CONSP (arg)) /* Just C-u. */
5239 center_p = 1;
5240 else
5242 arg = Fprefix_numeric_value (arg);
5243 CHECK_NUMBER (arg);
5244 iarg = XINT (arg);
5247 set_buffer_internal (buf);
5249 /* Do this after making BUF current
5250 in case scroll_margin is buffer-local. */
5251 this_scroll_margin =
5252 max (0, min (scroll_margin, XFASTINT (w->total_lines) / 4));
5254 /* Handle centering on a graphical frame specially. Such frames can
5255 have variable-height lines and centering point on the basis of
5256 line counts would lead to strange effects. */
5257 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5259 if (center_p)
5261 struct it it;
5262 struct text_pos pt;
5263 void *itdata = bidi_shelve_cache ();
5265 SET_TEXT_POS (pt, PT, PT_BYTE);
5266 start_display (&it, w, pt);
5267 move_it_vertically_backward (&it, window_box_height (w) / 2);
5268 charpos = IT_CHARPOS (it);
5269 bytepos = IT_BYTEPOS (it);
5270 bidi_unshelve_cache (itdata, 0);
5272 else if (iarg < 0)
5274 struct it it;
5275 struct text_pos pt;
5276 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
5277 int extra_line_spacing;
5278 int h = window_box_height (w);
5279 void *itdata = bidi_shelve_cache ();
5281 iarg = - max (-iarg, this_scroll_margin);
5283 SET_TEXT_POS (pt, PT, PT_BYTE);
5284 start_display (&it, w, pt);
5286 /* Be sure we have the exact height of the full line containing PT. */
5287 move_it_by_lines (&it, 0);
5289 /* The amount of pixels we have to move back is the window
5290 height minus what's displayed in the line containing PT,
5291 and the lines below. */
5292 it.current_y = 0;
5293 it.vpos = 0;
5294 move_it_by_lines (&it, nlines);
5296 if (it.vpos == nlines)
5297 h -= it.current_y;
5298 else
5300 /* Last line has no newline */
5301 h -= line_bottom_y (&it);
5302 it.vpos++;
5305 /* Don't reserve space for extra line spacing of last line. */
5306 extra_line_spacing = it.max_extra_line_spacing;
5308 /* If we can't move down NLINES lines because we hit
5309 the end of the buffer, count in some empty lines. */
5310 if (it.vpos < nlines)
5312 nlines -= it.vpos;
5313 extra_line_spacing = it.extra_line_spacing;
5314 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5316 if (h <= 0)
5318 bidi_unshelve_cache (itdata, 0);
5319 return Qnil;
5322 /* Now find the new top line (starting position) of the window. */
5323 start_display (&it, w, pt);
5324 it.current_y = 0;
5325 move_it_vertically_backward (&it, h);
5327 /* If extra line spacing is present, we may move too far
5328 back. This causes the last line to be only partially
5329 visible (which triggers redisplay to recenter that line
5330 in the middle), so move forward.
5331 But ignore extra line spacing on last line, as it is not
5332 considered to be part of the visible height of the line.
5334 h += extra_line_spacing;
5335 while (-it.current_y > h)
5336 move_it_by_lines (&it, 1);
5338 charpos = IT_CHARPOS (it);
5339 bytepos = IT_BYTEPOS (it);
5341 bidi_unshelve_cache (itdata, 0);
5343 else
5345 struct position pos;
5347 iarg = max (iarg, this_scroll_margin);
5349 pos = *vmotion (PT, -iarg, w);
5350 charpos = pos.bufpos;
5351 bytepos = pos.bytepos;
5354 else
5356 struct position pos;
5357 int ht = window_internal_height (w);
5359 if (center_p)
5360 iarg = ht / 2;
5361 else if (iarg < 0)
5362 iarg += ht;
5364 /* Don't let it get into the margin at either top or bottom. */
5365 iarg = clip_to_bounds (this_scroll_margin, iarg,
5366 ht - this_scroll_margin - 1);
5368 pos = *vmotion (PT, - iarg, w);
5369 charpos = pos.bufpos;
5370 bytepos = pos.bytepos;
5373 /* Set the new window start. */
5374 set_marker_both (w->start, w->buffer, charpos, bytepos);
5375 wset_window_end_valid (w, Qnil);
5377 w->optional_new_start = 1;
5379 w->start_at_line_beg = (bytepos == BEGV_BYTE ||
5380 FETCH_BYTE (bytepos - 1) == '\n');
5382 set_buffer_internal (obuf);
5383 return Qnil;
5386 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5387 0, 1, 0,
5388 doc: /* Return the height in lines of the text display area of WINDOW.
5389 WINDOW must be a live window and defaults to the selected one.
5391 The returned height does not include the mode line, any header line,
5392 nor any partial-height lines at the bottom of the text area. */)
5393 (Lisp_Object window)
5395 struct window *w = decode_live_window (window);
5396 int pixel_height = window_box_height (w);
5397 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5398 return make_number (line_height);
5403 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5404 1, 1, "P",
5405 doc: /* Position point relative to window.
5406 ARG nil means position point at center of window.
5407 Else, ARG specifies vertical position within the window;
5408 zero means top of window, negative means relative to bottom of window. */)
5409 (Lisp_Object arg)
5411 struct window *w = XWINDOW (selected_window);
5412 int lines, start;
5413 Lisp_Object window;
5414 #if 0
5415 int this_scroll_margin;
5416 #endif
5418 if (!(BUFFERP (w->buffer)
5419 && XBUFFER (w->buffer) == current_buffer))
5420 /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
5421 when passed below to set_marker_both. */
5422 error ("move-to-window-line called from unrelated buffer");
5424 window = selected_window;
5425 start = marker_position (w->start);
5426 if (start < BEGV || start > ZV)
5428 int height = window_internal_height (w);
5429 Fvertical_motion (make_number (- (height / 2)), window);
5430 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5431 w->start_at_line_beg = !NILP (Fbolp ());
5432 w->force_start = 1;
5434 else
5435 Fgoto_char (w->start);
5437 lines = displayed_window_lines (w);
5439 #if 0
5440 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
5441 #endif
5443 if (NILP (arg))
5444 XSETFASTINT (arg, lines / 2);
5445 else
5447 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
5449 if (iarg < 0)
5450 iarg = iarg + lines;
5452 #if 0 /* This code would prevent move-to-window-line from moving point
5453 to a place inside the scroll margins (which would cause the
5454 next redisplay to scroll). I wrote this code, but then concluded
5455 it is probably better not to install it. However, it is here
5456 inside #if 0 so as not to lose it. -- rms. */
5458 /* Don't let it get into the margin at either top or bottom. */
5459 iarg = max (iarg, this_scroll_margin);
5460 iarg = min (iarg, lines - this_scroll_margin - 1);
5461 #endif
5463 arg = make_number (iarg);
5466 /* Skip past a partially visible first line. */
5467 if (w->vscroll)
5468 XSETINT (arg, XINT (arg) + 1);
5470 return Fvertical_motion (arg, window);
5475 /***********************************************************************
5476 Window Configuration
5477 ***********************************************************************/
5479 struct save_window_data
5481 struct vectorlike_header header;
5482 Lisp_Object selected_frame;
5483 Lisp_Object current_window;
5484 Lisp_Object current_buffer;
5485 Lisp_Object minibuf_scroll_window;
5486 Lisp_Object minibuf_selected_window;
5487 Lisp_Object root_window;
5488 Lisp_Object focus_frame;
5489 /* A vector, each of whose elements is a struct saved_window
5490 for one window. */
5491 Lisp_Object saved_windows;
5493 /* All fields above are traced by the GC.
5494 From `fame-cols' down, the fields are ignored by the GC. */
5496 int frame_cols, frame_lines, frame_menu_bar_lines;
5497 int frame_tool_bar_lines;
5500 /* This is saved as a Lisp_Vector */
5501 struct saved_window
5503 struct vectorlike_header header;
5505 Lisp_Object window, buffer, start, pointm, mark;
5506 Lisp_Object left_col, top_line, total_cols, total_lines;
5507 Lisp_Object normal_cols, normal_lines;
5508 Lisp_Object hscroll, min_hscroll;
5509 Lisp_Object parent, prev;
5510 Lisp_Object start_at_line_beg;
5511 Lisp_Object display_table;
5512 Lisp_Object left_margin_cols, right_margin_cols;
5513 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5514 Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
5515 Lisp_Object combination_limit, window_parameters;
5518 #define SAVED_WINDOW_N(swv,n) \
5519 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5521 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5522 doc: /* Return t if OBJECT is a window-configuration object. */)
5523 (Lisp_Object object)
5525 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5528 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5529 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5530 (Lisp_Object config)
5532 register struct save_window_data *data;
5533 struct Lisp_Vector *saved_windows;
5535 CHECK_WINDOW_CONFIGURATION (config);
5537 data = (struct save_window_data *) XVECTOR (config);
5538 saved_windows = XVECTOR (data->saved_windows);
5539 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5542 DEFUN ("set-window-configuration", Fset_window_configuration,
5543 Sset_window_configuration, 1, 1, 0,
5544 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5545 CONFIGURATION must be a value previously returned
5546 by `current-window-configuration' (which see).
5547 If CONFIGURATION was made from a frame that is now deleted,
5548 only frame-independent values can be restored. In this case,
5549 the return value is nil. Otherwise the value is t. */)
5550 (Lisp_Object configuration)
5552 register struct save_window_data *data;
5553 struct Lisp_Vector *saved_windows;
5554 Lisp_Object new_current_buffer;
5555 Lisp_Object frame;
5556 FRAME_PTR f;
5557 ptrdiff_t old_point = -1;
5559 CHECK_WINDOW_CONFIGURATION (configuration);
5561 data = (struct save_window_data *) XVECTOR (configuration);
5562 saved_windows = XVECTOR (data->saved_windows);
5564 new_current_buffer = data->current_buffer;
5565 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5566 new_current_buffer = Qnil;
5567 else
5569 if (XBUFFER (new_current_buffer) == current_buffer)
5570 /* The code further down "preserves point" by saving here PT in
5571 old_point and then setting it later back into PT. When the
5572 current-selected-window and the final-selected-window both show
5573 the current buffer, this suffers from the problem that the
5574 current PT is the window-point of the current-selected-window,
5575 while the final PT is the point of the final-selected-window, so
5576 this copy from one PT to the other would end up moving the
5577 window-point of the final-selected-window to the window-point of
5578 the current-selected-window. So we have to be careful which
5579 point of the current-buffer we copy into old_point. */
5580 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5581 && WINDOWP (selected_window)
5582 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
5583 && !EQ (selected_window, data->current_window))
5584 old_point = marker_position (XWINDOW (data->current_window)->pointm);
5585 else
5586 old_point = PT;
5587 else
5588 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5589 point in new_current_buffer as of the last time this buffer was
5590 used. This can be non-deterministic since it can be changed by
5591 things like jit-lock by mere temporary selection of some random
5592 window that happens to show this buffer.
5593 So if possible we want this arbitrary choice of "which point" to
5594 be the one from the to-be-selected-window so as to prevent this
5595 window's cursor from being copied from another window. */
5596 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5597 /* If current_window = selected_window, its point is in BUF_PT. */
5598 && !EQ (selected_window, data->current_window))
5599 old_point = marker_position (XWINDOW (data->current_window)->pointm);
5600 else
5601 old_point = BUF_PT (XBUFFER (new_current_buffer));
5604 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5605 f = XFRAME (frame);
5607 /* If f is a dead frame, don't bother rebuilding its window tree.
5608 However, there is other stuff we should still try to do below. */
5609 if (FRAME_LIVE_P (f))
5611 Lisp_Object window;
5612 Lisp_Object dead_windows = Qnil;
5613 register Lisp_Object tem, par, pers;
5614 register struct window *w;
5615 register struct saved_window *p;
5616 struct window *root_window;
5617 struct window **leaf_windows;
5618 int n_leaf_windows;
5619 ptrdiff_t k;
5620 int i, n;
5622 /* If the frame has been resized since this window configuration was
5623 made, we change the frame to the size specified in the
5624 configuration, restore the configuration, and then resize it
5625 back. We keep track of the prevailing height in these variables. */
5626 int previous_frame_lines = FRAME_LINES (f);
5627 int previous_frame_cols = FRAME_COLS (f);
5628 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5629 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5631 /* Don't do this within the main loop below: This may call Lisp
5632 code and is thus potentially unsafe while input is blocked. */
5633 for (k = 0; k < saved_windows->header.size; k++)
5635 p = SAVED_WINDOW_N (saved_windows, k);
5636 window = p->window;
5637 w = XWINDOW (window);
5638 if (!NILP (w->buffer)
5639 && !EQ (w->buffer, p->buffer)
5640 && BUFFER_LIVE_P (XBUFFER (p->buffer)))
5641 /* If a window we restore gets another buffer, record the
5642 window's old buffer. */
5643 call1 (Qrecord_window_buffer, window);
5646 /* The mouse highlighting code could get screwed up
5647 if it runs during this. */
5648 block_input ();
5650 if (data->frame_lines != previous_frame_lines
5651 || data->frame_cols != previous_frame_cols)
5652 change_frame_size (f, data->frame_lines,
5653 data->frame_cols, 0, 0, 0);
5654 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5655 if (data->frame_menu_bar_lines
5656 != previous_frame_menu_bar_lines)
5657 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
5658 make_number (0));
5659 #ifdef HAVE_WINDOW_SYSTEM
5660 if (data->frame_tool_bar_lines
5661 != previous_frame_tool_bar_lines)
5662 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
5663 make_number (0));
5664 #endif
5665 #endif
5667 /* "Swap out" point from the selected window's buffer
5668 into the window itself. (Normally the pointm of the selected
5669 window holds garbage.) We do this now, before
5670 restoring the window contents, and prevent it from
5671 being done later on when we select a new window. */
5672 if (! NILP (XWINDOW (selected_window)->buffer))
5674 w = XWINDOW (selected_window);
5675 set_marker_both (w->pointm,
5676 w->buffer,
5677 BUF_PT (XBUFFER (w->buffer)),
5678 BUF_PT_BYTE (XBUFFER (w->buffer)));
5681 windows_or_buffers_changed++;
5682 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5684 /* Problem: Freeing all matrices and later allocating them again
5685 is a serious redisplay flickering problem. What we would
5686 really like to do is to free only those matrices not reused
5687 below. */
5688 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5689 leaf_windows = alloca (count_windows (root_window)
5690 * sizeof *leaf_windows);
5691 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5693 /* Kludge Alert!
5694 Mark all windows now on frame as "deleted".
5695 Restoring the new configuration "undeletes" any that are in it.
5697 Save their current buffers in their height fields, since we may
5698 need it later, if a buffer saved in the configuration is now
5699 dead. */
5700 delete_all_child_windows (FRAME_ROOT_WINDOW (f));
5702 for (k = 0; k < saved_windows->header.size; k++)
5704 p = SAVED_WINDOW_N (saved_windows, k);
5705 window = p->window;
5706 w = XWINDOW (window);
5707 wset_next (w, Qnil);
5709 if (!NILP (p->parent))
5710 wset_parent
5711 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window);
5712 else
5713 wset_parent (w, Qnil);
5715 if (!NILP (p->prev))
5717 wset_prev
5718 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window);
5719 wset_next (XWINDOW (w->prev), p->window);
5721 else
5723 wset_prev (w, Qnil);
5724 if (!NILP (w->parent))
5726 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
5728 wset_vchild (XWINDOW (w->parent), p->window);
5729 wset_hchild (XWINDOW (w->parent), Qnil);
5731 else
5733 wset_hchild (XWINDOW (w->parent), p->window);
5734 wset_vchild (XWINDOW (w->parent), Qnil);
5739 /* If we squirreled away the buffer in the window's height,
5740 restore it now. */
5741 if (BUFFERP (w->total_lines))
5742 wset_buffer (w, w->total_lines);
5743 wset_left_col (w, p->left_col);
5744 wset_top_line (w, p->top_line);
5745 wset_total_cols (w, p->total_cols);
5746 wset_total_lines (w, p->total_lines);
5747 wset_normal_cols (w, p->normal_cols);
5748 wset_normal_lines (w, p->normal_lines);
5749 w->hscroll = XFASTINT (p->hscroll);
5750 w->min_hscroll = XFASTINT (p->min_hscroll);
5751 wset_display_table (w, p->display_table);
5752 wset_left_margin_cols (w, p->left_margin_cols);
5753 wset_right_margin_cols (w, p->right_margin_cols);
5754 wset_left_fringe_width (w, p->left_fringe_width);
5755 wset_right_fringe_width (w, p->right_fringe_width);
5756 w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
5757 wset_scroll_bar_width (w, p->scroll_bar_width);
5758 wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
5759 wset_dedicated (w, p->dedicated);
5760 wset_combination_limit (w, p->combination_limit);
5761 /* Restore any window parameters that have been saved.
5762 Parameters that have not been saved are left alone. */
5763 for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
5765 pers = XCAR (tem);
5766 if (CONSP (pers))
5768 if (NILP (XCDR (pers)))
5770 par = Fassq (XCAR (pers), w->window_parameters);
5771 if (CONSP (par) && !NILP (XCDR (par)))
5772 /* Reset a parameter to nil if and only if it
5773 has a non-nil association. Don't make new
5774 associations. */
5775 Fsetcdr (par, Qnil);
5777 else
5778 /* Always restore a non-nil value. */
5779 Fset_window_parameter (window, XCAR (pers), XCDR (pers));
5783 w->last_modified = 0;
5784 w->last_overlay_modified = 0;
5786 /* Reinstall the saved buffer and pointers into it. */
5787 if (NILP (p->buffer))
5788 /* An internal window. */
5789 wset_buffer (w, p->buffer);
5790 else if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5791 /* If saved buffer is alive, install it. */
5793 wset_buffer (w, p->buffer);
5794 w->start_at_line_beg = !NILP (p->start_at_line_beg);
5795 set_marker_restricted (w->start, p->start, w->buffer);
5796 set_marker_restricted (w->pointm, p->pointm,
5797 w->buffer);
5798 Fset_marker (BVAR (XBUFFER (w->buffer), mark),
5799 p->mark, w->buffer);
5801 /* As documented in Fcurrent_window_configuration, don't
5802 restore the location of point in the buffer which was
5803 current when the window configuration was recorded. */
5804 if (!EQ (p->buffer, new_current_buffer)
5805 && XBUFFER (p->buffer) == current_buffer)
5806 Fgoto_char (w->pointm);
5808 else if (!NILP (w->buffer)
5809 && BUFFER_LIVE_P (XBUFFER (w->buffer)))
5810 /* Keep window's old buffer; make sure the markers are
5811 real. */
5813 /* Set window markers at start of visible range. */
5814 if (XMARKER (w->start)->buffer == 0)
5815 set_marker_restricted (w->start, make_number (0),
5816 w->buffer);
5817 if (XMARKER (w->pointm)->buffer == 0)
5818 set_marker_restricted_both
5819 (w->pointm, w->buffer,
5820 BUF_PT (XBUFFER (w->buffer)),
5821 BUF_PT_BYTE (XBUFFER (w->buffer)));
5822 w->start_at_line_beg = 1;
5824 else
5825 /* Window has no live buffer, get one. */
5827 /* Get the buffer via other_buffer_safely in order to
5828 avoid showing an unimportant buffer and, if necessary, to
5829 recreate *scratch* in the course (part of Juanma's bs-show
5830 scenario from March 2011). */
5831 wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
5832 /* This will set the markers to beginning of visible
5833 range. */
5834 set_marker_restricted (w->start,
5835 make_number (0), w->buffer);
5836 set_marker_restricted (w->pointm,
5837 make_number (0), w->buffer);
5838 w->start_at_line_beg = 1;
5839 if (!NILP (w->dedicated))
5840 /* Record this window as dead. */
5841 dead_windows = Fcons (window, dead_windows);
5842 /* Make sure window is no more dedicated. */
5843 wset_dedicated (w, Qnil);
5847 fset_root_window (f, data->root_window);
5848 /* Arrange *not* to restore point in the buffer that was
5849 current when the window configuration was saved. */
5850 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5851 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5852 make_number (old_point),
5853 XWINDOW (data->current_window)->buffer);
5855 /* In the following call to `select-window', prevent "swapping out
5856 point" in the old selected window using the buffer that has
5857 been restored into it. We already swapped out that point from
5858 that window's old buffer. */
5859 select_window (data->current_window, Qnil, 1);
5860 BVAR (XBUFFER (XWINDOW (selected_window)->buffer), last_selected_window)
5861 = selected_window;
5863 if (NILP (data->focus_frame)
5864 || (FRAMEP (data->focus_frame)
5865 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5866 Fredirect_frame_focus (frame, data->focus_frame);
5868 /* Set the screen height to the value it had before this function. */
5869 if (previous_frame_lines != FRAME_LINES (f)
5870 || previous_frame_cols != FRAME_COLS (f))
5871 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5872 0, 0, 0);
5873 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5874 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5875 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5876 make_number (0));
5877 #ifdef HAVE_WINDOW_SYSTEM
5878 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5879 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5880 make_number (0));
5881 #endif
5882 #endif
5884 /* Now, free glyph matrices in windows that were not reused. */
5885 for (i = n = 0; i < n_leaf_windows; ++i)
5887 if (NILP (leaf_windows[i]->buffer))
5889 /* Assert it's not reused as a combination. */
5890 eassert (NILP (leaf_windows[i]->hchild)
5891 && NILP (leaf_windows[i]->vchild));
5892 free_window_matrices (leaf_windows[i]);
5894 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5895 ++n;
5898 adjust_glyphs (f);
5899 unblock_input ();
5901 /* Scan dead buffer windows. */
5902 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
5904 window = XCAR (dead_windows);
5905 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
5906 delete_deletable_window (window);
5909 /* Fselect_window will have made f the selected frame, so we
5910 reselect the proper frame here. Fhandle_switch_frame will change the
5911 selected window too, but that doesn't make the call to
5912 Fselect_window above totally superfluous; it still sets f's
5913 selected window. */
5914 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5915 do_switch_frame (data->selected_frame, 0, 0, Qnil);
5917 run_window_configuration_change_hook (f);
5920 if (!NILP (new_current_buffer))
5922 Fset_buffer (new_current_buffer);
5923 /* If the new current buffer doesn't appear in the selected
5924 window, go to its old point (see bug#12208). */
5925 if (!EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5926 Fgoto_char (make_number (old_point));
5929 Vminibuf_scroll_window = data->minibuf_scroll_window;
5930 minibuf_selected_window = data->minibuf_selected_window;
5932 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5936 /* Recursively delete all child windows reachable via the next, vchild,
5937 and hchild slots of WINDOW. */
5938 void
5939 delete_all_child_windows (Lisp_Object window)
5941 register struct window *w;
5943 w = XWINDOW (window);
5945 if (!NILP (w->next))
5946 /* Delete WINDOW's siblings (we traverse postorderly). */
5947 delete_all_child_windows (w->next);
5949 /* See Fset_window_configuration for excuse. */
5950 wset_total_lines (w, w->buffer);
5952 if (!NILP (w->vchild))
5954 delete_all_child_windows (w->vchild);
5955 wset_vchild (w, Qnil);
5957 else if (!NILP (w->hchild))
5959 delete_all_child_windows (w->hchild);
5960 wset_hchild (w, Qnil);
5962 else if (!NILP (w->buffer))
5964 unshow_buffer (w);
5965 unchain_marker (XMARKER (w->pointm));
5966 unchain_marker (XMARKER (w->start));
5967 wset_buffer (w, Qnil);
5970 Vwindow_list = Qnil;
5973 static int
5974 count_windows (register struct window *window)
5976 register int count = 1;
5977 if (!NILP (window->next))
5978 count += count_windows (XWINDOW (window->next));
5979 if (!NILP (window->vchild))
5980 count += count_windows (XWINDOW (window->vchild));
5981 if (!NILP (window->hchild))
5982 count += count_windows (XWINDOW (window->hchild));
5983 return count;
5987 /* Fill vector FLAT with leaf windows under W, starting at index I.
5988 Value is last index + 1. */
5989 static int
5990 get_leaf_windows (struct window *w, struct window **flat, int i)
5992 while (w)
5994 if (!NILP (w->hchild))
5995 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5996 else if (!NILP (w->vchild))
5997 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5998 else
5999 flat[i++] = w;
6001 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6004 return i;
6008 /* Return a pointer to the glyph W's physical cursor is on. Value is
6009 null if W's current matrix is invalid, so that no meaningful glyph
6010 can be returned. */
6011 struct glyph *
6012 get_phys_cursor_glyph (struct window *w)
6014 struct glyph_row *row;
6015 struct glyph *glyph;
6016 int hpos = w->phys_cursor.hpos;
6018 if (!(w->phys_cursor.vpos >= 0
6019 && w->phys_cursor.vpos < w->current_matrix->nrows))
6020 return NULL;
6022 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
6023 if (!row->enabled_p)
6024 return NULL;
6026 if (w->hscroll)
6028 /* When the window is hscrolled, cursor hpos can legitimately be
6029 out of bounds, but we draw the cursor at the corresponding
6030 window margin in that case. */
6031 if (!row->reversed_p && hpos < 0)
6032 hpos = 0;
6033 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
6034 hpos = row->used[TEXT_AREA] - 1;
6037 if (row->used[TEXT_AREA] > hpos
6038 && 0 <= hpos)
6039 glyph = row->glyphs[TEXT_AREA] + hpos;
6040 else
6041 glyph = NULL;
6043 return glyph;
6047 static int
6048 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
6050 register struct saved_window *p;
6051 register struct window *w;
6052 register Lisp_Object tem, pers, par;
6054 for (;!NILP (window); window = w->next)
6056 p = SAVED_WINDOW_N (vector, i);
6057 w = XWINDOW (window);
6059 wset_temslot (w, make_number (i)); i++;
6060 p->window = window;
6061 p->buffer = w->buffer;
6062 p->left_col = w->left_col;
6063 p->top_line = w->top_line;
6064 p->total_cols = w->total_cols;
6065 p->total_lines = w->total_lines;
6066 p->normal_cols = w->normal_cols;
6067 p->normal_lines = w->normal_lines;
6068 XSETFASTINT (p->hscroll, w->hscroll);
6069 XSETFASTINT (p->min_hscroll, w->min_hscroll);
6070 p->display_table = w->display_table;
6071 p->left_margin_cols = w->left_margin_cols;
6072 p->right_margin_cols = w->right_margin_cols;
6073 p->left_fringe_width = w->left_fringe_width;
6074 p->right_fringe_width = w->right_fringe_width;
6075 p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
6076 p->scroll_bar_width = w->scroll_bar_width;
6077 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6078 p->dedicated = w->dedicated;
6079 p->combination_limit = w->combination_limit;
6080 p->window_parameters = Qnil;
6082 if (!NILP (Vwindow_persistent_parameters))
6084 /* Run cycle detection on Vwindow_persistent_parameters. */
6085 Lisp_Object tortoise, hare;
6087 hare = tortoise = Vwindow_persistent_parameters;
6088 while (CONSP (hare))
6090 hare = XCDR (hare);
6091 if (!CONSP (hare))
6092 break;
6094 hare = XCDR (hare);
6095 tortoise = XCDR (tortoise);
6097 if (EQ (hare, tortoise))
6098 /* Reset Vwindow_persistent_parameters to Qnil. */
6100 Vwindow_persistent_parameters = Qnil;
6101 break;
6105 for (tem = Vwindow_persistent_parameters; CONSP (tem);
6106 tem = XCDR (tem))
6108 pers = XCAR (tem);
6109 /* Save values for persistent window parameters. */
6110 if (CONSP (pers) && !NILP (XCDR (pers)))
6112 par = Fassq (XCAR (pers), w->window_parameters);
6113 if (NILP (par))
6114 /* If the window has no value for the parameter,
6115 make one. */
6116 p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
6117 p->window_parameters);
6118 else
6119 /* If the window has a value for the parameter,
6120 save it. */
6121 p->window_parameters = Fcons (Fcons (XCAR (par),
6122 XCDR (par)),
6123 p->window_parameters);
6128 if (!NILP (w->buffer))
6130 /* Save w's value of point in the window configuration. If w
6131 is the selected window, then get the value of point from
6132 the buffer; pointm is garbage in the selected window. */
6133 if (EQ (window, selected_window))
6134 p->pointm = build_marker (XBUFFER (w->buffer),
6135 BUF_PT (XBUFFER (w->buffer)),
6136 BUF_PT_BYTE (XBUFFER (w->buffer)));
6137 else
6138 p->pointm = Fcopy_marker (w->pointm, Qnil);
6139 XMARKER (p->pointm)->insertion_type
6140 = !NILP (Vwindow_point_insertion_type);
6142 p->start = Fcopy_marker (w->start, Qnil);
6143 p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
6145 tem = BVAR (XBUFFER (w->buffer), mark);
6146 p->mark = Fcopy_marker (tem, Qnil);
6148 else
6150 p->pointm = Qnil;
6151 p->start = Qnil;
6152 p->mark = Qnil;
6153 p->start_at_line_beg = Qnil;
6156 if (NILP (w->parent))
6157 p->parent = Qnil;
6158 else
6159 p->parent = XWINDOW (w->parent)->temslot;
6161 if (NILP (w->prev))
6162 p->prev = Qnil;
6163 else
6164 p->prev = XWINDOW (w->prev)->temslot;
6166 if (!NILP (w->vchild))
6167 i = save_window_save (w->vchild, vector, i);
6168 if (!NILP (w->hchild))
6169 i = save_window_save (w->hchild, vector, i);
6172 return i;
6175 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6176 Scurrent_window_configuration, 0, 1, 0,
6177 doc: /* Return an object representing the current window configuration of FRAME.
6178 If FRAME is nil or omitted, use the selected frame.
6179 This describes the number of windows, their sizes and current buffers,
6180 and for each displayed buffer, where display starts, and the positions of
6181 point and mark. An exception is made for point in the current buffer:
6182 its value is -not- saved.
6183 This also records the currently selected frame, and FRAME's focus
6184 redirection (see `redirect-frame-focus'). The variable
6185 `window-persistent-parameters' specifies which window parameters are
6186 saved by this function. */)
6187 (Lisp_Object frame)
6189 register Lisp_Object tem;
6190 register int n_windows;
6191 register struct save_window_data *data;
6192 register int i;
6193 struct frame *f = decode_live_frame (frame);
6195 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6196 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6197 PVEC_WINDOW_CONFIGURATION);
6199 data->frame_cols = FRAME_COLS (f);
6200 data->frame_lines = FRAME_LINES (f);
6201 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6202 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6203 data->selected_frame = selected_frame;
6204 data->current_window = FRAME_SELECTED_WINDOW (f);
6205 XSETBUFFER (data->current_buffer, current_buffer);
6206 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6207 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6208 data->root_window = FRAME_ROOT_WINDOW (f);
6209 data->focus_frame = FRAME_FOCUS_FRAME (f);
6210 tem = Fmake_vector (make_number (n_windows), Qnil);
6211 data->saved_windows = tem;
6212 for (i = 0; i < n_windows; i++)
6213 ASET (tem, i,
6214 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil));
6215 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6216 XSETWINDOW_CONFIGURATION (tem, data);
6217 return (tem);
6220 /***********************************************************************
6221 Marginal Areas
6222 ***********************************************************************/
6224 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6225 2, 3, 0,
6226 doc: /* Set width of marginal areas of window WINDOW.
6227 WINDOW must be a live window and defaults to the selected one.
6229 Second arg LEFT-WIDTH specifies the number of character cells to
6230 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6231 does the same for the right marginal area. A nil width parameter
6232 means no margin. */)
6233 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6235 struct window *w = decode_live_window (window);
6237 /* Translate negative or zero widths to nil.
6238 Margins that are too wide have to be checked elsewhere. */
6240 if (!NILP (left_width))
6242 CHECK_NUMBER (left_width);
6243 if (XINT (left_width) <= 0)
6244 left_width = Qnil;
6247 if (!NILP (right_width))
6249 CHECK_NUMBER (right_width);
6250 if (XINT (right_width) <= 0)
6251 right_width = Qnil;
6254 if (!EQ (w->left_margin_cols, left_width)
6255 || !EQ (w->right_margin_cols, right_width))
6257 wset_left_margin_cols (w, left_width);
6258 wset_right_margin_cols (w, right_width);
6260 adjust_window_margins (w);
6262 ++windows_or_buffers_changed;
6263 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6266 return Qnil;
6270 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6271 0, 1, 0,
6272 doc: /* Get width of marginal areas of window WINDOW.
6273 WINDOW must be a live window and defaults to the selected one.
6275 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6276 If a marginal area does not exist, its width will be returned
6277 as nil. */)
6278 (Lisp_Object window)
6280 struct window *w = decode_live_window (window);
6281 return Fcons (w->left_margin_cols, w->right_margin_cols);
6286 /***********************************************************************
6287 Fringes
6288 ***********************************************************************/
6290 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6291 2, 4, 0,
6292 doc: /* Set the fringe widths of window WINDOW.
6293 WINDOW must be a live window and defaults to the selected one.
6295 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6296 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6297 fringe width. If a fringe width arg is nil, that means to use the
6298 frame's default fringe width. Default fringe widths can be set with
6299 the command `set-fringe-style'.
6300 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6301 outside of the display margins. By default, fringes are drawn between
6302 display marginal areas and the text area. */)
6303 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width, Lisp_Object outside_margins)
6305 struct window *w = decode_live_window (window);
6306 int outside = !NILP (outside_margins);
6308 if (!NILP (left_width))
6309 CHECK_NATNUM (left_width);
6310 if (!NILP (right_width))
6311 CHECK_NATNUM (right_width);
6313 /* Do nothing on a tty. */
6314 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6315 && (!EQ (w->left_fringe_width, left_width)
6316 || !EQ (w->right_fringe_width, right_width)
6317 || w->fringes_outside_margins != outside))
6319 wset_left_fringe_width (w, left_width);
6320 wset_right_fringe_width (w, right_width);
6321 w->fringes_outside_margins = outside;
6323 adjust_window_margins (w);
6325 clear_glyph_matrix (w->current_matrix);
6326 wset_window_end_valid (w, Qnil);
6328 ++windows_or_buffers_changed;
6329 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6332 return Qnil;
6336 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6337 0, 1, 0,
6338 doc: /* Get width of fringes of window WINDOW.
6339 WINDOW must be a live window and defaults to the selected one.
6341 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6342 (Lisp_Object window)
6344 struct window *w = decode_live_window (window);
6346 return list3 (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6347 make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6348 WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil);
6353 /***********************************************************************
6354 Scroll bars
6355 ***********************************************************************/
6357 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
6358 Sset_window_scroll_bars, 2, 4, 0,
6359 doc: /* Set width and type of scroll bars of window WINDOW.
6360 WINDOW must be a live window and defaults to the selected one.
6362 Second parameter WIDTH specifies the pixel width for the scroll bar;
6363 this is automatically adjusted to a multiple of the frame column width.
6364 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6365 bar: left, right, or nil.
6366 If WIDTH is nil, use the frame's scroll-bar width.
6367 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6368 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6369 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, Lisp_Object horizontal_type)
6371 struct window *w = decode_live_window (window);
6373 if (!NILP (width))
6375 CHECK_RANGED_INTEGER (width, 0, INT_MAX);
6377 if (XINT (width) == 0)
6378 vertical_type = Qnil;
6381 if (!(NILP (vertical_type)
6382 || EQ (vertical_type, Qleft)
6383 || EQ (vertical_type, Qright)
6384 || EQ (vertical_type, Qt)))
6385 error ("Invalid type of vertical scroll bar");
6387 if (!EQ (w->scroll_bar_width, width)
6388 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6390 wset_scroll_bar_width (w, width);
6391 wset_vertical_scroll_bar_type (w, vertical_type);
6393 adjust_window_margins (w);
6395 clear_glyph_matrix (w->current_matrix);
6396 wset_window_end_valid (w, Qnil);
6398 ++windows_or_buffers_changed;
6399 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6402 return Qnil;
6406 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6407 0, 1, 0,
6408 doc: /* Get width and type of scroll bars of window WINDOW.
6409 WINDOW must be a live window and defaults to the selected one.
6411 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6412 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6413 value. */)
6414 (Lisp_Object window)
6416 struct window *w = decode_live_window (window);
6418 return list4 (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6419 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6420 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6421 make_number (WINDOW_SCROLL_BAR_COLS (w)),
6422 w->vertical_scroll_bar_type, Qnil);
6427 /***********************************************************************
6428 Smooth scrolling
6429 ***********************************************************************/
6431 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6432 doc: /* Return the amount by which WINDOW is scrolled vertically.
6433 If WINDOW is omitted or nil, it defaults to the selected window.
6434 Normally, value is a multiple of the canonical character height of WINDOW;
6435 optional second arg PIXELS-P means value is measured in pixels. */)
6436 (Lisp_Object window, Lisp_Object pixels_p)
6438 Lisp_Object result;
6439 struct window *w = decode_live_window (window);
6440 struct frame *f = XFRAME (w->frame);
6442 if (FRAME_WINDOW_P (f))
6443 result = (NILP (pixels_p)
6444 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6445 : make_number (-w->vscroll));
6446 else
6447 result = make_number (0);
6448 return result;
6452 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6453 2, 3, 0,
6454 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6455 WINDOW nil means use the selected window. Normally, VSCROLL is a
6456 non-negative multiple of the canonical character height of WINDOW;
6457 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6458 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6459 corresponds to an integral number of pixels. The return value is the
6460 result of this rounding.
6461 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6462 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
6464 struct window *w = decode_live_window (window);
6465 struct frame *f = XFRAME (w->frame);
6467 CHECK_NUMBER_OR_FLOAT (vscroll);
6469 if (FRAME_WINDOW_P (f))
6471 int old_dy = w->vscroll;
6473 w->vscroll = - (NILP (pixels_p)
6474 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6475 : XFLOATINT (vscroll));
6476 w->vscroll = min (w->vscroll, 0);
6478 if (w->vscroll != old_dy)
6480 /* Adjust glyph matrix of the frame if the virtual display
6481 area becomes larger than before. */
6482 if (w->vscroll < 0 && w->vscroll < old_dy)
6483 adjust_glyphs (f);
6485 /* Prevent redisplay shortcuts. */
6486 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6490 return Fwindow_vscroll (window, pixels_p);
6494 /* Call FN for all leaf windows on frame F. FN is called with the
6495 first argument being a pointer to the leaf window, and with
6496 additional argument USER_DATA. Stops when FN returns 0. */
6498 static void
6499 foreach_window (struct frame *f, int (*fn) (struct window *, void *),
6500 void *user_data)
6502 /* delete_frame may set FRAME_ROOT_WINDOW (f) to Qnil. */
6503 if (WINDOWP (FRAME_ROOT_WINDOW (f)))
6504 foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
6508 /* Helper function for foreach_window. Call FN for all leaf windows
6509 reachable from W. FN is called with the first argument being a
6510 pointer to the leaf window, and with additional argument USER_DATA.
6511 Stop when FN returns 0. Value is 0 if stopped by FN. */
6513 static int
6514 foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
6516 int cont;
6518 for (cont = 1; w && cont;)
6520 if (!NILP (w->hchild))
6521 cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
6522 else if (!NILP (w->vchild))
6523 cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
6524 else
6525 cont = fn (w, user_data);
6527 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6530 return cont;
6534 /* Freeze or unfreeze the window start of W unless it is a
6535 mini-window or the selected window. FREEZE_P non-null means freeze
6536 the window start. */
6538 static int
6539 freeze_window_start (struct window *w, void *freeze_p)
6541 if (MINI_WINDOW_P (w)
6542 || (WINDOWP (selected_window) /* Can be nil in corner cases. */
6543 && (w == XWINDOW (selected_window)
6544 || (MINI_WINDOW_P (XWINDOW (selected_window))
6545 && ! NILP (Vminibuf_scroll_window)
6546 && w == XWINDOW (Vminibuf_scroll_window)))))
6547 freeze_p = NULL;
6549 w->frozen_window_start_p = freeze_p != NULL;
6550 return 1;
6554 /* Freeze or unfreeze the window starts of all leaf windows on frame
6555 F, except the selected window and a mini-window. FREEZE_P non-zero
6556 means freeze the window start. */
6558 void
6559 freeze_window_starts (struct frame *f, int freeze_p)
6561 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6565 /***********************************************************************
6566 Initialization
6567 ***********************************************************************/
6569 /* Return 1 if window configurations CONFIGURATION1 and CONFIGURATION2
6570 describe the same state of affairs. This is used by Fequal.
6572 IGNORE_POSITIONS means ignore non-matching scroll positions
6573 and the like.
6575 This ignores a couple of things like the dedication status of
6576 window, combination_limit and the like. This might have to be
6577 fixed. */
6579 bool
6580 compare_window_configurations (Lisp_Object configuration1,
6581 Lisp_Object configuration2,
6582 bool ignore_positions)
6584 register struct save_window_data *d1, *d2;
6585 struct Lisp_Vector *sws1, *sws2;
6586 ptrdiff_t i;
6588 CHECK_WINDOW_CONFIGURATION (configuration1);
6589 CHECK_WINDOW_CONFIGURATION (configuration2);
6591 d1 = (struct save_window_data *) XVECTOR (configuration1);
6592 d2 = (struct save_window_data *) XVECTOR (configuration2);
6593 sws1 = XVECTOR (d1->saved_windows);
6594 sws2 = XVECTOR (d2->saved_windows);
6596 /* Frame settings must match. */
6597 if (d1->frame_cols != d2->frame_cols
6598 || d1->frame_lines != d2->frame_lines
6599 || d1->frame_menu_bar_lines != d2->frame_menu_bar_lines
6600 || !EQ (d1->selected_frame, d2->selected_frame)
6601 || !EQ (d1->current_buffer, d2->current_buffer)
6602 || (!ignore_positions
6603 && (!EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)
6604 || !EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)))
6605 || !EQ (d1->focus_frame, d2->focus_frame)
6606 /* Verify that the two configurations have the same number of windows. */
6607 || sws1->header.size != sws2->header.size)
6608 return 0;
6610 for (i = 0; i < sws1->header.size; i++)
6612 struct saved_window *sw1, *sw2;
6614 sw1 = SAVED_WINDOW_N (sws1, i);
6615 sw2 = SAVED_WINDOW_N (sws2, i);
6617 if (
6618 /* The "current" windows in the two configurations must
6619 correspond to each other. */
6620 EQ (d1->current_window, sw1->window)
6621 != EQ (d2->current_window, sw2->window)
6622 /* Windows' buffers must match. */
6623 || !EQ (sw1->buffer, sw2->buffer)
6624 || !EQ (sw1->left_col, sw2->left_col)
6625 || !EQ (sw1->top_line, sw2->top_line)
6626 || !EQ (sw1->total_cols, sw2->total_cols)
6627 || !EQ (sw1->total_lines, sw2->total_lines)
6628 || !EQ (sw1->display_table, sw2->display_table)
6629 /* The next two disjuncts check the window structure for
6630 equality. */
6631 || !EQ (sw1->parent, sw2->parent)
6632 || !EQ (sw1->prev, sw2->prev)
6633 || (!ignore_positions
6634 && (!EQ (sw1->hscroll, sw2->hscroll)
6635 || !EQ (sw1->min_hscroll, sw2->min_hscroll)
6636 || !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
6637 || NILP (Fequal (sw1->start, sw2->start))
6638 || NILP (Fequal (sw1->pointm, sw2->pointm))
6639 || NILP (Fequal (sw1->mark, sw2->mark))))
6640 || !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
6641 || !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
6642 || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
6643 || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
6644 || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
6645 || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
6646 || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type))
6647 return 0;
6650 return 1;
6653 DEFUN ("compare-window-configurations", Fcompare_window_configurations,
6654 Scompare_window_configurations, 2, 2, 0,
6655 doc: /* Compare two window configurations as regards the structure of windows.
6656 This function ignores details such as the values of point and mark
6657 and scrolling positions. */)
6658 (Lisp_Object x, Lisp_Object y)
6660 if (compare_window_configurations (x, y, 1))
6661 return Qt;
6662 return Qnil;
6665 void
6666 init_window_once (void)
6668 struct frame *f = make_initial_frame ();
6669 XSETFRAME (selected_frame, f);
6670 Vterminal_frame = selected_frame;
6671 minibuf_window = f->minibuffer_window;
6672 selected_window = f->selected_window;
6673 last_nonminibuf_frame = f;
6675 window_initialized = 1;
6678 void
6679 init_window (void)
6681 Vwindow_list = Qnil;
6684 void
6685 syms_of_window (void)
6687 DEFSYM (Qscroll_up, "scroll-up");
6688 DEFSYM (Qscroll_down, "scroll-down");
6689 DEFSYM (Qscroll_command, "scroll-command");
6691 Fput (Qscroll_up, Qscroll_command, Qt);
6692 Fput (Qscroll_down, Qscroll_command, Qt);
6694 DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
6695 DEFSYM (Qwindowp, "windowp");
6696 DEFSYM (Qwindow_configuration_p, "window-configuration-p");
6697 DEFSYM (Qwindow_live_p, "window-live-p");
6698 DEFSYM (Qwindow_valid_p, "window-valid-p");
6699 DEFSYM (Qwindow_deletable_p, "window-deletable-p");
6700 DEFSYM (Qdelete_window, "delete-window");
6701 DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
6702 DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
6703 DEFSYM (Qsafe, "safe");
6704 DEFSYM (Qdisplay_buffer, "display-buffer");
6705 DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
6706 DEFSYM (Qrecord_window_buffer, "record-window-buffer");
6707 DEFSYM (Qget_mru_window, "get-mru-window");
6708 DEFSYM (Qwindow_size, "window-size");
6709 DEFSYM (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6710 DEFSYM (Qabove, "above");
6711 DEFSYM (Qbelow, "below");
6712 DEFSYM (Qclone_of, "clone-of");
6714 staticpro (&Vwindow_list);
6716 minibuf_selected_window = Qnil;
6717 staticpro (&minibuf_selected_window);
6719 window_scroll_pixel_based_preserve_x = -1;
6720 window_scroll_pixel_based_preserve_y = -1;
6721 window_scroll_preserve_hpos = -1;
6722 window_scroll_preserve_vpos = -1;
6724 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
6725 doc: /* Non-nil means call as function to display a help buffer.
6726 The function is called with one argument, the buffer to be displayed.
6727 Used by `with-output-to-temp-buffer'.
6728 If this function is used, then it must do the entire job of showing
6729 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6730 Vtemp_buffer_show_function = Qnil;
6732 DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
6733 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6734 Vminibuf_scroll_window = Qnil;
6736 DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
6737 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6738 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6739 is displayed in the `mode-line' face. */);
6740 mode_line_in_non_selected_windows = 1;
6742 DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
6743 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6744 Vother_window_scroll_buffer = Qnil;
6746 DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
6747 doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
6748 auto_window_vscroll_p = 1;
6750 DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
6751 doc: /* Number of lines of continuity when scrolling by screenfuls. */);
6752 next_screen_context_lines = 2;
6754 DEFVAR_LISP ("scroll-preserve-screen-position",
6755 Vscroll_preserve_screen_position,
6756 doc: /* Controls if scroll commands move point to keep its screen position unchanged.
6757 A value of nil means point does not keep its screen position except
6758 at the scroll margin or window boundary respectively.
6759 A value of t means point keeps its screen position if the scroll
6760 command moved it vertically out of the window, e.g. when scrolling
6761 by full screens.
6762 Any other value means point always keeps its screen position.
6763 Scroll commands should have the `scroll-command' property
6764 on their symbols to be controlled by this variable. */);
6765 Vscroll_preserve_screen_position = Qnil;
6767 DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
6768 doc: /* Type of marker to use for `window-point'. */);
6769 Vwindow_point_insertion_type = Qnil;
6771 DEFVAR_LISP ("window-configuration-change-hook",
6772 Vwindow_configuration_change_hook,
6773 doc: /* Functions to call when window configuration changes.
6774 The buffer-local part is run once per window, with the relevant window
6775 selected; while the global part is run only once for the modified frame,
6776 with the relevant frame selected. */);
6777 Vwindow_configuration_change_hook = Qnil;
6779 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
6780 doc: /* Non-nil means `recenter' redraws entire frame.
6781 If this option is non-nil, then the `recenter' command with a nil
6782 argument will redraw the entire frame; the special value `tty' causes
6783 the frame to be redrawn only if it is a tty frame. */);
6784 Vrecenter_redisplay = Qtty;
6786 DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
6787 doc: /* If t, resize window combinations proportionally.
6788 If this variable is nil, splitting a window gets the entire screen space
6789 for displaying the new window from the window to split. Deleting and
6790 resizing a window preferably resizes one adjacent window only.
6792 If this variable is t, splitting a window tries to get the space
6793 proportionally from all windows in the same combination. This also
6794 allows to split a window that is otherwise too small or of fixed size.
6795 Resizing and deleting a window proportionally resize all windows in the
6796 same combination.
6798 Other values are reserved for future use.
6800 This variable takes no effect if `window-combination-limit' is non-nil. */);
6801 Vwindow_combination_resize = Qnil;
6803 DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
6804 doc: /* If non-nil, splitting a window makes a new parent window.
6805 The following values are recognized:
6807 nil means splitting a window will create a new parent window only if the
6808 window has no parent window or the window shall become part of a
6809 combination orthogonal to the one it is part of.
6811 `window-size' means that splitting a window for displaying a buffer
6812 makes a new parent window provided `display-buffer' is supposed to
6813 explicitly set the window's size due to the presence of a
6814 `window-height' or `window-width' entry in the alist used by
6815 `display-buffer'. Otherwise, this value is handled like nil.
6817 `temp-buffer' means that splitting a window for displaying a temporary
6818 buffer always makes a new parent window. Otherwise, this value is
6819 handled like nil.
6821 `display-buffer' means that splitting a window for displaying a buffer
6822 always makes a new parent window. Since temporary buffers are
6823 displayed by the function `display-buffer', this value is stronger
6824 than `temp-buffer'. Splitting a window for other purpose makes a
6825 new parent window only if needed.
6827 t means that splitting a window always creates a new parent window. If
6828 all splits behave this way, each frame's window tree is a binary
6829 tree and every window but the frame's root window has exactly one
6830 sibling.
6832 Other values are reserved for future use. */);
6833 Vwindow_combination_limit = Qwindow_size;
6835 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
6836 doc: /* Alist of persistent window parameters.
6837 This alist specifies which window parameters shall get saved by
6838 `current-window-configuration' and `window-state-get' and subsequently
6839 restored to their previous values by `set-window-configuration' and
6840 `window-state-put'.
6842 The car of each entry of this alist is the symbol specifying the
6843 parameter. The cdr is one of the following:
6845 nil means the parameter is neither saved by `window-state-get' nor by
6846 `current-window-configuration'.
6848 t means the parameter is saved by `current-window-configuration' and,
6849 provided its WRITABLE argument is nil, by `window-state-get'.
6851 The symbol `writable' means the parameter is saved unconditionally by
6852 both `current-window-configuration' and `window-state-get'. Do not use
6853 this value for parameters without read syntax (like windows or frames).
6855 Parameters not saved by `current-window-configuration' or
6856 `window-state-get' are left alone by `set-window-configuration'
6857 respectively are not installed by `window-state-put'. */);
6858 Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
6860 defsubr (&Sselected_window);
6861 defsubr (&Sminibuffer_window);
6862 defsubr (&Swindow_minibuffer_p);
6863 defsubr (&Swindowp);
6864 defsubr (&Swindow_valid_p);
6865 defsubr (&Swindow_live_p);
6866 defsubr (&Swindow_frame);
6867 defsubr (&Sframe_root_window);
6868 defsubr (&Sframe_first_window);
6869 defsubr (&Sframe_selected_window);
6870 defsubr (&Sset_frame_selected_window);
6871 defsubr (&Spos_visible_in_window_p);
6872 defsubr (&Swindow_line_height);
6873 defsubr (&Swindow_buffer);
6874 defsubr (&Swindow_parent);
6875 defsubr (&Swindow_top_child);
6876 defsubr (&Swindow_left_child);
6877 defsubr (&Swindow_next_sibling);
6878 defsubr (&Swindow_prev_sibling);
6879 defsubr (&Swindow_combination_limit);
6880 defsubr (&Sset_window_combination_limit);
6881 defsubr (&Swindow_use_time);
6882 defsubr (&Swindow_top_line);
6883 defsubr (&Swindow_left_column);
6884 defsubr (&Swindow_total_height);
6885 defsubr (&Swindow_total_width);
6886 defsubr (&Swindow_normal_size);
6887 defsubr (&Swindow_new_total);
6888 defsubr (&Swindow_new_normal);
6889 defsubr (&Sset_window_new_total);
6890 defsubr (&Sset_window_new_normal);
6891 defsubr (&Swindow_resize_apply);
6892 defsubr (&Swindow_body_height);
6893 defsubr (&Swindow_body_width);
6894 defsubr (&Swindow_hscroll);
6895 defsubr (&Sset_window_hscroll);
6896 defsubr (&Swindow_redisplay_end_trigger);
6897 defsubr (&Sset_window_redisplay_end_trigger);
6898 defsubr (&Swindow_edges);
6899 defsubr (&Swindow_pixel_edges);
6900 defsubr (&Swindow_absolute_pixel_edges);
6901 defsubr (&Swindow_inside_edges);
6902 defsubr (&Swindow_inside_pixel_edges);
6903 defsubr (&Swindow_inside_absolute_pixel_edges);
6904 defsubr (&Scoordinates_in_window_p);
6905 defsubr (&Swindow_at);
6906 defsubr (&Swindow_point);
6907 defsubr (&Swindow_start);
6908 defsubr (&Swindow_end);
6909 defsubr (&Sset_window_point);
6910 defsubr (&Sset_window_start);
6911 defsubr (&Swindow_dedicated_p);
6912 defsubr (&Sset_window_dedicated_p);
6913 defsubr (&Swindow_display_table);
6914 defsubr (&Sset_window_display_table);
6915 defsubr (&Snext_window);
6916 defsubr (&Sprevious_window);
6917 defsubr (&Sget_buffer_window);
6918 defsubr (&Sdelete_other_windows_internal);
6919 defsubr (&Sdelete_window_internal);
6920 defsubr (&Sresize_mini_window_internal);
6921 defsubr (&Sset_window_buffer);
6922 defsubr (&Srun_window_configuration_change_hook);
6923 defsubr (&Sselect_window);
6924 defsubr (&Sforce_window_update);
6925 defsubr (&Ssplit_window_internal);
6926 defsubr (&Sscroll_up);
6927 defsubr (&Sscroll_down);
6928 defsubr (&Sscroll_left);
6929 defsubr (&Sscroll_right);
6930 defsubr (&Sother_window_for_scrolling);
6931 defsubr (&Sscroll_other_window);
6932 defsubr (&Sminibuffer_selected_window);
6933 defsubr (&Srecenter);
6934 defsubr (&Swindow_text_height);
6935 defsubr (&Smove_to_window_line);
6936 defsubr (&Swindow_configuration_p);
6937 defsubr (&Swindow_configuration_frame);
6938 defsubr (&Sset_window_configuration);
6939 defsubr (&Scurrent_window_configuration);
6940 defsubr (&Sset_window_margins);
6941 defsubr (&Swindow_margins);
6942 defsubr (&Sset_window_fringes);
6943 defsubr (&Swindow_fringes);
6944 defsubr (&Sset_window_scroll_bars);
6945 defsubr (&Swindow_scroll_bars);
6946 defsubr (&Swindow_vscroll);
6947 defsubr (&Sset_window_vscroll);
6948 defsubr (&Scompare_window_configurations);
6949 defsubr (&Swindow_list);
6950 defsubr (&Swindow_list_1);
6951 defsubr (&Swindow_prev_buffers);
6952 defsubr (&Sset_window_prev_buffers);
6953 defsubr (&Swindow_next_buffers);
6954 defsubr (&Sset_window_next_buffers);
6955 defsubr (&Swindow_parameters);
6956 defsubr (&Swindow_parameter);
6957 defsubr (&Sset_window_parameter);
6960 void
6961 keys_of_window (void)
6963 initial_define_key (control_x_map, '<', "scroll-left");
6964 initial_define_key (control_x_map, '>', "scroll-right");
6966 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
6967 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6968 initial_define_key (meta_map, 'v', "scroll-down-command");