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