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