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