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