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