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