Merge from emacs-24; up to 2012-05-07T14:57:18Z!michael.albinus@gmx.de
[bpt/emacs.git] / src / window.c
1 /* Window creation, deletion and examination for GNU Emacs.
2 Does not include redisplay.
3 Copyright (C) 1985-1987, 1993-1998, 2000-2012
4 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
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.
12
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.
17
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/>. */
20
21 #include <config.h>
22
23 #define WINDOW_INLINE EXTERN_INLINE
24
25 #include <stdio.h>
26
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. */
42
43 #ifdef HAVE_X_WINDOWS
44 #include "xterm.h"
45 #endif /* HAVE_X_WINDOWS */
46 #ifdef WINDOWSNT
47 #include "w32term.h"
48 #endif
49 #ifdef MSDOS
50 #include "msdos.h"
51 #endif
52 #ifdef HAVE_NS
53 #include "nsterm.h"
54 #endif
55
56 Lisp_Object Qwindowp, Qwindow_live_p;
57 static Lisp_Object Qwindow_valid_p;
58 static Lisp_Object Qwindow_configuration_p, Qrecord_window_buffer;
59 static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
60 static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
61 static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
62 static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
63 static Lisp_Object Qsafe, Qabove, Qbelow;
64 static Lisp_Object Qclone_of;
65
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
92 /* This is the window in which the terminal's cursor should
93 be left when nothing is being done with it. This must
94 always be a leaf window, and its buffer is selected by
95 the top level editing loop at the end of each command.
96
97 This value is always the same as
98 FRAME_SELECTED_WINDOW (selected_frame). */
99 Lisp_Object selected_window;
100
101 /* A list of all windows for use by next_window and Fwindow_list.
102 Functions creating or deleting windows should invalidate this cache
103 by setting it to nil. */
104 Lisp_Object Vwindow_list;
105
106 /* The mini-buffer window of the selected frame.
107 Note that you cannot test for mini-bufferness of an arbitrary window
108 by comparing against this; but you can test for mini-bufferness of
109 the selected window. */
110 Lisp_Object minibuf_window;
111
112 /* Non-nil means it is the window whose mode line should be
113 shown as the selected window when the minibuffer is selected. */
114 Lisp_Object minibuf_selected_window;
115
116 /* Hook run at end of temp_output_buffer_show. */
117 static Lisp_Object Qtemp_buffer_show_hook;
118
119 /* Incremented for each window created. */
120 static int sequence_number;
121
122 /* Nonzero after init_window_once has finished. */
123 static int window_initialized;
124
125 /* Hook to run when window config changes. */
126 static Lisp_Object Qwindow_configuration_change_hook;
127
128 /* Used by the function window_scroll_pixel_based */
129 static int window_scroll_pixel_based_preserve_x;
130 static int window_scroll_pixel_based_preserve_y;
131
132 /* Same for window_scroll_line_based. */
133 static EMACS_INT window_scroll_preserve_hpos;
134 static EMACS_INT window_scroll_preserve_vpos;
135 \f
136 /* These setters are used only in this file, so they can be private. */
137 static inline void
138 wset_combination_limit (struct window *w, Lisp_Object val)
139 {
140 w->combination_limit = val;
141 }
142 static inline void
143 wset_dedicated (struct window *w, Lisp_Object val)
144 {
145 w->dedicated = val;
146 }
147 static inline void
148 wset_display_table (struct window *w, Lisp_Object val)
149 {
150 w->display_table = val;
151 }
152 static inline void
153 wset_hchild (struct window *w, Lisp_Object val)
154 {
155 w->hchild = val;
156 }
157 static inline void
158 wset_left_fringe_width (struct window *w, Lisp_Object val)
159 {
160 w->left_fringe_width = val;
161 }
162 static inline void
163 wset_left_margin_cols (struct window *w, Lisp_Object val)
164 {
165 w->left_margin_cols = val;
166 }
167 static inline void
168 wset_new_normal (struct window *w, Lisp_Object val)
169 {
170 w->new_normal = val;
171 }
172 static inline void
173 wset_new_total (struct window *w, Lisp_Object val)
174 {
175 w->new_total = val;
176 }
177 static inline void
178 wset_normal_cols (struct window *w, Lisp_Object val)
179 {
180 w->normal_cols = val;
181 }
182 static inline void
183 wset_normal_lines (struct window *w, Lisp_Object val)
184 {
185 w->normal_lines = val;
186 }
187 static inline void
188 wset_parent (struct window *w, Lisp_Object val)
189 {
190 w->parent = val;
191 }
192 static inline void
193 wset_pointm (struct window *w, Lisp_Object val)
194 {
195 w->pointm = val;
196 }
197 static inline void
198 wset_right_fringe_width (struct window *w, Lisp_Object val)
199 {
200 w->right_fringe_width = val;
201 }
202 static inline void
203 wset_right_margin_cols (struct window *w, Lisp_Object val)
204 {
205 w->right_margin_cols = val;
206 }
207 static inline void
208 wset_scroll_bar_width (struct window *w, Lisp_Object val)
209 {
210 w->scroll_bar_width = val;
211 }
212 static inline void
213 wset_start (struct window *w, Lisp_Object val)
214 {
215 w->start = val;
216 }
217 static inline void
218 wset_temslot (struct window *w, Lisp_Object val)
219 {
220 w->temslot = val;
221 }
222 static inline void
223 wset_vchild (struct window *w, Lisp_Object val)
224 {
225 w->vchild = val;
226 }
227 static inline void
228 wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
229 {
230 w->vertical_scroll_bar_type = val;
231 }
232 static inline void
233 wset_window_parameters (struct window *w, Lisp_Object val)
234 {
235 w->window_parameters = val;
236 }
237
238 struct window *
239 decode_live_window (register Lisp_Object window)
240 {
241 if (NILP (window))
242 return XWINDOW (selected_window);
243
244 CHECK_LIVE_WINDOW (window);
245 return XWINDOW (window);
246 }
247
248 static struct window *
249 decode_any_window (register Lisp_Object window)
250 {
251 struct window *w;
252
253 if (NILP (window))
254 return XWINDOW (selected_window);
255
256 CHECK_WINDOW (window);
257 w = XWINDOW (window);
258 return w;
259 }
260
261 static struct window *
262 decode_valid_window (register Lisp_Object window)
263 {
264 struct window *w;
265
266 if (NILP (window))
267 return XWINDOW (selected_window);
268
269 CHECK_VALID_WINDOW (window);
270 w = XWINDOW (window);
271 return w;
272 }
273
274 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
275 doc: /* Return t if OBJECT is a window and nil otherwise. */)
276 (Lisp_Object object)
277 {
278 return WINDOWP (object) ? Qt : Qnil;
279 }
280
281 DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
282 doc: /* Return t if OBJECT is a valid window and nil otherwise.
283 A valid window is either a window that displays a buffer or an internal
284 window. Deleted windows are not live. */)
285 (Lisp_Object object)
286 {
287 return WINDOW_VALID_P (object) ? Qt : Qnil;
288 }
289
290 DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
291 doc: /* Return t if OBJECT is a live window and nil otherwise.
292 A live window is a window that displays a buffer.
293 Internal windows and deleted windows are not live. */)
294 (Lisp_Object object)
295 {
296 return WINDOW_LIVE_P (object) ? Qt : Qnil;
297 }
298 \f
299 /* Frames and windows. */
300 DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
301 doc: /* Return the frame that window WINDOW is on.
302 WINDOW must be a valid window and defaults to the selected one. */)
303 (Lisp_Object window)
304 {
305 return decode_valid_window (window)->frame;
306 }
307
308 DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
309 doc: /* Return the root window of FRAME-OR-WINDOW.
310 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
311 With a frame argument, return that frame's root window.
312 With a window argument, return the root window of that window's frame. */)
313 (Lisp_Object frame_or_window)
314 {
315 Lisp_Object window;
316
317 if (NILP (frame_or_window))
318 window = SELECTED_FRAME ()->root_window;
319 else if (WINDOW_VALID_P (frame_or_window))
320 window = XFRAME (XWINDOW (frame_or_window)->frame)->root_window;
321 else
322 {
323 CHECK_LIVE_FRAME (frame_or_window);
324 window = XFRAME (frame_or_window)->root_window;
325 }
326
327 return window;
328 }
329
330 DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
331 doc: /* Return the minibuffer window for frame FRAME.
332 If FRAME is omitted or nil, it defaults to the selected frame. */)
333 (Lisp_Object frame)
334 {
335 if (NILP (frame))
336 frame = selected_frame;
337 CHECK_LIVE_FRAME (frame);
338 return FRAME_MINIBUF_WINDOW (XFRAME (frame));
339 }
340
341 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p,
342 Swindow_minibuffer_p, 0, 1, 0,
343 doc: /* Return non-nil if WINDOW is a minibuffer window.
344 WINDOW must be a valid window and defaults to the selected one. */)
345 (Lisp_Object window)
346 {
347 return MINI_WINDOW_P (decode_valid_window (window)) ? Qt : Qnil;
348 }
349
350 /* Don't move this to window.el - this must be a safe routine. */
351 DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
352 doc: /* Return the topmost, leftmost live window on FRAME-OR-WINDOW.
353 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
354 Else if FRAME-OR-WINDOW denotes a valid window, return the first window
355 of that window's frame. If FRAME-OR-WINDOW denotes a live frame, return
356 the first window of that frame. */)
357 (Lisp_Object frame_or_window)
358 {
359 Lisp_Object window;
360
361 if (NILP (frame_or_window))
362 window = SELECTED_FRAME ()->root_window;
363 else if (WINDOW_VALID_P (frame_or_window))
364 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->root_window;
365 else
366 {
367 CHECK_LIVE_FRAME (frame_or_window);
368 window = XFRAME (frame_or_window)->root_window;
369 }
370
371 while (NILP (XWINDOW (window)->buffer))
372 {
373 if (! NILP (XWINDOW (window)->hchild))
374 window = XWINDOW (window)->hchild;
375 else if (! NILP (XWINDOW (window)->vchild))
376 window = XWINDOW (window)->vchild;
377 else
378 emacs_abort ();
379 }
380
381 return window;
382 }
383
384 DEFUN ("frame-selected-window", Fframe_selected_window,
385 Sframe_selected_window, 0, 1, 0,
386 doc: /* Return the selected window of FRAME-OR-WINDOW.
387 If omitted, FRAME-OR-WINDOW defaults to the currently selected frame.
388 Else if FRAME-OR-WINDOW denotes a valid window, return the selected
389 window of that window's frame. If FRAME-OR-WINDOW denotes a live frame,
390 return the selected window of that frame. */)
391 (Lisp_Object frame_or_window)
392 {
393 Lisp_Object window;
394
395 if (NILP (frame_or_window))
396 window = SELECTED_FRAME ()->selected_window;
397 else if (WINDOW_VALID_P (frame_or_window))
398 window = XFRAME (WINDOW_FRAME (XWINDOW (frame_or_window)))->selected_window;
399 else
400 {
401 CHECK_LIVE_FRAME (frame_or_window);
402 window = XFRAME (frame_or_window)->selected_window;
403 }
404
405 return window;
406 }
407
408 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
409 Sset_frame_selected_window, 2, 3, 0,
410 doc: /* Set selected window of FRAME to WINDOW.
411 FRAME must be a live frame and defaults to the selected one. If FRAME
412 is the selected frame, this makes WINDOW the selected window. Optional
413 argument NORECORD non-nil means to neither change the order of recently
414 selected windows nor the buffer list. WINDOW must denote a live window.
415 Return WINDOW. */)
416 (Lisp_Object frame, Lisp_Object window, Lisp_Object norecord)
417 {
418 if (NILP (frame))
419 frame = selected_frame;
420
421 CHECK_LIVE_FRAME (frame);
422 CHECK_LIVE_WINDOW (window);
423
424 if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
425 error ("In `set-frame-selected-window', WINDOW is not on FRAME");
426
427 if (EQ (frame, selected_frame))
428 return Fselect_window (window, norecord);
429 else
430 {
431 fset_selected_window (XFRAME (frame), window);
432 return window;
433 }
434 }
435
436 DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
437 doc: /* Return the selected window.
438 The selected window is the window in which the standard cursor for
439 selected windows appears and to which many commands apply. */)
440 (void)
441 {
442 return selected_window;
443 }
444
445 int window_select_count;
446
447 /* If select_window is called with inhibit_point_swap non-zero it will
448 not store point of the old selected window's buffer back into that
449 window's pointm slot. This is needed by Fset_window_configuration to
450 avoid that the display routine is called with selected_window set to
451 Qnil causing a subsequent crash. */
452 static Lisp_Object
453 select_window (Lisp_Object window, Lisp_Object norecord, int inhibit_point_swap)
454 {
455 register struct window *w;
456 register struct window *ow;
457 struct frame *sf;
458
459 CHECK_LIVE_WINDOW (window);
460
461 w = XWINDOW (window);
462 w->frozen_window_start_p = 0;
463
464 if (NILP (norecord))
465 {
466 w->use_time = ++window_select_count;
467 record_buffer (w->buffer);
468 }
469
470 /* Make the selected window's buffer current. */
471 Fset_buffer (w->buffer);
472
473 if (EQ (window, selected_window) && !inhibit_point_swap)
474 return window;
475
476 sf = SELECTED_FRAME ();
477 if (XFRAME (WINDOW_FRAME (w)) != sf)
478 {
479 fset_selected_window (XFRAME (WINDOW_FRAME (w)), window);
480 /* Use this rather than Fhandle_switch_frame
481 so that FRAME_FOCUS_FRAME is moved appropriately as we
482 move around in the state where a minibuffer in a separate
483 frame is active. */
484 Fselect_frame (WINDOW_FRAME (w), norecord);
485 /* Fselect_frame called us back so we've done all the work already. */
486 eassert (EQ (window, selected_window));
487 return window;
488 }
489 else
490 fset_selected_window (sf, window);
491
492 /* Store the old selected window's buffer's point in pointm of the old
493 selected window. It belongs to that window, and when the window is
494 not selected, must be in the window. */
495 if (!inhibit_point_swap)
496 {
497 ow = XWINDOW (selected_window);
498 if (! NILP (ow->buffer))
499 set_marker_both (ow->pointm, ow->buffer,
500 BUF_PT (XBUFFER (ow->buffer)),
501 BUF_PT_BYTE (XBUFFER (ow->buffer)));
502 }
503
504 selected_window = window;
505 bset_last_selected_window (XBUFFER (w->buffer), window);
506
507 /* Go to the point recorded in the window.
508 This is important when the buffer is in more
509 than one window. It also matters when
510 redisplay_window has altered point after scrolling,
511 because it makes the change only in the window. */
512 {
513 register ptrdiff_t new_point = marker_position (w->pointm);
514 if (new_point < BEGV)
515 SET_PT (BEGV);
516 else if (new_point > ZV)
517 SET_PT (ZV);
518 else
519 SET_PT (new_point);
520 }
521
522 windows_or_buffers_changed++;
523 return window;
524 }
525
526 DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
527 doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
528 Also make WINDOW's buffer current and make WINDOW the frame's selected
529 window. Return WINDOW.
530
531 Optional second arg NORECORD non-nil means do not put this buffer at the
532 front of the buffer list and do not make this window the most recently
533 selected one.
534
535 Note that the main editor command loop sets the current buffer to the
536 buffer of the selected window before each command. */)
537 (register Lisp_Object window, Lisp_Object norecord)
538 {
539 return select_window (window, norecord, 0);
540 }
541 \f
542 DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
543 doc: /* Return the buffer displayed in window WINDOW.
544 If WINDOW is omitted or nil, it defaults to the selected window.
545 Return nil for an internal window or a deleted window. */)
546 (Lisp_Object window)
547 {
548 return decode_any_window (window)->buffer;
549 }
550
551 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
552 doc: /* Return the parent window of window WINDOW.
553 WINDOW must be a valid window and defaults to the selected one.
554 Return nil for a window with no parent (e.g. a root window). */)
555 (Lisp_Object window)
556 {
557 return decode_valid_window (window)->parent;
558 }
559
560 DEFUN ("window-top-child", Fwindow_top_child, Swindow_top_child, 1, 1, 0,
561 doc: /* Return the topmost child window of window WINDOW.
562 WINDOW must be a valid window and defaults to the selected one.
563 Return nil if WINDOW is a live window (live windows have no children).
564 Return nil if WINDOW is an internal window whose children form a
565 horizontal combination. */)
566 (Lisp_Object window)
567 {
568 CHECK_WINDOW (window);
569 return decode_valid_window (window)->vchild;
570 }
571
572 DEFUN ("window-left-child", Fwindow_left_child, Swindow_left_child, 1, 1, 0,
573 doc: /* Return the leftmost child window of window WINDOW.
574 WINDOW must be a valid window and defaults to the selected one.
575 Return nil if WINDOW is a live window (live windows have no children).
576 Return nil if WINDOW is an internal window whose children form a
577 vertical combination. */)
578 (Lisp_Object window)
579 {
580 CHECK_WINDOW (window);
581 return decode_valid_window (window)->hchild;
582 }
583
584 DEFUN ("window-next-sibling", Fwindow_next_sibling, Swindow_next_sibling, 0, 1, 0,
585 doc: /* Return the next sibling window of window WINDOW.
586 WINDOW must be a valid window and defaults to the selected one.
587 Return nil if WINDOW has no next sibling. */)
588 (Lisp_Object window)
589 {
590 return decode_valid_window (window)->next;
591 }
592
593 DEFUN ("window-prev-sibling", Fwindow_prev_sibling, Swindow_prev_sibling, 0, 1, 0,
594 doc: /* Return the previous sibling window of window WINDOW.
595 WINDOW must be a valid window and defaults to the selected one.
596 Return nil if WINDOW has no previous sibling. */)
597 (Lisp_Object window)
598 {
599 return decode_valid_window (window)->prev;
600 }
601
602 DEFUN ("window-combination-limit", Fwindow_combination_limit, Swindow_combination_limit, 1, 1, 0,
603 doc: /* Return combination limit of window WINDOW.
604 WINDOW must be a valid window and defaults to the selected one.
605 If the return value is nil, child windows of WINDOW can be recombined with
606 WINDOW's siblings. A return value of t means that child windows of
607 WINDOW are never \(re-)combined with WINDOW's siblings. */)
608 (Lisp_Object window)
609 {
610 return decode_valid_window (window)->combination_limit;
611 }
612
613 DEFUN ("set-window-combination-limit", Fset_window_combination_limit, Sset_window_combination_limit, 2, 2, 0,
614 doc: /* Set combination limit of window WINDOW to LIMIT; return LIMIT.
615 WINDOW must be a valid window and defaults to the selected one.
616 If LIMIT is nil, child windows of WINDOW can be recombined with
617 WINDOW's siblings. LIMIT t means that child windows of WINDOW are
618 never \(re-)combined with WINDOW's siblings. Other values are reserved
619 for future use. */)
620 (Lisp_Object window, Lisp_Object limit)
621 {
622 wset_combination_limit (decode_valid_window (window), limit);
623 return limit;
624 }
625
626 DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
627 doc: /* Return the use time of window WINDOW.
628 WINDOW must be a live window and defaults to the selected one.
629 The window with the highest use time is the most recently selected
630 one. The window with the lowest use time is the least recently
631 selected one. */)
632 (Lisp_Object window)
633 {
634 return make_number (decode_live_window (window)->use_time);
635 }
636 \f
637 DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 1, 0,
638 doc: /* Return the total height, in lines, of window WINDOW.
639 WINDOW must be a valid window and defaults to the selected one.
640
641 The return value includes the mode line and header line, if any.
642 If WINDOW is an internal window, the total height is the height
643 of the screen areas spanned by its children.
644
645 On a graphical display, this total height is reported as an
646 integer multiple of the default character height. */)
647 (Lisp_Object window)
648 {
649 return decode_valid_window (window)->total_lines;
650 }
651
652 DEFUN ("window-total-width", Fwindow_total_width, Swindow_total_width, 0, 1, 0,
653 doc: /* Return the total width, in columns, of window WINDOW.
654 WINDOW must be a valid window and defaults to the selected one.
655
656 The return value includes any vertical dividers or scroll bars
657 belonging to WINDOW. If WINDOW is an internal window, the total width
658 is the width of the screen areas spanned by its children.
659
660 On a graphical display, this total width is reported as an
661 integer multiple of the default character width. */)
662 (Lisp_Object window)
663 {
664 return decode_valid_window (window)->total_cols;
665 }
666
667 DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
668 doc: /* Return the new total size of window WINDOW.
669 WINDOW must be a valid window and defaults to the selected one. */)
670 (Lisp_Object window)
671 {
672 return decode_valid_window (window)->new_total;
673 }
674
675 DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
676 doc: /* Return the normal height of window WINDOW.
677 WINDOW must be a valid window and defaults to the selected one.
678 If HORIZONTAL is non-nil, return the normal width of WINDOW. */)
679 (Lisp_Object window, Lisp_Object horizontal)
680 {
681 struct window *w = decode_valid_window (window);
682
683 return NILP (horizontal) ? w->normal_lines : w->normal_cols;
684 }
685
686 DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
687 doc: /* Return new normal size of window WINDOW.
688 WINDOW must be a valid window and defaults to the selected one. */)
689 (Lisp_Object window)
690 {
691 return decode_valid_window (window)->new_normal;
692 }
693
694 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
695 doc: /* Return left column of window WINDOW.
696 This is the distance, in columns, between the left edge of WINDOW and
697 the left edge of the frame's window area. For instance, the return
698 value is 0 if there is no window to the left of WINDOW.
699
700 WINDOW must be a valid window and defaults to the selected one. */)
701 (Lisp_Object window)
702 {
703 return decode_valid_window (window)->left_col;
704 }
705
706 DEFUN ("window-top-line", Fwindow_top_line, Swindow_top_line, 0, 1, 0,
707 doc: /* Return top line of window WINDOW.
708 This is the distance, in lines, between the top of WINDOW and the top
709 of the frame's window area. For instance, the return value is 0 if
710 there is no window above WINDOW.
711
712 WINDOW must be a valid window and defaults to the selected one. */)
713 (Lisp_Object window)
714 {
715 return decode_valid_window (window)->top_line;
716 }
717
718 /* Return the number of lines of W's body. Don't count any mode or
719 header line of W. */
720
721 static int
722 window_body_lines (struct window *w)
723 {
724 int height = XFASTINT (w->total_lines);
725
726 if (!MINI_WINDOW_P (w))
727 {
728 if (WINDOW_WANTS_MODELINE_P (w))
729 --height;
730 if (WINDOW_WANTS_HEADER_LINE_P (w))
731 --height;
732 }
733
734 return height;
735 }
736
737 /* Return the number of columns of W's body. Don't count columns
738 occupied by the scroll bar or the vertical bar separating W from its
739 right sibling. On window-systems don't count fringes or display
740 margins either. */
741
742 int
743 window_body_cols (struct window *w)
744 {
745 struct frame *f = XFRAME (WINDOW_FRAME (w));
746 int width = XINT (w->total_cols);
747
748 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
749 /* Scroll bars occupy a few columns. */
750 width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
751 else if (!FRAME_WINDOW_P (f)
752 && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
753 /* The column of `|' characters separating side-by-side windows
754 occupies one column only. */
755 width -= 1;
756
757 if (FRAME_WINDOW_P (f))
758 /* On window-systems, fringes and display margins cannot be
759 used for normal text. */
760 width -= (WINDOW_FRINGE_COLS (w)
761 + WINDOW_LEFT_MARGIN_COLS (w)
762 + WINDOW_RIGHT_MARGIN_COLS (w));
763
764 return width;
765 }
766
767 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 1, 0,
768 doc: /* Return the height, in lines, of WINDOW's text area.
769 WINDOW must be a live window and defaults to the selected one.
770
771 The returned height does not include the mode line or header line.
772 On a graphical display, the height is expressed as an integer multiple
773 of the default character height. If a line at the bottom of the text
774 area is only partially visible, that counts as a whole line; to
775 exclude partially-visible lines, use `window-text-height'. */)
776 (Lisp_Object window)
777 {
778 struct window *w = decode_live_window (window);
779 return make_number (window_body_lines (w));
780 }
781
782 DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 1, 0,
783 doc: /* Return the width, in columns, of WINDOW's text area.
784 WINDOW must be a live window and defaults to the selected one.
785
786 The return value does not include any vertical dividers, fringe or
787 marginal areas, or scroll bars. On a graphical display, the width is
788 expressed as an integer multiple of the default character width. */)
789 (Lisp_Object window)
790 {
791 struct window *w = decode_live_window (window);
792 return make_number (window_body_cols (w));
793 }
794
795 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
796 doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
797 WINDOW must be a live window and defaults to the selected one. */)
798 (Lisp_Object window)
799 {
800 return make_number (decode_live_window (window)->hscroll);
801 }
802
803 /* Set W's horizontal scroll amount to HSCROLL clipped to a reasonable
804 range, returning the new amount as a fixnum. */
805 static Lisp_Object
806 set_window_hscroll (struct window *w, EMACS_INT hscroll)
807 {
808 /* Horizontal scrolling has problems with large scroll amounts.
809 It's too slow with long lines, and even with small lines the
810 display can be messed up. For now, though, impose only the limits
811 required by the internal representation: horizontal scrolling must
812 fit in fixnum (since it's visible to Elisp) and into ptrdiff_t
813 (since it's stored in a ptrdiff_t). */
814 ptrdiff_t hscroll_max = min (MOST_POSITIVE_FIXNUM, PTRDIFF_MAX);
815 ptrdiff_t new_hscroll = clip_to_bounds (0, hscroll, hscroll_max);
816
817 /* Prevent redisplay shortcuts when changing the hscroll. */
818 if (w->hscroll != new_hscroll)
819 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
820
821 w->hscroll = new_hscroll;
822 return make_number (new_hscroll);
823 }
824
825 DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
826 doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
827 WINDOW must be a live window and defaults to the selected one.
828 Clip the number to a reasonable value if out of range.
829 Return the new number. NCOL should be zero or positive.
830
831 Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
832 window so that the location of point moves off-window. */)
833 (Lisp_Object window, Lisp_Object ncol)
834 {
835 struct window *w = decode_live_window (window);
836
837 CHECK_NUMBER (ncol);
838 return set_window_hscroll (w, XINT (ncol));
839 }
840
841 DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
842 Swindow_redisplay_end_trigger, 0, 1, 0,
843 doc: /* Return WINDOW's redisplay end trigger value.
844 WINDOW must be a live window and defaults to the selected one.
845 See `set-window-redisplay-end-trigger' for more information. */)
846 (Lisp_Object window)
847 {
848 return decode_live_window (window)->redisplay_end_trigger;
849 }
850
851 DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
852 Sset_window_redisplay_end_trigger, 2, 2, 0,
853 doc: /* Set WINDOW's redisplay end trigger value to VALUE.
854 WINDOW must be a live window and defaults to the selected one. VALUE
855 should be a buffer position (typically a marker) or nil. If it is a
856 buffer position, then if redisplay in WINDOW reaches a position beyond
857 VALUE, the functions in `redisplay-end-trigger-functions' are called
858 with two arguments: WINDOW, and the end trigger value. Afterwards the
859 end-trigger value is reset to nil. */)
860 (register Lisp_Object window, Lisp_Object value)
861 {
862 wset_redisplay_end_trigger (decode_live_window (window), value);
863 return value;
864 }
865
866 DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
867 doc: /* Return a list of the edge coordinates of WINDOW.
868 WINDOW must be a valid window and defaults to the selected one.
869
870 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
871 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
872 0 at top left corner of frame.
873
874 RIGHT is one more than the rightmost column occupied by WINDOW. BOTTOM
875 is one more than the bottommost row occupied by WINDOW. The edges
876 include the space used by WINDOW's scroll bar, display margins, fringes,
877 header line, and/or mode line. For the edges of just the text area, use
878 `window-inside-edges'. */)
879 (Lisp_Object window)
880 {
881 register struct window *w = decode_valid_window (window);
882
883 return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
884 Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
885 Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
886 Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
887 Qnil))));
888 }
889
890 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
891 doc: /* Return a list of the edge pixel coordinates of WINDOW.
892 WINDOW must be a valid window and defaults to the selected one.
893
894 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
895 0, 0 at the top left corner of the frame.
896
897 RIGHT is one more than the rightmost x position occupied by WINDOW.
898 BOTTOM is one more than the bottommost y position occupied by WINDOW.
899 The pixel edges include the space used by WINDOW's scroll bar, display
900 margins, fringes, header line, and/or mode line. For the pixel edges
901 of just the text area, use `window-inside-pixel-edges'. */)
902 (Lisp_Object window)
903 {
904 register struct window *w = decode_valid_window (window);
905
906 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
907 Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
908 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
909 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
910 Qnil))));
911 }
912
913 static void
914 calc_absolute_offset (struct window *w, int *add_x, int *add_y)
915 {
916 struct frame *f = XFRAME (w->frame);
917 *add_y = f->top_pos;
918 #ifdef FRAME_MENUBAR_HEIGHT
919 *add_y += FRAME_MENUBAR_HEIGHT (f);
920 #endif
921 #ifdef FRAME_TOOLBAR_TOP_HEIGHT
922 *add_y += FRAME_TOOLBAR_TOP_HEIGHT (f);
923 #elif FRAME_TOOLBAR_HEIGHT
924 *add_y += FRAME_TOOLBAR_HEIGHT (f);
925 #endif
926 #ifdef FRAME_NS_TITLEBAR_HEIGHT
927 *add_y += FRAME_NS_TITLEBAR_HEIGHT (f);
928 #endif
929 *add_x = f->left_pos;
930 #ifdef FRAME_TOOLBAR_LEFT_WIDTH
931 *add_x += FRAME_TOOLBAR_LEFT_WIDTH (f);
932 #endif
933 }
934
935 DEFUN ("window-absolute-pixel-edges", Fwindow_absolute_pixel_edges,
936 Swindow_absolute_pixel_edges, 0, 1, 0,
937 doc: /* Return a list of the edge pixel coordinates of WINDOW.
938 WINDOW must be a valid window and defaults to the selected one.
939
940 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
941 0, 0 at the top left corner of the display.
942
943 RIGHT is one more than the rightmost x position occupied by WINDOW.
944 BOTTOM is one more than the bottommost y position occupied by WINDOW.
945 The pixel edges include the space used by WINDOW's scroll bar, display
946 margins, fringes, header line, and/or mode line. For the pixel edges
947 of just the text area, use `window-inside-absolute-pixel-edges'. */)
948 (Lisp_Object window)
949 {
950 register struct window *w = decode_valid_window (window);
951 int add_x, add_y;
952 calc_absolute_offset (w, &add_x, &add_y);
953
954 return Fcons (make_number (WINDOW_LEFT_EDGE_X (w) + add_x),
955 Fcons (make_number (WINDOW_TOP_EDGE_Y (w) + add_y),
956 Fcons (make_number (WINDOW_RIGHT_EDGE_X (w) + add_x),
957 Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w) + add_y),
958 Qnil))));
959 }
960
961 DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
962 doc: /* Return a list of the edge coordinates of WINDOW.
963 WINDOW must be a live window and defaults to the selected one.
964
965 The returned list has the form (LEFT TOP RIGHT BOTTOM). TOP and BOTTOM
966 count by lines, and LEFT and RIGHT count by columns, all relative to 0,
967 0 at top left corner of frame.
968
969 RIGHT is one more than the rightmost column of WINDOW's text area.
970 BOTTOM is one more than the bottommost row of WINDOW's text area. The
971 inside edges do not include the space used by the WINDOW's scroll bar,
972 display margins, fringes, header line, and/or mode line. */)
973 (Lisp_Object window)
974 {
975 register struct window *w = decode_live_window (window);
976
977 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
978 + WINDOW_LEFT_MARGIN_COLS (w)
979 + WINDOW_LEFT_FRINGE_COLS (w)),
980 make_number (WINDOW_TOP_EDGE_LINE (w)
981 + WINDOW_HEADER_LINE_LINES (w)),
982 make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
983 - WINDOW_RIGHT_MARGIN_COLS (w)
984 - WINDOW_RIGHT_FRINGE_COLS (w)),
985 make_number (WINDOW_BOTTOM_EDGE_LINE (w)
986 - WINDOW_MODE_LINE_LINES (w)));
987 }
988
989 DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
990 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
991 WINDOW must be a live window and defaults to the selected one.
992
993 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
994 (0,0) at the top left corner of the frame's window area.
995
996 RIGHT is one more than the rightmost x position of WINDOW's text area.
997 BOTTOM is one more than the bottommost y position of WINDOW's text area.
998 The inside edges do not include the space used by WINDOW's scroll bar,
999 display margins, fringes, header line, and/or mode line. */)
1000 (Lisp_Object window)
1001 {
1002 register struct window *w = decode_live_window (window);
1003
1004 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
1005 + WINDOW_LEFT_MARGIN_WIDTH (w)
1006 + WINDOW_LEFT_FRINGE_WIDTH (w)),
1007 make_number (WINDOW_TOP_EDGE_Y (w)
1008 + WINDOW_HEADER_LINE_HEIGHT (w)),
1009 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
1010 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1011 - WINDOW_RIGHT_FRINGE_WIDTH (w)),
1012 make_number (WINDOW_BOTTOM_EDGE_Y (w)
1013 - WINDOW_MODE_LINE_HEIGHT (w)));
1014 }
1015
1016 DEFUN ("window-inside-absolute-pixel-edges",
1017 Fwindow_inside_absolute_pixel_edges,
1018 Swindow_inside_absolute_pixel_edges, 0, 1, 0,
1019 doc: /* Return a list of the edge pixel coordinates of WINDOW's text area.
1020 WINDOW must be a live window and defaults to the selected one.
1021
1022 The returned list has the form (LEFT TOP RIGHT BOTTOM), all relative to
1023 (0,0) at the top left corner of the frame's window area.
1024
1025 RIGHT is one more than the rightmost x position of WINDOW's text area.
1026 BOTTOM is one more than the bottommost y position of WINDOW's text area.
1027 The inside edges do not include the space used by WINDOW's scroll bar,
1028 display margins, fringes, header line, and/or mode line. */)
1029 (Lisp_Object window)
1030 {
1031 register struct window *w = decode_live_window (window);
1032 int add_x, add_y;
1033 calc_absolute_offset (w, &add_x, &add_y);
1034
1035 return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
1036 + WINDOW_LEFT_MARGIN_WIDTH (w)
1037 + WINDOW_LEFT_FRINGE_WIDTH (w) + add_x),
1038 make_number (WINDOW_TOP_EDGE_Y (w)
1039 + WINDOW_HEADER_LINE_HEIGHT (w) + add_y),
1040 make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
1041 - WINDOW_RIGHT_MARGIN_WIDTH (w)
1042 - WINDOW_RIGHT_FRINGE_WIDTH (w) + add_x),
1043 make_number (WINDOW_BOTTOM_EDGE_Y (w)
1044 - WINDOW_MODE_LINE_HEIGHT (w) + add_y));
1045 }
1046
1047 /* Test if the character at column X, row Y is within window W.
1048 If it is not, return ON_NOTHING;
1049 if it is in the window's text area, return ON_TEXT;
1050 if it is on the window's modeline, return ON_MODE_LINE;
1051 if it is on the border between the window and its right sibling,
1052 return ON_VERTICAL_BORDER.
1053 if it is on a scroll bar, return ON_SCROLL_BAR.
1054 if it is on the window's top line, return ON_HEADER_LINE;
1055 if it is in left or right fringe of the window,
1056 return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
1057 if it is in the marginal area to the left/right of the window,
1058 return ON_LEFT_MARGIN or ON_RIGHT_MARGIN.
1059
1060 X and Y are frame relative pixel coordinates. */
1061
1062 static enum window_part
1063 coordinates_in_window (register struct window *w, int x, int y)
1064 {
1065 struct frame *f = XFRAME (WINDOW_FRAME (w));
1066 enum window_part part;
1067 int ux = FRAME_COLUMN_WIDTH (f);
1068 int left_x = WINDOW_LEFT_EDGE_X (w);
1069 int right_x = WINDOW_RIGHT_EDGE_X (w);
1070 int top_y = WINDOW_TOP_EDGE_Y (w);
1071 int bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
1072 /* The width of the area where the vertical line can be dragged.
1073 (Between mode lines for instance. */
1074 int grabbable_width = ux;
1075 int lmargin_width, rmargin_width, text_left, text_right;
1076
1077 /* Outside any interesting row or column? */
1078 if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
1079 return ON_NOTHING;
1080
1081 /* On the mode line or header line? */
1082 if ((WINDOW_WANTS_MODELINE_P (w)
1083 && y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
1084 && (part = ON_MODE_LINE))
1085 || (WINDOW_WANTS_HEADER_LINE_P (w)
1086 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
1087 && (part = ON_HEADER_LINE)))
1088 {
1089 /* If it's under/over the scroll bar portion of the mode/header
1090 line, say it's on the vertical line. That's to be able to
1091 resize windows horizontally in case we're using toolkit scroll
1092 bars. Note: If scrollbars are on the left, the window that
1093 must be eventually resized is that on the left of WINDOW. */
1094 if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1095 && !WINDOW_LEFTMOST_P (w)
1096 && eabs (x - left_x) < grabbable_width)
1097 || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
1098 && !WINDOW_RIGHTMOST_P (w)
1099 && eabs (x - right_x) < grabbable_width))
1100 return ON_VERTICAL_BORDER;
1101 else
1102 return part;
1103 }
1104
1105 /* In what's below, we subtract 1 when computing right_x because we
1106 want the rightmost pixel, which is given by left_pixel+width-1. */
1107 if (w->pseudo_window_p)
1108 {
1109 left_x = 0;
1110 right_x = WINDOW_TOTAL_WIDTH (w) - 1;
1111 }
1112 else
1113 {
1114 left_x = WINDOW_BOX_LEFT_EDGE_X (w);
1115 right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
1116 }
1117
1118 /* Outside any interesting column? */
1119 if (x < left_x || x > right_x)
1120 return ON_SCROLL_BAR;
1121
1122 lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
1123 rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
1124
1125 text_left = window_box_left (w, TEXT_AREA);
1126 text_right = text_left + window_box_width (w, TEXT_AREA);
1127
1128 if (FRAME_WINDOW_P (f))
1129 {
1130 if (!w->pseudo_window_p
1131 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
1132 && !WINDOW_RIGHTMOST_P (w)
1133 && (eabs (x - right_x) < grabbable_width))
1134 return ON_VERTICAL_BORDER;
1135 }
1136 /* Need to say "x > right_x" rather than >=, since on character
1137 terminals, the vertical line's x coordinate is right_x. */
1138 else if (!w->pseudo_window_p
1139 && !WINDOW_RIGHTMOST_P (w)
1140 && x > right_x - ux)
1141 return ON_VERTICAL_BORDER;
1142
1143 if (x < text_left)
1144 {
1145 if (lmargin_width > 0
1146 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1147 ? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
1148 : (x < left_x + lmargin_width)))
1149 return ON_LEFT_MARGIN;
1150
1151 return ON_LEFT_FRINGE;
1152 }
1153
1154 if (x >= text_right)
1155 {
1156 if (rmargin_width > 0
1157 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1158 ? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
1159 : (x >= right_x - rmargin_width)))
1160 return ON_RIGHT_MARGIN;
1161
1162 return ON_RIGHT_FRINGE;
1163 }
1164
1165 /* Everything special ruled out - must be on text area */
1166 return ON_TEXT;
1167 }
1168
1169 /* Take X is the frame-relative pixel x-coordinate, and return the
1170 x-coordinate relative to part PART of window W. */
1171 int
1172 window_relative_x_coord (struct window *w, enum window_part part, int x)
1173 {
1174 int left_x = (w->pseudo_window_p) ? 0 : WINDOW_BOX_LEFT_EDGE_X (w);
1175
1176 switch (part)
1177 {
1178 case ON_TEXT:
1179 return x - window_box_left (w, TEXT_AREA);
1180
1181 case ON_LEFT_FRINGE:
1182 return x - left_x;
1183
1184 case ON_RIGHT_FRINGE:
1185 return x - left_x - WINDOW_LEFT_FRINGE_WIDTH (w);
1186
1187 case ON_LEFT_MARGIN:
1188 return (x - left_x
1189 - ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1190 ? WINDOW_LEFT_FRINGE_WIDTH (w) : 0));
1191
1192 case ON_RIGHT_MARGIN:
1193 return (x + 1
1194 - ((w->pseudo_window_p)
1195 ? WINDOW_TOTAL_WIDTH (w)
1196 : WINDOW_BOX_RIGHT_EDGE_X (w))
1197 + window_box_width (w, RIGHT_MARGIN_AREA)
1198 + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1199 ? WINDOW_RIGHT_FRINGE_WIDTH (w) : 0));
1200 }
1201
1202 /* ON_SCROLL_BAR, ON_NOTHING, and ON_VERTICAL_BORDER: */
1203 return 0;
1204 }
1205
1206
1207 DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
1208 Scoordinates_in_window_p, 2, 2, 0,
1209 doc: /* Return non-nil if COORDINATES are in WINDOW.
1210 WINDOW must be a live window and defaults to the selected one.
1211 COORDINATES is a cons of the form (X . Y), X and Y being distances
1212 measured in characters from the upper-left corner of the frame.
1213 \(0 . 0) denotes the character in the upper left corner of the
1214 frame.
1215 If COORDINATES are in the text portion of WINDOW,
1216 the coordinates relative to the window are returned.
1217 If they are in the mode line of WINDOW, `mode-line' is returned.
1218 If they are in the top mode line of WINDOW, `header-line' is returned.
1219 If they are in the left fringe of WINDOW, `left-fringe' is returned.
1220 If they are in the right fringe of WINDOW, `right-fringe' is returned.
1221 If they are on the border between WINDOW and its right sibling,
1222 `vertical-line' is returned.
1223 If they are in the windows's left or right marginal areas, `left-margin'\n\
1224 or `right-margin' is returned. */)
1225 (register Lisp_Object coordinates, Lisp_Object window)
1226 {
1227 struct window *w;
1228 struct frame *f;
1229 int x, y;
1230 Lisp_Object lx, ly;
1231
1232 w = decode_live_window (window);
1233 f = XFRAME (w->frame);
1234 CHECK_CONS (coordinates);
1235 lx = Fcar (coordinates);
1236 ly = Fcdr (coordinates);
1237 CHECK_NUMBER_OR_FLOAT (lx);
1238 CHECK_NUMBER_OR_FLOAT (ly);
1239 x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
1240 y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
1241
1242 switch (coordinates_in_window (w, x, y))
1243 {
1244 case ON_NOTHING:
1245 return Qnil;
1246
1247 case ON_TEXT:
1248 /* Convert X and Y to window relative pixel coordinates, and
1249 return the canonical char units. */
1250 x -= window_box_left (w, TEXT_AREA);
1251 y -= WINDOW_TOP_EDGE_Y (w);
1252 return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
1253 FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
1254
1255 case ON_MODE_LINE:
1256 return Qmode_line;
1257
1258 case ON_VERTICAL_BORDER:
1259 return Qvertical_line;
1260
1261 case ON_HEADER_LINE:
1262 return Qheader_line;
1263
1264 case ON_LEFT_FRINGE:
1265 return Qleft_fringe;
1266
1267 case ON_RIGHT_FRINGE:
1268 return Qright_fringe;
1269
1270 case ON_LEFT_MARGIN:
1271 return Qleft_margin;
1272
1273 case ON_RIGHT_MARGIN:
1274 return Qright_margin;
1275
1276 case ON_SCROLL_BAR:
1277 /* Historically we are supposed to return nil in this case. */
1278 return Qnil;
1279
1280 default:
1281 emacs_abort ();
1282 }
1283 }
1284
1285
1286 /* Callback for foreach_window, used in window_from_coordinates.
1287 Check if window W contains coordinates specified by USER_DATA which
1288 is actually a pointer to a struct check_window_data CW.
1289
1290 Check if window W contains coordinates *CW->x and *CW->y. If it
1291 does, return W in *CW->window, as Lisp_Object, and return in
1292 *CW->part the part of the window under coordinates *X,*Y. Return
1293 zero from this function to stop iterating over windows. */
1294
1295 struct check_window_data
1296 {
1297 Lisp_Object *window;
1298 int x, y;
1299 enum window_part *part;
1300 };
1301
1302 static int
1303 check_window_containing (struct window *w, void *user_data)
1304 {
1305 struct check_window_data *cw = (struct check_window_data *) user_data;
1306 enum window_part found;
1307 int continue_p = 1;
1308
1309 found = coordinates_in_window (w, cw->x, cw->y);
1310 if (found != ON_NOTHING)
1311 {
1312 *cw->part = found;
1313 XSETWINDOW (*cw->window, w);
1314 continue_p = 0;
1315 }
1316
1317 return continue_p;
1318 }
1319
1320
1321 /* Find the window containing frame-relative pixel position X/Y and
1322 return it as a Lisp_Object.
1323
1324 If X, Y is on one of the window's special `window_part' elements,
1325 set *PART to the id of that element.
1326
1327 If there is no window under X, Y return nil and leave *PART
1328 unmodified. TOOL_BAR_P non-zero means detect tool-bar windows.
1329
1330 This function was previously implemented with a loop cycling over
1331 windows with Fnext_window, and starting with the frame's selected
1332 window. It turned out that this doesn't work with an
1333 implementation of next_window using Vwindow_list, because
1334 FRAME_SELECTED_WINDOW (F) is not always contained in the window
1335 tree of F when this function is called asynchronously from
1336 note_mouse_highlight. The original loop didn't terminate in this
1337 case. */
1338
1339 Lisp_Object
1340 window_from_coordinates (struct frame *f, int x, int y,
1341 enum window_part *part, int tool_bar_p)
1342 {
1343 Lisp_Object window;
1344 struct check_window_data cw;
1345 enum window_part dummy;
1346
1347 if (part == 0)
1348 part = &dummy;
1349
1350 window = Qnil;
1351 cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
1352 foreach_window (f, check_window_containing, &cw);
1353
1354 /* If not found above, see if it's in the tool bar window, if a tool
1355 bar exists. */
1356 if (NILP (window)
1357 && tool_bar_p
1358 && WINDOWP (f->tool_bar_window)
1359 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
1360 && (coordinates_in_window (XWINDOW (f->tool_bar_window), x, y)
1361 != ON_NOTHING))
1362 {
1363 *part = ON_TEXT;
1364 window = f->tool_bar_window;
1365 }
1366
1367 return window;
1368 }
1369
1370 DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
1371 doc: /* Return window containing coordinates X and Y on FRAME.
1372 FRAME must be a live frame and defaults to the selected one.
1373 The top left corner of the frame is considered to be row 0,
1374 column 0. */)
1375 (Lisp_Object x, Lisp_Object y, Lisp_Object frame)
1376 {
1377 struct frame *f;
1378
1379 if (NILP (frame))
1380 frame = selected_frame;
1381 CHECK_LIVE_FRAME (frame);
1382 f = XFRAME (frame);
1383
1384 /* Check that arguments are integers or floats. */
1385 CHECK_NUMBER_OR_FLOAT (x);
1386 CHECK_NUMBER_OR_FLOAT (y);
1387
1388 return window_from_coordinates (f,
1389 (FRAME_PIXEL_X_FROM_CANON_X (f, x)
1390 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1391 (FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
1392 + FRAME_INTERNAL_BORDER_WIDTH (f)),
1393 0, 0);
1394 }
1395
1396 DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
1397 doc: /* Return current value of point in WINDOW.
1398 WINDOW must be a live window and defaults to the selected one.
1399
1400 For a nonselected window, this is the value point would have if that
1401 window were selected.
1402
1403 Note that, when WINDOW is selected, the value returned is the same as
1404 that returned by `point' for WINDOW's buffer. It would be more strictly
1405 correct to return the `top-level' value of `point', outside of any
1406 `save-excursion' forms. But that is hard to define. */)
1407 (Lisp_Object window)
1408 {
1409 register struct window *w = decode_live_window (window);
1410
1411 if (w == XWINDOW (selected_window))
1412 return make_number (BUF_PT (XBUFFER (w->buffer)));
1413 else
1414 return Fmarker_position (w->pointm);
1415 }
1416
1417 DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
1418 doc: /* Return position at which display currently starts in WINDOW.
1419 WINDOW must be a live window and defaults to the selected one.
1420 This is updated by redisplay or by calling `set-window-start'. */)
1421 (Lisp_Object window)
1422 {
1423 return Fmarker_position (decode_live_window (window)->start);
1424 }
1425
1426 /* This is text temporarily removed from the doc string below.
1427
1428 This function returns nil if the position is not currently known.
1429 That happens when redisplay is preempted and doesn't finish.
1430 If in that case you want to compute where the end of the window would
1431 have been if redisplay had finished, do this:
1432 (save-excursion
1433 (goto-char (window-start window))
1434 (vertical-motion (1- (window-height window)) window)
1435 (point))") */
1436
1437 DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
1438 doc: /* Return position at which display currently ends in WINDOW.
1439 WINDOW must be a live window and defaults to the selected one.
1440 This is updated by redisplay, when it runs to completion.
1441 Simply changing the buffer text or setting `window-start'
1442 does not update this value.
1443 Return nil if there is no recorded value. (This can happen if the
1444 last redisplay of WINDOW was preempted, and did not finish.)
1445 If UPDATE is non-nil, compute the up-to-date position
1446 if it isn't already recorded. */)
1447 (Lisp_Object window, Lisp_Object update)
1448 {
1449 Lisp_Object value;
1450 struct window *w = decode_live_window (window);
1451 Lisp_Object buf;
1452 struct buffer *b;
1453
1454 buf = w->buffer;
1455 CHECK_BUFFER (buf);
1456 b = XBUFFER (buf);
1457
1458 #if 0 /* This change broke some things. We should make it later. */
1459 /* If we don't know the end position, return nil.
1460 The user can compute it with vertical-motion if he wants to.
1461 It would be nicer to do it automatically,
1462 but that's so slow that it would probably bother people. */
1463 if (NILP (w->window_end_valid))
1464 return Qnil;
1465 #endif
1466
1467 if (! NILP (update)
1468 && ! (! NILP (w->window_end_valid)
1469 && w->last_modified >= BUF_MODIFF (b)
1470 && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b))
1471 && !noninteractive)
1472 {
1473 struct text_pos startp;
1474 struct it it;
1475 struct buffer *old_buffer = NULL;
1476 void *itdata = NULL;
1477
1478 /* Cannot use Fvertical_motion because that function doesn't
1479 cope with variable-height lines. */
1480 if (b != current_buffer)
1481 {
1482 old_buffer = current_buffer;
1483 set_buffer_internal (b);
1484 }
1485
1486 /* In case W->start is out of the range, use something
1487 reasonable. This situation occurred when loading a file with
1488 `-l' containing a call to `rmail' with subsequent other
1489 commands. At the end, W->start happened to be BEG, while
1490 rmail had already narrowed the buffer. */
1491 if (XMARKER (w->start)->charpos < BEGV)
1492 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
1493 else if (XMARKER (w->start)->charpos > ZV)
1494 SET_TEXT_POS (startp, ZV, ZV_BYTE);
1495 else
1496 SET_TEXT_POS_FROM_MARKER (startp, w->start);
1497
1498 itdata = bidi_shelve_cache ();
1499 start_display (&it, w, startp);
1500 move_it_vertically (&it, window_box_height (w));
1501 if (it.current_y < it.last_visible_y)
1502 move_it_past_eol (&it);
1503 value = make_number (IT_CHARPOS (it));
1504 bidi_unshelve_cache (itdata, 0);
1505
1506 if (old_buffer)
1507 set_buffer_internal (old_buffer);
1508 }
1509 else
1510 XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
1511
1512 return value;
1513 }
1514
1515 DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
1516 doc: /* Make point value in WINDOW be at position POS in WINDOW's buffer.
1517 WINDOW must be a live window and defaults to the selected one.
1518 Return POS. */)
1519 (Lisp_Object window, Lisp_Object pos)
1520 {
1521 register struct window *w = decode_live_window (window);
1522
1523 CHECK_NUMBER_COERCE_MARKER (pos);
1524
1525 if (w == XWINDOW (selected_window))
1526 {
1527 if (XBUFFER (w->buffer) == current_buffer)
1528 Fgoto_char (pos);
1529 else
1530 {
1531 struct buffer *old_buffer = current_buffer;
1532
1533 set_buffer_internal (XBUFFER (w->buffer));
1534 Fgoto_char (pos);
1535 set_buffer_internal (old_buffer);
1536 }
1537 }
1538 else
1539 {
1540 set_marker_restricted (w->pointm, pos, w->buffer);
1541 /* We have to make sure that redisplay updates the window to show
1542 the new value of point. */
1543 ++windows_or_buffers_changed;
1544 }
1545
1546 return pos;
1547 }
1548
1549 DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
1550 doc: /* Make display in WINDOW start at position POS in WINDOW's buffer.
1551 WINDOW must be a live window and defaults to the selected one. Return
1552 POS. Optional third arg NOFORCE non-nil inhibits next redisplay from
1553 overriding motion of point in order to display at this exact start. */)
1554 (Lisp_Object window, Lisp_Object pos, Lisp_Object noforce)
1555 {
1556 register struct window *w = decode_live_window (window);
1557
1558 CHECK_NUMBER_COERCE_MARKER (pos);
1559 set_marker_restricted (w->start, pos, w->buffer);
1560 /* this is not right, but much easier than doing what is right. */
1561 w->start_at_line_beg = 0;
1562 if (NILP (noforce))
1563 w->force_start = 1;
1564 w->update_mode_line = 1;
1565 w->last_modified = 0;
1566 w->last_overlay_modified = 0;
1567 if (!EQ (window, selected_window))
1568 windows_or_buffers_changed++;
1569
1570 return pos;
1571 }
1572
1573 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
1574 Spos_visible_in_window_p, 0, 3, 0,
1575 doc: /* Return non-nil if position POS is currently on the frame in WINDOW.
1576 WINDOW must be a live window and defaults to the selected one.
1577
1578 Return nil if that position is scrolled vertically out of view. If a
1579 character is only partially visible, nil is returned, unless the
1580 optional argument PARTIALLY is non-nil. If POS is only out of view
1581 because of horizontal scrolling, return non-nil. If POS is t, it
1582 specifies the position of the last visible glyph in WINDOW. POS
1583 defaults to point in WINDOW; WINDOW defaults to the selected window.
1584
1585 If POS is visible, return t if PARTIALLY is nil; if PARTIALLY is non-nil,
1586 return value is a list of 2 or 6 elements (X Y [RTOP RBOT ROWH VPOS]),
1587 where X and Y are the pixel coordinates relative to the top left corner
1588 of the window. The remaining elements are omitted if the character after
1589 POS is fully visible; otherwise, RTOP and RBOT are the number of pixels
1590 off-window at the top and bottom of the row, ROWH is the height of the
1591 display row, and VPOS is the row number (0-based) containing POS. */)
1592 (Lisp_Object pos, Lisp_Object window, Lisp_Object partially)
1593 {
1594 register struct window *w;
1595 register EMACS_INT posint;
1596 register struct buffer *buf;
1597 struct text_pos top;
1598 Lisp_Object in_window = Qnil;
1599 int rtop, rbot, rowh, vpos, fully_p = 1;
1600 int x, y;
1601
1602 w = decode_live_window (window);
1603 buf = XBUFFER (w->buffer);
1604 SET_TEXT_POS_FROM_MARKER (top, w->start);
1605
1606 if (EQ (pos, Qt))
1607 posint = -1;
1608 else if (!NILP (pos))
1609 {
1610 CHECK_NUMBER_COERCE_MARKER (pos);
1611 posint = XINT (pos);
1612 }
1613 else if (w == XWINDOW (selected_window))
1614 posint = PT;
1615 else
1616 posint = XMARKER (w->pointm)->charpos;
1617
1618 /* If position is above window start or outside buffer boundaries,
1619 or if window start is out of range, position is not visible. */
1620 if ((EQ (pos, Qt)
1621 || (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
1622 && CHARPOS (top) >= BUF_BEGV (buf)
1623 && CHARPOS (top) <= BUF_ZV (buf)
1624 && pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
1625 && (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
1626 in_window = Qt;
1627
1628 if (!NILP (in_window) && !NILP (partially))
1629 {
1630 Lisp_Object part = Qnil;
1631 if (!fully_p)
1632 part = list4 (make_number (rtop), make_number (rbot),
1633 make_number (rowh), make_number (vpos));
1634 in_window = Fcons (make_number (x),
1635 Fcons (make_number (y), part));
1636 }
1637
1638 return in_window;
1639 }
1640
1641 DEFUN ("window-line-height", Fwindow_line_height,
1642 Swindow_line_height, 0, 2, 0,
1643 doc: /* Return height in pixels of text line LINE in window WINDOW.
1644 WINDOW must be a live window and defaults to the selected one.
1645
1646 Return height of current line if LINE is omitted or nil. Return height of
1647 header or mode line if LINE is `header-line' or `mode-line'.
1648 Otherwise, LINE is a text line number starting from 0. A negative number
1649 counts from the end of the window.
1650
1651 Value is a list (HEIGHT VPOS YPOS OFFBOT), where HEIGHT is the height
1652 in pixels of the visible part of the line, VPOS and YPOS are the
1653 vertical position in lines and pixels of the line, relative to the top
1654 of the first text line, and OFFBOT is the number of off-window pixels at
1655 the bottom of the text line. If there are off-window pixels at the top
1656 of the (first) text line, YPOS is negative.
1657
1658 Return nil if window display is not up-to-date. In that case, use
1659 `pos-visible-in-window-p' to obtain the information. */)
1660 (Lisp_Object line, Lisp_Object window)
1661 {
1662 register struct window *w;
1663 register struct buffer *b;
1664 struct glyph_row *row, *end_row;
1665 int max_y, crop, i;
1666 EMACS_INT n;
1667
1668 w = decode_live_window (window);
1669
1670 if (noninteractive || w->pseudo_window_p)
1671 return Qnil;
1672
1673 CHECK_BUFFER (w->buffer);
1674 b = XBUFFER (w->buffer);
1675
1676 /* Fail if current matrix is not up-to-date. */
1677 if (NILP (w->window_end_valid)
1678 || current_buffer->clip_changed
1679 || current_buffer->prevent_redisplay_optimizations_p
1680 || w->last_modified < BUF_MODIFF (b)
1681 || w->last_overlay_modified < BUF_OVERLAY_MODIFF (b))
1682 return Qnil;
1683
1684 if (NILP (line))
1685 {
1686 i = w->cursor.vpos;
1687 if (i < 0 || i >= w->current_matrix->nrows
1688 || (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
1689 return Qnil;
1690 max_y = window_text_bottom_y (w);
1691 goto found_row;
1692 }
1693
1694 if (EQ (line, Qheader_line))
1695 {
1696 if (!WINDOW_WANTS_HEADER_LINE_P (w))
1697 return Qnil;
1698 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1699 if (!row->enabled_p)
1700 return Qnil;
1701 return list4 (make_number (row->height),
1702 make_number (0), make_number (0),
1703 make_number (0));
1704 }
1705
1706 if (EQ (line, Qmode_line))
1707 {
1708 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1709 if (!row->enabled_p)
1710 return Qnil;
1711 return list4 (make_number (row->height),
1712 make_number (0), /* not accurate */
1713 make_number (WINDOW_HEADER_LINE_HEIGHT (w)
1714 + window_text_bottom_y (w)),
1715 make_number (0));
1716 }
1717
1718 CHECK_NUMBER (line);
1719 n = XINT (line);
1720
1721 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
1722 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
1723 max_y = window_text_bottom_y (w);
1724 i = 0;
1725
1726 while ((n < 0 || i < n)
1727 && row <= end_row && row->enabled_p
1728 && row->y + row->height < max_y)
1729 row++, i++;
1730
1731 if (row > end_row || !row->enabled_p)
1732 return Qnil;
1733
1734 if (++n < 0)
1735 {
1736 if (-n > i)
1737 return Qnil;
1738 row += n;
1739 i += n;
1740 }
1741
1742 found_row:
1743 crop = max (0, (row->y + row->height) - max_y);
1744 return list4 (make_number (row->height + min (0, row->y) - crop),
1745 make_number (i),
1746 make_number (row->y),
1747 make_number (crop));
1748 }
1749
1750 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1751 0, 1, 0,
1752 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
1753 More precisely, return the value assigned by the last call of
1754 `set-window-dedicated-p' for WINDOW. Return nil if that function was
1755 never called with WINDOW as its argument, or the value set by that
1756 function was internally reset since its last call. WINDOW must be a
1757 live window and defaults to the selected one.
1758
1759 When a window is dedicated to its buffer, `display-buffer' will refrain
1760 from displaying another buffer in it. `get-lru-window' and
1761 `get-largest-window' treat dedicated windows specially.
1762 `delete-windows-on', `replace-buffer-in-windows', `quit-window' and
1763 `kill-buffer' can delete a dedicated window and the containing frame.
1764
1765 Functions like `set-window-buffer' may change the buffer displayed by a
1766 window, unless that window is "strongly" dedicated to its buffer, that
1767 is the value returned by `window-dedicated-p' is t. */)
1768 (Lisp_Object window)
1769 {
1770 return decode_live_window (window)->dedicated;
1771 }
1772
1773 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
1774 Sset_window_dedicated_p, 2, 2, 0,
1775 doc: /* Mark WINDOW as dedicated according to FLAG.
1776 WINDOW must be a live window and defaults to the selected one. FLAG
1777 non-nil means mark WINDOW as dedicated to its buffer. FLAG nil means
1778 mark WINDOW as non-dedicated. Return FLAG.
1779
1780 When a window is dedicated to its buffer, `display-buffer' will refrain
1781 from displaying another buffer in it. `get-lru-window' and
1782 `get-largest-window' treat dedicated windows specially.
1783 `delete-windows-on', `replace-buffer-in-windows', `quit-window',
1784 `quit-restore-window' and `kill-buffer' can delete a dedicated window
1785 and the containing frame.
1786
1787 As a special case, if FLAG is t, mark WINDOW as "strongly" dedicated to
1788 its buffer. Functions like `set-window-buffer' may change the buffer
1789 displayed by a window, unless that window is strongly dedicated to its
1790 buffer. If and when `set-window-buffer' displays another buffer in a
1791 window, it also makes sure that the window is no more dedicated. */)
1792 (Lisp_Object window, Lisp_Object flag)
1793 {
1794 wset_dedicated (decode_live_window (window), flag);
1795 return flag;
1796 }
1797
1798 DEFUN ("window-prev-buffers", Fwindow_prev_buffers, Swindow_prev_buffers,
1799 0, 1, 0,
1800 doc: /* Return buffers previously shown in WINDOW.
1801 WINDOW must be a live window and defaults to the selected one.
1802
1803 The return value is a list of elements (BUFFER WINDOW-START POS),
1804 where BUFFER is a buffer, WINDOW-START is the start position of the
1805 window for that buffer, and POS is a window-specific point value. */)
1806 (Lisp_Object window)
1807 {
1808 return decode_live_window (window)->prev_buffers;
1809 }
1810
1811 DEFUN ("set-window-prev-buffers", Fset_window_prev_buffers,
1812 Sset_window_prev_buffers, 2, 2, 0,
1813 doc: /* Set WINDOW's previous buffers to PREV-BUFFERS.
1814 WINDOW must be a live window and defaults to the selected one.
1815
1816 PREV-BUFFERS should be a list of elements (BUFFER WINDOW-START POS),
1817 where BUFFER is a buffer, WINDOW-START is the start position of the
1818 window for that buffer, and POS is a window-specific point value. */)
1819 (Lisp_Object window, Lisp_Object prev_buffers)
1820 {
1821 wset_prev_buffers (decode_live_window (window), prev_buffers);
1822 return prev_buffers;
1823 }
1824
1825 DEFUN ("window-next-buffers", Fwindow_next_buffers, Swindow_next_buffers,
1826 0, 1, 0,
1827 doc: /* Return list of buffers recently re-shown in WINDOW.
1828 WINDOW must be a live window and defaults to the selected one. */)
1829 (Lisp_Object window)
1830 {
1831 return decode_live_window (window)->next_buffers;
1832 }
1833
1834 DEFUN ("set-window-next-buffers", Fset_window_next_buffers,
1835 Sset_window_next_buffers, 2, 2, 0,
1836 doc: /* Set WINDOW's next buffers to NEXT-BUFFERS.
1837 WINDOW must be a live window and defaults to the selected one.
1838 NEXT-BUFFERS should be a list of buffers. */)
1839 (Lisp_Object window, Lisp_Object next_buffers)
1840 {
1841 wset_next_buffers (decode_live_window (window), next_buffers);
1842 return next_buffers;
1843 }
1844
1845 DEFUN ("window-parameters", Fwindow_parameters, Swindow_parameters,
1846 0, 1, 0,
1847 doc: /* Return the parameters of WINDOW and their values.
1848 WINDOW must be a valid window and defaults to the selected one. The
1849 return value is a list of elements of the form (PARAMETER . VALUE). */)
1850 (Lisp_Object window)
1851 {
1852 return Fcopy_alist (decode_valid_window (window)->window_parameters);
1853 }
1854
1855 DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
1856 2, 2, 0,
1857 doc: /* Return WINDOW's value for PARAMETER.
1858 WINDOW can be any window and defaults to the selected one. */)
1859 (Lisp_Object window, Lisp_Object parameter)
1860 {
1861 Lisp_Object result;
1862
1863 result = Fassq (parameter, decode_any_window (window)->window_parameters);
1864 return CDR_SAFE (result);
1865 }
1866
1867 DEFUN ("set-window-parameter", Fset_window_parameter,
1868 Sset_window_parameter, 3, 3, 0,
1869 doc: /* Set WINDOW's value of PARAMETER to VALUE.
1870 WINDOW can be any window and defaults to the selected one.
1871 Return VALUE. */)
1872 (Lisp_Object window, Lisp_Object parameter, Lisp_Object value)
1873 {
1874 register struct window *w = decode_any_window (window);
1875 Lisp_Object old_alist_elt;
1876
1877 old_alist_elt = Fassq (parameter, w->window_parameters);
1878 if (NILP (old_alist_elt))
1879 wset_window_parameters
1880 (w, Fcons (Fcons (parameter, value), w->window_parameters));
1881 else
1882 Fsetcdr (old_alist_elt, value);
1883 return value;
1884 }
1885
1886 DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
1887 0, 1, 0,
1888 doc: /* Return the display-table that WINDOW is using.
1889 WINDOW must be a live window and defaults to the selected one. */)
1890 (Lisp_Object window)
1891 {
1892 return decode_live_window (window)->display_table;
1893 }
1894
1895 /* Get the display table for use on window W. This is either W's
1896 display table or W's buffer's display table. Ignore the specified
1897 tables if they are not valid; if no valid table is specified,
1898 return 0. */
1899
1900 struct Lisp_Char_Table *
1901 window_display_table (struct window *w)
1902 {
1903 struct Lisp_Char_Table *dp = NULL;
1904
1905 if (DISP_TABLE_P (w->display_table))
1906 dp = XCHAR_TABLE (w->display_table);
1907 else if (BUFFERP (w->buffer))
1908 {
1909 struct buffer *b = XBUFFER (w->buffer);
1910
1911 if (DISP_TABLE_P (BVAR (b, display_table)))
1912 dp = XCHAR_TABLE (BVAR (b, display_table));
1913 else if (DISP_TABLE_P (Vstandard_display_table))
1914 dp = XCHAR_TABLE (Vstandard_display_table);
1915 }
1916
1917 return dp;
1918 }
1919
1920 DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
1921 doc: /* Set WINDOW's display-table to TABLE.
1922 WINDOW must be a live window and defaults to the selected one. */)
1923 (register Lisp_Object window, Lisp_Object table)
1924 {
1925 wset_display_table (decode_live_window (window), table);
1926 return table;
1927 }
1928 \f
1929 /* Record info on buffer window W is displaying
1930 when it is about to cease to display that buffer. */
1931 static void
1932 unshow_buffer (register struct window *w)
1933 {
1934 Lisp_Object buf;
1935 struct buffer *b;
1936
1937 buf = w->buffer;
1938 b = XBUFFER (buf);
1939 if (b != XMARKER (w->pointm)->buffer)
1940 emacs_abort ();
1941
1942 #if 0
1943 if (w == XWINDOW (selected_window)
1944 || ! EQ (buf, XWINDOW (selected_window)->buffer))
1945 /* Do this except when the selected window's buffer
1946 is being removed from some other window. */
1947 #endif
1948 /* last_window_start records the start position that this buffer
1949 had in the last window to be disconnected from it.
1950 Now that this statement is unconditional,
1951 it is possible for the buffer to be displayed in the
1952 selected window, while last_window_start reflects another
1953 window which was recently showing the same buffer.
1954 Some people might say that might be a good thing. Let's see. */
1955 b->last_window_start = marker_position (w->start);
1956
1957 /* Point in the selected window's buffer
1958 is actually stored in that buffer, and the window's pointm isn't used.
1959 So don't clobber point in that buffer. */
1960 if (! EQ (buf, XWINDOW (selected_window)->buffer)
1961 /* Don't clobber point in current buffer either (this could be
1962 useful in connection with bug#12208).
1963 && XBUFFER (buf) != current_buffer */
1964 /* This line helps to fix Horsley's testbug.el bug. */
1965 && !(WINDOWP (BVAR (b, last_selected_window))
1966 && w != XWINDOW (BVAR (b, last_selected_window))
1967 && EQ (buf, XWINDOW (BVAR (b, last_selected_window))->buffer)))
1968 temp_set_point_both (b,
1969 clip_to_bounds (BUF_BEGV (b),
1970 XMARKER (w->pointm)->charpos,
1971 BUF_ZV (b)),
1972 clip_to_bounds (BUF_BEGV_BYTE (b),
1973 marker_byte_position (w->pointm),
1974 BUF_ZV_BYTE (b)));
1975
1976 if (WINDOWP (BVAR (b, last_selected_window))
1977 && w == XWINDOW (BVAR (b, last_selected_window)))
1978 bset_last_selected_window (b, Qnil);
1979 }
1980
1981 /* Put NEW into the window structure in place of OLD. SETFLAG zero
1982 means change window structure only. Otherwise store geometry and
1983 other settings as well. */
1984 static void
1985 replace_window (Lisp_Object old, Lisp_Object new, int setflag)
1986 {
1987 register Lisp_Object tem;
1988 register struct window *o = XWINDOW (old), *n = XWINDOW (new);
1989
1990 /* If OLD is its frame's root window, then NEW is the new
1991 root window for that frame. */
1992 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
1993 fset_root_window (XFRAME (o->frame), new);
1994
1995 if (setflag)
1996 {
1997 wset_left_col (n, o->left_col);
1998 wset_top_line (n, o->top_line);
1999 wset_total_cols (n, o->total_cols);
2000 wset_total_lines (n, o->total_lines);
2001 wset_normal_cols (n, o->normal_cols);
2002 wset_normal_cols (o, make_float (1.0));
2003 wset_normal_lines (n, o->normal_lines);
2004 wset_normal_lines (o, make_float (1.0));
2005 n->desired_matrix = n->current_matrix = 0;
2006 n->vscroll = 0;
2007 memset (&n->cursor, 0, sizeof (n->cursor));
2008 memset (&n->last_cursor, 0, sizeof (n->last_cursor));
2009 memset (&n->phys_cursor, 0, sizeof (n->phys_cursor));
2010 n->phys_cursor_type = -1;
2011 n->phys_cursor_width = -1;
2012 n->must_be_updated_p = 0;
2013 n->pseudo_window_p = 0;
2014 wset_window_end_vpos (n, make_number (0));
2015 wset_window_end_pos (n, make_number (0));
2016 wset_window_end_valid (n, Qnil);
2017 n->frozen_window_start_p = 0;
2018 }
2019
2020 tem = o->next;
2021 wset_next (n, tem);
2022 if (!NILP (tem))
2023 wset_prev (XWINDOW (tem), new);
2024
2025 tem = o->prev;
2026 wset_prev (n, tem);
2027 if (!NILP (tem))
2028 wset_next (XWINDOW (tem), new);
2029
2030 tem = o->parent;
2031 wset_parent (n, tem);
2032 if (!NILP (tem))
2033 {
2034 if (EQ (XWINDOW (tem)->vchild, old))
2035 wset_vchild (XWINDOW (tem), new);
2036 if (EQ (XWINDOW (tem)->hchild, old))
2037 wset_hchild (XWINDOW (tem), new);
2038 }
2039 }
2040
2041 /* If window WINDOW and its parent window are iso-combined, merge
2042 WINDOW's children into those of its parent window and mark WINDOW as
2043 deleted. */
2044
2045 static void
2046 recombine_windows (Lisp_Object window)
2047 {
2048 struct window *w, *p, *c;
2049 Lisp_Object parent, child;
2050 int horflag;
2051
2052 w = XWINDOW (window);
2053 parent = w->parent;
2054 if (!NILP (parent) && NILP (w->combination_limit))
2055 {
2056 p = XWINDOW (parent);
2057 if (((!NILP (p->vchild) && !NILP (w->vchild))
2058 || (!NILP (p->hchild) && !NILP (w->hchild))))
2059 /* WINDOW and PARENT are both either a vertical or a horizontal
2060 combination. */
2061 {
2062 horflag = NILP (w->vchild);
2063 child = horflag ? w->hchild : w->vchild;
2064 c = XWINDOW (child);
2065
2066 /* Splice WINDOW's children into its parent's children and
2067 assign new normal sizes. */
2068 if (NILP (w->prev))
2069 if (horflag)
2070 wset_hchild (p, child);
2071 else
2072 wset_vchild (p, child);
2073 else
2074 {
2075 wset_prev (c, w->prev);
2076 wset_next (XWINDOW (w->prev), child);
2077 }
2078
2079 while (c)
2080 {
2081 wset_parent (c, parent);
2082
2083 if (horflag)
2084 wset_normal_cols (c,
2085 make_float (XFLOATINT (c->total_cols)
2086 / XFLOATINT (p->total_cols)));
2087 else
2088 wset_normal_lines (c,
2089 make_float (XFLOATINT (c->total_lines)
2090 / XFLOATINT (p->total_lines)));
2091
2092 if (NILP (c->next))
2093 {
2094 if (!NILP (w->next))
2095 {
2096 wset_next (c, w->next);
2097 wset_prev (XWINDOW (c->next), child);
2098 }
2099
2100 c = 0;
2101 }
2102 else
2103 {
2104 child = c->next;
2105 c = XWINDOW (child);
2106 }
2107 }
2108
2109 /* WINDOW can be deleted now. */
2110 wset_vchild (w, Qnil);
2111 wset_hchild (w, Qnil);
2112 }
2113 }
2114 }
2115
2116 /* If WINDOW can be deleted, delete it. */
2117 static void
2118 delete_deletable_window (Lisp_Object window)
2119 {
2120 if (!NILP (call1 (Qwindow_deletable_p, window)))
2121 call1 (Qdelete_window, window);
2122 }
2123 \f
2124 /***********************************************************************
2125 Window List
2126 ***********************************************************************/
2127
2128 /* Add window W to *USER_DATA. USER_DATA is actually a Lisp_Object
2129 pointer. This is a callback function for foreach_window, used in
2130 the window_list function. */
2131
2132 static int
2133 add_window_to_list (struct window *w, void *user_data)
2134 {
2135 Lisp_Object *list = (Lisp_Object *) user_data;
2136 Lisp_Object window;
2137 XSETWINDOW (window, w);
2138 *list = Fcons (window, *list);
2139 return 1;
2140 }
2141
2142
2143 /* Return a list of all windows, for use by next_window. If
2144 Vwindow_list is a list, return that list. Otherwise, build a new
2145 list, cache it in Vwindow_list, and return that. */
2146
2147 static Lisp_Object
2148 window_list (void)
2149 {
2150 if (!CONSP (Vwindow_list))
2151 {
2152 Lisp_Object tail;
2153
2154 Vwindow_list = Qnil;
2155 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
2156 {
2157 Lisp_Object args[2];
2158
2159 /* We are visiting windows in canonical order, and add
2160 new windows at the front of args[1], which means we
2161 have to reverse this list at the end. */
2162 args[1] = Qnil;
2163 foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
2164 args[0] = Vwindow_list;
2165 args[1] = Fnreverse (args[1]);
2166 Vwindow_list = Fnconc (2, args);
2167 }
2168 }
2169
2170 return Vwindow_list;
2171 }
2172
2173
2174 /* Value is non-zero if WINDOW satisfies the constraints given by
2175 OWINDOW, MINIBUF and ALL_FRAMES.
2176
2177 MINIBUF t means WINDOW may be minibuffer windows.
2178 `lambda' means WINDOW may not be a minibuffer window.
2179 a window means a specific minibuffer window
2180
2181 ALL_FRAMES t means search all frames,
2182 nil means search just current frame,
2183 `visible' means search just visible frames on the
2184 current terminal,
2185 0 means search visible and iconified frames on the
2186 current terminal,
2187 a window means search the frame that window belongs to,
2188 a frame means consider windows on that frame, only. */
2189
2190 static int
2191 candidate_window_p (Lisp_Object window, Lisp_Object owindow, Lisp_Object minibuf, Lisp_Object all_frames)
2192 {
2193 struct window *w = XWINDOW (window);
2194 struct frame *f = XFRAME (w->frame);
2195 int candidate_p = 1;
2196
2197 if (!BUFFERP (w->buffer))
2198 candidate_p = 0;
2199 else if (MINI_WINDOW_P (w)
2200 && (EQ (minibuf, Qlambda)
2201 || (WINDOWP (minibuf) && !EQ (minibuf, window))))
2202 {
2203 /* If MINIBUF is `lambda' don't consider any mini-windows.
2204 If it is a window, consider only that one. */
2205 candidate_p = 0;
2206 }
2207 else if (EQ (all_frames, Qt))
2208 candidate_p = 1;
2209 else if (NILP (all_frames))
2210 {
2211 eassert (WINDOWP (owindow));
2212 candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
2213 }
2214 else if (EQ (all_frames, Qvisible))
2215 {
2216 FRAME_SAMPLE_VISIBILITY (f);
2217 candidate_p = FRAME_VISIBLE_P (f)
2218 && (FRAME_TERMINAL (XFRAME (w->frame))
2219 == FRAME_TERMINAL (XFRAME (selected_frame)));
2220
2221 }
2222 else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
2223 {
2224 FRAME_SAMPLE_VISIBILITY (f);
2225 candidate_p = (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)
2226 #ifdef HAVE_X_WINDOWS
2227 /* Yuck!! If we've just created the frame and the
2228 window-manager requested the user to place it
2229 manually, the window may still not be considered
2230 `visible'. I'd argue it should be at least
2231 something like `iconified', but don't know how to do
2232 that yet. --Stef */
2233 || (FRAME_X_P (f) && f->output_data.x->asked_for_visible
2234 && !f->output_data.x->has_been_visible)
2235 #endif
2236 )
2237 && (FRAME_TERMINAL (XFRAME (w->frame))
2238 == FRAME_TERMINAL (XFRAME (selected_frame)));
2239 }
2240 else if (WINDOWP (all_frames))
2241 candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
2242 || EQ (XWINDOW (all_frames)->frame, w->frame)
2243 || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
2244 else if (FRAMEP (all_frames))
2245 candidate_p = EQ (all_frames, w->frame);
2246
2247 return candidate_p;
2248 }
2249
2250
2251 /* Decode arguments as allowed by Fnext_window, Fprevious_window, and
2252 Fwindow_list. See candidate_window_p for the meaning of WINDOW,
2253 MINIBUF, and ALL_FRAMES. */
2254
2255 static void
2256 decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
2257 {
2258 if (NILP (*window))
2259 *window = selected_window;
2260 else
2261 CHECK_LIVE_WINDOW (*window);
2262
2263 /* MINIBUF nil may or may not include minibuffers. Decide if it
2264 does. */
2265 if (NILP (*minibuf))
2266 *minibuf = minibuf_level ? minibuf_window : Qlambda;
2267 else if (!EQ (*minibuf, Qt))
2268 *minibuf = Qlambda;
2269
2270 /* Now *MINIBUF can be t => count all minibuffer windows, `lambda'
2271 => count none of them, or a specific minibuffer window (the
2272 active one) to count. */
2273
2274 /* ALL_FRAMES nil doesn't specify which frames to include. */
2275 if (NILP (*all_frames))
2276 *all_frames
2277 = (!EQ (*minibuf, Qlambda)
2278 ? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
2279 : Qnil);
2280 else if (EQ (*all_frames, Qvisible))
2281 ;
2282 else if (EQ (*all_frames, make_number (0)))
2283 ;
2284 else if (FRAMEP (*all_frames))
2285 ;
2286 else if (!EQ (*all_frames, Qt))
2287 *all_frames = Qnil;
2288 }
2289
2290
2291 /* Return the next or previous window of WINDOW in cyclic ordering
2292 of windows. NEXT_P non-zero means return the next window. See the
2293 documentation string of next-window for the meaning of MINIBUF and
2294 ALL_FRAMES. */
2295
2296 static Lisp_Object
2297 next_window (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames, int next_p)
2298 {
2299 decode_next_window_args (&window, &minibuf, &all_frames);
2300
2301 /* If ALL_FRAMES is a frame, and WINDOW isn't on that frame, just
2302 return the first window on the frame. */
2303 if (FRAMEP (all_frames)
2304 && !EQ (all_frames, XWINDOW (window)->frame))
2305 return Fframe_first_window (all_frames);
2306
2307 if (next_p)
2308 {
2309 Lisp_Object list;
2310
2311 /* Find WINDOW in the list of all windows. */
2312 list = Fmemq (window, window_list ());
2313
2314 /* Scan forward from WINDOW to the end of the window list. */
2315 if (CONSP (list))
2316 for (list = XCDR (list); CONSP (list); list = XCDR (list))
2317 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2318 break;
2319
2320 /* Scan from the start of the window list up to WINDOW. */
2321 if (!CONSP (list))
2322 for (list = Vwindow_list;
2323 CONSP (list) && !EQ (XCAR (list), window);
2324 list = XCDR (list))
2325 if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
2326 break;
2327
2328 if (CONSP (list))
2329 window = XCAR (list);
2330 }
2331 else
2332 {
2333 Lisp_Object candidate, list;
2334
2335 /* Scan through the list of windows for candidates. If there are
2336 candidate windows in front of WINDOW, the last one of these
2337 is the one we want. If there are candidates following WINDOW
2338 in the list, again the last one of these is the one we want. */
2339 candidate = Qnil;
2340 for (list = window_list (); CONSP (list); list = XCDR (list))
2341 {
2342 if (EQ (XCAR (list), window))
2343 {
2344 if (WINDOWP (candidate))
2345 break;
2346 }
2347 else if (candidate_window_p (XCAR (list), window, minibuf,
2348 all_frames))
2349 candidate = XCAR (list);
2350 }
2351
2352 if (WINDOWP (candidate))
2353 window = candidate;
2354 }
2355
2356 return window;
2357 }
2358
2359
2360 DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
2361 doc: /* Return live window after WINDOW in the cyclic ordering of windows.
2362 WINDOW must be a live window and defaults to the selected one. The
2363 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2364 consider.
2365
2366 MINIBUF nil or omitted means consider the minibuffer window only if the
2367 minibuffer is active. MINIBUF t means consider the minibuffer window
2368 even if the minibuffer is not active. Any other value means do not
2369 consider the minibuffer window even if the minibuffer is active.
2370
2371 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2372 plus the minibuffer window if specified by the MINIBUF argument. If the
2373 minibuffer counts, consider all windows on all frames that share that
2374 minibuffer too. The following non-nil values of ALL-FRAMES have special
2375 meanings:
2376
2377 - t means consider all windows on all existing frames.
2378
2379 - `visible' means consider all windows on all visible frames.
2380
2381 - 0 (the number zero) means consider all windows on all visible and
2382 iconified frames.
2383
2384 - A frame means consider all windows on that frame only.
2385
2386 Anything else means consider all windows on WINDOW's frame and no
2387 others.
2388
2389 If you use consistent values for MINIBUF and ALL-FRAMES, you can use
2390 `next-window' to iterate through the entire cycle of acceptable
2391 windows, eventually ending up back at the window you started with.
2392 `previous-window' traverses the same cycle, in the reverse order. */)
2393 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2394 {
2395 return next_window (window, minibuf, all_frames, 1);
2396 }
2397
2398
2399 DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
2400 doc: /* Return live window before WINDOW in the cyclic ordering of windows.
2401 WINDOW must be a live window and defaults to the selected one. The
2402 optional arguments MINIBUF and ALL-FRAMES specify the set of windows to
2403 consider.
2404
2405 MINIBUF nil or omitted means consider the minibuffer window only if the
2406 minibuffer is active. MINIBUF t means consider the minibuffer window
2407 even if the minibuffer is not active. Any other value means do not
2408 consider the minibuffer window even if the minibuffer is active.
2409
2410 ALL-FRAMES nil or omitted means consider all windows on WINDOW's frame,
2411 plus the minibuffer window if specified by the MINIBUF argument. If the
2412 minibuffer counts, consider all windows on all frames that share that
2413 minibuffer too. The following non-nil values of ALL-FRAMES have special
2414 meanings:
2415
2416 - t means consider all windows on all existing frames.
2417
2418 - `visible' means consider all windows on all visible frames.
2419
2420 - 0 (the number zero) means consider all windows on all visible and
2421 iconified frames.
2422
2423 - A frame means consider all windows on that frame only.
2424
2425 Anything else means consider all windows on WINDOW's frame and no
2426 others.
2427
2428 If you use consistent values for MINIBUF and ALL-FRAMES, you can
2429 use `previous-window' to iterate through the entire cycle of
2430 acceptable windows, eventually ending up back at the window you
2431 started with. `next-window' traverses the same cycle, in the
2432 reverse order. */)
2433 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2434 {
2435 return next_window (window, minibuf, all_frames, 0);
2436 }
2437
2438
2439 /* Return a list of windows in cyclic ordering. Arguments are like
2440 for `next-window'. */
2441
2442 static Lisp_Object
2443 window_list_1 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2444 {
2445 Lisp_Object tail, list, rest;
2446
2447 decode_next_window_args (&window, &minibuf, &all_frames);
2448 list = Qnil;
2449
2450 for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
2451 if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
2452 list = Fcons (XCAR (tail), list);
2453
2454 /* Rotate the list to start with WINDOW. */
2455 list = Fnreverse (list);
2456 rest = Fmemq (window, list);
2457 if (!NILP (rest) && !EQ (rest, list))
2458 {
2459 for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
2460 ;
2461 XSETCDR (tail, Qnil);
2462 list = nconc2 (rest, list);
2463 }
2464 return list;
2465 }
2466
2467
2468 DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
2469 doc: /* Return a list of windows on FRAME, starting with WINDOW.
2470 FRAME nil or omitted means use the selected frame.
2471 WINDOW nil or omitted means use the window selected within FRAME.
2472 MINIBUF t means include the minibuffer window, even if it isn't active.
2473 MINIBUF nil or omitted means include the minibuffer window only
2474 if it's active.
2475 MINIBUF neither nil nor t means never include the minibuffer window. */)
2476 (Lisp_Object frame, Lisp_Object minibuf, Lisp_Object window)
2477 {
2478 if (NILP (window))
2479 window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
2480 CHECK_WINDOW (window);
2481 if (NILP (frame))
2482 frame = selected_frame;
2483
2484 if (!EQ (frame, XWINDOW (window)->frame))
2485 error ("Window is on a different frame");
2486
2487 return window_list_1 (window, minibuf, frame);
2488 }
2489
2490
2491 DEFUN ("window-list-1", Fwindow_list_1, Swindow_list_1, 0, 3, 0,
2492 doc: /* Return a list of all live windows.
2493 WINDOW specifies the first window to list and defaults to the selected
2494 window.
2495
2496 Optional argument MINIBUF nil or omitted means consider the minibuffer
2497 window only if the minibuffer is active. MINIBUF t means consider the
2498 minibuffer window even if the minibuffer is not active. Any other value
2499 means do not consider the minibuffer window even if the minibuffer is
2500 active.
2501
2502 Optional argument ALL-FRAMES nil or omitted means consider all windows
2503 on WINDOW's frame, plus the minibuffer window if specified by the
2504 MINIBUF argument. If the minibuffer counts, consider all windows on all
2505 frames that share that minibuffer too. The following non-nil values of
2506 ALL-FRAMES have special meanings:
2507
2508 - t means consider all windows on all existing frames.
2509
2510 - `visible' means consider all windows on all visible frames.
2511
2512 - 0 (the number zero) means consider all windows on all visible and
2513 iconified frames.
2514
2515 - A frame means consider all windows on that frame only.
2516
2517 Anything else means consider all windows on WINDOW's frame and no
2518 others.
2519
2520 If WINDOW is not on the list of windows returned, some other window will
2521 be listed first but no error is signaled. */)
2522 (Lisp_Object window, Lisp_Object minibuf, Lisp_Object all_frames)
2523 {
2524 return window_list_1 (window, minibuf, all_frames);
2525 }
2526 \f
2527 /* Look at all windows, performing an operation specified by TYPE
2528 with argument OBJ.
2529 If FRAMES is Qt, look at all frames;
2530 Qnil, look at just the selected frame;
2531 Qvisible, look at visible frames;
2532 a frame, just look at windows on that frame.
2533 If MINI is non-zero, perform the operation on minibuffer windows too. */
2534
2535 enum window_loop
2536 {
2537 WINDOW_LOOP_UNUSED,
2538 GET_BUFFER_WINDOW, /* Arg is buffer */
2539 REPLACE_BUFFER_IN_WINDOWS_SAFELY, /* Arg is buffer */
2540 REDISPLAY_BUFFER_WINDOWS, /* Arg is buffer */
2541 CHECK_ALL_WINDOWS
2542 };
2543
2544 static Lisp_Object
2545 window_loop (enum window_loop type, Lisp_Object obj, int mini, Lisp_Object frames)
2546 {
2547 Lisp_Object window, windows, best_window, frame_arg;
2548 int frame_best_window_flag = 0;
2549 struct frame *f;
2550 struct gcpro gcpro1;
2551
2552 /* If we're only looping through windows on a particular frame,
2553 frame points to that frame. If we're looping through windows
2554 on all frames, frame is 0. */
2555 if (FRAMEP (frames))
2556 f = XFRAME (frames);
2557 else if (NILP (frames))
2558 f = SELECTED_FRAME ();
2559 else
2560 f = NULL;
2561
2562 if (f)
2563 frame_arg = Qlambda;
2564 else if (EQ (frames, make_number (0)))
2565 frame_arg = frames;
2566 else if (EQ (frames, Qvisible))
2567 frame_arg = frames;
2568 else
2569 frame_arg = Qt;
2570
2571 /* frame_arg is Qlambda to stick to one frame,
2572 Qvisible to consider all visible frames,
2573 or Qt otherwise. */
2574
2575 /* Pick a window to start with. */
2576 if (WINDOWP (obj))
2577 window = obj;
2578 else if (f)
2579 window = FRAME_SELECTED_WINDOW (f);
2580 else
2581 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
2582
2583 windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
2584 GCPRO1 (windows);
2585 best_window = Qnil;
2586
2587 for (; CONSP (windows); windows = XCDR (windows))
2588 {
2589 struct window *w;
2590
2591 window = XCAR (windows);
2592 w = XWINDOW (window);
2593
2594 /* Note that we do not pay attention here to whether the frame
2595 is visible, since Fwindow_list skips non-visible frames if
2596 that is desired, under the control of frame_arg. */
2597 if (!MINI_WINDOW_P (w)
2598 /* For REPLACE_BUFFER_IN_WINDOWS_SAFELY, we must always
2599 consider all windows. */
2600 || type == REPLACE_BUFFER_IN_WINDOWS_SAFELY
2601 || (mini && minibuf_level > 0))
2602 switch (type)
2603 {
2604 case GET_BUFFER_WINDOW:
2605 if (EQ (w->buffer, obj)
2606 /* Don't find any minibuffer window except the one that
2607 is currently in use. */
2608 && (MINI_WINDOW_P (w) ? EQ (window, minibuf_window) : 1))
2609 {
2610 if (EQ (window, selected_window))
2611 /* Preferably return the selected window. */
2612 RETURN_UNGCPRO (window);
2613 else if (EQ (XWINDOW (window)->frame, selected_frame)
2614 && !frame_best_window_flag)
2615 /* Prefer windows on the current frame (but don't
2616 choose another one if we have one already). */
2617 {
2618 best_window = window;
2619 frame_best_window_flag = 1;
2620 }
2621 else if (NILP (best_window))
2622 best_window = window;
2623 }
2624 break;
2625
2626 case REPLACE_BUFFER_IN_WINDOWS_SAFELY:
2627 /* We could simply check whether the buffer shown by window
2628 is live, and show another buffer in case it isn't. */
2629 if (EQ (w->buffer, obj))
2630 {
2631 /* Undedicate WINDOW. */
2632 wset_dedicated (w, Qnil);
2633 /* Make WINDOW show the buffer returned by
2634 other_buffer_safely, don't run any hooks. */
2635 set_window_buffer
2636 (window, other_buffer_safely (w->buffer), 0, 0);
2637 /* If WINDOW is the selected window, make its buffer
2638 current. But do so only if the window shows the
2639 current buffer (Bug#6454). */
2640 if (EQ (window, selected_window)
2641 && XBUFFER (w->buffer) == current_buffer)
2642 Fset_buffer (w->buffer);
2643 }
2644 break;
2645
2646 case REDISPLAY_BUFFER_WINDOWS:
2647 if (EQ (w->buffer, obj))
2648 {
2649 mark_window_display_accurate (window, 0);
2650 w->update_mode_line = 1;
2651 XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
2652 ++update_mode_lines;
2653 best_window = window;
2654 }
2655 break;
2656
2657 /* Check for a window that has a killed buffer. */
2658 case CHECK_ALL_WINDOWS:
2659 if (! NILP (w->buffer)
2660 && !BUFFER_LIVE_P (XBUFFER (w->buffer)))
2661 emacs_abort ();
2662 break;
2663
2664 case WINDOW_LOOP_UNUSED:
2665 break;
2666 }
2667 }
2668
2669 UNGCPRO;
2670 return best_window;
2671 }
2672
2673 /* Used for debugging. Abort if any window has a dead buffer. */
2674
2675 extern void check_all_windows (void) EXTERNALLY_VISIBLE;
2676 void
2677 check_all_windows (void)
2678 {
2679 window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
2680 }
2681
2682 DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 0, 2, 0,
2683 doc: /* Return a window currently displaying BUFFER-OR-NAME, or nil if none.
2684 BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
2685 the current buffer.
2686
2687 The optional argument ALL-FRAMES specifies the frames to consider:
2688
2689 - t means consider all windows on all existing frames.
2690
2691 - `visible' means consider all windows on all visible frames.
2692
2693 - 0 (the number zero) means consider all windows on all visible
2694 and iconified frames.
2695
2696 - A frame means consider all windows on that frame only.
2697
2698 Any other value of ALL-FRAMES means consider all windows on the
2699 selected frame and no others. */)
2700 (Lisp_Object buffer_or_name, Lisp_Object all_frames)
2701 {
2702 Lisp_Object buffer;
2703
2704 if (NILP (buffer_or_name))
2705 buffer = Fcurrent_buffer ();
2706 else
2707 buffer = Fget_buffer (buffer_or_name);
2708
2709 if (BUFFERP (buffer))
2710 return window_loop (GET_BUFFER_WINDOW, buffer, 1, all_frames);
2711 else
2712 return Qnil;
2713 }
2714
2715 static Lisp_Object
2716 resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore)
2717 {
2718 return call4 (Qwindow_resize_root_window, window, delta, horizontal, ignore);
2719 }
2720
2721
2722 DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
2723 Sdelete_other_windows_internal, 0, 2, "",
2724 doc: /* Make WINDOW fill its frame.
2725 Only the frame WINDOW is on is affected. WINDOW must be a valid window
2726 and defaults to the selected one.
2727
2728 Optional argument ROOT, if non-nil, must specify an internal window such
2729 that WINDOW is in its window subtree. If this is the case, replace ROOT
2730 by WINDOW and leave alone any windows not part of ROOT's subtree.
2731
2732 When WINDOW is live try to reduce display jumps by keeping the text
2733 previously visible in WINDOW in the same place on the frame. Doing this
2734 depends on the value of (window-start WINDOW), so if calling this
2735 function in a program gives strange scrolling, make sure the
2736 window-start value is reasonable when this function is called. */)
2737 (Lisp_Object window, Lisp_Object root)
2738 {
2739 struct window *w, *r, *s;
2740 struct frame *f;
2741 Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta;
2742 ptrdiff_t startpos IF_LINT (= 0);
2743 int top IF_LINT (= 0), new_top, resize_failed;
2744
2745 w = decode_valid_window (window);
2746 XSETWINDOW (window, w);
2747 f = XFRAME (w->frame);
2748
2749 if (NILP (root))
2750 /* ROOT is the frame's root window. */
2751 {
2752 root = FRAME_ROOT_WINDOW (f);
2753 r = XWINDOW (root);
2754 }
2755 else
2756 /* ROOT must be an ancestor of WINDOW. */
2757 {
2758 r = decode_valid_window (root);
2759 pwindow = XWINDOW (window)->parent;
2760 while (!NILP (pwindow))
2761 if (EQ (pwindow, root))
2762 break;
2763 else
2764 pwindow = XWINDOW (pwindow)->parent;
2765 if (!EQ (pwindow, root))
2766 error ("Specified root is not an ancestor of specified window");
2767 }
2768
2769 if (EQ (window, root))
2770 /* A noop. */
2771 return Qnil;
2772 /* I don't understand the "top > 0" part below. If we deal with a
2773 standalone minibuffer it would have been caught by the preceding
2774 test. */
2775 else if (MINI_WINDOW_P (w)) /* && top > 0) */
2776 error ("Can't expand minibuffer to full frame");
2777
2778 if (!NILP (w->buffer))
2779 {
2780 startpos = marker_position (w->start);
2781 top = WINDOW_TOP_EDGE_LINE (w)
2782 - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2783 /* Make sure WINDOW is the frame's selected window. */
2784 if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
2785 {
2786 if (EQ (selected_frame, w->frame))
2787 Fselect_window (window, Qnil);
2788 else
2789 fset_selected_window (f, window);
2790 }
2791 }
2792 else
2793 {
2794 /* See if the frame's selected window is a part of the window
2795 subtree rooted at WINDOW, by finding all the selected window's
2796 parents and comparing each one with WINDOW. If it isn't we
2797 need a new selected window for this frame. */
2798 swindow = FRAME_SELECTED_WINDOW (f);
2799 while (1)
2800 {
2801 pwindow = swindow;
2802 while (!NILP (pwindow) && !EQ (window, pwindow))
2803 pwindow = XWINDOW (pwindow)->parent;
2804
2805 if (EQ (window, pwindow))
2806 /* If WINDOW is an ancestor of SWINDOW, then SWINDOW is ok
2807 as the new selected window. */
2808 break;
2809 else
2810 /* Else try the previous window of SWINDOW. */
2811 swindow = Fprevious_window (swindow, Qlambda, Qnil);
2812 }
2813
2814 if (!EQ (swindow, FRAME_SELECTED_WINDOW (f)))
2815 {
2816 if (EQ (selected_frame, w->frame))
2817 Fselect_window (swindow, Qnil);
2818 else
2819 fset_selected_window (f, swindow);
2820 }
2821 }
2822
2823 BLOCK_INPUT;
2824 if (!FRAME_INITIAL_P (f))
2825 {
2826 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
2827
2828 /* We are going to free the glyph matrices of WINDOW, and with
2829 that we might lose any information about glyph rows that have
2830 some of their glyphs highlighted in mouse face. (These rows
2831 are marked with a non-zero mouse_face_p flag.) If WINDOW
2832 indeed has some glyphs highlighted in mouse face, signal to
2833 frame's up-to-date hook that mouse highlight was overwritten,
2834 so that it will arrange for redisplaying the highlight. */
2835 if (EQ (hlinfo->mouse_face_window, window))
2836 {
2837 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
2838 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
2839 hlinfo->mouse_face_window = Qnil;
2840 }
2841 }
2842 free_window_matrices (r);
2843
2844 windows_or_buffers_changed++;
2845 Vwindow_list = Qnil;
2846 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
2847 resize_failed = 0;
2848
2849 if (NILP (w->buffer))
2850 {
2851 /* Resize child windows vertically. */
2852 XSETINT (delta, XINT (r->total_lines)
2853 - XINT (w->total_lines));
2854 wset_top_line (w, r->top_line);
2855 resize_root_window (window, delta, Qnil, Qnil);
2856 if (window_resize_check (w, 0))
2857 window_resize_apply (w, 0);
2858 else
2859 {
2860 resize_root_window (window, delta, Qnil, Qt);
2861 if (window_resize_check (w, 0))
2862 window_resize_apply (w, 0);
2863 else
2864 resize_failed = 1;
2865 }
2866
2867 /* Resize child windows horizontally. */
2868 if (!resize_failed)
2869 {
2870 wset_left_col (w, r->left_col);
2871 XSETINT (delta,
2872 XINT (r->total_cols) - XINT (w->total_cols));
2873 wset_left_col (w, r->left_col);
2874 resize_root_window (window, delta, Qt, Qnil);
2875 if (window_resize_check (w, 1))
2876 window_resize_apply (w, 1);
2877 else
2878 {
2879 resize_root_window (window, delta, Qt, Qt);
2880 if (window_resize_check (w, 1))
2881 window_resize_apply (w, 1);
2882 else
2883 resize_failed = 1;
2884 }
2885 }
2886
2887 if (resize_failed)
2888 /* Play safe, if we still can ... */
2889 {
2890 window = swindow;
2891 w = XWINDOW (window);
2892 }
2893 }
2894
2895 /* Cleanly unlink WINDOW from window-tree. */
2896 if (!NILP (w->prev))
2897 /* Get SIBLING above (on the left of) WINDOW. */
2898 {
2899 sibling = w->prev;
2900 s = XWINDOW (sibling);
2901 wset_next (s, w->next);
2902 if (!NILP (s->next))
2903 wset_prev (XWINDOW (s->next), sibling);
2904 }
2905 else
2906 /* Get SIBLING below (on the right of) WINDOW. */
2907 {
2908 sibling = w->next;
2909 s = XWINDOW (sibling);
2910 wset_prev (s, Qnil);
2911 if (!NILP (XWINDOW (w->parent)->vchild))
2912 wset_vchild (XWINDOW (w->parent), sibling);
2913 else
2914 wset_hchild (XWINDOW (w->parent), sibling);
2915 }
2916
2917 /* Delete ROOT and all child windows of ROOT. */
2918 if (!NILP (r->vchild))
2919 {
2920 delete_all_child_windows (r->vchild);
2921 wset_vchild (r, Qnil);
2922 }
2923 else if (!NILP (r->hchild))
2924 {
2925 delete_all_child_windows (r->hchild);
2926 wset_hchild (r, Qnil);
2927 }
2928
2929 replace_window (root, window, 1);
2930
2931 /* This must become SWINDOW anyway ....... */
2932 if (!NILP (w->buffer) && !resize_failed)
2933 {
2934 /* Try to minimize scrolling, by setting the window start to the
2935 point will cause the text at the old window start to be at the
2936 same place on the frame. But don't try to do this if the
2937 window start is outside the visible portion (as might happen
2938 when the display is not current, due to typeahead). */
2939 new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
2940 if (new_top != top
2941 && startpos >= BUF_BEGV (XBUFFER (w->buffer))
2942 && startpos <= BUF_ZV (XBUFFER (w->buffer)))
2943 {
2944 struct position pos;
2945 struct buffer *obuf = current_buffer;
2946
2947 Fset_buffer (w->buffer);
2948 /* This computation used to temporarily move point, but that
2949 can have unwanted side effects due to text properties. */
2950 pos = *vmotion (startpos, -top, w);
2951
2952 set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
2953 wset_window_end_valid (w, Qnil);
2954 w->start_at_line_beg = (pos.bytepos == BEGV_BYTE
2955 || FETCH_BYTE (pos.bytepos - 1) == '\n');
2956 /* We need to do this, so that the window-scroll-functions
2957 get called. */
2958 w->optional_new_start = 1;
2959
2960 set_buffer_internal (obuf);
2961 }
2962 }
2963
2964 adjust_glyphs (f);
2965 UNBLOCK_INPUT;
2966
2967 run_window_configuration_change_hook (f);
2968
2969 return Qnil;
2970 }
2971
2972
2973 void
2974 replace_buffer_in_windows (Lisp_Object buffer)
2975 {
2976 call1 (Qreplace_buffer_in_windows, buffer);
2977 }
2978
2979
2980 /* Safely replace BUFFER with some other buffer in all windows of all
2981 frames, even those on other keyboards. */
2982
2983 void
2984 replace_buffer_in_windows_safely (Lisp_Object buffer)
2985 {
2986 Lisp_Object tail, frame;
2987
2988 /* A single call to window_loop won't do the job because it only
2989 considers frames on the current keyboard. So loop manually over
2990 frames, and handle each one. */
2991 FOR_EACH_FRAME (tail, frame)
2992 window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
2993 }
2994 \f
2995 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
2996 minimum allowable size. */
2997
2998 void
2999 check_frame_size (FRAME_PTR frame, int *rows, int *cols)
3000 {
3001 /* For height, we have to see:
3002 how many windows the frame has at minimum (one or two),
3003 and whether it has a menu bar or other special stuff at the top. */
3004 int min_height
3005 = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
3006 ? MIN_SAFE_WINDOW_HEIGHT
3007 : 2 * MIN_SAFE_WINDOW_HEIGHT);
3008
3009 if (FRAME_TOP_MARGIN (frame) > 0)
3010 min_height += FRAME_TOP_MARGIN (frame);
3011
3012 if (*rows < min_height)
3013 *rows = min_height;
3014 if (*cols < MIN_SAFE_WINDOW_WIDTH)
3015 *cols = MIN_SAFE_WINDOW_WIDTH;
3016 }
3017
3018 /* Adjust the margins of window W if text area is too small.
3019 Return 1 if window width is ok after adjustment; 0 if window
3020 is still too narrow. */
3021
3022 static int
3023 adjust_window_margins (struct window *w)
3024 {
3025 int box_cols = (WINDOW_TOTAL_COLS (w)
3026 - WINDOW_FRINGE_COLS (w)
3027 - WINDOW_SCROLL_BAR_COLS (w));
3028 int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
3029 + WINDOW_RIGHT_MARGIN_COLS (w));
3030
3031 if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
3032 return 1;
3033
3034 if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
3035 return 0;
3036
3037 /* Window's text area is too narrow, but reducing the window
3038 margins will fix that. */
3039 margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
3040 if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
3041 {
3042 if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
3043 {
3044 wset_left_margin_cols (w, make_number (margin_cols / 2));
3045 wset_right_margin_cols (w, make_number (margin_cols / 2));
3046 }
3047 else
3048 wset_right_margin_cols (w, make_number (margin_cols));
3049 }
3050 else
3051 wset_left_margin_cols (w, make_number (margin_cols));
3052 return 1;
3053 }
3054 \f
3055 /* The following three routines are needed for running a window's
3056 configuration change hook. */
3057 static void
3058 run_funs (Lisp_Object funs)
3059 {
3060 for (; CONSP (funs); funs = XCDR (funs))
3061 if (!EQ (XCAR (funs), Qt))
3062 call0 (XCAR (funs));
3063 }
3064
3065 static Lisp_Object
3066 select_window_norecord (Lisp_Object window)
3067 {
3068 return WINDOW_LIVE_P (window)
3069 ? Fselect_window (window, Qt) : selected_window;
3070 }
3071
3072 static Lisp_Object
3073 select_frame_norecord (Lisp_Object frame)
3074 {
3075 return FRAME_LIVE_P (XFRAME (frame))
3076 ? Fselect_frame (frame, Qt) : selected_frame;
3077 }
3078
3079 void
3080 run_window_configuration_change_hook (struct frame *f)
3081 {
3082 ptrdiff_t count = SPECPDL_INDEX ();
3083 Lisp_Object frame, global_wcch
3084 = Fdefault_value (Qwindow_configuration_change_hook);
3085 XSETFRAME (frame, f);
3086
3087 if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code))
3088 return;
3089
3090 /* Use the right buffer. Matters when running the local hooks. */
3091 if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
3092 {
3093 record_unwind_current_buffer ();
3094 Fset_buffer (Fwindow_buffer (Qnil));
3095 }
3096
3097 if (SELECTED_FRAME () != f)
3098 {
3099 record_unwind_protect (select_frame_norecord, Fselected_frame ());
3100 select_frame_norecord (frame);
3101 }
3102
3103 /* Look for buffer-local values. */
3104 {
3105 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3106 for (; CONSP (windows); windows = XCDR (windows))
3107 {
3108 Lisp_Object window = XCAR (windows);
3109 Lisp_Object buffer = Fwindow_buffer (window);
3110 if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
3111 buffer)))
3112 {
3113 ptrdiff_t inner_count = SPECPDL_INDEX ();
3114 record_unwind_protect (select_window_norecord, Fselected_window ());
3115 select_window_norecord (window);
3116 run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
3117 buffer));
3118 unbind_to (inner_count, Qnil);
3119 }
3120 }
3121 }
3122
3123 run_funs (global_wcch);
3124 unbind_to (count, Qnil);
3125 }
3126
3127 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
3128 Srun_window_configuration_change_hook, 1, 1, 0,
3129 doc: /* Run `window-configuration-change-hook' for FRAME. */)
3130 (Lisp_Object frame)
3131 {
3132 CHECK_LIVE_FRAME (frame);
3133 run_window_configuration_change_hook (XFRAME (frame));
3134 return Qnil;
3135 }
3136
3137 /* Make WINDOW display BUFFER as its contents. RUN_HOOKS_P non-zero
3138 means it's allowed to run hooks. See make_frame for a case where
3139 it's not allowed. KEEP_MARGINS_P non-zero means that the current
3140 margins, fringes, and scroll-bar settings of the window are not
3141 reset from the buffer's local settings. */
3142
3143 void
3144 set_window_buffer (Lisp_Object window, Lisp_Object buffer, int run_hooks_p, int keep_margins_p)
3145 {
3146 struct window *w = XWINDOW (window);
3147 struct buffer *b = XBUFFER (buffer);
3148 ptrdiff_t count = SPECPDL_INDEX ();
3149 int samebuf = EQ (buffer, w->buffer);
3150
3151 wset_buffer (w, buffer);
3152
3153 if (EQ (window, selected_window))
3154 bset_last_selected_window (b, window);
3155
3156 /* Let redisplay errors through. */
3157 b->display_error_modiff = 0;
3158
3159 /* Update time stamps of buffer display. */
3160 if (INTEGERP (BVAR (b, display_count)))
3161 bset_display_count (b, make_number (XINT (BVAR (b, display_count)) + 1));
3162 bset_display_time (b, Fcurrent_time ());
3163
3164 wset_window_end_pos (w, make_number (0));
3165 wset_window_end_vpos (w, make_number (0));
3166 memset (&w->last_cursor, 0, sizeof w->last_cursor);
3167 wset_window_end_valid (w, Qnil);
3168 if (!(keep_margins_p && samebuf))
3169 { /* If we're not actually changing the buffer, don't reset hscroll and
3170 vscroll. This case happens for example when called from
3171 change_frame_size_1, where we use a dummy call to
3172 Fset_window_buffer on the frame's selected window (and no other)
3173 just in order to run window-configuration-change-hook.
3174 Resetting hscroll and vscroll here is problematic for things like
3175 image-mode and doc-view-mode since it resets the image's position
3176 whenever we resize the frame. */
3177 w->hscroll = w->min_hscroll = 0;
3178 w->vscroll = 0;
3179 set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
3180 set_marker_restricted (w->start,
3181 make_number (b->last_window_start),
3182 buffer);
3183 w->start_at_line_beg = 0;
3184 w->force_start = 0;
3185 w->last_modified = 0;
3186 w->last_overlay_modified = 0;
3187 }
3188 /* Maybe we could move this into the `if' but it's not obviously safe and
3189 I doubt it's worth the trouble. */
3190 windows_or_buffers_changed++;
3191
3192 /* We must select BUFFER for running the window-scroll-functions. */
3193 /* We can't check ! NILP (Vwindow_scroll_functions) here
3194 because that might itself be a local variable. */
3195 if (window_initialized)
3196 {
3197 record_unwind_current_buffer ();
3198 Fset_buffer (buffer);
3199 }
3200
3201 XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
3202
3203 if (!keep_margins_p)
3204 {
3205 /* Set left and right marginal area width etc. from buffer. */
3206
3207 /* This may call adjust_window_margins three times, so
3208 temporarily disable window margins. */
3209 Lisp_Object save_left = w->left_margin_cols;
3210 Lisp_Object save_right = w->right_margin_cols;
3211
3212 wset_left_margin_cols (w, Qnil);
3213 wset_right_margin_cols (w, Qnil);
3214
3215 Fset_window_fringes (window,
3216 BVAR (b, left_fringe_width), BVAR (b, right_fringe_width),
3217 BVAR (b, fringes_outside_margins));
3218
3219 Fset_window_scroll_bars (window,
3220 BVAR (b, scroll_bar_width),
3221 BVAR (b, vertical_scroll_bar_type), Qnil);
3222
3223 wset_left_margin_cols (w, save_left);
3224 wset_right_margin_cols (w, save_right);
3225
3226 Fset_window_margins (window,
3227 BVAR (b, left_margin_cols), BVAR (b, right_margin_cols));
3228 }
3229
3230 if (run_hooks_p)
3231 {
3232 if (! NILP (Vwindow_scroll_functions))
3233 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3234 Fmarker_position (w->start));
3235 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
3236 }
3237
3238 unbind_to (count, Qnil);
3239 }
3240
3241 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
3242 doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
3243 WINDOW must be a live window and defaults to the selected one.
3244 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
3245
3246 Optional third argument KEEP-MARGINS non-nil means that WINDOW's current
3247 display margins, fringe widths, and scroll bar settings are preserved;
3248 the default is to reset these from the local settings for BUFFER-OR-NAME
3249 or the frame defaults. Return nil.
3250
3251 This function throws an error when WINDOW is strongly dedicated to its
3252 buffer (that is `window-dedicated-p' returns t for WINDOW) and does not
3253 already display BUFFER-OR-NAME.
3254
3255 This function runs `window-scroll-functions' before running
3256 `window-configuration-change-hook'. */)
3257 (register Lisp_Object window, Lisp_Object buffer_or_name, Lisp_Object keep_margins)
3258 {
3259 register Lisp_Object tem, buffer;
3260 register struct window *w = decode_live_window (window);
3261
3262 XSETWINDOW (window, w);
3263 buffer = Fget_buffer (buffer_or_name);
3264 CHECK_BUFFER (buffer);
3265 if (!BUFFER_LIVE_P (XBUFFER (buffer)))
3266 error ("Attempt to display deleted buffer");
3267
3268 tem = w->buffer;
3269 if (NILP (tem))
3270 error ("Window is deleted");
3271 else if (!EQ (tem, Qt))
3272 /* w->buffer is t when the window is first being set up. */
3273 {
3274 if (!EQ (tem, buffer))
3275 {
3276 if (EQ (w->dedicated, Qt))
3277 /* WINDOW is strongly dedicated to its buffer, signal an
3278 error. */
3279 error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
3280 else
3281 /* WINDOW is weakly dedicated to its buffer, reset
3282 dedication. */
3283 wset_dedicated (w, Qnil);
3284
3285 call1 (Qrecord_window_buffer, window);
3286 }
3287
3288 unshow_buffer (w);
3289 }
3290
3291 set_window_buffer (window, buffer, 1, !NILP (keep_margins));
3292
3293 return Qnil;
3294 }
3295 \f
3296 static Lisp_Object
3297 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, Lisp_Object override_frame)
3298 {
3299 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame);
3300 }
3301
3302 DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
3303 0, 1, 0,
3304 doc: /* Force all windows to be updated on next redisplay.
3305 If optional arg OBJECT is a window, force redisplay of that window only.
3306 If OBJECT is a buffer or buffer name, force redisplay of all windows
3307 displaying that buffer. */)
3308 (Lisp_Object object)
3309 {
3310 if (NILP (object))
3311 {
3312 windows_or_buffers_changed++;
3313 update_mode_lines++;
3314 return Qt;
3315 }
3316
3317 if (WINDOWP (object))
3318 {
3319 struct window *w = XWINDOW (object);
3320 mark_window_display_accurate (object, 0);
3321 w->update_mode_line = 1;
3322 if (BUFFERP (w->buffer))
3323 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
3324 ++update_mode_lines;
3325 return Qt;
3326 }
3327
3328 if (STRINGP (object))
3329 object = Fget_buffer (object);
3330 if (BUFFERP (object) && BUFFER_LIVE_P (XBUFFER (object)))
3331 {
3332 /* Walk all windows looking for buffer, and force update
3333 of each of those windows. */
3334
3335 object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
3336 return NILP (object) ? Qnil : Qt;
3337 }
3338
3339 /* If nothing suitable was found, just return.
3340 We could signal an error, but this feature will typically be used
3341 asynchronously in timers or process sentinels, so we don't. */
3342 return Qnil;
3343 }
3344
3345
3346 void
3347 temp_output_buffer_show (register Lisp_Object buf)
3348 {
3349 register struct buffer *old = current_buffer;
3350 register Lisp_Object window;
3351 register struct window *w;
3352
3353 bset_directory (XBUFFER (buf), BVAR (current_buffer, directory));
3354
3355 Fset_buffer (buf);
3356 BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
3357 BEGV = BEG;
3358 ZV = Z;
3359 SET_PT (BEG);
3360 set_buffer_internal (old);
3361
3362 if (!NILP (Vtemp_buffer_show_function))
3363 call1 (Vtemp_buffer_show_function, buf);
3364 else
3365 {
3366 window = display_buffer (buf, Qnil, Qnil);
3367
3368 if (!EQ (XWINDOW (window)->frame, selected_frame))
3369 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
3370 Vminibuf_scroll_window = window;
3371 w = XWINDOW (window);
3372 w->hscroll = 0;
3373 w->min_hscroll = 0;
3374 set_marker_restricted_both (w->start, buf, BEG, BEG);
3375 set_marker_restricted_both (w->pointm, buf, BEG, BEG);
3376
3377 /* Run temp-buffer-show-hook, with the chosen window selected
3378 and its buffer current. */
3379 {
3380 ptrdiff_t count = SPECPDL_INDEX ();
3381 Lisp_Object prev_window, prev_buffer;
3382 prev_window = selected_window;
3383 XSETBUFFER (prev_buffer, old);
3384
3385 /* Select the window that was chosen, for running the hook.
3386 Note: Both Fselect_window and select_window_norecord may
3387 set-buffer to the buffer displayed in the window,
3388 so we need to save the current buffer. --stef */
3389 record_unwind_protect (Fset_buffer, prev_buffer);
3390 record_unwind_protect (select_window_norecord, prev_window);
3391 Fselect_window (window, Qt);
3392 Fset_buffer (w->buffer);
3393 Frun_hooks (1, &Qtemp_buffer_show_hook);
3394 unbind_to (count, Qnil);
3395 }
3396 }
3397 }
3398
3399 DEFUN ("internal-temp-output-buffer-show",
3400 Ftemp_output_buffer_show, Stemp_output_buffer_show,
3401 1, 1, 0,
3402 doc: /* Internal function for `with-output-to-temp-buffer'. */)
3403 (Lisp_Object buf)
3404 {
3405 temp_output_buffer_show (buf);
3406 return Qnil;
3407 }
3408 \f
3409 /* Make new window, have it replace WINDOW in window-tree, and make
3410 WINDOW its only vertical child (HORFLAG 1 means make WINDOW its only
3411 horizontal child). */
3412 static void
3413 make_parent_window (Lisp_Object window, int horflag)
3414 {
3415 Lisp_Object parent;
3416 register struct window *o, *p;
3417
3418 o = XWINDOW (window);
3419 p = allocate_window ();
3420 memcpy ((char *) p + sizeof (struct vectorlike_header),
3421 (char *) o + sizeof (struct vectorlike_header),
3422 word_size * VECSIZE (struct window));
3423 XSETWINDOW (parent, p);
3424
3425 p->sequence_number = ++sequence_number;
3426
3427 replace_window (window, parent, 1);
3428
3429 wset_next (o, Qnil);
3430 wset_prev (o, Qnil);
3431 wset_parent (o, parent);
3432
3433 wset_hchild (p, horflag ? window : Qnil);
3434 wset_vchild (p, horflag ? Qnil : window);
3435 wset_start (p, Qnil);
3436 wset_pointm (p, Qnil);
3437 wset_buffer (p, Qnil);
3438 wset_combination_limit (p, Qnil);
3439 wset_window_parameters (p, Qnil);
3440 }
3441
3442 /* Make new window from scratch. */
3443 Lisp_Object
3444 make_window (void)
3445 {
3446 Lisp_Object window;
3447 register struct window *w;
3448
3449 w = allocate_window ();
3450 /* Initialize Lisp data. Note that allocate_window initializes all
3451 Lisp data to nil, so do it only for slots which should not be nil. */
3452 wset_left_col (w, make_number (0));
3453 wset_top_line (w, make_number (0));
3454 wset_total_lines (w, make_number (0));
3455 wset_total_cols (w, make_number (0));
3456 wset_normal_lines (w, make_float (1.0));
3457 wset_normal_cols (w, make_float (1.0));
3458 wset_new_total (w, make_number (0));
3459 wset_new_normal (w, make_number (0));
3460 wset_start (w, Fmake_marker ());
3461 wset_pointm (w, Fmake_marker ());
3462 wset_vertical_scroll_bar_type (w, Qt);
3463 wset_window_end_pos (w, make_number (0));
3464 wset_window_end_vpos (w, make_number (0));
3465 /* These Lisp fields are marked specially so they're not set to nil by
3466 allocate_window. */
3467 wset_prev_buffers (w, Qnil);
3468 wset_next_buffers (w, Qnil);
3469
3470 /* Initialize non-Lisp data. Note that allocate_window zeroes out all
3471 non-Lisp data, so do it only for slots which should not be zero. */
3472 w->nrows_scale_factor = w->ncols_scale_factor = 1;
3473 w->phys_cursor_type = -1;
3474 w->phys_cursor_width = -1;
3475 w->sequence_number = ++sequence_number;
3476
3477 /* Reset window_list. */
3478 Vwindow_list = Qnil;
3479 /* Return window. */
3480 XSETWINDOW (window, w);
3481 return window;
3482 }
3483 \f
3484 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
3485 doc: /* Set new total size of WINDOW to SIZE.
3486 WINDOW must be a valid window and defaults to the selected one.
3487 Return SIZE.
3488
3489 Optional argument ADD non-nil means add SIZE to the new total size of
3490 WINDOW and return the sum.
3491
3492 Note: This function does not operate on any child windows of WINDOW. */)
3493 (Lisp_Object window, Lisp_Object size, Lisp_Object add)
3494 {
3495 struct window *w = decode_valid_window (window);
3496
3497 CHECK_NUMBER (size);
3498 if (NILP (add))
3499 wset_new_total (w, size);
3500 else
3501 wset_new_total (w, make_number (XINT (w->new_total) + XINT (size)));
3502
3503 return w->new_total;
3504 }
3505
3506 DEFUN ("set-window-new-normal", Fset_window_new_normal, Sset_window_new_normal, 1, 2, 0,
3507 doc: /* Set new normal size of WINDOW to SIZE.
3508 WINDOW must be a valid window and defaults to the selected one.
3509 Return SIZE.
3510
3511 Note: This function does not operate on any child windows of WINDOW. */)
3512 (Lisp_Object window, Lisp_Object size)
3513 {
3514 wset_new_normal (decode_valid_window (window), size);
3515 return size;
3516 }
3517
3518 /* Return 1 if setting w->total_lines (w->total_cols if HORFLAG is
3519 non-zero) to w->new_total would result in correct heights (widths)
3520 for window W and recursively all child windows of W.
3521
3522 Note: This function does not check any of `window-fixed-size-p',
3523 `window-min-height' or `window-min-width'. It does check that window
3524 sizes do not drop below one line (two columns). */
3525 static int
3526 window_resize_check (struct window *w, int horflag)
3527 {
3528 struct window *c;
3529
3530 if (!NILP (w->vchild))
3531 /* W is a vertical combination. */
3532 {
3533 c = XWINDOW (w->vchild);
3534 if (horflag)
3535 /* All child windows of W must have the same width as W. */
3536 {
3537 while (c)
3538 {
3539 if ((XINT (c->new_total) != XINT (w->new_total))
3540 || !window_resize_check (c, horflag))
3541 return 0;
3542 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3543 }
3544 return 1;
3545 }
3546 else
3547 /* The sum of the heights of the child windows of W must equal
3548 W's height. */
3549 {
3550 int sum_of_sizes = 0;
3551 while (c)
3552 {
3553 if (!window_resize_check (c, horflag))
3554 return 0;
3555 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3556 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3557 }
3558 return (sum_of_sizes == XINT (w->new_total));
3559 }
3560 }
3561 else if (!NILP (w->hchild))
3562 /* W is a horizontal combination. */
3563 {
3564 c = XWINDOW (w->hchild);
3565 if (horflag)
3566 /* The sum of the widths of the child windows of W must equal W's
3567 width. */
3568 {
3569 int sum_of_sizes = 0;
3570 while (c)
3571 {
3572 if (!window_resize_check (c, horflag))
3573 return 0;
3574 sum_of_sizes = sum_of_sizes + XINT (c->new_total);
3575 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3576 }
3577 return (sum_of_sizes == XINT (w->new_total));
3578 }
3579 else
3580 /* All child windows of W must have the same height as W. */
3581 {
3582 while (c)
3583 {
3584 if ((XINT (c->new_total) != XINT (w->new_total))
3585 || !window_resize_check (c, horflag))
3586 return 0;
3587 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3588 }
3589 return 1;
3590 }
3591 }
3592 else
3593 /* A leaf window. Make sure it's not too small. The following
3594 hardcodes the values of `window-safe-min-width' (2) and
3595 `window-safe-min-height' (1) which are defined in window.el. */
3596 return XINT (w->new_total) >= (horflag ? 2 : 1);
3597 }
3598
3599 /* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
3600 w->new_total for window W and recursively all child windows of W.
3601 Also calculate and assign the new vertical (horizontal) start
3602 positions of each of these windows.
3603
3604 This function does not perform any error checks. Make sure you have
3605 run window_resize_check on W before applying this function. */
3606 static void
3607 window_resize_apply (struct window *w, int horflag)
3608 {
3609 struct window *c;
3610 int pos;
3611
3612 /* Note: Assigning new_normal requires that the new total size of the
3613 parent window has been set *before*. */
3614 if (horflag)
3615 {
3616 wset_total_cols (w, w->new_total);
3617 if (NUMBERP (w->new_normal))
3618 wset_normal_cols (w, w->new_normal);
3619
3620 pos = XINT (w->left_col);
3621 }
3622 else
3623 {
3624 wset_total_lines (w, w->new_total);
3625 if (NUMBERP (w->new_normal))
3626 wset_normal_lines (w, w->new_normal);
3627
3628 pos = XINT (w->top_line);
3629 }
3630
3631 if (!NILP (w->vchild))
3632 /* W is a vertical combination. */
3633 {
3634 c = XWINDOW (w->vchild);
3635 while (c)
3636 {
3637 if (horflag)
3638 wset_left_col (c, make_number (pos));
3639 else
3640 wset_top_line (c, make_number (pos));
3641 window_resize_apply (c, horflag);
3642 if (!horflag)
3643 pos = pos + XINT (c->total_lines);
3644 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3645 }
3646 }
3647 else if (!NILP (w->hchild))
3648 /* W is a horizontal combination. */
3649 {
3650 c = XWINDOW (w->hchild);
3651 while (c)
3652 {
3653 if (horflag)
3654 wset_left_col (c, make_number (pos));
3655 else
3656 wset_top_line (c, make_number (pos));
3657 window_resize_apply (c, horflag);
3658 if (horflag)
3659 pos = pos + XINT (c->total_cols);
3660 c = NILP (c->next) ? 0 : XWINDOW (c->next);
3661 }
3662 }
3663
3664 /* Clear out some redisplay caches. */
3665 w->last_modified = 0;
3666 w->last_overlay_modified = 0;
3667 }
3668
3669
3670 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 1, 2, 0,
3671 doc: /* Apply requested size values for window-tree of FRAME.
3672 Optional argument HORIZONTAL omitted or nil means apply requested height
3673 values. HORIZONTAL non-nil means apply requested width values.
3674
3675 This function checks whether the requested values sum up to a valid
3676 window layout, recursively assigns the new sizes of all child windows
3677 and calculates and assigns the new start positions of these windows.
3678
3679 Note: This function does not check any of `window-fixed-size-p',
3680 `window-min-height' or `window-min-width'. All these checks have to
3681 be applied on the Elisp level. */)
3682 (Lisp_Object frame, Lisp_Object horizontal)
3683 {
3684 struct frame *f;
3685 struct window *r;
3686 int horflag = !NILP (horizontal);
3687
3688 if (NILP (frame))
3689 frame = selected_frame;
3690 CHECK_LIVE_FRAME (frame);
3691
3692 f = XFRAME (frame);
3693 r = XWINDOW (FRAME_ROOT_WINDOW (f));
3694
3695 if (!window_resize_check (r, horflag)
3696 || ! EQ (r->new_total,
3697 (horflag ? r->total_cols : r->total_lines)))
3698 return Qnil;
3699
3700 BLOCK_INPUT;
3701 window_resize_apply (r, horflag);
3702
3703 windows_or_buffers_changed++;
3704 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3705
3706 adjust_glyphs (f);
3707 UNBLOCK_INPUT;
3708
3709 run_window_configuration_change_hook (f);
3710
3711 return Qt;
3712 }
3713
3714
3715 /* Resize frame F's windows when number of lines of F is set to SIZE.
3716 HORFLAG 1 means resize windows when number of columns of F is set to
3717 SIZE.
3718
3719 This function can delete all windows but the selected one in order to
3720 satisfy the request. The result will be meaningful if and only if
3721 F's windows have meaningful sizes when you call this. */
3722 void
3723 resize_frame_windows (struct frame *f, int size, int horflag)
3724 {
3725 Lisp_Object root = f->root_window;
3726 struct window *r = XWINDOW (root);
3727 Lisp_Object mini = f->minibuffer_window;
3728 struct window *m;
3729 /* new_size is the new size of the frame's root window. */
3730 int new_size = (horflag
3731 ? size
3732 : (size
3733 - FRAME_TOP_MARGIN (f)
3734 - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3735 ? 1 : 0)));
3736
3737 wset_top_line (r, make_number (FRAME_TOP_MARGIN (f)));
3738 if (NILP (r->vchild) && NILP (r->hchild))
3739 /* For a leaf root window just set the size. */
3740 if (horflag)
3741 wset_total_cols (r, make_number (new_size));
3742 else
3743 wset_total_lines (r, make_number (new_size));
3744 else
3745 {
3746 /* old_size is the old size of the frame's root window. */
3747 int old_size = XFASTINT (horflag ? r->total_cols
3748 : r->total_lines);
3749 Lisp_Object delta;
3750
3751 XSETINT (delta, new_size - old_size);
3752 /* Try a "normal" resize first. */
3753 resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil);
3754 if (window_resize_check (r, horflag)
3755 && new_size == XINT (r->new_total))
3756 window_resize_apply (r, horflag);
3757 else
3758 {
3759 /* Try with "reasonable" minimum sizes next. */
3760 resize_root_window (root, delta, horflag ? Qt : Qnil, Qt);
3761 if (window_resize_check (r, horflag)
3762 && new_size == XINT (r->new_total))
3763 window_resize_apply (r, horflag);
3764 else
3765 {
3766 /* Finally, try with "safe" minimum sizes. */
3767 resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe);
3768 if (window_resize_check (r, horflag)
3769 && new_size == XINT (r->new_total))
3770 window_resize_apply (r, horflag);
3771 else
3772 {
3773 /* We lost. Delete all windows but the frame's
3774 selected one. */
3775 root = f->selected_window;
3776 Fdelete_other_windows_internal (root, Qnil);
3777 if (horflag)
3778 wset_total_cols (XWINDOW (root), make_number (new_size));
3779 else
3780 wset_total_lines (XWINDOW (root), make_number (new_size));
3781 }
3782 }
3783 }
3784 }
3785
3786 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3787 {
3788 m = XWINDOW (mini);
3789 if (horflag)
3790 wset_total_cols (m, make_number (size));
3791 else
3792 {
3793 /* Are we sure we always want 1 line here? */
3794 wset_total_lines (m, make_number (1));
3795 wset_top_line
3796 (m, make_number (XINT (r->top_line) + XINT (r->total_lines)));
3797 }
3798 }
3799 }
3800
3801
3802 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
3803 doc: /* Split window OLD.
3804 Second argument TOTAL-SIZE specifies the number of lines or columns of the
3805 new window. In any case TOTAL-SIZE must be a positive integer.
3806
3807 Third argument SIDE nil (or `below') specifies that the new window shall
3808 be located below WINDOW. SIDE `above' means the new window shall be
3809 located above WINDOW. In both cases TOTAL-SIZE specifies the number of
3810 lines of the new window including space reserved for the mode and/or
3811 header line.
3812
3813 SIDE t (or `right') specifies that the new window shall be located on
3814 the right side of WINDOW. SIDE `left' means the new window shall be
3815 located on the left of WINDOW. In both cases TOTAL-SIZE specifies the
3816 number of columns of the new window including space reserved for fringes
3817 and the scrollbar or a divider column.
3818
3819 Fourth argument NORMAL-SIZE specifies the normal size of the new window
3820 according to the SIDE argument.
3821
3822 The new total and normal sizes of all involved windows must have been
3823 set correctly. See the code of `split-window' for how this is done. */)
3824 (Lisp_Object old, Lisp_Object total_size, Lisp_Object side, Lisp_Object normal_size)
3825 {
3826 /* OLD (*o) is the window we have to split. (*p) is either OLD's
3827 parent window or an internal window we have to install as OLD's new
3828 parent. REFERENCE (*r) must denote a live window, or is set to OLD
3829 provided OLD is a leaf window, or to the frame's selected window.
3830 NEW (*n) is the new window created with some parameters taken from
3831 REFERENCE (*r). */
3832 register Lisp_Object new, frame, reference;
3833 register struct window *o, *p, *n, *r;
3834 struct frame *f;
3835 int horflag
3836 /* HORFLAG is 1 when we split side-by-side, 0 otherwise. */
3837 = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
3838 int combination_limit = 0;
3839
3840 CHECK_WINDOW (old);
3841 o = XWINDOW (old);
3842 frame = WINDOW_FRAME (o);
3843 f = XFRAME (frame);
3844
3845 CHECK_NUMBER (total_size);
3846
3847 /* Set combination_limit to 1 if we have to make a new parent window.
3848 We do that if either `window-combination-limit' is t, or OLD has no
3849 parent, or OLD is ortho-combined. */
3850 combination_limit =
3851 !NILP (Vwindow_combination_limit)
3852 || NILP (o->parent)
3853 || NILP (horflag
3854 ? (XWINDOW (o->parent)->hchild)
3855 : (XWINDOW (o->parent)->vchild));
3856
3857 /* We need a live reference window to initialize some parameters. */
3858 if (WINDOW_LIVE_P (old))
3859 /* OLD is live, use it as reference window. */
3860 reference = old;
3861 else
3862 /* Use the frame's selected window as reference window. */
3863 reference = FRAME_SELECTED_WINDOW (f);
3864 r = XWINDOW (reference);
3865
3866 /* The following bugs are caught by `split-window'. */
3867 if (MINI_WINDOW_P (o))
3868 error ("Attempt to split minibuffer window");
3869 else if (XINT (total_size) < (horflag ? 2 : 1))
3870 error ("Size of new window too small (after split)");
3871 else if (!combination_limit && !NILP (Vwindow_combination_resize))
3872 /* `window-combination-resize' non-nil means try to resize OLD's siblings
3873 proportionally. */
3874 {
3875 p = XWINDOW (o->parent);
3876 /* Temporarily pretend we split the parent window. */
3877 wset_new_total
3878 (p, make_number (XINT (horflag ? p->total_cols : p->total_lines)
3879 - XINT (total_size)));
3880 if (!window_resize_check (p, horflag))
3881 error ("Window sizes don't fit");
3882 else
3883 /* Undo the temporary pretension. */
3884 wset_new_total (p, horflag ? p->total_cols : p->total_lines);
3885 }
3886 else
3887 {
3888 if (!window_resize_check (o, horflag))
3889 error ("Resizing old window failed");
3890 else if (XINT (total_size) + XINT (o->new_total)
3891 != XINT (horflag ? o->total_cols : o->total_lines))
3892 error ("Sum of sizes of old and new window don't fit");
3893 }
3894
3895 /* This is our point of no return. */
3896 if (combination_limit)
3897 {
3898 /* Save the old value of o->normal_cols/lines. It gets corrupted
3899 by make_parent_window and we need it below for assigning it to
3900 p->new_normal. */
3901 Lisp_Object new_normal
3902 = horflag ? o->normal_cols : o->normal_lines;
3903
3904 make_parent_window (old, horflag);
3905 p = XWINDOW (o->parent);
3906 /* Store value of `window-combination-limit' in new parent's
3907 combination_limit slot. */
3908 wset_combination_limit (p, Vwindow_combination_limit);
3909 /* These get applied below. */
3910 wset_new_total (p, horflag ? o->total_cols : o->total_lines);
3911 wset_new_normal (p, new_normal);
3912 }
3913 else
3914 p = XWINDOW (o->parent);
3915
3916 windows_or_buffers_changed++;
3917 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
3918 new = make_window ();
3919 n = XWINDOW (new);
3920 wset_frame (n, frame);
3921 wset_parent (n, o->parent);
3922 wset_vchild (n, Qnil);
3923 wset_hchild (n, Qnil);
3924
3925 if (EQ (side, Qabove) || EQ (side, Qleft))
3926 {
3927 wset_prev (n, o->prev);
3928 if (NILP (n->prev))
3929 if (horflag)
3930 wset_hchild (p, new);
3931 else
3932 wset_vchild (p, new);
3933 else
3934 wset_next (XWINDOW (n->prev), new);
3935 wset_next (n, old);
3936 wset_prev (o, new);
3937 }
3938 else
3939 {
3940 wset_next (n, o->next);
3941 if (!NILP (n->next))
3942 wset_prev (XWINDOW (n->next), new);
3943 wset_prev (n, old);
3944 wset_next (o, new);
3945 }
3946
3947 wset_buffer (n, Qt);
3948 wset_window_end_valid (n, Qnil);
3949 memset (&n->last_cursor, 0, sizeof n->last_cursor);
3950
3951 /* Get special geometry settings from reference window. */
3952 wset_left_margin_cols (n, r->left_margin_cols);
3953 wset_right_margin_cols (n, r->right_margin_cols);
3954 wset_left_fringe_width (n, r->left_fringe_width);
3955 wset_right_fringe_width (n, r->right_fringe_width);
3956 n->fringes_outside_margins = r->fringes_outside_margins;
3957 wset_scroll_bar_width (n, r->scroll_bar_width);
3958 wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
3959
3960 /* Directly assign orthogonal coordinates and sizes. */
3961 if (horflag)
3962 {
3963 wset_top_line (n, o->top_line);
3964 wset_total_lines (n, o->total_lines);
3965 }
3966 else
3967 {
3968 wset_left_col (n, o->left_col);
3969 wset_total_cols (n, o->total_cols);
3970 }
3971
3972 /* Iso-coordinates and sizes are assigned by window_resize_apply,
3973 get them ready here. */
3974 wset_new_total (n, total_size);
3975 wset_new_normal (n, normal_size);
3976
3977 BLOCK_INPUT;
3978 window_resize_apply (p, horflag);
3979 adjust_glyphs (f);
3980 /* Set buffer of NEW to buffer of reference window. Don't run
3981 any hooks. */
3982 set_window_buffer (new, r->buffer, 0, 1);
3983 UNBLOCK_INPUT;
3984
3985 /* Maybe we should run the scroll functions in Elisp (which already
3986 runs the configuration change hook). */
3987 if (! NILP (Vwindow_scroll_functions))
3988 run_hook_with_args_2 (Qwindow_scroll_functions, new,
3989 Fmarker_position (n->start));
3990 /* Return NEW. */
3991 return new;
3992 }
3993
3994
3995 DEFUN ("delete-window-internal", Fdelete_window_internal, Sdelete_window_internal, 1, 1, 0,
3996 doc: /* Remove WINDOW from its frame.
3997 WINDOW defaults to the selected window. Return nil.
3998 Signal an error when WINDOW is the only window on its frame. */)
3999 (register Lisp_Object window)
4000 {
4001 register Lisp_Object parent, sibling, frame, root;
4002 struct window *w, *p, *s, *r;
4003 struct frame *f;
4004 int horflag;
4005 int before_sibling = 0;
4006
4007 w = decode_any_window (window);
4008 XSETWINDOW (window, w);
4009 if (NILP (w->buffer)
4010 && NILP (w->hchild) && NILP (w->vchild))
4011 /* It's a no-op to delete an already deleted window. */
4012 return Qnil;
4013
4014 parent = w->parent;
4015 if (NILP (parent))
4016 /* Never delete a minibuffer or frame root window. */
4017 error ("Attempt to delete minibuffer or sole ordinary window");
4018 else if (NILP (w->prev) && NILP (w->next))
4019 /* Rather bow out here, this case should be handled on the Elisp
4020 level. */
4021 error ("Attempt to delete sole window of parent");
4022
4023 p = XWINDOW (parent);
4024 horflag = NILP (p->vchild);
4025
4026 frame = WINDOW_FRAME (w);
4027 f = XFRAME (frame);
4028
4029 root = FRAME_ROOT_WINDOW (f);
4030 r = XWINDOW (root);
4031
4032 /* Unlink WINDOW from window tree. */
4033 if (NILP (w->prev))
4034 /* Get SIBLING below (on the right of) WINDOW. */
4035 {
4036 /* before_sibling 1 means WINDOW is the first child of its
4037 parent and thus before the sibling. */
4038 before_sibling = 1;
4039 sibling = w->next;
4040 s = XWINDOW (sibling);
4041 wset_prev (s, Qnil);
4042 if (horflag)
4043 wset_hchild (p, sibling);
4044 else
4045 wset_vchild (p, sibling);
4046 }
4047 else
4048 /* Get SIBLING above (on the left of) WINDOW. */
4049 {
4050 sibling = w->prev;
4051 s = XWINDOW (sibling);
4052 wset_next (s, w->next);
4053 if (!NILP (s->next))
4054 wset_prev (XWINDOW (s->next), sibling);
4055 }
4056
4057 if (window_resize_check (r, horflag)
4058 && EQ (r->new_total,
4059 (horflag ? r->total_cols : r->total_lines)))
4060 /* We can delete WINDOW now. */
4061 {
4062
4063 /* Block input. */
4064 BLOCK_INPUT;
4065 window_resize_apply (p, horflag);
4066
4067 /* If this window is referred to by the dpyinfo's mouse
4068 highlight, invalidate that slot to be safe (Bug#9904). */
4069 if (!FRAME_INITIAL_P (f))
4070 {
4071 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
4072
4073 if (EQ (hlinfo->mouse_face_window, window))
4074 hlinfo->mouse_face_window = Qnil;
4075 }
4076
4077 windows_or_buffers_changed++;
4078 Vwindow_list = Qnil;
4079 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4080
4081 wset_next (w, Qnil); /* Don't delete w->next too. */
4082 free_window_matrices (w);
4083
4084 if (!NILP (w->vchild))
4085 {
4086 delete_all_child_windows (w->vchild);
4087 wset_vchild (w, Qnil);
4088 }
4089 else if (!NILP (w->hchild))
4090 {
4091 delete_all_child_windows (w->hchild);
4092 wset_hchild (w, Qnil);
4093 }
4094 else if (!NILP (w->buffer))
4095 {
4096 unshow_buffer (w);
4097 unchain_marker (XMARKER (w->pointm));
4098 unchain_marker (XMARKER (w->start));
4099 wset_buffer (w, Qnil);
4100 }
4101
4102 if (NILP (s->prev) && NILP (s->next))
4103 /* A matrjoshka where SIBLING has become the only child of
4104 PARENT. */
4105 {
4106 /* Put SIBLING into PARENT's place. */
4107 replace_window (parent, sibling, 0);
4108 /* Have SIBLING inherit the following three slot values from
4109 PARENT (the combination_limit slot is not inherited). */
4110 wset_normal_cols (s, p->normal_cols);
4111 wset_normal_lines (s, p->normal_lines);
4112 /* Mark PARENT as deleted. */
4113 wset_vchild (p, Qnil);
4114 wset_hchild (p, Qnil);
4115 /* Try to merge SIBLING into its new parent. */
4116 recombine_windows (sibling);
4117 }
4118
4119 adjust_glyphs (f);
4120
4121 if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f)))
4122 /* We deleted the frame's selected window. */
4123 {
4124 /* Use the frame's first window as fallback ... */
4125 Lisp_Object new_selected_window = Fframe_first_window (frame);
4126 /* ... but preferably use its most recently used window. */
4127 Lisp_Object mru_window;
4128
4129 /* `get-mru-window' might fail for some reason so play it safe
4130 - promote the first window _without recording it_ first. */
4131 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4132 Fselect_window (new_selected_window, Qt);
4133 else
4134 fset_selected_window (f, new_selected_window);
4135
4136 UNBLOCK_INPUT;
4137
4138 /* Now look whether `get-mru-window' gets us something. */
4139 mru_window = call1 (Qget_mru_window, frame);
4140 if (WINDOW_LIVE_P (mru_window)
4141 && EQ (XWINDOW (mru_window)->frame, frame))
4142 new_selected_window = mru_window;
4143
4144 /* If all ended up well, we now promote the mru window. */
4145 if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
4146 Fselect_window (new_selected_window, Qnil);
4147 else
4148 fset_selected_window (f, new_selected_window);
4149 }
4150 else
4151 UNBLOCK_INPUT;
4152
4153 /* Must be run by the caller:
4154 run_window_configuration_change_hook (f); */
4155 }
4156 else
4157 /* We failed: Relink WINDOW into window tree. */
4158 {
4159 if (before_sibling)
4160 {
4161 wset_prev (s, window);
4162 if (horflag)
4163 wset_hchild (p, window);
4164 else
4165 wset_vchild (p, window);
4166 }
4167 else
4168 {
4169 wset_next (s, window);
4170 if (!NILP (w->next))
4171 wset_prev (XWINDOW (w->next), window);
4172 }
4173 error ("Deletion failed");
4174 }
4175
4176 return Qnil;
4177 }
4178 \f
4179 /***********************************************************************
4180 Resizing Mini-Windows
4181 ***********************************************************************/
4182
4183 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
4184 can. */
4185 void
4186 grow_mini_window (struct window *w, int delta)
4187 {
4188 struct frame *f = XFRAME (w->frame);
4189 struct window *r;
4190 Lisp_Object root, value;
4191
4192 eassert (MINI_WINDOW_P (w));
4193 eassert (delta >= 0);
4194
4195 root = FRAME_ROOT_WINDOW (f);
4196 r = XWINDOW (root);
4197 value = call2 (Qwindow_resize_root_window_vertically,
4198 root, make_number (- delta));
4199 if (INTEGERP (value) && window_resize_check (r, 0))
4200 {
4201 BLOCK_INPUT;
4202 window_resize_apply (r, 0);
4203
4204 /* Grow the mini-window. */
4205 wset_top_line
4206 (w, make_number (XFASTINT (r->top_line) + XFASTINT (r->total_lines)));
4207 wset_total_lines
4208 (w, make_number (XFASTINT (w->total_lines) - XINT (value)));
4209 w->last_modified = 0;
4210 w->last_overlay_modified = 0;
4211
4212 adjust_glyphs (f);
4213 UNBLOCK_INPUT;
4214 }
4215 }
4216
4217
4218 /* Shrink mini-window W. */
4219 void
4220 shrink_mini_window (struct window *w)
4221 {
4222 struct frame *f = XFRAME (w->frame);
4223 struct window *r;
4224 Lisp_Object root, value;
4225 EMACS_INT size;
4226
4227 eassert (MINI_WINDOW_P (w));
4228
4229 size = XINT (w->total_lines);
4230 if (size > 1)
4231 {
4232 root = FRAME_ROOT_WINDOW (f);
4233 r = XWINDOW (root);
4234 value = call2 (Qwindow_resize_root_window_vertically,
4235 root, make_number (size - 1));
4236 if (INTEGERP (value) && window_resize_check (r, 0))
4237 {
4238 BLOCK_INPUT;
4239 window_resize_apply (r, 0);
4240
4241 /* Shrink the mini-window. */
4242 wset_top_line (w, make_number (XFASTINT (r->top_line)
4243 + XFASTINT (r->total_lines)));
4244 wset_total_lines (w, make_number (1));
4245
4246 w->last_modified = 0;
4247 w->last_overlay_modified = 0;
4248
4249 adjust_glyphs (f);
4250 UNBLOCK_INPUT;
4251 }
4252 /* If the above failed for whatever strange reason we must make a
4253 one window frame here. The same routine will be needed when
4254 shrinking the frame (and probably when making the initial
4255 *scratch* window). For the moment leave things as they are. */
4256 }
4257 }
4258
4259 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini_window_internal, 1, 1, 0,
4260 doc: /* Resize minibuffer window WINDOW. */)
4261 (Lisp_Object window)
4262 {
4263 struct window *w = XWINDOW (window);
4264 struct window *r;
4265 struct frame *f;
4266 int height;
4267
4268 CHECK_WINDOW (window);
4269 f = XFRAME (w->frame);
4270
4271 if (!EQ (FRAME_MINIBUF_WINDOW (XFRAME (w->frame)), window))
4272 error ("Not a valid minibuffer window");
4273 else if (FRAME_MINIBUF_ONLY_P (f))
4274 error ("Cannot resize a minibuffer-only frame");
4275
4276 r = XWINDOW (FRAME_ROOT_WINDOW (f));
4277 height = XINT (r->total_lines) + XINT (w->total_lines);
4278 if (window_resize_check (r, 0)
4279 && XINT (w->new_total) > 0
4280 && height == XINT (r->new_total) + XINT (w->new_total))
4281 {
4282 BLOCK_INPUT;
4283 window_resize_apply (r, 0);
4284
4285 wset_total_lines (w, w->new_total);
4286 wset_top_line (w, make_number (XINT (r->top_line)
4287 + XINT (r->total_lines)));
4288
4289 windows_or_buffers_changed++;
4290 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
4291 adjust_glyphs (f);
4292 UNBLOCK_INPUT;
4293
4294 run_window_configuration_change_hook (f);
4295 return Qt;
4296 }
4297 else error ("Failed to resize minibuffer window");
4298 }
4299 \f
4300 /* Mark window cursors off for all windows in the window tree rooted
4301 at W by setting their phys_cursor_on_p flag to zero. Called from
4302 xterm.c, e.g. when a frame is cleared and thereby all cursors on
4303 the frame are cleared. */
4304
4305 void
4306 mark_window_cursors_off (struct window *w)
4307 {
4308 while (w)
4309 {
4310 if (!NILP (w->hchild))
4311 mark_window_cursors_off (XWINDOW (w->hchild));
4312 else if (!NILP (w->vchild))
4313 mark_window_cursors_off (XWINDOW (w->vchild));
4314 else
4315 w->phys_cursor_on_p = 0;
4316
4317 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4318 }
4319 }
4320
4321
4322 /* Return number of lines of text (not counting mode lines) in W. */
4323
4324 int
4325 window_internal_height (struct window *w)
4326 {
4327 int ht = XFASTINT (w->total_lines);
4328
4329 if (!MINI_WINDOW_P (w))
4330 {
4331 if (!NILP (w->parent)
4332 || !NILP (w->vchild)
4333 || !NILP (w->hchild)
4334 || !NILP (w->next)
4335 || !NILP (w->prev)
4336 || WINDOW_WANTS_MODELINE_P (w))
4337 --ht;
4338
4339 if (WINDOW_WANTS_HEADER_LINE_P (w))
4340 --ht;
4341 }
4342
4343 return ht;
4344 }
4345 \f
4346 /************************************************************************
4347 Window Scrolling
4348 ***********************************************************************/
4349
4350 /* Scroll contents of window WINDOW up. If WHOLE is non-zero, scroll
4351 N screen-fulls, which is defined as the height of the window minus
4352 next_screen_context_lines. If WHOLE is zero, scroll up N lines
4353 instead. Negative values of N mean scroll down. NOERROR non-zero
4354 means don't signal an error if we try to move over BEGV or ZV,
4355 respectively. */
4356
4357 static void
4358 window_scroll (Lisp_Object window, EMACS_INT n, int whole, int noerror)
4359 {
4360 immediate_quit = 1;
4361 n = clip_to_bounds (INT_MIN, n, INT_MAX);
4362
4363 /* If we must, use the pixel-based version which is much slower than
4364 the line-based one but can handle varying line heights. */
4365 if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
4366 window_scroll_pixel_based (window, n, whole, noerror);
4367 else
4368 window_scroll_line_based (window, n, whole, noerror);
4369
4370 immediate_quit = 0;
4371 }
4372
4373
4374 /* Implementation of window_scroll that works based on pixel line
4375 heights. See the comment of window_scroll for parameter
4376 descriptions. */
4377
4378 static void
4379 window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
4380 {
4381 struct it it;
4382 struct window *w = XWINDOW (window);
4383 struct text_pos start;
4384 int this_scroll_margin;
4385 /* True if we fiddled the window vscroll field without really scrolling. */
4386 int vscrolled = 0;
4387 int x, y, rtop, rbot, rowh, vpos;
4388 void *itdata = NULL;
4389
4390 SET_TEXT_POS_FROM_MARKER (start, w->start);
4391 /* Scrolling a minibuffer window via scroll bar when the echo area
4392 shows long text sometimes resets the minibuffer contents behind
4393 our backs. */
4394 if (CHARPOS (start) > ZV)
4395 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
4396
4397 /* If PT is not visible in WINDOW, move back one half of
4398 the screen. Allow PT to be partially visible, otherwise
4399 something like (scroll-down 1) with PT in the line before
4400 the partially visible one would recenter. */
4401
4402 if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
4403 {
4404 itdata = bidi_shelve_cache ();
4405 /* Move backward half the height of the window. Performance note:
4406 vmotion used here is about 10% faster, but would give wrong
4407 results for variable height lines. */
4408 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4409 it.current_y = it.last_visible_y;
4410 move_it_vertically_backward (&it, window_box_height (w) / 2);
4411
4412 /* The function move_iterator_vertically may move over more than
4413 the specified y-distance. If it->w is small, e.g. a
4414 mini-buffer window, we may end up in front of the window's
4415 display area. This is the case when Start displaying at the
4416 start of the line containing PT in this case. */
4417 if (it.current_y <= 0)
4418 {
4419 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
4420 move_it_vertically_backward (&it, 0);
4421 it.current_y = 0;
4422 }
4423
4424 start = it.current.pos;
4425 bidi_unshelve_cache (itdata, 0);
4426 }
4427 else if (auto_window_vscroll_p)
4428 {
4429 if (rtop || rbot) /* partially visible */
4430 {
4431 int px;
4432 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4433 if (whole)
4434 dy = max ((window_box_height (w)
4435 - next_screen_context_lines * dy),
4436 dy);
4437 dy *= n;
4438
4439 if (n < 0)
4440 {
4441 /* Only vscroll backwards if already vscrolled forwards. */
4442 if (w->vscroll < 0 && rtop > 0)
4443 {
4444 px = max (0, -w->vscroll - min (rtop, -dy));
4445 Fset_window_vscroll (window, make_number (px), Qt);
4446 return;
4447 }
4448 }
4449 if (n > 0)
4450 {
4451 /* Do vscroll if already vscrolled or only display line. */
4452 if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
4453 {
4454 px = max (0, -w->vscroll + min (rbot, dy));
4455 Fset_window_vscroll (window, make_number (px), Qt);
4456 return;
4457 }
4458
4459 /* Maybe modify window start instead of scrolling. */
4460 if (rbot > 0 || w->vscroll < 0)
4461 {
4462 ptrdiff_t spos;
4463
4464 Fset_window_vscroll (window, make_number (0), Qt);
4465 /* If there are other text lines above the current row,
4466 move window start to current row. Else to next row. */
4467 if (rbot > 0)
4468 spos = XINT (Fline_beginning_position (Qnil));
4469 else
4470 spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
4471 set_marker_restricted (w->start, make_number (spos),
4472 w->buffer);
4473 w->start_at_line_beg = 1;
4474 w->update_mode_line = 1;
4475 w->last_modified = 0;
4476 w->last_overlay_modified = 0;
4477 /* Set force_start so that redisplay_window will run the
4478 window-scroll-functions. */
4479 w->force_start = 1;
4480 return;
4481 }
4482 }
4483 }
4484 /* Cancel previous vscroll. */
4485 Fset_window_vscroll (window, make_number (0), Qt);
4486 }
4487
4488 itdata = bidi_shelve_cache ();
4489 /* If scroll_preserve_screen_position is non-nil, we try to set
4490 point in the same window line as it is now, so get that line. */
4491 if (!NILP (Vscroll_preserve_screen_position))
4492 {
4493 /* We preserve the goal pixel coordinate across consecutive
4494 calls to scroll-up, scroll-down and other commands that
4495 have the `scroll-command' property. This avoids the
4496 possibility of point becoming "stuck" on a tall line when
4497 scrolling by one line. */
4498 if (window_scroll_pixel_based_preserve_y < 0
4499 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4500 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4501 {
4502 start_display (&it, w, start);
4503 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4504 window_scroll_pixel_based_preserve_y = it.current_y;
4505 window_scroll_pixel_based_preserve_x = it.current_x;
4506 }
4507 }
4508 else
4509 window_scroll_pixel_based_preserve_y
4510 = window_scroll_pixel_based_preserve_x = -1;
4511
4512 /* Move iterator it from start the specified distance forward or
4513 backward. The result is the new window start. */
4514 start_display (&it, w, start);
4515 if (whole)
4516 {
4517 ptrdiff_t start_pos = IT_CHARPOS (it);
4518 int dy = WINDOW_FRAME_LINE_HEIGHT (w);
4519 dy = max ((window_box_height (w)
4520 - next_screen_context_lines * dy),
4521 dy) * n;
4522
4523 /* Note that move_it_vertically always moves the iterator to the
4524 start of a line. So, if the last line doesn't have a newline,
4525 we would end up at the start of the line ending at ZV. */
4526 if (dy <= 0)
4527 {
4528 move_it_vertically_backward (&it, -dy);
4529 /* Ensure we actually do move, e.g. in case we are currently
4530 looking at an image that is taller that the window height. */
4531 while (start_pos == IT_CHARPOS (it)
4532 && start_pos > BEGV)
4533 move_it_by_lines (&it, -1);
4534 }
4535 else if (dy > 0)
4536 {
4537 move_it_to (&it, ZV, -1, it.current_y + dy, -1,
4538 MOVE_TO_POS | MOVE_TO_Y);
4539 /* Ensure we actually do move, e.g. in case we are currently
4540 looking at an image that is taller that the window height. */
4541 while (start_pos == IT_CHARPOS (it)
4542 && start_pos < ZV)
4543 move_it_by_lines (&it, 1);
4544 }
4545 }
4546 else
4547 move_it_by_lines (&it, n);
4548
4549 /* We failed if we find ZV is already on the screen (scrolling up,
4550 means there's nothing past the end), or if we can't start any
4551 earlier (scrolling down, means there's nothing past the top). */
4552 if ((n > 0 && IT_CHARPOS (it) == ZV)
4553 || (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
4554 {
4555 if (IT_CHARPOS (it) == ZV)
4556 {
4557 if (it.current_y < it.last_visible_y
4558 && (it.current_y + it.max_ascent + it.max_descent
4559 > it.last_visible_y))
4560 {
4561 /* The last line was only partially visible, make it fully
4562 visible. */
4563 w->vscroll = (it.last_visible_y
4564 - it.current_y + it.max_ascent + it.max_descent);
4565 adjust_glyphs (it.f);
4566 }
4567 else
4568 {
4569 bidi_unshelve_cache (itdata, 0);
4570 if (noerror)
4571 return;
4572 else if (n < 0) /* could happen with empty buffers */
4573 xsignal0 (Qbeginning_of_buffer);
4574 else
4575 xsignal0 (Qend_of_buffer);
4576 }
4577 }
4578 else
4579 {
4580 if (w->vscroll != 0)
4581 /* The first line was only partially visible, make it fully
4582 visible. */
4583 w->vscroll = 0;
4584 else
4585 {
4586 bidi_unshelve_cache (itdata, 0);
4587 if (noerror)
4588 return;
4589 else
4590 xsignal0 (Qbeginning_of_buffer);
4591 }
4592 }
4593
4594 /* If control gets here, then we vscrolled. */
4595
4596 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
4597
4598 /* Don't try to change the window start below. */
4599 vscrolled = 1;
4600 }
4601
4602 if (! vscrolled)
4603 {
4604 ptrdiff_t pos = IT_CHARPOS (it);
4605 ptrdiff_t bytepos;
4606
4607 /* If in the middle of a multi-glyph character move forward to
4608 the next character. */
4609 if (in_display_vector_p (&it))
4610 {
4611 ++pos;
4612 move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
4613 }
4614
4615 /* Set the window start, and set up the window for redisplay. */
4616 set_marker_restricted (w->start, make_number (pos),
4617 w->buffer);
4618 bytepos = XMARKER (w->start)->bytepos;
4619 w->start_at_line_beg = (pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n');
4620 w->update_mode_line = 1;
4621 w->last_modified = 0;
4622 w->last_overlay_modified = 0;
4623 /* Set force_start so that redisplay_window will run the
4624 window-scroll-functions. */
4625 w->force_start = 1;
4626 }
4627
4628 /* The rest of this function uses current_y in a nonstandard way,
4629 not including the height of the header line if any. */
4630 it.current_y = it.vpos = 0;
4631
4632 /* Move PT out of scroll margins.
4633 This code wants current_y to be zero at the window start position
4634 even if there is a header line. */
4635 this_scroll_margin = max (0, scroll_margin);
4636 this_scroll_margin
4637 = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
4638 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
4639
4640 if (n > 0)
4641 {
4642 /* We moved the window start towards ZV, so PT may be now
4643 in the scroll margin at the top. */
4644 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
4645 if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
4646 && (NILP (Vscroll_preserve_screen_position)
4647 || EQ (Vscroll_preserve_screen_position, Qt)))
4648 /* We found PT at a legitimate height. Leave it alone. */
4649 ;
4650 else if (window_scroll_pixel_based_preserve_y >= 0)
4651 {
4652 /* If we have a header line, take account of it.
4653 This is necessary because we set it.current_y to 0, above. */
4654 move_it_to (&it, -1,
4655 window_scroll_pixel_based_preserve_x,
4656 window_scroll_pixel_based_preserve_y
4657 - (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
4658 -1, MOVE_TO_Y | MOVE_TO_X);
4659 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4660 }
4661 else
4662 {
4663 while (it.current_y < this_scroll_margin)
4664 {
4665 int prev = it.current_y;
4666 move_it_by_lines (&it, 1);
4667 if (prev == it.current_y)
4668 break;
4669 }
4670 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4671 }
4672 }
4673 else if (n < 0)
4674 {
4675 ptrdiff_t charpos, bytepos;
4676 int partial_p;
4677
4678 /* Save our position, for the
4679 window_scroll_pixel_based_preserve_y case. */
4680 charpos = IT_CHARPOS (it);
4681 bytepos = IT_BYTEPOS (it);
4682
4683 /* We moved the window start towards BEGV, so PT may be now
4684 in the scroll margin at the bottom. */
4685 move_it_to (&it, PT, -1,
4686 (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
4687 - this_scroll_margin - 1),
4688 -1,
4689 MOVE_TO_POS | MOVE_TO_Y);
4690
4691 /* Save our position, in case it's correct. */
4692 charpos = IT_CHARPOS (it);
4693 bytepos = IT_BYTEPOS (it);
4694
4695 /* See if point is on a partially visible line at the end. */
4696 if (it.what == IT_EOB)
4697 partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
4698 else
4699 {
4700 move_it_by_lines (&it, 1);
4701 partial_p = it.current_y > it.last_visible_y;
4702 }
4703
4704 if (charpos == PT && !partial_p
4705 && (NILP (Vscroll_preserve_screen_position)
4706 || EQ (Vscroll_preserve_screen_position, Qt)))
4707 /* We found PT before we found the display margin, so PT is ok. */
4708 ;
4709 else if (window_scroll_pixel_based_preserve_y >= 0)
4710 {
4711 SET_TEXT_POS_FROM_MARKER (start, w->start);
4712 start_display (&it, w, start);
4713 /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT
4714 here because we called start_display again and did not
4715 alter it.current_y this time. */
4716 move_it_to (&it, -1, window_scroll_pixel_based_preserve_x,
4717 window_scroll_pixel_based_preserve_y, -1,
4718 MOVE_TO_Y | MOVE_TO_X);
4719 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4720 }
4721 else
4722 {
4723 if (partial_p)
4724 /* The last line was only partially visible, so back up two
4725 lines to make sure we're on a fully visible line. */
4726 {
4727 move_it_by_lines (&it, -2);
4728 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
4729 }
4730 else
4731 /* No, the position we saved is OK, so use it. */
4732 SET_PT_BOTH (charpos, bytepos);
4733 }
4734 }
4735 bidi_unshelve_cache (itdata, 0);
4736 }
4737
4738
4739 /* Implementation of window_scroll that works based on screen lines.
4740 See the comment of window_scroll for parameter descriptions. */
4741
4742 static void
4743 window_scroll_line_based (Lisp_Object window, int n, int whole, int noerror)
4744 {
4745 register struct window *w = XWINDOW (window);
4746 /* Fvertical_motion enters redisplay, which can trigger
4747 fontification, which in turn can modify buffer text (e.g., if the
4748 fontification functions replace escape sequences with faces, as
4749 in `grep-mode-font-lock-keywords'). So we use a marker to record
4750 the old point position, to prevent crashes in SET_PT_BOTH. */
4751 Lisp_Object opoint_marker = Fpoint_marker ();
4752 register ptrdiff_t pos, pos_byte;
4753 register int ht = window_internal_height (w);
4754 register Lisp_Object tem;
4755 int lose;
4756 Lisp_Object bolp;
4757 ptrdiff_t startpos;
4758 Lisp_Object original_pos = Qnil;
4759
4760 /* If scrolling screen-fulls, compute the number of lines to
4761 scroll from the window's height. */
4762 if (whole)
4763 n *= max (1, ht - next_screen_context_lines);
4764
4765 startpos = marker_position (w->start);
4766
4767 if (!NILP (Vscroll_preserve_screen_position))
4768 {
4769 if (window_scroll_preserve_vpos <= 0
4770 || !SYMBOLP (KVAR (current_kboard, Vlast_command))
4771 || NILP (Fget (KVAR (current_kboard, Vlast_command), Qscroll_command)))
4772 {
4773 struct position posit
4774 = *compute_motion (startpos, 0, 0, 0,
4775 PT, ht, 0,
4776 -1, w->hscroll,
4777 0, w);
4778 window_scroll_preserve_vpos = posit.vpos;
4779 window_scroll_preserve_hpos = posit.hpos + w->hscroll;
4780 }
4781
4782 original_pos = Fcons (make_number (window_scroll_preserve_hpos),
4783 make_number (window_scroll_preserve_vpos));
4784 }
4785
4786 XSETFASTINT (tem, PT);
4787 tem = Fpos_visible_in_window_p (tem, window, Qnil);
4788
4789 if (NILP (tem))
4790 {
4791 Fvertical_motion (make_number (- (ht / 2)), window);
4792 startpos = PT;
4793 }
4794
4795 SET_PT (startpos);
4796 lose = n < 0 && PT == BEGV;
4797 Fvertical_motion (make_number (n), window);
4798 pos = PT;
4799 pos_byte = PT_BYTE;
4800 bolp = Fbolp ();
4801 SET_PT_BOTH (marker_position (opoint_marker),
4802 marker_byte_position (opoint_marker));
4803
4804 if (lose)
4805 {
4806 if (noerror)
4807 return;
4808 else
4809 xsignal0 (Qbeginning_of_buffer);
4810 }
4811
4812 if (pos < ZV)
4813 {
4814 /* Don't use a scroll margin that is negative or too large. */
4815 int this_scroll_margin =
4816 max (0, min (scroll_margin, XINT (w->total_lines) / 4));
4817
4818 set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
4819 w->start_at_line_beg = !NILP (bolp);
4820 w->update_mode_line = 1;
4821 w->last_modified = 0;
4822 w->last_overlay_modified = 0;
4823 /* Set force_start so that redisplay_window will run
4824 the window-scroll-functions. */
4825 w->force_start = 1;
4826
4827 if (!NILP (Vscroll_preserve_screen_position)
4828 && (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
4829 {
4830 SET_PT_BOTH (pos, pos_byte);
4831 Fvertical_motion (original_pos, window);
4832 }
4833 /* If we scrolled forward, put point enough lines down
4834 that it is outside the scroll margin. */
4835 else if (n > 0)
4836 {
4837 int top_margin;
4838
4839 if (this_scroll_margin > 0)
4840 {
4841 SET_PT_BOTH (pos, pos_byte);
4842 Fvertical_motion (make_number (this_scroll_margin), window);
4843 top_margin = PT;
4844 }
4845 else
4846 top_margin = pos;
4847
4848 if (top_margin <= marker_position (opoint_marker))
4849 SET_PT_BOTH (marker_position (opoint_marker),
4850 marker_byte_position (opoint_marker));
4851 else if (!NILP (Vscroll_preserve_screen_position))
4852 {
4853 SET_PT_BOTH (pos, pos_byte);
4854 Fvertical_motion (original_pos, window);
4855 }
4856 else
4857 SET_PT (top_margin);
4858 }
4859 else if (n < 0)
4860 {
4861 int bottom_margin;
4862
4863 /* If we scrolled backward, put point near the end of the window
4864 but not within the scroll margin. */
4865 SET_PT_BOTH (pos, pos_byte);
4866 tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
4867 if (XFASTINT (tem) == ht - this_scroll_margin)
4868 bottom_margin = PT;
4869 else
4870 bottom_margin = PT + 1;
4871
4872 if (bottom_margin > marker_position (opoint_marker))
4873 SET_PT_BOTH (marker_position (opoint_marker),
4874 marker_byte_position (opoint_marker));
4875 else
4876 {
4877 if (!NILP (Vscroll_preserve_screen_position))
4878 {
4879 SET_PT_BOTH (pos, pos_byte);
4880 Fvertical_motion (original_pos, window);
4881 }
4882 else
4883 Fvertical_motion (make_number (-1), window);
4884 }
4885 }
4886 }
4887 else
4888 {
4889 if (noerror)
4890 return;
4891 else
4892 xsignal0 (Qend_of_buffer);
4893 }
4894 }
4895
4896
4897 /* Scroll selected_window up or down. If N is nil, scroll a
4898 screen-full which is defined as the height of the window minus
4899 next_screen_context_lines. If N is the symbol `-', scroll.
4900 DIRECTION may be 1 meaning to scroll down, or -1 meaning to scroll
4901 up. This is the guts of Fscroll_up and Fscroll_down. */
4902
4903 static void
4904 scroll_command (Lisp_Object n, int direction)
4905 {
4906 ptrdiff_t count = SPECPDL_INDEX ();
4907
4908 eassert (eabs (direction) == 1);
4909
4910 /* If selected window's buffer isn't current, make it current for
4911 the moment. But don't screw up if window_scroll gets an error. */
4912 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
4913 {
4914 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4915 Fset_buffer (XWINDOW (selected_window)->buffer);
4916
4917 /* Make redisplay consider other windows than just selected_window. */
4918 ++windows_or_buffers_changed;
4919 }
4920
4921 if (NILP (n))
4922 window_scroll (selected_window, direction, 1, 0);
4923 else if (EQ (n, Qminus))
4924 window_scroll (selected_window, -direction, 1, 0);
4925 else
4926 {
4927 n = Fprefix_numeric_value (n);
4928 window_scroll (selected_window, XINT (n) * direction, 0, 0);
4929 }
4930
4931 unbind_to (count, Qnil);
4932 }
4933
4934 DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
4935 doc: /* Scroll text of selected window upward ARG lines.
4936 If ARG is omitted or nil, scroll upward by a near full screen.
4937 A near full screen is `next-screen-context-lines' less than a full screen.
4938 Negative ARG means scroll downward.
4939 If ARG is the atom `-', scroll downward by nearly full screen.
4940 When calling from a program, supply as argument a number, nil, or `-'. */)
4941 (Lisp_Object arg)
4942 {
4943 scroll_command (arg, 1);
4944 return Qnil;
4945 }
4946
4947 DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "^P",
4948 doc: /* Scroll text of selected window down ARG lines.
4949 If ARG is omitted or nil, scroll down by a near full screen.
4950 A near full screen is `next-screen-context-lines' less than a full screen.
4951 Negative ARG means scroll upward.
4952 If ARG is the atom `-', scroll upward by nearly full screen.
4953 When calling from a program, supply as argument a number, nil, or `-'. */)
4954 (Lisp_Object arg)
4955 {
4956 scroll_command (arg, -1);
4957 return Qnil;
4958 }
4959 \f
4960 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
4961 doc: /* Return the other window for \"other window scroll\" commands.
4962 If `other-window-scroll-buffer' is non-nil, a window
4963 showing that buffer is used.
4964 If in the minibuffer, `minibuffer-scroll-window' if non-nil
4965 specifies the window. This takes precedence over
4966 `other-window-scroll-buffer'. */)
4967 (void)
4968 {
4969 Lisp_Object window;
4970
4971 if (MINI_WINDOW_P (XWINDOW (selected_window))
4972 && !NILP (Vminibuf_scroll_window))
4973 window = Vminibuf_scroll_window;
4974 /* If buffer is specified, scroll that buffer. */
4975 else if (!NILP (Vother_window_scroll_buffer))
4976 {
4977 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
4978 if (NILP (window))
4979 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil);
4980 }
4981 else
4982 {
4983 /* Nothing specified; look for a neighboring window on the same
4984 frame. */
4985 window = Fnext_window (selected_window, Qnil, Qnil);
4986
4987 if (EQ (window, selected_window))
4988 /* That didn't get us anywhere; look for a window on another
4989 visible frame. */
4990 do
4991 window = Fnext_window (window, Qnil, Qt);
4992 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
4993 && ! EQ (window, selected_window));
4994 }
4995
4996 CHECK_LIVE_WINDOW (window);
4997
4998 if (EQ (window, selected_window))
4999 error ("There is no other window");
5000
5001 return window;
5002 }
5003
5004 DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
5005 doc: /* Scroll next window upward ARG lines; or near full screen if no ARG.
5006 A near full screen is `next-screen-context-lines' less than a full screen.
5007 The next window is the one below the current one; or the one at the top
5008 if the current one is at the bottom. Negative ARG means scroll downward.
5009 If ARG is the atom `-', scroll downward by nearly full screen.
5010 When calling from a program, supply as argument a number, nil, or `-'.
5011
5012 If `other-window-scroll-buffer' is non-nil, scroll the window
5013 showing that buffer, popping the buffer up if necessary.
5014 If in the minibuffer, `minibuffer-scroll-window' if non-nil
5015 specifies the window to scroll. This takes precedence over
5016 `other-window-scroll-buffer'. */)
5017 (Lisp_Object arg)
5018 {
5019 Lisp_Object window;
5020 struct window *w;
5021 ptrdiff_t count = SPECPDL_INDEX ();
5022
5023 window = Fother_window_for_scrolling ();
5024 w = XWINDOW (window);
5025
5026 /* Don't screw up if window_scroll gets an error. */
5027 record_unwind_protect (save_excursion_restore, save_excursion_save ());
5028 ++windows_or_buffers_changed;
5029
5030 Fset_buffer (w->buffer);
5031 SET_PT (marker_position (w->pointm));
5032
5033 if (NILP (arg))
5034 window_scroll (window, 1, 1, 1);
5035 else if (EQ (arg, Qminus))
5036 window_scroll (window, -1, 1, 1);
5037 else
5038 {
5039 if (CONSP (arg))
5040 arg = XCAR (arg);
5041 CHECK_NUMBER (arg);
5042 window_scroll (window, XINT (arg), 0, 1);
5043 }
5044
5045 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5046 unbind_to (count, Qnil);
5047
5048 return Qnil;
5049 }
5050 \f
5051 DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "^P\np",
5052 doc: /* Scroll selected window display ARG columns left.
5053 Default for ARG is window width minus 2.
5054 Value is the total amount of leftward horizontal scrolling in
5055 effect after the change.
5056 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5057 lower bound for automatic scrolling, i.e. automatic scrolling
5058 will not scroll a window to a column less than the value returned
5059 by this function. This happens in an interactive call. */)
5060 (register Lisp_Object arg, Lisp_Object set_minimum)
5061 {
5062 struct window *w = XWINDOW (selected_window);
5063 EMACS_INT requested_arg = (NILP (arg)
5064 ? window_body_cols (w) - 2
5065 : XINT (Fprefix_numeric_value (arg)));
5066 Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
5067
5068 if (!NILP (set_minimum))
5069 w->min_hscroll = w->hscroll;
5070
5071 return result;
5072 }
5073
5074 DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "^P\np",
5075 doc: /* Scroll selected window display ARG columns right.
5076 Default for ARG is window width minus 2.
5077 Value is the total amount of leftward horizontal scrolling in
5078 effect after the change.
5079 If SET-MINIMUM is non-nil, the new scroll amount becomes the
5080 lower bound for automatic scrolling, i.e. automatic scrolling
5081 will not scroll a window to a column less than the value returned
5082 by this function. This happens in an interactive call. */)
5083 (register Lisp_Object arg, Lisp_Object set_minimum)
5084 {
5085 struct window *w = XWINDOW (selected_window);
5086 EMACS_INT requested_arg = (NILP (arg)
5087 ? window_body_cols (w) - 2
5088 : XINT (Fprefix_numeric_value (arg)));
5089 Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
5090
5091 if (!NILP (set_minimum))
5092 w->min_hscroll = w->hscroll;
5093
5094 return result;
5095 }
5096
5097 DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
5098 doc: /* Return the window which was selected when entering the minibuffer.
5099 Returns nil, if selected window is not a minibuffer window. */)
5100 (void)
5101 {
5102 if (minibuf_level > 0
5103 && MINI_WINDOW_P (XWINDOW (selected_window))
5104 && WINDOW_LIVE_P (minibuf_selected_window))
5105 return minibuf_selected_window;
5106
5107 return Qnil;
5108 }
5109
5110 /* Value is the number of lines actually displayed in window W,
5111 as opposed to its height. */
5112
5113 static int
5114 displayed_window_lines (struct window *w)
5115 {
5116 struct it it;
5117 struct text_pos start;
5118 int height = window_box_height (w);
5119 struct buffer *old_buffer;
5120 int bottom_y;
5121 void *itdata = NULL;
5122
5123 if (XBUFFER (w->buffer) != current_buffer)
5124 {
5125 old_buffer = current_buffer;
5126 set_buffer_internal (XBUFFER (w->buffer));
5127 }
5128 else
5129 old_buffer = NULL;
5130
5131 /* In case W->start is out of the accessible range, do something
5132 reasonable. This happens in Info mode when Info-scroll-down
5133 calls (recenter -1) while W->start is 1. */
5134 if (XMARKER (w->start)->charpos < BEGV)
5135 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
5136 else if (XMARKER (w->start)->charpos > ZV)
5137 SET_TEXT_POS (start, ZV, ZV_BYTE);
5138 else
5139 SET_TEXT_POS_FROM_MARKER (start, w->start);
5140
5141 itdata = bidi_shelve_cache ();
5142 start_display (&it, w, start);
5143 move_it_vertically (&it, height);
5144 bottom_y = line_bottom_y (&it);
5145 bidi_unshelve_cache (itdata, 0);
5146
5147 /* rms: On a non-window display,
5148 the value of it.vpos at the bottom of the screen
5149 seems to be 1 larger than window_box_height (w).
5150 This kludge fixes a bug whereby (move-to-window-line -1)
5151 when ZV is on the last screen line
5152 moves to the previous screen line instead of the last one. */
5153 if (! FRAME_WINDOW_P (XFRAME (w->frame)))
5154 height++;
5155
5156 /* Add in empty lines at the bottom of the window. */
5157 if (bottom_y < height)
5158 {
5159 int uy = FRAME_LINE_HEIGHT (it.f);
5160 it.vpos += (height - bottom_y + uy - 1) / uy;
5161 }
5162
5163 if (old_buffer)
5164 set_buffer_internal (old_buffer);
5165
5166 return it.vpos;
5167 }
5168
5169
5170 DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
5171 doc: /* Center point in selected window and maybe redisplay frame.
5172 With prefix argument ARG, recenter putting point on screen line ARG
5173 relative to the selected window. If ARG is negative, it counts up from the
5174 bottom of the window. (ARG should be less than the height of the window.)
5175
5176 If ARG is omitted or nil, then recenter with point on the middle line of
5177 the selected window; if the variable `recenter-redisplay' is non-nil,
5178 also erase the entire frame and redraw it (when `auto-resize-tool-bars'
5179 is set to `grow-only', this resets the tool-bar's height to the minimum
5180 height needed); if `recenter-redisplay' has the special value `tty',
5181 then only tty frames are redrawn.
5182
5183 Just C-u as prefix means put point in the center of the window
5184 and redisplay normally--don't erase and redraw the frame. */)
5185 (register Lisp_Object arg)
5186 {
5187 struct window *w = XWINDOW (selected_window);
5188 struct buffer *buf = XBUFFER (w->buffer);
5189 struct buffer *obuf = current_buffer;
5190 int center_p = 0;
5191 ptrdiff_t charpos, bytepos;
5192 EMACS_INT iarg IF_LINT (= 0);
5193 int this_scroll_margin;
5194
5195 /* If redisplay is suppressed due to an error, try again. */
5196 obuf->display_error_modiff = 0;
5197
5198 if (NILP (arg))
5199 {
5200 if (!NILP (Vrecenter_redisplay)
5201 && (!EQ (Vrecenter_redisplay, Qtty)
5202 || !NILP (Ftty_type (selected_frame))))
5203 {
5204 ptrdiff_t i;
5205
5206 /* Invalidate pixel data calculated for all compositions. */
5207 for (i = 0; i < n_compositions; i++)
5208 composition_table[i]->font = NULL;
5209
5210 WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
5211
5212 Fredraw_frame (WINDOW_FRAME (w));
5213 SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
5214 }
5215
5216 center_p = 1;
5217 }
5218 else if (CONSP (arg)) /* Just C-u. */
5219 center_p = 1;
5220 else
5221 {
5222 arg = Fprefix_numeric_value (arg);
5223 CHECK_NUMBER (arg);
5224 iarg = XINT (arg);
5225 }
5226
5227 set_buffer_internal (buf);
5228
5229 /* Do this after making BUF current
5230 in case scroll_margin is buffer-local. */
5231 this_scroll_margin =
5232 max (0, min (scroll_margin, XFASTINT (w->total_lines) / 4));
5233
5234 /* Handle centering on a graphical frame specially. Such frames can
5235 have variable-height lines and centering point on the basis of
5236 line counts would lead to strange effects. */
5237 if (FRAME_WINDOW_P (XFRAME (w->frame)))
5238 {
5239 if (center_p)
5240 {
5241 struct it it;
5242 struct text_pos pt;
5243 void *itdata = bidi_shelve_cache ();
5244
5245 SET_TEXT_POS (pt, PT, PT_BYTE);
5246 start_display (&it, w, pt);
5247 move_it_vertically_backward (&it, window_box_height (w) / 2);
5248 charpos = IT_CHARPOS (it);
5249 bytepos = IT_BYTEPOS (it);
5250 bidi_unshelve_cache (itdata, 0);
5251 }
5252 else if (iarg < 0)
5253 {
5254 struct it it;
5255 struct text_pos pt;
5256 ptrdiff_t nlines = min (PTRDIFF_MAX, -iarg);
5257 int extra_line_spacing;
5258 int h = window_box_height (w);
5259 void *itdata = bidi_shelve_cache ();
5260
5261 iarg = - max (-iarg, this_scroll_margin);
5262
5263 SET_TEXT_POS (pt, PT, PT_BYTE);
5264 start_display (&it, w, pt);
5265
5266 /* Be sure we have the exact height of the full line containing PT. */
5267 move_it_by_lines (&it, 0);
5268
5269 /* The amount of pixels we have to move back is the window
5270 height minus what's displayed in the line containing PT,
5271 and the lines below. */
5272 it.current_y = 0;
5273 it.vpos = 0;
5274 move_it_by_lines (&it, nlines);
5275
5276 if (it.vpos == nlines)
5277 h -= it.current_y;
5278 else
5279 {
5280 /* Last line has no newline */
5281 h -= line_bottom_y (&it);
5282 it.vpos++;
5283 }
5284
5285 /* Don't reserve space for extra line spacing of last line. */
5286 extra_line_spacing = it.max_extra_line_spacing;
5287
5288 /* If we can't move down NLINES lines because we hit
5289 the end of the buffer, count in some empty lines. */
5290 if (it.vpos < nlines)
5291 {
5292 nlines -= it.vpos;
5293 extra_line_spacing = it.extra_line_spacing;
5294 h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
5295 }
5296 if (h <= 0)
5297 {
5298 bidi_unshelve_cache (itdata, 0);
5299 return Qnil;
5300 }
5301
5302 /* Now find the new top line (starting position) of the window. */
5303 start_display (&it, w, pt);
5304 it.current_y = 0;
5305 move_it_vertically_backward (&it, h);
5306
5307 /* If extra line spacing is present, we may move too far
5308 back. This causes the last line to be only partially
5309 visible (which triggers redisplay to recenter that line
5310 in the middle), so move forward.
5311 But ignore extra line spacing on last line, as it is not
5312 considered to be part of the visible height of the line.
5313 */
5314 h += extra_line_spacing;
5315 while (-it.current_y > h)
5316 move_it_by_lines (&it, 1);
5317
5318 charpos = IT_CHARPOS (it);
5319 bytepos = IT_BYTEPOS (it);
5320
5321 bidi_unshelve_cache (itdata, 0);
5322 }
5323 else
5324 {
5325 struct position pos;
5326
5327 iarg = max (iarg, this_scroll_margin);
5328
5329 pos = *vmotion (PT, -iarg, w);
5330 charpos = pos.bufpos;
5331 bytepos = pos.bytepos;
5332 }
5333 }
5334 else
5335 {
5336 struct position pos;
5337 int ht = window_internal_height (w);
5338
5339 if (center_p)
5340 iarg = ht / 2;
5341 else if (iarg < 0)
5342 iarg += ht;
5343
5344 /* Don't let it get into the margin at either top or bottom. */
5345 iarg = max (iarg, this_scroll_margin);
5346 iarg = min (iarg, ht - this_scroll_margin - 1);
5347
5348 pos = *vmotion (PT, - iarg, w);
5349 charpos = pos.bufpos;
5350 bytepos = pos.bytepos;
5351 }
5352
5353 /* Set the new window start. */
5354 set_marker_both (w->start, w->buffer, charpos, bytepos);
5355 wset_window_end_valid (w, Qnil);
5356
5357 w->optional_new_start = 1;
5358
5359 w->start_at_line_beg = (bytepos == BEGV_BYTE ||
5360 FETCH_BYTE (bytepos - 1) == '\n');
5361
5362 set_buffer_internal (obuf);
5363 return Qnil;
5364 }
5365
5366 DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
5367 0, 1, 0,
5368 doc: /* Return the height in lines of the text display area of WINDOW.
5369 WINDOW must be a live window and defaults to the selected one.
5370
5371 The returned height does not include the mode line, any header line,
5372 nor any partial-height lines at the bottom of the text area. */)
5373 (Lisp_Object window)
5374 {
5375 struct window *w = decode_live_window (window);
5376 int pixel_height = window_box_height (w);
5377 int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
5378 return make_number (line_height);
5379 }
5380
5381
5382 \f
5383 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
5384 1, 1, "P",
5385 doc: /* Position point relative to window.
5386 ARG nil means position point at center of window.
5387 Else, ARG specifies vertical position within the window;
5388 zero means top of window, negative means relative to bottom of window. */)
5389 (Lisp_Object arg)
5390 {
5391 struct window *w = XWINDOW (selected_window);
5392 int lines, start;
5393 Lisp_Object window;
5394 #if 0
5395 int this_scroll_margin;
5396 #endif
5397
5398 if (!(BUFFERP (w->buffer)
5399 && XBUFFER (w->buffer) == current_buffer))
5400 /* This test is needed to make sure PT/PT_BYTE make sense in w->buffer
5401 when passed below to set_marker_both. */
5402 error ("move-to-window-line called from unrelated buffer");
5403
5404 window = selected_window;
5405 start = marker_position (w->start);
5406 if (start < BEGV || start > ZV)
5407 {
5408 int height = window_internal_height (w);
5409 Fvertical_motion (make_number (- (height / 2)), window);
5410 set_marker_both (w->start, w->buffer, PT, PT_BYTE);
5411 w->start_at_line_beg = !NILP (Fbolp ());
5412 w->force_start = 1;
5413 }
5414 else
5415 Fgoto_char (w->start);
5416
5417 lines = displayed_window_lines (w);
5418
5419 #if 0
5420 this_scroll_margin = max (0, min (scroll_margin, lines / 4));
5421 #endif
5422
5423 if (NILP (arg))
5424 XSETFASTINT (arg, lines / 2);
5425 else
5426 {
5427 EMACS_INT iarg = XINT (Fprefix_numeric_value (arg));
5428
5429 if (iarg < 0)
5430 iarg = iarg + lines;
5431
5432 #if 0 /* This code would prevent move-to-window-line from moving point
5433 to a place inside the scroll margins (which would cause the
5434 next redisplay to scroll). I wrote this code, but then concluded
5435 it is probably better not to install it. However, it is here
5436 inside #if 0 so as not to lose it. -- rms. */
5437
5438 /* Don't let it get into the margin at either top or bottom. */
5439 iarg = max (iarg, this_scroll_margin);
5440 iarg = min (iarg, lines - this_scroll_margin - 1);
5441 #endif
5442
5443 arg = make_number (iarg);
5444 }
5445
5446 /* Skip past a partially visible first line. */
5447 if (w->vscroll)
5448 XSETINT (arg, XINT (arg) + 1);
5449
5450 return Fvertical_motion (arg, window);
5451 }
5452
5453
5454 \f
5455 /***********************************************************************
5456 Window Configuration
5457 ***********************************************************************/
5458
5459 struct save_window_data
5460 {
5461 struct vectorlike_header header;
5462 Lisp_Object selected_frame;
5463 Lisp_Object current_window;
5464 Lisp_Object current_buffer;
5465 Lisp_Object minibuf_scroll_window;
5466 Lisp_Object minibuf_selected_window;
5467 Lisp_Object root_window;
5468 Lisp_Object focus_frame;
5469 /* A vector, each of whose elements is a struct saved_window
5470 for one window. */
5471 Lisp_Object saved_windows;
5472
5473 /* All fields above are traced by the GC.
5474 From `fame-cols' down, the fields are ignored by the GC. */
5475
5476 int frame_cols, frame_lines, frame_menu_bar_lines;
5477 int frame_tool_bar_lines;
5478 };
5479
5480 /* This is saved as a Lisp_Vector */
5481 struct saved_window
5482 {
5483 struct vectorlike_header header;
5484
5485 Lisp_Object window, buffer, start, pointm, mark;
5486 Lisp_Object left_col, top_line, total_cols, total_lines;
5487 Lisp_Object normal_cols, normal_lines;
5488 Lisp_Object hscroll, min_hscroll;
5489 Lisp_Object parent, prev;
5490 Lisp_Object start_at_line_beg;
5491 Lisp_Object display_table;
5492 Lisp_Object left_margin_cols, right_margin_cols;
5493 Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
5494 Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
5495 Lisp_Object combination_limit, window_parameters;
5496 };
5497
5498 #define SAVED_WINDOW_N(swv,n) \
5499 ((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
5500
5501 DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
5502 doc: /* Return t if OBJECT is a window-configuration object. */)
5503 (Lisp_Object object)
5504 {
5505 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
5506 }
5507
5508 DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
5509 doc: /* Return the frame that CONFIG, a window-configuration object, is about. */)
5510 (Lisp_Object config)
5511 {
5512 register struct save_window_data *data;
5513 struct Lisp_Vector *saved_windows;
5514
5515 CHECK_WINDOW_CONFIGURATION (config);
5516
5517 data = (struct save_window_data *) XVECTOR (config);
5518 saved_windows = XVECTOR (data->saved_windows);
5519 return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5520 }
5521
5522 DEFUN ("set-window-configuration", Fset_window_configuration,
5523 Sset_window_configuration, 1, 1, 0,
5524 doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
5525 CONFIGURATION must be a value previously returned
5526 by `current-window-configuration' (which see).
5527 If CONFIGURATION was made from a frame that is now deleted,
5528 only frame-independent values can be restored. In this case,
5529 the return value is nil. Otherwise the value is t. */)
5530 (Lisp_Object configuration)
5531 {
5532 register struct save_window_data *data;
5533 struct Lisp_Vector *saved_windows;
5534 Lisp_Object new_current_buffer;
5535 Lisp_Object frame;
5536 FRAME_PTR f;
5537 ptrdiff_t old_point = -1;
5538
5539 CHECK_WINDOW_CONFIGURATION (configuration);
5540
5541 data = (struct save_window_data *) XVECTOR (configuration);
5542 saved_windows = XVECTOR (data->saved_windows);
5543
5544 new_current_buffer = data->current_buffer;
5545 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer)))
5546 new_current_buffer = Qnil;
5547 else
5548 {
5549 if (XBUFFER (new_current_buffer) == current_buffer)
5550 /* The code further down "preserves point" by saving here PT in
5551 old_point and then setting it later back into PT. When the
5552 current-selected-window and the final-selected-window both show
5553 the current buffer, this suffers from the problem that the
5554 current PT is the window-point of the current-selected-window,
5555 while the final PT is the point of the final-selected-window, so
5556 this copy from one PT to the other would end up moving the
5557 window-point of the final-selected-window to the window-point of
5558 the current-selected-window. So we have to be careful which
5559 point of the current-buffer we copy into old_point. */
5560 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5561 && WINDOWP (selected_window)
5562 && EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
5563 && !EQ (selected_window, data->current_window))
5564 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5565 else
5566 old_point = PT;
5567 else
5568 /* BUF_PT (XBUFFER (new_current_buffer)) gives us the position of
5569 point in new_current_buffer as of the last time this buffer was
5570 used. This can be non-deterministic since it can be changed by
5571 things like jit-lock by mere temporary selection of some random
5572 window that happens to show this buffer.
5573 So if possible we want this arbitrary choice of "which point" to
5574 be the one from the to-be-selected-window so as to prevent this
5575 window's cursor from being copied from another window. */
5576 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
5577 /* If current_window = selected_window, its point is in BUF_PT. */
5578 && !EQ (selected_window, data->current_window))
5579 old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
5580 else
5581 old_point = BUF_PT (XBUFFER (new_current_buffer));
5582 }
5583
5584 frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
5585 f = XFRAME (frame);
5586
5587 /* If f is a dead frame, don't bother rebuilding its window tree.
5588 However, there is other stuff we should still try to do below. */
5589 if (FRAME_LIVE_P (f))
5590 {
5591 Lisp_Object window;
5592 Lisp_Object dead_windows = Qnil;
5593 register Lisp_Object tem, par, pers;
5594 register struct window *w;
5595 register struct saved_window *p;
5596 struct window *root_window;
5597 struct window **leaf_windows;
5598 int n_leaf_windows;
5599 ptrdiff_t k;
5600 int i, n;
5601
5602 /* If the frame has been resized since this window configuration was
5603 made, we change the frame to the size specified in the
5604 configuration, restore the configuration, and then resize it
5605 back. We keep track of the prevailing height in these variables. */
5606 int previous_frame_lines = FRAME_LINES (f);
5607 int previous_frame_cols = FRAME_COLS (f);
5608 int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
5609 int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
5610
5611 /* Don't do this within the main loop below: This may call Lisp
5612 code and is thus potentially unsafe while input is blocked. */
5613 for (k = 0; k < saved_windows->header.size; k++)
5614 {
5615 p = SAVED_WINDOW_N (saved_windows, k);
5616 window = p->window;
5617 w = XWINDOW (window);
5618 if (!NILP (w->buffer)
5619 && !EQ (w->buffer, p->buffer)
5620 && BUFFER_LIVE_P (XBUFFER (p->buffer)))
5621 /* If a window we restore gets another buffer, record the
5622 window's old buffer. */
5623 call1 (Qrecord_window_buffer, window);
5624 }
5625
5626 /* The mouse highlighting code could get screwed up
5627 if it runs during this. */
5628 BLOCK_INPUT;
5629
5630 if (data->frame_lines != previous_frame_lines
5631 || data->frame_cols != previous_frame_cols)
5632 change_frame_size (f, data->frame_lines,
5633 data->frame_cols, 0, 0, 0);
5634 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5635 if (data->frame_menu_bar_lines
5636 != previous_frame_menu_bar_lines)
5637 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
5638 make_number (0));
5639 #ifdef HAVE_WINDOW_SYSTEM
5640 if (data->frame_tool_bar_lines
5641 != previous_frame_tool_bar_lines)
5642 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
5643 make_number (0));
5644 #endif
5645 #endif
5646
5647 /* "Swap out" point from the selected window's buffer
5648 into the window itself. (Normally the pointm of the selected
5649 window holds garbage.) We do this now, before
5650 restoring the window contents, and prevent it from
5651 being done later on when we select a new window. */
5652 if (! NILP (XWINDOW (selected_window)->buffer))
5653 {
5654 w = XWINDOW (selected_window);
5655 set_marker_both (w->pointm,
5656 w->buffer,
5657 BUF_PT (XBUFFER (w->buffer)),
5658 BUF_PT_BYTE (XBUFFER (w->buffer)));
5659 }
5660
5661 windows_or_buffers_changed++;
5662 FRAME_WINDOW_SIZES_CHANGED (f) = 1;
5663
5664 /* Problem: Freeing all matrices and later allocating them again
5665 is a serious redisplay flickering problem. What we would
5666 really like to do is to free only those matrices not reused
5667 below. */
5668 root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
5669 leaf_windows = alloca (count_windows (root_window)
5670 * sizeof *leaf_windows);
5671 n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
5672
5673 /* Kludge Alert!
5674 Mark all windows now on frame as "deleted".
5675 Restoring the new configuration "undeletes" any that are in it.
5676
5677 Save their current buffers in their height fields, since we may
5678 need it later, if a buffer saved in the configuration is now
5679 dead. */
5680 delete_all_child_windows (FRAME_ROOT_WINDOW (f));
5681
5682 for (k = 0; k < saved_windows->header.size; k++)
5683 {
5684 p = SAVED_WINDOW_N (saved_windows, k);
5685 window = p->window;
5686 w = XWINDOW (window);
5687 wset_next (w, Qnil);
5688
5689 if (!NILP (p->parent))
5690 wset_parent
5691 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->parent))->window);
5692 else
5693 wset_parent (w, Qnil);
5694
5695 if (!NILP (p->prev))
5696 {
5697 wset_prev
5698 (w, SAVED_WINDOW_N (saved_windows, XFASTINT (p->prev))->window);
5699 wset_next (XWINDOW (w->prev), p->window);
5700 }
5701 else
5702 {
5703 wset_prev (w, Qnil);
5704 if (!NILP (w->parent))
5705 {
5706 if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
5707 {
5708 wset_vchild (XWINDOW (w->parent), p->window);
5709 wset_hchild (XWINDOW (w->parent), Qnil);
5710 }
5711 else
5712 {
5713 wset_hchild (XWINDOW (w->parent), p->window);
5714 wset_vchild (XWINDOW (w->parent), Qnil);
5715 }
5716 }
5717 }
5718
5719 /* If we squirreled away the buffer in the window's height,
5720 restore it now. */
5721 if (BUFFERP (w->total_lines))
5722 wset_buffer (w, w->total_lines);
5723 wset_left_col (w, p->left_col);
5724 wset_top_line (w, p->top_line);
5725 wset_total_cols (w, p->total_cols);
5726 wset_total_lines (w, p->total_lines);
5727 wset_normal_cols (w, p->normal_cols);
5728 wset_normal_lines (w, p->normal_lines);
5729 w->hscroll = XFASTINT (p->hscroll);
5730 w->min_hscroll = XFASTINT (p->min_hscroll);
5731 wset_display_table (w, p->display_table);
5732 wset_left_margin_cols (w, p->left_margin_cols);
5733 wset_right_margin_cols (w, p->right_margin_cols);
5734 wset_left_fringe_width (w, p->left_fringe_width);
5735 wset_right_fringe_width (w, p->right_fringe_width);
5736 w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
5737 wset_scroll_bar_width (w, p->scroll_bar_width);
5738 wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
5739 wset_dedicated (w, p->dedicated);
5740 wset_combination_limit (w, p->combination_limit);
5741 /* Restore any window parameters that have been saved.
5742 Parameters that have not been saved are left alone. */
5743 for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
5744 {
5745 pers = XCAR (tem);
5746 if (CONSP (pers))
5747 {
5748 if (NILP (XCDR (pers)))
5749 {
5750 par = Fassq (XCAR (pers), w->window_parameters);
5751 if (CONSP (par) && !NILP (XCDR (par)))
5752 /* Reset a parameter to nil if and only if it
5753 has a non-nil association. Don't make new
5754 associations. */
5755 Fsetcdr (par, Qnil);
5756 }
5757 else
5758 /* Always restore a non-nil value. */
5759 Fset_window_parameter (window, XCAR (pers), XCDR (pers));
5760 }
5761 }
5762
5763 w->last_modified = 0;
5764 w->last_overlay_modified = 0;
5765
5766 /* Reinstall the saved buffer and pointers into it. */
5767 if (NILP (p->buffer))
5768 /* An internal window. */
5769 wset_buffer (w, p->buffer);
5770 else if (BUFFER_LIVE_P (XBUFFER (p->buffer)))
5771 /* If saved buffer is alive, install it. */
5772 {
5773 wset_buffer (w, p->buffer);
5774 w->start_at_line_beg = !NILP (p->start_at_line_beg);
5775 set_marker_restricted (w->start, p->start, w->buffer);
5776 set_marker_restricted (w->pointm, p->pointm,
5777 w->buffer);
5778 Fset_marker (BVAR (XBUFFER (w->buffer), mark),
5779 p->mark, w->buffer);
5780
5781 /* As documented in Fcurrent_window_configuration, don't
5782 restore the location of point in the buffer which was
5783 current when the window configuration was recorded. */
5784 if (!EQ (p->buffer, new_current_buffer)
5785 && XBUFFER (p->buffer) == current_buffer)
5786 Fgoto_char (w->pointm);
5787 }
5788 else if (!NILP (w->buffer)
5789 && BUFFER_LIVE_P (XBUFFER (w->buffer)))
5790 /* Keep window's old buffer; make sure the markers are
5791 real. */
5792 {
5793 /* Set window markers at start of visible range. */
5794 if (XMARKER (w->start)->buffer == 0)
5795 set_marker_restricted (w->start, make_number (0),
5796 w->buffer);
5797 if (XMARKER (w->pointm)->buffer == 0)
5798 set_marker_restricted_both
5799 (w->pointm, w->buffer,
5800 BUF_PT (XBUFFER (w->buffer)),
5801 BUF_PT_BYTE (XBUFFER (w->buffer)));
5802 w->start_at_line_beg = 1;
5803 }
5804 else
5805 /* Window has no live buffer, get one. */
5806 {
5807 /* Get the buffer via other_buffer_safely in order to
5808 avoid showing an unimportant buffer and, if necessary, to
5809 recreate *scratch* in the course (part of Juanma's bs-show
5810 scenario from March 2011). */
5811 wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
5812 /* This will set the markers to beginning of visible
5813 range. */
5814 set_marker_restricted (w->start,
5815 make_number (0), w->buffer);
5816 set_marker_restricted (w->pointm,
5817 make_number (0), w->buffer);
5818 w->start_at_line_beg = 1;
5819 if (!NILP (w->dedicated))
5820 /* Record this window as dead. */
5821 dead_windows = Fcons (window, dead_windows);
5822 /* Make sure window is no more dedicated. */
5823 wset_dedicated (w, Qnil);
5824 }
5825 }
5826
5827 fset_root_window (f, data->root_window);
5828 /* Arrange *not* to restore point in the buffer that was
5829 current when the window configuration was saved. */
5830 if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5831 set_marker_restricted (XWINDOW (data->current_window)->pointm,
5832 make_number (old_point),
5833 XWINDOW (data->current_window)->buffer);
5834
5835 /* In the following call to `select-window', prevent "swapping out
5836 point" in the old selected window using the buffer that has
5837 been restored into it. We already swapped out that point from
5838 that window's old buffer. */
5839 select_window (data->current_window, Qnil, 1);
5840 BVAR (XBUFFER (XWINDOW (selected_window)->buffer), last_selected_window)
5841 = selected_window;
5842
5843 if (NILP (data->focus_frame)
5844 || (FRAMEP (data->focus_frame)
5845 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
5846 Fredirect_frame_focus (frame, data->focus_frame);
5847
5848 /* Set the screen height to the value it had before this function. */
5849 if (previous_frame_lines != FRAME_LINES (f)
5850 || previous_frame_cols != FRAME_COLS (f))
5851 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5852 0, 0, 0);
5853 #if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
5854 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5855 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5856 make_number (0));
5857 #ifdef HAVE_WINDOW_SYSTEM
5858 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5859 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5860 make_number (0));
5861 #endif
5862 #endif
5863
5864 /* Now, free glyph matrices in windows that were not reused. */
5865 for (i = n = 0; i < n_leaf_windows; ++i)
5866 {
5867 if (NILP (leaf_windows[i]->buffer))
5868 {
5869 /* Assert it's not reused as a combination. */
5870 eassert (NILP (leaf_windows[i]->hchild)
5871 && NILP (leaf_windows[i]->vchild));
5872 free_window_matrices (leaf_windows[i]);
5873 }
5874 else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
5875 ++n;
5876 }
5877
5878 adjust_glyphs (f);
5879 UNBLOCK_INPUT;
5880
5881 /* Scan dead buffer windows. */
5882 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
5883 {
5884 window = XCAR (dead_windows);
5885 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
5886 delete_deletable_window (window);
5887 }
5888
5889 /* Fselect_window will have made f the selected frame, so we
5890 reselect the proper frame here. Fhandle_switch_frame will change the
5891 selected window too, but that doesn't make the call to
5892 Fselect_window above totally superfluous; it still sets f's
5893 selected window. */
5894 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
5895 do_switch_frame (data->selected_frame, 0, 0, Qnil);
5896
5897 run_window_configuration_change_hook (f);
5898 }
5899
5900 if (!NILP (new_current_buffer))
5901 {
5902 Fset_buffer (new_current_buffer);
5903 /* If the new current buffer doesn't appear in the selected
5904 window, go to its old point (see bug#12208). */
5905 if (!EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
5906 Fgoto_char (make_number (old_point));
5907 }
5908
5909 Vminibuf_scroll_window = data->minibuf_scroll_window;
5910 minibuf_selected_window = data->minibuf_selected_window;
5911
5912 return (FRAME_LIVE_P (f) ? Qt : Qnil);
5913 }
5914
5915
5916 /* Recursively delete all child windows reachable via the next, vchild,
5917 and hchild slots of WINDOW. */
5918 void
5919 delete_all_child_windows (Lisp_Object window)
5920 {
5921 register struct window *w;
5922
5923 w = XWINDOW (window);
5924
5925 if (!NILP (w->next))
5926 /* Delete WINDOW's siblings (we traverse postorderly). */
5927 delete_all_child_windows (w->next);
5928
5929 /* See Fset_window_configuration for excuse. */
5930 wset_total_lines (w, w->buffer);
5931
5932 if (!NILP (w->vchild))
5933 {
5934 delete_all_child_windows (w->vchild);
5935 wset_vchild (w, Qnil);
5936 }
5937 else if (!NILP (w->hchild))
5938 {
5939 delete_all_child_windows (w->hchild);
5940 wset_hchild (w, Qnil);
5941 }
5942 else if (!NILP (w->buffer))
5943 {
5944 unshow_buffer (w);
5945 unchain_marker (XMARKER (w->pointm));
5946 unchain_marker (XMARKER (w->start));
5947 wset_buffer (w, Qnil);
5948 }
5949
5950 Vwindow_list = Qnil;
5951 }
5952 \f
5953 static int
5954 count_windows (register struct window *window)
5955 {
5956 register int count = 1;
5957 if (!NILP (window->next))
5958 count += count_windows (XWINDOW (window->next));
5959 if (!NILP (window->vchild))
5960 count += count_windows (XWINDOW (window->vchild));
5961 if (!NILP (window->hchild))
5962 count += count_windows (XWINDOW (window->hchild));
5963 return count;
5964 }
5965
5966
5967 /* Fill vector FLAT with leaf windows under W, starting at index I.
5968 Value is last index + 1. */
5969 static int
5970 get_leaf_windows (struct window *w, struct window **flat, int i)
5971 {
5972 while (w)
5973 {
5974 if (!NILP (w->hchild))
5975 i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
5976 else if (!NILP (w->vchild))
5977 i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
5978 else
5979 flat[i++] = w;
5980
5981 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5982 }
5983
5984 return i;
5985 }
5986
5987
5988 /* Return a pointer to the glyph W's physical cursor is on. Value is
5989 null if W's current matrix is invalid, so that no meaningful glyph
5990 can be returned. */
5991 struct glyph *
5992 get_phys_cursor_glyph (struct window *w)
5993 {
5994 struct glyph_row *row;
5995 struct glyph *glyph;
5996 int hpos = w->phys_cursor.hpos;
5997
5998 if (!(w->phys_cursor.vpos >= 0
5999 && w->phys_cursor.vpos < w->current_matrix->nrows))
6000 return NULL;
6001
6002 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
6003 if (!row->enabled_p)
6004 return NULL;
6005
6006 if (w->hscroll)
6007 {
6008 /* When the window is hscrolled, cursor hpos can legitimately be
6009 out of bounds, but we draw the cursor at the corresponding
6010 window margin in that case. */
6011 if (!row->reversed_p && hpos < 0)
6012 hpos = 0;
6013 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
6014 hpos = row->used[TEXT_AREA] - 1;
6015 }
6016
6017 if (row->used[TEXT_AREA] > hpos
6018 && 0 <= hpos)
6019 glyph = row->glyphs[TEXT_AREA] + hpos;
6020 else
6021 glyph = NULL;
6022
6023 return glyph;
6024 }
6025
6026
6027 static int
6028 save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
6029 {
6030 register struct saved_window *p;
6031 register struct window *w;
6032 register Lisp_Object tem, pers, par;
6033
6034 for (;!NILP (window); window = w->next)
6035 {
6036 p = SAVED_WINDOW_N (vector, i);
6037 w = XWINDOW (window);
6038
6039 wset_temslot (w, make_number (i)); i++;
6040 p->window = window;
6041 p->buffer = w->buffer;
6042 p->left_col = w->left_col;
6043 p->top_line = w->top_line;
6044 p->total_cols = w->total_cols;
6045 p->total_lines = w->total_lines;
6046 p->normal_cols = w->normal_cols;
6047 p->normal_lines = w->normal_lines;
6048 XSETFASTINT (p->hscroll, w->hscroll);
6049 XSETFASTINT (p->min_hscroll, w->min_hscroll);
6050 p->display_table = w->display_table;
6051 p->left_margin_cols = w->left_margin_cols;
6052 p->right_margin_cols = w->right_margin_cols;
6053 p->left_fringe_width = w->left_fringe_width;
6054 p->right_fringe_width = w->right_fringe_width;
6055 p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
6056 p->scroll_bar_width = w->scroll_bar_width;
6057 p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
6058 p->dedicated = w->dedicated;
6059 p->combination_limit = w->combination_limit;
6060 p->window_parameters = Qnil;
6061
6062 if (!NILP (Vwindow_persistent_parameters))
6063 {
6064 /* Run cycle detection on Vwindow_persistent_parameters. */
6065 Lisp_Object tortoise, hare;
6066
6067 hare = tortoise = Vwindow_persistent_parameters;
6068 while (CONSP (hare))
6069 {
6070 hare = XCDR (hare);
6071 if (!CONSP (hare))
6072 break;
6073
6074 hare = XCDR (hare);
6075 tortoise = XCDR (tortoise);
6076
6077 if (EQ (hare, tortoise))
6078 /* Reset Vwindow_persistent_parameters to Qnil. */
6079 {
6080 Vwindow_persistent_parameters = Qnil;
6081 break;
6082 }
6083 }
6084
6085 for (tem = Vwindow_persistent_parameters; CONSP (tem);
6086 tem = XCDR (tem))
6087 {
6088 pers = XCAR (tem);
6089 /* Save values for persistent window parameters. */
6090 if (CONSP (pers) && !NILP (XCDR (pers)))
6091 {
6092 par = Fassq (XCAR (pers), w->window_parameters);
6093 if (NILP (par))
6094 /* If the window has no value for the parameter,
6095 make one. */
6096 p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
6097 p->window_parameters);
6098 else
6099 /* If the window has a value for the parameter,
6100 save it. */
6101 p->window_parameters = Fcons (Fcons (XCAR (par),
6102 XCDR (par)),
6103 p->window_parameters);
6104 }
6105 }
6106 }
6107
6108 if (!NILP (w->buffer))
6109 {
6110 /* Save w's value of point in the window configuration. If w
6111 is the selected window, then get the value of point from
6112 the buffer; pointm is garbage in the selected window. */
6113 if (EQ (window, selected_window))
6114 p->pointm = build_marker (XBUFFER (w->buffer),
6115 BUF_PT (XBUFFER (w->buffer)),
6116 BUF_PT_BYTE (XBUFFER (w->buffer)));
6117 else
6118 p->pointm = Fcopy_marker (w->pointm, Qnil);
6119 XMARKER (p->pointm)->insertion_type
6120 = !NILP (Vwindow_point_insertion_type);
6121
6122 p->start = Fcopy_marker (w->start, Qnil);
6123 p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
6124
6125 tem = BVAR (XBUFFER (w->buffer), mark);
6126 p->mark = Fcopy_marker (tem, Qnil);
6127 }
6128 else
6129 {
6130 p->pointm = Qnil;
6131 p->start = Qnil;
6132 p->mark = Qnil;
6133 p->start_at_line_beg = Qnil;
6134 }
6135
6136 if (NILP (w->parent))
6137 p->parent = Qnil;
6138 else
6139 p->parent = XWINDOW (w->parent)->temslot;
6140
6141 if (NILP (w->prev))
6142 p->prev = Qnil;
6143 else
6144 p->prev = XWINDOW (w->prev)->temslot;
6145
6146 if (!NILP (w->vchild))
6147 i = save_window_save (w->vchild, vector, i);
6148 if (!NILP (w->hchild))
6149 i = save_window_save (w->hchild, vector, i);
6150 }
6151
6152 return i;
6153 }
6154
6155 DEFUN ("current-window-configuration", Fcurrent_window_configuration,
6156 Scurrent_window_configuration, 0, 1, 0,
6157 doc: /* Return an object representing the current window configuration of FRAME.
6158 If FRAME is nil or omitted, use the selected frame.
6159 This describes the number of windows, their sizes and current buffers,
6160 and for each displayed buffer, where display starts, and the positions of
6161 point and mark. An exception is made for point in the current buffer:
6162 its value is -not- saved.
6163 This also records the currently selected frame, and FRAME's focus
6164 redirection (see `redirect-frame-focus'). The variable
6165 `window-persistent-parameters' specifies which window parameters are
6166 saved by this function. */)
6167 (Lisp_Object frame)
6168 {
6169 register Lisp_Object tem;
6170 register int n_windows;
6171 register struct save_window_data *data;
6172 register int i;
6173 FRAME_PTR f;
6174
6175 if (NILP (frame))
6176 frame = selected_frame;
6177 CHECK_LIVE_FRAME (frame);
6178 f = XFRAME (frame);
6179
6180 n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
6181 data = ALLOCATE_PSEUDOVECTOR (struct save_window_data, frame_cols,
6182 PVEC_WINDOW_CONFIGURATION);
6183
6184 data->frame_cols = FRAME_COLS (f);
6185 data->frame_lines = FRAME_LINES (f);
6186 data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
6187 data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
6188 data->selected_frame = selected_frame;
6189 data->current_window = FRAME_SELECTED_WINDOW (f);
6190 XSETBUFFER (data->current_buffer, current_buffer);
6191 data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
6192 data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
6193 data->root_window = FRAME_ROOT_WINDOW (f);
6194 data->focus_frame = FRAME_FOCUS_FRAME (f);
6195 tem = Fmake_vector (make_number (n_windows), Qnil);
6196 data->saved_windows = tem;
6197 for (i = 0; i < n_windows; i++)
6198 ASET (tem, i,
6199 Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil));
6200 save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
6201 XSETWINDOW_CONFIGURATION (tem, data);
6202 return (tem);
6203 }
6204 \f
6205 /***********************************************************************
6206 Marginal Areas
6207 ***********************************************************************/
6208
6209 DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
6210 2, 3, 0,
6211 doc: /* Set width of marginal areas of window WINDOW.
6212 WINDOW must be a live window and defaults to the selected one.
6213
6214 Second arg LEFT-WIDTH specifies the number of character cells to
6215 reserve for the left marginal area. Optional third arg RIGHT-WIDTH
6216 does the same for the right marginal area. A nil width parameter
6217 means no margin. */)
6218 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width)
6219 {
6220 struct window *w = decode_live_window (window);
6221
6222 /* Translate negative or zero widths to nil.
6223 Margins that are too wide have to be checked elsewhere. */
6224
6225 if (!NILP (left_width))
6226 {
6227 CHECK_NUMBER (left_width);
6228 if (XINT (left_width) <= 0)
6229 left_width = Qnil;
6230 }
6231
6232 if (!NILP (right_width))
6233 {
6234 CHECK_NUMBER (right_width);
6235 if (XINT (right_width) <= 0)
6236 right_width = Qnil;
6237 }
6238
6239 if (!EQ (w->left_margin_cols, left_width)
6240 || !EQ (w->right_margin_cols, right_width))
6241 {
6242 wset_left_margin_cols (w, left_width);
6243 wset_right_margin_cols (w, right_width);
6244
6245 adjust_window_margins (w);
6246
6247 ++windows_or_buffers_changed;
6248 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6249 }
6250
6251 return Qnil;
6252 }
6253
6254
6255 DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
6256 0, 1, 0,
6257 doc: /* Get width of marginal areas of window WINDOW.
6258 WINDOW must be a live window and defaults to the selected one.
6259
6260 Value is a cons of the form (LEFT-WIDTH . RIGHT-WIDTH).
6261 If a marginal area does not exist, its width will be returned
6262 as nil. */)
6263 (Lisp_Object window)
6264 {
6265 struct window *w = decode_live_window (window);
6266 return Fcons (w->left_margin_cols, w->right_margin_cols);
6267 }
6268
6269
6270 \f
6271 /***********************************************************************
6272 Fringes
6273 ***********************************************************************/
6274
6275 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
6276 2, 4, 0,
6277 doc: /* Set the fringe widths of window WINDOW.
6278 WINDOW must be a live window and defaults to the selected one.
6279
6280 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
6281 the left fringe. Optional third arg RIGHT-WIDTH specifies the right
6282 fringe width. If a fringe width arg is nil, that means to use the
6283 frame's default fringe width. Default fringe widths can be set with
6284 the command `set-fringe-style'.
6285 If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
6286 outside of the display margins. By default, fringes are drawn between
6287 display marginal areas and the text area. */)
6288 (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width, Lisp_Object outside_margins)
6289 {
6290 struct window *w = decode_live_window (window);
6291 int outside = !NILP (outside_margins);
6292
6293 if (!NILP (left_width))
6294 CHECK_NATNUM (left_width);
6295 if (!NILP (right_width))
6296 CHECK_NATNUM (right_width);
6297
6298 /* Do nothing on a tty. */
6299 if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
6300 && (!EQ (w->left_fringe_width, left_width)
6301 || !EQ (w->right_fringe_width, right_width)
6302 || w->fringes_outside_margins != outside))
6303 {
6304 wset_left_fringe_width (w, left_width);
6305 wset_right_fringe_width (w, right_width);
6306 w->fringes_outside_margins = outside;
6307
6308 adjust_window_margins (w);
6309
6310 clear_glyph_matrix (w->current_matrix);
6311 wset_window_end_valid (w, Qnil);
6312
6313 ++windows_or_buffers_changed;
6314 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6315 }
6316
6317 return Qnil;
6318 }
6319
6320
6321 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
6322 0, 1, 0,
6323 doc: /* Get width of fringes of window WINDOW.
6324 WINDOW must be a live window and defaults to the selected one.
6325
6326 Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS). */)
6327 (Lisp_Object window)
6328 {
6329 struct window *w = decode_live_window (window);
6330
6331 return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
6332 Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
6333 Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
6334 ? Qt : Qnil), Qnil)));
6335 }
6336
6337
6338 \f
6339 /***********************************************************************
6340 Scroll bars
6341 ***********************************************************************/
6342
6343 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
6344 Sset_window_scroll_bars, 2, 4, 0,
6345 doc: /* Set width and type of scroll bars of window WINDOW.
6346 WINDOW must be a live window and defaults to the selected one.
6347
6348 Second parameter WIDTH specifies the pixel width for the scroll bar;
6349 this is automatically adjusted to a multiple of the frame column width.
6350 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
6351 bar: left, right, or nil.
6352 If WIDTH is nil, use the frame's scroll-bar width.
6353 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
6354 Fourth parameter HORIZONTAL-TYPE is currently unused. */)
6355 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, Lisp_Object horizontal_type)
6356 {
6357 struct window *w = decode_live_window (window);
6358
6359 if (!NILP (width))
6360 {
6361 CHECK_RANGED_INTEGER (width, 0, INT_MAX);
6362
6363 if (XINT (width) == 0)
6364 vertical_type = Qnil;
6365 }
6366
6367 if (!(NILP (vertical_type)
6368 || EQ (vertical_type, Qleft)
6369 || EQ (vertical_type, Qright)
6370 || EQ (vertical_type, Qt)))
6371 error ("Invalid type of vertical scroll bar");
6372
6373 if (!EQ (w->scroll_bar_width, width)
6374 || !EQ (w->vertical_scroll_bar_type, vertical_type))
6375 {
6376 wset_scroll_bar_width (w, width);
6377 wset_vertical_scroll_bar_type (w, vertical_type);
6378
6379 adjust_window_margins (w);
6380
6381 clear_glyph_matrix (w->current_matrix);
6382 wset_window_end_valid (w, Qnil);
6383
6384 ++windows_or_buffers_changed;
6385 adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
6386 }
6387
6388 return Qnil;
6389 }
6390
6391
6392 DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
6393 0, 1, 0,
6394 doc: /* Get width and type of scroll bars of window WINDOW.
6395 WINDOW must be a live window and defaults to the selected one.
6396
6397 Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
6398 If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
6399 value. */)
6400 (Lisp_Object window)
6401 {
6402 struct window *w = decode_live_window (window);
6403 return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6404 ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
6405 : WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
6406 Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
6407 Fcons (w->vertical_scroll_bar_type,
6408 Fcons (Qnil, Qnil))));
6409 }
6410
6411
6412 \f
6413 /***********************************************************************
6414 Smooth scrolling
6415 ***********************************************************************/
6416
6417 DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
6418 doc: /* Return the amount by which WINDOW is scrolled vertically.
6419 If WINDOW is omitted or nil, it defaults to the selected window.
6420 Normally, value is a multiple of the canonical character height of WINDOW;
6421 optional second arg PIXELS-P means value is measured in pixels. */)
6422 (Lisp_Object window, Lisp_Object pixels_p)
6423 {
6424 Lisp_Object result;
6425 struct frame *f;
6426 struct window *w;
6427
6428 if (NILP (window))
6429 window = selected_window;
6430 else
6431 CHECK_WINDOW (window);
6432 w = XWINDOW (window);
6433 f = XFRAME (w->frame);
6434
6435 if (FRAME_WINDOW_P (f))
6436 result = (NILP (pixels_p)
6437 ? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
6438 : make_number (-w->vscroll));
6439 else
6440 result = make_number (0);
6441 return result;
6442 }
6443
6444
6445 DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
6446 2, 3, 0,
6447 doc: /* Set amount by which WINDOW should be scrolled vertically to VSCROLL.
6448 WINDOW nil means use the selected window. Normally, VSCROLL is a
6449 non-negative multiple of the canonical character height of WINDOW;
6450 optional third arg PIXELS-P non-nil means that VSCROLL is in pixels.
6451 If PIXELS-P is nil, VSCROLL may have to be rounded so that it
6452 corresponds to an integral number of pixels. The return value is the
6453 result of this rounding.
6454 If PIXELS-P is non-nil, the return value is VSCROLL. */)
6455 (Lisp_Object window, Lisp_Object vscroll, Lisp_Object pixels_p)
6456 {
6457 struct window *w;
6458 struct frame *f;
6459
6460 if (NILP (window))
6461 window = selected_window;
6462 else
6463 CHECK_WINDOW (window);
6464 CHECK_NUMBER_OR_FLOAT (vscroll);
6465
6466 w = XWINDOW (window);
6467 f = XFRAME (w->frame);
6468
6469 if (FRAME_WINDOW_P (f))
6470 {
6471 int old_dy = w->vscroll;
6472
6473 w->vscroll = - (NILP (pixels_p)
6474 ? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
6475 : XFLOATINT (vscroll));
6476 w->vscroll = min (w->vscroll, 0);
6477
6478 if (w->vscroll != old_dy)
6479 {
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);
6484
6485 /* Prevent redisplay shortcuts. */
6486 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
6487 }
6488 }
6489
6490 return Fwindow_vscroll (window, pixels_p);
6491 }
6492
6493 \f
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. */
6497
6498 static void
6499 foreach_window (struct frame *f, int (*fn) (struct window *, void *),
6500 void *user_data)
6501 {
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);
6505 }
6506
6507
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. */
6512
6513 static int
6514 foreach_window_1 (struct window *w, int (*fn) (struct window *, void *), void *user_data)
6515 {
6516 int cont;
6517
6518 for (cont = 1; w && cont;)
6519 {
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);
6526
6527 w = NILP (w->next) ? 0 : XWINDOW (w->next);
6528 }
6529
6530 return cont;
6531 }
6532
6533
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. */
6537
6538 static int
6539 freeze_window_start (struct window *w, void *freeze_p)
6540 {
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;
6548
6549 w->frozen_window_start_p = freeze_p != NULL;
6550 return 1;
6551 }
6552
6553
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. */
6557
6558 void
6559 freeze_window_starts (struct frame *f, int freeze_p)
6560 {
6561 foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
6562 }
6563
6564 \f
6565 /***********************************************************************
6566 Initialization
6567 ***********************************************************************/
6568
6569 /* Return 1 if window configurations CONFIGURATION1 and CONFIGURATION2
6570 describe the same state of affairs. This is used by Fequal.
6571
6572 IGNORE_POSITIONS means ignore non-matching scroll positions
6573 and the like.
6574
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. */
6578
6579 bool
6580 compare_window_configurations (Lisp_Object configuration1,
6581 Lisp_Object configuration2,
6582 bool ignore_positions)
6583 {
6584 register struct save_window_data *d1, *d2;
6585 struct Lisp_Vector *sws1, *sws2;
6586 ptrdiff_t i;
6587
6588 CHECK_WINDOW_CONFIGURATION (configuration1);
6589 CHECK_WINDOW_CONFIGURATION (configuration2);
6590
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);
6595
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;
6609
6610 for (i = 0; i < sws1->header.size; i++)
6611 {
6612 struct saved_window *sw1, *sw2;
6613
6614 sw1 = SAVED_WINDOW_N (sws1, i);
6615 sw2 = SAVED_WINDOW_N (sws2, i);
6616
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;
6648 }
6649
6650 return 1;
6651 }
6652
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)
6659 {
6660 if (compare_window_configurations (x, y, 1))
6661 return Qt;
6662 return Qnil;
6663 }
6664 \f
6665 void
6666 init_window_once (void)
6667 {
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;
6674
6675 window_initialized = 1;
6676 }
6677
6678 void
6679 init_window (void)
6680 {
6681 Vwindow_list = Qnil;
6682 }
6683
6684 void
6685 syms_of_window (void)
6686 {
6687 DEFSYM (Qscroll_up, "scroll-up");
6688 DEFSYM (Qscroll_down, "scroll-down");
6689 DEFSYM (Qscroll_command, "scroll-command");
6690
6691 Fput (Qscroll_up, Qscroll_command, Qt);
6692 Fput (Qscroll_down, Qscroll_command, Qt);
6693
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 (Qtemp_buffer_show_hook, "temp-buffer-show-hook");
6709 DEFSYM (Qabove, "above");
6710 DEFSYM (Qbelow, "below");
6711 DEFSYM (Qclone_of, "clone-of");
6712
6713 staticpro (&Vwindow_list);
6714
6715 minibuf_selected_window = Qnil;
6716 staticpro (&minibuf_selected_window);
6717
6718 window_scroll_pixel_based_preserve_x = -1;
6719 window_scroll_pixel_based_preserve_y = -1;
6720 window_scroll_preserve_hpos = -1;
6721 window_scroll_preserve_vpos = -1;
6722
6723 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
6724 doc: /* Non-nil means call as function to display a help buffer.
6725 The function is called with one argument, the buffer to be displayed.
6726 Used by `with-output-to-temp-buffer'.
6727 If this function is used, then it must do the entire job of showing
6728 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. */);
6729 Vtemp_buffer_show_function = Qnil;
6730
6731 DEFVAR_LISP ("minibuffer-scroll-window", Vminibuf_scroll_window,
6732 doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */);
6733 Vminibuf_scroll_window = Qnil;
6734
6735 DEFVAR_BOOL ("mode-line-in-non-selected-windows", mode_line_in_non_selected_windows,
6736 doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
6737 If the minibuffer is active, the `minibuffer-scroll-window' mode line
6738 is displayed in the `mode-line' face. */);
6739 mode_line_in_non_selected_windows = 1;
6740
6741 DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
6742 doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
6743 Vother_window_scroll_buffer = Qnil;
6744
6745 DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
6746 doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
6747 auto_window_vscroll_p = 1;
6748
6749 DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
6750 doc: /* Number of lines of continuity when scrolling by screenfuls. */);
6751 next_screen_context_lines = 2;
6752
6753 DEFVAR_LISP ("scroll-preserve-screen-position",
6754 Vscroll_preserve_screen_position,
6755 doc: /* Controls if scroll commands move point to keep its screen position unchanged.
6756 A value of nil means point does not keep its screen position except
6757 at the scroll margin or window boundary respectively.
6758 A value of t means point keeps its screen position if the scroll
6759 command moved it vertically out of the window, e.g. when scrolling
6760 by full screens.
6761 Any other value means point always keeps its screen position.
6762 Scroll commands should have the `scroll-command' property
6763 on their symbols to be controlled by this variable. */);
6764 Vscroll_preserve_screen_position = Qnil;
6765
6766 DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
6767 doc: /* Type of marker to use for `window-point'. */);
6768 Vwindow_point_insertion_type = Qnil;
6769
6770 DEFVAR_LISP ("window-configuration-change-hook",
6771 Vwindow_configuration_change_hook,
6772 doc: /* Functions to call when window configuration changes.
6773 The buffer-local part is run once per window, with the relevant window
6774 selected; while the global part is run only once for the modified frame,
6775 with the relevant frame selected. */);
6776 Vwindow_configuration_change_hook = Qnil;
6777
6778 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
6779 doc: /* Non-nil means `recenter' redraws entire frame.
6780 If this option is non-nil, then the `recenter' command with a nil
6781 argument will redraw the entire frame; the special value `tty' causes
6782 the frame to be redrawn only if it is a tty frame. */);
6783 Vrecenter_redisplay = Qtty;
6784
6785 DEFVAR_LISP ("window-combination-resize", Vwindow_combination_resize,
6786 doc: /* If t, resize window combinations proportionally.
6787 If this variable is nil, splitting a window gets the entire screen space
6788 for displaying the new window from the window to split. Deleting and
6789 resizing a window preferably resizes one adjacent window only.
6790
6791 If this variable is t, splitting a window tries to get the space
6792 proportionally from all windows in the same combination. This also
6793 allows to split a window that is otherwise too small or of fixed size.
6794 Resizing and deleting a window proportionally resize all windows in the
6795 same combination.
6796
6797 Other values are reserved for future use.
6798
6799 This variable takes no effect if `window-combination-limit' is non-nil. */);
6800 Vwindow_combination_resize = Qnil;
6801
6802 DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
6803 doc: /* If t, splitting a window makes a new parent window.
6804 If this variable is nil, splitting a window will create a new parent
6805 window only if the window has no parent window or the window shall
6806 become a combination orthogonal to the one it is part of.
6807
6808 If this variable is t, splitting a window always creates a new parent
6809 window. If all splits behave this way, each frame's window tree is a
6810 binary tree and every window but the frame's root window has exactly one
6811 sibling.
6812
6813 Other values are reserved for future use.
6814
6815 The value of this variable is also assigned to the combination limit of
6816 the new parent window. The combination limit of a window can be
6817 retrieved via the function `window-combination-limit' and altered by the
6818 function `set-window-combination-limit'. */);
6819 Vwindow_combination_limit = Qnil;
6820
6821 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
6822 doc: /* Alist of persistent window parameters.
6823 This alist specifies which window parameters shall get saved by
6824 `current-window-configuration' and `window-state-get' and subsequently
6825 restored to their previous values by `set-window-configuration' and
6826 `window-state-put'.
6827
6828 The car of each entry of this alist is the symbol specifying the
6829 parameter. The cdr is one of the following:
6830
6831 nil means the parameter is neither saved by `window-state-get' nor by
6832 `current-window-configuration'.
6833
6834 t means the parameter is saved by `current-window-configuration' and,
6835 provided its WRITABLE argument is nil, by `window-state-get'.
6836
6837 The symbol `writable' means the parameter is saved unconditionally by
6838 both `current-window-configuration' and `window-state-get'. Do not use
6839 this value for parameters without read syntax (like windows or frames).
6840
6841 Parameters not saved by `current-window-configuration' or
6842 `window-state-get' are left alone by `set-window-configuration'
6843 respectively are not installed by `window-state-put'. */);
6844 Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
6845
6846 defsubr (&Sselected_window);
6847 defsubr (&Sminibuffer_window);
6848 defsubr (&Swindow_minibuffer_p);
6849 defsubr (&Swindowp);
6850 defsubr (&Swindow_valid_p);
6851 defsubr (&Swindow_live_p);
6852 defsubr (&Swindow_frame);
6853 defsubr (&Sframe_root_window);
6854 defsubr (&Sframe_first_window);
6855 defsubr (&Sframe_selected_window);
6856 defsubr (&Sset_frame_selected_window);
6857 defsubr (&Spos_visible_in_window_p);
6858 defsubr (&Swindow_line_height);
6859 defsubr (&Swindow_buffer);
6860 defsubr (&Swindow_parent);
6861 defsubr (&Swindow_top_child);
6862 defsubr (&Swindow_left_child);
6863 defsubr (&Swindow_next_sibling);
6864 defsubr (&Swindow_prev_sibling);
6865 defsubr (&Swindow_combination_limit);
6866 defsubr (&Sset_window_combination_limit);
6867 defsubr (&Swindow_use_time);
6868 defsubr (&Swindow_top_line);
6869 defsubr (&Swindow_left_column);
6870 defsubr (&Swindow_total_height);
6871 defsubr (&Swindow_total_width);
6872 defsubr (&Swindow_normal_size);
6873 defsubr (&Swindow_new_total);
6874 defsubr (&Swindow_new_normal);
6875 defsubr (&Sset_window_new_total);
6876 defsubr (&Sset_window_new_normal);
6877 defsubr (&Swindow_resize_apply);
6878 defsubr (&Swindow_body_height);
6879 defsubr (&Swindow_body_width);
6880 defsubr (&Swindow_hscroll);
6881 defsubr (&Sset_window_hscroll);
6882 defsubr (&Swindow_redisplay_end_trigger);
6883 defsubr (&Sset_window_redisplay_end_trigger);
6884 defsubr (&Swindow_edges);
6885 defsubr (&Swindow_pixel_edges);
6886 defsubr (&Swindow_absolute_pixel_edges);
6887 defsubr (&Swindow_inside_edges);
6888 defsubr (&Swindow_inside_pixel_edges);
6889 defsubr (&Swindow_inside_absolute_pixel_edges);
6890 defsubr (&Scoordinates_in_window_p);
6891 defsubr (&Swindow_at);
6892 defsubr (&Swindow_point);
6893 defsubr (&Swindow_start);
6894 defsubr (&Swindow_end);
6895 defsubr (&Sset_window_point);
6896 defsubr (&Sset_window_start);
6897 defsubr (&Swindow_dedicated_p);
6898 defsubr (&Sset_window_dedicated_p);
6899 defsubr (&Swindow_display_table);
6900 defsubr (&Sset_window_display_table);
6901 defsubr (&Snext_window);
6902 defsubr (&Sprevious_window);
6903 defsubr (&Sget_buffer_window);
6904 defsubr (&Sdelete_other_windows_internal);
6905 defsubr (&Sdelete_window_internal);
6906 defsubr (&Sresize_mini_window_internal);
6907 defsubr (&Sset_window_buffer);
6908 defsubr (&Srun_window_configuration_change_hook);
6909 defsubr (&Sselect_window);
6910 defsubr (&Sforce_window_update);
6911 defsubr (&Stemp_output_buffer_show);
6912 defsubr (&Ssplit_window_internal);
6913 defsubr (&Sscroll_up);
6914 defsubr (&Sscroll_down);
6915 defsubr (&Sscroll_left);
6916 defsubr (&Sscroll_right);
6917 defsubr (&Sother_window_for_scrolling);
6918 defsubr (&Sscroll_other_window);
6919 defsubr (&Sminibuffer_selected_window);
6920 defsubr (&Srecenter);
6921 defsubr (&Swindow_text_height);
6922 defsubr (&Smove_to_window_line);
6923 defsubr (&Swindow_configuration_p);
6924 defsubr (&Swindow_configuration_frame);
6925 defsubr (&Sset_window_configuration);
6926 defsubr (&Scurrent_window_configuration);
6927 defsubr (&Sset_window_margins);
6928 defsubr (&Swindow_margins);
6929 defsubr (&Sset_window_fringes);
6930 defsubr (&Swindow_fringes);
6931 defsubr (&Sset_window_scroll_bars);
6932 defsubr (&Swindow_scroll_bars);
6933 defsubr (&Swindow_vscroll);
6934 defsubr (&Sset_window_vscroll);
6935 defsubr (&Scompare_window_configurations);
6936 defsubr (&Swindow_list);
6937 defsubr (&Swindow_list_1);
6938 defsubr (&Swindow_prev_buffers);
6939 defsubr (&Sset_window_prev_buffers);
6940 defsubr (&Swindow_next_buffers);
6941 defsubr (&Sset_window_next_buffers);
6942 defsubr (&Swindow_parameters);
6943 defsubr (&Swindow_parameter);
6944 defsubr (&Sset_window_parameter);
6945 }
6946
6947 void
6948 keys_of_window (void)
6949 {
6950 initial_define_key (control_x_map, '<', "scroll-left");
6951 initial_define_key (control_x_map, '>', "scroll-right");
6952
6953 initial_define_key (global_map, Ctl ('V'), "scroll-up-command");
6954 initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
6955 initial_define_key (meta_map, 'v', "scroll-down-command");
6956 }