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